@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,111 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
3
|
+
import { type LucideIcon } from "lucide-react";
|
|
4
|
+
import type { AvatarData } from "../../components/Avatar/avatar";
|
|
5
|
+
import { type RowSize } from "../../patterns/element-anatomy/item-anatomy";
|
|
6
|
+
/**
|
|
7
|
+
* DropdownMenu — Radix DropdownMenu + MenuItem visual layer
|
|
8
|
+
*
|
|
9
|
+
* 架構分工:
|
|
10
|
+
* - Radix primitives:behavior(keyboard nav, focus management, aria roles)
|
|
11
|
+
* - MenuItem:visual(layout, padding, icon alignment, typography)
|
|
12
|
+
*
|
|
13
|
+
* Radix primitive 是外層容器,控制 `data-[highlighted]:bg-neutral-hover`。
|
|
14
|
+
* MenuItem 內層只負責佈局,不加互動樣式。
|
|
15
|
+
*
|
|
16
|
+
* ── Hover / highlight canonical(2026-04-22 修正)──
|
|
17
|
+
* 用 Radix 官方的 `data-[highlighted]` attribute,**不用 `:focus-visible` / `:hover` /
|
|
18
|
+
* `:focus`**:
|
|
19
|
+
* - Radix 在 **mouse hover、keyboard arrow nav、focus move in** 時自動 set `data-highlighted`
|
|
20
|
+
* - mouse leave / focus move out / menu close 時自動清掉
|
|
21
|
+
* - 不會在 click 後留殘影(Radix 內部已處理)
|
|
22
|
+
* - 跨瀏覽器一致(不依賴 `:focus-visible` 的 heuristic)
|
|
23
|
+
*
|
|
24
|
+
* 曾經用過 `focus-visible:bg-neutral-hover` 的理由:避免 click 後殘影。但實測:mouse hover
|
|
25
|
+
* 觸發 Radix 程式化 `.focus()`,Chromium / Safari / Firefox 對 programmatic focus 是否 fire
|
|
26
|
+
* `:focus-visible` 行為不一致,導致 mouse hover 有時無 bg。改用 `data-[highlighted]:` 後行為
|
|
27
|
+
* 一致 —— 世界級 canonical(shadcn / Radix docs / Ariakit 皆此)。
|
|
28
|
+
*/
|
|
29
|
+
declare const floatingLayerClass: string;
|
|
30
|
+
type SizeKey = RowSize;
|
|
31
|
+
declare const DropdownMenu: React.FC<DropdownMenuPrimitive.DropdownMenuProps>;
|
|
32
|
+
declare const DropdownMenuTrigger: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuTriggerProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
33
|
+
declare const DropdownMenuGroup: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuGroupProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
34
|
+
declare const DropdownMenuPortal: React.FC<DropdownMenuPrimitive.DropdownMenuPortalProps>;
|
|
35
|
+
declare const DropdownMenuSub: React.FC<DropdownMenuPrimitive.DropdownMenuSubProps>;
|
|
36
|
+
declare const DropdownMenuRadioGroup: React.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuRadioGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
37
|
+
interface DropdownMenuContentProps extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> {
|
|
38
|
+
size?: SizeKey;
|
|
39
|
+
/** 最小寬度(px),預設跟隨觸發元件寬度 */
|
|
40
|
+
minWidth?: number;
|
|
41
|
+
/** 最大高度(px),超過時捲動 */
|
|
42
|
+
maxHeight?: number;
|
|
43
|
+
}
|
|
44
|
+
declare const DropdownMenuContent: React.ForwardRefExoticComponent<DropdownMenuContentProps & React.RefAttributes<HTMLDivElement>>;
|
|
45
|
+
declare const DropdownMenuSubContent: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuSubContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
46
|
+
interface DropdownMenuItemProps extends Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>, 'children'> {
|
|
47
|
+
children: React.ReactNode;
|
|
48
|
+
/** 左側 icon */
|
|
49
|
+
startIcon?: LucideIcon;
|
|
50
|
+
/** 左側頭像資料(AvatarData),與 startIcon 互斥 */
|
|
51
|
+
avatar?: AvatarData;
|
|
52
|
+
/** 次要說明文字 */
|
|
53
|
+
description?: React.ReactNode;
|
|
54
|
+
/** 後綴 Tag(ReactNode) */
|
|
55
|
+
tag?: React.ReactNode;
|
|
56
|
+
/** 後綴 Badge(ReactNode) */
|
|
57
|
+
badge?: React.ReactNode;
|
|
58
|
+
/** 後綴指示型 icon(LucideIcon),fg-muted */
|
|
59
|
+
endIcon?: LucideIcon;
|
|
60
|
+
/** 鍵盤快捷鍵 */
|
|
61
|
+
shortcut?: string;
|
|
62
|
+
/** 單選選中(bg-neutral-selected,持續選中狀態)*/
|
|
63
|
+
selected?: boolean;
|
|
64
|
+
}
|
|
65
|
+
declare const DropdownMenuItem: React.ForwardRefExoticComponent<DropdownMenuItemProps & React.RefAttributes<HTMLDivElement>>;
|
|
66
|
+
interface DropdownMenuSubTriggerProps extends Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger>, 'children'> {
|
|
67
|
+
children: React.ReactNode;
|
|
68
|
+
/** 左側 icon */
|
|
69
|
+
startIcon?: LucideIcon;
|
|
70
|
+
/** 子選單目前狀態值文字(如 "深色") */
|
|
71
|
+
value?: string;
|
|
72
|
+
/** 子選單狀態 badge */
|
|
73
|
+
badge?: React.ReactNode;
|
|
74
|
+
}
|
|
75
|
+
declare const DropdownMenuSubTrigger: React.ForwardRefExoticComponent<DropdownMenuSubTriggerProps & React.RefAttributes<HTMLDivElement>>;
|
|
76
|
+
interface DropdownMenuCheckboxItemProps extends Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>, 'children'> {
|
|
77
|
+
children: React.ReactNode;
|
|
78
|
+
/** 左側 icon */
|
|
79
|
+
startIcon?: LucideIcon;
|
|
80
|
+
/** 次要說明文字 */
|
|
81
|
+
description?: React.ReactNode;
|
|
82
|
+
}
|
|
83
|
+
declare const DropdownMenuCheckboxItem: React.ForwardRefExoticComponent<DropdownMenuCheckboxItemProps & React.RefAttributes<HTMLDivElement>>;
|
|
84
|
+
declare const DropdownMenuLabel: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuLabelProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
85
|
+
declare const DropdownMenuSeparator: React.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuSeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
86
|
+
interface DropdownMenuRadioItemProps extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem> {
|
|
87
|
+
/** Prefix icon(LucideIcon) */
|
|
88
|
+
startIcon?: LucideIcon;
|
|
89
|
+
/** 次要說明文字 */
|
|
90
|
+
description?: React.ReactNode;
|
|
91
|
+
}
|
|
92
|
+
declare const DropdownMenuRadioItem: React.ForwardRefExoticComponent<DropdownMenuRadioItemProps & React.RefAttributes<HTMLDivElement>>;
|
|
93
|
+
declare const DropdownMenuShortcut: {
|
|
94
|
+
({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>): import("react/jsx-runtime").JSX.Element;
|
|
95
|
+
displayName: string;
|
|
96
|
+
};
|
|
97
|
+
export declare const dropdownMenuMeta: {
|
|
98
|
+
readonly component: "DropdownMenu";
|
|
99
|
+
readonly family: null;
|
|
100
|
+
readonly variants: {};
|
|
101
|
+
readonly sizes: {};
|
|
102
|
+
readonly states: readonly ["default", "hover", "active", "focus-visible", "disabled"];
|
|
103
|
+
readonly tokens: {
|
|
104
|
+
readonly bg: readonly ["bg-neutral-hover", "bg-surface-raised", "bg-transparent"];
|
|
105
|
+
readonly fg: readonly ["text-fg-disabled", "text-fg-muted"];
|
|
106
|
+
readonly ring: readonly [];
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup, DropdownMenuPortal, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuShortcut, floatingLayerClass, };
|
|
110
|
+
export type { SizeKey, DropdownMenuItemProps };
|
|
111
|
+
//# sourceMappingURL=dropdown-menu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../../src/components/DropdownMenu/dropdown-menu.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
4
|
+
import { ChevronRight } from "lucide-react";
|
|
5
|
+
import { cn } from "../../lib/utils.js";
|
|
6
|
+
import { MenuItem } from "../Menu/menu-item.js";
|
|
7
|
+
import { ScrollArea } from "../ScrollArea/scroll-area.js";
|
|
8
|
+
import { OVERLAY_COLLISION_PADDING, OVERLAY_SIDE_OFFSET } from "../../tokens/elevation/overlay-geometry.js";
|
|
9
|
+
import { useRowSize, RowSizeProvider, ICON_SIZE as ICON_SIZE$1 } from "../../patterns/element-anatomy/item-anatomy.js";
|
|
10
|
+
const floatingLayerClass = [
|
|
11
|
+
"z-50 overflow-hidden rounded-lg border border-border bg-surface-raised",
|
|
12
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out motion-reduce:animate-none",
|
|
13
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
14
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
15
|
+
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
|
|
16
|
+
"data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
17
|
+
"origin-[var(--radix-dropdown-menu-content-transform-origin)]"
|
|
18
|
+
].join(" ");
|
|
19
|
+
const ICON_SIZE = ICON_SIZE$1;
|
|
20
|
+
const radixItemClass = [
|
|
21
|
+
"relative cursor-pointer select-none outline-none",
|
|
22
|
+
"transition-colors duration-150",
|
|
23
|
+
"data-[highlighted]:bg-neutral-hover",
|
|
24
|
+
"data-[disabled]:pointer-events-none data-[disabled]:text-fg-disabled data-[disabled]:cursor-default"
|
|
25
|
+
].join(" ");
|
|
26
|
+
const DropdownMenu = DropdownMenuPrimitive.Root;
|
|
27
|
+
const DropdownMenuTrigger = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
28
|
+
DropdownMenuPrimitive.Trigger,
|
|
29
|
+
{
|
|
30
|
+
ref,
|
|
31
|
+
className: cn("outline-none", className),
|
|
32
|
+
...props
|
|
33
|
+
}
|
|
34
|
+
));
|
|
35
|
+
DropdownMenuTrigger.displayName = DropdownMenuPrimitive.Trigger.displayName;
|
|
36
|
+
const DropdownMenuGroup = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
37
|
+
DropdownMenuPrimitive.Group,
|
|
38
|
+
{
|
|
39
|
+
ref,
|
|
40
|
+
className: cn("[&+&]:border-t [&+&]:border-divider [&+&]:mt-2 [&+&]:pt-2", className),
|
|
41
|
+
...props
|
|
42
|
+
}
|
|
43
|
+
));
|
|
44
|
+
DropdownMenuGroup.displayName = "DropdownMenuGroup";
|
|
45
|
+
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
|
46
|
+
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
|
47
|
+
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
|
48
|
+
const DropdownMenuContent = React.forwardRef(({ className, size = "md", sideOffset = OVERLAY_SIDE_OFFSET, collisionPadding = OVERLAY_COLLISION_PADDING, align = "start", minWidth, maxHeight, children, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
49
|
+
DropdownMenuPrimitive.Content,
|
|
50
|
+
{
|
|
51
|
+
ref,
|
|
52
|
+
sideOffset,
|
|
53
|
+
collisionPadding,
|
|
54
|
+
align,
|
|
55
|
+
onCloseAutoFocus: (e) => e.preventDefault(),
|
|
56
|
+
className: cn(floatingLayerClass, !maxHeight && "py-2", className),
|
|
57
|
+
style: {
|
|
58
|
+
boxShadow: "var(--elevation-200)",
|
|
59
|
+
minWidth: minWidth ?? "max(180px, var(--radix-dropdown-menu-trigger-width))",
|
|
60
|
+
maxHeight
|
|
61
|
+
},
|
|
62
|
+
...props,
|
|
63
|
+
children: /* @__PURE__ */ jsx(RowSizeProvider, { value: size, children: maxHeight ? (
|
|
64
|
+
// 長選單用 ScrollArea 跨 OS 一致捲動(不吃寬度,macOS/Windows 視覺一致)
|
|
65
|
+
// py-2 移到內層,ScrollArea Viewport 才能 scroll 整個 padded 區
|
|
66
|
+
/* @__PURE__ */ jsx(ScrollArea, { className: "max-h-[inherit]", children: /* @__PURE__ */ jsx("div", { className: "py-2", children }) })
|
|
67
|
+
) : children })
|
|
68
|
+
}
|
|
69
|
+
) }));
|
|
70
|
+
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
|
71
|
+
const DropdownMenuSubContent = React.forwardRef(({ className, children, ...props }, ref) => {
|
|
72
|
+
const size = useRowSize();
|
|
73
|
+
return /* @__PURE__ */ jsx(
|
|
74
|
+
DropdownMenuPrimitive.SubContent,
|
|
75
|
+
{
|
|
76
|
+
ref,
|
|
77
|
+
sideOffset: OVERLAY_SIDE_OFFSET,
|
|
78
|
+
className: cn(floatingLayerClass, "py-2", className),
|
|
79
|
+
style: { boxShadow: "var(--elevation-200)", minWidth: 180 },
|
|
80
|
+
...props,
|
|
81
|
+
children: /* @__PURE__ */ jsx(RowSizeProvider, { value: size, children })
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
|
|
86
|
+
function buildEndContent(size, badge, endIcon, shortcut) {
|
|
87
|
+
const EndIcon = endIcon;
|
|
88
|
+
if (!badge && !EndIcon && !shortcut) return void 0;
|
|
89
|
+
const iconPx = ICON_SIZE[size];
|
|
90
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
91
|
+
badge,
|
|
92
|
+
EndIcon && /* @__PURE__ */ jsx(EndIcon, { size: iconPx, className: "text-fg-muted", "aria-hidden": true }),
|
|
93
|
+
shortcut && /* @__PURE__ */ jsx("span", { className: "text-caption text-fg-muted", children: shortcut })
|
|
94
|
+
] });
|
|
95
|
+
}
|
|
96
|
+
const DropdownMenuItem = React.forwardRef(({ className, children, startIcon, avatar, description, tag, badge, endIcon, shortcut, selected, disabled, ...props }, ref) => {
|
|
97
|
+
const size = useRowSize();
|
|
98
|
+
const endContent = buildEndContent(size, badge, endIcon, shortcut);
|
|
99
|
+
return /* @__PURE__ */ jsx(
|
|
100
|
+
DropdownMenuPrimitive.Item,
|
|
101
|
+
{
|
|
102
|
+
ref,
|
|
103
|
+
disabled,
|
|
104
|
+
className: cn(
|
|
105
|
+
radixItemClass,
|
|
106
|
+
selected && "bg-neutral-selected",
|
|
107
|
+
className
|
|
108
|
+
),
|
|
109
|
+
...props,
|
|
110
|
+
children: /* @__PURE__ */ jsx(
|
|
111
|
+
MenuItem,
|
|
112
|
+
{
|
|
113
|
+
size,
|
|
114
|
+
startIcon,
|
|
115
|
+
avatar,
|
|
116
|
+
description,
|
|
117
|
+
tag,
|
|
118
|
+
endContent,
|
|
119
|
+
disabled,
|
|
120
|
+
role: "presentation",
|
|
121
|
+
className: "!bg-transparent hover:!bg-transparent pointer-events-none",
|
|
122
|
+
children
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
|
129
|
+
const DropdownMenuSubTrigger = React.forwardRef(({ className, children, startIcon, value, badge, ...props }, ref) => {
|
|
130
|
+
const size = useRowSize();
|
|
131
|
+
const iconPx = ICON_SIZE[size];
|
|
132
|
+
const endContent = /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
133
|
+
value && /* @__PURE__ */ jsx("span", { className: "text-fg-muted", children: value }),
|
|
134
|
+
badge,
|
|
135
|
+
/* @__PURE__ */ jsx(ChevronRight, { size: iconPx, className: "text-fg-muted" })
|
|
136
|
+
] });
|
|
137
|
+
return /* @__PURE__ */ jsx(
|
|
138
|
+
DropdownMenuPrimitive.SubTrigger,
|
|
139
|
+
{
|
|
140
|
+
ref,
|
|
141
|
+
className: cn(
|
|
142
|
+
radixItemClass,
|
|
143
|
+
"data-[state=open]:bg-neutral-hover",
|
|
144
|
+
className
|
|
145
|
+
),
|
|
146
|
+
...props,
|
|
147
|
+
children: /* @__PURE__ */ jsx(
|
|
148
|
+
MenuItem,
|
|
149
|
+
{
|
|
150
|
+
size,
|
|
151
|
+
startIcon,
|
|
152
|
+
endContent,
|
|
153
|
+
role: "presentation",
|
|
154
|
+
className: "!bg-transparent hover:!bg-transparent pointer-events-none",
|
|
155
|
+
children
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
|
|
162
|
+
const DropdownMenuCheckboxItem = React.forwardRef(({ className, children, startIcon, description, checked, disabled, ...props }, ref) => {
|
|
163
|
+
const size = useRowSize();
|
|
164
|
+
return /* @__PURE__ */ jsx(
|
|
165
|
+
DropdownMenuPrimitive.CheckboxItem,
|
|
166
|
+
{
|
|
167
|
+
ref,
|
|
168
|
+
checked,
|
|
169
|
+
disabled,
|
|
170
|
+
onSelect: (e) => e.preventDefault(),
|
|
171
|
+
className: cn(radixItemClass, className),
|
|
172
|
+
...props,
|
|
173
|
+
children: /* @__PURE__ */ jsx(
|
|
174
|
+
MenuItem,
|
|
175
|
+
{
|
|
176
|
+
size,
|
|
177
|
+
checkbox: true,
|
|
178
|
+
checked: !!checked,
|
|
179
|
+
startIcon,
|
|
180
|
+
description,
|
|
181
|
+
disabled,
|
|
182
|
+
role: "presentation",
|
|
183
|
+
className: "!bg-transparent hover:!bg-transparent pointer-events-none",
|
|
184
|
+
children
|
|
185
|
+
}
|
|
186
|
+
)
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
});
|
|
190
|
+
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
|
|
191
|
+
const DropdownMenuLabel = React.forwardRef(({ className, children, ...props }, ref) => {
|
|
192
|
+
const size = useRowSize();
|
|
193
|
+
return /* @__PURE__ */ jsx(
|
|
194
|
+
DropdownMenuPrimitive.Label,
|
|
195
|
+
{
|
|
196
|
+
ref,
|
|
197
|
+
className: cn("outline-none", className),
|
|
198
|
+
...props,
|
|
199
|
+
children: /* @__PURE__ */ jsx(
|
|
200
|
+
MenuItem,
|
|
201
|
+
{
|
|
202
|
+
size,
|
|
203
|
+
header: true,
|
|
204
|
+
role: "presentation",
|
|
205
|
+
className: "pointer-events-none",
|
|
206
|
+
children
|
|
207
|
+
}
|
|
208
|
+
)
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
});
|
|
212
|
+
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
|
213
|
+
const DropdownMenuSeparator = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
214
|
+
DropdownMenuPrimitive.Separator,
|
|
215
|
+
{
|
|
216
|
+
ref,
|
|
217
|
+
className: cn("my-2 h-px bg-divider", className),
|
|
218
|
+
...props
|
|
219
|
+
}
|
|
220
|
+
));
|
|
221
|
+
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
|
|
222
|
+
const DropdownMenuRadioItem = React.forwardRef(({ className, children, startIcon, description, disabled, ...props }, ref) => {
|
|
223
|
+
const size = useRowSize();
|
|
224
|
+
return /* @__PURE__ */ jsx(
|
|
225
|
+
DropdownMenuPrimitive.RadioItem,
|
|
226
|
+
{
|
|
227
|
+
ref,
|
|
228
|
+
disabled,
|
|
229
|
+
onSelect: (e) => e.preventDefault(),
|
|
230
|
+
className: cn(radixItemClass, "data-[state=checked]:[&>*]:bg-neutral-selected", className),
|
|
231
|
+
...props,
|
|
232
|
+
children: /* @__PURE__ */ jsx(
|
|
233
|
+
MenuItem,
|
|
234
|
+
{
|
|
235
|
+
size,
|
|
236
|
+
startIcon,
|
|
237
|
+
description,
|
|
238
|
+
disabled,
|
|
239
|
+
role: "presentation",
|
|
240
|
+
className: "!bg-transparent hover:!bg-transparent pointer-events-none",
|
|
241
|
+
children
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
});
|
|
247
|
+
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
|
248
|
+
const DropdownMenuShortcut = ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
249
|
+
"span",
|
|
250
|
+
{
|
|
251
|
+
className: cn("ml-auto text-footnote text-fg-muted tracking-shortcut", className),
|
|
252
|
+
...props
|
|
253
|
+
}
|
|
254
|
+
);
|
|
255
|
+
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
|
256
|
+
const dropdownMenuMeta = {
|
|
257
|
+
component: "DropdownMenu",
|
|
258
|
+
family: null,
|
|
259
|
+
// non-family composite / overlay / layout
|
|
260
|
+
variants: {},
|
|
261
|
+
sizes: {},
|
|
262
|
+
states: ["default", "hover", "active", "focus-visible", "disabled"],
|
|
263
|
+
tokens: {
|
|
264
|
+
bg: ["bg-neutral-hover", "bg-surface-raised", "bg-transparent"],
|
|
265
|
+
fg: ["text-fg-disabled", "text-fg-muted"],
|
|
266
|
+
ring: []
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
export {
|
|
270
|
+
DropdownMenu,
|
|
271
|
+
DropdownMenuCheckboxItem,
|
|
272
|
+
DropdownMenuContent,
|
|
273
|
+
DropdownMenuGroup,
|
|
274
|
+
DropdownMenuItem,
|
|
275
|
+
DropdownMenuLabel,
|
|
276
|
+
DropdownMenuPortal,
|
|
277
|
+
DropdownMenuRadioGroup,
|
|
278
|
+
DropdownMenuRadioItem,
|
|
279
|
+
DropdownMenuSeparator,
|
|
280
|
+
DropdownMenuShortcut,
|
|
281
|
+
DropdownMenuSub,
|
|
282
|
+
DropdownMenuSubContent,
|
|
283
|
+
DropdownMenuSubTrigger,
|
|
284
|
+
DropdownMenuTrigger,
|
|
285
|
+
dropdownMenuMeta,
|
|
286
|
+
floatingLayerClass
|
|
287
|
+
};
|
|
288
|
+
//# sourceMappingURL=dropdown-menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dropdown-menu.js","sources":["../../../src/components/DropdownMenu/dropdown-menu.tsx"],"sourcesContent":["import * as React from \"react\"\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\"\nimport { ChevronRight, type LucideIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport type { AvatarData } from \"@/design-system/components/Avatar/avatar\"\nimport { MenuItem } from \"@/design-system/components/Menu/menu-item\"\nimport { ScrollArea } from \"@/design-system/components/ScrollArea/scroll-area\"\nimport { OVERLAY_SIDE_OFFSET, OVERLAY_COLLISION_PADDING } from \"@/design-system/tokens/elevation/overlay-geometry\"\nimport {\n RowSizeProvider,\n useRowSize,\n ICON_SIZE as ROW_ICON_SIZE,\n type RowSize,\n} from \"@/design-system/patterns/element-anatomy/item-anatomy\"\n\n/**\n * DropdownMenu — Radix DropdownMenu + MenuItem visual layer\n *\n * 架構分工:\n * - Radix primitives:behavior(keyboard nav, focus management, aria roles)\n * - MenuItem:visual(layout, padding, icon alignment, typography)\n *\n * Radix primitive 是外層容器,控制 `data-[highlighted]:bg-neutral-hover`。\n * MenuItem 內層只負責佈局,不加互動樣式。\n *\n * ── Hover / highlight canonical(2026-04-22 修正)──\n * 用 Radix 官方的 `data-[highlighted]` attribute,**不用 `:focus-visible` / `:hover` /\n * `:focus`**:\n * - Radix 在 **mouse hover、keyboard arrow nav、focus move in** 時自動 set `data-highlighted`\n * - mouse leave / focus move out / menu close 時自動清掉\n * - 不會在 click 後留殘影(Radix 內部已處理)\n * - 跨瀏覽器一致(不依賴 `:focus-visible` 的 heuristic)\n *\n * 曾經用過 `focus-visible:bg-neutral-hover` 的理由:避免 click 後殘影。但實測:mouse hover\n * 觸發 Radix 程式化 `.focus()`,Chromium / Safari / Firefox 對 programmatic focus 是否 fire\n * `:focus-visible` 行為不一致,導致 mouse hover 有時無 bg。改用 `data-[highlighted]:` 後行為\n * 一致 —— 世界級 canonical(shadcn / Radix docs / Ariakit 皆此)。\n */\n\n// ── Floating layer 共用樣式 ──\nconst floatingLayerClass = [\n 'z-50 overflow-hidden rounded-lg border border-border bg-surface-raised',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out motion-reduce:animate-none',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2',\n 'data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n 'origin-[var(--radix-dropdown-menu-content-transform-origin)]',\n].join(' ')\n\n// ── Size:統一用 RowSizeContext(item-layout module),消除本地 SizeContext 漂移 ──\ntype SizeKey = RowSize\n// Re-export for backward compat(內部命名)\nconst ICON_SIZE = ROW_ICON_SIZE\n\n// ── Shared item classes on Radix primitive ──\n// Highlight(hover + keyboard nav): 用 Radix `data-[highlighted]` canonical(見 docblock)\nconst radixItemClass = [\n 'relative cursor-pointer select-none outline-none',\n 'transition-colors duration-150',\n 'data-[highlighted]:bg-neutral-hover',\n 'data-[disabled]:pointer-events-none data-[disabled]:text-fg-disabled data-[disabled]:cursor-default',\n].join(' ')\n\n// ── Root ──\nconst DropdownMenu = DropdownMenuPrimitive.Root\nconst DropdownMenuTrigger = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Trigger\n ref={ref}\n className={cn('outline-none', className)}\n {...props}\n />\n))\nDropdownMenuTrigger.displayName = DropdownMenuPrimitive.Trigger.displayName\n// DropdownMenuGroup — 對齊 MenuGroup 的 group separation 設計語言\n//\n// 設計語言(跨 Menu-like 元件統一,SSOT 見 item-anatomy.spec.md\n// 「Group auto-separation」):\n// 每個 group 上下各 8px padding,相鄰 group 之間用 border-divider 分隔\n// 兩個 group 之間視覺 gap = 8px(上一個 bottom)+ 8px(下一個 top)= 16px + border\n//\n// MenuGroup(menu-item.tsx)實作:`py-2 [&+&]:border-t [&+&]:border-divider`\n// (在 Command.List 下提供 Content 邊界 8px + group 間 16px gap)\n//\n// DropdownMenuGroup(本元件)實作:`[&+&]:mt-2 [&+&]:pt-2 [&+&]:border-t\n// [&+&]:border-divider`(因為 DropdownMenuContent 已有 py-2 提供 Content 邊界\n// 的 8px,只需在第二個起的 group 加 8+8 = 16px gap + border)\n//\n// **視覺結果等同**:兩種實作的 visual output 一致,只是「padding 住在哪層」\n// 不同。不強制統一 CSS 表達式——DropdownMenuContent 的 py-2 是既有 Radix\n// 期望的行為,移除會影響 trigger 鍵盤導覽的 focus offset。\nconst DropdownMenuGroup = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Group\n ref={ref}\n className={cn('[&+&]:border-t [&+&]:border-divider [&+&]:mt-2 [&+&]:pt-2', className)}\n {...props}\n />\n))\nDropdownMenuGroup.displayName = 'DropdownMenuGroup'\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup\n\n// ── Content ──\ninterface DropdownMenuContentProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> {\n size?: SizeKey\n /** 最小寬度(px),預設跟隨觸發元件寬度 */\n minWidth?: number\n /** 最大高度(px),超過時捲動 */\n maxHeight?: number\n}\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n DropdownMenuContentProps\n>(({ className, size = 'md', sideOffset = OVERLAY_SIDE_OFFSET, collisionPadding = OVERLAY_COLLISION_PADDING, align = 'start', minWidth, maxHeight, children, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n align={align}\n onCloseAutoFocus={(e) => e.preventDefault()}\n className={cn(floatingLayerClass, !maxHeight && 'py-2', className)}\n style={{\n boxShadow: 'var(--elevation-200)',\n minWidth: minWidth ?? 'max(180px, var(--radix-dropdown-menu-trigger-width))',\n maxHeight,\n }}\n {...props}\n >\n <RowSizeProvider value={size}>\n {maxHeight ? (\n // 長選單用 ScrollArea 跨 OS 一致捲動(不吃寬度,macOS/Windows 視覺一致)\n // py-2 移到內層,ScrollArea Viewport 才能 scroll 整個 padded 區\n <ScrollArea className=\"max-h-[inherit]\">\n <div className=\"py-2\">{children}</div>\n </ScrollArea>\n ) : (\n children\n )}\n </RowSizeProvider>\n </DropdownMenuPrimitive.Content>\n </DropdownMenuPrimitive.Portal>\n))\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName\n\n// ── SubContent ──\nconst DropdownMenuSubContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, children, ...props }, ref) => {\n const size = useRowSize()\n return (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n sideOffset={OVERLAY_SIDE_OFFSET}\n className={cn(floatingLayerClass, 'py-2', className)}\n style={{ boxShadow: 'var(--elevation-200)', minWidth: 180 }}\n {...props}\n >\n <RowSizeProvider value={size}>\n {children}\n </RowSizeProvider>\n </DropdownMenuPrimitive.SubContent>\n )\n})\nDropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName\n\n// ── Helper: build endContent from badge + endIcon + shortcut ──\nfunction buildEndContent(\n size: SizeKey,\n badge?: React.ReactNode,\n endIcon?: LucideIcon,\n shortcut?: string,\n): React.ReactNode | undefined {\n const EndIcon = endIcon\n if (!badge && !EndIcon && !shortcut) return undefined\n const iconPx = ICON_SIZE[size]\n return (\n <>\n {badge}\n {EndIcon && <EndIcon size={iconPx} className=\"text-fg-muted\" aria-hidden />}\n {shortcut && <span className=\"text-caption text-fg-muted\">{shortcut}</span>}\n </>\n )\n}\n\n// ── Item ──\ninterface DropdownMenuItemProps\n extends Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item>, 'children'> {\n children: React.ReactNode\n /** 左側 icon */\n startIcon?: LucideIcon\n /** 左側頭像資料(AvatarData),與 startIcon 互斥 */\n avatar?: AvatarData\n /** 次要說明文字 */\n description?: React.ReactNode\n /** 後綴 Tag(ReactNode) */\n tag?: React.ReactNode\n /** 後綴 Badge(ReactNode) */\n badge?: React.ReactNode\n /** 後綴指示型 icon(LucideIcon),fg-muted */\n endIcon?: LucideIcon\n /** 鍵盤快捷鍵 */\n shortcut?: string\n /** 單選選中(bg-neutral-selected,持續選中狀態)*/\n selected?: boolean\n}\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n DropdownMenuItemProps\n>(({ className, children, startIcon, avatar, description, tag, badge, endIcon, shortcut, selected, disabled, ...props }, ref) => {\n const size = useRowSize()\n const endContent = buildEndContent(size, badge, endIcon, shortcut)\n\n return (\n <DropdownMenuPrimitive.Item\n ref={ref}\n disabled={disabled}\n className={cn(\n radixItemClass,\n selected && 'bg-neutral-selected',\n className,\n )}\n {...props}\n >\n <MenuItem\n size={size}\n startIcon={startIcon}\n avatar={avatar}\n description={description}\n tag={tag}\n endContent={endContent}\n disabled={disabled}\n // Pure visual — Radix parent handles role/aria/interaction\n role=\"presentation\"\n className=\"!bg-transparent hover:!bg-transparent pointer-events-none\"\n >\n {children}\n </MenuItem>\n </DropdownMenuPrimitive.Item>\n )\n})\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName\n\n// ── SubTrigger(子選單觸發器,自動附加 ChevronRight)──\ninterface DropdownMenuSubTriggerProps\n extends Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger>, 'children'> {\n children: React.ReactNode\n /** 左側 icon */\n startIcon?: LucideIcon\n /** 子選單目前狀態值文字(如 \"深色\") */\n value?: string\n /** 子選單狀態 badge */\n badge?: React.ReactNode\n}\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n DropdownMenuSubTriggerProps\n>(({ className, children, startIcon, value, badge, ...props }, ref) => {\n const size = useRowSize()\n const iconPx = ICON_SIZE[size]\n\n // SubTrigger suffix: [value?] [badge?] [ChevronRight] with gap-1\n const endContent = (\n <div className=\"flex items-center gap-1\">\n {value && <span className=\"text-fg-muted\">{value}</span>}\n {badge}\n <ChevronRight size={iconPx} className=\"text-fg-muted\" />\n </div>\n )\n\n return (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n radixItemClass,\n 'data-[state=open]:bg-neutral-hover',\n className,\n )}\n {...props}\n >\n <MenuItem\n size={size}\n startIcon={startIcon}\n endContent={endContent}\n role=\"presentation\"\n className=\"!bg-transparent hover:!bg-transparent pointer-events-none\"\n >\n {children}\n </MenuItem>\n </DropdownMenuPrimitive.SubTrigger>\n )\n})\nDropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName\n\n// ── CheckboxItem ──\ninterface DropdownMenuCheckboxItemProps\n extends Omit<React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>, 'children'> {\n children: React.ReactNode\n /** 左側 icon */\n startIcon?: LucideIcon\n /** 次要說明文字 */\n description?: React.ReactNode\n}\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n DropdownMenuCheckboxItemProps\n>(({ className, children, startIcon, description, checked, disabled, ...props }, ref) => {\n const size = useRowSize()\n\n return (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n checked={checked}\n disabled={disabled}\n onSelect={(e) => e.preventDefault()}\n className={cn(radixItemClass, className)}\n {...props}\n >\n <MenuItem\n size={size}\n checkbox\n checked={!!checked}\n startIcon={startIcon}\n description={description}\n disabled={disabled}\n role=\"presentation\"\n className=\"!bg-transparent hover:!bg-transparent pointer-events-none\"\n >\n {children}\n </MenuItem>\n </DropdownMenuPrimitive.CheckboxItem>\n )\n})\nDropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName\n\n// ── Label(群組標題)──\nconst DropdownMenuLabel = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label>\n>(({ className, children, ...props }, ref) => {\n const size = useRowSize()\n return (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn('outline-none', className)}\n {...props}\n >\n <MenuItem\n size={size}\n header\n role=\"presentation\"\n className=\"pointer-events-none\"\n >\n {children}\n </MenuItem>\n </DropdownMenuPrimitive.Label>\n )\n})\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName\n\n// ── Separator ──\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"my-2 h-px bg-divider\", className)}\n {...props}\n />\n))\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName\n\n// ── RadioItem(單選,排序方式等)──\n// Radix handles checked state; visual用 MenuItem 的 selected highlight。\ninterface DropdownMenuRadioItemProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem> {\n /** Prefix icon(LucideIcon) */\n startIcon?: LucideIcon\n /** 次要說明文字 */\n description?: React.ReactNode\n}\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n DropdownMenuRadioItemProps\n>(({ className, children, startIcon, description, disabled, ...props }, ref) => {\n const size = useRowSize()\n\n return (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n disabled={disabled}\n onSelect={(e) => e.preventDefault()}\n className={cn(radixItemClass, 'data-[state=checked]:[&>*]:bg-neutral-selected', className)}\n {...props}\n >\n <MenuItem\n size={size}\n startIcon={startIcon}\n description={description}\n disabled={disabled}\n role=\"presentation\"\n className=\"!bg-transparent hover:!bg-transparent pointer-events-none\"\n >\n {children}\n </MenuItem>\n </DropdownMenuPrimitive.RadioItem>\n )\n})\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName\n\n// ── Shortcut(鍵盤快捷鍵提示,ml-auto 靠右)──\n// 作為 MenuItem children 的後綴,視覺為 fg-muted 小字。\nconst DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => (\n <span\n className={cn('ml-auto text-footnote text-fg-muted tracking-shortcut', className)}\n {...props}\n />\n)\nDropdownMenuShortcut.displayName = 'DropdownMenuShortcut'\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 dropdownMenuMeta = {\n component: 'DropdownMenu',\n family: null, // non-family composite / overlay / layout\n variants: {\n\n },\n sizes: {\n\n },\n states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],\n tokens: {\n bg: ['bg-neutral-hover', 'bg-surface-raised', 'bg-transparent'],\n fg: ['text-fg-disabled', 'text-fg-muted'],\n ring: [],\n },\n} as const\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuGroup,\n DropdownMenuPortal,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuShortcut,\n floatingLayerClass,\n}\nexport type { SizeKey, DropdownMenuItemProps }\n"],"names":["ROW_ICON_SIZE"],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { LucideIcon } from 'lucide-react';
|
|
3
|
+
/**
|
|
4
|
+
* Empty — 空狀態視覺元件
|
|
5
|
+
*
|
|
6
|
+
* 居中垂直堆疊:icon(Avatar) → title → description → action。
|
|
7
|
+
* 所有 slot 皆可選,預設只需 description。
|
|
8
|
+
*
|
|
9
|
+
* 間距固定,不隨 density 變(Empty 是展示性元件,不是工作區域元件):
|
|
10
|
+
* icon → text = mb-4(16px)
|
|
11
|
+
* desc → action = mt-6(24px)
|
|
12
|
+
* title → desc = `var(--item-gap-label-desc)`(token,預設 2px,item-anatomy SSOT)
|
|
13
|
+
*
|
|
14
|
+
* Outer padding 由 consumer 容器決定(py-12 / py-6 / py-16 等)。
|
|
15
|
+
*/
|
|
16
|
+
export interface EmptyProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
17
|
+
/** LucideIcon → 自動包 Avatar 48px neutral;ReactElement → 原樣渲染 */
|
|
18
|
+
icon?: LucideIcon | React.ReactElement;
|
|
19
|
+
/** 標題(可選,font-medium,適用於首次引導) */
|
|
20
|
+
title?: string;
|
|
21
|
+
/** 說明文字 */
|
|
22
|
+
description?: string;
|
|
23
|
+
/** 行動按鈕(可選) */
|
|
24
|
+
action?: React.ReactNode;
|
|
25
|
+
}
|
|
26
|
+
declare const Empty: React.ForwardRefExoticComponent<EmptyProps & React.RefAttributes<HTMLDivElement>>;
|
|
27
|
+
export declare const emptyMeta: {
|
|
28
|
+
readonly component: "Empty";
|
|
29
|
+
readonly family: null;
|
|
30
|
+
readonly variants: {};
|
|
31
|
+
readonly sizes: {};
|
|
32
|
+
readonly states: readonly ["default", "hover", "active", "focus-visible", "disabled"];
|
|
33
|
+
readonly tokens: {
|
|
34
|
+
readonly bg: readonly [];
|
|
35
|
+
readonly fg: readonly ["text-fg-muted", "text-fg-secondary", "text-foreground"];
|
|
36
|
+
readonly ring: readonly [];
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
export { Empty };
|
|
40
|
+
//# sourceMappingURL=empty.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty.d.ts","sourceRoot":"","sources":["../../../src/components/Empty/empty.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAK9C;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,UAAW,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACtE,+DAA+D;IAC/D,IAAI,CAAC,EAAE,UAAU,GAAG,KAAK,CAAC,YAAY,CAAA;IACtC,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe;IACf,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACzB;AAED,QAAA,MAAM,KAAK,mFAsDV,CAAA;AAKD,eAAO,MAAM,SAAS;;;;;;;;;;;CAeZ,CAAA;AAEV,OAAO,EAAE,KAAK,EAAE,CAAA"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
import { Avatar } from "../Avatar/avatar.js";
|
|
5
|
+
import { useRowSize } from "../../patterns/element-anatomy/item-anatomy.js";
|
|
6
|
+
const Empty = React.forwardRef(
|
|
7
|
+
({ icon, title, description, action, className, ...props }, ref) => {
|
|
8
|
+
const rowSize = useRowSize("md");
|
|
9
|
+
const descFont = rowSize === "lg" ? "text-body-lg" : "text-body";
|
|
10
|
+
let iconElement = null;
|
|
11
|
+
if (icon) {
|
|
12
|
+
if (React.isValidElement(icon)) {
|
|
13
|
+
iconElement = icon;
|
|
14
|
+
} else {
|
|
15
|
+
const Icon = icon;
|
|
16
|
+
iconElement = /* @__PURE__ */ jsx(Avatar, { icon: Icon, size: 48, color: "neutral" });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return /* @__PURE__ */ jsxs(
|
|
20
|
+
"div",
|
|
21
|
+
{
|
|
22
|
+
ref,
|
|
23
|
+
className: cn("flex flex-col items-center text-center", className),
|
|
24
|
+
...props,
|
|
25
|
+
children: [
|
|
26
|
+
iconElement && /* @__PURE__ */ jsx("div", { className: "mb-4", children: iconElement }),
|
|
27
|
+
title && /* @__PURE__ */ jsx("span", { className: "text-body-lg font-medium text-foreground", children: title }),
|
|
28
|
+
description && /* @__PURE__ */ jsx(
|
|
29
|
+
"span",
|
|
30
|
+
{
|
|
31
|
+
className: cn(
|
|
32
|
+
// 字體跟 RowSizeContext 對齊:sm/md = text-body (14px),lg = text-body-lg (16px)
|
|
33
|
+
// 在 menu 內自動對齊 menu items;standalone 時 fallback text-body
|
|
34
|
+
descFont,
|
|
35
|
+
title || action ? "text-fg-secondary" : "text-fg-muted",
|
|
36
|
+
// Empty title 永遠 body-lg(16)→ 用 reading-lg token(label tier 決定)
|
|
37
|
+
title && "mt-[var(--item-gap-label-desc-reading-lg)]"
|
|
38
|
+
),
|
|
39
|
+
children: description
|
|
40
|
+
}
|
|
41
|
+
),
|
|
42
|
+
action && /* @__PURE__ */ jsx("div", { className: "mt-6", children: action })
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
Empty.displayName = "Empty";
|
|
49
|
+
const emptyMeta = {
|
|
50
|
+
component: "Empty",
|
|
51
|
+
family: null,
|
|
52
|
+
// non-family composite / overlay / layout
|
|
53
|
+
variants: {},
|
|
54
|
+
sizes: {},
|
|
55
|
+
states: ["default", "hover", "active", "focus-visible", "disabled"],
|
|
56
|
+
tokens: {
|
|
57
|
+
bg: [],
|
|
58
|
+
fg: ["text-fg-muted", "text-fg-secondary", "text-foreground"],
|
|
59
|
+
ring: []
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
export {
|
|
63
|
+
Empty,
|
|
64
|
+
emptyMeta
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=empty.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty.js","sources":["../../../src/components/Empty/empty.tsx"],"sourcesContent":["import * as React from 'react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Avatar } from '@/design-system/components/Avatar/avatar'\nimport { useRowSize } from '@/design-system/patterns/element-anatomy/item-anatomy'\n\n/**\n * Empty — 空狀態視覺元件\n *\n * 居中垂直堆疊:icon(Avatar) → title → description → action。\n * 所有 slot 皆可選,預設只需 description。\n *\n * 間距固定,不隨 density 變(Empty 是展示性元件,不是工作區域元件):\n * icon → text = mb-4(16px)\n * desc → action = mt-6(24px)\n * title → desc = `var(--item-gap-label-desc)`(token,預設 2px,item-anatomy SSOT)\n *\n * Outer padding 由 consumer 容器決定(py-12 / py-6 / py-16 等)。\n */\n\nexport interface EmptyProps extends React.HTMLAttributes<HTMLDivElement> {\n /** LucideIcon → 自動包 Avatar 48px neutral;ReactElement → 原樣渲染 */\n icon?: LucideIcon | React.ReactElement\n /** 標題(可選,font-medium,適用於首次引導) */\n title?: string\n /** 說明文字 */\n description?: string\n /** 行動按鈕(可選) */\n action?: React.ReactNode\n}\n\nconst Empty = React.forwardRef<HTMLDivElement, EmptyProps>(\n ({ icon, title, description, action, className, ...props }, ref) => {\n // 字體 tier:讀 RowSizeContext(menu 內自動對齊 menu items 的字體)\n // 沒有 context(standalone)→ fallback 'md' → text-body (14px)\n const rowSize = useRowSize('md')\n const descFont = rowSize === 'lg' ? 'text-body-lg' : 'text-body'\n\n // Icon rendering: ReactElement → as-is;LucideIcon(component,包括 forwardRef 物件)→ 包 Avatar\n // 注意:Lucide v0.577+ icons 是 forwardRef 物件(`typeof === 'object'`),不是 function。\n // 必用 React.isValidElement 判斷 element vs component(typeof 會把 forwardRef 物件誤歸 object)。\n let iconElement: React.ReactNode = null\n if (icon) {\n if (React.isValidElement(icon)) {\n iconElement = icon\n } else {\n const Icon = icon as LucideIcon\n iconElement = <Avatar icon={Icon} size={48} color=\"neutral\" />\n }\n }\n\n return (\n <div\n ref={ref}\n className={cn('flex flex-col items-center text-center', className)}\n {...props}\n >\n {iconElement && (\n <div className=\"mb-4\">{iconElement}</div>\n )}\n {title && (\n <span className=\"text-body-lg font-medium text-foreground\">\n {title}\n </span>\n )}\n {description && (\n <span\n className={cn(\n // 字體跟 RowSizeContext 對齊:sm/md = text-body (14px),lg = text-body-lg (16px)\n // 在 menu 內自動對齊 menu items;standalone 時 fallback text-body\n descFont,\n (title || action) ? 'text-fg-secondary' : 'text-fg-muted',\n // Empty title 永遠 body-lg(16)→ 用 reading-lg token(label tier 決定)\n title && 'mt-[var(--item-gap-label-desc-reading-lg)]',\n )}\n >\n {description}\n </span>\n )}\n {action && (\n <div className=\"mt-6\">{action}</div>\n )}\n </div>\n )\n },\n)\nEmpty.displayName = 'Empty'\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 emptyMeta = {\n component: 'Empty',\n family: null, // non-family composite / overlay / layout\n variants: {\n\n },\n sizes: {\n\n },\n states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],\n tokens: {\n bg: [],\n fg: ['text-fg-muted', 'text-fg-secondary', 'text-foreground'],\n ring: [],\n },\n} as const\n\nexport { Empty }\n"],"names":[],"mappings":";;;;;AA+BA,MAAM,QAAQ,MAAM;AAAA,EAClB,CAAC,EAAE,MAAM,OAAO,aAAa,QAAQ,WAAW,GAAG,MAAA,GAAS,QAAQ;AAGlE,UAAM,UAAU,WAAW,IAAI;AAC/B,UAAM,WAAW,YAAY,OAAO,iBAAiB;AAKrD,QAAI,cAA+B;AACnC,QAAI,MAAM;AACR,UAAI,MAAM,eAAe,IAAI,GAAG;AAC9B,sBAAc;AAAA,MAChB,OAAO;AACL,cAAM,OAAO;AACb,0CAAe,QAAA,EAAO,MAAM,MAAM,MAAM,IAAI,OAAM,WAAU;AAAA,MAC9D;AAAA,IACF;AAEA,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,0CAA0C,SAAS;AAAA,QAChE,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,eACC,oBAAC,OAAA,EAAI,WAAU,QAAQ,UAAA,aAAY;AAAA,UAEpC,SACC,oBAAC,QAAA,EAAK,WAAU,4CACb,UAAA,OACH;AAAA,UAED,eACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW;AAAA;AAAA;AAAA,gBAGT;AAAA,gBACC,SAAS,SAAU,sBAAsB;AAAA;AAAA,gBAE1C,SAAS;AAAA,cAAA;AAAA,cAGV,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGJ,UACC,oBAAC,OAAA,EAAI,WAAU,QAAQ,UAAA,OAAA,CAAO;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAItC;AACF;AACA,MAAM,cAAc;AAIb,MAAM,YAAY;AAAA,EACvB,WAAW;AAAA,EACX,QAAQ;AAAA;AAAA,EACR,UAAU,CAAA;AAAA,EAGV,OAAO,CAAA;AAAA,EAGP,QAAQ,CAAC,WAAW,SAAS,UAAU,iBAAiB,UAAU;AAAA,EAClE,QAAQ;AAAA,IACN,IAAI,CAAA;AAAA,IACJ,IAAI,CAAC,iBAAiB,qBAAqB,iBAAiB;AAAA,IAC5D,MAAM,CAAA;AAAA,EAAC;AAEX;"}
|