se-design 1.0.51 → 1.0.52

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.
Files changed (76) hide show
  1. package/dist/index177.js +5 -5
  2. package/dist/index185.js +20 -56
  3. package/dist/index185.js.map +1 -1
  4. package/dist/{index194.js → index193.js} +1 -1
  5. package/dist/{index194.js.map → index193.js.map} +1 -1
  6. package/dist/{index202.js → index201.js} +1 -1
  7. package/dist/{index202.js.map → index201.js.map} +1 -1
  8. package/dist/index203.js +35 -0
  9. package/dist/index203.js.map +1 -0
  10. package/dist/index204.js +41 -32
  11. package/dist/index204.js.map +1 -1
  12. package/dist/{index214.js → index213.js} +1 -1
  13. package/dist/{index214.js.map → index213.js.map} +1 -1
  14. package/dist/index215.js +65 -0
  15. package/dist/index215.js.map +1 -0
  16. package/dist/index216.js +5 -62
  17. package/dist/index216.js.map +1 -1
  18. package/dist/index217.js +10 -5
  19. package/dist/index217.js.map +1 -1
  20. package/dist/index218.js +9 -21
  21. package/dist/index218.js.map +1 -1
  22. package/dist/index219.js +4 -9
  23. package/dist/index219.js.map +1 -1
  24. package/dist/index220.js +170 -10
  25. package/dist/index220.js.map +1 -1
  26. package/dist/index221.js +11 -5
  27. package/dist/index221.js.map +1 -1
  28. package/dist/index222.js +6 -170
  29. package/dist/index222.js.map +1 -1
  30. package/dist/index223.js +6 -11
  31. package/dist/index223.js.map +1 -1
  32. package/dist/index224.js +37 -5
  33. package/dist/index224.js.map +1 -1
  34. package/dist/index225.js +2 -6
  35. package/dist/index225.js.map +1 -1
  36. package/dist/index226.js +7 -37
  37. package/dist/index226.js.map +1 -1
  38. package/dist/index227.js +327 -2
  39. package/dist/index227.js.map +1 -1
  40. package/dist/index228.js +49 -7
  41. package/dist/index228.js.map +1 -1
  42. package/dist/index229.js +2 -327
  43. package/dist/index229.js.map +1 -1
  44. package/dist/index230.js +71 -45
  45. package/dist/index230.js.map +1 -1
  46. package/dist/index231.js +93 -2
  47. package/dist/index231.js.map +1 -1
  48. package/dist/index232.js +48 -72
  49. package/dist/index232.js.map +1 -1
  50. package/dist/index233.js +7 -92
  51. package/dist/index233.js.map +1 -1
  52. package/dist/index234.js +4 -51
  53. package/dist/index234.js.map +1 -1
  54. package/dist/index235.js +51 -7
  55. package/dist/index235.js.map +1 -1
  56. package/dist/index236.js +2 -5
  57. package/dist/index236.js.map +1 -1
  58. package/dist/index237.js +2 -52
  59. package/dist/index237.js.map +1 -1
  60. package/dist/index26.js +51 -57
  61. package/dist/index26.js.map +1 -1
  62. package/dist/index38.js +1 -1
  63. package/dist/index44.js +1 -1
  64. package/dist/index47.js +2 -2
  65. package/dist/index51.js +1 -1
  66. package/dist/index61.js +1 -1
  67. package/dist/index65.js +1 -1
  68. package/package.json +1 -1
  69. package/dist/index186.js +0 -26
  70. package/dist/index186.js.map +0 -1
  71. package/dist/index205.js +0 -44
  72. package/dist/index205.js.map +0 -1
  73. package/dist/index238.js +0 -5
  74. package/dist/index238.js.map +0 -1
  75. package/dist/index239.js +0 -5
  76. package/dist/index239.js.map +0 -1
package/dist/index177.js CHANGED
@@ -1,8 +1,8 @@
1
- import N from "./index219.js";
2
- import R from "./index220.js";
3
- import D from "./index221.js";
4
- import { SVGInjector as A } from "./index222.js";
5
- import { p as t } from "./index223.js";
1
+ import N from "./index217.js";
2
+ import R from "./index218.js";
3
+ import D from "./index219.js";
4
+ import { SVGInjector as A } from "./index220.js";
5
+ import { p as t } from "./index221.js";
6
6
  import * as h from "react";
7
7
  var O = function(s) {
8
8
  var o = s?.ownerDocument || document;
package/dist/index185.js CHANGED
@@ -1,62 +1,26 @@
1
- import { useRef as E, useLayoutEffect as f } from "react";
2
- import { getFirstFocusableElement as d, getFocusableElements as g } from "./index218.js";
3
- function y(e, t) {
4
- return t === "first" ? d({
5
- container: e
6
- }) || e : t === "container" ? e : typeof t == "string" ? e.querySelector(t) : t instanceof HTMLElement ? t : null;
7
- }
8
- function L({
9
- enabled: e,
10
- containerRef: t,
11
- restoreFocus: i = !0,
12
- initialFocus: l = "first"
1
+ import { useEffect as d } from "react";
2
+ function p({
3
+ containerRef: r,
4
+ onDismiss: e,
5
+ enabled: n = !0,
6
+ preventDefault: u = !0,
7
+ stopPropagation: c = !0
13
8
  }) {
14
- const s = E(null), m = E(null);
15
- return f(() => {
16
- if (!e) {
17
- i && s.current && requestAnimationFrame(() => {
18
- s.current?.focus(), s.current = null;
19
- });
20
- return;
21
- }
22
- const r = t.current;
23
- r && (s.current = document.activeElement, requestAnimationFrame(() => {
24
- y(r, l)?.focus();
25
- }));
26
- }, [e, t, i, l]), f(() => {
27
- if (!e) return;
28
- const r = t.current;
29
- if (!r) return;
30
- const c = (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 o = u[0], a = u[u.length - 1], v = document.activeElement;
40
- n.shiftKey && v === o ? (n.preventDefault(), a.focus()) : !n.shiftKey && v === a && (n.preventDefault(), o.focus());
41
- }
42
- };
43
- return document.addEventListener("keydown", c, !0), () => document.removeEventListener("keydown", c, !0);
44
- }, [e, t]), f(() => {
45
- if (!e) return;
46
- const r = t.current;
47
- if (!r) return;
48
- const c = (n) => {
49
- const u = n.target;
50
- r.contains(u) ? m.current = u : (m.current || d({
51
- container: r
52
- }) || r).focus();
9
+ d(() => {
10
+ if (!n || !e) return;
11
+ const o = r.current;
12
+ if (!o) return;
13
+ const a = (t) => {
14
+ t.key === "Escape" && o.contains(document.activeElement) && (u && t.preventDefault(), c && t.stopPropagation(), e());
53
15
  };
54
- return document.addEventListener("focusin", c, !0), () => document.removeEventListener("focusin", c, !0);
55
- }, [e, t]), {
56
- triggerRef: s
57
- };
16
+ return document.addEventListener("keydown", a, {
17
+ capture: !0
18
+ }), () => document.removeEventListener("keydown", a, {
19
+ capture: !0
20
+ });
21
+ }, [n, e, r, u, c]);
58
22
  }
59
23
  export {
60
- L as useFocusTrap
24
+ p as useDismissOnEscape
61
25
  };
62
26
  //# sourceMappingURL=index185.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index185.js","sources":["../src/utils/a11y/useFocusTrap.ts"],"sourcesContent":["import { useLayoutEffect, useRef } from 'react';\nimport { getFocusableElements, getFirstFocusableElement } from './focusableElements';\n\nexport interface UseFocusTrapOptions<T extends HTMLElement = HTMLElement> {\n /**\n * Whether the focus trap is active.\n */\n enabled: boolean;\n /**\n * Container element ref to trap focus within.\n */\n containerRef: React.RefObject<T | null>;\n /**\n * Whether to restore focus to the element that had focus before trap activated.\n * Default: true\n */\n restoreFocus?: boolean;\n /**\n * Initial focus target when trap activates.\n * - 'first': Focus first focusable element (default)\n * - 'container': Focus the container itself\n * - CSS selector: Focus element matching selector\n * - HTMLElement: Focus this specific element\n */\n initialFocus?: 'first' | 'container' | string | HTMLElement;\n}\n\nexport interface UseFocusTrapReturn {\n /**\n * Ref to the element that had focus before trap activated.\n * Useful for manual focus restoration if needed.\n */\n triggerRef: React.MutableRefObject<HTMLElement | null>;\n}\n\n/**\n * Hook to trap focus within a container (for modals, dialogs, drawers).\n * \n * Implements WCAG 2.1 focus trap pattern:\n * - Moves focus into container on activation\n * - Wraps Tab/Shift+Tab navigation within container\n * - Restores focus to trigger element on deactivation\n * - Safety net: catches focus escaping via other means\n * \n * Note: For Escape key handling, use `useDismissOnEscape` hook separately.\n * This keeps focus trap (accessibility) separate from Escape handling (UX).\n * \n * @example\n * ```tsx\n * const MyModal = ({ isOpen, onClose }) => {\n * const containerRef = useRef<HTMLDivElement>(null);\n * \n * // Escape handling (UX)\n * useDismissOnEscape({\n * containerRef,\n * onDismiss: onClose,\n * enabled: isOpen\n * });\n * \n * // Focus trap (accessibility)\n * const { triggerRef } = useFocusTrap({\n * enabled: isOpen,\n * containerRef,\n * restoreFocus: true\n * });\n * \n * return (\n * <div ref={containerRef}>\n * <button>First</button>\n * <button>Second</button>\n * </div>\n * );\n * };\n * ```\n */\n/**\n * Resolve the initial focus target based on the initialFocus option.\n */\nfunction resolveInitialFocusTarget(\n container: HTMLElement,\n initialFocus: 'first' | 'container' | string | HTMLElement\n): HTMLElement | null {\n if (initialFocus === 'first') {\n return getFirstFocusableElement({ container }) || container;\n }\n if (initialFocus === 'container') {\n return container;\n }\n if (typeof initialFocus === 'string') {\n return container.querySelector<HTMLElement>(initialFocus);\n }\n if (initialFocus instanceof HTMLElement) {\n return initialFocus;\n }\n return null;\n}\n\nexport function useFocusTrap<T extends HTMLElement = HTMLElement>({\n enabled,\n containerRef,\n restoreFocus = true,\n initialFocus = 'first'\n}: UseFocusTrapOptions<T>): UseFocusTrapReturn {\n const triggerRef = useRef<HTMLElement | null>(null);\n const lastFocusedInContainer = useRef<HTMLElement | null>(null);\n\n // Focus management: save trigger, move focus into container on activate, restore on deactivate\n useLayoutEffect(() => {\n if (!enabled) {\n // Restore focus to trigger when trap deactivates\n if (restoreFocus && triggerRef.current) {\n requestAnimationFrame(() => {\n triggerRef.current?.focus();\n triggerRef.current = null;\n });\n }\n return;\n }\n\n const container = containerRef.current;\n if (!container) return;\n\n // Save the element that had focus before trap activated\n triggerRef.current = document.activeElement as HTMLElement;\n\n // Focus initial target\n requestAnimationFrame(() => {\n resolveInitialFocusTarget(container, initialFocus)?.focus();\n });\n }, [enabled, containerRef, restoreFocus, initialFocus]);\n\n // Focus trap: Tab wrapping (only when enabled)\n useLayoutEffect(() => {\n if (!enabled) return;\n \n const container = containerRef.current;\n if (!container) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n // Tab wrapping\n if (e.key === 'Tab') {\n const focusables = getFocusableElements({ container });\n\n if (focusables.length === 0) {\n e.preventDefault();\n container.focus();\n return;\n }\n\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const activeElement = document.activeElement;\n\n if (e.shiftKey && activeElement === first) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && activeElement === last) {\n e.preventDefault();\n first.focus();\n }\n }\n };\n\n document.addEventListener('keydown', handleKeyDown, true);\n return () => document.removeEventListener('keydown', handleKeyDown, true);\n }, [enabled, containerRef]);\n\n // Focus trap safety net: catch focus escaping\n useLayoutEffect(() => {\n if (!enabled) return;\n \n const container = containerRef.current;\n if (!container) return;\n\n const handleFocusIn = (e: FocusEvent) => {\n const target = e.target as Node;\n \n if (container.contains(target)) {\n lastFocusedInContainer.current = target as HTMLElement;\n } else {\n // Focus escaped - redirect back\n const fallback = lastFocusedInContainer.current \n || getFirstFocusableElement({ container }) \n || container;\n fallback.focus();\n }\n };\n\n document.addEventListener('focusin', handleFocusIn, true);\n return () => document.removeEventListener('focusin', handleFocusIn, true);\n }, [enabled, containerRef]);\n\n return { triggerRef };\n}\n"],"names":["useRef","useLayoutEffect","getFirstFocusableElement","getFocusableElements","resolveInitialFocusTarget","container","initialFocus","querySelector","HTMLElement","useFocusTrap","enabled","containerRef","restoreFocus","triggerRef","lastFocusedInContainer","current","requestAnimationFrame","focus","document","activeElement","handleKeyDown","e","key","focusables","length","preventDefault","first","last","shiftKey","addEventListener","removeEventListener","handleFocusIn","target","contains"],"mappings":"AA8EA,SAAA,UAAAA,GAAA,mBAAAC,SAAA;AAAA,SAAA,4BAAAC,GAAA,wBAAAC,SAAA;AAAA,SAASC,EACPC,GACAC,GACoB;AACpB,SAAIA,MAAiB,UACZJ,EAAyB;AAAA,IAAEG,WAAAA;AAAAA,EAAAA,CAAW,KAAKA,IAEhDC,MAAiB,cACZD,IAEL,OAAOC,KAAiB,WACnBD,EAAUE,cAA2BD,CAAY,IAEtDA,aAAwBE,cACnBF,IAEF;AACT;AAEO,SAASG,EAAkD;AAAA,EAChEC,SAAAA;AAAAA,EACAC,cAAAA;AAAAA,EACAC,cAAAA,IAAe;AAAA,EACfN,cAAAA,IAAe;AACO,GAAuB;AAC7C,QAAMO,IAAab,EAA2B,IAAI,GAC5Cc,IAAyBd,EAA2B,IAAI;AAG9DC,SAAAA,EAAgB,MAAM;AACpB,QAAI,CAACS,GAAS;AAEZ,MAAIE,KAAgBC,EAAWE,WAC7BC,sBAAsB,MAAM;AAC1BH,QAAAA,EAAWE,SAASE,MAAAA,GACpBJ,EAAWE,UAAU;AAAA,MACvB,CAAC;AAEH;AAAA,IACF;AAEA,UAAMV,IAAYM,EAAaI;AAC/B,IAAKV,MAGLQ,EAAWE,UAAUG,SAASC,eAG9BH,sBAAsB,MAAM;AAC1BZ,MAAAA,EAA0BC,GAAWC,CAAY,GAAGW,MAAAA;AAAAA,IACtD,CAAC;AAAA,EACH,GAAG,CAACP,GAASC,GAAcC,GAAcN,CAAY,CAAC,GAGtDL,EAAgB,MAAM;AACpB,QAAI,CAACS,EAAS;AAEd,UAAML,IAAYM,EAAaI;AAC/B,QAAI,CAACV,EAAW;AAEhB,UAAMe,IAAgBA,CAACC,MAAqB;AAE1C,UAAIA,EAAEC,QAAQ,OAAO;AACnB,cAAMC,IAAapB,EAAqB;AAAA,UAAEE,WAAAA;AAAAA,QAAAA,CAAW;AAErD,YAAIkB,EAAWC,WAAW,GAAG;AAC3BH,UAAAA,EAAEI,eAAAA,GACFpB,EAAUY,MAAAA;AACV;AAAA,QACF;AAEA,cAAMS,IAAQH,EAAW,CAAC,GACpBI,IAAOJ,EAAWA,EAAWC,SAAS,CAAC,GACvCL,IAAgBD,SAASC;AAE/B,QAAIE,EAAEO,YAAYT,MAAkBO,KAClCL,EAAEI,eAAAA,GACFE,EAAKV,MAAAA,KACI,CAACI,EAAEO,YAAYT,MAAkBQ,MAC1CN,EAAEI,eAAAA,GACFC,EAAMT,MAAAA;AAAAA,MAEV;AAAA,IACF;AAEAC,oBAASW,iBAAiB,WAAWT,GAAe,EAAI,GACjD,MAAMF,SAASY,oBAAoB,WAAWV,GAAe,EAAI;AAAA,EAC1E,GAAG,CAACV,GAASC,CAAY,CAAC,GAG1BV,EAAgB,MAAM;AACpB,QAAI,CAACS,EAAS;AAEd,UAAML,IAAYM,EAAaI;AAC/B,QAAI,CAACV,EAAW;AAEhB,UAAM0B,IAAgBA,CAACV,MAAkB;AACvC,YAAMW,IAASX,EAAEW;AAEjB,MAAI3B,EAAU4B,SAASD,CAAM,IAC3BlB,EAAuBC,UAAUiB,KAGhBlB,EAAuBC,WACnCb,EAAyB;AAAA,QAAEG,WAAAA;AAAAA,MAAAA,CAAW,KACtCA,GACIY,MAAAA;AAAAA,IAEb;AAEAC,oBAASW,iBAAiB,WAAWE,GAAe,EAAI,GACjD,MAAMb,SAASY,oBAAoB,WAAWC,GAAe,EAAI;AAAA,EAC1E,GAAG,CAACrB,GAASC,CAAY,CAAC,GAEnB;AAAA,IAAEE,YAAAA;AAAAA,EAAAA;AACX;"}
1
+ {"version":3,"file":"index185.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;"}
@@ -12,4 +12,4 @@ function n(o, u) {
12
12
  export {
13
13
  n as debounce
14
14
  };
15
- //# sourceMappingURL=index194.js.map
15
+ //# sourceMappingURL=index193.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index194.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
+ {"version":3,"file":"index193.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;"}
@@ -1233,4 +1233,4 @@ const e = [
1233
1233
  export {
1234
1234
  e as default
1235
1235
  };
1236
- //# sourceMappingURL=index202.js.map
1236
+ //# sourceMappingURL=index201.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index202.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index201.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,35 @@
1
+ import u, { forwardRef as c } from "react";
2
+ import { Button as p } from "./index3.js";
3
+ const b = /* @__PURE__ */ c(({
4
+ id: t,
5
+ label: e,
6
+ isSelected: a,
7
+ isDisabled: r = !1,
8
+ panelId: o,
9
+ tabIndex: l,
10
+ className: n = "",
11
+ automationId: d,
12
+ onClick: s,
13
+ onFocus: f,
14
+ onKeyDown: i
15
+ }, m) => /* @__PURE__ */ u.createElement(p, {
16
+ ref: m,
17
+ type: "unstyled",
18
+ label: e,
19
+ disabled: r,
20
+ onClick: s,
21
+ className: n,
22
+ automationId: d,
23
+ role: "tab",
24
+ id: t,
25
+ "aria-selected": a,
26
+ "aria-controls": o,
27
+ tabIndex: l,
28
+ onFocus: f,
29
+ onKeyDown: i
30
+ }));
31
+ b.displayName = "TabButton";
32
+ export {
33
+ b as TabButton
34
+ };
35
+ //# sourceMappingURL=index203.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index203.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 aria-controls={panelId}\n tabIndex={tabIndex}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n />\n );\n }\n);\n\nTabButton.displayName = 'TabButton';\n"],"names":["React__default","forwardRef","Button","TabButton","id","label","isSelected","isDisabled","panelId","tabIndex","className","automationId","onClick","onFocus","onKeyDown","ref","React","createElement","type","disabled","role","displayName"],"mappings":"AAsBO,OAAAA,KAAA,cAAAC,SAAA;AAAA,SAAA,UAAAC,SAAA;AAAA,MAAMC,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,cAACf,GAAM;AAAA,EACLa,KAAAA;AAAAA,EACAG,MAAK;AAAA,EACLb,OAAAA;AAAAA,EACAc,UAAUZ;AAAAA,EACVK,SAAAA;AAAAA,EACAF,WAAAA;AAAAA,EACAC,cAAAA;AAAAA,EACAS,MAAK;AAAA,EACLhB,IAAAA;AAAAA,EACA,iBAAeE;AAAAA,EACf,iBAAeE;AAAAA,EACfC,UAAAA;AAAAA,EACAI,SAAAA;AAAAA,EACAC,WAAAA;AAAAA,CACD,CAGP;AAEAX,EAAUkB,cAAc;"}
package/dist/index204.js CHANGED
@@ -1,35 +1,44 @@
1
- import u, { forwardRef as c } from "react";
2
- import { Button as p } from "./index3.js";
3
- const b = /* @__PURE__ */ c(({
4
- id: t,
5
- label: e,
6
- isSelected: a,
7
- isDisabled: r = !1,
8
- panelId: o,
9
- tabIndex: l,
10
- className: n = "",
11
- automationId: d,
12
- onClick: s,
13
- onFocus: f,
14
- onKeyDown: i
15
- }, m) => /* @__PURE__ */ u.createElement(p, {
16
- ref: m,
17
- type: "unstyled",
18
- label: e,
19
- disabled: r,
20
- onClick: s,
21
- className: n,
22
- automationId: d,
23
- role: "tab",
24
- id: t,
25
- "aria-selected": a,
26
- "aria-controls": o,
27
- tabIndex: l,
28
- onFocus: f,
29
- onKeyDown: i
30
- }));
31
- b.displayName = "TabButton";
1
+ import { useCallback as d } from "react";
2
+ import { useRovingFocus as g } from "./index215.js";
3
+ const u = (e, t) => `tab${t ? `-${t}` : ""}-${e}`, c = (e, t) => `panel${t ? `-${t}` : ""}-${e}`;
4
+ function P({
5
+ itemIds: e,
6
+ orientation: t = "horizontal",
7
+ activeNavigationItem: r,
8
+ idBase: n = ""
9
+ }) {
10
+ const {
11
+ setFocusedId: f,
12
+ handleKeyDown: l,
13
+ getRovingItemProps: s
14
+ } = g({
15
+ itemIds: e,
16
+ defaultFocusedId: r,
17
+ orientation: t,
18
+ loop: !0
19
+ });
20
+ return {
21
+ getTabProps: d((o) => {
22
+ const {
23
+ ref: b,
24
+ tabIndex: a
25
+ } = s(o), p = r === o;
26
+ return {
27
+ ref: b,
28
+ tabIndex: a,
29
+ id: u(o, n),
30
+ "aria-controls": c(o, n),
31
+ "aria-selected": p,
32
+ role: "tab"
33
+ };
34
+ }, [r, s, n]),
35
+ setFocusedTabId: f,
36
+ handleKeyDown: l,
37
+ getPanelId: (o) => c(o, n),
38
+ getTabId: (o) => u(o, n)
39
+ };
40
+ }
32
41
  export {
33
- b as TabButton
42
+ P as useTabsA11y
34
43
  };
35
44
  //# sourceMappingURL=index204.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index204.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 aria-controls={panelId}\n tabIndex={tabIndex}\n onFocus={onFocus}\n onKeyDown={onKeyDown}\n />\n );\n }\n);\n\nTabButton.displayName = 'TabButton';\n"],"names":["React__default","forwardRef","Button","TabButton","id","label","isSelected","isDisabled","panelId","tabIndex","className","automationId","onClick","onFocus","onKeyDown","ref","React","createElement","type","disabled","role","displayName"],"mappings":"AAsBO,OAAAA,KAAA,cAAAC,SAAA;AAAA,SAAA,UAAAC,SAAA;AAAA,MAAMC,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,cAACf,GAAM;AAAA,EACLa,KAAAA;AAAAA,EACAG,MAAK;AAAA,EACLb,OAAAA;AAAAA,EACAc,UAAUZ;AAAAA,EACVK,SAAAA;AAAAA,EACAF,WAAAA;AAAAA,EACAC,cAAAA;AAAAA,EACAS,MAAK;AAAA,EACLhB,IAAAA;AAAAA,EACA,iBAAeE;AAAAA,EACf,iBAAeE;AAAAA,EACfC,UAAAA;AAAAA,EACAI,SAAAA;AAAAA,EACAC,WAAAA;AAAAA,CACD,CAGP;AAEAX,EAAUkB,cAAc;"}
1
+ {"version":3,"file":"index204.js","sources":["../src/components/NavigationBar/useTabsA11y.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useRovingFocus } from '../../utils/a11y';\n\nconst getTabId = (itemId: string, idBase: string) => {\n const suffix = idBase ? `-${idBase}` : '';\n return `tab${suffix}-${itemId}`;\n};\n\nconst getPanelId = (itemId: string, idBase: string) => {\n const suffix = idBase ? `-${idBase}` : '';\n return `panel${suffix}-${itemId}`;\n};\n\ninterface UseTabsA11yProps {\n itemIds: string[];\n orientation?: 'horizontal' | 'vertical';\n activeNavigationItem: string;\n idBase?: string;\n}\n\ninterface TabA11yProps {\n ref: (el: HTMLElement | null) => void;\n tabIndex: number;\n id: string;\n 'aria-controls': string;\n 'aria-selected': boolean;\n role: 'tab';\n}\n\n/**\n * Hook for managing Tabs (NavigationBar) focus and ARIA props.\n * Handles roving tabindex pattern and generates tab-specific ARIA attributes.\n * \n * @example\n * const itemIds = useMemo(() => navigationItems.map(item => item.id), [navigationItems]);\n * const { getTabProps, setFocusedTabId, handleKeyDown } = useTabsA11y({\n * itemIds,\n * activeNavigationItem: 'tab-1',\n * orientation: 'horizontal',\n * idBase: 'settings'\n * });\n */\nexport function useTabsA11y({\n itemIds,\n orientation = 'horizontal',\n activeNavigationItem,\n idBase = ''\n}: UseTabsA11yProps) {\n const {\n setFocusedId: setFocusedTabId,\n handleKeyDown,\n getRovingItemProps\n } = useRovingFocus({\n itemIds,\n defaultFocusedId: activeNavigationItem,\n orientation,\n loop: true\n });\n\n /**\n * Get all props needed for a tab button.\n * Combines roving focus props (ref, tabIndex) with tab-specific ARIA attributes.\n */\n const getTabProps = useCallback((itemId: string): TabA11yProps => {\n const { ref, tabIndex } = getRovingItemProps(itemId);\n const isSelected = activeNavigationItem === itemId;\n\n return {\n ref,\n tabIndex,\n id: getTabId(itemId, idBase),\n 'aria-controls': getPanelId(itemId, idBase),\n 'aria-selected': isSelected,\n role: 'tab'\n };\n }, [activeNavigationItem, getRovingItemProps, idBase]);\n\n return {\n getTabProps,\n setFocusedTabId,\n handleKeyDown,\n getPanelId: (itemId: string) => getPanelId(itemId, idBase),\n getTabId: (itemId: string) => getTabId(itemId, idBase)\n };\n}\n\n"],"names":["useCallback","useRovingFocus","getTabId","itemId","idBase","getPanelId","useTabsA11y","itemIds","orientation","activeNavigationItem","setFocusedId","setFocusedTabId","handleKeyDown","getRovingItemProps","defaultFocusedId","loop","getTabProps","ref","tabIndex","isSelected","id","role"],"mappings":"AAGA,SAAA,eAAAA,SAAA;AAAA,SAAA,kBAAAC,SAAA;AAAA,MAAMC,IAAWA,CAACC,GAAgBC,MAEzB,MADQA,IAAS,IAAIA,CAAM,KAAK,EACpB,IAAID,CAAM,IAGzBE,IAAaA,CAACF,GAAgBC,MAE3B,QADQA,IAAS,IAAIA,CAAM,KAAK,EAClB,IAAID,CAAM;AAgC1B,SAASG,EAAY;AAAA,EAC1BC,SAAAA;AAAAA,EACAC,aAAAA,IAAc;AAAA,EACdC,sBAAAA;AAAAA,EACAL,QAAAA,IAAS;AACO,GAAG;AACnB,QAAM;AAAA,IACJM,cAAcC;AAAAA,IACdC,eAAAA;AAAAA,IACAC,oBAAAA;AAAAA,EAAAA,IACEZ,EAAe;AAAA,IACjBM,SAAAA;AAAAA,IACAO,kBAAkBL;AAAAA,IAClBD,aAAAA;AAAAA,IACAO,MAAM;AAAA,EAAA,CACP;AAoBD,SAAO;AAAA,IACLC,aAfkBhB,EAAY,CAACG,MAAiC;AAChE,YAAM;AAAA,QAAEc,KAAAA;AAAAA,QAAKC,UAAAA;AAAAA,MAAAA,IAAaL,EAAmBV,CAAM,GAC7CgB,IAAaV,MAAyBN;AAE5C,aAAO;AAAA,QACLc,KAAAA;AAAAA,QACAC,UAAAA;AAAAA,QACAE,IAAIlB,EAASC,GAAQC,CAAM;AAAA,QAC3B,iBAAiBC,EAAWF,GAAQC,CAAM;AAAA,QAC1C,iBAAiBe;AAAAA,QACjBE,MAAM;AAAA,MAAA;AAAA,IAEV,GAAG,CAACZ,GAAsBI,GAAoBT,CAAM,CAAC;AAAA,IAInDO,iBAAAA;AAAAA,IACAC,eAAAA;AAAAA,IACAP,YAAYA,CAACF,MAAmBE,EAAWF,GAAQC,CAAM;AAAA,IACzDF,UAAUA,CAACC,MAAmBD,EAASC,GAAQC,CAAM;AAAA,EAAA;AAEzD;"}
@@ -4,4 +4,4 @@ function n(e) {
4
4
  export {
5
5
  n as delay
6
6
  };
7
- //# sourceMappingURL=index214.js.map
7
+ //# sourceMappingURL=index213.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index214.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;"}
1
+ {"version":3,"file":"index213.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;"}
@@ -0,0 +1,65 @@
1
+ import * as c from "react";
2
+ function y({
3
+ itemIds: t,
4
+ tabIndex: h = 0,
5
+ defaultFocusedId: l,
6
+ orientation: f = "horizontal",
7
+ loop: u = !0,
8
+ onFocusChange: k
9
+ }) {
10
+ const [a, x] = c.useState(l || t[0] || ""), g = c.useRef({});
11
+ c.useEffect(() => {
12
+ if (t.length > 0 && !t.includes(a)) {
13
+ const e = l || t[0] || "";
14
+ x(e);
15
+ }
16
+ }, [t, a, l]);
17
+ const p = c.useCallback((e) => {
18
+ x(e), k?.(e);
19
+ }, [k]), s = c.useCallback((e) => {
20
+ if (t.length === 0) return;
21
+ const o = t.indexOf(a), n = Math.max(0, o);
22
+ let r = n;
23
+ switch (e) {
24
+ case "first":
25
+ r = 0;
26
+ break;
27
+ case "last":
28
+ r = t.length - 1;
29
+ break;
30
+ case "prev":
31
+ u ? r = (n - 1 + t.length) % t.length : r = Math.max(0, n - 1);
32
+ break;
33
+ case "next":
34
+ u ? r = (n + 1) % t.length : r = Math.min(t.length - 1, n + 1);
35
+ break;
36
+ }
37
+ const v = t[r];
38
+ v && g.current[v]?.focus();
39
+ }, [t, a, u]), b = c.useCallback((e) => ({
40
+ ref: (o) => {
41
+ g.current[e] = o;
42
+ },
43
+ tabIndex: a === e ? h : -1
44
+ }), [a, h]), w = c.useCallback((e) => {
45
+ if (e.key === "Home") {
46
+ e.preventDefault(), s("first");
47
+ return;
48
+ }
49
+ if (e.key === "End") {
50
+ e.preventDefault(), s("last");
51
+ return;
52
+ }
53
+ const o = f === "horizontal" ? "ArrowLeft" : "ArrowUp", n = f === "horizontal" ? "ArrowRight" : "ArrowDown";
54
+ e.key === o ? (e.preventDefault(), s("prev")) : e.key === n && (e.preventDefault(), s("next"));
55
+ }, [f, s]);
56
+ return {
57
+ setFocusedId: p,
58
+ handleKeyDown: w,
59
+ getRovingItemProps: b
60
+ };
61
+ }
62
+ export {
63
+ y as useRovingFocus
64
+ };
65
+ //# sourceMappingURL=index215.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index215.js","sources":["../src/utils/a11y/useRovingFocus.ts"],"sourcesContent":["import * as React from 'react';\n\nexport type RovingDirection = 'prev' | 'next' | 'first' | 'last';\n\nexport interface UseRovingFocusOptions {\n /**\n * Array of item IDs in order\n */\n itemIds: string[];\n\n /**\n * The tabIndex to apply to the currently focused item in the roving group.\n * Defaults to 0 \n */\n tabIndex?: number;\n\n /**\n * Initial focused item ID. Defaults to first item.\n */\n defaultFocusedId?: string;\n\n /**\n * Orientation for arrow key mapping.\n * - horizontal: ArrowLeft/ArrowRight\n * - vertical: ArrowUp/ArrowDown\n */\n orientation?: 'horizontal' | 'vertical';\n\n /**\n * Whether navigation wraps around at ends. Defaults to true.\n */\n loop?: boolean;\n\n /**\n * Callback when focus changes\n */\n onFocusChange?: (id: string) => void;\n}\n\nexport interface RovingItemProps {\n ref: (el: HTMLElement | null) => void;\n tabIndex: number;\n}\n\nexport interface UseRovingFocusReturn {\n /**\n * Set focused item ID manually\n */\n setFocusedId: (id: string) => void;\n\n /**\n * Keyboard handler for arrow/Home/End navigation.\n * Attach to each item's onKeyDown.\n */\n handleKeyDown: (e: React.KeyboardEvent) => void;\n\n /**\n * Get props for an item in the roving focus group (ref + tabIndex)\n */\n getRovingItemProps: (id: string) => RovingItemProps;\n}\n\n/**\n * Hook for managing roving focus pattern (roving tabindex).\n * Reusable for composite widgets: tabs, toolbars, menus, listboxes, radio groups.\n *\n * @example\n * const { getRovingItemProps, handleKeyDown } = useRovingFocus({\n * itemIds: ['tab1', 'tab2', 'tab3'],\n * orientation: 'horizontal'\n * });\n *\n * // In render:\n * <button {...getRovingItemProps('tab1')} onKeyDown={handleKeyDown}>Tab 1</button>\n */\nexport function useRovingFocus({\n itemIds,\n tabIndex = 0,\n defaultFocusedId,\n orientation = 'horizontal',\n loop = true,\n onFocusChange\n}: UseRovingFocusOptions): UseRovingFocusReturn {\n const [focusedId, setFocusedIdState] = React.useState<string>(\n defaultFocusedId || itemIds[0] || ''\n );\n\n const itemRefs = React.useRef<Record<string, HTMLElement | null>>({});\n\n // Sync focusedId if itemIds change and current focusedId is no longer valid\n React.useEffect(() => {\n if (itemIds.length > 0 && !itemIds.includes(focusedId)) {\n const newFocusedId = defaultFocusedId || itemIds[0] || '';\n setFocusedIdState(newFocusedId);\n }\n }, [itemIds, focusedId, defaultFocusedId]);\n\n const setFocusedId = React.useCallback(\n (id: string) => {\n setFocusedIdState(id);\n onFocusChange?.(id);\n },\n [onFocusChange]\n );\n\n const moveFocus = React.useCallback(\n (direction: RovingDirection) => {\n if (itemIds.length === 0) return;\n\n const currentIdx = itemIds.indexOf(focusedId);\n const safeIdx = Math.max(0, currentIdx);\n let nextIdx = safeIdx;\n\n switch (direction) {\n case 'first':\n nextIdx = 0;\n break;\n case 'last':\n nextIdx = itemIds.length - 1;\n break;\n case 'prev':\n if (loop) {\n nextIdx = (safeIdx - 1 + itemIds.length) % itemIds.length;\n } else {\n nextIdx = Math.max(0, safeIdx - 1);\n }\n break;\n case 'next':\n if (loop) {\n nextIdx = (safeIdx + 1) % itemIds.length;\n } else {\n nextIdx = Math.min(itemIds.length - 1, safeIdx + 1);\n }\n break;\n }\n\n const nextId = itemIds[nextIdx];\n if (!nextId) return;\n\n // Focus the element\n itemRefs.current[nextId]?.focus();\n // Note: We don't call setFocusedId here because the element's onFocus\n // should handle that (follows \"focus follows DOM focus\" pattern)\n },\n [itemIds, focusedId, loop]\n );\n\n const getRovingItemProps = React.useCallback(\n (id: string): RovingItemProps => ({\n ref: (el: HTMLElement | null) => {\n itemRefs.current[id] = el;\n },\n tabIndex: focusedId === id ? tabIndex : -1\n }),\n [focusedId, tabIndex]\n );\n\n // Keyboard handler for arrow/Home/End navigation\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Home') {\n e.preventDefault();\n moveFocus('first');\n return;\n }\n if (e.key === 'End') {\n e.preventDefault();\n moveFocus('last');\n return;\n }\n\n const prevKey = orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp';\n const nextKey = orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown';\n\n if (e.key === prevKey) {\n e.preventDefault();\n moveFocus('prev');\n } else if (e.key === nextKey) {\n e.preventDefault();\n moveFocus('next');\n }\n },\n [orientation, moveFocus]\n );\n\n return {\n setFocusedId,\n handleKeyDown,\n getRovingItemProps\n };\n}\n"],"names":["React","useRovingFocus","itemIds","tabIndex","defaultFocusedId","orientation","loop","onFocusChange","focusedId","setFocusedIdState","useState","itemRefs","useRef","useEffect","length","includes","newFocusedId","setFocusedId","useCallback","id","moveFocus","direction","currentIdx","indexOf","safeIdx","Math","max","nextIdx","min","nextId","current","focus","getRovingItemProps","ref","el","handleKeyDown","e","key","preventDefault","prevKey","nextKey"],"mappings":"AA2EO,YAAAA,OAAA;AAAA,SAASC,EAAe;AAAA,EAC7BC,SAAAA;AAAAA,EACAC,UAAAA,IAAW;AAAA,EACXC,kBAAAA;AAAAA,EACAC,aAAAA,IAAc;AAAA,EACdC,MAAAA,IAAO;AAAA,EACPC,eAAAA;AACqB,GAAyB;AAC9C,QAAM,CAACC,GAAWC,CAAiB,IAAIT,EAAMU,SAC3CN,KAAoBF,EAAQ,CAAC,KAAK,EACpC,GAEMS,IAAWX,EAAMY,OAA2C,EAAE;AAGpEZ,EAAAA,EAAMa,UAAU,MAAM;AACpB,QAAIX,EAAQY,SAAS,KAAK,CAACZ,EAAQa,SAASP,CAAS,GAAG;AACtD,YAAMQ,IAAeZ,KAAoBF,EAAQ,CAAC,KAAK;AACvDO,MAAAA,EAAkBO,CAAY;AAAA,IAChC;AAAA,EACF,GAAG,CAACd,GAASM,GAAWJ,CAAgB,CAAC;AAEzC,QAAMa,IAAejB,EAAMkB,YACzB,CAACC,MAAe;AACdV,IAAAA,EAAkBU,CAAE,GACpBZ,IAAgBY,CAAE;AAAA,EACpB,GACA,CAACZ,CAAa,CAChB,GAEMa,IAAYpB,EAAMkB,YACtB,CAACG,MAA+B;AAC9B,QAAInB,EAAQY,WAAW,EAAG;AAE1B,UAAMQ,IAAapB,EAAQqB,QAAQf,CAAS,GACtCgB,IAAUC,KAAKC,IAAI,GAAGJ,CAAU;AACtC,QAAIK,IAAUH;AAEd,YAAQH,GAAAA;AAAAA,MACN,KAAK;AACHM,QAAAA,IAAU;AACV;AAAA,MACF,KAAK;AACHA,QAAAA,IAAUzB,EAAQY,SAAS;AAC3B;AAAA,MACF,KAAK;AACH,QAAIR,IACFqB,KAAWH,IAAU,IAAItB,EAAQY,UAAUZ,EAAQY,SAEnDa,IAAUF,KAAKC,IAAI,GAAGF,IAAU,CAAC;AAEnC;AAAA,MACF,KAAK;AACH,QAAIlB,IACFqB,KAAWH,IAAU,KAAKtB,EAAQY,SAElCa,IAAUF,KAAKG,IAAI1B,EAAQY,SAAS,GAAGU,IAAU,CAAC;AAEpD;AAAA,IAAA;AAGJ,UAAMK,IAAS3B,EAAQyB,CAAO;AAC9B,IAAKE,KAGLlB,EAASmB,QAAQD,CAAM,GAAGE,MAAAA;AAAAA,EAG5B,GACA,CAAC7B,GAASM,GAAWF,CAAI,CAC3B,GAEM0B,IAAqBhC,EAAMkB,YAC/B,CAACC,OAAiC;AAAA,IAChCc,KAAKA,CAACC,MAA2B;AAC/BvB,MAAAA,EAASmB,QAAQX,CAAE,IAAIe;AAAAA,IACzB;AAAA,IACA/B,UAAUK,MAAcW,IAAKhB,IAAW;AAAA,EAAA,IAE1C,CAACK,GAAWL,CAAQ,CACtB,GAGMgC,IAAgBnC,EAAMkB,YAC1B,CAACkB,MAA2B;AAC1B,QAAIA,EAAEC,QAAQ,QAAQ;AACpBD,QAAEE,eAAAA,GACFlB,EAAU,OAAO;AACjB;AAAA,IACF;AACA,QAAIgB,EAAEC,QAAQ,OAAO;AACnBD,QAAEE,eAAAA,GACFlB,EAAU,MAAM;AAChB;AAAA,IACF;AAEA,UAAMmB,IAAUlC,MAAgB,eAAe,cAAc,WACvDmC,IAAUnC,MAAgB,eAAe,eAAe;AAE9D,IAAI+B,EAAEC,QAAQE,KACZH,EAAEE,eAAAA,GACFlB,EAAU,MAAM,KACPgB,EAAEC,QAAQG,MACnBJ,EAAEE,eAAAA,GACFlB,EAAU,MAAM;AAAA,EAEpB,GACA,CAACf,GAAae,CAAS,CACzB;AAEA,SAAO;AAAA,IACLH,cAAAA;AAAAA,IACAkB,eAAAA;AAAAA,IACAH,oBAAAA;AAAAA,EAAAA;AAEJ;"}
package/dist/index216.js CHANGED
@@ -1,65 +1,8 @@
1
- import * as c from "react";
2
- function y({
3
- itemIds: t,
4
- tabIndex: h = 0,
5
- defaultFocusedId: l,
6
- orientation: f = "horizontal",
7
- loop: u = !0,
8
- onFocusChange: k
9
- }) {
10
- const [a, x] = c.useState(l || t[0] || ""), g = c.useRef({});
11
- c.useEffect(() => {
12
- if (t.length > 0 && !t.includes(a)) {
13
- const e = l || t[0] || "";
14
- x(e);
15
- }
16
- }, [t, a, l]);
17
- const p = c.useCallback((e) => {
18
- x(e), k?.(e);
19
- }, [k]), s = c.useCallback((e) => {
20
- if (t.length === 0) return;
21
- const o = t.indexOf(a), n = Math.max(0, o);
22
- let r = n;
23
- switch (e) {
24
- case "first":
25
- r = 0;
26
- break;
27
- case "last":
28
- r = t.length - 1;
29
- break;
30
- case "prev":
31
- u ? r = (n - 1 + t.length) % t.length : r = Math.max(0, n - 1);
32
- break;
33
- case "next":
34
- u ? r = (n + 1) % t.length : r = Math.min(t.length - 1, n + 1);
35
- break;
36
- }
37
- const v = t[r];
38
- v && g.current[v]?.focus();
39
- }, [t, a, u]), b = c.useCallback((e) => ({
40
- ref: (o) => {
41
- g.current[e] = o;
42
- },
43
- tabIndex: a === e ? h : -1
44
- }), [a, h]), w = c.useCallback((e) => {
45
- if (e.key === "Home") {
46
- e.preventDefault(), s("first");
47
- return;
48
- }
49
- if (e.key === "End") {
50
- e.preventDefault(), s("last");
51
- return;
52
- }
53
- const o = f === "horizontal" ? "ArrowLeft" : "ArrowUp", n = f === "horizontal" ? "ArrowRight" : "ArrowDown";
54
- e.key === o ? (e.preventDefault(), s("prev")) : e.key === n && (e.preventDefault(), s("next"));
55
- }, [f, s]);
56
- return {
57
- setFocusedId: p,
58
- handleKeyDown: w,
59
- getRovingItemProps: b
60
- };
61
- }
1
+ const t = () => typeof navigator < "u" && /Android/i.test(navigator.userAgent), o = (i) => {
2
+ const r = "pointerType" in i ? i.pointerType : void 0;
3
+ return r === "" && i.isTrusted ? !0 : t() && r ? i.type === "click" && i.buttons === 1 : i.detail === 0 && !r;
4
+ };
62
5
  export {
63
- y as useRovingFocus
6
+ o as isVirtualClick
64
7
  };
65
8
  //# sourceMappingURL=index216.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index216.js","sources":["../src/utils/a11y/useRovingFocus.ts"],"sourcesContent":["import * as React from 'react';\n\nexport type RovingDirection = 'prev' | 'next' | 'first' | 'last';\n\nexport interface UseRovingFocusOptions {\n /**\n * Array of item IDs in order\n */\n itemIds: string[];\n\n /**\n * The tabIndex to apply to the currently focused item in the roving group.\n * Defaults to 0 \n */\n tabIndex?: number;\n\n /**\n * Initial focused item ID. Defaults to first item.\n */\n defaultFocusedId?: string;\n\n /**\n * Orientation for arrow key mapping.\n * - horizontal: ArrowLeft/ArrowRight\n * - vertical: ArrowUp/ArrowDown\n */\n orientation?: 'horizontal' | 'vertical';\n\n /**\n * Whether navigation wraps around at ends. Defaults to true.\n */\n loop?: boolean;\n\n /**\n * Callback when focus changes\n */\n onFocusChange?: (id: string) => void;\n}\n\nexport interface RovingItemProps {\n ref: (el: HTMLElement | null) => void;\n tabIndex: number;\n}\n\nexport interface UseRovingFocusReturn {\n /**\n * Set focused item ID manually\n */\n setFocusedId: (id: string) => void;\n\n /**\n * Keyboard handler for arrow/Home/End navigation.\n * Attach to each item's onKeyDown.\n */\n handleKeyDown: (e: React.KeyboardEvent) => void;\n\n /**\n * Get props for an item in the roving focus group (ref + tabIndex)\n */\n getRovingItemProps: (id: string) => RovingItemProps;\n}\n\n/**\n * Hook for managing roving focus pattern (roving tabindex).\n * Reusable for composite widgets: tabs, toolbars, menus, listboxes, radio groups.\n *\n * @example\n * const { getRovingItemProps, handleKeyDown } = useRovingFocus({\n * itemIds: ['tab1', 'tab2', 'tab3'],\n * orientation: 'horizontal'\n * });\n *\n * // In render:\n * <button {...getRovingItemProps('tab1')} onKeyDown={handleKeyDown}>Tab 1</button>\n */\nexport function useRovingFocus({\n itemIds,\n tabIndex = 0,\n defaultFocusedId,\n orientation = 'horizontal',\n loop = true,\n onFocusChange\n}: UseRovingFocusOptions): UseRovingFocusReturn {\n const [focusedId, setFocusedIdState] = React.useState<string>(\n defaultFocusedId || itemIds[0] || ''\n );\n\n const itemRefs = React.useRef<Record<string, HTMLElement | null>>({});\n\n // Sync focusedId if itemIds change and current focusedId is no longer valid\n React.useEffect(() => {\n if (itemIds.length > 0 && !itemIds.includes(focusedId)) {\n const newFocusedId = defaultFocusedId || itemIds[0] || '';\n setFocusedIdState(newFocusedId);\n }\n }, [itemIds, focusedId, defaultFocusedId]);\n\n const setFocusedId = React.useCallback(\n (id: string) => {\n setFocusedIdState(id);\n onFocusChange?.(id);\n },\n [onFocusChange]\n );\n\n const moveFocus = React.useCallback(\n (direction: RovingDirection) => {\n if (itemIds.length === 0) return;\n\n const currentIdx = itemIds.indexOf(focusedId);\n const safeIdx = Math.max(0, currentIdx);\n let nextIdx = safeIdx;\n\n switch (direction) {\n case 'first':\n nextIdx = 0;\n break;\n case 'last':\n nextIdx = itemIds.length - 1;\n break;\n case 'prev':\n if (loop) {\n nextIdx = (safeIdx - 1 + itemIds.length) % itemIds.length;\n } else {\n nextIdx = Math.max(0, safeIdx - 1);\n }\n break;\n case 'next':\n if (loop) {\n nextIdx = (safeIdx + 1) % itemIds.length;\n } else {\n nextIdx = Math.min(itemIds.length - 1, safeIdx + 1);\n }\n break;\n }\n\n const nextId = itemIds[nextIdx];\n if (!nextId) return;\n\n // Focus the element\n itemRefs.current[nextId]?.focus();\n // Note: We don't call setFocusedId here because the element's onFocus\n // should handle that (follows \"focus follows DOM focus\" pattern)\n },\n [itemIds, focusedId, loop]\n );\n\n const getRovingItemProps = React.useCallback(\n (id: string): RovingItemProps => ({\n ref: (el: HTMLElement | null) => {\n itemRefs.current[id] = el;\n },\n tabIndex: focusedId === id ? tabIndex : -1\n }),\n [focusedId, tabIndex]\n );\n\n // Keyboard handler for arrow/Home/End navigation\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Home') {\n e.preventDefault();\n moveFocus('first');\n return;\n }\n if (e.key === 'End') {\n e.preventDefault();\n moveFocus('last');\n return;\n }\n\n const prevKey = orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp';\n const nextKey = orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown';\n\n if (e.key === prevKey) {\n e.preventDefault();\n moveFocus('prev');\n } else if (e.key === nextKey) {\n e.preventDefault();\n moveFocus('next');\n }\n },\n [orientation, moveFocus]\n );\n\n return {\n setFocusedId,\n handleKeyDown,\n getRovingItemProps\n };\n}\n"],"names":["React","useRovingFocus","itemIds","tabIndex","defaultFocusedId","orientation","loop","onFocusChange","focusedId","setFocusedIdState","useState","itemRefs","useRef","useEffect","length","includes","newFocusedId","setFocusedId","useCallback","id","moveFocus","direction","currentIdx","indexOf","safeIdx","Math","max","nextIdx","min","nextId","current","focus","getRovingItemProps","ref","el","handleKeyDown","e","key","preventDefault","prevKey","nextKey"],"mappings":"AA2EO,YAAAA,OAAA;AAAA,SAASC,EAAe;AAAA,EAC7BC,SAAAA;AAAAA,EACAC,UAAAA,IAAW;AAAA,EACXC,kBAAAA;AAAAA,EACAC,aAAAA,IAAc;AAAA,EACdC,MAAAA,IAAO;AAAA,EACPC,eAAAA;AACqB,GAAyB;AAC9C,QAAM,CAACC,GAAWC,CAAiB,IAAIT,EAAMU,SAC3CN,KAAoBF,EAAQ,CAAC,KAAK,EACpC,GAEMS,IAAWX,EAAMY,OAA2C,EAAE;AAGpEZ,EAAAA,EAAMa,UAAU,MAAM;AACpB,QAAIX,EAAQY,SAAS,KAAK,CAACZ,EAAQa,SAASP,CAAS,GAAG;AACtD,YAAMQ,IAAeZ,KAAoBF,EAAQ,CAAC,KAAK;AACvDO,MAAAA,EAAkBO,CAAY;AAAA,IAChC;AAAA,EACF,GAAG,CAACd,GAASM,GAAWJ,CAAgB,CAAC;AAEzC,QAAMa,IAAejB,EAAMkB,YACzB,CAACC,MAAe;AACdV,IAAAA,EAAkBU,CAAE,GACpBZ,IAAgBY,CAAE;AAAA,EACpB,GACA,CAACZ,CAAa,CAChB,GAEMa,IAAYpB,EAAMkB,YACtB,CAACG,MAA+B;AAC9B,QAAInB,EAAQY,WAAW,EAAG;AAE1B,UAAMQ,IAAapB,EAAQqB,QAAQf,CAAS,GACtCgB,IAAUC,KAAKC,IAAI,GAAGJ,CAAU;AACtC,QAAIK,IAAUH;AAEd,YAAQH,GAAAA;AAAAA,MACN,KAAK;AACHM,QAAAA,IAAU;AACV;AAAA,MACF,KAAK;AACHA,QAAAA,IAAUzB,EAAQY,SAAS;AAC3B;AAAA,MACF,KAAK;AACH,QAAIR,IACFqB,KAAWH,IAAU,IAAItB,EAAQY,UAAUZ,EAAQY,SAEnDa,IAAUF,KAAKC,IAAI,GAAGF,IAAU,CAAC;AAEnC;AAAA,MACF,KAAK;AACH,QAAIlB,IACFqB,KAAWH,IAAU,KAAKtB,EAAQY,SAElCa,IAAUF,KAAKG,IAAI1B,EAAQY,SAAS,GAAGU,IAAU,CAAC;AAEpD;AAAA,IAAA;AAGJ,UAAMK,IAAS3B,EAAQyB,CAAO;AAC9B,IAAKE,KAGLlB,EAASmB,QAAQD,CAAM,GAAGE,MAAAA;AAAAA,EAG5B,GACA,CAAC7B,GAASM,GAAWF,CAAI,CAC3B,GAEM0B,IAAqBhC,EAAMkB,YAC/B,CAACC,OAAiC;AAAA,IAChCc,KAAKA,CAACC,MAA2B;AAC/BvB,MAAAA,EAASmB,QAAQX,CAAE,IAAIe;AAAAA,IACzB;AAAA,IACA/B,UAAUK,MAAcW,IAAKhB,IAAW;AAAA,EAAA,IAE1C,CAACK,GAAWL,CAAQ,CACtB,GAGMgC,IAAgBnC,EAAMkB,YAC1B,CAACkB,MAA2B;AAC1B,QAAIA,EAAEC,QAAQ,QAAQ;AACpBD,QAAEE,eAAAA,GACFlB,EAAU,OAAO;AACjB;AAAA,IACF;AACA,QAAIgB,EAAEC,QAAQ,OAAO;AACnBD,QAAEE,eAAAA,GACFlB,EAAU,MAAM;AAChB;AAAA,IACF;AAEA,UAAMmB,IAAUlC,MAAgB,eAAe,cAAc,WACvDmC,IAAUnC,MAAgB,eAAe,eAAe;AAE9D,IAAI+B,EAAEC,QAAQE,KACZH,EAAEE,eAAAA,GACFlB,EAAU,MAAM,KACPgB,EAAEC,QAAQG,MACnBJ,EAAEE,eAAAA,GACFlB,EAAU,MAAM;AAAA,EAEpB,GACA,CAACf,GAAae,CAAS,CACzB;AAEA,SAAO;AAAA,IACLH,cAAAA;AAAAA,IACAkB,eAAAA;AAAAA,IACAH,oBAAAA;AAAAA,EAAAA;AAEJ;"}
1
+ {"version":3,"file":"index216.js","sources":["../src/utils/virtualClick.ts"],"sourcesContent":["/**\n * Input/virtual click detection helpers.\n */\n\nconst isAndroid = () =>\n typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent);\n\nexport const isVirtualClick = (event: MouseEvent | PointerEvent): boolean => {\n const pointerType = 'pointerType' in event ? event.pointerType : undefined;\n\n // JAWS/NVDA with Firefox.\n if (pointerType === '' && event.isTrusted) {\n return true;\n }\n\n // Android TalkBack's detail value varies depending on listener type.\n if (isAndroid() && pointerType) {\n return event.type === 'click' && event.buttons === 1;\n }\n\n // Most browsers: virtual click has detail === 0 and no pointerType.\n return event.detail === 0 && !pointerType;\n};\n\n\n"],"names":["isAndroid","navigator","test","userAgent","isVirtualClick","event","pointerType","undefined","isTrusted","type","buttons","detail"],"mappings":"AAIA,MAAMA,IAAYA,MAChB,OAAOC,YAAc,OAAe,WAAWC,KAAKD,UAAUE,SAAS,GAE5DC,IAAiBA,CAACC,MAA8C;AAC3E,QAAMC,IAAc,iBAAiBD,IAAQA,EAAMC,cAAcC;AAGjE,SAAID,MAAgB,MAAMD,EAAMG,YACvB,KAILR,EAAAA,KAAeM,IACVD,EAAMI,SAAS,WAAWJ,EAAMK,YAAY,IAI9CL,EAAMM,WAAW,KAAK,CAACL;AAChC;"}
package/dist/index217.js CHANGED
@@ -1,8 +1,13 @@
1
- const t = () => typeof navigator < "u" && /Android/i.test(navigator.userAgent), o = (i) => {
2
- const r = "pointerType" in i ? i.pointerType : void 0;
3
- return r === "" && i.isTrusted ? !0 : t() && r ? i.type === "click" && i.buttons === 1 : i.detail === 0 && !r;
4
- };
1
+ function r(t, i) {
2
+ if (t == null) return {};
3
+ var o = {};
4
+ for (var e in t) if ({}.hasOwnProperty.call(t, e)) {
5
+ if (i.indexOf(e) !== -1) continue;
6
+ o[e] = t[e];
7
+ }
8
+ return o;
9
+ }
5
10
  export {
6
- o as isVirtualClick
11
+ r as default
7
12
  };
8
13
  //# sourceMappingURL=index217.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index217.js","sources":["../src/utils/virtualClick.ts"],"sourcesContent":["/**\n * Input/virtual click detection helpers.\n */\n\nconst isAndroid = () =>\n typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent);\n\nexport const isVirtualClick = (event: MouseEvent | PointerEvent): boolean => {\n const pointerType = 'pointerType' in event ? event.pointerType : undefined;\n\n // JAWS/NVDA with Firefox.\n if (pointerType === '' && event.isTrusted) {\n return true;\n }\n\n // Android TalkBack's detail value varies depending on listener type.\n if (isAndroid() && pointerType) {\n return event.type === 'click' && event.buttons === 1;\n }\n\n // Most browsers: virtual click has detail === 0 and no pointerType.\n return event.detail === 0 && !pointerType;\n};\n\n\n"],"names":["isAndroid","navigator","test","userAgent","isVirtualClick","event","pointerType","undefined","isTrusted","type","buttons","detail"],"mappings":"AAIA,MAAMA,IAAYA,MAChB,OAAOC,YAAc,OAAe,WAAWC,KAAKD,UAAUE,SAAS,GAE5DC,IAAiBA,CAACC,MAA8C;AAC3E,QAAMC,IAAc,iBAAiBD,IAAQA,EAAMC,cAAcC;AAGjE,SAAID,MAAgB,MAAMD,EAAMG,YACvB,KAILR,EAAAA,KAAeM,IACVD,EAAMI,SAAS,WAAWJ,EAAMK,YAAY,IAI9CL,EAAMM,WAAW,KAAK,CAACL;AAChC;"}
1
+ {"version":3,"file":"index217.js","sources":["../node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js"],"sourcesContent":["function _objectWithoutPropertiesLoose(r, e) {\n if (null == r) return {};\n var t = {};\n for (var n in r) if ({}.hasOwnProperty.call(r, n)) {\n if (-1 !== e.indexOf(n)) continue;\n t[n] = r[n];\n }\n return t;\n}\nexport { _objectWithoutPropertiesLoose as default };"],"names":["_objectWithoutPropertiesLoose","r","e","t","n"],"mappings":"AAAA,SAASA,EAA8BC,GAAGC,GAAG;AAC3C,MAAYD,KAAR,KAAW,QAAO,CAAA;AACtB,MAAIE,IAAI,CAAA;AACR,WAASC,KAAKH,EAAG,KAAI,CAAA,EAAG,eAAe,KAAKA,GAAGG,CAAC,GAAG;AACjD,QAAWF,EAAE,QAAQE,CAAC,MAAlB,GAAqB;AACzB,IAAAD,EAAEC,CAAC,IAAIH,EAAEG,CAAC;AAAA,EACZ;AACA,SAAOD;AACT;","x_google_ignoreList":[0]}
package/dist/index218.js CHANGED
@@ -1,25 +1,13 @@
1
- const l = ["button:not([disabled])", "[href]", "input:not([disabled])", "select:not([disabled])", "textarea:not([disabled])", '[tabindex]:not([tabindex="-1"]):not([disabled])', '[contenteditable="true"]'].join(", "), a = [l, '[role="menuitem"]', '[role="option"]', '[role="menuitemcheckbox"]', '[role="menuitemradio"]'].join(", ");
2
- function u({
3
- container: e,
4
- includeRoles: t = !1,
5
- additionalSelectors: r = [],
6
- filterHidden: s = !1
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;
14
- }
15
- function c(e) {
16
- const t = u(e);
17
- return t.length > 0 ? t[0] : null;
1
+ function e() {
2
+ return e = Object.assign ? Object.assign.bind() : function(t) {
3
+ for (var n = 1; n < arguments.length; n++) {
4
+ var a = arguments[n];
5
+ for (var r in a) ({}).hasOwnProperty.call(a, r) && (t[r] = a[r]);
6
+ }
7
+ return t;
8
+ }, e.apply(null, arguments);
18
9
  }
19
10
  export {
20
- l as FOCUSABLE_SELECTOR,
21
- a as FOCUSABLE_WITH_ROLES_SELECTOR,
22
- c as getFirstFocusableElement,
23
- u as getFocusableElements
11
+ e as default
24
12
  };
25
13
  //# sourceMappingURL=index218.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index218.js","sources":["../src/utils/a11y/focusableElements.ts"],"sourcesContent":["/**\n * Utilities for finding focusable elements within a container.\n * \n * Used for focus management in modals, popovers, and other interactive overlays.\n */\n\n/**\n * Base selector for standard focusable elements.\n * Matches: buttons, links, inputs, selects, textareas, elements with tabindex >= 0, contenteditable.\n */\nexport const FOCUSABLE_SELECTOR = [\n 'button:not([disabled])',\n '[href]',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"]):not([disabled])',\n '[contenteditable=\"true\"]'\n].join(', ');\n\n/**\n * Extended selector that includes ARIA role-based focusable elements.\n * Useful for composite widgets like menus, listboxes, etc.\n */\nexport const FOCUSABLE_WITH_ROLES_SELECTOR = [\n FOCUSABLE_SELECTOR,\n '[role=\"menuitem\"]',\n '[role=\"option\"]',\n '[role=\"menuitemcheckbox\"]',\n '[role=\"menuitemradio\"]'\n].join(', ');\n\n/**\n * Options for getFocusableElements\n */\nexport interface GetFocusableElementsOptions {\n /**\n * Container element to search within. If null/undefined, returns empty array.\n */\n container: HTMLElement | null;\n /**\n * Whether to include role-based focusable elements (menuitem, option, etc.).\n * Default: false (uses base selector only)\n */\n includeRoles?: boolean;\n /**\n * Additional custom selectors to include.\n */\n additionalSelectors?: string[];\n /**\n * Whether to filter out hidden/invisible elements.\n * Default: false (returns all matching elements regardless of visibility)\n */\n filterHidden?: boolean;\n}\n\n/**\n * Get all focusable elements within a container.\n * \n * @example Basic usage (standard focusable elements)\n * ```ts\n * const focusables = getFocusableElements({ container: dialogRef.current });\n * focusables[0]?.focus(); // Focus first element\n * ```\n * \n * @example With role-based elements (for menus/listboxes)\n * ```ts\n * const focusables = getFocusableElements({ \n * container: menuRef.current,\n * includeRoles: true \n * });\n * ```\n * \n * @example With custom selectors\n * ```ts\n * const focusables = getFocusableElements({ \n * container: customWidgetRef.current,\n * additionalSelectors: ['[data-focusable=\"true\"]']\n * });\n * ```\n */\nexport function getFocusableElements({\n container,\n includeRoles = false,\n additionalSelectors = [],\n filterHidden = false\n}: GetFocusableElementsOptions): HTMLElement[] {\n if (!container) return [];\n\n const selector = [\n includeRoles ? FOCUSABLE_WITH_ROLES_SELECTOR : FOCUSABLE_SELECTOR,\n ...additionalSelectors\n ].filter(Boolean).join(', ');\n\n const elements = Array.from(container.querySelectorAll<HTMLElement>(selector));\n\n if (!filterHidden) return elements;\n\n // Filter out hidden/invisible elements\n return elements.filter((el) => {\n const style = window.getComputedStyle(el);\n return (\n style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0' &&\n !el.hasAttribute('hidden') &&\n el.offsetWidth > 0 &&\n el.offsetHeight > 0\n );\n });\n}\n\n/**\n * Get the first focusable element in a container.\n * Returns null if none found.\n */\nexport function getFirstFocusableElement(\n options: GetFocusableElementsOptions\n): HTMLElement | null {\n const focusables = getFocusableElements(options);\n return focusables.length > 0 ? focusables[0] : null;\n}\n\n/**\n * Get the last focusable element in a container.\n * Returns null if none found.\n */\nexport function getLastFocusableElement(\n options: GetFocusableElementsOptions\n): HTMLElement | null {\n const focusables = getFocusableElements(options);\n return focusables.length > 0 ? focusables[focusables.length - 1] : null;\n}\n"],"names":["FOCUSABLE_SELECTOR","join","FOCUSABLE_WITH_ROLES_SELECTOR","getFocusableElements","container","includeRoles","additionalSelectors","filterHidden","selector","filter","Boolean","elements","Array","from","querySelectorAll","el","style","window","getComputedStyle","display","visibility","opacity","hasAttribute","offsetWidth","offsetHeight","getFirstFocusableElement","options","focusables","length"],"mappings":"AAUO,MAAMA,IAAqB,CAChC,0BACA,UACA,yBACA,0BACA,4BACA,mDACA,0BAA0B,EAC1BC,KAAK,IAAI,GAMEC,IAAgC,CAC3CF,GACA,qBACA,mBACA,6BACA,wBAAwB,EACxBC,KAAK,IAAI;AAmDJ,SAASE,EAAqB;AAAA,EACnCC,WAAAA;AAAAA,EACAC,cAAAA,IAAe;AAAA,EACfC,qBAAAA,IAAsB,CAAA;AAAA,EACtBC,cAAAA,IAAe;AACY,GAAkB;AAC7C,MAAI,CAACH,EAAW,QAAO,CAAA;AAEvB,QAAMI,IAAW,CACfH,IAAeH,IAAgCF,GAC/C,GAAGM,CAAmB,EACtBG,OAAOC,OAAO,EAAET,KAAK,IAAI,GAErBU,IAAWC,MAAMC,KAAKT,EAAUU,iBAA8BN,CAAQ,CAAC;AAE7E,SAAKD,IAGEI,EAASF,OAAQM,CAAAA,MAAO;AAC7B,UAAMC,IAAQC,OAAOC,iBAAiBH,CAAE;AACxC,WACEC,EAAMG,YAAY,UAClBH,EAAMI,eAAe,YACrBJ,EAAMK,YAAY,OAClB,CAACN,EAAGO,aAAa,QAAQ,KACzBP,EAAGQ,cAAc,KACjBR,EAAGS,eAAe;AAAA,EAEtB,CAAC,IAbyBb;AAc5B;AAMO,SAASc,EACdC,GACoB;AACpB,QAAMC,IAAaxB,EAAqBuB,CAAO;AAC/C,SAAOC,EAAWC,SAAS,IAAID,EAAW,CAAC,IAAI;AACjD;"}
1
+ {"version":3,"file":"index218.js","sources":["../node_modules/@babel/runtime/helpers/esm/extends.js"],"sourcesContent":["function _extends() {\n return _extends = Object.assign ? Object.assign.bind() : function (n) {\n for (var e = 1; e < arguments.length; e++) {\n var t = arguments[e];\n for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);\n }\n return n;\n }, _extends.apply(null, arguments);\n}\nexport { _extends as default };"],"names":["_extends","n","e","t"],"mappings":"AAAA,SAASA,IAAW;AAClB,SAAOA,IAAW,OAAO,SAAS,OAAO,OAAO,KAAI,IAAK,SAAUC,GAAG;AACpE,aAASC,IAAI,GAAGA,IAAI,UAAU,QAAQA,KAAK;AACzC,UAAIC,IAAI,UAAUD,CAAC;AACnB,eAAS,KAAKC,EAAG,EAAC,CAAA,GAAI,eAAe,KAAKA,GAAG,CAAC,MAAMF,EAAE,CAAC,IAAIE,EAAE,CAAC;AAAA,IAChE;AACA,WAAOF;AAAA,EACT,GAAGD,EAAS,MAAM,MAAM,SAAS;AACnC;","x_google_ignoreList":[0]}