@nofinite/nui 1.1.2 → 2.0.1

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 +118 -107
  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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MultiSelect.cjs","sources":["../../../src/components/multiselect/MultiSelect.tsx"],"sourcesContent":["\"use client\";\n\nimport React, {\n useState,\n useRef,\n useEffect,\n useCallback,\n useLayoutEffect,\n KeyboardEvent,\n forwardRef,\n} from 'react';\nimport { cn } from '../../utils';\nimport { Portal, onClickOutside, restoreFocus } from '../../utils';\nimport './MultiSelect.css';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport type MultiSelectOption = {\n value: string;\n label: React.ReactNode;\n disabled?: boolean;\n};\n\nexport interface MultiSelectProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'value' | 'defaultValue' | 'onChange'> {\n /** Array of available options */\n options: MultiSelectOption[];\n /** Controlled state for selected values */\n value?: string[]; \n /** Uncontrolled initial state for selected values */\n defaultValue?: string[]; \n /** Callback fired when the selection changes */\n onChange?: (value: string[]) => void;\n /** Text displayed when no options are selected */\n placeholder?: string;\n /** Name attribute applied to hidden inputs for native form submission */\n name?: string; \n /** Toggles error styling */\n error?: boolean;\n /** Number of tags to render before collapsing into a summary string (e.g., \"3 selected\") */\n maxTags?: number; \n}\n\n/* Helper: find next enabled index given direction */\nfunction findNextEnabled(options: MultiSelectOption[], start: number, direction: 1 | -1) {\n const len = options.length;\n let i = start;\n for (let step = 0; step < len; step++) {\n i = (i + direction + len) % len;\n if (!options[i].disabled) return i;\n }\n return -1;\n}\n\n/* ============================================================\n * Component\n * ============================================================ */\n\n/**\n * MultiSelect Component\n * * A custom, WAI-ARIA compliant dropdown for selecting multiple options.\n * * Architecture Note: Unlike a standard Select, the dropdown list intentionally \n * remains open after a selection is made, allowing the user to quickly select \n * multiple items without repeatedly reopening the menu.\n */\nexport const MultiSelect = forwardRef<HTMLButtonElement, MultiSelectProps>(({\n options,\n value,\n defaultValue,\n onChange,\n placeholder = 'Select multiple...',\n disabled = false,\n error = false,\n name,\n id,\n className,\n maxTags = 3,\n ...props\n}, ref) => {\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<string[]>(defaultValue || []);\n const selectedValues = isControlled ? value : internalValue;\n\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState<number>(() => options.findIndex((o) => !o.disabled));\n\n // Used for keyboard typeahead navigation\n const typeaheadRef = useRef({ buffer: '', lastTime: 0 });\n \n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const listRef = useRef<HTMLDivElement | null>(null);\n const activeOptionRef = useRef<HTMLDivElement | null>(null);\n\n const reactId = React.useId();\n const baseId = id ?? reactId;\n const listboxId = `${baseId}-listbox`;\n const labelId = `${baseId}-label`;\n\n /* ----------------------------------------------------\n Ref Merging\n ---------------------------------------------------- */\n const setTriggerRef = useCallback((node: HTMLButtonElement | null) => {\n triggerRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }, [ref]);\n\n /* ----------------------------------------------------\n Smart Position & Width Sync\n ---------------------------------------------------- */\n const [coords, setCoords] = useState({ top: -9999, left: -9999, width: 0 });\n\n const updatePosition = useCallback(() => {\n if (!triggerRef.current || !listRef.current) return;\n\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const listRect = listRef.current.getBoundingClientRect();\n const scrollY = window.scrollY;\n const scrollX = window.scrollX;\n\n let top = triggerRect.bottom + scrollY + 4;\n const left = triggerRect.left + scrollX;\n const width = triggerRect.width; \n\n // Viewport Bottom Collision & Hard Top Clamp\n const padding = 16;\n if (triggerRect.bottom + listRect.height + 4 > document.documentElement.clientHeight - padding) {\n top = triggerRect.top + scrollY - listRect.height - 4; \n if (top < padding + scrollY) top = padding + scrollY; \n }\n\n setCoords({ top, left, width });\n }, []);\n\n useLayoutEffect(() => {\n if (!open) return;\n updatePosition();\n window.addEventListener('resize', updatePosition);\n window.addEventListener('scroll', updatePosition, true);\n return () => {\n window.removeEventListener('resize', updatePosition);\n window.removeEventListener('scroll', updatePosition, true);\n };\n }, [open, updatePosition]);\n\n /* ----------------------------------------------------\n Focus & Scroll Management\n ---------------------------------------------------- */\n const closeList = useCallback(() => {\n setOpen(false);\n restoreFocus(triggerRef.current);\n }, []);\n\n useEffect(() => {\n if (!open) return;\n const cleanup = onClickOutside([listRef, triggerRef], () => setOpen(false));\n return cleanup;\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n // Reset active index to first non-disabled item when opened\n const idx = options.findIndex((o) => !o.disabled);\n setActiveIndex(idx >= 0 ? idx : -1);\n \n // Defer focus slightly to ensure Portal has rendered\n const timeoutId = setTimeout(() => listRef.current?.focus(), 10);\n return () => clearTimeout(timeoutId);\n }, [open, options]);\n\n // Auto-scroll to active item\n useEffect(() => {\n if (open && activeOptionRef.current) {\n activeOptionRef.current.scrollIntoView({ block: 'nearest' });\n }\n }, [activeIndex, open]);\n\n /* ----------------------------------------------------\n Event Handlers\n ---------------------------------------------------- */\n const toggleOption = useCallback((optValue: string) => {\n const isSelected = selectedValues.includes(optValue);\n const nextValues = isSelected \n ? selectedValues.filter(v => v !== optValue) \n : [...selectedValues, optValue];\n\n if (!isControlled) setInternalValue(nextValues);\n onChange?.(nextValues);\n \n // WAI-ARIA Standard: Do not close the dropdown for Multi-Select!\n // Refocus the list so the user can keep navigating via keyboard.\n listRef.current?.focus();\n }, [isControlled, selectedValues, onChange]);\n\n const onTriggerKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {\n if (disabled) return;\n if (['ArrowDown', 'ArrowUp', ' ', 'Enter'].includes(e.key)) {\n e.preventDefault();\n setOpen(true);\n }\n };\n\n const onListKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n const key = e.key;\n if (key === 'ArrowDown') {\n e.preventDefault();\n const next = findNextEnabled(options, activeIndex, 1);\n if (next >= 0) setActiveIndex(next);\n } else if (key === 'ArrowUp') {\n e.preventDefault();\n const prev = findNextEnabled(options, activeIndex, -1);\n if (prev >= 0) setActiveIndex(prev);\n } else if (key === 'Home') {\n e.preventDefault();\n const first = options.findIndex((o) => !o.disabled);\n if (first >= 0) setActiveIndex(first);\n } else if (key === 'End') {\n e.preventDefault();\n const last = options.length - 1 - [...options].reverse().findIndex((o) => !o.disabled);\n if (last >= 0) setActiveIndex(last);\n } else if (key === 'Enter' || key === ' ') {\n e.preventDefault();\n if (activeIndex >= 0) {\n const opt = options[activeIndex];\n if (!opt.disabled) toggleOption(opt.value);\n }\n } else if (key === 'Escape') {\n e.preventDefault();\n closeList();\n } else if (key.length === 1 && key.match(/\\S/)) {\n // Typeahead logic\n const now = Date.now();\n if (now - typeaheadRef.current.lastTime > 700) typeaheadRef.current.buffer = '';\n typeaheadRef.current.buffer += key.toLowerCase();\n typeaheadRef.current.lastTime = now;\n\n const buf = typeaheadRef.current.buffer;\n const start = activeIndex >= 0 ? activeIndex + 1 : 0;\n const len = options.length;\n for (let i = 0; i < len; i++) {\n const idx = (start + i) % len;\n const lab = String(options[idx].label).toLowerCase();\n if (!options[idx].disabled && lab.startsWith(buf)) {\n setActiveIndex(idx);\n break;\n }\n }\n }\n };\n\n /* ----------------------------------------------------\n Trigger Rendering Logic\n ---------------------------------------------------- */\n const renderTriggerContent = () => {\n if (selectedValues.length === 0) {\n return <span className=\"nui-multiselect-placeholder\">{placeholder}</span>;\n }\n\n if (selectedValues.length > maxTags) {\n return (\n <span className=\"nui-multiselect-summary\">\n {selectedValues.length} items selected\n </span>\n );\n }\n\n // Render individual tags\n return (\n <div className=\"nui-multiselect-tags\">\n {selectedValues.map(val => {\n const label = options.find(o => o.value === val)?.label ?? val;\n return (\n <span key={val} className=\"nui-multiselect-tag\">\n {label}\n </span>\n );\n })}\n </div>\n );\n };\n\n /* ----------------------------------------------------\n Render\n ---------------------------------------------------- */\n return (\n <div className={cn(\"nui-multiselect-root\", className)}>\n \n {/* Hidden inputs for native form submission */}\n {name && selectedValues.map((val) => (\n <input key={val} type=\"hidden\" name={name} value={val} />\n ))}\n\n <button\n ref={setTriggerRef}\n id={labelId}\n type=\"button\"\n className={cn(\"nui-multiselect-trigger\", error && \"error\")}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={open ? listboxId : undefined}\n aria-disabled={disabled || undefined}\n onClick={() => !disabled && setOpen((s) => !s)}\n onKeyDown={onTriggerKeyDown}\n disabled={disabled}\n {...props}\n >\n <div className=\"nui-multiselect-value-container\">\n {renderTriggerContent()}\n </div>\n <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\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </button>\n\n {open && (\n <Portal>\n <div\n id={listboxId}\n ref={listRef}\n className=\"nui-multiselect-listbox\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n aria-labelledby={labelId}\n tabIndex={0}\n style={{ top: coords.top, left: coords.left, width: coords.width }}\n onKeyDown={onListKeyDown}\n >\n {options.map((opt, i) => {\n const isSelected = selectedValues.includes(opt.value);\n const isActive = activeIndex === i;\n \n return (\n <div\n key={opt.value}\n ref={isActive ? activeOptionRef : null}\n id={`${listboxId}-option-${i}`}\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={opt.disabled || undefined}\n className={cn(\n \"nui-multiselect-option\",\n isActive && \"active\",\n isSelected && \"selected\",\n opt.disabled && \"disabled\"\n )}\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()} \n onClick={() => !opt.disabled && toggleOption(opt.value)}\n onMouseEnter={() => !opt.disabled && setActiveIndex(i)}\n >\n \n {/* Custom Checkbox UI */}\n <div className={cn(\"nui-multiselect-checkbox\", isSelected && \"checked\")} aria-hidden=\"true\">\n {isSelected && (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n )}\n </div>\n\n <span className=\"nui-multiselect-option-label\">{opt.label}</span>\n </div>\n );\n })}\n </div>\n </Portal>\n )}\n </div>\n );\n});\nMultiSelect.displayName = 'MultiSelect';"],"names":["findNextEnabled","options","start","direction","len","i","step","MultiSelect","forwardRef","value","defaultValue","onChange","placeholder","disabled","error","name","id","className","maxTags","props","ref","isControlled","internalValue","setInternalValue","useState","selectedValues","open","setOpen","activeIndex","setActiveIndex","o","typeaheadRef","useRef","triggerRef","listRef","activeOptionRef","reactId","React","baseId","listboxId","labelId","setTriggerRef","useCallback","node","coords","setCoords","updatePosition","triggerRect","listRect","scrollY","scrollX","top","left","width","padding","useLayoutEffect","closeList","restoreFocus","useEffect","onClickOutside","idx","timeoutId","toggleOption","optValue","nextValues","v","onTriggerKeyDown","onListKeyDown","key","next","prev","first","last","opt","now","buf","lab","renderTriggerContent","jsx","jsxs","val","label","cn","s","Portal","isSelected","isActive","e"],"mappings":"gXA6CA,SAASA,EAAgBC,EAA8BC,EAAeC,EAAmB,CACvF,MAAMC,EAAMH,EAAQ,OACpB,IAAII,EAAIH,EACR,QAASI,EAAO,EAAGA,EAAOF,EAAKE,IAE7B,GADAD,GAAKA,EAAIF,EAAYC,GAAOA,EACxB,CAACH,EAAQI,CAAC,EAAE,SAAU,OAAOA,EAEnC,MAAO,EACT,CAaO,MAAME,EAAcC,EAAAA,WAAgD,CAAC,CAC1E,QAAAP,EACA,MAAAQ,EACA,aAAAC,EACA,SAAAC,EACA,YAAAC,EAAc,qBACd,SAAAC,EAAW,GACX,MAAAC,EAAQ,GACR,KAAAC,EACA,GAAAC,EACA,UAAAC,EACA,QAAAC,EAAU,EACV,GAAGC,CACL,EAAGC,IAAQ,CACT,MAAMC,EAAeZ,IAAU,OACzB,CAACa,EAAeC,CAAgB,EAAIC,EAAAA,SAAmBd,GAAgB,CAAA,CAAE,EACzEe,EAAiBJ,EAAeZ,EAAQa,EAExC,CAACI,EAAMC,CAAO,EAAIH,EAAAA,SAAS,EAAK,EAChC,CAACI,EAAaC,CAAc,EAAIL,EAAAA,SAAiB,IAAMvB,EAAQ,UAAW6B,GAAM,CAACA,EAAE,QAAQ,CAAC,EAG5FC,EAAeC,EAAAA,OAAO,CAAE,OAAQ,GAAI,SAAU,EAAG,EAEjDC,EAAaD,EAAAA,OAAiC,IAAI,EAClDE,EAAUF,EAAAA,OAA8B,IAAI,EAC5CG,EAAkBH,EAAAA,OAA8B,IAAI,EAEpDI,EAAUC,EAAM,MAAA,EAChBC,EAAStB,GAAMoB,EACfG,EAAY,GAAGD,CAAM,WACrBE,EAAU,GAAGF,CAAM,SAKnBG,EAAgBC,cAAaC,GAAmC,CACpEV,EAAW,QAAUU,EACjB,OAAOvB,GAAQ,WAAYA,EAAIuB,CAAI,EAC9BvB,MAAS,QAAUuB,EAC9B,EAAG,CAACvB,CAAG,CAAC,EAKF,CAACwB,EAAQC,CAAS,EAAIrB,EAAAA,SAAS,CAAE,IAAK,MAAO,KAAM,MAAO,MAAO,CAAA,CAAG,EAEpEsB,EAAiBJ,EAAAA,YAAY,IAAM,CACvC,GAAI,CAACT,EAAW,SAAW,CAACC,EAAQ,QAAS,OAE7C,MAAMa,EAAcd,EAAW,QAAQ,sBAAA,EACjCe,EAAWd,EAAQ,QAAQ,sBAAA,EAC3Be,EAAU,OAAO,QACjBC,EAAU,OAAO,QAEvB,IAAIC,EAAMJ,EAAY,OAASE,EAAU,EACzC,MAAMG,EAAOL,EAAY,KAAOG,EAC1BG,EAAQN,EAAY,MAGpBO,EAAU,GACZP,EAAY,OAASC,EAAS,OAAS,EAAI,SAAS,gBAAgB,aAAeM,IACrFH,EAAMJ,EAAY,IAAME,EAAUD,EAAS,OAAS,EAChDG,EAAMG,EAAUL,IAASE,EAAMG,EAAUL,IAG/CJ,EAAU,CAAE,IAAAM,EAAK,KAAAC,EAAM,MAAAC,CAAA,CAAO,CAChC,EAAG,CAAA,CAAE,EAELE,EAAAA,gBAAgB,IAAM,CACpB,GAAK7B,EACL,OAAAoB,EAAA,EACA,OAAO,iBAAiB,SAAUA,CAAc,EAChD,OAAO,iBAAiB,SAAUA,EAAgB,EAAI,EAC/C,IAAM,CACX,OAAO,oBAAoB,SAAUA,CAAc,EACnD,OAAO,oBAAoB,SAAUA,EAAgB,EAAI,CAC3D,CACF,EAAG,CAACpB,EAAMoB,CAAc,CAAC,EAKzB,MAAMU,EAAYd,EAAAA,YAAY,IAAM,CAClCf,EAAQ,EAAK,EACb8B,EAAAA,aAAaxB,EAAW,OAAO,CACjC,EAAG,CAAA,CAAE,EAELyB,EAAAA,UAAU,IACHhC,EACWiC,EAAAA,eAAe,CAACzB,EAASD,CAAU,EAAG,IAAMN,EAAQ,EAAK,CAAC,EAD/D,OAGV,CAACD,CAAI,CAAC,EAETgC,EAAAA,UAAU,IAAM,CACd,GAAI,CAAChC,EAAM,OAEX,MAAMkC,EAAM3D,EAAQ,UAAW6B,GAAM,CAACA,EAAE,QAAQ,EAChDD,EAAe+B,GAAO,EAAIA,EAAM,EAAE,EAGlC,MAAMC,EAAY,WAAW,IAAM3B,EAAQ,SAAS,MAAA,EAAS,EAAE,EAC/D,MAAO,IAAM,aAAa2B,CAAS,CACrC,EAAG,CAACnC,EAAMzB,CAAO,CAAC,EAGlByD,EAAAA,UAAU,IAAM,CACVhC,GAAQS,EAAgB,SAC1BA,EAAgB,QAAQ,eAAe,CAAE,MAAO,UAAW,CAE/D,EAAG,CAACP,EAAaF,CAAI,CAAC,EAKtB,MAAMoC,EAAepB,cAAaqB,GAAqB,CAErD,MAAMC,EADavC,EAAe,SAASsC,CAAQ,EAE/CtC,EAAe,OAAOwC,GAAKA,IAAMF,CAAQ,EACzC,CAAC,GAAGtC,EAAgBsC,CAAQ,EAE3B1C,GAAcE,EAAiByC,CAAU,EAC9CrD,IAAWqD,CAAU,EAIrB9B,EAAQ,SAAS,MAAA,CACnB,EAAG,CAACb,EAAcI,EAAgBd,CAAQ,CAAC,EAErCuD,EAAoB,GAAwC,CAC5DrD,GACA,CAAC,YAAa,UAAW,IAAK,OAAO,EAAE,SAAS,EAAE,GAAG,IACvD,EAAE,eAAA,EACFc,EAAQ,EAAI,EAEhB,EAEMwC,EAAiB,GAAqC,CAC1D,MAAMC,EAAM,EAAE,IACd,GAAIA,IAAQ,YAAa,CACvB,EAAE,eAAA,EACF,MAAMC,EAAOrE,EAAgBC,EAAS2B,EAAa,CAAC,EAChDyC,GAAQ,GAAGxC,EAAewC,CAAI,CACpC,SAAWD,IAAQ,UAAW,CAC5B,EAAE,eAAA,EACF,MAAME,EAAOtE,EAAgBC,EAAS2B,EAAa,EAAE,EACjD0C,GAAQ,GAAGzC,EAAeyC,CAAI,CACpC,SAAWF,IAAQ,OAAQ,CACzB,EAAE,eAAA,EACF,MAAMG,EAAQtE,EAAQ,UAAW6B,GAAM,CAACA,EAAE,QAAQ,EAC9CyC,GAAS,GAAG1C,EAAe0C,CAAK,CACtC,SAAWH,IAAQ,MAAO,CACxB,EAAE,eAAA,EACF,MAAMI,EAAOvE,EAAQ,OAAS,EAAI,CAAC,GAAGA,CAAO,EAAE,QAAA,EAAU,UAAW6B,GAAM,CAACA,EAAE,QAAQ,EACjF0C,GAAQ,GAAG3C,EAAe2C,CAAI,CACpC,SAAWJ,IAAQ,SAAWA,IAAQ,KAEpC,GADA,EAAE,eAAA,EACExC,GAAe,EAAG,CACpB,MAAM6C,EAAMxE,EAAQ2B,CAAW,EAC1B6C,EAAI,UAAUX,EAAaW,EAAI,KAAK,CAC3C,UACSL,IAAQ,SACjB,EAAE,eAAA,EACFZ,EAAA,UACSY,EAAI,SAAW,GAAKA,EAAI,MAAM,IAAI,EAAG,CAE9C,MAAMM,EAAM,KAAK,IAAA,EACbA,EAAM3C,EAAa,QAAQ,SAAW,MAAKA,EAAa,QAAQ,OAAS,IAC7EA,EAAa,QAAQ,QAAUqC,EAAI,YAAA,EACnCrC,EAAa,QAAQ,SAAW2C,EAEhC,MAAMC,EAAM5C,EAAa,QAAQ,OAC3B7B,EAAQ0B,GAAe,EAAIA,EAAc,EAAI,EAC7CxB,EAAMH,EAAQ,OACpB,QAASI,EAAI,EAAGA,EAAID,EAAKC,IAAK,CAC5B,MAAMuD,GAAO1D,EAAQG,GAAKD,EACpBwE,EAAM,OAAO3E,EAAQ2D,CAAG,EAAE,KAAK,EAAE,YAAA,EACvC,GAAI,CAAC3D,EAAQ2D,CAAG,EAAE,UAAYgB,EAAI,WAAWD,CAAG,EAAG,CACjD9C,EAAe+B,CAAG,EAClB,KACF,CACF,CACF,CACF,EAKMiB,EAAuB,IACvBpD,EAAe,SAAW,EACrBqD,EAAAA,IAAC,OAAA,CAAK,UAAU,8BAA+B,SAAAlE,EAAY,EAGhEa,EAAe,OAASP,EAExB6D,EAAAA,KAAC,OAAA,CAAK,UAAU,0BACb,SAAA,CAAAtD,EAAe,OAAO,iBAAA,EACzB,QAMD,MAAA,CAAI,UAAU,uBACZ,SAAAA,EAAe,IAAIuD,GAAO,CACzB,MAAMC,EAAQhF,EAAQ,KAAK6B,GAAKA,EAAE,QAAUkD,CAAG,GAAG,OAASA,EAC3D,OACEF,EAAAA,IAAC,OAAA,CAAe,UAAU,sBACvB,YADQE,CAEX,CAEJ,CAAC,CAAA,CACH,EAOJ,cACG,MAAA,CAAI,UAAWE,EAAAA,GAAG,uBAAwBjE,CAAS,EAGjD,SAAA,CAAAF,GAAQU,EAAe,IAAKuD,GAC3BF,EAAAA,IAAC,QAAA,CAAgB,KAAK,SAAS,KAAA/D,EAAY,MAAOiE,CAAA,EAAtCA,CAA2C,CACxD,EAEDD,EAAAA,KAAC,SAAA,CACC,IAAKtC,EACL,GAAID,EACJ,KAAK,SACL,UAAW0C,EAAAA,GAAG,0BAA2BpE,GAAS,OAAO,EACzD,gBAAc,UACd,gBAAeY,EACf,gBAAeA,EAAOa,EAAY,OAClC,gBAAe1B,GAAY,OAC3B,QAAS,IAAM,CAACA,GAAYc,EAASwD,GAAM,CAACA,CAAC,EAC7C,UAAWjB,EACX,SAAArD,EACC,GAAGM,EAEJ,SAAA,CAAA2D,EAAAA,IAAC,MAAA,CAAI,UAAU,kCACZ,SAAAD,EAAA,EACH,EACAC,EAAAA,IAAC,MAAA,CAAI,UAAU,0BAA0B,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,OAAO,eAAe,YAAY,IAAI,cAAc,QAAQ,eAAe,QAAQ,cAAY,OAC7L,SAAAA,EAAAA,IAAC,WAAA,CAAS,OAAO,gBAAA,CAAiB,CAAA,CACpC,CAAA,CAAA,CAAA,EAGDpD,SACE0D,UAAA,CACC,SAAAN,EAAAA,IAAC,MAAA,CACC,GAAIvC,EACJ,IAAKL,EACL,UAAU,0BACV,KAAK,UACL,uBAAqB,OACrB,kBAAiBM,EACjB,SAAU,EACV,MAAO,CAAE,IAAKI,EAAO,IAAK,KAAMA,EAAO,KAAM,MAAOA,EAAO,KAAA,EAC3D,UAAWuB,EAEV,SAAAlE,EAAQ,IAAI,CAACwE,EAAKpE,IAAM,CACvB,MAAMgF,EAAa5D,EAAe,SAASgD,EAAI,KAAK,EAC9Ca,EAAW1D,IAAgBvB,EAEjC,OACE0E,EAAAA,KAAC,MAAA,CAEC,IAAKO,EAAWnD,EAAkB,KAClC,GAAI,GAAGI,CAAS,WAAWlC,CAAC,GAC5B,KAAK,SACL,gBAAegF,EACf,gBAAeZ,EAAI,UAAY,OAC/B,UAAWS,EAAAA,GACT,yBACAI,GAAY,SACZD,GAAc,WACdZ,EAAI,UAAY,UAAA,EAElB,SAAU,GACV,YAAcc,GAAMA,EAAE,eAAA,EACtB,QAAS,IAAM,CAACd,EAAI,UAAYX,EAAaW,EAAI,KAAK,EACtD,aAAc,IAAM,CAACA,EAAI,UAAY5C,EAAexB,CAAC,EAIrD,SAAA,CAAAyE,MAAC,MAAA,CAAI,UAAWI,EAAAA,GAAG,2BAA4BG,GAAc,SAAS,EAAG,cAAY,OAClF,SAAAA,GACCP,EAAAA,IAAC,MAAA,CAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,OAAO,eAAe,YAAY,IAAI,cAAc,QAAQ,eAAe,QACrI,SAAAA,EAAAA,IAAC,WAAA,CAAS,OAAO,gBAAA,CAAiB,EACpC,EAEJ,EAEAA,EAAAA,IAAC,OAAA,CAAK,UAAU,+BAAgC,WAAI,KAAA,CAAM,CAAA,CAAA,EA3BrDL,EAAI,KAAA,CA8Bf,CAAC,CAAA,CAAA,CACH,CACF,CAAA,EAEJ,CAEJ,CAAC,EACDlE,EAAY,YAAc"}
@@ -0,0 +1,176 @@
1
+ import { jsxs as I, jsx as l } from "react/jsx-runtime";
2
+ import te, { forwardRef as ne, useState as N, useRef as E, useCallback as L, useLayoutEffect as ie, useEffect as B } from "react";
3
+ /* empty css */
4
+ import { restoreFocus as le } from "../../utils/restorefocus/restoreFocus.js";
5
+ import { onClickOutside as re } from "../../utils/onclickoutside/onClickOutside.js";
6
+ import { cn as C } from "../../utils/cn/cn.js";
7
+ import { Portal as se } from "../../utils/portal/portal.js";
8
+ function V(i, k, R) {
9
+ const m = i.length;
10
+ let h = k;
11
+ for (let d = 0; d < m; d++)
12
+ if (h = (h + R + m) % m, !i[h].disabled) return h;
13
+ return -1;
14
+ }
15
+ const ce = ne(({
16
+ options: i,
17
+ value: k,
18
+ defaultValue: R,
19
+ onChange: m,
20
+ placeholder: h = "Select multiple...",
21
+ disabled: d = !1,
22
+ error: W = !1,
23
+ name: K,
24
+ id: z,
25
+ className: H,
26
+ maxTags: P = 3,
27
+ ...U
28
+ }, v) => {
29
+ const S = k !== void 0, [X, Y] = N(R || []), c = S ? k : X, [s, y] = N(!1), [o, u] = N(() => i.findIndex((e) => !e.disabled)), w = E({ buffer: "", lastTime: 0 }), g = E(null), b = E(null), T = E(null), F = te.useId(), M = z ?? F, A = `${M}-listbox`, O = `${M}-label`, q = L((e) => {
30
+ g.current = e, typeof v == "function" ? v(e) : v && (v.current = e);
31
+ }, [v]), [j, G] = N({ top: -9999, left: -9999, width: 0 }), p = L(() => {
32
+ if (!g.current || !b.current) return;
33
+ const e = g.current.getBoundingClientRect(), n = b.current.getBoundingClientRect(), t = window.scrollY, r = window.scrollX;
34
+ let a = e.bottom + t + 4;
35
+ const D = e.left + r, x = e.width, f = 16;
36
+ e.bottom + n.height + 4 > document.documentElement.clientHeight - f && (a = e.top + t - n.height - 4, a < f + t && (a = f + t)), G({ top: a, left: D, width: x });
37
+ }, []);
38
+ ie(() => {
39
+ if (s)
40
+ return p(), window.addEventListener("resize", p), window.addEventListener("scroll", p, !0), () => {
41
+ window.removeEventListener("resize", p), window.removeEventListener("scroll", p, !0);
42
+ };
43
+ }, [s, p]);
44
+ const J = L(() => {
45
+ y(!1), le(g.current);
46
+ }, []);
47
+ B(() => s ? re([b, g], () => y(!1)) : void 0, [s]), B(() => {
48
+ if (!s) return;
49
+ const e = i.findIndex((t) => !t.disabled);
50
+ u(e >= 0 ? e : -1);
51
+ const n = setTimeout(() => b.current?.focus(), 10);
52
+ return () => clearTimeout(n);
53
+ }, [s, i]), B(() => {
54
+ s && T.current && T.current.scrollIntoView({ block: "nearest" });
55
+ }, [o, s]);
56
+ const $ = L((e) => {
57
+ const t = c.includes(e) ? c.filter((r) => r !== e) : [...c, e];
58
+ S || Y(t), m?.(t), b.current?.focus();
59
+ }, [S, c, m]), Q = (e) => {
60
+ d || ["ArrowDown", "ArrowUp", " ", "Enter"].includes(e.key) && (e.preventDefault(), y(!0));
61
+ }, Z = (e) => {
62
+ const n = e.key;
63
+ if (n === "ArrowDown") {
64
+ e.preventDefault();
65
+ const t = V(i, o, 1);
66
+ t >= 0 && u(t);
67
+ } else if (n === "ArrowUp") {
68
+ e.preventDefault();
69
+ const t = V(i, o, -1);
70
+ t >= 0 && u(t);
71
+ } else if (n === "Home") {
72
+ e.preventDefault();
73
+ const t = i.findIndex((r) => !r.disabled);
74
+ t >= 0 && u(t);
75
+ } else if (n === "End") {
76
+ e.preventDefault();
77
+ const t = i.length - 1 - [...i].reverse().findIndex((r) => !r.disabled);
78
+ t >= 0 && u(t);
79
+ } else if (n === "Enter" || n === " ") {
80
+ if (e.preventDefault(), o >= 0) {
81
+ const t = i[o];
82
+ t.disabled || $(t.value);
83
+ }
84
+ } else if (n === "Escape")
85
+ e.preventDefault(), J();
86
+ else if (n.length === 1 && n.match(/\S/)) {
87
+ const t = Date.now();
88
+ t - w.current.lastTime > 700 && (w.current.buffer = ""), w.current.buffer += n.toLowerCase(), w.current.lastTime = t;
89
+ const r = w.current.buffer, a = o >= 0 ? o + 1 : 0, D = i.length;
90
+ for (let x = 0; x < D; x++) {
91
+ const f = (a + x) % D, ee = String(i[f].label).toLowerCase();
92
+ if (!i[f].disabled && ee.startsWith(r)) {
93
+ u(f);
94
+ break;
95
+ }
96
+ }
97
+ }
98
+ }, _ = () => c.length === 0 ? /* @__PURE__ */ l("span", { className: "nui-multiselect-placeholder", children: h }) : c.length > P ? /* @__PURE__ */ I("span", { className: "nui-multiselect-summary", children: [
99
+ c.length,
100
+ " items selected"
101
+ ] }) : /* @__PURE__ */ l("div", { className: "nui-multiselect-tags", children: c.map((e) => {
102
+ const n = i.find((t) => t.value === e)?.label ?? e;
103
+ return /* @__PURE__ */ l("span", { className: "nui-multiselect-tag", children: n }, e);
104
+ }) });
105
+ return /* @__PURE__ */ I("div", { className: C("nui-multiselect-root", H), children: [
106
+ K && c.map((e) => /* @__PURE__ */ l("input", { type: "hidden", name: K, value: e }, e)),
107
+ /* @__PURE__ */ I(
108
+ "button",
109
+ {
110
+ ref: q,
111
+ id: O,
112
+ type: "button",
113
+ className: C("nui-multiselect-trigger", W && "error"),
114
+ "aria-haspopup": "listbox",
115
+ "aria-expanded": s,
116
+ "aria-controls": s ? A : void 0,
117
+ "aria-disabled": d || void 0,
118
+ onClick: () => !d && y((e) => !e),
119
+ onKeyDown: Q,
120
+ disabled: d,
121
+ ...U,
122
+ children: [
123
+ /* @__PURE__ */ l("div", { className: "nui-multiselect-value-container", children: _() }),
124
+ /* @__PURE__ */ l("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: /* @__PURE__ */ l("polyline", { points: "6 9 12 15 18 9" }) })
125
+ ]
126
+ }
127
+ ),
128
+ s && /* @__PURE__ */ l(se, { children: /* @__PURE__ */ l(
129
+ "div",
130
+ {
131
+ id: A,
132
+ ref: b,
133
+ className: "nui-multiselect-listbox",
134
+ role: "listbox",
135
+ "aria-multiselectable": "true",
136
+ "aria-labelledby": O,
137
+ tabIndex: 0,
138
+ style: { top: j.top, left: j.left, width: j.width },
139
+ onKeyDown: Z,
140
+ children: i.map((e, n) => {
141
+ const t = c.includes(e.value), r = o === n;
142
+ return /* @__PURE__ */ I(
143
+ "div",
144
+ {
145
+ ref: r ? T : null,
146
+ id: `${A}-option-${n}`,
147
+ role: "option",
148
+ "aria-selected": t,
149
+ "aria-disabled": e.disabled || void 0,
150
+ className: C(
151
+ "nui-multiselect-option",
152
+ r && "active",
153
+ t && "selected",
154
+ e.disabled && "disabled"
155
+ ),
156
+ tabIndex: -1,
157
+ onMouseDown: (a) => a.preventDefault(),
158
+ onClick: () => !e.disabled && $(e.value),
159
+ onMouseEnter: () => !e.disabled && u(n),
160
+ children: [
161
+ /* @__PURE__ */ l("div", { className: C("nui-multiselect-checkbox", t && "checked"), "aria-hidden": "true", children: t && /* @__PURE__ */ l("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ l("polyline", { points: "20 6 9 17 4 12" }) }) }),
162
+ /* @__PURE__ */ l("span", { className: "nui-multiselect-option-label", children: e.label })
163
+ ]
164
+ },
165
+ e.value
166
+ );
167
+ })
168
+ }
169
+ ) })
170
+ ] });
171
+ });
172
+ ce.displayName = "MultiSelect";
173
+ export {
174
+ ce as MultiSelect
175
+ };
176
+ //# sourceMappingURL=MultiSelect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MultiSelect.js","sources":["../../../src/components/multiselect/MultiSelect.tsx"],"sourcesContent":["\"use client\";\n\nimport React, {\n useState,\n useRef,\n useEffect,\n useCallback,\n useLayoutEffect,\n KeyboardEvent,\n forwardRef,\n} from 'react';\nimport { cn } from '../../utils';\nimport { Portal, onClickOutside, restoreFocus } from '../../utils';\nimport './MultiSelect.css';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport type MultiSelectOption = {\n value: string;\n label: React.ReactNode;\n disabled?: boolean;\n};\n\nexport interface MultiSelectProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'value' | 'defaultValue' | 'onChange'> {\n /** Array of available options */\n options: MultiSelectOption[];\n /** Controlled state for selected values */\n value?: string[]; \n /** Uncontrolled initial state for selected values */\n defaultValue?: string[]; \n /** Callback fired when the selection changes */\n onChange?: (value: string[]) => void;\n /** Text displayed when no options are selected */\n placeholder?: string;\n /** Name attribute applied to hidden inputs for native form submission */\n name?: string; \n /** Toggles error styling */\n error?: boolean;\n /** Number of tags to render before collapsing into a summary string (e.g., \"3 selected\") */\n maxTags?: number; \n}\n\n/* Helper: find next enabled index given direction */\nfunction findNextEnabled(options: MultiSelectOption[], start: number, direction: 1 | -1) {\n const len = options.length;\n let i = start;\n for (let step = 0; step < len; step++) {\n i = (i + direction + len) % len;\n if (!options[i].disabled) return i;\n }\n return -1;\n}\n\n/* ============================================================\n * Component\n * ============================================================ */\n\n/**\n * MultiSelect Component\n * * A custom, WAI-ARIA compliant dropdown for selecting multiple options.\n * * Architecture Note: Unlike a standard Select, the dropdown list intentionally \n * remains open after a selection is made, allowing the user to quickly select \n * multiple items without repeatedly reopening the menu.\n */\nexport const MultiSelect = forwardRef<HTMLButtonElement, MultiSelectProps>(({\n options,\n value,\n defaultValue,\n onChange,\n placeholder = 'Select multiple...',\n disabled = false,\n error = false,\n name,\n id,\n className,\n maxTags = 3,\n ...props\n}, ref) => {\n const isControlled = value !== undefined;\n const [internalValue, setInternalValue] = useState<string[]>(defaultValue || []);\n const selectedValues = isControlled ? value : internalValue;\n\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState<number>(() => options.findIndex((o) => !o.disabled));\n\n // Used for keyboard typeahead navigation\n const typeaheadRef = useRef({ buffer: '', lastTime: 0 });\n \n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const listRef = useRef<HTMLDivElement | null>(null);\n const activeOptionRef = useRef<HTMLDivElement | null>(null);\n\n const reactId = React.useId();\n const baseId = id ?? reactId;\n const listboxId = `${baseId}-listbox`;\n const labelId = `${baseId}-label`;\n\n /* ----------------------------------------------------\n Ref Merging\n ---------------------------------------------------- */\n const setTriggerRef = useCallback((node: HTMLButtonElement | null) => {\n triggerRef.current = node;\n if (typeof ref === 'function') ref(node);\n else if (ref) ref.current = node;\n }, [ref]);\n\n /* ----------------------------------------------------\n Smart Position & Width Sync\n ---------------------------------------------------- */\n const [coords, setCoords] = useState({ top: -9999, left: -9999, width: 0 });\n\n const updatePosition = useCallback(() => {\n if (!triggerRef.current || !listRef.current) return;\n\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const listRect = listRef.current.getBoundingClientRect();\n const scrollY = window.scrollY;\n const scrollX = window.scrollX;\n\n let top = triggerRect.bottom + scrollY + 4;\n const left = triggerRect.left + scrollX;\n const width = triggerRect.width; \n\n // Viewport Bottom Collision & Hard Top Clamp\n const padding = 16;\n if (triggerRect.bottom + listRect.height + 4 > document.documentElement.clientHeight - padding) {\n top = triggerRect.top + scrollY - listRect.height - 4; \n if (top < padding + scrollY) top = padding + scrollY; \n }\n\n setCoords({ top, left, width });\n }, []);\n\n useLayoutEffect(() => {\n if (!open) return;\n updatePosition();\n window.addEventListener('resize', updatePosition);\n window.addEventListener('scroll', updatePosition, true);\n return () => {\n window.removeEventListener('resize', updatePosition);\n window.removeEventListener('scroll', updatePosition, true);\n };\n }, [open, updatePosition]);\n\n /* ----------------------------------------------------\n Focus & Scroll Management\n ---------------------------------------------------- */\n const closeList = useCallback(() => {\n setOpen(false);\n restoreFocus(triggerRef.current);\n }, []);\n\n useEffect(() => {\n if (!open) return;\n const cleanup = onClickOutside([listRef, triggerRef], () => setOpen(false));\n return cleanup;\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n // Reset active index to first non-disabled item when opened\n const idx = options.findIndex((o) => !o.disabled);\n setActiveIndex(idx >= 0 ? idx : -1);\n \n // Defer focus slightly to ensure Portal has rendered\n const timeoutId = setTimeout(() => listRef.current?.focus(), 10);\n return () => clearTimeout(timeoutId);\n }, [open, options]);\n\n // Auto-scroll to active item\n useEffect(() => {\n if (open && activeOptionRef.current) {\n activeOptionRef.current.scrollIntoView({ block: 'nearest' });\n }\n }, [activeIndex, open]);\n\n /* ----------------------------------------------------\n Event Handlers\n ---------------------------------------------------- */\n const toggleOption = useCallback((optValue: string) => {\n const isSelected = selectedValues.includes(optValue);\n const nextValues = isSelected \n ? selectedValues.filter(v => v !== optValue) \n : [...selectedValues, optValue];\n\n if (!isControlled) setInternalValue(nextValues);\n onChange?.(nextValues);\n \n // WAI-ARIA Standard: Do not close the dropdown for Multi-Select!\n // Refocus the list so the user can keep navigating via keyboard.\n listRef.current?.focus();\n }, [isControlled, selectedValues, onChange]);\n\n const onTriggerKeyDown = (e: KeyboardEvent<HTMLButtonElement>) => {\n if (disabled) return;\n if (['ArrowDown', 'ArrowUp', ' ', 'Enter'].includes(e.key)) {\n e.preventDefault();\n setOpen(true);\n }\n };\n\n const onListKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {\n const key = e.key;\n if (key === 'ArrowDown') {\n e.preventDefault();\n const next = findNextEnabled(options, activeIndex, 1);\n if (next >= 0) setActiveIndex(next);\n } else if (key === 'ArrowUp') {\n e.preventDefault();\n const prev = findNextEnabled(options, activeIndex, -1);\n if (prev >= 0) setActiveIndex(prev);\n } else if (key === 'Home') {\n e.preventDefault();\n const first = options.findIndex((o) => !o.disabled);\n if (first >= 0) setActiveIndex(first);\n } else if (key === 'End') {\n e.preventDefault();\n const last = options.length - 1 - [...options].reverse().findIndex((o) => !o.disabled);\n if (last >= 0) setActiveIndex(last);\n } else if (key === 'Enter' || key === ' ') {\n e.preventDefault();\n if (activeIndex >= 0) {\n const opt = options[activeIndex];\n if (!opt.disabled) toggleOption(opt.value);\n }\n } else if (key === 'Escape') {\n e.preventDefault();\n closeList();\n } else if (key.length === 1 && key.match(/\\S/)) {\n // Typeahead logic\n const now = Date.now();\n if (now - typeaheadRef.current.lastTime > 700) typeaheadRef.current.buffer = '';\n typeaheadRef.current.buffer += key.toLowerCase();\n typeaheadRef.current.lastTime = now;\n\n const buf = typeaheadRef.current.buffer;\n const start = activeIndex >= 0 ? activeIndex + 1 : 0;\n const len = options.length;\n for (let i = 0; i < len; i++) {\n const idx = (start + i) % len;\n const lab = String(options[idx].label).toLowerCase();\n if (!options[idx].disabled && lab.startsWith(buf)) {\n setActiveIndex(idx);\n break;\n }\n }\n }\n };\n\n /* ----------------------------------------------------\n Trigger Rendering Logic\n ---------------------------------------------------- */\n const renderTriggerContent = () => {\n if (selectedValues.length === 0) {\n return <span className=\"nui-multiselect-placeholder\">{placeholder}</span>;\n }\n\n if (selectedValues.length > maxTags) {\n return (\n <span className=\"nui-multiselect-summary\">\n {selectedValues.length} items selected\n </span>\n );\n }\n\n // Render individual tags\n return (\n <div className=\"nui-multiselect-tags\">\n {selectedValues.map(val => {\n const label = options.find(o => o.value === val)?.label ?? val;\n return (\n <span key={val} className=\"nui-multiselect-tag\">\n {label}\n </span>\n );\n })}\n </div>\n );\n };\n\n /* ----------------------------------------------------\n Render\n ---------------------------------------------------- */\n return (\n <div className={cn(\"nui-multiselect-root\", className)}>\n \n {/* Hidden inputs for native form submission */}\n {name && selectedValues.map((val) => (\n <input key={val} type=\"hidden\" name={name} value={val} />\n ))}\n\n <button\n ref={setTriggerRef}\n id={labelId}\n type=\"button\"\n className={cn(\"nui-multiselect-trigger\", error && \"error\")}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={open ? listboxId : undefined}\n aria-disabled={disabled || undefined}\n onClick={() => !disabled && setOpen((s) => !s)}\n onKeyDown={onTriggerKeyDown}\n disabled={disabled}\n {...props}\n >\n <div className=\"nui-multiselect-value-container\">\n {renderTriggerContent()}\n </div>\n <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\">\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </button>\n\n {open && (\n <Portal>\n <div\n id={listboxId}\n ref={listRef}\n className=\"nui-multiselect-listbox\"\n role=\"listbox\"\n aria-multiselectable=\"true\"\n aria-labelledby={labelId}\n tabIndex={0}\n style={{ top: coords.top, left: coords.left, width: coords.width }}\n onKeyDown={onListKeyDown}\n >\n {options.map((opt, i) => {\n const isSelected = selectedValues.includes(opt.value);\n const isActive = activeIndex === i;\n \n return (\n <div\n key={opt.value}\n ref={isActive ? activeOptionRef : null}\n id={`${listboxId}-option-${i}`}\n role=\"option\"\n aria-selected={isSelected}\n aria-disabled={opt.disabled || undefined}\n className={cn(\n \"nui-multiselect-option\",\n isActive && \"active\",\n isSelected && \"selected\",\n opt.disabled && \"disabled\"\n )}\n tabIndex={-1}\n onMouseDown={(e) => e.preventDefault()} \n onClick={() => !opt.disabled && toggleOption(opt.value)}\n onMouseEnter={() => !opt.disabled && setActiveIndex(i)}\n >\n \n {/* Custom Checkbox UI */}\n <div className={cn(\"nui-multiselect-checkbox\", isSelected && \"checked\")} aria-hidden=\"true\">\n {isSelected && (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n )}\n </div>\n\n <span className=\"nui-multiselect-option-label\">{opt.label}</span>\n </div>\n );\n })}\n </div>\n </Portal>\n )}\n </div>\n );\n});\nMultiSelect.displayName = 'MultiSelect';"],"names":["findNextEnabled","options","start","direction","len","i","step","MultiSelect","forwardRef","value","defaultValue","onChange","placeholder","disabled","error","name","id","className","maxTags","props","ref","isControlled","internalValue","setInternalValue","useState","selectedValues","open","setOpen","activeIndex","setActiveIndex","o","typeaheadRef","useRef","triggerRef","listRef","activeOptionRef","reactId","React","baseId","listboxId","labelId","setTriggerRef","useCallback","node","coords","setCoords","updatePosition","triggerRect","listRect","scrollY","scrollX","top","left","width","padding","useLayoutEffect","closeList","restoreFocus","useEffect","onClickOutside","idx","timeoutId","toggleOption","optValue","nextValues","v","onTriggerKeyDown","onListKeyDown","key","next","prev","first","last","opt","now","buf","lab","renderTriggerContent","jsx","jsxs","val","label","cn","s","Portal","isSelected","isActive","e"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("react/jsx-runtime"),t=require("react"),m=t.createContext(void 0);function w(){const i=t.useContext(m);if(i===void 0)throw new Error("useTheme must be used within a <NUIProvider>");return i}function T({children:i,defaultTheme:u="system",storageKey:c="nui-theme"}){const[r,d]=t.useState(u),[l,h]=t.useState("light"),[a,f]=t.useState(!1),s=t.useCallback(e=>{const n=document.documentElement;let o;e==="system"?o=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":o=e,n.setAttribute("data-theme",o),o==="dark"?n.classList.add("dark"):n.classList.remove("dark"),h(o)},[]);return t.useEffect(()=>{f(!0);const e=window.localStorage.getItem(c);e?(d(e),s(e)):s(u)},[c,u,s]),t.useEffect(()=>{a&&(window.localStorage.setItem(c,r),s(r))},[r,c,a,s]),t.useEffect(()=>{if(!a||r!=="system")return;const e=window.matchMedia("(prefers-color-scheme: dark)"),n=()=>s("system");return e.addEventListener("change",n),()=>e.removeEventListener("change",n)},[r,a,s]),v.jsx(m.Provider,{value:{theme:r,resolvedTheme:l,setTheme:d},children:i})}exports.NUIProvider=T;exports.useTheme=w;
2
+ //# sourceMappingURL=NUIProvider.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NUIProvider.cjs","sources":["../../../src/components/nuiprovider/NUIProvider.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext, useEffect, useState, useCallback } from 'react';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport type ThemeMode = 'light' | 'dark' | 'system';\n\nexport interface NUIProviderProps {\n children: React.ReactNode;\n /** The default theme if nothing is in local storage. Defaults to 'system'. */\n defaultTheme?: ThemeMode;\n /** The local storage key used to persist the theme preference. Defaults to 'nui-theme'. */\n storageKey?: string;\n}\n\nexport interface ThemeContextState {\n /** The user's selected preference (includes 'system') */\n theme: ThemeMode;\n /** The actual calculated theme currently rendered in the DOM ('light' or 'dark') */\n resolvedTheme: 'light' | 'dark';\n /** Function to update the theme */\n setTheme: (theme: ThemeMode) => void;\n}\n\n/* ============================================================\n * Context & Hook\n * ============================================================ */\n\nconst ThemeContext = createContext<ThemeContextState | undefined>(undefined);\n\n/**\n * useTheme Hook\n * * Consumes the NUI Theme context to read or update the current theme.\n */\nexport function useTheme() {\n const context = useContext(ThemeContext);\n if (context === undefined) {\n throw new Error('useTheme must be used within a <NUIProvider>');\n }\n return context;\n}\n\n/* ============================================================\n * Component\n * ============================================================ */\n\n/**\n * NUIProvider\n * * The root provider for the NUI component library.\n * * Manages theme state, synchronizes with localStorage, and listens for system preference changes.\n */\nexport function NUIProvider({\n children,\n defaultTheme = 'system',\n storageKey = 'nui-theme',\n}: NUIProviderProps) {\n const [theme, setTheme] = useState<ThemeMode>(defaultTheme);\n const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>('light');\n const [isMounted, setIsMounted] = useState(false);\n\n // 1. Core logic to apply the theme to the DOM\n const applyTheme = useCallback((mode: ThemeMode) => {\n const root = document.documentElement;\n let finalTheme: 'light' | 'dark';\n\n if (mode === 'system') {\n finalTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n } else {\n finalTheme = mode;\n }\n\n // Set standard data attribute for CSS variables\n root.setAttribute('data-theme', finalTheme);\n \n // Toggle the 'dark' class for Tailwind CSS compatibility\n if (finalTheme === 'dark') {\n root.classList.add('dark');\n } else {\n root.classList.remove('dark');\n }\n\n setResolvedTheme(finalTheme);\n }, []);\n\n // 2. Hydration & Initial Load\n useEffect(() => {\n setIsMounted(true);\n const storedTheme = window.localStorage.getItem(storageKey) as ThemeMode | null;\n \n if (storedTheme) {\n setTheme(storedTheme);\n applyTheme(storedTheme);\n } else {\n applyTheme(defaultTheme);\n }\n }, [storageKey, defaultTheme, applyTheme]);\n\n // 3. Sync state changes to LocalStorage\n useEffect(() => {\n if (!isMounted) return;\n window.localStorage.setItem(storageKey, theme);\n applyTheme(theme);\n }, [theme, storageKey, isMounted, applyTheme]);\n\n // 4. System Preference Listener\n useEffect(() => {\n if (!isMounted || theme !== 'system') return;\n\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n const handleChange = () => applyTheme('system');\n\n mediaQuery.addEventListener('change', handleChange);\n return () => mediaQuery.removeEventListener('change', handleChange);\n }, [theme, isMounted, applyTheme]);\n\n // 5. Render Provider\n return (\n <ThemeContext.Provider value={{ theme, resolvedTheme, setTheme }}>\n {children}\n </ThemeContext.Provider>\n );\n}"],"names":["ThemeContext","createContext","useTheme","context","useContext","NUIProvider","children","defaultTheme","storageKey","theme","setTheme","useState","resolvedTheme","setResolvedTheme","isMounted","setIsMounted","applyTheme","useCallback","mode","root","finalTheme","useEffect","storedTheme","mediaQuery","handleChange","jsx"],"mappings":"wIA+BMA,EAAeC,EAAAA,cAA6C,MAAS,EAMpE,SAASC,GAAW,CACzB,MAAMC,EAAUC,EAAAA,WAAWJ,CAAY,EACvC,GAAIG,IAAY,OACd,MAAM,IAAI,MAAM,8CAA8C,EAEhE,OAAOA,CACT,CAWO,SAASE,EAAY,CAC1B,SAAAC,EACA,aAAAC,EAAe,SACf,WAAAC,EAAa,WACf,EAAqB,CACnB,KAAM,CAACC,EAAOC,CAAQ,EAAIC,EAAAA,SAAoBJ,CAAY,EACpD,CAACK,EAAeC,CAAgB,EAAIF,EAAAA,SAA2B,OAAO,EACtE,CAACG,EAAWC,CAAY,EAAIJ,EAAAA,SAAS,EAAK,EAG1CK,EAAaC,cAAaC,GAAoB,CAClD,MAAMC,EAAO,SAAS,gBACtB,IAAIC,EAEAF,IAAS,SACXE,EAAa,OAAO,WAAW,8BAA8B,EAAE,QAAU,OAAS,QAElFA,EAAaF,EAIfC,EAAK,aAAa,aAAcC,CAAU,EAGtCA,IAAe,OACjBD,EAAK,UAAU,IAAI,MAAM,EAEzBA,EAAK,UAAU,OAAO,MAAM,EAG9BN,EAAiBO,CAAU,CAC7B,EAAG,CAAA,CAAE,EAGLC,OAAAA,EAAAA,UAAU,IAAM,CACdN,EAAa,EAAI,EACjB,MAAMO,EAAc,OAAO,aAAa,QAAQd,CAAU,EAEtDc,GACFZ,EAASY,CAAW,EACpBN,EAAWM,CAAW,GAEtBN,EAAWT,CAAY,CAE3B,EAAG,CAACC,EAAYD,EAAcS,CAAU,CAAC,EAGzCK,EAAAA,UAAU,IAAM,CACTP,IACL,OAAO,aAAa,QAAQN,EAAYC,CAAK,EAC7CO,EAAWP,CAAK,EAClB,EAAG,CAACA,EAAOD,EAAYM,EAAWE,CAAU,CAAC,EAG7CK,EAAAA,UAAU,IAAM,CACd,GAAI,CAACP,GAAaL,IAAU,SAAU,OAEtC,MAAMc,EAAa,OAAO,WAAW,8BAA8B,EAC7DC,EAAe,IAAMR,EAAW,QAAQ,EAE9C,OAAAO,EAAW,iBAAiB,SAAUC,CAAY,EAC3C,IAAMD,EAAW,oBAAoB,SAAUC,CAAY,CACpE,EAAG,CAACf,EAAOK,EAAWE,CAAU,CAAC,EAI/BS,MAACzB,EAAa,SAAb,CAAsB,MAAO,CAAE,MAAAS,EAAO,cAAAG,EAAe,SAAAF,GACnD,SAAAJ,EACH,CAEJ"}
@@ -0,0 +1,36 @@
1
+ import { jsx as w } from "react/jsx-runtime";
2
+ import { createContext as k, useContext as p, useState as a, useCallback as T, useEffect as d } from "react";
3
+ const l = k(void 0);
4
+ function C() {
5
+ const n = p(l);
6
+ if (n === void 0)
7
+ throw new Error("useTheme must be used within a <NUIProvider>");
8
+ return n;
9
+ }
10
+ function E({
11
+ children: n,
12
+ defaultTheme: m = "system",
13
+ storageKey: i = "nui-theme"
14
+ }) {
15
+ const [s, h] = a(m), [u, f] = a("light"), [c, v] = a(!1), t = T((e) => {
16
+ const o = document.documentElement;
17
+ let r;
18
+ e === "system" ? r = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : r = e, o.setAttribute("data-theme", r), r === "dark" ? o.classList.add("dark") : o.classList.remove("dark"), f(r);
19
+ }, []);
20
+ return d(() => {
21
+ v(!0);
22
+ const e = window.localStorage.getItem(i);
23
+ e ? (h(e), t(e)) : t(m);
24
+ }, [i, m, t]), d(() => {
25
+ c && (window.localStorage.setItem(i, s), t(s));
26
+ }, [s, i, c, t]), d(() => {
27
+ if (!c || s !== "system") return;
28
+ const e = window.matchMedia("(prefers-color-scheme: dark)"), o = () => t("system");
29
+ return e.addEventListener("change", o), () => e.removeEventListener("change", o);
30
+ }, [s, c, t]), /* @__PURE__ */ w(l.Provider, { value: { theme: s, resolvedTheme: u, setTheme: h }, children: n });
31
+ }
32
+ export {
33
+ E as NUIProvider,
34
+ C as useTheme
35
+ };
36
+ //# sourceMappingURL=NUIProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NUIProvider.js","sources":["../../../src/components/nuiprovider/NUIProvider.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext, useEffect, useState, useCallback } from 'react';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport type ThemeMode = 'light' | 'dark' | 'system';\n\nexport interface NUIProviderProps {\n children: React.ReactNode;\n /** The default theme if nothing is in local storage. Defaults to 'system'. */\n defaultTheme?: ThemeMode;\n /** The local storage key used to persist the theme preference. Defaults to 'nui-theme'. */\n storageKey?: string;\n}\n\nexport interface ThemeContextState {\n /** The user's selected preference (includes 'system') */\n theme: ThemeMode;\n /** The actual calculated theme currently rendered in the DOM ('light' or 'dark') */\n resolvedTheme: 'light' | 'dark';\n /** Function to update the theme */\n setTheme: (theme: ThemeMode) => void;\n}\n\n/* ============================================================\n * Context & Hook\n * ============================================================ */\n\nconst ThemeContext = createContext<ThemeContextState | undefined>(undefined);\n\n/**\n * useTheme Hook\n * * Consumes the NUI Theme context to read or update the current theme.\n */\nexport function useTheme() {\n const context = useContext(ThemeContext);\n if (context === undefined) {\n throw new Error('useTheme must be used within a <NUIProvider>');\n }\n return context;\n}\n\n/* ============================================================\n * Component\n * ============================================================ */\n\n/**\n * NUIProvider\n * * The root provider for the NUI component library.\n * * Manages theme state, synchronizes with localStorage, and listens for system preference changes.\n */\nexport function NUIProvider({\n children,\n defaultTheme = 'system',\n storageKey = 'nui-theme',\n}: NUIProviderProps) {\n const [theme, setTheme] = useState<ThemeMode>(defaultTheme);\n const [resolvedTheme, setResolvedTheme] = useState<'light' | 'dark'>('light');\n const [isMounted, setIsMounted] = useState(false);\n\n // 1. Core logic to apply the theme to the DOM\n const applyTheme = useCallback((mode: ThemeMode) => {\n const root = document.documentElement;\n let finalTheme: 'light' | 'dark';\n\n if (mode === 'system') {\n finalTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n } else {\n finalTheme = mode;\n }\n\n // Set standard data attribute for CSS variables\n root.setAttribute('data-theme', finalTheme);\n \n // Toggle the 'dark' class for Tailwind CSS compatibility\n if (finalTheme === 'dark') {\n root.classList.add('dark');\n } else {\n root.classList.remove('dark');\n }\n\n setResolvedTheme(finalTheme);\n }, []);\n\n // 2. Hydration & Initial Load\n useEffect(() => {\n setIsMounted(true);\n const storedTheme = window.localStorage.getItem(storageKey) as ThemeMode | null;\n \n if (storedTheme) {\n setTheme(storedTheme);\n applyTheme(storedTheme);\n } else {\n applyTheme(defaultTheme);\n }\n }, [storageKey, defaultTheme, applyTheme]);\n\n // 3. Sync state changes to LocalStorage\n useEffect(() => {\n if (!isMounted) return;\n window.localStorage.setItem(storageKey, theme);\n applyTheme(theme);\n }, [theme, storageKey, isMounted, applyTheme]);\n\n // 4. System Preference Listener\n useEffect(() => {\n if (!isMounted || theme !== 'system') return;\n\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n const handleChange = () => applyTheme('system');\n\n mediaQuery.addEventListener('change', handleChange);\n return () => mediaQuery.removeEventListener('change', handleChange);\n }, [theme, isMounted, applyTheme]);\n\n // 5. Render Provider\n return (\n <ThemeContext.Provider value={{ theme, resolvedTheme, setTheme }}>\n {children}\n </ThemeContext.Provider>\n );\n}"],"names":["ThemeContext","createContext","useTheme","context","useContext","NUIProvider","children","defaultTheme","storageKey","theme","setTheme","useState","resolvedTheme","setResolvedTheme","isMounted","setIsMounted","applyTheme","useCallback","mode","root","finalTheme","useEffect","storedTheme","mediaQuery","handleChange","jsx"],"mappings":";;AA+BA,MAAMA,IAAeC,EAA6C,MAAS;AAMpE,SAASC,IAAW;AACzB,QAAMC,IAAUC,EAAWJ,CAAY;AACvC,MAAIG,MAAY;AACd,UAAM,IAAI,MAAM,8CAA8C;AAEhE,SAAOA;AACT;AAWO,SAASE,EAAY;AAAA,EAC1B,UAAAC;AAAA,EACA,cAAAC,IAAe;AAAA,EACf,YAAAC,IAAa;AACf,GAAqB;AACnB,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAAoBJ,CAAY,GACpD,CAACK,GAAeC,CAAgB,IAAIF,EAA2B,OAAO,GACtE,CAACG,GAAWC,CAAY,IAAIJ,EAAS,EAAK,GAG1CK,IAAaC,EAAY,CAACC,MAAoB;AAClD,UAAMC,IAAO,SAAS;AACtB,QAAIC;AAEJ,IAAIF,MAAS,WACXE,IAAa,OAAO,WAAW,8BAA8B,EAAE,UAAU,SAAS,UAElFA,IAAaF,GAIfC,EAAK,aAAa,cAAcC,CAAU,GAGtCA,MAAe,SACjBD,EAAK,UAAU,IAAI,MAAM,IAEzBA,EAAK,UAAU,OAAO,MAAM,GAG9BN,EAAiBO,CAAU;AAAA,EAC7B,GAAG,CAAA,CAAE;AAGL,SAAAC,EAAU,MAAM;AACd,IAAAN,EAAa,EAAI;AACjB,UAAMO,IAAc,OAAO,aAAa,QAAQd,CAAU;AAE1D,IAAIc,KACFZ,EAASY,CAAW,GACpBN,EAAWM,CAAW,KAEtBN,EAAWT,CAAY;AAAA,EAE3B,GAAG,CAACC,GAAYD,GAAcS,CAAU,CAAC,GAGzCK,EAAU,MAAM;AACd,IAAKP,MACL,OAAO,aAAa,QAAQN,GAAYC,CAAK,GAC7CO,EAAWP,CAAK;AAAA,EAClB,GAAG,CAACA,GAAOD,GAAYM,GAAWE,CAAU,CAAC,GAG7CK,EAAU,MAAM;AACd,QAAI,CAACP,KAAaL,MAAU,SAAU;AAEtC,UAAMc,IAAa,OAAO,WAAW,8BAA8B,GAC7DC,IAAe,MAAMR,EAAW,QAAQ;AAE9C,WAAAO,EAAW,iBAAiB,UAAUC,CAAY,GAC3C,MAAMD,EAAW,oBAAoB,UAAUC,CAAY;AAAA,EACpE,GAAG,CAACf,GAAOK,GAAWE,CAAU,CAAC,GAI/B,gBAAAS,EAACzB,EAAa,UAAb,EAAsB,OAAO,EAAE,OAAAS,GAAO,eAAAG,GAAe,UAAAF,KACnD,UAAAJ,GACH;AAEJ;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime");;/* empty css */function f({page:n,total:a,onChange:u,siblings:r=1,className:c=""}){if(a<=1)return null;const t=i=>{i<1||i>a||u(i)},e=[],l=n-r>2,o=n+r<a-1,h=Math.max(1,n-r),d=Math.min(a,n+r);e.push(1),l&&e.push("...");for(let i=h;i<=d;i++)i!==1&&i!==a&&e.push(i);return o&&e.push("..."),a>1&&e.push(a),s.jsxs("nav",{className:`ui-pagination ${c}`,"aria-label":"Pagination Navigation",children:[s.jsx("button",{className:"ui-page-btn",onClick:()=>t(n-1),disabled:n===1,"aria-label":"Previous Page",children:""}),e.map((i,b)=>i==="..."?s.jsx("span",{className:"ui-page-ellipsis",children:""},`ellipsis-${b}`):s.jsx("button",{className:`ui-page-btn ${i===n?"active":""}`,"aria-current":i===n?"page":void 0,onClick:()=>t(i),children:i},`page-${i}`)),s.jsx("button",{className:"ui-page-btn",onClick:()=>t(n+1),disabled:n===a,"aria-label":"Next Page",children:""})]})}exports.Pagination=f;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),y=require("react");;/* empty css */const m=require("../../utils/cn/cn.cjs");function w({page:p,total:i,onChange:k,siblings:a=1,className:v,disabled:l=!1,...b}){const r=Math.max(1,Math.min(p,i)),c=e=>{l||e<1||e>i||e===r||k(e)},P=y.useMemo(()=>{const e=5+a*2;if(i<=e)return Array.from({length:i},(o,s)=>s+1);const t=Math.max(r-a,1),x=Math.min(r+a,i),u=t>2,g=x<i-2,f=1,j=i;if(!u&&g){const o=3+2*a;return[...Array.from({length:o},(h,d)=>d+1),"right-ellipsis",j]}if(u&&!g){const o=3+2*a,s=Array.from({length:o},(h,d)=>i-o+1+d);return[f,"left-ellipsis",...s]}if(u&&g){const o=Array.from({length:x-t+1},(s,h)=>t+h);return[f,"left-ellipsis",...o,"right-ellipsis",j]}return[]},[i,r,a]);return i<=1?null:n.jsx("nav",{className:m.cn("nui-pagination",v),"aria-label":"Pagination Navigation",...b,children:n.jsxs("ul",{className:"nui-pagination-list",children:[n.jsx("li",{children:n.jsx("button",{className:"nui-pagination-btn nui-pagination-btn--nav",onClick:()=>c(r-1),disabled:l||r===1,"aria-label":"Previous Page",children:n.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:n.jsx("polyline",{points:"15 18 9 12 15 6"})})})}),P.map(e=>{if(e==="left-ellipsis"||e==="right-ellipsis")return n.jsx("li",{className:"nui-pagination-ellipsis","aria-hidden":"true",children:n.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[n.jsx("circle",{cx:"12",cy:"12",r:"1"}),n.jsx("circle",{cx:"19",cy:"12",r:"1"}),n.jsx("circle",{cx:"5",cy:"12",r:"1"})]})},e);const t=e===r;return n.jsx("li",{children:n.jsx("button",{className:m.cn("nui-pagination-btn",t&&"nui-pagination-btn--active"),"aria-current":t?"page":void 0,"aria-label":t?`Page ${e}`:`Go to page ${e}`,disabled:l,onClick:()=>c(e),children:e})},`page-${e}`)}),n.jsx("li",{children:n.jsx("button",{className:"nui-pagination-btn nui-pagination-btn--nav",onClick:()=>c(r+1),disabled:l||r===i,"aria-label":"Next Page",children:n.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:n.jsx("polyline",{points:"9 18 15 12 9 6"})})})})]})})}exports.Pagination=w;
2
2
  //# sourceMappingURL=Pagination.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.cjs","sources":["../../../src/components/pagination/Pagination.tsx"],"sourcesContent":["/**\r\n * Pagination.tsx\r\n * -----------------\r\n * WAI-ARIA compliant pagination component.\r\n *\r\n * Features:\r\n * - First / Prev / Next / Last controls\r\n * - Arrow key navigation\r\n * - Controlled + fully typed\r\n * - Accessible roles & labels\r\n * - Works with screen readers\r\n * - Theme-aware classes only (no inline styles)\r\n */\r\n\r\n/**\r\n * Pagination.tsx FINAL VERSION\r\n * --------------------------------\r\n * - No duplicate keys\r\n * - GitHub-style gap rendering\r\n * - Clean, predictable page logic\r\n * - Fully accessible\r\n * - No external dependencies\r\n */\r\n\r\nimport './Pagination.css';\r\n\r\nexport interface PaginationProps {\r\n page: number; // current page (1-based)\r\n total: number; // total pages\r\n onChange: (p: number) => void;\r\n siblings?: number; // how many pages to show around active page\r\n className?: string;\r\n}\r\n\r\nexport function Pagination({\r\n page,\r\n total,\r\n onChange,\r\n siblings = 1,\r\n className = '',\r\n}: PaginationProps) {\r\n if (total <= 1) return null;\r\n\r\n const goTo = (p: number) => {\r\n if (p < 1 || p > total) return;\r\n onChange(p);\r\n };\r\n\r\n /* -------------------------------------------------------\r\n * Page calculation (no duplicates, GitHub-style)\r\n * ------------------------------------------------------*/\r\n\r\n const pages: (number | '...')[] = [];\r\n\r\n const hasLeftGap = page - siblings > 2;\r\n const hasRightGap = page + siblings < total - 1;\r\n\r\n const start = Math.max(1, page - siblings);\r\n const end = Math.min(total, page + siblings);\r\n\r\n // Always add first page\r\n pages.push(1);\r\n\r\n // Left gap …\r\n if (hasLeftGap) pages.push('...');\r\n\r\n // Middle pages\r\n for (let i = start; i <= end; i++) {\r\n if (i !== 1 && i !== total) {\r\n pages.push(i);\r\n }\r\n }\r\n\r\n // Right gap …\r\n if (hasRightGap) pages.push('...');\r\n\r\n // Always add last page\r\n if (total > 1) pages.push(total);\r\n\r\n return (\r\n <nav\r\n className={`ui-pagination ${className}`}\r\n aria-label=\"Pagination Navigation\"\r\n >\r\n {/* Previous */}\r\n <button\r\n className=\"ui-page-btn\"\r\n onClick={() => goTo(page - 1)}\r\n disabled={page === 1}\r\n aria-label=\"Previous Page\"\r\n >\r\n ←\r\n </button>\r\n\r\n {/* Pages */}\r\n {pages.map((p, i) =>\r\n p === '...' ? (\r\n <span key={`ellipsis-${i}`} className=\"ui-page-ellipsis\">\r\n …\r\n </span>\r\n ) : (\r\n <button\r\n key={`page-${p}`}\r\n className={`ui-page-btn ${p === page ? 'active' : ''}`}\r\n aria-current={p === page ? 'page' : undefined}\r\n onClick={() => goTo(p)}\r\n >\r\n {p}\r\n </button>\r\n )\r\n )}\r\n\r\n {/* Next */}\r\n <button\r\n className=\"ui-page-btn\"\r\n onClick={() => goTo(page + 1)}\r\n disabled={page === total}\r\n aria-label=\"Next Page\"\r\n >\r\n →\r\n </button>\r\n </nav>\r\n );\r\n}\r\n"],"names":["Pagination","page","total","onChange","siblings","className","goTo","p","pages","hasLeftGap","hasRightGap","start","end","jsxs","jsx","i"],"mappings":"qJAkCO,SAASA,EAAW,CACzB,KAAAC,EACA,MAAAC,EACA,SAAAC,EACA,SAAAC,EAAW,EACX,UAAAC,EAAY,EACd,EAAoB,CAClB,GAAIH,GAAS,EAAG,OAAO,KAEvB,MAAMI,EAAQC,GAAc,CACtBA,EAAI,GAAKA,EAAIL,GACjBC,EAASI,CAAC,CACZ,EAMMC,EAA4B,CAAA,EAE5BC,EAAaR,EAAOG,EAAW,EAC/BM,EAAcT,EAAOG,EAAWF,EAAQ,EAExCS,EAAQ,KAAK,IAAI,EAAGV,EAAOG,CAAQ,EACnCQ,EAAM,KAAK,IAAIV,EAAOD,EAAOG,CAAQ,EAG3CI,EAAM,KAAK,CAAC,EAGRC,GAAYD,EAAM,KAAK,KAAK,EAGhC,QAAS,EAAIG,EAAO,GAAKC,EAAK,IACxB,IAAM,GAAK,IAAMV,GACnBM,EAAM,KAAK,CAAC,EAKhB,OAAIE,GAAaF,EAAM,KAAK,KAAK,EAG7BN,EAAQ,GAAGM,EAAM,KAAKN,CAAK,EAG7BW,EAAAA,KAAC,MAAA,CACC,UAAW,iBAAiBR,CAAS,GACrC,aAAW,wBAGX,SAAA,CAAAS,EAAAA,IAAC,SAAA,CACC,UAAU,cACV,QAAS,IAAMR,EAAKL,EAAO,CAAC,EAC5B,SAAUA,IAAS,EACnB,aAAW,gBACZ,SAAA,GAAA,CAAA,EAKAO,EAAM,IAAI,CAACD,EAAGQ,IACbR,IAAM,MACJO,EAAAA,IAAC,OAAA,CAA2B,UAAU,mBAAmB,SAAA,KAA9C,YAAYC,CAAC,EAExB,EAEAD,EAAAA,IAAC,SAAA,CAEC,UAAW,eAAeP,IAAMN,EAAO,SAAW,EAAE,GACpD,eAAcM,IAAMN,EAAO,OAAS,OACpC,QAAS,IAAMK,EAAKC,CAAC,EAEpB,SAAAA,CAAA,EALI,QAAQA,CAAC,EAAA,CAMhB,EAKJO,EAAAA,IAAC,SAAA,CACC,UAAU,cACV,QAAS,IAAMR,EAAKL,EAAO,CAAC,EAC5B,SAAUA,IAASC,EACnB,aAAW,YACZ,SAAA,GAAA,CAAA,CAED,CAAA,CAAA,CAGN"}
1
+ {"version":3,"file":"Pagination.cjs","sources":["../../../src/components/pagination/Pagination.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport { cn } from '../../utils';\nimport './Pagination.css';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport interface PaginationProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {\n /** The current active page number (1-indexed) */\n page: number;\n /** The total number of pages available */\n total: number;\n /** Callback fired when a new page is selected */\n onChange: (page: number) => void;\n /** Number of page links to show on each side of the current page. Defaults to 1. */\n siblings?: number;\n /** Custom class name applied to the root navigation element */\n className?: string;\n /** Disables all interaction with the pagination controls */\n disabled?: boolean;\n}\n\ntype PaginationItem = number | 'left-ellipsis' | 'right-ellipsis';\n\n/* ============================================================\n * Component\n * ============================================================ */\n\n/**\n * Pagination Component\n * * A navigation structure for splitting large lists across multiple pages.\n * * Automatically calculates when to collapse page ranges into ellipses based on siblings.\n * * Uses standard <nav> and <ul> elements for WAI-ARIA compliance.\n */\nexport function Pagination({\n page,\n total,\n onChange,\n siblings = 1,\n className,\n disabled = false,\n ...props\n}: PaginationProps) {\n \n // Guard against invalid ranges supplied by the developer\n const currentPage = Math.max(1, Math.min(page, total));\n\n const goTo = (p: number) => {\n if (disabled || p < 1 || p > total || p === currentPage) return;\n onChange(p);\n };\n\n /* ----------------------------------------------------\n Mathematically Perfect Page Generation\n ---------------------------------------------------- */\n const pages = useMemo<PaginationItem[]>(() => {\n // Math: 1 (first) + 1 (last) + 2 (siblings) + 1 (current) + 2 (ellipses)\n const totalPageNumbersToShow = 5 + siblings * 2;\n\n // 1. If we don't have enough pages to warrant an ellipsis, show them all\n if (total <= totalPageNumbersToShow) {\n return Array.from({ length: total }, (_, i) => i + 1);\n }\n\n const leftSiblingIndex = Math.max(currentPage - siblings, 1);\n const rightSiblingIndex = Math.min(currentPage + siblings, total);\n\n // 2. We only show an ellipsis if there are MORE than 2 pages hidden\n const showLeftDots = leftSiblingIndex > 2;\n const showRightDots = rightSiblingIndex < total - 2;\n\n const firstPageIndex = 1;\n const lastPageIndex = total;\n\n // Case 1: Show right dots only (e.g., [1] 2 3 4 5 ... 10)\n if (!showLeftDots && showRightDots) {\n const leftItemCount = 3 + 2 * siblings;\n const leftRange = Array.from({ length: leftItemCount }, (_, i) => i + 1);\n return [...leftRange, 'right-ellipsis', lastPageIndex];\n }\n\n // Case 2: Show left dots only (e.g., 1 ... 6 7 8 9 [10])\n if (showLeftDots && !showRightDots) {\n const rightItemCount = 3 + 2 * siblings;\n const rightRange = Array.from({ length: rightItemCount }, (_, i) => total - rightItemCount + 1 + i);\n return [firstPageIndex, 'left-ellipsis', ...rightRange];\n }\n\n // Case 3: Show both dots (e.g., 1 ... 4 [5] 6 ... 10)\n if (showLeftDots && showRightDots) {\n const middleRange = Array.from(\n { length: rightSiblingIndex - leftSiblingIndex + 1 },\n (_, i) => leftSiblingIndex + i\n );\n return [firstPageIndex, 'left-ellipsis', ...middleRange, 'right-ellipsis', lastPageIndex];\n }\n\n return [];\n }, [total, currentPage, siblings]);\n\n if (total <= 1) return null;\n\n /* ----------------------------------------------------\n Render\n ---------------------------------------------------- */\n return (\n <nav\n className={cn(\"nui-pagination\", className)}\n aria-label=\"Pagination Navigation\"\n {...props}\n >\n <ul className=\"nui-pagination-list\">\n \n {/* Previous Button */}\n <li>\n <button\n className=\"nui-pagination-btn nui-pagination-btn--nav\"\n onClick={() => goTo(currentPage - 1)}\n disabled={disabled || currentPage === 1}\n aria-label=\"Previous Page\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"15 18 9 12 15 6\"></polyline>\n </svg>\n </button>\n </li>\n\n {/* Page Numbers & Ellipses */}\n {pages.map((p) => {\n if (p === 'left-ellipsis' || p === 'right-ellipsis') {\n return (\n <li key={p} className=\"nui-pagination-ellipsis\" aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"1\"></circle>\n <circle cx=\"19\" cy=\"12\" r=\"1\"></circle>\n <circle cx=\"5\" cy=\"12\" r=\"1\"></circle>\n </svg>\n </li>\n );\n }\n\n const isCurrent = p === currentPage;\n\n return (\n <li key={`page-${p}`}>\n <button\n className={cn(\n \"nui-pagination-btn\",\n isCurrent && \"nui-pagination-btn--active\"\n )}\n aria-current={isCurrent ? 'page' : undefined}\n aria-label={isCurrent ? `Page ${p}` : `Go to page ${p}`}\n disabled={disabled}\n onClick={() => goTo(p)}\n >\n {p}\n </button>\n </li>\n );\n })}\n\n {/* Next Button */}\n <li>\n <button\n className=\"nui-pagination-btn nui-pagination-btn--nav\"\n onClick={() => goTo(currentPage + 1)}\n disabled={disabled || currentPage === total}\n aria-label=\"Next Page\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"9 18 15 12 9 6\"></polyline>\n </svg>\n </button>\n </li>\n </ul>\n </nav>\n );\n}"],"names":["Pagination","page","total","onChange","siblings","className","disabled","props","currentPage","goTo","p","pages","useMemo","totalPageNumbersToShow","_","i","leftSiblingIndex","rightSiblingIndex","showLeftDots","showRightDots","firstPageIndex","lastPageIndex","leftItemCount","rightItemCount","rightRange","middleRange","jsx","cn","jsxs","isCurrent"],"mappings":"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"}
@@ -1,62 +1,95 @@
1
- import { jsxs as f, jsx as r } from "react/jsx-runtime";
1
+ import { jsx as i, jsxs as x } from "react/jsx-runtime";
2
+ import { useMemo as C } from "react";
2
3
  /* empty css */
3
- function p({
4
- page: a,
5
- total: n,
6
- onChange: t,
7
- siblings: e = 1,
8
- className: u = ""
4
+ import { cn as k } from "../../utils/cn/cn.js";
5
+ function M({
6
+ page: v,
7
+ total: e,
8
+ onChange: b,
9
+ siblings: a = 1,
10
+ className: P,
11
+ disabled: s = !1,
12
+ ...w
9
13
  }) {
10
- if (n <= 1) return null;
11
- const c = (i) => {
12
- i < 1 || i > n || t(i);
13
- }, s = [], o = a - e > 2, l = a + e < n - 1, h = Math.max(1, a - e), d = Math.min(n, a + e);
14
- s.push(1), o && s.push("...");
15
- for (let i = h; i <= d; i++)
16
- i !== 1 && i !== n && s.push(i);
17
- return l && s.push("..."), n > 1 && s.push(n), /* @__PURE__ */ f(
14
+ const r = Math.max(1, Math.min(v, e)), c = (n) => {
15
+ s || n < 1 || n > e || n === r || b(n);
16
+ }, y = C(() => {
17
+ const n = 5 + a * 2;
18
+ if (e <= n)
19
+ return Array.from({ length: e }, (o, l) => l + 1);
20
+ const t = Math.max(r - a, 1), f = Math.min(r + a, e), h = t > 2, u = f < e - 2, m = 1, p = e;
21
+ if (!h && u) {
22
+ const o = 3 + 2 * a;
23
+ return [...Array.from({ length: o }, (g, d) => d + 1), "right-ellipsis", p];
24
+ }
25
+ if (h && !u) {
26
+ const o = 3 + 2 * a, l = Array.from({ length: o }, (g, d) => e - o + 1 + d);
27
+ return [m, "left-ellipsis", ...l];
28
+ }
29
+ if (h && u) {
30
+ const o = Array.from(
31
+ { length: f - t + 1 },
32
+ (l, g) => t + g
33
+ );
34
+ return [m, "left-ellipsis", ...o, "right-ellipsis", p];
35
+ }
36
+ return [];
37
+ }, [e, r, a]);
38
+ return e <= 1 ? null : /* @__PURE__ */ i(
18
39
  "nav",
19
40
  {
20
- className: `ui-pagination ${u}`,
41
+ className: k("nui-pagination", P),
21
42
  "aria-label": "Pagination Navigation",
22
- children: [
23
- /* @__PURE__ */ r(
43
+ ...w,
44
+ children: /* @__PURE__ */ x("ul", { className: "nui-pagination-list", children: [
45
+ /* @__PURE__ */ i("li", { children: /* @__PURE__ */ i(
24
46
  "button",
25
47
  {
26
- className: "ui-page-btn",
27
- onClick: () => c(a - 1),
28
- disabled: a === 1,
48
+ className: "nui-pagination-btn nui-pagination-btn--nav",
49
+ onClick: () => c(r - 1),
50
+ disabled: s || r === 1,
29
51
  "aria-label": "Previous Page",
30
- children: ""
52
+ children: /* @__PURE__ */ i("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ i("polyline", { points: "15 18 9 12 15 6" }) })
31
53
  }
32
- ),
33
- s.map(
34
- (i, m) => i === "..." ? /* @__PURE__ */ r("span", { className: "ui-page-ellipsis", children: "…" }, `ellipsis-${m}`) : /* @__PURE__ */ r(
54
+ ) }),
55
+ y.map((n) => {
56
+ if (n === "left-ellipsis" || n === "right-ellipsis")
57
+ return /* @__PURE__ */ i("li", { className: "nui-pagination-ellipsis", "aria-hidden": "true", children: /* @__PURE__ */ x("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
58
+ /* @__PURE__ */ i("circle", { cx: "12", cy: "12", r: "1" }),
59
+ /* @__PURE__ */ i("circle", { cx: "19", cy: "12", r: "1" }),
60
+ /* @__PURE__ */ i("circle", { cx: "5", cy: "12", r: "1" })
61
+ ] }) }, n);
62
+ const t = n === r;
63
+ return /* @__PURE__ */ i("li", { children: /* @__PURE__ */ i(
35
64
  "button",
36
65
  {
37
- className: `ui-page-btn ${i === a ? "active" : ""}`,
38
- "aria-current": i === a ? "page" : void 0,
39
- onClick: () => c(i),
40
- children: i
41
- },
42
- `page-${i}`
43
- )
44
- ),
45
- /* @__PURE__ */ r(
66
+ className: k(
67
+ "nui-pagination-btn",
68
+ t && "nui-pagination-btn--active"
69
+ ),
70
+ "aria-current": t ? "page" : void 0,
71
+ "aria-label": t ? `Page ${n}` : `Go to page ${n}`,
72
+ disabled: s,
73
+ onClick: () => c(n),
74
+ children: n
75
+ }
76
+ ) }, `page-${n}`);
77
+ }),
78
+ /* @__PURE__ */ i("li", { children: /* @__PURE__ */ i(
46
79
  "button",
47
80
  {
48
- className: "ui-page-btn",
49
- onClick: () => c(a + 1),
50
- disabled: a === n,
81
+ className: "nui-pagination-btn nui-pagination-btn--nav",
82
+ onClick: () => c(r + 1),
83
+ disabled: s || r === e,
51
84
  "aria-label": "Next Page",
52
- children: ""
85
+ children: /* @__PURE__ */ i("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ i("polyline", { points: "9 18 15 12 9 6" }) })
53
86
  }
54
- )
55
- ]
87
+ ) })
88
+ ] })
56
89
  }
57
90
  );
58
91
  }
59
92
  export {
60
- p as Pagination
93
+ M as Pagination
61
94
  };
62
95
  //# sourceMappingURL=Pagination.js.map