@votodigital-onpeui/react 0.1.55 → 0.1.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-PYHXDWTI.mjs → chunk-7WO2CKUD.mjs} +3 -3
- package/dist/{chunk-PYHXDWTI.mjs.map → chunk-7WO2CKUD.mjs.map} +1 -1
- package/dist/{chunk-DFOTZ4CC.mjs → chunk-RFIMDKOY.mjs} +3 -3
- package/dist/{chunk-DFOTZ4CC.mjs.map → chunk-RFIMDKOY.mjs.map} +1 -1
- package/dist/{chunk-RIILZBD5.mjs → chunk-RL3RQN4O.mjs} +109 -61
- package/dist/chunk-RL3RQN4O.mjs.map +1 -0
- package/dist/{chunk-6DPRQ3EM.mjs → chunk-XUSUDWMU.mjs} +3 -3
- package/dist/{chunk-6DPRQ3EM.mjs.map → chunk-XUSUDWMU.mjs.map} +1 -1
- package/dist/components.js +107 -59
- package/dist/components.js.map +1 -1
- package/dist/components.mjs +3 -3
- package/dist/hooks.js +107 -59
- package/dist/hooks.js.map +1 -1
- package/dist/hooks.mjs +2 -2
- package/dist/index.js +107 -59
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/modal.js +107 -59
- package/dist/modal.js.map +1 -1
- package/dist/modal.mjs +2 -2
- package/package.json +1 -1
- package/dist/chunk-RIILZBD5.mjs.map +0 -1
package/dist/components.js
CHANGED
|
@@ -445,6 +445,61 @@ var unlockBodyScroll = (id, enabled) => {
|
|
|
445
445
|
document.body.style.overflow = "";
|
|
446
446
|
}
|
|
447
447
|
};
|
|
448
|
+
var FOCUSABLE_SELECTOR = [
|
|
449
|
+
"a[href]",
|
|
450
|
+
"area[href]",
|
|
451
|
+
"button:not([disabled])",
|
|
452
|
+
'input:not([disabled]):not([type="hidden"])',
|
|
453
|
+
"select:not([disabled])",
|
|
454
|
+
"textarea:not([disabled])",
|
|
455
|
+
"iframe",
|
|
456
|
+
"object",
|
|
457
|
+
"embed",
|
|
458
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
459
|
+
'[contenteditable="true"]'
|
|
460
|
+
].join(",");
|
|
461
|
+
var FOCUS_GUARD_ATTRIBUTE = "data-focus-guard";
|
|
462
|
+
var focusGuardStyle = {
|
|
463
|
+
position: "absolute",
|
|
464
|
+
width: "1px",
|
|
465
|
+
height: "1px",
|
|
466
|
+
padding: 0,
|
|
467
|
+
margin: 0,
|
|
468
|
+
overflow: "hidden",
|
|
469
|
+
clip: "rect(0, 0, 0, 0)",
|
|
470
|
+
whiteSpace: "nowrap",
|
|
471
|
+
border: 0
|
|
472
|
+
};
|
|
473
|
+
var isElementVisible = (element) => {
|
|
474
|
+
const style = globalThis.getComputedStyle(element);
|
|
475
|
+
return style.visibility !== "hidden" && style.display !== "none" && element.offsetParent !== null;
|
|
476
|
+
};
|
|
477
|
+
var getFocusableElements = (wrapper, includeWrapper = true) => {
|
|
478
|
+
let focusable = Array.from(wrapper.querySelectorAll(FOCUSABLE_SELECTOR)).filter(
|
|
479
|
+
(el) => !el.hasAttribute(FOCUS_GUARD_ATTRIBUTE) && isElementVisible(el) && el.tabIndex !== -1
|
|
480
|
+
);
|
|
481
|
+
if (includeWrapper && wrapper.tabIndex >= 0) {
|
|
482
|
+
focusable = [wrapper, ...focusable];
|
|
483
|
+
}
|
|
484
|
+
return focusable;
|
|
485
|
+
};
|
|
486
|
+
var focusWrapper = (wrapper, options) => {
|
|
487
|
+
if (wrapper.tabIndex >= 0) {
|
|
488
|
+
wrapper.focus(options);
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
const focusable = getFocusableElements(wrapper, false);
|
|
492
|
+
focusable[0]?.focus(options);
|
|
493
|
+
};
|
|
494
|
+
var focusEdgeElement = (wrapper, position, options) => {
|
|
495
|
+
const focusable = getFocusableElements(wrapper, false);
|
|
496
|
+
const target = position === "last" ? focusable.at(-1) : focusable[0];
|
|
497
|
+
if (target) {
|
|
498
|
+
target.focus(options);
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
focusWrapper(wrapper, options);
|
|
502
|
+
};
|
|
448
503
|
var Modal = ({
|
|
449
504
|
isOpen,
|
|
450
505
|
onClose,
|
|
@@ -473,6 +528,16 @@ var Modal = ({
|
|
|
473
528
|
const modalRef = react.useRef(null);
|
|
474
529
|
const contentRef = react.useRef(null);
|
|
475
530
|
const previousActiveElement = react.useRef(null);
|
|
531
|
+
const handleStartFocusGuard = () => {
|
|
532
|
+
const wrapper = modalRef.current;
|
|
533
|
+
if (!wrapper) return;
|
|
534
|
+
focusEdgeElement(wrapper, "last", { preventScroll: true });
|
|
535
|
+
};
|
|
536
|
+
const handleEndFocusGuard = () => {
|
|
537
|
+
const wrapper = modalRef.current;
|
|
538
|
+
if (!wrapper) return;
|
|
539
|
+
focusEdgeElement(wrapper, "first", { preventScroll: true });
|
|
540
|
+
};
|
|
476
541
|
const [mounted, setMounted] = react.useState(false);
|
|
477
542
|
const [visible, setVisible] = react.useState(false);
|
|
478
543
|
const [cachedChildren, setCachedChildren] = react.useState(children);
|
|
@@ -522,52 +587,21 @@ var Modal = ({
|
|
|
522
587
|
[10, 50, 100, 200].forEach((d) => setTimeout(resetScroll, d));
|
|
523
588
|
}, [isOpen]);
|
|
524
589
|
react.useEffect(() => {
|
|
525
|
-
let focusOutWrapper = null;
|
|
526
590
|
const pendingTasks = [];
|
|
527
|
-
const
|
|
528
|
-
const style = globalThis.getComputedStyle(element);
|
|
529
|
-
return style.visibility !== "hidden" && style.display !== "none" && element.offsetParent !== null;
|
|
530
|
-
};
|
|
531
|
-
const getFocusableElements = (wrapper) => {
|
|
532
|
-
const selector = [
|
|
533
|
-
"a[href]",
|
|
534
|
-
"area[href]",
|
|
535
|
-
"button:not([disabled])",
|
|
536
|
-
'input:not([disabled]):not([type="hidden"])',
|
|
537
|
-
"select:not([disabled])",
|
|
538
|
-
"textarea:not([disabled])",
|
|
539
|
-
"iframe",
|
|
540
|
-
"object",
|
|
541
|
-
"embed",
|
|
542
|
-
'[tabindex]:not([tabindex="-1"])',
|
|
543
|
-
'[contenteditable="true"]'
|
|
544
|
-
].join(",");
|
|
545
|
-
let focusable = Array.from(
|
|
546
|
-
wrapper.querySelectorAll(selector)
|
|
547
|
-
).filter((el) => isElementVisible(el) && el.tabIndex !== -1);
|
|
548
|
-
if (wrapper.tabIndex >= 0) {
|
|
549
|
-
focusable = [wrapper, ...focusable];
|
|
550
|
-
}
|
|
551
|
-
return focusable;
|
|
552
|
-
};
|
|
553
|
-
const handleFocusOut = (e) => {
|
|
591
|
+
const handleDocumentFocusIn = (e) => {
|
|
554
592
|
if (!isOpen || disableFocus) return;
|
|
555
593
|
const wrapper = modalRef.current;
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
setTimeout(() => {
|
|
560
|
-
const currentActive = document.activeElement;
|
|
561
|
-
if (!currentActive || !wrapper.contains(currentActive)) {
|
|
562
|
-
const focusable = getFocusableElements(wrapper);
|
|
563
|
-
if (focusable.length > 0) {
|
|
564
|
-
focusable[focusable.length - 1].focus();
|
|
565
|
-
} else {
|
|
566
|
-
wrapper.focus();
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}, 0);
|
|
594
|
+
const target = e.target;
|
|
595
|
+
if (!wrapper || !(target instanceof HTMLElement) || wrapper.contains(target)) {
|
|
596
|
+
return;
|
|
570
597
|
}
|
|
598
|
+
requestAnimationFrame(() => {
|
|
599
|
+
const currentActive = document.activeElement;
|
|
600
|
+
if (currentActive instanceof HTMLElement && wrapper.contains(currentActive)) {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
focusWrapper(wrapper, { preventScroll: true });
|
|
604
|
+
});
|
|
571
605
|
};
|
|
572
606
|
const handleKeyDown = (e) => {
|
|
573
607
|
if (e.key === "Escape" && escapeToClose && !closeDisabled) {
|
|
@@ -586,7 +620,7 @@ var Modal = ({
|
|
|
586
620
|
if ((e.key === "ArrowUp" || e.key === "ArrowLeft") && activeIndex2 === 0) {
|
|
587
621
|
e.preventDefault();
|
|
588
622
|
e.stopPropagation();
|
|
589
|
-
if (focusable.length > 1) focusable
|
|
623
|
+
if (focusable.length > 1) focusable.at(-1)?.focus();
|
|
590
624
|
else active.focus();
|
|
591
625
|
return;
|
|
592
626
|
}
|
|
@@ -610,7 +644,7 @@ var Modal = ({
|
|
|
610
644
|
e.preventDefault();
|
|
611
645
|
if (focusable.length > 0) {
|
|
612
646
|
if (e.key === "ArrowUp" || e.key === "ArrowLeft")
|
|
613
|
-
focusable
|
|
647
|
+
focusable.at(-1)?.focus();
|
|
614
648
|
else focusable[0].focus();
|
|
615
649
|
} else {
|
|
616
650
|
wrapper.focus();
|
|
@@ -625,8 +659,13 @@ var Modal = ({
|
|
|
625
659
|
return;
|
|
626
660
|
}
|
|
627
661
|
const first = focusable[0];
|
|
628
|
-
const last = focusable
|
|
662
|
+
const last = focusable.at(-1);
|
|
629
663
|
const isShift = e.shiftKey;
|
|
664
|
+
if (!first || !last) {
|
|
665
|
+
e.preventDefault();
|
|
666
|
+
wrapper.focus();
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
630
669
|
if (!active || !wrapper.contains(active)) {
|
|
631
670
|
e.preventDefault();
|
|
632
671
|
(isShift ? last : first).focus();
|
|
@@ -649,14 +688,7 @@ var Modal = ({
|
|
|
649
688
|
if (isOpen && !disableFocus) {
|
|
650
689
|
previousActiveElement.current = document.activeElement;
|
|
651
690
|
const focusInitial = (wrapper) => {
|
|
652
|
-
|
|
653
|
-
wrapper.focus({ preventScroll: true });
|
|
654
|
-
return;
|
|
655
|
-
}
|
|
656
|
-
const focusable = getFocusableElements(wrapper);
|
|
657
|
-
const first = focusable[0];
|
|
658
|
-
if (first) first.focus({ preventScroll: true });
|
|
659
|
-
else wrapper.focus();
|
|
691
|
+
focusWrapper(wrapper, { preventScroll: true });
|
|
660
692
|
};
|
|
661
693
|
const bindFocusManagement = (attempt = 0) => {
|
|
662
694
|
const wrapper = modalRef.current;
|
|
@@ -668,14 +700,10 @@ var Modal = ({
|
|
|
668
700
|
}
|
|
669
701
|
return;
|
|
670
702
|
}
|
|
671
|
-
if (focusOutWrapper !== wrapper) {
|
|
672
|
-
focusOutWrapper?.removeEventListener("focusout", handleFocusOut);
|
|
673
|
-
wrapper.addEventListener("focusout", handleFocusOut);
|
|
674
|
-
focusOutWrapper = wrapper;
|
|
675
|
-
}
|
|
676
703
|
focusInitial(wrapper);
|
|
677
704
|
};
|
|
678
705
|
document.addEventListener("keydown", handleKeyDown);
|
|
706
|
+
document.addEventListener("focusin", handleDocumentFocusIn, true);
|
|
679
707
|
pendingTasks.push(globalThis.setTimeout(() => bindFocusManagement(), 0));
|
|
680
708
|
} else if (isOpen && disableFocus) {
|
|
681
709
|
document.addEventListener("keydown", handleKeyDown);
|
|
@@ -683,7 +711,7 @@ var Modal = ({
|
|
|
683
711
|
return () => {
|
|
684
712
|
pendingTasks.forEach((task) => globalThis.clearTimeout(task));
|
|
685
713
|
document.removeEventListener("keydown", handleKeyDown);
|
|
686
|
-
|
|
714
|
+
document.removeEventListener("focusin", handleDocumentFocusIn, true);
|
|
687
715
|
if (!disableFocus && !disableFocusRestore && previousActiveElement.current) {
|
|
688
716
|
previousActiveElement.current.focus();
|
|
689
717
|
}
|
|
@@ -743,6 +771,16 @@ var Modal = ({
|
|
|
743
771
|
"aria-describedby": props["aria-describedby"],
|
|
744
772
|
"aria-label": props["aria-label"],
|
|
745
773
|
children: [
|
|
774
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
775
|
+
"span",
|
|
776
|
+
{
|
|
777
|
+
tabIndex: disableFocus ? -1 : 0,
|
|
778
|
+
"aria-hidden": "true",
|
|
779
|
+
...{ [FOCUS_GUARD_ATTRIBUTE]: "start" },
|
|
780
|
+
style: focusGuardStyle,
|
|
781
|
+
onFocus: handleStartFocusGuard
|
|
782
|
+
}
|
|
783
|
+
),
|
|
746
784
|
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: contentRef, className: contentClass, children: isOpen ? children : cachedChildren }),
|
|
747
785
|
closeButton && /* @__PURE__ */ jsxRuntime.jsx(
|
|
748
786
|
"button",
|
|
@@ -753,6 +791,16 @@ var Modal = ({
|
|
|
753
791
|
type: "button",
|
|
754
792
|
children: /* @__PURE__ */ jsxRuntime.jsx(IconCloseRadius, { "aria-hidden": "true", className: "w-full h-full" })
|
|
755
793
|
}
|
|
794
|
+
),
|
|
795
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
796
|
+
"span",
|
|
797
|
+
{
|
|
798
|
+
tabIndex: disableFocus ? -1 : 0,
|
|
799
|
+
"aria-hidden": "true",
|
|
800
|
+
...{ [FOCUS_GUARD_ATTRIBUTE]: "end" },
|
|
801
|
+
style: focusGuardStyle,
|
|
802
|
+
onFocus: handleEndFocusGuard
|
|
803
|
+
}
|
|
756
804
|
)
|
|
757
805
|
]
|
|
758
806
|
}
|