@nofinite/nui 1.1.2 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (405) hide show
  1. package/README.md +61 -48
  2. package/dist/components/accordion/Accordion.cjs +1 -1
  3. package/dist/components/accordion/Accordion.cjs.map +1 -1
  4. package/dist/components/accordion/Accordion.js +64 -43
  5. package/dist/components/accordion/Accordion.js.map +1 -1
  6. package/dist/components/alert/Alert.cjs +1 -1
  7. package/dist/components/alert/Alert.cjs.map +1 -1
  8. package/dist/components/alert/Alert.js +39 -25
  9. package/dist/components/alert/Alert.js.map +1 -1
  10. package/dist/components/avatar/Avatar.cjs +1 -1
  11. package/dist/components/avatar/Avatar.cjs.map +1 -1
  12. package/dist/components/avatar/Avatar.js +58 -44
  13. package/dist/components/avatar/Avatar.js.map +1 -1
  14. package/dist/components/avatar/AvatarGroup.cjs +1 -1
  15. package/dist/components/avatar/AvatarGroup.cjs.map +1 -1
  16. package/dist/components/avatar/AvatarGroup.js +34 -25
  17. package/dist/components/avatar/AvatarGroup.js.map +1 -1
  18. package/dist/components/badge/Badge.cjs +1 -1
  19. package/dist/components/badge/Badge.cjs.map +1 -1
  20. package/dist/components/badge/Badge.js +43 -68
  21. package/dist/components/badge/Badge.js.map +1 -1
  22. package/dist/components/badge/BadgeGroup.cjs +1 -1
  23. package/dist/components/badge/BadgeGroup.cjs.map +1 -1
  24. package/dist/components/badge/BadgeGroup.js +20 -10
  25. package/dist/components/badge/BadgeGroup.js.map +1 -1
  26. package/dist/components/breadcrumbs/Breadcrumbs.cjs +1 -1
  27. package/dist/components/breadcrumbs/Breadcrumbs.cjs.map +1 -1
  28. package/dist/components/breadcrumbs/Breadcrumbs.js +59 -39
  29. package/dist/components/breadcrumbs/Breadcrumbs.js.map +1 -1
  30. package/dist/components/button/Button.cjs +1 -1
  31. package/dist/components/button/Button.cjs.map +1 -1
  32. package/dist/components/button/Button.js +52 -17
  33. package/dist/components/button/Button.js.map +1 -1
  34. package/dist/components/card/Card.cjs +1 -1
  35. package/dist/components/card/Card.cjs.map +1 -1
  36. package/dist/components/card/Card.js +44 -41
  37. package/dist/components/card/Card.js.map +1 -1
  38. package/dist/components/checkbox/Checkbox.cjs +1 -1
  39. package/dist/components/checkbox/Checkbox.cjs.map +1 -1
  40. package/dist/components/checkbox/Checkbox.js +59 -40
  41. package/dist/components/checkbox/Checkbox.js.map +1 -1
  42. package/dist/components/chip/Chip.cjs +1 -1
  43. package/dist/components/chip/Chip.cjs.map +1 -1
  44. package/dist/components/chip/Chip.js +67 -47
  45. package/dist/components/chip/Chip.js.map +1 -1
  46. package/dist/components/combobox/Combobox.cjs +1 -1
  47. package/dist/components/combobox/Combobox.cjs.map +1 -1
  48. package/dist/components/combobox/Combobox.js +123 -108
  49. package/dist/components/combobox/Combobox.js.map +1 -1
  50. package/dist/components/commandpalette/CommandPalette.cjs +1 -1
  51. package/dist/components/commandpalette/CommandPalette.cjs.map +1 -1
  52. package/dist/components/commandpalette/CommandPalette.js +96 -73
  53. package/dist/components/commandpalette/CommandPalette.js.map +1 -1
  54. package/dist/components/contextmenu/ContextMenu.cjs +1 -1
  55. package/dist/components/contextmenu/ContextMenu.cjs.map +1 -1
  56. package/dist/components/contextmenu/ContextMenu.js +79 -58
  57. package/dist/components/contextmenu/ContextMenu.js.map +1 -1
  58. package/dist/components/datagrid/DataGrid.cjs +1 -1
  59. package/dist/components/datagrid/DataGrid.cjs.map +1 -1
  60. package/dist/components/datagrid/DataGrid.js +184 -202
  61. package/dist/components/datagrid/DataGrid.js.map +1 -1
  62. package/dist/components/datepicker/DatePicker.cjs +1 -1
  63. package/dist/components/datepicker/DatePicker.cjs.map +1 -1
  64. package/dist/components/datepicker/DatePicker.js +197 -164
  65. package/dist/components/datepicker/DatePicker.js.map +1 -1
  66. package/dist/components/daterangepicker/DateRangePicker.cjs +1 -1
  67. package/dist/components/daterangepicker/DateRangePicker.cjs.map +1 -1
  68. package/dist/components/daterangepicker/DateRangePicker.js +254 -213
  69. package/dist/components/daterangepicker/DateRangePicker.js.map +1 -1
  70. package/dist/components/dialog/DialogProvider.cjs +2 -0
  71. package/dist/components/dialog/DialogProvider.cjs.map +1 -0
  72. package/dist/components/dialog/DialogProvider.js +71 -0
  73. package/dist/components/dialog/DialogProvider.js.map +1 -0
  74. package/dist/components/dialog/dialogStore.cjs +2 -0
  75. package/dist/components/dialog/dialogStore.cjs.map +1 -0
  76. package/dist/components/dialog/dialogStore.js +60 -0
  77. package/dist/components/dialog/dialogStore.js.map +1 -0
  78. package/dist/components/drawer/Drawer.cjs +1 -1
  79. package/dist/components/drawer/Drawer.cjs.map +1 -1
  80. package/dist/components/drawer/Drawer.js +69 -47
  81. package/dist/components/drawer/Drawer.js.map +1 -1
  82. package/dist/components/dropdown/Dropdown.cjs +1 -1
  83. package/dist/components/dropdown/Dropdown.cjs.map +1 -1
  84. package/dist/components/dropdown/Dropdown.js +134 -108
  85. package/dist/components/dropdown/Dropdown.js.map +1 -1
  86. package/dist/components/fileuploader/FileUploader.cjs +1 -1
  87. package/dist/components/fileuploader/FileUploader.cjs.map +1 -1
  88. package/dist/components/fileuploader/FileUploader.js +96 -61
  89. package/dist/components/fileuploader/FileUploader.js.map +1 -1
  90. package/dist/components/hovercard/HoverCard.cjs +1 -1
  91. package/dist/components/hovercard/HoverCard.cjs.map +1 -1
  92. package/dist/components/hovercard/HoverCard.js +124 -69
  93. package/dist/components/hovercard/HoverCard.js.map +1 -1
  94. package/dist/components/input/Input.cjs +1 -1
  95. package/dist/components/input/Input.cjs.map +1 -1
  96. package/dist/components/input/Input.js +62 -37
  97. package/dist/components/input/Input.js.map +1 -1
  98. package/dist/components/layout/Container.cjs +1 -1
  99. package/dist/components/layout/Container.cjs.map +1 -1
  100. package/dist/components/layout/Container.js +21 -30
  101. package/dist/components/layout/Container.js.map +1 -1
  102. package/dist/components/layout/Flex.cjs +1 -1
  103. package/dist/components/layout/Flex.cjs.map +1 -1
  104. package/dist/components/layout/Flex.js +36 -19
  105. package/dist/components/layout/Flex.js.map +1 -1
  106. package/dist/components/layout/Grid.cjs +1 -1
  107. package/dist/components/layout/Grid.cjs.map +1 -1
  108. package/dist/components/layout/Grid.js +30 -18
  109. package/dist/components/layout/Grid.js.map +1 -1
  110. package/dist/components/link/Link.cjs +2 -0
  111. package/dist/components/link/Link.cjs.map +1 -0
  112. package/dist/components/link/Link.js +41 -0
  113. package/dist/components/link/Link.js.map +1 -0
  114. package/dist/components/megamenu/MegaMenu.cjs +1 -1
  115. package/dist/components/megamenu/MegaMenu.cjs.map +1 -1
  116. package/dist/components/megamenu/MegaMenu.js +107 -38
  117. package/dist/components/megamenu/MegaMenu.js.map +1 -1
  118. package/dist/components/modal/Modal.cjs +1 -1
  119. package/dist/components/modal/Modal.cjs.map +1 -1
  120. package/dist/components/modal/Modal.js +91 -83
  121. package/dist/components/modal/Modal.js.map +1 -1
  122. package/dist/components/multiselect/MultiSelect.cjs +2 -0
  123. package/dist/components/multiselect/MultiSelect.cjs.map +1 -0
  124. package/dist/components/multiselect/MultiSelect.js +176 -0
  125. package/dist/components/multiselect/MultiSelect.js.map +1 -0
  126. package/dist/components/nuiprovider/NUIProvider.cjs +2 -0
  127. package/dist/components/nuiprovider/NUIProvider.cjs.map +1 -0
  128. package/dist/components/nuiprovider/NUIProvider.js +36 -0
  129. package/dist/components/nuiprovider/NUIProvider.js.map +1 -0
  130. package/dist/components/pagination/Pagination.cjs +1 -1
  131. package/dist/components/pagination/Pagination.cjs.map +1 -1
  132. package/dist/components/pagination/Pagination.js +74 -41
  133. package/dist/components/pagination/Pagination.js.map +1 -1
  134. package/dist/components/popover/Popover.cjs +1 -1
  135. package/dist/components/popover/Popover.cjs.map +1 -1
  136. package/dist/components/popover/Popover.js +99 -100
  137. package/dist/components/popover/Popover.js.map +1 -1
  138. package/dist/components/progress/Progress.cjs +1 -1
  139. package/dist/components/progress/Progress.cjs.map +1 -1
  140. package/dist/components/progress/Progress.js +44 -22
  141. package/dist/components/progress/Progress.js.map +1 -1
  142. package/dist/components/radiogroup/RadioGroup.cjs +1 -1
  143. package/dist/components/radiogroup/RadioGroup.cjs.map +1 -1
  144. package/dist/components/radiogroup/RadioGroup.js +69 -74
  145. package/dist/components/radiogroup/RadioGroup.js.map +1 -1
  146. package/dist/components/rating/Rating.cjs +1 -1
  147. package/dist/components/rating/Rating.cjs.map +1 -1
  148. package/dist/components/rating/Rating.js +72 -33
  149. package/dist/components/rating/Rating.js.map +1 -1
  150. package/dist/components/resizable/Resizable.cjs +2 -0
  151. package/dist/components/resizable/Resizable.cjs.map +1 -0
  152. package/dist/components/resizable/Resizable.js +134 -0
  153. package/dist/components/resizable/Resizable.js.map +1 -0
  154. package/dist/components/select/Select.cjs +1 -1
  155. package/dist/components/select/Select.cjs.map +1 -1
  156. package/dist/components/select/Select.js +114 -113
  157. package/dist/components/select/Select.js.map +1 -1
  158. package/dist/components/skeleton/Skeleton.cjs +1 -1
  159. package/dist/components/skeleton/Skeleton.cjs.map +1 -1
  160. package/dist/components/skeleton/Skeleton.js +90 -67
  161. package/dist/components/skeleton/Skeleton.js.map +1 -1
  162. package/dist/components/slider/Slider.cjs +1 -1
  163. package/dist/components/slider/Slider.cjs.map +1 -1
  164. package/dist/components/slider/Slider.js +85 -82
  165. package/dist/components/slider/Slider.js.map +1 -1
  166. package/dist/components/spinner/Spinner.cjs +1 -1
  167. package/dist/components/spinner/Spinner.cjs.map +1 -1
  168. package/dist/components/spinner/Spinner.js +60 -17
  169. package/dist/components/spinner/Spinner.js.map +1 -1
  170. package/dist/components/stepper/Stepper.cjs +1 -5
  171. package/dist/components/stepper/Stepper.cjs.map +1 -1
  172. package/dist/components/stepper/Stepper.js +65 -39
  173. package/dist/components/stepper/Stepper.js.map +1 -1
  174. package/dist/components/switch/Switch.cjs +1 -1
  175. package/dist/components/switch/Switch.cjs.map +1 -1
  176. package/dist/components/switch/Switch.js +89 -62
  177. package/dist/components/switch/Switch.js.map +1 -1
  178. package/dist/components/table/Table.cjs +1 -1
  179. package/dist/components/table/Table.cjs.map +1 -1
  180. package/dist/components/table/Table.js +62 -35
  181. package/dist/components/table/Table.js.map +1 -1
  182. package/dist/components/tabs/Tabs.cjs +1 -1
  183. package/dist/components/tabs/Tabs.cjs.map +1 -1
  184. package/dist/components/tabs/Tabs.js +110 -50
  185. package/dist/components/tabs/Tabs.js.map +1 -1
  186. package/dist/components/textarea/Textarea.cjs +1 -1
  187. package/dist/components/textarea/Textarea.cjs.map +1 -1
  188. package/dist/components/textarea/Textarea.js +63 -58
  189. package/dist/components/textarea/Textarea.js.map +1 -1
  190. package/dist/components/timepicker/TimePicker.cjs +2 -0
  191. package/dist/components/timepicker/TimePicker.cjs.map +1 -0
  192. package/dist/components/timepicker/TimePicker.js +159 -0
  193. package/dist/components/timepicker/TimePicker.js.map +1 -0
  194. package/dist/components/timerangepicker/TimeRangePicker.cjs +2 -0
  195. package/dist/components/timerangepicker/TimeRangePicker.cjs.map +1 -0
  196. package/dist/components/timerangepicker/TimeRangePicker.js +208 -0
  197. package/dist/components/timerangepicker/TimeRangePicker.js.map +1 -0
  198. package/dist/components/toast/Toast.cjs +1 -1
  199. package/dist/components/toast/Toast.cjs.map +1 -1
  200. package/dist/components/toast/Toast.js +91 -38
  201. package/dist/components/toast/Toast.js.map +1 -1
  202. package/dist/components/tooltip/Tooltip.cjs +1 -1
  203. package/dist/components/tooltip/Tooltip.cjs.map +1 -1
  204. package/dist/components/tooltip/Tooltip.js +72 -56
  205. package/dist/components/tooltip/Tooltip.js.map +1 -1
  206. package/dist/components/treeview/TreeView.cjs +1 -1
  207. package/dist/components/treeview/TreeView.cjs.map +1 -1
  208. package/dist/components/treeview/TreeView.js +120 -90
  209. package/dist/components/treeview/TreeView.js.map +1 -1
  210. package/dist/components/virtuallist/VirtualList.cjs +1 -1
  211. package/dist/components/virtuallist/VirtualList.cjs.map +1 -1
  212. package/dist/components/virtuallist/VirtualList.js +52 -34
  213. package/dist/components/virtuallist/VirtualList.js.map +1 -1
  214. package/dist/index.cjs +1 -1
  215. package/dist/index.css +1 -0
  216. package/dist/index.js +120 -106
  217. package/dist/index.js.map +1 -1
  218. package/dist/package.json +49 -6
  219. package/dist/types/components/accordion/Accordion.d.ts +7 -3
  220. package/dist/types/components/accordion/Accordion.d.ts.map +1 -1
  221. package/dist/types/components/alert/Alert.d.ts +18 -5
  222. package/dist/types/components/alert/Alert.d.ts.map +1 -1
  223. package/dist/types/components/avatar/Avatar.d.ts +12 -8
  224. package/dist/types/components/avatar/Avatar.d.ts.map +1 -1
  225. package/dist/types/components/avatar/AvatarGroup.d.ts +11 -4
  226. package/dist/types/components/avatar/AvatarGroup.d.ts.map +1 -1
  227. package/dist/types/components/badge/Badge.d.ts +19 -11
  228. package/dist/types/components/badge/Badge.d.ts.map +1 -1
  229. package/dist/types/components/badge/BadgeGroup.d.ts +7 -4
  230. package/dist/types/components/badge/BadgeGroup.d.ts.map +1 -1
  231. package/dist/types/components/breadcrumbs/Breadcrumbs.d.ts +14 -6
  232. package/dist/types/components/breadcrumbs/Breadcrumbs.d.ts.map +1 -1
  233. package/dist/types/components/button/Button.d.ts +25 -10
  234. package/dist/types/components/button/Button.d.ts.map +1 -1
  235. package/dist/types/components/card/Card.d.ts +12 -21
  236. package/dist/types/components/card/Card.d.ts.map +1 -1
  237. package/dist/types/components/checkbox/Checkbox.d.ts +12 -7
  238. package/dist/types/components/checkbox/Checkbox.d.ts.map +1 -1
  239. package/dist/types/components/chip/Chip.d.ts +14 -11
  240. package/dist/types/components/chip/Chip.d.ts.map +1 -1
  241. package/dist/types/components/combobox/Combobox.d.ts +15 -4
  242. package/dist/types/components/combobox/Combobox.d.ts.map +1 -1
  243. package/dist/types/components/commandpalette/CommandPalette.d.ts +12 -3
  244. package/dist/types/components/commandpalette/CommandPalette.d.ts.map +1 -1
  245. package/dist/types/components/contextmenu/ContextMenu.d.ts +14 -6
  246. package/dist/types/components/contextmenu/ContextMenu.d.ts.map +1 -1
  247. package/dist/types/components/datagrid/DataGrid.d.ts +16 -4
  248. package/dist/types/components/datagrid/DataGrid.d.ts.map +1 -1
  249. package/dist/types/components/datepicker/DatePicker.d.ts +13 -1
  250. package/dist/types/components/datepicker/DatePicker.d.ts.map +1 -1
  251. package/dist/types/components/daterangepicker/DateRangePicker.d.ts +3 -1
  252. package/dist/types/components/daterangepicker/DateRangePicker.d.ts.map +1 -1
  253. package/dist/types/components/dialog/DialogProvider.d.ts +2 -0
  254. package/dist/types/components/dialog/DialogProvider.d.ts.map +1 -0
  255. package/dist/types/components/dialog/dialogStore.d.ts +42 -0
  256. package/dist/types/components/dialog/dialogStore.d.ts.map +1 -0
  257. package/dist/types/components/drawer/Drawer.d.ts +18 -4
  258. package/dist/types/components/drawer/Drawer.d.ts.map +1 -1
  259. package/dist/types/components/dropdown/Dropdown.d.ts +21 -16
  260. package/dist/types/components/dropdown/Dropdown.d.ts.map +1 -1
  261. package/dist/types/components/fileuploader/FileUploader.d.ts +22 -3
  262. package/dist/types/components/fileuploader/FileUploader.d.ts.map +1 -1
  263. package/dist/types/components/hovercard/HoverCard.d.ts +45 -5
  264. package/dist/types/components/hovercard/HoverCard.d.ts.map +1 -1
  265. package/dist/types/components/input/Input.d.ts +20 -10
  266. package/dist/types/components/input/Input.d.ts.map +1 -1
  267. package/dist/types/components/layout/Container.d.ts +8 -4
  268. package/dist/types/components/layout/Container.d.ts.map +1 -1
  269. package/dist/types/components/layout/Flex.d.ts +27 -10
  270. package/dist/types/components/layout/Flex.d.ts.map +1 -1
  271. package/dist/types/components/layout/Grid.d.ts +11 -5
  272. package/dist/types/components/layout/Grid.d.ts.map +1 -1
  273. package/dist/types/components/link/Link.d.ts +22 -0
  274. package/dist/types/components/link/Link.d.ts.map +1 -0
  275. package/dist/types/components/megamenu/MegaMenu.d.ts +8 -11
  276. package/dist/types/components/megamenu/MegaMenu.d.ts.map +1 -1
  277. package/dist/types/components/modal/Modal.d.ts +8 -7
  278. package/dist/types/components/modal/Modal.d.ts.map +1 -1
  279. package/dist/types/components/multiselect/MultiSelect.d.ts +33 -0
  280. package/dist/types/components/multiselect/MultiSelect.d.ts.map +1 -0
  281. package/dist/types/components/nuiprovider/NUIProvider.d.ts +29 -0
  282. package/dist/types/components/nuiprovider/NUIProvider.d.ts.map +1 -0
  283. package/dist/types/components/pagination/Pagination.d.ts +17 -3
  284. package/dist/types/components/pagination/Pagination.d.ts.map +1 -1
  285. package/dist/types/components/popover/Popover.d.ts +54 -16
  286. package/dist/types/components/popover/Popover.d.ts.map +1 -1
  287. package/dist/types/components/progress/Progress.d.ts +17 -7
  288. package/dist/types/components/progress/Progress.d.ts.map +1 -1
  289. package/dist/types/components/radiogroup/RadioGroup.d.ts +15 -10
  290. package/dist/types/components/radiogroup/RadioGroup.d.ts.map +1 -1
  291. package/dist/types/components/rating/Rating.d.ts +24 -10
  292. package/dist/types/components/rating/Rating.d.ts.map +1 -1
  293. package/dist/types/components/resizable/Resizable.d.ts +24 -0
  294. package/dist/types/components/resizable/Resizable.d.ts.map +1 -0
  295. package/dist/types/components/select/Select.d.ts +17 -8
  296. package/dist/types/components/select/Select.d.ts.map +1 -1
  297. package/dist/types/components/skeleton/Skeleton.d.ts +37 -36
  298. package/dist/types/components/skeleton/Skeleton.d.ts.map +1 -1
  299. package/dist/types/components/slider/Slider.d.ts +15 -4
  300. package/dist/types/components/slider/Slider.d.ts.map +1 -1
  301. package/dist/types/components/spinner/Spinner.d.ts +14 -4
  302. package/dist/types/components/spinner/Spinner.d.ts.map +1 -1
  303. package/dist/types/components/stepper/Stepper.d.ts +17 -3
  304. package/dist/types/components/stepper/Stepper.d.ts.map +1 -1
  305. package/dist/types/components/switch/Switch.d.ts +20 -5
  306. package/dist/types/components/switch/Switch.d.ts.map +1 -1
  307. package/dist/types/components/table/Table.d.ts +24 -4
  308. package/dist/types/components/table/Table.d.ts.map +1 -1
  309. package/dist/types/components/tabs/Tabs.d.ts +25 -12
  310. package/dist/types/components/tabs/Tabs.d.ts.map +1 -1
  311. package/dist/types/components/textarea/Textarea.d.ts +8 -5
  312. package/dist/types/components/textarea/Textarea.d.ts.map +1 -1
  313. package/dist/types/components/timepicker/TimePicker.d.ts +26 -0
  314. package/dist/types/components/timepicker/TimePicker.d.ts.map +1 -0
  315. package/dist/types/components/timerangepicker/TimeRangePicker.d.ts +32 -0
  316. package/dist/types/components/timerangepicker/TimeRangePicker.d.ts.map +1 -0
  317. package/dist/types/components/toast/Toast.d.ts +23 -7
  318. package/dist/types/components/toast/Toast.d.ts.map +1 -1
  319. package/dist/types/components/tooltip/Tooltip.d.ts +13 -2
  320. package/dist/types/components/tooltip/Tooltip.d.ts.map +1 -1
  321. package/dist/types/components/treeview/TreeView.d.ts +20 -6
  322. package/dist/types/components/treeview/TreeView.d.ts.map +1 -1
  323. package/dist/types/components/virtuallist/VirtualList.d.ts +12 -16
  324. package/dist/types/components/virtuallist/VirtualList.d.ts.map +1 -1
  325. package/dist/types/index.d.ts +8 -4
  326. package/dist/types/index.d.ts.map +1 -1
  327. package/dist/types/utils/cn/cn.d.ts +19 -0
  328. package/dist/types/utils/cn/cn.d.ts.map +1 -0
  329. package/dist/types/utils/generateid/generateId.d.ts +7 -0
  330. package/dist/types/utils/generateid/generateId.d.ts.map +1 -1
  331. package/dist/types/utils/index.d.ts +2 -0
  332. package/dist/types/utils/index.d.ts.map +1 -1
  333. package/dist/types/utils/inertmanager/inertManager.d.ts +13 -0
  334. package/dist/types/utils/inertmanager/inertManager.d.ts.map +1 -1
  335. package/dist/types/utils/keyboardnav/keyboardNav.d.ts +17 -6
  336. package/dist/types/utils/keyboardnav/keyboardNav.d.ts.map +1 -1
  337. package/dist/types/utils/onclickoutside/onClickOutside.d.ts +9 -1
  338. package/dist/types/utils/onclickoutside/onClickOutside.d.ts.map +1 -1
  339. package/dist/types/utils/portal/portal.d.ts +14 -1
  340. package/dist/types/utils/portal/portal.d.ts.map +1 -1
  341. package/dist/types/utils/restorefocus/restoreFocus.d.ts +8 -4
  342. package/dist/types/utils/restorefocus/restoreFocus.d.ts.map +1 -1
  343. package/dist/types/utils/scrolllock/scrollLock.d.ts +10 -2
  344. package/dist/types/utils/scrolllock/scrollLock.d.ts.map +1 -1
  345. package/dist/types/utils/slot/slot.d.ts +12 -0
  346. package/dist/types/utils/slot/slot.d.ts.map +1 -0
  347. package/dist/types/utils/trapfocus/trapFocus.d.ts +6 -2
  348. package/dist/types/utils/trapfocus/trapFocus.d.ts.map +1 -1
  349. package/dist/utils/cn/cn.cjs +2 -0
  350. package/dist/utils/cn/cn.cjs.map +1 -0
  351. package/dist/utils/cn/cn.js +21 -0
  352. package/dist/utils/cn/cn.js.map +1 -0
  353. package/dist/utils/inertmanager/inertManager.cjs.map +1 -1
  354. package/dist/utils/inertmanager/inertManager.js.map +1 -1
  355. package/dist/utils/onclickoutside/onClickOutside.cjs +1 -1
  356. package/dist/utils/onclickoutside/onClickOutside.cjs.map +1 -1
  357. package/dist/utils/onclickoutside/onClickOutside.js +10 -6
  358. package/dist/utils/onclickoutside/onClickOutside.js.map +1 -1
  359. package/dist/utils/portal/portal.cjs.map +1 -1
  360. package/dist/utils/portal/portal.js.map +1 -1
  361. package/dist/utils/restorefocus/restoreFocus.cjs.map +1 -1
  362. package/dist/utils/restorefocus/restoreFocus.js.map +1 -1
  363. package/dist/utils/scrolllock/scrollLock.cjs.map +1 -1
  364. package/dist/utils/scrolllock/scrollLock.js +7 -0
  365. package/dist/utils/scrolllock/scrollLock.js.map +1 -1
  366. package/dist/utils/slot/slot.cjs +2 -0
  367. package/dist/utils/slot/slot.cjs.map +1 -0
  368. package/dist/utils/slot/slot.js +57 -0
  369. package/dist/utils/slot/slot.js.map +1 -0
  370. package/dist/utils/trapfocus/trapFocus.cjs.map +1 -1
  371. package/dist/utils/trapfocus/trapFocus.js.map +1 -1
  372. package/package.json +49 -6
  373. package/dist/components/layout/HStack.cjs +0 -2
  374. package/dist/components/layout/HStack.cjs.map +0 -1
  375. package/dist/components/layout/HStack.js +0 -9
  376. package/dist/components/layout/HStack.js.map +0 -1
  377. package/dist/components/layout/Stack.cjs +0 -2
  378. package/dist/components/layout/Stack.cjs.map +0 -1
  379. package/dist/components/layout/Stack.js +0 -9
  380. package/dist/components/layout/Stack.js.map +0 -1
  381. package/dist/styles/nui.css +0 -1
  382. package/dist/theme/NUIProvider.cjs +0 -2
  383. package/dist/theme/NUIProvider.cjs.map +0 -1
  384. package/dist/theme/NUIProvider.js +0 -34
  385. package/dist/theme/NUIProvider.js.map +0 -1
  386. package/dist/theme/useTheme.cjs +0 -2
  387. package/dist/theme/useTheme.cjs.map +0 -1
  388. package/dist/theme/useTheme.js +0 -9
  389. package/dist/theme/useTheme.js.map +0 -1
  390. package/dist/types/components/layout/HStack.d.ts +0 -8
  391. package/dist/types/components/layout/HStack.d.ts.map +0 -1
  392. package/dist/types/components/layout/Stack.d.ts +0 -8
  393. package/dist/types/components/layout/Stack.d.ts.map +0 -1
  394. package/dist/types/theme/NUIProvider.d.ts +0 -14
  395. package/dist/types/theme/NUIProvider.d.ts.map +0 -1
  396. package/dist/types/theme/useTheme.d.ts +0 -11
  397. package/dist/types/theme/useTheme.d.ts.map +0 -1
  398. package/dist/utils/generateid/generateId.cjs +0 -2
  399. package/dist/utils/generateid/generateId.cjs.map +0 -1
  400. package/dist/utils/generateid/generateId.js +0 -7
  401. package/dist/utils/generateid/generateId.js.map +0 -1
  402. package/dist/utils/keyboardnav/keyboardNav.cjs +0 -2
  403. package/dist/utils/keyboardnav/keyboardNav.cjs.map +0 -1
  404. package/dist/utils/keyboardnav/keyboardNav.js +0 -10
  405. package/dist/utils/keyboardnav/keyboardNav.js.map +0 -1
@@ -1,83 +1,118 @@
1
- import { jsxs as c, jsx as r } from "react/jsx-runtime";
2
- import { useRef as y, useState as f, useCallback as b } from "react";
1
+ import { jsxs as r, jsx as i } from "react/jsx-runtime";
2
+ import { useRef as j, useState as k, useCallback as z } from "react";
3
3
  /* empty css */
4
- function O({
5
- multiple: n = !1,
6
- accept: d,
7
- onChange: s,
8
- className: u = "",
9
- placeholder: p = "Drag files here or click to upload"
4
+ import { cn as y } from "../../utils/cn/cn.js";
5
+ function I(o, u = 2) {
6
+ if (!+o) return "0 Bytes";
7
+ const a = 1024, s = u < 0 ? 0 : u, h = ["Bytes", "KB", "MB", "GB", "TB"], l = Math.floor(Math.log(o) / Math.log(a));
8
+ return `${parseFloat((o / Math.pow(a, l)).toFixed(s))} ${h[l]}`;
9
+ }
10
+ function R({
11
+ value: o,
12
+ defaultValue: u,
13
+ onChange: a,
14
+ multiple: s = !1,
15
+ accept: h,
16
+ maxSize: l,
17
+ className: x,
18
+ placeholder: N = "Drag & drop files here, or click to browse",
19
+ disabled: n = !1
10
20
  }) {
11
- const t = y(null), [a, m] = f([]), [v, o] = f(!1), i = b(
12
- (e) => {
13
- m(e), s?.(e);
14
- },
15
- [s]
16
- ), h = (e) => {
17
- e.preventDefault(), o(!1);
18
- const l = Array.from(e.dataTransfer.files);
19
- if (!n) {
20
- i([l[0]]);
21
- return;
22
- }
23
- i([...a, ...l]);
24
- }, g = (e) => {
25
- const l = e.target.files ? Array.from(e.target.files) : [];
26
- if (!n) {
27
- i([l[0]]);
28
- return;
29
- }
30
- i([...a, ...l]);
31
- }, D = (e) => {
32
- const l = a.filter((N, k) => k !== e);
33
- i(l);
21
+ const c = j(null), d = o !== void 0, [B, v] = k(u || []), f = d ? o : B, [D, m] = k(!1), g = z((e) => {
22
+ let t = e;
23
+ l && (t = e.filter(($) => $.size <= l));
24
+ const p = s ? [...f, ...t] : [t[0]].filter(Boolean);
25
+ d || v(p), a?.(p);
26
+ }, [f, s, l, d, a]), F = (e) => {
27
+ if (n) return;
28
+ const t = f.filter((p) => p !== e);
29
+ d || v(t), a?.(t);
30
+ }, w = (e) => {
31
+ e.preventDefault(), e.stopPropagation(), n || m(!0);
32
+ }, M = (e) => {
33
+ e.preventDefault(), e.stopPropagation(), m(!1);
34
+ }, L = (e) => {
35
+ e.preventDefault(), e.stopPropagation(), m(!1), !n && e.dataTransfer.files && e.dataTransfer.files.length > 0 && g(Array.from(e.dataTransfer.files));
36
+ }, C = (e) => {
37
+ e.target.files && e.target.files.length > 0 && g(Array.from(e.target.files)), c.current && (c.current.value = "");
34
38
  };
35
- return /* @__PURE__ */ c("div", { className: `ui-fileupload ${u}`, children: [
39
+ return /* @__PURE__ */ r("div", { className: y("nui-file-uploader", x), children: [
36
40
  /* @__PURE__ */ r(
37
41
  "div",
38
42
  {
39
- className: `ui-fileupload-dropzone ${v ? "dragover" : ""}`,
40
- tabIndex: 0,
41
43
  role: "button",
44
+ tabIndex: n ? -1 : 0,
42
45
  "aria-label": "Upload files",
43
- onClick: () => t.current?.click(),
46
+ "aria-disabled": n,
47
+ className: y(
48
+ "nui-file-dropzone",
49
+ D && "dragover",
50
+ n && "disabled"
51
+ ),
52
+ onClick: () => !n && c.current?.click(),
44
53
  onKeyDown: (e) => {
45
- (e.key === "Enter" || e.key === " ") && t.current?.click();
46
- },
47
- onDragOver: (e) => {
48
- e.preventDefault(), o(!0);
54
+ !n && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), c.current?.click());
49
55
  },
50
- onDragLeave: () => o(!1),
51
- onDrop: h,
52
- children: /* @__PURE__ */ r("span", { children: p })
56
+ onDragOver: w,
57
+ onDragLeave: M,
58
+ onDrop: L,
59
+ children: [
60
+ /* @__PURE__ */ r("svg", { className: "nui-file-icon", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
61
+ /* @__PURE__ */ i("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
62
+ /* @__PURE__ */ i("polyline", { points: "17 8 12 3 7 8" }),
63
+ /* @__PURE__ */ i("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
64
+ ] }),
65
+ /* @__PURE__ */ i("span", { className: "nui-file-placeholder", children: N })
66
+ ]
53
67
  }
54
68
  ),
55
- /* @__PURE__ */ r(
69
+ /* @__PURE__ */ i(
56
70
  "input",
57
71
  {
58
- ref: t,
72
+ ref: c,
59
73
  type: "file",
60
- accept: d,
61
- multiple: n,
62
- style: { display: "none" },
63
- onChange: g
74
+ "data-testid": "nui-file-input",
75
+ accept: h,
76
+ multiple: s,
77
+ disabled: n,
78
+ onChange: C,
79
+ className: "nui-file-hidden-input",
80
+ tabIndex: -1,
81
+ "aria-hidden": "true"
64
82
  }
65
83
  ),
66
- a.length > 0 && /* @__PURE__ */ r("ul", { className: "ui-fileupload-list", children: a.map((e, l) => /* @__PURE__ */ c("li", { className: "ui-fileupload-item", children: [
67
- /* @__PURE__ */ r("span", { className: "ui-fileupload-filename", children: e.name }),
68
- /* @__PURE__ */ r(
69
- "button",
70
- {
71
- className: "ui-fileupload-remove",
72
- "aria-label": "Remove file",
73
- onClick: () => D(l),
74
- children: "×"
75
- }
76
- )
77
- ] }, l)) })
84
+ f.length > 0 && /* @__PURE__ */ i("ul", { className: "nui-file-list", "aria-label": "Selected files", children: f.map((e) => {
85
+ const t = `${e.name}-${e.size}-${e.lastModified}`;
86
+ return /* @__PURE__ */ r("li", { className: "nui-file-item", children: [
87
+ /* @__PURE__ */ r("div", { className: "nui-file-info", children: [
88
+ /* @__PURE__ */ r("svg", { className: "nui-file-item-icon", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
89
+ /* @__PURE__ */ i("path", { d: "M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z" }),
90
+ /* @__PURE__ */ i("polyline", { points: "13 2 13 9 20 9" })
91
+ ] }),
92
+ /* @__PURE__ */ r("div", { className: "nui-file-text", children: [
93
+ /* @__PURE__ */ i("span", { className: "nui-file-name", children: e.name }),
94
+ /* @__PURE__ */ i("span", { className: "nui-file-size", children: I(e.size) })
95
+ ] })
96
+ ] }),
97
+ /* @__PURE__ */ i(
98
+ "button",
99
+ {
100
+ type: "button",
101
+ className: "nui-file-remove",
102
+ "aria-label": `Remove ${e.name}`,
103
+ onClick: () => F(e),
104
+ disabled: n,
105
+ children: /* @__PURE__ */ r("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
106
+ /* @__PURE__ */ i("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
107
+ /* @__PURE__ */ i("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
108
+ ] })
109
+ }
110
+ )
111
+ ] }, t);
112
+ }) })
78
113
  ] });
79
114
  }
80
115
  export {
81
- O as FileUploader
116
+ R as FileUploader
82
117
  };
83
118
  //# sourceMappingURL=FileUploader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileUploader.js","sources":["../../../src/components/fileuploader/FileUploader.tsx"],"sourcesContent":["/**\r\n * FileUploader.tsx — FINAL VERSION\r\n * --------------------------------\r\n * Features:\r\n * - Drag & drop\r\n * - Click to upload\r\n * - Keyboard activate\r\n * - File list preview\r\n * - Remove file\r\n * - Accept filters\r\n * - Multiple uploads\r\n */\r\n\r\nimport { useRef, useState, useCallback, DragEvent, ChangeEvent } from 'react';\r\nimport './FileUploader.css';\r\n\r\nexport interface FileUploaderProps {\r\n multiple?: boolean;\r\n accept?: string;\r\n onChange?: (files: File[]) => void;\r\n className?: string;\r\n placeholder?: string;\r\n}\r\n\r\nexport function FileUploader({\r\n multiple = false,\r\n accept,\r\n onChange,\r\n className = '',\r\n placeholder = 'Drag files here or click to upload',\r\n}: FileUploaderProps) {\r\n const inputRef = useRef<HTMLInputElement | null>(null);\r\n const [files, setFiles] = useState<File[]>([]);\r\n const [dragOver, setDragOver] = useState(false);\r\n\r\n const updateFiles = useCallback(\r\n (newFiles: File[]) => {\r\n setFiles(newFiles);\r\n onChange?.(newFiles);\r\n },\r\n [onChange]\r\n );\r\n\r\n const handleDrop = (e: DragEvent) => {\r\n e.preventDefault();\r\n setDragOver(false);\r\n\r\n const dropped = Array.from(e.dataTransfer.files);\r\n\r\n if (!multiple) {\r\n updateFiles([dropped[0]]);\r\n return;\r\n }\r\n\r\n updateFiles([...files, ...dropped]);\r\n };\r\n\r\n const handleSelect = (e: ChangeEvent<HTMLInputElement>) => {\r\n const selected = e.target.files ? Array.from(e.target.files) : [];\r\n if (!multiple) {\r\n updateFiles([selected[0]]);\r\n return;\r\n }\r\n updateFiles([...files, ...selected]);\r\n };\r\n\r\n const removeFile = (index: number) => {\r\n const newList = files.filter((_, i) => i !== index);\r\n updateFiles(newList);\r\n };\r\n\r\n return (\r\n <div className={`ui-fileupload ${className}`}>\r\n {/* DROP ZONE */}\r\n <div\r\n className={`ui-fileupload-dropzone ${dragOver ? 'dragover' : ''}`}\r\n tabIndex={0}\r\n role=\"button\"\r\n aria-label=\"Upload files\"\r\n onClick={() => inputRef.current?.click()}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter' || e.key === ' ') inputRef.current?.click();\r\n }}\r\n onDragOver={(e) => {\r\n e.preventDefault();\r\n setDragOver(true);\r\n }}\r\n onDragLeave={() => setDragOver(false)}\r\n onDrop={handleDrop}\r\n >\r\n <span>{placeholder}</span>\r\n </div>\r\n\r\n {/* HIDDEN INPUT */}\r\n <input\r\n ref={inputRef}\r\n type=\"file\"\r\n accept={accept}\r\n multiple={multiple}\r\n style={{ display: 'none' }}\r\n onChange={handleSelect}\r\n />\r\n\r\n {/* FILE LIST */}\r\n {files.length > 0 && (\r\n <ul className=\"ui-fileupload-list\">\r\n {files.map((file, i) => (\r\n <li key={i} className=\"ui-fileupload-item\">\r\n <span className=\"ui-fileupload-filename\">{file.name}</span>\r\n <button\r\n className=\"ui-fileupload-remove\"\r\n aria-label=\"Remove file\"\r\n onClick={() => removeFile(i)}\r\n >\r\n ×\r\n </button>\r\n </li>\r\n ))}\r\n </ul>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["FileUploader","multiple","accept","onChange","className","placeholder","inputRef","useRef","files","setFiles","useState","dragOver","setDragOver","updateFiles","useCallback","newFiles","handleDrop","dropped","handleSelect","selected","removeFile","index","newList","_","i","jsxs","jsx","file"],"mappings":";;;AAwBO,SAASA,EAAa;AAAA,EAC3B,UAAAC,IAAW;AAAA,EACX,QAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,aAAAC,IAAc;AAChB,GAAsB;AACpB,QAAMC,IAAWC,EAAgC,IAAI,GAC/C,CAACC,GAAOC,CAAQ,IAAIC,EAAiB,CAAA,CAAE,GACvC,CAACC,GAAUC,CAAW,IAAIF,EAAS,EAAK,GAExCG,IAAcC;AAAA,IAClB,CAACC,MAAqB;AACpB,MAAAN,EAASM,CAAQ,GACjBZ,IAAWY,CAAQ;AAAA,IACrB;AAAA,IACA,CAACZ,CAAQ;AAAA,EAAA,GAGLa,IAAa,CAAC,MAAiB;AACnC,MAAE,eAAA,GACFJ,EAAY,EAAK;AAEjB,UAAMK,IAAU,MAAM,KAAK,EAAE,aAAa,KAAK;AAE/C,QAAI,CAAChB,GAAU;AACb,MAAAY,EAAY,CAACI,EAAQ,CAAC,CAAC,CAAC;AACxB;AAAA,IACF;AAEA,IAAAJ,EAAY,CAAC,GAAGL,GAAO,GAAGS,CAAO,CAAC;AAAA,EACpC,GAEMC,IAAe,CAAC,MAAqC;AACzD,UAAMC,IAAW,EAAE,OAAO,QAAQ,MAAM,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;AAC/D,QAAI,CAAClB,GAAU;AACb,MAAAY,EAAY,CAACM,EAAS,CAAC,CAAC,CAAC;AACzB;AAAA,IACF;AACA,IAAAN,EAAY,CAAC,GAAGL,GAAO,GAAGW,CAAQ,CAAC;AAAA,EACrC,GAEMC,IAAa,CAACC,MAAkB;AACpC,UAAMC,IAAUd,EAAM,OAAO,CAACe,GAAGC,MAAMA,MAAMH,CAAK;AAClD,IAAAR,EAAYS,CAAO;AAAA,EACrB;AAEA,SACE,gBAAAG,EAAC,OAAA,EAAI,WAAW,iBAAiBrB,CAAS,IAExC,UAAA;AAAA,IAAA,gBAAAsB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,0BAA0Bf,IAAW,aAAa,EAAE;AAAA,QAC/D,UAAU;AAAA,QACV,MAAK;AAAA,QACL,cAAW;AAAA,QACX,SAAS,MAAML,EAAS,SAAS,MAAA;AAAA,QACjC,WAAW,CAAC,MAAM;AAChB,WAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,QAAKA,EAAS,SAAS,MAAA;AAAA,QAC5D;AAAA,QACA,YAAY,CAAC,MAAM;AACjB,YAAE,eAAA,GACFM,EAAY,EAAI;AAAA,QAClB;AAAA,QACA,aAAa,MAAMA,EAAY,EAAK;AAAA,QACpC,QAAQI;AAAA,QAER,UAAA,gBAAAU,EAAC,UAAM,UAAArB,EAAA,CAAY;AAAA,MAAA;AAAA,IAAA;AAAA,IAIrB,gBAAAqB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKpB;AAAA,QACL,MAAK;AAAA,QACL,QAAAJ;AAAA,QACA,UAAAD;AAAA,QACA,OAAO,EAAE,SAAS,OAAA;AAAA,QAClB,UAAUiB;AAAA,MAAA;AAAA,IAAA;AAAA,IAIXV,EAAM,SAAS,KACd,gBAAAkB,EAAC,QAAG,WAAU,sBACX,UAAAlB,EAAM,IAAI,CAACmB,GAAMH,MAChB,gBAAAC,EAAC,MAAA,EAAW,WAAU,sBACpB,UAAA;AAAA,MAAA,gBAAAC,EAAC,QAAA,EAAK,WAAU,0BAA0B,UAAAC,EAAK,MAAK;AAAA,MACpD,gBAAAD;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,cAAW;AAAA,UACX,SAAS,MAAMN,EAAWI,CAAC;AAAA,UAC5B,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,EAAA,GAROA,CAST,CACD,EAAA,CACH;AAAA,EAAA,GAEJ;AAEJ;"}
1
+ {"version":3,"file":"FileUploader.js","sources":["../../../src/components/fileuploader/FileUploader.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useRef, useState, useCallback, DragEvent, ChangeEvent } from 'react';\nimport { cn } from '../../utils';\nimport './FileUploader.css';\n\n/* ============================================================\n * Helper\n * ============================================================ */\n\n/**\n * Formats a byte count into a human-readable string (e.g., 1.5 MB).\n */\nfunction formatBytes(bytes: number, decimals = 2) {\n if (!+bytes) return '0 Bytes';\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;\n}\n\n/* ============================================================\n * Types\n * ============================================================ */\n\nexport interface FileUploaderProps {\n /** Controlled state for the selected files */\n value?: File[];\n /** Uncontrolled initial state for the selected files */\n defaultValue?: File[];\n /** Callback fired when the list of selected files changes */\n onChange?: (files: File[]) => void;\n /** Whether to allow multiple files to be selected. Defaults to false. */\n multiple?: boolean;\n /** A comma-separated list of allowed file extensions or MIME types (e.g., '.jpg, .png, application/pdf') */\n accept?: string;\n /** Maximum allowed file size in bytes */\n maxSize?: number;\n /** Custom class name applied to the root container */\n className?: string;\n /** Custom text or element displayed inside the dropzone */\n placeholder?: React.ReactNode;\n /** Disables the dropzone and prevents file selection */\n disabled?: boolean;\n}\n\n/* ============================================================\n * Component\n * ============================================================ */\n\n/**\n * FileUploader Component\n * * A drag-and-drop zone for file uploads with built-in preview and file management.\n * * Follows WAI-ARIA guidelines by delegating keyboard interactions to a hidden native file input.\n */\nexport function FileUploader({\n value,\n defaultValue,\n onChange,\n multiple = false,\n accept,\n maxSize,\n className,\n placeholder = 'Drag & drop files here, or click to browse',\n disabled = false,\n}: FileUploaderProps) {\n const inputRef = useRef<HTMLInputElement | null>(null);\n \n const isControlled = value !== undefined;\n const [internalFiles, setInternalFiles] = useState<File[]>(defaultValue || []);\n const files = isControlled ? value : internalFiles;\n \n const [isDragOver, setIsDragOver] = useState(false);\n\n /* ----------------------------------------------------\n File Handlers\n ---------------------------------------------------- */\n const updateFiles = useCallback((newFiles: File[]) => {\n let validFiles = newFiles;\n\n // Filter by max size if provided\n if (maxSize) {\n validFiles = newFiles.filter(f => f.size <= maxSize);\n }\n\n const nextFiles = multiple ? [...files, ...validFiles] : [validFiles[0]].filter(Boolean);\n \n if (!isControlled) setInternalFiles(nextFiles);\n onChange?.(nextFiles);\n }, [files, multiple, maxSize, isControlled, onChange]);\n\n const removeFile = (fileToRemove: File) => {\n if (disabled) return;\n const nextFiles = files.filter(f => f !== fileToRemove);\n if (!isControlled) setInternalFiles(nextFiles);\n onChange?.(nextFiles);\n };\n\n /* ----------------------------------------------------\n Event Listeners\n ---------------------------------------------------- */\n const onDragOver = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n if (!disabled) setIsDragOver(true);\n };\n\n const onDragLeave = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n };\n\n const onDrop = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n \n if (disabled) return;\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n updateFiles(Array.from(e.dataTransfer.files));\n }\n };\n\n const onFileSelect = (e: ChangeEvent<HTMLInputElement>) => {\n if (e.target.files && e.target.files.length > 0) {\n updateFiles(Array.from(e.target.files));\n }\n // Clear the native input value so the exact same file can be selected again if removed\n if (inputRef.current) inputRef.current.value = '';\n };\n\n /* ----------------------------------------------------\n Render\n ---------------------------------------------------- */\n return (\n <div className={cn(\"nui-file-uploader\", className)}>\n \n {/* DROP ZONE */}\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-label=\"Upload files\"\n aria-disabled={disabled}\n className={cn(\n \"nui-file-dropzone\",\n isDragOver && \"dragover\",\n disabled && \"disabled\"\n )}\n onClick={() => !disabled && inputRef.current?.click()}\n onKeyDown={(e) => {\n if (!disabled && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n inputRef.current?.click();\n }\n }}\n onDragOver={onDragOver}\n onDragLeave={onDragLeave}\n onDrop={onDrop}\n >\n <svg className=\"nui-file-icon\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"></path>\n <polyline points=\"17 8 12 3 7 8\"></polyline>\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"></line>\n </svg>\n <span className=\"nui-file-placeholder\">{placeholder}</span>\n </div>\n\n {/* HIDDEN NATIVE INPUT */}\n <input\n ref={inputRef}\n type=\"file\"\n data-testid=\"nui-file-input\"\n accept={accept}\n multiple={multiple}\n disabled={disabled}\n onChange={onFileSelect}\n className=\"nui-file-hidden-input\"\n tabIndex={-1}\n aria-hidden=\"true\"\n />\n\n {/* FILE LIST PREVIEW */}\n {files.length > 0 && (\n <ul className=\"nui-file-list\" aria-label=\"Selected files\">\n {files.map((file) => {\n // Create a stable key based on file properties\n const fileKey = `${file.name}-${file.size}-${file.lastModified}`;\n \n return (\n <li key={fileKey} className=\"nui-file-item\">\n <div className=\"nui-file-info\">\n <svg className=\"nui-file-item-icon\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z\"></path>\n <polyline points=\"13 2 13 9 20 9\"></polyline>\n </svg>\n <div className=\"nui-file-text\">\n <span className=\"nui-file-name\">{file.name}</span>\n <span className=\"nui-file-size\">{formatBytes(file.size)}</span>\n </div>\n </div>\n \n <button\n type=\"button\"\n className=\"nui-file-remove\"\n aria-label={`Remove ${file.name}`}\n onClick={() => removeFile(file)}\n disabled={disabled}\n >\n <svg width=\"14\" height=\"14\" 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 </li>\n );\n })}\n </ul>\n )}\n </div>\n );\n}"],"names":["formatBytes","bytes","decimals","k","dm","sizes","i","FileUploader","value","defaultValue","onChange","multiple","accept","maxSize","className","placeholder","disabled","inputRef","useRef","isControlled","internalFiles","setInternalFiles","useState","files","isDragOver","setIsDragOver","updateFiles","useCallback","newFiles","validFiles","f","nextFiles","removeFile","fileToRemove","onDragOver","onDragLeave","onDrop","onFileSelect","cn","jsxs","jsx","file","fileKey"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react/jsx-runtime"),e=require("react");;/* empty css */const L=require("../../utils/onclickoutside/onClickOutside.cjs"),T=require("../../utils/portal/portal.cjs");function C({trigger:E,children:p,openDelay:g=120,closeDelay:h=140,className:w=""}){const[t,n]=e.useState(!1),f=e.useRef(null),v=e.useRef(null),i=e.useRef(null),c=e.useRef(null),l=()=>{i.current&&clearTimeout(i.current),c.current&&clearTimeout(c.current)},m=()=>{l(),i.current=setTimeout(()=>n(!0),g)},a=()=>{l(),c.current=setTimeout(()=>n(!1),h)};e.useEffect(()=>{if(!t)return;const o=s=>{s.key==="Escape"&&n(!1)};return document.addEventListener("keydown",o),()=>document.removeEventListener("keydown",o)},[t]),e.useEffect(()=>{if(t)return L.onClickOutside(v,()=>n(!1))},[t]);const[d,R]=e.useState(null),r=e.useCallback(()=>{const o=f.current;if(!o)return;const s=o.getBoundingClientRect();R({top:s.bottom+8,left:s.left})},[]);return e.useEffect(()=>{if(t)return r(),window.addEventListener("resize",r),window.addEventListener("scroll",r,!0),()=>{window.removeEventListener("resize",r),window.removeEventListener("scroll",r,!0)}},[t,r]),u.jsxs("div",{className:"ui-hovercard-root",children:[u.jsx("div",{ref:f,className:"ui-hovercard-trigger",onMouseEnter:m,onMouseLeave:a,onFocus:m,onBlur:a,children:E}),t&&d&&u.jsx(T.Portal,{children:u.jsx("div",{ref:v,className:`ui-hovercard ${w}`,style:{top:d.top,left:d.left},role:"dialog","aria-hidden":!t,onMouseEnter:()=>{l(),n(!0)},onMouseLeave:a,children:p})})]})}exports.HoverCard=C;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const H=require("react/jsx-runtime"),e=require("react");;/* empty css */const q=require("../../utils/onclickoutside/onClickOutside.cjs"),S=require("../../utils/portal/portal.cjs"),B=require("../../utils/cn/cn.cjs"),L=e.createContext(null);function k(){const a=e.useContext(L);if(!a)throw new Error("HoverCard components must be inside <HoverCard>");return a}function b({children:a,openDelay:f=200,closeDelay:c=300}){const[u,d]=e.useState(!1),o=e.useRef(null),r=e.useRef(null),n=`hovercard-${e.useId()}`,s=e.useRef(null),t=e.useRef(null),l=e.useCallback(()=>{s.current&&clearTimeout(s.current),t.current&&clearTimeout(t.current)},[]),R=e.useCallback(()=>{l(),s.current=setTimeout(()=>d(!0),f)},[f,l]),w=e.useCallback(()=>{l(),t.current=setTimeout(()=>d(!1),c)},[c,l]);return e.useEffect(()=>()=>l(),[l]),H.jsx(L.Provider,{value:{open:u,setOpen:d,triggerRef:o,contentRef:r,contentId:n,scheduleOpen:R,scheduleClose:w,clearTimers:l},children:a})}b.displayName="HoverCard";function T({children:a}){const{open:f,triggerRef:c,contentId:u,scheduleOpen:d,scheduleClose:o}=k(),r=e.Children.only(a),n=r.props.ref??r.ref,s={ref:t=>{c.current=t,typeof n=="function"?n(t):n&&typeof n=="object"&&"current"in n&&(n.current=t)},"aria-haspopup":"dialog","aria-expanded":f,"aria-controls":f?u:void 0,onMouseEnter:t=>{d(),r.props.onMouseEnter?.(t)},onMouseLeave:t=>{o(),r.props.onMouseLeave?.(t)},onFocus:t=>{d(),r.props.onFocus?.(t)},onBlur:t=>{o(),r.props.onBlur?.(t)}};return e.cloneElement(r,s)}T.displayName="HoverCard.Trigger";function x({children:a,className:f,placement:c="bottom",offset:u=8,...d}){const{open:o,setOpen:r,triggerRef:n,contentRef:s,contentId:t,scheduleClose:l,clearTimers:R}=k(),[w,O]=e.useState({top:-9999,left:-9999}),[P,j]=e.useState(c);e.useEffect(()=>{if(!o)return;const i=p=>{p.key==="Escape"&&r(!1)};return document.addEventListener("keydown",i),()=>document.removeEventListener("keydown",i)},[o,r]),e.useEffect(()=>o?q.onClickOutside([s,n],()=>{r(!1)}):void 0,[o,r,s,n]);const C=e.useCallback(()=>{if(!n.current||!s.current)return;const i=n.current.getBoundingClientRect(),p=s.current.getBoundingClientRect(),M=window.scrollX,v=window.scrollY;let m=i.left+M+i.width/2-p.width/2;const h=12,y=document.documentElement.clientWidth-p.width-h;m<h&&(m=h),m>y&&(m=y);let g=i.bottom+v+u,E=c;c==="bottom"&&g+p.height>window.innerHeight+v-h?(g=i.top+v-p.height-u,E="top"):c==="top"&&(g=i.top+v-p.height-u,g<v+h&&(g=i.bottom+v+u,E="bottom")),j(E),O({top:g,left:m})},[c,u,n,s]);return e.useLayoutEffect(()=>{if(o)return C(),window.addEventListener("resize",C),window.addEventListener("scroll",C,!0),()=>{window.removeEventListener("resize",C),window.removeEventListener("scroll",C,!0)}},[o,C]),o?H.jsx(S.Portal,{children:H.jsx("div",{id:t,ref:s,role:"dialog","data-placement":P,className:B.cn("nui-hovercard-content",f),style:{position:"absolute",top:w.top,left:w.left},onMouseEnter:()=>{R()},onMouseLeave:l,...d,children:a})}):null}x.displayName="HoverCard.Content";const I=Object.assign(b,{Trigger:T,Content:x});exports.HoverCard=I;exports.HoverCardContent=x;exports.HoverCardRoot=b;exports.HoverCardTrigger=T;
2
2
  //# sourceMappingURL=HoverCard.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"HoverCard.cjs","sources":["../../../src/components/hovercard/HoverCard.tsx"],"sourcesContent":["/**\r\n * HoverCard.tsx — FINAL VERSION\r\n * --------------------------------\r\n * Features:\r\n * - Open on hover / focus\r\n * - Close on leave / blur\r\n * - Delay open & close\r\n * - ESC to dismiss\r\n * - Outside dismiss\r\n * - Auto position (simple version)\r\n * - Portal rendering\r\n */\r\n\r\nimport { useState, useRef, useEffect, ReactNode, useCallback } from 'react';\r\nimport './HoverCard.css';\r\nimport { Portal, onClickOutside } from '../../utils/index';\r\n\r\nexport interface HoverCardProps {\r\n trigger: ReactNode;\r\n children: ReactNode;\r\n openDelay?: number;\r\n closeDelay?: number;\r\n className?: string;\r\n}\r\n\r\nexport function HoverCard({\r\n trigger,\r\n children,\r\n openDelay = 120,\r\n closeDelay = 140,\r\n className = '',\r\n}: HoverCardProps) {\r\n const [open, setOpen] = useState(false);\r\n\r\n const triggerRef = useRef<HTMLDivElement | null>(null);\r\n const cardRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const openTimer = useRef<NodeJS.Timeout | null>(null);\r\n const closeTimer = useRef<NodeJS.Timeout | null>(null);\r\n\r\n const clearTimers = () => {\r\n if (openTimer.current) clearTimeout(openTimer.current);\r\n if (closeTimer.current) clearTimeout(closeTimer.current);\r\n };\r\n\r\n const scheduleOpen = () => {\r\n clearTimers();\r\n openTimer.current = setTimeout(() => setOpen(true), openDelay);\r\n };\r\n\r\n const scheduleClose = () => {\r\n clearTimers();\r\n closeTimer.current = setTimeout(() => setOpen(false), closeDelay);\r\n };\r\n\r\n // ESC key dismiss\r\n useEffect(() => {\r\n if (!open) return;\r\n const handler = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setOpen(false);\r\n };\r\n document.addEventListener('keydown', handler);\r\n return () => document.removeEventListener('keydown', handler);\r\n }, [open]);\r\n\r\n // click outside\r\n useEffect(() => {\r\n if (!open) return;\r\n return onClickOutside(cardRef, () => setOpen(false));\r\n }, [open]);\r\n\r\n // compute position\r\n const [pos, setPos] = useState<{ top: number; left: number } | null>(null);\r\n\r\n const updatePosition = useCallback(() => {\r\n const triggerEl = triggerRef.current;\r\n if (!triggerEl) return;\r\n\r\n const rect = triggerEl.getBoundingClientRect();\r\n setPos({\r\n top: rect.bottom + 8, // spacing\r\n left: rect.left,\r\n });\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n updatePosition();\r\n window.addEventListener('resize', updatePosition);\r\n window.addEventListener('scroll', updatePosition, true);\r\n return () => {\r\n window.removeEventListener('resize', updatePosition);\r\n window.removeEventListener('scroll', updatePosition, true);\r\n };\r\n }, [open, updatePosition]);\r\n\r\n return (\r\n <div className=\"ui-hovercard-root\">\r\n {/* TRIGGER */}\r\n <div\r\n ref={triggerRef}\r\n className=\"ui-hovercard-trigger\"\r\n onMouseEnter={scheduleOpen}\r\n onMouseLeave={scheduleClose}\r\n onFocus={scheduleOpen}\r\n onBlur={scheduleClose}\r\n >\r\n {trigger}\r\n </div>\r\n\r\n {/* CARD */}\r\n {open && pos && (\r\n <Portal>\r\n <div\r\n ref={cardRef}\r\n className={`ui-hovercard ${className}`}\r\n style={{ top: pos.top, left: pos.left }}\r\n role=\"dialog\"\r\n aria-hidden={!open}\r\n onMouseEnter={() => {\r\n clearTimers();\r\n setOpen(true);\r\n }}\r\n onMouseLeave={scheduleClose}\r\n >\r\n {children}\r\n </div>\r\n </Portal>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["HoverCard","trigger","children","openDelay","closeDelay","className","open","setOpen","useState","triggerRef","useRef","cardRef","openTimer","closeTimer","clearTimers","scheduleOpen","scheduleClose","useEffect","handler","e","onClickOutside","pos","setPos","updatePosition","useCallback","triggerEl","rect","jsxs","jsx","Portal"],"mappings":"mRAyBO,SAASA,EAAU,CACxB,QAAAC,EACA,SAAAC,EACA,UAAAC,EAAY,IACZ,WAAAC,EAAa,IACb,UAAAC,EAAY,EACd,EAAmB,CACjB,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAS,EAAK,EAEhCC,EAAaC,EAAAA,OAA8B,IAAI,EAC/CC,EAAUD,EAAAA,OAA8B,IAAI,EAE5CE,EAAYF,EAAAA,OAA8B,IAAI,EAC9CG,EAAaH,EAAAA,OAA8B,IAAI,EAE/CI,EAAc,IAAM,CACpBF,EAAU,SAAS,aAAaA,EAAU,OAAO,EACjDC,EAAW,SAAS,aAAaA,EAAW,OAAO,CACzD,EAEME,EAAe,IAAM,CACzBD,EAAA,EACAF,EAAU,QAAU,WAAW,IAAML,EAAQ,EAAI,EAAGJ,CAAS,CAC/D,EAEMa,EAAgB,IAAM,CAC1BF,EAAA,EACAD,EAAW,QAAU,WAAW,IAAMN,EAAQ,EAAK,EAAGH,CAAU,CAClE,EAGAa,EAAAA,UAAU,IAAM,CACd,GAAI,CAACX,EAAM,OACX,MAAMY,EAAWC,GAAqB,CAChCA,EAAE,MAAQ,UAAUZ,EAAQ,EAAK,CACvC,EACA,gBAAS,iBAAiB,UAAWW,CAAO,EACrC,IAAM,SAAS,oBAAoB,UAAWA,CAAO,CAC9D,EAAG,CAACZ,CAAI,CAAC,EAGTW,EAAAA,UAAU,IAAM,CACd,GAAKX,EACL,OAAOc,EAAAA,eAAeT,EAAS,IAAMJ,EAAQ,EAAK,CAAC,CACrD,EAAG,CAACD,CAAI,CAAC,EAGT,KAAM,CAACe,EAAKC,CAAM,EAAId,EAAAA,SAA+C,IAAI,EAEnEe,EAAiBC,EAAAA,YAAY,IAAM,CACvC,MAAMC,EAAYhB,EAAW,QAC7B,GAAI,CAACgB,EAAW,OAEhB,MAAMC,EAAOD,EAAU,sBAAA,EACvBH,EAAO,CACL,IAAKI,EAAK,OAAS,EACnB,KAAMA,EAAK,IAAA,CACZ,CACH,EAAG,CAAA,CAAE,EAELT,OAAAA,EAAAA,UAAU,IAAM,CACd,GAAKX,EACL,OAAAiB,EAAA,EACA,OAAO,iBAAiB,SAAUA,CAAc,EAChD,OAAO,iBAAiB,SAAUA,EAAgB,EAAI,EAC/C,IAAM,CACX,OAAO,oBAAoB,SAAUA,CAAc,EACnD,OAAO,oBAAoB,SAAUA,EAAgB,EAAI,CAC3D,CACF,EAAG,CAACjB,EAAMiB,CAAc,CAAC,EAGvBI,EAAAA,KAAC,MAAA,CAAI,UAAU,oBAEb,SAAA,CAAAC,EAAAA,IAAC,MAAA,CACC,IAAKnB,EACL,UAAU,uBACV,aAAcM,EACd,aAAcC,EACd,QAASD,EACT,OAAQC,EAEP,SAAAf,CAAA,CAAA,EAIFK,GAAQe,GACPO,EAAAA,IAACC,EAAAA,OAAA,CACC,SAAAD,EAAAA,IAAC,MAAA,CACC,IAAKjB,EACL,UAAW,gBAAgBN,CAAS,GACpC,MAAO,CAAE,IAAKgB,EAAI,IAAK,KAAMA,EAAI,IAAA,EACjC,KAAK,SACL,cAAa,CAACf,EACd,aAAc,IAAM,CAClBQ,EAAA,EACAP,EAAQ,EAAI,CACd,EACA,aAAcS,EAEb,SAAAd,CAAA,CAAA,CACH,CACF,CAAA,EAEJ,CAEJ"}
1
+ {"version":3,"file":"HoverCard.cjs","sources":["../../../src/components/hovercard/HoverCard.tsx"],"sourcesContent":["\"use client\";\n\nimport React, {\n createContext,\n useContext,\n useState,\n useRef,\n useEffect,\n useCallback,\n useLayoutEffect,\n useId,\n} from 'react';\nimport { cn } from '../../utils';\nimport { Portal, onClickOutside } from '../../utils';\nimport './HoverCard.css';\n\nexport type HoverCardPlacement = 'top' | 'bottom';\n\n/* -------------------------------------------------------\n * Context\n * ------------------------------------------------------*/\ninterface HoverCardContextValue {\n open: boolean;\n setOpen: React.Dispatch<React.SetStateAction<boolean>>;\n triggerRef: React.RefObject<HTMLElement | null>;\n contentRef: React.RefObject<HTMLDivElement | null>;\n contentId: string;\n scheduleOpen: () => void;\n scheduleClose: () => void;\n clearTimers: () => void;\n}\n\nconst HoverCardContext = createContext<HoverCardContextValue | null>(null);\n\nfunction useHoverCard() {\n const ctx = useContext(HoverCardContext);\n if (!ctx) throw new Error('HoverCard components must be inside <HoverCard>');\n return ctx;\n}\n\n/* -------------------------------------------------------\n * 1. Root\n * ------------------------------------------------------*/\nexport interface HoverCardProps {\n children: React.ReactNode;\n /** Delay in milliseconds before the card opens. Defaults to 200ms. */\n openDelay?: number;\n /** Delay in milliseconds before the card closes. Defaults to 300ms. */\n closeDelay?: number;\n}\n\n/**\n * HoverCard Component (Root)\n * * Implements a Compound Component Architecture.\n * * Manages the delayed hover state and provides context to the Trigger and Content.\n */\nexport function HoverCardRoot({\n children,\n openDelay = 200, // Standard modern UI delay\n closeDelay = 300,\n}: HoverCardProps) {\n const [open, setOpen] = useState(false);\n const triggerRef = useRef<HTMLElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const contentId = `hovercard-${useId()}`;\n\n const openTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearTimers = useCallback(() => {\n if (openTimer.current) clearTimeout(openTimer.current);\n if (closeTimer.current) clearTimeout(closeTimer.current);\n }, []);\n\n const scheduleOpen = useCallback(() => {\n clearTimers();\n openTimer.current = setTimeout(() => setOpen(true), openDelay);\n }, [openDelay, clearTimers]);\n\n const scheduleClose = useCallback(() => {\n clearTimers();\n closeTimer.current = setTimeout(() => setOpen(false), closeDelay);\n }, [closeDelay, clearTimers]);\n\n // Clean up timers on unmount to prevent memory leaks\n useEffect(() => {\n return () => clearTimers();\n }, [clearTimers]);\n\n return (\n <HoverCardContext.Provider\n value={{\n open,\n setOpen,\n triggerRef,\n contentRef,\n contentId,\n scheduleOpen,\n scheduleClose,\n clearTimers,\n }}\n >\n {children}\n </HoverCardContext.Provider>\n );\n}\nHoverCardRoot.displayName = 'HoverCard';\n\n/* -------------------------------------------------------\n * 2. Trigger\n * ------------------------------------------------------*/\nexport interface HoverCardTriggerProps {\n children: React.ReactElement;\n}\n\n/**\n * HoverCard Trigger\n * * Automatically clones the child element and injects necessary event listeners and ARIA attributes.\n */\nexport function HoverCardTrigger({ children }: HoverCardTriggerProps) {\n const { open, triggerRef, contentId, scheduleOpen, scheduleClose } = useHoverCard();\n\n const child = React.Children.only(children) as React.ReactElement<React.HTMLProps<HTMLElement>>;\n const childRef = child.props.ref ?? (child as unknown as { ref?: React.Ref<HTMLElement> }).ref;\n\n const triggerProps: React.HTMLProps<HTMLElement> = {\n ref: (node: HTMLElement | null) => {\n triggerRef.current = node;\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-haspopup': 'dialog',\n 'aria-expanded': open,\n 'aria-controls': open ? contentId : undefined,\n onMouseEnter: (e: React.MouseEvent<HTMLElement>) => {\n scheduleOpen();\n child.props.onMouseEnter?.(e);\n },\n onMouseLeave: (e: React.MouseEvent<HTMLElement>) => {\n scheduleClose();\n child.props.onMouseLeave?.(e);\n },\n // WAI-ARIA Standard: Hover cards must open on keyboard focus\n onFocus: (e: React.FocusEvent<HTMLElement>) => {\n scheduleOpen();\n child.props.onFocus?.(e);\n },\n onBlur: (e: React.FocusEvent<HTMLElement>) => {\n scheduleClose();\n child.props.onBlur?.(e);\n },\n };\n\n return React.cloneElement(child, triggerProps);\n}\nHoverCardTrigger.displayName = 'HoverCard.Trigger';\n\n/* -------------------------------------------------------\n * 3. Content\n * ------------------------------------------------------*/\nexport interface HoverCardContentProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Preferred placement of the card relative to the trigger. Defaults to 'bottom' */\n placement?: HoverCardPlacement;\n /** Gap in pixels between the trigger and the card. Defaults to 8px. */\n offset?: number;\n}\n\n/**\n * HoverCard Content\n * * Renders in a Portal and implements smart collision detection.\n */\nexport function HoverCardContent({\n children,\n className,\n placement = 'bottom',\n offset = 8,\n ...props\n}: HoverCardContentProps) {\n const { open, setOpen, triggerRef, contentRef, contentId, scheduleClose, clearTimers } = useHoverCard();\n const [coords, setCoords] = useState({ top: -9999, left: -9999 });\n const [actualPlacement, setActualPlacement] = useState<HoverCardPlacement>(placement);\n\n // ESC Key Dismiss\n useEffect(() => {\n if (!open) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n }, [open, setOpen]);\n\n // Click Outside\n useEffect(() => {\n if (!open) return;\n // Pass both refs in an array to prevent the trigger from immediately closing the card\n const cleanup = onClickOutside([contentRef, triggerRef], () => {\n setOpen(false);\n });\n return cleanup;\n }, [open, setOpen, contentRef, triggerRef]);\n\n // Smart Positioning & Collision Math\n const updatePosition = useCallback(() => {\n if (!triggerRef.current || !contentRef.current) return;\n\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const contentRect = contentRef.current.getBoundingClientRect();\n\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n\n // Center horizontally by default relative to the trigger\n let left = triggerRect.left + scrollX + (triggerRect.width / 2) - (contentRect.width / 2);\n \n // Boundary Clamp (Left/Right)\n const padding = 12;\n const maxLeft = document.documentElement.clientWidth - contentRect.width - padding;\n if (left < padding) left = padding;\n if (left > maxLeft) left = maxLeft;\n\n // Y Axis Placement\n let top = triggerRect.bottom + scrollY + offset;\n let nextPlacement = placement;\n\n // Collision Detection: Flip to top if no space at bottom\n if (placement === 'bottom' && top + contentRect.height > window.innerHeight + scrollY - padding) {\n top = triggerRect.top + scrollY - contentRect.height - offset;\n nextPlacement = 'top';\n } \n // Collision Detection: Flip to bottom if no space at top\n else if (placement === 'top') {\n top = triggerRect.top + scrollY - contentRect.height - offset;\n if (top < scrollY + padding) {\n top = triggerRect.bottom + scrollY + offset;\n nextPlacement = 'bottom';\n }\n }\n\n setActualPlacement(nextPlacement);\n setCoords({ top, left });\n }, [placement, offset, triggerRef, contentRef]);\n\n useLayoutEffect(() => {\n if (!open) return;\n updatePosition();\n window.addEventListener('resize', updatePosition);\n window.addEventListener('scroll', updatePosition, true);\n return () => {\n window.removeEventListener('resize', updatePosition);\n window.removeEventListener('scroll', updatePosition, true);\n };\n }, [open, updatePosition]);\n\n if (!open) return null;\n\n return (\n <Portal>\n <div\n id={contentId}\n ref={contentRef}\n role=\"dialog\"\n data-placement={actualPlacement}\n className={cn('nui-hovercard-content', className)}\n style={{\n position: 'absolute',\n top: coords.top,\n left: coords.left,\n } as React.CSSProperties}\n onMouseEnter={() => {\n // If user moves mouse onto the card, cancel the close timer!\n // This allows users to move from the trigger to the content without it disappearing.\n clearTimers();\n }}\n onMouseLeave={scheduleClose}\n {...props}\n >\n {children}\n </div>\n </Portal>\n );\n}\nHoverCardContent.displayName = 'HoverCard.Content';\n\n/* -------------------------------------------------------\n * Export\n * ------------------------------------------------------*/\nexport const HoverCard = Object.assign(HoverCardRoot, {\n Trigger: HoverCardTrigger,\n Content: HoverCardContent,\n});"],"names":["HoverCardContext","createContext","useHoverCard","ctx","useContext","HoverCardRoot","children","openDelay","closeDelay","open","setOpen","useState","triggerRef","useRef","contentRef","contentId","useId","openTimer","closeTimer","clearTimers","useCallback","scheduleOpen","scheduleClose","useEffect","jsx","HoverCardTrigger","child","React","childRef","triggerProps","node","e","HoverCardContent","className","placement","offset","props","coords","setCoords","actualPlacement","setActualPlacement","handler","onClickOutside","updatePosition","triggerRect","contentRect","scrollX","scrollY","left","padding","maxLeft","top","nextPlacement","useLayoutEffect","Portal","cn","HoverCard"],"mappings":"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"}
@@ -1,78 +1,133 @@
1
- import { jsxs as C, jsx as a } from "react/jsx-runtime";
2
- import { useState as E, useRef as s, useEffect as f, useCallback as y } from "react";
1
+ import { jsx as L } from "react/jsx-runtime";
2
+ import y, { useState as T, useRef as w, useId as F, useCallback as E, useEffect as b, createContext as X, useLayoutEffect as Y, useContext as A } from "react";
3
3
  /* empty css */
4
- import { onClickOutside as M } from "../../utils/onclickoutside/onClickOutside.js";
5
- import { Portal as R } from "../../utils/portal/portal.js";
6
- function j({
7
- trigger: h,
8
- children: w,
9
- openDelay: g = 120,
10
- closeDelay: L = 140,
11
- className: T = ""
4
+ import { onClickOutside as S } from "../../utils/onclickoutside/onClickOutside.js";
5
+ import { Portal as W } from "../../utils/portal/portal.js";
6
+ import { cn as $ } from "../../utils/cn/cn.js";
7
+ const P = X(null);
8
+ function M() {
9
+ const l = A(P);
10
+ if (!l) throw new Error("HoverCard components must be inside <HoverCard>");
11
+ return l;
12
+ }
13
+ function O({
14
+ children: l,
15
+ openDelay: a = 200,
16
+ // Standard modern UI delay
17
+ closeDelay: c = 300
12
18
  }) {
13
- const [e, t] = E(!1), m = s(null), v = s(null), i = s(null), u = s(null), c = () => {
14
- i.current && clearTimeout(i.current), u.current && clearTimeout(u.current);
15
- }, p = () => {
16
- c(), i.current = setTimeout(() => t(!0), g);
17
- }, l = () => {
18
- c(), u.current = setTimeout(() => t(!1), L);
19
+ const [i, d] = T(!1), n = w(null), t = w(null), o = `hovercard-${F()}`, r = w(null), e = w(null), u = E(() => {
20
+ r.current && clearTimeout(r.current), e.current && clearTimeout(e.current);
21
+ }, []), R = E(() => {
22
+ u(), r.current = setTimeout(() => d(!0), a);
23
+ }, [a, u]), h = E(() => {
24
+ u(), e.current = setTimeout(() => d(!1), c);
25
+ }, [c, u]);
26
+ return b(() => () => u(), [u]), /* @__PURE__ */ L(
27
+ P.Provider,
28
+ {
29
+ value: {
30
+ open: i,
31
+ setOpen: d,
32
+ triggerRef: n,
33
+ contentRef: t,
34
+ contentId: o,
35
+ scheduleOpen: R,
36
+ scheduleClose: h,
37
+ clearTimers: u
38
+ },
39
+ children: l
40
+ }
41
+ );
42
+ }
43
+ O.displayName = "HoverCard";
44
+ function k({ children: l }) {
45
+ const { open: a, triggerRef: c, contentId: i, scheduleOpen: d, scheduleClose: n } = M(), t = y.Children.only(l), o = t.props.ref ?? t.ref, r = {
46
+ ref: (e) => {
47
+ c.current = e, typeof o == "function" ? o(e) : o && typeof o == "object" && "current" in o && (o.current = e);
48
+ },
49
+ "aria-haspopup": "dialog",
50
+ "aria-expanded": a,
51
+ "aria-controls": a ? i : void 0,
52
+ onMouseEnter: (e) => {
53
+ d(), t.props.onMouseEnter?.(e);
54
+ },
55
+ onMouseLeave: (e) => {
56
+ n(), t.props.onMouseLeave?.(e);
57
+ },
58
+ // WAI-ARIA Standard: Hover cards must open on keyboard focus
59
+ onFocus: (e) => {
60
+ d(), t.props.onFocus?.(e);
61
+ },
62
+ onBlur: (e) => {
63
+ n(), t.props.onBlur?.(e);
64
+ }
19
65
  };
20
- f(() => {
21
- if (!e) return;
22
- const n = (o) => {
23
- o.key === "Escape" && t(!1);
24
- };
25
- return document.addEventListener("keydown", n), () => document.removeEventListener("keydown", n);
26
- }, [e]), f(() => {
27
- if (e)
28
- return M(v, () => t(!1));
29
- }, [e]);
30
- const [d, k] = E(null), r = y(() => {
31
- const n = m.current;
66
+ return y.cloneElement(t, r);
67
+ }
68
+ k.displayName = "HoverCard.Trigger";
69
+ function B({
70
+ children: l,
71
+ className: a,
72
+ placement: c = "bottom",
73
+ offset: i = 8,
74
+ ...d
75
+ }) {
76
+ const { open: n, setOpen: t, triggerRef: o, contentRef: r, contentId: e, scheduleClose: u, clearTimers: R } = M(), [h, I] = T({ top: -9999, left: -9999 }), [N, j] = T(c);
77
+ b(() => {
32
78
  if (!n) return;
33
- const o = n.getBoundingClientRect();
34
- k({
35
- top: o.bottom + 8,
36
- // spacing
37
- left: o.left
38
- });
39
- }, []);
40
- return f(() => {
41
- if (e)
42
- return r(), window.addEventListener("resize", r), window.addEventListener("scroll", r, !0), () => {
43
- window.removeEventListener("resize", r), window.removeEventListener("scroll", r, !0);
79
+ const s = (p) => {
80
+ p.key === "Escape" && t(!1);
81
+ };
82
+ return document.addEventListener("keydown", s), () => document.removeEventListener("keydown", s);
83
+ }, [n, t]), b(() => n ? S([r, o], () => {
84
+ t(!1);
85
+ }) : void 0, [n, t, r, o]);
86
+ const f = E(() => {
87
+ if (!o.current || !r.current) return;
88
+ const s = o.current.getBoundingClientRect(), p = r.current.getBoundingClientRect(), z = window.scrollX, m = window.scrollY;
89
+ let g = s.left + z + s.width / 2 - p.width / 2;
90
+ const C = 12, x = document.documentElement.clientWidth - p.width - C;
91
+ g < C && (g = C), g > x && (g = x);
92
+ let v = s.bottom + m + i, H = c;
93
+ c === "bottom" && v + p.height > window.innerHeight + m - C ? (v = s.top + m - p.height - i, H = "top") : c === "top" && (v = s.top + m - p.height - i, v < m + C && (v = s.bottom + m + i, H = "bottom")), j(H), I({ top: v, left: g });
94
+ }, [c, i, o, r]);
95
+ return Y(() => {
96
+ if (n)
97
+ return f(), window.addEventListener("resize", f), window.addEventListener("scroll", f, !0), () => {
98
+ window.removeEventListener("resize", f), window.removeEventListener("scroll", f, !0);
44
99
  };
45
- }, [e, r]), /* @__PURE__ */ C("div", { className: "ui-hovercard-root", children: [
46
- /* @__PURE__ */ a(
47
- "div",
48
- {
49
- ref: m,
50
- className: "ui-hovercard-trigger",
51
- onMouseEnter: p,
52
- onMouseLeave: l,
53
- onFocus: p,
54
- onBlur: l,
55
- children: h
56
- }
57
- ),
58
- e && d && /* @__PURE__ */ a(R, { children: /* @__PURE__ */ a(
59
- "div",
60
- {
61
- ref: v,
62
- className: `ui-hovercard ${T}`,
63
- style: { top: d.top, left: d.left },
64
- role: "dialog",
65
- "aria-hidden": !e,
66
- onMouseEnter: () => {
67
- c(), t(!0);
68
- },
69
- onMouseLeave: l,
70
- children: w
71
- }
72
- ) })
73
- ] });
100
+ }, [n, f]), n ? /* @__PURE__ */ L(W, { children: /* @__PURE__ */ L(
101
+ "div",
102
+ {
103
+ id: e,
104
+ ref: r,
105
+ role: "dialog",
106
+ "data-placement": N,
107
+ className: $("nui-hovercard-content", a),
108
+ style: {
109
+ position: "absolute",
110
+ top: h.top,
111
+ left: h.left
112
+ },
113
+ onMouseEnter: () => {
114
+ R();
115
+ },
116
+ onMouseLeave: u,
117
+ ...d,
118
+ children: l
119
+ }
120
+ ) }) : null;
74
121
  }
122
+ B.displayName = "HoverCard.Content";
123
+ const V = Object.assign(O, {
124
+ Trigger: k,
125
+ Content: B
126
+ });
75
127
  export {
76
- j as HoverCard
128
+ V as HoverCard,
129
+ B as HoverCardContent,
130
+ O as HoverCardRoot,
131
+ k as HoverCardTrigger
77
132
  };
78
133
  //# sourceMappingURL=HoverCard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"HoverCard.js","sources":["../../../src/components/hovercard/HoverCard.tsx"],"sourcesContent":["/**\r\n * HoverCard.tsx — FINAL VERSION\r\n * --------------------------------\r\n * Features:\r\n * - Open on hover / focus\r\n * - Close on leave / blur\r\n * - Delay open & close\r\n * - ESC to dismiss\r\n * - Outside dismiss\r\n * - Auto position (simple version)\r\n * - Portal rendering\r\n */\r\n\r\nimport { useState, useRef, useEffect, ReactNode, useCallback } from 'react';\r\nimport './HoverCard.css';\r\nimport { Portal, onClickOutside } from '../../utils/index';\r\n\r\nexport interface HoverCardProps {\r\n trigger: ReactNode;\r\n children: ReactNode;\r\n openDelay?: number;\r\n closeDelay?: number;\r\n className?: string;\r\n}\r\n\r\nexport function HoverCard({\r\n trigger,\r\n children,\r\n openDelay = 120,\r\n closeDelay = 140,\r\n className = '',\r\n}: HoverCardProps) {\r\n const [open, setOpen] = useState(false);\r\n\r\n const triggerRef = useRef<HTMLDivElement | null>(null);\r\n const cardRef = useRef<HTMLDivElement | null>(null);\r\n\r\n const openTimer = useRef<NodeJS.Timeout | null>(null);\r\n const closeTimer = useRef<NodeJS.Timeout | null>(null);\r\n\r\n const clearTimers = () => {\r\n if (openTimer.current) clearTimeout(openTimer.current);\r\n if (closeTimer.current) clearTimeout(closeTimer.current);\r\n };\r\n\r\n const scheduleOpen = () => {\r\n clearTimers();\r\n openTimer.current = setTimeout(() => setOpen(true), openDelay);\r\n };\r\n\r\n const scheduleClose = () => {\r\n clearTimers();\r\n closeTimer.current = setTimeout(() => setOpen(false), closeDelay);\r\n };\r\n\r\n // ESC key dismiss\r\n useEffect(() => {\r\n if (!open) return;\r\n const handler = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setOpen(false);\r\n };\r\n document.addEventListener('keydown', handler);\r\n return () => document.removeEventListener('keydown', handler);\r\n }, [open]);\r\n\r\n // click outside\r\n useEffect(() => {\r\n if (!open) return;\r\n return onClickOutside(cardRef, () => setOpen(false));\r\n }, [open]);\r\n\r\n // compute position\r\n const [pos, setPos] = useState<{ top: number; left: number } | null>(null);\r\n\r\n const updatePosition = useCallback(() => {\r\n const triggerEl = triggerRef.current;\r\n if (!triggerEl) return;\r\n\r\n const rect = triggerEl.getBoundingClientRect();\r\n setPos({\r\n top: rect.bottom + 8, // spacing\r\n left: rect.left,\r\n });\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n updatePosition();\r\n window.addEventListener('resize', updatePosition);\r\n window.addEventListener('scroll', updatePosition, true);\r\n return () => {\r\n window.removeEventListener('resize', updatePosition);\r\n window.removeEventListener('scroll', updatePosition, true);\r\n };\r\n }, [open, updatePosition]);\r\n\r\n return (\r\n <div className=\"ui-hovercard-root\">\r\n {/* TRIGGER */}\r\n <div\r\n ref={triggerRef}\r\n className=\"ui-hovercard-trigger\"\r\n onMouseEnter={scheduleOpen}\r\n onMouseLeave={scheduleClose}\r\n onFocus={scheduleOpen}\r\n onBlur={scheduleClose}\r\n >\r\n {trigger}\r\n </div>\r\n\r\n {/* CARD */}\r\n {open && pos && (\r\n <Portal>\r\n <div\r\n ref={cardRef}\r\n className={`ui-hovercard ${className}`}\r\n style={{ top: pos.top, left: pos.left }}\r\n role=\"dialog\"\r\n aria-hidden={!open}\r\n onMouseEnter={() => {\r\n clearTimers();\r\n setOpen(true);\r\n }}\r\n onMouseLeave={scheduleClose}\r\n >\r\n {children}\r\n </div>\r\n </Portal>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"names":["HoverCard","trigger","children","openDelay","closeDelay","className","open","setOpen","useState","triggerRef","useRef","cardRef","openTimer","closeTimer","clearTimers","scheduleOpen","scheduleClose","useEffect","handler","e","onClickOutside","pos","setPos","updatePosition","useCallback","triggerEl","rect","jsxs","jsx","Portal"],"mappings":";;;;;AAyBO,SAASA,EAAU;AAAA,EACxB,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,YAAAC,IAAa;AAAA,EACb,WAAAC,IAAY;AACd,GAAmB;AACjB,QAAM,CAACC,GAAMC,CAAO,IAAIC,EAAS,EAAK,GAEhCC,IAAaC,EAA8B,IAAI,GAC/CC,IAAUD,EAA8B,IAAI,GAE5CE,IAAYF,EAA8B,IAAI,GAC9CG,IAAaH,EAA8B,IAAI,GAE/CI,IAAc,MAAM;AACxB,IAAIF,EAAU,WAAS,aAAaA,EAAU,OAAO,GACjDC,EAAW,WAAS,aAAaA,EAAW,OAAO;AAAA,EACzD,GAEME,IAAe,MAAM;AACzB,IAAAD,EAAA,GACAF,EAAU,UAAU,WAAW,MAAML,EAAQ,EAAI,GAAGJ,CAAS;AAAA,EAC/D,GAEMa,IAAgB,MAAM;AAC1B,IAAAF,EAAA,GACAD,EAAW,UAAU,WAAW,MAAMN,EAAQ,EAAK,GAAGH,CAAU;AAAA,EAClE;AAGA,EAAAa,EAAU,MAAM;AACd,QAAI,CAACX,EAAM;AACX,UAAMY,IAAU,CAACC,MAAqB;AACpC,MAAIA,EAAE,QAAQ,YAAUZ,EAAQ,EAAK;AAAA,IACvC;AACA,oBAAS,iBAAiB,WAAWW,CAAO,GACrC,MAAM,SAAS,oBAAoB,WAAWA,CAAO;AAAA,EAC9D,GAAG,CAACZ,CAAI,CAAC,GAGTW,EAAU,MAAM;AACd,QAAKX;AACL,aAAOc,EAAeT,GAAS,MAAMJ,EAAQ,EAAK,CAAC;AAAA,EACrD,GAAG,CAACD,CAAI,CAAC;AAGT,QAAM,CAACe,GAAKC,CAAM,IAAId,EAA+C,IAAI,GAEnEe,IAAiBC,EAAY,MAAM;AACvC,UAAMC,IAAYhB,EAAW;AAC7B,QAAI,CAACgB,EAAW;AAEhB,UAAMC,IAAOD,EAAU,sBAAA;AACvB,IAAAH,EAAO;AAAA,MACL,KAAKI,EAAK,SAAS;AAAA;AAAA,MACnB,MAAMA,EAAK;AAAA,IAAA,CACZ;AAAA,EACH,GAAG,CAAA,CAAE;AAEL,SAAAT,EAAU,MAAM;AACd,QAAKX;AACL,aAAAiB,EAAA,GACA,OAAO,iBAAiB,UAAUA,CAAc,GAChD,OAAO,iBAAiB,UAAUA,GAAgB,EAAI,GAC/C,MAAM;AACX,eAAO,oBAAoB,UAAUA,CAAc,GACnD,OAAO,oBAAoB,UAAUA,GAAgB,EAAI;AAAA,MAC3D;AAAA,EACF,GAAG,CAACjB,GAAMiB,CAAc,CAAC,GAGvB,gBAAAI,EAAC,OAAA,EAAI,WAAU,qBAEb,UAAA;AAAA,IAAA,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKnB;AAAA,QACL,WAAU;AAAA,QACV,cAAcM;AAAA,QACd,cAAcC;AAAA,QACd,SAASD;AAAA,QACT,QAAQC;AAAA,QAEP,UAAAf;AAAA,MAAA;AAAA,IAAA;AAAA,IAIFK,KAAQe,KACP,gBAAAO,EAACC,GAAA,EACC,UAAA,gBAAAD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKjB;AAAA,QACL,WAAW,gBAAgBN,CAAS;AAAA,QACpC,OAAO,EAAE,KAAKgB,EAAI,KAAK,MAAMA,EAAI,KAAA;AAAA,QACjC,MAAK;AAAA,QACL,eAAa,CAACf;AAAA,QACd,cAAc,MAAM;AAClB,UAAAQ,EAAA,GACAP,EAAQ,EAAI;AAAA,QACd;AAAA,QACA,cAAcS;AAAA,QAEb,UAAAd;AAAA,MAAA;AAAA,IAAA,EACH,CACF;AAAA,EAAA,GAEJ;AAEJ;"}
1
+ {"version":3,"file":"HoverCard.js","sources":["../../../src/components/hovercard/HoverCard.tsx"],"sourcesContent":["\"use client\";\n\nimport React, {\n createContext,\n useContext,\n useState,\n useRef,\n useEffect,\n useCallback,\n useLayoutEffect,\n useId,\n} from 'react';\nimport { cn } from '../../utils';\nimport { Portal, onClickOutside } from '../../utils';\nimport './HoverCard.css';\n\nexport type HoverCardPlacement = 'top' | 'bottom';\n\n/* -------------------------------------------------------\n * Context\n * ------------------------------------------------------*/\ninterface HoverCardContextValue {\n open: boolean;\n setOpen: React.Dispatch<React.SetStateAction<boolean>>;\n triggerRef: React.RefObject<HTMLElement | null>;\n contentRef: React.RefObject<HTMLDivElement | null>;\n contentId: string;\n scheduleOpen: () => void;\n scheduleClose: () => void;\n clearTimers: () => void;\n}\n\nconst HoverCardContext = createContext<HoverCardContextValue | null>(null);\n\nfunction useHoverCard() {\n const ctx = useContext(HoverCardContext);\n if (!ctx) throw new Error('HoverCard components must be inside <HoverCard>');\n return ctx;\n}\n\n/* -------------------------------------------------------\n * 1. Root\n * ------------------------------------------------------*/\nexport interface HoverCardProps {\n children: React.ReactNode;\n /** Delay in milliseconds before the card opens. Defaults to 200ms. */\n openDelay?: number;\n /** Delay in milliseconds before the card closes. Defaults to 300ms. */\n closeDelay?: number;\n}\n\n/**\n * HoverCard Component (Root)\n * * Implements a Compound Component Architecture.\n * * Manages the delayed hover state and provides context to the Trigger and Content.\n */\nexport function HoverCardRoot({\n children,\n openDelay = 200, // Standard modern UI delay\n closeDelay = 300,\n}: HoverCardProps) {\n const [open, setOpen] = useState(false);\n const triggerRef = useRef<HTMLElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const contentId = `hovercard-${useId()}`;\n\n const openTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const clearTimers = useCallback(() => {\n if (openTimer.current) clearTimeout(openTimer.current);\n if (closeTimer.current) clearTimeout(closeTimer.current);\n }, []);\n\n const scheduleOpen = useCallback(() => {\n clearTimers();\n openTimer.current = setTimeout(() => setOpen(true), openDelay);\n }, [openDelay, clearTimers]);\n\n const scheduleClose = useCallback(() => {\n clearTimers();\n closeTimer.current = setTimeout(() => setOpen(false), closeDelay);\n }, [closeDelay, clearTimers]);\n\n // Clean up timers on unmount to prevent memory leaks\n useEffect(() => {\n return () => clearTimers();\n }, [clearTimers]);\n\n return (\n <HoverCardContext.Provider\n value={{\n open,\n setOpen,\n triggerRef,\n contentRef,\n contentId,\n scheduleOpen,\n scheduleClose,\n clearTimers,\n }}\n >\n {children}\n </HoverCardContext.Provider>\n );\n}\nHoverCardRoot.displayName = 'HoverCard';\n\n/* -------------------------------------------------------\n * 2. Trigger\n * ------------------------------------------------------*/\nexport interface HoverCardTriggerProps {\n children: React.ReactElement;\n}\n\n/**\n * HoverCard Trigger\n * * Automatically clones the child element and injects necessary event listeners and ARIA attributes.\n */\nexport function HoverCardTrigger({ children }: HoverCardTriggerProps) {\n const { open, triggerRef, contentId, scheduleOpen, scheduleClose } = useHoverCard();\n\n const child = React.Children.only(children) as React.ReactElement<React.HTMLProps<HTMLElement>>;\n const childRef = child.props.ref ?? (child as unknown as { ref?: React.Ref<HTMLElement> }).ref;\n\n const triggerProps: React.HTMLProps<HTMLElement> = {\n ref: (node: HTMLElement | null) => {\n triggerRef.current = node;\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-haspopup': 'dialog',\n 'aria-expanded': open,\n 'aria-controls': open ? contentId : undefined,\n onMouseEnter: (e: React.MouseEvent<HTMLElement>) => {\n scheduleOpen();\n child.props.onMouseEnter?.(e);\n },\n onMouseLeave: (e: React.MouseEvent<HTMLElement>) => {\n scheduleClose();\n child.props.onMouseLeave?.(e);\n },\n // WAI-ARIA Standard: Hover cards must open on keyboard focus\n onFocus: (e: React.FocusEvent<HTMLElement>) => {\n scheduleOpen();\n child.props.onFocus?.(e);\n },\n onBlur: (e: React.FocusEvent<HTMLElement>) => {\n scheduleClose();\n child.props.onBlur?.(e);\n },\n };\n\n return React.cloneElement(child, triggerProps);\n}\nHoverCardTrigger.displayName = 'HoverCard.Trigger';\n\n/* -------------------------------------------------------\n * 3. Content\n * ------------------------------------------------------*/\nexport interface HoverCardContentProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n /** Preferred placement of the card relative to the trigger. Defaults to 'bottom' */\n placement?: HoverCardPlacement;\n /** Gap in pixels between the trigger and the card. Defaults to 8px. */\n offset?: number;\n}\n\n/**\n * HoverCard Content\n * * Renders in a Portal and implements smart collision detection.\n */\nexport function HoverCardContent({\n children,\n className,\n placement = 'bottom',\n offset = 8,\n ...props\n}: HoverCardContentProps) {\n const { open, setOpen, triggerRef, contentRef, contentId, scheduleClose, clearTimers } = useHoverCard();\n const [coords, setCoords] = useState({ top: -9999, left: -9999 });\n const [actualPlacement, setActualPlacement] = useState<HoverCardPlacement>(placement);\n\n // ESC Key Dismiss\n useEffect(() => {\n if (!open) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n }, [open, setOpen]);\n\n // Click Outside\n useEffect(() => {\n if (!open) return;\n // Pass both refs in an array to prevent the trigger from immediately closing the card\n const cleanup = onClickOutside([contentRef, triggerRef], () => {\n setOpen(false);\n });\n return cleanup;\n }, [open, setOpen, contentRef, triggerRef]);\n\n // Smart Positioning & Collision Math\n const updatePosition = useCallback(() => {\n if (!triggerRef.current || !contentRef.current) return;\n\n const triggerRect = triggerRef.current.getBoundingClientRect();\n const contentRect = contentRef.current.getBoundingClientRect();\n\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n\n // Center horizontally by default relative to the trigger\n let left = triggerRect.left + scrollX + (triggerRect.width / 2) - (contentRect.width / 2);\n \n // Boundary Clamp (Left/Right)\n const padding = 12;\n const maxLeft = document.documentElement.clientWidth - contentRect.width - padding;\n if (left < padding) left = padding;\n if (left > maxLeft) left = maxLeft;\n\n // Y Axis Placement\n let top = triggerRect.bottom + scrollY + offset;\n let nextPlacement = placement;\n\n // Collision Detection: Flip to top if no space at bottom\n if (placement === 'bottom' && top + contentRect.height > window.innerHeight + scrollY - padding) {\n top = triggerRect.top + scrollY - contentRect.height - offset;\n nextPlacement = 'top';\n } \n // Collision Detection: Flip to bottom if no space at top\n else if (placement === 'top') {\n top = triggerRect.top + scrollY - contentRect.height - offset;\n if (top < scrollY + padding) {\n top = triggerRect.bottom + scrollY + offset;\n nextPlacement = 'bottom';\n }\n }\n\n setActualPlacement(nextPlacement);\n setCoords({ top, left });\n }, [placement, offset, triggerRef, contentRef]);\n\n useLayoutEffect(() => {\n if (!open) return;\n updatePosition();\n window.addEventListener('resize', updatePosition);\n window.addEventListener('scroll', updatePosition, true);\n return () => {\n window.removeEventListener('resize', updatePosition);\n window.removeEventListener('scroll', updatePosition, true);\n };\n }, [open, updatePosition]);\n\n if (!open) return null;\n\n return (\n <Portal>\n <div\n id={contentId}\n ref={contentRef}\n role=\"dialog\"\n data-placement={actualPlacement}\n className={cn('nui-hovercard-content', className)}\n style={{\n position: 'absolute',\n top: coords.top,\n left: coords.left,\n } as React.CSSProperties}\n onMouseEnter={() => {\n // If user moves mouse onto the card, cancel the close timer!\n // This allows users to move from the trigger to the content without it disappearing.\n clearTimers();\n }}\n onMouseLeave={scheduleClose}\n {...props}\n >\n {children}\n </div>\n </Portal>\n );\n}\nHoverCardContent.displayName = 'HoverCard.Content';\n\n/* -------------------------------------------------------\n * Export\n * ------------------------------------------------------*/\nexport const HoverCard = Object.assign(HoverCardRoot, {\n Trigger: HoverCardTrigger,\n Content: HoverCardContent,\n});"],"names":["HoverCardContext","createContext","useHoverCard","ctx","useContext","HoverCardRoot","children","openDelay","closeDelay","open","setOpen","useState","triggerRef","useRef","contentRef","contentId","useId","openTimer","closeTimer","clearTimers","useCallback","scheduleOpen","scheduleClose","useEffect","jsx","HoverCardTrigger","child","React","childRef","triggerProps","node","HoverCardContent","className","placement","offset","props","coords","setCoords","actualPlacement","setActualPlacement","handler","e","onClickOutside","updatePosition","triggerRect","contentRect","scrollX","scrollY","left","padding","maxLeft","top","nextPlacement","useLayoutEffect","Portal","cn","HoverCard"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),o=require("react");;/* empty css */function p({label:t,description:s,error:i,inputSize:u="md",className:r="",id:a,...d}){const c=o.useId(),e=a??c,l=i?`${e}-error`:s?`${e}-description`:void 0;return n.jsxs("div",{className:`ui-input-wrapper ${r}`,children:[t&&n.jsxs("label",{htmlFor:e,className:"ui-input-label",children:[t,d.required&&" *"]}),n.jsx("input",{id:e,className:["ui-input",u==="sm"&&"ui-input--sm",u==="lg"&&"ui-input--lg",i&&"ui-input--error"].filter(Boolean).join(" "),"aria-invalid":!!i,"aria-describedby":l,...d}),s&&!i&&n.jsx("div",{id:`${e}-description`,className:"ui-input-description",children:s}),i&&n.jsx("div",{id:`${e}-error`,className:"ui-input-error",children:i})]})}exports.Input=p;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),o=require("react");;/* empty css */const t=require("../../utils/cn/cn.cjs"),_=o.forwardRef(({label:c,description:e,error:n,inputSize:m="md",leftIcon:u,rightIcon:a,className:h,wrapperClassName:j,id:x,required:d,disabled:r,...N},v)=>{const b=o.useId(),s=x??b,l=`${s}-error`,p=`${s}-description`,y=n?l:e?p:void 0;return i.jsxs("div",{className:t.cn("nui-input-wrapper",j),children:[c&&i.jsxs("label",{htmlFor:s,className:t.cn("nui-input__label",r&&"nui-input__label--disabled"),children:[c,d&&i.jsx("span",{className:"nui-input__required","aria-hidden":"true",children:" *"})]}),i.jsxs("div",{className:"nui-input__container",children:[u&&i.jsx("span",{className:"nui-input__icon -left",children:u}),i.jsx("input",{ref:v,id:s,required:d,disabled:r,className:t.cn("nui-input",`nui-input--${m}`,!!n&&"nui-input--error",!!u&&"nui-input--has-left",!!a&&"nui-input--has-right",h),"aria-invalid":!!n,"aria-describedby":y,...N}),a&&i.jsx("span",{className:"nui-input__icon -right",children:a})]}),e&&!n&&i.jsx("div",{id:p,className:"nui-input__description",children:e}),n&&i.jsx("div",{id:l,className:"nui-input__error","aria-live":"polite",children:n})]})});_.displayName="Input";exports.Input=_;
2
2
  //# sourceMappingURL=Input.cjs.map