se-design 1.0.73-dev2 → 1.0.73-dev3
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/components/CustomModal/index.d.ts +18 -0
- package/dist/components/Modal/index.d.ts +1 -0
- package/dist/index11.js +53 -38
- package/dist/index11.js.map +1 -1
- package/dist/index12.js.map +1 -1
- package/dist/index15.js +1 -1
- package/dist/index18.js +1 -1
- package/dist/index188.js +5 -5
- package/dist/index192.js +43 -0
- package/dist/index192.js.map +1 -0
- package/dist/{index194.js → index195.js} +1 -1
- package/dist/{index194.js.map → index195.js.map} +1 -1
- package/dist/{index196.js → index197.js} +3 -3
- package/dist/{index196.js.map → index197.js.map} +1 -1
- package/dist/{index198.js → index199.js} +1 -1
- package/dist/{index198.js.map → index199.js.map} +1 -1
- package/dist/{index206.js → index207.js} +1 -1
- package/dist/{index206.js.map → index207.js.map} +1 -1
- package/dist/{index214.js → index215.js} +1 -1
- package/dist/{index214.js.map → index215.js.map} +1 -1
- package/dist/{index217.js → index218.js} +1 -1
- package/dist/{index217.js.map → index218.js.map} +1 -1
- package/dist/{index226.js → index227.js} +1 -1
- package/dist/{index226.js.map → index227.js.map} +1 -1
- package/dist/index229.js +57 -20
- package/dist/index229.js.map +1 -1
- package/dist/index230.js +20 -52
- package/dist/index230.js.map +1 -1
- package/dist/index231.js +51 -16
- package/dist/index231.js.map +1 -1
- package/dist/index232.js +18 -9
- package/dist/index232.js.map +1 -1
- package/dist/index233.js +9 -9
- package/dist/index233.js.map +1 -1
- package/dist/index234.js +9 -4
- package/dist/index234.js.map +1 -1
- package/dist/index235.js +5 -170
- package/dist/index235.js.map +1 -1
- package/dist/index236.js +170 -11
- package/dist/index236.js.map +1 -1
- package/dist/index237.js +11 -6
- package/dist/index237.js.map +1 -1
- package/dist/index238.js +5 -5
- package/dist/index238.js.map +1 -1
- package/dist/index239.js +5 -37
- package/dist/index239.js.map +1 -1
- package/dist/index24.js +1 -1
- package/dist/index240.js +38 -2
- package/dist/index240.js.map +1 -1
- package/dist/index241.js +2 -8
- package/dist/index241.js.map +1 -1
- package/dist/index242.js +7 -326
- package/dist/index242.js.map +1 -1
- package/dist/index243.js +324 -47
- package/dist/index243.js.map +1 -1
- package/dist/index244.js +50 -2
- package/dist/index244.js.map +1 -1
- package/dist/index245.js +2 -76
- package/dist/index245.js.map +1 -1
- package/dist/index246.js +65 -82
- package/dist/index246.js.map +1 -1
- package/dist/index247.js +89 -48
- package/dist/index247.js.map +1 -1
- package/dist/index248.js +51 -7
- package/dist/index248.js.map +1 -1
- package/dist/index249.js +7 -4
- package/dist/index249.js.map +1 -1
- package/dist/index250.js +4 -51
- package/dist/index250.js.map +1 -1
- package/dist/index251.js +52 -2
- package/dist/index251.js.map +1 -1
- package/dist/index252.js +2 -2
- package/dist/index253.js +5 -0
- package/dist/index253.js.map +1 -0
- package/dist/index27.js +1 -1
- package/dist/index37.js +1 -1
- package/dist/index39.js +1 -1
- package/dist/index44.js +1 -1
- package/dist/index45.js +2 -2
- package/dist/index48.js +1 -1
- package/dist/index52.js +1 -1
- package/dist/index62.js +1 -1
- package/dist/index64.js +1 -1
- package/package.json +1 -1
- package/dist/index228.js +0 -62
- package/dist/index228.js.map +0 -1
|
@@ -10,4 +10,22 @@ export interface CustomModalProps {
|
|
|
10
10
|
contentClassName?: string;
|
|
11
11
|
automationId?: string;
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* A11y note: CustomModal is a dumb container — consumers are responsible for adding dialog semantics
|
|
15
|
+
* to the content rendered via `renderModalContent`. Follow the same pattern as Modal/index.tsx:
|
|
16
|
+
*
|
|
17
|
+
* <div
|
|
18
|
+
* ref={containerRef}
|
|
19
|
+
* role="dialog"
|
|
20
|
+
* aria-modal="true"
|
|
21
|
+
* aria-labelledby={titleId} // or aria-label if no visible heading
|
|
22
|
+
* tabIndex={-1}
|
|
23
|
+
* >
|
|
24
|
+
* <h2 id={titleId}>...</h2>
|
|
25
|
+
* ...
|
|
26
|
+
* </div>
|
|
27
|
+
*
|
|
28
|
+
* Also use useFocusTrap + useDismissOnEscape from 'src/utils/a11y' inside the consumer component.
|
|
29
|
+
* See Paywall/index.tsx for a complete reference implementation.
|
|
30
|
+
*/
|
|
13
31
|
export declare const CustomModal: FC<CustomModalProps>;
|
package/dist/index11.js
CHANGED
|
@@ -1,57 +1,72 @@
|
|
|
1
1
|
import e from "react";
|
|
2
|
-
import { Button as
|
|
3
|
-
import { Icon as
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
import { Button as m } from "./index3.js";
|
|
3
|
+
import { Icon as E } from "./index5.js";
|
|
4
|
+
import { useModalA11y as C } from "./index192.js";
|
|
5
|
+
function n() {
|
|
6
|
+
return n = Object.assign ? Object.assign.bind() : function(l) {
|
|
7
|
+
for (var t = 1; t < arguments.length; t++) {
|
|
8
|
+
var o = arguments[t];
|
|
9
|
+
for (var a in o) ({}).hasOwnProperty.call(o, a) && (l[a] = o[a]);
|
|
9
10
|
}
|
|
10
|
-
return
|
|
11
|
-
},
|
|
11
|
+
return l;
|
|
12
|
+
}, n.apply(null, arguments);
|
|
12
13
|
}
|
|
13
|
-
const
|
|
14
|
+
const I = (l) => {
|
|
14
15
|
const {
|
|
15
|
-
title:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
16
|
+
title: t,
|
|
17
|
+
ariaLabel: o,
|
|
18
|
+
content: a = "",
|
|
19
|
+
showCloseIcon: d = !1,
|
|
20
|
+
successButtonProps: r,
|
|
21
|
+
cancelButtonProps: i,
|
|
22
|
+
cancelAction: s,
|
|
23
|
+
successAction: u,
|
|
24
|
+
isOpen: c,
|
|
25
|
+
width: p = "500px",
|
|
26
|
+
height: g = "auto",
|
|
27
|
+
automationId: f = "",
|
|
28
|
+
customModalClassName: b = ""
|
|
29
|
+
} = l, {
|
|
30
|
+
containerRef: v,
|
|
31
|
+
titleId: h,
|
|
32
|
+
dialogProps: x
|
|
33
|
+
} = C({
|
|
34
|
+
isOpen: c,
|
|
35
|
+
onDismiss: s,
|
|
36
|
+
title: t,
|
|
37
|
+
ariaLabel: o
|
|
38
|
+
}), y = typeof a == "string";
|
|
28
39
|
return /* @__PURE__ */ e.createElement("div", {
|
|
29
|
-
className: `${
|
|
30
|
-
}, /* @__PURE__ */ e.createElement("div", {
|
|
40
|
+
className: `${b} se-design-modal fixed inset-0 flex items-start justify-center z-[2001] backdrop-brightness-50 backdrop-blur-sm ${c ? "visible" : "invisible pointer-events-none"}`
|
|
41
|
+
}, /* @__PURE__ */ e.createElement("div", n({
|
|
42
|
+
ref: v
|
|
43
|
+
}, x, {
|
|
31
44
|
className: "modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded-xl shadow-lg p-7 mt-[48px] relative",
|
|
32
45
|
style: {
|
|
33
|
-
width:
|
|
34
|
-
height:
|
|
46
|
+
width: p,
|
|
47
|
+
height: g,
|
|
35
48
|
maxWidth: "100vw"
|
|
36
49
|
},
|
|
37
|
-
"data-automation-id":
|
|
38
|
-
},
|
|
50
|
+
"data-automation-id": f
|
|
51
|
+
}), t && /* @__PURE__ */ e.createElement("h2", {
|
|
52
|
+
id: h,
|
|
39
53
|
className: "text-lg font-semibold color-[var(--color-gray-900)]"
|
|
40
|
-
},
|
|
54
|
+
}, t), y ? /* @__PURE__ */ e.createElement("p", {
|
|
41
55
|
className: "leading-normal color-[var(--color-gray-700)]"
|
|
42
|
-
},
|
|
56
|
+
}, a) : a, /* @__PURE__ */ e.createElement("div", {
|
|
43
57
|
className: "flex items-center justify-end gap-4 pt-3"
|
|
44
|
-
},
|
|
45
|
-
onClick:
|
|
46
|
-
})),
|
|
47
|
-
onClick:
|
|
48
|
-
}))),
|
|
58
|
+
}, i?.label && /* @__PURE__ */ e.createElement(m, n({}, i, {
|
|
59
|
+
onClick: s
|
|
60
|
+
})), r?.label && /* @__PURE__ */ e.createElement(m, n({}, r, {
|
|
61
|
+
onClick: u
|
|
62
|
+
}))), d && /* @__PURE__ */ e.createElement(E, {
|
|
49
63
|
name: "close",
|
|
50
|
-
onClick:
|
|
64
|
+
onClick: s,
|
|
65
|
+
ariaLabel: "Close dialog",
|
|
51
66
|
className: "absolute top-8 right-8 cursor-pointer"
|
|
52
67
|
})));
|
|
53
68
|
};
|
|
54
69
|
export {
|
|
55
|
-
|
|
70
|
+
I as Modal
|
|
56
71
|
};
|
|
57
72
|
//# sourceMappingURL=index11.js.map
|
package/dist/index11.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index11.js","sources":["../src/components/Modal/index.tsx"],"sourcesContent":["import React, { FC } from 'react';\nimport { Button } from 'src/components/Button';\nimport { ButtonProps } from 'src/components/Button';\nimport { Icon } from '../Icon';\n\nexport interface ModalProps {\n title?: string;\n content: string | React.ReactNode;\n successButtonProps?: ButtonProps;\n cancelButtonProps?: ButtonProps;\n cancelAction?: () => void;\n successAction?: () => void;\n showCloseIcon?: boolean;\n isOpen: boolean;\n width?: string;\n height?: string;\n automationId?: string;\n customModalClassName?: string;\n}\n\nexport const Modal: FC<ModalProps> = (props) => {\n const {\n title,\n content = '',\n showCloseIcon = false,\n successButtonProps,\n cancelButtonProps,\n cancelAction,\n successAction,\n isOpen,\n width = '500px',\n height = 'auto',\n automationId = '',\n customModalClassName = ''\n } = props;\n\n const isContentString = typeof content === 'string';\n\n return (\n <div\n className={`${customModalClassName} se-design-modal fixed inset-0 flex items-start justify-center z-[2001] backdrop-brightness-50 backdrop-blur-sm ${isOpen ? 'visible' : 'invisible pointer-events-none'\n }`}\n >\n <div\n className=\"modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded-xl shadow-lg p-7 mt-[48px] relative\"\n style={{ width, height, maxWidth: '100vw' }}\n data-automation-id={automationId}\n >\n {title && <
|
|
1
|
+
{"version":3,"file":"index11.js","sources":["../src/components/Modal/index.tsx"],"sourcesContent":["import React, { FC } from 'react';\nimport { Button } from 'src/components/Button';\nimport { ButtonProps } from 'src/components/Button';\nimport { Icon } from '../Icon';\nimport { useModalA11y } from 'src/utils/a11y';\n\nexport interface ModalProps {\n title?: string;\n ariaLabel?: string;\n content: string | React.ReactNode;\n successButtonProps?: ButtonProps;\n cancelButtonProps?: ButtonProps;\n cancelAction?: () => void;\n successAction?: () => void;\n showCloseIcon?: boolean;\n isOpen: boolean;\n width?: string;\n height?: string;\n automationId?: string;\n customModalClassName?: string;\n}\n\nexport const Modal: FC<ModalProps> = (props) => {\n const {\n title,\n ariaLabel,\n content = '',\n showCloseIcon = false,\n successButtonProps,\n cancelButtonProps,\n cancelAction,\n successAction,\n isOpen,\n width = '500px',\n height = 'auto',\n automationId = '',\n customModalClassName = ''\n } = props;\n\n const { containerRef, titleId, dialogProps } = useModalA11y({\n isOpen,\n onDismiss: cancelAction,\n title,\n ariaLabel,\n });\n\n const isContentString = typeof content === 'string';\n\n return (\n <div\n className={`${customModalClassName} se-design-modal fixed inset-0 flex items-start justify-center z-[2001] backdrop-brightness-50 backdrop-blur-sm ${isOpen ? 'visible' : 'invisible pointer-events-none'\n }`}\n >\n <div\n ref={containerRef}\n {...dialogProps}\n className=\"modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded-xl shadow-lg p-7 mt-[48px] relative\"\n style={{ width, height, maxWidth: '100vw' }}\n data-automation-id={automationId}\n >\n {title && <h2 id={titleId} className=\"text-lg font-semibold color-[var(--color-gray-900)]\">{title}</h2>}\n {isContentString ? <p className=\"leading-normal color-[var(--color-gray-700)]\">{content}</p> : content}\n <div className=\"flex items-center justify-end gap-4 pt-3\">\n {cancelButtonProps?.label && <Button {...cancelButtonProps} onClick={cancelAction} />}\n {successButtonProps?.label && <Button {...successButtonProps} onClick={successAction} />}\n </div>\n {showCloseIcon && (\n <Icon name=\"close\" onClick={cancelAction} ariaLabel=\"Close dialog\" className=\"absolute top-8 right-8 cursor-pointer\" />\n )}\n </div>\n </div>\n );\n};\n"],"names":["Modal","props","title","ariaLabel","content","showCloseIcon","successButtonProps","cancelButtonProps","cancelAction","successAction","isOpen","width","height","automationId","customModalClassName","containerRef","titleId","dialogProps","useModalA11y","onDismiss","isContentString","React","createElement","className","_extends","ref","style","maxWidth","id","label","Button","onClick","Icon","name"],"mappings":";;;;;;;;;;;;;AAsBO,MAAMA,IAAyBC,CAAAA,MAAU;AAC9C,QAAM;AAAA,IACJC,OAAAA;AAAAA,IACAC,WAAAA;AAAAA,IACAC,SAAAA,IAAU;AAAA,IACVC,eAAAA,IAAgB;AAAA,IAChBC,oBAAAA;AAAAA,IACAC,mBAAAA;AAAAA,IACAC,cAAAA;AAAAA,IACAC,eAAAA;AAAAA,IACAC,QAAAA;AAAAA,IACAC,OAAAA,IAAQ;AAAA,IACRC,QAAAA,IAAS;AAAA,IACTC,cAAAA,IAAe;AAAA,IACfC,sBAAAA,IAAuB;AAAA,EAAA,IACrBb,GAEE;AAAA,IAAEc,cAAAA;AAAAA,IAAcC,SAAAA;AAAAA,IAASC,aAAAA;AAAAA,EAAAA,IAAgBC,EAAa;AAAA,IAC1DR,QAAAA;AAAAA,IACAS,WAAWX;AAAAA,IACXN,OAAAA;AAAAA,IACAC,WAAAA;AAAAA,EAAAA,CACD,GAEKiB,IAAkB,OAAOhB,KAAY;AAE3C,SACEiB,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IACEC,WAAW,GAAGT,CAAoB,mHAAmHJ,IAAS,YAAY,+BAA+B;AAAA,EAAA,GAGzMW,gBAAAA,EAAAC,cAAA,OAAAE,EAAA;AAAA,IACEC,KAAKV;AAAAA,EAAAA,GACDE,GAAW;AAAA,IACfM,WAAU;AAAA,IACVG,OAAO;AAAA,MAAEf,OAAAA;AAAAA,MAAOC,QAAAA;AAAAA,MAAQe,UAAU;AAAA,IAAA;AAAA,IAClC,sBAAoBd;AAAAA,EAAAA,CAAa,GAEhCX,KAASmB,gBAAAA,EAAAC,cAAA,MAAA;AAAA,IAAIM,IAAIZ;AAAAA,IAASO,WAAU;AAAA,EAAA,GAAuDrB,CAAU,GACrGkB,IAAkBC,gBAAAA,EAAAC,cAAA,KAAA;AAAA,IAAGC,WAAU;AAAA,EAAA,GAAgDnB,CAAW,IAAIA,GAC/FiB,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IAAKC,WAAU;AAAA,EAAA,GACZhB,GAAmBsB,SAASR,gBAAAA,EAAAC,cAACQ,GAAMN,EAAA,CAAA,GAAKjB,GAAiB;AAAA,IAAEwB,SAASvB;AAAAA,EAAAA,CAAa,CAAE,GACnFF,GAAoBuB,SAASR,gBAAAA,EAAAC,cAACQ,GAAMN,MAAKlB,GAAkB;AAAA,IAAEyB,SAAStB;AAAAA,EAAAA,CAAc,CAAE,CACpF,GACJJ,KACCgB,gBAAAA,EAAAC,cAACU,GAAI;AAAA,IAACC,MAAK;AAAA,IAAQF,SAASvB;AAAAA,IAAcL,WAAU;AAAA,IAAeoB,WAAU;AAAA,EAAA,CAAyC,CAErH,CACF;AAET;"}
|
package/dist/index12.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index12.js","sources":["../src/components/CustomModal/index.tsx"],"sourcesContent":["import React, { FC } from 'react';\n\nexport interface CustomModalProps {\n onSubmit?: () => void;\n onClose?: () => void;\n onModalClick?: () => void;\n renderModalContent: () => React.ReactNode;\n isOpen: boolean;\n width?: string;\n className?: string;\n contentClassName?: string;\n automationId?: string;\n}\n\nexport const CustomModal: FC<CustomModalProps> = (props) => {\n const {\n renderModalContent,\n isOpen,\n width = '500px',\n className = '',\n contentClassName = '',\n automationId = '',\n onModalClick = () => {}\n } = props;\n\n return (\n <div\n className={`se-design-modal fixed inset-0 flex items-start justify-center z-[2001] backdrop-brightness-50 backdrop-blur-sm ${\n isOpen ? 'visible' : 'invisible pointer-events-none'\n } ${className}`}\n data-automation-id={automationId}\n onClick={onModalClick}\n >\n <div\n className={`modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded shadow-lg p-8 mt-[48px] ${contentClassName}`}\n style={{ width, maxWidth: '100vw' }}\n >\n {renderModalContent()}\n </div>\n </div>\n );\n};\n"],"names":["React__default","CustomModal","props","renderModalContent","isOpen","width","className","contentClassName","automationId","onModalClick","React","createElement","onClick","style","maxWidth"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index12.js","sources":["../src/components/CustomModal/index.tsx"],"sourcesContent":["import React, { FC } from 'react';\n\nexport interface CustomModalProps {\n onSubmit?: () => void;\n onClose?: () => void;\n onModalClick?: () => void;\n renderModalContent: () => React.ReactNode;\n isOpen: boolean;\n width?: string;\n className?: string;\n contentClassName?: string;\n automationId?: string;\n}\n\n/**\n * A11y note: CustomModal is a dumb container — consumers are responsible for adding dialog semantics\n * to the content rendered via `renderModalContent`. Follow the same pattern as Modal/index.tsx:\n *\n * <div\n * ref={containerRef}\n * role=\"dialog\"\n * aria-modal=\"true\"\n * aria-labelledby={titleId} // or aria-label if no visible heading\n * tabIndex={-1}\n * >\n * <h2 id={titleId}>...</h2>\n * ...\n * </div>\n *\n * Also use useFocusTrap + useDismissOnEscape from 'src/utils/a11y' inside the consumer component.\n * See Paywall/index.tsx for a complete reference implementation.\n */\nexport const CustomModal: FC<CustomModalProps> = (props) => {\n const {\n renderModalContent,\n isOpen,\n width = '500px',\n className = '',\n contentClassName = '',\n automationId = '',\n onModalClick = () => {}\n } = props;\n\n return (\n <div\n className={`se-design-modal fixed inset-0 flex items-start justify-center z-[2001] backdrop-brightness-50 backdrop-blur-sm ${\n isOpen ? 'visible' : 'invisible pointer-events-none'\n } ${className}`}\n data-automation-id={automationId}\n onClick={onModalClick}\n >\n <div\n className={`modal-content flex flex-col gap-3 bg-[var(--color-white)] rounded shadow-lg p-8 mt-[48px] ${contentClassName}`}\n style={{ width, maxWidth: '100vw' }}\n >\n {renderModalContent()}\n </div>\n </div>\n );\n};\n"],"names":["React__default","CustomModal","props","renderModalContent","isOpen","width","className","contentClassName","automationId","onModalClick","React","createElement","onClick","style","maxWidth"],"mappings":"AAgCO,OAAAA,OAAA;AAAA,MAAMC,IAAqCC,CAAAA,MAAU;AAC1D,QAAM;AAAA,IACJC,oBAAAA;AAAAA,IACAC,QAAAA;AAAAA,IACAC,OAAAA,IAAQ;AAAA,IACRC,WAAAA,IAAY;AAAA,IACZC,kBAAAA,IAAmB;AAAA,IACnBC,cAAAA,IAAe;AAAA,IACfC,cAAAA,IAAeA,MAAM;AAAA,IAAC;AAAA,EAAA,IACpBP;AAEJ,SACEQ,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IACEL,WAAW,kHACTF,IAAS,YAAY,+BAA+B,IAClDE,CAAS;AAAA,IACb,sBAAoBE;AAAAA,IACpBI,SAASH;AAAAA,EAAAA,GAETC,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IACEL,WAAW,6FAA6FC,CAAgB;AAAA,IACxHM,OAAO;AAAA,MAAER,OAAAA;AAAAA,MAAOS,UAAU;AAAA,IAAA;AAAA,EAAQ,GAEjCX,EAAAA,CACE,CACF;AAET;"}
|
package/dist/index15.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import m, { useState as N, useRef as $, useEffect as P } from "react";
|
|
2
2
|
import V, { flushSync as Z } from "react-dom";
|
|
3
3
|
import { useStableId as O } from "./index190.js";
|
|
4
|
-
import { useDismissOnFocusOut as ee } from "./
|
|
4
|
+
import { useDismissOnFocusOut as ee } from "./index195.js";
|
|
5
5
|
function I() {
|
|
6
6
|
return I = Object.assign ? Object.assign.bind() : function(g) {
|
|
7
7
|
for (var h = 1; h < arguments.length; h++) {
|
package/dist/index18.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import F, { forwardRef as at, useState as A, useRef as J, useEffect as H, useImperativeHandle as lt } from "react";
|
|
2
2
|
import ft from "react-dom";
|
|
3
3
|
import { getA11yNameAttributes as ut } from "./index71.js";
|
|
4
|
-
import { useDismissOnFocusOut as pt } from "./
|
|
4
|
+
import { useDismissOnFocusOut as pt } from "./index195.js";
|
|
5
5
|
function O() {
|
|
6
6
|
return O = Object.assign ? Object.assign.bind() : function(y) {
|
|
7
7
|
for (var k = 1; k < arguments.length; k++) {
|
package/dist/index188.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import N from "./
|
|
2
|
-
import R from "./
|
|
3
|
-
import D from "./
|
|
4
|
-
import { SVGInjector as A } from "./
|
|
5
|
-
import { p as t } from "./
|
|
1
|
+
import N from "./index233.js";
|
|
2
|
+
import R from "./index234.js";
|
|
3
|
+
import D from "./index235.js";
|
|
4
|
+
import { SVGInjector as A } from "./index236.js";
|
|
5
|
+
import { p as t } from "./index237.js";
|
|
6
6
|
import * as h from "react";
|
|
7
7
|
var O = function(s) {
|
|
8
8
|
var o = s?.ownerDocument || document;
|
package/dist/index192.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useRef as n } from "react";
|
|
2
|
+
import { useFocusTrap as d } from "./index229.js";
|
|
3
|
+
import { useDismissOnEscape as u } from "./index199.js";
|
|
4
|
+
import { getA11yNameAttributes as c } from "./index71.js";
|
|
5
|
+
import { useStableId as f } from "./index190.js";
|
|
6
|
+
function I({
|
|
7
|
+
isOpen: o,
|
|
8
|
+
onDismiss: a,
|
|
9
|
+
title: t,
|
|
10
|
+
ariaLabel: s,
|
|
11
|
+
titleIdPrefix: i = "modal-title",
|
|
12
|
+
initialFocus: m = "first"
|
|
13
|
+
}) {
|
|
14
|
+
const e = n(null), r = f(void 0, i);
|
|
15
|
+
d({
|
|
16
|
+
enabled: o,
|
|
17
|
+
containerRef: e,
|
|
18
|
+
restoreFocus: !0,
|
|
19
|
+
initialFocus: m
|
|
20
|
+
}), u({
|
|
21
|
+
containerRef: e,
|
|
22
|
+
onDismiss: a,
|
|
23
|
+
enabled: o
|
|
24
|
+
});
|
|
25
|
+
const l = {
|
|
26
|
+
role: "dialog",
|
|
27
|
+
"aria-modal": !0,
|
|
28
|
+
tabIndex: -1,
|
|
29
|
+
...c({
|
|
30
|
+
ariaLabelledBy: t ? r : void 0,
|
|
31
|
+
ariaLabel: t ? void 0 : s
|
|
32
|
+
})
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
containerRef: e,
|
|
36
|
+
titleId: r,
|
|
37
|
+
dialogProps: l
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
I as useModalA11y
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=index192.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index192.js","sources":["../src/utils/a11y/useModalA11y.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { useFocusTrap } from './useFocusTrap';\nimport { useDismissOnEscape } from './useDismissOnEscape';\nimport { getA11yNameAttributes } from './accessibleName';\nimport { useStableId } from 'src/utils/useStableId';\n\nexport interface UseModalA11yOptions {\n /**\n * Whether the modal is open. Controls focus trap and Escape handler activation.\n */\n isOpen: boolean;\n /**\n * Called when Escape is pressed while focus is within the modal.\n * If undefined, Escape dismissal is disabled.\n */\n onDismiss?: () => void;\n /**\n * Visible title text. When provided, the dialog is labelled via aria-labelledby\n * pointing to the title element (preferred over aria-label when a visible heading exists).\n * Render `<h2 id={titleId}>` inside the modal to complete the association.\n */\n title?: string;\n /**\n * aria-label for modals without a visible title heading.\n * Only used when `title` is not provided.\n */\n ariaLabel?: string;\n /**\n * Prefix for the auto-generated title element id. Default: 'modal-title'.\n */\n titleIdPrefix?: string;\n /**\n * Initial focus target when the modal opens. Forwarded to useFocusTrap.\n * - 'first': Focus first focusable element (default)\n * - 'container': Focus the dialog container itself\n * - 'none': Skip — browser handles it (e.g. autofocus attribute on inner element)\n * - CSS selector string: Focus matching element\n * - HTMLElement: Focus specific element\n */\n initialFocus?: 'first' | 'container' | 'none' | string | HTMLElement;\n}\n\nexport interface UseModalA11yReturn {\n /**\n * Ref to attach to the dialog container element.\n */\n containerRef: React.RefObject<HTMLDivElement | null>;\n /**\n * Stable ID to set on the visible title element: `<h2 id={titleId}>`.\n * Only relevant when `title` is provided.\n */\n titleId: string;\n /**\n * Spread onto the dialog container element.\n * Includes: role=\"dialog\", aria-modal, tabIndex, aria-labelledby or aria-label.\n */\n dialogProps: {\n role: 'dialog';\n 'aria-modal': true;\n tabIndex: number;\n [key: string]: unknown;\n };\n}\n\n/**\n * Bundles all WCAG dialog semantics into a single hook.\n *\n * Handles:\n * - Stable ID for title element (aria-labelledby association)\n * - Focus trap: moves focus into modal on open, wraps Tab, restores focus on close\n * - Escape dismissal: calls onDismiss when Escape is pressed within the modal\n * - dialogProps: role=\"dialog\", aria-modal, tabIndex, aria-labelledby / aria-label\n *\n * @example\n * ```tsx\n * const MyModal = ({ isOpen, onClose, title }) => {\n * const { containerRef, titleId, dialogProps } = useModalA11y({\n * isOpen,\n * onDismiss: onClose,\n * title,\n * });\n *\n * return (\n * <div ref={containerRef} {...dialogProps} className=\"modal-content\">\n * <h2 id={titleId}>{title}</h2>\n * ...\n * </div>\n * );\n * };\n * ```\n *\n * @example Modal without a visible title\n * ```tsx\n * const { containerRef, titleId, dialogProps } = useModalA11y({\n * isOpen,\n * onDismiss: onClose,\n * ariaLabel: 'Upload document',\n * });\n * ```\n *\n * @example Custom initial focus (specific button) or skip (autofocus)\n * ```tsx\n * useModalA11y({ isOpen, onDismiss, title, initialFocus: '.my-cta-btn' });\n * useModalA11y({ isOpen, onDismiss, title, initialFocus: 'none' }); // autofocus on inner element\n * ```\n */\nexport function useModalA11y({\n isOpen,\n onDismiss,\n title,\n ariaLabel,\n titleIdPrefix = 'modal-title',\n initialFocus = 'first',\n}: UseModalA11yOptions): UseModalA11yReturn {\n const containerRef = useRef<HTMLDivElement>(null);\n const titleId = useStableId(undefined, titleIdPrefix);\n\n useFocusTrap({\n enabled: isOpen,\n containerRef,\n restoreFocus: true,\n initialFocus,\n });\n\n useDismissOnEscape({\n containerRef,\n onDismiss,\n enabled: isOpen,\n });\n\n const nameAttrs = getA11yNameAttributes({\n ariaLabelledBy: title ? titleId : undefined,\n ariaLabel: !title ? ariaLabel : undefined,\n });\n\n const dialogProps = {\n role: 'dialog' as const,\n 'aria-modal': true as const,\n tabIndex: -1,\n ...nameAttrs,\n };\n\n return { containerRef, titleId, dialogProps };\n}\n"],"names":["useRef","useFocusTrap","useDismissOnEscape","getA11yNameAttributes","useStableId","useModalA11y","isOpen","onDismiss","title","ariaLabel","titleIdPrefix","initialFocus","containerRef","titleId","undefined","enabled","restoreFocus","dialogProps","role","tabIndex","ariaLabelledBy","nameAttrs"],"mappings":"AA0GO,SAAA,UAAAA,SAAA;AAAA,SAAA,gBAAAC,SAAA;AAAA,SAAA,sBAAAC,SAAA;AAAA,SAAA,yBAAAC,SAAA;AAAA,SAAA,eAAAC,SAAA;AAAA,SAASC,EAAa;AAAA,EAC3BC,QAAAA;AAAAA,EACAC,WAAAA;AAAAA,EACAC,OAAAA;AAAAA,EACAC,WAAAA;AAAAA,EACAC,eAAAA,IAAgB;AAAA,EAChBC,cAAAA,IAAe;AACI,GAAuB;AAC1C,QAAMC,IAAeZ,EAAuB,IAAI,GAC1Ca,IAAUT,EAAYU,QAAWJ,CAAa;AAEpDT,EAAAA,EAAa;AAAA,IACXc,SAAST;AAAAA,IACTM,cAAAA;AAAAA,IACAI,cAAc;AAAA,IACdL,cAAAA;AAAAA,EAAAA,CACD,GAEDT,EAAmB;AAAA,IACjBU,cAAAA;AAAAA,IACAL,WAAAA;AAAAA,IACAQ,SAAST;AAAAA,EAAAA,CACV;AAOD,QAAMW,IAAc;AAAA,IAClBC,MAAM;AAAA,IACN,cAAc;AAAA,IACdC,UAAU;AAAA,IACV,GATgBhB,EAAsB;AAAA,MACtCiB,gBAAgBZ,IAAQK,IAAUC;AAAAA,MAClCL,WAAYD,IAAoBM,SAAZL;AAAAA,IAAYK,CACjC;AAAA,EAMIO;AAGL,SAAO;AAAA,IAAET,cAAAA;AAAAA,IAAcC,SAAAA;AAAAA,IAASI,aAAAA;AAAAA,EAAAA;AAClC;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"index195.js","sources":["../src/utils/a11y/useDismissOnFocusOut.ts"],"sourcesContent":["import * as React from 'react';\n\nexport type UseDismissOnFocusOutOptions = {\n /**\n * Disable all handlers (no-ops). Useful when a component provides alternate\n * focus/keyboard behavior (e.g., disabled-trigger tooltip wrapper).\n */\n disabled?: boolean;\n /**\n * Called when focus enters anywhere within the target.\n */\n onFocusIn?: () => void;\n /**\n * Called when focus leaves the target (i.e., focus moves to an element\n * outside the currentTarget).\n */\n onFocusOut?: () => void;\n /**\n * Called when Escape is pressed while focus is within the target.\n */\n onEscape?: () => void;\n /**\n * Whether Escape should trigger dismissal. Default: true.\n */\n closeOnEscape?: boolean;\n};\n\nexport type UseDismissOnFocusOutReturn<T extends HTMLElement = HTMLElement> = {\n onFocusCapture: (e: React.FocusEvent<T>) => void;\n onBlurCapture: (e: React.FocusEvent<T>) => void;\n onKeyDownCapture: (e: React.KeyboardEvent<T>) => void;\n};\n\n/**\n * Returns capture-phase handlers to \"show on focus within\" and \"dismiss on focus out\",\n * with optional Escape-to-dismiss.\n *\n * Intended for non-interactive surfaces like tooltips where content should remain\n * visible while focus stays within the wrapper.\n */\nexport function useDismissOnFocusOut<T extends HTMLElement = HTMLElement>({\n disabled = false,\n onFocusIn,\n onFocusOut,\n onEscape,\n closeOnEscape = true\n}: UseDismissOnFocusOutOptions): UseDismissOnFocusOutReturn<T> {\n const onFocusCapture = React.useCallback(\n (_e: React.FocusEvent<T>) => {\n if (disabled) return;\n onFocusIn?.();\n },\n [disabled, onFocusIn]\n );\n\n const onBlurCapture = React.useCallback(\n (e: React.FocusEvent<T>) => {\n if (disabled) return;\n\n const nextFocused = e.relatedTarget as Node | null;\n if (nextFocused && e.currentTarget.contains(nextFocused)) return;\n\n onFocusOut?.();\n },\n [disabled, onFocusOut]\n );\n\n const onKeyDownCapture = React.useCallback(\n (e: React.KeyboardEvent<T>) => {\n if (disabled || !closeOnEscape || e.key !== 'Escape') return;\n\n e.preventDefault();\n onEscape?.();\n },\n [disabled, closeOnEscape, onEscape]\n );\n\n return { onFocusCapture, onBlurCapture, onKeyDownCapture };\n}\n\n"],"names":["React","useDismissOnFocusOut","disabled","onFocusIn","onFocusOut","onEscape","closeOnEscape","onFocusCapture","useCallback","_e","onBlurCapture","e","nextFocused","relatedTarget","currentTarget","contains","onKeyDownCapture","key","preventDefault"],"mappings":"AAwCO,YAAAA,OAAA;AAAA,SAASC,EAA0D;AAAA,EACxEC,UAAAA,IAAW;AAAA,EACXC,WAAAA;AAAAA,EACAC,YAAAA;AAAAA,EACAC,UAAAA;AAAAA,EACAC,eAAAA,IAAgB;AACW,GAAkC;AAC7D,QAAMC,IAAiBP,EAAMQ,YAC3B,CAACC,MAA4B;AAC3B,IAAIP,KACJC,IAAAA;AAAAA,EACF,GACA,CAACD,GAAUC,CAAS,CACtB,GAEMO,IAAgBV,EAAMQ,YAC1B,CAACG,MAA2B;AAC1B,QAAIT,EAAU;AAEd,UAAMU,IAAcD,EAAEE;AACtB,IAAID,KAAeD,EAAEG,cAAcC,SAASH,CAAW,KAEvDR,IAAAA;AAAAA,EACF,GACA,CAACF,GAAUE,CAAU,CACvB,GAEMY,IAAmBhB,EAAMQ,YAC7B,CAACG,MAA8B;AAC7B,IAAIT,KAAY,CAACI,KAAiBK,EAAEM,QAAQ,aAE5CN,EAAEO,eAAAA,GACFb,IAAAA;AAAAA,EACF,GACA,CAACH,GAAUI,GAAeD,CAAQ,CACpC;AAEA,SAAO;AAAA,IAAEE,gBAAAA;AAAAA,IAAgBG,eAAAA;AAAAA,IAAeM,kBAAAA;AAAAA,EAAAA;AAC1C;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useRef as u, useCallback as f, useEffect as P } from "react";
|
|
2
|
-
import { useComboboxNavigation as y } from "./
|
|
3
|
-
import { useDismissOnFocusOut as R } from "./
|
|
2
|
+
import { useComboboxNavigation as y } from "./index231.js";
|
|
3
|
+
import { useDismissOnFocusOut as R } from "./index195.js";
|
|
4
4
|
function M({
|
|
5
5
|
items: l,
|
|
6
6
|
isOpen: t,
|
|
@@ -84,4 +84,4 @@ function M({
|
|
|
84
84
|
export {
|
|
85
85
|
M as useCombobox
|
|
86
86
|
};
|
|
87
|
-
//# sourceMappingURL=
|
|
87
|
+
//# sourceMappingURL=index197.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index196.js","sources":["../src/utils/a11y/useCombobox.ts"],"sourcesContent":["import { useRef, useCallback, useEffect } from 'react';\nimport type { RefObject } from 'react';\nimport { useComboboxNavigation } from './useComboboxNavigation';\nimport { useDismissOnFocusOut } from './useDismissOnFocusOut';\nimport type { UseDismissOnFocusOutReturn } from './useDismissOnFocusOut';\n\nexport interface UseComboboxOptions<T = any> {\n /**\n * Array of items to navigate through\n */\n items: T[];\n \n /**\n * Whether the dropdown is currently open\n */\n isOpen: boolean;\n \n /**\n * Callback to change the open state\n */\n onOpenChange: (open: boolean) => void;\n \n /**\n * Callback when an item is selected (Enter key)\n */\n onSelect: (item: T, index: number) => void;\n \n /**\n * Stable ID for the listbox element\n */\n listboxId: string;\n \n /**\n * Whether to wrap around at the ends of the list.\n * Default: true\n */\n loop?: boolean;\n \n /**\n * Whether keyboard navigation is disabled\n * (e.g., for custom rendered content)\n */\n disabled?: boolean;\n \n /**\n * CSS selector for option elements (default: '[role=\"option\"]')\n */\n optionSelector?: string;\n \n /**\n * Whether the listbox has any items to show\n * Used for aria-expanded logic\n * Default: items.length > 0\n */\n hasItems?: boolean;\n}\n\nexport interface UseComboboxReturn {\n /**\n * Props to spread on the container element (handles dismiss on focus out)\n */\n containerProps: UseDismissOnFocusOutReturn<HTMLElement>;\n \n /**\n * Props to spread on the combobox input element\n */\n inputProps: {\n role: 'combobox';\n 'aria-expanded': boolean;\n 'aria-haspopup': 'listbox';\n 'aria-controls': string | undefined;\n 'aria-autocomplete': 'list';\n 'aria-activedescendant': string | undefined;\n onKeyDown: (e: React.KeyboardEvent) => void;\n };\n \n /**\n * Props to spread on the listbox element\n */\n listboxProps: {\n id: string;\n role: 'listbox';\n ref: RefObject<HTMLDivElement | null>;\n onMouseDownCapture: (e: React.MouseEvent) => void;\n onMouseUpCapture: (e: React.MouseEvent) => void;\n onMouseLeave: (e: React.MouseEvent) => void;\n };\n \n /**\n * Generate props for an option element at the given index\n * @param selected - Whether this option is the currently selected/chosen value (not keyboard highlight)\n */\n getOptionProps: (index: number, selected?: boolean) => {\n id: string;\n role: 'option';\n 'aria-selected': boolean;\n };\n \n /**\n * Currently highlighted index (-1 if none)\n */\n highlightedIndex: number;\n \n /**\n * Set the highlighted index manually\n */\n setHighlightedIndex: (index: number | ((prev: number) => number)) => void;\n \n /**\n * Generate stable ID for an option\n */\n getOptionId: (listboxId: string, index: number) => string;\n}\n\n/**\n * Comprehensive hook for implementing WAI-ARIA combobox pattern.\n * \n * Combines:\n * - Keyboard navigation (Arrow Up/Down, Enter, Escape, Tab)\n * - Focus management and dismissal\n * - ARIA attributes for accessibility\n * - Auto-scroll highlighted item into view\n * \n * This hook provides a complete, batteries-included solution for building\n * accessible combobox components (autocomplete, select, search with suggestions, etc.)\n * \n * @example Basic usage\n * ```tsx\n * const MyCombobox = () => {\n * const [isOpen, setIsOpen] = useState(false);\n * const [items, setItems] = useState(['Apple', 'Banana', 'Cherry']);\n * \n * const {\n * containerProps,\n * inputProps,\n * listboxProps,\n * getOptionProps,\n * highlightedIndex\n * } = useCombobox({\n * items,\n * isOpen,\n * onOpenChange: setIsOpen,\n * onSelect: (item) => console.log('Selected:', item),\n * listboxId: 'my-listbox'\n * });\n * \n * return (\n * <div {...containerProps}>\n * <input {...inputProps} />\n * {isOpen && (\n * <div {...listboxProps}>\n * {items.map((item, i) => (\n * <div key={i} {...getOptionProps(i)}>\n * {item}\n * </div>\n * ))}\n * </div>\n * )}\n * </div>\n * );\n * };\n * ```\n * \n * @example With custom ARIA labels and handlers\n * ```tsx\n * const MySearchBox = () => {\n * const [query, setQuery] = useState('');\n * const [suggestions, setSuggestions] = useState([]);\n * const [isOpen, setIsOpen] = useState(false);\n * \n * const { containerProps, inputProps, listboxProps, getOptionProps } = useCombobox({\n * items: suggestions,\n * isOpen,\n * onOpenChange: setIsOpen,\n * onSelect: (suggestion) => {\n * setQuery(suggestion);\n * setIsOpen(false);\n * },\n * listboxId: 'search-suggestions'\n * });\n * \n * return (\n * <div {...containerProps}>\n * <input\n * {...inputProps}\n * value={query}\n * onChange={(e) => setQuery(e.target.value)}\n * aria-label=\"Search\"\n * />\n * {isOpen && suggestions.length > 0 && (\n * <div {...listboxProps} aria-label=\"Search suggestions\">\n * {suggestions.map((suggestion, i) => (\n * <div\n * key={i}\n * {...getOptionProps(i)}\n * onClick={() => {\n * setQuery(suggestion);\n * setIsOpen(false);\n * }}\n * >\n * {suggestion}\n * </div>\n * ))}\n * </div>\n * )}\n * </div>\n * );\n * };\n * ```\n */\nexport function useCombobox<T = any>({\n items,\n isOpen,\n onOpenChange,\n onSelect,\n listboxId,\n loop = true,\n disabled = false,\n optionSelector = '[role=\"option\"]',\n hasItems\n}: UseComboboxOptions<T>): UseComboboxReturn {\n const listboxRef = useRef<HTMLDivElement | null>(null);\n const pointerDownInListboxRef = useRef(false);\n const tabKeyPressedRef = useRef(false);\n \n // Determine if we should show as expanded\n const shouldShowExpanded = hasItems !== undefined ? hasItems : items.length > 0;\n \n // Close dropdown callback\n const closeDropdown = useCallback(() => {\n onOpenChange(false);\n }, [onOpenChange]);\n\n // Ensure pointer state doesn't get stuck when listbox unmounts\n useEffect(() => {\n if (!isOpen) {\n pointerDownInListboxRef.current = false;\n }\n }, [isOpen]);\n \n // Keyboard navigation with aria-activedescendant\n const navigation = useComboboxNavigation<T>({\n items,\n isOpen,\n onSelect,\n onClose: closeDropdown,\n onOpen: () => onOpenChange(true),\n loop,\n disabled,\n listboxRef,\n optionSelector\n });\n \n // Focus out / Escape dismissal\n const dismissHandlers = useDismissOnFocusOut({\n onFocusOut: closeDropdown,\n onEscape: closeDropdown,\n disabled: !isOpen\n });\n\n const containerProps: UseDismissOnFocusOutReturn<HTMLElement> = {\n ...dismissHandlers,\n onBlurCapture: (e) => {\n // Clicking inside a listbox option can blur the input (relatedTarget is null),\n // which would dismiss before the click handler runs. Prevent that.\n if (pointerDownInListboxRef.current) return;\n \n // Tab key pressed - let Tab handler close dropdown, skip blur detection\n if (tabKeyPressedRef.current) {\n tabKeyPressedRef.current = false;\n return;\n }\n \n dismissHandlers.onBlurCapture(e);\n }\n };\n \n // Build input props\n const inputProps = {\n role: 'combobox' as const,\n 'aria-expanded': isOpen && shouldShowExpanded,\n 'aria-haspopup': 'listbox' as const,\n 'aria-controls': isOpen ? listboxId : undefined,\n 'aria-autocomplete': 'list' as const,\n 'aria-activedescendant': \n navigation.highlightedIndex >= 0 \n ? navigation.getOptionId(listboxId, navigation.highlightedIndex) \n : undefined,\n onKeyDown: (e: React.KeyboardEvent) => {\n // Set flag when Tab is pressed (before blur fires)\n if (e.key === 'Tab') {\n tabKeyPressedRef.current = true;\n }\n navigation.handleKeyDown(e);\n }\n };\n \n // Build listbox props\n const listboxProps = {\n id: listboxId,\n role: 'listbox' as const,\n ref: listboxRef,\n onMouseDownCapture: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = true;\n },\n onMouseUpCapture: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = false;\n },\n onMouseLeave: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = false;\n }\n };\n \n // Option props generator\n const getOptionProps = useCallback(\n (index: number, selected: boolean = false) => ({\n id: navigation.getOptionId(listboxId, index),\n role: 'option' as const,\n 'aria-selected': selected\n }),\n [navigation.getOptionId, listboxId]\n );\n \n return {\n containerProps,\n inputProps,\n listboxProps,\n getOptionProps,\n highlightedIndex: navigation.highlightedIndex,\n setHighlightedIndex: navigation.setHighlightedIndex,\n getOptionId: navigation.getOptionId\n };\n}\n"],"names":["useRef","useCallback","useEffect","useComboboxNavigation","useDismissOnFocusOut","useCombobox","items","isOpen","onOpenChange","onSelect","listboxId","loop","disabled","optionSelector","hasItems","listboxRef","pointerDownInListboxRef","tabKeyPressedRef","shouldShowExpanded","undefined","length","closeDropdown","current","navigation","onClose","onOpen","dismissHandlers","onFocusOut","onEscape","containerProps","onBlurCapture","e","inputProps","role","highlightedIndex","getOptionId","onKeyDown","key","handleKeyDown","listboxProps","id","ref","onMouseDownCapture","_e","onMouseUpCapture","onMouseLeave","getOptionProps","index","selected","setHighlightedIndex"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index197.js","sources":["../src/utils/a11y/useCombobox.ts"],"sourcesContent":["import { useRef, useCallback, useEffect } from 'react';\nimport type { RefObject } from 'react';\nimport { useComboboxNavigation } from './useComboboxNavigation';\nimport { useDismissOnFocusOut } from './useDismissOnFocusOut';\nimport type { UseDismissOnFocusOutReturn } from './useDismissOnFocusOut';\n\nexport interface UseComboboxOptions<T = any> {\n /**\n * Array of items to navigate through\n */\n items: T[];\n \n /**\n * Whether the dropdown is currently open\n */\n isOpen: boolean;\n \n /**\n * Callback to change the open state\n */\n onOpenChange: (open: boolean) => void;\n \n /**\n * Callback when an item is selected (Enter key)\n */\n onSelect: (item: T, index: number) => void;\n \n /**\n * Stable ID for the listbox element\n */\n listboxId: string;\n \n /**\n * Whether to wrap around at the ends of the list.\n * Default: true\n */\n loop?: boolean;\n \n /**\n * Whether keyboard navigation is disabled\n * (e.g., for custom rendered content)\n */\n disabled?: boolean;\n \n /**\n * CSS selector for option elements (default: '[role=\"option\"]')\n */\n optionSelector?: string;\n \n /**\n * Whether the listbox has any items to show\n * Used for aria-expanded logic\n * Default: items.length > 0\n */\n hasItems?: boolean;\n}\n\nexport interface UseComboboxReturn {\n /**\n * Props to spread on the container element (handles dismiss on focus out)\n */\n containerProps: UseDismissOnFocusOutReturn<HTMLElement>;\n \n /**\n * Props to spread on the combobox input element\n */\n inputProps: {\n role: 'combobox';\n 'aria-expanded': boolean;\n 'aria-haspopup': 'listbox';\n 'aria-controls': string | undefined;\n 'aria-autocomplete': 'list';\n 'aria-activedescendant': string | undefined;\n onKeyDown: (e: React.KeyboardEvent) => void;\n };\n \n /**\n * Props to spread on the listbox element\n */\n listboxProps: {\n id: string;\n role: 'listbox';\n ref: RefObject<HTMLDivElement | null>;\n onMouseDownCapture: (e: React.MouseEvent) => void;\n onMouseUpCapture: (e: React.MouseEvent) => void;\n onMouseLeave: (e: React.MouseEvent) => void;\n };\n \n /**\n * Generate props for an option element at the given index\n * @param selected - Whether this option is the currently selected/chosen value (not keyboard highlight)\n */\n getOptionProps: (index: number, selected?: boolean) => {\n id: string;\n role: 'option';\n 'aria-selected': boolean;\n };\n \n /**\n * Currently highlighted index (-1 if none)\n */\n highlightedIndex: number;\n \n /**\n * Set the highlighted index manually\n */\n setHighlightedIndex: (index: number | ((prev: number) => number)) => void;\n \n /**\n * Generate stable ID for an option\n */\n getOptionId: (listboxId: string, index: number) => string;\n}\n\n/**\n * Comprehensive hook for implementing WAI-ARIA combobox pattern.\n * \n * Combines:\n * - Keyboard navigation (Arrow Up/Down, Enter, Escape, Tab)\n * - Focus management and dismissal\n * - ARIA attributes for accessibility\n * - Auto-scroll highlighted item into view\n * \n * This hook provides a complete, batteries-included solution for building\n * accessible combobox components (autocomplete, select, search with suggestions, etc.)\n * \n * @example Basic usage\n * ```tsx\n * const MyCombobox = () => {\n * const [isOpen, setIsOpen] = useState(false);\n * const [items, setItems] = useState(['Apple', 'Banana', 'Cherry']);\n * \n * const {\n * containerProps,\n * inputProps,\n * listboxProps,\n * getOptionProps,\n * highlightedIndex\n * } = useCombobox({\n * items,\n * isOpen,\n * onOpenChange: setIsOpen,\n * onSelect: (item) => console.log('Selected:', item),\n * listboxId: 'my-listbox'\n * });\n * \n * return (\n * <div {...containerProps}>\n * <input {...inputProps} />\n * {isOpen && (\n * <div {...listboxProps}>\n * {items.map((item, i) => (\n * <div key={i} {...getOptionProps(i)}>\n * {item}\n * </div>\n * ))}\n * </div>\n * )}\n * </div>\n * );\n * };\n * ```\n * \n * @example With custom ARIA labels and handlers\n * ```tsx\n * const MySearchBox = () => {\n * const [query, setQuery] = useState('');\n * const [suggestions, setSuggestions] = useState([]);\n * const [isOpen, setIsOpen] = useState(false);\n * \n * const { containerProps, inputProps, listboxProps, getOptionProps } = useCombobox({\n * items: suggestions,\n * isOpen,\n * onOpenChange: setIsOpen,\n * onSelect: (suggestion) => {\n * setQuery(suggestion);\n * setIsOpen(false);\n * },\n * listboxId: 'search-suggestions'\n * });\n * \n * return (\n * <div {...containerProps}>\n * <input\n * {...inputProps}\n * value={query}\n * onChange={(e) => setQuery(e.target.value)}\n * aria-label=\"Search\"\n * />\n * {isOpen && suggestions.length > 0 && (\n * <div {...listboxProps} aria-label=\"Search suggestions\">\n * {suggestions.map((suggestion, i) => (\n * <div\n * key={i}\n * {...getOptionProps(i)}\n * onClick={() => {\n * setQuery(suggestion);\n * setIsOpen(false);\n * }}\n * >\n * {suggestion}\n * </div>\n * ))}\n * </div>\n * )}\n * </div>\n * );\n * };\n * ```\n */\nexport function useCombobox<T = any>({\n items,\n isOpen,\n onOpenChange,\n onSelect,\n listboxId,\n loop = true,\n disabled = false,\n optionSelector = '[role=\"option\"]',\n hasItems\n}: UseComboboxOptions<T>): UseComboboxReturn {\n const listboxRef = useRef<HTMLDivElement | null>(null);\n const pointerDownInListboxRef = useRef(false);\n const tabKeyPressedRef = useRef(false);\n \n // Determine if we should show as expanded\n const shouldShowExpanded = hasItems !== undefined ? hasItems : items.length > 0;\n \n // Close dropdown callback\n const closeDropdown = useCallback(() => {\n onOpenChange(false);\n }, [onOpenChange]);\n\n // Ensure pointer state doesn't get stuck when listbox unmounts\n useEffect(() => {\n if (!isOpen) {\n pointerDownInListboxRef.current = false;\n }\n }, [isOpen]);\n \n // Keyboard navigation with aria-activedescendant\n const navigation = useComboboxNavigation<T>({\n items,\n isOpen,\n onSelect,\n onClose: closeDropdown,\n onOpen: () => onOpenChange(true),\n loop,\n disabled,\n listboxRef,\n optionSelector\n });\n \n // Focus out / Escape dismissal\n const dismissHandlers = useDismissOnFocusOut({\n onFocusOut: closeDropdown,\n onEscape: closeDropdown,\n disabled: !isOpen\n });\n\n const containerProps: UseDismissOnFocusOutReturn<HTMLElement> = {\n ...dismissHandlers,\n onBlurCapture: (e) => {\n // Clicking inside a listbox option can blur the input (relatedTarget is null),\n // which would dismiss before the click handler runs. Prevent that.\n if (pointerDownInListboxRef.current) return;\n \n // Tab key pressed - let Tab handler close dropdown, skip blur detection\n if (tabKeyPressedRef.current) {\n tabKeyPressedRef.current = false;\n return;\n }\n \n dismissHandlers.onBlurCapture(e);\n }\n };\n \n // Build input props\n const inputProps = {\n role: 'combobox' as const,\n 'aria-expanded': isOpen && shouldShowExpanded,\n 'aria-haspopup': 'listbox' as const,\n 'aria-controls': isOpen ? listboxId : undefined,\n 'aria-autocomplete': 'list' as const,\n 'aria-activedescendant': \n navigation.highlightedIndex >= 0 \n ? navigation.getOptionId(listboxId, navigation.highlightedIndex) \n : undefined,\n onKeyDown: (e: React.KeyboardEvent) => {\n // Set flag when Tab is pressed (before blur fires)\n if (e.key === 'Tab') {\n tabKeyPressedRef.current = true;\n }\n navigation.handleKeyDown(e);\n }\n };\n \n // Build listbox props\n const listboxProps = {\n id: listboxId,\n role: 'listbox' as const,\n ref: listboxRef,\n onMouseDownCapture: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = true;\n },\n onMouseUpCapture: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = false;\n },\n onMouseLeave: (_e: React.MouseEvent) => {\n pointerDownInListboxRef.current = false;\n }\n };\n \n // Option props generator\n const getOptionProps = useCallback(\n (index: number, selected: boolean = false) => ({\n id: navigation.getOptionId(listboxId, index),\n role: 'option' as const,\n 'aria-selected': selected\n }),\n [navigation.getOptionId, listboxId]\n );\n \n return {\n containerProps,\n inputProps,\n listboxProps,\n getOptionProps,\n highlightedIndex: navigation.highlightedIndex,\n setHighlightedIndex: navigation.setHighlightedIndex,\n getOptionId: navigation.getOptionId\n };\n}\n"],"names":["useRef","useCallback","useEffect","useComboboxNavigation","useDismissOnFocusOut","useCombobox","items","isOpen","onOpenChange","onSelect","listboxId","loop","disabled","optionSelector","hasItems","listboxRef","pointerDownInListboxRef","tabKeyPressedRef","shouldShowExpanded","undefined","length","closeDropdown","current","navigation","onClose","onOpen","dismissHandlers","onFocusOut","onEscape","containerProps","onBlurCapture","e","inputProps","role","highlightedIndex","getOptionId","onKeyDown","key","handleKeyDown","listboxProps","id","ref","onMouseDownCapture","_e","onMouseUpCapture","onMouseLeave","getOptionProps","index","selected","setHighlightedIndex"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"index199.js","sources":["../src/utils/a11y/useDismissOnEscape.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport type { RefObject } from 'react';\n\nexport interface UseDismissOnEscapeOptions<T extends HTMLElement = HTMLElement> {\n /**\n * Container element ref to check if focus is within.\n * Escape will only trigger if focus is within this container.\n */\n containerRef: RefObject<T | null>;\n /**\n * Callback when Escape key is pressed and focus is within container.\n */\n onDismiss?: () => void;\n /**\n * Whether the Escape handler is active.\n * Default: true\n */\n enabled?: boolean;\n /**\n * Whether to call preventDefault() when handling Escape.\n * Default: true\n */\n preventDefault?: boolean;\n /**\n * Whether to call stopPropagation() when handling Escape.\n * Default: true\n */\n stopPropagation?: boolean;\n}\n\n/**\n * Hook to handle Escape key dismissal when focus is within a container.\n * \n * This is a UX pattern: if user is interacting with an overlay/sidebar\n * (indicated by focus being within it), Escape should close it.\n * \n * @example\n * ```tsx\n * const MySidebar = ({ isOpen, onClose }) => {\n * const containerRef = useRef<HTMLDivElement>(null);\n * \n * useDismissOnEscape({\n * containerRef,\n * onDismiss: onClose,\n * enabled: isOpen\n * });\n * \n * return <div ref={containerRef}>...</div>;\n * };\n * ```\n */\nexport function useDismissOnEscape<T extends HTMLElement = HTMLElement>({\n containerRef,\n onDismiss,\n enabled = true,\n preventDefault = true,\n stopPropagation = true\n}: UseDismissOnEscapeOptions<T>): void {\n useEffect(() => {\n if (!enabled || !onDismiss) return;\n \n const container = containerRef.current;\n if (!container) return;\n\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && container.contains(document.activeElement)) {\n preventDefault && e.preventDefault();\n stopPropagation && e.stopPropagation();\n onDismiss();\n }\n };\n\n document.addEventListener('keydown', handleEscape, { capture: true });\n return () => document.removeEventListener('keydown', handleEscape, { capture: true });\n }, [enabled, onDismiss, containerRef, preventDefault, stopPropagation]);\n}\n"],"names":["useEffect","useDismissOnEscape","containerRef","onDismiss","enabled","preventDefault","stopPropagation","container","current","handleEscape","e","key","contains","document","activeElement","addEventListener","capture","removeEventListener"],"mappings":"AAmDO,SAAA,aAAAA,SAAA;AAAA,SAASC,EAAwD;AAAA,EACtEC,cAAAA;AAAAA,EACAC,WAAAA;AAAAA,EACAC,SAAAA,IAAU;AAAA,EACVC,gBAAAA,IAAiB;AAAA,EACjBC,iBAAAA,IAAkB;AACU,GAAS;AACrCN,EAAAA,EAAU,MAAM;AACd,QAAI,CAACI,KAAW,CAACD,EAAW;AAE5B,UAAMI,IAAYL,EAAaM;AAC/B,QAAI,CAACD,EAAW;AAEhB,UAAME,IAAeA,CAACC,MAAqB;AACzC,MAAIA,EAAEC,QAAQ,YAAYJ,EAAUK,SAASC,SAASC,aAAa,MACjET,KAAkBK,EAAEL,eAAAA,GACpBC,KAAmBI,EAAEJ,gBAAAA,GACrBH,EAAAA;AAAAA,IAEJ;AAEAU,oBAASE,iBAAiB,WAAWN,GAAc;AAAA,MAAEO,SAAS;AAAA,IAAA,CAAM,GAC7D,MAAMH,SAASI,oBAAoB,WAAWR,GAAc;AAAA,MAAEO,SAAS;AAAA,IAAA,CAAM;AAAA,EACtF,GAAG,CAACZ,GAASD,GAAWD,GAAcG,GAAgBC,CAAe,CAAC;AACxE;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"index207.js","sources":["../src/utils/debounce.ts"],"sourcesContent":["export function debounce<T extends (...args: any[]) => void>(func: T, wait: number) {\n let timeout: ReturnType<typeof setTimeout> | null;\n const debounced = (...args: Parameters<T>) => {\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(() => {\n func(...args);\n }, wait);\n };\n debounced.cancel = () => {\n if (timeout) clearTimeout(timeout);\n timeout = null;\n };\n return debounced as T & { cancel: () => void };\n }"],"names":["debounce","func","wait","timeout","debounced","args","setTimeout","cancel"],"mappings":"AAAO,SAASA,EAA6CC,GAASC,GAAc;AAChF,MAAIC;AACJ,QAAMC,IAAYA,IAAIC,MAAwB;AAC5C,IAAIF,kBAAsBA,CAAO,GACjCA,IAAUG,WAAW,MAAM;AACzBL,MAAAA,EAAK,GAAGI,CAAI;AAAA,IACd,GAAGH,CAAI;AAAA,EACT;AACAE,SAAAA,EAAUG,SAAS,MAAM;AACvB,IAAIJ,kBAAsBA,CAAO,GACjCA,IAAU;AAAA,EACZ,GACOC;AACT;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"index215.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"index218.js","sources":["../src/components/NavigationBar/TabButton.tsx"],"sourcesContent":["import React, { forwardRef } from 'react';\nimport { Button } from '../Button';\n\nexport interface TabButtonProps {\n id: string;\n label: string;\n isSelected: boolean;\n isDisabled?: boolean;\n panelId?: string;\n tabIndex: number;\n className?: string;\n automationId?: string;\n onClick: (e: React.MouseEvent<HTMLButtonElement>) => void;\n onFocus: () => void;\n onKeyDown: (e: React.KeyboardEvent<HTMLButtonElement>) => void;\n}\n\n/**\n * Internal TabButton component for NavigationBar.\n * Uses Button (unstyled) internally for consistent activation handling.\n * Supports forwardRef for focus management (roving tabindex).\n */\nexport const TabButton = forwardRef<HTMLButtonElement, TabButtonProps>(\n (\n {\n id,\n label,\n isSelected,\n isDisabled = false,\n panelId,\n tabIndex,\n className = '',\n automationId,\n onClick,\n onFocus,\n onKeyDown\n },\n ref\n ) => {\n return (\n <Button\n ref={ref}\n type=\"unstyled\"\n label={label}\n disabled={isDisabled}\n onClick={onClick}\n className={className}\n automationId={automationId}\n role=\"tab\"\n id={id}\n aria-selected={isSelected}\n {...(panelId ? { 'aria-controls': panelId } : {})}\n tabIndex={tabIndex}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n />\n );\n }\n);\n\nTabButton.displayName = 'TabButton';\n"],"names":["TabButton","id","label","isSelected","isDisabled","panelId","tabIndex","className","automationId","onClick","onFocus","onKeyDown","ref","React","createElement","Button","_extends","type","disabled","role","displayName"],"mappings":";;;;;;;;;;;AAsBO,MAAMA,sBACX,CACE;AAAA,EACEC,IAAAA;AAAAA,EACAC,OAAAA;AAAAA,EACAC,YAAAA;AAAAA,EACAC,YAAAA,IAAa;AAAA,EACbC,SAAAA;AAAAA,EACAC,UAAAA;AAAAA,EACAC,WAAAA,IAAY;AAAA,EACZC,cAAAA;AAAAA,EACAC,SAAAA;AAAAA,EACAC,SAAAA;AAAAA,EACAC,WAAAA;AACF,GACAC,MAGEC,gBAAAA,EAAAC,cAACC,GAAMC,EAAA;AAAA,EACLJ,KAAAA;AAAAA,EACAK,MAAK;AAAA,EACLf,OAAAA;AAAAA,EACAgB,UAAUd;AAAAA,EACVK,SAAAA;AAAAA,EACAF,WAAAA;AAAAA,EACAC,cAAAA;AAAAA,EACAW,MAAK;AAAA,EACLlB,IAAAA;AAAAA,EACA,iBAAeE;AAAAA,GACVE,IAAU;AAAA,EAAE,iBAAiBA;AAAAA,IAAY,IAAE;AAAA,EAChDC,UAAAA;AAAAA,EACAI,SAAAA;AAAAA,EACAC,WAAAA;AAAAA,CAAqB,CACtB,CAGP;AAEAX,EAAUoB,cAAc;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"
|
|
1
|
+
{"version":3,"file":"index227.js","sources":["../src/utils/delay.ts"],"sourcesContent":["/**\n * Delays execution by the specified number of milliseconds\n * @param ms - The number of milliseconds to delay\n * @returns A Promise that resolves after the specified delay\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n} "],"names":["delay","ms","Promise","resolve","setTimeout"],"mappings":"AAKO,SAASA,EAAMC,GAA2B;AAC7C,SAAO,IAAIC,QAAQC,CAAAA,MAAWC,WAAWD,GAASF,CAAE,CAAC;AACzD;"}
|
package/dist/index229.js
CHANGED
|
@@ -1,25 +1,62 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}) {
|
|
8
|
-
if (!e) return [];
|
|
9
|
-
const d = [t ? a : l, ...r].filter(Boolean).join(", "), i = Array.from(e.querySelectorAll(d));
|
|
10
|
-
return s ? i.filter((n) => {
|
|
11
|
-
const o = window.getComputedStyle(n);
|
|
12
|
-
return o.display !== "none" && o.visibility !== "hidden" && o.opacity !== "0" && !n.hasAttribute("hidden") && n.offsetWidth > 0 && n.offsetHeight > 0;
|
|
13
|
-
}) : i;
|
|
1
|
+
import { useRef as E, useLayoutEffect as f } from "react";
|
|
2
|
+
import { getFirstFocusableElement as d, getFocusableElements as g } from "./index230.js";
|
|
3
|
+
function y(t, e) {
|
|
4
|
+
return e === "none" ? null : e === "first" ? d({
|
|
5
|
+
container: t
|
|
6
|
+
}) || t : e === "container" ? t : typeof e == "string" ? t.querySelector(e) : e instanceof HTMLElement ? e : null;
|
|
14
7
|
}
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
function L({
|
|
9
|
+
enabled: t,
|
|
10
|
+
containerRef: e,
|
|
11
|
+
restoreFocus: l = !0,
|
|
12
|
+
initialFocus: i = "first"
|
|
13
|
+
}) {
|
|
14
|
+
const s = E(null), m = E(null);
|
|
15
|
+
return f(() => {
|
|
16
|
+
if (!t) {
|
|
17
|
+
l && s.current && requestAnimationFrame(() => {
|
|
18
|
+
s.current?.focus(), s.current = null;
|
|
19
|
+
});
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const r = e.current;
|
|
23
|
+
r && (s.current = document.activeElement, requestAnimationFrame(() => {
|
|
24
|
+
y(r, i)?.focus();
|
|
25
|
+
}));
|
|
26
|
+
}, [t, e, l, i]), f(() => {
|
|
27
|
+
if (!t) return;
|
|
28
|
+
const r = e.current;
|
|
29
|
+
if (!r) return;
|
|
30
|
+
const o = (n) => {
|
|
31
|
+
if (n.key === "Tab") {
|
|
32
|
+
const u = g({
|
|
33
|
+
container: r
|
|
34
|
+
});
|
|
35
|
+
if (u.length === 0) {
|
|
36
|
+
n.preventDefault(), r.focus();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const c = u[0], a = u[u.length - 1], v = document.activeElement;
|
|
40
|
+
n.shiftKey && v === c ? (n.preventDefault(), a.focus()) : !n.shiftKey && v === a && (n.preventDefault(), c.focus());
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
return document.addEventListener("keydown", o, !0), () => document.removeEventListener("keydown", o, !0);
|
|
44
|
+
}, [t, e]), f(() => {
|
|
45
|
+
if (!t) return;
|
|
46
|
+
const r = e.current;
|
|
47
|
+
if (!r) return;
|
|
48
|
+
const o = (n) => {
|
|
49
|
+
const u = n.target;
|
|
50
|
+
r.contains(u) ? m.current = u : (m.current || d({
|
|
51
|
+
container: r
|
|
52
|
+
}) || r).focus();
|
|
53
|
+
};
|
|
54
|
+
return document.addEventListener("focusin", o, !0), () => document.removeEventListener("focusin", o, !0);
|
|
55
|
+
}, [t, e]), {
|
|
56
|
+
triggerRef: s
|
|
57
|
+
};
|
|
18
58
|
}
|
|
19
59
|
export {
|
|
20
|
-
|
|
21
|
-
a as FOCUSABLE_WITH_ROLES_SELECTOR,
|
|
22
|
-
c as getFirstFocusableElement,
|
|
23
|
-
u as getFocusableElements
|
|
60
|
+
L as useFocusTrap
|
|
24
61
|
};
|
|
25
62
|
//# sourceMappingURL=index229.js.map
|