@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,322 @@
|
|
|
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 { Paperclip, CircleCheck, XCircle, Download, RotateCw } from 'lucide-react'
|
|
4
|
+
import { cn } from '@/lib/utils'
|
|
5
|
+
import { Avatar } from '@/design-system/components/Avatar/avatar'
|
|
6
|
+
import { Button } from '@/design-system/components/Button/button'
|
|
7
|
+
import { ProgressBar } from '@/design-system/components/ProgressBar/progress-bar'
|
|
8
|
+
import { ItemContent, ItemPrefix } from '@/design-system/patterns/element-anatomy/item-anatomy'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* FileItem โ ๆชๆก้กฏ็คบ / ไธๅณ้ฒๅบฆ
|
|
12
|
+
*
|
|
13
|
+
* Typography: ้ฑ่ฎๆจกๅผ โ text-body (14px) ้ ่จญ่ก้ซ (1.5)
|
|
14
|
+
*
|
|
15
|
+
* ๅ
ฉ็จฎ mode๏ผ็ฒพ็ฐก vs ๅฎๆดๅ
งๅฎนๅ็พ๏ผ:
|
|
16
|
+
*
|
|
17
|
+
* compact๏ผโ
default๏ผ: Paperclip 16px ๅจๅทฆใๅณๅด content + barใ
|
|
18
|
+
* py = gap = 4px (gap-1)๏ผๅฐ็จฑใ
|
|
19
|
+
* description ๅชๆ error ๆ้กฏ็คบใ
|
|
20
|
+
* bar ่ทๆๅญๅทฆ้ๅฐ้ฝ๏ผๅจ icon ๅณ้็ column ๅ
ง๏ผใ
|
|
21
|
+
*
|
|
22
|
+
* rich: Avatar 48px square ๅจๅทฆ๏ผ้กฏ็คบๆชๆกๅ
งๅฎน็ธฎๅ๏ผใๅณๅด content + barใ
|
|
23
|
+
* ๅค่ก description๏ผsize / status message๏ผใ
|
|
24
|
+
* ๆ bar โ justify-between๏ผbar ๅบ้จๅฐ้ฝ avatar๏ผ
|
|
25
|
+
* ็ก bar โ justify-center๏ผๆๅญๅ็ด็ฝฎไธญๅฐ้ฝ avatar๏ผ
|
|
26
|
+
*
|
|
27
|
+
* status ๅฏ้ธใไธๅณ = ๅทฒไธๅณๆชๆก๏ผ็ก bar๏ผๅฏ้ปๆไธ่ผ๏ผใ
|
|
28
|
+
* onClick โ hover:bg-neutral-hover + cursor-pointerใ
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const STATUS_ICON = {
|
|
32
|
+
completed: { icon: CircleCheck, color: 'text-success' },
|
|
33
|
+
error: { icon: XCircle, color: 'text-error' },
|
|
34
|
+
} as const
|
|
35
|
+
|
|
36
|
+
// ProgressBar status ๆ ๅฐ:uploading=inProgress(่) / completed=success(็ถ ) / error=error(็ด
)
|
|
37
|
+
// ่ ProgressBar ๅ
ไปถ็ status prop ๅฐ้ฝ,ไธ้ๅ็ถญ่ญท PROGRESS_COLOR ๆฌๅฐ mapใ
|
|
38
|
+
const PROGRESS_STATUS_MAP = {
|
|
39
|
+
uploading: 'inProgress',
|
|
40
|
+
completed: 'success',
|
|
41
|
+
error: 'error',
|
|
42
|
+
} as const
|
|
43
|
+
|
|
44
|
+
const AVATAR_SIZE = 48
|
|
45
|
+
const ICON_PX = 16
|
|
46
|
+
|
|
47
|
+
export interface FileItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
|
|
48
|
+
name: string
|
|
49
|
+
/**
|
|
50
|
+
* ๅ
ฉ็จฎๅ็พ mode๏ผ็ฒพ็ฐก vs ๅฎๆด๏ผ๏ผ
|
|
51
|
+
* - `compact`๏ผ้ ่จญ๏ผ๏ผpaperclip + filename ๅฎ่ก inline
|
|
52
|
+
* - `rich`๏ผ็ธฎๅ + ๆชๅ + size + status + progress ็ๅฎๆด card ๅ็พ
|
|
53
|
+
*/
|
|
54
|
+
mode?: 'compact' | 'rich'
|
|
55
|
+
status?: 'uploading' | 'completed' | 'error'
|
|
56
|
+
progress?: number
|
|
57
|
+
/** rich mode: ๆชๆกๅคงๅฐใ็ๆ
่จๆฏใcompact: ๅชๆ error ๆ้กฏ็คบใ ReactNode ๆฏๆด inline clickable link(ๅฆใView logใ)ใ */
|
|
58
|
+
description?: React.ReactNode
|
|
59
|
+
thumbnailSrc?: string
|
|
60
|
+
actions?: React.ReactNode
|
|
61
|
+
onClick?: () => void
|
|
62
|
+
/**
|
|
63
|
+
* Hover ๅไฝ(passive ็ๆ
icon ่ฎไบๅ button ็ UX):
|
|
64
|
+
* - `onDownload`:ๆๅผๆ,`status="completed"` ็็ถ โ icon ๅจ row hover ๆ
|
|
65
|
+
* ๆๆ Download โ button;click ่งธ็ผ onDownloadใ็กๅผไฟๆ passive ็ถ โใ
|
|
66
|
+
* - `onRetry`:ๆๅผๆ,`status="error"` ็็ด
โ icon ๅจ row hover ๆๆๆ RotateCw โฒ
|
|
67
|
+
* button;click ่งธ็ผ onRetryใ็กๅผไฟๆ passive ็ด
โใ
|
|
68
|
+
*
|
|
69
|
+
* ไธ็็ดๅฐ็
ง:Gmail / Slack / Dropbox ้ไปถ็ passive ็ๆ
โ hover ่ฎ action
|
|
70
|
+
* ็ UX,ไฝฟ็จ่
็ฅ้ๆชๆก็ๆ
ไธ่ฝ็ซๅณ่กๅใ
|
|
71
|
+
*/
|
|
72
|
+
onDownload?: () => void
|
|
73
|
+
onRetry?: () => void
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// code-quality-allow: long-function โ foundational composite main body โ ๆ sub-fn ๆ่ค้ๅ local state / ref / context binding
|
|
77
|
+
const FileItem = React.forwardRef<HTMLDivElement, FileItemProps>(
|
|
78
|
+
(
|
|
79
|
+
{
|
|
80
|
+
name,
|
|
81
|
+
mode = 'compact',
|
|
82
|
+
status,
|
|
83
|
+
progress = 0,
|
|
84
|
+
description,
|
|
85
|
+
thumbnailSrc,
|
|
86
|
+
actions,
|
|
87
|
+
onClick,
|
|
88
|
+
onDownload,
|
|
89
|
+
onRetry,
|
|
90
|
+
className,
|
|
91
|
+
...props
|
|
92
|
+
},
|
|
93
|
+
ref,
|
|
94
|
+
) => {
|
|
95
|
+
const isRich = mode === 'rich'
|
|
96
|
+
const hasStatus = !!status
|
|
97
|
+
const statusConfig = status && status !== 'uploading' ? STATUS_ICON[status] : null
|
|
98
|
+
const progressWidth = status === 'completed' ? 100 : progress
|
|
99
|
+
|
|
100
|
+
// compact ๅชๆ error ๆ้กฏ็คบ description
|
|
101
|
+
const showDesc = isRich ? !!description : (status === 'error' && !!description)
|
|
102
|
+
|
|
103
|
+
// Hover ่ก็บ canonical(2026-04-23 user ๆ กๆบ):**FileItem ๆฐธไธ้กฏ็คบ hover-bg**ใ
|
|
104
|
+
// ไธ็จฎๅๆ
้ฝๆๆฐธไน
visual anchor:rich = border card / compact Type B = bg-secondary /
|
|
105
|
+
// compact Type A = ๅบ้จ progress bar(ๅ้็ทๅ affordance)โโๅๅ hover-bg ๆฏ
|
|
106
|
+
// double-emphasis,่ฆ่ฆบ้ใไธ็็ดๅ
ฑ่ญ(Slack / Notion / Figma / Gmail ็็ก hover-bg):
|
|
107
|
+
// permanent-anchored ๅ
ไปถ hover ๅช้ cursor + action icon fade / border highlight,
|
|
108
|
+
// ไธ้ row bgใonClick ๅญๅจๆๅช็ตฆ `cursor-pointer`,affordance ้ cursor + ้ปๆ่ก็บๆฌ่บซใ
|
|
109
|
+
const hoverClass = onClick ? 'cursor-pointer' : ''
|
|
110
|
+
|
|
111
|
+
// ๆถ่ฒป ProgressBar ๅ
ไปถ(SSOT);ไธๅ่ช roll barใ
|
|
112
|
+
// height override:compact mode ็จ 2px(ๆฅตๅฏ้ row layout),rich mode ็จ้ ่จญ 4pxใ
|
|
113
|
+
// ้ๆฏ ProgressBar `height` prop ็ๅฏไธๅๆณ consumer(่ฆ progress-bar.tsx docblock)ใ
|
|
114
|
+
// a11y(2026-04-25 axe aria-progressbar-name):aria-label ็จ file name ไฝ contextใ
|
|
115
|
+
const progressBar = hasStatus ? (
|
|
116
|
+
<ProgressBar
|
|
117
|
+
value={progressWidth}
|
|
118
|
+
status={PROGRESS_STATUS_MAP[status!]}
|
|
119
|
+
height={isRich ? undefined : 2}
|
|
120
|
+
aria-label={`${name} ไธๅณ้ฒๅบฆ`}
|
|
121
|
+
/>
|
|
122
|
+
) : null
|
|
123
|
+
|
|
124
|
+
// suffix ๅฐ้ฝ label ็ฌฌไธ่ก(item-anatomyใ24px ้พๅผๅฐ้ฝ่ฆๅใๅฐ suffix canonical):
|
|
125
|
+
// icons 16 โค 24 ๅฑฌๅฐ suffix,็ตฑไธ `h-[1lh]` inline,ไธๅ desc wrap ๆนๅ
ฌๅผใ
|
|
126
|
+
// ๅ
ฉ mode ๅๅ
ฌๅผ,่ท item-anatomy ไธ่ดใ
|
|
127
|
+
const suffixAlign = 'h-[1lh]'
|
|
128
|
+
|
|
129
|
+
// Status slot ๅนพไฝ(2026-04-23 user ็ตฑไธ):rich + compact ้ฝ็จ `var(--field-height-xs)`(24)
|
|
130
|
+
// ๅฎนๅจ,่ฃก้ข Button xs iconOnly variant="text"(auto data-unbounded)ใ
|
|
131
|
+
// Compact ไธๅฝฑ้ฟ row ้ซๅบฆ = suffix wrapper ็ data-unbounded CSS ่ฎ Button layout
|
|
132
|
+
// ๆถๆๅฐ 1lh(ๅ compact row ๅ
งๅฎน้ซ),่ฆ่ฆบ/touch target ไป 24ใ
|
|
133
|
+
const slotHw = 'var(--field-height-xs)'
|
|
134
|
+
|
|
135
|
+
const hoverAction =
|
|
136
|
+
status === 'completed' && onDownload ? { icon: Download, onClick: onDownload, label: 'ไธ่ผ' } :
|
|
137
|
+
status === 'error' && onRetry ? { icon: RotateCw, onClick: onRetry, label: '้่ฉฆ' } :
|
|
138
|
+
null
|
|
139
|
+
|
|
140
|
+
const statusSlot = statusConfig ? (
|
|
141
|
+
<span
|
|
142
|
+
data-unbounded="true"
|
|
143
|
+
className="relative inline-flex items-center justify-center shrink-0"
|
|
144
|
+
style={{ width: slotHw, height: slotHw }}
|
|
145
|
+
>
|
|
146
|
+
{/* Passive ็ๆ
icon:้ ่จญๅฏ่ฆ;่ฅๆ hover-swap,row-hover ๆๆทกๅบ */}
|
|
147
|
+
<statusConfig.icon
|
|
148
|
+
size={ICON_PX}
|
|
149
|
+
className={cn(
|
|
150
|
+
'shrink-0 transition-opacity',
|
|
151
|
+
statusConfig.color,
|
|
152
|
+
hoverAction && 'group-hover/row:opacity-0',
|
|
153
|
+
)}
|
|
154
|
+
aria-hidden
|
|
155
|
+
/>
|
|
156
|
+
{/* Active action:row-hover ๆๆทกๅ
ฅ(rich + compact ๅ Button xs ็ตฑไธ) */}
|
|
157
|
+
{hoverAction && (
|
|
158
|
+
<Button
|
|
159
|
+
variant="text"
|
|
160
|
+
size="xs"
|
|
161
|
+
iconOnly
|
|
162
|
+
startIcon={hoverAction.icon}
|
|
163
|
+
aria-label={hoverAction.label}
|
|
164
|
+
onClick={(e) => { e.stopPropagation(); hoverAction.onClick() }}
|
|
165
|
+
className="absolute inset-0 opacity-0 group-hover/row:opacity-100 transition-opacity"
|
|
166
|
+
/>
|
|
167
|
+
)}
|
|
168
|
+
</span>
|
|
169
|
+
) : null
|
|
170
|
+
|
|
171
|
+
const suffix = (
|
|
172
|
+
<div
|
|
173
|
+
className={cn(
|
|
174
|
+
'flex items-center gap-2 shrink-0',
|
|
175
|
+
suffixAlign,
|
|
176
|
+
// data-unbounded chrome-canonical trick:let Button xs (24) live inside h-[1lh]
|
|
177
|
+
// wrapper(compact ~18.2 / rich ~18.2 scanning)without pushing row heightใ
|
|
178
|
+
// ่ฆ่ฆบ/hit area ไป 24,layout footprint ๆถๆๅฐ 1lhใๅ overlay-surface
|
|
179
|
+
// ็ SurfaceHeader dismiss canonical(2026-04-22 v5)ใ
|
|
180
|
+
// **child selector `[&>[data-unbounded]]`(้ descendant)**:ๅช้ๅฐ suffix
|
|
181
|
+
// wrapper **็ดๆฅๅญๅ
็ด **(statusSlot spanใactions Button)ๅฅ margin,
|
|
182
|
+
// ้ฟๅ
status slot ๅ
ง้จ hover-swap Button(nested)ไนๅฅ้ ๆ layout ่ทณๅใ
|
|
183
|
+
'[&>[data-unbounded]]:my-[calc((1lh-var(--field-height-xs))/2)]',
|
|
184
|
+
)}
|
|
185
|
+
>
|
|
186
|
+
{status === 'uploading' && isRich && (
|
|
187
|
+
<span className="text-fg-secondary tabular-nums">{progress}%</span>
|
|
188
|
+
)}
|
|
189
|
+
{statusSlot}
|
|
190
|
+
{actions}
|
|
191
|
+
</div>
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
// content row โ ๆถ่ฒป ItemContent primitive(ๅฐ่ฃ label + desc + mt-gap token SSOT)ใ
|
|
195
|
+
// ๅ
ฉ mode ๅ
ฑ็จ:primitive ๆน โ ๅ
ฉ mode ๅๆญฅ,ไธ้ grepใ
|
|
196
|
+
// typography:scanning mode(2026-04-23 user ๆ็คบ)โโ label body(14/1.3) + desc caption(12/1.3);
|
|
197
|
+
// row ๆฌ่บซๅ `leading-compact` ้
ๅ scanning idiom(ๅ MenuItem row)ใ
|
|
198
|
+
const contentRow = (
|
|
199
|
+
<div className="flex items-start gap-2">
|
|
200
|
+
<ItemContent
|
|
201
|
+
label={name}
|
|
202
|
+
description={showDesc ? description : undefined}
|
|
203
|
+
mode="scanning"
|
|
204
|
+
descriptionTone={status === 'error' ? 'error' : 'secondary'}
|
|
205
|
+
/>
|
|
206
|
+
{suffix}
|
|
207
|
+
</div>
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
// a11y(2026-04-25 nested-interactive fix):FileItem row ๅซ inner interactive
|
|
211
|
+
// (hover-swap action button / ProgressBar / Avatar hoverCard trigger)ใๅๆฌ
|
|
212
|
+
// role='button' + tabIndex=0 ๆดๅๅฏ้ต็ค้ป,่ inner buttons ๆงๆ nested-interactive
|
|
213
|
+
// (axe serious)ใ็งป้ค row ๅฑค button semantic โ mouse ไปๅฏ้ป(onClick ไฟ็),
|
|
214
|
+
// ้ต็ค user ็ดๆฅ tab ๅฐ inner primary actionใTrade-off:ๅคฑๅปใๆดๅ Enter ้ๅใ
|
|
215
|
+
// ไฝๆปฟ่ถณ WCAG;ไธ็็ดๅฐ็
ง:Slack message row / Notion page row ๅๆจกๅผ โ row ๅช
|
|
216
|
+
// mouse ้ป,inner ๆ explicit ๆ้่ฒ ่ฒฌ้ต็คใ
|
|
217
|
+
const rowA11y = {}
|
|
218
|
+
|
|
219
|
+
// Compact ้ๆ
่ๆฏ(AR20):็ก้ฒๅบฆๆข โ ้กฏ็คบ `bg-secondary`(= neutral-3)ไฝใๆชๆกๅทฒไธๅณ /
|
|
220
|
+
// ้ๆ
ๅ่กจใ่ฆ่ฆบๅ้,่ทใไธๅณไธญ(ๆ progress bar)ใๅฐ็
งใhover ไธๆน bg(่ฆไธๆน
|
|
221
|
+
// hoverClass canonical:FileItem ๆฐธไธ้กฏ็คบ hover-bg)ใ
|
|
222
|
+
// **็บไป้บผ bg-secondary ไธ bg-neutral-3**:`bg-neutral-3` ไธๆฏๅๆณ Tailwind utility
|
|
223
|
+
// (primitive token `--color-neutral-3` ๆฒ็ถ `@theme inline` ๆฉๆฅ);`bg-secondary`
|
|
224
|
+
// ๆฏ semantic token ๆฉๆฅ็ utility(่ฆ `tokens/color/semantic.css`@theme inline),
|
|
225
|
+
// ๅบ่ฒๅๆจฃๆๅ `--color-neutral-3`ใๅฐ้ฝ Badge low / ProgressBar track SSOTใ
|
|
226
|
+
const compactStaticBg = !progressBar ? 'bg-secondary' : ''
|
|
227
|
+
|
|
228
|
+
// โโ rich(ๅซ็ธฎๅๅฎๆดๅ็พ)โโAR17 canonical:ๅ ้ๆก + gap-2 โโ
|
|
229
|
+
// Rich mode ๆฏใๆชๆก cardใ้ขจๆ ผ,ๅคๆก่ฎๆฏๅ row ่ฆ่ฆบไธๆฏ็จ็ซ card
|
|
230
|
+
// (Slack / Notion / Linear attachment ๆ
ฃไพ)
|
|
231
|
+
if (isRich) {
|
|
232
|
+
return (
|
|
233
|
+
<div
|
|
234
|
+
ref={ref}
|
|
235
|
+
className={cn(
|
|
236
|
+
'group/row flex items-start gap-2 px-3 py-3 w-full text-body leading-compact transition-colors',
|
|
237
|
+
'border border-divider rounded-md bg-surface',
|
|
238
|
+
hoverClass,
|
|
239
|
+
className,
|
|
240
|
+
)}
|
|
241
|
+
onClick={onClick}
|
|
242
|
+
{...rowA11y}
|
|
243
|
+
{...props}
|
|
244
|
+
>
|
|
245
|
+
<Avatar src={thumbnailSrc} alt={name} size={AVATAR_SIZE} shape="square" className="shrink-0" />
|
|
246
|
+
{/* Rich layout invariant(2026-04-23 user ๆ กๆบ):
|
|
247
|
+
- content col minHeight = AVATAR_SIZE(48),็ขบไฟ 1-line desc ๆๅ
งๅฎน โฅ avatar ้ซ
|
|
248
|
+
- `justify-between`(ๆ bar)/`justify-center`(็ก bar):
|
|
249
|
+
* 1-line desc:label ้ + progress bar ๅบ **่ชๅๅฐ้ฝ avatar ้ /ๅบ**
|
|
250
|
+
* ็ก bar:content ๅ็ด center ๅฐ้ฝ avatar ไธญ
|
|
251
|
+
- `gap-2`:desc โ progress bar **่ณๅฐ 8px gap**(multi-line desc ๆ bar ๆบขๅบไปไฟ 8px)
|
|
252
|
+
- row `items-start`:avatar top-align ไฝ่ฆ่ฆบๅผๅฐ(tight-stack box ๅ
ง item ้็) */}
|
|
253
|
+
<div
|
|
254
|
+
className={cn(
|
|
255
|
+
'flex flex-col flex-1 min-w-0 gap-2',
|
|
256
|
+
progressBar ? 'justify-between' : 'justify-center',
|
|
257
|
+
)}
|
|
258
|
+
style={{ minHeight: AVATAR_SIZE }}
|
|
259
|
+
>
|
|
260
|
+
{contentRow}
|
|
261
|
+
{progressBar}
|
|
262
|
+
</div>
|
|
263
|
+
</div>
|
|
264
|
+
)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// โโ compact: py-2 ๅฐ็จฑ, bar absolute ๅบ้จ โโ
|
|
268
|
+
return (
|
|
269
|
+
<div
|
|
270
|
+
ref={ref}
|
|
271
|
+
className={cn(
|
|
272
|
+
'group/row relative flex items-start gap-2 px-3 py-2 w-full text-body leading-compact transition-colors rounded-md',
|
|
273
|
+
compactStaticBg,
|
|
274
|
+
hoverClass,
|
|
275
|
+
className,
|
|
276
|
+
)}
|
|
277
|
+
onClick={onClick}
|
|
278
|
+
{...rowA11y}
|
|
279
|
+
{...props}
|
|
280
|
+
>
|
|
281
|
+
<ItemPrefix>
|
|
282
|
+
<Paperclip size={ICON_PX} className="shrink-0 text-fg-muted" aria-hidden />
|
|
283
|
+
</ItemPrefix>
|
|
284
|
+
{/* Compact ๅ
ฑ็จ contentRow(via ItemContent primitive SSOT)โโ ๅ
ๅ inline
|
|
285
|
+
hand-craft ๅฐ่ด compact labelโdesc gap ่ท rich ไธๅๆญฅใshared contentRow
|
|
286
|
+
ไฟ่ญๅ
ฉ mode ไฟฎ primitive ไธ่ๅ
จๅๆญฅใ */}
|
|
287
|
+
<div className="flex flex-col flex-1 min-w-0">
|
|
288
|
+
{contentRow}
|
|
289
|
+
</div>
|
|
290
|
+
|
|
291
|
+
{/* ProgressBar: absolute ๅบ้จ, left ๅฐ้ฝ label(่ทณ้ icon + gap) */}
|
|
292
|
+
{progressBar && (
|
|
293
|
+
<div className="absolute bottom-0 right-3" style={{ left: `calc(0.75rem + ${ICON_PX}px + 0.5rem)` }}>
|
|
294
|
+
{progressBar}
|
|
295
|
+
</div>
|
|
296
|
+
)}
|
|
297
|
+
</div>
|
|
298
|
+
)
|
|
299
|
+
},
|
|
300
|
+
)
|
|
301
|
+
FileItem.displayName = 'FileItem'
|
|
302
|
+
|
|
303
|
+
// Story auto-compile metadata โ Phase 1 mechanical migration(2026-04-24)
|
|
304
|
+
// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs
|
|
305
|
+
export const fileItemMeta = {
|
|
306
|
+
component: 'FileItem',
|
|
307
|
+
family: 2,
|
|
308
|
+
variants: {
|
|
309
|
+
|
|
310
|
+
},
|
|
311
|
+
sizes: {
|
|
312
|
+
|
|
313
|
+
},
|
|
314
|
+
states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
|
|
315
|
+
tokens: {
|
|
316
|
+
bg: ['bg-neutral-hover', 'bg-secondary', 'bg-surface'],
|
|
317
|
+
fg: ['text-fg-muted', 'text-fg-secondary'],
|
|
318
|
+
ring: [],
|
|
319
|
+
},
|
|
320
|
+
} as const
|
|
321
|
+
|
|
322
|
+
export { FileItem }
|
|
@@ -0,0 +1,326 @@
|
|
|
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 { Upload as UploadIcon, X } from 'lucide-react'
|
|
4
|
+
import { cn } from '@/lib/utils'
|
|
5
|
+
import { Empty } from '@/design-system/components/Empty/empty'
|
|
6
|
+
import { CircularProgress } from '@/design-system/components/CircularProgress/circular-progress'
|
|
7
|
+
import { FileItem } from '@/design-system/components/FileItem/file-item'
|
|
8
|
+
import { Button } from '@/design-system/components/Button/button'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* FileUpload โ ๆๆพ / ้ปๆไธๅณๅๅก
|
|
12
|
+
*
|
|
13
|
+
* ไธ็็ดๅฐ็
ง:Ant Design `Upload.Dragger`ใPolaris `DropZone`ใMaterial community MUI-File-Inputใ
|
|
14
|
+
* ่ๆฌ DS ๆขๆ FileItem(้กฏ็คบๅทฒไธๅณๆชๆก)้
ๅฐ โ ้่ฃก ownใไธๅณ่งธ็ผ + ๆๆพๅตๆธฌใ,
|
|
15
|
+
* ไธๅณๅพ็ๆชๆกๆธ
ๅฎ้กฏ็คบไบค็ตฆ consumer ็จ FileItem ๆธฒๆใ
|
|
16
|
+
*
|
|
17
|
+
* โโ 4 ็ๆ
โโ
|
|
18
|
+
* idle (default) โ border-dashed border-divider bg-surface
|
|
19
|
+
* drag-over โ border-dashed border-primary bg-primary-subtle
|
|
20
|
+
* loading โ ไธๅณไธญ(async)้กฏ็คบ CircularProgress,้ปๆๆฐไบๅ
|
|
21
|
+
* disabled โ opacity-disabled pointer-events-none
|
|
22
|
+
*
|
|
23
|
+
* โโ children ๆๆงฝ โโ
|
|
24
|
+
* ้ ่จญๆธฒๆ `<Empty icon={Upload} title description />` โ ้็จ Empty ๅ
ไปถ own
|
|
25
|
+
* ็ใicon + title + description ๅ็ดๅฑ
ไธญใSSOT ้ฟๅ
่ฆ่ฆบๆผ็งปใEmpty ๆนๅญ้ซ /
|
|
26
|
+
* gap / icon ๅฐบๅฏธๆ FileUpload ่ชๅ่ท้ฒใ่ฅ consumer ๅณ children ๅๆดๅ่ฆๅฏซใ
|
|
27
|
+
*
|
|
28
|
+
* โโ API โโ
|
|
29
|
+
* onUpload: ไฝฟ็จ่
้ธๅๆๆๆพๆชๆกๆ่งธ็ผ,ๅๅณ File[](่ณๅฐ 1 ๅ)ใ
|
|
30
|
+
* multiple: ๅ
่จฑๅคๆชใ้ ่จญ false(ๅฎๆช)ใ
|
|
31
|
+
* accept: MIME filter(ไพ "image/*,.pdf"),ๅณ็ตฆ <input type=file>ใ
|
|
32
|
+
* maxSize: ๅฎๆชๆๅคง bytes;่ถ
้้้ปๅฟฝ็ฅ(consumer ่ฅ้่ฆ้ฏ่ชคๆ็คบ,่ตฐ onReject)ใ
|
|
33
|
+
* onReject: ่ขซ maxSize / accept ๆไธ็ๆชๆก(ๆไพ้ฏ่ชค่จๆฏ้กฏ็คบๆฉๆ)ใ
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Uploaded / uploading file status item(for `files` prop)ใ
|
|
38
|
+
* Consumer ๆ state(progress / status),FileUpload ๅช่ฒ ่ฒฌๆธฒๆใ
|
|
39
|
+
*/
|
|
40
|
+
export interface FileUploadStatus {
|
|
41
|
+
id: string
|
|
42
|
+
name: string
|
|
43
|
+
/** bytes */
|
|
44
|
+
size?: number
|
|
45
|
+
/** Upload ้ฒๅบฆ(0-100)โ uploading ๆ้กฏ็คบ progress bar */
|
|
46
|
+
progress?: number
|
|
47
|
+
status?: 'uploading' | 'completed' | 'error'
|
|
48
|
+
/** Error ่จๆฏ / size ็ญ description */
|
|
49
|
+
description?: React.ReactNode
|
|
50
|
+
/** Thumbnail URL for rich mode */
|
|
51
|
+
thumbnailSrc?: string
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface FileUploadProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onDrop'> {
|
|
55
|
+
onUpload?: (files: File[]) => void
|
|
56
|
+
onReject?: (files: File[], reason: 'size' | 'type') => void
|
|
57
|
+
multiple?: boolean
|
|
58
|
+
accept?: string
|
|
59
|
+
maxSize?: number
|
|
60
|
+
disabled?: boolean
|
|
61
|
+
/**
|
|
62
|
+
* Loading ็ๆ
(async ไธๅณ / ไผบๆๅจ่็ไธญ)ใ
|
|
63
|
+
* - ้กฏ็คบ CircularProgress ๅไปฃ้ ่จญ Empty ๅ
งๅฎน
|
|
64
|
+
* - ้ปๆๆฐ้ปๆ / drag ไบไปถ(้ฟๅ
double-submit)
|
|
65
|
+
* - ๅฎฃๅ `aria-busy="true"` ่ฎ screen reader ๆ็ฅ่็ไธญ
|
|
66
|
+
* - Consumer ่ฒ ่ฒฌๅจไธๅณๅฎๆๅพ่ชๅทฑๅๅ `loading={false}`
|
|
67
|
+
*/
|
|
68
|
+
loading?: boolean
|
|
69
|
+
/** Loading ็ๆ
็ๆๅญๆจ้ก(้ ่จญใไธๅณไธญโฆใ) */
|
|
70
|
+
loadingTitle?: string
|
|
71
|
+
/** ๆจ้กๆๅญ(้ ่จญใClick or drag file here to uploadใ) */
|
|
72
|
+
title?: string
|
|
73
|
+
/** ่ชชๆๆๅญ(้ ่จญใSupport for a single or bulk uploadใ) */
|
|
74
|
+
description?: string
|
|
75
|
+
/** ่ฅๅณๅ
ฅ children,่ฆๅฏซ้ ่จญ Empty ็ตๆง */
|
|
76
|
+
children?: React.ReactNode
|
|
77
|
+
/**
|
|
78
|
+
* Uploaded / uploading ๆชๆกๆธ
ๅฎใๅณๅ
ฅ โ FileUpload ๅจ drop zone ไธๆนๆธฒๆๅ่กจใ
|
|
79
|
+
* ไธๅณ โ ไธ้กฏ็คบ(consumer ๅฏ่ช่ก็จ FileItem ็ตๆ,pre-2026-04-24 ่ก็บ)ใ
|
|
80
|
+
* ๆฏ้
ๆ status ็ๆ
ๆๅฐๆ icon:
|
|
81
|
+
* - `uploading`:CircularProgress(+ progress bar ่ฅ progress ็ตฆ)
|
|
82
|
+
* - `completed`:็ถ ่ฒ โ(success ็ๆ
่ฆ่ฆบ็ขบ่ช)
|
|
83
|
+
* - `error`:็ด
่ฒ โ(+ description ้กฏ็คบ้ฏ่ชค่จๆฏ)
|
|
84
|
+
*/
|
|
85
|
+
files?: FileUploadStatus[]
|
|
86
|
+
/** File list ๆฏ้
้กฏ็คบๆจกๅผใDefault: 'compact'(ๅฎ่ก);'rich' = ๅซ thumbnail / size / progress bar */
|
|
87
|
+
fileListMode?: 'compact' | 'rich'
|
|
88
|
+
/** File list ็งป้ค callbackใๆๅผ โ ๆฏ้
ๅณๅด้กฏ็คบ X dismiss button;็ก โ ไธๅฏ็งป้ค(view-only) */
|
|
89
|
+
onRemove?: (id: string) => void
|
|
90
|
+
/** File list dismiss button ARIA label templateใ้ ่จญ `็งป้ค {name}`ใFor i18n. */
|
|
91
|
+
removeAriaLabel?: (name: string) => string
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// code-quality-allow: long-function โ foundational composite main body โ ๆ sub-fn ๆ่ค้ๅ local state / ref / context binding
|
|
95
|
+
const FileUpload = React.forwardRef<HTMLDivElement, FileUploadProps>(
|
|
96
|
+
(
|
|
97
|
+
{
|
|
98
|
+
onUpload,
|
|
99
|
+
onReject,
|
|
100
|
+
multiple = false,
|
|
101
|
+
accept,
|
|
102
|
+
maxSize,
|
|
103
|
+
disabled = false,
|
|
104
|
+
loading = false,
|
|
105
|
+
loadingTitle = 'ไธๅณไธญโฆ', // i18n-allow: DS default; consumer override via loadingTitle prop
|
|
106
|
+
title = 'Click or drag file here to upload', // i18n-allow: DS default; consumer override via title prop
|
|
107
|
+
description = multiple ? 'Support for a single or bulk upload' : 'Support for a single file upload', // i18n-allow: DS default; consumer override via description prop
|
|
108
|
+
children,
|
|
109
|
+
files,
|
|
110
|
+
fileListMode = 'compact',
|
|
111
|
+
onRemove,
|
|
112
|
+
removeAriaLabel = (name: string) => `็งป้ค ${name}`, // i18n-allow: DS default; consumer override via removeAriaLabel prop
|
|
113
|
+
className,
|
|
114
|
+
onClick,
|
|
115
|
+
...props
|
|
116
|
+
},
|
|
117
|
+
ref,
|
|
118
|
+
) => {
|
|
119
|
+
const inputRef = React.useRef<HTMLInputElement>(null)
|
|
120
|
+
const [isDragOver, setDragOver] = React.useState(false)
|
|
121
|
+
|
|
122
|
+
const filterAndDispatch = (files: FileList | null) => {
|
|
123
|
+
if (!files || files.length === 0) return
|
|
124
|
+
const accepted: File[] = []
|
|
125
|
+
const rejectedBySize: File[] = []
|
|
126
|
+
const rejectedByType: File[] = []
|
|
127
|
+
|
|
128
|
+
Array.from(files).forEach((f) => {
|
|
129
|
+
if (maxSize != null && f.size > maxSize) {
|
|
130
|
+
rejectedBySize.push(f)
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
if (accept && !matchAccept(f, accept)) {
|
|
134
|
+
rejectedByType.push(f)
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
accepted.push(f)
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
if (rejectedBySize.length) onReject?.(rejectedBySize, 'size')
|
|
141
|
+
if (rejectedByType.length) onReject?.(rejectedByType, 'type')
|
|
142
|
+
if (accepted.length) onUpload?.(multiple ? accepted : accepted.slice(0, 1))
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
146
|
+
if (!disabled) inputRef.current?.click()
|
|
147
|
+
onClick?.(e)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// State ๅชๅ
ๅบ:disabled > loading > drag-over > idle(disabled ๆ็กฌ,loading ๆฌกไน)
|
|
151
|
+
const state = disabled ? 'disabled' : loading ? 'loading' : isDragOver ? 'drag-over' : 'idle'
|
|
152
|
+
const isBlocked = disabled || loading
|
|
153
|
+
|
|
154
|
+
const hasFiles = Array.isArray(files) && files.length > 0
|
|
155
|
+
|
|
156
|
+
const fileListNode = hasFiles ? (
|
|
157
|
+
<ul
|
|
158
|
+
className={cn(
|
|
159
|
+
// stack vertically with consistent gap;bg-surface ๅจๅฎนๅจๅค็ chrome / consumer bg ไนไธ
|
|
160
|
+
'flex flex-col gap-2 w-full',
|
|
161
|
+
'mt-3',
|
|
162
|
+
)}
|
|
163
|
+
aria-label="Uploaded files"
|
|
164
|
+
>
|
|
165
|
+
{files!.map((f) => (
|
|
166
|
+
<li key={f.id} className="list-none">
|
|
167
|
+
<FileItem
|
|
168
|
+
mode={fileListMode}
|
|
169
|
+
name={f.name}
|
|
170
|
+
status={f.status}
|
|
171
|
+
progress={f.progress}
|
|
172
|
+
description={f.description ?? (f.size != null ? formatBytes(f.size) : undefined)}
|
|
173
|
+
thumbnailSrc={f.thumbnailSrc}
|
|
174
|
+
actions={
|
|
175
|
+
onRemove ? (
|
|
176
|
+
// Collection remove(per-file)โ ไธๆฏ dismiss surface,ๆ
ไธๅฅ `dismiss` propใ
|
|
177
|
+
// ่ฆ่ฆบ่ dismiss ไธ่ด(text variant + fg-muted dim)โ ๅฐ้ฝ inline-action.spec.md
|
|
178
|
+
// ใDismiss canonical โ X close onlyใL249-251:onRemove callback ไธ่งธ็ผ dismiss propใ
|
|
179
|
+
<Button
|
|
180
|
+
iconOnly
|
|
181
|
+
variant="text"
|
|
182
|
+
size="xs"
|
|
183
|
+
startIcon={X}
|
|
184
|
+
aria-label={removeAriaLabel(f.name)}
|
|
185
|
+
onClick={(e) => {
|
|
186
|
+
e.stopPropagation()
|
|
187
|
+
onRemove(f.id)
|
|
188
|
+
}}
|
|
189
|
+
className="text-fg-muted hover:text-foreground"
|
|
190
|
+
/>
|
|
191
|
+
) : undefined
|
|
192
|
+
}
|
|
193
|
+
/>
|
|
194
|
+
</li>
|
|
195
|
+
))}
|
|
196
|
+
</ul>
|
|
197
|
+
) : null
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<div ref={ref} className={cn('w-full', hasFiles && 'flex flex-col')}>
|
|
201
|
+
<div
|
|
202
|
+
role="button"
|
|
203
|
+
tabIndex={isBlocked ? -1 : 0}
|
|
204
|
+
aria-disabled={disabled || undefined}
|
|
205
|
+
aria-busy={loading || undefined}
|
|
206
|
+
data-state={state}
|
|
207
|
+
onClick={handleClick}
|
|
208
|
+
onKeyDown={(e) => {
|
|
209
|
+
if (isBlocked) return
|
|
210
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
211
|
+
e.preventDefault()
|
|
212
|
+
inputRef.current?.click()
|
|
213
|
+
}
|
|
214
|
+
}}
|
|
215
|
+
onDragEnter={(e) => {
|
|
216
|
+
if (isBlocked) return
|
|
217
|
+
e.preventDefault()
|
|
218
|
+
setDragOver(true)
|
|
219
|
+
}}
|
|
220
|
+
onDragLeave={(e) => {
|
|
221
|
+
if (isBlocked) return
|
|
222
|
+
e.preventDefault()
|
|
223
|
+
setDragOver(false)
|
|
224
|
+
}}
|
|
225
|
+
onDragOver={(e) => {
|
|
226
|
+
if (isBlocked) return
|
|
227
|
+
e.preventDefault()
|
|
228
|
+
}}
|
|
229
|
+
onDrop={(e) => {
|
|
230
|
+
if (isBlocked) return
|
|
231
|
+
e.preventDefault()
|
|
232
|
+
setDragOver(false)
|
|
233
|
+
filterAndDispatch(e.dataTransfer.files)
|
|
234
|
+
}}
|
|
235
|
+
className={cn(
|
|
236
|
+
// ๅฏฌๅบฆ w-full ๅกซๆปฟ consumer ๅฎนๅจ(user ๆ็คบใๅฏฌๅบฆๅกซๆปฟใ);้ซๅบฆ็ฑ padding + ๅ
งๅฎน็ฉๆฑบๅฎ(ไธๅบๅฎ h)
|
|
237
|
+
'flex flex-col items-center justify-center gap-2 text-center w-full',
|
|
238
|
+
// ๅฐ็จฑ padding p-[var(--layout-space-loose)]:ๅ้็ญ่ท,density-aware(md=24px / lg=32px),ๅฐ้ฝ DS chrome padding canonicalใ
|
|
239
|
+
// ไธๅ็กฌๅฏซ px-6 py-10(ไธๅฐ็จฑ+้ token)ใๅ
งๅฎน็ฉ(icon + title + description)ๅ็ดๅ ็็ฑ gap-2 ๆงๅถ
|
|
240
|
+
'rounded-md border-2 border-dashed p-[var(--layout-space-loose)]',
|
|
241
|
+
'cursor-pointer transition-colors',
|
|
242
|
+
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
|
243
|
+
// idle
|
|
244
|
+
'border-divider bg-surface hover:bg-neutral-hover',
|
|
245
|
+
// drag-over
|
|
246
|
+
'data-[state=drag-over]:border-primary data-[state=drag-over]:bg-primary-subtle data-[state=drag-over]:hover:bg-primary-subtle',
|
|
247
|
+
// loading(้ปๆๆฐไบๅไฝไธ opacity-disabled โ ้ฟๅ
่ท disabled ่ฆ่ฆบๆ,ไฟๆใ่็ไธญใ่ชๆ)
|
|
248
|
+
'data-[state=loading]:cursor-progress data-[state=loading]:pointer-events-none',
|
|
249
|
+
// disabled
|
|
250
|
+
'data-[state=disabled]:opacity-disabled data-[state=disabled]:pointer-events-none data-[state=disabled]:cursor-not-allowed',
|
|
251
|
+
className,
|
|
252
|
+
)}
|
|
253
|
+
{...props}
|
|
254
|
+
>
|
|
255
|
+
<input
|
|
256
|
+
ref={inputRef}
|
|
257
|
+
type="file"
|
|
258
|
+
className="hidden"
|
|
259
|
+
multiple={multiple}
|
|
260
|
+
accept={accept}
|
|
261
|
+
disabled={disabled}
|
|
262
|
+
onChange={(e) => filterAndDispatch(e.target.files)}
|
|
263
|
+
/>
|
|
264
|
+
{loading ? (
|
|
265
|
+
<Empty
|
|
266
|
+
icon={<CircularProgress size={48} />}
|
|
267
|
+
title={loadingTitle}
|
|
268
|
+
/>
|
|
269
|
+
) : (
|
|
270
|
+
children ?? (
|
|
271
|
+
<Empty
|
|
272
|
+
icon={UploadIcon}
|
|
273
|
+
title={title}
|
|
274
|
+
description={description}
|
|
275
|
+
/>
|
|
276
|
+
)
|
|
277
|
+
)}
|
|
278
|
+
</div>
|
|
279
|
+
{fileListNode}
|
|
280
|
+
</div>
|
|
281
|
+
)
|
|
282
|
+
},
|
|
283
|
+
)
|
|
284
|
+
FileUpload.displayName = 'FileUpload'
|
|
285
|
+
|
|
286
|
+
// โโ helper: bytes formatter โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
287
|
+
function formatBytes(n: number): string {
|
|
288
|
+
if (n < 1024) return `${n} B`
|
|
289
|
+
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`
|
|
290
|
+
if (n < 1024 * 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(1)} MB`
|
|
291
|
+
return `${(n / (1024 * 1024 * 1024)).toFixed(1)} GB`
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// โโ helpers โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
295
|
+
|
|
296
|
+
function matchAccept(file: File, accept: string): boolean {
|
|
297
|
+
const patterns = accept.split(',').map((s) => s.trim().toLowerCase())
|
|
298
|
+
const fileName = file.name.toLowerCase()
|
|
299
|
+
const fileType = file.type.toLowerCase()
|
|
300
|
+
return patterns.some((p) => {
|
|
301
|
+
if (p.startsWith('.')) return fileName.endsWith(p) // ๅฏๆชๅ e.g. ".pdf"
|
|
302
|
+
if (p.endsWith('/*')) return fileType.startsWith(p.slice(0, -1)) // e.g. "image/*"
|
|
303
|
+
return fileType === p // ๅฎๆด MIME
|
|
304
|
+
})
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Story auto-compile metadata โ Phase 1 mechanical migration(2026-04-24)
|
|
308
|
+
// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs
|
|
309
|
+
export const fileUploadMeta = {
|
|
310
|
+
component: 'FileUpload',
|
|
311
|
+
family: null, // non-family composite / overlay / layout
|
|
312
|
+
variants: {
|
|
313
|
+
|
|
314
|
+
},
|
|
315
|
+
sizes: {
|
|
316
|
+
|
|
317
|
+
},
|
|
318
|
+
states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
|
|
319
|
+
tokens: {
|
|
320
|
+
bg: ['bg-neutral-hover', 'bg-primary-subtle', 'bg-surface'],
|
|
321
|
+
fg: [],
|
|
322
|
+
ring: ['ring-ring'],
|
|
323
|
+
},
|
|
324
|
+
} as const
|
|
325
|
+
|
|
326
|
+
export { FileUpload }
|