@raydenui/ui 0.9.7 → 0.10.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 (308) hide show
  1. package/dist/Table-DCNSxua1.d.cts +31 -0
  2. package/dist/Table-DCNSxua1.d.ts +31 -0
  3. package/dist/blocks/ApplicationShellBlock.cjs +157 -0
  4. package/dist/blocks/ApplicationShellBlock.js +154 -0
  5. package/dist/blocks/CheckoutReviewBlock.cjs +16 -0
  6. package/dist/blocks/CheckoutReviewBlock.js +13 -0
  7. package/dist/blocks/CommandPaletteBlock.cjs +334 -0
  8. package/dist/blocks/CommandPaletteBlock.js +331 -0
  9. package/dist/blocks/CreateAccountBlock.cjs +147 -0
  10. package/dist/blocks/CreateAccountBlock.js +143 -0
  11. package/dist/blocks/EmptyStateBlock.cjs +19 -0
  12. package/dist/blocks/EmptyStateBlock.js +16 -0
  13. package/dist/blocks/FeatureOverviewBlock.cjs +54 -0
  14. package/dist/blocks/FeatureOverviewBlock.js +51 -0
  15. package/dist/blocks/HeaderBlock.cjs +230 -0
  16. package/dist/blocks/HeaderBlock.js +227 -0
  17. package/dist/blocks/KpiOverviewBlock.cjs +63 -0
  18. package/dist/blocks/KpiOverviewBlock.js +60 -0
  19. package/dist/blocks/LoginBlock.cjs +66 -0
  20. package/dist/blocks/LoginBlock.js +63 -0
  21. package/dist/blocks/NotificationsBlock.cjs +17 -0
  22. package/dist/blocks/NotificationsBlock.js +14 -0
  23. package/dist/blocks/PageHeaderBlock.cjs +121 -0
  24. package/dist/blocks/PageHeaderBlock.js +118 -0
  25. package/dist/blocks/PricingPlansBlock.cjs +146 -0
  26. package/dist/blocks/PricingPlansBlock.js +143 -0
  27. package/dist/blocks/ProductCollectionBlock.cjs +37 -0
  28. package/dist/blocks/ProductCollectionBlock.js +34 -0
  29. package/dist/blocks/ProductDetailBlock.cjs +30 -0
  30. package/dist/blocks/ProductDetailBlock.js +27 -0
  31. package/dist/blocks/ProductHeroBlock.cjs +83 -0
  32. package/dist/blocks/ProductHeroBlock.js +80 -0
  33. package/dist/blocks/ProfileSettingsBlock.cjs +130 -0
  34. package/dist/blocks/ProfileSettingsBlock.js +126 -0
  35. package/dist/blocks/QuickSendBlock.cjs +11 -0
  36. package/dist/blocks/QuickSendBlock.js +8 -0
  37. package/dist/blocks/RecentTransactionsBlock.cjs +13 -0
  38. package/dist/blocks/RecentTransactionsBlock.js +10 -0
  39. package/dist/blocks/SearchableTableBlock.cjs +91 -0
  40. package/dist/blocks/SearchableTableBlock.js +88 -0
  41. package/dist/blocks/ShoppingCartBlock.cjs +16 -0
  42. package/dist/blocks/ShoppingCartBlock.js +13 -0
  43. package/dist/blocks/SiteFooterBlock.cjs +69 -0
  44. package/dist/blocks/SiteFooterBlock.js +66 -0
  45. package/dist/blocks/TableBlock.cjs +20 -0
  46. package/dist/blocks/TableBlock.js +17 -0
  47. package/dist/blocks/TaskListBlock.cjs +198 -0
  48. package/dist/blocks/TaskListBlock.js +195 -0
  49. package/dist/blocks/WorkspaceSwitcherBlock.cjs +291 -0
  50. package/dist/blocks/WorkspaceSwitcherBlock.js +288 -0
  51. package/dist/blocks/commerce.cjs +44 -0
  52. package/dist/blocks/commerce.js +35 -0
  53. package/dist/blocks/index.cjs +53 -0
  54. package/dist/blocks/index.js +24 -0
  55. package/dist/blocks.d.cts +1820 -0
  56. package/dist/blocks.d.ts +1820 -0
  57. package/dist/chart.cjs +13 -0
  58. package/dist/chart.d.cts +59 -0
  59. package/dist/chart.d.ts +59 -0
  60. package/dist/chart.js +5 -0
  61. package/dist/components/Accordion/Accordion.cjs +94 -0
  62. package/dist/components/Accordion/Accordion.js +91 -0
  63. package/dist/components/Accordion/index.cjs +8 -0
  64. package/dist/components/Accordion/index.js +1 -0
  65. package/dist/components/ActivityFeed/ActivityContent.cjs +40 -0
  66. package/dist/components/ActivityFeed/ActivityContent.js +37 -0
  67. package/dist/components/ActivityFeed/ActivityItem.cjs +19 -0
  68. package/dist/components/ActivityFeed/ActivityItem.js +16 -0
  69. package/dist/components/ActivityFeed/index.cjs +7 -0
  70. package/dist/components/ActivityFeed/index.js +2 -0
  71. package/dist/components/Alert/Alert.cjs +42 -0
  72. package/dist/components/Alert/Alert.js +39 -0
  73. package/dist/components/Alert/index.cjs +5 -0
  74. package/dist/components/Alert/index.js +1 -0
  75. package/dist/components/Avatar/Avatar.cjs +101 -0
  76. package/dist/components/Avatar/Avatar.js +98 -0
  77. package/dist/components/Avatar/index.cjs +6 -0
  78. package/dist/components/Avatar/index.js +1 -0
  79. package/dist/components/Badge/Badge.cjs +53 -0
  80. package/dist/components/Badge/Badge.js +50 -0
  81. package/dist/components/Badge/index.cjs +5 -0
  82. package/dist/components/Badge/index.js +1 -0
  83. package/dist/components/Banner/Banner.cjs +83 -0
  84. package/dist/components/Banner/Banner.js +80 -0
  85. package/dist/components/Banner/index.cjs +5 -0
  86. package/dist/components/Banner/index.js +1 -0
  87. package/dist/components/Breadcrumb/Breadcrumb.cjs +31 -0
  88. package/dist/components/Breadcrumb/Breadcrumb.js +28 -0
  89. package/dist/components/Breadcrumb/index.cjs +5 -0
  90. package/dist/components/Breadcrumb/index.js +1 -0
  91. package/dist/components/Button/Button.cjs +88 -0
  92. package/dist/components/Button/Button.js +85 -0
  93. package/dist/components/Button/index.cjs +5 -0
  94. package/dist/components/Button/index.js +1 -0
  95. package/dist/components/ButtonGroup/ButtonGroup.cjs +8 -0
  96. package/dist/components/ButtonGroup/ButtonGroup.js +5 -0
  97. package/dist/components/ButtonGroup/ButtonGroupItem.cjs +15 -0
  98. package/dist/components/ButtonGroup/ButtonGroupItem.js +12 -0
  99. package/dist/components/ButtonGroup/index.cjs +7 -0
  100. package/dist/components/ButtonGroup/index.js +2 -0
  101. package/dist/components/Card/Card.cjs +94 -0
  102. package/dist/components/Card/Card.js +91 -0
  103. package/dist/components/Card/index.cjs +9 -0
  104. package/dist/components/Card/index.js +1 -0
  105. package/dist/components/Chart/Chart.cjs +160 -0
  106. package/dist/components/Chart/Chart.js +153 -0
  107. package/dist/components/Chart/index.cjs +10 -0
  108. package/dist/components/Chart/index.js +2 -0
  109. package/dist/components/Chart/theme.cjs +67 -0
  110. package/dist/components/Chart/theme.js +62 -0
  111. package/dist/components/Chip/Chip.cjs +18 -0
  112. package/dist/components/Chip/Chip.js +15 -0
  113. package/dist/components/Chip/index.cjs +5 -0
  114. package/dist/components/Chip/index.js +1 -0
  115. package/dist/components/Counter/Counter.cjs +74 -0
  116. package/dist/components/Counter/Counter.js +71 -0
  117. package/dist/components/Counter/index.cjs +6 -0
  118. package/dist/components/Counter/index.js +1 -0
  119. package/dist/components/DatePicker/DatePicker.cjs +343 -0
  120. package/dist/components/DatePicker/DatePicker.js +340 -0
  121. package/dist/components/DatePicker/index.cjs +5 -0
  122. package/dist/components/DatePicker/index.js +1 -0
  123. package/dist/components/Divider/Divider.cjs +31 -0
  124. package/dist/components/Divider/Divider.js +28 -0
  125. package/dist/components/Divider/index.cjs +5 -0
  126. package/dist/components/Divider/index.js +1 -0
  127. package/dist/components/DropdownMenu/DropdownMenu.cjs +108 -0
  128. package/dist/components/DropdownMenu/DropdownMenu.js +105 -0
  129. package/dist/components/DropdownMenu/index.cjs +11 -0
  130. package/dist/components/DropdownMenu/index.js +1 -0
  131. package/dist/components/EmptyStateIllustration/EmptyStateIllustration.cjs +42 -0
  132. package/dist/components/EmptyStateIllustration/EmptyStateIllustration.js +39 -0
  133. package/dist/components/EmptyStateIllustration/illustrations.cjs +3322 -0
  134. package/dist/components/EmptyStateIllustration/illustrations.js +3319 -0
  135. package/dist/components/EmptyStateIllustration/index.cjs +7 -0
  136. package/dist/components/EmptyStateIllustration/index.js +2 -0
  137. package/dist/components/FileUpload/FileUpload.cjs +116 -0
  138. package/dist/components/FileUpload/FileUpload.js +113 -0
  139. package/dist/components/FileUpload/FileUploadDropZone.cjs +58 -0
  140. package/dist/components/FileUpload/FileUploadDropZone.js +55 -0
  141. package/dist/components/FileUpload/FileUploadIcons.cjs +55 -0
  142. package/dist/components/FileUpload/FileUploadIcons.js +50 -0
  143. package/dist/components/FileUpload/FileUploadItem.cjs +34 -0
  144. package/dist/components/FileUpload/FileUploadItem.js +31 -0
  145. package/dist/components/FileUpload/index.cjs +9 -0
  146. package/dist/components/FileUpload/index.js +3 -0
  147. package/dist/components/FormControl/Checkbox.cjs +27 -0
  148. package/dist/components/FormControl/Checkbox.js +24 -0
  149. package/dist/components/FormControl/Radio.cjs +15 -0
  150. package/dist/components/FormControl/Radio.js +12 -0
  151. package/dist/components/FormControl/Toggle.cjs +15 -0
  152. package/dist/components/FormControl/Toggle.js +12 -0
  153. package/dist/components/FormControl/index.cjs +9 -0
  154. package/dist/components/FormControl/index.js +3 -0
  155. package/dist/components/Icon/Icon.cjs +70 -0
  156. package/dist/components/Icon/Icon.js +34 -0
  157. package/dist/components/Icon/catalog.cjs +1672 -0
  158. package/dist/components/Icon/catalog.js +1669 -0
  159. package/dist/components/Icon/icons.cjs +5621 -0
  160. package/dist/components/Icon/icons.js +5610 -0
  161. package/dist/components/Icon/index.cjs +8 -0
  162. package/dist/components/Icon/index.js +2 -0
  163. package/dist/components/Input/Input.cjs +64 -0
  164. package/dist/components/Input/Input.js +61 -0
  165. package/dist/components/Input/index.cjs +5 -0
  166. package/dist/components/Input/index.js +1 -0
  167. package/dist/components/MetricsCard/MetricsCard.cjs +107 -0
  168. package/dist/components/MetricsCard/MetricsCard.js +104 -0
  169. package/dist/components/MetricsCard/index.cjs +5 -0
  170. package/dist/components/MetricsCard/index.js +1 -0
  171. package/dist/components/Modal/Modal.cjs +126 -0
  172. package/dist/components/Modal/Modal.js +123 -0
  173. package/dist/components/Modal/index.cjs +5 -0
  174. package/dist/components/Modal/index.js +1 -0
  175. package/dist/components/Pagination/Pagination.cjs +42 -0
  176. package/dist/components/Pagination/Pagination.js +39 -0
  177. package/dist/components/Pagination/index.cjs +5 -0
  178. package/dist/components/Pagination/index.js +1 -0
  179. package/dist/components/ProgressBar/ProgressBar.cjs +34 -0
  180. package/dist/components/ProgressBar/ProgressBar.js +31 -0
  181. package/dist/components/ProgressBar/index.cjs +5 -0
  182. package/dist/components/ProgressBar/index.js +1 -0
  183. package/dist/components/ProgressCircle/ProgressCircle.cjs +34 -0
  184. package/dist/components/ProgressCircle/ProgressCircle.js +31 -0
  185. package/dist/components/ProgressCircle/index.cjs +5 -0
  186. package/dist/components/ProgressCircle/index.js +1 -0
  187. package/dist/components/Select/Select.cjs +84 -0
  188. package/dist/components/Select/Select.js +80 -0
  189. package/dist/components/Select/SelectOption.cjs +26 -0
  190. package/dist/components/Select/SelectOption.js +23 -0
  191. package/dist/components/Select/index.cjs +7 -0
  192. package/dist/components/Select/index.js +2 -0
  193. package/dist/components/SidebarMenu/SidebarMenu.cjs +85 -0
  194. package/dist/components/SidebarMenu/SidebarMenu.js +81 -0
  195. package/dist/components/SidebarMenu/SidebarMenuItem.cjs +126 -0
  196. package/dist/components/SidebarMenu/SidebarMenuItem.js +122 -0
  197. package/dist/components/SidebarMenu/SidebarMenuSection.cjs +14 -0
  198. package/dist/components/SidebarMenu/SidebarMenuSection.js +11 -0
  199. package/dist/components/SidebarMenu/index.cjs +12 -0
  200. package/dist/components/SidebarMenu/index.js +4 -0
  201. package/dist/components/Slider/Slider.cjs +161 -0
  202. package/dist/components/Slider/Slider.js +158 -0
  203. package/dist/components/Slider/index.cjs +6 -0
  204. package/dist/components/Slider/index.js +1 -0
  205. package/dist/components/Spinner/Spinner.cjs +93 -0
  206. package/dist/components/Spinner/Spinner.js +90 -0
  207. package/dist/components/Spinner/index.cjs +5 -0
  208. package/dist/components/Spinner/index.js +1 -0
  209. package/dist/components/Stepper/Stepper.cjs +82 -0
  210. package/dist/components/Stepper/Stepper.js +79 -0
  211. package/dist/components/Stepper/index.cjs +7 -0
  212. package/dist/components/Stepper/index.js +1 -0
  213. package/dist/components/Table/Table.cjs +25 -0
  214. package/dist/components/Table/Table.js +22 -0
  215. package/dist/components/Table/index.cjs +10 -0
  216. package/dist/components/Table/index.js +1 -0
  217. package/dist/components/Table/useTableSelection.cjs +60 -0
  218. package/dist/components/Table/useTableSelection.js +57 -0
  219. package/dist/components/Tabs/Tab.cjs +70 -0
  220. package/dist/components/Tabs/Tab.js +67 -0
  221. package/dist/components/Tabs/Tabs.cjs +133 -0
  222. package/dist/components/Tabs/Tabs.js +129 -0
  223. package/dist/components/Tabs/index.cjs +7 -0
  224. package/dist/components/Tabs/index.js +2 -0
  225. package/dist/components/Tooltip/Tooltip.cjs +101 -0
  226. package/dist/components/Tooltip/Tooltip.js +98 -0
  227. package/dist/components/Tooltip/index.cjs +5 -0
  228. package/dist/components/Tooltip/index.js +1 -0
  229. package/dist/context/ThemeContext.cjs +97 -0
  230. package/dist/context/ThemeContext.js +92 -0
  231. package/dist/fonts/README.md +13 -0
  232. package/dist/fonts/hanken-grotesk-cyrillic-ext-italic.woff2 +0 -0
  233. package/dist/fonts/hanken-grotesk-cyrillic-ext-normal.woff2 +0 -0
  234. package/dist/fonts/hanken-grotesk-latin-ext-italic.woff2 +0 -0
  235. package/dist/fonts/hanken-grotesk-latin-ext-normal.woff2 +0 -0
  236. package/dist/fonts/hanken-grotesk-latin-italic.woff2 +0 -0
  237. package/dist/fonts/hanken-grotesk-latin-normal.woff2 +0 -0
  238. package/dist/fonts/hanken-grotesk-vietnamese-italic.woff2 +0 -0
  239. package/dist/fonts/hanken-grotesk-vietnamese-normal.woff2 +0 -0
  240. package/dist/fonts/hankengrotesk-LICENSE.txt +94 -0
  241. package/dist/fonts/manrope-LICENSE.txt +93 -0
  242. package/dist/fonts/manrope-cyrillic-ext-normal.woff2 +0 -0
  243. package/dist/fonts/manrope-cyrillic-normal.woff2 +0 -0
  244. package/dist/fonts/manrope-greek-normal.woff2 +0 -0
  245. package/dist/fonts/manrope-latin-ext-normal.woff2 +0 -0
  246. package/dist/fonts/manrope-latin-normal.woff2 +0 -0
  247. package/dist/fonts/manrope-vietnamese-normal.woff2 +0 -0
  248. package/dist/fonts.css +148 -0
  249. package/dist/hooks/form/index.cjs +11 -0
  250. package/dist/hooks/form/index.js +3 -0
  251. package/dist/hooks/form/useRaydenFormControl.cjs +81 -0
  252. package/dist/hooks/form/useRaydenFormControl.js +76 -0
  253. package/dist/hooks/form/useRaydenInput.cjs +38 -0
  254. package/dist/hooks/form/useRaydenInput.js +35 -0
  255. package/dist/hooks/form/useRaydenSelect.cjs +45 -0
  256. package/dist/hooks/form/useRaydenSelect.js +42 -0
  257. package/dist/hooks/index.cjs +17 -0
  258. package/dist/hooks/index.js +1 -0
  259. package/dist/hooks/useBodyScrollLock.cjs +24 -0
  260. package/dist/hooks/useBodyScrollLock.js +21 -0
  261. package/dist/hooks/useCollisionAwareSide.cjs +72 -0
  262. package/dist/hooks/useCollisionAwareSide.js +69 -0
  263. package/dist/hooks/useControllableValue.cjs +16 -0
  264. package/dist/hooks/useControllableValue.js +13 -0
  265. package/dist/hooks/useDismissableLayer.cjs +100 -0
  266. package/dist/hooks/useDismissableLayer.js +97 -0
  267. package/dist/hooks/usePopupList.cjs +101 -0
  268. package/dist/hooks/usePopupList.js +98 -0
  269. package/dist/icons-8yD7I5jO.d.cts +430 -0
  270. package/dist/icons-8yD7I5jO.d.ts +430 -0
  271. package/dist/icons.cjs +2111 -418
  272. package/dist/icons.d.cts +1256 -429
  273. package/dist/icons.d.ts +1256 -429
  274. package/dist/icons.js +2089 -1
  275. package/dist/index.cjs +128 -15046
  276. package/dist/index.d.cts +697 -662
  277. package/dist/index.d.ts +697 -662
  278. package/dist/index.js +43 -14962
  279. package/dist/motion/Collapse.cjs +28 -0
  280. package/dist/motion/Collapse.js +25 -0
  281. package/dist/motion/MotionProvider.cjs +43 -0
  282. package/dist/motion/MotionProvider.js +38 -0
  283. package/dist/motion/Pressable.cjs +46 -0
  284. package/dist/motion/Pressable.js +43 -0
  285. package/dist/motion/Reveal.cjs +19 -0
  286. package/dist/motion/Reveal.js +16 -0
  287. package/dist/motion/SharedLayout.cjs +46 -0
  288. package/dist/motion/SharedLayout.js +43 -0
  289. package/dist/motion/index.cjs +19 -0
  290. package/dist/motion/index.js +6 -0
  291. package/dist/motion/presence.cjs +58 -0
  292. package/dist/motion/presence.js +55 -0
  293. package/dist/motion/presets.cjs +88 -0
  294. package/dist/motion/presets.js +84 -0
  295. package/dist/motion.d.cts +51 -0
  296. package/dist/motion.d.ts +51 -0
  297. package/dist/preset.cjs +356 -195
  298. package/dist/preset.d.cts +111 -32
  299. package/dist/preset.d.ts +111 -32
  300. package/dist/preset.js +353 -187
  301. package/dist/presets-Ba5QndHg.d.cts +144 -0
  302. package/dist/presets-Ba5QndHg.d.ts +144 -0
  303. package/dist/styles.css +1 -1
  304. package/dist/utils/cn.cjs +38 -0
  305. package/dist/utils/cn.js +35 -0
  306. package/dist/utils/resolveIcon.cjs +18 -0
  307. package/dist/utils/resolveIcon.js +15 -0
  308. package/package.json +79 -21
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Adapter hook for using Rayden Select with react-hook-form.
3
+ *
4
+ * @example
5
+ * ```tsx
6
+ * import { useForm } from "react-hook-form";
7
+ * import { Select, SelectOption, useRaydenSelect } from "@raydenui/ui";
8
+ *
9
+ * function MyForm() {
10
+ * const form = useForm<{ country: string }>();
11
+ *
12
+ * return (
13
+ * <form onSubmit={form.handleSubmit(onSubmit)}>
14
+ * <Select
15
+ * label="Country"
16
+ * {...useRaydenSelect({ form, name: "country" })}
17
+ * >
18
+ * <SelectOption value="us">United States</SelectOption>
19
+ * <SelectOption value="uk">United Kingdom</SelectOption>
20
+ * </Select>
21
+ * </form>
22
+ * );
23
+ * }
24
+ * ```
25
+ */
26
+ export function useRaydenSelect({ form, name }) {
27
+ const value = form.watch(name);
28
+ // See useRaydenInput: a flat errors[name] lookup cannot see nested field paths.
29
+ const { error } = form.getFieldState(name, form.formState);
30
+ const onValueChange = (newValue) => {
31
+ form.setValue(name, newValue, {
32
+ shouldValidate: true,
33
+ shouldDirty: true,
34
+ shouldTouch: true,
35
+ });
36
+ };
37
+ return {
38
+ value: value ?? "",
39
+ onValueChange,
40
+ error: error?.message,
41
+ };
42
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./form/index.cjs"), exports);
@@ -0,0 +1 @@
1
+ export * from "./form/index.js";
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useBodyScrollLock = useBodyScrollLock;
4
+ const react_1 = require("react");
5
+ const useBrowserLayoutEffect = typeof window === "undefined" ? react_1.useEffect : react_1.useLayoutEffect;
6
+ const locks = new WeakMap();
7
+ /** Restore the original style only after the last open modal releases its lock. */
8
+ function useBodyScrollLock(locked) {
9
+ useBrowserLayoutEffect(() => {
10
+ if (!locked)
11
+ return;
12
+ const body = document.body;
13
+ const lock = locks.get(body) ?? { count: 0, overflow: body.style.overflow };
14
+ lock.count++;
15
+ locks.set(body, lock);
16
+ body.style.overflow = "hidden";
17
+ return () => {
18
+ if (--lock.count === 0) {
19
+ body.style.overflow = lock.overflow;
20
+ locks.delete(body);
21
+ }
22
+ };
23
+ }, [locked]);
24
+ }
@@ -0,0 +1,21 @@
1
+ import { useEffect, useLayoutEffect } from "react";
2
+ const useBrowserLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
3
+ const locks = new WeakMap();
4
+ /** Restore the original style only after the last open modal releases its lock. */
5
+ export function useBodyScrollLock(locked) {
6
+ useBrowserLayoutEffect(() => {
7
+ if (!locked)
8
+ return;
9
+ const body = document.body;
10
+ const lock = locks.get(body) ?? { count: 0, overflow: body.style.overflow };
11
+ lock.count++;
12
+ locks.set(body, lock);
13
+ body.style.overflow = "hidden";
14
+ return () => {
15
+ if (--lock.count === 0) {
16
+ body.style.overflow = lock.overflow;
17
+ locks.delete(body);
18
+ }
19
+ };
20
+ }, [locked]);
21
+ }
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useCollisionAwareSide = useCollisionAwareSide;
4
+ const react_1 = require("react");
5
+ const OPPOSITE = {
6
+ top: "bottom",
7
+ bottom: "top",
8
+ left: "right",
9
+ right: "left",
10
+ };
11
+ /** Does the panel fit between the trigger and the viewport edge on this side? */
12
+ function fits(side, trigger, panel, margin, viewport) {
13
+ switch (side) {
14
+ case "top":
15
+ return trigger.top - panel.height - margin >= 0;
16
+ case "bottom":
17
+ return trigger.bottom + panel.height + margin <= viewport.innerHeight;
18
+ case "left":
19
+ return trigger.left - panel.width - margin >= 0;
20
+ case "right":
21
+ return trigger.right + panel.width + margin <= viewport.innerWidth;
22
+ }
23
+ }
24
+ /**
25
+ * Resolve which side an anchored panel should actually open on.
26
+ *
27
+ * Fixed side classes put panels off-screen near a viewport edge — a tooltip anchored
28
+ * at the top rendered above the visible area, and a listbox near the bottom opened
29
+ * past it. This flips to the opposite side when the preferred one does not fit and
30
+ * the opposite one does, and re-measures on scroll and resize.
31
+ *
32
+ * Returns the preferred side unchanged until the panel has been measured, so the
33
+ * first paint matches the caller's intent.
34
+ */
35
+ function useCollisionAwareSide(preferred, open, triggerRef, panelRef, margin = 8) {
36
+ const [side, setSide] = (0, react_1.useState)(preferred);
37
+ const measure = (0, react_1.useCallback)(() => {
38
+ const trigger = triggerRef.current?.getBoundingClientRect();
39
+ const panel = panelRef.current?.getBoundingClientRect();
40
+ const viewport = triggerRef.current?.ownerDocument.defaultView;
41
+ if (!trigger || !panel || !viewport || panel.height === 0)
42
+ return;
43
+ const opposite = OPPOSITE[preferred];
44
+ setSide(!fits(preferred, trigger, panel, margin, viewport) &&
45
+ fits(opposite, trigger, panel, margin, viewport)
46
+ ? opposite
47
+ : preferred);
48
+ }, [preferred, triggerRef, panelRef, margin]);
49
+ (0, react_1.useEffect)(() => {
50
+ if (!open) {
51
+ setSide(preferred);
52
+ return;
53
+ }
54
+ const viewport = triggerRef.current?.ownerDocument.defaultView;
55
+ if (!viewport)
56
+ return;
57
+ measure();
58
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
59
+ if (triggerRef.current)
60
+ observer?.observe(triggerRef.current);
61
+ if (panelRef.current)
62
+ observer?.observe(panelRef.current);
63
+ viewport.addEventListener("scroll", measure, true);
64
+ viewport.addEventListener("resize", measure);
65
+ return () => {
66
+ observer?.disconnect();
67
+ viewport.removeEventListener("scroll", measure, true);
68
+ viewport.removeEventListener("resize", measure);
69
+ };
70
+ }, [open, preferred, measure, triggerRef, panelRef]);
71
+ return side;
72
+ }
@@ -0,0 +1,69 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ const OPPOSITE = {
3
+ top: "bottom",
4
+ bottom: "top",
5
+ left: "right",
6
+ right: "left",
7
+ };
8
+ /** Does the panel fit between the trigger and the viewport edge on this side? */
9
+ function fits(side, trigger, panel, margin, viewport) {
10
+ switch (side) {
11
+ case "top":
12
+ return trigger.top - panel.height - margin >= 0;
13
+ case "bottom":
14
+ return trigger.bottom + panel.height + margin <= viewport.innerHeight;
15
+ case "left":
16
+ return trigger.left - panel.width - margin >= 0;
17
+ case "right":
18
+ return trigger.right + panel.width + margin <= viewport.innerWidth;
19
+ }
20
+ }
21
+ /**
22
+ * Resolve which side an anchored panel should actually open on.
23
+ *
24
+ * Fixed side classes put panels off-screen near a viewport edge — a tooltip anchored
25
+ * at the top rendered above the visible area, and a listbox near the bottom opened
26
+ * past it. This flips to the opposite side when the preferred one does not fit and
27
+ * the opposite one does, and re-measures on scroll and resize.
28
+ *
29
+ * Returns the preferred side unchanged until the panel has been measured, so the
30
+ * first paint matches the caller's intent.
31
+ */
32
+ export function useCollisionAwareSide(preferred, open, triggerRef, panelRef, margin = 8) {
33
+ const [side, setSide] = useState(preferred);
34
+ const measure = useCallback(() => {
35
+ const trigger = triggerRef.current?.getBoundingClientRect();
36
+ const panel = panelRef.current?.getBoundingClientRect();
37
+ const viewport = triggerRef.current?.ownerDocument.defaultView;
38
+ if (!trigger || !panel || !viewport || panel.height === 0)
39
+ return;
40
+ const opposite = OPPOSITE[preferred];
41
+ setSide(!fits(preferred, trigger, panel, margin, viewport) &&
42
+ fits(opposite, trigger, panel, margin, viewport)
43
+ ? opposite
44
+ : preferred);
45
+ }, [preferred, triggerRef, panelRef, margin]);
46
+ useEffect(() => {
47
+ if (!open) {
48
+ setSide(preferred);
49
+ return;
50
+ }
51
+ const viewport = triggerRef.current?.ownerDocument.defaultView;
52
+ if (!viewport)
53
+ return;
54
+ measure();
55
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
56
+ if (triggerRef.current)
57
+ observer?.observe(triggerRef.current);
58
+ if (panelRef.current)
59
+ observer?.observe(panelRef.current);
60
+ viewport.addEventListener("scroll", measure, true);
61
+ viewport.addEventListener("resize", measure);
62
+ return () => {
63
+ observer?.disconnect();
64
+ viewport.removeEventListener("scroll", measure, true);
65
+ viewport.removeEventListener("resize", measure);
66
+ };
67
+ }, [open, preferred, measure, triggerRef, panelRef]);
68
+ return side;
69
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useControllableValue = useControllableValue;
4
+ const react_1 = require("react");
5
+ /** Internal controlled/uncontrolled state; callback changes never reset the value. */
6
+ function useControllableValue(value, defaultValue, onChange) {
7
+ const [internal, setInternal] = (0, react_1.useState)(defaultValue);
8
+ const latest = (0, react_1.useRef)({ value, onChange });
9
+ latest.current = { value, onChange };
10
+ const setValue = (0, react_1.useCallback)((next) => {
11
+ if (latest.current.value === undefined)
12
+ setInternal(next);
13
+ latest.current.onChange?.(next);
14
+ }, []);
15
+ return [value === undefined ? internal : value, setValue];
16
+ }
@@ -0,0 +1,13 @@
1
+ import { useCallback, useRef, useState } from "react";
2
+ /** Internal controlled/uncontrolled state; callback changes never reset the value. */
3
+ export function useControllableValue(value, defaultValue, onChange) {
4
+ const [internal, setInternal] = useState(defaultValue);
5
+ const latest = useRef({ value, onChange });
6
+ latest.current = { value, onChange };
7
+ const setValue = useCallback((next) => {
8
+ if (latest.current.value === undefined)
9
+ setInternal(next);
10
+ latest.current.onChange?.(next);
11
+ }, []);
12
+ return [value === undefined ? internal : value, setValue];
13
+ }
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useDismissableLayer = useDismissableLayer;
4
+ const react_1 = require("react");
5
+ // One listener set per document. Nested layers must not all handle the same Escape.
6
+ const documents = new WeakMap();
7
+ function topLayer(layers) {
8
+ return layers
9
+ .filter((layer) => layer.element.isConnected && layer.active())
10
+ .reduce((top, layer) => (top && layer.element.contains(top.element) ? top : layer), undefined);
11
+ }
12
+ function register(document, layer) {
13
+ let state = documents.get(document);
14
+ if (!state) {
15
+ const layers = [];
16
+ const contains = (layer, event) => event.composedPath().includes(layer.element);
17
+ const key = (event) => {
18
+ if (event.key !== "Escape" || event.defaultPrevented || event.isComposing)
19
+ return;
20
+ const top = topLayer(layers);
21
+ if (!top)
22
+ return;
23
+ // Also prevent the native dialog cancel action when a child popup consumes Escape.
24
+ event.preventDefault();
25
+ event.stopPropagation();
26
+ top.dismiss("escape");
27
+ };
28
+ const pointer = (event) => {
29
+ if (event.defaultPrevented)
30
+ return;
31
+ for (const layer of [...layers].reverse()) {
32
+ if (layer.active() && !contains(layer, event))
33
+ layer.dismiss("outside-pointer");
34
+ }
35
+ };
36
+ const focus = (event) => {
37
+ for (const layer of [...layers].reverse()) {
38
+ if (layer.active() && layer.focusOutside() && !contains(layer, event))
39
+ layer.dismiss("outside-focus");
40
+ }
41
+ };
42
+ const blur = (event) => {
43
+ // A null destination can mean Tab left the document or focus was removed.
44
+ if (event.relatedTarget !== null)
45
+ return;
46
+ const affected = layers.filter((layer) => contains(layer, event));
47
+ queueMicrotask(() => {
48
+ for (const layer of affected) {
49
+ if (layer.active() &&
50
+ layer.focusOutside() &&
51
+ !layer.element.contains(document.activeElement))
52
+ layer.dismiss("outside-focus");
53
+ }
54
+ });
55
+ };
56
+ document.addEventListener("keydown", key);
57
+ document.addEventListener("pointerdown", pointer);
58
+ document.addEventListener("focusin", focus);
59
+ document.addEventListener("focusout", blur);
60
+ state = {
61
+ layers,
62
+ dispose: () => {
63
+ document.removeEventListener("keydown", key);
64
+ document.removeEventListener("pointerdown", pointer);
65
+ document.removeEventListener("focusin", focus);
66
+ document.removeEventListener("focusout", blur);
67
+ },
68
+ };
69
+ documents.set(document, state);
70
+ }
71
+ state.layers.push(layer);
72
+ return () => {
73
+ const index = state.layers.indexOf(layer);
74
+ if (index !== -1)
75
+ state.layers.splice(index, 1);
76
+ if (!state.layers.length) {
77
+ state.dispose();
78
+ documents.delete(document);
79
+ }
80
+ };
81
+ }
82
+ /** For anchored, non-portalled popup roots. Modal dialogs retain native dismissal. */
83
+ function useDismissableLayer({ open, containerRef, onDismiss, dismissOnFocusOutside = true, }) {
84
+ const latest = (0, react_1.useRef)({ open, onDismiss, dismissOnFocusOutside });
85
+ latest.current = { open, onDismiss, dismissOnFocusOutside };
86
+ (0, react_1.useEffect)(() => {
87
+ const element = containerRef.current;
88
+ if (!open || !element)
89
+ return;
90
+ return register(element.ownerDocument, {
91
+ element,
92
+ active: () => latest.current.open && element.isConnected,
93
+ dismiss: (reason) => {
94
+ if (latest.current.open)
95
+ latest.current.onDismiss(reason);
96
+ },
97
+ focusOutside: () => latest.current.dismissOnFocusOutside,
98
+ });
99
+ }, [open, containerRef]);
100
+ }
@@ -0,0 +1,97 @@
1
+ import { useEffect, useRef } from "react";
2
+ // One listener set per document. Nested layers must not all handle the same Escape.
3
+ const documents = new WeakMap();
4
+ function topLayer(layers) {
5
+ return layers
6
+ .filter((layer) => layer.element.isConnected && layer.active())
7
+ .reduce((top, layer) => (top && layer.element.contains(top.element) ? top : layer), undefined);
8
+ }
9
+ function register(document, layer) {
10
+ let state = documents.get(document);
11
+ if (!state) {
12
+ const layers = [];
13
+ const contains = (layer, event) => event.composedPath().includes(layer.element);
14
+ const key = (event) => {
15
+ if (event.key !== "Escape" || event.defaultPrevented || event.isComposing)
16
+ return;
17
+ const top = topLayer(layers);
18
+ if (!top)
19
+ return;
20
+ // Also prevent the native dialog cancel action when a child popup consumes Escape.
21
+ event.preventDefault();
22
+ event.stopPropagation();
23
+ top.dismiss("escape");
24
+ };
25
+ const pointer = (event) => {
26
+ if (event.defaultPrevented)
27
+ return;
28
+ for (const layer of [...layers].reverse()) {
29
+ if (layer.active() && !contains(layer, event))
30
+ layer.dismiss("outside-pointer");
31
+ }
32
+ };
33
+ const focus = (event) => {
34
+ for (const layer of [...layers].reverse()) {
35
+ if (layer.active() && layer.focusOutside() && !contains(layer, event))
36
+ layer.dismiss("outside-focus");
37
+ }
38
+ };
39
+ const blur = (event) => {
40
+ // A null destination can mean Tab left the document or focus was removed.
41
+ if (event.relatedTarget !== null)
42
+ return;
43
+ const affected = layers.filter((layer) => contains(layer, event));
44
+ queueMicrotask(() => {
45
+ for (const layer of affected) {
46
+ if (layer.active() &&
47
+ layer.focusOutside() &&
48
+ !layer.element.contains(document.activeElement))
49
+ layer.dismiss("outside-focus");
50
+ }
51
+ });
52
+ };
53
+ document.addEventListener("keydown", key);
54
+ document.addEventListener("pointerdown", pointer);
55
+ document.addEventListener("focusin", focus);
56
+ document.addEventListener("focusout", blur);
57
+ state = {
58
+ layers,
59
+ dispose: () => {
60
+ document.removeEventListener("keydown", key);
61
+ document.removeEventListener("pointerdown", pointer);
62
+ document.removeEventListener("focusin", focus);
63
+ document.removeEventListener("focusout", blur);
64
+ },
65
+ };
66
+ documents.set(document, state);
67
+ }
68
+ state.layers.push(layer);
69
+ return () => {
70
+ const index = state.layers.indexOf(layer);
71
+ if (index !== -1)
72
+ state.layers.splice(index, 1);
73
+ if (!state.layers.length) {
74
+ state.dispose();
75
+ documents.delete(document);
76
+ }
77
+ };
78
+ }
79
+ /** For anchored, non-portalled popup roots. Modal dialogs retain native dismissal. */
80
+ export function useDismissableLayer({ open, containerRef, onDismiss, dismissOnFocusOutside = true, }) {
81
+ const latest = useRef({ open, onDismiss, dismissOnFocusOutside });
82
+ latest.current = { open, onDismiss, dismissOnFocusOutside };
83
+ useEffect(() => {
84
+ const element = containerRef.current;
85
+ if (!open || !element)
86
+ return;
87
+ return register(element.ownerDocument, {
88
+ element,
89
+ active: () => latest.current.open && element.isConnected,
90
+ dismiss: (reason) => {
91
+ if (latest.current.open)
92
+ latest.current.onDismiss(reason);
93
+ },
94
+ focusOutside: () => latest.current.dismissOnFocusOutside,
95
+ });
96
+ }, [open, containerRef]);
97
+ }
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usePopupList = usePopupList;
4
+ const react_1 = require("react");
5
+ const useDismissableLayer_1 = require("./useDismissableLayer.cjs");
6
+ /** Shared focus, dismissal and navigation for Select and DropdownMenu. */
7
+ function usePopupList({ open, setOpen, containerRef, triggerRef, listRef, role, selected = false, }) {
8
+ const initial = (0, react_1.useRef)("selected");
9
+ const search = (0, react_1.useRef)({ value: "", time: 0 });
10
+ const items = (0, react_1.useCallback)(() => {
11
+ const list = listRef.current;
12
+ if (!list)
13
+ return [];
14
+ return Array.from(list.querySelectorAll(`[role="${role}"]`)).filter((item) => item.closest('[role="menu"], [role="listbox"]') === list &&
15
+ !item.matches(':disabled, [aria-disabled="true"]') &&
16
+ !item.closest("[hidden], [inert]") &&
17
+ item.getClientRects().length > 0 &&
18
+ item.ownerDocument.defaultView?.getComputedStyle(item).visibility !== "hidden");
19
+ }, [listRef, role]);
20
+ const focusInitial = (0, react_1.useCallback)(() => {
21
+ const enabled = items();
22
+ const target = initial.current === "last"
23
+ ? enabled[enabled.length - 1]
24
+ : initial.current === "selected" && selected
25
+ ? (enabled.find((item) => item.getAttribute("aria-selected") === "true") ?? enabled[0])
26
+ : enabled[0];
27
+ target?.focus();
28
+ }, [items, selected]);
29
+ (0, react_1.useEffect)(() => {
30
+ if (!open) {
31
+ search.current = { value: "", time: 0 };
32
+ return;
33
+ }
34
+ const timer = setTimeout(focusInitial, 0);
35
+ return () => clearTimeout(timer);
36
+ }, [open, focusInitial]);
37
+ const close = (0, react_1.useCallback)((restoreFocus = false) => {
38
+ const list = listRef.current;
39
+ // Restore before consumer callbacks can open another dialog. No delayed focus theft.
40
+ if (restoreFocus && list?.contains(list.ownerDocument.activeElement))
41
+ triggerRef.current?.focus({ preventScroll: true });
42
+ setOpen(false);
43
+ initial.current = "selected";
44
+ }, [listRef, triggerRef, setOpen]);
45
+ (0, useDismissableLayer_1.useDismissableLayer)({ open, containerRef, onDismiss: (reason) => close(reason === "escape") });
46
+ const onTriggerKeyDown = (event) => {
47
+ if (event.defaultPrevented ||
48
+ event.currentTarget.disabled ||
49
+ (event.key !== "ArrowDown" && event.key !== "ArrowUp"))
50
+ return;
51
+ event.preventDefault();
52
+ initial.current = event.key === "ArrowUp" ? "last" : selected ? "selected" : "first";
53
+ if (open)
54
+ focusInitial();
55
+ else
56
+ setOpen(true);
57
+ };
58
+ const onListKeyDown = (event) => {
59
+ if (event.defaultPrevented ||
60
+ event.isPropagationStopped() ||
61
+ event.nativeEvent.isComposing ||
62
+ event.target.closest('[role="menu"], [role="listbox"]') !== listRef.current)
63
+ return;
64
+ const enabled = items();
65
+ if (!enabled.length)
66
+ return;
67
+ const current = enabled.findIndex((item) => item === event.currentTarget.ownerDocument.activeElement);
68
+ let next;
69
+ if (event.key === "ArrowDown")
70
+ next = (current + 1) % enabled.length;
71
+ else if (event.key === "ArrowUp")
72
+ next = current <= 0 ? enabled.length - 1 : current - 1;
73
+ else if (event.key === "Home")
74
+ next = 0;
75
+ else if (event.key === "End")
76
+ next = enabled.length - 1;
77
+ else if (event.key.length === 1 &&
78
+ event.key !== " " &&
79
+ !event.ctrlKey &&
80
+ !event.metaKey &&
81
+ !event.altKey) {
82
+ const now = Date.now();
83
+ const value = (now - search.current.time < 500 ? search.current.value : "") + event.key.toLowerCase();
84
+ search.current = { value, time: now };
85
+ const query = [...value].every((char) => char === value[0]) ? value[0] : value;
86
+ const start = query.length === 1 ? current + 1 : Math.max(current, 0);
87
+ for (let offset = 0; offset < enabled.length; offset++) {
88
+ const index = (start + offset + enabled.length) % enabled.length;
89
+ if (enabled[index].textContent?.trim().toLowerCase().startsWith(query)) {
90
+ next = index;
91
+ break;
92
+ }
93
+ }
94
+ }
95
+ if (next !== undefined) {
96
+ event.preventDefault();
97
+ enabled[next]?.focus();
98
+ }
99
+ };
100
+ return { close, onTriggerKeyDown, onListKeyDown };
101
+ }