@qijenchen/design-system 0.1.0-beta.10
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 +163 -0
- package/dist/components/Accordion/accordion.d.ts +37 -0
- package/dist/components/Accordion/accordion.d.ts.map +1 -0
- package/dist/components/Accordion/accordion.js +78 -0
- package/dist/components/Accordion/accordion.js.map +1 -0
- package/dist/components/Alert/alert.d.ts +47 -0
- package/dist/components/Alert/alert.d.ts.map +1 -0
- package/dist/components/Alert/alert.js +132 -0
- package/dist/components/Alert/alert.js.map +1 -0
- package/dist/components/AppShell/_demo-helpers.d.ts +49 -0
- package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -0
- package/dist/components/AppShell/app-shell.d.ts +76 -0
- package/dist/components/AppShell/app-shell.d.ts.map +1 -0
- package/dist/components/AppShell/app-shell.js +214 -0
- package/dist/components/AppShell/app-shell.js.map +1 -0
- package/dist/components/AspectRatio/aspect-ratio.d.ts +40 -0
- package/dist/components/AspectRatio/aspect-ratio.d.ts.map +1 -0
- package/dist/components/AspectRatio/aspect-ratio.js +23 -0
- package/dist/components/AspectRatio/aspect-ratio.js.map +1 -0
- package/dist/components/Avatar/avatar.d.ts +85 -0
- package/dist/components/Avatar/avatar.d.ts.map +1 -0
- package/dist/components/Avatar/avatar.js +195 -0
- package/dist/components/Avatar/avatar.js.map +1 -0
- package/dist/components/Badge/badge.d.ts +43 -0
- package/dist/components/Badge/badge.d.ts.map +1 -0
- package/dist/components/Badge/badge.js +69 -0
- package/dist/components/Badge/badge.js.map +1 -0
- package/dist/components/Breadcrumb/breadcrumb.d.ts +163 -0
- package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -0
- package/dist/components/Breadcrumb/breadcrumb.js +300 -0
- package/dist/components/Breadcrumb/breadcrumb.js.map +1 -0
- package/dist/components/BulkActionBar/bulk-action-bar.d.ts +46 -0
- package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -0
- package/dist/components/BulkActionBar/bulk-action-bar.js +78 -0
- package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -0
- package/dist/components/Button/button-group.d.ts +49 -0
- package/dist/components/Button/button-group.d.ts.map +1 -0
- package/dist/components/Button/button-group.js +46 -0
- package/dist/components/Button/button-group.js.map +1 -0
- package/dist/components/Button/button.d.ts +203 -0
- package/dist/components/Button/button.d.ts.map +1 -0
- package/dist/components/Button/button.js +309 -0
- package/dist/components/Button/button.js.map +1 -0
- package/dist/components/Calendar/calendar.d.ts +81 -0
- package/dist/components/Calendar/calendar.d.ts.map +1 -0
- package/dist/components/Calendar/calendar.js +282 -0
- package/dist/components/Calendar/calendar.js.map +1 -0
- package/dist/components/Carousel/carousel.d.ts +61 -0
- package/dist/components/Carousel/carousel.d.ts.map +1 -0
- package/dist/components/Carousel/carousel.js +276 -0
- package/dist/components/Carousel/carousel.js.map +1 -0
- package/dist/components/Chart/chart.d.ts +94 -0
- package/dist/components/Chart/chart.d.ts.map +1 -0
- package/dist/components/Chart/chart.js +233 -0
- package/dist/components/Chart/chart.js.map +1 -0
- package/dist/components/Checkbox/checkbox-group.d.ts +58 -0
- package/dist/components/Checkbox/checkbox-group.d.ts.map +1 -0
- package/dist/components/Checkbox/checkbox-group.js +28 -0
- package/dist/components/Checkbox/checkbox-group.js.map +1 -0
- package/dist/components/Checkbox/checkbox.d.ts +73 -0
- package/dist/components/Checkbox/checkbox.d.ts.map +1 -0
- package/dist/components/Checkbox/checkbox.js +125 -0
- package/dist/components/Checkbox/checkbox.js.map +1 -0
- package/dist/components/Chip/chip.d.ts +54 -0
- package/dist/components/Chip/chip.d.ts.map +1 -0
- package/dist/components/Chip/chip.js +224 -0
- package/dist/components/Chip/chip.js.map +1 -0
- package/dist/components/CircularProgress/circular-progress.d.ts +40 -0
- package/dist/components/CircularProgress/circular-progress.d.ts.map +1 -0
- package/dist/components/CircularProgress/circular-progress.js +118 -0
- package/dist/components/CircularProgress/circular-progress.js.map +1 -0
- package/dist/components/Coachmark/coachmark.d.ts +100 -0
- package/dist/components/Coachmark/coachmark.d.ts.map +1 -0
- package/dist/components/Coachmark/coachmark.js +107 -0
- package/dist/components/Coachmark/coachmark.js.map +1 -0
- package/dist/components/Combobox/combobox.d.ts +150 -0
- package/dist/components/Combobox/combobox.d.ts.map +1 -0
- package/dist/components/Combobox/combobox.js +595 -0
- package/dist/components/Combobox/combobox.js.map +1 -0
- package/dist/components/Command/command.d.ts +106 -0
- package/dist/components/Command/command.d.ts.map +1 -0
- package/dist/components/Command/command.js +123 -0
- package/dist/components/Command/command.js.map +1 -0
- package/dist/components/DataTable/active-editor-controller.d.ts +66 -0
- package/dist/components/DataTable/active-editor-controller.d.ts.map +1 -0
- package/dist/components/DataTable/cell-registry.d.ts +37 -0
- package/dist/components/DataTable/cell-registry.d.ts.map +1 -0
- package/dist/components/DataTable/cell-registry.js +377 -0
- package/dist/components/DataTable/cell-registry.js.map +1 -0
- package/dist/components/DataTable/column-types.d.ts +145 -0
- package/dist/components/DataTable/column-types.d.ts.map +1 -0
- package/dist/components/DataTable/column-types.js +17 -0
- package/dist/components/DataTable/column-types.js.map +1 -0
- package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +49 -0
- package/dist/components/DataTable/data-table-column-visibility-panel.d.ts.map +1 -0
- package/dist/components/DataTable/data-table-filter-panel.d.ts +30 -0
- package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -0
- package/dist/components/DataTable/data-table-interaction-layer.d.ts +78 -0
- package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -0
- package/dist/components/DataTable/data-table-interaction-layer.js +220 -0
- package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -0
- package/dist/components/DataTable/data-table-sort-manager.d.ts +19 -0
- package/dist/components/DataTable/data-table-sort-manager.d.ts.map +1 -0
- package/dist/components/DataTable/data-table.d.ts +181 -0
- package/dist/components/DataTable/data-table.d.ts.map +1 -0
- package/dist/components/DataTable/data-table.js +1851 -0
- package/dist/components/DataTable/data-table.js.map +1 -0
- package/dist/components/DataTable/filter-operators.d.ts +116 -0
- package/dist/components/DataTable/filter-operators.d.ts.map +1 -0
- package/dist/components/DataTable/filter-tree.d.ts +66 -0
- package/dist/components/DataTable/filter-tree.d.ts.map +1 -0
- package/dist/components/DataTable/lib/column-meta.d.ts +49 -0
- package/dist/components/DataTable/lib/column-meta.d.ts.map +1 -0
- package/dist/components/DateGrid/date-grid.d.ts +61 -0
- package/dist/components/DateGrid/date-grid.d.ts.map +1 -0
- package/dist/components/DateGrid/date-grid.js +168 -0
- package/dist/components/DateGrid/date-grid.js.map +1 -0
- package/dist/components/DatePicker/date-picker.d.ts +119 -0
- package/dist/components/DatePicker/date-picker.d.ts.map +1 -0
- package/dist/components/DatePicker/date-picker.js +743 -0
- package/dist/components/DatePicker/date-picker.js.map +1 -0
- package/dist/components/DescriptionList/description-list.d.ts +60 -0
- package/dist/components/DescriptionList/description-list.d.ts.map +1 -0
- package/dist/components/DescriptionList/description-list.js +77 -0
- package/dist/components/DescriptionList/description-list.js.map +1 -0
- package/dist/components/Dialog/dialog.d.ts +54 -0
- package/dist/components/Dialog/dialog.d.ts.map +1 -0
- package/dist/components/Dialog/dialog.js +151 -0
- package/dist/components/Dialog/dialog.js.map +1 -0
- package/dist/components/DropdownMenu/dropdown-menu.d.ts +111 -0
- package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -0
- package/dist/components/DropdownMenu/dropdown-menu.js +288 -0
- package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -0
- package/dist/components/Empty/empty.d.ts +40 -0
- package/dist/components/Empty/empty.d.ts.map +1 -0
- package/dist/components/Empty/empty.js +66 -0
- package/dist/components/Empty/empty.js.map +1 -0
- package/dist/components/Field/field-context.d.ts +77 -0
- package/dist/components/Field/field-context.d.ts.map +1 -0
- package/dist/components/Field/field-context.js +37 -0
- package/dist/components/Field/field-context.js.map +1 -0
- package/dist/components/Field/field-types.d.ts +5 -0
- package/dist/components/Field/field-types.d.ts.map +1 -0
- package/dist/components/Field/field-types.js +13 -0
- package/dist/components/Field/field-types.js.map +1 -0
- package/dist/components/Field/field-wrapper.d.ts +17 -0
- package/dist/components/Field/field-wrapper.d.ts.map +1 -0
- package/dist/components/Field/field-wrapper.js +252 -0
- package/dist/components/Field/field-wrapper.js.map +1 -0
- package/dist/components/Field/field.d.ts +127 -0
- package/dist/components/Field/field.d.ts.map +1 -0
- package/dist/components/Field/field.js +295 -0
- package/dist/components/Field/field.js.map +1 -0
- package/dist/components/FieldControlGroup/field-control-group.d.ts +74 -0
- package/dist/components/FieldControlGroup/field-control-group.d.ts.map +1 -0
- package/dist/components/FieldControlGroup/field-control-group.js +62 -0
- package/dist/components/FieldControlGroup/field-control-group.js.map +1 -0
- package/dist/components/FileItem/file-item.d.ts +44 -0
- package/dist/components/FileItem/file-item.d.ts.map +1 -0
- package/dist/components/FileItem/file-item.js +202 -0
- package/dist/components/FileItem/file-item.js.map +1 -0
- package/dist/components/FileUpload/file-upload.d.ts +97 -0
- package/dist/components/FileUpload/file-upload.d.ts.map +1 -0
- package/dist/components/FileUpload/file-upload.js +231 -0
- package/dist/components/FileUpload/file-upload.js.map +1 -0
- package/dist/components/FileViewer/file-viewer-types.d.ts +73 -0
- package/dist/components/FileViewer/file-viewer-types.d.ts.map +1 -0
- package/dist/components/FileViewer/file-viewer.d.ts +82 -0
- package/dist/components/FileViewer/file-viewer.d.ts.map +1 -0
- package/dist/components/FileViewer/file-viewer.js +752 -0
- package/dist/components/FileViewer/file-viewer.js.map +1 -0
- package/dist/components/FileViewer/image-renderer.d.ts +9 -0
- package/dist/components/FileViewer/image-renderer.d.ts.map +1 -0
- package/dist/components/FileViewer/image-renderer.js +165 -0
- package/dist/components/FileViewer/image-renderer.js.map +1 -0
- package/dist/components/HoverCard/hover-card.d.ts +30 -0
- package/dist/components/HoverCard/hover-card.d.ts.map +1 -0
- package/dist/components/HoverCard/hover-card.js +61 -0
- package/dist/components/HoverCard/hover-card.js.map +1 -0
- package/dist/components/Input/input.d.ts +72 -0
- package/dist/components/Input/input.d.ts.map +1 -0
- package/dist/components/Input/input.js +148 -0
- package/dist/components/Input/input.js.map +1 -0
- package/dist/components/LinkInput/link-input.d.ts +46 -0
- package/dist/components/LinkInput/link-input.d.ts.map +1 -0
- package/dist/components/LinkInput/link-input.js +215 -0
- package/dist/components/LinkInput/link-input.js.map +1 -0
- package/dist/components/Menu/menu-item.d.ts +83 -0
- package/dist/components/Menu/menu-item.d.ts.map +1 -0
- package/dist/components/Menu/menu-item.js +209 -0
- package/dist/components/Menu/menu-item.js.map +1 -0
- package/dist/components/NameCard/name-card.d.ts +85 -0
- package/dist/components/NameCard/name-card.d.ts.map +1 -0
- package/dist/components/NameCard/name-card.js +153 -0
- package/dist/components/NameCard/name-card.js.map +1 -0
- package/dist/components/Notice/notice.d.ts +69 -0
- package/dist/components/Notice/notice.d.ts.map +1 -0
- package/dist/components/Notice/notice.js +121 -0
- package/dist/components/Notice/notice.js.map +1 -0
- package/dist/components/NumberInput/number-input.d.ts +57 -0
- package/dist/components/NumberInput/number-input.d.ts.map +1 -0
- package/dist/components/NumberInput/number-input.js +131 -0
- package/dist/components/NumberInput/number-input.js.map +1 -0
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts +23 -0
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -0
- package/dist/components/OverflowIndicator/overflow-indicator.js +111 -0
- package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -0
- package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts +57 -0
- package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts.map +1 -0
- package/dist/components/PeoplePicker/avatar-stack-overflow.js +35 -0
- package/dist/components/PeoplePicker/avatar-stack-overflow.js.map +1 -0
- package/dist/components/PeoplePicker/people-picker-helpers.d.ts +7 -0
- package/dist/components/PeoplePicker/people-picker-helpers.d.ts.map +1 -0
- package/dist/components/PeoplePicker/people-picker-helpers.js +25 -0
- package/dist/components/PeoplePicker/people-picker-helpers.js.map +1 -0
- package/dist/components/PeoplePicker/people-picker.d.ts +77 -0
- package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -0
- package/dist/components/PeoplePicker/people-picker.js +263 -0
- package/dist/components/PeoplePicker/people-picker.js.map +1 -0
- package/dist/components/PeoplePicker/person-display.d.ts +66 -0
- package/dist/components/PeoplePicker/person-display.d.ts.map +1 -0
- package/dist/components/PeoplePicker/person-display.js +203 -0
- package/dist/components/PeoplePicker/person-display.js.map +1 -0
- package/dist/components/Popover/popover.d.ts +50 -0
- package/dist/components/Popover/popover.d.ts.map +1 -0
- package/dist/components/Popover/popover.js +113 -0
- package/dist/components/Popover/popover.js.map +1 -0
- package/dist/components/ProgressBar/progress-bar.d.ts +37 -0
- package/dist/components/ProgressBar/progress-bar.d.ts.map +1 -0
- package/dist/components/ProgressBar/progress-bar.js +86 -0
- package/dist/components/ProgressBar/progress-bar.js.map +1 -0
- package/dist/components/RadioGroup/radio-group.d.ts +78 -0
- package/dist/components/RadioGroup/radio-group.d.ts.map +1 -0
- package/dist/components/RadioGroup/radio-group.js +153 -0
- package/dist/components/RadioGroup/radio-group.js.map +1 -0
- package/dist/components/Rating/rating.d.ts +46 -0
- package/dist/components/Rating/rating.d.ts.map +1 -0
- package/dist/components/Rating/rating.js +179 -0
- package/dist/components/Rating/rating.js.map +1 -0
- package/dist/components/ScrollArea/scroll-area.d.ts +45 -0
- package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -0
- package/dist/components/ScrollArea/scroll-area.js +65 -0
- package/dist/components/ScrollArea/scroll-area.js.map +1 -0
- package/dist/components/SegmentedControl/segmented-control.d.ts +102 -0
- package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -0
- package/dist/components/SegmentedControl/segmented-control.js +171 -0
- package/dist/components/SegmentedControl/segmented-control.js.map +1 -0
- package/dist/components/Select/select.d.ts +102 -0
- package/dist/components/Select/select.d.ts.map +1 -0
- package/dist/components/Select/select.js +435 -0
- package/dist/components/Select/select.js.map +1 -0
- package/dist/components/SelectMenu/select-menu.d.ts +103 -0
- package/dist/components/SelectMenu/select-menu.d.ts.map +1 -0
- package/dist/components/SelectMenu/select-menu.js +239 -0
- package/dist/components/SelectMenu/select-menu.js.map +1 -0
- package/dist/components/SelectionControl/selection-item.d.ts +69 -0
- package/dist/components/SelectionControl/selection-item.d.ts.map +1 -0
- package/dist/components/SelectionControl/selection-item.js +142 -0
- package/dist/components/SelectionControl/selection-item.js.map +1 -0
- package/dist/components/Separator/separator.d.ts +17 -0
- package/dist/components/Separator/separator.d.ts.map +1 -0
- package/dist/components/Separator/separator.js +39 -0
- package/dist/components/Separator/separator.js.map +1 -0
- package/dist/components/Sheet/sheet.d.ts +56 -0
- package/dist/components/Sheet/sheet.d.ts.map +1 -0
- package/dist/components/Sheet/sheet.js +145 -0
- package/dist/components/Sheet/sheet.js.map +1 -0
- package/dist/components/Sidebar/sidebar.d.ts +195 -0
- package/dist/components/Sidebar/sidebar.d.ts.map +1 -0
- package/dist/components/Sidebar/sidebar.js +826 -0
- package/dist/components/Sidebar/sidebar.js.map +1 -0
- package/dist/components/Skeleton/skeleton.d.ts +16 -0
- package/dist/components/Skeleton/skeleton.d.ts.map +1 -0
- package/dist/components/Skeleton/skeleton.js +30 -0
- package/dist/components/Skeleton/skeleton.js.map +1 -0
- package/dist/components/Slider/slider.d.ts +48 -0
- package/dist/components/Slider/slider.d.ts.map +1 -0
- package/dist/components/Slider/slider.js +108 -0
- package/dist/components/Slider/slider.js.map +1 -0
- package/dist/components/Steps/steps.d.ts +71 -0
- package/dist/components/Steps/steps.d.ts.map +1 -0
- package/dist/components/Steps/steps.js +583 -0
- package/dist/components/Steps/steps.js.map +1 -0
- package/dist/components/Switch/switch.d.ts +112 -0
- package/dist/components/Switch/switch.d.ts.map +1 -0
- package/dist/components/Switch/switch.js +179 -0
- package/dist/components/Switch/switch.js.map +1 -0
- package/dist/components/Tabs/tabs.d.ts +104 -0
- package/dist/components/Tabs/tabs.d.ts.map +1 -0
- package/dist/components/Tabs/tabs.js +316 -0
- package/dist/components/Tabs/tabs.js.map +1 -0
- package/dist/components/Tag/tag.d.ts +86 -0
- package/dist/components/Tag/tag.d.ts.map +1 -0
- package/dist/components/Tag/tag.js +172 -0
- package/dist/components/Tag/tag.js.map +1 -0
- package/dist/components/Textarea/textarea.d.ts +74 -0
- package/dist/components/Textarea/textarea.d.ts.map +1 -0
- package/dist/components/Textarea/textarea.js +224 -0
- package/dist/components/Textarea/textarea.js.map +1 -0
- package/dist/components/TimePicker/time-columns.d.ts +46 -0
- package/dist/components/TimePicker/time-columns.d.ts.map +1 -0
- package/dist/components/TimePicker/time-columns.js +173 -0
- package/dist/components/TimePicker/time-columns.js.map +1 -0
- package/dist/components/TimePicker/time-picker.d.ts +94 -0
- package/dist/components/TimePicker/time-picker.d.ts.map +1 -0
- package/dist/components/TimePicker/time-picker.js +253 -0
- package/dist/components/TimePicker/time-picker.js.map +1 -0
- package/dist/components/Toast/toast.d.ts +61 -0
- package/dist/components/Toast/toast.d.ts.map +1 -0
- package/dist/components/Toast/toast.js +76 -0
- package/dist/components/Toast/toast.js.map +1 -0
- package/dist/components/Tooltip/tooltip.d.ts +20 -0
- package/dist/components/Tooltip/tooltip.d.ts.map +1 -0
- package/dist/components/Tooltip/tooltip.js +53 -0
- package/dist/components/Tooltip/tooltip.js.map +1 -0
- package/dist/components/TreeView/tree-view.d.ts +166 -0
- package/dist/components/TreeView/tree-view.d.ts.map +1 -0
- package/dist/components/TreeView/tree-view.js +617 -0
- package/dist/components/TreeView/tree-view.js.map +1 -0
- package/dist/hooks/use-controllable.d.ts +16 -0
- package/dist/hooks/use-controllable.d.ts.map +1 -0
- package/dist/hooks/use-controllable.js +26 -0
- package/dist/hooks/use-controllable.js.map +1 -0
- package/dist/hooks/use-is-narrow-viewport.d.ts +2 -0
- package/dist/hooks/use-is-narrow-viewport.d.ts.map +1 -0
- package/dist/hooks/use-is-narrow-viewport.js +19 -0
- package/dist/hooks/use-is-narrow-viewport.js.map +1 -0
- package/dist/hooks/use-is-touch-device.d.ts +8 -0
- package/dist/hooks/use-is-touch-device.d.ts.map +1 -0
- package/dist/hooks/use-is-touch-device.js +16 -0
- package/dist/hooks/use-is-touch-device.js.map +1 -0
- package/dist/hooks/use-overflow-items.d.ts +124 -0
- package/dist/hooks/use-overflow-items.d.ts.map +1 -0
- package/dist/hooks/use-overflow-items.js +97 -0
- package/dist/hooks/use-overflow-items.js.map +1 -0
- package/dist/index.d.ts +74 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +371 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/drag-visual.d.ts +158 -0
- package/dist/lib/drag-visual.d.ts.map +1 -0
- package/dist/lib/drag-visual.js +96 -0
- package/dist/lib/drag-visual.js.map +1 -0
- package/dist/lib/i18n/i18n-context.d.ts +105 -0
- package/dist/lib/i18n/i18n-context.d.ts.map +1 -0
- package/dist/lib/multi-select-ordering.d.ts +54 -0
- package/dist/lib/multi-select-ordering.d.ts.map +1 -0
- package/dist/lib/multi-select-ordering.js +13 -0
- package/dist/lib/multi-select-ordering.js.map +1 -0
- package/dist/lib/utils.d.ts +12 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +79 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/patterns/element-anatomy/item-anatomy.d.ts +370 -0
- package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -0
- package/dist/patterns/element-anatomy/item-anatomy.js +272 -0
- package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -0
- package/dist/patterns/header-canonical/chrome-header.d.ts +80 -0
- package/dist/patterns/header-canonical/chrome-header.d.ts.map +1 -0
- package/dist/patterns/header-canonical/chrome-header.js +75 -0
- package/dist/patterns/header-canonical/chrome-header.js.map +1 -0
- package/dist/patterns/horizontal-overflow/horizontal-overflow.d.ts +101 -0
- package/dist/patterns/horizontal-overflow/horizontal-overflow.d.ts.map +1 -0
- package/dist/patterns/horizontal-overflow/horizontal-overflow.js +105 -0
- package/dist/patterns/horizontal-overflow/horizontal-overflow.js.map +1 -0
- package/dist/patterns/overlay-surface/overlay-surface.d.ts +28 -0
- package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -0
- package/dist/patterns/overlay-surface/overlay-surface.js +85 -0
- package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -0
- package/dist/patterns/resize-handle/resize-handle.d.ts +102 -0
- package/dist/patterns/resize-handle/resize-handle.d.ts.map +1 -0
- package/dist/patterns/resize-handle/resize-handle.js +74 -0
- package/dist/patterns/resize-handle/resize-handle.js.map +1 -0
- package/dist/react-day-picker.css +457 -0
- package/dist/stories-helpers/anatomy/anatomy-utils.d.ts +40 -0
- package/dist/stories-helpers/anatomy/anatomy-utils.d.ts.map +1 -0
- package/dist/tokens/elevation/overlay-geometry.d.ts +12 -0
- package/dist/tokens/elevation/overlay-geometry.d.ts.map +1 -0
- package/dist/tokens/elevation/overlay-geometry.js +7 -0
- package/dist/tokens/elevation/overlay-geometry.js.map +1 -0
- package/dist/tokens/motion/motion.d.ts +15 -0
- package/dist/tokens/motion/motion.d.ts.map +1 -0
- package/dist/tokens/motion/motion.js +9 -0
- package/dist/tokens/motion/motion.js.map +1 -0
- package/dist/tokens/uiSize/icon-size.d.ts +53 -0
- package/dist/tokens/uiSize/icon-size.d.ts.map +1 -0
- package/package.json +92 -0
- package/src/README.md +32 -0
- package/src/components/Accordion/accordion.tsx +104 -0
- package/src/components/Alert/alert.tsx +188 -0
- package/src/components/AppShell/_demo-helpers.tsx +198 -0
- package/src/components/AppShell/app-shell.tsx +364 -0
- package/src/components/AspectRatio/aspect-ratio.tsx +58 -0
- package/src/components/Avatar/avatar.tsx +368 -0
- package/src/components/Badge/badge.tsx +104 -0
- package/src/components/Breadcrumb/breadcrumb.tsx +619 -0
- package/src/components/BulkActionBar/bulk-action-bar.tsx +156 -0
- package/src/components/Button/button-group.tsx +96 -0
- package/src/components/Button/button.tsx +539 -0
- package/src/components/Calendar/calendar.tsx +411 -0
- package/src/components/Carousel/carousel.tsx +371 -0
- package/src/components/Chart/chart.tsx +376 -0
- package/src/components/Checkbox/checkbox-group.tsx +94 -0
- package/src/components/Checkbox/checkbox.tsx +237 -0
- package/src/components/Chip/chip.tsx +359 -0
- package/src/components/CircularProgress/circular-progress.tsx +204 -0
- package/src/components/Coachmark/coachmark.tsx +255 -0
- package/src/components/Combobox/combobox.tsx +826 -0
- package/src/components/Command/command.tsx +187 -0
- package/src/components/DataTable/active-editor-controller.ts +72 -0
- package/src/components/DataTable/cell-registry.tsx +520 -0
- package/src/components/DataTable/column-types.ts +180 -0
- package/src/components/DataTable/data-table-column-visibility-panel.tsx +261 -0
- package/src/components/DataTable/data-table-filter-panel.tsx +813 -0
- package/src/components/DataTable/data-table-interaction-layer.tsx +483 -0
- package/src/components/DataTable/data-table-sort-manager.tsx +210 -0
- package/src/components/DataTable/data-table.css +165 -0
- package/src/components/DataTable/data-table.tsx +2924 -0
- package/src/components/DataTable/filter-operators.ts +225 -0
- package/src/components/DataTable/filter-tree.ts +313 -0
- package/src/components/DataTable/lib/column-meta.ts +79 -0
- package/src/components/DateGrid/date-grid.tsx +209 -0
- package/src/components/DatePicker/date-picker.tsx +1114 -0
- package/src/components/DescriptionList/description-list.tsx +141 -0
- package/src/components/Dialog/dialog.tsx +267 -0
- package/src/components/DropdownMenu/dropdown-menu.tsx +475 -0
- package/src/components/Empty/empty.tsx +108 -0
- package/src/components/Field/field-context.ts +136 -0
- package/src/components/Field/field-types.ts +52 -0
- package/src/components/Field/field-wrapper.tsx +348 -0
- package/src/components/Field/field.tsx +535 -0
- package/src/components/FieldControlGroup/field-control-group.tsx +136 -0
- package/src/components/FileItem/file-item.tsx +322 -0
- package/src/components/FileUpload/file-upload.tsx +326 -0
- package/src/components/FileViewer/file-viewer-types.ts +76 -0
- package/src/components/FileViewer/file-viewer.tsx +1065 -0
- package/src/components/FileViewer/image-renderer.tsx +256 -0
- package/src/components/HoverCard/hover-card.tsx +79 -0
- package/src/components/Input/input.tsx +233 -0
- package/src/components/LinkInput/link-input.tsx +304 -0
- package/src/components/Menu/menu-item.tsx +334 -0
- package/src/components/NameCard/name-card.tsx +319 -0
- package/src/components/Notice/notice.tsx +196 -0
- package/src/components/NumberInput/number-input.tsx +203 -0
- package/src/components/OverflowIndicator/overflow-indicator.tsx +156 -0
- package/src/components/PeoplePicker/avatar-stack-overflow.ts +100 -0
- package/src/components/PeoplePicker/people-picker-helpers.ts +76 -0
- package/src/components/PeoplePicker/people-picker.tsx +455 -0
- package/src/components/PeoplePicker/person-display.tsx +358 -0
- package/src/components/Popover/popover.tsx +183 -0
- package/src/components/ProgressBar/progress-bar.tsx +157 -0
- package/src/components/README.md +58 -0
- package/src/components/RadioGroup/radio-group.tsx +261 -0
- package/src/components/Rating/rating.tsx +295 -0
- package/src/components/ScrollArea/scroll-area.tsx +110 -0
- package/src/components/SegmentedControl/segmented-control.tsx +304 -0
- package/src/components/Select/select.tsx +658 -0
- package/src/components/SelectMenu/select-menu.tsx +430 -0
- package/src/components/SelectionControl/selection-item.tsx +261 -0
- package/src/components/Separator/separator.tsx +48 -0
- package/src/components/Sheet/sheet.tsx +240 -0
- package/src/components/Sidebar/sidebar.tsx +1280 -0
- package/src/components/Skeleton/skeleton.tsx +35 -0
- package/src/components/Slider/slider.tsx +158 -0
- package/src/components/Steps/steps.tsx +850 -0
- package/src/components/Switch/switch.tsx +285 -0
- package/src/components/Tabs/tabs.tsx +515 -0
- package/src/components/Tag/tag.tsx +246 -0
- package/src/components/Textarea/textarea.tsx +280 -0
- package/src/components/TimePicker/time-columns.tsx +260 -0
- package/src/components/TimePicker/time-picker.tsx +419 -0
- package/src/components/Toast/toast.tsx +129 -0
- package/src/components/Tooltip/tooltip.tsx +68 -0
- package/src/components/TreeView/tree-view.tsx +1031 -0
- package/src/hooks/use-controllable.ts +40 -0
- package/src/hooks/use-is-narrow-viewport.ts +19 -0
- package/src/hooks/use-is-touch-device.ts +21 -0
- package/src/hooks/use-overflow-items.ts +256 -0
- package/src/index.ts +85 -0
- package/src/lib/README.md +82 -0
- package/src/lib/drag-visual.ts +272 -0
- package/src/lib/i18n/README.md +60 -0
- package/src/lib/i18n/i18n-context.tsx +129 -0
- package/src/lib/multi-select-ordering.ts +61 -0
- package/src/lib/utils.ts +93 -0
- package/src/patterns/README.md +67 -0
- package/src/patterns/element-anatomy/item-anatomy.tsx +744 -0
- package/src/patterns/header-canonical/chrome-header.tsx +175 -0
- package/src/patterns/header-canonical/header-canonical.css +27 -0
- package/src/patterns/horizontal-overflow/horizontal-overflow.tsx +217 -0
- package/src/patterns/overlay-surface/overlay-surface.tsx +191 -0
- package/src/patterns/resize-handle/resize-handle.tsx +188 -0
- package/src/stories-helpers/anatomy/anatomy-utils.tsx +64 -0
- package/src/styles/preset.css +31 -0
- package/src/styles/tokens.css +35 -0
- package/src/tokens/README.md +53 -0
- package/src/tokens/color/primitives.css +429 -0
- package/src/tokens/color/semantic.css +539 -0
- package/src/tokens/elevation/overlay-geometry.ts +13 -0
- package/src/tokens/layoutSpace/layoutSpace.css +36 -0
- package/src/tokens/motion/motion.css +30 -0
- package/src/tokens/motion/motion.ts +17 -0
- package/src/tokens/opacity/opacity.css +23 -0
- package/src/tokens/radius/radius.css +19 -0
- package/src/tokens/typography/typography.css +118 -0
- package/src/tokens/uiSize/icon-size.ts +52 -0
- package/src/tokens/uiSize/uiSize.css +125 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { LucideIcon } from 'lucide-react';
|
|
3
|
+
import type { FieldMode, FieldVariant } from '../../components/Field/field-types';
|
|
4
|
+
import { type TimeParts, type TimeStep } from '../../components/TimePicker/time-columns';
|
|
5
|
+
/**
|
|
6
|
+
* TimePicker — 單一時間(時/分/秒)輸入與顯示元件
|
|
7
|
+
*
|
|
8
|
+
* ── 定位(同 DatePicker 家族)──
|
|
9
|
+
* Value 以 ISO time string 儲存("HH:mm" 或 "HH:mm:ss"),local-time 語義(不帶時區)。
|
|
10
|
+
* Edit 用本 DS 自建 time column panel + Popover 呈現,視覺與 DatePicker 一致。
|
|
11
|
+
* Display 用 Intl.DateTimeFormat 格式化(跨 locale / 12h-24h 統一經過此 API)。
|
|
12
|
+
*
|
|
13
|
+
* ── Layout Family ──
|
|
14
|
+
* CLAUDE.md 4-Family Model Family 4(Field control layout)消費者。結構繼承
|
|
15
|
+
* `fieldWrapperStyles + [<editable>] [endIcon=Clock]`,視覺對齊 DatePicker(同
|
|
16
|
+
* 「點擊觸發浮層」role:indicator 在 suffix slot,對齊 Material `endAdornment` /
|
|
17
|
+
* Ant DatePicker / Polaris Picker 共識)。
|
|
18
|
+
*
|
|
19
|
+
* ── 實作基礎 ──
|
|
20
|
+
* Trigger:`<button>` + `fieldWrapperStyles`(視覺仍是 Input wrapper,改為可點擊觸發浮層)
|
|
21
|
+
* Popup:`Popover`(消費 overlay-surface pattern)
|
|
22
|
+
* Panel 主體:自建 column picker(三欄 scrollable list),不引入第三方 time library
|
|
23
|
+
*
|
|
24
|
+
* ── 共用規則 ──
|
|
25
|
+
* Mode / size / disabled / error 等詳見 `../Field/field-controls.spec.md`。
|
|
26
|
+
*/
|
|
27
|
+
export interface TimeFormatOptions {
|
|
28
|
+
/** Intl.DateTimeFormat options(預設 { hour: '2-digit', minute: '2-digit', hour12: false }) */
|
|
29
|
+
formatOptions?: Intl.DateTimeFormatOptions;
|
|
30
|
+
/** locale(預設 'en-US') */
|
|
31
|
+
locale?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface DisabledTimeResult {
|
|
34
|
+
disabledHours?: number[];
|
|
35
|
+
disabledMinutes?: number[];
|
|
36
|
+
disabledSeconds?: number[];
|
|
37
|
+
}
|
|
38
|
+
export interface TimePickerProps extends TimeFormatOptions, Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'placeholder'> {
|
|
39
|
+
mode?: FieldMode;
|
|
40
|
+
/** Field chrome variant. Default = context.variant ?? 'default'. Per-prop override. */
|
|
41
|
+
variant?: FieldVariant;
|
|
42
|
+
error?: boolean;
|
|
43
|
+
size?: 'sm' | 'md' | 'lg';
|
|
44
|
+
/** ISO time string("HH:mm" 或 "HH:mm:ss") */
|
|
45
|
+
value?: string | null;
|
|
46
|
+
onChange?: (value: string) => void;
|
|
47
|
+
placeholder?: string;
|
|
48
|
+
className?: string;
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
/** 允許清空已選值 */
|
|
51
|
+
clearable?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* 是否顯示秒欄(三欄 picker)。預設 false(兩欄:時/分)。
|
|
54
|
+
* format 自動對應:false → "HH:mm",true → "HH:mm:ss"。
|
|
55
|
+
*/
|
|
56
|
+
showSeconds?: boolean;
|
|
57
|
+
/** 分鐘步進(會議常用 15)。預設 1 */
|
|
58
|
+
minuteStep?: TimeStep;
|
|
59
|
+
/** 秒步進。預設 1。僅 showSeconds=true 有效 */
|
|
60
|
+
secondStep?: TimeStep;
|
|
61
|
+
/** 動態 disabled 某些時/分/秒(基於已選其他欄位)。 */
|
|
62
|
+
disabledTime?: (parts: TimeParts) => DisabledTimeResult;
|
|
63
|
+
/**
|
|
64
|
+
* Suffix indicator(2026-05-05 v9 canonical fix):「點擊觸發浮層」indicator 一律 suffix
|
|
65
|
+
* (對齊 DatePicker calendar / Material endAdornment)。預設 Clock,傳 null 可關閉。
|
|
66
|
+
*/
|
|
67
|
+
endIcon?: LucideIcon | null;
|
|
68
|
+
/**
|
|
69
|
+
* Display 是否渲 endIcon + Field naked wrapper(D-path opt-in,2026-05-08)
|
|
70
|
+
* — DataTable cell display↔edit 像素級對齊用。預設 false(裸 span,backward compat)。
|
|
71
|
+
* 設 true 時 display 也走 fieldWrapperStyles(naked variant)+ ItemSuffix Clock,
|
|
72
|
+
* 與 edit 同 DOM 結構,消除 Layer-B padding mismatch。
|
|
73
|
+
*/
|
|
74
|
+
showDisplayEndIcon?: boolean;
|
|
75
|
+
/** Initial open state(uncontrolled)— DataTable cell-as-input 1-step open canonical */
|
|
76
|
+
defaultOpen?: boolean;
|
|
77
|
+
/** open state 變更 callback。DataTable cell-as-input 用:open=false → cell exit edit */
|
|
78
|
+
onOpenChange?: (open: boolean) => void;
|
|
79
|
+
}
|
|
80
|
+
declare const TimePicker: React.ForwardRefExoticComponent<TimePickerProps & React.RefAttributes<HTMLDivElement>>;
|
|
81
|
+
export declare const timePickerMeta: {
|
|
82
|
+
readonly component: "TimePicker";
|
|
83
|
+
readonly family: 4;
|
|
84
|
+
readonly variants: {};
|
|
85
|
+
readonly sizes: {};
|
|
86
|
+
readonly states: readonly ["default", "hover", "active", "focus-visible", "disabled"];
|
|
87
|
+
readonly tokens: {
|
|
88
|
+
readonly bg: readonly ["bg-neutral-hover", "bg-primary", "bg-transparent"];
|
|
89
|
+
readonly fg: readonly ["text-fg-disabled", "text-fg-muted", "text-foreground"];
|
|
90
|
+
readonly ring: readonly [];
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
export { TimePicker };
|
|
94
|
+
//# sourceMappingURL=time-picker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-picker.d.ts","sourceRoot":"","sources":["../../../src/components/TimePicker/time-picker.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,8CAA8C,CAAA;AAW3F,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,QAAQ,EAEd,MAAM,oDAAoD,CAAA;AAG3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AASH,MAAM,WAAW,iBAAiB;IAChC,4FAA4F;IAC5F,aAAa,CAAC,EAAE,IAAI,CAAC,qBAAqB,CAAA;IAC1C,yBAAyB;IACzB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAsBD,MAAM,WAAW,kBAAkB;IACjC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAC3B;AAID,MAAM,WAAW,eACf,SAAQ,iBAAiB,EACvB,IAAI,CACF,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EACpC,UAAU,GAAG,aAAa,CAC3B;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,uFAAuF;IACvF,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IACzB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,cAAc;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,yBAAyB;IACzB,UAAU,CAAC,EAAE,QAAQ,CAAA;IACrB,qCAAqC;IACrC,UAAU,CAAC,EAAE,QAAQ,CAAA;IACrB,qCAAqC;IACrC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,kBAAkB,CAAA;IACvD;;;OAGG;IACH,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;IAC3B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,sFAAsF;IACtF,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,mFAAmF;IACnF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CACvC;AAGD,QAAA,MAAM,UAAU,wFAgQf,CAAA;AAKD,eAAO,MAAM,cAAc;;;;;;;;;;;CAejB,CAAA;AAEV,OAAO,EAAE,UAAU,EAAE,CAAA"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Clock, X } from "lucide-react";
|
|
4
|
+
import { cn } from "../../lib/utils.js";
|
|
5
|
+
import { EMPTY_DISPLAY, fieldWrapperStyles, fieldDisplayTextClass, bareInputStyles } from "../Field/field-wrapper.js";
|
|
6
|
+
import { ItemSuffix, ICON_SIZE, ItemInlineAction } from "../../patterns/element-anatomy/item-anatomy.js";
|
|
7
|
+
import { Popover, PopoverTrigger, PopoverContent } from "../Popover/popover.js";
|
|
8
|
+
import { useFieldContext } from "../Field/field-context.js";
|
|
9
|
+
import { Button } from "../Button/button.js";
|
|
10
|
+
import { isoToTimeParts, TimeColumns, timePartsToString } from "./time-columns.js";
|
|
11
|
+
function formatTime(iso, options = {}) {
|
|
12
|
+
const parts = isoToTimeParts(iso);
|
|
13
|
+
if (!parts) return iso;
|
|
14
|
+
const {
|
|
15
|
+
formatOptions = { hour: "2-digit", minute: "2-digit", hour12: false },
|
|
16
|
+
locale = "en-US"
|
|
17
|
+
} = options;
|
|
18
|
+
const d = /* @__PURE__ */ new Date();
|
|
19
|
+
d.setHours(parts.hours, parts.minutes, parts.seconds, 0);
|
|
20
|
+
return new Intl.DateTimeFormat(locale, formatOptions).format(d);
|
|
21
|
+
}
|
|
22
|
+
const TimePicker = React.forwardRef(
|
|
23
|
+
({
|
|
24
|
+
mode = "edit",
|
|
25
|
+
variant: variantProp,
|
|
26
|
+
error: errorProp = false,
|
|
27
|
+
size = "md",
|
|
28
|
+
value,
|
|
29
|
+
onChange,
|
|
30
|
+
placeholder,
|
|
31
|
+
className,
|
|
32
|
+
disabled: disabledProp,
|
|
33
|
+
clearable = false,
|
|
34
|
+
showSeconds = false,
|
|
35
|
+
minuteStep = 1,
|
|
36
|
+
secondStep = 1,
|
|
37
|
+
disabledTime,
|
|
38
|
+
endIcon,
|
|
39
|
+
showDisplayEndIcon = false,
|
|
40
|
+
formatOptions,
|
|
41
|
+
locale,
|
|
42
|
+
defaultOpen = false,
|
|
43
|
+
onOpenChange,
|
|
44
|
+
id: idProp,
|
|
45
|
+
"aria-describedby": ariaDescribedByProp,
|
|
46
|
+
"aria-errormessage": ariaErrorMessageProp,
|
|
47
|
+
...props
|
|
48
|
+
}, ref) => {
|
|
49
|
+
const fieldCtx = useFieldContext();
|
|
50
|
+
const error = errorProp || ((fieldCtx == null ? void 0 : fieldCtx.invalid) ?? false);
|
|
51
|
+
const disabled = disabledProp ?? (fieldCtx == null ? void 0 : fieldCtx.disabled);
|
|
52
|
+
const resolvedMode = disabled ? "disabled" : mode;
|
|
53
|
+
const variant = variantProp ?? (fieldCtx == null ? void 0 : fieldCtx.variant) ?? "default";
|
|
54
|
+
const isEditable = resolvedMode === "edit";
|
|
55
|
+
const iconSize = ICON_SIZE[size];
|
|
56
|
+
const EndIconCmp = endIcon === null ? null : endIcon ?? Clock;
|
|
57
|
+
const defaultPlaceholder = showSeconds ? "HH:MM:SS" : "HH:MM";
|
|
58
|
+
const resolvedPlaceholder = placeholder ?? defaultPlaceholder;
|
|
59
|
+
const showClear = clearable && !!value && isEditable;
|
|
60
|
+
const [open, setOpenState] = React.useState(defaultOpen);
|
|
61
|
+
const setOpen = React.useCallback((next) => {
|
|
62
|
+
setOpenState(next);
|
|
63
|
+
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
64
|
+
}, [onOpenChange]);
|
|
65
|
+
const currentParts = React.useMemo(() => isoToTimeParts(value), [value]);
|
|
66
|
+
const [draft, setDraft] = React.useState(
|
|
67
|
+
() => currentParts ?? { hours: 0, minutes: 0, seconds: 0 }
|
|
68
|
+
);
|
|
69
|
+
React.useEffect(() => {
|
|
70
|
+
if (open) {
|
|
71
|
+
setDraft(currentParts ?? { hours: 0, minutes: 0, seconds: 0 });
|
|
72
|
+
}
|
|
73
|
+
}, [open, currentParts]);
|
|
74
|
+
const disabledForColumns = React.useMemo(() => {
|
|
75
|
+
if (!disabledTime) return void 0;
|
|
76
|
+
const res = disabledTime(draft);
|
|
77
|
+
return {
|
|
78
|
+
hours: res.disabledHours,
|
|
79
|
+
minutes: res.disabledMinutes,
|
|
80
|
+
seconds: res.disabledSeconds
|
|
81
|
+
};
|
|
82
|
+
}, [disabledTime, draft]);
|
|
83
|
+
const commitDraft = (next) => {
|
|
84
|
+
setDraft(next);
|
|
85
|
+
onChange == null ? void 0 : onChange(timePartsToString(next, showSeconds));
|
|
86
|
+
};
|
|
87
|
+
const handleNow = () => {
|
|
88
|
+
const now = /* @__PURE__ */ new Date();
|
|
89
|
+
const m = Math.round(now.getMinutes() / minuteStep) * minuteStep;
|
|
90
|
+
const s = showSeconds ? Math.round(now.getSeconds() / secondStep) * secondStep : 0;
|
|
91
|
+
const next = {
|
|
92
|
+
hours: now.getHours(),
|
|
93
|
+
minutes: Math.min(m, 59),
|
|
94
|
+
seconds: Math.min(s, 59)
|
|
95
|
+
};
|
|
96
|
+
commitDraft(next);
|
|
97
|
+
setOpen(false);
|
|
98
|
+
};
|
|
99
|
+
if (resolvedMode === "display") {
|
|
100
|
+
if (!showDisplayEndIcon) {
|
|
101
|
+
if (!value) return /* @__PURE__ */ jsx("span", { className: cn(fieldDisplayTextClass(size), "text-fg-muted", className), children: EMPTY_DISPLAY });
|
|
102
|
+
return /* @__PURE__ */ jsx("span", { className: cn(fieldDisplayTextClass(size), "truncate", className), children: formatTime(value, { formatOptions, locale }) });
|
|
103
|
+
}
|
|
104
|
+
return /* @__PURE__ */ jsxs(
|
|
105
|
+
"div",
|
|
106
|
+
{
|
|
107
|
+
className: cn(fieldWrapperStyles({ mode: "display", variant, size }), className),
|
|
108
|
+
"data-field-mode": "display",
|
|
109
|
+
children: [
|
|
110
|
+
/* @__PURE__ */ jsx("span", { className: cn(bareInputStyles, "flex-1 min-w-0 truncate", !value && "text-fg-muted"), children: value ? formatTime(value, { formatOptions, locale }) : EMPTY_DISPLAY }),
|
|
111
|
+
EndIconCmp && /* @__PURE__ */ jsx(ItemSuffix, { className: "pointer-events-none", children: /* @__PURE__ */ jsx(EndIconCmp, { size: iconSize, className: "text-fg-muted", "aria-hidden": true }) })
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
if (!isEditable) {
|
|
117
|
+
return /* @__PURE__ */ jsxs(
|
|
118
|
+
"div",
|
|
119
|
+
{
|
|
120
|
+
className: cn(fieldWrapperStyles({ mode: resolvedMode, variant, size }), className),
|
|
121
|
+
"data-field-mode": resolvedMode,
|
|
122
|
+
...props,
|
|
123
|
+
children: [
|
|
124
|
+
/* @__PURE__ */ jsx(
|
|
125
|
+
"span",
|
|
126
|
+
{
|
|
127
|
+
className: cn(
|
|
128
|
+
"flex-1 min-w-0",
|
|
129
|
+
resolvedMode === "disabled" && "text-fg-disabled"
|
|
130
|
+
),
|
|
131
|
+
children: value ? formatTime(value, { formatOptions, locale }) : /* @__PURE__ */ jsx("span", { className: "text-fg-muted", children: EMPTY_DISPLAY })
|
|
132
|
+
}
|
|
133
|
+
),
|
|
134
|
+
EndIconCmp && /* @__PURE__ */ jsx(ItemSuffix, { className: "pointer-events-none", children: /* @__PURE__ */ jsx(
|
|
135
|
+
EndIconCmp,
|
|
136
|
+
{
|
|
137
|
+
size: iconSize,
|
|
138
|
+
className: resolvedMode === "disabled" ? "text-fg-disabled" : "text-fg-muted",
|
|
139
|
+
"aria-hidden": true
|
|
140
|
+
}
|
|
141
|
+
) })
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
const displayText = value ? formatTime(value, { formatOptions, locale }) : /* @__PURE__ */ jsx("span", { className: "text-fg-muted", children: resolvedPlaceholder });
|
|
147
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
|
|
148
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
149
|
+
"div",
|
|
150
|
+
{
|
|
151
|
+
ref,
|
|
152
|
+
id: idProp ?? (fieldCtx == null ? void 0 : fieldCtx.id),
|
|
153
|
+
role: "combobox",
|
|
154
|
+
tabIndex: disabled ? -1 : 0,
|
|
155
|
+
"aria-disabled": disabled || void 0,
|
|
156
|
+
"aria-labelledby": fieldCtx == null ? void 0 : fieldCtx.labelId,
|
|
157
|
+
"aria-invalid": error || void 0,
|
|
158
|
+
"aria-required": (fieldCtx == null ? void 0 : fieldCtx.required) || void 0,
|
|
159
|
+
"aria-describedby": ariaDescribedByProp ?? (fieldCtx == null ? void 0 : fieldCtx.descriptionId),
|
|
160
|
+
"aria-errormessage": ariaErrorMessageProp ?? (error ? fieldCtx == null ? void 0 : fieldCtx.errorId : void 0),
|
|
161
|
+
"aria-haspopup": "dialog",
|
|
162
|
+
"aria-expanded": open,
|
|
163
|
+
"data-field-mode": "edit",
|
|
164
|
+
"data-error": error ? "" : void 0,
|
|
165
|
+
className: cn(
|
|
166
|
+
fieldWrapperStyles({ mode: "edit", variant, size }),
|
|
167
|
+
"text-left cursor-pointer",
|
|
168
|
+
"focus-visible:outline-none",
|
|
169
|
+
error && [
|
|
170
|
+
"border-error hover:border-error-hover",
|
|
171
|
+
"focus-within:border-error focus-within:hover:border-error"
|
|
172
|
+
],
|
|
173
|
+
className
|
|
174
|
+
),
|
|
175
|
+
...props,
|
|
176
|
+
children: [
|
|
177
|
+
/* @__PURE__ */ jsx("span", { className: cn(bareInputStyles, "truncate", !value && "text-fg-muted"), children: displayText }),
|
|
178
|
+
showClear && /* @__PURE__ */ jsx(
|
|
179
|
+
ItemInlineAction,
|
|
180
|
+
{
|
|
181
|
+
size: size ?? "md",
|
|
182
|
+
action: {
|
|
183
|
+
icon: X,
|
|
184
|
+
label: "清除時間",
|
|
185
|
+
// i18n-allow: DS default inline-action label
|
|
186
|
+
onClick: (e) => {
|
|
187
|
+
e == null ? void 0 : e.stopPropagation();
|
|
188
|
+
onChange == null ? void 0 : onChange("");
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
),
|
|
193
|
+
EndIconCmp && /* @__PURE__ */ jsx(ItemSuffix, { className: "pointer-events-none", children: /* @__PURE__ */ jsx(EndIconCmp, { size: iconSize, className: "text-fg-muted", "aria-hidden": true }) })
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
) }),
|
|
197
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "w-auto p-0", align: "start", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-[216px]", children: [
|
|
198
|
+
/* @__PURE__ */ jsx(
|
|
199
|
+
TimeColumns,
|
|
200
|
+
{
|
|
201
|
+
value: draft,
|
|
202
|
+
onChange: commitDraft,
|
|
203
|
+
showSeconds,
|
|
204
|
+
minuteStep,
|
|
205
|
+
secondStep,
|
|
206
|
+
disabled: disabledForColumns,
|
|
207
|
+
className: "flex-1 min-h-0"
|
|
208
|
+
}
|
|
209
|
+
),
|
|
210
|
+
/* @__PURE__ */ jsxs(
|
|
211
|
+
"div",
|
|
212
|
+
{
|
|
213
|
+
className: cn(
|
|
214
|
+
"flex items-center justify-between gap-2",
|
|
215
|
+
"border-t border-divider",
|
|
216
|
+
"px-[var(--layout-space-tight)] py-[var(--layout-space-tight)]"
|
|
217
|
+
),
|
|
218
|
+
children: [
|
|
219
|
+
/* @__PURE__ */ jsx(Button, { variant: "text", size: "sm", onClick: handleNow, children: "此刻" }),
|
|
220
|
+
/* @__PURE__ */ jsx(
|
|
221
|
+
Button,
|
|
222
|
+
{
|
|
223
|
+
variant: "primary",
|
|
224
|
+
size: "sm",
|
|
225
|
+
onClick: () => setOpen(false),
|
|
226
|
+
children: "確定"
|
|
227
|
+
}
|
|
228
|
+
)
|
|
229
|
+
]
|
|
230
|
+
}
|
|
231
|
+
)
|
|
232
|
+
] }) })
|
|
233
|
+
] });
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
TimePicker.displayName = "TimePicker";
|
|
237
|
+
const timePickerMeta = {
|
|
238
|
+
component: "TimePicker",
|
|
239
|
+
family: 4,
|
|
240
|
+
variants: {},
|
|
241
|
+
sizes: {},
|
|
242
|
+
states: ["default", "hover", "active", "focus-visible", "disabled"],
|
|
243
|
+
tokens: {
|
|
244
|
+
bg: ["bg-neutral-hover", "bg-primary", "bg-transparent"],
|
|
245
|
+
fg: ["text-fg-disabled", "text-fg-muted", "text-foreground"],
|
|
246
|
+
ring: []
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
export {
|
|
250
|
+
TimePicker,
|
|
251
|
+
timePickerMeta
|
|
252
|
+
};
|
|
253
|
+
//# sourceMappingURL=time-picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time-picker.js","sources":["../../../src/components/TimePicker/time-picker.tsx"],"sourcesContent":["// @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.\nimport * as React from 'react'\nimport { X, Clock } from 'lucide-react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport type { FieldMode, FieldVariant } from '@/design-system/components/Field/field-types'\nimport {\n fieldWrapperStyles,\n bareInputStyles,\n EMPTY_DISPLAY,\n fieldDisplayTextClass,\n} from '@/design-system/components/Field/field-wrapper'\nimport { ItemInlineAction, ItemSuffix } from '@/design-system/patterns/element-anatomy/item-anatomy'\nimport { Popover, PopoverTrigger, PopoverContent } from '@/design-system/components/Popover/popover'\nimport { useFieldContext } from '@/design-system/components/Field/field-context'\nimport { Button } from '@/design-system/components/Button/button'\nimport {\n TimeColumns,\n isoToTimeParts,\n timePartsToString,\n type TimeParts,\n type TimeStep,\n type TimeColumnsDisabled,\n} from '@/design-system/components/TimePicker/time-columns'\nimport { ICON_SIZE } from '@/design-system/tokens/uiSize/icon-size'\n\n/**\n * TimePicker — 單一時間(時/分/秒)輸入與顯示元件\n *\n * ── 定位(同 DatePicker 家族)──\n * Value 以 ISO time string 儲存(\"HH:mm\" 或 \"HH:mm:ss\"),local-time 語義(不帶時區)。\n * Edit 用本 DS 自建 time column panel + Popover 呈現,視覺與 DatePicker 一致。\n * Display 用 Intl.DateTimeFormat 格式化(跨 locale / 12h-24h 統一經過此 API)。\n *\n * ── Layout Family ──\n * CLAUDE.md 4-Family Model Family 4(Field control layout)消費者。結構繼承\n * `fieldWrapperStyles + [<editable>] [endIcon=Clock]`,視覺對齊 DatePicker(同\n * 「點擊觸發浮層」role:indicator 在 suffix slot,對齊 Material `endAdornment` /\n * Ant DatePicker / Polaris Picker 共識)。\n *\n * ── 實作基礎 ──\n * Trigger:`<button>` + `fieldWrapperStyles`(視覺仍是 Input wrapper,改為可點擊觸發浮層)\n * Popup:`Popover`(消費 overlay-surface pattern)\n * Panel 主體:自建 column picker(三欄 scrollable list),不引入第三方 time library\n *\n * ── 共用規則 ──\n * Mode / size / disabled / error 等詳見 `../Field/field-controls.spec.md`。\n */\n\n// ── Time ISO <-> parts conversion ───────────────────────────────────────────\n// Value 用 ISO time string(HH:mm 或 HH:mm:ss),local-time 語義(不帶時區/日期)。\n// 跟 DatePicker 的 ISO date string 策略一致。\n// `isoToTimeParts` / `timePartsToString` 改 import from time-columns(M17 SSOT)。\n\n// ── Display formatting ──────────────────────────────────────────────────────\n\nexport interface TimeFormatOptions {\n /** Intl.DateTimeFormat options(預設 { hour: '2-digit', minute: '2-digit', hour12: false }) */\n formatOptions?: Intl.DateTimeFormatOptions\n /** locale(預設 'en-US') */\n locale?: string\n}\n\nfunction formatTime(\n iso: string,\n options: TimeFormatOptions = {},\n): string {\n const parts = isoToTimeParts(iso)\n if (!parts) return iso\n const {\n formatOptions = { hour: '2-digit', minute: '2-digit', hour12: false },\n locale = 'en-US',\n } = options\n // 借用 Date 讓 Intl.DateTimeFormat 處理 locale / 12h-24h\n const d = new Date()\n d.setHours(parts.hours, parts.minutes, parts.seconds, 0)\n return new Intl.DateTimeFormat(locale, formatOptions).format(d)\n}\n\n// ── Disabled time callback ──────────────────────────────────────────────────\n// `Step` / `buildRange` / `TimeColumn`(內部欄位實作)拔掉,改 import `TimeColumns` primitive。\n\n// code-quality-allow: dead-export — public API surface — consumer-exposed for future use\nexport interface DisabledTimeResult {\n disabledHours?: number[]\n disabledMinutes?: number[]\n disabledSeconds?: number[]\n}\n\n// ── Component props ─────────────────────────────────────────────────────────\n\nexport interface TimePickerProps\n extends TimeFormatOptions,\n Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'onChange' | 'placeholder'\n > {\n mode?: FieldMode\n /** Field chrome variant. Default = context.variant ?? 'default'. Per-prop override. */\n variant?: FieldVariant\n error?: boolean\n size?: 'sm' | 'md' | 'lg'\n /** ISO time string(\"HH:mm\" 或 \"HH:mm:ss\") */\n value?: string | null\n onChange?: (value: string) => void\n placeholder?: string\n className?: string\n disabled?: boolean\n /** 允許清空已選值 */\n clearable?: boolean\n /**\n * 是否顯示秒欄(三欄 picker)。預設 false(兩欄:時/分)。\n * format 自動對應:false → \"HH:mm\",true → \"HH:mm:ss\"。\n */\n showSeconds?: boolean\n /** 分鐘步進(會議常用 15)。預設 1 */\n minuteStep?: TimeStep\n /** 秒步進。預設 1。僅 showSeconds=true 有效 */\n secondStep?: TimeStep\n /** 動態 disabled 某些時/分/秒(基於已選其他欄位)。 */\n disabledTime?: (parts: TimeParts) => DisabledTimeResult\n /**\n * Suffix indicator(2026-05-05 v9 canonical fix):「點擊觸發浮層」indicator 一律 suffix\n * (對齊 DatePicker calendar / Material endAdornment)。預設 Clock,傳 null 可關閉。\n */\n endIcon?: LucideIcon | null\n /**\n * Display 是否渲 endIcon + Field naked wrapper(D-path opt-in,2026-05-08)\n * — DataTable cell display↔edit 像素級對齊用。預設 false(裸 span,backward compat)。\n * 設 true 時 display 也走 fieldWrapperStyles(naked variant)+ ItemSuffix Clock,\n * 與 edit 同 DOM 結構,消除 Layer-B padding mismatch。\n */\n showDisplayEndIcon?: boolean\n /** Initial open state(uncontrolled)— DataTable cell-as-input 1-step open canonical */\n defaultOpen?: boolean\n /** open state 變更 callback。DataTable cell-as-input 用:open=false → cell exit edit */\n onOpenChange?: (open: boolean) => void\n}\n\n// code-quality-allow: long-function — foundational composite main body — 拆 sub-fn 會複雜化 local state / ref / context binding\nconst TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>(\n (\n {\n mode = 'edit',\n variant: variantProp,\n error: errorProp = false,\n size = 'md',\n value,\n onChange,\n placeholder,\n className,\n disabled: disabledProp,\n clearable = false,\n showSeconds = false,\n minuteStep = 1,\n secondStep = 1,\n disabledTime,\n endIcon,\n showDisplayEndIcon = false,\n formatOptions,\n locale,\n defaultOpen = false,\n onOpenChange,\n id: idProp,\n 'aria-describedby': ariaDescribedByProp,\n 'aria-errormessage': ariaErrorMessageProp,\n ...props\n },\n ref,\n ) => {\n const fieldCtx = useFieldContext()\n const error = errorProp || (fieldCtx?.invalid ?? false)\n const disabled = disabledProp ?? fieldCtx?.disabled\n const resolvedMode = disabled ? 'disabled' : mode\n const variant: FieldVariant = variantProp ?? fieldCtx?.variant ?? 'default'\n const isEditable = resolvedMode === 'edit'\n // 2026-05-18 改 import ICON_SIZE SSOT(per user『做完』approval,消除 M17 違反 7+ 重複 ternary)\n const iconSize = ICON_SIZE[size as 'sm' | 'md' | 'lg']\n const EndIconCmp: LucideIcon | null =\n endIcon === null ? null : (endIcon ?? Clock)\n const defaultPlaceholder = showSeconds ? 'HH:MM:SS' : 'HH:MM'\n const resolvedPlaceholder = placeholder ?? defaultPlaceholder\n const showClear = clearable && !!value && isEditable\n const [open, setOpenState] = React.useState(defaultOpen)\n const setOpen = React.useCallback((next: boolean) => { setOpenState(next); onOpenChange?.(next) }, [onOpenChange])\n\n const currentParts = React.useMemo(() => isoToTimeParts(value), [value])\n // draft 僅在 panel 開啟時用來處理 commit(OK button)的暫存\n const [draft, setDraft] = React.useState<TimeParts>(\n () => currentParts ?? { hours: 0, minutes: 0, seconds: 0 },\n )\n\n // 每次 popover 開啟時以當前 value 初始化 draft\n React.useEffect(() => {\n if (open) {\n setDraft(currentParts ?? { hours: 0, minutes: 0, seconds: 0 })\n }\n }, [open, currentParts])\n\n const disabledForColumns: TimeColumnsDisabled | undefined = React.useMemo(() => {\n if (!disabledTime) return undefined\n const res = disabledTime(draft)\n return {\n hours: res.disabledHours,\n minutes: res.disabledMinutes,\n seconds: res.disabledSeconds,\n }\n }, [disabledTime, draft])\n\n const commitDraft = (next: TimeParts) => {\n setDraft(next)\n onChange?.(timePartsToString(next, showSeconds))\n }\n\n const handleNow = () => {\n const now = new Date()\n // 按照 minuteStep / secondStep 對齊\n const m = Math.round(now.getMinutes() / minuteStep) * minuteStep\n const s = showSeconds\n ? Math.round(now.getSeconds() / secondStep) * secondStep\n : 0\n const next: TimeParts = {\n hours: now.getHours(),\n minutes: Math.min(m, 59),\n seconds: Math.min(s, 59),\n }\n commitDraft(next)\n setOpen(false)\n }\n\n // mode='display'(Phase B2 2026-05-05):純內容輸出 — 對齊原 TimePickerDisplay sub-component(retired)。\n // Default(showDisplayEndIcon=false):無 Field wrapper / 無 Clock icon — backward compat 裸 span。\n // Opt-in(showDisplayEndIcon=true,2026-05-08 D-path):Field naked wrapper + ItemSuffix Clock,\n // 與 edit 同結構消除 cell display↔edit 像素偏移(Layer-B padding mismatch)。\n if (resolvedMode === 'display') {\n if (!showDisplayEndIcon) {\n // 2026-05-14 I2 fix(spec contract (e) display typography canonical):bare span 套\n // `fieldDisplayTextClass(size)`(sm/md→text-body,lg→text-body-lg)— 對齊 Field family 統一。\n if (!value) return <span className={cn(fieldDisplayTextClass(size), 'text-fg-muted', className)}>{EMPTY_DISPLAY}</span>\n return <span className={cn(fieldDisplayTextClass(size), 'truncate', className)}>{formatTime(value, { formatOptions, locale })}</span>\n }\n return (\n <div\n className={cn(fieldWrapperStyles({ mode: 'display', variant, size }), className)}\n data-field-mode=\"display\"\n >\n <span className={cn(bareInputStyles, 'flex-1 min-w-0 truncate', !value && 'text-fg-muted')}>\n {value ? formatTime(value, { formatOptions, locale }) : EMPTY_DISPLAY}\n </span>\n {EndIconCmp && (\n <ItemSuffix className=\"pointer-events-none\">\n <EndIconCmp size={iconSize} className=\"text-fg-muted\" aria-hidden />\n </ItemSuffix>\n )}\n </div>\n )\n }\n\n // readonly / disabled\n if (!isEditable) {\n return (\n <div\n className={cn(fieldWrapperStyles({ mode: resolvedMode, variant: variant, size }), className)}\n data-field-mode={resolvedMode}\n {...(props as React.HTMLAttributes<HTMLDivElement>)}\n >\n <span\n className={cn(\n 'flex-1 min-w-0',\n resolvedMode === 'disabled' && 'text-fg-disabled',\n )}\n >\n {value\n ? formatTime(value, { formatOptions, locale })\n : <span className=\"text-fg-muted\">{EMPTY_DISPLAY}</span>\n }\n </span>\n {EndIconCmp && (\n <ItemSuffix className=\"pointer-events-none\">\n <EndIconCmp\n size={iconSize}\n className={resolvedMode === 'disabled' ? 'text-fg-disabled' : 'text-fg-muted'}\n aria-hidden\n />\n </ItemSuffix>\n )}\n </div>\n )\n }\n\n const displayText = value\n ? formatTime(value, { formatOptions, locale })\n : <span className=\"text-fg-muted\">{resolvedPlaceholder}</span>\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n {/* a11y(2026-04-25 nested-interactive fix):trigger 改 <div role='combobox'>\n (對齊 Select / Combobox 同 pattern),原 <button> 會與內層 ItemInlineAction\n 清除 button 構成 nested-interactive。Radix Popover 在 trigger asChild 下會\n 自動 inject keyboard handler(Enter / Space 開啟)+ 正確 aria attributes。 */}\n <PopoverTrigger asChild>\n <div\n ref={ref}\n id={idProp ?? fieldCtx?.id}\n role=\"combobox\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled || undefined}\n aria-labelledby={fieldCtx?.labelId}\n aria-invalid={error || undefined}\n aria-required={fieldCtx?.required || undefined}\n aria-describedby={ariaDescribedByProp ?? fieldCtx?.descriptionId}\n aria-errormessage={ariaErrorMessageProp ?? (error ? fieldCtx?.errorId : undefined)}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n data-field-mode=\"edit\"\n data-error={error ? '' : undefined}\n className={cn(\n fieldWrapperStyles({ mode: 'edit', variant: variant, size }),\n 'text-left cursor-pointer',\n 'focus-visible:outline-none',\n error && [\n 'border-error hover:border-error-hover',\n 'focus-within:border-error focus-within:hover:border-error',\n ],\n className,\n )}\n {...props}\n >\n <span className={cn(bareInputStyles, 'truncate', !value && 'text-fg-muted')}>\n {displayText}\n </span>\n {showClear && (\n <ItemInlineAction\n size={size ?? 'md'}\n action={{\n icon: X,\n label: '清除時間', // i18n-allow: DS default inline-action label\n onClick: (e) => {\n e?.stopPropagation()\n onChange?.('')\n },\n }}\n />\n )}\n {EndIconCmp && (\n <ItemSuffix className=\"pointer-events-none\">\n <EndIconCmp size={iconSize} className=\"text-fg-muted\" aria-hidden />\n </ItemSuffix>\n )}\n </div>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"start\">\n {/* Panel 對齊 ref/timepicker.png:2-3 個 SelectMenu 式欄位並排,分隔線分開。\n Width 依欄數由 TimeColumns 決定:2 欄 w-40 / 3 欄 w-60。\n Height 由 wrapper 控:216px 預設(~7 items)。\n TimeColumns 本身 h-full,parent 控 height — 讓 DatePicker showTime / Range 可\n 用 flex-row items-stretch 自動同 calendar 高。 */}\n <div className=\"flex flex-col h-[216px]\">\n <TimeColumns\n value={draft}\n onChange={commitDraft}\n showSeconds={showSeconds}\n minuteStep={minuteStep}\n secondStep={secondStep}\n disabled={disabledForColumns}\n // 2026-05-06 v9.1 M25 chain fix:TimeColumns 自然高 = 24 buttons × ~28.7px = 688px\n // 會撐破 parent h-[216px]。flex-1 + min-h-0 讓 TimeColumns 取 parent 剩餘空間\n // (216 - footer 40 = 176px)→ ScrollArea h-full 才能正確收斂 →\n // listbox scrollIntoView 找對 nearest scrollable ancestor(內部 viewport),\n // 不會走到 document body 把 popover 內容推出畫面(user 報「hours 欄空白」根因)。\n className=\"flex-1 min-h-0\"\n />\n {/* Footer:Now + OK */}\n <div\n className={cn(\n 'flex items-center justify-between gap-2',\n 'border-t border-divider',\n 'px-[var(--layout-space-tight)] py-[var(--layout-space-tight)]',\n )}\n >\n <Button variant=\"text\" size=\"sm\" onClick={handleNow}>\n 此刻\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={() => setOpen(false)}\n >\n 確定\n </Button>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n )\n },\n)\nTimePicker.displayName = 'TimePicker'\n\n// Story auto-compile metadata — Phase 1 mechanical migration(2026-04-24)\n// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs\nexport const timePickerMeta = {\n component: 'TimePicker',\n family: 4,\n variants: {\n\n },\n sizes: {\n\n },\n states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],\n tokens: {\n bg: ['bg-neutral-hover', 'bg-primary', 'bg-transparent'],\n fg: ['text-fg-disabled', 'text-fg-muted', 'text-foreground'],\n ring: [],\n },\n} as const\n\nexport { TimePicker }\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type NoticeVariant } from '../../components/Notice/notice';
|
|
3
|
+
/**
|
|
4
|
+
* Toast — 非阻斷式浮動通知
|
|
5
|
+
*
|
|
6
|
+
* ── Container 三層結構(所有 variant 統一) ──
|
|
7
|
+
*
|
|
8
|
+
* 1. Shadow wrapper: rounded-lg + elevation-200(永遠在頁面 theme 解析)
|
|
9
|
+
* 2. Bg layer: bg-{color}(有色相 variant 在頁面 theme 解析)
|
|
10
|
+
* 3. Theme layer: data-theme + text-foreground(content token re-resolve)
|
|
11
|
+
*
|
|
12
|
+
* neutral/success(inverse): bg + theme 同層(bg-surface-raised 需要跟 data-theme 一起翻轉)
|
|
13
|
+
* info/error(dark): bg 在 outer,theme 在 inner
|
|
14
|
+
* warning(light always): bg 在 outer,theme="light" 在 inner
|
|
15
|
+
*/
|
|
16
|
+
export type ToastVariant = NoticeVariant;
|
|
17
|
+
export interface ToastOptions {
|
|
18
|
+
variant?: ToastVariant;
|
|
19
|
+
title: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
action?: {
|
|
22
|
+
label: string;
|
|
23
|
+
onClick: () => void;
|
|
24
|
+
};
|
|
25
|
+
duration?: number;
|
|
26
|
+
}
|
|
27
|
+
export declare function toast(options: ToastOptions): string | number;
|
|
28
|
+
export interface ToasterProps {
|
|
29
|
+
position?: 'top-left' | 'top-right' | 'top-center' | 'bottom-left' | 'bottom-right' | 'bottom-center';
|
|
30
|
+
}
|
|
31
|
+
declare const Toaster: React.ForwardRefExoticComponent<ToasterProps & React.RefAttributes<HTMLDivElement>>;
|
|
32
|
+
export declare const toastMeta: {
|
|
33
|
+
readonly component: "Toast";
|
|
34
|
+
readonly family: null;
|
|
35
|
+
readonly variants: {
|
|
36
|
+
readonly neutral: {
|
|
37
|
+
readonly when: "非狀態通知;一般 announcement / tip";
|
|
38
|
+
};
|
|
39
|
+
readonly info: {
|
|
40
|
+
readonly when: "資訊性提示(新版本 / 同步完成)";
|
|
41
|
+
};
|
|
42
|
+
readonly success: {
|
|
43
|
+
readonly when: "成功確認(已寄送 / 付款完成)";
|
|
44
|
+
};
|
|
45
|
+
readonly warning: {
|
|
46
|
+
readonly when: "可恢復警告(未儲存 / 連線不穩)";
|
|
47
|
+
};
|
|
48
|
+
readonly error: {
|
|
49
|
+
readonly when: "錯誤(匯入失敗 / 權限不足);action prop 可加重試";
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
readonly sizes: {};
|
|
53
|
+
readonly states: readonly ["default", "hover", "active", "focus-visible", "disabled"];
|
|
54
|
+
readonly tokens: {
|
|
55
|
+
readonly bg: readonly ["bg-error", "bg-info", "bg-surface-raised", "bg-warning"];
|
|
56
|
+
readonly fg: readonly ["text-foreground"];
|
|
57
|
+
readonly ring: readonly [];
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
export { Toaster };
|
|
61
|
+
//# sourceMappingURL=toast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../../../src/components/Toast/toast.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAA2B,KAAK,aAAa,EAAE,MAAM,0CAA0C,CAAA;AAGtG;;;;;;;;;;;;GAYG;AAGH,MAAM,MAAM,YAAY,GAAG,aAAa,CAAA;AAExC,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,YAAY,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,CAAA;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAqDD,wBAAgB,KAAK,CAAC,OAAO,EAAE,YAAY,mBAG1C;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,YAAY,GAAG,aAAa,GAAG,cAAc,GAAG,eAAe,CAAA;CACtG;AAMD,QAAA,MAAM,OAAO,qFAUZ,CAAA;AAKD,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiBZ,CAAA;AAEV,OAAO,EAAE,OAAO,EAAE,CAAA"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Toaster as Toaster$1, toast as toast$1 } from "sonner";
|
|
4
|
+
import { useInverseTheme, Notice } from "../Notice/notice.js";
|
|
5
|
+
import { Button } from "../Button/button.js";
|
|
6
|
+
function ToastInner({
|
|
7
|
+
id,
|
|
8
|
+
variant = "neutral",
|
|
9
|
+
action,
|
|
10
|
+
...rest
|
|
11
|
+
}) {
|
|
12
|
+
const inverseTheme = useInverseTheme();
|
|
13
|
+
const isInverse = variant === "neutral" || variant === "success";
|
|
14
|
+
const dismiss = () => toast$1.dismiss(id);
|
|
15
|
+
const actionButton = action ? /* @__PURE__ */ jsx(Button, { variant: "tertiary", size: "xs", onClick: action.onClick, children: action.label }) : void 0;
|
|
16
|
+
const isCritical = variant === "error" || variant === "warning";
|
|
17
|
+
const liveRole = isCritical ? "alert" : "status";
|
|
18
|
+
const liveLevel = isCritical ? "assertive" : "polite";
|
|
19
|
+
if (isInverse) {
|
|
20
|
+
return /* @__PURE__ */ jsx("div", { role: liveRole, "aria-live": liveLevel, className: "rounded-lg overflow-hidden", style: { boxShadow: "var(--elevation-200)" }, children: /* @__PURE__ */ jsx("div", { "data-theme": inverseTheme, className: "bg-surface-raised text-foreground", children: /* @__PURE__ */ jsx(
|
|
21
|
+
Notice,
|
|
22
|
+
{
|
|
23
|
+
variant,
|
|
24
|
+
iconClassName: variant === "success" ? "text-success" : void 0,
|
|
25
|
+
endContent: actionButton,
|
|
26
|
+
onDismiss: dismiss,
|
|
27
|
+
...rest
|
|
28
|
+
}
|
|
29
|
+
) }) });
|
|
30
|
+
}
|
|
31
|
+
const bg = variant === "warning" ? "bg-warning" : variant === "error" ? "bg-error" : "bg-info";
|
|
32
|
+
const theme = variant === "warning" ? "light" : "dark";
|
|
33
|
+
return /* @__PURE__ */ jsx("div", { role: liveRole, "aria-live": liveLevel, className: "rounded-lg overflow-hidden", style: { boxShadow: "var(--elevation-200)" }, children: /* @__PURE__ */ jsx("div", { className: bg, children: /* @__PURE__ */ jsx("div", { "data-theme": theme, className: "text-foreground", children: /* @__PURE__ */ jsx(Notice, { variant, endContent: actionButton, onDismiss: dismiss, ...rest }) }) }) });
|
|
34
|
+
}
|
|
35
|
+
function toast(options) {
|
|
36
|
+
const { duration = 4e3, ...rest } = options;
|
|
37
|
+
return toast$1.custom((id) => /* @__PURE__ */ jsx(ToastInner, { id, ...rest }), { duration });
|
|
38
|
+
}
|
|
39
|
+
const Toaster = React.forwardRef(
|
|
40
|
+
({ position = "bottom-right", ...props }, _ref) => {
|
|
41
|
+
return /* @__PURE__ */ jsx(
|
|
42
|
+
Toaster$1,
|
|
43
|
+
{
|
|
44
|
+
position,
|
|
45
|
+
toastOptions: { unstyled: true, className: "w-[360px]" },
|
|
46
|
+
...props
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
Toaster.displayName = "Toaster";
|
|
52
|
+
const toastMeta = {
|
|
53
|
+
component: "Toast",
|
|
54
|
+
family: null,
|
|
55
|
+
// non-family composite / overlay / layout
|
|
56
|
+
variants: {
|
|
57
|
+
neutral: { when: "非狀態通知;一般 announcement / tip" },
|
|
58
|
+
info: { when: "資訊性提示(新版本 / 同步完成)" },
|
|
59
|
+
success: { when: "成功確認(已寄送 / 付款完成)" },
|
|
60
|
+
warning: { when: "可恢復警告(未儲存 / 連線不穩)" },
|
|
61
|
+
error: { when: "錯誤(匯入失敗 / 權限不足);action prop 可加重試" }
|
|
62
|
+
},
|
|
63
|
+
sizes: {},
|
|
64
|
+
states: ["default", "hover", "active", "focus-visible", "disabled"],
|
|
65
|
+
tokens: {
|
|
66
|
+
bg: ["bg-error", "bg-info", "bg-surface-raised", "bg-warning"],
|
|
67
|
+
fg: ["text-foreground"],
|
|
68
|
+
ring: []
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
export {
|
|
72
|
+
Toaster,
|
|
73
|
+
toast,
|
|
74
|
+
toastMeta
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast.js","sources":["../../../src/components/Toast/toast.tsx"],"sourcesContent":["import * as React from 'react'\nimport { Toaster as SonnerToaster, toast as sonnerToast } from 'sonner'\nimport { Notice, useInverseTheme, type NoticeVariant } from '@/design-system/components/Notice/notice'\nimport { Button } from '@/design-system/components/Button/button'\n\n/**\n * Toast — 非阻斷式浮動通知\n *\n * ── Container 三層結構(所有 variant 統一) ──\n *\n * 1. Shadow wrapper: rounded-lg + elevation-200(永遠在頁面 theme 解析)\n * 2. Bg layer: bg-{color}(有色相 variant 在頁面 theme 解析)\n * 3. Theme layer: data-theme + text-foreground(content token re-resolve)\n *\n * neutral/success(inverse): bg + theme 同層(bg-surface-raised 需要跟 data-theme 一起翻轉)\n * info/error(dark): bg 在 outer,theme 在 inner\n * warning(light always): bg 在 outer,theme=\"light\" 在 inner\n */\n\n// code-quality-allow: dead-export — public API surface — consumer-exposed for future use\nexport type ToastVariant = NoticeVariant\n\nexport interface ToastOptions {\n variant?: ToastVariant\n title: string\n description?: string\n action?: { label: string; onClick: () => void }\n duration?: number\n}\n\nfunction ToastInner({\n id,\n variant = 'neutral',\n action,\n ...rest\n}: ToastOptions & { id: string | number }) {\n const inverseTheme = useInverseTheme()\n const isInverse = variant === 'neutral' || variant === 'success'\n const dismiss = () => sonnerToast.dismiss(id)\n\n const actionButton = action ? (\n <Button variant=\"tertiary\" size=\"xs\" onClick={action.onClick}>{action.label}</Button>\n ) : undefined\n\n // ── Live region 由 outer Toast wrapper 擁有(WAI-ARIA + spec L59-60 canonical) ──\n // Notice(inner layout)不再帶 role,避免 nested live region。\n // - error / warning → role=\"alert\" + aria-live=\"assertive\"(中斷朗讀)\n // - info / success / neutral → role=\"status\" + aria-live=\"polite\"(空閒朗讀)\n const isCritical = variant === 'error' || variant === 'warning'\n const liveRole = isCritical ? 'alert' : 'status'\n const liveLevel = isCritical ? 'assertive' : 'polite'\n\n // ── 1. Shadow wrapper(統一,永遠在頁面 theme) ──\n // ── 2+3. Bg + theme layer ──\n\n if (isInverse) {\n // bg-surface-raised 需要跟 data-theme 同層翻轉\n return (\n <div role={liveRole} aria-live={liveLevel} className=\"rounded-lg overflow-hidden\" style={{ boxShadow: 'var(--elevation-200)' }}>\n <div data-theme={inverseTheme} className=\"bg-surface-raised text-foreground\">\n <Notice variant={variant} iconClassName={variant === 'success' ? 'text-success' : undefined}\n endContent={actionButton} onDismiss={dismiss} {...rest} />\n </div>\n </div>\n )\n }\n\n const bg = variant === 'warning' ? 'bg-warning' : variant === 'error' ? 'bg-error' : 'bg-info'\n const theme = variant === 'warning' ? 'light' : 'dark'\n\n return (\n <div role={liveRole} aria-live={liveLevel} className=\"rounded-lg overflow-hidden\" style={{ boxShadow: 'var(--elevation-200)' }}>\n <div className={bg}>\n <div data-theme={theme} className=\"text-foreground\">\n <Notice variant={variant} endContent={actionButton} onDismiss={dismiss} {...rest} />\n </div>\n </div>\n </div>\n )\n}\n\nexport function toast(options: ToastOptions) {\n const { duration = 4000, ...rest } = options\n return sonnerToast.custom((id) => <ToastInner id={id} {...rest} />, { duration })\n}\n\nexport interface ToasterProps {\n position?: 'top-left' | 'top-right' | 'top-center' | 'bottom-left' | 'bottom-right' | 'bottom-center'\n}\n\n// shadcn canonical:forwardRef + displayName 統一。Sonner Toaster portal-renders\n// 到 document body,ref 對 Toaster 本身無實際 DOM 節點可接(portal 逃逸),\n// 但保留 forwardRef 簽名以符合 DS 統一 API(consumer 可 typecheck 傳 ref,\n// 與其他 DS 元件一致)。\nconst Toaster = React.forwardRef<HTMLDivElement, ToasterProps>(\n ({ position = 'bottom-right', ...props }, _ref) => {\n return (\n <SonnerToaster\n position={position}\n toastOptions={{ unstyled: true, className: 'w-[360px]' }}\n {...props}\n />\n )\n },\n)\nToaster.displayName = 'Toaster'\n\n// Story auto-compile metadata — Phase 1 mechanical migration(2026-04-24)\n// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs\nexport const toastMeta = {\n component: 'Toast',\n family: null, // non-family composite / overlay / layout\n variants: {\n neutral: { when: '非狀態通知;一般 announcement / tip' },\n info: { when: '資訊性提示(新版本 / 同步完成)' },\n success: { when: '成功確認(已寄送 / 付款完成)' },\n warning: { when: '可恢復警告(未儲存 / 連線不穩)' },\n error: { when: '錯誤(匯入失敗 / 權限不足);action prop 可加重試' },\n },\n sizes: {},\n states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],\n tokens: {\n bg: ['bg-error', 'bg-info', 'bg-surface-raised', 'bg-warning'],\n fg: ['text-foreground'],\n ring: [],\n },\n} as const\n\nexport { Toaster }\n"],"names":["sonnerToast","SonnerToaster"],"mappings":";;;;;AA8BA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA,GAAG;AACL,GAA2C;AACzC,QAAM,eAAe,gBAAA;AACrB,QAAM,YAAY,YAAY,aAAa,YAAY;AACvD,QAAM,UAAU,MAAMA,QAAY,QAAQ,EAAE;AAE5C,QAAM,eAAe,SACnB,oBAAC,QAAA,EAAO,SAAQ,YAAW,MAAK,MAAK,SAAS,OAAO,SAAU,UAAA,OAAO,OAAM,IAC1E;AAMJ,QAAM,aAAa,YAAY,WAAW,YAAY;AACtD,QAAM,WAAW,aAAa,UAAU;AACxC,QAAM,YAAY,aAAa,cAAc;AAK7C,MAAI,WAAW;AAEb,+BACG,OAAA,EAAI,MAAM,UAAU,aAAW,WAAW,WAAU,8BAA6B,OAAO,EAAE,WAAW,0BACpG,UAAA,oBAAC,SAAI,cAAY,cAAc,WAAU,qCACvC,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAO;AAAA,QAAkB,eAAe,YAAY,YAAY,iBAAiB;AAAA,QAChF,YAAY;AAAA,QAAc,WAAW;AAAA,QAAU,GAAG;AAAA,MAAA;AAAA,IAAA,GACtD,EAAA,CACF;AAAA,EAEJ;AAEA,QAAM,KAAK,YAAY,YAAY,eAAe,YAAY,UAAU,aAAa;AACrF,QAAM,QAAQ,YAAY,YAAY,UAAU;AAEhD,SACE,oBAAC,OAAA,EAAI,MAAM,UAAU,aAAW,WAAW,WAAU,8BAA6B,OAAO,EAAE,WAAW,uBAAA,GACpG,UAAA,oBAAC,SAAI,WAAW,IACd,UAAA,oBAAC,OAAA,EAAI,cAAY,OAAO,WAAU,mBAChC,8BAAC,QAAA,EAAO,SAAkB,YAAY,cAAc,WAAW,SAAU,GAAG,MAAM,EAAA,CACpF,GACF,GACF;AAEJ;AAEO,SAAS,MAAM,SAAuB;AAC3C,QAAM,EAAE,WAAW,KAAM,GAAG,SAAS;AACrC,SAAOA,QAAY,OAAO,CAAC,OAAO,oBAAC,YAAA,EAAW,IAAS,GAAG,KAAA,CAAM,GAAI,EAAE,SAAA,CAAU;AAClF;AAUA,MAAM,UAAU,MAAM;AAAA,EACpB,CAAC,EAAE,WAAW,gBAAgB,GAAG,MAAA,GAAS,SAAS;AACjD,WACE;AAAA,MAACC;AAAAA,MAAA;AAAA,QACC;AAAA,QACA,cAAc,EAAE,UAAU,MAAM,WAAW,YAAA;AAAA,QAC1C,GAAG;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AACA,QAAQ,cAAc;AAIf,MAAM,YAAY;AAAA,EACvB,WAAW;AAAA,EACX,QAAQ;AAAA;AAAA,EACR,UAAU;AAAA,IACR,SAAS,EAAE,MAAM,8BAAA;AAAA,IACjB,MAAM,EAAE,MAAM,oBAAA;AAAA,IACd,SAAS,EAAE,MAAM,mBAAA;AAAA,IACjB,SAAS,EAAE,MAAM,oBAAA;AAAA,IACjB,OAAO,EAAE,MAAM,mCAAA;AAAA,EAAmC;AAAA,EAEpD,OAAO,CAAA;AAAA,EACP,QAAQ,CAAC,WAAW,SAAS,UAAU,iBAAiB,UAAU;AAAA,EAClE,QAAQ;AAAA,IACN,IAAI,CAAC,YAAY,WAAW,qBAAqB,YAAY;AAAA,IAC7D,IAAI,CAAC,iBAAiB;AAAA,IACtB,MAAM,CAAA;AAAA,EAAC;AAEX;"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
3
|
+
declare const TooltipProvider: ({ delayDuration, ...props }: React.ComponentProps<typeof TooltipPrimitive.Provider>) => import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
declare const Tooltip: ({ delayDuration, ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
declare const TooltipTrigger: React.ForwardRefExoticComponent<TooltipPrimitive.TooltipTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
6
|
+
declare const TooltipContent: React.ForwardRefExoticComponent<Omit<TooltipPrimitive.TooltipContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
7
|
+
export declare const tooltipMeta: {
|
|
8
|
+
readonly component: "Tooltip";
|
|
9
|
+
readonly family: null;
|
|
10
|
+
readonly variants: {};
|
|
11
|
+
readonly sizes: {};
|
|
12
|
+
readonly states: readonly ["default", "hover", "active", "focus-visible", "disabled"];
|
|
13
|
+
readonly tokens: {
|
|
14
|
+
readonly bg: readonly [];
|
|
15
|
+
readonly fg: readonly [];
|
|
16
|
+
readonly ring: readonly [];
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
|
20
|
+
//# sourceMappingURL=tooltip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../../src/components/Tooltip/tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAA;AAU3D,QAAA,MAAM,eAAe,GAAI,6BAAoD,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,QAAQ,CAAC,4CAElI,CAAA;AAED,QAAA,MAAM,OAAO,GAAI,6BAAoD,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,IAAI,CAAC,4CAEtH,CAAA;AAED,QAAA,MAAM,cAAc,gHAA2B,CAAA;AAE/C,QAAA,MAAM,cAAc,gKAwBlB,CAAA;AAKF,eAAO,MAAM,WAAW;;;;;;;;;;;CAed,CAAA;AAEV,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,eAAe,EAAE,CAAA"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
4
|
+
import { cn } from "../../lib/utils.js";
|
|
5
|
+
import { OVERLAY_COLLISION_PADDING, OVERLAY_SIDE_OFFSET } from "../../tokens/elevation/overlay-geometry.js";
|
|
6
|
+
import { HOVER_DELAY_PLAIN_MS } from "../../tokens/motion/motion.js";
|
|
7
|
+
const TooltipProvider = ({ delayDuration = HOVER_DELAY_PLAIN_MS, ...props }) => /* @__PURE__ */ jsx(TooltipPrimitive.Provider, { delayDuration, ...props });
|
|
8
|
+
const Tooltip = ({ delayDuration = HOVER_DELAY_PLAIN_MS, ...props }) => /* @__PURE__ */ jsx(TooltipPrimitive.Root, { delayDuration, ...props });
|
|
9
|
+
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
10
|
+
const TooltipContent = React.forwardRef(({ className, sideOffset = OVERLAY_SIDE_OFFSET, collisionPadding = OVERLAY_COLLISION_PADDING, style, children, ...props }, ref) => (
|
|
11
|
+
// collisionPadding default 8px:避免 tooltip 貼 viewport 邊(Radix avoidCollisions 預設 true 但 padding 0 會貼邊)
|
|
12
|
+
// 對齊 HoverCard canonical 避免 viewport edge clipping
|
|
13
|
+
/* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
14
|
+
TooltipPrimitive.Content,
|
|
15
|
+
{
|
|
16
|
+
ref,
|
|
17
|
+
sideOffset,
|
|
18
|
+
collisionPadding,
|
|
19
|
+
className: cn(
|
|
20
|
+
"z-50 overflow-hidden rounded-md px-3 py-2 text-body font-normal text-on-emphasis bg-tooltip max-w-[280px]",
|
|
21
|
+
"animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 motion-reduce:animate-none motion-reduce:zoom-in-100",
|
|
22
|
+
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
23
|
+
"origin-[var(--radix-tooltip-content-transform-origin)]",
|
|
24
|
+
className
|
|
25
|
+
),
|
|
26
|
+
style: { boxShadow: "var(--elevation-200)", ...style },
|
|
27
|
+
...props,
|
|
28
|
+
children: /* @__PURE__ */ jsx("div", { "data-theme": "dark", className: "contents", children })
|
|
29
|
+
}
|
|
30
|
+
) })
|
|
31
|
+
));
|
|
32
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
33
|
+
const tooltipMeta = {
|
|
34
|
+
component: "Tooltip",
|
|
35
|
+
family: null,
|
|
36
|
+
// non-family composite / overlay / layout
|
|
37
|
+
variants: {},
|
|
38
|
+
sizes: {},
|
|
39
|
+
states: ["default", "hover", "active", "focus-visible", "disabled"],
|
|
40
|
+
tokens: {
|
|
41
|
+
bg: [],
|
|
42
|
+
fg: [],
|
|
43
|
+
ring: []
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export {
|
|
47
|
+
Tooltip,
|
|
48
|
+
TooltipContent,
|
|
49
|
+
TooltipProvider,
|
|
50
|
+
TooltipTrigger,
|
|
51
|
+
tooltipMeta
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=tooltip.js.map
|