@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,368 @@
|
|
|
1
|
+
// @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.
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
import { User } from 'lucide-react'
|
|
4
|
+
import type { LucideIcon } from 'lucide-react'
|
|
5
|
+
import { cn } from '@/lib/utils'
|
|
6
|
+
import { HoverCard, HoverCardTrigger, HoverCardContent } from '@/design-system/components/HoverCard/hover-card'
|
|
7
|
+
import { HOVER_DELAY_RICH_MS, HOVER_DELAY_CLOSE_MS } from '@/design-system/tokens/motion/motion'
|
|
8
|
+
import { Badge } from '@/design-system/components/Badge/badge'
|
|
9
|
+
import { useFieldContext, useTableIsScrolling } from '@/design-system/components/Field/field-context'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Avatar — 頭像元件
|
|
13
|
+
*
|
|
14
|
+
* 三種內容模式(按優先順序):
|
|
15
|
+
* 1. src → 圖片
|
|
16
|
+
* 2. icon → icon 在底色圓/方形內
|
|
17
|
+
* 3. alt → 取首字作文字 fallback
|
|
18
|
+
* 4. 都沒有 → 預設 User icon
|
|
19
|
+
*
|
|
20
|
+
* ── 尺寸 ──
|
|
21
|
+
* size 接受任意 px 值,icon 自動 = round_even(size × 0.6)
|
|
22
|
+
* 文字 fallback 字體 = size × 0.5
|
|
23
|
+
*
|
|
24
|
+
* ── 形狀 ──
|
|
25
|
+
* circle(預設)→ rounded-full,用於人物
|
|
26
|
+
* square → rounded-md (4px),用於實體(專案、組織、App)
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
// ── 色彩 ──
|
|
30
|
+
// 直接引用 primitive(bg=step-1, text=step-7),不經過語義層
|
|
31
|
+
// solid:step-6 全色底 + 白色前景(yellow 例外用 --warning-foreground)
|
|
32
|
+
// neutral solid:neutral-9 + --inverse-fg(自動反轉)
|
|
33
|
+
type ColorKey = 'neutral' | 'blue' | 'red' | 'green' | 'yellow' | 'turquoise' | 'purple' | 'magenta' | 'indigo'
|
|
34
|
+
type VariantKey = 'subtle' | 'solid'
|
|
35
|
+
|
|
36
|
+
const COLOR_MAP: Record<VariantKey, Record<ColorKey, { bg: string; text: string }>> = {
|
|
37
|
+
subtle: {
|
|
38
|
+
neutral: { bg: 'var(--muted)', text: 'var(--foreground)' },
|
|
39
|
+
blue: { bg: 'var(--color-blue-1)', text: 'var(--color-blue-7)' },
|
|
40
|
+
red: { bg: 'var(--color-deep-orange-1)', text: 'var(--color-deep-orange-7)' },
|
|
41
|
+
green: { bg: 'var(--color-green-1)', text: 'var(--color-green-7)' },
|
|
42
|
+
yellow: { bg: 'var(--color-yellow-1)', text: 'var(--color-yellow-7)' },
|
|
43
|
+
turquoise: { bg: 'var(--color-turquoise-1)', text: 'var(--color-turquoise-7)' },
|
|
44
|
+
purple: { bg: 'var(--color-purple-1)', text: 'var(--color-purple-7)' },
|
|
45
|
+
magenta: { bg: 'var(--color-magenta-1)', text: 'var(--color-magenta-7)' },
|
|
46
|
+
indigo: { bg: 'var(--color-indigo-1)', text: 'var(--color-indigo-7)' },
|
|
47
|
+
},
|
|
48
|
+
solid: {
|
|
49
|
+
neutral: { bg: 'var(--color-neutral-9)', text: 'var(--inverse-fg)' },
|
|
50
|
+
blue: { bg: 'var(--color-blue-6)', text: 'var(--on-emphasis)' },
|
|
51
|
+
red: { bg: 'var(--color-deep-orange-6)', text: 'var(--on-emphasis)' },
|
|
52
|
+
green: { bg: 'var(--color-green-6)', text: 'var(--on-emphasis)' },
|
|
53
|
+
yellow: { bg: 'var(--color-yellow-6)', text: 'var(--warning-foreground)' },
|
|
54
|
+
turquoise: { bg: 'var(--color-turquoise-6)', text: 'var(--on-emphasis)' },
|
|
55
|
+
purple: { bg: 'var(--color-purple-6)', text: 'var(--on-emphasis)' },
|
|
56
|
+
magenta: { bg: 'var(--color-magenta-6)', text: 'var(--on-emphasis)' },
|
|
57
|
+
indigo: { bg: 'var(--color-indigo-6)', text: 'var(--on-emphasis)' },
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ── Icon size: round to nearest even, ≈ 60% ──
|
|
62
|
+
function getIconSize(avatarSize: number): number {
|
|
63
|
+
return Math.round((avatarSize * 0.6) / 2) * 2
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── Text fallback: first character ──
|
|
67
|
+
function getInitial(text: string): string {
|
|
68
|
+
return text.trim().charAt(0).toUpperCase()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Semantic presence tokens — 見 color/semantic.css
|
|
72
|
+
// Module-level constant(2026-04-22 D3 perf audit):從 render body 移到 module scope,
|
|
73
|
+
// 避免每次 Avatar render 都 re-declare 此 4-entry object(Low impact 但渲染大量 avatars 時累積可觀)
|
|
74
|
+
const STATUS_DOT_COLOR: Record<string, string> = {
|
|
75
|
+
online: 'var(--status-online)',
|
|
76
|
+
away: 'var(--status-away)',
|
|
77
|
+
busy: 'var(--status-busy)',
|
|
78
|
+
offline: 'var(--status-offline)',
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ── useDocumentTheme(2026-04-23;M3 Portal 逃脫防線,scope verified 2026-04-25)──
|
|
82
|
+
// 讀 `<html data-theme>` 並 observe mutation。用於 Avatar hoverCard NameCard:
|
|
83
|
+
// Portal 後的 HoverCardContent 會繼承 trigger subtree theme(如 OverflowIndicator
|
|
84
|
+
// dark tooltip 內部),造成 NameCard 被污染成 dark。顯式 bind app-level theme
|
|
85
|
+
// 確保 NameCard 永遠跟 app 本身 theme 一致(light-in-light-app / dark-in-dark-app)。
|
|
86
|
+
//
|
|
87
|
+
// 範圍 audit 2026-04-25:觀察對象是 `document.documentElement` 自有 DOM,非 3rd-party
|
|
88
|
+
// lib 內部(不屬 M2 scope);attributeFilter 限定 `data-theme` 單一 attr,re-render 成本
|
|
89
|
+
// 為每次全站 theme 切換 × Avatar 數量,可接受。
|
|
90
|
+
function useDocumentTheme(): string | null {
|
|
91
|
+
const [theme, setTheme] = React.useState<string | null>(() =>
|
|
92
|
+
typeof document !== 'undefined' ? document.documentElement.getAttribute('data-theme') : null,
|
|
93
|
+
)
|
|
94
|
+
React.useEffect(() => {
|
|
95
|
+
if (typeof document === 'undefined') return
|
|
96
|
+
const root = document.documentElement
|
|
97
|
+
const update = () => setTheme(root.getAttribute('data-theme'))
|
|
98
|
+
update()
|
|
99
|
+
const obs = new MutationObserver(update)
|
|
100
|
+
obs.observe(root, { attributes: true, attributeFilter: ['data-theme'] })
|
|
101
|
+
return () => obs.disconnect()
|
|
102
|
+
}, [])
|
|
103
|
+
return theme
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ── Component ──
|
|
107
|
+
|
|
108
|
+
export interface AvatarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
109
|
+
/** 尺寸:number (px) 或 'fill'(填滿父容器,由父層決定大小)。預設 32 */
|
|
110
|
+
size?: number | 'fill'
|
|
111
|
+
/** 形狀:circle(人物)或 square(實體),預設 circle */
|
|
112
|
+
shape?: 'circle' | 'square'
|
|
113
|
+
/** 圖片 URL */
|
|
114
|
+
src?: string
|
|
115
|
+
/** 替代文字(圖片失敗時取首字作 fallback) */
|
|
116
|
+
alt?: string
|
|
117
|
+
/** Icon 模式(LucideIcon) */
|
|
118
|
+
icon?: LucideIcon
|
|
119
|
+
/** Icon / text fallback 的背景色,預設 neutral */
|
|
120
|
+
color?: ColorKey
|
|
121
|
+
/** 深底白字模式(step-6 背景 + 白色前景,warning 例外),預設 false */
|
|
122
|
+
solid?: boolean
|
|
123
|
+
/**
|
|
124
|
+
* 在線狀態指示器(presence),顯示在 avatar **右下角**。
|
|
125
|
+
* 世界級對照:Slack / Teams / Discord — `online` 是最廣泛被理解的術語。
|
|
126
|
+
* 位置語義:右下 = "此人的 presence"(使用者聚焦於「這個人是誰 + 現在 在不在」)。
|
|
127
|
+
*/
|
|
128
|
+
status?: 'online' | 'away' | 'busy' | 'offline'
|
|
129
|
+
/**
|
|
130
|
+
* 未讀 / 通知計數 badge,顯示在 avatar **右上角**。
|
|
131
|
+
* 世界級對照:chat app(iMessage / Slack thread / LINE / WhatsApp)一律右上角。
|
|
132
|
+
* 位置語義:右上 = "關於此對話的新事件數量"(使用者聚焦於「有多少未處理」);
|
|
133
|
+
* 與右下的 presence 共存不衝突(不同角、不同語義)。
|
|
134
|
+
* `> 99` 自動顯示 "99+"(交給內部 Badge 的 `max` 行為)。
|
|
135
|
+
*/
|
|
136
|
+
badgeCount?: number
|
|
137
|
+
/**
|
|
138
|
+
* 傳入 HoverCard 內容(如 NameCard),hover avatar 時自動顯示。
|
|
139
|
+
* 只有人員 avatar 需要傳;實體 avatar(專案、組織)不傳。
|
|
140
|
+
*/
|
|
141
|
+
hoverCard?: React.ReactNode
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// code-quality-allow: long-function — foundational composite main body — 拆 sub-fn 會複雜化 local state / ref / context binding
|
|
145
|
+
// 2026-05-13 (a) perf fix part-2(per codex Layer C Roadmap rich-cell dominant + user 拍 Path (a)):
|
|
146
|
+
// `React.memo` wrap forwardRef Avatar — Roadmap 13 columns 含 person/multiPerson,每 row 多 avatar
|
|
147
|
+
// × HoverCard subtree + useDocumentTheme observer = 重渲染 hotspot。memo shallow-equal props,
|
|
148
|
+
// HoverCard / themeRef stable across scroll 時 skip re-render。對齊 codex Profile Plan step 5
|
|
149
|
+
// (filter Avatar/PeoplePicker/FieldSurfaceProvider remounts)。
|
|
150
|
+
// code-quality-allow: long-function — size × shape × color × solid × status × badgeCount × hoverCard × img-fallback 多軸 prop 組合,拆 sub-fn 會跨 fn 傳 imgError state + isTableScrolling observer 結果
|
|
151
|
+
const AvatarInner = React.forwardRef<HTMLDivElement, AvatarProps>(
|
|
152
|
+
({ size = 32, shape = 'circle', src, alt, icon: Icon, color = 'neutral', solid = false, status, badgeCount, hoverCard, className, style, ...props }, ref) => {
|
|
153
|
+
const [imgError, setImgError] = React.useState(false)
|
|
154
|
+
const documentTheme = useDocumentTheme()
|
|
155
|
+
const isTableScrolling = useTableIsScrolling()
|
|
156
|
+
// 2026-05-13 R3.5(per codex Q3 verdict + user 拍「想盡辦法 auto-handle prereq」):
|
|
157
|
+
// Avatar self-dim when in disabled Field wrapper context(取代既有 wrapper opacity-disabled blanket
|
|
158
|
+
// 逃生艙 — color.spec.md:729 specific-disabled-color canonical)。
|
|
159
|
+
// Scope narrowest:`fieldCtx?.mode === 'disabled' && fieldCtx?.hasFieldWrapper === true`,標準 Field
|
|
160
|
+
// 家族 wrapper disabled 時才 dim;**沒包在 Field wrapper 內的 standalone Avatar**(NameCard / FileItem /
|
|
161
|
+
// HoverCard / Dialog 等 display 場景)**backward compat 不變**。對齊 avatar.spec.md「Avatar 在 disabled
|
|
162
|
+
// 元件內 host-controlled opacity」canonical — 升級成「Avatar self-managed via fieldCtx」。
|
|
163
|
+
const fieldCtx = useFieldContext()
|
|
164
|
+
const isDisabledInField = fieldCtx?.mode === 'disabled' && fieldCtx?.hasFieldWrapper === true
|
|
165
|
+
const isFill = size === 'fill'
|
|
166
|
+
// Fill 模式下 icon 用 60% 寬高、text 用 50cqi(container query inline-size);
|
|
167
|
+
// 數字模式下用既有 px 計算
|
|
168
|
+
const numSize = isFill ? 32 : (size as number)
|
|
169
|
+
const iconPx = getIconSize(numSize)
|
|
170
|
+
const fontSizePx = Math.round(numSize * 0.5)
|
|
171
|
+
const variantKey: VariantKey = solid ? 'solid' : 'subtle'
|
|
172
|
+
const colors = COLOR_MAP[variantKey]?.[color] ?? COLOR_MAP.subtle.neutral
|
|
173
|
+
const radius = shape === 'circle' ? '9999px' : '4px'
|
|
174
|
+
|
|
175
|
+
// 決定內容
|
|
176
|
+
const showImage = src && !imgError
|
|
177
|
+
const showIcon = !showImage && (Icon || (!alt))
|
|
178
|
+
const showText = !showImage && !showIcon && alt
|
|
179
|
+
|
|
180
|
+
const FallbackIcon = Icon ?? User
|
|
181
|
+
|
|
182
|
+
// Status dot 尺寸:avatar 的 28%(Slack / Teams / Discord 世界級平均),
|
|
183
|
+
// clamp [8, 16] — floor 8 保小 avatar 仍可辨識但不喧賓奪主(10 floor 會讓 24px
|
|
184
|
+
// avatar 的 dot 占 42% 太大);ceiling 16 防大 avatar dot 過度放大
|
|
185
|
+
const dotSize = isFill ? 10 : Math.max(8, Math.min(16, Math.round(numSize * 0.28)))
|
|
186
|
+
// Border ring 在 surface 上分離 dot 與 avatar,dotSize ≥ 12 時升階到 3px 保持視覺比例
|
|
187
|
+
const dotBorder = dotSize >= 12 ? 3 : 2
|
|
188
|
+
|
|
189
|
+
const avatarEl = (
|
|
190
|
+
<div
|
|
191
|
+
className={cn(
|
|
192
|
+
'inline-flex items-center justify-center shrink-0 overflow-hidden select-none',
|
|
193
|
+
isFill && 'w-full h-full',
|
|
194
|
+
// 2026-05-13 R3.5 self-dim:Avatar 在 disabled Field wrapper context 內自 dim
|
|
195
|
+
// (取代 field-wrapper.tsx default/bare/naked disabled blanket opacity-disabled 逃生艙)
|
|
196
|
+
isDisabledInField && 'opacity-disabled',
|
|
197
|
+
)}
|
|
198
|
+
style={{
|
|
199
|
+
...(isFill
|
|
200
|
+
? { containerType: 'inline-size' as React.CSSProperties['containerType'] }
|
|
201
|
+
: { width: numSize, height: numSize }),
|
|
202
|
+
borderRadius: radius,
|
|
203
|
+
backgroundColor: showImage ? undefined : colors.bg,
|
|
204
|
+
color: showImage ? undefined : colors.text,
|
|
205
|
+
}}
|
|
206
|
+
data-avatar-size={isFill ? 'fill' : numSize}
|
|
207
|
+
>
|
|
208
|
+
{showImage && (
|
|
209
|
+
<img
|
|
210
|
+
src={src}
|
|
211
|
+
alt={alt ?? ''}
|
|
212
|
+
className="w-full h-full object-cover"
|
|
213
|
+
onError={() => setImgError(true)}
|
|
214
|
+
/>
|
|
215
|
+
)}
|
|
216
|
+
{showIcon && (
|
|
217
|
+
isFill
|
|
218
|
+
? <FallbackIcon className="w-[60%] h-[60%]" aria-hidden />
|
|
219
|
+
: <FallbackIcon size={iconPx} aria-hidden />
|
|
220
|
+
)}
|
|
221
|
+
{showText && (
|
|
222
|
+
<span
|
|
223
|
+
className="font-medium leading-none"
|
|
224
|
+
style={{ fontSize: isFill ? '50cqi' : fontSizePx }}
|
|
225
|
+
aria-hidden
|
|
226
|
+
>
|
|
227
|
+
{getInitial(alt!)}
|
|
228
|
+
</span>
|
|
229
|
+
)}
|
|
230
|
+
</div>
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
const hasOverlay = status || typeof badgeCount === 'number'
|
|
234
|
+
// Keyboard access canonical(D4 UX audit 2026-04-22 finding):Avatar with `hoverCard`
|
|
235
|
+
// 需 keyboard 可達 — Radix `HoverCardTrigger asChild` 不自動加 tabIndex,non-focusable
|
|
236
|
+
// `<div>` 會讓 keyboard-only user 無法 reach NameCard popover(WCAG 2.1.1 / 4.1.2 違反)。
|
|
237
|
+
// 解:當 `hoverCard` 存在時,wrapper `<div>` 變 focusable(`tabIndex=0` + `role="button"` +
|
|
238
|
+
// `aria-haspopup="dialog"` + focus-visible ring)。若無 hoverCard 則維持純展示 `<div>`。
|
|
239
|
+
const focusableProps = hoverCard
|
|
240
|
+
? {
|
|
241
|
+
tabIndex: 0,
|
|
242
|
+
role: 'button' as const,
|
|
243
|
+
'aria-haspopup': 'dialog' as const,
|
|
244
|
+
'aria-label': alt ?? 'View profile',
|
|
245
|
+
}
|
|
246
|
+
: {}
|
|
247
|
+
const focusableClass = hoverCard
|
|
248
|
+
? 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 rounded-full'
|
|
249
|
+
: ''
|
|
250
|
+
const baseEl = !hasOverlay
|
|
251
|
+
? <div ref={ref} className={cn('inline-flex shrink-0', focusableClass, className)} style={style} {...focusableProps} {...props}>{avatarEl}</div>
|
|
252
|
+
: (
|
|
253
|
+
<div ref={ref} className={cn('relative inline-flex shrink-0', focusableClass, className)} style={style} {...focusableProps} {...props}>
|
|
254
|
+
{avatarEl}
|
|
255
|
+
{/* Status dot:bottom-right(presence — 世界級對照 Slack / Teams / Discord),
|
|
256
|
+
落在 circle avatar 圓周 45° 位置 / square avatar 右下直角;
|
|
257
|
+
border ring 用 surface 色讓 dot 從 avatar 邊界視覺分離。
|
|
258
|
+
a11y:`aria-hidden` — presence 資訊整合到 parent avatar 的 aria-label
|
|
259
|
+
(world-class Slack 做法),避免多 `role="status"` 造成 screen reader 洪水 */}
|
|
260
|
+
{status && (
|
|
261
|
+
<span
|
|
262
|
+
className="absolute block rounded-full"
|
|
263
|
+
style={{
|
|
264
|
+
width: dotSize,
|
|
265
|
+
height: dotSize,
|
|
266
|
+
bottom: 0,
|
|
267
|
+
right: 0,
|
|
268
|
+
backgroundColor: STATUS_DOT_COLOR[status],
|
|
269
|
+
boxShadow: `0 0 0 ${dotBorder}px var(--surface-raised, var(--canvas))`,
|
|
270
|
+
}}
|
|
271
|
+
aria-hidden
|
|
272
|
+
/>
|
|
273
|
+
)}
|
|
274
|
+
{/* Count badge:top-right(chat 未讀 / 通知計數 — 世界級對照 iMessage /
|
|
275
|
+
Slack thread / LINE / WhatsApp)。消費 DS Badge(critical variant),
|
|
276
|
+
再加 ring 與 avatar 分離 */}
|
|
277
|
+
{typeof badgeCount === 'number' && badgeCount > 0 && (
|
|
278
|
+
<Badge
|
|
279
|
+
variant="critical"
|
|
280
|
+
count={badgeCount}
|
|
281
|
+
max={99}
|
|
282
|
+
className="absolute -top-1 -right-1"
|
|
283
|
+
style={{
|
|
284
|
+
boxShadow: `0 0 0 2px var(--surface-raised, var(--canvas))`,
|
|
285
|
+
}}
|
|
286
|
+
aria-label={`${badgeCount} unread`}
|
|
287
|
+
/>
|
|
288
|
+
)}
|
|
289
|
+
</div>
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
// 2026-05-13 (c) scroll-defer perf(per user 拍 Path (c) + codex Q3 verdict):
|
|
293
|
+
// DataTable scrolling 期間跳 HoverCard wrapper(Portal + useDocumentTheme observer 是
|
|
294
|
+
// Roadmap 重渲 hotspot,per codex Layer C 分析)。scroll 結束 → context flips false →
|
|
295
|
+
// re-render 接回完整 HoverCard tree(NameCard 仍可 hover 顯示)。
|
|
296
|
+
// 對齊 AG Grid `deferRender` for slow React cell components / MUI X DataGrid scroll-defer。
|
|
297
|
+
if (!hoverCard || isTableScrolling) return baseEl
|
|
298
|
+
|
|
299
|
+
return (
|
|
300
|
+
<HoverCard openDelay={HOVER_DELAY_RICH_MS} closeDelay={HOVER_DELAY_CLOSE_MS}>
|
|
301
|
+
<HoverCardTrigger asChild>
|
|
302
|
+
{baseEl}
|
|
303
|
+
</HoverCardTrigger>
|
|
304
|
+
{/* HoverCardContent canonical(2026-04-23):
|
|
305
|
+
- 無 inner padding(consumer NameCard 自帶 `px-4 py-3` chrome)
|
|
306
|
+
- `overflow-hidden` + `rounded-lg` → child(NameCard)圓角裁切
|
|
307
|
+
- **不設 max-height**:NameCard 自己消費 `--radix-hover-card-content-available-height`
|
|
308
|
+
自約束高度 + 內部 ScrollArea 處理捲動
|
|
309
|
+
- `data-theme={documentTheme}`:NameCard 永遠跟隨 **app-level theme**(從 `<html data-theme>`
|
|
310
|
+
動態讀),不受 trigger subtree theme 污染。範例:Avatar 位於 OverflowIndicator 的 dark
|
|
311
|
+
tooltip 內,其 Portal 會繼承該 subtree dark theme → NameCard 變全黑。顯式設回 app theme
|
|
312
|
+
確保 NameCard 永遠 light-in-light-app / dark-in-dark-app。 */}
|
|
313
|
+
<HoverCardContent
|
|
314
|
+
data-theme={documentTheme ?? undefined}
|
|
315
|
+
className="bg-surface-raised rounded-lg border border-border overflow-hidden"
|
|
316
|
+
style={{ boxShadow: 'var(--elevation-200)' }}
|
|
317
|
+
>
|
|
318
|
+
{hoverCard}
|
|
319
|
+
</HoverCardContent>
|
|
320
|
+
</HoverCard>
|
|
321
|
+
)
|
|
322
|
+
}
|
|
323
|
+
)
|
|
324
|
+
AvatarInner.displayName = 'AvatarInner'
|
|
325
|
+
|
|
326
|
+
// ── AvatarData ─────────────────────────────────────────────────────────────
|
|
327
|
+
// 資料型別,讓 consumer 傳資料而非 ReactNode。
|
|
328
|
+
// 接收端內部用 Avatar 元件渲染,統一控制尺寸與 fallback。
|
|
329
|
+
|
|
330
|
+
export interface AvatarData {
|
|
331
|
+
/** 圖片 URL */
|
|
332
|
+
src?: string
|
|
333
|
+
/** 替代文字(圖片失敗時取首字作 fallback) */
|
|
334
|
+
alt: string
|
|
335
|
+
/** Icon / text fallback 的背景色,預設 neutral */
|
|
336
|
+
color?: ColorKey
|
|
337
|
+
/**
|
|
338
|
+
* Person avatar hover NameCard(DS-wide canonical,person avatar 預設必有,見 avatar.spec.md)。
|
|
339
|
+
* Entity avatar(專案 / 組織 logo)不帶 → consumer 不傳 hoverCard 即豁免。
|
|
340
|
+
* 所有消費 AvatarData 的 primitive(MenuItem / DropdownMenu / SelectMenu / SelectionItem / NameCard)
|
|
341
|
+
* 需 forward 此 prop 到內部 <Avatar hoverCard={avatar.hoverCard} />。
|
|
342
|
+
*/
|
|
343
|
+
hoverCard?: React.ReactNode
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Story auto-compile metadata — Phase 1 mechanical migration(2026-04-24)
|
|
347
|
+
// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs
|
|
348
|
+
export const avatarMeta = {
|
|
349
|
+
component: 'Avatar',
|
|
350
|
+
family: null, // non-family composite / overlay / layout
|
|
351
|
+
variants: {
|
|
352
|
+
|
|
353
|
+
},
|
|
354
|
+
sizes: {
|
|
355
|
+
|
|
356
|
+
},
|
|
357
|
+
states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
|
|
358
|
+
tokens: {
|
|
359
|
+
bg: ['bg-surface-raised'],
|
|
360
|
+
fg: ['--foreground', '--on-emphasis'],
|
|
361
|
+
ring: ['ring-ring'],
|
|
362
|
+
},
|
|
363
|
+
} as const
|
|
364
|
+
|
|
365
|
+
AvatarInner.displayName = 'Avatar'
|
|
366
|
+
const Avatar = React.memo(AvatarInner)
|
|
367
|
+
|
|
368
|
+
export { Avatar }
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { cva, type VariantProps } from 'class-variance-authority'
|
|
3
|
+
import { cn } from '@/lib/utils'
|
|
4
|
+
|
|
5
|
+
// ── Badge(notification count indicator)────────────────────────────────────
|
|
6
|
+
// 通知計數指示器,用於未讀數量、待辦計數等。
|
|
7
|
+
//
|
|
8
|
+
// 兩種模式:
|
|
9
|
+
// count — 16px 高,10px 字,font-medium。個位數正圓,多位數膠囊。
|
|
10
|
+
// dot — 6×6px 純色圓點,無文字。
|
|
11
|
+
//
|
|
12
|
+
// 四個層級(由 passive 到 urgent):
|
|
13
|
+
// low(預設) — 灰底灰字(neutral-3 + neutral-7),被動計數
|
|
14
|
+
// medium — 淺藍底藍字(bg-info-subtle + text-info-text),可延後看
|
|
15
|
+
// high — 藍底白字(bg-info),有感影響的待辦
|
|
16
|
+
// critical — 紅底白字(bg-notification),立即處理
|
|
17
|
+
//
|
|
18
|
+
// 規則:default low, escalate with reason。見 badge.spec.md「選 level 的流程」。
|
|
19
|
+
|
|
20
|
+
const badgeVariants = cva(
|
|
21
|
+
// 2026-05-23 Path B revert:icon-as-text / numeric-in-circle 用 leading-none canonical(對齊 Material Avatar `line-height: 1` / Polaris Badge / Carbon Tag 共識)。
|
|
22
|
+
// 視覺等效驗證:Badge container 顯式 `h-4 (16px)` + `flex items-center` 主導,text 被 items-center 置中,line-height 1.0 vs 1.3 視覺零差別。
|
|
23
|
+
// user 2026-05-23「或是其實根本不用分?」+「照你建議」path B:統一 leading-none,不分。
|
|
24
|
+
// 廢除 2026-05-21 F1 fix 的 leading-compact migration(那次 anchor「不影響高度的話就改」core constraint 是高度不變,Path B 同樣滿足且更簡單)。
|
|
25
|
+
'inline-flex items-center justify-center rounded-full leading-none',
|
|
26
|
+
{
|
|
27
|
+
variants: {
|
|
28
|
+
variant: {
|
|
29
|
+
critical: 'bg-notification text-on-emphasis',
|
|
30
|
+
high: 'bg-info text-on-emphasis',
|
|
31
|
+
medium: 'bg-info-subtle text-info-text',
|
|
32
|
+
low: 'bg-secondary text-fg-muted',
|
|
33
|
+
},
|
|
34
|
+
dot: {
|
|
35
|
+
true: 'w-1.5 h-1.5',
|
|
36
|
+
false: 'min-w-4 h-4 px-1 text-[10px] font-medium',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
defaultVariants: {
|
|
40
|
+
variant: 'low',
|
|
41
|
+
dot: false,
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
export interface BadgeProps
|
|
47
|
+
extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'children'>,
|
|
48
|
+
Omit<VariantProps<typeof badgeVariants>, 'dot'> {
|
|
49
|
+
/** dot 模式:6×6px 純色圓點,無文字 */
|
|
50
|
+
dot?: boolean
|
|
51
|
+
/** 顯示的數量(dot 模式下忽略) */
|
|
52
|
+
count?: number
|
|
53
|
+
/** 數量上限,超過時顯示 "max+"(例:max=99 → "99+") */
|
|
54
|
+
max?: number
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(
|
|
58
|
+
({ variant, dot = false, count, max, className, role, ...props }, ref) => {
|
|
59
|
+
const display = dot ? null : (
|
|
60
|
+
max != null && count != null && count > max ? `${max}+` : `${count}`
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
// a11y(2026-04-25 axe aria-prohibited-attr fix):
|
|
64
|
+
// span default 無 role → 不接 aria-label(WCAG 禁止)。Badge 是通知指示器,
|
|
65
|
+
// `role="status"` 語意正確(live region 可播報計數變化)且允許 aria-label。
|
|
66
|
+
// Consumer 可 override(傳 role="img" / role={undefined})。
|
|
67
|
+
return (
|
|
68
|
+
<span
|
|
69
|
+
ref={ref}
|
|
70
|
+
role={role ?? 'status'}
|
|
71
|
+
className={cn(badgeVariants({ variant, dot }), className)}
|
|
72
|
+
{...props}
|
|
73
|
+
>
|
|
74
|
+
{display}
|
|
75
|
+
</span>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
Badge.displayName = 'Badge'
|
|
80
|
+
|
|
81
|
+
// Story auto-compile metadata — Phase 1 mechanical migration(2026-04-24)
|
|
82
|
+
// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs
|
|
83
|
+
export const badgeMeta = {
|
|
84
|
+
component: 'Badge',
|
|
85
|
+
family: 3,
|
|
86
|
+
variants: {
|
|
87
|
+
critical: { purpose: '紅底白字(bg-notification)' },
|
|
88
|
+
high: { purpose: '藍底白字(bg-info)' },
|
|
89
|
+
medium: { purpose: '淺藍底藍字(bg-info-subtle)' },
|
|
90
|
+
low: { purpose: '使用者切 tab 才看,不需搶注意力' },
|
|
91
|
+
},
|
|
92
|
+
sizes: {
|
|
93
|
+
|
|
94
|
+
},
|
|
95
|
+
states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
|
|
96
|
+
tokens: {
|
|
97
|
+
bg: ['bg-info', 'bg-info-subtle', 'bg-notification', 'bg-secondary'],
|
|
98
|
+
fg: ['text-fg-muted', 'text-info-text'],
|
|
99
|
+
ring: [],
|
|
100
|
+
},
|
|
101
|
+
defaultVariant: 'low',
|
|
102
|
+
} as const
|
|
103
|
+
|
|
104
|
+
export { Badge, badgeVariants }
|