Project Init

This commit is contained in:
Muluhabt
2026-05-29 15:23:46 +03:00
commit 2fbc557aac
67387 changed files with 6063341 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
'use client';
import { findTabbableDescendants } from './tabbable.mjs';
function scopeTab(node, event) {
const tabbable = findTabbableDescendants(node);
if (!tabbable.length) {
event.preventDefault();
return;
}
const finalTabbable = tabbable[event.shiftKey ? 0 : tabbable.length - 1];
const root = node.getRootNode();
let leavingFinalTabbable = finalTabbable === root.activeElement || node === root.activeElement;
const activeElement = root.activeElement;
const activeElementIsRadio = activeElement.tagName === "INPUT" && activeElement.getAttribute("type") === "radio";
if (activeElementIsRadio) {
const activeRadioGroup = tabbable.filter(
(element) => element.getAttribute("type") === "radio" && element.getAttribute("name") === activeElement.getAttribute("name")
);
leavingFinalTabbable = activeRadioGroup.includes(finalTabbable);
}
if (!leavingFinalTabbable) {
return;
}
event.preventDefault();
const target = tabbable[event.shiftKey ? tabbable.length - 1 : 0];
if (target) {
target.focus();
}
}
export { scopeTab };
//# sourceMappingURL=scope-tab.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,53 @@
'use client';
const TABBABLE_NODES = /input|select|textarea|button|object/;
const FOCUS_SELECTOR = "a, input, select, textarea, button, object, [tabindex]";
function hidden(element) {
if (process.env.NODE_ENV === "test") {
return false;
}
return element.style.display === "none";
}
function visible(element) {
const isHidden = element.getAttribute("aria-hidden") || element.getAttribute("hidden") || element.getAttribute("type") === "hidden";
if (isHidden) {
return false;
}
let parentElement = element;
while (parentElement) {
if (parentElement === document.body || parentElement.nodeType === 11) {
break;
}
if (hidden(parentElement)) {
return false;
}
parentElement = parentElement.parentNode;
}
return true;
}
function getElementTabIndex(element) {
let tabIndex = element.getAttribute("tabindex");
if (tabIndex === null) {
tabIndex = void 0;
}
return parseInt(tabIndex, 10);
}
function focusable(element) {
const nodeName = element.nodeName.toLowerCase();
const isTabIndexNotNaN = !Number.isNaN(getElementTabIndex(element));
const res = (
// @ts-expect-error function accepts any html element but if it is a button, it should not be disabled to trigger the condition
TABBABLE_NODES.test(nodeName) && !element.disabled || (element instanceof HTMLAnchorElement ? element.href || isTabIndexNotNaN : isTabIndexNotNaN)
);
return res && visible(element);
}
function tabbable(element) {
const tabIndex = getElementTabIndex(element);
const isTabIndexNaN = Number.isNaN(tabIndex);
return (isTabIndexNaN || tabIndex >= 0) && focusable(element);
}
function findTabbableDescendants(element) {
return Array.from(element.querySelectorAll(FOCUS_SELECTOR)).filter(tabbable);
}
export { FOCUS_SELECTOR, findTabbableDescendants, focusable, tabbable };
//# sourceMappingURL=tabbable.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,69 @@
'use client';
import { useRef, useCallback, useEffect } from 'react';
import { scopeTab } from './scope-tab.mjs';
import { FOCUS_SELECTOR, tabbable, focusable } from './tabbable.mjs';
function useFocusTrap(active = true) {
const ref = useRef(null);
const focusNode = (node) => {
let focusElement = node.querySelector("[data-autofocus]");
if (!focusElement) {
const children = Array.from(node.querySelectorAll(FOCUS_SELECTOR));
focusElement = children.find(tabbable) || children.find(focusable) || null;
if (!focusElement && focusable(node)) {
focusElement = node;
}
}
if (focusElement) {
focusElement.focus({ preventScroll: true });
} else if (process.env.NODE_ENV === "development") {
console.warn(
"[@mantine/hooks/use-focus-trap] Failed to find focusable element within provided node",
node
);
}
};
const setRef = useCallback(
(node) => {
if (!active) {
return;
}
if (node === null) {
return;
}
if (ref.current === node) {
return;
}
if (node) {
setTimeout(() => {
if (node.getRootNode()) {
focusNode(node);
} else if (process.env.NODE_ENV === "development") {
console.warn("[@mantine/hooks/use-focus-trap] Ref node is not part of the dom", node);
}
});
ref.current = node;
} else {
ref.current = null;
}
},
[active]
);
useEffect(() => {
if (!active) {
return void 0;
}
ref.current && setTimeout(() => focusNode(ref.current));
const handleKeyDown = (event) => {
if (event.key === "Tab" && ref.current) {
scopeTab(ref.current, event);
}
};
document.addEventListener("keydown", handleKeyDown);
return () => document.removeEventListener("keydown", handleKeyDown);
}, [active]);
return setRef;
}
export { useFocusTrap };
//# sourceMappingURL=use-focus-trap.mjs.map

File diff suppressed because one or more lines are too long