haze-ui 1.26.0 → 1.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (479) hide show
  1. package/README.md +420 -36
  2. package/dist/components/Anchor/Anchor.js +78 -0
  3. package/dist/components/Anchor/index.js +3 -0
  4. package/dist/components/AppShell/AppShell.js +44 -0
  5. package/dist/components/AppShell/index.js +3 -0
  6. package/dist/components/AspectRatio/AspectRatio.js +0 -1
  7. package/dist/components/AspectRatio/index.js +0 -1
  8. package/dist/components/Badge/Badge.js +5 -17
  9. package/dist/components/Badge/badge-styles.js +15 -0
  10. package/dist/components/Badge/index.js +3 -3
  11. package/dist/components/BottomSheet/BottomSheet.js +133 -22
  12. package/dist/components/Button/index.js +4 -3
  13. package/dist/components/Calendar/Calendar.js +525 -78
  14. package/dist/components/Calendar/date.js +35 -2
  15. package/dist/components/Card/Card.js +0 -1
  16. package/dist/components/Card/index.js +0 -1
  17. package/dist/components/Carousel/Carousel.js +64 -41
  18. package/dist/components/Cascader/Cascader.js +222 -140
  19. package/dist/components/Chart/Chart.js +34 -0
  20. package/dist/components/Chart/chart-elements.js +164 -0
  21. package/dist/components/Chart/index.js +3 -0
  22. package/dist/components/ChatContainer/ChatContainer.js +36 -16
  23. package/dist/components/ChatInput/ChatInput.js +49 -29
  24. package/dist/components/ChatMessage/ChatMessage.js +76 -29
  25. package/dist/components/Checkbox/Checkbox.js +6 -5
  26. package/dist/components/Checkbox/CheckboxCore.js +6 -5
  27. package/dist/components/CodeBlock/CodeBlock.js +39 -10
  28. package/dist/components/CodeBlock/index.js +0 -1
  29. package/dist/components/Collapsible/Collapsible.js +23 -10
  30. package/dist/components/ColorPicker/ColorPicker.js +5 -4
  31. package/dist/components/ColorPicker/ColorPickerCore.js +5 -4
  32. package/dist/components/Combobox/Combobox.js +202 -75
  33. package/dist/components/Combobox/ComboboxGroup.js +23 -0
  34. package/dist/components/Combobox/ComboboxOption.js +7 -6
  35. package/dist/components/Combobox/index.js +4 -3
  36. package/dist/components/Command/Command.js +102 -59
  37. package/dist/components/Command/CommandDialog.js +48 -0
  38. package/dist/components/Command/command-filter.js +16 -0
  39. package/dist/components/Command/index.js +3 -2
  40. package/dist/components/ConfirmDialog/ConfirmDialog.js +3 -3
  41. package/dist/components/Container/Container.js +0 -1
  42. package/dist/components/Container/index.js +0 -1
  43. package/dist/components/ContextMenu/ContextMenuContent.js +4 -4
  44. package/dist/components/DataTable/CellEditor.js +38 -0
  45. package/dist/components/DataTable/DataTable.js +394 -143
  46. package/dist/components/DataTable/csv.js +29 -0
  47. package/dist/components/DataTable/features.js +25 -0
  48. package/dist/components/DataTable/index.js +3 -1
  49. package/dist/components/DataTable/summary.js +17 -0
  50. package/dist/components/DateRangePicker/DateRangePicker.js +31 -13
  51. package/dist/components/DateRangePicker/DateRangePickerCore.js +59 -27
  52. package/dist/components/DateRangePicker/presets.js +43 -0
  53. package/dist/components/Datepicker/Datepicker.js +17 -12
  54. package/dist/components/Datepicker/DatepickerCore.js +73 -39
  55. package/dist/components/Datepicker/datetime.js +23 -0
  56. package/dist/components/Descriptions/Descriptions.js +46 -0
  57. package/dist/components/Descriptions/index.js +3 -0
  58. package/dist/components/Dialog/Dialog.js +56 -32
  59. package/dist/components/DiffViewer/DiffViewer.js +31 -30
  60. package/dist/components/Divider/Divider.js +0 -1
  61. package/dist/components/Divider/index.js +0 -1
  62. package/dist/components/Drawer/Drawer.js +49 -29
  63. package/dist/components/DropdownMenu/DropdownMenu.js +38 -26
  64. package/dist/components/DropdownMenu/DropdownMenuSub.js +23 -0
  65. package/dist/components/DropdownMenu/DropdownMenuSubContent.js +24 -0
  66. package/dist/components/DropdownMenu/DropdownMenuSubTrigger.js +30 -0
  67. package/dist/components/DropdownMenu/index.js +4 -1
  68. package/dist/components/FilePreview/FilePreview.js +135 -0
  69. package/dist/components/FilePreview/file-preview-format.js +23 -0
  70. package/dist/components/FilePreview/index.js +3 -0
  71. package/dist/components/Flex/Flex.js +0 -1
  72. package/dist/components/Flex/index.js +0 -1
  73. package/dist/components/FloatButton/FloatButton.js +42 -0
  74. package/dist/components/FloatButton/FloatButtonGroup.js +58 -0
  75. package/dist/components/FloatButton/float-button-context.js +9 -0
  76. package/dist/components/FloatButton/float-button-glyphs.js +26 -0
  77. package/dist/components/FloatButton/float-button-styles.js +14 -0
  78. package/dist/components/FloatButton/index.js +4 -0
  79. package/dist/components/Fullscreen/Fullscreen.js +29 -0
  80. package/dist/components/Fullscreen/index.js +3 -0
  81. package/dist/components/Grid/Grid.js +0 -1
  82. package/dist/components/Grid/GridItem.js +0 -1
  83. package/dist/components/Grid/index.js +0 -1
  84. package/dist/components/Icon/Icon.js +0 -1
  85. package/dist/components/Icon/index.js +0 -1
  86. package/dist/components/Image/Image.js +37 -19
  87. package/dist/components/Image/ImagePreview.js +233 -0
  88. package/dist/components/InlineCompletion/InlineCompletion.js +81 -0
  89. package/dist/components/InlineCompletion/index.js +3 -0
  90. package/dist/components/Input/Input.js +6 -5
  91. package/dist/components/Input/InputCore.js +3 -2
  92. package/dist/components/JsonView/JsonView.js +209 -0
  93. package/dist/components/JsonView/index.js +3 -0
  94. package/dist/components/JsonView/json-view-utils.js +24 -0
  95. package/dist/components/Kbd/Kbd.js +0 -1
  96. package/dist/components/Kbd/index.js +0 -1
  97. package/dist/components/LocaleProvider/LocaleProvider.js +16 -13
  98. package/dist/components/LocaleProvider/index.js +5 -3
  99. package/dist/components/LocaleProvider/ja-jp.js +222 -0
  100. package/dist/components/LocaleProvider/locale.js +99 -5
  101. package/dist/components/LocaleProvider/strings.js +15 -0
  102. package/dist/components/LocaleProvider/useStrings.js +13 -11
  103. package/dist/components/LocaleProvider/zh-cn.js +99 -5
  104. package/dist/components/Masonry/Masonry.js +29 -0
  105. package/dist/components/Masonry/index.js +3 -0
  106. package/dist/components/Masonry/masonry-distribute.js +15 -0
  107. package/dist/components/Mentions/Mentions.js +6 -5
  108. package/dist/components/Mentions/MentionsCore.js +69 -68
  109. package/dist/components/Menu/Menu.js +5 -5
  110. package/dist/components/Menu/MenuSub.js +23 -0
  111. package/dist/components/Menu/MenuSubContent.js +24 -0
  112. package/dist/components/Menu/MenuSubTrigger.js +30 -0
  113. package/dist/components/Menu/index.js +4 -1
  114. package/dist/components/NumberInput/NumberInput.js +6 -5
  115. package/dist/components/NumberInput/NumberInputCore.js +9 -8
  116. package/dist/components/OTPInput/OTPInput.js +5 -4
  117. package/dist/components/OTPInput/OTPInputCore.js +34 -33
  118. package/dist/components/PasswordInput/PasswordInput.js +5 -4
  119. package/dist/components/PasswordInput/PasswordInputCore.js +8 -7
  120. package/dist/components/Popover/Popover.js +43 -31
  121. package/dist/components/PromptInput/PromptInput.js +213 -0
  122. package/dist/components/PromptInput/index.js +3 -0
  123. package/dist/components/Radio/Radio.js +7 -6
  124. package/dist/components/Radio/RadioGroup.js +5 -4
  125. package/dist/components/Radio/RadioGroupCore.js +23 -14
  126. package/dist/components/Rating/Rating.js +5 -4
  127. package/dist/components/Rating/RatingCore.js +62 -28
  128. package/dist/components/Resizable/index.js +1 -1
  129. package/dist/components/Segmented/Segmented.js +5 -4
  130. package/dist/components/Segmented/SegmentedCore.js +22 -18
  131. package/dist/components/Select/OptionGroup.js +12 -0
  132. package/dist/components/Select/Select.js +20 -9
  133. package/dist/components/Select/SelectCore.js +74 -13
  134. package/dist/components/Select/SelectFloating.js +256 -0
  135. package/dist/components/Select/index.js +5 -4
  136. package/dist/components/Select/select-options.js +57 -0
  137. package/dist/components/Sidebar/Sidebar.js +9 -9
  138. package/dist/components/Signature/Signature.js +165 -0
  139. package/dist/components/Signature/index.js +3 -0
  140. package/dist/components/Signature/signature-points.js +28 -0
  141. package/dist/components/Skeleton/Skeleton.js +0 -1
  142. package/dist/components/Skeleton/index.js +0 -1
  143. package/dist/components/Slider/Slider.js +16 -8
  144. package/dist/components/Slider/SliderCore.js +75 -12
  145. package/dist/components/Sources/Sources.js +109 -0
  146. package/dist/components/Sources/index.js +3 -0
  147. package/dist/components/Stat/Stat.js +0 -1
  148. package/dist/components/Stat/index.js +0 -1
  149. package/dist/components/Switch/Switch.js +6 -5
  150. package/dist/components/Switch/SwitchCore.js +3 -2
  151. package/dist/components/Tabs/Tab.js +7 -4
  152. package/dist/components/Tabs/TabList.js +38 -7
  153. package/dist/components/Tabs/TabPanel.js +4 -3
  154. package/dist/components/Tabs/Tabs.js +11 -6
  155. package/dist/components/TagGroup/SortableTagGroup.js +26 -0
  156. package/dist/components/TagGroup/TagGroup.js +4 -6
  157. package/dist/components/TagGroup/TagGroupItem.js +17 -11
  158. package/dist/components/TagGroup/index.js +2 -1
  159. package/dist/components/TagGroup/tag-group-styles.js +7 -0
  160. package/dist/components/TagInput/SortableTagInput.js +24 -0
  161. package/dist/components/TagInput/SortableTagInputCore.js +52 -0
  162. package/dist/components/TagInput/TagInput.js +5 -4
  163. package/dist/components/TagInput/TagInputCore.js +71 -57
  164. package/dist/components/TagInput/index.js +3 -1
  165. package/dist/components/TagInput/tag-input-styles.js +7 -0
  166. package/dist/components/Textarea/Textarea.js +6 -5
  167. package/dist/components/Textarea/TextareaCore.js +3 -2
  168. package/dist/components/TimePicker/TimePicker.js +6 -5
  169. package/dist/components/TimePicker/TimePickerCore.js +3 -2
  170. package/dist/components/Toast/Toast.js +44 -42
  171. package/dist/components/Toast/ToastContainer.js +67 -47
  172. package/dist/components/Toast/ToastContext.js +23 -4
  173. package/dist/components/Toast/toast2.js +63 -28
  174. package/dist/components/Toast/useToast.js +9 -7
  175. package/dist/components/Toggle/Toggle.js +20 -0
  176. package/dist/components/Toggle/ToggleCore.js +31 -0
  177. package/dist/components/Toggle/index.js +4 -0
  178. package/dist/components/Toolbar/Toolbar.js +33 -32
  179. package/dist/components/Toolbar/ToolbarToggle.js +31 -0
  180. package/dist/components/Toolbar/index.js +2 -1
  181. package/dist/components/Tooltip/Tooltip.js +1 -1
  182. package/dist/components/Tour/Tour.js +57 -53
  183. package/dist/components/Tree/Tree.js +265 -80
  184. package/dist/components/Tree/TreeItem.js +91 -55
  185. package/dist/components/Tree/utils.js +82 -10
  186. package/dist/components/Typography/Typography.js +0 -1
  187. package/dist/components/Typography/index.js +0 -1
  188. package/dist/components/Upload/Upload.js +24 -8
  189. package/dist/components/Upload/UploadCore.js +230 -37
  190. package/dist/components/Upload/UploadList.js +300 -0
  191. package/dist/components/Upload/xhr-upload.js +22 -0
  192. package/dist/components/VirtualList/VirtualList.js +84 -56
  193. package/dist/components/Watermark/Watermark.js +55 -0
  194. package/dist/components/Watermark/index.js +3 -0
  195. package/dist/css/anchor.css +2 -0
  196. package/dist/css/app-shell.css +2 -0
  197. package/dist/css/badge.css +1 -1
  198. package/dist/css/bottom-sheet.css +1 -1
  199. package/dist/css/button.css +1 -1
  200. package/dist/css/calendar.css +1 -1
  201. package/dist/css/cascader.css +1 -1
  202. package/dist/css/chart.css +2 -0
  203. package/dist/css/chat-container.css +1 -1
  204. package/dist/css/chat-message.css +1 -1
  205. package/dist/css/combobox.css +3 -2
  206. package/dist/css/command.css +2 -1
  207. package/dist/css/context-menu.css +1 -1
  208. package/dist/css/data-table.css +2 -1
  209. package/dist/css/date-range-picker.css +1 -1
  210. package/dist/css/datepicker.css +2 -2
  211. package/dist/css/descriptions.css +2 -0
  212. package/dist/css/dialog.css +1 -1
  213. package/dist/css/drawer.css +1 -1
  214. package/dist/css/dropdown-menu.css +4 -1
  215. package/dist/css/file-preview.css +2 -0
  216. package/dist/css/float-button.css +2 -0
  217. package/dist/css/image.css +2 -1
  218. package/dist/css/inline-completion.css +2 -0
  219. package/dist/css/json-view.css +2 -0
  220. package/dist/css/masonry.css +2 -0
  221. package/dist/css/menu.css +4 -1
  222. package/dist/css/popover.css +1 -1
  223. package/dist/css/prompt-input.css +2 -0
  224. package/dist/css/rating.css +1 -1
  225. package/dist/css/select.css +3 -1
  226. package/dist/css/signature.css +2 -0
  227. package/dist/css/slider.css +1 -1
  228. package/dist/css/sources.css +2 -0
  229. package/dist/css/tag-group.css +3 -1
  230. package/dist/css/tag-input.css +2 -1
  231. package/dist/css/toggle.css +2 -0
  232. package/dist/css/toolbar.css +1 -0
  233. package/dist/css/tooltip.css +1 -1
  234. package/dist/css/tree.css +2 -2
  235. package/dist/css/upload.css +2 -1
  236. package/dist/css/watermark.css +2 -0
  237. package/dist/css-manifest.json +75 -1
  238. package/dist/form/FormItem.js +55 -50
  239. package/dist/form/FormList.js +79 -0
  240. package/dist/form/index.js +5 -1
  241. package/dist/form/standard-schema.js +16 -0
  242. package/dist/haze-ui.css +61 -30
  243. package/dist/headless/index.js +19 -0
  244. package/dist/hooks/useClickOutside.js +24 -0
  245. package/dist/hooks/useDarkMode.js +27 -0
  246. package/dist/hooks/useFullscreen.js +42 -0
  247. package/dist/hooks/useHotkeys.js +77 -0
  248. package/dist/hooks/useInView.js +27 -0
  249. package/dist/hooks/useLocalStorage.js +8 -0
  250. package/dist/hooks/useMediaQuery.js +2 -1
  251. package/dist/hooks/usePrevious.js +11 -0
  252. package/dist/hooks/useSessionStorage.js +8 -0
  253. package/dist/hooks/useStorageState.js +80 -0
  254. package/dist/index.js +220 -171
  255. package/dist/registry.json +2435 -91
  256. package/dist/tokens/colors.js +0 -1
  257. package/dist/tokens/index.js +0 -1
  258. package/dist/tokens/motion.js +0 -1
  259. package/dist/tokens/oklch.js +0 -1
  260. package/dist/tokens/palette.js +0 -1
  261. package/dist/tokens/registry.js +17 -28
  262. package/dist/tokens/spacing.js +0 -1
  263. package/dist/tokens/typography.js +0 -1
  264. package/dist/types/components/Anchor/Anchor.d.ts +25 -0
  265. package/dist/types/components/Anchor/index.d.ts +2 -0
  266. package/dist/types/components/AppShell/AppShell.d.ts +17 -0
  267. package/dist/types/components/AppShell/index.d.ts +2 -0
  268. package/dist/types/components/Badge/badge-styles.d.ts +21 -0
  269. package/dist/types/components/Badge/index.d.ts +1 -0
  270. package/dist/types/components/BottomSheet/BottomSheet.d.ts +52 -3
  271. package/dist/types/components/BottomSheet/index.d.ts +1 -1
  272. package/dist/types/components/Button/Button.d.ts +7 -0
  273. package/dist/types/components/Button/ButtonLink.d.ts +3 -0
  274. package/dist/types/components/Button/index.d.ts +1 -0
  275. package/dist/types/components/Button/styles.d.ts +17 -0
  276. package/dist/types/components/Calendar/Calendar.d.ts +71 -7
  277. package/dist/types/components/Calendar/date.d.ts +52 -0
  278. package/dist/types/components/Calendar/index.d.ts +1 -1
  279. package/dist/types/components/Cascader/Cascader.d.ts +48 -3
  280. package/dist/types/components/Chart/Chart.d.ts +43 -0
  281. package/dist/types/components/Chart/chart-elements.d.ts +104 -0
  282. package/dist/types/components/Chart/index.d.ts +2 -0
  283. package/dist/types/components/ChatContainer/ChatContainer.d.ts +18 -3
  284. package/dist/types/components/ChatInput/ChatInput.d.ts +11 -1
  285. package/dist/types/components/ChatMessage/ChatMessage.d.ts +13 -1
  286. package/dist/types/components/Checkbox/Checkbox.d.ts +6 -2
  287. package/dist/types/components/Checkbox/CheckboxCore.d.ts +4 -2
  288. package/dist/types/components/CodeBlock/CodeBlock.d.ts +19 -2
  289. package/dist/types/components/CodeBlock/index.d.ts +1 -1
  290. package/dist/types/components/Collapsible/Collapsible.d.ts +24 -2
  291. package/dist/types/components/Collapsible/index.d.ts +1 -1
  292. package/dist/types/components/ColorPicker/ColorPicker.d.ts +7 -1
  293. package/dist/types/components/ColorPicker/ColorPickerCore.d.ts +7 -1
  294. package/dist/types/components/Combobox/Combobox.d.ts +111 -7
  295. package/dist/types/components/Combobox/ComboboxGroup.d.ts +22 -0
  296. package/dist/types/components/Combobox/ComboboxOption.d.ts +7 -2
  297. package/dist/types/components/Combobox/index.d.ts +3 -1
  298. package/dist/types/components/Command/Command.d.ts +70 -6
  299. package/dist/types/components/Command/CommandDialog.d.ts +36 -0
  300. package/dist/types/components/Command/command-filter.d.ts +34 -0
  301. package/dist/types/components/Command/index.d.ts +4 -2
  302. package/dist/types/components/DataTable/CellEditor.d.ts +24 -0
  303. package/dist/types/components/DataTable/DataTable.d.ts +184 -32
  304. package/dist/types/components/DataTable/csv.d.ts +36 -0
  305. package/dist/types/components/DataTable/features.d.ts +124 -0
  306. package/dist/types/components/DataTable/index.d.ts +4 -1
  307. package/dist/types/components/DataTable/summary.d.ts +19 -0
  308. package/dist/types/components/DateRangePicker/DateRangePicker.d.ts +28 -2
  309. package/dist/types/components/DateRangePicker/DateRangePickerCore.d.ts +26 -2
  310. package/dist/types/components/DateRangePicker/index.d.ts +2 -2
  311. package/dist/types/components/DateRangePicker/presets.d.ts +23 -0
  312. package/dist/types/components/Datepicker/Datepicker.d.ts +21 -1
  313. package/dist/types/components/Datepicker/DatepickerCore.d.ts +29 -2
  314. package/dist/types/components/Datepicker/datetime.d.ts +27 -0
  315. package/dist/types/components/Datepicker/index.d.ts +1 -1
  316. package/dist/types/components/Descriptions/Descriptions.d.ts +30 -0
  317. package/dist/types/components/Descriptions/index.d.ts +2 -0
  318. package/dist/types/components/Dialog/Dialog.d.ts +68 -3
  319. package/dist/types/components/Dialog/index.d.ts +1 -1
  320. package/dist/types/components/Drawer/Drawer.d.ts +33 -3
  321. package/dist/types/components/Drawer/index.d.ts +1 -1
  322. package/dist/types/components/DropdownMenu/DropdownMenu.d.ts +23 -3
  323. package/dist/types/components/DropdownMenu/DropdownMenuSub.d.ts +18 -0
  324. package/dist/types/components/DropdownMenu/DropdownMenuSubContent.d.ts +13 -0
  325. package/dist/types/components/DropdownMenu/DropdownMenuSubTrigger.d.ts +14 -0
  326. package/dist/types/components/DropdownMenu/index.d.ts +7 -1
  327. package/dist/types/components/FilePreview/FilePreview.d.ts +35 -0
  328. package/dist/types/components/FilePreview/file-preview-format.d.ts +20 -0
  329. package/dist/types/components/FilePreview/index.d.ts +2 -0
  330. package/dist/types/components/FloatButton/FloatButton.d.ts +43 -0
  331. package/dist/types/components/FloatButton/FloatButtonGroup.d.ts +33 -0
  332. package/dist/types/components/FloatButton/float-button-context.d.ts +11 -0
  333. package/dist/types/components/FloatButton/float-button-glyphs.d.ts +3 -0
  334. package/dist/types/components/FloatButton/float-button-styles.d.ts +58 -0
  335. package/dist/types/components/FloatButton/index.d.ts +4 -0
  336. package/dist/types/components/Fullscreen/Fullscreen.d.ts +34 -0
  337. package/dist/types/components/Fullscreen/index.d.ts +3 -0
  338. package/dist/types/components/Image/Image.d.ts +20 -5
  339. package/dist/types/components/Image/ImagePreview.d.ts +13 -0
  340. package/dist/types/components/Image/index.d.ts +1 -1
  341. package/dist/types/components/InlineCompletion/InlineCompletion.d.ts +29 -0
  342. package/dist/types/components/InlineCompletion/index.d.ts +2 -0
  343. package/dist/types/components/Input/Input.d.ts +5 -2
  344. package/dist/types/components/Input/InputCore.d.ts +4 -2
  345. package/dist/types/components/JsonView/JsonView.d.ts +26 -0
  346. package/dist/types/components/JsonView/index.d.ts +2 -0
  347. package/dist/types/components/JsonView/json-view-utils.d.ts +22 -0
  348. package/dist/types/components/LocaleProvider/LocaleContext.d.ts +9 -0
  349. package/dist/types/components/LocaleProvider/LocaleProvider.d.ts +12 -1
  350. package/dist/types/components/LocaleProvider/index.d.ts +3 -0
  351. package/dist/types/components/LocaleProvider/ja-jp.d.ts +13 -0
  352. package/dist/types/components/LocaleProvider/locale.d.ts +100 -0
  353. package/dist/types/components/LocaleProvider/strings.d.ts +28 -0
  354. package/dist/types/components/Masonry/Masonry.d.ts +34 -0
  355. package/dist/types/components/Masonry/index.d.ts +2 -0
  356. package/dist/types/components/Masonry/masonry-distribute.d.ts +16 -0
  357. package/dist/types/components/Mentions/Mentions.d.ts +5 -2
  358. package/dist/types/components/Mentions/MentionsCore.d.ts +4 -2
  359. package/dist/types/components/Menu/MenuSub.d.ts +18 -0
  360. package/dist/types/components/Menu/MenuSubContent.d.ts +12 -0
  361. package/dist/types/components/Menu/MenuSubTrigger.d.ts +14 -0
  362. package/dist/types/components/Menu/index.d.ts +6 -0
  363. package/dist/types/components/NumberInput/NumberInput.d.ts +5 -2
  364. package/dist/types/components/NumberInput/NumberInputCore.d.ts +4 -2
  365. package/dist/types/components/OTPInput/OTPInput.d.ts +5 -1
  366. package/dist/types/components/OTPInput/OTPInputCore.d.ts +4 -1
  367. package/dist/types/components/PasswordInput/PasswordInput.d.ts +5 -1
  368. package/dist/types/components/PasswordInput/PasswordInputCore.d.ts +4 -1
  369. package/dist/types/components/Popover/Popover.d.ts +41 -3
  370. package/dist/types/components/Popover/index.d.ts +1 -1
  371. package/dist/types/components/PromptInput/PromptInput.d.ts +46 -0
  372. package/dist/types/components/PromptInput/index.d.ts +2 -0
  373. package/dist/types/components/Radio/Radio.d.ts +5 -2
  374. package/dist/types/components/Radio/RadioGroup.d.ts +8 -2
  375. package/dist/types/components/Radio/RadioGroupCore.d.ts +7 -2
  376. package/dist/types/components/Rating/Rating.d.ts +8 -1
  377. package/dist/types/components/Rating/RatingCore.d.ts +7 -1
  378. package/dist/types/components/Resizable/index.d.ts +2 -0
  379. package/dist/types/components/Segmented/Segmented.d.ts +8 -1
  380. package/dist/types/components/Segmented/SegmentedCore.d.ts +7 -2
  381. package/dist/types/components/Select/OptionGroup.d.ts +16 -0
  382. package/dist/types/components/Select/Select.d.ts +78 -4
  383. package/dist/types/components/Select/SelectCore.d.ts +79 -6
  384. package/dist/types/components/Select/SelectFloating.d.ts +94 -0
  385. package/dist/types/components/Select/index.d.ts +2 -0
  386. package/dist/types/components/Select/select-options.d.ts +53 -0
  387. package/dist/types/components/Signature/Signature.d.ts +51 -0
  388. package/dist/types/components/Signature/index.d.ts +2 -0
  389. package/dist/types/components/Signature/signature-points.d.ts +31 -0
  390. package/dist/types/components/Slider/Slider.d.ts +29 -4
  391. package/dist/types/components/Slider/SliderCore.d.ts +35 -6
  392. package/dist/types/components/Sources/Sources.d.ts +37 -0
  393. package/dist/types/components/Sources/index.d.ts +2 -0
  394. package/dist/types/components/Switch/Switch.d.ts +5 -2
  395. package/dist/types/components/Switch/SwitchCore.d.ts +4 -2
  396. package/dist/types/components/Tabs/TabList.d.ts +7 -0
  397. package/dist/types/components/Tabs/Tabs.d.ts +8 -1
  398. package/dist/types/components/Tabs/TabsContext.d.ts +20 -0
  399. package/dist/types/components/Tabs/index.d.ts +1 -0
  400. package/dist/types/components/TagGroup/SortableTagGroup.d.ts +20 -0
  401. package/dist/types/components/TagGroup/TagGroup.d.ts +3 -0
  402. package/dist/types/components/TagGroup/index.d.ts +2 -0
  403. package/dist/types/components/TagGroup/tag-group-styles.d.ts +7 -0
  404. package/dist/types/components/TagInput/SortableTagInput.d.ts +34 -0
  405. package/dist/types/components/TagInput/SortableTagInputCore.d.ts +18 -0
  406. package/dist/types/components/TagInput/TagInput.d.ts +5 -1
  407. package/dist/types/components/TagInput/TagInputCore.d.ts +6 -2
  408. package/dist/types/components/TagInput/index.d.ts +4 -0
  409. package/dist/types/components/TagInput/tag-input-styles.d.ts +12 -0
  410. package/dist/types/components/Textarea/Textarea.d.ts +5 -2
  411. package/dist/types/components/Textarea/TextareaCore.d.ts +4 -2
  412. package/dist/types/components/TimePicker/TimePicker.d.ts +5 -2
  413. package/dist/types/components/TimePicker/TimePickerCore.d.ts +4 -2
  414. package/dist/types/components/Toast/Toast.d.ts +31 -2
  415. package/dist/types/components/Toast/ToastContainer.d.ts +11 -1
  416. package/dist/types/components/Toast/ToastContext.d.ts +44 -3
  417. package/dist/types/components/Toast/index.d.ts +1 -1
  418. package/dist/types/components/Toast/toast.d.ts +35 -4
  419. package/dist/types/components/Toast/useToast.d.ts +16 -4
  420. package/dist/types/components/Toggle/Toggle.d.ts +19 -0
  421. package/dist/types/components/Toggle/ToggleCore.d.ts +23 -0
  422. package/dist/types/components/Toggle/index.d.ts +4 -0
  423. package/dist/types/components/Toolbar/ToolbarToggle.d.ts +19 -0
  424. package/dist/types/components/Toolbar/index.d.ts +2 -0
  425. package/dist/types/components/Tour/Tour.d.ts +3 -3
  426. package/dist/types/components/Tree/Tree.d.ts +3 -3
  427. package/dist/types/components/Tree/TreeItem.d.ts +16 -1
  428. package/dist/types/components/Tree/types.d.ts +51 -0
  429. package/dist/types/components/Tree/utils.d.ts +73 -0
  430. package/dist/types/components/Upload/Upload.d.ts +47 -3
  431. package/dist/types/components/Upload/UploadCore.d.ts +95 -4
  432. package/dist/types/components/Upload/UploadList.d.ts +18 -0
  433. package/dist/types/components/Upload/index.d.ts +1 -0
  434. package/dist/types/components/Upload/types.d.ts +60 -0
  435. package/dist/types/components/Upload/xhr-upload.d.ts +20 -0
  436. package/dist/types/components/VirtualList/VirtualList.d.ts +16 -1
  437. package/dist/types/components/Watermark/Watermark.d.ts +32 -0
  438. package/dist/types/components/Watermark/index.d.ts +2 -0
  439. package/dist/types/form/FormItem.d.ts +33 -8
  440. package/dist/types/form/FormList.d.ts +113 -0
  441. package/dist/types/form/index.d.ts +26 -0
  442. package/dist/types/form/standard-schema.d.ts +30 -0
  443. package/dist/types/headless/index.d.ts +399 -0
  444. package/dist/types/hooks/index.d.ts +13 -0
  445. package/dist/types/hooks/useClickOutside.d.ts +46 -0
  446. package/dist/types/hooks/useDarkMode.d.ts +40 -0
  447. package/dist/types/hooks/useFullscreen.d.ts +33 -0
  448. package/dist/types/hooks/useHotkeys.d.ts +53 -0
  449. package/dist/types/hooks/useInView.d.ts +32 -0
  450. package/dist/types/hooks/useLocalStorage.d.ts +33 -0
  451. package/dist/types/hooks/useMediaQuery.d.ts +3 -0
  452. package/dist/types/hooks/usePrevious.d.ts +18 -0
  453. package/dist/types/hooks/useSessionStorage.d.ts +26 -0
  454. package/dist/types/hooks/useStorageState.d.ts +12 -0
  455. package/dist/types/index.d.ts +79 -37
  456. package/dist/types/utils/collision.d.ts +39 -1
  457. package/dist/types/utils/direction.d.ts +22 -0
  458. package/dist/types/utils/floating.d.ts +32 -4
  459. package/dist/types/utils/focus-scope.d.ts +2 -1
  460. package/dist/types/utils/focus.d.ts +2 -1
  461. package/dist/types/utils/menuKeyboard.d.ts +19 -4
  462. package/dist/types/utils/refs.d.ts +16 -0
  463. package/dist/types/utils/sortable-handle.d.ts +25 -0
  464. package/dist/types/utils/sortable-shared.d.ts +30 -0
  465. package/dist/types/utils/sortable.d.ts +36 -0
  466. package/dist/types/utils/submenu.d.ts +63 -0
  467. package/dist/types/utils/view-transition.d.ts +28 -0
  468. package/dist/utils/classnames.js +0 -1
  469. package/dist/utils/collision.js +37 -26
  470. package/dist/utils/direction.js +34 -0
  471. package/dist/utils/floating.js +163 -143
  472. package/dist/utils/menuKeyboard.js +59 -46
  473. package/dist/utils/refs.js +9 -0
  474. package/dist/utils/sortable-handle.js +12 -0
  475. package/dist/utils/sortable-shared.js +16 -0
  476. package/dist/utils/sortable.js +47 -0
  477. package/dist/utils/submenu.js +106 -0
  478. package/dist/utils/view-transition.js +26 -0
  479. package/package.json +169 -16
package/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
  English | [简体中文](./README-zh_CN.md)
6
6
 
7
7
  [![npm](https://img.shields.io/npm/v/haze-ui)](https://www.npmjs.com/package/haze-ui)
8
+ [![downloads](https://img.shields.io/npm/dm/haze-ui.svg)](https://www.npmjs.com/package/haze-ui)
8
9
  [![CI](https://github.com/wmzy/haze-ui/actions/workflows/ci.yml/badge.svg)](https://github.com/wmzy/haze-ui/actions/workflows/ci.yml)
9
10
 
10
11
  ## Features
@@ -14,6 +15,15 @@ English | [简体中文](./README-zh_CN.md)
14
15
  - Keep strict, provide lightweight, composable, and easily extendable components
15
16
  - Support themes customization
16
17
  - Support Tree-shaking
18
+ - RTL by construction: CSS logical properties, mirrored horizontal-key
19
+ semantics (Tabs, Rating, Slider, Carousel, Calendar, menus, …) and
20
+ mirrored floating placements under `dir="rtl"`
21
+ - RSC-aware dist: interactive modules carry `'use client'`; 36 static,
22
+ hook-free modules (tokens, Badge, Card, Typography, …) ship without it
23
+ so they render as React Server Components
24
+ - Tested like a product: 120+ unit test files, axe accessibility cases in
25
+ every component test suite, ~50 Playwright e2e scenarios across
26
+ Chromium/Firefox/WebKit, and pixel-locked visual baselines
17
27
 
18
28
  ## Why npm-distributed (not copy-paste)
19
29
 
@@ -33,6 +43,42 @@ npm i haze-ui
33
43
  pnpm add haze-ui
34
44
  ```
35
45
 
46
+ ### Install via shadcn CLI (GitHub registry)
47
+
48
+ The repository is also a [shadcn registry](https://ui.shadcn.com/docs/registry/github),
49
+ so the shadcn CLI installs any component directly from GitHub — no manual
50
+ npm setup:
51
+
52
+ ```sh
53
+ pnpm dlx shadcn@latest add wmzy/haze-ui/button
54
+ pnpm dlx shadcn@latest add wmzy/haze-ui/dialog wmzy/haze-ui/tabs
55
+ pnpm dlx shadcn@latest add wmzy/haze-ui/base # everything at once
56
+ pnpm dlx shadcn@latest list wmzy/haze-ui # browse all items
57
+ ```
58
+
59
+ The `base` item (type `registry:base`) is the one-command path: it
60
+ installs the theme-token activation plus a wrapper for every component in
61
+ a single `shadcn add` — the 107 component items are pulled in through
62
+ `registryDependencies` (full `wmzy/haze-ui/<item>` addresses, since plain
63
+ names would resolve against the official shadcn registry).
64
+
65
+ Every **styled** export is covered (107 component items — one per CSS
66
+ family, so compound components like `tabs` arrive as `Tabs`/`TabList`/
67
+ `Tab`/`TabPanel` together). What lands in your project is a thin
68
+ **wrapper** file under `components/ui/haze/` that re-exports the
69
+ component from `haze-ui` and imports its stylesheet — not vendored
70
+ source. The wrapper is your customization layer (fork it, wrap it,
71
+ restyle it), while `haze-ui` itself is installed as a normal npm
72
+ dependency and keeps updating through your package manager. Common items:
73
+ `button`, `input`, `select`, `dialog`, `tabs`, `toast`, `sidebar`,
74
+ `form`, `data-table`, `chart`, `chat-message`, plus `tokens` (the theme
75
+ classes) and `haze-tokens` (a token onboarding guide doc). Each item also
76
+ carries `docs` (markdown usage — description, install command, theme
77
+ activation — printed by `shadcn view`) and `categories` (kebab-case tags
78
+ — `form`, `overlay`, `data-display`, `agent`, … — used by registry
79
+ search/filter tooling). See [registry/README.md](./registry/README.md)
80
+ for the full picture.
81
+
36
82
  ### React 19+ by design
37
83
 
38
84
  The peer range is `react: ^19.0.0` on purpose — haze-ui is built on
@@ -52,26 +98,61 @@ modern React rather than carrying a compatibility layer for 18:
52
98
  On React 18? Upgrade first. haze-ui ships no React 18 compatibility
53
99
  layer, and none is planned.
54
100
 
55
- ### Optional peer dependencies
56
-
57
- haze-ui's only required runtime dependency is `react-use-control` the
58
- engine behind `ControlOrValue<T>`. Two integrations are optional peers,
59
- installed only when you use the components that need them:
101
+ #### Migrating from React 18
102
+
103
+ Once the app itself is on React 19, run through the haze-ui-relevant
104
+ checklist:
105
+
106
+ - **`ref` is a prop.** React 19 passes `ref` to function components
107
+ directly — drop any `forwardRef` wrapper you had around haze components
108
+ and pass `ref` like any other prop.
109
+ - **No `defaultValue` dual track.** Stateful components speak
110
+ `ControlOrValue<T>` (`checked?: Control<T> | boolean`): one prop covers
111
+ controlled *and* uncontrolled usage, so there is no
112
+ `defaultChecked`/`defaultValue` pair to migrate. Where you used to pass
113
+ `defaultValue`, pass the plain value (uncontrolled) or switch to
114
+ controlled with `onChange`.
115
+ - **Floating panels assume the modern-platform baseline.** Popover,
116
+ DropdownMenu, Tooltip, ContextMenu, Combobox and Datepicker
117
+ feature-detect between native `popover` + CSS anchor positioning,
118
+ `popover` alone, or a JS fallback — no polyfills to carry over from
119
+ your React 18 setup, but the floor from [Browser support](#browser-support)
120
+ applies.
121
+ - **Colors are OKLCH with runtime-derived interaction states.** Requires
122
+ Chrome/Edge 119+, Safari 16.4+ or Firefox 128+; no HSL/hex fallbacks
123
+ are shipped.
124
+ - **`'use client'` is pre-injected on interactive modules.** Every
125
+ stateful module in `dist/` starts with the directive; the static,
126
+ hook-free set (tokens and presentational components) ships without it
127
+ so those render as React Server Components (see
128
+ [Server Components](#server-components-nextjs-app-router)).
129
+
130
+ ### Dependencies
131
+
132
+ haze-ui ships two runtime dependencies — `react-use-control`, the engine
133
+ behind `ControlOrValue<T>`, and `react-f0rm` (^1.3), the form engine
134
+ behind `FormItem`/`FormList` (the same author's headless form store).
135
+ Five integrations remain optional peers, installed only when you use the
136
+ components that need them:
60
137
 
61
138
  ```sh
62
- npm i react-f0rm # FormItem (peer range ^1.1.1)
63
- npm i @tanstack/react-table # DataTable (peer range ^9.2.4)
139
+ npm i @tanstack/react-table # DataTable (peer range ^9.2.4)
140
+ npm i recharts # Chart (peer range ^3.10.1)
141
+ npm i @dnd-kit/core @dnd-kit/sortable \
142
+ @dnd-kit/utilities # TagInput/TagGroup sortable
143
+ # (^6.3.1 / ^10.0.0 / ^3.2.2)
64
144
  ```
65
145
 
66
146
  Everything else — `Button`, `Input`, `Dialog`, `Select`, … — runs with
67
- nothing beyond `react` and `react-use-control`. The dist is ESM with
68
- `preserveModules` and side-effect-free JS, so bundlers (Next.js, Vite,
69
- webpack, Turbopack, Rollup) tree-shake the unused re-export chains and
70
- never resolve peers you haven't installed: `import { Button } from
71
- 'haze-ui'` works without `react-f0rm`. Only bundler-less consumers
72
- (bare Node ESM importing the barrel, which links the module graph
73
- eagerly) must install both peers; the `haze-ui/form` and
74
- `haze-ui/components/DataTable` subpaths bypass the barrel entirely.
147
+ nothing beyond `react` and the two runtime dependencies. The dist is ESM
148
+ with `preserveModules` and side-effect-free JS, so bundlers (Next.js,
149
+ Vite, webpack, Turbopack, Rollup) tree-shake the unused re-export chains
150
+ and never resolve peers you haven't installed: `import { Button } from
151
+ 'haze-ui'` works without `@tanstack/react-table`. Only bundler-less
152
+ consumers (bare Node ESM importing the barrel, which links the module
153
+ graph eagerly) must install the optional peers; the
154
+ `haze-ui/components/DataTable` and `haze-ui/components/Chart` subpaths
155
+ bypass the barrel entirely.
75
156
 
76
157
  ### Browser support
77
158
 
@@ -126,7 +207,7 @@ re-deriving file names — the mapping changes in lockstep with the build.
126
207
 
127
208
  ### Server Components (Next.js App Router)
128
209
 
129
- Every JS module in `dist/` starts with the `'use client'` directive,
210
+ Interactive modules in `dist/` carry the `'use client'` directive,
130
211
  injected at build time — the same convention Radix, Base UI and React
131
212
  Aria ship. In an App Router project you import haze-ui straight from
132
213
  your client components; there is no need for a wrapper module that
@@ -141,6 +222,26 @@ export function Actions() {
141
222
  }
142
223
  ```
143
224
 
225
+ **A static subset renders as React Server Components.** Modules with no
226
+ hooks and no DOM access ship *without* the directive, so they can be
227
+ imported directly into server components and cost zero client JS:
228
+
229
+ - tokens: everything on the `haze-ui/tokens` subpath (`lightTheme`,
230
+ `darkTheme`, `spacing`, `typography`, `TOKEN_REGISTRY`, OKLCH utils)
231
+ - components: `AspectRatio`, `Badge`, `Card`, `CodeBlock`, `Container`,
232
+ `Divider`, `Flex`, `Grid`/`GridItem`, `Icon`, `Kbd`, `Skeleton`,
233
+ `Stat`/`StatGroup`, `Typography` (`Title`/`Text`/`Paragraph`)
234
+
235
+ Import them from the subpath (`import { Badge } from
236
+ 'haze-ui/components/Badge'`) or the barrel — in an RSC module the
237
+ bundler resolves the module itself, not the client-marked barrel shell.
238
+ The emitted markup carries the usual Linaria class names, so CSS loading
239
+ is unchanged (`haze-ui/styles.css` or the `css/*` subpaths). The safe
240
+ list lives in `scripts/rsc-safe.mjs` and is enforced by
241
+ `src/lib/dist-esm-contract.test.ts` (including a transitive-closure
242
+ check: every static import inside a safe module must itself be safe) —
243
+ new components only join the list when they stay hook-free.
244
+
144
245
  CSS loading is unchanged from the two modes above — `haze-ui/styles.css`
145
246
  in the root layout, or the `haze-ui/css/*` subpaths. A runnable Next.js
146
247
  15 project lives in [`examples/nextjs`](./examples/nextjs).
@@ -222,6 +323,116 @@ function SettingsView() {
222
323
  }
223
324
  ```
224
325
 
326
+ ## Anchor: scroll-spy navigation
327
+
328
+ Sticky anchor navigation with an IntersectionObserver scroll-spy (a
329
+ scroll-listener fallback covers engines without IO). Pass `items`, and
330
+ the highlighted section is a controllable state like everything else —
331
+ `activeId?: ControlOrValue<string>`. Clicks scroll the container
332
+ (`getContainer` defaults to the window) with an `offsetTop` adjustment,
333
+ and the active link carries `aria-current="true"`.
334
+
335
+ ```jsx
336
+ import 'haze-ui/css/tokens.css';
337
+ import 'haze-ui/css/anchor.css';
338
+ import { Anchor } from 'haze-ui';
339
+
340
+ <Anchor items={[{ id: 'intro', label: 'Intro' }, { id: 'api', label: 'API' }]} />;
341
+ ```
342
+
343
+ ## Watermark: tiled canvas watermark
344
+
345
+ A canvas-tiled watermark layer: text rows (`content: string | string[]`)
346
+ rendered onto an off-screen tile (rotated, `gap`-spaced,
347
+ device-pixel-ratio aware) and repeated as a background over the
348
+ container — or the whole viewport with `fullscreen`. Default color
349
+ follows the theme's `--haze-color-text-muted`; the layer is
350
+ `pointer-events: none` and `aria-hidden`, and engines without a canvas
351
+ 2d context degrade to no watermark rather than crashing.
352
+
353
+ ```jsx
354
+ <Watermark content="CONFIDENTIAL" rotate={-22}>
355
+ <Report />
356
+ </Watermark>
357
+ ```
358
+
359
+ ## Fullscreen: wrap-mode fullscreen binding
360
+
361
+ `useFullscreen(target?)` returns `[isFullscreen, toggle, handle]` — the
362
+ Fullscreen API wired to `ControlOrValue` semantics: `Fullscreen`
363
+ wraps a single trigger child (its `onClick` is preserved and composed)
364
+ and exposes `fullscreen?: ControlOrValue<boolean>`, so browser-side
365
+ exits (Esc, OS gestures) write back through the control and fire
366
+ `onChange` exactly once.
367
+
368
+ ```jsx
369
+ const [fs, setFs, fsCtrl] = useControl(undefined, false);
370
+ <Fullscreen fullscreen={fsCtrl} onChange={setFs}>
371
+ <Button>Enter focus mode</Button>
372
+ </Fullscreen>
373
+ ```
374
+
375
+ ## Utility hooks
376
+
377
+ All hooks ship on the main barrel (no separate import path) and follow
378
+ the same conventions as the components: `ControlOrValue` where state is
379
+ user-controllable, SSR/jsdom-safe when the underlying API is missing.
380
+
381
+ | Hook | Returns | Notes |
382
+ | --- | --- | --- |
383
+ | `useClipboard(resetMs?)` | `{ copied, copy }` | `copied` resets after `resetMs` |
384
+ | `useDebouncedCallback(fn, delayMs)` | debounced `fn` | Stable identity across renders |
385
+ | `useDebouncedValue(value, delayMs)` | `T` | Trails the input by `delayMs` |
386
+ | `useFullscreen(target?)` | `[isFullscreen, toggle, handle]` | See section above |
387
+ | `useHotkeys(map, options?)` | — | `'mod+s'`-style specs (`mod` normalizes to ⌘ on macOS, Ctrl elsewhere); skips events from editable targets unless `allowInInput`; `hotkey(...keys)` builds specs type-safely |
388
+ | `useInView(options?)` | `[refCallback, inView]` | IntersectionObserver; `once` freezes after the first hit; `false` forever when the API is missing (SSR) |
389
+ | `useLocalStorage(key, control?, initial?)` | `[value, setValue]` | `ControlOrValue` semantics, cross-tab `storage` sync, corrupt JSON self-heals to `initial` |
390
+ | `useSessionStorage(key, control?, initial?)` | `[value, setValue]` | Same kernel, `sessionStorage` scope |
391
+ | `useMediaQuery(query)` | `boolean` | Reactive `matchMedia`; `false` when missing |
392
+ | `usePrefersReducedMotion()` | `boolean` | Token-aware animation gating |
393
+ | `useTitle(title)` | — | Document title while mounted |
394
+ | `useToast()` | toast API | Requires a `ToastContainer` ancestor |
395
+
396
+ ## Sortable tags and chips (optional dnd-kit peers)
397
+
398
+ `TagInput` and `TagGroup` accept `sortable?: boolean` — opt-in drag
399
+ reordering powered by `@dnd-kit/core` / `@dnd-kit/sortable` /
400
+ `@dnd-kit/utilities` (optional peers, same tree-shaking contract as
401
+ recharts and TanStack Table). `TagInput` writes the new array through
402
+ `onChange`; `TagGroup` reports `onReorder(nextOrder)` (the new
403
+ arrangement of original child indexes) and leaves re-rendering to the
404
+ parent. Sorting is keyboard-complete: focus a tag, `Space` to lift,
405
+ arrows to move, `Space` to drop, `Escape` to cancel.
406
+
407
+ ## Imperative overlay handles
408
+
409
+ `Dialog`, `Drawer`, `BottomSheet`, `Popover` and `DropdownMenu` accept a
410
+ `ref` (React 19 style — no `forwardRef`) exposing
411
+ `{ open(), close(), focusTrigger() }`. The methods drive the same state
412
+ outset as user interaction — `Dialog`'s `close()` goes through the
413
+ native `close` event path so `onClose` and focus restoration fire
414
+ exactly once — and they honor controlled mode, writing through the
415
+ control.
416
+
417
+ ```tsx
418
+ const dialog = useRef<DialogHandle>(null);
419
+ <Dialog ref={dialog} …>…</Dialog>;
420
+ <button onClick={() => dialog.current?.open()}>Show</button>;
421
+ ```
422
+
423
+ ## View Transitions on modals (opt-in)
424
+
425
+ `Dialog`, `Drawer` and `BottomSheet` accept `viewTransition?: boolean`
426
+ (default `false`). When enabled, their open/close state flips are wrapped
427
+ in `document.startViewTransition(() => flushSync(...))` — the synchronous
428
+ DOM-update pattern React requires — so modals animate through the native
429
+ View Transitions API alongside their regular enter/exit animations. The
430
+ transition itself degrades to a plain state flip when the engine lacks
431
+ `startViewTransition` or the user prefers reduced motion; transition
432
+ appearance is yours to style via `::view-transition-*`. Controlled
433
+ consumers' own flips happen outside the component and are intentionally
434
+ not wrapped.
435
+
225
436
  ## Design tokens export (Figma)
226
437
 
227
438
  `toDesignTokens()` converts the token registry into a [W3C Design Tokens](https://tr.designtokens.org/) JSON file — grouped by category (`color` / `font` / `spacing` / `dimension` / `shadow`), each token carrying a W3C `$type` and the source CSS variable in `$extensions['haze-ui.css-var']`, with `$value` being the resolved value of the chosen theme (`light` by default). The Theme Editor ships a one-click entry: the **Export W3C tokens (.json)** button in the toolbar downloads the file for the mode currently being edited, live edits included. The exported file can be imported directly into Figma Tokens / Tokens Studio.
@@ -245,29 +456,167 @@ function SettingsView() {
245
456
  }
246
457
  ```
247
458
 
459
+ ## Component-level tokens
460
+
461
+ Global `--haze-*` tokens theme the whole system; **component-level tokens**
462
+ theme one component family without touching anything else. They are plain
463
+ CSS custom properties consumed through a fallback chain baked into the
464
+ component's own stylesheet:
465
+
466
+ ```css
467
+ /* inside haze-ui/css/button.css */
468
+ height: var(--haze-button-height-md, auto);
469
+ ```
470
+
471
+ The library never defines these variables — nothing to register, no
472
+ runtime. When you set one on `:root` or any ancestor of the component, your
473
+ value wins; when you don't, the built-in fallback applies and the component
474
+ looks exactly as shipped. Scoping is ordinary CSS inheritance: set the
475
+ variable on a wrapper element to retheme only that subtree.
476
+
477
+ `Button`/`ButtonLink` (pilot — they share one skin, so both change
478
+ together; `Toggle` and the Toolbar items wearing the same skin follow
479
+ along):
480
+
481
+ | Token | Fallback (default look) |
482
+ | ---------------------------------- | ----------------------- |
483
+ | `--haze-button-height-sm/md/lg` | `auto` (content-driven) |
484
+ | `--haze-button-font-size-sm/md` | `var(--haze-text-sm)` |
485
+ | `--haze-button-font-size-lg` | `var(--haze-text-base)` |
486
+ | `--haze-button-radius` | `var(--haze-radius-md)` |
487
+
488
+ `Dialog`:
489
+
490
+ | Token | Fallback (default look) |
491
+ | -------------------------------- | ------------------------ |
492
+ | `--haze-dialog-width` | `480px` (on `max-width`) |
493
+ | `--haze-dialog-radius` | `var(--haze-radius-xl)` |
494
+ | `--haze-dialog-padding` | `var(--haze-space-6)` |
495
+ | `--haze-dialog-title-gap` | `var(--haze-space-4)` |
496
+ | `--haze-dialog-title-font-size` | `var(--haze-text-lg)` |
497
+
498
+ ```css
499
+ /* app-wide denser buttons; every other component keeps its sizing */
500
+ :root {
501
+ --haze-button-height-md: 32px;
502
+ }
503
+
504
+ /* only dialogs inside this subtree get wider */
505
+ .wide-dialogs {
506
+ --haze-dialog-width: 720px;
507
+ }
508
+ ```
509
+
510
+ `COMPONENT_TOKENS` (exported from `haze-ui` and `haze-ui/tokens`) lists
511
+ each component's component-level tokens alongside the global tokens it
512
+ consumes.
513
+
248
514
  ## AI-friendly distribution
249
515
 
250
516
  **llms.txt** — a markdown overview of the whole library (the `ControlOrValue<T>`
251
- state protocol, both CSS loading modes, all 101 components grouped with one-line
517
+ state protocol, both CSS loading modes, all 107 components grouped with one-line
252
518
  purposes, the token system, the floating-overlay tiers, form integration) written
253
519
  for AI coding tools and crawlers. It lives at the repo root
254
520
  ([llms.txt](./llms.txt)) and, on the docs site, at
255
521
  <https://wmzy.github.io/haze-ui/llms.txt> (`build:demo` copies it into `dist/`).
256
522
 
257
- **registry.json** — a shadcn/ui-compatible registry shipped as the
258
- `haze-ui/registry.json` npm artifact (regenerated by `scripts/generate-registry.mjs`
259
- on every build), also reachable at <https://unpkg.com/haze-ui/registry.json>.
260
- Consume it with the shadcn CLI:
523
+ **registry.json** — an agent-installable registry shipped as the
524
+ `haze-ui/registry.json` npm artifact (regenerated by
525
+ `scripts/generate-registry.mjs` on every build), also reachable at
526
+ <https://unpkg.com/haze-ui/registry.json>. Point any registry-aware
527
+ tooling at it — the shadcn CLI works:
261
528
 
262
529
  ```sh
263
530
  pnpm dlx shadcn@latest add https://unpkg.com/haze-ui/registry.json
264
531
  ```
265
532
 
266
- To be precise about coverage: it contains only the **agent components** (the
267
- AI & Chat group plus AsyncSection). Each item is a wrapper file, not vendored
268
- source it re-exports the published component and imports its stylesheet, so
269
- haze-ui stays an npm dependency that keeps updating underneath; treat the
270
- generated file as your customization layer.
533
+ Every item is a **wrapper file, not vendored source**: it re-exports the
534
+ component from the published haze-ui npm package and imports its
535
+ stylesheet, so `haze-ui` stays a normal npm dependency that keeps
536
+ updating underneath the shadcn CLI is only the distribution channel.
537
+ That is the point: AI coding agents (and anyone who wants a fast setup
538
+ while keeping the npm update path) get working imports in one step,
539
+ without the copy-paste expectation of owning pasted source. When you
540
+ want different styles or behavior, fork the generated wrapper file — it
541
+ is your customization layer, not a source drop. Coverage: **every styled
542
+ export** (107 css families / 185 components), generated from the build's
543
+ own css manifest. The same items are also installable straight from this
544
+ GitHub repository — see
545
+ [Install via shadcn CLI (GitHub registry)](#install-via-shadcn-cli-github-registry).
546
+
547
+ ## AI runtime integration (Vercel AI SDK `useChat`)
548
+
549
+ haze-ui ships the agent chat surface as **presentational** components —
550
+ `ChatContainer` (scrolling), `ChatMessage` (bubbles), `StreamingText`
551
+ (typewriter reveal), `ToolCallCard` (tool input/output), `ThinkingIndicator`
552
+ (waiting dots), `ChatInput` (composer) — with no opinion about where
553
+ messages come from. The Vercel AI SDK's `useChat` is the stateful half: it
554
+ owns `messages` (a `UIMessage[]` of typed `parts`), `status`
555
+ (`submitted | streaming | ready | error`) and the `sendMessage`/`stop`
556
+ pair. One small adapter bridges them — pure functions over duck-typed
557
+ shapes, so the `ai` package never enters your dependency tree through
558
+ haze-ui:
559
+
560
+ ```tsx
561
+ import { useChat } from '@ai-sdk/react';
562
+ import { DefaultChatTransport } from 'ai';
563
+ import { Button, ChatContainer, ChatInput } from 'haze-ui';
564
+
565
+ import { useHazeChat } from './ai-chat-adapter'; // the recipe module
566
+
567
+ function SupportChat() {
568
+ const chat = useChat({ transport: new DefaultChatTransport({ api: '/api/chat' }) });
569
+ const { messages, busy, send, stop } = useHazeChat(chat);
570
+
571
+ return (
572
+ <div>
573
+ <ChatContainer>{messages}</ChatContainer>
574
+ <ChatInput disabled={busy} onSend={send} />
575
+ {busy && <Button variant='outline' onClick={stop}>Stop</Button>}
576
+ </div>
577
+ );
578
+ }
579
+ ```
580
+
581
+ The mapping rules: text parts → `ChatMessage` bubbles (`StreamingText`
582
+ typewriter while a part streams), reasoning → `ThinkingIndicator` then a
583
+ collapsible transcript, `tool-*` parts → `ToolCallCard` driven by v5
584
+ `states` (with v4 `tool-call`/`tool-result` pairs folded into one card by
585
+ `toolCallId`), sources → links; `status: submitted` → thinking dots before
586
+ the first token, `error` → a system bubble with the transport error. The
587
+ whole thing is one small, unit-tested module that never throws on odd
588
+ payloads — unknown part types are skipped, so future SDK parts degrade
589
+ instead of crashing.
590
+
591
+ The full recipe — live runnable demo (same adapter over a mock streaming
592
+ source, no network), the complete adapter source, the `useHazeChat` hook,
593
+ per-part mapping table and known limits (attachments, branching, voice out
594
+ of scope; `StreamingText` restart-on-grow caveat for char-by-char
595
+ transports) — lives on the docs site:
596
+ **<https://wmzy.github.io/haze-ui/recipes>**.
597
+
598
+ ## Headless primitives
599
+
600
+ The behavior layer the styled components are built on ships as its own
601
+ subpath: `haze-ui/headless`. Component authors assembling their own panels
602
+ get the same primitives Popover, DropdownMenu and Tooltip use internally —
603
+ with the same version, no re-implementation:
604
+
605
+ - `useFloating` — the three-tier floating engine (native `popover` + CSS
606
+ anchor positioning → `popover` alone → JS fallback), plus
607
+ `placeFloatingPanel`, `useFloatingPosition` and the placement/panel types
608
+ - `Presence` — mount/unmount with exit animations
609
+ - `useFocusScope` / `isTabbable` / `getTabbables` — focus trapping and
610
+ tab-order queries
611
+ - `computeFloatingPosition` — the flip/shift collision math as a pure
612
+ function
613
+
614
+ ```jsx
615
+ import { useFloating, Presence } from 'haze-ui/headless';
616
+ ```
617
+
618
+ Stable public API — same semver commitment as the component library:
619
+ breaking changes land only on a major version.
271
620
 
272
621
  ## react-f0rm Integration
273
622
 
@@ -280,6 +629,25 @@ pair with zero adapters, and `FormItem` wraps the hook's state in label,
280
629
  error and aria wiring. The sugar components (`Input`, `Select`, ...)
281
630
  keep their `ControlOrValue<T>` (`Control<T> | T`) API for standalone use outside forms.
282
631
 
632
+ Beyond `FormItem`, the `haze-ui` barrel re-exports the whole form layer
633
+ so consumers never import react-f0rm directly: `FormList` (array fields
634
+ over `useFieldArray` — append/prepend/insert/remove/swap/move with
635
+ stable row keys), `FormProvider`/`useFormContext` (`FormItem`/`FormList`
636
+ fall back to context when the `form` prop is omitted), the imperative
637
+ APIs (`setValue`, `getValue`, `reset`, `trigger`, `setFocus`,
638
+ `setServerErrors`, `useWatch`, ...), and schema resolvers:
639
+
640
+ ```jsx
641
+ import { FormItem, FormList, zodResolver, standardSchemaResolver } from 'haze-ui';
642
+ ```
643
+
644
+ `zodResolver` adapts any zod schema (v4) as a field validator;
645
+ `standardSchemaResolver` adapts any Standard Schema v1 implementation
646
+ (zod, valibot, arktype, ...) the same way. Field controls forward refs
647
+ to their focusable element and `FormItem` wires f0rm's `focusRef`
648
+ channel, so `setFocus(form, 'name')` and a failed submit's
649
+ first-error auto-focus land on the real input.
650
+
283
651
  ### useField: field → {value, onChange}
284
652
 
285
653
  ```jsx
@@ -552,10 +920,25 @@ state changes with no per-component wiring.
552
920
  haze-ui supports RTL via CSS logical properties wherever a side is
553
921
  semantic (the *start/end* of reading flow), not just decorative. Set
554
922
  `dir="rtl"` (or `direction: rtl`) on an ancestor and those sides mirror
555
- automatically — no component props change. A regression smoke test
556
- (`src/lib/rtl.test.tsx`) renders Progress, Alert, Badge, Tag and Dialog
557
- in a `dir="rtl"` subtree asserting rendering, axe cleanliness and
558
- unchanged aria contracts.
923
+ automatically — no component props change. The same goes for keyboard
924
+ semantics: horizontal arrow keys invert their meaning in RTL (Tabs,
925
+ Rating, Slider, Carousel, Calendar, Toolbar, Cascader, Tour and
926
+ horizontal menus), and floating placements are logical — a panel with
927
+ `placement="bottom"` in an RTL document lands on the mirrored inline
928
+ side without passing a mirrored placement. `src/lib/rtl.test.tsx` is a
929
+ four-layer contract suite (rendering + axe, keyboard mirroring, floating
930
+ mirroring, and a CSS-codemod guard with an explicit exemption list),
931
+ backed by `e2e/rtl.spec.ts` cross-engine checks.
932
+
933
+ `LocaleProvider` takes an optional `direction` prop (`'ltr' | 'rtl'`,
934
+ explicit wins over derivation from the locale — Arabic, Hebrew, Farsi
935
+ and friends are derived automatically) and feeds `useDirection()`, the
936
+ hook components use internally. `getDirection(el)` (DOM resolution with
937
+ `[dir]` fallback) and `localeDirection(locale)` are exported from the
938
+ barrel alongside it, plus `createStrings(base, overrides)` — a
939
+ `DeepPartial<HazeStrings>` deep-merge for deriving locale packs without
940
+ forking a whole string table (see the *Adding a locale* recipe on the
941
+ docs site).
559
942
 
560
943
  ### Direction-responsive by construction (no physical CSS)
561
944
 
@@ -595,12 +978,13 @@ Checkbox's rotated checkmark, Radio's centered dot, Affix's symmetric
595
978
  ### Partial support: known gaps
596
979
 
597
980
  - **Floating panels (Popover, DropdownMenu, Tooltip, ContextMenu,
598
- Combobox, Datepicker)** — placements are physical sides
599
- (`'left'`/`'right'`/`'bottom-end'`, …). The CSS anchor-positioning
600
- `position-area` grid keywords and the JS collision math
601
- (`utils/collision.ts`, viewport coordinates) are physical; migrating to
602
- logical `position-area` keywords is a tracked future change. In RTL the
603
- panels position identically to LTR.
981
+ Combobox, Datepicker)** — *fixed*: `FloatingPlacement` is logical now.
982
+ Tier 1 uses logical `position-area` values (`span-inline-end
983
+ block-end`, …) where engines accept them and falls back to
984
+ dir-switched physical classes; the tier-2 JS math
985
+ (`utils/collision.ts` `computeFloatingPosition(..., { dir })`)
986
+ mirrors the x-axis. In RTL the panels open on the mirrored side
987
+ automatically.
604
988
  - **Input adornments** — `SelectCore` / `ModelPicker` chevrons
605
989
  (`background-position: right …` + `padding-right`) and
606
990
  `PasswordInputCore`'s absolute reveal button sit on the physical right
@@ -0,0 +1,78 @@
1
+
2
+ "use client";
3
+ import { classnames as e } from "../../utils/classnames.js";
4
+ /* empty css */
5
+ import { jsx as t } from "react/jsx-runtime";
6
+ import { useEffect as n } from "react";
7
+ import { useControl as r } from "react-use-control";
8
+ //#region src/lib/components/Anchor/Anchor.tsx
9
+ var i = "haze-Anchor__nav", a = "haze-Anchor__list", o = "haze-Anchor__link", s = "haze-Anchor__linkActive";
10
+ function c({ items: c, activeId: l, onClick: u, offsetTop: d = 0, bounds: f = 5, getContainer: p, className: m, ...h }) {
11
+ let [g, _] = r(l, () => c[0]?.id ?? ""), v = (e) => {
12
+ let t = document.getElementById(e);
13
+ if (!t) return;
14
+ let n = p?.() ?? window;
15
+ if (n instanceof HTMLElement) {
16
+ n.scrollTop = t.getBoundingClientRect().top - n.getBoundingClientRect().top + n.scrollTop - d;
17
+ return;
18
+ }
19
+ n.scrollTo({
20
+ top: t.getBoundingClientRect().top + window.scrollY - d,
21
+ behavior: "smooth"
22
+ });
23
+ };
24
+ return n(() => {
25
+ if (typeof IntersectionObserver > "u") return;
26
+ let e = /* @__PURE__ */ new Set(), t = p?.() ?? window, n = new IntersectionObserver((t) => {
27
+ for (let n of t) n.isIntersecting ? e.add(n.target.id) : e.delete(n.target.id);
28
+ let n = c.find((t) => e.has(t.id));
29
+ n && _(n.id);
30
+ }, {
31
+ root: t instanceof HTMLElement ? t : null,
32
+ rootMargin: `${-d}px 0px 0px 0px`
33
+ });
34
+ for (let e of c) {
35
+ let t = document.getElementById(e.id);
36
+ t && n.observe(t);
37
+ }
38
+ return () => n.disconnect();
39
+ }, [
40
+ c,
41
+ d,
42
+ p,
43
+ _
44
+ ]), n(() => {
45
+ if (typeof IntersectionObserver < "u") return;
46
+ let e = p?.() ?? window, t = e instanceof HTMLElement ? e : window, n = e instanceof HTMLElement ? e.getBoundingClientRect().top : 0, r = () => {
47
+ let e;
48
+ for (let t of c) {
49
+ let r = document.getElementById(t.id);
50
+ r && r.getBoundingClientRect().top - n <= f && (e = t.id);
51
+ }
52
+ e && _(e);
53
+ };
54
+ return t.addEventListener("scroll", r, { passive: !0 }), () => t.removeEventListener("scroll", r);
55
+ }, [
56
+ c,
57
+ f,
58
+ p,
59
+ _
60
+ ]), /* @__PURE__ */ t("nav", {
61
+ ...h,
62
+ className: e([i, m]),
63
+ children: t("ul", {
64
+ className: e([a]),
65
+ children: c.map((n) => /* @__PURE__ */ t("li", { children: /* @__PURE__ */ t("a", {
66
+ href: `#${n.id}`,
67
+ "aria-current": g === n.id ? "true" : void 0,
68
+ onClick: (e) => {
69
+ e.preventDefault(), _(n.id), u?.(n.id), v(n.id);
70
+ },
71
+ className: e([o, g === n.id && s]),
72
+ children: n.label
73
+ }) }, n.id))
74
+ })
75
+ });
76
+ }
77
+ //#endregion
78
+ export { c as default };
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import e from "./Anchor.js";
3
+ export { e as Anchor };