se-design 1.0.83 → 1.0.84-dev.0
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/assets/style.css +1 -1
- package/dist/components/Avatar/index.d.ts +1 -0
- package/dist/components/InfoTooltip/index.d.ts +6 -1
- package/dist/components/TableLayout/index.d.ts +10 -0
- package/dist/index16.js +4 -4
- package/dist/index16.js.map +1 -1
- package/dist/index18.js +61 -58
- package/dist/index18.js.map +1 -1
- package/dist/index19.js +27 -27
- package/dist/index19.js.map +1 -1
- package/dist/index207.js +16 -15
- package/dist/index207.js.map +1 -1
- package/dist/index215.js +17 -12
- package/dist/index215.js.map +1 -1
- package/dist/index22.js +51 -46
- package/dist/index22.js.map +1 -1
- package/dist/index25.js +257 -212
- package/dist/index25.js.map +1 -1
- package/dist/index28.js +49 -45
- package/dist/index28.js.map +1 -1
- package/dist/index31.js +43 -36
- package/dist/index31.js.map +1 -1
- package/dist/index38.js +184 -172
- package/dist/index38.js.map +1 -1
- package/dist/index4.js +53 -48
- package/dist/index4.js.map +1 -1
- package/dist/index43.js +30 -30
- package/dist/index43.js.map +1 -1
- package/dist/index48.js +15 -12
- package/dist/index48.js.map +1 -1
- package/dist/index53.js +22 -17
- package/dist/index53.js.map +1 -1
- package/dist/index61.js +57 -47
- package/dist/index61.js.map +1 -1
- package/dist/index68.js +46 -49
- package/dist/index68.js.map +1 -1
- package/dist/index75.js +107 -44
- package/dist/index75.js.map +1 -1
- package/package.json +1 -1
package/dist/index53.js
CHANGED
|
@@ -1,41 +1,46 @@
|
|
|
1
|
-
import e, { useEffect as
|
|
1
|
+
import e, { useEffect as a } from "react";
|
|
2
2
|
import { delay as m } from "./index245.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { announce as i } from "./index75.js";
|
|
4
|
+
import { Icon as s } from "./index6.js";
|
|
5
|
+
const u = (l) => {
|
|
5
6
|
const {
|
|
6
|
-
title:
|
|
7
|
+
title: o = "",
|
|
7
8
|
itemsList: t = [],
|
|
8
|
-
handleDownload:
|
|
9
|
-
backgroundColor:
|
|
10
|
-
titleBackgroundColor:
|
|
11
|
-
} =
|
|
12
|
-
return
|
|
13
|
-
t?.length > 0 && t?.forEach((
|
|
9
|
+
handleDownload: n,
|
|
10
|
+
backgroundColor: c = "var(--color-white)",
|
|
11
|
+
titleBackgroundColor: d = "var(--color-blue-50)"
|
|
12
|
+
} = l;
|
|
13
|
+
return a(() => {
|
|
14
|
+
t?.length > 0 && t?.forEach((r) => {
|
|
14
15
|
m(2e3).then(() => {
|
|
15
|
-
|
|
16
|
+
n(r);
|
|
16
17
|
});
|
|
17
18
|
});
|
|
18
|
-
}, [t?.length]),
|
|
19
|
+
}, [t?.length]), a(() => {
|
|
20
|
+
o && i(o, {
|
|
21
|
+
delay: 300
|
|
22
|
+
});
|
|
23
|
+
}, []), /* @__PURE__ */ e.createElement("div", {
|
|
19
24
|
className: "download-widgets-container rounded-t-xl border border-[var(--color-gray-400)] w-[300px] overflow-hidden fixed bottom-0 right-5 z-[1100]",
|
|
20
25
|
style: {
|
|
21
|
-
backgroundColor:
|
|
26
|
+
backgroundColor: c
|
|
22
27
|
}
|
|
23
28
|
}, /* @__PURE__ */ e.createElement("div", {
|
|
24
29
|
className: "p-4 text-base font-medium",
|
|
25
30
|
style: {
|
|
26
|
-
backgroundColor:
|
|
31
|
+
backgroundColor: d
|
|
27
32
|
}
|
|
28
|
-
},
|
|
33
|
+
}, o), t?.map((r) => /* @__PURE__ */ e.createElement("div", {
|
|
29
34
|
className: " download-item flex items-center gap-2 px-4 pt-4 last:pb-4"
|
|
30
35
|
}, /* @__PURE__ */ e.createElement("span", {
|
|
31
36
|
className: "text-base font-normal flex-1"
|
|
32
|
-
},
|
|
37
|
+
}, r.label), /* @__PURE__ */ e.createElement(s, {
|
|
33
38
|
name: "checked-circle",
|
|
34
39
|
stroke: "var(--color-green-500)",
|
|
35
40
|
size: 16
|
|
36
41
|
}))));
|
|
37
42
|
};
|
|
38
43
|
export {
|
|
39
|
-
|
|
44
|
+
u as DownloadWidget
|
|
40
45
|
};
|
|
41
46
|
//# sourceMappingURL=index53.js.map
|
package/dist/index53.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index53.js","sources":["../src/components/DownloadWidget/index.tsx"],"sourcesContent":["import React, { useEffect } from 'react';\n\nimport { delay } from 'utils/delay';\n\nimport { Icon } from '../Icon';\n\ntype ItemType = { label: string; id?: number; metadata?: any };\n\ntype DownloadWidgetProps = {\n title: string;\n itemsList: ItemType[];\n handleDownload: (downloadItem?: any) => void;\n backgroundColor?: string;\n titleBackgroundColor?: string;\n};\n\nexport const DownloadWidget = (props: DownloadWidgetProps) => {\n const {\n title = '',\n itemsList = [],\n handleDownload,\n backgroundColor = 'var(--color-white)',\n titleBackgroundColor = 'var(--color-blue-50)'\n } = props;\n\n useEffect(() => {\n if (itemsList?.length > 0) {\n itemsList?.forEach((downloadItem) => {\n delay(2000).then(() => {\n handleDownload(downloadItem);\n });\n });\n }\n }, [itemsList?.length]);\n\n return (\n <div\n className=\"download-widgets-container rounded-t-xl border border-[var(--color-gray-400)] w-[300px] overflow-hidden fixed bottom-0 right-5 z-[1100]\"\n style={{ backgroundColor }}\n >\n <div className=\"p-4 text-base font-medium\" style={{ backgroundColor: titleBackgroundColor }}>\n {title}\n </div>\n {itemsList?.map((item) => (\n <div className=\" download-item flex items-center gap-2 px-4 pt-4 last:pb-4\">\n <span className=\"text-base font-normal flex-1\">{item.label}</span>\n <Icon name=\"checked-circle\" stroke=\"var(--color-green-500)\" size={16} />\n </div>\n ))}\n </div>\n );\n};\n"],"names":["React__default","useEffect","delay","Icon","DownloadWidget","props","title","itemsList","handleDownload","backgroundColor","titleBackgroundColor","length","forEach","downloadItem","then","React","createElement","className","style","map","item","label","name","stroke","size"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index53.js","sources":["../src/components/DownloadWidget/index.tsx"],"sourcesContent":["import React, { useEffect } from 'react';\n\nimport { delay } from 'utils/delay';\nimport { announce } from 'src/utils/a11y/liveAnnouncer/LiveAnnouncer';\n\nimport { Icon } from '../Icon';\n\ntype ItemType = { label: string; id?: number; metadata?: any };\n\ntype DownloadWidgetProps = {\n title: string;\n itemsList: ItemType[];\n handleDownload: (downloadItem?: any) => void;\n backgroundColor?: string;\n titleBackgroundColor?: string;\n};\n\nexport const DownloadWidget = (props: DownloadWidgetProps) => {\n const {\n title = '',\n itemsList = [],\n handleDownload,\n backgroundColor = 'var(--color-white)',\n titleBackgroundColor = 'var(--color-blue-50)'\n } = props;\n\n useEffect(() => {\n if (itemsList?.length > 0) {\n itemsList?.forEach((downloadItem) => {\n delay(2000).then(() => {\n handleDownload(downloadItem);\n });\n });\n }\n }, [itemsList?.length]);\n\n useEffect(() => {\n if (title) {\n announce(title, { delay: 300 });\n }\n }, []);\n\n return (\n <div\n className=\"download-widgets-container rounded-t-xl border border-[var(--color-gray-400)] w-[300px] overflow-hidden fixed bottom-0 right-5 z-[1100]\"\n style={{ backgroundColor }}\n >\n <div className=\"p-4 text-base font-medium\" style={{ backgroundColor: titleBackgroundColor }}>\n {title}\n </div>\n {itemsList?.map((item) => (\n <div className=\" download-item flex items-center gap-2 px-4 pt-4 last:pb-4\">\n <span className=\"text-base font-normal flex-1\">{item.label}</span>\n <Icon name=\"checked-circle\" stroke=\"var(--color-green-500)\" size={16} />\n </div>\n ))}\n </div>\n );\n};\n"],"names":["React__default","useEffect","delay","announce","Icon","DownloadWidget","props","title","itemsList","handleDownload","backgroundColor","titleBackgroundColor","length","forEach","downloadItem","then","React","createElement","className","style","map","item","label","name","stroke","size"],"mappings":"AAiBO,OAAAA,KAAA,aAAAC,SAAA;AAAA,SAAA,SAAAC,SAAA;AAAA,SAAA,YAAAC,SAAA;AAAA,SAAA,QAAAC,SAAA;AAAA,MAAMC,IAAiBA,CAACC,MAA+B;AAC5D,QAAM;AAAA,IACJC,OAAAA,IAAQ;AAAA,IACRC,WAAAA,IAAY,CAAA;AAAA,IACZC,gBAAAA;AAAAA,IACAC,iBAAAA,IAAkB;AAAA,IAClBC,sBAAAA,IAAuB;AAAA,EAAA,IACrBL;AAEJL,SAAAA,EAAU,MAAM;AACd,IAAIO,GAAWI,SAAS,KACtBJ,GAAWK,QAASC,CAAAA,MAAiB;AACnCZ,MAAAA,EAAM,GAAI,EAAEa,KAAK,MAAM;AACrBN,QAAAA,EAAeK,CAAY;AAAA,MAC7B,CAAC;AAAA,IACH,CAAC;AAAA,EAEL,GAAG,CAACN,GAAWI,MAAM,CAAC,GAEtBX,EAAU,MAAM;AACd,IAAIM,KACFJ,EAASI,GAAO;AAAA,MAAEL,OAAO;AAAA,IAAA,CAAK;AAAA,EAElC,GAAG,CAAA,CAAE,GAGHc,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IACEC,WAAU;AAAA,IACVC,OAAO;AAAA,MAAET,iBAAAA;AAAAA,IAAAA;AAAAA,EAAgB,GAEzBM,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IAAKC,WAAU;AAAA,IAA4BC,OAAO;AAAA,MAAET,iBAAiBC;AAAAA,IAAAA;AAAAA,EAAqB,GACvFJ,CACE,GACJC,GAAWY,IAAKC,CAAAA,MACfL,gBAAAA,EAAAC,cAAA,OAAA;AAAA,IAAKC,WAAU;AAAA,EAAA,GACbF,gBAAAA,EAAAC,cAAA,QAAA;AAAA,IAAMC,WAAU;AAAA,EAAA,GAAgCG,EAAKC,KAAY,GACjEN,gBAAAA,EAAAC,cAACb,GAAI;AAAA,IAACmB,MAAK;AAAA,IAAiBC,QAAO;AAAA,IAAyBC,MAAM;AAAA,EAAA,CAAK,CACpE,CACN,CACE;AAET;"}
|
package/dist/index61.js
CHANGED
|
@@ -1,61 +1,71 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Popover as
|
|
1
|
+
import n, { useState as u, useCallback as y, useEffect as P } from "react";
|
|
2
|
+
import { Popover as I } from "./index19.js";
|
|
3
|
+
import { useStableId as k } from "./index205.js";
|
|
3
4
|
/* empty css */
|
|
4
|
-
function
|
|
5
|
-
return
|
|
6
|
-
for (var
|
|
7
|
-
var
|
|
8
|
-
for (var
|
|
5
|
+
function p() {
|
|
6
|
+
return p = Object.assign ? Object.assign.bind() : function(r) {
|
|
7
|
+
for (var o = 1; o < arguments.length; o++) {
|
|
8
|
+
var s = arguments[o];
|
|
9
|
+
for (var t in s) ({}).hasOwnProperty.call(s, t) && (r[t] = s[t]);
|
|
9
10
|
}
|
|
10
|
-
return
|
|
11
|
-
},
|
|
11
|
+
return r;
|
|
12
|
+
}, p.apply(null, arguments);
|
|
12
13
|
}
|
|
13
|
-
const
|
|
14
|
-
label:
|
|
15
|
-
children:
|
|
16
|
-
iconColor:
|
|
17
|
-
hoverBackgroundColor:
|
|
18
|
-
isDisabled:
|
|
19
|
-
noPadding:
|
|
14
|
+
const N = ({
|
|
15
|
+
label: r,
|
|
16
|
+
children: o,
|
|
17
|
+
iconColor: s = "",
|
|
18
|
+
hoverBackgroundColor: t,
|
|
19
|
+
isDisabled: i = !1,
|
|
20
|
+
noPadding: m = !1,
|
|
21
|
+
noDescribedBy: g = !1
|
|
20
22
|
}) => {
|
|
21
|
-
const [
|
|
22
|
-
|
|
23
|
+
const c = k(void 0, "info-tooltip"), [v, a] = u(!1), [E, l] = u(!1), d = v || E, f = y((e) => {
|
|
24
|
+
e.key === "Escape" && (a(!1), l(!1), e.stopImmediatePropagation());
|
|
23
25
|
}, []);
|
|
24
|
-
|
|
25
|
-
if (
|
|
26
|
-
return document.addEventListener("keydown",
|
|
27
|
-
}, [
|
|
28
|
-
const
|
|
29
|
-
onMouseEnter: () =>
|
|
30
|
-
onMouseLeave: () =>
|
|
31
|
-
onFocus: (
|
|
32
|
-
|
|
26
|
+
P(() => {
|
|
27
|
+
if (d)
|
|
28
|
+
return document.addEventListener("keydown", f), () => document.removeEventListener("keydown", f);
|
|
29
|
+
}, [d, f]);
|
|
30
|
+
const b = {
|
|
31
|
+
onMouseEnter: () => a(!0),
|
|
32
|
+
onMouseLeave: () => a(!1),
|
|
33
|
+
onFocus: (e) => {
|
|
34
|
+
e.target.matches(":focus-visible") && l(!0);
|
|
33
35
|
},
|
|
34
|
-
onBlur: () =>
|
|
36
|
+
onBlur: () => l(!1)
|
|
35
37
|
};
|
|
36
|
-
return /* @__PURE__ */
|
|
37
|
-
className: `se-design-info-tooltip-outer ${
|
|
38
|
-
},
|
|
38
|
+
return /* @__PURE__ */ n.createElement("div", p({
|
|
39
|
+
className: `se-design-info-tooltip-outer ${i ? "se-design-info-tooltip-wrapper-disabled" : ""}`
|
|
40
|
+
}, i ? {} : b), /* @__PURE__ */ n.createElement(I, {
|
|
39
41
|
className: "inline-flex items-center",
|
|
40
42
|
position: "bottom-center",
|
|
41
|
-
isPopoverOpen:
|
|
42
|
-
onPopoverToggle: (
|
|
43
|
-
|
|
43
|
+
isPopoverOpen: d,
|
|
44
|
+
onPopoverToggle: (e) => {
|
|
45
|
+
e || (a(!1), l(!1));
|
|
44
46
|
},
|
|
45
|
-
renderPopoverSrcElement: () =>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
} :
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
47
|
+
renderPopoverSrcElement: () => {
|
|
48
|
+
const e = !g && /* @__PURE__ */ n.isValidElement(o) ? /* @__PURE__ */ n.cloneElement(o, {
|
|
49
|
+
"aria-describedby": c,
|
|
50
|
+
ariaDescribedBy: c
|
|
51
|
+
}) : o;
|
|
52
|
+
return /* @__PURE__ */ n.createElement("div", {
|
|
53
|
+
className: `se-design-info-tooltip-src ${m ? "no-padding" : ""} ${i ? "se-design-info-tooltip-disabled" : ""}`,
|
|
54
|
+
style: {
|
|
55
|
+
"--info-tooltip-icon-color": s,
|
|
56
|
+
...t ? {
|
|
57
|
+
"--info-tooltip-hover-bg": t
|
|
58
|
+
} : {},
|
|
59
|
+
cursor: i ? "not-allowed" : "pointer"
|
|
60
|
+
}
|
|
61
|
+
}, e);
|
|
62
|
+
},
|
|
63
|
+
renderPopoverContents: () => /* @__PURE__ */ n.createElement("div", {
|
|
64
|
+
id: c,
|
|
65
|
+
role: "tooltip",
|
|
56
66
|
className: "se-design-info-tooltip-content",
|
|
57
67
|
"data-automation-id": "se-design-info-tooltip-content"
|
|
58
|
-
},
|
|
68
|
+
}, r),
|
|
59
69
|
isWithPortal: !0,
|
|
60
70
|
noBorder: !0,
|
|
61
71
|
disableClickToggle: !0,
|
|
@@ -66,6 +76,6 @@ const I = ({
|
|
|
66
76
|
}));
|
|
67
77
|
};
|
|
68
78
|
export {
|
|
69
|
-
|
|
79
|
+
N as InfoTooltip
|
|
70
80
|
};
|
|
71
81
|
//# sourceMappingURL=index61.js.map
|
package/dist/index61.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index61.js","sources":["../src/components/InfoTooltip/index.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport { Popover } from '../Popover';\nimport './styles.scss';\n\nexport interface InfoTooltipProps {\n label: string;\n children: React.ReactNode;\n iconColor?: string;\n /**\n * Background color shown on hover. Defaults to var(--color-blue-200).\n */\n hoverBackgroundColor?: string;\n isDisabled?: boolean;\n /**\n * Remove padding from tooltip wrapper (useful for precise alignment)\n */\n noPadding?: boolean;\n}\n\nexport const InfoTooltip = ({\n label,\n children,\n iconColor = '',\n hoverBackgroundColor,\n isDisabled = false,\n noPadding = false\n}: InfoTooltipProps) => {\n const [isHovered, setIsHovered] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n // Show tooltip on hover OR focus (for keyboard accessibility)\n const isOpen = isHovered || isFocused;\n\n // Global Escape key handler (W3C WAI-ARIA tooltip pattern requirement)\n const handleEscapeKey = useCallback((event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsHovered(false);\n setIsFocused(false);\n // Prevent other handlers (e.g., modal) from also closing - \"innermost first\" pattern\n event.stopImmediatePropagation();\n }\n }, []);\n\n useEffect(() => {\n if (isOpen) {\n document.addEventListener('keydown', handleEscapeKey);\n return () => document.removeEventListener('keydown', handleEscapeKey);\n }\n }, [isOpen, handleEscapeKey]);\n\n const interactionHandlers = {\n onMouseEnter: () => setIsHovered(true),\n onMouseLeave: () => setIsHovered(false),\n onFocus: (event: React.FocusEvent<HTMLDivElement>) => {\n const focusTarget = event.target as HTMLElement;\n if (focusTarget.matches(':focus-visible')) {\n setIsFocused(true);\n }\n },\n onBlur: () => setIsFocused(false)\n };\n\n return (\n <div\n className={`se-design-info-tooltip-outer ${isDisabled ? 'se-design-info-tooltip-wrapper-disabled' : ''}`}\n {...(isDisabled ? {} : interactionHandlers)}\n >\n <Popover\n className=\"inline-flex items-center\"\n position={'bottom-center'}\n isPopoverOpen={isOpen}\n onPopoverToggle={(open) => {\n // Sync popover state changes (e.g., Escape key) back to component state\n if (!open) {\n setIsHovered(false);\n setIsFocused(false);\n }\n }}\n renderPopoverSrcElement={() => (\n <div\n
|
|
1
|
+
{"version":3,"file":"index61.js","sources":["../src/components/InfoTooltip/index.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from 'react';\nimport { Popover } from '../Popover';\nimport { useStableId } from '../../utils/useStableId';\nimport './styles.scss';\n\nexport interface InfoTooltipProps {\n label: string;\n children: React.ReactNode;\n iconColor?: string;\n /**\n * Background color shown on hover. Defaults to var(--color-blue-200).\n */\n hoverBackgroundColor?: string;\n isDisabled?: boolean;\n /**\n * Remove padding from tooltip wrapper (useful for precise alignment)\n */\n noPadding?: boolean;\n /**\n * When true, skips wiring aria-describedby between the trigger and tooltip content.\n * Use when the tooltip label duplicates the trigger's accessible name — avoids redundant announcements.\n */\n noDescribedBy?: boolean;\n}\n\nexport const InfoTooltip = ({\n label,\n children,\n iconColor = '',\n hoverBackgroundColor,\n isDisabled = false,\n noPadding = false,\n noDescribedBy = false\n}: InfoTooltipProps) => {\n const tooltipContentId = useStableId(undefined, 'info-tooltip');\n const [isHovered, setIsHovered] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n\n // Show tooltip on hover OR focus (for keyboard accessibility)\n const isOpen = isHovered || isFocused;\n\n // Global Escape key handler (W3C WAI-ARIA tooltip pattern requirement)\n const handleEscapeKey = useCallback((event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsHovered(false);\n setIsFocused(false);\n // Prevent other handlers (e.g., modal) from also closing - \"innermost first\" pattern\n event.stopImmediatePropagation();\n }\n }, []);\n\n useEffect(() => {\n if (isOpen) {\n document.addEventListener('keydown', handleEscapeKey);\n return () => document.removeEventListener('keydown', handleEscapeKey);\n }\n }, [isOpen, handleEscapeKey]);\n\n const interactionHandlers = {\n onMouseEnter: () => setIsHovered(true),\n onMouseLeave: () => setIsHovered(false),\n onFocus: (event: React.FocusEvent<HTMLDivElement>) => {\n const focusTarget = event.target as HTMLElement;\n if (focusTarget.matches(':focus-visible')) {\n setIsFocused(true);\n }\n },\n onBlur: () => setIsFocused(false)\n };\n\n return (\n <div\n className={`se-design-info-tooltip-outer ${isDisabled ? 'se-design-info-tooltip-wrapper-disabled' : ''}`}\n {...(isDisabled ? {} : interactionHandlers)}\n >\n <Popover\n className=\"inline-flex items-center\"\n position={'bottom-center'}\n isPopoverOpen={isOpen}\n onPopoverToggle={(open) => {\n // Sync popover state changes (e.g., Escape key) back to component state\n if (!open) {\n setIsHovered(false);\n setIsFocused(false);\n }\n }}\n renderPopoverSrcElement={() => {\n const trigger =\n !noDescribedBy && React.isValidElement(children)\n ? React.cloneElement(children as React.ReactElement<Record<string, unknown>>, {\n 'aria-describedby': tooltipContentId,\n ariaDescribedBy: tooltipContentId\n })\n : children;\n return (\n <div\n className={`se-design-info-tooltip-src ${noPadding ? 'no-padding' : ''} ${\n isDisabled ? 'se-design-info-tooltip-disabled' : ''\n }`}\n style={\n {\n '--info-tooltip-icon-color': iconColor,\n ...(hoverBackgroundColor ? { '--info-tooltip-hover-bg': hoverBackgroundColor } : {}),\n cursor: isDisabled ? 'not-allowed' : 'pointer'\n } as React.CSSProperties\n }\n >\n {trigger}\n </div>\n );\n }}\n renderPopoverContents={() => (\n <div\n id={tooltipContentId}\n role=\"tooltip\"\n className=\"se-design-info-tooltip-content\"\n data-automation-id=\"se-design-info-tooltip-content\"\n >\n {label}\n </div>\n )}\n isWithPortal\n noBorder\n disableClickToggle\n popoverContentStyleProperty={{\n zIndex: 2000,\n backgroundColor: ''\n }}\n />\n </div>\n );\n};\n"],"names":["InfoTooltip","label","children","iconColor","hoverBackgroundColor","isDisabled","noPadding","noDescribedBy","tooltipContentId","useStableId","undefined","isHovered","setIsHovered","useState","isFocused","setIsFocused","isOpen","handleEscapeKey","useCallback","event","key","stopImmediatePropagation","useEffect","document","addEventListener","removeEventListener","interactionHandlers","onMouseEnter","onMouseLeave","onFocus","target","matches","onBlur","React","createElement","_extends","className","Popover","position","isPopoverOpen","onPopoverToggle","open","renderPopoverSrcElement","trigger","isValidElement","cloneElement","ariaDescribedBy","style","cursor","renderPopoverContents","id","role","isWithPortal","noBorder","disableClickToggle","popoverContentStyleProperty","zIndex","backgroundColor"],"mappings":";;;;;;;;;;;;;AAyBO,MAAMA,IAAcA,CAAC;AAAA,EAC1BC,OAAAA;AAAAA,EACAC,UAAAA;AAAAA,EACAC,WAAAA,IAAY;AAAA,EACZC,sBAAAA;AAAAA,EACAC,YAAAA,IAAa;AAAA,EACbC,WAAAA,IAAY;AAAA,EACZC,eAAAA,IAAgB;AACA,MAAM;AACtB,QAAMC,IAAmBC,EAAYC,QAAW,cAAc,GACxD,CAACC,GAAWC,CAAY,IAAIC,EAAS,EAAK,GAC1C,CAACC,GAAWC,CAAY,IAAIF,EAAS,EAAK,GAG1CG,IAASL,KAAaG,GAGtBG,IAAkBC,EAAY,CAACC,MAAyB;AAC5D,IAAIA,EAAMC,QAAQ,aAChBR,EAAa,EAAK,GAClBG,EAAa,EAAK,GAElBI,EAAME,yBAAAA;AAAAA,EAEV,GAAG,CAAA,CAAE;AAELC,EAAAA,EAAU,MAAM;AACd,QAAIN;AACFO,sBAASC,iBAAiB,WAAWP,CAAe,GAC7C,MAAMM,SAASE,oBAAoB,WAAWR,CAAe;AAAA,EAExE,GAAG,CAACD,GAAQC,CAAe,CAAC;AAE5B,QAAMS,IAAsB;AAAA,IAC1BC,cAAcA,MAAMf,EAAa,EAAI;AAAA,IACrCgB,cAAcA,MAAMhB,EAAa,EAAK;AAAA,IACtCiB,SAASA,CAACV,MAA4C;AAEpD,MADoBA,EAAMW,OACVC,QAAQ,gBAAgB,KACtChB,EAAa,EAAI;AAAA,IAErB;AAAA,IACAiB,QAAQA,MAAMjB,EAAa,EAAK;AAAA,EAAA;AAGlC,SACEkB,gBAAAA,EAAAC,cAAA,OAAAC,EAAA;AAAA,IACEC,WAAW,gCAAgC/B,IAAa,4CAA4C,EAAE;AAAA,EAAA,GACjGA,IAAa,CAAA,IAAKqB,CAAmB,GAE1CO,gBAAAA,EAAAC,cAACG,GAAO;AAAA,IACND,WAAU;AAAA,IACVE,UAAU;AAAA,IACVC,eAAevB;AAAAA,IACfwB,iBAAkBC,CAAAA,MAAS;AAEzB,MAAKA,MACH7B,EAAa,EAAK,GAClBG,EAAa,EAAK;AAAA,IAEtB;AAAA,IACA2B,yBAAyBA,MAAM;AAC7B,YAAMC,IACJ,CAACpC,KAAiB0B,gBAAAA,EAAMW,eAAe1C,CAAQ,IAC3C+B,gBAAAA,EAAMY,aAAa3C,GAAyD;AAAA,QAC1E,oBAAoBM;AAAAA,QACpBsC,iBAAiBtC;AAAAA,MAAAA,CAClB,IACDN;AACN,aACE+B,gBAAAA,EAAAC,cAAA,OAAA;AAAA,QACEE,WAAW,8BAA8B9B,IAAY,eAAe,EAAE,IACpED,IAAa,oCAAoC,EAAE;AAAA,QAErD0C,OACE;AAAA,UACE,6BAA6B5C;AAAAA,UAC7B,GAAIC,IAAuB;AAAA,YAAE,2BAA2BA;AAAAA,UAAAA,IAAyB,CAAA;AAAA,UACjF4C,QAAQ3C,IAAa,gBAAgB;AAAA,QAAA;AAAA,MACvC,GAGDsC,CACE;AAAA,IAET;AAAA,IACAM,uBAAuBA,MACrBhB,gBAAAA,EAAAC,cAAA,OAAA;AAAA,MACEgB,IAAI1C;AAAAA,MACJ2C,MAAK;AAAA,MACLf,WAAU;AAAA,MACV,sBAAmB;AAAA,IAAA,GAElBnC,CACE;AAAA,IAEPmD,cAAY;AAAA,IACZC,UAAQ;AAAA,IACRC,oBAAkB;AAAA,IAClBC,6BAA6B;AAAA,MAC3BC,QAAQ;AAAA,MACRC,iBAAiB;AAAA,IAAA;AAAA,EACnB,CACD,CACE;AAET;"}
|
package/dist/index68.js
CHANGED
|
@@ -1,70 +1,67 @@
|
|
|
1
|
-
import { useRef as i, useState as
|
|
2
|
-
import { useComboboxNavigation as
|
|
3
|
-
import { useDismissOnFocusOut as
|
|
1
|
+
import { useRef as i, useState as R, useCallback as w, useEffect as A } from "react";
|
|
2
|
+
import { useComboboxNavigation as M } from "./index79.js";
|
|
3
|
+
import { useDismissOnFocusOut as U } from "./index80.js";
|
|
4
4
|
function _({
|
|
5
|
-
items:
|
|
5
|
+
items: d,
|
|
6
6
|
isOpen: t,
|
|
7
|
-
onOpenChange:
|
|
8
|
-
onSelect:
|
|
7
|
+
onOpenChange: l,
|
|
8
|
+
onSelect: b,
|
|
9
9
|
listboxId: n,
|
|
10
|
-
loop:
|
|
11
|
-
disabled:
|
|
12
|
-
optionSelector:
|
|
10
|
+
loop: x = !0,
|
|
11
|
+
disabled: y = !1,
|
|
12
|
+
optionSelector: D = '[role="option"]',
|
|
13
13
|
hasItems: p,
|
|
14
|
-
keepHighlightOnSelect:
|
|
15
|
-
closeOnTab:
|
|
14
|
+
keepHighlightOnSelect: m = !1,
|
|
15
|
+
closeOnTab: C = !0
|
|
16
16
|
}) {
|
|
17
|
-
const g = i(null), s = i(!1),
|
|
18
|
-
|
|
19
|
-
}, [
|
|
20
|
-
|
|
21
|
-
t || (s.current = !1);
|
|
17
|
+
const g = i(null), s = i(!1), c = i(!1), a = i(!1), [h, r] = R(!1), v = p !== void 0 ? p : d.length > 0, f = w(() => {
|
|
18
|
+
l(!1);
|
|
19
|
+
}, [l]);
|
|
20
|
+
A(() => {
|
|
21
|
+
t || (s.current = !1, a.current = !1);
|
|
22
22
|
}, [t]);
|
|
23
|
-
const o =
|
|
24
|
-
items:
|
|
23
|
+
const o = M({
|
|
24
|
+
items: d,
|
|
25
25
|
isOpen: t,
|
|
26
|
-
onSelect:
|
|
27
|
-
onClose:
|
|
28
|
-
onOpen: () =>
|
|
29
|
-
loop:
|
|
30
|
-
disabled:
|
|
26
|
+
onSelect: b,
|
|
27
|
+
onClose: f,
|
|
28
|
+
onOpen: () => l(!0),
|
|
29
|
+
loop: x,
|
|
30
|
+
disabled: y,
|
|
31
31
|
listboxRef: g,
|
|
32
|
-
optionSelector:
|
|
33
|
-
keepHighlightOnSelect:
|
|
34
|
-
closeOnTab:
|
|
35
|
-
}),
|
|
36
|
-
onFocusOut:
|
|
37
|
-
onEscape:
|
|
32
|
+
optionSelector: D,
|
|
33
|
+
keepHighlightOnSelect: m,
|
|
34
|
+
closeOnTab: C
|
|
35
|
+
}), u = U({
|
|
36
|
+
onFocusOut: f,
|
|
37
|
+
onEscape: f,
|
|
38
38
|
disabled: !t
|
|
39
|
-
}),
|
|
40
|
-
...
|
|
39
|
+
}), I = {
|
|
40
|
+
...u,
|
|
41
41
|
onPointerMove: () => {
|
|
42
42
|
h && r(!1);
|
|
43
43
|
},
|
|
44
44
|
onPointerDown: () => {
|
|
45
|
-
|
|
45
|
+
a.current = !0, r(!1);
|
|
46
46
|
},
|
|
47
47
|
onPointerUp: () => {
|
|
48
|
-
requestAnimationFrame(() => {
|
|
49
|
-
c.current = !1;
|
|
50
|
-
});
|
|
51
48
|
},
|
|
52
49
|
onFocusCapture: (e) => {
|
|
53
|
-
|
|
50
|
+
u.onFocusCapture(e), a.current ? r(!1) : r(!0);
|
|
54
51
|
},
|
|
55
52
|
onKeyDownCapture: (e) => {
|
|
56
|
-
|
|
53
|
+
u.onKeyDownCapture(e), (e.key === "Tab" || e.key === "ArrowDown" || e.key === "ArrowUp") && (a.current = !1), (e.key === "ArrowDown" || e.key === "ArrowUp") && r(!0);
|
|
57
54
|
},
|
|
58
55
|
onBlurCapture: (e) => {
|
|
59
56
|
if (r(!1), !s.current) {
|
|
60
|
-
if (
|
|
61
|
-
|
|
57
|
+
if (c.current) {
|
|
58
|
+
c.current = !1;
|
|
62
59
|
return;
|
|
63
60
|
}
|
|
64
|
-
|
|
61
|
+
u.onBlurCapture(e);
|
|
65
62
|
}
|
|
66
63
|
}
|
|
67
|
-
},
|
|
64
|
+
}, P = {
|
|
68
65
|
role: "combobox",
|
|
69
66
|
"aria-expanded": t && v,
|
|
70
67
|
"aria-haspopup": "listbox",
|
|
@@ -72,9 +69,9 @@ function _({
|
|
|
72
69
|
"aria-autocomplete": "list",
|
|
73
70
|
"aria-activedescendant": o.highlightedIndex >= 0 ? o.getOptionId(n, o.highlightedIndex) : void 0,
|
|
74
71
|
onKeyDown: (e) => {
|
|
75
|
-
e.key === "Tab" && (
|
|
72
|
+
e.key === "Tab" && (c.current = !0), o.handleKeyDown(e);
|
|
76
73
|
}
|
|
77
|
-
},
|
|
74
|
+
}, k = {
|
|
78
75
|
id: n,
|
|
79
76
|
role: "listbox",
|
|
80
77
|
ref: g,
|
|
@@ -87,16 +84,16 @@ function _({
|
|
|
87
84
|
onMouseLeave: (e) => {
|
|
88
85
|
s.current = !1;
|
|
89
86
|
}
|
|
90
|
-
},
|
|
87
|
+
}, F = w((e, K = !1) => ({
|
|
91
88
|
id: o.getOptionId(n, e),
|
|
92
89
|
role: "option",
|
|
93
|
-
"aria-selected":
|
|
90
|
+
"aria-selected": K
|
|
94
91
|
}), [o.getOptionId, n]);
|
|
95
92
|
return {
|
|
96
|
-
containerProps:
|
|
97
|
-
inputProps:
|
|
98
|
-
listboxProps:
|
|
99
|
-
getOptionProps:
|
|
93
|
+
containerProps: I,
|
|
94
|
+
inputProps: P,
|
|
95
|
+
listboxProps: k,
|
|
96
|
+
getOptionProps: F,
|
|
100
97
|
highlightedIndex: o.highlightedIndex,
|
|
101
98
|
setHighlightedIndex: o.setHighlightedIndex,
|
|
102
99
|
getOptionId: o.getOptionId,
|
package/dist/index68.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index68.js","sources":["../src/utils/a11y/useCombobox.ts"],"sourcesContent":["import { useRef, useCallback, useEffect, useState } 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 /**\n * Whether to keep the highlighted index after selecting an item.\n * Useful for multi-select where the dropdown stays open after selection.\n * Default: false\n */\n keepHighlightOnSelect?: boolean;\n\n /**\n * Whether Tab should close the dropdown.\n * Set to false when Tab should move focus to elements within the popup (e.g. CTAs).\n * Default: true\n */\n closeOnTab?: boolean;\n}\n\nexport interface UseComboboxReturn {\n /**\n * Props to spread on the container element (handles dismiss on focus out + keyboard focus tracking)\n */\n containerProps: UseDismissOnFocusOutReturn<HTMLElement> & {\n onPointerMove: () => void;\n onPointerDown: () => void;\n onPointerUp: () => void;\n };\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 * Whether the combobox input was focused via keyboard (Tab) rather than pointer.\n * Use to conditionally show focus ring only on keyboard interaction.\n */\n isKeyboardFocused: boolean;\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 keepHighlightOnSelect = false,\n closeOnTab = true\n}: UseComboboxOptions<T>): UseComboboxReturn {\n const listboxRef = useRef<HTMLDivElement | null>(null);\n const pointerDownInListboxRef = useRef(false);\n const tabKeyPressedRef = useRef(false);\n const pointerFocusRef = useRef(false);\n const [isKeyboardFocused, setIsKeyboardFocused] = useState(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 keepHighlightOnSelect,\n closeOnTab\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 = {\n ...dismissHandlers,\n onPointerMove: () => {\n if (isKeyboardFocused) {\n setIsKeyboardFocused(false);\n }\n },\n onPointerDown: () => {\n pointerFocusRef.current = true;\n setIsKeyboardFocused(false);\n },\n onPointerUp: () => {\n // Reset after the full pointer interaction (down → focus → up).\n // Delayed so any setTimeout-based auto-focus (e.g. Popover open)\n // still sees pointerFocusRef=true and doesn't flip to keyboard mode.\n requestAnimationFrame(() => {\n pointerFocusRef.current = false;\n });\n },\n onFocusCapture: (e: React.FocusEvent<HTMLElement>) => {\n dismissHandlers.onFocusCapture(e);\n\n if (pointerFocusRef.current) {\n setIsKeyboardFocused(false);\n } else {\n setIsKeyboardFocused(true);\n }\n },\n onKeyDownCapture: (e: React.KeyboardEvent<HTMLElement>) => {\n dismissHandlers.onKeyDownCapture(e);\n\n // Arrow keys mean keyboard navigation — show focus outline even if\n // the combobox was opened with mouse (activedescendant doesn't move\n // DOM focus, so onFocusCapture alone can't detect the switch).\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n setIsKeyboardFocused(true);\n }\n },\n onBlurCapture: (e: React.FocusEvent<HTMLElement>) => {\n setIsKeyboardFocused(false);\n\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 isKeyboardFocused\n };\n}\n"],"names":["useRef","useState","useCallback","useEffect","useComboboxNavigation","useDismissOnFocusOut","useCombobox","items","isOpen","onOpenChange","onSelect","listboxId","loop","disabled","optionSelector","hasItems","keepHighlightOnSelect","closeOnTab","listboxRef","pointerDownInListboxRef","tabKeyPressedRef","pointerFocusRef","isKeyboardFocused","setIsKeyboardFocused","shouldShowExpanded","undefined","length","closeDropdown","current","navigation","onClose","onOpen","dismissHandlers","onFocusOut","onEscape","containerProps","onPointerMove","onPointerDown","onPointerUp","requestAnimationFrame","onFocusCapture","e","onKeyDownCapture","key","onBlurCapture","inputProps","role","highlightedIndex","getOptionId","onKeyDown","handleKeyDown","listboxProps","id","ref","onMouseDownCapture","_e","onMouseUpCapture","onMouseLeave","getOptionProps","index","selected","setHighlightedIndex"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index68.js","sources":["../src/utils/a11y/useCombobox.ts"],"sourcesContent":["import { useRef, useCallback, useEffect, useState } 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 /**\n * Whether to keep the highlighted index after selecting an item.\n * Useful for multi-select where the dropdown stays open after selection.\n * Default: false\n */\n keepHighlightOnSelect?: boolean;\n\n /**\n * Whether Tab should close the dropdown.\n * Set to false when Tab should move focus to elements within the popup (e.g. CTAs).\n * Default: true\n */\n closeOnTab?: boolean;\n}\n\nexport interface UseComboboxReturn {\n /**\n * Props to spread on the container element (handles dismiss on focus out + keyboard focus tracking)\n */\n containerProps: UseDismissOnFocusOutReturn<HTMLElement> & {\n onPointerMove: () => void;\n onPointerDown: () => void;\n onPointerUp: () => void;\n };\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 * Whether the combobox input was focused via keyboard (Tab) rather than pointer.\n * Use to conditionally show focus ring only on keyboard interaction.\n */\n isKeyboardFocused: boolean;\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 keepHighlightOnSelect = false,\n closeOnTab = true\n}: UseComboboxOptions<T>): UseComboboxReturn {\n const listboxRef = useRef<HTMLDivElement | null>(null);\n const pointerDownInListboxRef = useRef(false);\n const tabKeyPressedRef = useRef(false);\n const pointerFocusRef = useRef(false);\n const [isKeyboardFocused, setIsKeyboardFocused] = useState(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 pointerFocusRef.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 keepHighlightOnSelect,\n closeOnTab\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 = {\n ...dismissHandlers,\n onPointerMove: () => {\n if (isKeyboardFocused) {\n setIsKeyboardFocused(false);\n }\n },\n onPointerDown: () => {\n pointerFocusRef.current = true;\n setIsKeyboardFocused(false);\n },\n onPointerUp: () => {\n // Don't reset pointerFocusRef here — timing races with programmatic focus\n // (e.g. focus-on-open via double rAF) cause it to clear before onFocusCapture\n // fires, incorrectly setting isKeyboardFocused=true.\n // Instead, pointerFocusRef is reset only when keyboard navigation starts\n // (Tab/Arrow in onKeyDownCapture), ensuring any programmatic focus after a\n // click is always treated as pointer context.\n },\n onFocusCapture: (e: React.FocusEvent<HTMLElement>) => {\n dismissHandlers.onFocusCapture(e);\n\n if (pointerFocusRef.current) {\n setIsKeyboardFocused(false);\n } else {\n setIsKeyboardFocused(true);\n }\n },\n onKeyDownCapture: (e: React.KeyboardEvent<HTMLElement>) => {\n dismissHandlers.onKeyDownCapture(e);\n\n // Keyboard interaction starts — clear pointer context so subsequent\n // focus events are correctly identified as keyboard-initiated.\n if (e.key === 'Tab' || e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n pointerFocusRef.current = false;\n }\n\n // Arrow keys mean keyboard navigation — show focus outline even if\n // the combobox was opened with mouse (activedescendant doesn't move\n // DOM focus, so onFocusCapture alone can't detect the switch).\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n setIsKeyboardFocused(true);\n }\n },\n onBlurCapture: (e: React.FocusEvent<HTMLElement>) => {\n setIsKeyboardFocused(false);\n\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 isKeyboardFocused\n };\n}\n"],"names":["useRef","useState","useCallback","useEffect","useComboboxNavigation","useDismissOnFocusOut","useCombobox","items","isOpen","onOpenChange","onSelect","listboxId","loop","disabled","optionSelector","hasItems","keepHighlightOnSelect","closeOnTab","listboxRef","pointerDownInListboxRef","tabKeyPressedRef","pointerFocusRef","isKeyboardFocused","setIsKeyboardFocused","shouldShowExpanded","undefined","length","closeDropdown","current","navigation","onClose","onOpen","dismissHandlers","onFocusOut","onEscape","containerProps","onPointerMove","onPointerDown","onPointerUp","onFocusCapture","e","onKeyDownCapture","key","onBlurCapture","inputProps","role","highlightedIndex","getOptionId","onKeyDown","handleKeyDown","listboxProps","id","ref","onMouseDownCapture","_e","onMouseUpCapture","onMouseLeave","getOptionProps","index","selected","setHighlightedIndex"],"mappings":"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"}
|