@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
@@ -1,52 +1,105 @@
1
- import { jsxs as l, jsx as i } from "react/jsx-runtime";
2
- import { useState as f, useCallback as h, createContext as p, useContext as v } from "react";
3
- import { Portal as T } from "../../utils/portal/portal.js";
1
+ import { jsxs as m, jsx as o } from "react/jsx-runtime";
2
+ import { useContext as g, createContext as T, useState as p, useEffect as h, useCallback as a, useRef as y } from "react";
4
3
  /* empty css */
5
- function x({ id: e, message: s, onClose: o }) {
6
- return /* @__PURE__ */ l("div", { className: "ui-toast", role: "alert", children: [
7
- /* @__PURE__ */ i("span", { children: s }),
8
- /* @__PURE__ */ i(
9
- "button",
10
- {
11
- type: "button",
12
- "aria-label": "Close notification",
13
- onClick: () => o(e),
14
- children: "×"
15
- }
16
- )
17
- ] });
4
+ import { Portal as C } from "../../utils/portal/portal.js";
5
+ import { cn as _ } from "../../utils/cn/cn.js";
6
+ const v = T(null);
7
+ function M() {
8
+ const t = g(v);
9
+ if (!t) throw new Error("useToast must be used inside a <ToastProvider>");
10
+ return t;
18
11
  }
19
- const c = p(null);
20
- function w({ children: e }) {
21
- const [s, o] = f([]), u = h((t, n = 3e3) => {
22
- const r = Math.random().toString(36).slice(2);
23
- o((a) => [...a, { id: r, message: t }]), setTimeout(() => {
24
- o((a) => a.filter((m) => m.id !== r));
25
- }, n);
26
- }, []), d = (t) => {
27
- o((n) => n.filter((r) => r.id !== t));
28
- };
29
- return /* @__PURE__ */ l(c.Provider, { value: { show: u }, children: [
30
- e,
31
- /* @__PURE__ */ i(T, { children: /* @__PURE__ */ i(
12
+ function D({ children: t }) {
13
+ const [d, r] = p([]), [f, c] = p(!1);
14
+ h(() => {
15
+ c(!0);
16
+ }, []);
17
+ const u = a((e, s) => {
18
+ const i = typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : `toast-${Date.now()}-${Math.floor(Math.random() * 1e4)}`;
19
+ return r((x) => [...x, { id: i, message: e, ...s }]), i;
20
+ }, []), n = a((e) => {
21
+ r((s) => s.map((i) => i.id === e ? { ...i, isClosing: !0 } : i));
22
+ }, []), l = a((e) => {
23
+ r((s) => s.filter((i) => i.id !== e));
24
+ }, []);
25
+ return /* @__PURE__ */ m(v.Provider, { value: { show: u, dismiss: n }, children: [
26
+ t,
27
+ f && /* @__PURE__ */ o(C, { children: /* @__PURE__ */ o(
32
28
  "div",
33
29
  {
34
- className: "ui-toast-container",
30
+ className: "nui-toast-region",
35
31
  "aria-live": "polite",
36
32
  "aria-atomic": "true",
37
- children: s.map((t) => /* @__PURE__ */ i(x, { id: t.id, message: t.message, onClose: d }, t.id))
33
+ role: "region",
34
+ "aria-label": "Notifications",
35
+ children: d.map((e) => /* @__PURE__ */ o(
36
+ N,
37
+ {
38
+ toast: e,
39
+ onDismiss: () => n(e.id),
40
+ onRemove: () => l(e.id)
41
+ },
42
+ e.id
43
+ ))
38
44
  }
39
45
  ) })
40
46
  ] });
41
47
  }
42
- function j() {
43
- const e = v(c);
44
- if (!e) throw new Error("useToast must be used inside <ToastProvider>");
45
- return e;
48
+ function N({ toast: t, onRemove: d }) {
49
+ const [r, f] = p(!1), c = y(null), u = t.duration !== void 0 ? t.duration : 4e3, n = a(() => {
50
+ f(!0), setTimeout(() => {
51
+ d();
52
+ }, 200);
53
+ }, [d]);
54
+ h(() => {
55
+ t.isClosing && n();
56
+ }, [t.isClosing, n]);
57
+ const l = a(() => {
58
+ u === 1 / 0 || r || (c.current = setTimeout(() => {
59
+ n();
60
+ }, u));
61
+ }, [u, r, n]), e = a(() => {
62
+ c.current && clearTimeout(c.current);
63
+ }, []);
64
+ h(() => (l(), e), [l, e]);
65
+ const s = t.variant === "error" ? "alert" : "status";
66
+ return /* @__PURE__ */ m(
67
+ "div",
68
+ {
69
+ className: _(
70
+ "nui-toast",
71
+ `nui-toast--${t.variant || "default"}`
72
+ ),
73
+ "data-state": r ? "closed" : "open",
74
+ onMouseEnter: e,
75
+ onMouseLeave: l,
76
+ role: s,
77
+ children: [
78
+ /* @__PURE__ */ m("div", { className: "nui-toast__content", children: [
79
+ /* @__PURE__ */ o("strong", { className: "nui-toast__title", children: t.message }),
80
+ t.description && /* @__PURE__ */ o("p", { className: "nui-toast__description", children: t.description })
81
+ ] }),
82
+ /* @__PURE__ */ o(
83
+ "button",
84
+ {
85
+ type: "button",
86
+ "aria-label": "Close notification",
87
+ className: "nui-toast__close",
88
+ onClick: (i) => {
89
+ i.preventDefault(), e(), n();
90
+ },
91
+ children: /* @__PURE__ */ m("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
92
+ /* @__PURE__ */ o("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
93
+ /* @__PURE__ */ o("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
94
+ ] })
95
+ }
96
+ )
97
+ ]
98
+ }
99
+ );
46
100
  }
47
101
  export {
48
- x as Toast,
49
- w as ToastProvider,
50
- j as useToast
102
+ D as ToastProvider,
103
+ M as useToast
51
104
  };
52
105
  //# sourceMappingURL=Toast.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.js","sources":["../../../src/components/toast/Toast.tsx"],"sourcesContent":["/**\r\n * Toast.tsx\r\n * ----------\r\n * Basic toast component UI. The provider handles logic.\r\n * ------------------\r\n * - Global provider that renders all toasts\r\n * - Contains aria-live region for screen readers\r\n * - Handles auto-dismiss\r\n * - Provides useToast() hook\r\n */\r\n\r\nimport React, { createContext, useContext, useState, useCallback } from 'react';\r\nimport { Portal } from '../../utils/portal/portal';\r\nimport './Toast.css';\r\n\r\ninterface ToastItem {\r\n id: string;\r\n message: string;\r\n}\r\n\r\ninterface ToastContextValue {\r\n show: (message: string, timeout?: number) => void;\r\n}\r\n\r\ninterface ToastProps {\r\n id: string;\r\n message: string;\r\n onClose: (id: string) => void;\r\n}\r\n\r\nexport function Toast({ id, message, onClose }: ToastProps) {\r\n return (\r\n <div className=\"ui-toast\" role=\"alert\">\r\n <span>{message}</span>\r\n <button\r\n type=\"button\"\r\n aria-label=\"Close notification\"\r\n onClick={() => onClose(id)}\r\n >\r\n ×\r\n </button>\r\n </div>\r\n );\r\n}\r\n\r\nconst ToastContext = createContext<ToastContextValue | null>(null);\r\n\r\nexport function ToastProvider({ children }: { children: React.ReactNode }) {\r\n const [toasts, setToasts] = useState<ToastItem[]>([]);\r\n\r\n const show = useCallback((message: string, timeout = 3000) => {\r\n const id = Math.random().toString(36).slice(2);\r\n\r\n setToasts((prev) => [...prev, { id, message }]);\r\n\r\n setTimeout(() => {\r\n setToasts((prev) => prev.filter((t) => t.id !== id));\r\n }, timeout);\r\n }, []);\r\n\r\n const remove = (id: string) => {\r\n setToasts((prev) => prev.filter((t) => t.id !== id));\r\n };\r\n\r\n return (\r\n <ToastContext.Provider value={{ show }}>\r\n {/* Main app */}\r\n {children}\r\n\r\n {/* Portal for notification list */}\r\n <Portal>\r\n <div\r\n className=\"ui-toast-container\"\r\n aria-live=\"polite\"\r\n aria-atomic=\"true\"\r\n >\r\n {toasts.map((t) => (\r\n <Toast key={t.id} id={t.id} message={t.message} onClose={remove} />\r\n ))}\r\n </div>\r\n </Portal>\r\n </ToastContext.Provider>\r\n );\r\n}\r\n\r\nexport function useToast() {\r\n const ctx = useContext(ToastContext);\r\n if (!ctx) throw new Error('useToast must be used inside <ToastProvider>');\r\n return ctx;\r\n}\r\n"],"names":["Toast","id","message","onClose","jsxs","jsx","ToastContext","createContext","ToastProvider","children","toasts","setToasts","useState","show","useCallback","timeout","prev","t","remove","Portal","useToast","ctx","useContext"],"mappings":";;;;AA8BO,SAASA,EAAM,EAAE,IAAAC,GAAI,SAAAC,GAAS,SAAAC,KAAuB;AAC1D,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAU,YAAW,MAAK,SAC7B,UAAA;AAAA,IAAA,gBAAAC,EAAC,UAAM,UAAAH,EAAA,CAAQ;AAAA,IACf,gBAAAG;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAW;AAAA,QACX,SAAS,MAAMF,EAAQF,CAAE;AAAA,QAC1B,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAED,GACF;AAEJ;AAEA,MAAMK,IAAeC,EAAwC,IAAI;AAE1D,SAASC,EAAc,EAAE,UAAAC,KAA2C;AACzE,QAAM,CAACC,GAAQC,CAAS,IAAIC,EAAsB,CAAA,CAAE,GAE9CC,IAAOC,EAAY,CAACZ,GAAiBa,IAAU,QAAS;AAC5D,UAAMd,IAAK,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,CAAC;AAE7C,IAAAU,EAAU,CAACK,MAAS,CAAC,GAAGA,GAAM,EAAE,IAAAf,GAAI,SAAAC,EAAA,CAAS,CAAC,GAE9C,WAAW,MAAM;AACf,MAAAS,EAAU,CAACK,MAASA,EAAK,OAAO,CAACC,MAAMA,EAAE,OAAOhB,CAAE,CAAC;AAAA,IACrD,GAAGc,CAAO;AAAA,EACZ,GAAG,CAAA,CAAE,GAECG,IAAS,CAACjB,MAAe;AAC7B,IAAAU,EAAU,CAACK,MAASA,EAAK,OAAO,CAACC,MAAMA,EAAE,OAAOhB,CAAE,CAAC;AAAA,EACrD;AAEA,2BACGK,EAAa,UAAb,EAAsB,OAAO,EAAE,MAAAO,KAE7B,UAAA;AAAA,IAAAJ;AAAA,sBAGAU,GAAA,EACC,UAAA,gBAAAd;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,aAAU;AAAA,QACV,eAAY;AAAA,QAEX,YAAO,IAAI,CAAC,MACX,gBAAAA,EAACL,KAAiB,IAAI,EAAE,IAAI,SAAS,EAAE,SAAS,SAASkB,EAAA,GAA7C,EAAE,EAAmD,CAClE;AAAA,MAAA;AAAA,IAAA,EACH,CACF;AAAA,EAAA,GACF;AAEJ;AAEO,SAASE,IAAW;AACzB,QAAMC,IAAMC,EAAWhB,CAAY;AACnC,MAAI,CAACe,EAAK,OAAM,IAAI,MAAM,8CAA8C;AACxE,SAAOA;AACT;"}
1
+ {"version":3,"file":"Toast.js","sources":["../../../src/components/toast/Toast.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { createContext, useContext, useState, useCallback, useEffect, useRef } from 'react';\nimport { cn } from '../../utils';\nimport { Portal } from '../../utils';\nimport './Toast.css';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport type ToastVariant = 'default' | 'success' | 'error' | 'warning';\n\nexport interface ToastOptions {\n /** Time in milliseconds before the toast auto-dismisses. Set to Infinity to disable. Defaults to 4000. */\n duration?: number;\n /** The semantic visual variant of the toast. Defaults to 'default'. */\n variant?: ToastVariant;\n /** Secondary descriptive text displayed below the main message. */\n description?: React.ReactNode;\n}\n\nexport interface ToastData extends ToastOptions {\n id: string;\n message: React.ReactNode;\n}\n\ninterface ToastContextValue {\n /** Displays a new toast notification and returns its unique ID */\n show: (message: React.ReactNode, options?: ToastOptions) => string;\n /** Programmatically triggers the exit animation and removes the toast by ID */\n dismiss: (id: string) => void;\n}\n\n/* ============================================================\n * Context\n * ============================================================ */\n\nconst ToastContext = createContext<ToastContextValue | null>(null);\n\nexport function useToast() {\n const ctx = useContext(ToastContext);\n if (!ctx) throw new Error('useToast must be used inside a <ToastProvider>');\n return ctx;\n}\n\n/* ============================================================\n * 1. Provider & Container\n * ============================================================ */\n\n/**\n * Toast Provider\n * * Wraps your application to provide the `useToast` hook.\n * * Automatically manages the WAI-ARIA live region Portal for rendering notifications.\n * * Note: Does not use `forwardRef` as it strictly returns a Context Provider and a Portal.\n */\nexport function ToastProvider({ children }: { children: React.ReactNode }) {\n const [toasts, setToasts] = useState<ToastData[]>([]);\n const [isMounted, setIsMounted] = useState(false);\n\n // Prevent SSR Hydration mismatch for the Portal by only mounting the region on the client\n useEffect(() => {\n setIsMounted(true);\n }, []);\n\n const show = useCallback((message: React.ReactNode, options?: ToastOptions) => {\n // Generate a secure, unique ID without relying on math.random() alone\n const id = typeof crypto !== 'undefined' && crypto.randomUUID \n ? crypto.randomUUID() \n : `toast-${Date.now()}-${Math.floor(Math.random() * 10000)}`;\n\n setToasts((prev) => [...prev, { id, message, ...options }]);\n return id;\n }, []);\n\n const dismiss = useCallback((id: string) => {\n // We don't remove it from the array immediately. \n // Flagging it triggers the ToastItem's CSS exit animation, which then calls remove() safely.\n setToasts((prev) => prev.map((t) => (t.id === id ? { ...t, isClosing: true } : t)));\n }, []);\n\n const remove = useCallback((id: string) => {\n setToasts((prev) => prev.filter((t) => t.id !== id));\n }, []);\n\n return (\n <ToastContext.Provider value={{ show, dismiss }}>\n {children}\n\n {isMounted && (\n <Portal>\n <div\n className=\"nui-toast-region\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n role=\"region\"\n aria-label=\"Notifications\"\n >\n {toasts.map((toast) => (\n <ToastItem \n key={toast.id} \n toast={toast} \n onDismiss={() => dismiss(toast.id)} \n onRemove={() => remove(toast.id)} \n />\n ))}\n </div>\n </Portal>\n )}\n </ToastContext.Provider>\n );\n}\n\n/* ============================================================\n * 2. Individual Toast Item (Smart Component)\n * ============================================================ */\n\ninterface ToastItemProps {\n toast: ToastData & { isClosing?: boolean };\n onDismiss: () => void;\n onRemove: () => void;\n}\n\nfunction ToastItem({ toast, onRemove }: ToastItemProps) {\n const [isExiting, setIsExiting] = useState(false);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Duration defaults to 4000ms. Set to Infinity to disable auto-close.\n const duration = toast.duration !== undefined ? toast.duration : 4000;\n\n // 1. Handle Animation and Removal\n const triggerExit = useCallback(() => {\n setIsExiting(true);\n // Wait for the CSS exit animation to finish before destroying the DOM node (matches CSS 0.2s duration)\n setTimeout(() => {\n onRemove();\n }, 200); \n }, [onRemove]);\n\n // If the provider tells us to close programmatically, trigger exit\n useEffect(() => {\n if (toast.isClosing) triggerExit();\n }, [toast.isClosing, triggerExit]);\n\n // 2. Timer Management (Pause on Hover)\n const startTimer = useCallback(() => {\n if (duration === Infinity || isExiting) return;\n timerRef.current = setTimeout(() => {\n triggerExit();\n }, duration);\n }, [duration, isExiting, triggerExit]);\n\n const clearTimer = useCallback(() => {\n if (timerRef.current) clearTimeout(timerRef.current);\n }, []);\n\n // Start timer on mount\n useEffect(() => {\n startTimer();\n return clearTimer;\n }, [startTimer, clearTimer]);\n\n // 3. Render\n // Critical WAI-ARIA logic: Errors must use role=\"alert\" to interrupt screen readers immediately.\n const role = toast.variant === 'error' ? 'alert' : 'status';\n\n return (\n <div\n className={cn(\n 'nui-toast',\n `nui-toast--${toast.variant || 'default'}`,\n )}\n data-state={isExiting ? 'closed' : 'open'}\n onMouseEnter={clearTimer}\n onMouseLeave={startTimer}\n role={role}\n >\n <div className=\"nui-toast__content\">\n <strong className=\"nui-toast__title\">{toast.message}</strong>\n {toast.description && (\n <p className=\"nui-toast__description\">{toast.description}</p>\n )}\n </div>\n\n <button\n type=\"button\"\n aria-label=\"Close notification\"\n className=\"nui-toast__close\"\n onClick={(e) => {\n e.preventDefault();\n clearTimer();\n triggerExit();\n }}\n >\n {/* Simple crisp SVG close icon */}\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 <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n </div>\n );\n}"],"names":["ToastContext","createContext","useToast","ctx","useContext","ToastProvider","children","toasts","setToasts","useState","isMounted","setIsMounted","useEffect","show","useCallback","message","options","id","prev","dismiss","t","remove","jsxs","Portal","jsx","toast","ToastItem","onRemove","isExiting","setIsExiting","timerRef","useRef","duration","triggerExit","startTimer","clearTimer","role","cn","e"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),e=require("react");;/* empty css */const P=require("../../utils/portal/portal.cjs");function S({label:g,children:R,className:E="",delay:y=200,offset:i=8}){const[o,p]=e.useState(!1),[m,h]=e.useState({top:0,left:0}),[L,x]=e.useState("top"),c=e.useRef(null),l=e.useRef(null),r=e.useRef(null),w=`tooltip-${e.useId()}`,v=()=>{r.current=window.setTimeout(()=>{p(!0)},y)},u=()=>{r.current&&clearTimeout(r.current),p(!1)},n=e.useCallback(()=>{if(!c.current||!l.current)return;const t=c.current.getBoundingClientRect(),a=l.current.getBoundingClientRect(),j=window.scrollX,d=window.scrollY,T=t.left+j+t.width/2;let f=t.top+d-a.height-i,b="top";f<d+8&&(f=t.bottom+d+i,b="bottom"),x(b),h({top:f,left:T})},[i]);return e.useLayoutEffect(()=>{if(o)return n(),window.addEventListener("scroll",n,!0),window.addEventListener("resize",n),()=>{window.removeEventListener("scroll",n,!0),window.removeEventListener("resize",n)}},[o,n]),e.useEffect(()=>{if(!o)return;const t=a=>{a.key==="Escape"&&u()};return document.addEventListener("keydown",t),()=>document.removeEventListener("keydown",t)},[o]),e.useEffect(()=>()=>{r.current&&clearTimeout(r.current)},[]),s.jsxs(s.Fragment,{children:[s.jsx("span",{ref:c,className:"ui-tooltip-container","aria-describedby":o?w:void 0,onMouseEnter:v,onMouseLeave:u,onFocus:v,onBlur:u,tabIndex:0,children:R}),o&&s.jsx(P.Portal,{children:s.jsx("div",{ref:l,id:w,role:"tooltip","data-placement":L,className:`ui-tooltip-bubble ${E}`,style:{position:"absolute",top:m.top,left:m.left},children:g})})]})}exports.Tooltip=S;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("react/jsx-runtime"),t=require("react");;/* empty css */const X=require("../../utils/portal/portal.cjs"),Y=require("../../utils/cn/cn.cjs");function $({label:j,children:k,className:P,delay:h=200,offset:a=8}){const[c,g]=t.useState(!1),[p,q]=t.useState({top:0,left:0,arrowLeft:50}),[I,S]=t.useState("top"),w=t.useRef(null),m=t.useRef(null),r=t.useRef(null),E=`tooltip-${t.useId()}`,L=t.useCallback(()=>{r.current&&clearTimeout(r.current),r.current=setTimeout(()=>{g(!0)},h)},[h]),d=t.useCallback(()=>{r.current&&clearTimeout(r.current),g(!1)},[]),i=t.useCallback(()=>{if(!w.current||!m.current)return;const e=w.current.getBoundingClientRect(),o=m.current.getBoundingClientRect(),O=window.scrollX,v=window.scrollY,R=e.left+O+e.width/2;let l=R;const y=o.width/2+8,b=document.documentElement.clientWidth-o.width/2-8;l<y&&(l=y),l>b&&(l=b);const z=l-o.width/2;let u=R-z;const x=12,C=o.width-12;u<x&&(u=x),u>C&&(u=C);let M=e.top+v-o.height-a,T="top";e.top-o.height-a<0&&(M=e.bottom+v+a,T="bottom"),S(T),q({top:M,left:l,arrowLeft:u})},[a]);t.useLayoutEffect(()=>{if(c)return i(),window.addEventListener("scroll",i,!0),window.addEventListener("resize",i),()=>{window.removeEventListener("scroll",i,!0),window.removeEventListener("resize",i)}},[c,i]),t.useEffect(()=>{if(!c)return;const e=o=>{o.key==="Escape"&&d()};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[c,d]),t.useEffect(()=>()=>{r.current&&clearTimeout(r.current)},[]);const n=t.Children.only(k),s=n.props.ref??n.ref,B={ref:e=>{e&&(w.current=e,typeof s=="function"?s(e):s&&typeof s=="object"&&"current"in s&&(s.current=e))},"aria-describedby":c?E:void 0,onMouseEnter:e=>{L(),n.props.onMouseEnter?.(e)},onMouseLeave:e=>{d(),n.props.onMouseLeave?.(e)},onFocus:e=>{L(),n.props.onFocus?.(e)},onBlur:e=>{d(),n.props.onBlur?.(e)}},F=t.cloneElement(n,B);return f.jsxs(f.Fragment,{children:[F,c&&f.jsx(X.Portal,{children:f.jsx("div",{ref:m,id:E,role:"tooltip","data-placement":I,className:Y.cn("nui-tooltip",P),style:{position:"absolute",top:p.top,left:p.left,"--nui-tooltip-arrow-x":`${p.arrowLeft}px`},children:j})})]})}exports.Tooltip=$;
2
2
  //# sourceMappingURL=Tooltip.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.cjs","sources":["../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["import React, {\r\n useState,\r\n useRef,\r\n useLayoutEffect,\r\n useEffect,\r\n useCallback,\r\n useId,\r\n} from 'react';\r\nimport './Tooltip.css';\r\nimport { Portal } from '../../utils/portal/portal';\r\n\r\ntype Placement = 'top' | 'bottom';\r\n\r\nexport interface TooltipProps {\r\n label: string;\r\n children: React.ReactNode;\r\n className?: string;\r\n delay?: number;\r\n offset?: number;\r\n}\r\n\r\nexport function Tooltip({\r\n label,\r\n children,\r\n className = '',\r\n delay = 200,\r\n offset = 8,\r\n}: TooltipProps) {\r\n const [open, setOpen] = useState(false);\r\n const [coords, setCoords] = useState({ top: 0, left: 0 });\r\n const [placement, setPlacement] = useState<Placement>('top');\r\n\r\n const triggerRef = useRef<HTMLSpanElement | null>(null);\r\n const tooltipRef = useRef<HTMLDivElement | null>(null);\r\nconst timeoutRef = useRef<number | null>(null);\r\n\r\n const id = `tooltip-${useId()}`;\r\n\r\n /* ---------------- Visibility ---------------- */\r\n\r\n const show = () => {\r\n timeoutRef.current = window.setTimeout(() => {\r\n setOpen(true);\r\n }, delay);\r\n };\r\n\r\n const hide = () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n setOpen(false);\r\n };\r\n\r\n /* ---------------- Positioning ---------------- */\r\n\r\n const updatePosition = useCallback(() => {\r\n if (!triggerRef.current || !tooltipRef.current) return;\r\n\r\n const triggerRect = triggerRef.current.getBoundingClientRect();\r\n const tooltipRect = tooltipRef.current.getBoundingClientRect();\r\n\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n\r\n const centerX =\r\n triggerRect.left + scrollX + triggerRect.width / 2;\r\n\r\n // Try top first\r\n let top =\r\n triggerRect.top +\r\n scrollY -\r\n tooltipRect.height -\r\n offset;\r\n\r\n let nextPlacement: Placement = 'top';\r\n\r\n // Flip to bottom if clipped\r\n if (top < scrollY + 8) {\r\n top =\r\n triggerRect.bottom +\r\n scrollY +\r\n offset;\r\n nextPlacement = 'bottom';\r\n }\r\n\r\n setPlacement(nextPlacement);\r\n setCoords({ top, left: centerX });\r\n }, [offset]);\r\n\r\n /* ---------------- Effects ---------------- */\r\n\r\n useLayoutEffect(() => {\r\n if (!open) return;\r\n\r\n updatePosition();\r\n\r\n window.addEventListener('scroll', updatePosition, true);\r\n window.addEventListener('resize', updatePosition);\r\n\r\n return () => {\r\n window.removeEventListener('scroll', updatePosition, true);\r\n window.removeEventListener('resize', updatePosition);\r\n };\r\n }, [open, updatePosition]);\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n\r\n const onKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') hide();\r\n };\r\n\r\n document.addEventListener('keydown', onKeyDown);\r\n return () => document.removeEventListener('keydown', onKeyDown);\r\n }, [open]);\r\n\r\n useEffect(() => {\r\n return () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n };\r\n }, []);\r\n\r\n /* ---------------- Render ---------------- */\r\n\r\n return (\r\n <>\r\n <span\r\n ref={triggerRef}\r\n className=\"ui-tooltip-container\"\r\n aria-describedby={open ? id : undefined}\r\n onMouseEnter={show}\r\n onMouseLeave={hide}\r\n onFocus={show}\r\n onBlur={hide}\r\n tabIndex={0}\r\n >\r\n {children}\r\n </span>\r\n\r\n {open && (\r\n <Portal>\r\n <div\r\n ref={tooltipRef}\r\n id={id}\r\n role=\"tooltip\"\r\n data-placement={placement}\r\n className={`ui-tooltip-bubble ${className}`}\r\n style={{\r\n position: 'absolute',\r\n top: coords.top,\r\n left: coords.left,\r\n }}\r\n >\r\n {label}\r\n </div>\r\n </Portal>\r\n )}\r\n </>\r\n );\r\n}\r\n"],"names":["Tooltip","label","children","className","delay","offset","open","setOpen","useState","coords","setCoords","placement","setPlacement","triggerRef","useRef","tooltipRef","timeoutRef","id","useId","show","hide","updatePosition","useCallback","triggerRect","tooltipRect","scrollX","scrollY","centerX","top","nextPlacement","useLayoutEffect","useEffect","onKeyDown","e","jsxs","Fragment","jsx","Portal"],"mappings":"sNAqBO,SAASA,EAAQ,CACtB,MAAAC,EACA,SAAAC,EACA,UAAAC,EAAY,GACZ,MAAAC,EAAQ,IACR,OAAAC,EAAS,CACX,EAAiB,CACf,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAS,EAAK,EAChC,CAACC,EAAQC,CAAS,EAAIF,EAAAA,SAAS,CAAE,IAAK,EAAG,KAAM,EAAG,EAClD,CAACG,EAAWC,CAAY,EAAIJ,EAAAA,SAAoB,KAAK,EAErDK,EAAaC,EAAAA,OAA+B,IAAI,EAChDC,EAAaD,EAAAA,OAA8B,IAAI,EACjDE,EAAaF,EAAAA,OAAsB,IAAI,EAErCG,EAAK,WAAWC,EAAAA,MAAA,CAAO,GAIvBC,EAAO,IAAM,CACjBH,EAAW,QAAU,OAAO,WAAW,IAAM,CAC3CT,EAAQ,EAAI,CACd,EAAGH,CAAK,CACV,EAEMgB,EAAO,IAAM,CACbJ,EAAW,SAAS,aAAaA,EAAW,OAAO,EACvDT,EAAQ,EAAK,CACf,EAIMc,EAAiBC,EAAAA,YAAY,IAAM,CACvC,GAAI,CAACT,EAAW,SAAW,CAACE,EAAW,QAAS,OAEhD,MAAMQ,EAAcV,EAAW,QAAQ,sBAAA,EACjCW,EAAcT,EAAW,QAAQ,sBAAA,EAEjCU,EAAU,OAAO,QACjBC,EAAU,OAAO,QAEjBC,EACJJ,EAAY,KAAOE,EAAUF,EAAY,MAAQ,EAGnD,IAAIK,EACFL,EAAY,IACZG,EACAF,EAAY,OACZnB,EAEEwB,EAA2B,MAG3BD,EAAMF,EAAU,IAClBE,EACEL,EAAY,OACZG,EACArB,EACFwB,EAAgB,UAGlBjB,EAAaiB,CAAa,EAC1BnB,EAAU,CAAE,IAAAkB,EAAK,KAAMD,CAAA,CAAS,CAClC,EAAG,CAACtB,CAAM,CAAC,EAIXyB,OAAAA,EAAAA,gBAAgB,IAAM,CACpB,GAAKxB,EAEL,OAAAe,EAAA,EAEA,OAAO,iBAAiB,SAAUA,EAAgB,EAAI,EACtD,OAAO,iBAAiB,SAAUA,CAAc,EAEzC,IAAM,CACX,OAAO,oBAAoB,SAAUA,EAAgB,EAAI,EACzD,OAAO,oBAAoB,SAAUA,CAAc,CACrD,CACF,EAAG,CAACf,EAAMe,CAAc,CAAC,EAEzBU,EAAAA,UAAU,IAAM,CACd,GAAI,CAACzB,EAAM,OAEX,MAAM0B,EAAaC,GAAqB,CAClCA,EAAE,MAAQ,UAAUb,EAAA,CAC1B,EAEA,gBAAS,iBAAiB,UAAWY,CAAS,EACvC,IAAM,SAAS,oBAAoB,UAAWA,CAAS,CAChE,EAAG,CAAC1B,CAAI,CAAC,EAETyB,EAAAA,UAAU,IACD,IAAM,CACPf,EAAW,SAAS,aAAaA,EAAW,OAAO,CACzD,EACC,CAAA,CAAE,EAKHkB,EAAAA,KAAAC,WAAA,CACE,SAAA,CAAAC,EAAAA,IAAC,OAAA,CACC,IAAKvB,EACL,UAAU,uBACV,mBAAkBP,EAAOW,EAAK,OAC9B,aAAcE,EACd,aAAcC,EACd,QAASD,EACT,OAAQC,EACR,SAAU,EAET,SAAAlB,CAAA,CAAA,EAGFI,SACE+B,SAAA,CACC,SAAAD,EAAAA,IAAC,MAAA,CACC,IAAKrB,EACL,GAAAE,EACA,KAAK,UACL,iBAAgBN,EAChB,UAAW,qBAAqBR,CAAS,GACzC,MAAO,CACL,SAAU,WACV,IAAKM,EAAO,IACZ,KAAMA,EAAO,IAAA,EAGd,SAAAR,CAAA,CAAA,CACH,CACF,CAAA,EAEJ,CAEJ"}
1
+ {"version":3,"file":"Tooltip.cjs","sources":["../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["\"use client\";\n\nimport React, {\n useState,\n useRef,\n useLayoutEffect,\n useEffect,\n useCallback,\n useId,\n} from 'react';\nimport { cn } from '../../utils';\nimport { Portal } from '../../utils';\nimport './Tooltip.css';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport type TooltipPlacement = 'top' | 'bottom';\n\nexport interface TooltipProps {\n /** The text or content displayed inside the tooltip */\n label: React.ReactNode;\n /** The trigger element. Must be a single valid React Element (like a button) */\n children: React.ReactElement;\n /** Additional CSS classes for the tooltip container */\n className?: string;\n /** Delay in milliseconds before showing the tooltip on hover/focus. Defaults to 200. */\n delay?: number;\n /** Distance in pixels between the tooltip and the trigger. Defaults to 8. */\n offset?: number;\n}\n\n/* ============================================================\n * Component\n * ============================================================ */\n\n/**\n * Tooltip Component\n * * A contextual popup that displays information when hovering or focusing an element.\n * * Uses a custom math engine to calculate collision-safe positioning and dynamic arrow rendering.\n */\nexport function Tooltip({\n label,\n children,\n className,\n delay = 200,\n offset = 8,\n}: TooltipProps) {\n const [isOpen, setIsOpen] = useState(false);\n // ArrowLeft is injected as a CSS custom property to slide the pseudo-element arrow!\n const [coords, setCoords] = useState({ top: 0, left: 0, arrowLeft: 50 });\n const [placement, setPlacement] = useState<TooltipPlacement>('top');\n\n const triggerRef = useRef<HTMLElement>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const reactId = useId();\n const tooltipId = `tooltip-${reactId}`;\n\n /* ----------------------------------------------------\n Visibility\n ---------------------------------------------------- */\n const show = useCallback(() => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n timeoutRef.current = setTimeout(() => {\n setIsOpen(true);\n }, delay);\n }, [delay]);\n\n const hide = useCallback(() => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n setIsOpen(false);\n }, []);\n\n /* ----------------------------------------------------\n Positioning Engine\n ---------------------------------------------------- */\n const updatePosition = useCallback(() => {\n if (!triggerRef.current || !tooltipRef.current) return;\n\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const tooltipRect = tooltipRef.current.getBoundingClientRect();\n\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n\n // 1. Calculate ideal X (Center of the trigger)\n const actualCenter = triggerRect.left + scrollX + triggerRect.width / 2;\n let left = actualCenter;\n \n // Prevent bleeding off left/right edges of the viewport\n const minLeft = tooltipRect.width / 2 + 8;\n const maxLeft = document.documentElement.clientWidth - (tooltipRect.width / 2) - 8;\n if (left < minLeft) left = minLeft;\n if (left > maxLeft) left = maxLeft;\n\n // 2. Arrow offset math (Keep arrow pointing at trigger even if the box got clamped)\n const physicalLeftEdge = left - (tooltipRect.width / 2);\n let arrowLeft = actualCenter - physicalLeftEdge;\n\n // Clamp arrow so it doesn't break out of the rounded corners of the tooltip box\n const arrowMin = 12;\n const arrowMax = tooltipRect.width - 12;\n if (arrowLeft < arrowMin) arrowLeft = arrowMin;\n if (arrowLeft > arrowMax) arrowLeft = arrowMax;\n\n // 3. Calculate Y\n let top = triggerRect.top + scrollY - tooltipRect.height - offset;\n let nextPlacement: TooltipPlacement = 'top';\n\n // Flip to bottom if there is no space at the top of the viewport\n if (triggerRect.top - tooltipRect.height - offset < 0) {\n top = triggerRect.bottom + scrollY + offset;\n nextPlacement = 'bottom';\n }\n\n setPlacement(nextPlacement);\n setCoords({ top, left, arrowLeft });\n }, [offset]);\n\n /* ----------------------------------------------------\n Effects\n ---------------------------------------------------- */\n useLayoutEffect(() => {\n if (!isOpen) return;\n updatePosition();\n window.addEventListener('scroll', updatePosition, true);\n window.addEventListener('resize', updatePosition);\n return () => {\n window.removeEventListener('scroll', updatePosition, true);\n window.removeEventListener('resize', updatePosition);\n };\n }, [isOpen, updatePosition]);\n\n useEffect(() => {\n if (!isOpen) return;\n const onKeyDown = (e: KeyboardEvent) => {\n // WAI-ARIA states Tooltips must close on Escape\n if (e.key === 'Escape') hide();\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [isOpen, hide]);\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, []);\n\n /* ----------------------------------------------------\n Render\n ---------------------------------------------------- */\n \n // 1. Extract the child and type it to include ALL HTML props + Ref attributes\n const child = React.Children.only(children) as React.ReactElement<React.HTMLProps<HTMLElement>>;\n\n // 2. Safely extract the original ref (Handles both React 18 element refs and React 19 prop refs)\n const childRef = child.props.ref ?? (child as unknown as { ref?: React.Ref<HTMLElement> }).ref;\n\n // 3. Explicitly type the new props object so TypeScript knows 'ref' is allowed\n const triggerProps: React.HTMLProps<HTMLElement> = {\n ref: (node: HTMLElement | null) => {\n if (!node) return;\n \n // Assign to our internal ref for positioning math\n triggerRef.current = node;\n \n // Preserve user's ref if they passed one originally\n if (typeof childRef === 'function') {\n childRef(node);\n } else if (childRef && typeof childRef === 'object' && 'current' in childRef) {\n (childRef as { current: HTMLElement | null }).current = node;\n }\n },\n 'aria-describedby': isOpen ? tooltipId : undefined,\n onMouseEnter: (e: React.MouseEvent<HTMLElement>) => {\n show();\n child.props.onMouseEnter?.(e);\n },\n onMouseLeave: (e: React.MouseEvent<HTMLElement>) => {\n hide();\n child.props.onMouseLeave?.(e);\n },\n onFocus: (e: React.FocusEvent<HTMLElement>) => {\n show();\n child.props.onFocus?.(e);\n },\n onBlur: (e: React.FocusEvent<HTMLElement>) => {\n hide();\n child.props.onBlur?.(e);\n },\n };\n\n // 4. Clone the child and inject the event listeners and refs\n const trigger = React.cloneElement(child, triggerProps);\n\n return (\n <>\n {trigger}\n\n {isOpen && (\n <Portal>\n <div\n ref={tooltipRef}\n id={tooltipId}\n role=\"tooltip\"\n data-placement={placement}\n className={cn('nui-tooltip', className)}\n style={{\n position: 'absolute',\n top: coords.top,\n left: coords.left,\n // Pass the arrow position dynamically to CSS!\n '--nui-tooltip-arrow-x': `${coords.arrowLeft}px`,\n } as React.CSSProperties}\n >\n {label}\n </div>\n </Portal>\n )}\n </>\n );\n}"],"names":["Tooltip","label","children","className","delay","offset","isOpen","setIsOpen","useState","coords","setCoords","placement","setPlacement","triggerRef","useRef","tooltipRef","timeoutRef","tooltipId","useId","show","useCallback","hide","updatePosition","triggerRect","tooltipRect","scrollX","scrollY","actualCenter","left","minLeft","maxLeft","physicalLeftEdge","arrowLeft","arrowMin","arrowMax","top","nextPlacement","useLayoutEffect","useEffect","onKeyDown","e","child","React","childRef","triggerProps","node","trigger","jsxs","Fragment","Portal","jsx","cn"],"mappings":"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"}
@@ -1,73 +1,89 @@
1
- import { jsxs as B, Fragment as X, jsx as a } from "react/jsx-runtime";
2
- import { useState as p, useRef as m, useId as j, useCallback as z, useLayoutEffect as F, useEffect as E } from "react";
1
+ import { jsxs as S, Fragment as W, jsx as T } from "react/jsx-runtime";
2
+ import k, { useState as m, useRef as w, useId as q, useCallback as h, useLayoutEffect as A, useEffect as B } from "react";
3
3
  /* empty css */
4
- import { Portal as I } from "../../utils/portal/portal.js";
5
- function D({
6
- label: h,
7
- children: L,
8
- className: R = "",
9
- delay: y = 200,
10
- offset: r = 8
4
+ import { Portal as G } from "../../utils/portal/portal.js";
5
+ import { cn as H } from "../../utils/cn/cn.js";
6
+ function tt({
7
+ label: j,
8
+ children: F,
9
+ className: z,
10
+ delay: g = 200,
11
+ offset: u = 8
11
12
  }) {
12
- const [t, f] = p(!1), [w, x] = p({ top: 0, left: 0 }), [k, C] = p("top"), i = m(null), s = m(null), n = m(null), v = `tooltip-${j()}`, b = () => {
13
- n.current = window.setTimeout(() => {
14
- f(!0);
15
- }, y);
16
- }, c = () => {
17
- n.current && clearTimeout(n.current), f(!1);
18
- }, o = z(() => {
19
- if (!i.current || !s.current) return;
20
- const e = i.current.getBoundingClientRect(), l = s.current.getBoundingClientRect(), P = window.scrollX, u = window.scrollY, T = e.left + P + e.width / 2;
21
- let d = e.top + u - l.height - r, g = "top";
22
- d < u + 8 && (d = e.bottom + u + r, g = "bottom"), C(g), x({ top: d, left: T });
23
- }, [r]);
24
- return F(() => {
25
- if (t)
26
- return o(), window.addEventListener("scroll", o, !0), window.addEventListener("resize", o), () => {
27
- window.removeEventListener("scroll", o, !0), window.removeEventListener("resize", o);
13
+ const [n, L] = m(!1), [d, O] = m({ top: 0, left: 0, arrowLeft: 50 }), [X, Y] = m("top"), f = w(null), a = w(null), o = w(null), E = `tooltip-${q()}`, v = h(() => {
14
+ o.current && clearTimeout(o.current), o.current = setTimeout(() => {
15
+ L(!0);
16
+ }, g);
17
+ }, [g]), p = h(() => {
18
+ o.current && clearTimeout(o.current), L(!1);
19
+ }, []), i = h(() => {
20
+ if (!f.current || !a.current) return;
21
+ const t = f.current.getBoundingClientRect(), e = a.current.getBoundingClientRect(), K = window.scrollX, y = window.scrollY, R = t.left + K + t.width / 2;
22
+ let s = R;
23
+ const x = e.width / 2 + 8, b = document.documentElement.clientWidth - e.width / 2 - 8;
24
+ s < x && (s = x), s > b && (s = b);
25
+ const N = s - e.width / 2;
26
+ let l = R - N;
27
+ const C = 12, M = e.width - 12;
28
+ l < C && (l = C), l > M && (l = M);
29
+ let I = t.top + y - e.height - u, P = "top";
30
+ t.top - e.height - u < 0 && (I = t.bottom + y + u, P = "bottom"), Y(P), O({ top: I, left: s, arrowLeft: l });
31
+ }, [u]);
32
+ A(() => {
33
+ if (n)
34
+ return i(), window.addEventListener("scroll", i, !0), window.addEventListener("resize", i), () => {
35
+ window.removeEventListener("scroll", i, !0), window.removeEventListener("resize", i);
28
36
  };
29
- }, [t, o]), E(() => {
30
- if (!t) return;
31
- const e = (l) => {
32
- l.key === "Escape" && c();
37
+ }, [n, i]), B(() => {
38
+ if (!n) return;
39
+ const t = (e) => {
40
+ e.key === "Escape" && p();
33
41
  };
34
- return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
35
- }, [t]), E(() => () => {
36
- n.current && clearTimeout(n.current);
37
- }, []), /* @__PURE__ */ B(X, { children: [
38
- /* @__PURE__ */ a(
39
- "span",
40
- {
41
- ref: i,
42
- className: "ui-tooltip-container",
43
- "aria-describedby": t ? v : void 0,
44
- onMouseEnter: b,
45
- onMouseLeave: c,
46
- onFocus: b,
47
- onBlur: c,
48
- tabIndex: 0,
49
- children: L
50
- }
51
- ),
52
- t && /* @__PURE__ */ a(I, { children: /* @__PURE__ */ a(
42
+ return document.addEventListener("keydown", t), () => document.removeEventListener("keydown", t);
43
+ }, [n, p]), B(() => () => {
44
+ o.current && clearTimeout(o.current);
45
+ }, []);
46
+ const r = k.Children.only(F), c = r.props.ref ?? r.ref, $ = {
47
+ ref: (t) => {
48
+ t && (f.current = t, typeof c == "function" ? c(t) : c && typeof c == "object" && "current" in c && (c.current = t));
49
+ },
50
+ "aria-describedby": n ? E : void 0,
51
+ onMouseEnter: (t) => {
52
+ v(), r.props.onMouseEnter?.(t);
53
+ },
54
+ onMouseLeave: (t) => {
55
+ p(), r.props.onMouseLeave?.(t);
56
+ },
57
+ onFocus: (t) => {
58
+ v(), r.props.onFocus?.(t);
59
+ },
60
+ onBlur: (t) => {
61
+ p(), r.props.onBlur?.(t);
62
+ }
63
+ }, D = k.cloneElement(r, $);
64
+ return /* @__PURE__ */ S(W, { children: [
65
+ D,
66
+ n && /* @__PURE__ */ T(G, { children: /* @__PURE__ */ T(
53
67
  "div",
54
68
  {
55
- ref: s,
56
- id: v,
69
+ ref: a,
70
+ id: E,
57
71
  role: "tooltip",
58
- "data-placement": k,
59
- className: `ui-tooltip-bubble ${R}`,
72
+ "data-placement": X,
73
+ className: H("nui-tooltip", z),
60
74
  style: {
61
75
  position: "absolute",
62
- top: w.top,
63
- left: w.left
76
+ top: d.top,
77
+ left: d.left,
78
+ // Pass the arrow position dynamically to CSS!
79
+ "--nui-tooltip-arrow-x": `${d.arrowLeft}px`
64
80
  },
65
- children: h
81
+ children: j
66
82
  }
67
83
  ) })
68
84
  ] });
69
85
  }
70
86
  export {
71
- D as Tooltip
87
+ tt as Tooltip
72
88
  };
73
89
  //# sourceMappingURL=Tooltip.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.js","sources":["../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["import React, {\r\n useState,\r\n useRef,\r\n useLayoutEffect,\r\n useEffect,\r\n useCallback,\r\n useId,\r\n} from 'react';\r\nimport './Tooltip.css';\r\nimport { Portal } from '../../utils/portal/portal';\r\n\r\ntype Placement = 'top' | 'bottom';\r\n\r\nexport interface TooltipProps {\r\n label: string;\r\n children: React.ReactNode;\r\n className?: string;\r\n delay?: number;\r\n offset?: number;\r\n}\r\n\r\nexport function Tooltip({\r\n label,\r\n children,\r\n className = '',\r\n delay = 200,\r\n offset = 8,\r\n}: TooltipProps) {\r\n const [open, setOpen] = useState(false);\r\n const [coords, setCoords] = useState({ top: 0, left: 0 });\r\n const [placement, setPlacement] = useState<Placement>('top');\r\n\r\n const triggerRef = useRef<HTMLSpanElement | null>(null);\r\n const tooltipRef = useRef<HTMLDivElement | null>(null);\r\nconst timeoutRef = useRef<number | null>(null);\r\n\r\n const id = `tooltip-${useId()}`;\r\n\r\n /* ---------------- Visibility ---------------- */\r\n\r\n const show = () => {\r\n timeoutRef.current = window.setTimeout(() => {\r\n setOpen(true);\r\n }, delay);\r\n };\r\n\r\n const hide = () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n setOpen(false);\r\n };\r\n\r\n /* ---------------- Positioning ---------------- */\r\n\r\n const updatePosition = useCallback(() => {\r\n if (!triggerRef.current || !tooltipRef.current) return;\r\n\r\n const triggerRect = triggerRef.current.getBoundingClientRect();\r\n const tooltipRect = tooltipRef.current.getBoundingClientRect();\r\n\r\n const scrollX = window.scrollX;\r\n const scrollY = window.scrollY;\r\n\r\n const centerX =\r\n triggerRect.left + scrollX + triggerRect.width / 2;\r\n\r\n // Try top first\r\n let top =\r\n triggerRect.top +\r\n scrollY -\r\n tooltipRect.height -\r\n offset;\r\n\r\n let nextPlacement: Placement = 'top';\r\n\r\n // Flip to bottom if clipped\r\n if (top < scrollY + 8) {\r\n top =\r\n triggerRect.bottom +\r\n scrollY +\r\n offset;\r\n nextPlacement = 'bottom';\r\n }\r\n\r\n setPlacement(nextPlacement);\r\n setCoords({ top, left: centerX });\r\n }, [offset]);\r\n\r\n /* ---------------- Effects ---------------- */\r\n\r\n useLayoutEffect(() => {\r\n if (!open) return;\r\n\r\n updatePosition();\r\n\r\n window.addEventListener('scroll', updatePosition, true);\r\n window.addEventListener('resize', updatePosition);\r\n\r\n return () => {\r\n window.removeEventListener('scroll', updatePosition, true);\r\n window.removeEventListener('resize', updatePosition);\r\n };\r\n }, [open, updatePosition]);\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n\r\n const onKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') hide();\r\n };\r\n\r\n document.addEventListener('keydown', onKeyDown);\r\n return () => document.removeEventListener('keydown', onKeyDown);\r\n }, [open]);\r\n\r\n useEffect(() => {\r\n return () => {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n };\r\n }, []);\r\n\r\n /* ---------------- Render ---------------- */\r\n\r\n return (\r\n <>\r\n <span\r\n ref={triggerRef}\r\n className=\"ui-tooltip-container\"\r\n aria-describedby={open ? id : undefined}\r\n onMouseEnter={show}\r\n onMouseLeave={hide}\r\n onFocus={show}\r\n onBlur={hide}\r\n tabIndex={0}\r\n >\r\n {children}\r\n </span>\r\n\r\n {open && (\r\n <Portal>\r\n <div\r\n ref={tooltipRef}\r\n id={id}\r\n role=\"tooltip\"\r\n data-placement={placement}\r\n className={`ui-tooltip-bubble ${className}`}\r\n style={{\r\n position: 'absolute',\r\n top: coords.top,\r\n left: coords.left,\r\n }}\r\n >\r\n {label}\r\n </div>\r\n </Portal>\r\n )}\r\n </>\r\n );\r\n}\r\n"],"names":["Tooltip","label","children","className","delay","offset","open","setOpen","useState","coords","setCoords","placement","setPlacement","triggerRef","useRef","tooltipRef","timeoutRef","id","useId","show","hide","updatePosition","useCallback","triggerRect","tooltipRect","scrollX","scrollY","centerX","top","nextPlacement","useLayoutEffect","useEffect","onKeyDown","e","jsxs","Fragment","jsx","Portal"],"mappings":"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"}
1
+ {"version":3,"file":"Tooltip.js","sources":["../../../src/components/tooltip/Tooltip.tsx"],"sourcesContent":["\"use client\";\n\nimport React, {\n useState,\n useRef,\n useLayoutEffect,\n useEffect,\n useCallback,\n useId,\n} from 'react';\nimport { cn } from '../../utils';\nimport { Portal } from '../../utils';\nimport './Tooltip.css';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport type TooltipPlacement = 'top' | 'bottom';\n\nexport interface TooltipProps {\n /** The text or content displayed inside the tooltip */\n label: React.ReactNode;\n /** The trigger element. Must be a single valid React Element (like a button) */\n children: React.ReactElement;\n /** Additional CSS classes for the tooltip container */\n className?: string;\n /** Delay in milliseconds before showing the tooltip on hover/focus. Defaults to 200. */\n delay?: number;\n /** Distance in pixels between the tooltip and the trigger. Defaults to 8. */\n offset?: number;\n}\n\n/* ============================================================\n * Component\n * ============================================================ */\n\n/**\n * Tooltip Component\n * * A contextual popup that displays information when hovering or focusing an element.\n * * Uses a custom math engine to calculate collision-safe positioning and dynamic arrow rendering.\n */\nexport function Tooltip({\n label,\n children,\n className,\n delay = 200,\n offset = 8,\n}: TooltipProps) {\n const [isOpen, setIsOpen] = useState(false);\n // ArrowLeft is injected as a CSS custom property to slide the pseudo-element arrow!\n const [coords, setCoords] = useState({ top: 0, left: 0, arrowLeft: 50 });\n const [placement, setPlacement] = useState<TooltipPlacement>('top');\n\n const triggerRef = useRef<HTMLElement>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const reactId = useId();\n const tooltipId = `tooltip-${reactId}`;\n\n /* ----------------------------------------------------\n Visibility\n ---------------------------------------------------- */\n const show = useCallback(() => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n timeoutRef.current = setTimeout(() => {\n setIsOpen(true);\n }, delay);\n }, [delay]);\n\n const hide = useCallback(() => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n setIsOpen(false);\n }, []);\n\n /* ----------------------------------------------------\n Positioning Engine\n ---------------------------------------------------- */\n const updatePosition = useCallback(() => {\n if (!triggerRef.current || !tooltipRef.current) return;\n\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const tooltipRect = tooltipRef.current.getBoundingClientRect();\n\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n\n // 1. Calculate ideal X (Center of the trigger)\n const actualCenter = triggerRect.left + scrollX + triggerRect.width / 2;\n let left = actualCenter;\n \n // Prevent bleeding off left/right edges of the viewport\n const minLeft = tooltipRect.width / 2 + 8;\n const maxLeft = document.documentElement.clientWidth - (tooltipRect.width / 2) - 8;\n if (left < minLeft) left = minLeft;\n if (left > maxLeft) left = maxLeft;\n\n // 2. Arrow offset math (Keep arrow pointing at trigger even if the box got clamped)\n const physicalLeftEdge = left - (tooltipRect.width / 2);\n let arrowLeft = actualCenter - physicalLeftEdge;\n\n // Clamp arrow so it doesn't break out of the rounded corners of the tooltip box\n const arrowMin = 12;\n const arrowMax = tooltipRect.width - 12;\n if (arrowLeft < arrowMin) arrowLeft = arrowMin;\n if (arrowLeft > arrowMax) arrowLeft = arrowMax;\n\n // 3. Calculate Y\n let top = triggerRect.top + scrollY - tooltipRect.height - offset;\n let nextPlacement: TooltipPlacement = 'top';\n\n // Flip to bottom if there is no space at the top of the viewport\n if (triggerRect.top - tooltipRect.height - offset < 0) {\n top = triggerRect.bottom + scrollY + offset;\n nextPlacement = 'bottom';\n }\n\n setPlacement(nextPlacement);\n setCoords({ top, left, arrowLeft });\n }, [offset]);\n\n /* ----------------------------------------------------\n Effects\n ---------------------------------------------------- */\n useLayoutEffect(() => {\n if (!isOpen) return;\n updatePosition();\n window.addEventListener('scroll', updatePosition, true);\n window.addEventListener('resize', updatePosition);\n return () => {\n window.removeEventListener('scroll', updatePosition, true);\n window.removeEventListener('resize', updatePosition);\n };\n }, [isOpen, updatePosition]);\n\n useEffect(() => {\n if (!isOpen) return;\n const onKeyDown = (e: KeyboardEvent) => {\n // WAI-ARIA states Tooltips must close on Escape\n if (e.key === 'Escape') hide();\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [isOpen, hide]);\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, []);\n\n /* ----------------------------------------------------\n Render\n ---------------------------------------------------- */\n \n // 1. Extract the child and type it to include ALL HTML props + Ref attributes\n const child = React.Children.only(children) as React.ReactElement<React.HTMLProps<HTMLElement>>;\n\n // 2. Safely extract the original ref (Handles both React 18 element refs and React 19 prop refs)\n const childRef = child.props.ref ?? (child as unknown as { ref?: React.Ref<HTMLElement> }).ref;\n\n // 3. Explicitly type the new props object so TypeScript knows 'ref' is allowed\n const triggerProps: React.HTMLProps<HTMLElement> = {\n ref: (node: HTMLElement | null) => {\n if (!node) return;\n \n // Assign to our internal ref for positioning math\n triggerRef.current = node;\n \n // Preserve user's ref if they passed one originally\n if (typeof childRef === 'function') {\n childRef(node);\n } else if (childRef && typeof childRef === 'object' && 'current' in childRef) {\n (childRef as { current: HTMLElement | null }).current = node;\n }\n },\n 'aria-describedby': isOpen ? tooltipId : undefined,\n onMouseEnter: (e: React.MouseEvent<HTMLElement>) => {\n show();\n child.props.onMouseEnter?.(e);\n },\n onMouseLeave: (e: React.MouseEvent<HTMLElement>) => {\n hide();\n child.props.onMouseLeave?.(e);\n },\n onFocus: (e: React.FocusEvent<HTMLElement>) => {\n show();\n child.props.onFocus?.(e);\n },\n onBlur: (e: React.FocusEvent<HTMLElement>) => {\n hide();\n child.props.onBlur?.(e);\n },\n };\n\n // 4. Clone the child and inject the event listeners and refs\n const trigger = React.cloneElement(child, triggerProps);\n\n return (\n <>\n {trigger}\n\n {isOpen && (\n <Portal>\n <div\n ref={tooltipRef}\n id={tooltipId}\n role=\"tooltip\"\n data-placement={placement}\n className={cn('nui-tooltip', className)}\n style={{\n position: 'absolute',\n top: coords.top,\n left: coords.left,\n // Pass the arrow position dynamically to CSS!\n '--nui-tooltip-arrow-x': `${coords.arrowLeft}px`,\n } as React.CSSProperties}\n >\n {label}\n </div>\n </Portal>\n )}\n </>\n );\n}"],"names":["Tooltip","label","children","className","delay","offset","isOpen","setIsOpen","useState","coords","setCoords","placement","setPlacement","triggerRef","useRef","tooltipRef","timeoutRef","tooltipId","useId","show","useCallback","hide","updatePosition","triggerRect","tooltipRect","scrollX","scrollY","actualCenter","left","minLeft","maxLeft","physicalLeftEdge","arrowLeft","arrowMin","arrowMax","top","nextPlacement","useLayoutEffect","useEffect","onKeyDown","child","React","childRef","triggerProps","node","e","trigger","jsxs","Fragment","Portal","jsx","cn"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),x=require("react");;/* empty css */function j({data:f,selectedId:w,onSelect:h,className:g=""}){const[d,y]=x.useState(new Set),[A,o]=x.useState(null),u=e=>{y(i=>{const r=new Set(i);return r.has(e)?r.delete(e):r.add(e),r})},p=(e,i=[])=>(e.forEach(r=>{i.push(r);const t=d.has(r.id);r.children&&r.children.length>0&&t&&p(r.children,i)}),i),N=(e,i,r)=>{const t=e.key;if(t==="Enter"||t===" "){e.preventDefault(),h&&h(i.id);return}if(t==="ArrowLeft"){e.preventDefault();const n=i.children&&i.children.length>0,s=d.has(i.id);if(n&&s){u(i.id);return}r&&o(r.id);return}if(t==="ArrowRight"){e.preventDefault();const n=i.children&&i.children.length>0,s=d.has(i.id);if(n&&!s){u(i.id);return}if(n&&s){const c=Array.isArray(i.children)&&i.children.length>0?i.children[0]:void 0;c&&o(c.id)}return}if(t==="ArrowUp"||t==="ArrowDown"){e.preventDefault();const n=p(f),s=n.findIndex(m=>m.id===i.id);if(s===-1)return;const c=t==="ArrowUp"?s-1:s+1,l=n[c];l&&o(l.id)}},v=(e,i,r)=>{const t=d.has(e.id),n=e.id===w,s=e.id===A,c=Array.isArray(e.children)&&e.children.length>0;return a.jsxs("div",{children:[a.jsxs("div",{role:"treeitem","aria-expanded":c?t:void 0,tabIndex:s?0:-1,className:["ui-tree-node",n?"selected":"",s?"active":""].filter(Boolean).join(" "),style:{paddingLeft:r*16},onClick:()=>{h&&h(e.id),o(e.id),Array.isArray(e.children)&&e.children.length>0&&u(e.id)},onKeyDown:l=>N(l,e,i),children:[c?a.jsx("span",{className:`ui-tree-arrow ${t?"open":""}`,onClick:l=>{l.stopPropagation(),u(e.id)},children:""}):a.jsx("span",{className:"ui-tree-arrow empty",children:""}),e.icon&&a.jsx("span",{className:"ui-tree-icon",children:e.icon}),a.jsx("span",{className:"ui-tree-label",children:e.label})]}),c&&t&&e.children&&a.jsx("div",{role:"group",children:e.children.map(l=>v(l,e,r+1))})]},e.id)};return a.jsx("div",{className:`ui-treeview ${g}`,role:"tree",children:f.map(e=>v(e,void 0,0))})}exports.TreeView=j;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),o=require("react");;/* empty css */const h=require("../../utils/cn/cn.cjs"),w=o.forwardRef(({data:m,selectedId:k,defaultExpandedIds:j=[],onSelect:f,className:y,...A},E)=>{const[p,N]=o.useState(new Set(j)),b=o.useRef(null),I=`nui-tree-${o.useId().replace(/:/g,"")}`,c=o.useCallback((t,r)=>{r?.stopPropagation(),N(d=>{const e=new Set(d);return e.has(t)?e.delete(t):e.add(t),e})},[]),T=o.useCallback((t,r,d)=>{["ArrowUp","ArrowDown","ArrowLeft","ArrowRight","Home","End"," ","Enter"].includes(t.key)&&t.preventDefault(),t.stopPropagation();const e=t.currentTarget,l=p.has(r.id),n=!!r.children?.length,i=b.current?Array.from(b.current.querySelectorAll('[role="treeitem"]:not([aria-disabled="true"])')):[],u=i.indexOf(e);switch(t.key){case"Enter":case" ":if(r.disabled)return;n&&c(r.id),f?.(r.id,r);break;case"ArrowRight":n&&!l?c(r.id):n&&l&&i[u+1]?.focus();break;case"ArrowLeft":n&&l?c(r.id):d&&i.find(v=>v.id.endsWith(`-${d.id}`))?.focus();break;case"ArrowDown":i[u+1]?.focus();break;case"ArrowUp":i[u-1]?.focus();break;case"Home":i[0]?.focus();break;case"End":i[i.length-1]?.focus();break}},[p,c,f]),g=(t,r=1,d)=>s.jsx("ul",{role:r===1?"tree":"group",className:h.cn("nui-tree",r>1&&"nui-tree--nested"),ref:r===1?b:void 0,children:t.map((e,l)=>{const n=p.has(e.id),x=k===e.id,i=!!e.children?.length,u=r===1&&l===0;return s.jsxs("li",{id:`${I}-${e.id}`,role:"treeitem","aria-expanded":i?n:void 0,"aria-selected":x,"aria-disabled":e.disabled,tabIndex:u?0:-1,className:h.cn("nui-tree-item",x&&"nui-tree-item--selected",e.disabled&&"nui-tree-item--disabled"),onKeyDown:a=>T(a,e,d),onClick:a=>{a.stopPropagation(),!e.disabled&&(a.currentTarget.focus(),i&&c(e.id),f?.(e.id,e))},children:[s.jsxs("div",{className:"nui-tree-item-content",style:{paddingLeft:`${(r-1)*16}px`},children:[s.jsx("span",{className:h.cn("nui-tree-chevron",!i&&"nui-tree-chevron--hidden"),onClick:a=>{i&&c(e.id,a)},children:s.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",className:h.cn("nui-tree-chevron-icon",n&&"nui-tree-chevron-icon--open"),"aria-hidden":"true",children:s.jsx("polyline",{points:"9 18 15 12 9 6"})})}),e.icon&&s.jsx("span",{className:"nui-tree-icon","aria-hidden":"true",children:e.icon}),s.jsx("span",{className:"nui-tree-label",children:e.label})]}),i&&n&&e.children&&g(e.children,r+1,e)]},e.id)})});return s.jsx("div",{ref:E,className:h.cn("nui-tree-wrapper",y),...A,children:g(m)})});w.displayName="TreeView";exports.TreeView=w;
2
2
  //# sourceMappingURL=TreeView.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"TreeView.cjs","sources":["../../../src/components/treeview/TreeView.tsx"],"sourcesContent":["/**\r\n * TreeView.tsx — FINAL VERSION\r\n * ----------------------------\r\n * Features:\r\n * - Expand/collapse\r\n * - Recursive rendering\r\n * - Arrow key navigation\r\n * - Enter/Space to select\r\n * - ARIA TreeView roles\r\n * - Value controlled OR internal state\r\n */\r\n\r\nimport React, { useState } from 'react';\r\nimport './TreeView.css';\r\n\r\nexport interface TreeNode {\r\n id: string;\r\n label: string;\r\n icon?: React.ReactNode;\r\n children?: TreeNode[];\r\n}\r\n\r\ninterface TreeViewProps {\r\n data: TreeNode[];\r\n selectedId?: string;\r\n onSelect?: (id: string) => void;\r\n className?: string;\r\n}\r\n\r\nexport function TreeView({\r\n data,\r\n selectedId,\r\n onSelect,\r\n className = '',\r\n}: TreeViewProps) {\r\n const [openNodes, setOpenNodes] = useState<Set<string>>(new Set());\r\n const [activeNode, setActiveNode] = useState<string | null>(null);\r\n\r\n const toggleNode = (id: string) => {\r\n setOpenNodes((prev) => {\r\n const next = new Set(prev);\r\n if (next.has(id)) next.delete(id);\r\n else next.add(id);\r\n return next;\r\n });\r\n };\r\n\r\n const flatten = (nodes: TreeNode[], acc: TreeNode[] = []): TreeNode[] => {\r\n nodes.forEach((node) => {\r\n acc.push(node);\r\n\r\n const isOpen = openNodes.has(node.id);\r\n if (node.children && node.children.length > 0 && isOpen) {\r\n flatten(node.children, acc);\r\n }\r\n });\r\n return acc;\r\n };\r\n\r\n const handleKeyDown = (\r\n e: React.KeyboardEvent,\r\n node: TreeNode,\r\n parent: TreeNode | undefined\r\n ) => {\r\n const key = e.key;\r\n\r\n // Select\r\n if (key === 'Enter' || key === ' ') {\r\n e.preventDefault();\r\n if (onSelect) onSelect(node.id);\r\n return;\r\n }\r\n\r\n // Collapse or go to parent\r\n if (key === 'ArrowLeft') {\r\n e.preventDefault();\r\n\r\n const hasChildren = node.children && node.children.length > 0;\r\n const isOpen = openNodes.has(node.id);\r\n\r\n if (hasChildren && isOpen) {\r\n toggleNode(node.id);\r\n return;\r\n }\r\n\r\n if (parent) {\r\n setActiveNode(parent.id);\r\n }\r\n return;\r\n }\r\n\r\n // Expand or go to first child\r\n if (key === 'ArrowRight') {\r\n e.preventDefault();\r\n\r\n const hasChildren = node.children && node.children.length > 0;\r\n const isOpen = openNodes.has(node.id);\r\n\r\n if (hasChildren && !isOpen) {\r\n toggleNode(node.id);\r\n return;\r\n }\r\n\r\n if (hasChildren && isOpen) {\r\n const firstChild =\r\n Array.isArray(node.children) && node.children.length > 0\r\n ? node.children[0]\r\n : undefined;\r\n\r\n if (firstChild) {\r\n setActiveNode(firstChild.id);\r\n }\r\n }\r\n return;\r\n }\r\n\r\n // Up/Down navigation\r\n if (key === 'ArrowUp' || key === 'ArrowDown') {\r\n e.preventDefault();\r\n const flat = flatten(data);\r\n const index = flat.findIndex((n) => n.id === node.id);\r\n\r\n if (index === -1) return;\r\n\r\n const nextIndex = key === 'ArrowUp' ? index - 1 : index + 1;\r\n const nextNode = flat[nextIndex];\r\n\r\n if (nextNode) {\r\n setActiveNode(nextNode.id);\r\n }\r\n }\r\n };\r\n\r\n const renderNode = (\r\n node: TreeNode,\r\n parent: TreeNode | undefined,\r\n depth: number\r\n ) => {\r\n const isOpen = openNodes.has(node.id);\r\n const isSelected = node.id === selectedId;\r\n const isActive = node.id === activeNode;\r\n const hasChildren =\r\n Array.isArray(node.children) && node.children.length > 0;\r\n\r\n return (\r\n <div key={node.id}>\r\n <div\r\n role=\"treeitem\"\r\n aria-expanded={hasChildren ? isOpen : undefined}\r\n tabIndex={isActive ? 0 : -1}\r\n className={[\r\n 'ui-tree-node',\r\n isSelected ? 'selected' : '',\r\n isActive ? 'active' : '',\r\n ]\r\n .filter(Boolean)\r\n .join(' ')}\r\n style={{ paddingLeft: depth * 16 }}\r\n onClick={() => {\r\n if (onSelect) onSelect(node.id);\r\n setActiveNode(node.id);\r\n\r\n const hasChildren =\r\n Array.isArray(node.children) && node.children.length > 0;\r\n\r\n // Clicking node should expand/collapse just like arrow\r\n if (hasChildren) {\r\n toggleNode(node.id);\r\n }\r\n }}\r\n onKeyDown={(e) => handleKeyDown(e, node, parent)}\r\n >\r\n {/* Arrow */}\r\n {hasChildren ? (\r\n <span\r\n className={`ui-tree-arrow ${isOpen ? 'open' : ''}`}\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n toggleNode(node.id);\r\n }}\r\n >\r\n ▶\r\n </span>\r\n ) : (\r\n <span className=\"ui-tree-arrow empty\">•</span>\r\n )}\r\n\r\n {/* Icon */}\r\n {node.icon && <span className=\"ui-tree-icon\">{node.icon}</span>}\r\n\r\n <span className=\"ui-tree-label\">{node.label}</span>\r\n </div>\r\n\r\n {/* Children */}\r\n {hasChildren && isOpen && node.children && (\r\n <div role=\"group\">\r\n {node.children.map((child) => renderNode(child, node, depth + 1))}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n };\r\n\r\n return (\r\n <div className={`ui-treeview ${className}`} role=\"tree\">\r\n {data.map((node) => renderNode(node, undefined, 0))}\r\n </div>\r\n );\r\n}\r\n"],"names":["TreeView","data","selectedId","onSelect","className","openNodes","setOpenNodes","useState","activeNode","setActiveNode","toggleNode","id","prev","next","flatten","nodes","acc","node","isOpen","handleKeyDown","parent","key","hasChildren","firstChild","flat","index","n","nextIndex","nextNode","renderNode","depth","isSelected","isActive","jsxs","e","jsx","child"],"mappings":"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"}
1
+ {"version":3,"file":"TreeView.cjs","sources":["../../../src/components/treeview/TreeView.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useState, useCallback, useRef, forwardRef } from 'react';\nimport { cn } from '../../utils';\nimport './TreeView.css';\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport interface TreeNode {\n /** Unique identifier for the node */\n id: string;\n /** Text or element to display */\n label: React.ReactNode;\n /** Optional icon to display next to the label */\n icon?: React.ReactNode;\n /** Nested children nodes */\n children?: TreeNode[];\n /** Prevents interaction and applies muted styles */\n disabled?: boolean;\n}\n\nexport interface TreeViewProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'> {\n /** The hierarchical data structure to render */\n data: TreeNode[];\n /** The ID of the currently selected node (Controlled) */\n selectedId?: string;\n /** Array of node IDs to expand by default on initial render */\n defaultExpandedIds?: string[];\n /** Callback fired when a node is selected */\n onSelect?: (id: string, node: TreeNode) => void;\n}\n\n/* ============================================================\n * Component\n * ============================================================ */\n\n/**\n * TreeView Component\n * * A hierarchical list display with nested collapsible folders.\n * * Fully WAI-ARIA compliant with a smart roving tabindex for keyboard navigation.\n */\nexport const TreeView = forwardRef<HTMLDivElement, TreeViewProps>(({\n data,\n selectedId,\n defaultExpandedIds = [],\n onSelect,\n className,\n ...props\n}, ref) => {\n const [expandedIds, setExpandedIds] = useState<Set<string>>(new Set(defaultExpandedIds));\n const treeRef = useRef<HTMLUListElement>(null);\n \n // Generate a unique prefix so multiple TreeViews on the same page never clash IDs\n const baseId = React.useId();\n // Strip the colons that React adds to make it strictly valid for query selectors\n const treeIdPrefix = `nui-tree-${baseId.replace(/:/g, '')}`;\n\n const toggleExpand = useCallback((id: string, e?: React.MouseEvent) => {\n e?.stopPropagation();\n setExpandedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n }, []);\n\n /* ----------------------------------------------------\n Keyboard Navigation (WAI-ARIA Standard)\n ---------------------------------------------------- */\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent, node: TreeNode, parentNode?: TreeNode) => {\n // 1. Instantly kill all default browser scrolling for arrow keys\n if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', ' ', 'Enter'].includes(e.key)) {\n e.preventDefault();\n }\n \n // 2. Stop parent folders from stealing the keypress\n e.stopPropagation();\n\n const target = e.currentTarget as HTMLLIElement;\n const isExpanded = expandedIds.has(node.id);\n const hasChildren = !!node.children?.length;\n\n // Get all currently visible nodes in the exact DOM order\n const getVisibleNodes = () => {\n if (!treeRef.current) return [];\n return Array.from(\n treeRef.current.querySelectorAll('[role=\"treeitem\"]:not([aria-disabled=\"true\"])')\n ) as HTMLLIElement[];\n };\n\n const nodes = getVisibleNodes();\n const currentIndex = nodes.indexOf(target);\n\n switch (e.key) {\n case 'Enter':\n case ' ':\n if (node.disabled) return;\n // Modern UX: Enter/Space should expand/collapse folders\n if (hasChildren) toggleExpand(node.id);\n onSelect?.(node.id, node);\n break;\n\n case 'ArrowRight':\n if (hasChildren && !isExpanded) {\n // Closed folder -> Open it\n toggleExpand(node.id);\n } else if (hasChildren && isExpanded) {\n // Open folder -> The very next visible node in the DOM is ALWAYS its first child!\n nodes[currentIndex + 1]?.focus();\n }\n break;\n\n case 'ArrowLeft':\n if (hasChildren && isExpanded) {\n // Open folder -> Close it\n toggleExpand(node.id);\n } else if (parentNode) {\n // Closed folder or File -> Safely find parent by checking the end of the ID\n const parentEl = nodes.find(n => n.id.endsWith(`-${parentNode.id}`));\n parentEl?.focus();\n }\n break;\n\n case 'ArrowDown':\n nodes[currentIndex + 1]?.focus();\n break;\n\n case 'ArrowUp':\n nodes[currentIndex - 1]?.focus();\n break;\n\n case 'Home':\n nodes[0]?.focus();\n break;\n\n case 'End':\n nodes[nodes.length - 1]?.focus();\n break;\n }\n },\n [expandedIds, toggleExpand, onSelect]\n );\n\n /* ----------------------------------------------------\n Recursive Render Function\n ---------------------------------------------------- */\n const renderTree = (nodes: TreeNode[], level = 1, parentNode?: TreeNode) => {\n return (\n <ul\n role={level === 1 ? 'tree' : 'group'}\n className={cn(\"nui-tree\", level > 1 && \"nui-tree--nested\")}\n ref={level === 1 ? treeRef : undefined}\n >\n {nodes.map((node, index) => {\n const isExpanded = expandedIds.has(node.id);\n const isSelected = selectedId === node.id;\n const hasChildren = !!node.children?.length;\n \n // Only the first item in the entire tree is tabbable by default (Roving Tabindex)\n const isTabbable = level === 1 && index === 0;\n\n return (\n <li\n key={node.id}\n id={`${treeIdPrefix}-${node.id}`} \n role=\"treeitem\"\n aria-expanded={hasChildren ? isExpanded : undefined}\n aria-selected={isSelected}\n aria-disabled={node.disabled}\n tabIndex={isTabbable ? 0 : -1}\n className={cn(\n \"nui-tree-item\",\n isSelected && \"nui-tree-item--selected\",\n node.disabled && \"nui-tree-item--disabled\"\n )}\n onKeyDown={(e) => handleKeyDown(e, node, parentNode)} \n onClick={(e) => {\n e.stopPropagation();\n if (node.disabled) return;\n \n (e.currentTarget as HTMLElement).focus();\n \n if (hasChildren) {\n toggleExpand(node.id);\n }\n onSelect?.(node.id, node);\n }}\n >\n <div \n className=\"nui-tree-item-content\"\n style={{ paddingLeft: `${(level - 1) * 16}px` }}\n >\n <span \n className={cn(\"nui-tree-chevron\", !hasChildren && \"nui-tree-chevron--hidden\")}\n onClick={(e) => {\n if (hasChildren) toggleExpand(node.id, e);\n }}\n >\n <svg \n width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\"\n className={cn(\"nui-tree-chevron-icon\", isExpanded && \"nui-tree-chevron-icon--open\")}\n aria-hidden=\"true\"\n >\n <polyline points=\"9 18 15 12 9 6\"></polyline>\n </svg>\n </span>\n\n {node.icon && (\n <span className=\"nui-tree-icon\" aria-hidden=\"true\">{node.icon}</span>\n )}\n\n <span className=\"nui-tree-label\">{node.label}</span>\n </div>\n\n {hasChildren && isExpanded && node.children && (\n renderTree(node.children, level + 1, node) // Pass 'node' as the parent for the next level\n )}\n </li>\n );\n })}\n </ul>\n );\n };\n\n return (\n <div ref={ref} className={cn(\"nui-tree-wrapper\", className)} {...props}>\n {renderTree(data)}\n </div>\n );\n});\n\nTreeView.displayName = 'TreeView';"],"names":["TreeView","forwardRef","data","selectedId","defaultExpandedIds","onSelect","className","props","ref","expandedIds","setExpandedIds","useState","treeRef","useRef","treeIdPrefix","React","toggleExpand","useCallback","id","e","prev","next","handleKeyDown","node","parentNode","target","isExpanded","hasChildren","nodes","currentIndex","n","renderTree","level","jsx","cn","index","isSelected","isTabbable","jsxs"],"mappings":"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"}