@thangnqdev/ui 0.1.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.
Files changed (253) hide show
  1. package/README.md +196 -0
  2. package/dist/Label-DWOlgSNW.d.cts +14 -0
  3. package/dist/Label-DWOlgSNW.d.ts +14 -0
  4. package/dist/bento/index.cjs +140 -0
  5. package/dist/bento/index.cjs.map +1 -0
  6. package/dist/bento/index.d.cts +4 -0
  7. package/dist/bento/index.d.ts +4 -0
  8. package/dist/bento/index.js +4 -0
  9. package/dist/bento/index.js.map +1 -0
  10. package/dist/bento/styles.css +46 -0
  11. package/dist/buttons/index.cjs +365 -0
  12. package/dist/buttons/index.cjs.map +1 -0
  13. package/dist/buttons/index.d.cts +4 -0
  14. package/dist/buttons/index.d.ts +4 -0
  15. package/dist/buttons/index.js +5 -0
  16. package/dist/buttons/index.js.map +1 -0
  17. package/dist/buttons/styles.css +6 -0
  18. package/dist/chunk-2OXZK6IP.js +514 -0
  19. package/dist/chunk-2OXZK6IP.js.map +1 -0
  20. package/dist/chunk-4S6L5V7X.js +15 -0
  21. package/dist/chunk-4S6L5V7X.js.map +1 -0
  22. package/dist/chunk-5FZ6ZFII.js +728 -0
  23. package/dist/chunk-5FZ6ZFII.js.map +1 -0
  24. package/dist/chunk-66VWUJEI.js +86 -0
  25. package/dist/chunk-66VWUJEI.js.map +1 -0
  26. package/dist/chunk-A7P3O5Z5.js +163 -0
  27. package/dist/chunk-A7P3O5Z5.js.map +1 -0
  28. package/dist/chunk-ATYGDTMK.js +257 -0
  29. package/dist/chunk-ATYGDTMK.js.map +1 -0
  30. package/dist/chunk-C4SUXMI3.js +138 -0
  31. package/dist/chunk-C4SUXMI3.js.map +1 -0
  32. package/dist/chunk-EU2LPUYP.js +25 -0
  33. package/dist/chunk-EU2LPUYP.js.map +1 -0
  34. package/dist/chunk-F5Q7BTMH.js +1991 -0
  35. package/dist/chunk-F5Q7BTMH.js.map +1 -0
  36. package/dist/chunk-GXI2H5XA.js +46 -0
  37. package/dist/chunk-GXI2H5XA.js.map +1 -0
  38. package/dist/chunk-H3LCNPMC.js +101 -0
  39. package/dist/chunk-H3LCNPMC.js.map +1 -0
  40. package/dist/chunk-IABPUCAQ.js +19 -0
  41. package/dist/chunk-IABPUCAQ.js.map +1 -0
  42. package/dist/chunk-KJRBRTQE.js +101 -0
  43. package/dist/chunk-KJRBRTQE.js.map +1 -0
  44. package/dist/chunk-LBUBXUYQ.js +40 -0
  45. package/dist/chunk-LBUBXUYQ.js.map +1 -0
  46. package/dist/chunk-LWFRUJRU.js +537 -0
  47. package/dist/chunk-LWFRUJRU.js.map +1 -0
  48. package/dist/chunk-NFVONJUK.js +882 -0
  49. package/dist/chunk-NFVONJUK.js.map +1 -0
  50. package/dist/chunk-PF4ZHGVW.js +284 -0
  51. package/dist/chunk-PF4ZHGVW.js.map +1 -0
  52. package/dist/chunk-WAFHC4DQ.js +366 -0
  53. package/dist/chunk-WAFHC4DQ.js.map +1 -0
  54. package/dist/chunk-X76KBH4Y.js +71 -0
  55. package/dist/chunk-X76KBH4Y.js.map +1 -0
  56. package/dist/core/index.cjs +103 -0
  57. package/dist/core/index.cjs.map +1 -0
  58. package/dist/core/index.d.cts +3 -0
  59. package/dist/core/index.d.ts +3 -0
  60. package/dist/core/index.js +4 -0
  61. package/dist/core/index.js.map +1 -0
  62. package/dist/core/styles.css +128 -0
  63. package/dist/data-display/index.cjs +1023 -0
  64. package/dist/data-display/index.cjs.map +1 -0
  65. package/dist/data-display/index.d.cts +4 -0
  66. package/dist/data-display/index.d.ts +4 -0
  67. package/dist/data-display/index.js +6 -0
  68. package/dist/data-display/index.js.map +1 -0
  69. package/dist/data-display/styles.css +4 -0
  70. package/dist/feedback/index.cjs +368 -0
  71. package/dist/feedback/index.cjs.map +1 -0
  72. package/dist/feedback/index.d.cts +4 -0
  73. package/dist/feedback/index.d.ts +4 -0
  74. package/dist/feedback/index.js +4 -0
  75. package/dist/feedback/index.js.map +1 -0
  76. package/dist/feedback/styles.css +4 -0
  77. package/dist/forms/index.cjs +2287 -0
  78. package/dist/forms/index.cjs.map +1 -0
  79. package/dist/forms/index.d.cts +5 -0
  80. package/dist/forms/index.d.ts +5 -0
  81. package/dist/forms/index.js +10 -0
  82. package/dist/forms/index.js.map +1 -0
  83. package/dist/forms/styles.css +6 -0
  84. package/dist/glass/index.cjs +165 -0
  85. package/dist/glass/index.cjs.map +1 -0
  86. package/dist/glass/index.d.cts +4 -0
  87. package/dist/glass/index.d.ts +4 -0
  88. package/dist/glass/index.js +4 -0
  89. package/dist/glass/index.js.map +1 -0
  90. package/dist/glass/styles.css +81 -0
  91. package/dist/index-BTvkbCIj.d.cts +146 -0
  92. package/dist/index-BTvkbCIj.d.ts +146 -0
  93. package/dist/index-BkRqGNG1.d.cts +201 -0
  94. package/dist/index-BkRqGNG1.d.ts +201 -0
  95. package/dist/index-BlPcGeW-.d.cts +45 -0
  96. package/dist/index-BlPcGeW-.d.ts +45 -0
  97. package/dist/index-BzOCqvC6.d.cts +32 -0
  98. package/dist/index-BzOCqvC6.d.ts +32 -0
  99. package/dist/index-CCeWYAvn.d.cts +83 -0
  100. package/dist/index-COQ7uwt9.d.cts +44 -0
  101. package/dist/index-COQ7uwt9.d.ts +44 -0
  102. package/dist/index-CenuF_P2.d.cts +221 -0
  103. package/dist/index-CenuF_P2.d.ts +221 -0
  104. package/dist/index-Cle6QzQl.d.ts +371 -0
  105. package/dist/index-D6fE7w-b.d.cts +90 -0
  106. package/dist/index-D6fE7w-b.d.ts +90 -0
  107. package/dist/index-DR8cfJUG.d.ts +83 -0
  108. package/dist/index-DzcWh1Hs.d.cts +131 -0
  109. package/dist/index-DzcWh1Hs.d.ts +131 -0
  110. package/dist/index-TyK-Ldpy.d.cts +371 -0
  111. package/dist/index-ugj5s6a3.d.cts +95 -0
  112. package/dist/index-ugj5s6a3.d.ts +95 -0
  113. package/dist/index.cjs +6400 -0
  114. package/dist/index.cjs.map +1 -0
  115. package/dist/index.d.cts +16 -0
  116. package/dist/index.d.ts +16 -0
  117. package/dist/index.js +21 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/layout/index.cjs +516 -0
  120. package/dist/layout/index.cjs.map +1 -0
  121. package/dist/layout/index.d.cts +4 -0
  122. package/dist/layout/index.d.ts +4 -0
  123. package/dist/layout/index.js +4 -0
  124. package/dist/layout/index.js.map +1 -0
  125. package/dist/layout/styles.css +8 -0
  126. package/dist/navigation/index.cjs +673 -0
  127. package/dist/navigation/index.cjs.map +1 -0
  128. package/dist/navigation/index.d.cts +2 -0
  129. package/dist/navigation/index.d.ts +2 -0
  130. package/dist/navigation/index.js +8 -0
  131. package/dist/navigation/index.js.map +1 -0
  132. package/dist/navigation/styles.css +4 -0
  133. package/dist/overlays/index.cjs +954 -0
  134. package/dist/overlays/index.cjs.map +1 -0
  135. package/dist/overlays/index.d.cts +4 -0
  136. package/dist/overlays/index.d.ts +4 -0
  137. package/dist/overlays/index.js +9 -0
  138. package/dist/overlays/index.js.map +1 -0
  139. package/dist/overlays/styles.css +8 -0
  140. package/dist/styles.css +333 -0
  141. package/dist/typography/index.cjs +311 -0
  142. package/dist/typography/index.cjs.map +1 -0
  143. package/dist/typography/index.d.cts +5 -0
  144. package/dist/typography/index.d.ts +5 -0
  145. package/dist/typography/index.js +6 -0
  146. package/dist/typography/index.js.map +1 -0
  147. package/dist/typography/styles.css +5 -0
  148. package/llms.txt +113 -0
  149. package/package.json +116 -0
  150. package/src/bento/BentoCard.tsx +140 -0
  151. package/src/bento/BentoGrid.tsx +50 -0
  152. package/src/bento/index.ts +2 -0
  153. package/src/bento/tokens.css +46 -0
  154. package/src/buttons/Button.tsx +104 -0
  155. package/src/buttons/ButtonGroup.tsx +43 -0
  156. package/src/buttons/IconButton.tsx +79 -0
  157. package/src/buttons/SplitButton.tsx +86 -0
  158. package/src/buttons/ToggleButton.tsx +157 -0
  159. package/src/buttons/index.ts +5 -0
  160. package/src/buttons/tokens.css +6 -0
  161. package/src/core/ThemeProvider.tsx +123 -0
  162. package/src/core/index.ts +2 -0
  163. package/src/core/tokens.css +128 -0
  164. package/src/data-display/Accordion.tsx +147 -0
  165. package/src/data-display/Avatar.tsx +134 -0
  166. package/src/data-display/Card.tsx +112 -0
  167. package/src/data-display/Carousel.tsx +130 -0
  168. package/src/data-display/Chip.tsx +74 -0
  169. package/src/data-display/DataTablePro.tsx +356 -0
  170. package/src/data-display/StatCard.tsx +60 -0
  171. package/src/data-display/Table.tsx +74 -0
  172. package/src/data-display/Timeline.tsx +62 -0
  173. package/src/data-display/TreeView.tsx +140 -0
  174. package/src/data-display/index.ts +10 -0
  175. package/src/data-display/tokens.css +4 -0
  176. package/src/feedback/Alert.tsx +80 -0
  177. package/src/feedback/EmptyState.tsx +45 -0
  178. package/src/feedback/ProgressBar.tsx +174 -0
  179. package/src/feedback/Skeleton.tsx +66 -0
  180. package/src/feedback/Spinner.tsx +65 -0
  181. package/src/feedback/index.ts +5 -0
  182. package/src/feedback/tokens.css +4 -0
  183. package/src/forms/Checkbox.tsx +69 -0
  184. package/src/forms/CheckboxGroup.tsx +29 -0
  185. package/src/forms/Combobox.tsx +368 -0
  186. package/src/forms/DatePicker.tsx +480 -0
  187. package/src/forms/FileUpload.tsx +222 -0
  188. package/src/forms/FormField.tsx +115 -0
  189. package/src/forms/Input.tsx +151 -0
  190. package/src/forms/MaskedInput.tsx +97 -0
  191. package/src/forms/NumberInput.tsx +248 -0
  192. package/src/forms/PasswordInput.tsx +35 -0
  193. package/src/forms/PinInput.tsx +125 -0
  194. package/src/forms/Radio.tsx +142 -0
  195. package/src/forms/RangeSlider.tsx +111 -0
  196. package/src/forms/SearchInput.tsx +34 -0
  197. package/src/forms/Select.tsx +103 -0
  198. package/src/forms/Slider.tsx +85 -0
  199. package/src/forms/Switch.tsx +95 -0
  200. package/src/forms/Textarea.tsx +114 -0
  201. package/src/forms/index.ts +18 -0
  202. package/src/forms/tokens.css +6 -0
  203. package/src/glass/GlassBadge.tsx +61 -0
  204. package/src/glass/GlassButton.tsx +59 -0
  205. package/src/glass/GlassCard.tsx +71 -0
  206. package/src/glass/index.ts +3 -0
  207. package/src/glass/tokens.css +81 -0
  208. package/src/index.ts +26 -0
  209. package/src/layout/AspectRatio.tsx +39 -0
  210. package/src/layout/Container.tsx +53 -0
  211. package/src/layout/Divider.tsx +61 -0
  212. package/src/layout/Flex.tsx +79 -0
  213. package/src/layout/Grid.tsx +124 -0
  214. package/src/layout/PageLayout.tsx +59 -0
  215. package/src/layout/ScrollArea.tsx +43 -0
  216. package/src/layout/Section.tsx +47 -0
  217. package/src/layout/Spacer.tsx +30 -0
  218. package/src/layout/Stack.tsx +88 -0
  219. package/src/layout/index.ts +10 -0
  220. package/src/layout/tokens.css +8 -0
  221. package/src/navigation/Breadcrumb.tsx +73 -0
  222. package/src/navigation/CommandPalette.tsx +142 -0
  223. package/src/navigation/DropdownMenu.tsx +160 -0
  224. package/src/navigation/Pagination.tsx +114 -0
  225. package/src/navigation/Stepper.tsx +93 -0
  226. package/src/navigation/Tabs.tsx +133 -0
  227. package/src/navigation/index.ts +6 -0
  228. package/src/navigation/tokens.css +4 -0
  229. package/src/overlays/AlertDialog.tsx +54 -0
  230. package/src/overlays/BottomSheet.tsx +123 -0
  231. package/src/overlays/ContextMenu.tsx +119 -0
  232. package/src/overlays/Drawer.tsx +145 -0
  233. package/src/overlays/FocusTrap.tsx +49 -0
  234. package/src/overlays/HoverCard.tsx +72 -0
  235. package/src/overlays/Modal.tsx +219 -0
  236. package/src/overlays/Popover.tsx +126 -0
  237. package/src/overlays/Portal.tsx +23 -0
  238. package/src/overlays/Toast.tsx +137 -0
  239. package/src/overlays/Tooltip.tsx +100 -0
  240. package/src/overlays/index.ts +11 -0
  241. package/src/overlays/tokens.css +8 -0
  242. package/src/styles/tokens.css +2 -0
  243. package/src/typography/Blockquote.tsx +32 -0
  244. package/src/typography/Code.tsx +89 -0
  245. package/src/typography/Heading.tsx +56 -0
  246. package/src/typography/Kbd.tsx +25 -0
  247. package/src/typography/Label.tsx +47 -0
  248. package/src/typography/Link.tsx +56 -0
  249. package/src/typography/Text.tsx +62 -0
  250. package/src/typography/index.ts +7 -0
  251. package/src/typography/tokens.css +5 -0
  252. package/src/utils/cn.ts +6 -0
  253. package/ui-contract.json +62 -0
@@ -0,0 +1,101 @@
1
+ import { __export, cn } from './chunk-4S6L5V7X.js';
2
+ import { createContext, useState, useEffect, useMemo, useContext } from 'react';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ // src/core/index.ts
6
+ var core_exports = {};
7
+ __export(core_exports, {
8
+ ThemeProvider: () => ThemeProvider,
9
+ cn: () => cn,
10
+ useTheme: () => useTheme
11
+ });
12
+ var ThemeContext = createContext(void 0);
13
+ function ThemeProvider({
14
+ children,
15
+ defaultTheme = "dark",
16
+ storageKey = "ui-theme",
17
+ attribute = "data-theme",
18
+ enableSystem = true
19
+ }) {
20
+ const [theme, setThemeState] = useState(() => {
21
+ if (typeof window !== "undefined" && typeof window.localStorage !== "undefined") {
22
+ try {
23
+ const stored = window.localStorage.getItem(storageKey);
24
+ if (stored) return stored;
25
+ } catch {
26
+ }
27
+ }
28
+ return defaultTheme;
29
+ });
30
+ const [resolvedTheme, setResolvedTheme] = useState("dark");
31
+ useEffect(() => {
32
+ const root = document.documentElement;
33
+ const computeResolved = (t) => {
34
+ if (t === "system" && enableSystem && typeof window !== "undefined" && window.matchMedia) {
35
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
36
+ }
37
+ return t === "dark" ? "dark" : "light";
38
+ };
39
+ const currentResolved = computeResolved(theme);
40
+ setResolvedTheme(currentResolved);
41
+ root.setAttribute(attribute, currentResolved);
42
+ if (currentResolved === "dark") {
43
+ root.classList.add("dark");
44
+ root.classList.remove("light");
45
+ } else {
46
+ root.classList.add("light");
47
+ root.classList.remove("dark");
48
+ }
49
+ if (typeof window !== "undefined" && typeof window.localStorage !== "undefined") {
50
+ try {
51
+ window.localStorage.setItem(storageKey, theme);
52
+ } catch {
53
+ }
54
+ }
55
+ }, [theme, attribute, enableSystem, storageKey]);
56
+ useEffect(() => {
57
+ if (theme !== "system" || !enableSystem) return;
58
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
59
+ const handleChange = () => {
60
+ const newResolved = mediaQuery.matches ? "dark" : "light";
61
+ setResolvedTheme(newResolved);
62
+ document.documentElement.setAttribute(attribute, newResolved);
63
+ if (newResolved === "dark") {
64
+ document.documentElement.classList.add("dark");
65
+ document.documentElement.classList.remove("light");
66
+ } else {
67
+ document.documentElement.classList.add("light");
68
+ document.documentElement.classList.remove("dark");
69
+ }
70
+ };
71
+ mediaQuery.addEventListener("change", handleChange);
72
+ return () => mediaQuery.removeEventListener("change", handleChange);
73
+ }, [theme, enableSystem, attribute]);
74
+ const toggleTheme = () => {
75
+ setThemeState((prev) => {
76
+ if (prev === "dark") return "light";
77
+ return "dark";
78
+ });
79
+ };
80
+ const value = useMemo(
81
+ () => ({
82
+ theme,
83
+ resolvedTheme,
84
+ setTheme: setThemeState,
85
+ toggleTheme
86
+ }),
87
+ [theme, resolvedTheme]
88
+ );
89
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value, children });
90
+ }
91
+ function useTheme() {
92
+ const context = useContext(ThemeContext);
93
+ if (!context) {
94
+ throw new Error("useTheme must be used within a ThemeProvider");
95
+ }
96
+ return context;
97
+ }
98
+
99
+ export { ThemeProvider, core_exports, useTheme };
100
+ //# sourceMappingURL=chunk-KJRBRTQE.js.map
101
+ //# sourceMappingURL=chunk-KJRBRTQE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/index.ts","../src/core/ThemeProvider.tsx"],"names":[],"mappings":"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","file":"chunk-KJRBRTQE.js","sourcesContent":["export * from './ThemeProvider';\r\nexport * from '../utils/cn';\r\n","import React, { createContext, useContext, useEffect, useState, useMemo } from 'react';\r\n\r\nexport type Theme = 'dark' | 'light' | 'system';\r\n\r\nexport interface ThemeProviderProps {\r\n children: React.ReactNode;\r\n defaultTheme?: Theme;\r\n storageKey?: string;\r\n attribute?: string;\r\n enableSystem?: boolean;\r\n}\r\n\r\ninterface ThemeContextType {\r\n theme: Theme;\r\n resolvedTheme: 'dark' | 'light';\r\n setTheme: (theme: Theme) => void;\r\n toggleTheme: () => void;\r\n}\r\n\r\nconst ThemeContext = createContext<ThemeContextType | undefined>(undefined);\r\n\r\nexport function ThemeProvider({\r\n children,\r\n defaultTheme = 'dark',\r\n storageKey = 'ui-theme',\r\n attribute = 'data-theme',\r\n enableSystem = true,\r\n}: ThemeProviderProps) {\r\n const [theme, setThemeState] = useState<Theme>(() => {\r\n if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {\r\n try {\r\n const stored = window.localStorage.getItem(storageKey) as Theme | null;\r\n if (stored) return stored;\r\n } catch {\r\n // Ignore storage access errors in test/restricted environments\r\n }\r\n }\r\n return defaultTheme;\r\n });\r\n\r\n const [resolvedTheme, setResolvedTheme] = useState<'dark' | 'light'>('dark');\r\n\r\n useEffect(() => {\r\n const root = document.documentElement;\r\n\r\n const computeResolved = (t: Theme): 'dark' | 'light' => {\r\n if (t === 'system' && enableSystem && typeof window !== 'undefined' && window.matchMedia) {\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n }\r\n return t === 'dark' ? 'dark' : 'light';\r\n };\r\n\r\n const currentResolved = computeResolved(theme);\r\n setResolvedTheme(currentResolved);\r\n\r\n // Apply attributes and classes\r\n root.setAttribute(attribute, currentResolved);\r\n if (currentResolved === 'dark') {\r\n root.classList.add('dark');\r\n root.classList.remove('light');\r\n } else {\r\n root.classList.add('light');\r\n root.classList.remove('dark');\r\n }\r\n\r\n if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') {\r\n try {\r\n window.localStorage.setItem(storageKey, theme);\r\n } catch {\r\n // Ignore storage access errors\r\n }\r\n }\r\n }, [theme, attribute, enableSystem, storageKey]);\r\n\r\n // System theme listener\r\n useEffect(() => {\r\n if (theme !== 'system' || !enableSystem) return;\r\n\r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n const handleChange = () => {\r\n const newResolved = mediaQuery.matches ? 'dark' : 'light';\r\n setResolvedTheme(newResolved);\r\n document.documentElement.setAttribute(attribute, newResolved);\r\n if (newResolved === 'dark') {\r\n document.documentElement.classList.add('dark');\r\n document.documentElement.classList.remove('light');\r\n } else {\r\n document.documentElement.classList.add('light');\r\n document.documentElement.classList.remove('dark');\r\n }\r\n };\r\n\r\n mediaQuery.addEventListener('change', handleChange);\r\n return () => mediaQuery.removeEventListener('change', handleChange);\r\n }, [theme, enableSystem, attribute]);\r\n\r\n const toggleTheme = () => {\r\n setThemeState((prev) => {\r\n if (prev === 'dark') return 'light';\r\n return 'dark';\r\n });\r\n };\r\n\r\n const value = useMemo(\r\n () => ({\r\n theme,\r\n resolvedTheme,\r\n setTheme: setThemeState,\r\n toggleTheme,\r\n }),\r\n [theme, resolvedTheme]\r\n );\r\n\r\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\r\n}\r\n\r\nexport function useTheme(): ThemeContextType {\r\n const context = useContext(ThemeContext);\r\n if (!context) {\r\n throw new Error('useTheme must be used within a ThemeProvider');\r\n }\r\n return context;\r\n}\r\n"]}
@@ -0,0 +1,40 @@
1
+ import { useRef, useEffect } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ // src/overlays/FocusTrap.tsx
5
+ var FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])';
6
+ function FocusTrap({ children, active = true }) {
7
+ const rootRef = useRef(null);
8
+ useEffect(() => {
9
+ if (!active) return;
10
+ const root = rootRef.current;
11
+ if (!root) return;
12
+ const focusable = root.querySelectorAll(FOCUSABLE_SELECTOR);
13
+ const first = focusable[0];
14
+ const last = focusable[focusable.length - 1];
15
+ if (first) {
16
+ first.focus();
17
+ }
18
+ const handleKeyDown = (e) => {
19
+ if (e.key !== "Tab") return;
20
+ if (e.shiftKey) {
21
+ if (document.activeElement === first) {
22
+ e.preventDefault();
23
+ last?.focus();
24
+ }
25
+ } else {
26
+ if (document.activeElement === last) {
27
+ e.preventDefault();
28
+ first?.focus();
29
+ }
30
+ }
31
+ };
32
+ window.addEventListener("keydown", handleKeyDown);
33
+ return () => window.removeEventListener("keydown", handleKeyDown);
34
+ }, [active]);
35
+ return /* @__PURE__ */ jsx("div", { ref: rootRef, className: "contents", children });
36
+ }
37
+
38
+ export { FocusTrap };
39
+ //# sourceMappingURL=chunk-LBUBXUYQ.js.map
40
+ //# sourceMappingURL=chunk-LBUBXUYQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/overlays/FocusTrap.tsx"],"names":[],"mappings":";;;;AAOA,IAAM,kBAAA,GACJ,2IAAA;AAEK,SAAS,SAAA,CAAU,EAAE,QAAA,EAAU,MAAA,GAAS,MAAK,EAAmB;AACrE,EAAA,MAAM,OAAA,GAAU,OAAuB,IAAI,CAAA;AAE3C,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,IAAI,CAAC,IAAA,EAAM;AAEX,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,gBAAA,CAA8B,kBAAkB,CAAA;AACvE,IAAA,MAAM,KAAA,GAAQ,UAAU,CAAC,CAAA;AACzB,IAAA,MAAM,IAAA,GAAO,SAAA,CAAU,SAAA,CAAU,MAAA,GAAS,CAAC,CAAA;AAE3C,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,KAAA,CAAM,KAAA,EAAM;AAAA,IACd;AAEA,IAAA,MAAM,aAAA,GAAgB,CAAC,CAAA,KAAqB;AAC1C,MAAA,IAAI,CAAA,CAAE,QAAQ,KAAA,EAAO;AAErB,MAAA,IAAI,EAAE,QAAA,EAAU;AACd,QAAA,IAAI,QAAA,CAAS,kBAAkB,KAAA,EAAO;AACpC,UAAA,CAAA,CAAE,cAAA,EAAe;AACjB,UAAA,IAAA,EAAM,KAAA,EAAM;AAAA,QACd;AAAA,MACF,CAAA,MAAO;AACL,QAAA,IAAI,QAAA,CAAS,kBAAkB,IAAA,EAAM;AACnC,UAAA,CAAA,CAAE,cAAA,EAAe;AACjB,UAAA,KAAA,EAAO,KAAA,EAAM;AAAA,QACf;AAAA,MACF;AAAA,IACF,CAAA;AAEA,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,aAAa,CAAA;AAChD,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,aAAa,CAAA;AAAA,EAClE,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,2BAAQ,KAAA,EAAA,EAAI,GAAA,EAAK,OAAA,EAAS,SAAA,EAAU,YAAY,QAAA,EAAS,CAAA;AAC3D","file":"chunk-LBUBXUYQ.js","sourcesContent":["import React, { useEffect, useRef } from 'react';\r\n\r\nexport interface FocusTrapProps {\r\n children: React.ReactNode;\r\n active?: boolean;\r\n}\r\n\r\nconst FOCUSABLE_SELECTOR =\r\n 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\r\n\r\nexport function FocusTrap({ children, active = true }: FocusTrapProps) {\r\n const rootRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n if (!active) return;\r\n\r\n const root = rootRef.current;\r\n if (!root) return;\r\n\r\n const focusable = root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR);\r\n const first = focusable[0];\r\n const last = focusable[focusable.length - 1];\r\n\r\n if (first) {\r\n first.focus();\r\n }\r\n\r\n const handleKeyDown = (e: KeyboardEvent) => {\r\n if (e.key !== 'Tab') return;\r\n\r\n if (e.shiftKey) {\r\n if (document.activeElement === first) {\r\n e.preventDefault();\r\n last?.focus();\r\n }\r\n } else {\r\n if (document.activeElement === last) {\r\n e.preventDefault();\r\n first?.focus();\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('keydown', handleKeyDown);\r\n return () => window.removeEventListener('keydown', handleKeyDown);\r\n }, [active]);\r\n\r\n return <div ref={rootRef} className=\"contents\">{children}</div>;\r\n}\r\n"]}