@nofinite/nui 1.1.2 → 2.0.2

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 (405) hide show
  1. package/README.md +61 -48
  2. package/dist/components/accordion/Accordion.cjs +1 -1
  3. package/dist/components/accordion/Accordion.cjs.map +1 -1
  4. package/dist/components/accordion/Accordion.js +64 -43
  5. package/dist/components/accordion/Accordion.js.map +1 -1
  6. package/dist/components/alert/Alert.cjs +1 -1
  7. package/dist/components/alert/Alert.cjs.map +1 -1
  8. package/dist/components/alert/Alert.js +39 -25
  9. package/dist/components/alert/Alert.js.map +1 -1
  10. package/dist/components/avatar/Avatar.cjs +1 -1
  11. package/dist/components/avatar/Avatar.cjs.map +1 -1
  12. package/dist/components/avatar/Avatar.js +58 -44
  13. package/dist/components/avatar/Avatar.js.map +1 -1
  14. package/dist/components/avatar/AvatarGroup.cjs +1 -1
  15. package/dist/components/avatar/AvatarGroup.cjs.map +1 -1
  16. package/dist/components/avatar/AvatarGroup.js +34 -25
  17. package/dist/components/avatar/AvatarGroup.js.map +1 -1
  18. package/dist/components/badge/Badge.cjs +1 -1
  19. package/dist/components/badge/Badge.cjs.map +1 -1
  20. package/dist/components/badge/Badge.js +43 -68
  21. package/dist/components/badge/Badge.js.map +1 -1
  22. package/dist/components/badge/BadgeGroup.cjs +1 -1
  23. package/dist/components/badge/BadgeGroup.cjs.map +1 -1
  24. package/dist/components/badge/BadgeGroup.js +20 -10
  25. package/dist/components/badge/BadgeGroup.js.map +1 -1
  26. package/dist/components/breadcrumbs/Breadcrumbs.cjs +1 -1
  27. package/dist/components/breadcrumbs/Breadcrumbs.cjs.map +1 -1
  28. package/dist/components/breadcrumbs/Breadcrumbs.js +59 -39
  29. package/dist/components/breadcrumbs/Breadcrumbs.js.map +1 -1
  30. package/dist/components/button/Button.cjs +1 -1
  31. package/dist/components/button/Button.cjs.map +1 -1
  32. package/dist/components/button/Button.js +52 -17
  33. package/dist/components/button/Button.js.map +1 -1
  34. package/dist/components/card/Card.cjs +1 -1
  35. package/dist/components/card/Card.cjs.map +1 -1
  36. package/dist/components/card/Card.js +44 -41
  37. package/dist/components/card/Card.js.map +1 -1
  38. package/dist/components/checkbox/Checkbox.cjs +1 -1
  39. package/dist/components/checkbox/Checkbox.cjs.map +1 -1
  40. package/dist/components/checkbox/Checkbox.js +59 -40
  41. package/dist/components/checkbox/Checkbox.js.map +1 -1
  42. package/dist/components/chip/Chip.cjs +1 -1
  43. package/dist/components/chip/Chip.cjs.map +1 -1
  44. package/dist/components/chip/Chip.js +67 -47
  45. package/dist/components/chip/Chip.js.map +1 -1
  46. package/dist/components/combobox/Combobox.cjs +1 -1
  47. package/dist/components/combobox/Combobox.cjs.map +1 -1
  48. package/dist/components/combobox/Combobox.js +123 -108
  49. package/dist/components/combobox/Combobox.js.map +1 -1
  50. package/dist/components/commandpalette/CommandPalette.cjs +1 -1
  51. package/dist/components/commandpalette/CommandPalette.cjs.map +1 -1
  52. package/dist/components/commandpalette/CommandPalette.js +96 -73
  53. package/dist/components/commandpalette/CommandPalette.js.map +1 -1
  54. package/dist/components/contextmenu/ContextMenu.cjs +1 -1
  55. package/dist/components/contextmenu/ContextMenu.cjs.map +1 -1
  56. package/dist/components/contextmenu/ContextMenu.js +79 -58
  57. package/dist/components/contextmenu/ContextMenu.js.map +1 -1
  58. package/dist/components/datagrid/DataGrid.cjs +1 -1
  59. package/dist/components/datagrid/DataGrid.cjs.map +1 -1
  60. package/dist/components/datagrid/DataGrid.js +184 -202
  61. package/dist/components/datagrid/DataGrid.js.map +1 -1
  62. package/dist/components/datepicker/DatePicker.cjs +1 -1
  63. package/dist/components/datepicker/DatePicker.cjs.map +1 -1
  64. package/dist/components/datepicker/DatePicker.js +197 -164
  65. package/dist/components/datepicker/DatePicker.js.map +1 -1
  66. package/dist/components/daterangepicker/DateRangePicker.cjs +1 -1
  67. package/dist/components/daterangepicker/DateRangePicker.cjs.map +1 -1
  68. package/dist/components/daterangepicker/DateRangePicker.js +254 -213
  69. package/dist/components/daterangepicker/DateRangePicker.js.map +1 -1
  70. package/dist/components/dialog/DialogProvider.cjs +2 -0
  71. package/dist/components/dialog/DialogProvider.cjs.map +1 -0
  72. package/dist/components/dialog/DialogProvider.js +71 -0
  73. package/dist/components/dialog/DialogProvider.js.map +1 -0
  74. package/dist/components/dialog/dialogStore.cjs +2 -0
  75. package/dist/components/dialog/dialogStore.cjs.map +1 -0
  76. package/dist/components/dialog/dialogStore.js +60 -0
  77. package/dist/components/dialog/dialogStore.js.map +1 -0
  78. package/dist/components/drawer/Drawer.cjs +1 -1
  79. package/dist/components/drawer/Drawer.cjs.map +1 -1
  80. package/dist/components/drawer/Drawer.js +69 -47
  81. package/dist/components/drawer/Drawer.js.map +1 -1
  82. package/dist/components/dropdown/Dropdown.cjs +1 -1
  83. package/dist/components/dropdown/Dropdown.cjs.map +1 -1
  84. package/dist/components/dropdown/Dropdown.js +134 -108
  85. package/dist/components/dropdown/Dropdown.js.map +1 -1
  86. package/dist/components/fileuploader/FileUploader.cjs +1 -1
  87. package/dist/components/fileuploader/FileUploader.cjs.map +1 -1
  88. package/dist/components/fileuploader/FileUploader.js +96 -61
  89. package/dist/components/fileuploader/FileUploader.js.map +1 -1
  90. package/dist/components/hovercard/HoverCard.cjs +1 -1
  91. package/dist/components/hovercard/HoverCard.cjs.map +1 -1
  92. package/dist/components/hovercard/HoverCard.js +124 -69
  93. package/dist/components/hovercard/HoverCard.js.map +1 -1
  94. package/dist/components/input/Input.cjs +1 -1
  95. package/dist/components/input/Input.cjs.map +1 -1
  96. package/dist/components/input/Input.js +62 -37
  97. package/dist/components/input/Input.js.map +1 -1
  98. package/dist/components/layout/Container.cjs +1 -1
  99. package/dist/components/layout/Container.cjs.map +1 -1
  100. package/dist/components/layout/Container.js +21 -30
  101. package/dist/components/layout/Container.js.map +1 -1
  102. package/dist/components/layout/Flex.cjs +1 -1
  103. package/dist/components/layout/Flex.cjs.map +1 -1
  104. package/dist/components/layout/Flex.js +36 -19
  105. package/dist/components/layout/Flex.js.map +1 -1
  106. package/dist/components/layout/Grid.cjs +1 -1
  107. package/dist/components/layout/Grid.cjs.map +1 -1
  108. package/dist/components/layout/Grid.js +30 -18
  109. package/dist/components/layout/Grid.js.map +1 -1
  110. package/dist/components/link/Link.cjs +2 -0
  111. package/dist/components/link/Link.cjs.map +1 -0
  112. package/dist/components/link/Link.js +41 -0
  113. package/dist/components/link/Link.js.map +1 -0
  114. package/dist/components/megamenu/MegaMenu.cjs +1 -1
  115. package/dist/components/megamenu/MegaMenu.cjs.map +1 -1
  116. package/dist/components/megamenu/MegaMenu.js +107 -38
  117. package/dist/components/megamenu/MegaMenu.js.map +1 -1
  118. package/dist/components/modal/Modal.cjs +1 -1
  119. package/dist/components/modal/Modal.cjs.map +1 -1
  120. package/dist/components/modal/Modal.js +91 -83
  121. package/dist/components/modal/Modal.js.map +1 -1
  122. package/dist/components/multiselect/MultiSelect.cjs +2 -0
  123. package/dist/components/multiselect/MultiSelect.cjs.map +1 -0
  124. package/dist/components/multiselect/MultiSelect.js +176 -0
  125. package/dist/components/multiselect/MultiSelect.js.map +1 -0
  126. package/dist/components/nuiprovider/NUIProvider.cjs +2 -0
  127. package/dist/components/nuiprovider/NUIProvider.cjs.map +1 -0
  128. package/dist/components/nuiprovider/NUIProvider.js +36 -0
  129. package/dist/components/nuiprovider/NUIProvider.js.map +1 -0
  130. package/dist/components/pagination/Pagination.cjs +1 -1
  131. package/dist/components/pagination/Pagination.cjs.map +1 -1
  132. package/dist/components/pagination/Pagination.js +74 -41
  133. package/dist/components/pagination/Pagination.js.map +1 -1
  134. package/dist/components/popover/Popover.cjs +1 -1
  135. package/dist/components/popover/Popover.cjs.map +1 -1
  136. package/dist/components/popover/Popover.js +99 -100
  137. package/dist/components/popover/Popover.js.map +1 -1
  138. package/dist/components/progress/Progress.cjs +1 -1
  139. package/dist/components/progress/Progress.cjs.map +1 -1
  140. package/dist/components/progress/Progress.js +44 -22
  141. package/dist/components/progress/Progress.js.map +1 -1
  142. package/dist/components/radiogroup/RadioGroup.cjs +1 -1
  143. package/dist/components/radiogroup/RadioGroup.cjs.map +1 -1
  144. package/dist/components/radiogroup/RadioGroup.js +69 -74
  145. package/dist/components/radiogroup/RadioGroup.js.map +1 -1
  146. package/dist/components/rating/Rating.cjs +1 -1
  147. package/dist/components/rating/Rating.cjs.map +1 -1
  148. package/dist/components/rating/Rating.js +72 -33
  149. package/dist/components/rating/Rating.js.map +1 -1
  150. package/dist/components/resizable/Resizable.cjs +2 -0
  151. package/dist/components/resizable/Resizable.cjs.map +1 -0
  152. package/dist/components/resizable/Resizable.js +134 -0
  153. package/dist/components/resizable/Resizable.js.map +1 -0
  154. package/dist/components/select/Select.cjs +1 -1
  155. package/dist/components/select/Select.cjs.map +1 -1
  156. package/dist/components/select/Select.js +114 -113
  157. package/dist/components/select/Select.js.map +1 -1
  158. package/dist/components/skeleton/Skeleton.cjs +1 -1
  159. package/dist/components/skeleton/Skeleton.cjs.map +1 -1
  160. package/dist/components/skeleton/Skeleton.js +90 -67
  161. package/dist/components/skeleton/Skeleton.js.map +1 -1
  162. package/dist/components/slider/Slider.cjs +1 -1
  163. package/dist/components/slider/Slider.cjs.map +1 -1
  164. package/dist/components/slider/Slider.js +85 -82
  165. package/dist/components/slider/Slider.js.map +1 -1
  166. package/dist/components/spinner/Spinner.cjs +1 -1
  167. package/dist/components/spinner/Spinner.cjs.map +1 -1
  168. package/dist/components/spinner/Spinner.js +60 -17
  169. package/dist/components/spinner/Spinner.js.map +1 -1
  170. package/dist/components/stepper/Stepper.cjs +1 -5
  171. package/dist/components/stepper/Stepper.cjs.map +1 -1
  172. package/dist/components/stepper/Stepper.js +65 -39
  173. package/dist/components/stepper/Stepper.js.map +1 -1
  174. package/dist/components/switch/Switch.cjs +1 -1
  175. package/dist/components/switch/Switch.cjs.map +1 -1
  176. package/dist/components/switch/Switch.js +89 -62
  177. package/dist/components/switch/Switch.js.map +1 -1
  178. package/dist/components/table/Table.cjs +1 -1
  179. package/dist/components/table/Table.cjs.map +1 -1
  180. package/dist/components/table/Table.js +62 -35
  181. package/dist/components/table/Table.js.map +1 -1
  182. package/dist/components/tabs/Tabs.cjs +1 -1
  183. package/dist/components/tabs/Tabs.cjs.map +1 -1
  184. package/dist/components/tabs/Tabs.js +110 -50
  185. package/dist/components/tabs/Tabs.js.map +1 -1
  186. package/dist/components/textarea/Textarea.cjs +1 -1
  187. package/dist/components/textarea/Textarea.cjs.map +1 -1
  188. package/dist/components/textarea/Textarea.js +63 -58
  189. package/dist/components/textarea/Textarea.js.map +1 -1
  190. package/dist/components/timepicker/TimePicker.cjs +2 -0
  191. package/dist/components/timepicker/TimePicker.cjs.map +1 -0
  192. package/dist/components/timepicker/TimePicker.js +159 -0
  193. package/dist/components/timepicker/TimePicker.js.map +1 -0
  194. package/dist/components/timerangepicker/TimeRangePicker.cjs +2 -0
  195. package/dist/components/timerangepicker/TimeRangePicker.cjs.map +1 -0
  196. package/dist/components/timerangepicker/TimeRangePicker.js +208 -0
  197. package/dist/components/timerangepicker/TimeRangePicker.js.map +1 -0
  198. package/dist/components/toast/Toast.cjs +1 -1
  199. package/dist/components/toast/Toast.cjs.map +1 -1
  200. package/dist/components/toast/Toast.js +91 -38
  201. package/dist/components/toast/Toast.js.map +1 -1
  202. package/dist/components/tooltip/Tooltip.cjs +1 -1
  203. package/dist/components/tooltip/Tooltip.cjs.map +1 -1
  204. package/dist/components/tooltip/Tooltip.js +72 -56
  205. package/dist/components/tooltip/Tooltip.js.map +1 -1
  206. package/dist/components/treeview/TreeView.cjs +1 -1
  207. package/dist/components/treeview/TreeView.cjs.map +1 -1
  208. package/dist/components/treeview/TreeView.js +120 -90
  209. package/dist/components/treeview/TreeView.js.map +1 -1
  210. package/dist/components/virtuallist/VirtualList.cjs +1 -1
  211. package/dist/components/virtuallist/VirtualList.cjs.map +1 -1
  212. package/dist/components/virtuallist/VirtualList.js +52 -34
  213. package/dist/components/virtuallist/VirtualList.js.map +1 -1
  214. package/dist/index.cjs +1 -1
  215. package/dist/index.css +1 -0
  216. package/dist/index.js +120 -106
  217. package/dist/index.js.map +1 -1
  218. package/dist/package.json +49 -6
  219. package/dist/types/components/accordion/Accordion.d.ts +7 -3
  220. package/dist/types/components/accordion/Accordion.d.ts.map +1 -1
  221. package/dist/types/components/alert/Alert.d.ts +18 -5
  222. package/dist/types/components/alert/Alert.d.ts.map +1 -1
  223. package/dist/types/components/avatar/Avatar.d.ts +12 -8
  224. package/dist/types/components/avatar/Avatar.d.ts.map +1 -1
  225. package/dist/types/components/avatar/AvatarGroup.d.ts +11 -4
  226. package/dist/types/components/avatar/AvatarGroup.d.ts.map +1 -1
  227. package/dist/types/components/badge/Badge.d.ts +19 -11
  228. package/dist/types/components/badge/Badge.d.ts.map +1 -1
  229. package/dist/types/components/badge/BadgeGroup.d.ts +7 -4
  230. package/dist/types/components/badge/BadgeGroup.d.ts.map +1 -1
  231. package/dist/types/components/breadcrumbs/Breadcrumbs.d.ts +14 -6
  232. package/dist/types/components/breadcrumbs/Breadcrumbs.d.ts.map +1 -1
  233. package/dist/types/components/button/Button.d.ts +25 -10
  234. package/dist/types/components/button/Button.d.ts.map +1 -1
  235. package/dist/types/components/card/Card.d.ts +12 -21
  236. package/dist/types/components/card/Card.d.ts.map +1 -1
  237. package/dist/types/components/checkbox/Checkbox.d.ts +12 -7
  238. package/dist/types/components/checkbox/Checkbox.d.ts.map +1 -1
  239. package/dist/types/components/chip/Chip.d.ts +14 -11
  240. package/dist/types/components/chip/Chip.d.ts.map +1 -1
  241. package/dist/types/components/combobox/Combobox.d.ts +15 -4
  242. package/dist/types/components/combobox/Combobox.d.ts.map +1 -1
  243. package/dist/types/components/commandpalette/CommandPalette.d.ts +12 -3
  244. package/dist/types/components/commandpalette/CommandPalette.d.ts.map +1 -1
  245. package/dist/types/components/contextmenu/ContextMenu.d.ts +14 -6
  246. package/dist/types/components/contextmenu/ContextMenu.d.ts.map +1 -1
  247. package/dist/types/components/datagrid/DataGrid.d.ts +16 -4
  248. package/dist/types/components/datagrid/DataGrid.d.ts.map +1 -1
  249. package/dist/types/components/datepicker/DatePicker.d.ts +13 -1
  250. package/dist/types/components/datepicker/DatePicker.d.ts.map +1 -1
  251. package/dist/types/components/daterangepicker/DateRangePicker.d.ts +3 -1
  252. package/dist/types/components/daterangepicker/DateRangePicker.d.ts.map +1 -1
  253. package/dist/types/components/dialog/DialogProvider.d.ts +2 -0
  254. package/dist/types/components/dialog/DialogProvider.d.ts.map +1 -0
  255. package/dist/types/components/dialog/dialogStore.d.ts +42 -0
  256. package/dist/types/components/dialog/dialogStore.d.ts.map +1 -0
  257. package/dist/types/components/drawer/Drawer.d.ts +18 -4
  258. package/dist/types/components/drawer/Drawer.d.ts.map +1 -1
  259. package/dist/types/components/dropdown/Dropdown.d.ts +21 -16
  260. package/dist/types/components/dropdown/Dropdown.d.ts.map +1 -1
  261. package/dist/types/components/fileuploader/FileUploader.d.ts +22 -3
  262. package/dist/types/components/fileuploader/FileUploader.d.ts.map +1 -1
  263. package/dist/types/components/hovercard/HoverCard.d.ts +45 -5
  264. package/dist/types/components/hovercard/HoverCard.d.ts.map +1 -1
  265. package/dist/types/components/input/Input.d.ts +20 -10
  266. package/dist/types/components/input/Input.d.ts.map +1 -1
  267. package/dist/types/components/layout/Container.d.ts +8 -4
  268. package/dist/types/components/layout/Container.d.ts.map +1 -1
  269. package/dist/types/components/layout/Flex.d.ts +27 -10
  270. package/dist/types/components/layout/Flex.d.ts.map +1 -1
  271. package/dist/types/components/layout/Grid.d.ts +11 -5
  272. package/dist/types/components/layout/Grid.d.ts.map +1 -1
  273. package/dist/types/components/link/Link.d.ts +22 -0
  274. package/dist/types/components/link/Link.d.ts.map +1 -0
  275. package/dist/types/components/megamenu/MegaMenu.d.ts +8 -11
  276. package/dist/types/components/megamenu/MegaMenu.d.ts.map +1 -1
  277. package/dist/types/components/modal/Modal.d.ts +8 -7
  278. package/dist/types/components/modal/Modal.d.ts.map +1 -1
  279. package/dist/types/components/multiselect/MultiSelect.d.ts +33 -0
  280. package/dist/types/components/multiselect/MultiSelect.d.ts.map +1 -0
  281. package/dist/types/components/nuiprovider/NUIProvider.d.ts +29 -0
  282. package/dist/types/components/nuiprovider/NUIProvider.d.ts.map +1 -0
  283. package/dist/types/components/pagination/Pagination.d.ts +17 -3
  284. package/dist/types/components/pagination/Pagination.d.ts.map +1 -1
  285. package/dist/types/components/popover/Popover.d.ts +54 -16
  286. package/dist/types/components/popover/Popover.d.ts.map +1 -1
  287. package/dist/types/components/progress/Progress.d.ts +17 -7
  288. package/dist/types/components/progress/Progress.d.ts.map +1 -1
  289. package/dist/types/components/radiogroup/RadioGroup.d.ts +15 -10
  290. package/dist/types/components/radiogroup/RadioGroup.d.ts.map +1 -1
  291. package/dist/types/components/rating/Rating.d.ts +24 -10
  292. package/dist/types/components/rating/Rating.d.ts.map +1 -1
  293. package/dist/types/components/resizable/Resizable.d.ts +24 -0
  294. package/dist/types/components/resizable/Resizable.d.ts.map +1 -0
  295. package/dist/types/components/select/Select.d.ts +17 -8
  296. package/dist/types/components/select/Select.d.ts.map +1 -1
  297. package/dist/types/components/skeleton/Skeleton.d.ts +37 -36
  298. package/dist/types/components/skeleton/Skeleton.d.ts.map +1 -1
  299. package/dist/types/components/slider/Slider.d.ts +15 -4
  300. package/dist/types/components/slider/Slider.d.ts.map +1 -1
  301. package/dist/types/components/spinner/Spinner.d.ts +14 -4
  302. package/dist/types/components/spinner/Spinner.d.ts.map +1 -1
  303. package/dist/types/components/stepper/Stepper.d.ts +17 -3
  304. package/dist/types/components/stepper/Stepper.d.ts.map +1 -1
  305. package/dist/types/components/switch/Switch.d.ts +20 -5
  306. package/dist/types/components/switch/Switch.d.ts.map +1 -1
  307. package/dist/types/components/table/Table.d.ts +24 -4
  308. package/dist/types/components/table/Table.d.ts.map +1 -1
  309. package/dist/types/components/tabs/Tabs.d.ts +25 -12
  310. package/dist/types/components/tabs/Tabs.d.ts.map +1 -1
  311. package/dist/types/components/textarea/Textarea.d.ts +8 -5
  312. package/dist/types/components/textarea/Textarea.d.ts.map +1 -1
  313. package/dist/types/components/timepicker/TimePicker.d.ts +26 -0
  314. package/dist/types/components/timepicker/TimePicker.d.ts.map +1 -0
  315. package/dist/types/components/timerangepicker/TimeRangePicker.d.ts +32 -0
  316. package/dist/types/components/timerangepicker/TimeRangePicker.d.ts.map +1 -0
  317. package/dist/types/components/toast/Toast.d.ts +23 -7
  318. package/dist/types/components/toast/Toast.d.ts.map +1 -1
  319. package/dist/types/components/tooltip/Tooltip.d.ts +13 -2
  320. package/dist/types/components/tooltip/Tooltip.d.ts.map +1 -1
  321. package/dist/types/components/treeview/TreeView.d.ts +20 -6
  322. package/dist/types/components/treeview/TreeView.d.ts.map +1 -1
  323. package/dist/types/components/virtuallist/VirtualList.d.ts +12 -16
  324. package/dist/types/components/virtuallist/VirtualList.d.ts.map +1 -1
  325. package/dist/types/index.d.ts +8 -4
  326. package/dist/types/index.d.ts.map +1 -1
  327. package/dist/types/utils/cn/cn.d.ts +19 -0
  328. package/dist/types/utils/cn/cn.d.ts.map +1 -0
  329. package/dist/types/utils/generateid/generateId.d.ts +7 -0
  330. package/dist/types/utils/generateid/generateId.d.ts.map +1 -1
  331. package/dist/types/utils/index.d.ts +2 -0
  332. package/dist/types/utils/index.d.ts.map +1 -1
  333. package/dist/types/utils/inertmanager/inertManager.d.ts +13 -0
  334. package/dist/types/utils/inertmanager/inertManager.d.ts.map +1 -1
  335. package/dist/types/utils/keyboardnav/keyboardNav.d.ts +17 -6
  336. package/dist/types/utils/keyboardnav/keyboardNav.d.ts.map +1 -1
  337. package/dist/types/utils/onclickoutside/onClickOutside.d.ts +9 -1
  338. package/dist/types/utils/onclickoutside/onClickOutside.d.ts.map +1 -1
  339. package/dist/types/utils/portal/portal.d.ts +14 -1
  340. package/dist/types/utils/portal/portal.d.ts.map +1 -1
  341. package/dist/types/utils/restorefocus/restoreFocus.d.ts +8 -4
  342. package/dist/types/utils/restorefocus/restoreFocus.d.ts.map +1 -1
  343. package/dist/types/utils/scrolllock/scrollLock.d.ts +10 -2
  344. package/dist/types/utils/scrolllock/scrollLock.d.ts.map +1 -1
  345. package/dist/types/utils/slot/slot.d.ts +12 -0
  346. package/dist/types/utils/slot/slot.d.ts.map +1 -0
  347. package/dist/types/utils/trapfocus/trapFocus.d.ts +6 -2
  348. package/dist/types/utils/trapfocus/trapFocus.d.ts.map +1 -1
  349. package/dist/utils/cn/cn.cjs +2 -0
  350. package/dist/utils/cn/cn.cjs.map +1 -0
  351. package/dist/utils/cn/cn.js +21 -0
  352. package/dist/utils/cn/cn.js.map +1 -0
  353. package/dist/utils/inertmanager/inertManager.cjs.map +1 -1
  354. package/dist/utils/inertmanager/inertManager.js.map +1 -1
  355. package/dist/utils/onclickoutside/onClickOutside.cjs +1 -1
  356. package/dist/utils/onclickoutside/onClickOutside.cjs.map +1 -1
  357. package/dist/utils/onclickoutside/onClickOutside.js +10 -6
  358. package/dist/utils/onclickoutside/onClickOutside.js.map +1 -1
  359. package/dist/utils/portal/portal.cjs.map +1 -1
  360. package/dist/utils/portal/portal.js.map +1 -1
  361. package/dist/utils/restorefocus/restoreFocus.cjs.map +1 -1
  362. package/dist/utils/restorefocus/restoreFocus.js.map +1 -1
  363. package/dist/utils/scrolllock/scrollLock.cjs.map +1 -1
  364. package/dist/utils/scrolllock/scrollLock.js +7 -0
  365. package/dist/utils/scrolllock/scrollLock.js.map +1 -1
  366. package/dist/utils/slot/slot.cjs +2 -0
  367. package/dist/utils/slot/slot.cjs.map +1 -0
  368. package/dist/utils/slot/slot.js +57 -0
  369. package/dist/utils/slot/slot.js.map +1 -0
  370. package/dist/utils/trapfocus/trapFocus.cjs.map +1 -1
  371. package/dist/utils/trapfocus/trapFocus.js.map +1 -1
  372. package/package.json +49 -6
  373. package/dist/components/layout/HStack.cjs +0 -2
  374. package/dist/components/layout/HStack.cjs.map +0 -1
  375. package/dist/components/layout/HStack.js +0 -9
  376. package/dist/components/layout/HStack.js.map +0 -1
  377. package/dist/components/layout/Stack.cjs +0 -2
  378. package/dist/components/layout/Stack.cjs.map +0 -1
  379. package/dist/components/layout/Stack.js +0 -9
  380. package/dist/components/layout/Stack.js.map +0 -1
  381. package/dist/styles/nui.css +0 -1
  382. package/dist/theme/NUIProvider.cjs +0 -2
  383. package/dist/theme/NUIProvider.cjs.map +0 -1
  384. package/dist/theme/NUIProvider.js +0 -34
  385. package/dist/theme/NUIProvider.js.map +0 -1
  386. package/dist/theme/useTheme.cjs +0 -2
  387. package/dist/theme/useTheme.cjs.map +0 -1
  388. package/dist/theme/useTheme.js +0 -9
  389. package/dist/theme/useTheme.js.map +0 -1
  390. package/dist/types/components/layout/HStack.d.ts +0 -8
  391. package/dist/types/components/layout/HStack.d.ts.map +0 -1
  392. package/dist/types/components/layout/Stack.d.ts +0 -8
  393. package/dist/types/components/layout/Stack.d.ts.map +0 -1
  394. package/dist/types/theme/NUIProvider.d.ts +0 -14
  395. package/dist/types/theme/NUIProvider.d.ts.map +0 -1
  396. package/dist/types/theme/useTheme.d.ts +0 -11
  397. package/dist/types/theme/useTheme.d.ts.map +0 -1
  398. package/dist/utils/generateid/generateId.cjs +0 -2
  399. package/dist/utils/generateid/generateId.cjs.map +0 -1
  400. package/dist/utils/generateid/generateId.js +0 -7
  401. package/dist/utils/generateid/generateId.js.map +0 -1
  402. package/dist/utils/keyboardnav/keyboardNav.cjs +0 -2
  403. package/dist/utils/keyboardnav/keyboardNav.cjs.map +0 -1
  404. package/dist/utils/keyboardnav/keyboardNav.js +0 -10
  405. package/dist/utils/keyboardnav/keyboardNav.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"MegaMenu.cjs","sources":["../../../src/components/megamenu/MegaMenu.tsx"],"sourcesContent":["/**\r\n * MegaMenu.tsx\r\n * ------------\r\n * Accessible mega-menu dropdown for Navbar.\r\n */\r\n\r\nimport { useState, useRef, useEffect } from 'react';\r\nimport './MegaMenu.css';\r\n\r\nexport interface MegaMenuItem {\r\n title: string;\r\n description?: string;\r\n href: string;\r\n}\r\n\r\ninterface MegaMenuProps {\r\n label: string;\r\n items: MegaMenuItem[];\r\n}\r\n\r\nexport function MegaMenu({ label, items }: MegaMenuProps) {\r\n const [open, setOpen] = useState(false);\r\n const panelRef = useRef<HTMLDivElement | null>(null);\r\n const triggerRef = useRef<HTMLButtonElement | null>(null);\r\n\r\n // Close on outside click\r\n useEffect(() => {\r\n if (!open) return;\r\n const handler = (e: MouseEvent) => {\r\n if (\r\n panelRef.current &&\r\n !panelRef.current.contains(e.target as Node) &&\r\n triggerRef.current &&\r\n !triggerRef.current.contains(e.target as Node)\r\n ) {\r\n setOpen(false);\r\n }\r\n };\r\n document.addEventListener('mousedown', handler);\r\n return () => document.removeEventListener('mousedown', handler);\r\n }, [open]);\r\n\r\n return (\r\n <div className=\"ui-megamenu\">\r\n <button\r\n ref={triggerRef}\r\n className=\"ui-megamenu-trigger\"\r\n aria-expanded={open}\r\n onClick={() => setOpen((o) => !o)}\r\n >\r\n {label} ▾\r\n </button>\r\n\r\n <div\r\n ref={panelRef}\r\n className={`ui-megamenu-panel ${open ? 'ui-megamenu-panel--open' : ''}`}\r\n role=\"menu\"\r\n >\r\n <div className=\"ui-megamenu-grid\">\r\n {items.map((it) => (\r\n <a href={it.href} key={it.href} className=\"ui-megamenu-item\">\r\n <span className=\"ui-megamenu-item-title\">{it.title}</span>\r\n {it.description && (\r\n <span className=\"ui-megamenu-item-desc\">{it.description}</span>\r\n )}\r\n </a>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["MegaMenu","label","items","open","setOpen","useState","panelRef","useRef","triggerRef","useEffect","handler","e","jsxs","o","jsx","it"],"mappings":"sKAoBO,SAASA,EAAS,CAAE,MAAAC,EAAO,MAAAC,GAAwB,CACxD,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAS,EAAK,EAChCC,EAAWC,EAAAA,OAA8B,IAAI,EAC7CC,EAAaD,EAAAA,OAAiC,IAAI,EAGxDE,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAI,CAACN,EAAM,OACX,MAAMO,EAAWC,GAAkB,CAE/BL,EAAS,SACT,CAACA,EAAS,QAAQ,SAASK,EAAE,MAAc,GAC3CH,EAAW,SACX,CAACA,EAAW,QAAQ,SAASG,EAAE,MAAc,GAE7CP,EAAQ,EAAK,CAEjB,EACA,gBAAS,iBAAiB,YAAaM,CAAO,EACvC,IAAM,SAAS,oBAAoB,YAAaA,CAAO,CAChE,EAAG,CAACP,CAAI,CAAC,EAGPS,EAAAA,KAAC,MAAA,CAAI,UAAU,cACb,SAAA,CAAAA,EAAAA,KAAC,SAAA,CACC,IAAKJ,EACL,UAAU,sBACV,gBAAeL,EACf,QAAS,IAAMC,EAASS,GAAM,CAACA,CAAC,EAE/B,SAAA,CAAAZ,EAAM,IAAA,CAAA,CAAA,EAGTa,EAAAA,IAAC,MAAA,CACC,IAAKR,EACL,UAAW,qBAAqBH,EAAO,0BAA4B,EAAE,GACrE,KAAK,OAEL,SAAAW,EAAAA,IAAC,MAAA,CAAI,UAAU,mBACZ,WAAM,IAAKC,GACVH,OAAC,IAAA,CAAE,KAAMG,EAAG,KAAoB,UAAU,mBACxC,SAAA,CAAAD,EAAAA,IAAC,OAAA,CAAK,UAAU,yBAA0B,SAAAC,EAAG,MAAM,EAClDA,EAAG,aACFD,EAAAA,IAAC,QAAK,UAAU,wBAAyB,WAAG,WAAA,CAAY,CAAA,GAHrCC,EAAG,IAK1B,CACD,CAAA,CACH,CAAA,CAAA,CACF,EACF,CAEJ"}
1
+ {"version":3,"file":"MegaMenu.cjs","sources":["../../../src/components/megamenu/MegaMenu.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext, useState, useRef, useEffect, forwardRef } from 'react';\nimport { cn } from '../../utils';\nimport './MegaMenu.css';\n\n/* ============================================================\n * Context\n * ============================================================ */\n\ninterface MegaMenuContextValue {\n isOpen: boolean;\n setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;\n triggerRef: React.RefObject<HTMLButtonElement | null>;\n contentId: string;\n}\n\nconst MegaMenuContext = createContext<MegaMenuContextValue | null>(null);\n\nfunction useMegaMenu() {\n const ctx = useContext(MegaMenuContext);\n if (!ctx) throw new Error('MegaMenu components must be used within <MegaMenu>');\n return ctx;\n}\n\n/* ============================================================\n * 1. MegaMenu Root\n * ============================================================ */\n\nexport type MegaMenuProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * MegaMenu Component\n * * A structural navigation wrapper designed to hold complex layouts (like multi-column grids).\n * * Uses Compound Component Architecture.\n */\nconst MegaMenuRoot = forwardRef<HTMLDivElement, MegaMenuProps>(({\n className,\n children,\n ...props\n}, ref) => {\n const [isOpen, setIsOpen] = useState(false);\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const menuRef = useRef<HTMLDivElement | null>(null);\n \n // Unique ID for WAI-ARIA linkage between trigger and content\n const reactId = React.useId();\n const contentId = `nui-megamenu-content-${reactId}`;\n\n // Close on outside click\n useEffect(() => {\n if (!isOpen) return;\n const handleOutsideClick = (e: MouseEvent) => {\n // Check that the click occurred outside BOTH the menu content and the trigger button\n if (\n menuRef.current && \n !menuRef.current.contains(e.target as Node) &&\n triggerRef.current && \n !triggerRef.current.contains(e.target as Node)\n ) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handleOutsideClick);\n return () => document.removeEventListener('mousedown', handleOutsideClick);\n }, [isOpen]);\n\n // Close on Escape key and restore WAI-ARIA focus to the trigger\n useEffect(() => {\n if (!isOpen) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setIsOpen(false);\n triggerRef.current?.focus(); \n }\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen]);\n\n return (\n <MegaMenuContext.Provider value={{ isOpen, setIsOpen, triggerRef, contentId }}>\n <div \n ref={(node) => {\n menuRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }} \n className={cn(\"nui-megamenu\", className)} \n {...props}\n >\n {children}\n </div>\n </MegaMenuContext.Provider>\n );\n});\nMegaMenuRoot.displayName = 'MegaMenu';\n\n/* ============================================================\n * 2. MegaMenu Trigger\n * ============================================================ */\n\nexport type MegaMenuTriggerProps = React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * MegaMenu Trigger\n * * The interactive button that toggles the visibility of the MegaMenu Content.\n * * Automatically handles ARIA states (expanded, controls).\n */\nconst MegaMenuTrigger = forwardRef<HTMLButtonElement, MegaMenuTriggerProps>(({\n className,\n children,\n onClick,\n ...props\n}, ref) => {\n const { isOpen, setIsOpen, triggerRef, contentId } = useMegaMenu();\n\n return (\n <button\n ref={(node) => {\n // Assign to internal context ref\n if (triggerRef) {\n (triggerRef as React.MutableRefObject<HTMLButtonElement | null>).current = node;\n }\n // Assign to forwarded ref\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }}\n type=\"button\"\n className={cn(\"nui-megamenu__trigger\", isOpen && \"active\", className)}\n aria-expanded={isOpen}\n aria-controls={contentId}\n onClick={(e) => {\n setIsOpen((prev) => !prev);\n onClick?.(e);\n }}\n {...props}\n >\n {children}\n <svg \n className=\"nui-megamenu__chevron\" \n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" \n fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </button>\n );\n});\nMegaMenuTrigger.displayName = 'MegaMenu.Trigger';\n\n/* ============================================================\n * 3. MegaMenu Content\n * ============================================================ */\n\nexport type MegaMenuContentProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * MegaMenu Content\n * * The dropdown panel containing the complex layout grid.\n * * Unmounts from the DOM when closed to improve performance.\n */\nconst MegaMenuContent = forwardRef<HTMLDivElement, MegaMenuContentProps>(({\n className,\n children,\n ...props\n}, ref) => {\n const { isOpen, contentId } = useMegaMenu();\n\n if (!isOpen) return null;\n\n return (\n <div\n ref={ref}\n id={contentId}\n role=\"menu\"\n className={cn(\"nui-megamenu__content\", className)}\n {...props}\n >\n {children}\n </div>\n );\n});\nMegaMenuContent.displayName = 'MegaMenu.Content';\n\n/* ============================================================\n * Export\n * ============================================================ */\n\nexport const MegaMenu = Object.assign(MegaMenuRoot, {\n Trigger: MegaMenuTrigger,\n Content: MegaMenuContent,\n});"],"names":["MegaMenuContext","createContext","useMegaMenu","ctx","useContext","MegaMenuRoot","forwardRef","className","children","props","ref","isOpen","setIsOpen","useState","triggerRef","useRef","menuRef","contentId","React","useEffect","handleOutsideClick","e","handleKeyDown","jsx","node","cn","MegaMenuTrigger","onClick","jsxs","prev","MegaMenuContent","MegaMenu"],"mappings":"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"}
@@ -1,43 +1,112 @@
1
- import { jsxs as i, jsx as r } from "react/jsx-runtime";
2
- import { useState as o, useRef as u, useEffect as d } from "react";
1
+ import { jsx as d, jsxs as x } from "react/jsx-runtime";
2
+ import C, { forwardRef as l, useState as I, useRef as p, useEffect as M, createContext as E, useContext as N } from "react";
3
3
  /* empty css */
4
- function h({ label: c, items: l }) {
5
- const [n, m] = o(!1), a = u(null), t = u(null);
6
- return d(() => {
7
- if (!n) return;
8
- const e = (s) => {
9
- a.current && !a.current.contains(s.target) && t.current && !t.current.contains(s.target) && m(!1);
10
- };
11
- return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
12
- }, [n]), /* @__PURE__ */ i("div", { className: "ui-megamenu", children: [
13
- /* @__PURE__ */ i(
14
- "button",
15
- {
16
- ref: t,
17
- className: "ui-megamenu-trigger",
18
- "aria-expanded": n,
19
- onClick: () => m((e) => !e),
20
- children: [
21
- c,
22
- " ▾"
23
- ]
24
- }
25
- ),
26
- /* @__PURE__ */ r(
27
- "div",
28
- {
29
- ref: a,
30
- className: `ui-megamenu-panel ${n ? "ui-megamenu-panel--open" : ""}`,
31
- role: "menu",
32
- children: /* @__PURE__ */ r("div", { className: "ui-megamenu-grid", children: l.map((e) => /* @__PURE__ */ i("a", { href: e.href, className: "ui-megamenu-item", children: [
33
- /* @__PURE__ */ r("span", { className: "ui-megamenu-item-title", children: e.title }),
34
- e.description && /* @__PURE__ */ r("span", { className: "ui-megamenu-item-desc", children: e.description })
35
- ] }, e.href)) })
36
- }
37
- )
38
- ] });
4
+ import { cn as g } from "../../utils/cn/cn.js";
5
+ const v = E(null);
6
+ function h() {
7
+ const t = N(v);
8
+ if (!t) throw new Error("MegaMenu components must be used within <MegaMenu>");
9
+ return t;
39
10
  }
11
+ const w = l(({
12
+ className: t,
13
+ children: c,
14
+ ...a
15
+ }, r) => {
16
+ const [e, o] = I(!1), s = p(null), i = p(null), u = `nui-megamenu-content-${C.useId()}`;
17
+ return M(() => {
18
+ if (!e) return;
19
+ const n = (m) => {
20
+ i.current && !i.current.contains(m.target) && s.current && !s.current.contains(m.target) && o(!1);
21
+ };
22
+ return document.addEventListener("mousedown", n), () => document.removeEventListener("mousedown", n);
23
+ }, [e]), M(() => {
24
+ if (!e) return;
25
+ const n = (m) => {
26
+ m.key === "Escape" && (o(!1), s.current?.focus());
27
+ };
28
+ return document.addEventListener("keydown", n), () => document.removeEventListener("keydown", n);
29
+ }, [e]), /* @__PURE__ */ d(v.Provider, { value: { isOpen: e, setIsOpen: o, triggerRef: s, contentId: u }, children: /* @__PURE__ */ d(
30
+ "div",
31
+ {
32
+ ref: (n) => {
33
+ i.current = n, typeof r == "function" ? r(n) : r && (r.current = n);
34
+ },
35
+ className: g("nui-megamenu", t),
36
+ ...a,
37
+ children: c
38
+ }
39
+ ) });
40
+ });
41
+ w.displayName = "MegaMenu";
42
+ const y = l(({
43
+ className: t,
44
+ children: c,
45
+ onClick: a,
46
+ ...r
47
+ }, e) => {
48
+ const { isOpen: o, setIsOpen: s, triggerRef: i, contentId: f } = h();
49
+ return /* @__PURE__ */ x(
50
+ "button",
51
+ {
52
+ ref: (u) => {
53
+ i && (i.current = u), typeof e == "function" ? e(u) : e && (e.current = u);
54
+ },
55
+ type: "button",
56
+ className: g("nui-megamenu__trigger", o && "active", t),
57
+ "aria-expanded": o,
58
+ "aria-controls": f,
59
+ onClick: (u) => {
60
+ s((n) => !n), a?.(u);
61
+ },
62
+ ...r,
63
+ children: [
64
+ c,
65
+ /* @__PURE__ */ d(
66
+ "svg",
67
+ {
68
+ className: "nui-megamenu__chevron",
69
+ width: "16",
70
+ height: "16",
71
+ viewBox: "0 0 24 24",
72
+ fill: "none",
73
+ stroke: "currentColor",
74
+ strokeWidth: "2",
75
+ strokeLinecap: "round",
76
+ strokeLinejoin: "round",
77
+ "aria-hidden": "true",
78
+ children: /* @__PURE__ */ d("polyline", { points: "6 9 12 15 18 9" })
79
+ }
80
+ )
81
+ ]
82
+ }
83
+ );
84
+ });
85
+ y.displayName = "MegaMenu.Trigger";
86
+ const k = l(({
87
+ className: t,
88
+ children: c,
89
+ ...a
90
+ }, r) => {
91
+ const { isOpen: e, contentId: o } = h();
92
+ return e ? /* @__PURE__ */ d(
93
+ "div",
94
+ {
95
+ ref: r,
96
+ id: o,
97
+ role: "menu",
98
+ className: g("nui-megamenu__content", t),
99
+ ...a,
100
+ children: c
101
+ }
102
+ ) : null;
103
+ });
104
+ k.displayName = "MegaMenu.Content";
105
+ const b = Object.assign(w, {
106
+ Trigger: y,
107
+ Content: k
108
+ });
40
109
  export {
41
- h as MegaMenu
110
+ b as MegaMenu
42
111
  };
43
112
  //# sourceMappingURL=MegaMenu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MegaMenu.js","sources":["../../../src/components/megamenu/MegaMenu.tsx"],"sourcesContent":["/**\r\n * MegaMenu.tsx\r\n * ------------\r\n * Accessible mega-menu dropdown for Navbar.\r\n */\r\n\r\nimport { useState, useRef, useEffect } from 'react';\r\nimport './MegaMenu.css';\r\n\r\nexport interface MegaMenuItem {\r\n title: string;\r\n description?: string;\r\n href: string;\r\n}\r\n\r\ninterface MegaMenuProps {\r\n label: string;\r\n items: MegaMenuItem[];\r\n}\r\n\r\nexport function MegaMenu({ label, items }: MegaMenuProps) {\r\n const [open, setOpen] = useState(false);\r\n const panelRef = useRef<HTMLDivElement | null>(null);\r\n const triggerRef = useRef<HTMLButtonElement | null>(null);\r\n\r\n // Close on outside click\r\n useEffect(() => {\r\n if (!open) return;\r\n const handler = (e: MouseEvent) => {\r\n if (\r\n panelRef.current &&\r\n !panelRef.current.contains(e.target as Node) &&\r\n triggerRef.current &&\r\n !triggerRef.current.contains(e.target as Node)\r\n ) {\r\n setOpen(false);\r\n }\r\n };\r\n document.addEventListener('mousedown', handler);\r\n return () => document.removeEventListener('mousedown', handler);\r\n }, [open]);\r\n\r\n return (\r\n <div className=\"ui-megamenu\">\r\n <button\r\n ref={triggerRef}\r\n className=\"ui-megamenu-trigger\"\r\n aria-expanded={open}\r\n onClick={() => setOpen((o) => !o)}\r\n >\r\n {label} ▾\r\n </button>\r\n\r\n <div\r\n ref={panelRef}\r\n className={`ui-megamenu-panel ${open ? 'ui-megamenu-panel--open' : ''}`}\r\n role=\"menu\"\r\n >\r\n <div className=\"ui-megamenu-grid\">\r\n {items.map((it) => (\r\n <a href={it.href} key={it.href} className=\"ui-megamenu-item\">\r\n <span className=\"ui-megamenu-item-title\">{it.title}</span>\r\n {it.description && (\r\n <span className=\"ui-megamenu-item-desc\">{it.description}</span>\r\n )}\r\n </a>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"names":["MegaMenu","label","items","open","setOpen","useState","panelRef","useRef","triggerRef","useEffect","handler","e","jsxs","o","jsx","it"],"mappings":";;;AAoBO,SAASA,EAAS,EAAE,OAAAC,GAAO,OAAAC,KAAwB;AACxD,QAAM,CAACC,GAAMC,CAAO,IAAIC,EAAS,EAAK,GAChCC,IAAWC,EAA8B,IAAI,GAC7CC,IAAaD,EAAiC,IAAI;AAGxD,SAAAE,EAAU,MAAM;AACd,QAAI,CAACN,EAAM;AACX,UAAMO,IAAU,CAACC,MAAkB;AACjC,MACEL,EAAS,WACT,CAACA,EAAS,QAAQ,SAASK,EAAE,MAAc,KAC3CH,EAAW,WACX,CAACA,EAAW,QAAQ,SAASG,EAAE,MAAc,KAE7CP,EAAQ,EAAK;AAAA,IAEjB;AACA,oBAAS,iBAAiB,aAAaM,CAAO,GACvC,MAAM,SAAS,oBAAoB,aAAaA,CAAO;AAAA,EAChE,GAAG,CAACP,CAAI,CAAC,GAGP,gBAAAS,EAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,IAAA,gBAAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKJ;AAAA,QACL,WAAU;AAAA,QACV,iBAAeL;AAAA,QACf,SAAS,MAAMC,EAAQ,CAACS,MAAM,CAACA,CAAC;AAAA,QAE/B,UAAA;AAAA,UAAAZ;AAAA,UAAM;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAGT,gBAAAa;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKR;AAAA,QACL,WAAW,qBAAqBH,IAAO,4BAA4B,EAAE;AAAA,QACrE,MAAK;AAAA,QAEL,UAAA,gBAAAW,EAAC,OAAA,EAAI,WAAU,oBACZ,YAAM,IAAI,CAACC,MACV,gBAAAH,EAAC,KAAA,EAAE,MAAMG,EAAG,MAAoB,WAAU,oBACxC,UAAA;AAAA,UAAA,gBAAAD,EAAC,QAAA,EAAK,WAAU,0BAA0B,UAAAC,EAAG,OAAM;AAAA,UAClDA,EAAG,eACF,gBAAAD,EAAC,UAAK,WAAU,yBAAyB,YAAG,YAAA,CAAY;AAAA,QAAA,KAHrCC,EAAG,IAK1B,CACD,EAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,GACF;AAEJ;"}
1
+ {"version":3,"file":"MegaMenu.js","sources":["../../../src/components/megamenu/MegaMenu.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext, useState, useRef, useEffect, forwardRef } from 'react';\nimport { cn } from '../../utils';\nimport './MegaMenu.css';\n\n/* ============================================================\n * Context\n * ============================================================ */\n\ninterface MegaMenuContextValue {\n isOpen: boolean;\n setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;\n triggerRef: React.RefObject<HTMLButtonElement | null>;\n contentId: string;\n}\n\nconst MegaMenuContext = createContext<MegaMenuContextValue | null>(null);\n\nfunction useMegaMenu() {\n const ctx = useContext(MegaMenuContext);\n if (!ctx) throw new Error('MegaMenu components must be used within <MegaMenu>');\n return ctx;\n}\n\n/* ============================================================\n * 1. MegaMenu Root\n * ============================================================ */\n\nexport type MegaMenuProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * MegaMenu Component\n * * A structural navigation wrapper designed to hold complex layouts (like multi-column grids).\n * * Uses Compound Component Architecture.\n */\nconst MegaMenuRoot = forwardRef<HTMLDivElement, MegaMenuProps>(({\n className,\n children,\n ...props\n}, ref) => {\n const [isOpen, setIsOpen] = useState(false);\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const menuRef = useRef<HTMLDivElement | null>(null);\n \n // Unique ID for WAI-ARIA linkage between trigger and content\n const reactId = React.useId();\n const contentId = `nui-megamenu-content-${reactId}`;\n\n // Close on outside click\n useEffect(() => {\n if (!isOpen) return;\n const handleOutsideClick = (e: MouseEvent) => {\n // Check that the click occurred outside BOTH the menu content and the trigger button\n if (\n menuRef.current && \n !menuRef.current.contains(e.target as Node) &&\n triggerRef.current && \n !triggerRef.current.contains(e.target as Node)\n ) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handleOutsideClick);\n return () => document.removeEventListener('mousedown', handleOutsideClick);\n }, [isOpen]);\n\n // Close on Escape key and restore WAI-ARIA focus to the trigger\n useEffect(() => {\n if (!isOpen) return;\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setIsOpen(false);\n triggerRef.current?.focus(); \n }\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen]);\n\n return (\n <MegaMenuContext.Provider value={{ isOpen, setIsOpen, triggerRef, contentId }}>\n <div \n ref={(node) => {\n menuRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }} \n className={cn(\"nui-megamenu\", className)} \n {...props}\n >\n {children}\n </div>\n </MegaMenuContext.Provider>\n );\n});\nMegaMenuRoot.displayName = 'MegaMenu';\n\n/* ============================================================\n * 2. MegaMenu Trigger\n * ============================================================ */\n\nexport type MegaMenuTriggerProps = React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * MegaMenu Trigger\n * * The interactive button that toggles the visibility of the MegaMenu Content.\n * * Automatically handles ARIA states (expanded, controls).\n */\nconst MegaMenuTrigger = forwardRef<HTMLButtonElement, MegaMenuTriggerProps>(({\n className,\n children,\n onClick,\n ...props\n}, ref) => {\n const { isOpen, setIsOpen, triggerRef, contentId } = useMegaMenu();\n\n return (\n <button\n ref={(node) => {\n // Assign to internal context ref\n if (triggerRef) {\n (triggerRef as React.MutableRefObject<HTMLButtonElement | null>).current = node;\n }\n // Assign to forwarded ref\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }}\n type=\"button\"\n className={cn(\"nui-megamenu__trigger\", isOpen && \"active\", className)}\n aria-expanded={isOpen}\n aria-controls={contentId}\n onClick={(e) => {\n setIsOpen((prev) => !prev);\n onClick?.(e);\n }}\n {...props}\n >\n {children}\n <svg \n className=\"nui-megamenu__chevron\" \n width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" \n fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </button>\n );\n});\nMegaMenuTrigger.displayName = 'MegaMenu.Trigger';\n\n/* ============================================================\n * 3. MegaMenu Content\n * ============================================================ */\n\nexport type MegaMenuContentProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * MegaMenu Content\n * * The dropdown panel containing the complex layout grid.\n * * Unmounts from the DOM when closed to improve performance.\n */\nconst MegaMenuContent = forwardRef<HTMLDivElement, MegaMenuContentProps>(({\n className,\n children,\n ...props\n}, ref) => {\n const { isOpen, contentId } = useMegaMenu();\n\n if (!isOpen) return null;\n\n return (\n <div\n ref={ref}\n id={contentId}\n role=\"menu\"\n className={cn(\"nui-megamenu__content\", className)}\n {...props}\n >\n {children}\n </div>\n );\n});\nMegaMenuContent.displayName = 'MegaMenu.Content';\n\n/* ============================================================\n * Export\n * ============================================================ */\n\nexport const MegaMenu = Object.assign(MegaMenuRoot, {\n Trigger: MegaMenuTrigger,\n Content: MegaMenuContent,\n});"],"names":["MegaMenuContext","createContext","useMegaMenu","ctx","useContext","MegaMenuRoot","forwardRef","className","children","props","ref","isOpen","setIsOpen","useState","triggerRef","useRef","menuRef","contentId","React","useEffect","handleOutsideClick","e","handleKeyDown","jsx","node","cn","MegaMenuTrigger","onClick","jsxs","prev","MegaMenuContent","MegaMenu"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),r=require("react");;/* empty css */const x=require("../../utils/scrolllock/scrollLock.cjs"),g=require("../../utils/inertmanager/inertManager.cjs"),E=require("../../utils/trapfocus/trapFocus.cjs"),L=require("../../utils/onclickoutside/onClickOutside.cjs"),M=require("../../utils/restorefocus/restoreFocus.cjs"),S=require("../../utils/portal/portal.cjs");let h=0;const j=t=>(h+=1,`${t}-${h}`);function T({open:t,onClose:m,title:a,description:u,labelledById:p,describedById:q,disableClickOutside:i=!1,disableEsc:f=!1,initialFocusRef:l,className:I="",children:C}){const d=r.useRef(null),n=r.useRef(null),v=r.useRef(null),N=r.useRef(p||(a?j("modal-title"):void 0)),R=r.useRef(q||(u?j("modal-desc"):void 0)),y=N.current,k=R.current,o=r.useCallback(()=>{m()},[m]);return r.useEffect(()=>{if(!t||f)return;const c=s=>{s.key==="Escape"&&(s.preventDefault(),o())};return document.addEventListener("keydown",c),()=>document.removeEventListener("keydown",c)},[t,f,o]),r.useEffect(()=>{if(!t)return;v.current=document.activeElement,x.scrollLock.lock();const c=d.current?g.applyInertToSiblings(d.current):[];l?.current&&n.current?.contains(l.current)&&l.current.focus();const s=n.current?E.trapFocus(n.current):void 0;let b;return!i&&n.current&&(b=L.onClickOutside(n,o)),()=>{b?.(),s?.(),x.scrollLock.unlock(),g.removeInertFromSiblings(c),M.restoreFocus(v.current)}},[t,i,o,l]),t?e.jsx(S.Portal,{children:e.jsxs("div",{ref:d,className:"ui-modal-overlay","aria-hidden":"false",children:[e.jsxs("div",{ref:n,className:`ui-modal-container ${I}`,role:"dialog","aria-modal":"true","aria-labelledby":y,"aria-describedby":k,tabIndex:-1,onClick:c=>c.stopPropagation(),children:[a&&e.jsx("div",{id:y,className:"ui-modal-title",children:a}),u&&e.jsx("div",{id:k,className:"ui-modal-description",children:u}),e.jsx("div",{className:"ui-modal-content",children:C}),e.jsx("button",{type:"button","aria-label":"Close dialog",className:"ui-modal-close",onClick:o,children:"×"})]}),!i&&e.jsx("button",{"aria-hidden":"true",className:"ui-modal-overlay-catcher",onClick:o,tabIndex:-1})]})}):null}exports.Modal=T;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),t=require("react");;/* empty css */const g=require("../../utils/scrolllock/scrollLock.cjs"),q=require("../../utils/inertmanager/inertManager.cjs"),R=require("../../utils/trapfocus/trapFocus.cjs"),w=require("../../utils/onclickoutside/onClickOutside.cjs"),F=require("../../utils/restorefocus/restoreFocus.cjs"),O=require("../../utils/portal/portal.cjs"),_=require("../../utils/cn/cn.cjs");function P({open:u,onClose:f,title:l,description:c,labelledById:I,describedById:C,disableClickOutside:m=!1,disableEsc:v=!1,hideCloseButton:E=!1,initialFocusRef:i,className:L,overlayClassName:N,children:M,...S}){const[T,x]=t.useState(u),[n,h]=t.useState(!1),d=t.useRef(null),s=t.useRef(null),k=t.useRef(null),y=t.useId(),p=I||`${y}-title`,b=C||`${y}-desc`,o=t.useCallback(()=>{f()},[f]);return t.useEffect(()=>{let e;return u?(x(!0),e=setTimeout(()=>h(!0),10)):(h(!1),e=setTimeout(()=>x(!1),300)),()=>{e&&clearTimeout(e)}},[u]),t.useEffect(()=>{if(!n||v)return;const e=a=>{a.key==="Escape"&&(a.preventDefault(),o())};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[n,v,o]),t.useEffect(()=>{if(!n)return;k.current=document.activeElement,g.scrollLock.lock();const e=d.current?q.applyInertToSiblings(d.current):[];i?.current&&s.current?.contains(i.current)&&i.current.focus();const a=s.current?R.trapFocus(s.current):void 0;let j;return!m&&s.current&&(j=w.onClickOutside(s,o)),()=>{j?.(),a?.(),g.scrollLock.unlock(),q.removeInertFromSiblings(e),F.restoreFocus(k.current)}},[n,m,o,i]),T?r.jsx(O.Portal,{children:r.jsx("div",{ref:d,className:_.cn("nui-modal-overlay",N),"data-state":n?"open":"closed","aria-hidden":"true",children:r.jsxs("div",{ref:s,className:_.cn("nui-modal-container",L),"data-state":n?"open":"closed",role:"dialog","aria-modal":"true","aria-labelledby":l?p:void 0,"aria-describedby":c?b:void 0,tabIndex:-1,onClick:e=>e.stopPropagation(),...S,children:[(l||c)&&r.jsxs("div",{className:"nui-modal__header",children:[l&&r.jsx("h2",{id:p,className:"nui-modal__title",children:l}),c&&r.jsx("p",{id:b,className:"nui-modal__description",children:c})]}),r.jsx("div",{className:"nui-modal__content",children:M}),!E&&r.jsx("button",{type:"button","aria-label":"Close dialog",className:"nui-modal__close",onClick:o,children:r.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[r.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),r.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]})})}):null}exports.Modal=P;
2
2
  //# sourceMappingURL=Modal.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.cjs","sources":["../../../src/components/modal/Modal.tsx"],"sourcesContent":["/**\r\n * Modal.tsx\r\n * ----------\r\n * Fully accessible, WCAG-compliant modal/dialog component.\r\n *\r\n * Features:\r\n * - Role-based WAI-ARIA dialog semantics\r\n * - aria-modal, aria-labelledby, aria-describedby\r\n * - Portal rendering into <body>\r\n * - ESC-to-close (optional)\r\n * - Click-outside-to-close (optional)\r\n * - Focus trap (Tab / Shift+Tab)\r\n * - Focus restore on close\r\n * - Scroll locking on open\r\n * - INERT background content (full compliance)\r\n * - prefers-reduced-motion support\r\n * - initial focus element support\r\n *\r\n * Zero dependencies — all logic is pure React.\r\n */\r\n\r\n/**\r\n * Modal.tsx (Lint Clean Version)\r\n * ------------------------------\r\n * All ESLint issues fixed:\r\n * - No missing dependencies\r\n * - No inline re-created functions\r\n * - No non-null assertions\r\n * - No unused values\r\n */\r\n\r\nimport React, { useEffect, useRef, useCallback } from 'react';\r\nimport './Modal.css';\r\n\r\nimport { trapFocus, onClickOutside, restoreFocus, scrollLock, Portal, applyInertToSiblings,\r\n removeInertFromSiblings } from '../../utils/index';\r\n\r\nexport interface ModalProps {\r\n open: boolean;\r\n onClose: () => void;\r\n\r\n title?: string;\r\n description?: string;\r\n\r\n labelledById?: string;\r\n describedById?: string;\r\n\r\n disableClickOutside?: boolean;\r\n disableEsc?: boolean;\r\n\r\n initialFocusRef?: React.RefObject<HTMLElement>;\r\n\r\n className?: string;\r\n children?: React.ReactNode;\r\n}\r\n\r\nlet idCounter = 0;\r\nconst nextId = (prefix: string) => {\r\n idCounter += 1;\r\n return `${prefix}-${idCounter}`;\r\n};\r\n\r\nexport function Modal({\r\n open,\r\n onClose,\r\n title,\r\n description,\r\n labelledById,\r\n describedById,\r\n disableClickOutside = false,\r\n disableEsc = false,\r\n initialFocusRef,\r\n className = '',\r\n children,\r\n}: ModalProps) {\r\n const overlayRef = useRef<HTMLDivElement | null>(null);\r\n const dialogRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const previouslyFocusedElementRef = useRef<HTMLElement | null>(null);\r\n\r\n // Stable IDs (do NOT regenerate each render)\r\n const internalTitleId = useRef(\r\n labelledById || (title ? nextId('modal-title') : undefined)\r\n );\r\n\r\n const internalDescId = useRef(\r\n describedById || (description ? nextId('modal-desc') : undefined)\r\n );\r\n\r\n const titleId = internalTitleId.current;\r\n const descId = internalDescId.current;\r\n\r\n /**\r\n * Make onClose stable using useCallback\r\n */\r\n const handleClose = useCallback(() => {\r\n onClose();\r\n }, [onClose]);\r\n\r\n /**\r\n * ESC close handling\r\n */\r\n useEffect(() => {\r\n if (!open || disableEsc) return;\r\n\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') {\r\n e.preventDefault();\r\n handleClose();\r\n }\r\n };\r\n\r\n document.addEventListener('keydown', onKey);\r\n return () => document.removeEventListener('keydown', onKey);\r\n }, [open, disableEsc, handleClose]);\r\n\r\n /**\r\n * Main open/close lifecycle\r\n */\r\n useEffect(() => {\r\n if (!open) return;\r\n\r\n // Save previously focused element\r\n previouslyFocusedElementRef.current = document.activeElement as HTMLElement;\r\n\r\n // Lock scroll\r\n scrollLock.lock();\r\n\r\n // Make background inert\r\n const inertTargets = overlayRef.current\r\n ? applyInertToSiblings(overlayRef.current)\r\n : [];\r\n\r\n // Initial focus\r\n if (\r\n initialFocusRef?.current &&\r\n dialogRef.current?.contains(initialFocusRef.current)\r\n ) {\r\n initialFocusRef.current.focus();\r\n }\r\n\r\n // Focus trap\r\n const trapCleanup = dialogRef.current\r\n ? trapFocus(dialogRef.current)\r\n : undefined;\r\n\r\n // Click outside\r\n let clickOutsideCleanup: (() => void) | undefined;\r\n if (!disableClickOutside && dialogRef.current) {\r\n clickOutsideCleanup = onClickOutside(dialogRef, handleClose);\r\n }\r\n\r\n return () => {\r\n clickOutsideCleanup?.();\r\n trapCleanup?.();\r\n scrollLock.unlock();\r\n removeInertFromSiblings(inertTargets);\r\n restoreFocus(previouslyFocusedElementRef.current);\r\n };\r\n }, [open, disableClickOutside, handleClose, initialFocusRef]);\r\n\r\n if (!open) return null;\r\n\r\n return (\r\n <Portal>\r\n <div ref={overlayRef} className=\"ui-modal-overlay\" aria-hidden=\"false\">\r\n <div\r\n ref={dialogRef}\r\n className={`ui-modal-container ${className}`}\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-labelledby={titleId}\r\n aria-describedby={descId}\r\n tabIndex={-1}\r\n onClick={(e) => e.stopPropagation()}\r\n >\r\n {title && (\r\n <div id={titleId} className=\"ui-modal-title\">\r\n {title}\r\n </div>\r\n )}\r\n\r\n {description && (\r\n <div id={descId} className=\"ui-modal-description\">\r\n {description}\r\n </div>\r\n )}\r\n\r\n <div className=\"ui-modal-content\">{children}</div>\r\n\r\n <button\r\n type=\"button\"\r\n aria-label=\"Close dialog\"\r\n className=\"ui-modal-close\"\r\n onClick={handleClose}\r\n >\r\n ×\r\n </button>\r\n </div>\r\n\r\n {!disableClickOutside && (\r\n <button\r\n aria-hidden=\"true\"\r\n className=\"ui-modal-overlay-catcher\"\r\n onClick={handleClose}\r\n tabIndex={-1}\r\n />\r\n )}\r\n </div>\r\n </Portal>\r\n );\r\n}\r\n"],"names":["idCounter","nextId","prefix","Modal","open","onClose","title","description","labelledById","describedById","disableClickOutside","disableEsc","initialFocusRef","className","children","overlayRef","useRef","dialogRef","previouslyFocusedElementRef","internalTitleId","internalDescId","titleId","descId","handleClose","useCallback","useEffect","onKey","e","scrollLock","inertTargets","applyInertToSiblings","trapCleanup","trapFocus","clickOutsideCleanup","onClickOutside","removeInertFromSiblings","restoreFocus","jsx","Portal","jsxs"],"mappings":"ieAwDA,IAAIA,EAAY,EAChB,MAAMC,EAAUC,IACdF,GAAa,EACN,GAAGE,CAAM,IAAIF,CAAS,IAGxB,SAASG,EAAM,CACpB,KAAAC,EACA,QAAAC,EACA,MAAAC,EACA,YAAAC,EACA,aAAAC,EACA,cAAAC,EACA,oBAAAC,EAAsB,GACtB,WAAAC,EAAa,GACb,gBAAAC,EACA,UAAAC,EAAY,GACZ,SAAAC,CACF,EAAe,CACb,MAAMC,EAAaC,EAAAA,OAA8B,IAAI,EAC/CC,EAAYD,EAAAA,OAA8B,IAAI,EAE9CE,EAA8BF,EAAAA,OAA2B,IAAI,EAG7DG,EAAkBH,EAAAA,OACtBR,IAAiBF,EAAQL,EAAO,aAAa,EAAI,OAAA,EAG7CmB,EAAiBJ,EAAAA,OACrBP,IAAkBF,EAAcN,EAAO,YAAY,EAAI,OAAA,EAGnDoB,EAAUF,EAAgB,QAC1BG,EAASF,EAAe,QAKxBG,EAAcC,EAAAA,YAAY,IAAM,CACpCnB,EAAA,CACF,EAAG,CAACA,CAAO,CAAC,EAgEZ,OA3DAoB,EAAAA,UAAU,IAAM,CACd,GAAI,CAACrB,GAAQO,EAAY,OAEzB,MAAMe,EAASC,GAAqB,CAC9BA,EAAE,MAAQ,WACZA,EAAE,eAAA,EACFJ,EAAA,EAEJ,EAEA,gBAAS,iBAAiB,UAAWG,CAAK,EACnC,IAAM,SAAS,oBAAoB,UAAWA,CAAK,CAC5D,EAAG,CAACtB,EAAMO,EAAYY,CAAW,CAAC,EAKlCE,EAAAA,UAAU,IAAM,CACd,GAAI,CAACrB,EAAM,OAGXc,EAA4B,QAAU,SAAS,cAG/CU,EAAAA,WAAW,KAAA,EAGX,MAAMC,EAAed,EAAW,QAC5Be,EAAAA,qBAAqBf,EAAW,OAAO,EACvC,CAAA,EAIFH,GAAiB,SACjBK,EAAU,SAAS,SAASL,EAAgB,OAAO,GAEnDA,EAAgB,QAAQ,MAAA,EAI1B,MAAMmB,EAAcd,EAAU,QAC1Be,EAAAA,UAAUf,EAAU,OAAO,EAC3B,OAGJ,IAAIgB,EACJ,MAAI,CAACvB,GAAuBO,EAAU,UACpCgB,EAAsBC,EAAAA,eAAejB,EAAWM,CAAW,GAGtD,IAAM,CACXU,IAAA,EACAF,IAAA,EACAH,EAAAA,WAAW,OAAA,EACXO,EAAAA,wBAAwBN,CAAY,EACpCO,EAAAA,aAAalB,EAA4B,OAAO,CAClD,CACF,EAAG,CAACd,EAAMM,EAAqBa,EAAaX,CAAe,CAAC,EAEvDR,EAGHiC,EAAAA,IAACC,EAAAA,QACC,SAAAC,EAAAA,KAAC,MAAA,CAAI,IAAKxB,EAAY,UAAU,mBAAmB,cAAY,QAC7D,SAAA,CAAAwB,EAAAA,KAAC,MAAA,CACC,IAAKtB,EACL,UAAW,sBAAsBJ,CAAS,GAC1C,KAAK,SACL,aAAW,OACX,kBAAiBQ,EACjB,mBAAkBC,EAClB,SAAU,GACV,QAAUK,GAAMA,EAAE,gBAAA,EAEjB,SAAA,CAAArB,SACE,MAAA,CAAI,GAAIe,EAAS,UAAU,iBACzB,SAAAf,EACH,EAGDC,GACC8B,EAAAA,IAAC,MAAA,CAAI,GAAIf,EAAQ,UAAU,uBACxB,SAAAf,EACH,EAGF8B,EAAAA,IAAC,MAAA,CAAI,UAAU,mBAAoB,SAAAvB,CAAA,CAAS,EAE5CuB,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,aAAW,eACX,UAAU,iBACV,QAASd,EACV,SAAA,GAAA,CAAA,CAED,CAAA,CAAA,EAGD,CAACb,GACA2B,EAAAA,IAAC,SAAA,CACC,cAAY,OACZ,UAAU,2BACV,QAASd,EACT,SAAU,EAAA,CAAA,CACZ,CAAA,CAEJ,CAAA,CACF,EAhDgB,IAkDpB"}
1
+ {"version":3,"file":"Modal.cjs","sources":["../../../src/components/modal/Modal.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useEffect, useRef, useCallback, useState, useId } from 'react';\nimport { cn } from '../../utils';\nimport { \n trapFocus, \n onClickOutside, \n restoreFocus, \n scrollLock, \n Portal, \n applyInertToSiblings, \n removeInertFromSiblings \n} from '../../utils';\nimport './Modal.css';\n\n/* -------------------------------------------------------------------------- */\n/* Props */\n/* -------------------------------------------------------------------------- */\n\nexport interface ModalProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n open: boolean;\n onClose: () => void;\n title?: React.ReactNode;\n description?: React.ReactNode;\n \n labelledById?: string;\n describedById?: string;\n \n disableClickOutside?: boolean;\n disableEsc?: boolean;\n initialFocusRef?: React.RefObject<HTMLElement | null>;\n \n overlayClassName?: string;\n\n /** Hides the 'X' close button in the top right corner. */\n hideCloseButton?: boolean;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------------- */\n\nexport function Modal({\n open,\n onClose,\n title,\n description,\n labelledById,\n describedById,\n disableClickOutside = false,\n disableEsc = false,\n hideCloseButton = false,\n initialFocusRef,\n className,\n overlayClassName,\n children,\n ...props\n}: ModalProps) {\n const [isMounted, setIsMounted] = useState(open);\n const [isVisible, setIsVisible] = useState(false);\n\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const dialogRef = useRef<HTMLDivElement | null>(null);\n const previouslyFocusedElementRef = useRef<HTMLElement | null>(null);\n\n const baseId = useId();\n const titleId = labelledById || `${baseId}-title`;\n const descId = describedById || `${baseId}-desc`;\n\n const handleClose = useCallback(() => {\n onClose();\n }, [onClose]);\n\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout>;\n\n if (open) {\n setIsMounted(true);\n timer = setTimeout(() => setIsVisible(true), 10);\n } else {\n setIsVisible(false);\n timer = setTimeout(() => setIsMounted(false), 300);\n }\n\n return () => {\n if (timer) clearTimeout(timer);\n };\n }, [open]);\n\n useEffect(() => {\n if (!isVisible || disableEsc) return;\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n handleClose();\n }\n };\n\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [isVisible, disableEsc, handleClose]);\n\n useEffect(() => {\n if (!isVisible) return;\n\n previouslyFocusedElementRef.current = document.activeElement as HTMLElement;\n\n scrollLock.lock();\n\n const inertTargets = overlayRef.current\n ? applyInertToSiblings(overlayRef.current)\n : [];\n\n if (\n initialFocusRef?.current &&\n dialogRef.current?.contains(initialFocusRef.current)\n ) {\n initialFocusRef.current.focus();\n }\n\n const trapCleanup = dialogRef.current\n ? trapFocus(dialogRef.current)\n : undefined;\n\n let clickOutsideCleanup: (() => void) | undefined;\n if (!disableClickOutside && dialogRef.current) {\n clickOutsideCleanup = onClickOutside(dialogRef, handleClose);\n }\n\n return () => {\n clickOutsideCleanup?.();\n trapCleanup?.();\n scrollLock.unlock();\n removeInertFromSiblings(inertTargets);\n restoreFocus(previouslyFocusedElementRef.current);\n };\n }, [isVisible, disableClickOutside, handleClose, initialFocusRef]);\n\n if (!isMounted) return null;\n\n return (\n <Portal>\n <div \n ref={overlayRef} \n className={cn(\"nui-modal-overlay\", overlayClassName)} \n data-state={isVisible ? 'open' : 'closed'}\n aria-hidden=\"true\"\n >\n <div\n ref={dialogRef}\n className={cn(\"nui-modal-container\", className)}\n data-state={isVisible ? 'open' : 'closed'}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? titleId : undefined}\n aria-describedby={description ? descId : undefined}\n tabIndex={-1} \n onClick={(e) => e.stopPropagation()}\n {...props}\n >\n {(title || description) && (\n <div className=\"nui-modal__header\">\n {title && (\n <h2 id={titleId} className=\"nui-modal__title\">\n {title}\n </h2>\n )}\n {description && (\n <p id={descId} className=\"nui-modal__description\">\n {description}\n </p>\n )}\n </div>\n )}\n\n <div className=\"nui-modal__content\">\n {children}\n </div>\n\n {/* Conditionally render the close button */}\n {!hideCloseButton && (\n <button\n type=\"button\"\n aria-label=\"Close dialog\"\n className=\"nui-modal__close\"\n onClick={handleClose}\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n )}\n </div>\n </div>\n </Portal>\n );\n}"],"names":["Modal","open","onClose","title","description","labelledById","describedById","disableClickOutside","disableEsc","hideCloseButton","initialFocusRef","className","overlayClassName","children","props","isMounted","setIsMounted","useState","isVisible","setIsVisible","overlayRef","useRef","dialogRef","previouslyFocusedElementRef","baseId","useId","titleId","descId","handleClose","useCallback","useEffect","timer","onKey","e","scrollLock","inertTargets","applyInertToSiblings","trapCleanup","trapFocus","clickOutsideCleanup","onClickOutside","removeInertFromSiblings","restoreFocus","Portal","jsx","cn","jsxs"],"mappings":"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"}
@@ -1,91 +1,99 @@
1
- import { jsx as o, jsxs as h } from "react/jsx-runtime";
2
- import { useRef as l, useCallback as j, useEffect as k } from "react";
1
+ import { jsx as r, jsxs as u } from "react/jsx-runtime";
2
+ import { useState as C, useRef as m, useId as $, useCallback as B, useEffect as f } from "react";
3
3
  /* empty css */
4
- import { scrollLock as I } from "../../utils/scrolllock/scrollLock.js";
5
- import { applyInertToSiblings as w, removeInertFromSiblings as D } from "../../utils/inertmanager/inertManager.js";
6
- import { trapFocus as P } from "../../utils/trapfocus/trapFocus.js";
7
- import { onClickOutside as S } from "../../utils/onclickoutside/onClickOutside.js";
8
- import { restoreFocus as F } from "../../utils/restorefocus/restoreFocus.js";
9
- import { Portal as K } from "../../utils/portal/portal.js";
10
- let g = 0;
11
- const C = (e) => (g += 1, `${e}-${g}`);
12
- function O({
13
- open: e,
14
- onClose: m,
15
- title: i,
16
- description: d,
17
- labelledById: N,
18
- describedById: x,
19
- disableClickOutside: u = !1,
20
- disableEsc: f = !1,
21
- initialFocusRef: a,
22
- className: E = "",
23
- children: L
4
+ import { scrollLock as N } from "../../utils/scrolllock/scrollLock.js";
5
+ import { applyInertToSiblings as D, removeInertFromSiblings as F } from "../../utils/inertmanager/inertManager.js";
6
+ import { trapFocus as K } from "../../utils/trapfocus/trapFocus.js";
7
+ import { onClickOutside as O } from "../../utils/onclickoutside/onClickOutside.js";
8
+ import { restoreFocus as R } from "../../utils/restorefocus/restoreFocus.js";
9
+ import { Portal as W } from "../../utils/portal/portal.js";
10
+ import { cn as E } from "../../utils/cn/cn.js";
11
+ function Z({
12
+ open: c,
13
+ onClose: p,
14
+ title: l,
15
+ description: i,
16
+ labelledById: L,
17
+ describedById: T,
18
+ disableClickOutside: v = !1,
19
+ disableEsc: h = !1,
20
+ hideCloseButton: w = !1,
21
+ initialFocusRef: s,
22
+ className: j,
23
+ overlayClassName: M,
24
+ children: S,
25
+ ...P
24
26
  }) {
25
- const s = l(null), r = l(null), v = l(null), T = l(
26
- N || (i ? C("modal-title") : void 0)
27
- ), $ = l(
28
- x || (d ? C("modal-desc") : void 0)
29
- ), p = T.current, y = $.current, t = j(() => {
30
- m();
31
- }, [m]);
32
- return k(() => {
33
- if (!e || f) return;
34
- const n = (c) => {
35
- c.key === "Escape" && (c.preventDefault(), t());
27
+ const [V, y] = C(c), [t, k] = C(!1), d = m(null), o = m(null), b = m(null), _ = $(), g = L || `${_}-title`, x = T || `${_}-desc`, n = B(() => {
28
+ p();
29
+ }, [p]);
30
+ return f(() => {
31
+ let e;
32
+ return c ? (y(!0), e = setTimeout(() => k(!0), 10)) : (k(!1), e = setTimeout(() => y(!1), 300)), () => {
33
+ e && clearTimeout(e);
36
34
  };
37
- return document.addEventListener("keydown", n), () => document.removeEventListener("keydown", n);
38
- }, [e, f, t]), k(() => {
39
- if (!e) return;
40
- v.current = document.activeElement, I.lock();
41
- const n = s.current ? w(s.current) : [];
42
- a?.current && r.current?.contains(a.current) && a.current.focus();
43
- const c = r.current ? P(r.current) : void 0;
44
- let b;
45
- return !u && r.current && (b = S(r, t)), () => {
46
- b?.(), c?.(), I.unlock(), D(n), F(v.current);
35
+ }, [c]), f(() => {
36
+ if (!t || h) return;
37
+ const e = (a) => {
38
+ a.key === "Escape" && (a.preventDefault(), n());
47
39
  };
48
- }, [e, u, t, a]), e ? /* @__PURE__ */ o(K, { children: /* @__PURE__ */ h("div", { ref: s, className: "ui-modal-overlay", "aria-hidden": "false", children: [
49
- /* @__PURE__ */ h(
50
- "div",
51
- {
52
- ref: r,
53
- className: `ui-modal-container ${E}`,
54
- role: "dialog",
55
- "aria-modal": "true",
56
- "aria-labelledby": p,
57
- "aria-describedby": y,
58
- tabIndex: -1,
59
- onClick: (n) => n.stopPropagation(),
60
- children: [
61
- i && /* @__PURE__ */ o("div", { id: p, className: "ui-modal-title", children: i }),
62
- d && /* @__PURE__ */ o("div", { id: y, className: "ui-modal-description", children: d }),
63
- /* @__PURE__ */ o("div", { className: "ui-modal-content", children: L }),
64
- /* @__PURE__ */ o(
65
- "button",
66
- {
67
- type: "button",
68
- "aria-label": "Close dialog",
69
- className: "ui-modal-close",
70
- onClick: t,
71
- children: "×"
72
- }
73
- )
74
- ]
75
- }
76
- ),
77
- !u && /* @__PURE__ */ o(
78
- "button",
79
- {
80
- "aria-hidden": "true",
81
- className: "ui-modal-overlay-catcher",
82
- onClick: t,
83
- tabIndex: -1
84
- }
85
- )
86
- ] }) }) : null;
40
+ return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
41
+ }, [t, h, n]), f(() => {
42
+ if (!t) return;
43
+ b.current = document.activeElement, N.lock();
44
+ const e = d.current ? D(d.current) : [];
45
+ s?.current && o.current?.contains(s.current) && s.current.focus();
46
+ const a = o.current ? K(o.current) : void 0;
47
+ let I;
48
+ return !v && o.current && (I = O(o, n)), () => {
49
+ I?.(), a?.(), N.unlock(), F(e), R(b.current);
50
+ };
51
+ }, [t, v, n, s]), V ? /* @__PURE__ */ r(W, { children: /* @__PURE__ */ r(
52
+ "div",
53
+ {
54
+ ref: d,
55
+ className: E("nui-modal-overlay", M),
56
+ "data-state": t ? "open" : "closed",
57
+ "aria-hidden": "true",
58
+ children: /* @__PURE__ */ u(
59
+ "div",
60
+ {
61
+ ref: o,
62
+ className: E("nui-modal-container", j),
63
+ "data-state": t ? "open" : "closed",
64
+ role: "dialog",
65
+ "aria-modal": "true",
66
+ "aria-labelledby": l ? g : void 0,
67
+ "aria-describedby": i ? x : void 0,
68
+ tabIndex: -1,
69
+ onClick: (e) => e.stopPropagation(),
70
+ ...P,
71
+ children: [
72
+ (l || i) && /* @__PURE__ */ u("div", { className: "nui-modal__header", children: [
73
+ l && /* @__PURE__ */ r("h2", { id: g, className: "nui-modal__title", children: l }),
74
+ i && /* @__PURE__ */ r("p", { id: x, className: "nui-modal__description", children: i })
75
+ ] }),
76
+ /* @__PURE__ */ r("div", { className: "nui-modal__content", children: S }),
77
+ !w && /* @__PURE__ */ r(
78
+ "button",
79
+ {
80
+ type: "button",
81
+ "aria-label": "Close dialog",
82
+ className: "nui-modal__close",
83
+ onClick: n,
84
+ children: /* @__PURE__ */ u("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
85
+ /* @__PURE__ */ r("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
86
+ /* @__PURE__ */ r("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
87
+ ] })
88
+ }
89
+ )
90
+ ]
91
+ }
92
+ )
93
+ }
94
+ ) }) : null;
87
95
  }
88
96
  export {
89
- O as Modal
97
+ Z as Modal
90
98
  };
91
99
  //# sourceMappingURL=Modal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.js","sources":["../../../src/components/modal/Modal.tsx"],"sourcesContent":["/**\r\n * Modal.tsx\r\n * ----------\r\n * Fully accessible, WCAG-compliant modal/dialog component.\r\n *\r\n * Features:\r\n * - Role-based WAI-ARIA dialog semantics\r\n * - aria-modal, aria-labelledby, aria-describedby\r\n * - Portal rendering into <body>\r\n * - ESC-to-close (optional)\r\n * - Click-outside-to-close (optional)\r\n * - Focus trap (Tab / Shift+Tab)\r\n * - Focus restore on close\r\n * - Scroll locking on open\r\n * - INERT background content (full compliance)\r\n * - prefers-reduced-motion support\r\n * - initial focus element support\r\n *\r\n * Zero dependencies — all logic is pure React.\r\n */\r\n\r\n/**\r\n * Modal.tsx (Lint Clean Version)\r\n * ------------------------------\r\n * All ESLint issues fixed:\r\n * - No missing dependencies\r\n * - No inline re-created functions\r\n * - No non-null assertions\r\n * - No unused values\r\n */\r\n\r\nimport React, { useEffect, useRef, useCallback } from 'react';\r\nimport './Modal.css';\r\n\r\nimport { trapFocus, onClickOutside, restoreFocus, scrollLock, Portal, applyInertToSiblings,\r\n removeInertFromSiblings } from '../../utils/index';\r\n\r\nexport interface ModalProps {\r\n open: boolean;\r\n onClose: () => void;\r\n\r\n title?: string;\r\n description?: string;\r\n\r\n labelledById?: string;\r\n describedById?: string;\r\n\r\n disableClickOutside?: boolean;\r\n disableEsc?: boolean;\r\n\r\n initialFocusRef?: React.RefObject<HTMLElement>;\r\n\r\n className?: string;\r\n children?: React.ReactNode;\r\n}\r\n\r\nlet idCounter = 0;\r\nconst nextId = (prefix: string) => {\r\n idCounter += 1;\r\n return `${prefix}-${idCounter}`;\r\n};\r\n\r\nexport function Modal({\r\n open,\r\n onClose,\r\n title,\r\n description,\r\n labelledById,\r\n describedById,\r\n disableClickOutside = false,\r\n disableEsc = false,\r\n initialFocusRef,\r\n className = '',\r\n children,\r\n}: ModalProps) {\r\n const overlayRef = useRef<HTMLDivElement | null>(null);\r\n const dialogRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const previouslyFocusedElementRef = useRef<HTMLElement | null>(null);\r\n\r\n // Stable IDs (do NOT regenerate each render)\r\n const internalTitleId = useRef(\r\n labelledById || (title ? nextId('modal-title') : undefined)\r\n );\r\n\r\n const internalDescId = useRef(\r\n describedById || (description ? nextId('modal-desc') : undefined)\r\n );\r\n\r\n const titleId = internalTitleId.current;\r\n const descId = internalDescId.current;\r\n\r\n /**\r\n * Make onClose stable using useCallback\r\n */\r\n const handleClose = useCallback(() => {\r\n onClose();\r\n }, [onClose]);\r\n\r\n /**\r\n * ESC close handling\r\n */\r\n useEffect(() => {\r\n if (!open || disableEsc) return;\r\n\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') {\r\n e.preventDefault();\r\n handleClose();\r\n }\r\n };\r\n\r\n document.addEventListener('keydown', onKey);\r\n return () => document.removeEventListener('keydown', onKey);\r\n }, [open, disableEsc, handleClose]);\r\n\r\n /**\r\n * Main open/close lifecycle\r\n */\r\n useEffect(() => {\r\n if (!open) return;\r\n\r\n // Save previously focused element\r\n previouslyFocusedElementRef.current = document.activeElement as HTMLElement;\r\n\r\n // Lock scroll\r\n scrollLock.lock();\r\n\r\n // Make background inert\r\n const inertTargets = overlayRef.current\r\n ? applyInertToSiblings(overlayRef.current)\r\n : [];\r\n\r\n // Initial focus\r\n if (\r\n initialFocusRef?.current &&\r\n dialogRef.current?.contains(initialFocusRef.current)\r\n ) {\r\n initialFocusRef.current.focus();\r\n }\r\n\r\n // Focus trap\r\n const trapCleanup = dialogRef.current\r\n ? trapFocus(dialogRef.current)\r\n : undefined;\r\n\r\n // Click outside\r\n let clickOutsideCleanup: (() => void) | undefined;\r\n if (!disableClickOutside && dialogRef.current) {\r\n clickOutsideCleanup = onClickOutside(dialogRef, handleClose);\r\n }\r\n\r\n return () => {\r\n clickOutsideCleanup?.();\r\n trapCleanup?.();\r\n scrollLock.unlock();\r\n removeInertFromSiblings(inertTargets);\r\n restoreFocus(previouslyFocusedElementRef.current);\r\n };\r\n }, [open, disableClickOutside, handleClose, initialFocusRef]);\r\n\r\n if (!open) return null;\r\n\r\n return (\r\n <Portal>\r\n <div ref={overlayRef} className=\"ui-modal-overlay\" aria-hidden=\"false\">\r\n <div\r\n ref={dialogRef}\r\n className={`ui-modal-container ${className}`}\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-labelledby={titleId}\r\n aria-describedby={descId}\r\n tabIndex={-1}\r\n onClick={(e) => e.stopPropagation()}\r\n >\r\n {title && (\r\n <div id={titleId} className=\"ui-modal-title\">\r\n {title}\r\n </div>\r\n )}\r\n\r\n {description && (\r\n <div id={descId} className=\"ui-modal-description\">\r\n {description}\r\n </div>\r\n )}\r\n\r\n <div className=\"ui-modal-content\">{children}</div>\r\n\r\n <button\r\n type=\"button\"\r\n aria-label=\"Close dialog\"\r\n className=\"ui-modal-close\"\r\n onClick={handleClose}\r\n >\r\n ×\r\n </button>\r\n </div>\r\n\r\n {!disableClickOutside && (\r\n <button\r\n aria-hidden=\"true\"\r\n className=\"ui-modal-overlay-catcher\"\r\n onClick={handleClose}\r\n tabIndex={-1}\r\n />\r\n )}\r\n </div>\r\n </Portal>\r\n );\r\n}\r\n"],"names":["idCounter","nextId","prefix","Modal","open","onClose","title","description","labelledById","describedById","disableClickOutside","disableEsc","initialFocusRef","className","children","overlayRef","useRef","dialogRef","previouslyFocusedElementRef","internalTitleId","internalDescId","titleId","descId","handleClose","useCallback","useEffect","onKey","e","scrollLock","inertTargets","applyInertToSiblings","trapCleanup","trapFocus","clickOutsideCleanup","onClickOutside","removeInertFromSiblings","restoreFocus","jsx","Portal","jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Modal.js","sources":["../../../src/components/modal/Modal.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useEffect, useRef, useCallback, useState, useId } from 'react';\nimport { cn } from '../../utils';\nimport { \n trapFocus, \n onClickOutside, \n restoreFocus, \n scrollLock, \n Portal, \n applyInertToSiblings, \n removeInertFromSiblings \n} from '../../utils';\nimport './Modal.css';\n\n/* -------------------------------------------------------------------------- */\n/* Props */\n/* -------------------------------------------------------------------------- */\n\nexport interface ModalProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {\n open: boolean;\n onClose: () => void;\n title?: React.ReactNode;\n description?: React.ReactNode;\n \n labelledById?: string;\n describedById?: string;\n \n disableClickOutside?: boolean;\n disableEsc?: boolean;\n initialFocusRef?: React.RefObject<HTMLElement | null>;\n \n overlayClassName?: string;\n\n /** Hides the 'X' close button in the top right corner. */\n hideCloseButton?: boolean;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------------- */\n\nexport function Modal({\n open,\n onClose,\n title,\n description,\n labelledById,\n describedById,\n disableClickOutside = false,\n disableEsc = false,\n hideCloseButton = false,\n initialFocusRef,\n className,\n overlayClassName,\n children,\n ...props\n}: ModalProps) {\n const [isMounted, setIsMounted] = useState(open);\n const [isVisible, setIsVisible] = useState(false);\n\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const dialogRef = useRef<HTMLDivElement | null>(null);\n const previouslyFocusedElementRef = useRef<HTMLElement | null>(null);\n\n const baseId = useId();\n const titleId = labelledById || `${baseId}-title`;\n const descId = describedById || `${baseId}-desc`;\n\n const handleClose = useCallback(() => {\n onClose();\n }, [onClose]);\n\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout>;\n\n if (open) {\n setIsMounted(true);\n timer = setTimeout(() => setIsVisible(true), 10);\n } else {\n setIsVisible(false);\n timer = setTimeout(() => setIsMounted(false), 300);\n }\n\n return () => {\n if (timer) clearTimeout(timer);\n };\n }, [open]);\n\n useEffect(() => {\n if (!isVisible || disableEsc) return;\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n handleClose();\n }\n };\n\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [isVisible, disableEsc, handleClose]);\n\n useEffect(() => {\n if (!isVisible) return;\n\n previouslyFocusedElementRef.current = document.activeElement as HTMLElement;\n\n scrollLock.lock();\n\n const inertTargets = overlayRef.current\n ? applyInertToSiblings(overlayRef.current)\n : [];\n\n if (\n initialFocusRef?.current &&\n dialogRef.current?.contains(initialFocusRef.current)\n ) {\n initialFocusRef.current.focus();\n }\n\n const trapCleanup = dialogRef.current\n ? trapFocus(dialogRef.current)\n : undefined;\n\n let clickOutsideCleanup: (() => void) | undefined;\n if (!disableClickOutside && dialogRef.current) {\n clickOutsideCleanup = onClickOutside(dialogRef, handleClose);\n }\n\n return () => {\n clickOutsideCleanup?.();\n trapCleanup?.();\n scrollLock.unlock();\n removeInertFromSiblings(inertTargets);\n restoreFocus(previouslyFocusedElementRef.current);\n };\n }, [isVisible, disableClickOutside, handleClose, initialFocusRef]);\n\n if (!isMounted) return null;\n\n return (\n <Portal>\n <div \n ref={overlayRef} \n className={cn(\"nui-modal-overlay\", overlayClassName)} \n data-state={isVisible ? 'open' : 'closed'}\n aria-hidden=\"true\"\n >\n <div\n ref={dialogRef}\n className={cn(\"nui-modal-container\", className)}\n data-state={isVisible ? 'open' : 'closed'}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? titleId : undefined}\n aria-describedby={description ? descId : undefined}\n tabIndex={-1} \n onClick={(e) => e.stopPropagation()}\n {...props}\n >\n {(title || description) && (\n <div className=\"nui-modal__header\">\n {title && (\n <h2 id={titleId} className=\"nui-modal__title\">\n {title}\n </h2>\n )}\n {description && (\n <p id={descId} className=\"nui-modal__description\">\n {description}\n </p>\n )}\n </div>\n )}\n\n <div className=\"nui-modal__content\">\n {children}\n </div>\n\n {/* Conditionally render the close button */}\n {!hideCloseButton && (\n <button\n type=\"button\"\n aria-label=\"Close dialog\"\n className=\"nui-modal__close\"\n onClick={handleClose}\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n )}\n </div>\n </div>\n </Portal>\n );\n}"],"names":["Modal","open","onClose","title","description","labelledById","describedById","disableClickOutside","disableEsc","hideCloseButton","initialFocusRef","className","overlayClassName","children","props","isMounted","setIsMounted","useState","isVisible","setIsVisible","overlayRef","useRef","dialogRef","previouslyFocusedElementRef","baseId","useId","titleId","descId","handleClose","useCallback","useEffect","timer","onKey","e","scrollLock","inertTargets","applyInertToSiblings","trapCleanup","trapFocus","clickOutsideCleanup","onClickOutside","removeInertFromSiblings","restoreFocus","Portal","jsx","cn","jsxs"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),s=require("react");;/* empty css */const Z=require("../../utils/restorefocus/restoreFocus.cjs"),_=require("../../utils/onclickoutside/onClickOutside.cjs"),D=require("../../utils/cn/cn.cjs"),ee=require("../../utils/portal/portal.cjs");function M(l,j,I){const h=l.length;let m=j;for(let d=0;d<h;d++)if(m=(m+I+h)%h,!l[m].disabled)return m;return-1}const O=s.forwardRef(({options:l,value:j,defaultValue:I,onChange:h,placeholder:m="Select multiple...",disabled:d=!1,error:B=!1,name:L,id:K,className:$,maxTags:P=3,...V},w)=>{const R=j!==void 0,[W,z]=s.useState(I||[]),o=R?j:W,[c,y]=s.useState(!1),[u,f]=s.useState(()=>l.findIndex(e=>!e.disabled)),g=s.useRef({buffer:"",lastTime:0}),p=s.useRef(null),v=s.useRef(null),E=s.useRef(null),F=s.useId(),T=K??F,S=`${T}-listbox`,q=`${T}-label`,H=s.useCallback(e=>{p.current=e,typeof w=="function"?w(e):w&&(w.current=e)},[w]),[N,U]=s.useState({top:-9999,left:-9999,width:0}),x=s.useCallback(()=>{if(!p.current||!v.current)return;const e=p.current.getBoundingClientRect(),n=v.current.getBoundingClientRect(),t=window.scrollY,r=window.scrollX;let a=e.bottom+t+4;const C=e.left+r,k=e.width,b=16;e.bottom+n.height+4>document.documentElement.clientHeight-b&&(a=e.top+t-n.height-4,a<b+t&&(a=b+t)),U({top:a,left:C,width:k})},[]);s.useLayoutEffect(()=>{if(c)return x(),window.addEventListener("resize",x),window.addEventListener("scroll",x,!0),()=>{window.removeEventListener("resize",x),window.removeEventListener("scroll",x,!0)}},[c,x]);const X=s.useCallback(()=>{y(!1),Z.restoreFocus(p.current)},[]);s.useEffect(()=>c?_.onClickOutside([v,p],()=>y(!1)):void 0,[c]),s.useEffect(()=>{if(!c)return;const e=l.findIndex(t=>!t.disabled);f(e>=0?e:-1);const n=setTimeout(()=>v.current?.focus(),10);return()=>clearTimeout(n)},[c,l]),s.useEffect(()=>{c&&E.current&&E.current.scrollIntoView({block:"nearest"})},[u,c]);const A=s.useCallback(e=>{const t=o.includes(e)?o.filter(r=>r!==e):[...o,e];R||z(t),h?.(t),v.current?.focus()},[R,o,h]),Y=e=>{d||["ArrowDown","ArrowUp"," ","Enter"].includes(e.key)&&(e.preventDefault(),y(!0))},G=e=>{const n=e.key;if(n==="ArrowDown"){e.preventDefault();const t=M(l,u,1);t>=0&&f(t)}else if(n==="ArrowUp"){e.preventDefault();const t=M(l,u,-1);t>=0&&f(t)}else if(n==="Home"){e.preventDefault();const t=l.findIndex(r=>!r.disabled);t>=0&&f(t)}else if(n==="End"){e.preventDefault();const t=l.length-1-[...l].reverse().findIndex(r=>!r.disabled);t>=0&&f(t)}else if(n==="Enter"||n===" "){if(e.preventDefault(),u>=0){const t=l[u];t.disabled||A(t.value)}}else if(n==="Escape")e.preventDefault(),X();else if(n.length===1&&n.match(/\S/)){const t=Date.now();t-g.current.lastTime>700&&(g.current.buffer=""),g.current.buffer+=n.toLowerCase(),g.current.lastTime=t;const r=g.current.buffer,a=u>=0?u+1:0,C=l.length;for(let k=0;k<C;k++){const b=(a+k)%C,Q=String(l[b].label).toLowerCase();if(!l[b].disabled&&Q.startsWith(r)){f(b);break}}}},J=()=>o.length===0?i.jsx("span",{className:"nui-multiselect-placeholder",children:m}):o.length>P?i.jsxs("span",{className:"nui-multiselect-summary",children:[o.length," items selected"]}):i.jsx("div",{className:"nui-multiselect-tags",children:o.map(e=>{const n=l.find(t=>t.value===e)?.label??e;return i.jsx("span",{className:"nui-multiselect-tag",children:n},e)})});return i.jsxs("div",{className:D.cn("nui-multiselect-root",$),children:[L&&o.map(e=>i.jsx("input",{type:"hidden",name:L,value:e},e)),i.jsxs("button",{ref:H,id:q,type:"button",className:D.cn("nui-multiselect-trigger",B&&"error"),"aria-haspopup":"listbox","aria-expanded":c,"aria-controls":c?S:void 0,"aria-disabled":d||void 0,onClick:()=>!d&&y(e=>!e),onKeyDown:Y,disabled:d,...V,children:[i.jsx("div",{className:"nui-multiselect-value-container",children:J()}),i.jsx("svg",{className:"nui-multiselect-chevron",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:i.jsx("polyline",{points:"6 9 12 15 18 9"})})]}),c&&i.jsx(ee.Portal,{children:i.jsx("div",{id:S,ref:v,className:"nui-multiselect-listbox",role:"listbox","aria-multiselectable":"true","aria-labelledby":q,tabIndex:0,style:{top:N.top,left:N.left,width:N.width},onKeyDown:G,children:l.map((e,n)=>{const t=o.includes(e.value),r=u===n;return i.jsxs("div",{ref:r?E:null,id:`${S}-option-${n}`,role:"option","aria-selected":t,"aria-disabled":e.disabled||void 0,className:D.cn("nui-multiselect-option",r&&"active",t&&"selected",e.disabled&&"disabled"),tabIndex:-1,onMouseDown:a=>a.preventDefault(),onClick:()=>!e.disabled&&A(e.value),onMouseEnter:()=>!e.disabled&&f(n),children:[i.jsx("div",{className:D.cn("nui-multiselect-checkbox",t&&"checked"),"aria-hidden":"true",children:t&&i.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"3",strokeLinecap:"round",strokeLinejoin:"round",children:i.jsx("polyline",{points:"20 6 9 17 4 12"})})}),i.jsx("span",{className:"nui-multiselect-option-label",children:e.label})]},e.value)})})})]})});O.displayName="MultiSelect";exports.MultiSelect=O;
2
+ //# sourceMappingURL=MultiSelect.cjs.map