sudovanilla-website/public/@shoelace-style/shoelace/cdn/chunks/chunk.JEBKOPXW.js
2024-05-13 23:34:06 -04:00

136 lines
4.7 KiB
JavaScript

import {
getTabbableElements
} from "./chunk.LXDTFLWU.js";
import {
__yieldStar
} from "./chunk.KIILAQWQ.js";
// src/internal/active-elements.ts
function* activeElements(activeElement = document.activeElement) {
if (activeElement === null || activeElement === void 0)
return;
yield activeElement;
if ("shadowRoot" in activeElement && activeElement.shadowRoot && activeElement.shadowRoot.mode !== "closed") {
yield* __yieldStar(activeElements(activeElement.shadowRoot.activeElement));
}
}
function getDeepestActiveElement() {
return [...activeElements()].pop();
}
// src/internal/modal.ts
var activeModals = [];
var Modal = class {
constructor(element) {
this.tabDirection = "forward";
this.handleFocusIn = () => {
if (!this.isActive())
return;
this.checkFocus();
};
this.handleKeyDown = (event) => {
var _a;
if (event.key !== "Tab" || this.isExternalActivated)
return;
if (!this.isActive())
return;
const currentActiveElement = getDeepestActiveElement();
this.previousFocus = currentActiveElement;
if (this.previousFocus && this.possiblyHasTabbableChildren(this.previousFocus)) {
return;
}
if (event.shiftKey) {
this.tabDirection = "backward";
} else {
this.tabDirection = "forward";
}
const tabbableElements = getTabbableElements(this.element);
let currentFocusIndex = tabbableElements.findIndex((el) => el === currentActiveElement);
this.previousFocus = this.currentFocus;
const addition = this.tabDirection === "forward" ? 1 : -1;
while (true) {
if (currentFocusIndex + addition >= tabbableElements.length) {
currentFocusIndex = 0;
} else if (currentFocusIndex + addition < 0) {
currentFocusIndex = tabbableElements.length - 1;
} else {
currentFocusIndex += addition;
}
this.previousFocus = this.currentFocus;
const nextFocus = (
/** @type {HTMLElement} */
tabbableElements[currentFocusIndex]
);
if (this.tabDirection === "backward") {
if (this.previousFocus && this.possiblyHasTabbableChildren(this.previousFocus)) {
return;
}
}
if (nextFocus && this.possiblyHasTabbableChildren(nextFocus)) {
return;
}
event.preventDefault();
this.currentFocus = nextFocus;
(_a = this.currentFocus) == null ? void 0 : _a.focus({ preventScroll: false });
const allActiveElements = [...activeElements()];
if (allActiveElements.includes(this.currentFocus) || !allActiveElements.includes(this.previousFocus)) {
break;
}
}
setTimeout(() => this.checkFocus());
};
this.handleKeyUp = () => {
this.tabDirection = "forward";
};
this.element = element;
this.elementsWithTabbableControls = ["iframe"];
}
/** Activates focus trapping. */
activate() {
activeModals.push(this.element);
document.addEventListener("focusin", this.handleFocusIn);
document.addEventListener("keydown", this.handleKeyDown);
document.addEventListener("keyup", this.handleKeyUp);
}
/** Deactivates focus trapping. */
deactivate() {
activeModals = activeModals.filter((modal) => modal !== this.element);
this.currentFocus = null;
document.removeEventListener("focusin", this.handleFocusIn);
document.removeEventListener("keydown", this.handleKeyDown);
document.removeEventListener("keyup", this.handleKeyUp);
}
/** Determines if this modal element is currently active or not. */
isActive() {
return activeModals[activeModals.length - 1] === this.element;
}
/** Activates external modal behavior and temporarily disables focus trapping. */
activateExternal() {
this.isExternalActivated = true;
}
/** Deactivates external modal behavior and re-enables focus trapping. */
deactivateExternal() {
this.isExternalActivated = false;
}
checkFocus() {
if (this.isActive() && !this.isExternalActivated) {
const tabbableElements = getTabbableElements(this.element);
if (!this.element.matches(":focus-within")) {
const start = tabbableElements[0];
const end = tabbableElements[tabbableElements.length - 1];
const target = this.tabDirection === "forward" ? start : end;
if (typeof (target == null ? void 0 : target.focus) === "function") {
this.currentFocus = target;
target.focus({ preventScroll: false });
}
}
}
}
possiblyHasTabbableChildren(element) {
return this.elementsWithTabbableControls.includes(element.tagName.toLowerCase()) || element.hasAttribute("controls");
}
};
export {
Modal
};