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.
- package/README.md +420 -36
- package/dist/components/Anchor/Anchor.js +78 -0
- package/dist/components/Anchor/index.js +3 -0
- package/dist/components/AppShell/AppShell.js +44 -0
- package/dist/components/AppShell/index.js +3 -0
- package/dist/components/AspectRatio/AspectRatio.js +0 -1
- package/dist/components/AspectRatio/index.js +0 -1
- package/dist/components/Badge/Badge.js +5 -17
- package/dist/components/Badge/badge-styles.js +15 -0
- package/dist/components/Badge/index.js +3 -3
- package/dist/components/BottomSheet/BottomSheet.js +133 -22
- package/dist/components/Button/index.js +4 -3
- package/dist/components/Calendar/Calendar.js +525 -78
- package/dist/components/Calendar/date.js +35 -2
- package/dist/components/Card/Card.js +0 -1
- package/dist/components/Card/index.js +0 -1
- package/dist/components/Carousel/Carousel.js +64 -41
- package/dist/components/Cascader/Cascader.js +222 -140
- package/dist/components/Chart/Chart.js +34 -0
- package/dist/components/Chart/chart-elements.js +164 -0
- package/dist/components/Chart/index.js +3 -0
- package/dist/components/ChatContainer/ChatContainer.js +36 -16
- package/dist/components/ChatInput/ChatInput.js +49 -29
- package/dist/components/ChatMessage/ChatMessage.js +76 -29
- package/dist/components/Checkbox/Checkbox.js +6 -5
- package/dist/components/Checkbox/CheckboxCore.js +6 -5
- package/dist/components/CodeBlock/CodeBlock.js +39 -10
- package/dist/components/CodeBlock/index.js +0 -1
- package/dist/components/Collapsible/Collapsible.js +23 -10
- package/dist/components/ColorPicker/ColorPicker.js +5 -4
- package/dist/components/ColorPicker/ColorPickerCore.js +5 -4
- package/dist/components/Combobox/Combobox.js +202 -75
- package/dist/components/Combobox/ComboboxGroup.js +23 -0
- package/dist/components/Combobox/ComboboxOption.js +7 -6
- package/dist/components/Combobox/index.js +4 -3
- package/dist/components/Command/Command.js +102 -59
- package/dist/components/Command/CommandDialog.js +48 -0
- package/dist/components/Command/command-filter.js +16 -0
- package/dist/components/Command/index.js +3 -2
- package/dist/components/ConfirmDialog/ConfirmDialog.js +3 -3
- package/dist/components/Container/Container.js +0 -1
- package/dist/components/Container/index.js +0 -1
- package/dist/components/ContextMenu/ContextMenuContent.js +4 -4
- package/dist/components/DataTable/CellEditor.js +38 -0
- package/dist/components/DataTable/DataTable.js +394 -143
- package/dist/components/DataTable/csv.js +29 -0
- package/dist/components/DataTable/features.js +25 -0
- package/dist/components/DataTable/index.js +3 -1
- package/dist/components/DataTable/summary.js +17 -0
- package/dist/components/DateRangePicker/DateRangePicker.js +31 -13
- package/dist/components/DateRangePicker/DateRangePickerCore.js +59 -27
- package/dist/components/DateRangePicker/presets.js +43 -0
- package/dist/components/Datepicker/Datepicker.js +17 -12
- package/dist/components/Datepicker/DatepickerCore.js +73 -39
- package/dist/components/Datepicker/datetime.js +23 -0
- package/dist/components/Descriptions/Descriptions.js +46 -0
- package/dist/components/Descriptions/index.js +3 -0
- package/dist/components/Dialog/Dialog.js +56 -32
- package/dist/components/DiffViewer/DiffViewer.js +31 -30
- package/dist/components/Divider/Divider.js +0 -1
- package/dist/components/Divider/index.js +0 -1
- package/dist/components/Drawer/Drawer.js +49 -29
- package/dist/components/DropdownMenu/DropdownMenu.js +38 -26
- package/dist/components/DropdownMenu/DropdownMenuSub.js +23 -0
- package/dist/components/DropdownMenu/DropdownMenuSubContent.js +24 -0
- package/dist/components/DropdownMenu/DropdownMenuSubTrigger.js +30 -0
- package/dist/components/DropdownMenu/index.js +4 -1
- package/dist/components/FilePreview/FilePreview.js +135 -0
- package/dist/components/FilePreview/file-preview-format.js +23 -0
- package/dist/components/FilePreview/index.js +3 -0
- package/dist/components/Flex/Flex.js +0 -1
- package/dist/components/Flex/index.js +0 -1
- package/dist/components/FloatButton/FloatButton.js +42 -0
- package/dist/components/FloatButton/FloatButtonGroup.js +58 -0
- package/dist/components/FloatButton/float-button-context.js +9 -0
- package/dist/components/FloatButton/float-button-glyphs.js +26 -0
- package/dist/components/FloatButton/float-button-styles.js +14 -0
- package/dist/components/FloatButton/index.js +4 -0
- package/dist/components/Fullscreen/Fullscreen.js +29 -0
- package/dist/components/Fullscreen/index.js +3 -0
- package/dist/components/Grid/Grid.js +0 -1
- package/dist/components/Grid/GridItem.js +0 -1
- package/dist/components/Grid/index.js +0 -1
- package/dist/components/Icon/Icon.js +0 -1
- package/dist/components/Icon/index.js +0 -1
- package/dist/components/Image/Image.js +37 -19
- package/dist/components/Image/ImagePreview.js +233 -0
- package/dist/components/InlineCompletion/InlineCompletion.js +81 -0
- package/dist/components/InlineCompletion/index.js +3 -0
- package/dist/components/Input/Input.js +6 -5
- package/dist/components/Input/InputCore.js +3 -2
- package/dist/components/JsonView/JsonView.js +209 -0
- package/dist/components/JsonView/index.js +3 -0
- package/dist/components/JsonView/json-view-utils.js +24 -0
- package/dist/components/Kbd/Kbd.js +0 -1
- package/dist/components/Kbd/index.js +0 -1
- package/dist/components/LocaleProvider/LocaleProvider.js +16 -13
- package/dist/components/LocaleProvider/index.js +5 -3
- package/dist/components/LocaleProvider/ja-jp.js +222 -0
- package/dist/components/LocaleProvider/locale.js +99 -5
- package/dist/components/LocaleProvider/strings.js +15 -0
- package/dist/components/LocaleProvider/useStrings.js +13 -11
- package/dist/components/LocaleProvider/zh-cn.js +99 -5
- package/dist/components/Masonry/Masonry.js +29 -0
- package/dist/components/Masonry/index.js +3 -0
- package/dist/components/Masonry/masonry-distribute.js +15 -0
- package/dist/components/Mentions/Mentions.js +6 -5
- package/dist/components/Mentions/MentionsCore.js +69 -68
- package/dist/components/Menu/Menu.js +5 -5
- package/dist/components/Menu/MenuSub.js +23 -0
- package/dist/components/Menu/MenuSubContent.js +24 -0
- package/dist/components/Menu/MenuSubTrigger.js +30 -0
- package/dist/components/Menu/index.js +4 -1
- package/dist/components/NumberInput/NumberInput.js +6 -5
- package/dist/components/NumberInput/NumberInputCore.js +9 -8
- package/dist/components/OTPInput/OTPInput.js +5 -4
- package/dist/components/OTPInput/OTPInputCore.js +34 -33
- package/dist/components/PasswordInput/PasswordInput.js +5 -4
- package/dist/components/PasswordInput/PasswordInputCore.js +8 -7
- package/dist/components/Popover/Popover.js +43 -31
- package/dist/components/PromptInput/PromptInput.js +213 -0
- package/dist/components/PromptInput/index.js +3 -0
- package/dist/components/Radio/Radio.js +7 -6
- package/dist/components/Radio/RadioGroup.js +5 -4
- package/dist/components/Radio/RadioGroupCore.js +23 -14
- package/dist/components/Rating/Rating.js +5 -4
- package/dist/components/Rating/RatingCore.js +62 -28
- package/dist/components/Resizable/index.js +1 -1
- package/dist/components/Segmented/Segmented.js +5 -4
- package/dist/components/Segmented/SegmentedCore.js +22 -18
- package/dist/components/Select/OptionGroup.js +12 -0
- package/dist/components/Select/Select.js +20 -9
- package/dist/components/Select/SelectCore.js +74 -13
- package/dist/components/Select/SelectFloating.js +256 -0
- package/dist/components/Select/index.js +5 -4
- package/dist/components/Select/select-options.js +57 -0
- package/dist/components/Sidebar/Sidebar.js +9 -9
- package/dist/components/Signature/Signature.js +165 -0
- package/dist/components/Signature/index.js +3 -0
- package/dist/components/Signature/signature-points.js +28 -0
- package/dist/components/Skeleton/Skeleton.js +0 -1
- package/dist/components/Skeleton/index.js +0 -1
- package/dist/components/Slider/Slider.js +16 -8
- package/dist/components/Slider/SliderCore.js +75 -12
- package/dist/components/Sources/Sources.js +109 -0
- package/dist/components/Sources/index.js +3 -0
- package/dist/components/Stat/Stat.js +0 -1
- package/dist/components/Stat/index.js +0 -1
- package/dist/components/Switch/Switch.js +6 -5
- package/dist/components/Switch/SwitchCore.js +3 -2
- package/dist/components/Tabs/Tab.js +7 -4
- package/dist/components/Tabs/TabList.js +38 -7
- package/dist/components/Tabs/TabPanel.js +4 -3
- package/dist/components/Tabs/Tabs.js +11 -6
- package/dist/components/TagGroup/SortableTagGroup.js +26 -0
- package/dist/components/TagGroup/TagGroup.js +4 -6
- package/dist/components/TagGroup/TagGroupItem.js +17 -11
- package/dist/components/TagGroup/index.js +2 -1
- package/dist/components/TagGroup/tag-group-styles.js +7 -0
- package/dist/components/TagInput/SortableTagInput.js +24 -0
- package/dist/components/TagInput/SortableTagInputCore.js +52 -0
- package/dist/components/TagInput/TagInput.js +5 -4
- package/dist/components/TagInput/TagInputCore.js +71 -57
- package/dist/components/TagInput/index.js +3 -1
- package/dist/components/TagInput/tag-input-styles.js +7 -0
- package/dist/components/Textarea/Textarea.js +6 -5
- package/dist/components/Textarea/TextareaCore.js +3 -2
- package/dist/components/TimePicker/TimePicker.js +6 -5
- package/dist/components/TimePicker/TimePickerCore.js +3 -2
- package/dist/components/Toast/Toast.js +44 -42
- package/dist/components/Toast/ToastContainer.js +67 -47
- package/dist/components/Toast/ToastContext.js +23 -4
- package/dist/components/Toast/toast2.js +63 -28
- package/dist/components/Toast/useToast.js +9 -7
- package/dist/components/Toggle/Toggle.js +20 -0
- package/dist/components/Toggle/ToggleCore.js +31 -0
- package/dist/components/Toggle/index.js +4 -0
- package/dist/components/Toolbar/Toolbar.js +33 -32
- package/dist/components/Toolbar/ToolbarToggle.js +31 -0
- package/dist/components/Toolbar/index.js +2 -1
- package/dist/components/Tooltip/Tooltip.js +1 -1
- package/dist/components/Tour/Tour.js +57 -53
- package/dist/components/Tree/Tree.js +265 -80
- package/dist/components/Tree/TreeItem.js +91 -55
- package/dist/components/Tree/utils.js +82 -10
- package/dist/components/Typography/Typography.js +0 -1
- package/dist/components/Typography/index.js +0 -1
- package/dist/components/Upload/Upload.js +24 -8
- package/dist/components/Upload/UploadCore.js +230 -37
- package/dist/components/Upload/UploadList.js +300 -0
- package/dist/components/Upload/xhr-upload.js +22 -0
- package/dist/components/VirtualList/VirtualList.js +84 -56
- package/dist/components/Watermark/Watermark.js +55 -0
- package/dist/components/Watermark/index.js +3 -0
- package/dist/css/anchor.css +2 -0
- package/dist/css/app-shell.css +2 -0
- package/dist/css/badge.css +1 -1
- package/dist/css/bottom-sheet.css +1 -1
- package/dist/css/button.css +1 -1
- package/dist/css/calendar.css +1 -1
- package/dist/css/cascader.css +1 -1
- package/dist/css/chart.css +2 -0
- package/dist/css/chat-container.css +1 -1
- package/dist/css/chat-message.css +1 -1
- package/dist/css/combobox.css +3 -2
- package/dist/css/command.css +2 -1
- package/dist/css/context-menu.css +1 -1
- package/dist/css/data-table.css +2 -1
- package/dist/css/date-range-picker.css +1 -1
- package/dist/css/datepicker.css +2 -2
- package/dist/css/descriptions.css +2 -0
- package/dist/css/dialog.css +1 -1
- package/dist/css/drawer.css +1 -1
- package/dist/css/dropdown-menu.css +4 -1
- package/dist/css/file-preview.css +2 -0
- package/dist/css/float-button.css +2 -0
- package/dist/css/image.css +2 -1
- package/dist/css/inline-completion.css +2 -0
- package/dist/css/json-view.css +2 -0
- package/dist/css/masonry.css +2 -0
- package/dist/css/menu.css +4 -1
- package/dist/css/popover.css +1 -1
- package/dist/css/prompt-input.css +2 -0
- package/dist/css/rating.css +1 -1
- package/dist/css/select.css +3 -1
- package/dist/css/signature.css +2 -0
- package/dist/css/slider.css +1 -1
- package/dist/css/sources.css +2 -0
- package/dist/css/tag-group.css +3 -1
- package/dist/css/tag-input.css +2 -1
- package/dist/css/toggle.css +2 -0
- package/dist/css/toolbar.css +1 -0
- package/dist/css/tooltip.css +1 -1
- package/dist/css/tree.css +2 -2
- package/dist/css/upload.css +2 -1
- package/dist/css/watermark.css +2 -0
- package/dist/css-manifest.json +75 -1
- package/dist/form/FormItem.js +55 -50
- package/dist/form/FormList.js +79 -0
- package/dist/form/index.js +5 -1
- package/dist/form/standard-schema.js +16 -0
- package/dist/haze-ui.css +61 -30
- package/dist/headless/index.js +19 -0
- package/dist/hooks/useClickOutside.js +24 -0
- package/dist/hooks/useDarkMode.js +27 -0
- package/dist/hooks/useFullscreen.js +42 -0
- package/dist/hooks/useHotkeys.js +77 -0
- package/dist/hooks/useInView.js +27 -0
- package/dist/hooks/useLocalStorage.js +8 -0
- package/dist/hooks/useMediaQuery.js +2 -1
- package/dist/hooks/usePrevious.js +11 -0
- package/dist/hooks/useSessionStorage.js +8 -0
- package/dist/hooks/useStorageState.js +80 -0
- package/dist/index.js +220 -171
- package/dist/registry.json +2435 -91
- package/dist/tokens/colors.js +0 -1
- package/dist/tokens/index.js +0 -1
- package/dist/tokens/motion.js +0 -1
- package/dist/tokens/oklch.js +0 -1
- package/dist/tokens/palette.js +0 -1
- package/dist/tokens/registry.js +17 -28
- package/dist/tokens/spacing.js +0 -1
- package/dist/tokens/typography.js +0 -1
- package/dist/types/components/Anchor/Anchor.d.ts +25 -0
- package/dist/types/components/Anchor/index.d.ts +2 -0
- package/dist/types/components/AppShell/AppShell.d.ts +17 -0
- package/dist/types/components/AppShell/index.d.ts +2 -0
- package/dist/types/components/Badge/badge-styles.d.ts +21 -0
- package/dist/types/components/Badge/index.d.ts +1 -0
- package/dist/types/components/BottomSheet/BottomSheet.d.ts +52 -3
- package/dist/types/components/BottomSheet/index.d.ts +1 -1
- package/dist/types/components/Button/Button.d.ts +7 -0
- package/dist/types/components/Button/ButtonLink.d.ts +3 -0
- package/dist/types/components/Button/index.d.ts +1 -0
- package/dist/types/components/Button/styles.d.ts +17 -0
- package/dist/types/components/Calendar/Calendar.d.ts +71 -7
- package/dist/types/components/Calendar/date.d.ts +52 -0
- package/dist/types/components/Calendar/index.d.ts +1 -1
- package/dist/types/components/Cascader/Cascader.d.ts +48 -3
- package/dist/types/components/Chart/Chart.d.ts +43 -0
- package/dist/types/components/Chart/chart-elements.d.ts +104 -0
- package/dist/types/components/Chart/index.d.ts +2 -0
- package/dist/types/components/ChatContainer/ChatContainer.d.ts +18 -3
- package/dist/types/components/ChatInput/ChatInput.d.ts +11 -1
- package/dist/types/components/ChatMessage/ChatMessage.d.ts +13 -1
- package/dist/types/components/Checkbox/Checkbox.d.ts +6 -2
- package/dist/types/components/Checkbox/CheckboxCore.d.ts +4 -2
- package/dist/types/components/CodeBlock/CodeBlock.d.ts +19 -2
- package/dist/types/components/CodeBlock/index.d.ts +1 -1
- package/dist/types/components/Collapsible/Collapsible.d.ts +24 -2
- package/dist/types/components/Collapsible/index.d.ts +1 -1
- package/dist/types/components/ColorPicker/ColorPicker.d.ts +7 -1
- package/dist/types/components/ColorPicker/ColorPickerCore.d.ts +7 -1
- package/dist/types/components/Combobox/Combobox.d.ts +111 -7
- package/dist/types/components/Combobox/ComboboxGroup.d.ts +22 -0
- package/dist/types/components/Combobox/ComboboxOption.d.ts +7 -2
- package/dist/types/components/Combobox/index.d.ts +3 -1
- package/dist/types/components/Command/Command.d.ts +70 -6
- package/dist/types/components/Command/CommandDialog.d.ts +36 -0
- package/dist/types/components/Command/command-filter.d.ts +34 -0
- package/dist/types/components/Command/index.d.ts +4 -2
- package/dist/types/components/DataTable/CellEditor.d.ts +24 -0
- package/dist/types/components/DataTable/DataTable.d.ts +184 -32
- package/dist/types/components/DataTable/csv.d.ts +36 -0
- package/dist/types/components/DataTable/features.d.ts +124 -0
- package/dist/types/components/DataTable/index.d.ts +4 -1
- package/dist/types/components/DataTable/summary.d.ts +19 -0
- package/dist/types/components/DateRangePicker/DateRangePicker.d.ts +28 -2
- package/dist/types/components/DateRangePicker/DateRangePickerCore.d.ts +26 -2
- package/dist/types/components/DateRangePicker/index.d.ts +2 -2
- package/dist/types/components/DateRangePicker/presets.d.ts +23 -0
- package/dist/types/components/Datepicker/Datepicker.d.ts +21 -1
- package/dist/types/components/Datepicker/DatepickerCore.d.ts +29 -2
- package/dist/types/components/Datepicker/datetime.d.ts +27 -0
- package/dist/types/components/Datepicker/index.d.ts +1 -1
- package/dist/types/components/Descriptions/Descriptions.d.ts +30 -0
- package/dist/types/components/Descriptions/index.d.ts +2 -0
- package/dist/types/components/Dialog/Dialog.d.ts +68 -3
- package/dist/types/components/Dialog/index.d.ts +1 -1
- package/dist/types/components/Drawer/Drawer.d.ts +33 -3
- package/dist/types/components/Drawer/index.d.ts +1 -1
- package/dist/types/components/DropdownMenu/DropdownMenu.d.ts +23 -3
- package/dist/types/components/DropdownMenu/DropdownMenuSub.d.ts +18 -0
- package/dist/types/components/DropdownMenu/DropdownMenuSubContent.d.ts +13 -0
- package/dist/types/components/DropdownMenu/DropdownMenuSubTrigger.d.ts +14 -0
- package/dist/types/components/DropdownMenu/index.d.ts +7 -1
- package/dist/types/components/FilePreview/FilePreview.d.ts +35 -0
- package/dist/types/components/FilePreview/file-preview-format.d.ts +20 -0
- package/dist/types/components/FilePreview/index.d.ts +2 -0
- package/dist/types/components/FloatButton/FloatButton.d.ts +43 -0
- package/dist/types/components/FloatButton/FloatButtonGroup.d.ts +33 -0
- package/dist/types/components/FloatButton/float-button-context.d.ts +11 -0
- package/dist/types/components/FloatButton/float-button-glyphs.d.ts +3 -0
- package/dist/types/components/FloatButton/float-button-styles.d.ts +58 -0
- package/dist/types/components/FloatButton/index.d.ts +4 -0
- package/dist/types/components/Fullscreen/Fullscreen.d.ts +34 -0
- package/dist/types/components/Fullscreen/index.d.ts +3 -0
- package/dist/types/components/Image/Image.d.ts +20 -5
- package/dist/types/components/Image/ImagePreview.d.ts +13 -0
- package/dist/types/components/Image/index.d.ts +1 -1
- package/dist/types/components/InlineCompletion/InlineCompletion.d.ts +29 -0
- package/dist/types/components/InlineCompletion/index.d.ts +2 -0
- package/dist/types/components/Input/Input.d.ts +5 -2
- package/dist/types/components/Input/InputCore.d.ts +4 -2
- package/dist/types/components/JsonView/JsonView.d.ts +26 -0
- package/dist/types/components/JsonView/index.d.ts +2 -0
- package/dist/types/components/JsonView/json-view-utils.d.ts +22 -0
- package/dist/types/components/LocaleProvider/LocaleContext.d.ts +9 -0
- package/dist/types/components/LocaleProvider/LocaleProvider.d.ts +12 -1
- package/dist/types/components/LocaleProvider/index.d.ts +3 -0
- package/dist/types/components/LocaleProvider/ja-jp.d.ts +13 -0
- package/dist/types/components/LocaleProvider/locale.d.ts +100 -0
- package/dist/types/components/LocaleProvider/strings.d.ts +28 -0
- package/dist/types/components/Masonry/Masonry.d.ts +34 -0
- package/dist/types/components/Masonry/index.d.ts +2 -0
- package/dist/types/components/Masonry/masonry-distribute.d.ts +16 -0
- package/dist/types/components/Mentions/Mentions.d.ts +5 -2
- package/dist/types/components/Mentions/MentionsCore.d.ts +4 -2
- package/dist/types/components/Menu/MenuSub.d.ts +18 -0
- package/dist/types/components/Menu/MenuSubContent.d.ts +12 -0
- package/dist/types/components/Menu/MenuSubTrigger.d.ts +14 -0
- package/dist/types/components/Menu/index.d.ts +6 -0
- package/dist/types/components/NumberInput/NumberInput.d.ts +5 -2
- package/dist/types/components/NumberInput/NumberInputCore.d.ts +4 -2
- package/dist/types/components/OTPInput/OTPInput.d.ts +5 -1
- package/dist/types/components/OTPInput/OTPInputCore.d.ts +4 -1
- package/dist/types/components/PasswordInput/PasswordInput.d.ts +5 -1
- package/dist/types/components/PasswordInput/PasswordInputCore.d.ts +4 -1
- package/dist/types/components/Popover/Popover.d.ts +41 -3
- package/dist/types/components/Popover/index.d.ts +1 -1
- package/dist/types/components/PromptInput/PromptInput.d.ts +46 -0
- package/dist/types/components/PromptInput/index.d.ts +2 -0
- package/dist/types/components/Radio/Radio.d.ts +5 -2
- package/dist/types/components/Radio/RadioGroup.d.ts +8 -2
- package/dist/types/components/Radio/RadioGroupCore.d.ts +7 -2
- package/dist/types/components/Rating/Rating.d.ts +8 -1
- package/dist/types/components/Rating/RatingCore.d.ts +7 -1
- package/dist/types/components/Resizable/index.d.ts +2 -0
- package/dist/types/components/Segmented/Segmented.d.ts +8 -1
- package/dist/types/components/Segmented/SegmentedCore.d.ts +7 -2
- package/dist/types/components/Select/OptionGroup.d.ts +16 -0
- package/dist/types/components/Select/Select.d.ts +78 -4
- package/dist/types/components/Select/SelectCore.d.ts +79 -6
- package/dist/types/components/Select/SelectFloating.d.ts +94 -0
- package/dist/types/components/Select/index.d.ts +2 -0
- package/dist/types/components/Select/select-options.d.ts +53 -0
- package/dist/types/components/Signature/Signature.d.ts +51 -0
- package/dist/types/components/Signature/index.d.ts +2 -0
- package/dist/types/components/Signature/signature-points.d.ts +31 -0
- package/dist/types/components/Slider/Slider.d.ts +29 -4
- package/dist/types/components/Slider/SliderCore.d.ts +35 -6
- package/dist/types/components/Sources/Sources.d.ts +37 -0
- package/dist/types/components/Sources/index.d.ts +2 -0
- package/dist/types/components/Switch/Switch.d.ts +5 -2
- package/dist/types/components/Switch/SwitchCore.d.ts +4 -2
- package/dist/types/components/Tabs/TabList.d.ts +7 -0
- package/dist/types/components/Tabs/Tabs.d.ts +8 -1
- package/dist/types/components/Tabs/TabsContext.d.ts +20 -0
- package/dist/types/components/Tabs/index.d.ts +1 -0
- package/dist/types/components/TagGroup/SortableTagGroup.d.ts +20 -0
- package/dist/types/components/TagGroup/TagGroup.d.ts +3 -0
- package/dist/types/components/TagGroup/index.d.ts +2 -0
- package/dist/types/components/TagGroup/tag-group-styles.d.ts +7 -0
- package/dist/types/components/TagInput/SortableTagInput.d.ts +34 -0
- package/dist/types/components/TagInput/SortableTagInputCore.d.ts +18 -0
- package/dist/types/components/TagInput/TagInput.d.ts +5 -1
- package/dist/types/components/TagInput/TagInputCore.d.ts +6 -2
- package/dist/types/components/TagInput/index.d.ts +4 -0
- package/dist/types/components/TagInput/tag-input-styles.d.ts +12 -0
- package/dist/types/components/Textarea/Textarea.d.ts +5 -2
- package/dist/types/components/Textarea/TextareaCore.d.ts +4 -2
- package/dist/types/components/TimePicker/TimePicker.d.ts +5 -2
- package/dist/types/components/TimePicker/TimePickerCore.d.ts +4 -2
- package/dist/types/components/Toast/Toast.d.ts +31 -2
- package/dist/types/components/Toast/ToastContainer.d.ts +11 -1
- package/dist/types/components/Toast/ToastContext.d.ts +44 -3
- package/dist/types/components/Toast/index.d.ts +1 -1
- package/dist/types/components/Toast/toast.d.ts +35 -4
- package/dist/types/components/Toast/useToast.d.ts +16 -4
- package/dist/types/components/Toggle/Toggle.d.ts +19 -0
- package/dist/types/components/Toggle/ToggleCore.d.ts +23 -0
- package/dist/types/components/Toggle/index.d.ts +4 -0
- package/dist/types/components/Toolbar/ToolbarToggle.d.ts +19 -0
- package/dist/types/components/Toolbar/index.d.ts +2 -0
- package/dist/types/components/Tour/Tour.d.ts +3 -3
- package/dist/types/components/Tree/Tree.d.ts +3 -3
- package/dist/types/components/Tree/TreeItem.d.ts +16 -1
- package/dist/types/components/Tree/types.d.ts +51 -0
- package/dist/types/components/Tree/utils.d.ts +73 -0
- package/dist/types/components/Upload/Upload.d.ts +47 -3
- package/dist/types/components/Upload/UploadCore.d.ts +95 -4
- package/dist/types/components/Upload/UploadList.d.ts +18 -0
- package/dist/types/components/Upload/index.d.ts +1 -0
- package/dist/types/components/Upload/types.d.ts +60 -0
- package/dist/types/components/Upload/xhr-upload.d.ts +20 -0
- package/dist/types/components/VirtualList/VirtualList.d.ts +16 -1
- package/dist/types/components/Watermark/Watermark.d.ts +32 -0
- package/dist/types/components/Watermark/index.d.ts +2 -0
- package/dist/types/form/FormItem.d.ts +33 -8
- package/dist/types/form/FormList.d.ts +113 -0
- package/dist/types/form/index.d.ts +26 -0
- package/dist/types/form/standard-schema.d.ts +30 -0
- package/dist/types/headless/index.d.ts +399 -0
- package/dist/types/hooks/index.d.ts +13 -0
- package/dist/types/hooks/useClickOutside.d.ts +46 -0
- package/dist/types/hooks/useDarkMode.d.ts +40 -0
- package/dist/types/hooks/useFullscreen.d.ts +33 -0
- package/dist/types/hooks/useHotkeys.d.ts +53 -0
- package/dist/types/hooks/useInView.d.ts +32 -0
- package/dist/types/hooks/useLocalStorage.d.ts +33 -0
- package/dist/types/hooks/useMediaQuery.d.ts +3 -0
- package/dist/types/hooks/usePrevious.d.ts +18 -0
- package/dist/types/hooks/useSessionStorage.d.ts +26 -0
- package/dist/types/hooks/useStorageState.d.ts +12 -0
- package/dist/types/index.d.ts +79 -37
- package/dist/types/utils/collision.d.ts +39 -1
- package/dist/types/utils/direction.d.ts +22 -0
- package/dist/types/utils/floating.d.ts +32 -4
- package/dist/types/utils/focus-scope.d.ts +2 -1
- package/dist/types/utils/focus.d.ts +2 -1
- package/dist/types/utils/menuKeyboard.d.ts +19 -4
- package/dist/types/utils/refs.d.ts +16 -0
- package/dist/types/utils/sortable-handle.d.ts +25 -0
- package/dist/types/utils/sortable-shared.d.ts +30 -0
- package/dist/types/utils/sortable.d.ts +36 -0
- package/dist/types/utils/submenu.d.ts +63 -0
- package/dist/types/utils/view-transition.d.ts +28 -0
- package/dist/utils/classnames.js +0 -1
- package/dist/utils/collision.js +37 -26
- package/dist/utils/direction.js +34 -0
- package/dist/utils/floating.js +163 -143
- package/dist/utils/menuKeyboard.js +59 -46
- package/dist/utils/refs.js +9 -0
- package/dist/utils/sortable-handle.js +12 -0
- package/dist/utils/sortable-shared.js +16 -0
- package/dist/utils/sortable.js +47 -0
- package/dist/utils/submenu.js +106 -0
- package/dist/utils/view-transition.js +26 -0
- package/package.json +169 -16
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
English | [简体中文](./README-zh_CN.md)
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/haze-ui)
|
|
8
|
+
[](https://www.npmjs.com/package/haze-ui)
|
|
8
9
|
[](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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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-
|
|
63
|
-
npm i
|
|
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
|
|
68
|
-
`preserveModules` and side-effect-free JS, so bundlers (Next.js,
|
|
69
|
-
webpack, Turbopack, Rollup) tree-shake the unused re-export chains
|
|
70
|
-
never resolve peers you haven't installed: `import { Button } from
|
|
71
|
-
'haze-ui'` works without
|
|
72
|
-
(bare Node ESM importing the barrel, which links the module
|
|
73
|
-
eagerly) must install
|
|
74
|
-
`haze-ui/components/DataTable`
|
|
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
|
-
|
|
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
|
|
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** —
|
|
258
|
-
`haze-ui/registry.json` npm artifact (regenerated by
|
|
259
|
-
on every build), also reachable at
|
|
260
|
-
|
|
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
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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.
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
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)** —
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
panels
|
|
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 };
|