@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 @@
|
|
|
1
|
+
{"version":3,"file":"data-table.js","sources":["../../../src/components/DataTable/data-table.tsx"],"sourcesContent":["// @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.\n// code-quality-allow: file-size — foundational composite — 拆檔會複雜化 context / ref / state 同步\nimport * as React from 'react'\nimport { createPortal } from 'react-dom'\nimport { Empty } from '@/design-system/components/Empty/empty'\nimport {\n useReactTable,\n getCoreRowModel,\n getSortedRowModel,\n getExpandedRowModel,\n flexRender,\n type ColumnDef,\n type SortingState,\n type TableOptions,\n type Column,\n} from '@tanstack/react-table'\nimport { useVirtualizer } from '@tanstack/react-virtual'\nimport { TableScrollProvider } from '@/design-system/components/Field/field-context'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { ChevronDown, ArrowUp, ArrowDown, ArrowUpDown, Filter as FilterIcon, EyeOff, X as XIcon, GripVertical } from 'lucide-react'\n// **v15.0 Path B**(對齊 user 「source 留原位 / indicator 為 drop preview / 不 auto-shift」directive):\n// 砍 useSortable + SortableContext 用 useDraggable + useDroppable 分離 hooks(對齊 DS 內 TreeView SSOT)。\nimport { DndContext, DragOverlay, useDraggable, useDroppable, useDndContext, pointerWithin, rectIntersection, useSensor, useSensors, PointerSensor, KeyboardSensor, MeasuringStrategy, type DragEndEvent, type CollisionDetection } from '@dnd-kit/core'\nimport { cn } from '@/lib/utils'\nimport { ICON_SIZE } from '@/design-system/tokens/uiSize/icon-size'\nimport { dragSourceStyle, dropIndicatorRow, dropIndicatorColumn, dragActiveCursor, isReorderNoop, reconstructFullRowGhost, snapToCursorModifier } from '@/design-system/lib/drag-visual'\nimport { nakedCellEditableDisplayHover } from '@/design-system/components/Field/field-wrapper'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/design-system/components/Tooltip/tooltip'\nimport { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from '@/design-system/components/DropdownMenu/dropdown-menu'\nimport { ItemInlineActionButton } from '@/design-system/patterns/element-anatomy/item-anatomy'\nimport { columnTypeDefaults, type ColumnType } from './column-types'\nimport { resolveCellComponent } from './cell-registry'\nimport { DataTableInteractionLayer } from './data-table-interaction-layer'\nimport { Checkbox } from '@/design-system/components/Checkbox/checkbox'\nimport { RadioGroupItem } from '@/design-system/components/RadioGroup/radio-group'\nimport * as RadioGroupPrimitive from '@radix-ui/react-radio-group'\nimport { useControllable } from '@/design-system/hooks/use-controllable'\nimport { Button } from '@/design-system/components/Button/button'\n\n// ── Variants ─────────────────────────────────────────────────────────────────\n\n// outer border = `border-divider`(同 row divider 色)— T-junction connectivity 設計原則:\n// row divider 兩端 meet table outer border;若不同色 → 交匯處視覺斷層;\n// divider 不能加重(過搶眼)→ 淡化 outer border 至 divider 同色,seamless。\n// 對齊 Ant Design colorBorderSecondary idiom(table outer + divider 同色)。\n// 詳 tokens/color/color.spec.md「T-junction connectivity」段。\nconst dataTableVariants = cva('bg-surface rounded-md overflow-hidden', {\n variants: { bordered: { true: 'border border-divider', false: '' } },\n defaultVariants: { bordered: true },\n})\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\ntype TableSize = 'sm' | 'md' | 'lg'\n\nexport interface DataTableProps<TData>\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>,\n VariantProps<typeof dataTableVariants> {\n columns: ColumnDef<TData, any>[]\n data: TData[]\n size?: TableSize\n autoRowHeight?: boolean\n height?: string\n overscan?: number\n emptyState?: React.ReactNode\n enableHover?: boolean\n estimateRowHeight?: number\n tableOptions?: Partial<Omit<TableOptions<TData>, 'data' | 'columns' | 'getCoreRowModel'>>\n rowActions?: (row: TData) => React.ReactNode\n /**\n * Issue 9 cell error system(2026-05-10)。\n *\n * Map of `${rowId}:${colId}` → error message(string | string[])。Cell display mode 在 content\n * 下方渲 `text-body text-error` 訊息,gap-1 spacing。Multi-error 用 array → ul / li 分行渲。\n *\n * **使用建議**:\n * - 搭配 `autoRowHeight` prop:cell error 訊息 wrap → row 自動拉高吸收。fixed 高 row 模式\n * error 訊息會被裁切(consumer 應 set autoRowHeight=true 給有 error 的 use case)。\n * - Edit cell 自動 clear 自己的 error(展開 portal Field 時消失,新值 commit 由 consumer\n * onCellCommit 驗證後決定 set / clear)。\n * - aria-describedby:cell wrapper 接 error message id,AT 讀 cell 內容後讀 error。\n *\n * 對齊 AG Grid `cellClassRules='ag-cell-error'` + Material X-DataGrid `errorMessage` cell prop +\n * Airtable record validation idiom。\n */\n cellErrors?: Record<string, string | string[]>\n pinnedLeftColumns?: string[]\n pinnedRightColumns?: string[]\n /** Inline edit 視覺模式:body cell 間加垂直分隔線,select 類欄位顯示指示器 */\n inlineEdit?: boolean\n /**\n * Slice D Step 1B(2026-05-10):啟用 spreadsheet-grade interaction overlay。\n * Default false(backward-compat)。Enable 後 hover/editor/selected/range 由\n * `DataTableInteractionLayer` overlay 統一畫,per `.claude/planning/datatable-spreadsheet-rfc.md`。\n * 漸進切換階段,當前 v1 minimal:hover overlay 1 layer。\n */\n experimentalSpreadsheetOverlay?: boolean\n /**\n * Slice D Step 3.2(2026-05-10):啟用 ActiveEditorController portal Field。\n * Default false(backward-compat)。\n * Enable 後 active edit cell 不 render Field inline,改 portal 進 overlay layer\n * (per RFC Contract 8 「one geometry, two paint owners」)。\n * 當前 scaffold:prop 已收,functional portal logic Step 3.3 實作。\n * Per codex Q-7 string-first canary:string cell first,picker types 漸進。\n */\n experimentalActiveEditorController?: boolean\n /**\n * Slice D Step 4(spreadsheet semantics,2026-05-10 user 拍板 + codex Layer B Q2.1 confirm):\n * Excel-like cell selection:click 1=select / click 2=edit / Shift+click=range。\n * Default false opt-in(per codex「DataTable is not a spreadsheet」既有原則 +\n * data-table.principles.stories.tsx L283-292)。\n * Enable 後 inlineEdit cell click 行為:\n * - Plain click → setSelectedCellId,**不**進 edit mode\n * - Click on already-selected → enter edit\n * - Shift+click → extend range from anchor\n * - Double-click / Enter / F2 / printable(deferred) → enter edit on selected\n * - Click empty area → clear selection\n * 視覺:Layer 渲 SelectionRect(solid `--primary` 2px border)+ RangeRect\n * (`--primary-subtle` bg fill)— per user「不要 dash 直接實的就好」+ codex Q2.2 token。\n */\n spreadsheetMode?: boolean\n\n // ── L2 Selection(see data-table.spec.md「L2 選取」)──\n /** 已選 row IDs(controlled) */\n selection?: string[]\n /** 預設選取(uncontrolled) */\n defaultSelection?: string[]\n /** Selection 變更 callback */\n onSelectionChange?: (next: string[]) => void\n /** 是否啟用 selection / 模式;true 等同 'multi' */\n selectable?: boolean | 'single' | 'multi'\n /** Row 是否可選(disabled rows 只 disable checkbox,row 內容正常 render) */\n isRowSelectable?: (row: TData) => boolean\n /** 取 row 唯一 ID(selection 用);default `(row, index) => String(index)` */\n getRowId?: (row: TData, index: number) => string\n /** Checkbox aria-label fallback;default `'Select row'` */\n getRowAriaLabel?: (row: TData) => string\n /** Filter 後 hidden selected rows 是否保留(default false,對齊 Material/AG Grid 共識) */\n preserveSelectionOnFilter?: boolean\n\n // ── L3 Column visibility(顯示隱藏)──\n /** 欄位顯隱(controlled),Record<columnId, boolean>;true / undefined = 顯示 */\n columnVisibility?: Record<string, boolean>\n /** 預設顯隱(uncontrolled) */\n defaultColumnVisibility?: Record<string, boolean>\n /** 顯隱變更 callback */\n onColumnVisibilityChange?: (next: Record<string, boolean>) => void\n\n // ── L3 Sort(排序)──\n /** 啟用多欄排序(shift+click 加 secondary;單擊仍 replace);default true,對齊 AG Grid / Material */\n enableMultiSort?: boolean\n\n // ── L3 Filter trigger(callback only — UI in consumer)──\n /** Cell ⌄ menu「Filter by this」點擊,emit columnId 讓 consumer 開 global filter panel + prefill。\n * 對齊 ClickUp / Airtable / Notion 派 — filter 永遠 global,不 per-cell inline。 */\n onColumnFilterTrigger?: (columnId: string) => void\n\n // ── L4 Inline edit ──\n /**\n * Cell value commit callback。User 編完(blur/Enter/select-option)→ 觸發本 callback。\n * Consumer 自管 data update + persistence。\n * 啟用條件:該 column `meta.editable` 為 true 或 fn 回傳 true。詳 `column-types.ts`。\n */\n onCellCommit?: (rowId: string, columnId: string, value: unknown) => void\n\n // ── L4 Row drag(Jira-style reorder)──\n /**\n * 啟用 row drag reorder。為 true 時,row 最左出 GripVertical handle(hover-revealed),\n * 拖曳改 default order via `onRowReorder` callback。\n *\n * Sort × Drag 互斥:`sorting.length > 0` 時 drag handle 視覺 disabled + Tooltip\n * 「排序中無法拖曳,清除排序後可重排」。對齊 Notion / Airtable 共識。\n *\n * **必填 `getRowId`**:enableRowDrag 為 true 時 consumer 必傳 `getRowId`,用穩定 row identity 作 dnd source / target id。否則 dnd 用 row.index 會在 reorder 後錯位(runtime 不會 throw,但 reorder 行為不正確)。\n *\n * **v2(2026-05-05)修正**:\n * - Virtualizer × transform:被拖 row 略過 `measureElement`(透過 SortableRowCtx 廣播 active id),避免 transform 干擾測量\n * - 3-panel mirror sync:每 region 都呼叫 `useSortable({id})`(同 SortableContext 共用 state),mirror 自然取得相同 transform\n * - Cross-parent drop:nested 全 row 進 SortableContext.items,自訂 collisionDetection 過濾出「同 parent siblings」;cross-parent over → 不觸發,handle cursor `not-allowed`\n *\n * 詳 `data-table.spec.md`「L4 Row drag」段。\n */\n enableRowDrag?: boolean\n /**\n * Row reorder callback。User 拖曳完成觸發。\n * @param sourceId 拖曳的 row id\n * @param targetId 放下的目標 row id\n * @param position 'before' | 'after' — 放在 target 前 OR 後\n */\n onRowReorder?: (sourceId: string, targetId: string, position: 'before' | 'after') => void\n /**\n * 啟用全表 column resize(2026-05-06 v11):\n * - `true`: 所有 data columns 全 fixed width,header 右邊出現 resize handle(hover 顯色 +\n * cursor:col-resize),user 拖拉調整 column width。System columns(checkbox / drag handle /\n * row actions)永遠 fixed,不在 resize 集合。\n * - `false`(default): 所有 data columns 全 flex-grow:1 均分剩餘寬度。\n *\n * **二選一 canonical**(對齊 Notion / Airtable / Linear product UI 共識)— 不支援 per-column\n * mixed,簡單明確。Min width 預設 80px,consumer 透過 `columnDef.minSize` override。\n */\n enableColumnResize?: boolean\n /**\n * Column resize callback。User 拖完一輪觸發(commit-on-pointerup,非 live)。Consumer 收到\n * 自管 width persistence(localStorage / URL / API)— DS 不持久化(對齊「DS 不包全域 provider」原則)。\n * @param columnId 被 resize 的 column id\n * @param width 最終 width(px)\n */\n onColumnResize?: (columnId: string, width: number) => void\n /**\n * 啟用全表 column reorder(2026-05-06 v11):\n * - `true`: 所有 data column header 可拖曳重排,DragOverlay portal 顯示 ghost\n * - `false`(default): 不啟用\n *\n * 使用 `columnDef.meta.locked = true` 標示鎖定欄(無 grab cursor、不啟動 drag、被拖過不顯\n * drop indicator)。對齊 Notion / Linear locked column canonical。\n */\n enableColumnReorder?: boolean\n /**\n * Column reorder callback。\n * @param sourceId source column id\n * @param targetId target column id\n * @param position 'before' | 'after'\n */\n onColumnReorder?: (sourceId: string, targetId: string, position: 'before' | 'after') => void\n}\n\n// ── Cell Rendering(Phase C 2026-05-05 — type-keyed registry SSOT)─────────────\n//\n// 原 `renderTypedValue` switch + `EditableCellContent` switch 兩條平行 type-switch\n// 已 collapse 為單一 `cellRegistry`(./cell-registry.ts)— 每個 type → 一個 cell component,\n// 同時處理 display + edit mode(底層 Field control 的 mode prop)。對齊 M17 SSOT consolidation。\n//\n// 對齊 Notion / Airtable type-aware inline edit canonical(詳 spec §十二):\n// - string / number / currency:cell click → inline edit\n// - date / time / select / multiSelect / person / multiPerson:cell click → 進 edit mode\n// - boolean:不分 read/edit mode,直接 `<Checkbox>` 點即 toggle + commit\n// - url:read = LinkInput display + hover Pencil button,click Pencil 才進 edit mode\n//\n// Cell id format: `${rowId}__${columnId}`(編輯狀態 keying)\n// Commit: blur OR Enter OR overlay close → 呼叫 onCellCommit\n// Cancel: Esc → 退出 edit mode 不 commit\n//\n// World-class source(@benchmark-unverified):AG Grid cellRendererSelector / Material X-Grid\n// `valueGetter + renderCell` / Notion property type registry。\n\nconst cellEditId = (rowId: string, colId: string) => `${rowId}__${colId}`\n\n// ── Constants ────────────────────────────────────────────────────────────────\n\n// Phase C(2026-05-05):cell 水平 padding 從 magic `0.75rem` 提升為 `--table-cell-px` token\n// (詳 ./data-table.css)— consumer 可走 CSS override 改值,不再 hard-code in TS。\n// L2 selection 內部 column id(避免 magic string 重複)\nconst SELECT_COL_ID = '__select__'\nconst cellPadding: React.CSSProperties = { paddingBlock: 'var(--table-cell-py)', paddingInline: 'var(--table-cell-px)' }\nconst HEADER_BG = 'bg-muted'\n\n// Column sizing canonical(2026-05-06 v11 — table-level all-or-nothing,Notion / Airtable / Linear 共識):\n// - **Table-level prop `enableColumnResize`** 控制全表 mode(per-column mixed 已 retire,跟 product\n// UI 世界級對齊 — Notion / Airtable / Linear 都是全表二選一,簡單明確)\n// - `enableColumnResize=true` → 所有 data columns 全 fixed width(尊重 user 拖拉)\n// - `enableColumnResize=false` → 所有 data columns 全 flex-grow:1 均分剩餘寬度(預設,minWidth 保護)\n// - **System columns**(`__select__` / drag handle / row actions)永遠 fixed,跟 enableColumnResize 無關\n// - maxSize 一律 forward 為 maxWidth(防 flex 無限擴張)\n//\n// 預設 min width = `MIN_COLUMN_WIDTH`(80px;對齊 Polaris IndexTable / AG Grid 範圍下限),consumer\n// 可透過 `columnDef.minSize` override。\nexport const MIN_COLUMN_WIDTH = 80\n\nfunction columnSizeStyle(\n col: { id: string; getSize: () => number; columnDef: { minSize?: number; maxSize?: number } },\n opts: { resize: boolean; isSystemCol: boolean },\n): React.CSSProperties {\n const baseSize = col.getSize()\n // **Regression fix(2026-05-06 v14.1)**:default fallback 從 `MIN_COLUMN_WIDTH (80)` 改回\n // `baseSize`(等於 v9 行為)。前 v11 column resize commit 改 fallback 為 80 後,enableColumnResize=false\n // 的 default flex case 全 column 可 shrink 到 80 → flex 均分忽視 `size` prop → Note 360 被擠到 204\n // → text wrap 行數爆增 → autoRow cell 變高 → edit textarea rows=3 估算更不準 → shrink 看起來壞掉。\n // v9 直覺:沒明示 minSize 預設不 shrink 低於 size。enableColumnResize=true 仍 honour `MIN_COLUMN_WIDTH`\n // (因 user 主動拖拉時要能縮)。\n const minSize = col.columnDef.minSize ?? (opts.resize ? MIN_COLUMN_WIDTH : baseSize)\n const maxSize = col.columnDef.maxSize\n // System columns 永遠 fixed(checkbox / drag handle 等內建欄位,不在 resize 集合)\n if (opts.isSystemCol) {\n return { width: baseSize, minWidth: baseSize, maxWidth: maxSize }\n }\n // Data columns:enableColumnResize=true → fixed 尊重 user 拖拉\n if (opts.resize) {\n return { width: baseSize, minWidth: minSize, maxWidth: maxSize }\n }\n // Data columns:enableColumnResize=false → flex grow but NOT shrink below `size` prop。\n // 對齊 v9 行為:column 沒明示 minSize 時固定 ≥ baseSize(尊重 user `size` 設定),table 寬不夠\n // 觸發 H scroll(預期)。前 v11 換 MIN_COLUMN_WIDTH=80 fallback 讓 columns 全擠等寬,違 user\n // 預期。\n // **Tanstack default 干擾**:tanstack v8 `defaultColumn.minSize=20` 會 merge 進 column.columnDef\n // → `col.columnDef.minSize` 永遠不 undefined → `?? baseSize` 不 fall back。\n // 解法:直接用 baseSize(若 user 要明示 shrink-below-size,改 `enableColumnResize=true` 或別自設\n // `minSize` < size)。\n //\n // **flex-basis: baseSize(2026-05-06 v14.2)**:把 baseSize 當 explicit basis(不是 `0%`)。\n // 為什麼:flex item base = basis + padding(box-sizing: border-box content-box 行為)。前 `0%`\n // basis → cell padding 變 base 一部分。display(padding 12)vs edit(padding 0,Field 接管)\n // 兩態 base 不同 → flex 重分配 → user 報「Price cell 進 edit 寬度縮 12px」(verify by\n // debug-v14-1-display-edit-rect-match.mjs:Price display 130.5 → edit 118.5 = -12px)。\n // explicit basis = baseSize 讓 padding 不參與 base 計算 → display↔edit 寬度穩定。\n return { flex: `1 1 ${baseSize}px`, minWidth: baseSize, maxWidth: maxSize }\n}\n\nconst SYSTEM_COL_IDS = new Set([SELECT_COL_ID, '__drag__', '__actions__'])\nconst isSystemColumn = (colId: string) => SYSTEM_COL_IDS.has(colId)\n\n// ── TruncateCell ─────────────────────────────────────────────────────────────\n// Shared ResizeObserver(2026-04-22 D3 perf audit):從 per-cell RO 改為全 DS 共用一個 RO\n// dispatch 到 per-element callback。10 col × 100 row = 1 RO(before:1000 RO)。\n// 跨 OS 一致的 RO 行為;element 卸載時 cleanup。\n\ntype RoCallback = (entry: ResizeObserverEntry) => void\nlet sharedResizeObserver: ResizeObserver | null = null\nconst roCallbacks = new WeakMap<Element, RoCallback>()\n\nfunction getSharedRO(): ResizeObserver {\n if (sharedResizeObserver) return sharedResizeObserver\n sharedResizeObserver = new ResizeObserver((entries) => {\n entries.forEach((entry) => {\n const cb = roCallbacks.get(entry.target)\n if (cb) cb(entry)\n })\n })\n return sharedResizeObserver\n}\n\nfunction observeShared(el: Element, cb: RoCallback): () => void {\n const obs = getSharedRO()\n roCallbacks.set(el, cb)\n obs.observe(el)\n return () => {\n roCallbacks.delete(el)\n obs.unobserve(el)\n }\n}\n\nfunction TruncateCell({ children, className }: { children: React.ReactNode; className?: string }) {\n const ref = React.useRef<HTMLSpanElement>(null)\n const [isTruncated, setIsTruncated] = React.useState(false)\n React.useEffect(() => {\n const el = ref.current\n if (!el) return\n const check = () => setIsTruncated(el.scrollWidth > el.clientWidth)\n check()\n return observeShared(el, check)\n }, [])\n const span = <span ref={ref} className={cn('truncate min-w-0', className)}>{children}</span>\n if (!isTruncated) return span\n return <Tooltip><TooltipTrigger asChild>{span}</TooltipTrigger><TooltipContent>{children}</TooltipContent></Tooltip>\n}\n\n// ── L4 Row Drag: SortableRowContext (v2) ─────────────────────────────────────\n// v2:每 region(left / center / right)各 mount 一次 SortableRowProvider — 多個 useSortable\n// 共用同一 SortableContext / 同 row id 時,dnd-kit 內部以 id 為 unit 分發 transform / isDragging,\n// 各 hook instance 取得相同值,因此 mirror region 自然跟動(v1 mirror static bug 修正)。\n// listeners 仍只走 primary region(避免 pointer 事件雙重觸發);primary = left region 若存在否則 center。\n// `invalidDrop`(cross-parent over)走 prop 廣播給 DragHandleCell 切 cursor-not-allowed。\ninterface SortableRowCtxValue {\n setNodeRef: (el: HTMLElement | null) => void\n role: 'primary' | 'mirror'\n style: React.CSSProperties\n attributes: Record<string, unknown>\n isDragging: boolean\n /** **v15.6 button-only drag**(對齊 Notion / Linear / Jira canonical):\n * 整列拖 + ghost 跟 cursor 在 multi-instance same-id pinned column 場景互相矛盾——\n * 唯一 single-source-of-activation = visible RowDragHandle Button。\n * Source DOM = primary row(`setNodeRef`),activator = button(`handleSetActivatorNodeRef`),\n * listeners = button(`handleListeners`)。User 從哪個 region 都看見 portal'd button → 點下啟動。\n * Row click 不觸發 drag(允許 row click → select / open detail 等別的 UX)。\n * 保留 `rowListeners`/`rowAttributes` field 但 button-only mode 為 undefined。 */\n rowListeners: Record<string, unknown> | undefined\n rowAttributes: Record<string, unknown>\n /** RowDragHandle Button 用:接 setActivatorNodeRef → button rect 當 activator;\n * primary 才提供(mirror 不需要,RowDragHandle 只在 primary region 渲染) */\n handleSetActivatorNodeRef: ((el: HTMLElement | null) => void) | undefined\n handleListeners: Record<string, unknown> | undefined\n handleAttributes: Record<string, unknown>\n /** drag 進行中且當前 over target 與 active 不同 parent → invalid signal */\n invalidDrop: boolean\n}\nconst SortableRowCtx = React.createContext<SortableRowCtxValue | null>(null)\n\n/** Per-region per-row sortable wrapper(v2 multi-instance pattern)。\n * 同 row.id 在 left/center/right 三 region 各 mount 一次 — useSortable 共享同 SortableContext\n * state,各 instance 取得相同 transform → mirror 自動跟動。\n * primary instance 額外提供 listeners 給 DragHandleCell;mirror 不提供避免雙觸發。 */\nfunction SortableRowProvider(props: {\n id: string\n disabled?: boolean\n role: 'primary' | 'mirror'\n invalidDrop: boolean\n children: (ctx: SortableRowCtxValue) => React.ReactNode\n}) {\n // **v15.4 final architectural split**:multi-instance same-id 是 dnd-kit anti-pattern。\n // 必須完全分離 component 讓 hook mount tree 不衝突:\n // - primary 走 SourceRowProvider(useDraggable + useDroppable)— 唯一 source\n // - mirror 走 MirrorRowProvider(useDroppable only)— 接受 drop target 但不參與 drag source\n // 之前 v15.2/15.3 同 component 内 conditional setNodeRef/disabled 仍讓 mirror instance 進入\n // dnd-kit context store,導致 last-mount-wins 把 activator 取成 mirror region row → ghost\n // 起點偏離 cursor。Split 後 dnd-kit 只看到 primary instance,問題消滅。\n return props.role === 'primary' ? <SourceRowProvider {...props} /> : <MirrorRowProvider {...props} />\n}\n\nfunction SourceRowProvider({\n id,\n disabled,\n role,\n invalidDrop,\n children,\n}: {\n id: string\n disabled?: boolean\n role: 'primary' | 'mirror'\n invalidDrop: boolean\n children: (ctx: SortableRowCtxValue) => React.ReactNode\n}) {\n const draggable = useDraggable({ id, disabled, data: { type: 'row' } })\n const droppable = useDroppable({ id, disabled, data: { type: 'row' } })\n // **v15.6 button-only drag**:setActivatorNodeRef 不接 row,改由 RowDragHandle Button 接(via ctx)。\n // setNodeRef = primary row(source DOM,ghost 抓這個);droppable.setNodeRef = same row(droppable target)。\n const setRefs = React.useCallback((el: HTMLElement | null) => {\n draggable.setNodeRef(el)\n droppable.setNodeRef(el)\n }, [draggable.setNodeRef, droppable.setNodeRef])\n const isDragging = draggable.isDragging\n const style: React.CSSProperties = { ...dragSourceStyle(isDragging) }\n // a11y(2026-05-07 v15.10 codex P1 fix):button-only drag mode 下,row 本身不該成為\n // keyboard tab stop。dnd-kit `useDraggable.attributes` 含 `role=\"button\" tabIndex=0\n // aria-roledescription=\"...\"` 全給 activator 用,套到 row div 會讓每筆 row tabbable\n // (large table 累積上百 inert focus stops,grid navigation 體驗壞)。\n // **拆分**:rowAttributes 留空(row 是 passive container)/ handleAttributes 全給\n // RowDragHandle Button(它是真 activator,Button 自帶 role/tabIndex 完全相容)。\n const handleAttrs = draggable.attributes as unknown as Record<string, unknown>\n const ctxValue: SortableRowCtxValue = {\n setNodeRef: setRefs,\n role,\n style,\n attributes: {},\n isDragging,\n // row 不接 listeners(button-only),baseRowDiv `{...(extra?.listeners ?? {})}` 自動 noop\n rowListeners: undefined,\n rowAttributes: {},\n // Button activator + listener:portal'd RowDragHandle Button 走這條 ctx,\n // user 從任何 region 看見 button → 點下啟動 drag,activator rect = button DOM(24×24),\n // ghost 起點 = button 位置(table outer 左 12px),cursor 在 ghost 左前段(自然視覺)。\n handleSetActivatorNodeRef: draggable.setActivatorNodeRef,\n handleListeners: draggable.listeners as unknown as Record<string, unknown> | undefined,\n handleAttributes: handleAttrs,\n invalidDrop,\n }\n return <SortableRowCtx.Provider value={ctxValue}>{children(ctxValue)}</SortableRowCtx.Provider>\n}\n\nfunction MirrorRowProvider({\n id,\n disabled,\n role,\n invalidDrop,\n children,\n}: {\n id: string\n disabled?: boolean\n role: 'primary' | 'mirror'\n invalidDrop: boolean\n children: (ctx: SortableRowCtxValue) => React.ReactNode\n}) {\n // Mirror region(left / right pinned)只 mount useDroppable — 接受 drop target,\n // 但不參與 drag source(避免 multi-instance same-id 衝突)。\n // RowDragHandle Button 只在 primary region 渲染(per `showDragHandle = ... && isPrimaryRegion`),\n // mirror ctx 不需要 handle listeners / activator,相關 field 為 undefined。\n // **v15.8 Bug 3 fix**(對齊 user 「source 沒一整條都有 disabled opacity」):\n // mirror region drag 期間需跟 primary 同步顯 opacity-disabled,讓 source row 跨三 region\n // 視覺一致(SKU 釘選欄 + center + Updated 釘選欄整列半透明)。透過 useDndContext active\n // 判斷:any drag activated with active.id === own row id → mirror 也 isDragging。\n const droppable = useDroppable({ id, disabled, data: { type: 'row' } })\n const dndCtx = useDndContext()\n const isDragging = dndCtx.active?.id === id\n const ctxValue: SortableRowCtxValue = {\n setNodeRef: droppable.setNodeRef,\n role,\n style: { ...dragSourceStyle(isDragging) },\n attributes: {},\n isDragging,\n rowListeners: undefined,\n rowAttributes: {},\n handleSetActivatorNodeRef: undefined,\n handleListeners: undefined,\n handleAttributes: {},\n invalidDrop,\n }\n return <SortableRowCtx.Provider value={ctxValue}>{children(ctxValue)}</SortableRowCtx.Provider>\n}\n\n/** DraggableHeaderCell — wrap header cell 跟 dnd-kit useSortable 接軌(2026-05-06 v14.2)。\n *\n * Why wrap-not-rewrite:`headerCellEl` 既有邏輯複雜(sort / resize / select column / right region 等),\n * 改 inline useSortable 入侵性高。本 wrapper cloneElement 注入 ref / style / listeners → 既有 render\n * 保持 untouched,單一職責 = 加 drag affordance。\n *\n * Behavior:\n * - useSortable 永遠 call(Rules of Hooks)— `disabled=true` 時不啟動 listeners\n * - `data: { type: 'column', columnId }` 餵 dnd-kit handleDragStart / handleDragEnd 區分 row/column drag\n * - 注入 ref(setNodeRef)+ transform style + transition + opacity(drag 時 source invisible,DragOverlay 顯 ghost)\n * - draggable 時注入 attributes + listeners + cursor:grab / `data-column-id` (DragOverlay snapshot 用)\n * - locked column / system column → disabled,無 grab cursor / 不啟動 drag\n *\n * 對齊 TanStack Column DnD canonical(<https://tanstack.com/table/latest/docs/framework/react/examples/column-dnd>)\n * + Notion / Airtable header drag UX。 */\nfunction DraggableHeaderCell({\n id,\n disabled,\n isLocked,\n dropIndicatorSide,\n children,\n}: {\n id: string\n disabled: boolean\n isLocked: boolean\n /** Notion blue line drop indicator(2026-05-06 v14.4):'before' = 左邊緣藍線 / 'after' = 右邊緣藍線 / null = 無 */\n dropIndicatorSide: 'before' | 'after' | null\n children: React.ReactElement\n}) {\n // **v15.0 Path B refactor**(對齊 TreeView SSOT):分離 useDraggable + useDroppable,不 auto-shift\n const draggable = useDraggable({ id, disabled, data: { type: 'column', columnId: id } })\n const droppable = useDroppable({ id, disabled, data: { type: 'column', columnId: id } })\n const setRefs = React.useCallback((el: HTMLElement | null) => {\n draggable.setNodeRef(el)\n droppable.setNodeRef(el)\n }, [draggable.setNodeRef, droppable.setNodeRef])\n const isDragging = draggable.isDragging\n const dragStyle: React.CSSProperties = {\n ...dragSourceStyle(isDragging),\n }\n // cloneElement 注入 — 不額外加 wrapper div(避免破壞 flex / column width 計算)\n const childProps = (children as React.ReactElement<{ style?: React.CSSProperties; className?: string; role?: string }>).props\n // useDraggable.attributes 含 `role=\"button\"` + `tabIndex` 等 — 全部 spread 會蓋掉 header 原 `role=\"columnheader\"`\n // (a11y 必保 columnheader 語意)。strip role + 保留 aria-* / tabIndex / aria-roledescription:\n const { role: _draggableRole, ...draggableAttrs } = draggable.attributes as unknown as Record<string, unknown>\n // Drop indicator(SSOT 對齊 TreeView):2px primary line via pseudo-element\n const indicatorClass = dropIndicatorSide === 'before'\n ? dropIndicatorColumn.pseudoBefore\n : dropIndicatorSide === 'after'\n ? dropIndicatorColumn.pseudoAfter\n : ''\n return React.cloneElement(children as React.ReactElement<Record<string, unknown>>, {\n ref: setRefs,\n style: { ...(childProps.style ?? {}), ...dragStyle },\n 'data-column-id': id,\n 'data-column-locked': isLocked || undefined,\n ...(disabled ? {} : { ...draggableAttrs, ...(draggable.listeners as unknown as Record<string, unknown>) }),\n // 2026-05-06 v14.9 cursor canonical(對齊 Notion / Jira):\n // **idle hover NOT 顯 cursor-grab** — header click 觸發 sort,grab cursor 會誤導 user 以為「點 = 拖」;\n // **drag activation 後**(isDragging=true,過 8px activationConstraint)才顯 cursor-grabbing。\n // user 點 = sort / 長壓 = drag,兩語意分開不互踩。\n className: cn(childProps.className, isDragging && dragActiveCursor, indicatorClass),\n })\n}\n\n/** Row drag handle — Portal-rendered, position:fixed 真正水平置中於 table outer border line(Jira canonical)。\n *\n * v15.2 重構:**Button 純視覺 affordance**,不再 spread drag listeners — 改由 row div 整列接 listeners\n * (TreeView SSOT)。Button 只負責顯示「此 row 可拖」的視覺暗示。\n *\n * Why Portal + position:fixed(2026-05-05 v4):\n * DataTable 結構含三層 overflow-hidden(outer wrapper / leftBody / row),用 absolute + translate-x:-50%\n * 凸出 row 左 border 會被三層任一裁切。position:fixed escape 所有 ancestor overflow constraint。\n *\n * - 不佔 column 空間;hover-revealed 透過 row.dataset.hovered MutationObserver 觸發\n * - Button variant=\"tertiary\" iconOnly size=\"xs\"(24px chip)\n * - 任何 row drag 進行時(activeDragId != null)整體隱藏 — 對齊 user directive:\n * drag 期間「INDICATOR + GHOST」就夠了,所有 row 不顯 hover bg / drag button */\n// code-quality-allow: long-function — Portal escape + cross-region hover delegation + MutationObserver + scroll-tracking 4 mechanism 結合在 RowDragHandle 內;每 mechanism 獨立 hook 會破壞 row context coupling\nfunction RowDragHandle({ disabled, anyDragActive }: { disabled: boolean; anyDragActive: boolean }) {\n const ctx = React.useContext(SortableRowCtx)\n const [rowEl, setRowEl] = React.useState<HTMLDivElement | null>(null)\n const [portalTarget, setPortalTarget] = React.useState<HTMLElement | null>(null)\n const [pos, setPos] = React.useState<{ top: number; left: number; rowHovered: boolean } | null>(null)\n // Portal 逃逸 row DOM → cursor 移到 button 上時 row mouseleave → button hide → cycle flicker(2026-05-05)。\n // Fix:button 自帶 hover state,visibility = rowHovered || buttonHovered || isDragging。\n const [buttonHovered, setButtonHovered] = React.useState(false)\n\n // Anchor span ref callback finds the parent row element(自身位置 = row 內部,parentElement = row div)。\n // 用 useState 觸發 effect re-run(child ref callback 會 fire 在 commit phase,early enough for layout effect)\n const anchorRef = React.useCallback((node: HTMLSpanElement | null) => {\n setRowEl((node?.parentElement as HTMLDivElement) ?? null)\n }, [])\n\n React.useLayoutEffect(() => {\n if (!rowEl || !ctx || ctx.role !== 'primary') return\n\n // Portal target = table outer 的 parent(保持 CSS variable / theme scope 繼承,\n // 不 portal 到 document.body — body 沒 theme tokens 會使 Button tertiary 變透明)\n const tableEl = rowEl.closest<HTMLElement>('[data-data-table-outer]')\n setPortalTarget(tableEl?.parentElement ?? null)\n\n const update = () => {\n if (!tableEl) return\n const rRect = rowEl.getBoundingClientRect()\n const tRect = tableEl.getBoundingClientRect()\n // v15.1:drag 期間 source button hide(visible 邏輯已 guard isDragging),\n // 此處只報「真實 hover」狀態,不疊 isDragging mask。\n const rowHovered = rowEl.hasAttribute('data-hovered')\n setPos({\n top: rRect.top + rRect.height / 2,\n left: tRect.left, // table outer 左 border line position(viewport coords)\n rowHovered,\n })\n }\n\n update()\n\n // Observe row data-hovered changes(cross-region hover delegation 設置 dataset.hovered)\n const observer = new MutationObserver(update)\n observer.observe(rowEl, { attributes: true, attributeFilter: ['data-hovered'] })\n\n // Update on scroll(capture phase 抓所有 scroll container)+ resize\n // 2026-05-16 Round 5 codex audit fix:capture rAF ID + cancel on cleanup(原 uncancelled\n // rAF 在 unmount 後可能 fire `update` → setPos on stale ref。Same race-pattern class as\n // useOverflowCount fix `combobox.tsx:130`)。\n let scrollRafId = 0\n const onScroll = () => {\n if (scrollRafId) cancelAnimationFrame(scrollRafId)\n scrollRafId = requestAnimationFrame(() => {\n scrollRafId = 0\n update()\n })\n }\n window.addEventListener('scroll', onScroll, true)\n window.addEventListener('resize', onScroll)\n\n return () => {\n observer.disconnect()\n if (scrollRafId) cancelAnimationFrame(scrollRafId)\n window.removeEventListener('scroll', onScroll, true)\n window.removeEventListener('resize', onScroll)\n }\n }, [rowEl, ctx])\n\n // 永遠 render anchor span(讓 anchorRef 可拿到 row element)。\n // A3 fix(2026-05-05):顯式 `top:0 left:0 pointer-events:none` — 雖 width/height=0 不該佔\n // flex space,但部分瀏覽器對 abs span 在 flex container 行為微妙 → 顯式座標固定原點,\n // 確保第一個 cell 文字位置不被推開。\n // ctx 為 null 或 mirror role 時 anchor 仍渲染但不渲 handle Portal\n const anchor = (\n <span\n ref={anchorRef}\n aria-hidden\n style={{ position: 'absolute', top: 0, left: 0, width: 0, height: 0, pointerEvents: 'none' }}\n />\n )\n\n if (!ctx || ctx.role !== 'primary' || !pos) return anchor\n\n const canDrag = !disabled\n const showInvalid = !!ctx.invalidDrop && !!ctx.isDragging\n // Visibility canonical v15.3(對齊 Linear / Jira 世界級 + user directive\n // 「source 的 drag button 反倒是可以留在原本的位置維持被壓住的狀態」):\n // - idle:rowHovered || buttonHovered → 顯示\n // - drag 進行中:**source row 強制顯示 + active 視覺**(讓 user 知道哪個被壓住)\n // 其他 row 的 button 隱藏(由 anyDragActive guard)\n const visible = ctx.isDragging || (!anyDragActive && (pos.rowHovered || buttonHovered))\n\n // 2026-05-12 fix(user 抓 image 1):\n // (a) tooltip 偶爾不出 — root cause:`disabled={!canDrag}` HTML attribute 阻 pointer events\n // → Radix Tooltip pointerenter 不 fire → tooltip 不 trigger。Fix:改 `aria-disabled`\n // only(Button cva 已 handle disabled visual via aria-disabled),pointer events 仍 fire,\n // Tooltip stable trigger。\n // (b) drag button bg 透明蓋不住 row content — 加 `bg-surface-raised` overlay。\n // (c) source row drag button 在 drag 中應 dimmed visual — `isDragging` 加 `opacity-disabled`。\n const handle = (\n <Button\n ref={canDrag ? ctx.handleSetActivatorNodeRef : undefined}\n variant=\"tertiary\"\n iconOnly\n size=\"xs\"\n startIcon={GripVertical}\n aria-label={canDrag ? '拖曳重排此列' : '排序中無法拖曳'}\n aria-disabled={!canDrag || undefined}\n tabIndex={canDrag ? 0 : -1}\n // 2026-05-12 fix(a):移除 disabled HTML attr(改 aria-disabled);pointer events 必 fire 才能\n // 接 Tooltip pointerenter。Button cva 已 handle aria-disabled visual styling。\n onMouseEnter={() => setButtonHovered(true)}\n onMouseLeave={() => setButtonHovered(false)}\n style={{\n position: 'fixed',\n top: pos.top,\n left: pos.left,\n transform: 'translate(-50%, -50%)',\n zIndex: 50,\n // 2026-05-12 fix v2(user 抓「drag column sort 啟用時 button 不是 disable 視覺」):\n // 前 Round 4.5 加 `aria-disabled:opacity-[var(--opacity-disabled)]` 在 Button cva\n // 沒生效 — 因為 inline style `opacity` 永遠 win over Tailwind class。Fix:把 disabled\n // state opacity 也 compute 進 inline style。priority order:invisible 0 → drag 0.5 →\n // canDrag=false(sort active)disabled visual var(--opacity-disabled) 0.45 → idle 1。\n opacity: visible\n ? (ctx.isDragging ? 0.5 : (canDrag ? 1 : 'var(--opacity-disabled)' as unknown as number))\n : 0,\n pointerEvents: visible ? 'auto' : 'none',\n transition: 'opacity 150ms ease',\n }}\n className={cn(\n // 2026-05-12 debug fix(user 抓「hover 還是透明」)— Round 4.5 我未授權加\n // `border / shadow / hover:bg-neutral-hover` = over-design + hover override 讓\n // drag button hover bg 變 neutral-hover 跟 row hover bg 同色 → 視覺融入 row = 透明。\n // 撤回:**只保 bg-surface-raised(idle + hover + 所有 state 都同 bg)**,\n // border / shadow / hover override 全 retire(user verbatim「我有叫你加 elevation 嗎」)。\n // 對所有 state(idle / hover / aria-disabled / data-state)套同 bg-surface-raised — 跟\n // row 任何 state 視覺都有 token-level 對比(在 token 差異存在的 mode;light mode --surface-raised\n // 等於 --surface 是 design token semantic,非本 fix scope)。\n 'bg-surface-raised hover:bg-surface-raised aria-disabled:bg-surface-raised',\n canDrag && !showInvalid && 'cursor-grab',\n canDrag && showInvalid && 'cursor-not-allowed !text-error !border-error',\n // drag 進行中 source button cursor(opacity 0.5 via style;aria-disabled visual 由 Button cva 接管)\n ctx.isDragging && 'cursor-grabbing',\n )}\n {...(canDrag ? ctx.handleListeners ?? {} : {})}\n {...(canDrag ? ctx.handleAttributes ?? {} : {})}\n />\n )\n\n const wrapped = disabled ? (\n <Tooltip>\n <TooltipTrigger asChild>{handle}</TooltipTrigger>\n <TooltipContent>排序中無法拖曳,清除排序後可重排</TooltipContent>\n </Tooltip>\n ) : handle\n\n return (\n <>\n {anchor}\n {portalTarget && createPortal(wrapped, portalTarget)}\n </>\n )\n}\n\n// ══════════════════════════════════════════════════════════════════════════════\n// AG Grid 模式:header 在 scroll 外面,body 是唯一的垂直 scroll container。\n//\n// table\n// ├── header(固定頂部,不在 scroll 內)\n// │ ├── left-header\n// │ ├── center-header(overflow:hidden,JS sync scrollLeft)\n// │ └── right-header\n// └── body-viewport(overflow-y:auto,display:flex)\n// ├── left-body(overflow:hidden)\n// ├── center-body(overflow-x:auto, overflow-y:hidden)\n// └── right-body(overflow:hidden)\n//\n// 不用 CSS sticky。Header 永遠在頂部。\n// ══════════════════════════════════════════════════════════════════════════════\n\n// code-quality-allow: long-function — foundational composite main body — 拆 sub-fn 會複雜化 local state / ref / context binding\nfunction DataTableInner<TData>(\n {\n columns, data, size = 'md', autoRowHeight = false, height = '400px',\n overscan = 5, emptyState, enableHover = true, bordered,\n estimateRowHeight, tableOptions, rowActions, cellErrors,\n pinnedLeftColumns, pinnedRightColumns, inlineEdit = false,\n selection: selectionProp, defaultSelection, onSelectionChange,\n selectable = false, isRowSelectable, getRowId, getRowAriaLabel,\n preserveSelectionOnFilter = false,\n columnVisibility: columnVisibilityProp, defaultColumnVisibility, onColumnVisibilityChange,\n enableMultiSort = true,\n onColumnFilterTrigger,\n onCellCommit,\n enableRowDrag = false,\n onRowReorder,\n enableColumnResize = false,\n onColumnResize,\n enableColumnReorder = false,\n onColumnReorder,\n experimentalSpreadsheetOverlay = false,\n experimentalActiveEditorController = false,\n spreadsheetMode = false,\n className, ...props\n }: DataTableProps<TData>,\n ref: React.ForwardedRef<HTMLDivElement>\n) {\n // ── L4 Inline edit state ──\n // editingCellId: `${rowId}__${columnId}` 標識當前進 edit mode 的 cell;null = 無\n const [editingCellId, setEditingCellId] = React.useState<string | null>(null)\n // Phase 7 D.3 portal Field virtualizer unmount preserve draft(2026-05-10 per codex Q-B4 verdict):\n // Lifted draft state in DataTable — Cell DOM unmount(virtualizer scroll out)時 draft 不丟,\n // mount-back 時 portal Field value=draft 而非 row.value,user 編輯中字保留。\n // editingCellId 變時 useEffect reset draft 到新 cell row.value(全新 edit session)。\n const [editingDraft, setEditingDraft] = React.useState<unknown>(undefined)\n const exitEdit = React.useCallback(() => {\n setEditingCellId(null)\n setEditingDraft(undefined)\n }, [])\n\n // ── Slice D Step 4 spreadsheet semantics state(2026-05-10) ──\n // selectedCellId:`${rowId}:${colId}` Excel-like 選取(click 1)\n // rangeAnchor / rangeFocus:Shift+click range 起點 / 終點(rectangle from anchor↔focus)\n const [selectedCellId, setSelectedCellId] = React.useState<string | null>(null)\n const [rangeAnchor, setRangeAnchor] = React.useState<string | null>(null)\n const [rangeFocus, setRangeFocus] = React.useState<string | null>(null)\n // tableRef declared below (line 967) — click-outside effect 在 tableRef ready 後 wire,\n // 為避免 ordering 問題用 forwarded ref query via DOM `[data-data-table-outer]`。\n // 2026-05-12 click-outside canonical(user 抓「選完 range 後點任何地方該清掉 / 選 cell 後點別處該取消」):\n // 對齊 Excel / Google Sheets / Notion / Airtable cell-selection canonical — pointerdown 落在\n // table outer 外 → clear selection + range。內 cell click 由 onClick 自處理(不衝突)。\n React.useEffect(() => {\n if (!spreadsheetMode) return\n if (selectedCellId == null && rangeAnchor == null) return\n const handler = (e: PointerEvent) => {\n const target = e.target as HTMLElement | null\n if (!target) return\n // 點 table outer 外 → clear all selection\n if (!target.closest('[data-data-table-outer]')) {\n setSelectedCellId(null)\n setRangeAnchor(null)\n setRangeFocus(null)\n }\n }\n document.addEventListener('pointerdown', handler, true)\n return () => document.removeEventListener('pointerdown', handler, true)\n }, [spreadsheetMode, selectedCellId, rangeAnchor])\n const commitCell = React.useCallback(\n (rowId: string, colId: string, next: unknown) => {\n onCellCommit?.(rowId, colId, next)\n setEditingCellId(null)\n setEditingDraft(undefined) // Phase 7:commit 後清 draft\n },\n [onCellCommit],\n )\n // 判 column meta.editable 對特定 row 是否成立(支援 fn)\n // column meta 是 free-form consumer bag(同 renderTypedValue any policy),不適合窄型化\n const isCellEditable = React.useCallback(\n // any-allow: free-form consumer meta — same rationale as L143 renderTypedValue\n (meta: Record<string, any> | undefined, row: unknown): boolean => {\n const e = meta?.editable\n if (typeof e === 'function') return e(row) === true\n return e === true\n },\n [],\n )\n // 2026-05-13 Stream C Cluster B Q3 ship(per codex Q3 verdict + user 拍板「全部馬不停蹄做完」):\n // Mirror isCellEditable pattern。`column.meta.disabled` 接 bool 或 (row) => boolean fn。\n // cell disabled → (a) TD 加 `bg-disabled cursor-not-allowed` + 抑制 hover, (b) inner Field\n // 透過 isDisabled prop 走 mode='disabled'(各 Field type 內部具體 disabled token,非 wrapper blanket opacity),\n // (c) edit entry condition: `cellEditable && !cellDisabled`。\n const isCellDisabled = React.useCallback(\n // any-allow: free-form consumer meta — same rationale as L143 renderTypedValue\n (meta: Record<string, any> | undefined, row: unknown): boolean => {\n const d = meta?.disabled\n if (typeof d === 'function') return d(row) === true\n return d === true\n },\n [],\n )\n // 2026-05-13:canEditCell helper consolidation(per codex V4 follow-up + user「沒理由不做」拍板)\n // 抽 4-site repeated `editable && !disabled` pattern。3 path sites(keyboard / Tab / InteractionLayer)\n // call canEditCell;另 2 sites(renderCellContent + onEditableCellClick)用 already-computed `editable`/\n // `disabled` 變數(因為 disabled 還要單獨給 isDisabled prop + bg-disabled class),不 collapse to helper。\n const canEditCell = React.useCallback(\n (meta: Record<string, unknown> | undefined, row: unknown): boolean =>\n isCellEditable(meta, row) && !isCellDisabled(meta, row),\n [isCellEditable, isCellDisabled],\n )\n const [sorting, setSorting] = React.useState<SortingState>(tableOptions?.state?.sorting as SortingState ?? [])\n\n // ── L3 Column visibility state(controllable)──\n const [columnVisibility, setColumnVisibility] = useControllable<Record<string, boolean>>({\n value: columnVisibilityProp,\n defaultValue: defaultColumnVisibility ?? {},\n onChange: onColumnVisibilityChange,\n })\n\n // ── L2 Selection state ──\n const enabled = selectable !== false\n const mode = selectable === 'single' ? 'single' : 'multi'\n const [selection, setSelection] = useControllable<string[]>({\n value: selectionProp,\n defaultValue: defaultSelection ?? [],\n onChange: onSelectionChange,\n })\n // Shift-click anchor:存最後一次「單擊」的 row id,shift-click 時做區間選\n const anchorRowIdRef = React.useRef<string | null>(null)\n\n // 注入 checkbox column(L2 selection;L4 row drag handle 不佔 column,absolute 浮在 row 左 border)\n // 順序:[__select__?, ...consumer columns]\n // **Column resizable canonical**(2026-05-05 user E rule):per-column `enableResizing` flag\n // 決定 width 行為(getCanResize=true → fixed / false → flex 1 1 0%)。**無 auto-default**\n // \"last column !resizable\" — consumer 顯式設(對齊 user 拒絕「autoFillLastColumn」決策)。\n //\n // **2026-05-06 v14.3 DS canonical width API**:consumer 寫 `meta.width` / `meta.minWidth` /\n // `meta.maxWidth`(DS-internal naming,避開跟 `size: 'sm'|'md'|'lg'` density 命名衝突)。\n // 此 pre-process 把 meta 值 copy 到 root size/minSize/maxSize,確保 TanStack column\n // resize state 正常運作。**Back-compat**:consumer 寫 root `size` 仍 work(meta.width 沒設則\n // 不覆蓋 root)。新 code 一律用 meta.width。\n const dsProcessedColumns = React.useMemo<ColumnDef<TData>[]>(() => {\n return columns.map((c) => {\n const meta = c.meta as { width?: number; minWidth?: number; maxWidth?: number } | undefined\n if (!meta) return c\n const cAny = c as { size?: number; minSize?: number; maxSize?: number }\n const updates: { size?: number; minSize?: number; maxSize?: number } = {}\n if (meta.width !== undefined && cAny.size === undefined) updates.size = meta.width\n if (meta.minWidth !== undefined && cAny.minSize === undefined) updates.minSize = meta.minWidth\n if (meta.maxWidth !== undefined && cAny.maxSize === undefined) updates.maxSize = meta.maxWidth\n return Object.keys(updates).length > 0 ? ({ ...c, ...updates } as ColumnDef<TData>) : c\n })\n }, [columns])\n\n const columnsWithSelection = React.useMemo(() => {\n if (!enabled) return dsProcessedColumns\n const selectCol: ColumnDef<TData, any> = {\n id: SELECT_COL_ID,\n size: 40,\n enableSorting: false,\n enableResizing: false,\n enableHiding: false, // selection col 不能藏(L3 column visibility)\n header: 'Select', // header cell 由下方自訂 render 取代\n cell: () => null, // body cell 由下方自訂 render 取代\n }\n return [selectCol, ...dsProcessedColumns]\n }, [dsProcessedColumns, enabled])\n\n // pinned-left 自動加 __select__(__select__ 永遠最左)\n const effectivePinnedLeft = React.useMemo(() => {\n const list = pinnedLeftColumns ?? []\n const out = [...list]\n if (enabled && !out.includes(SELECT_COL_ID)) out.unshift(SELECT_COL_ID)\n return out\n }, [pinnedLeftColumns, enabled])\n\n // columnOrder 自動加 __select__ 在最前:consumer 傳的 columnOrder 通常只列 data\n // columns,TanStack 會把不在 order 的 column 推到末位 → 同步幫他補上\n const userColumnOrder = tableOptions?.state?.columnOrder\n const effectiveColumnOrder = React.useMemo(() => {\n if (!userColumnOrder) return userColumnOrder\n if (!enabled) return userColumnOrder\n const out = [...userColumnOrder]\n if (enabled && !out.includes(SELECT_COL_ID)) out.unshift(SELECT_COL_ID)\n return out\n }, [userColumnOrder, enabled])\n\n // 注意:`...tableOptions` 必 spread 在 `state` 前,否則 user 傳的 tableOptions 會\n // 整個 override 掉我們組的 state(含 __select__ 自動 pinning + columnOrder 注入)。\n // 之前 bug:checkbox column 跑到右邊 = 此處 spread 順序錯。\n const table = useReactTable({\n ...tableOptions,\n data, columns: columnsWithSelection,\n state: {\n sorting, columnVisibility,\n ...tableOptions?.state,\n // columnPinning + columnOrder 在 user state 後 override,確保 __select__ 永遠左\n columnPinning: { left: effectivePinnedLeft, right: pinnedRightColumns ?? [] },\n ...(effectiveColumnOrder ? { columnOrder: effectiveColumnOrder } : {}),\n },\n enableMultiSort,\n // **#1 fix(2026-05-04)**:chain user `tableOptions.onSortingChange`(spread 在前被 override = 之前 bug)\n // 同 onColumnVisibilityChange:both internal setState + forward 給 user external state\n onSortingChange: (updater) => {\n setSorting(updater)\n tableOptions?.onSortingChange?.(updater)\n },\n onColumnVisibilityChange: (updater) => {\n const next = typeof updater === 'function' ? updater(columnVisibility) : updater\n setColumnVisibility(next)\n tableOptions?.onColumnVisibilityChange?.(updater)\n },\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n // L4 nested rows:啟用 expanded row model(consumer 透過 tableOptions.getSubRows + state.expanded forward)\n getExpandedRowModel: getExpandedRowModel(),\n getRowId: getRowId,\n // 2026-05-06 v14 column resize:`onChange` mode → drag 中 column 即時跟動 cursor(world-class\n // canonical:TanStack docs / AG Grid / Excel / Google Sheets 全部 live resize)。前 v13.2\n // 用 `onEnd` 拖完才 jump,user 報「感覺超頓像 bug」。tanstack 內部管 columnSizing state\n // (uncontrolled);`columnSizingState` 變動透過 useEffect 觀測 + 呼 callback。\n //\n // 前 v11 用 `onColumnSizingChange` 接管 updater 但忘了 setColumnSizing,導致 state 永遠不變動 →\n // column.getSize() 永遠回初始值 → drag visual 完全沒效果(user 報 \"drag 沒反應\")。本 v13.2 改回\n // tanstack uncontrolled state(預設行為)+ useEffect 觀測 columnSizing 變動 fire callback。\n enableColumnResizing: enableColumnResize,\n columnResizeMode: 'onChange',\n })\n\n // v13.2:onColumnResize callback 透過 useEffect 觀測 columnSizing state 變動 fire(uncontrolled state pattern)\n const columnSizingState = table.getState().columnSizing\n const prevColumnSizingRef = React.useRef(columnSizingState)\n React.useEffect(() => {\n if (!onColumnResize) return\n const prev = prevColumnSizingRef.current\n Object.keys(columnSizingState).forEach(id => {\n if (columnSizingState[id] !== prev[id]) {\n onColumnResize(id, columnSizingState[id])\n }\n })\n prevColumnSizingRef.current = columnSizingState\n }, [columnSizingState, onColumnResize])\n\n const { rows } = table.getRowModel()\n const isEmpty = rows.length === 0\n const hasHeightConstraint = height !== 'auto'\n // Fill-parent mode:height='100%' / '100vh' / 'fill' 等百分比 / 視口語義 → outer flex column + body flex-1 撐滿。\n // 固定 px/rem 仍維持 maxHeight cap 行為(資料少 = 內容高度,資料多 = 上限後 scroll)— 對齊既有 stories 預期。\n const isFillHeight = hasHeightConstraint && /^(100%|100vh|fill)$/.test(height)\n // **Virtualization threshold(2026-05-07 v15.9 Bug G fix)**:小資料集 skip 虛擬化。\n // Root cause:虛擬化器(TanStack Virtual)`getVirtualItems()` 在 scrollElement\n // 還沒 mount(first render,centerBodyRef = null)時會返回空陣列 →「0 row → N row」\n // 跨 frame transition,user 看到「table 從矮長高 + 資料慢慢露出」。≤ 30 rows\n // direct render 完全 bypass 此 race,且小資料下虛擬化沒效益(浪費 reflow)。\n // 對齊 AG Grid `suppressVirtualization` / TanStack Table virtualization-when-needed idiom。\n const VIRTUAL_THRESHOLD = 30\n const useVirtual = hasHeightConstraint && !isEmpty && rows.length > VIRTUAL_THRESHOLD\n const hasRowActions = !!rowActions\n\n // Refs\n const tableRef = React.useRef<HTMLDivElement | null>(null)\n const bodyRef = React.useRef<HTMLDivElement>(null)\n const centerHeaderRef = React.useRef<HTMLDivElement>(null)\n const centerBodyRef = React.useRef<HTMLDivElement>(null)\n const leftHeaderRef = React.useRef<HTMLDivElement>(null)\n const rightHeaderRef = React.useRef<HTMLDivElement>(null)\n const [leftWidth, setLeftWidth] = React.useState(0)\n const [rightWidth, setRightWidth] = React.useState(0)\n\n // estimate 預設 size-aware 對齊 token(--table-row-{sm,md,lg} = 32/40/48 md density)\n // Q7 fix(2026-05-04):前用 hardcode 36 跟真高 40 差 4px,N rows 累積誤差呈現「table 慢慢長高」假象。\n // ResizeObserver+measureElement 的修正過程被 user 看見 = mount-time growth bug 的真因。\n const ESTIMATE_BY_SIZE: Record<string, number> = { sm: 32, md: 40, lg: 48 }\n const resolvedEstimate = estimateRowHeight ?? ESTIMATE_BY_SIZE[size] ?? 40\n // 2026-05-06 v10 DragOverlay canonical:retire windowed sticky range extractor (v4-v9 workaround)。\n // 改用 `<DragOverlay>` portal 把 source row 視覺解耦 — source 即使 unmount(virtual scroll out)\n // overlay 仍 render 由 cloned outerHTML 提供視覺。dnd-kit transform / collision 走 active item id\n // (id 永遠在 SortableContext.items 集合,跟 hook instance mount 狀態無關)。\n // 對齊 dnd-kit GitHub #1674 + drag-overlay docs canonical「virtualized list MUST use DragOverlay」。\n // overscan 仍輕微拉高(避免 source row 旁邊 rows 也 unmount 致使 hover signal 計算抖動)。\n const effectiveOverscan = enableRowDrag ? Math.max(overscan, 5) : overscan\n const activeDragIdRef = React.useRef<string | null>(null)\n\n const virtualizer = useVirtualizer({\n count: useVirtual ? rows.length : 0,\n // V scroll 現在在 centerBodyRef(不是外層 bodyRef)\n getScrollElement: () => centerBodyRef.current,\n estimateSize: () => resolvedEstimate,\n overscan: effectiveOverscan, enabled: useVirtual,\n // 2026-05-14 P3 perf tune(per codex+Layer A 共識,user 拍板「全部做完」+\n // CPU-throttle-reproducible verify infra):150ms → 250ms 減少 scroll\n // start/end flip 次數 → TableScrollContext 重 cascade visible rich cell\n // tree 機會降低。對齊 TanStack Virtual `isScrollingResetDelay` API。\n isScrollingResetDelay: 250,\n })\n\n // ── isFillHeight body maxHeight JS 計算(2026-04-30)──\n // CSS `%` height 在 flex column min-h-0 + auto basis 場景下,Chromium 不可靠 shrink\n // (實測:outer maxHeight 100% bind parent,但 body 不 shrink 反映 outer 約束 → outer\n // overflow-hidden 切掉 content,V scroll 不 trigger)。\n // 改用 ResizeObserver 算 body avail = outer rect - header rect → set centerBody\n // maxHeight = pixel value(不是 %)。content 大 → V scroll;content 小 → centerBody\n // = content,outer = intrinsic,沒留白。\n // **Q7 mount-time growth fix(2026-05-04 v3 真因)**:不是 visibility race,是 estimateRowHeight\n // 預設 36 ≠ 真實 row height(token md=40 / sm=32 / lg=48),virtualizer initial total = 6×36 = 216,\n // 後續 measureElement 修正到 6×40 = 240,差 24px 視覺看起來像「table 慢慢長高」。fix = estimate\n // 預設 size-aware 對齊 token(見下方 estimateRowHeight default 計算)。\n const [bodyMaxHeight, setBodyMaxHeight] = React.useState<number | null>(null)\n React.useLayoutEffect(() => {\n if (!isFillHeight) { setBodyMaxHeight(null); return }\n // **R4 真根因 fix(2026-05-09 v2 — codex Q3.6 root cause + Q3.9 reproduce verified)**:\n //\n // Bug:isFillHeight 時 outer 用 `style={{ maxHeight: height }}`(L1819-1824)沒 explicit height\n // → outer.getBoundingClientRect().height 受 children 反向影響(因 outer = children intrinsic,\n // children 又被 bodyMaxHeight 限制)→ **circular dependency**。\n //\n // 表現:viewport / layout 變化時 parent 變(392→672)但 outer 永遠卡(282)→ body 永遠 240,\n // 不跟 parent 變大時填滿。Initial mount 過程則看起來像 stepping(parent 從 0 慢慢長,outer 跟著\n // 一階一階長)。\n //\n // 真 fix:**改量 parent slot,不量 outer**。Parent 是 definite height 限制因子,不被 child 反向影響。\n // - rAF coalesce:RO callback 多次觸發 → 1 frame 內只 compute 1 次(降頻,防 RO 連續 fire redundant)\n // - diff guard:< 1px 不 setState(防 micro-step)\n // - **observe parent 而非 self**(打破 circular)\n //\n // Codex root cause cite:circular feedback `tableRef.height ↔ bodyMaxHeight ↔ body layout ↔ tableRef.height`\n // Reproduce verified:viewport 1280→1920→900,parentH 392/672/292 變化,但 a524e03 fix 下 bodyRectH 永遠 240。\n let rafId: number | null = null\n let stableTimer: ReturnType<typeof setTimeout> | null = null\n let lastValue: number | null = null\n let pendingValue: number | null = null\n // 2026-05-21 v4 真根因 fix(per user「請你仔細查查,務必仔細查」+「確保這個問題不再出現」):\n // 即使 v3(observe parent + rAF + diff guard < 4px),Tabs / Storybook iframe / nested\n // AppShell flex chain 仍可能 100ms+ settle period 內每 frame growth > 4px → setState\n // 多次 fire → user 視覺「stepping growth」。\n //\n // **v4 加 stability window**:layout 連續 100ms 無變動才 setState。意味:\n // - 初始 mount:bodyMaxHeight=null → body 不受 maxHeight 限制 → 顯全內容(intrinsic 高度)\n // - RO 多 frame fire(layout settling):每 fire reset timer,setState 不 fire\n // - Layout 穩定 100ms:setState fire 最終值,body 套 constraint(若 parent > content 無視覺變化)\n // - 真實 resize(viewport 縮 / aside toggle):δ 必 ≫ 4px + 跨多 frame,timer 自然 settle\n // 對齊 TanStack Virtual `observeElementRect` + Material X-DataGrid 「resize debounce 100ms」慣例。\n const compute = () => {\n if (!tableRef.current) return\n // ⭐ 量 parent slot(definite height,不受 child 反向影響),fallback 用 outer\n const parentEl = tableRef.current.parentElement\n const slotH = parentEl?.getBoundingClientRect().height\n ?? tableRef.current.getBoundingClientRect().height\n const headerEl = tableRef.current.firstElementChild as HTMLElement | null\n const headerH = headerEl?.getBoundingClientRect().height ?? 0\n const next = Math.max(0, slotH - headerH)\n // Diff guard < 4px(濾 micro-step,real resize δ 必 ≫ 4px)\n if (lastValue != null && Math.abs(next - lastValue) < 4) return\n lastValue = next\n pendingValue = next\n // Stability window 100ms:layout 連續 100ms 無變才 setState\n if (stableTimer != null) clearTimeout(stableTimer)\n stableTimer = setTimeout(() => {\n if (pendingValue != null) setBodyMaxHeight(pendingValue)\n stableTimer = null\n }, 100)\n }\n const scheduleCompute = () => {\n if (rafId != null) return\n rafId = requestAnimationFrame(() => {\n rafId = null\n compute()\n })\n }\n compute() // initial schedule(會 enter stability window 等 100ms settle)\n // ⭐ 只 observe parent,不 observe tableRef(打破 circular)\n const obs = new ResizeObserver(scheduleCompute)\n if (tableRef.current?.parentElement) obs.observe(tableRef.current.parentElement)\n return () => {\n obs.disconnect()\n if (rafId != null) cancelAnimationFrame(rafId)\n if (stableTimer != null) clearTimeout(stableTimer)\n }\n }, [isFillHeight])\n\n // JS scroll sync(AR44 user-reported UX fix):\n // 原本 V scroll 在 body-viewport(外層),center-body H scroll 於其內部底部 = 所有 row 都 render 下方。\n // Virtualized 1800px 內容 → H scrollbar 在 1800px 下方,user 必須 V-scroll 到底才看見 → UX bug。\n // **現在 V scroll 移到各 region 自己(left / center / right 分別)**,三者 scrollTop JS 同步;\n // H scroll 仍在 center-body,但因 center-body 現在有自己的 maxHeight,H scrollbar 落在 visible 視窗底部 → user 一眼看到。\n const leftBodyRef = React.useRef<HTMLDivElement>(null)\n const rightBodyRef = React.useRef<HTMLDivElement>(null)\n const onCenterBodyScroll = React.useCallback(() => {\n const cb = centerBodyRef.current\n if (!cb) return\n if (centerHeaderRef.current) centerHeaderRef.current.scrollLeft = cb.scrollLeft\n if (leftBodyRef.current) leftBodyRef.current.scrollTop = cb.scrollTop\n if (rightBodyRef.current) rightBodyRef.current.scrollTop = cb.scrollTop\n }, [])\n\n // ── Phase 9 Issue 1 fix(2026-05-10):range cells lifted compute + Set ────\n // 計算 spreadsheet range cell IDs(Shift+click rectangle from anchor↔focus),\n // 提供:\n // 1. `rangeCellIds` array → pass to layer for outer ring 4 line div boundary\n // 2. `rangeCellIdSet` Set → cell wrapper data-range-cell attr for cell-bg fill\n // (per codex Q1 verdict:bg fill 移到 cell bg layer 不在 overlay,內容才不被蓋)\n const rangeCellIds = React.useMemo<string[] | undefined>(() => {\n if (!spreadsheetMode || !rangeAnchor || !rangeFocus || rangeAnchor === rangeFocus) return undefined\n const parseCell = (id: string) => {\n const lastColon = id.lastIndexOf(':')\n return { rowId: id.slice(0, lastColon), colId: id.slice(lastColon + 1) }\n }\n const a = parseCell(rangeAnchor)\n const f = parseCell(rangeFocus)\n const allRows = table.getRowModel().rows.map((r) => r.id)\n const allCols = table.getVisibleLeafColumns().map((c) => c.id).filter((id) => id !== SELECT_COL_ID)\n const aRowIdx = allRows.indexOf(a.rowId)\n const fRowIdx = allRows.indexOf(f.rowId)\n const aColIdx = allCols.indexOf(a.colId)\n const fColIdx = allCols.indexOf(f.colId)\n if (aRowIdx < 0 || fRowIdx < 0 || aColIdx < 0 || fColIdx < 0) return undefined\n const rowStart = Math.min(aRowIdx, fRowIdx)\n const rowEnd = Math.max(aRowIdx, fRowIdx)\n const colStart = Math.min(aColIdx, fColIdx)\n const colEnd = Math.max(aColIdx, fColIdx)\n const ids: string[] = []\n for (let r = rowStart; r <= rowEnd; r++) {\n for (let c = colStart; c <= colEnd; c++) {\n ids.push(`${allRows[r]}:${allCols[c]}`)\n }\n }\n return ids\n // any-allow: react-table runtime lookup\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [spreadsheetMode, rangeAnchor, rangeFocus, table])\n const rangeCellIdSet = React.useMemo(() => new Set(rangeCellIds || []), [rangeCellIds])\n\n // 三區域欄位\n const leftCols = table.getLeftVisibleLeafColumns()\n const centerCols = table.getCenterVisibleLeafColumns()\n const rightCols = table.getRightVisibleLeafColumns()\n const hasLeft = leftCols.length > 0\n const hasRight = rightCols.length > 0 || hasRowActions\n // 2026-05-06 v13.1:Center region SSOT width — header inner wrapper + body inner wrapper 共用\n // 同一個 minWidth 算法,確保 header / body cell 寬度永遠對齊(前 v8 用 `w-max min-w-full`\n // 在 header(content max-content 小)vs body(content max-content 大)會 diverge 76+ px,\n // user 報「header / row 對不起來」)。\n const centerColsWidth = centerCols.reduce((a, c) => a + c.getSize(), 0)\n\n // Header 寬度 → body region 同步(virtual mode 需要明確寬度)\n React.useEffect(() => {\n const measure = () => {\n if (leftHeaderRef.current) setLeftWidth(leftHeaderRef.current.offsetWidth)\n if (rightHeaderRef.current) setRightWidth(rightHeaderRef.current.offsetWidth)\n }\n measure()\n const obs = new ResizeObserver(measure)\n if (leftHeaderRef.current) obs.observe(leftHeaderRef.current)\n if (rightHeaderRef.current) obs.observe(rightHeaderRef.current)\n return () => obs.disconnect()\n }, [hasLeft, hasRight, rows.length])\n\n const rowHeight = `h-table-row-${size}`\n\n // ── Cross-region row hover (2026-04-22 D3 perf audit):event delegation 改 per-row closure\n // 舊:每 row 建 `{ onMouseEnter, onMouseLeave }` + 2 arrow functions → 100 row = 200 closures/render\n // 新:表格層 single onMouseOver / onMouseOut,透過 event.target.closest 找 data-row-index\n const enterLeaveHandlers = React.useMemo(() => {\n if (!enableHover) return { onMouseOver: undefined, onMouseOut: undefined }\n const findRowIndex = (target: EventTarget | null): string | null => {\n if (!(target instanceof HTMLElement)) return null\n const rowEl = target.closest<HTMLElement>('[data-row-index]')\n return rowEl?.dataset.rowIndex ?? null\n }\n return {\n onMouseOver: (e: React.MouseEvent) => {\n // v15.3:drag 進行中只允許 source row 自己被標 hover(維持 active 視覺\n // 對齊 Linear / Jira「source 維持 pressed 狀態」canonical)。其他 row 抑制。\n if (activeDragIdRef.current != null) {\n const target = e.target instanceof HTMLElement ? e.target : null\n const rowEl = target?.closest<HTMLElement>('[data-sortable-row-id]')\n const isSource = rowEl?.dataset.sortableRowId === activeDragIdRef.current\n if (!isSource) return\n }\n const idx = findRowIndex(e.target)\n if (idx == null) return\n tableRef.current?.querySelectorAll(`[data-row-index=\"${idx}\"]`).forEach((el) => ((el as HTMLElement).dataset.hovered = ''))\n },\n onMouseOut: (e: React.MouseEvent) => {\n const idx = findRowIndex(e.target)\n if (idx == null) return\n // 仍在同一 row 的子元素間 bubble(e.g. cell → text node)則 relatedTarget 還在 row 內\n const related = e.relatedTarget instanceof HTMLElement ? e.relatedTarget.closest<HTMLElement>('[data-row-index]') : null\n if (related?.dataset.rowIndex === idx) return\n tableRef.current?.querySelectorAll(`[data-row-index=\"${idx}\"]`).forEach((el) => delete (el as HTMLElement).dataset.hovered)\n },\n }\n }, [enableHover])\n // 維持 API:hoverProps(idx) 仍存在但 no-op,實際邏輯搬到 table 層 delegation\n const hoverProps = (_idx: number): Record<string, never> => ({})\n\n // ── Cell render(Phase C 2026-05-05 — type-keyed registry SSOT)──\n // 命中 columnType → 走 cellRegistry(display / edit mode 同元件 with `mode` prop);\n // 無 columnType → consumer 自訂 cell.columnDef.cell。\n const renderCellContent = (cell: ReturnType<typeof rows[number]['getVisibleCells']>[number]) => {\n const meta = cell.column.columnDef.meta\n const colType = meta?.type as ColumnType | undefined\n const wrap = autoRowHeight && meta?.wrap === true\n // 已知 compound 欄位(Tag / PersonDisplay / LinkInput 等自帶 layout)直接 bypass TruncateCell,\n // 因為 `truncate` 的 inline baseline context 會破壞自訂 layout 的垂直對齊。\n // 2026-05-09 D-path:date / time 加入(showDisplayEndIcon → Field naked-display 需 full width 才能\n // 右對齊 ItemSuffix。TruncateCell 的 `<span truncate min-w-0>` block-display 會 collapse Field\n // to content size,讓 Calendar / Clock icon 緊貼 value text 而非右邊緣)。\n const isKnownCompound = colType === 'select' || colType === 'multiSelect' || colType === 'person' || colType === 'multiPerson' || colType === 'url' || colType === 'date' || colType === 'time'\n const rowId = cell.row.id\n const colId = cell.column.id\n const editable = isCellEditable(meta, cell.row.original)\n const disabled = isCellDisabled(meta, cell.row.original)\n const isEditingThisCell = editingCellId === cellEditId(rowId, colId)\n\n let content: React.ReactNode\n if (colType) {\n const Cell = resolveCellComponent(colType)\n // 2026-05-10 Slice D Step 5(D.3 portal Field):當 portal flag 啟 + cell 編輯中 →\n // cell 保持 display mode(SSOT preserved per codex Q6.2),portal layer 渲 edit Field 在上。\n // 預設 inline-edit:isEditingThisCell ? edit : display。\n // 2026-05-13 Q3 cell-disabled:disabled cell 永遠 display lifecycle(state overlay,不進 edit)。\n const cellMode: 'edit' | 'display' =\n (experimentalActiveEditorController && isEditingThisCell)\n ? 'display'\n : (isEditingThisCell && !disabled) ? 'edit' : 'display'\n content = (\n <Cell\n value={cell.getValue()}\n meta={meta ?? {}}\n mode={cellMode}\n size={size}\n autoRowHeight={autoRowHeight}\n isEditable={editable}\n isDisabled={disabled}\n onCommit={(next) => commitCell(rowId, colId, next)}\n onCommitLive={(next) => onCellCommit?.(rowId, colId, next)}\n onCancel={exitEdit}\n onRequestEdit={() => !disabled && setEditingCellId(cellEditId(rowId, colId))}\n />\n )\n } else {\n content = flexRender(cell.column.columnDef.cell, cell.getContext())\n }\n // Consumer 自訂 cell(無 colType)若回傳 React element,視為 compound — consumer 自己處理\n // 對齊與截斷。回傳 primitive(string / number)才走 TruncateCell。\n // 理由:TruncateCell 的 `span.truncate` 強制 white-space:nowrap + inline baseline,\n // 對 inline-flex / icon+text 自訂結構會拉歪(見 circular-progress sync table 案例)。\n // **edit mode bypass**(2026-05-05 v9 Bug 2 修):editing cell 內部是 Field 控件\n // (Input/Textarea/Select etc.)自管 layout + 替代元素(textarea)不該被包進 inline span\n // baseline context — 否則 line-box descender 加 5-7px 致 cell 進 edit 後 row 撐高 layout shift。\n const isConsumerCompound = !colType && React.isValidElement(content)\n return isEditingThisCell ? content\n : wrap ? <span className=\"break-words min-w-0\">{content}</span>\n : (isKnownCompound || isConsumerCompound) ? content\n : <TruncateCell>{content}</TruncateCell>\n }\n\n // 2026-05-18 改 import ICON_SIZE SSOT(per user『做完』approval,消除 M17 違反 7+ 重複 ternary)\n const iconSize = ICON_SIZE[size as 'sm' | 'md' | 'lg']\n\n // 2026-05-09 D-path retired:`getEditIndicator(colType)` parallel system 移除。\n // Indicator authority 從 DataTable cellEl 移交 **Field naked-display branch via `showDisplayEndIcon` opt-in**\n // — Select / TimePicker / DatePicker / Combobox / PeoplePicker 5 picker 的 display mode 內建\n // `<ItemSuffix>` 渲對應 trigger icon(同 edit DOM 結構)。LinkInput URL anchor 例外(無 suffix)。\n // SSOT chain:cell-registry.tsx(opt-in props)→ Field component(intrinsic icon + ItemSuffix DOM)→\n // item-anatomy ItemPrefix/ItemSuffix layout SSOT。詳 `.claude/planning/cell-indicator-ssot-rfc.md`。\n // 不再有 DataTable-level cell indicator code path — 跨元件 SSOT 對齊 Field family。\n\n // L4 row drag:sort active 時 drag handle disabled(對齊 Notion / Airtable 共識)\n const dragDisabled = sorting.length > 0\n\n // ── L4 Row drag v2:nested rows + parent map ─────────────────────────────────\n // v2 cross-parent fix:全 row 進 SortableContext.items(含 sub-rows),custom collisionDetection\n // 過濾掉 cross-parent over candidates,保留「同 parent siblings」。沒命中 → invalid drop signal。\n // parentMap: rowId → parentId(top-level row 的 parent = '' 哨兵 string)\n const { allRowIds, parentMap } = React.useMemo(() => {\n const ids: string[] = []\n const pmap = new Map<string, string>()\n const walk = (r: typeof rows[number], parentId: string) => {\n ids.push(r.id)\n pmap.set(r.id, parentId)\n const subs = (r as unknown as { subRows?: typeof rows }).subRows\n if (subs && Array.isArray(subs)) subs.forEach(s => walk(s, r.id))\n }\n rows.forEach(r => { if ((r.depth ?? 0) === 0) walk(r, '') })\n return { allRowIds: ids, parentMap: pmap }\n }, [rows])\n\n // active drag state(state for invalid signal re-render;ref for fast lookup in collisionDetection)\n const [activeDragId, setActiveDragId] = React.useState<string | null>(null)\n // sync ref + force virtualizer recompute so rangeExtractor 看得到新 active id(M25 chain invariant)\n React.useEffect(() => {\n activeDragIdRef.current = activeDragId\n if (enableRowDrag && useVirtual) virtualizer.measure()\n }, [activeDragId, enableRowDrag, useVirtual, virtualizer])\n const [invalidDropActive, setInvalidDropActive] = React.useState(false)\n // code-quality-allow: long-function — audit 誤偵測 invalidRef 為 function;真實 long-function = 下方 cellEl(L1334+,已標 markers per L1336)。type-shadow,不需 refactor\n const invalidRef = React.useRef(false)\n invalidRef.current = invalidDropActive\n\n // code-quality-allow: long-function — cell render 含 selection / pinned / type-aware formatter 三邏輯,拆會增 prop drilling\n const cellEl = (cell: ReturnType<typeof rows[number]['getVisibleCells']>[number], _isLastInRow = false) => {\n // L2 selection:__select__ 欄自訂 render\n // multi 模式 → Checkbox(可多選)\n // single 模式 → Radio(單選 visual,對齊 Material DataGrid / Polaris IndexTable canonical)\n if (enabled && cell.column.id === SELECT_COL_ID) {\n const rowId = cell.row.id\n const rowOriginal = cell.row.original\n const isDisabled = isRowSelectable ? !isRowSelectable(rowOriginal) : false\n const ariaLabel = getRowAriaLabel?.(rowOriginal) ?? 'Select row'\n const checkboxSize = size === 'lg' ? 'lg' : 'md'\n // Cell 整格可點:click cell padding 也觸發 toggle/select(對齊 Linear / Apple Mail / Material DataGrid)\n // 內部 checkbox/radio 用 stopPropagation 避免 double-fire\n const onCellClick = isDisabled ? undefined : (e: React.MouseEvent) => {\n e.stopPropagation()\n if (mode === 'single') setSelection([rowId])\n else toggleRow(rowId, rowOriginal, { shiftKey: e.shiftKey })\n }\n return (\n <div\n key={cell.id}\n role=\"cell\"\n // data-column-id 給 CSS scope:`[data-column-id=\"__select__\"]` 在 data-table.css 加\n // border-right divider,視覺把 system selection col 跟 data col 切開(Notion / Airtable\n // / Linear idiom)。**只有 inlineEdit + selectable 模式且 select 不在 leftBody 邊界時** style\n // 才生效(避免雙線)— CSS 用 `:not(:last-child)` selector 處理。\n data-column-id={SELECT_COL_ID}\n className={cn('flex items-center justify-center shrink-0', !isDisabled && 'cursor-pointer')}\n style={{ ...columnSizeStyle(cell.column, { resize: enableColumnResize, isSystemCol: isSystemColumn(cell.column.id) }), ...cellPadding }}\n onClick={onCellClick}\n >\n {mode === 'single' ? (\n <RadioGroupItem\n size={checkboxSize}\n value={rowId}\n disabled={isDisabled}\n aria-label={ariaLabel}\n onClick={(e) => e.stopPropagation()}\n />\n ) : (\n <Checkbox\n size={checkboxSize}\n checked={selectionSet.has(rowId)}\n disabled={isDisabled}\n aria-label={ariaLabel}\n onClick={(e) => {\n e.stopPropagation()\n if (isDisabled) return\n e.preventDefault() // 攔截 Radix 內部 toggle,自己 toggle 帶 shiftKey\n toggleRow(rowId, rowOriginal, { shiftKey: e.shiftKey })\n }}\n onKeyDown={(e) => {\n // Space:Radix 已處理 toggle,但要帶 shiftKey 區間選 → 攔截\n if (e.key === ' ' && !isDisabled) {\n e.preventDefault()\n toggleRow(rowId, rowOriginal, { shiftKey: e.shiftKey })\n }\n }}\n />\n )}\n </div>\n )\n }\n const meta = cell.column.columnDef.meta\n const colType = meta?.type as ColumnType | undefined\n const align = meta?.align ?? (colType ? columnTypeDefaults[colType].align : undefined)\n // L4 inline edit 整合\n const cellRowId = cell.row.id\n const cellColId = cell.column.id\n const cellEditable = isCellEditable(meta, cell.row.original)\n const cellDisabled = isCellDisabled(meta, cell.row.original)\n const isEditingThisCell = editingCellId === cellEditId(cellRowId, cellColId)\n // Indicator canonical(2026-05-09 D-path retire):**Field naked-display branch own** via\n // `showDisplayEndIcon` opt-in(per-picker `<ItemSuffix>` 渲 ChevronDown/Calendar/Clock)。\n // DataTable cellEl 不再 render parallel indicator — SSOT 對齊 Field family。\n // 詳 `.claude/planning/cell-indicator-ssot-rfc.md` Step 9。\n // Cell click → 進 edit mode(boolean 不需 — 自己 toggle;url 不需 — 走內部 Pencil button,Phase C 由 UrlCell 內處理)\n const cellSpreadsheetId = `${cellRowId}:${cellColId}`\n const isSelectedCell = spreadsheetMode && selectedCellId === cellSpreadsheetId\n // 2026-05-13 Q3:cellDisabled → 抑制 editable click(對齊 `editable && !disabled` invariant)\n const onEditableCellClick = cellEditable && !cellDisabled && colType !== 'boolean' && colType !== 'url' && !isEditingThisCell\n ? (e: React.MouseEvent) => {\n if (spreadsheetMode) {\n // Slice D Step 4 spreadsheet semantics(2026-05-10 user 拍板,2026-05-12 v2 fix):\n // Shift+click → extend range(set focus,**anchor 保持 selectedCellId**)\n // Click on already-selected → enter edit\n // Plain click → select(no edit)+ reset range to single cell\n // 2026-05-12 fix(user 抓「世界級設計藍邊框留在第一個選的 cell」):前 v1 setSelectedCellId\n // 到 focus(終點)→ 藍框跑去終點。Fix:selectedCellId 維持 anchor(起點)— 對齊\n // Excel / Google Sheets / Notion / Airtable shift-extend canonical(anchor 永遠 own\n // active-cell border,range 用 fill 視覺)。\n if (e.shiftKey && rangeAnchor != null) {\n setRangeFocus(cellSpreadsheetId)\n // selectedCellId stays at anchor (起點 keep active border canonical)\n return\n }\n if (isSelectedCell) {\n // 2nd click on already-selected → enter edit(Excel-like)\n setEditingCellId(cellEditId(cellRowId, cellColId))\n setSelectedCellId(null)\n setRangeAnchor(null)\n setRangeFocus(null)\n return\n }\n // 1st click → select only,no edit\n setSelectedCellId(cellSpreadsheetId)\n setRangeAnchor(cellSpreadsheetId)\n setRangeFocus(null)\n return\n }\n // Default(non-spreadsheet)inline-edit behavior:click → enter edit\n setEditingCellId(cellEditId(cellRowId, cellColId))\n }\n : undefined\n\n // L4 nested rows:該 cell 是否是 row 第 1 個非 select content cell(注入 chevron + indent)\n // 對齊 TreeView design language(token `--tree-indent-{sm,md,lg}` 為 SSOT,跨元件視覺一致)\n const allCells = cell.row.getVisibleCells()\n const firstContentCell = allCells.find(c => c.column.id !== SELECT_COL_ID)\n const isFirstContent = firstContentCell?.id === cell.id\n const depth = cell.row.depth ?? 0\n const canExpand = cell.row.getCanExpand?.() ?? false\n const isExpanded = cell.row.getIsExpanded?.() ?? false\n const toggleExpand = cell.row.getToggleExpandedHandler?.()\n const showNestedPrefix = isFirstContent && (depth > 0 || canExpand)\n // Issue 9 cell error(2026-05-10):lookup `${rowId}:${colId}` in cellErrors map\n // editing cell 自動 clear visual error(per spec 「edit-clears-own-cell」)— consumer 走\n // onCellCommit 驗證後決定回填新 error(由 consumer 端控制 cellErrors map state)。\n const rawCellError = cellErrors?.[`${cellRowId}:${cellColId}`]\n const cellErrorMessages: string[] | null = (() => {\n if (isEditingThisCell) return null // edit-clears-own-cell visual\n if (rawCellError == null) return null\n return Array.isArray(rawCellError) ? rawCellError : [rawCellError]\n })()\n const hasCellError = cellErrorMessages != null && cellErrorMessages.length > 0\n const cellErrorId = hasCellError ? `cell-err-${cellRowId}-${cellColId}` : undefined\n // H1 fix(2026-05-10):per-row autoRowHeight when this row has any cell error。\n // cell-level recompute(O(1) per cell map lookup)— cell-row coupling 透過 row.getVisibleCells()。\n // Field naked items-X 等 group-data-[row-mode=...] CSS propagation 跟著走。\n const rowHasAnyError = !!cellErrors && cell.row.getVisibleCells().some((c) => {\n const v = cellErrors[`${cell.row.id}:${c.column.id}`]\n return v != null && (Array.isArray(v) ? v.length > 0 : true)\n })\n const effectiveAutoRowForCell = autoRowHeight || rowHasAnyError\n return (\n <div\n key={cell.id}\n role=\"cell\"\n // group/cell + data-row-mode:讓 Field naked 用 `group-data-[row-mode=...]/cell:items-X`\n // 從 cell 取 alignment(autoRowHeight=auto 頂對齊 / fixed=fixed 置中)。CSS propagation,\n // Field API 不變;每個 mode 內 display↔edit 同 alignment(同 Field, 同 group → 同 items)。\n // H1(2026-05-10):per-row error → effectiveAutoRowForCell 同 row.tsx effectiveAutoRow\n data-row-mode={effectiveAutoRowForCell ? 'auto' : 'fixed'}\n data-column-id={cell.column.id}\n // Slice D Step 1B(2026-05-10):composite cell-id `${rowId}:${colId}` 給 Interaction Layer\n // getCellRect 用,per RFC §Overlay Geometry。\n data-cell-id={`${cell.row.id}:${cell.column.id}`}\n // Phase 9 Issue 1 fix(2026-05-10):range cell bg fill via CSS [data-range-cell],\n // 不在 overlay layer(避免 layer fixed-position bg 蓋 cell content)。\n data-range-cell={spreadsheetMode && rangeCellIdSet.has(`${cell.row.id}:${cell.column.id}`) ? '' : undefined}\n // 2026-05-13 V1.6:data-cell-disabled attribute 給 CSS `:not([data-cell-disabled])` 過濾,disabled cell 不被 range fill 蓋\n data-cell-disabled={cellDisabled ? 'true' : undefined}\n // Issue 9 cell error(2026-05-10):aria-describedby 接 error message id 給 AT 讀\n aria-describedby={cellErrorId}\n aria-invalid={hasCellError || undefined}\n className={cn(\n // Cell box(2026-05-05 v6 — A4 canonical: Field frame seamlessly replaces cell border):\n // - `self-stretch`: cell 永遠填 row 高\n // - **vertical alignment by row-mode**: autoRow=items-start(top per spec) /\n // fixed=items-center(centered per spec)。indicator + 非 Field 內容跟 cell 走。\n // - **editing cell**: padding=0 + 無 right divider → Field naked(`!h-full !px-[cell-px]\n // !py-[cell-py]`)邊框與 table divider 無縫接軌,seamlessly replace cell border。\n // Adjacent cell padding+divider 仍在,只 editing cell 自己改觀。對齊 user reminder\n // 「框框跟 cell 一樣大並取代 cell 的框且與 table 隔線無縫接軌」(2026-05-05)。\n // - **沒有** cell 自己 box-shadow ring — focus / hover / open ring 由 Field naked 自帶\n // state machine 提供(對齊 user「狀態樣式取決於原輸入框」reminder)\n 'group/cell flex text-foreground text-body font-normal shrink-0 relative self-stretch',\n // Issue 9(2026-05-10):有 cell error → unset overflow-hidden 讓 error message\n // wrap 撐 row 高。**H1(2026-05-10)升級**:overflow-visible 條件改 `rowHasAnyError` —\n // row 內任一 cell 有 error 整 row 全 cells 都 overflow-visible(error 訊息可能多行\n // 撐高 row,row 高同步 effectiveAutoRow auto)。\n rowHasAnyError ? 'overflow-visible' : 'overflow-hidden',\n effectiveAutoRowForCell ? 'items-start' : 'items-center',\n align === 'right' && 'justify-end text-right',\n align === 'center' && 'justify-center text-center',\n // Phase 9 Issue 8 fix(2026-05-10 user 撞 + codex 重比稿 verdict ADOPT):\n // 之前 `border-r border-divider` 只 right edge → hover overlay outline:-1px 只 right\n // 邊壓 cell border,上左下 sub-pixel 不一致(user 抓「右 1px / 上左下 2px」bug)。\n // 改 `dtCellGrid` (data-table.css:96-110)用 `box-shadow: inset` 4 邊 1px divider,\n // 不佔 layout(per user verbatim「在 cell 內容起始位置不變」前提)→ 4 邊一致 grid line\n // → overlay outline:-1px 4 邊都剛好壓 cell border line。\n // Field naked edit border 仍 own(per Field SSOT)— 編輯時 Field 自帶 border 1px,\n // 跟 cell 4 邊 inset divider 視覺相疊(同 pixel)= 1 line visual,不雙線。\n inlineEdit && 'dtCellGrid',\n onEditableCellClick && ['cursor-pointer', nakedCellEditableDisplayHover], // editable cell display hover affordance(對齊 Notion / Airtable hover-cell-shows-border canonical)\n // 2026-05-13 Q3 cell disabled SSOT(per codex Q3 verdict + user 拍板「全部馬不停蹄做完」):\n // bg `--bg-disabled` component-state token(color.spec.md:671 owner)+ cursor 抑制 click affordance。\n cellDisabled && 'bg-disabled cursor-not-allowed',\n // z-10 raise inline-edit cell;portal mode 不需(layer z-3 already on top)。\n isEditingThisCell && !experimentalActiveEditorController && 'z-10',\n )}\n style={{\n ...columnSizeStyle(cell.column, { resize: enableColumnResize, isSystemCol: isSystemColumn(cell.column.id) }),\n // Padding override 只在 inline-edit cell(naked Field 撐滿 cell);portal mode cell 走正常 display padding\n ...(isEditingThisCell && !experimentalActiveEditorController ? {} : cellPadding),\n // Slice D Step 2(2026-05-10):flag 開時 set CSS variable 抑制 Field naked hover outline,\n // 讓 overlay layer 接管 hover ring paint(per RFC Contract 8 「one geometry owner, two paint owners」)。\n // Backward-compat:flag 關時 unset → field-wrapper default `var(--border-hover)`(既有行為)。\n ...(experimentalSpreadsheetOverlay && { '--cell-hover-outline-color': 'transparent' } as React.CSSProperties),\n }}\n onClick={onEditableCellClick}\n >\n {/* Issue 9 cell error(2026-05-10):有 error → cell 內外結構切 flex-col,\n 上 row 渲既有 nested + content,下 row 渲 error message 14px text-error。\n 無 error 時走原 flex-row(backward-compat 0 layout shift)。 */}\n {hasCellError ? (\n <span className=\"flex flex-col self-stretch w-full min-w-0 gap-1\">\n <span className=\"flex flex-1 min-w-0\">\n {showNestedPrefix && (\n <span\n className=\"flex items-center shrink-0\"\n style={{ paddingLeft: depth > 0 ? `calc(${depth} * var(--tree-indent-${size}, var(--tree-indent-md)))` : 0 }}\n >\n {canExpand ? (\n <button\n type=\"button\"\n aria-label={isExpanded ? '收合' : '展開'}\n aria-expanded={isExpanded}\n className=\"inline-flex items-center justify-center shrink-0 w-4 h-4 mr-2 text-fg-muted hover:text-foreground rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-transform\"\n style={{ transform: isExpanded ? 'rotate(90deg)' : undefined }}\n onClick={(e) => { e.stopPropagation(); toggleExpand?.() }}\n >\n <ChevronDown size={iconSize} aria-hidden style={{ transform: 'rotate(-90deg)' }} />\n </button>\n ) : (\n <span aria-hidden className=\"shrink-0 w-4 h-4 mr-2\" />\n )}\n </span>\n )}\n <span className={cn(\n 'flex-1 min-w-0 flex',\n // 2026-05-12 Round 4.5 fix(codex M31 Layer C 抓漏)— error-cell branch 也用 per-row state\n // (`effectiveAutoRowForCell`)非 global `autoRowHeight`,跟 line 1559 non-error wrapper 同 SSOT。\n // 前 Round 4 漏修此 branch → error 那格 row 內視覺仍走 global mode mismatch。\n effectiveAutoRowForCell ? 'items-start' : 'items-center',\n align === 'right' && 'justify-end',\n )}>\n {renderCellContent(cell)}\n </span>\n </span>\n <span id={cellErrorId} className=\"text-body text-error break-words\" role=\"alert\">\n {cellErrorMessages!.length === 1 ? (\n cellErrorMessages![0]\n ) : (\n <ul className=\"list-disc list-inside flex flex-col gap-1\">\n {cellErrorMessages!.map((m, i) => <li key={i}>{m}</li>)}\n </ul>\n )}\n </span>\n </span>\n ) : (\n <>\n {/* L4 nested rows prefix(同上,無 error 時走 flex-row 原 path) */}\n {showNestedPrefix && (\n <span\n className=\"flex items-center shrink-0\"\n style={{ paddingLeft: depth > 0 ? `calc(${depth} * var(--tree-indent-${size}, var(--tree-indent-md)))` : 0 }}\n >\n {canExpand ? (\n <button\n type=\"button\"\n aria-label={isExpanded ? '收合' : '展開'}\n aria-expanded={isExpanded}\n className=\"inline-flex items-center justify-center shrink-0 w-4 h-4 mr-2 text-fg-muted hover:text-foreground rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-transform\"\n style={{ transform: isExpanded ? 'rotate(90deg)' : undefined }}\n onClick={(e) => { e.stopPropagation(); toggleExpand?.() }}\n >\n <ChevronDown size={iconSize} aria-hidden style={{ transform: 'rotate(-90deg)' }} />\n </button>\n ) : (\n <span aria-hidden className=\"shrink-0 w-4 h-4 mr-2\" />\n )}\n </span>\n )}\n <span className={cn(\n 'flex-1 min-w-0 self-stretch flex',\n // 2026-05-12 fix root invariant(M32 b):用 `effectiveAutoRowForCell` 而非 global\n // `autoRowHeight` — per-row error 時 row 是 auto-height,該 row 內所有 cell 都該\n // top-align(非僅 error cell)。前 v1 用 global autoRowHeight → 非 error cells in\n // error row 走 items-center → 視覺垂直置中於 tall row(user 抓 image 3 bug)。\n effectiveAutoRowForCell ? 'items-start' : 'items-center',\n align === 'right' && 'justify-end',\n )}>\n {renderCellContent(cell)}\n </span>\n </>\n )}\n </div>\n )\n }\n\n // ── L2 Selection helpers ──\n const visibleRowIdsKey = React.useMemo(() => rows.map(r => r.id).join(','), [rows])\n const visibleRowIdsSet = React.useMemo(() => new Set(rows.map(r => r.id)), [visibleRowIdsKey])\n\n // 對齊 spec L2 七、Filter 套用 → filtered-out selected rows 預設清掉\n React.useEffect(() => {\n if (!enabled || preserveSelectionOnFilter) return\n setSelection(prev => {\n const filtered = prev.filter(id => visibleRowIdsSet.has(id))\n return filtered.length === prev.length ? prev : filtered\n })\n }, [visibleRowIdsKey, enabled, preserveSelectionOnFilter, visibleRowIdsSet, setSelection])\n\n // Visible 可選 row IDs(扣除 disabled)\n const selectableVisibleIds = React.useMemo(() => {\n if (!enabled) return [] as string[]\n return rows\n .filter(r => !isRowSelectable || isRowSelectable(r.original))\n .map(r => r.id)\n }, [rows, enabled, isRowSelectable])\n\n // Header tri-state checkbox value\n const selectionSet = React.useMemo(() => new Set(selection), [selection])\n const visibleSelectedCount = selectableVisibleIds.filter(id => selectionSet.has(id)).length\n const headerCheckedState: boolean | 'indeterminate' =\n selectableVisibleIds.length === 0 ? false\n : visibleSelectedCount === 0 ? false\n : visibleSelectedCount === selectableVisibleIds.length ? true\n : 'indeterminate'\n\n // visibleIdToRow Map(shift-click 區間選 lookup,避免 O(n) `rows.find()`)\n const visibleIdToRow = React.useMemo(\n () => new Map(rows.map(r => [r.id, r])),\n [rows]\n )\n\n const toggleHeaderCheckbox = React.useCallback(() => {\n if (headerCheckedState === true) {\n // 清掉本頁可見已選(保留可見外的 selection)\n const visibleSet = new Set(selectableVisibleIds)\n setSelection(prev => prev.filter(id => !visibleSet.has(id)))\n } else {\n // 選全可見(扣除 disabled);保留可見外的既有 selection\n setSelection(prev => Array.from(new Set([...prev, ...selectableVisibleIds])))\n }\n }, [headerCheckedState, selectableVisibleIds, setSelection])\n\n const toggleRow = React.useCallback((rowId: string, rowOriginal: TData, opts?: { shiftKey?: boolean }) => {\n if (isRowSelectable && !isRowSelectable(rowOriginal)) return\n if (mode === 'single') {\n setSelection(selectionSet.has(rowId) ? [] : [rowId])\n anchorRowIdRef.current = rowId\n return\n }\n // multi 模式\n const anchor = anchorRowIdRef.current\n if (opts?.shiftKey && anchor && anchor !== rowId) {\n // 區間選:從 anchor 到 rowId(在 visible 順序內),全 toggle 成 willCheck 狀態\n const visibleIds = rows.map(r => r.id)\n const a = visibleIds.indexOf(anchor)\n const b = visibleIds.indexOf(rowId)\n if (a !== -1 && b !== -1) {\n const [from, to] = a < b ? [a, b] : [b, a]\n const rangeIds = visibleIds.slice(from, to + 1).filter(id => {\n const row = visibleIdToRow.get(id)\n return row && (!isRowSelectable || isRowSelectable(row.original))\n })\n // Mail / GitHub 慣例:shift-click 把 range 全變「rowId 點擊後該變的狀態」\n const willCheck = !selectionSet.has(rowId)\n setSelection(prev => {\n const set = new Set(prev)\n rangeIds.forEach(id => willCheck ? set.add(id) : set.delete(id))\n return Array.from(set)\n })\n return\n }\n }\n // 一般 toggle + 更新 anchor\n setSelection(prev => {\n const set = new Set(prev)\n if (set.has(rowId)) set.delete(rowId)\n else set.add(rowId)\n return Array.from(set)\n })\n anchorRowIdRef.current = rowId\n }, [isRowSelectable, mode, selectionSet, rows, visibleIdToRow, setSelection])\n\n // ── Cmd+A / Esc / Arrow keys 鍵盤 handler(table-level)──\n // code-quality-allow: long-function — single keyboard dispatch covering Cmd+A / Esc / Arrow / Space + selection state mutations,拆 sub-handler 會切散 keyboard mode coherence\n const tableKeyboardHandler = React.useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n // ── Spreadsheet mode keyboard nav(Phase B1+B2,2026-05-10 per codex Q-B verdict)──\n // ActiveCellId 由 mouse click(spreadsheet click 1)+ keyboard arrow 共用 SSOT。\n // ↑↓←→ 移動 / Enter / F2 進 edit / Esc exit edit OR clear active。\n // Codex Q-B1:不分 mouse selected vs keyboard focused,共用 selectedCellId state。\n // Phase B3 IME guard(2026-05-10 per codex Q-B3):中文輸入法組字中 ignore 所有 nav keys。\n // 2026-05-16 Round 5 audit Dim 27 fix:`keyCode` deprecated but still in KeyboardEvent type — no cast needed。\n if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return\n if (spreadsheetMode && selectedCellId != null && editingCellId == null) {\n const navKeys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Enter', 'F2', 'Escape']\n if (!navKeys.includes(e.key)) return\n const lastColon = selectedCellId.lastIndexOf(':')\n const curRowId = selectedCellId.slice(0, lastColon)\n const curColId = selectedCellId.slice(lastColon + 1)\n const allRows = table.getRowModel().rows.map((r) => r.id)\n const allCols = table.getVisibleLeafColumns().map((c) => c.id).filter((id) => id !== SELECT_COL_ID)\n const curRowIdx = allRows.indexOf(curRowId)\n const curColIdx = allCols.indexOf(curColId)\n if (curRowIdx < 0 || curColIdx < 0) return\n let nextRowIdx = curRowIdx\n let nextColIdx = curColIdx\n if (e.key === 'ArrowUp' && curRowIdx > 0) { nextRowIdx = curRowIdx - 1 }\n else if (e.key === 'ArrowDown' && curRowIdx < allRows.length - 1) { nextRowIdx = curRowIdx + 1 }\n else if (e.key === 'ArrowLeft' && curColIdx > 0) { nextColIdx = curColIdx - 1 }\n else if (e.key === 'ArrowRight' && curColIdx < allCols.length - 1) { nextColIdx = curColIdx + 1 }\n else if (e.key === 'Enter' || e.key === 'F2') {\n // Enter / F2 → 進 edit(若 cell editable + 非 boolean / url + 非 disabled)\n // 2026-05-13 codex V1 fix:加 `!isCellDisabled(meta, row)` gate(對齊 mouse click invariant)\n const row = table.getRowModel().rowsById[curRowId]\n const colDef = table.getAllLeafColumns().find((c) => c.id === curColId)\n // any-allow: column meta free-form\n const meta = (colDef?.columnDef as any)?.meta as Record<string, any> | undefined\n if (meta?.type && meta.type !== 'boolean' && meta.type !== 'url' && row && canEditCell(meta, row.original)) {\n e.preventDefault()\n setEditingCellId(cellEditId(curRowId, curColId))\n setSelectedCellId(null)\n setRangeAnchor(null)\n setRangeFocus(null)\n }\n return\n }\n else if (e.key === 'Escape') {\n e.preventDefault()\n setSelectedCellId(null)\n setRangeAnchor(null)\n setRangeFocus(null)\n return\n }\n if (nextRowIdx !== curRowIdx || nextColIdx !== curColIdx) {\n e.preventDefault()\n const nextCellId = `${allRows[nextRowIdx]}:${allCols[nextColIdx]}`\n setSelectedCellId(nextCellId)\n setRangeAnchor(nextCellId)\n setRangeFocus(null)\n }\n return\n }\n // ── Row selection mode keyboard handler(下方既有)──\n if (!enabled) return\n // Cmd/Ctrl+A:選全可見(扣 disabled)— 對齊 Mail / GitHub / Linear 慣例\n if ((e.metaKey || e.ctrlKey) && e.key === 'a' && mode === 'multi') {\n e.preventDefault()\n setSelection(prev => Array.from(new Set([...prev, ...selectableVisibleIds])))\n return\n }\n // Esc:clear selection\n if (e.key === 'Escape' && selection.length > 0) {\n e.preventDefault()\n setSelection([])\n anchorRowIdRef.current = null\n return\n }\n },\n [enabled, mode, selection.length, selectableVisibleIds, setSelection,\n spreadsheetMode, selectedCellId, editingCellId, table, isCellEditable]\n )\n\n // ── Header cell ──\n // code-quality-allow: long-function — header render 含 selection tri-state / sort indicator / column dropdown / pinned / divider 五邏輯,拆 sub-fn 會切散 column type-aware rendering coherence\n const headerCellEl = (header: ReturnType<typeof table.getHeaderGroups>[number]['headers'][number], showDivider: boolean) => {\n // L2 selection:__select__ 欄自訂 render(tri-state header checkbox)\n if (enabled && header.column.id === SELECT_COL_ID) {\n const isHeaderDisabled = selectableVisibleIds.length === 0 || mode !== 'multi'\n return (\n <div\n key={header.id}\n role=\"columnheader\"\n className={cn('flex items-center justify-center shrink-0 select-none', !isHeaderDisabled && 'cursor-pointer')}\n style={{ ...columnSizeStyle(header.column, { resize: enableColumnResize, isSystemCol: isSystemColumn(header.column.id) }), ...cellPadding }}\n onClick={isHeaderDisabled ? undefined : (e) => { e.stopPropagation(); toggleHeaderCheckbox() }}\n >\n {mode === 'multi' && (\n <Checkbox\n size={size === 'lg' ? 'lg' : 'md'}\n checked={headerCheckedState}\n onClick={(e) => e.stopPropagation()}\n onCheckedChange={() => toggleHeaderCheckbox()}\n aria-label=\"Select all visible rows\"\n disabled={selectableVisibleIds.length === 0}\n />\n )}\n </div>\n )\n }\n const meta = header.column.columnDef.meta\n const colType = meta?.type as ColumnType | undefined\n const align = meta?.align ?? (colType ? columnTypeDefaults[colType].align : undefined)\n // Sort UI(Phase A.1):header cell 兩區結構\n // 左區(label + indicator slot):click → toggle sort 三態(asc → desc → none)\n // 右區:reserve future ⌄ menu(filter / hide / pin 等;hover 才出,A.x 加)\n // Indicator inline collapse:已套才顯;未套不顯(任何混雜組合不推 — 對齊 AG Grid / Notion)\n const canSort = header.column.getCanSort()\n const sortDir = header.column.getIsSorted() // false | 'asc' | 'desc'\n // **A fix(2026-05-04)**:multi-sort(≥2)hide header arrow + 取消排序 option\n // 理由:無 order 編號的單個 arrow 在 multi-sort 下是 partial info → 反而混淆\n // user 走 SortManager panel 看完整 priority(SSOT)\n // 1 sort 仍秀 arrow(完整資訊);0 sort 自然不秀(canSort && sortDir 短路)\n const isMultiSort = (table.getState().sorting?.length ?? 0) > 1\n const SortIcon = sortDir === 'asc' ? ArrowUp : ArrowDown // 未套不渲染;套用後二擇一\n const sortHandler = canSort ? header.column.getToggleSortingHandler() : undefined\n return (\n <div\n key={header.id}\n role=\"columnheader\"\n aria-sort={sortDir === 'asc' ? 'ascending' : sortDir === 'desc' ? 'descending' : 'none'}\n className={cn(\n // **Inline action canonical**(2026-05-05 v2):header 用 `flex items-center gap-2`\n // (= 8px,inline-action.spec.md SSOT),more action 為 inline shrink-0 sibling 而非\n // absolute → hover 顯時佔位 → label 自動讓出空間給 sort + more,**不再重疊**(對齊\n // user 圖示質疑 + Notion / Airtable header layout 共識)。\n // cell padding 12px 由外層 cellPadding style 提供 → more 距 cell 右邊 = 12px。\n 'group relative flex items-center gap-2 text-fg-secondary text-body font-normal shrink-0 overflow-hidden select-none',\n align === 'right' && 'justify-end',\n align === 'center' && 'justify-center',\n )}\n style={{ ...columnSizeStyle(header.column, { resize: enableColumnResize, isSystemCol: isSystemColumn(header.column.id) }), ...cellPadding }}\n >\n {/* 左區:label + sort indicator(整區 click → toggle sort;Shift+click 加 secondary,enableMultiSort 啟用時) */}\n <div\n role={canSort ? 'button' : undefined}\n tabIndex={canSort ? 0 : undefined}\n onClick={sortHandler}\n // any-allow: event-cast — TanStack getToggleSortingHandler 內部會 narrow,接受 KeyboardEvent\n onKeyDown={canSort ? (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); sortHandler?.(e as any) } } : undefined}\n className={cn(\n 'flex items-center min-w-0 flex-1 gap-1 outline-none',\n canSort && 'cursor-pointer hover:text-foreground transition-colors',\n canSort && 'focus-visible:ring-2 focus-visible:ring-ring rounded-sm',\n )}\n >\n <TruncateCell className={cn('min-w-0', align === 'right' && 'text-right', align === 'center' && 'text-center')}>\n {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}\n </TruncateCell>\n {canSort && sortDir && !isMultiSort && (\n // 2026-05-18 改 per user 拍板「DataTable sort 跟 row size 變」+「做完」approval:\n // 原固定 14 違反 uiSize.spec.md Icon Tier(sm/md→16, lg→20)。改 ICON_SIZE[size]\n // 隨 DataTable size prop 變。\n <SortIcon size={ICON_SIZE[size]} aria-hidden className=\"shrink-0 text-fg-secondary\" />\n )}\n </div>\n {/* 右區:⌄ menu(hover/focus-within 才顯;**不顯示時不佔位**)\n **Layout canonical**(2026-05-06 v3 user explicit rule):`hidden` default →\n `group-hover:inline-flex` / `group-focus-within:inline-flex` / `has-[[data-state=open]]:inline-flex`\n 才出現 + 佔位。前 v2 用 `opacity-0 group-hover:opacity-100` 是「永遠佔位 hover 才顯影」—\n user 報「不應永遠佔位,沒顯示時應讓 label 多空間」。新行為:\n - 不顯示 → display:none → 不佔位 → label 取得整個 header width\n - hover/focus/menu-open → display:inline-flex → 佔位(width 同前;label 自然 truncate 讓位)\n 對齊 Notion(hover-row reveal action,inline action 不佔靜態 layout)/ Linear / Airtable。\n ItemInlineActionButton asChild-compatible,size=\"md\" 因 header 不在 RowSizeProvider。 */}\n <div className=\"shrink-0 hidden group-hover:inline-flex group-focus-within:inline-flex has-[[data-state=open]]:inline-flex\">\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <ItemInlineActionButton\n icon={ChevronDown}\n size=\"md\"\n aria-label={`${typeof header.column.columnDef.header === 'string' ? header.column.columnDef.header : header.column.id} 欄位選單`}\n overlayTrigger\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {canSort && (\n <>\n <DropdownMenuItem startIcon={ArrowUp} onClick={() => header.column.toggleSorting(false, false)}>升冪排序</DropdownMenuItem>\n <DropdownMenuItem startIcon={ArrowDown} onClick={() => header.column.toggleSorting(true, false)}>降冪排序</DropdownMenuItem>\n {sortDir && !isMultiSort && <DropdownMenuItem startIcon={XIcon} onClick={() => header.column.clearSorting()}>取消排序</DropdownMenuItem>}\n <DropdownMenuSeparator />\n </>\n )}\n {onColumnFilterTrigger && (\n <DropdownMenuItem startIcon={FilterIcon} onClick={() => onColumnFilterTrigger(header.column.id)}>依此欄篩選…</DropdownMenuItem>\n )}\n {header.column.getCanHide() && (\n <DropdownMenuItem startIcon={EyeOff} onClick={() => header.column.toggleVisibility(false)}>隱藏欄位</DropdownMenuItem>\n )}\n {/* 2026-05-06 v11:Auto-fit 放 more menu(不綁 double-click,避免跟 click-to-sort 衝突)。\n scan column body cells max scrollWidth + cellPadding → reset column.size。\n System columns 永遠 fixed 不顯此 item。 */}\n {enableColumnResize && !isSystemColumn(header.column.id) && (\n <DropdownMenuItem\n startIcon={ArrowUpDown}\n onClick={() => {\n const cells = document.querySelectorAll<HTMLElement>(\n `[role=\"cell\"][data-column-id=\"${header.column.id}\"]`,\n )\n let max = MIN_COLUMN_WIDTH\n cells.forEach(c => {\n const inner = c.firstElementChild as HTMLElement | null\n const w = (inner?.scrollWidth ?? c.scrollWidth) + 32 // + cellPadding 兩側 + buffer\n if (w > max) max = w\n })\n header.column.resetSize?.()\n table.setColumnSizing(prev => ({ ...prev, [header.column.id]: max }))\n onColumnResize?.(header.column.id, max)\n }}\n >\n 自動調整寬度\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n {/* Header divider + resize handle(2026-05-06 v11,**2026-05-10 H2+H3 重構**):\n - **2026-05-10 split**(per user 抓「pinned 欄位右邊分隔線無法 resize」):\n `showDivider` 只 gate **視覺 1px line**(panel boundary col 由 panel border-r 接,\n 不重複);**resize hot zone** 改 gate by `isResizable` 獨立,panel boundary col\n 仍可拖 resize(hot zone 視覺 invisible,跟 panel border-r 不衝突)。\n - **2026-05-10 H3**:per-column `meta.resizable === false` opt-out — consumer 可標\n 「此 col 寬度由內容決定不允許 resize」(對齊 AG Grid `colDef.resizable` /\n Material X-DataGrid 同 API)。System cols(__select__ / __drag__ / __actions__\n row-actions)自動 false(永遠固定寬)。\n - 視覺:1px line `bg-divider` 在 showDivider 時 paint\n - Hot zone:absolute 7px 兩側,讓 mouse 容易 hit(在 isResizable 時 render)\n - Hover/Active:`bg-border-hover` / `bg-primary`(hot zone 內 1px line 變色)\n - role=\"separator\" + aria-orientation=\"vertical\" 對齊 WAI-ARIA(isResizable 時)*/}\n {(() => {\n const colId = header.column.id\n const colMeta = header.column.columnDef.meta as { resizable?: boolean } | undefined\n // H3: meta.resizable === false 顯式 opt-out(default true)\n const colOptIn = colMeta?.resizable !== false\n const isResizable = enableColumnResize && !isSystemColumn(colId) && colOptIn\n const isResizing = header.column.getIsResizing?.()\n // H2: 不論 showDivider,只要 isResizable 就 render hot zone(panel boundary col 仍可拖)\n if (!showDivider && !isResizable) return null\n return (\n <span\n role={isResizable ? 'separator' : undefined}\n aria-orientation={isResizable ? 'vertical' : undefined}\n aria-label={isResizable ? '拖曳調整欄寬' : undefined}\n className={cn(\n 'group/resize absolute top-0 bottom-0 right-0 -mr-[3px] w-[7px]',\n isResizable && 'cursor-col-resize select-none',\n )}\n // 2026-05-12 fix v2(user 抓 R3 stopPropagation 沒生效):dnd-kit PointerSensor\n // 監聽 `pointerdown`,我前一輪只 stop `onMouseDown` → pointerdown 仍冒泡 →\n // drag activate。改用 `onPointerDownCapture` capture-phase 一次性吃 pointerdown\n // event,**先** dnd-kit listener 拿到 → drag 不啟動;接著 emit synthesized\n // mousedown 給 TanStack resize handler。對齊 AG Grid / Material X-Grid pinned-column\n // resize idiom(resize handle 永遠 own pointer event,drag listener 不競爭)。\n onPointerDownCapture={isResizable ? (e: React.PointerEvent<HTMLSpanElement>) => {\n e.stopPropagation()\n header.getResizeHandler?.()(e.nativeEvent)\n } : undefined}\n onTouchStart={isResizable ? (e: React.TouchEvent<HTMLSpanElement>) => {\n e.stopPropagation()\n header.getResizeHandler?.()(e.nativeEvent)\n } : undefined}\n >\n {/* H2: 視覺 1px line 只在 showDivider 時 paint(panel boundary col by panel-r 接管,不重) */}\n {showDivider && (\n <span\n aria-hidden\n className={cn(\n 'absolute right-[3px] w-px transition-colors',\n isResizing\n ? 'bg-primary'\n : isResizable\n ? 'bg-divider group-hover/resize:bg-[var(--border-hover)]'\n : 'bg-divider',\n )}\n style={{ top: 'var(--table-cell-py)', bottom: 'var(--table-cell-py)' }}\n />\n )}\n </span>\n )\n })()}\n </div>\n )\n }\n\n // ── Region helpers ──\n // hoist region id Sets 一次,避免 n_rows × n_regions 重建(virtual mode 1000+ rows 場景效益顯著)\n const leftIds = React.useMemo(() => new Set(leftCols.map(c => c.id)), [leftCols])\n const centerIds = React.useMemo(() => new Set(centerCols.map(c => c.id)), [centerCols])\n const rightIds = React.useMemo(() => new Set(rightCols.map(c => c.id)), [rightCols])\n const colsToIds = (cols: Column<TData, unknown>[]) =>\n cols === leftCols ? leftIds : cols === rightCols ? rightIds : centerIds\n\n const getRegionHeaders = (cols: Column<TData, unknown>[]) => {\n const ids = colsToIds(cols)\n return table.getHeaderGroups()[0]?.headers.filter(h => ids.has(h.id)) ?? []\n }\n\n const getRegionCells = (row: typeof rows[number], cols: Column<TData, unknown>[]) => {\n const ids = colsToIds(cols)\n return row.getVisibleCells().filter(c => ids.has(c.column.id))\n }\n\n // 2026-05-06 v14.4 Notion blue line drop indicator(column reorder visual canonical)\n // 必須宣告在 renderHeaderRow 之前(closure 引用,避 minified bundler TDZ false-positive)\n const [dropIndicator, setDropIndicator] = React.useState<{ id: string; side: 'before' | 'after'; type: 'row' | 'column' } | null>(null)\n // ref for stable lookup in handleDragOver(避免 closure 抓舊值)\n const reorderableColumnIdsRef = React.useRef<string[]>([])\n\n // ── Render header row for a region ──\n const renderHeaderRow = (cols: Column<TData, unknown>[], isRight: boolean) => {\n const headers = getRegionHeaders(cols)\n // a11y(2026-04-25 axe aria-required-children):若 region 無 visible cells(只有\n // invisible rowActions placeholder 或 region 本身空),不設 role='row' — 改為純\n // layout div,避免 axe 抓到「row 無 cell/columnheader 子元素」violation。\n const hasVisibleChildren = headers.length > 0\n const RowTag = hasVisibleChildren ? 'div' : 'div'\n const rowRole = hasVisibleChildren ? 'row' : undefined\n return (\n <RowTag role={rowRole} className={cn('flex items-center border-b border-divider', rowHeight, HEADER_BG)}>\n {headers.map((h, i) => {\n const showDivider = i < headers.length - 1 && !(isRight && i === headers.length - 1)\n const colId = h.column.id\n const meta = h.column.columnDef.meta as { locked?: boolean } | undefined\n const isLocked = meta?.locked === true\n const isSystem = isSystemColumn(colId)\n // useSortable per header(Rules of Hooks compliant — same hook count per render\n // as long as headers count consistent;column reorder/hide 整 row reflow 自然觸發 React reconcile)。\n // disabled=true 時仍 call hook 不啟動 listeners。\n const isDraggable = enableColumnReorder && !isLocked && !isSystem\n const indicatorSide = dropIndicator?.type === 'column' && dropIndicator.id === colId ? dropIndicator.side : null\n return (\n <DraggableHeaderCell\n key={h.id}\n id={colId}\n disabled={!isDraggable}\n isLocked={isLocked}\n dropIndicatorSide={indicatorSide}\n >\n {headerCellEl(h, showDivider)}\n </DraggableHeaderCell>\n )\n })}\n {isRight && hasRowActions && (\n <div className=\"flex items-center justify-end shrink-0 gap-2 invisible\" aria-hidden=\"true\" style={cellPadding}>\n {/* 渲染一個假 row 的 actions 來佔位,確保 header 和 body 同寬(aria-hidden 避免 screen reader 讀出 invisible 內容)*/}\n {rows[0] && rowActions!(rows[0].original)}\n </div>\n )}\n </RowTag>\n )\n }\n\n // ── Render body rows for a region ──\n // code-quality-allow: long-function — virtualizer × sticky region × empty state × per-row drag 四正交 render path 集中,拆 sub-fn 會將 virtualItems / rows / colVirtualizer 三 closure 跨 fn 傳\n const renderBodyRows = (cols: Column<TData, unknown>[], isCenter: boolean, isRight: boolean, regionWidth?: number) => {\n if (isEmpty && isCenter) {\n // 有框容器 → 垂直置中(design principle)\n if (emptyState && typeof emptyState !== 'string') return <div className=\"flex-1 flex items-center justify-center py-12\">{emptyState}</div>\n return <div className=\"flex-1 flex items-center justify-center py-12\"><Empty description={typeof emptyState === 'string' ? emptyState : '沒有資料'} /></div> // i18n-allow: DS default fallback; consumer override via emptyState prop\n }\n if (isEmpty) return null\n\n // **v15.4 architectural decision** — primary 永遠 = center region(不論是否 pinnedLeft)。\n // 之前 `primary = left if hasLeft else center` 有兩問題:\n // 1. multi-instance same-id 是 dnd-kit anti-pattern,setActivatorNodeRef 救不了\n // (last-mount-wins,用 last region 的 rect 當 activator → ghost 起點偏離 cursor)\n // 2. user 從 center 主視覺 grab 才直觀;pinned-left(SKU)/ pinned-right(Updated)\n // 是「鎖定欄」語意,不是 drag handle。Linear / Notion / Jira 的 pinned column\n // 都不接 drag listeners,純視覺鎖。\n // 改 center-only listeners → ghost activator = center row → cursor 跟 ghost 維持初始\n // 相對位置(SSOT 對齊 user directive)。\n // code-quality-allow: long-function — audit 誤偵測 isPrimaryRegion 為 function(實為 const);真實 long body = 下方 rowEl render closure(virtualizer × sticky × drag listeners × hover delegation),拆會破壞 closure capture\n const isPrimaryRegion = isCenter\n const regionRole: 'primary' | 'mirror' = isPrimaryRegion ? 'primary' : 'mirror'\n\n // code-quality-allow: long-function — virtualizer × sticky panel × drag listeners × hover delegation × per-row state 多 closure capture;拆會破壞 SortableContext / dnd-kit hooks 跟 row idx 的 stable binding\n const rowEl = (row: typeof rows[number], idx: number, opts?: { virtual?: boolean; start?: number; isLast?: boolean }) => {\n const showBorder = bordered !== false ? !opts?.isLast : true\n // L4 row drag v2:nested rows 也 sortable(配合 cross-parent collisionDetection 過濾)\n // sub-rows: depth>0 仍進 SortableContext,但 collisionDetection 只接受 same-parent over\n const isThisRowDragging = enableRowDrag && activeDragId === row.id\n const useSortableWrap = enableRowDrag\n\n // H1 fix(2026-05-10,per user 確認):per-row autoRowHeight when any cell in this row has\n // error。Fixed-height row 模式下,該 row 的任一 cell 有 error msg → THAT row 自動 auto-height\n // 撐 message;error 全清 → 回 fixed。Other rows 不受影響(global autoRowHeight prop 不變)。\n // Per Material X-DataGrid `getRowHeight` per-row dynamic + AG Grid `rowHeight: 'auto'`\n // per-row idiom。Compute by scanning row's visible cells for cellErrors map hit。\n const rowHasError = !!cellErrors && row.getVisibleCells().some((c) => {\n const key = `${row.id}:${c.column.id}`\n const v = cellErrors[key]\n return v != null && (Array.isArray(v) ? v.length > 0 : true)\n })\n const effectiveAutoRow = autoRowHeight || rowHasError\n\n // L4 row drag:handle absolute 貼齊 row 左 border(Jira canonical),不佔 column 空間。\n // 只在 primary region(left 若有,否則 center)+ depth===0 render — RowDragHandle\n // 內部再用 ctx.role === 'primary' 守門避免 mirror region 重複 render。\n const showDragHandle = enableRowDrag && (row.depth ?? 0) === 0 && isPrimaryRegion\n // v15.2 SSOT 對齊 TreeView:drag 期間 suppress 全表 hover state\n // (user directive「drag 時 row 不應 hover / drag button 不應出現」)\n const anyDragActive = activeDragId != null\n // code-quality-allow: long-function — baseRowDiv 含 row drag listeners / sticky panel / hover delegation / cell render loop / divider drawing 多 closure;拆 sub-fn 會破壞 dnd-kit hooks + row.id stable binding\n const baseRowDiv = (extra?: { ref?: (el: HTMLElement | null) => void; style?: React.CSSProperties; isDragging?: boolean; listeners?: Record<string, unknown>; attributes?: Record<string, unknown> }) => (\n <div\n key={row.id}\n ref={(el) => {\n // v2 fix #1:被拖 row 略過 measureElement(transform 干擾測量,長 list 累積誤差)\n // v2 fix #4(virtual freeze):drag 進行中(activeDragId != null)整個略過 measureElement\n // **2026-05-07 v15.17 A 路徑 — revert autoRowHeight guard**:\n // v15.8 加 `&& autoRowHeight` guard 為了解 R4 mount-time row growth animation\n // (假設 measureElement 在 fixed mode 觸發 getTotalSize 重算 → React re-render →\n // mount 時看起來 row height 在變)。但 codex P2 audit (`6d5188e` line 1699)指出\n // 此 guard 副作用:consumer 傳 custom `estimateRowHeight` 或 CSS theme override\n // row height 時,fixed mode 不再 reconcile estimate vs reality → getTotalSize 錯\n // → scroll 範圍截斷或末端留白。\n //\n // Codex deep R4 eval (`4399272774` follow-up reply) 認為 R4 真因更可能是\n // 「首幀樣式未齊 / 字型 async load / paint stagger」,不是 measureElement。\n // 故先 revert guard 觀察 R4 是否真回歸:\n // - R4 不重現(我 + codex 推論對)→ guard mis-fix,永久撤,P2 自動解\n // - R4 重現(measureElement 真因)→ 補 dampening (差異 <1px 不 setState /\n // 一幀只 update 一次)+ low-freq sampling per codex 雙模式方案\n if (isCenter && opts?.virtual && el && !isThisRowDragging && activeDragId == null) {\n virtualizer.measureElement(el)\n }\n extra?.ref?.(el)\n }}\n data-index={isCenter && opts?.virtual ? idx : undefined}\n data-row-index={idx}\n data-sortable-row-id={enableRowDrag ? row.id : undefined}\n // v15.4:primary region(center)= drag source row — ghost reconstruction 用此 marker\n // 找 source row(避免 multi-region 場景挑錯 region 的 row 當 ghost)\n data-row-drag-source={enableRowDrag && isPrimaryRegion ? 'true' : undefined}\n role=\"row\"\n aria-rowindex={idx + 2}\n className={cn(\n 'group/row flex relative',\n // H1 fix(2026-05-10):effectiveAutoRow 覆 global autoRowHeight,per-row 若有 cell error\n // 自動 auto-height(撐 message)。Error 清 → 回 fixed。Other rows 不受影響。\n effectiveAutoRow ? 'items-start' : 'items-center',\n !effectiveAutoRow && rowHeight,\n !effectiveAutoRow && 'overflow-hidden',\n opts?.virtual && 'absolute w-full',\n showBorder && 'border-b border-divider',\n // v15.3 hover bg canonical:hover class 永遠生效,但 onMouseOver delegate\n // 在 drag 期間只允許 source row 寫 data-hovered → 其他 row 自然不顯 bg。\n // (對齊 Linear / Jira:source 維持 active 視覺,其他 row 完全靜止)\n 'transition-colors data-[hovered]:bg-neutral-hover',\n extra?.isDragging && 'bg-neutral-hover',\n // **v15.3.1**:不變 cursor(對齊 Material / Carbon / Polaris / Notion canonical)。\n // 整列可拖的 affordance 由可見的 RowDragHandle Button 提供,不靠 cursor 暗示。\n // 之前 cursor-grab → drag 中 user 看到 cursor 變化反而干擾 indicator+ghost 的視覺焦點。\n )}\n style={{\n ...(opts?.virtual ? { transform: `translateY(${opts.start}px)` } : {}),\n ...(extra?.style ?? {}),\n }}\n {...hoverProps(idx)}\n {...(extra?.attributes ?? {})}\n {...(extra?.listeners ?? {})}\n >\n {showDragHandle && <RowDragHandle disabled={dragDisabled} anyDragActive={anyDragActive} />}\n {/* 2026-05-06 v14.6 row drop indicator(SSOT 對齊 TreeView):水平 2px primary line at top/bottom edge */}\n {dropIndicator?.type === 'row' && dropIndicator.id === row.id && dropIndicator.side === 'before' && (\n <div className={dropIndicatorRow.before} aria-hidden />\n )}\n {getRegionCells(row, cols).map((cell, ci, arr) => cellEl(cell, ci === arr.length - 1 && !(isRight && hasRowActions)))}\n {isRight && hasRowActions && (\n <div role=\"cell\" className=\"flex items-center justify-end shrink-0 gap-2 flex-1\" style={cellPadding}>\n {rowActions!(row.original)}\n </div>\n )}\n {dropIndicator?.type === 'row' && dropIndicator.id === row.id && dropIndicator.side === 'after' && (\n <div className={dropIndicatorRow.after} aria-hidden />\n )}\n </div>\n )\n\n if (useSortableWrap) {\n // invalidDrop 只對「正在被拖」的 row 顯示 — handle 在 active row 上,UI 警示只需該 row\n // code-quality-allow: long-function — 此 const 之下的整個 if-block 含 useSortable hooks + SortableRowProvider + baseRowDiv composition;audit 把 const 誤認為 function entry,實 long body 在 closure 內 dnd-kit + per-row state 多 capture,拆會破壞 hook order invariant\n const rowInvalidDrop = isThisRowDragging && invalidDropActive\n return (\n <SortableRowProvider key={row.id} id={row.id} disabled={dragDisabled} role={regionRole} invalidDrop={rowInvalidDrop}>\n {(ctx) => baseRowDiv({\n // mirror 也掛 setNodeRef — dnd-kit 內部以 hook instance 為單元,\n // 多 instance 同 id 時,measurement 走最後 mount 的;不影響 transform 一致性\n ref: ctx.setNodeRef,\n style: ctx.style,\n isDragging: ctx.isDragging,\n // v15.2 整列可拖:listeners + attributes spread 在 row div 上(只 primary,\n // mirror region 沒 listeners 避免 a11y 重複 announce / pointer 雙觸發)\n listeners: ctx.rowListeners,\n attributes: ctx.rowAttributes,\n })}\n </SortableRowProvider>\n )\n }\n return baseRowDiv()\n }\n\n // AR44 canonical(2026-04-21):virtual / non-virtual 都用 `minWidth: colsWidth` 的 wrapper,\n // 讓兩種 rendering path 的 **水平 overflow 行為一致** — 中段 column 區塊都會因\n // columns 實際寬度超過 centerBody 可用寬而觸發 H scrollbar。\n // 先前 non-virtual 走 `<>...</>`(無 wrapper),依靠 row 內 cells 自然寬推擠容器,\n // 跟 virtual 的 `minWidth: containerWidth` 行為不同,造成 story 1 / story 2 看起來水平\n // 捲軸出現時機不一致。現在統一靠 wrapper 的 minWidth 強制 overflow。\n const colsWidth = cols.reduce((a, c) => a + c.getSize(), 0)\n const containerWidth = regionWidth || colsWidth\n\n if (useVirtual) {\n // 2026-05-13 (c) scroll-defer perf(per user 拍 Path (c) Roadmap >50ms 後 escalate):\n // wrap virtual body with `<TableScrollProvider isScrolling={virtualizer.isScrolling}>` →\n // 重 cell subtree(Avatar HoverCard / future Tag / etc.)讀 useTableIsScrolling() 跳\n // expensive paths during scroll,scroll end 自動接回完整 affordance。\n // 對齊 AG Grid deferRender / MUI X DataGrid scroll-defer canonical。\n return (\n <TableScrollProvider isScrolling={virtualizer.isScrolling}>\n <div style={{ height: virtualizer.getTotalSize(), position: 'relative', minWidth: containerWidth }}>\n {virtualizer.getVirtualItems().map(vr => rowEl(rows[vr.index], vr.index, { virtual: true, start: vr.start, isLast: vr.index === rows.length - 1 }))}\n </div>\n </TableScrollProvider>\n )\n }\n return (\n <div style={{ minWidth: containerWidth }}>\n {rows.map((row, i) => rowEl(row, i, { isLast: i === rows.length - 1 }))}\n </div>\n )\n }\n\n // Single mode 用 RadioGroup wrap 整 table(Radix RadioGroup 用 context 傳遞 value/onValueChange)\n // Multi mode 不需 wrap(Checkbox 各自 controlled,不靠 context)\n const tableContent = (\n <div\n ref={(el) => { tableRef.current = el; if (typeof ref === 'function') ref(el); else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = el }}\n data-table-size={size}\n data-data-table-outer // anchor for RowDragHandle Portal getBoundingClientRect (M25 invariant: outer 一定存在)\n data-active-editor-controller={experimentalActiveEditorController ? 'enabled' : undefined} // Slice D Step 3.2 scaffold marker\n // 2026-05-12 fix(user 抓「為什麼按 shift 那麼容易會在 table 外圈出現一層藍色邊框」):\n // table outer tabIndex=0(spreadsheet keyboard nav needs)→ click 取得 focus →\n // browser default `:focus-visible` 來自 globals.css L63「outline: 2px solid var(--ring)」\n // → 整 table 藍框。Fix:`outline-none` 抑制 outer focus visual,cell selection rect\n // (SelectionRect z 2)IS the visual focus indicator per spreadsheet canonical\n // (對齊 Excel / Google Sheets / Notion / Airtable — focused cell own active border,\n // table 容器無 focus ring)。\n className={cn(dataTableVariants({ bordered }), isFillHeight && 'flex flex-col', 'outline-none focus:outline-none focus-visible:outline-none', className)}\n // isFillHeight:`maxHeight: 100%`(不是 height:100%)— content 小 → outer = intrinsic\n // (hug rows);content 大或 window 縮 < content → outer cap 到 100% of parent。\n // 行為:**永遠 hug rows**,只在被約束時才 cap + body shrink + V scroll。\n // 簡單需求:有約束 → rows 沒超就 hug;超就 cap+scroll;RWD 同理。\n style={isFillHeight ? { maxHeight: height } : undefined}\n role=\"table\" aria-rowcount={rows.length + 1}\n // Phase 9 Issue 12 fix(2026-05-10 codex 抓):**single tabIndex prop**,合併 selection\n // 跟 spreadsheet 兩 path。React 在 dup props 只 keep last 是 silent regression risk。\n tabIndex={enabled || spreadsheetMode ? 0 : undefined}\n // 2026-05-10:`enabled || spreadsheetMode` — spreadsheet keyboard nav 跨 row-selection-disabled 場景也要 fire\n onKeyDown={enabled || spreadsheetMode ? tableKeyboardHandler : undefined}\n onMouseOver={enterLeaveHandlers.onMouseOver}\n onMouseOut={enterLeaveHandlers.onMouseOut}\n {...props}\n >\n {/* ══ HEADER(固定頂部,不在 scroll 內)══ */}\n <div role=\"rowgroup\" className=\"flex\">\n {hasLeft && (\n <div ref={leftHeaderRef} data-datatable-header-panel=\"left\" className=\"shrink-0 overflow-hidden dtPanelBoundaryRight\">\n {renderHeaderRow(leftCols, false)}\n </div>\n )}\n {/* Header 的 center 區保持 overflow-hidden(非 scroll)—— body 的 center 才有 scroll,\n header 靠 JS 同步 scrollLeft(見 onCenterBodyScroll)。這樣不會出現雙 scrollbar。\n 為了對齊 body 的 V scrollbar(native 捲軸吃 ~15-17px 寬),header 等寬預留 gutter:\n `scrollbar-gutter: stable` 放在 centerBody(真正有 V scroll 的 container)+\n header 這層不需額外處理,因為 body 預留了空間後 H 內容寬度會自然等同 header。\n 注意:header 的 `scrollbar-gutter` 無效(因為 overflow-hidden),刻意不設 */}\n <div\n ref={centerHeaderRef}\n data-datatable-header-panel=\"center\"\n className=\"flex-1 min-w-0 overflow-hidden\"\n >\n {/* 2026-05-06 v13.1:retire `w-max min-w-full` — 改 `style={{minWidth: centerColsWidth}}`\n 跟 body inner wrapper 同 SSOT。前 `w-max` 讓 header content max-content(label 短)\n vs body content max-content(Note 長 break-words)diverge → header / row width 不對齊 76px。\n 統一 minWidth 公式後兩者永遠等寬,cells flex 均分結果一致。 */}\n <div style={{ minWidth: centerColsWidth }}>\n {renderHeaderRow(centerCols, false)}\n </div>\n </div>\n {hasRight && (\n <div ref={rightHeaderRef} data-datatable-header-panel=\"right\" className=\"shrink-0 overflow-hidden dtPanelBoundaryLeft\">\n {renderHeaderRow(rightCols, true)}\n </div>\n )}\n </div>\n\n {/* ══ BODY(AG Grid 流派:各 region 自己 V scroll + JS 同步)══\n AR44 user-reported UX fix:H scrollbar 現在落在 center-body 的 visible 底部(不是 1800px 內容底部)。\n 三個 region(left / center / right)各自 maxHeight + overflowY,JS 同步 scrollTop。\n Pinned 區 overflow-y:hidden(看不到自己的 V scrollbar),V scroll 真正發生在 center。\n isFillHeight 時 body div 加 min-h-0 讓它在 outer flex column 內可被 flex shrink — region maxHeight: 100% 才能 bind 到實際分配的高度。 */}\n {/* body 在 isFillHeight 用 `min-h-0 min-w-0`(**不**用 flex-1)。\n flex-1 會強制 body 撐滿 outer = 不 hug content。預設 `flex: 0 1 auto` + min-h-0 =\n body intrinsic = content,被 outer maxHeight 約束時可 shrink 到 outer 分配空間。\n centerBody.maxHeight 用 JS 算 px(bypass CSS % flex 場景 buggy shrink)。 */}\n <div ref={bodyRef} className={cn('flex items-start', isFillHeight && 'min-h-0 min-w-0')}>\n {hasLeft && (\n <div\n ref={leftBodyRef}\n data-datatable-panel=\"left\"\n className=\"shrink-0 overflow-hidden dtPanelBoundaryRight\"\n style={{\n width: leftWidth || undefined,\n // isFillHeight 用 JS 算的 px;固定 px(300px 等)直接套\n ...(isFillHeight && bodyMaxHeight != null ? { maxHeight: bodyMaxHeight } : hasHeightConstraint ? { maxHeight: height } : {}),\n }}\n >\n {renderBodyRows(leftCols, false, false, leftWidth)}\n </div>\n )}\n <div\n ref={centerBodyRef}\n // Center body 同時擁有 H + V scroll;maxHeight 限制讓 H scrollbar 落在 visible 底部\n // `scrollbar-gutter: stable` 永遠預留 V scrollbar 寬度(~15-17px),避免 body 出現 V\n // scrollbar 時右端被縮,跟 header 右端產生 gap(Windows/Linux native scrollbar 吃寬)\n data-datatable-hscroll\n data-datatable-panel=\"center\"\n // overflow-x/y: auto — 沒 overflow 就不顯 bar。wrapper minWidth 仍 trigger H 真 overflow。\n // **不**用 scrollbar-gutter: stable — 那會永遠保留 V 軸 15px 空間,\n // content fit 時看起來像「永遠有 V 捲軸」(Image #5 bug)。\n // trade-off:V scroll 出現時 body 內側少 15px,header 不縮 → 右端微 misalign,\n // 但 content fit 視覺乾淨優先(Mac 用戶 overlay scrollbar 不可見)。\n className=\"flex-1 min-w-0 overflow-x-auto overflow-y-auto\"\n // isFillHeight:用 JS 算的 px(bodyMaxHeight),bypass CSS % 在 flex 場景的不可靠 shrink。\n // 固定 px(300px etc):直接套 height。\n style={\n isFillHeight && bodyMaxHeight != null\n ? { maxHeight: bodyMaxHeight }\n : hasHeightConstraint\n ? { maxHeight: height }\n : undefined\n }\n onScroll={onCenterBodyScroll}\n >\n {/* 2026-05-06 v13.1:retire `w-max min-w-full` — 改 `style={{minWidth: centerColsWidth}}`\n 跟 header inner wrapper 同 SSOT。renderBodyRows 內部已用同 containerWidth 公式 wrap rows,\n 此外層 wrapper minWidth 跟內層一致 = 兩層都 = centerColsWidth → header / body 對齊。 */}\n <div style={{ minWidth: centerColsWidth }}>\n {renderBodyRows(centerCols, true, false)}\n </div>\n </div>\n {hasRight && (\n <div\n ref={rightBodyRef}\n data-datatable-panel=\"right\"\n className=\"shrink-0 overflow-hidden dtPanelBoundaryLeft\"\n style={{\n width: rightWidth || undefined,\n ...(isFillHeight && bodyMaxHeight != null ? { maxHeight: bodyMaxHeight } : hasHeightConstraint ? { maxHeight: height } : {}),\n }}\n >\n {renderBodyRows(rightCols, false, true, rightWidth)}\n </div>\n )}\n </div>\n {/* Slice D Step 1B(2026-05-10):Interaction Layer singleton(`.claude/planning/datatable-spreadsheet-rfc.md`)。\n Default disabled — backward-compat。Enable 後 hover/editor/selected/range 由 layer 統一畫,\n per Contract 8 「one geometry owner, two paint owners」。\n Step 1C-fix(2026-05-10):wire Contract 15 cellClickEntersEdit predicate 過濾 readonly /\n boolean / url cells(per RFC + user 拍板 USER #15「checkbox/url no-hover」)。\n Step 4(2026-05-10):wire spreadsheetMode select / range cells。 */}\n <DataTableInteractionLayer\n enabled={experimentalSpreadsheetOverlay || spreadsheetMode}\n containerRef={tableRef}\n // Slice D Step 3 wire(2026-05-10):pass editingCellId so layer renders\n // ActiveEditorHost rect at active cell。Composite cell-id format:\n // `${rowId}:${colId}` matches data-cell-id attribute(per Step 1B)。\n // Note:editingCellId 內部用 `__` separator,需轉 `:`。\n activeEditorCellId={editingCellId ? editingCellId.replace('__', ':') : null}\n // 2026-05-10 bug fix(user 圖1):dashed scaffold rect 改 gate 給\n // experimentalActiveEditorController 而非 experimentalSpreadsheetOverlay,\n // 避免 hover overlay 開啟時 cell 進 edit mode → dashed leak 出來跟 hover solid 並存。\n activeEditorEnabled={experimentalActiveEditorController}\n // Slice D Step 5(D.3 portal Field,2026-05-10):real portal Field render callback。\n // Layer 在 ActiveEditorHost(z 3 float rect)render `<Cell mode=\"edit\" />` 同 registry。\n // Cell wrapper 保持 mode=\"display\"(SSOT preserved per codex Q6.2)。\n activeEditorRender={experimentalActiveEditorController ? (cellId) => {\n const lastColon = cellId.lastIndexOf(':')\n if (lastColon < 0) return null\n const rowId = cellId.slice(0, lastColon)\n const colId = cellId.slice(lastColon + 1)\n const colDef = table.getAllLeafColumns().find((c) => c.id === colId)\n // any-allow: free-form column meta bag\n const meta = (colDef?.columnDef as any)?.meta as Record<string, any> | undefined\n if (!meta?.type) return null\n const colType = meta.type as ColumnType\n const Cell = resolveCellComponent(colType)\n const row = table.getRowModel().rowsById[rowId]\n if (!row) return null\n const cellEditable = isCellEditable(meta, row.original)\n // Phase 7 virtualizer unmount preserve draft:portal Field value 從 lifted editingDraft 取\n // (若 user 編輯中字 → draft 持有);未編輯時 fallback row.value(全新 edit session 顯示原值)\n // 2026-05-16 Round 5 audit Dim 27 fix:narrow type 取代 `as any`\n const rowValue = (row.original as Record<string, unknown>)[colId]\n const value = editingDraft !== undefined ? editingDraft : rowValue\n // Per codex Q6.2 invariant test:nested popovers register inside editor;\n // outside-click excludes them(future ActiveEditorController 接管 lifecycle scope)。\n // 當前 MVP:reuse cell-registry Cell mode=\"edit\" + bound onCommit/onCancel。\n //\n // Phase B2 completion(2026-05-10 per codex Q-B2):Tab → commit + next editable + auto-edit。\n // wrap Cell in div with onKeyDownCapture intercept Tab/Shift+Tab(capture mode 先抓\n // 不被 Field 內部 keydown 攔)。direction:Tab=next / Shift+Tab=prev。\n // findNext skip readonly / boolean / url(non-editable click types per Contract 15)。\n // Phase B3(2026-05-10 per codex Q-B3):IME composition guard。中文輸入法組字期間\n // compositionstart event fire,組字結束後 compositionend fire。期間 keydown 的\n // Enter / Tab / Esc 不該觸發 commit/exit/next 行為(因 user 還在組字)。\n const handleEditTab = (e: React.KeyboardEvent) => {\n // IME guard:組字中 ignore Tab(per codex Q-B3 verdict 在 controller 層,\n // 此處 portal wrapper 是最近 controller 等價層;Field 內部 input 自帶 isComposing 但\n // wrapper-level Tab handler 必須也 guard,避免 onKeyDownCapture 早於 Field input)\n // 2026-05-16 Round 5 audit Dim 27 fix:`keyCode` deprecated but still in KeyboardEvent type — no cast needed\n if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) return\n if (e.key !== 'Tab') return\n e.preventDefault()\n e.stopPropagation()\n const direction: 'next' | 'prev' = e.shiftKey ? 'prev' : 'next'\n const allRows = table.getRowModel().rows.map((r) => r.id)\n const allCols = table.getVisibleLeafColumns().map((c) => c.id).filter((id) => id !== SELECT_COL_ID)\n const curRowIdx = allRows.indexOf(rowId)\n const curColIdx = allCols.indexOf(colId)\n if (curRowIdx < 0 || curColIdx < 0) return\n // Step row-by-row,each step check editable + non-boolean/url\n const NON_EDIT_TYPES = ['boolean', 'url']\n let nextRowIdx = curRowIdx\n let nextColIdx = curColIdx\n const totalCells = allRows.length * allCols.length\n let safety = 0\n while (safety < totalCells) {\n safety++\n if (direction === 'next') {\n nextColIdx++\n if (nextColIdx >= allCols.length) { nextColIdx = 0; nextRowIdx++ }\n if (nextRowIdx >= allRows.length) return // 末尾,不 wrap\n } else {\n nextColIdx--\n if (nextColIdx < 0) { nextColIdx = allCols.length - 1; nextRowIdx-- }\n if (nextRowIdx < 0) return // 首端,不 wrap\n }\n const nextRow = table.getRowModel().rowsById[allRows[nextRowIdx]]\n const nextColDef = table.getAllLeafColumns().find((c) => c.id === allCols[nextColIdx])\n // any-allow: column meta free-form\n const nextMeta = (nextColDef?.columnDef as any)?.meta as Record<string, any> | undefined\n if (!nextMeta?.type || NON_EDIT_TYPES.includes(nextMeta.type)) continue\n // 2026-05-13:canEditCell helper(per V4 consolidation,合 editable + !disabled invariant)\n if (!nextRow || !canEditCell(nextMeta, nextRow.original)) continue\n // 找到 next editable cell → commit current + start next edit\n setEditingCellId(cellEditId(allRows[nextRowIdx], allCols[nextColIdx]))\n return\n }\n }\n return (\n <div onKeyDownCapture={handleEditTab} style={{ width: '100%', height: '100%' }}>\n <Cell\n value={value}\n meta={meta}\n mode=\"edit\"\n size={size}\n autoRowHeight={false} // portal MVP 單行;auto-row defer 到 Phase 5\n isEditable={cellEditable}\n onCommit={(next) => commitCell(rowId, colId, next)}\n onCommitLive={(next) => onCellCommit?.(rowId, colId, next)}\n onCancel={exitEdit}\n onDraft={setEditingDraft} // Phase 7:每 keystroke 寫 draft → preserve across virtualizer unmount\n />\n </div>\n )\n } : undefined}\n // Slice D Step 4 spreadsheet semantics(2026-05-10):\n // selectedCellId(click 1)= solid border SelectionRect z 2\n // rangeCellIds(Shift+click rectangle from anchor↔focus)= cell-bg fill via\n // CSS `[data-range-cell]`(per Issue 1 codex verdict;layer 不畫 fill,只畫\n // RangeOuterRing 4 line div boundary)\n selectedCellId={spreadsheetMode ? selectedCellId : null}\n rangeCellIds={rangeCellIds}\n cellClickEntersEdit={(cellId) => {\n // 2026-05-10 codex review red light fix(per dual-track verify):\n // 1. cellId parse 用 lastIndexOf(':')(row id 可含 colon)\n // 2. type allowlist(未知 type default false,non-editable types blocked)\n // 3. row-level editable(row) function 支援(per isCellEditable canonical)\n const lastColonIdx = cellId.lastIndexOf(':')\n if (lastColonIdx < 0) return false\n const rowId = cellId.slice(0, lastColonIdx)\n const colId = cellId.slice(lastColonIdx + 1)\n const colDef = table.getAllLeafColumns().find(c => c.id === colId)\n // any-allow: column meta 是 free-form bag\n const meta = (colDef?.columnDef as any)?.meta as Record<string, any> | undefined\n if (!meta) return false\n // Allowlist editable types(per Contract 15;未知 / boolean / url / readonly default false)\n const EDITABLE_CLICK_TYPES = ['string', 'number', 'currency', 'date', 'time', 'select', 'multiSelect', 'person', 'multiPerson', 'combobox']\n if (!EDITABLE_CLICK_TYPES.includes(meta.type)) return false\n // Row-level editable(row) function support(canonical per `isCellEditable` L720)\n // 2026-05-13:canEditCell helper consolidation(per V4)\n const row = table.getRowModel().rowsById[rowId]\n if (!row) return false\n return canEditCell(meta, row.original)\n }}\n />\n </div>\n )\n\n // ── L4 Row drag DnD wrapper ───────────────────────────────────────────────\n // Sensors:Pointer(8px activation distance,避免 cell click 誤觸 drag)+ Keyboard(a11y)\n // SortableContext items:**只 top-level row id**(nested sub-rows 不在 sortable 集合);\n // 同 parent level 限制由「sub-rows 不在 items 內」自然成立。\n // DragEnd:active.id / over.id → 算 position(active vs over 視覺位置),呼叫 onRowReorder。\n // hooks 必呼叫(rules-of-hooks)— 即使 enableRowDrag=false 也走 useSensors;wrap 才條件化。\n // **codex P1 fix(2026-05-07 v15.13)**:KeyboardSensor 不傳 `coordinateGetter`,用\n // dnd-kit 預設 25px 箭頭 stepping。`sortableKeyboardCoordinates` 是 `@dnd-kit/sortable`\n // preset,需 `<SortableContext>` 才正確 resolve 下一個 sortable target — 但 v15.0\n // path B 已 explicit 砍 SortableContext 改用 useDraggable+useDroppable(line 21),\n // 此 getter 在無 context 下 keyboard nav 無法 reliable resolve target → keyboard\n // drag/reorder regression。Default getter(arrow-key Δ25px)在 useDraggable 場景是\n // dnd-kit canonical(`@dnd-kit/core/src/sensors/keyboard/defaults.ts` 預設行為)。\n const dndSensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 8 } }),\n useSensor(KeyboardSensor),\n )\n\n // **2026-05-06 v14.8 collision detection canonical(對齊 dnd-kit official best practice)**:\n // 從 closestCenter 換 `pointerWithin + rectIntersection` composite。\n // **Why**:closestCenter 永遠返回最近 droppable → over 永遠非 null → 釋放任何位置都觸發\n // onRowReorder 強制 reorder(user 報「拉動就強制 reorder 不能 snap back」)。\n // pointerWithin 要求 pointer 真在 droppable rect 內才返回 → release 在 gap 自然 over=null →\n // 不觸發 reorder → snap back 自然成立(對齊 Notion / TreeView 行為)。\n // rectIntersection fallback 給 keyboard sensor(無 pointer)。\n // 詳 .claude/references/drag-canonical.md。\n const sameParentCollisionDetection: CollisionDetection = React.useCallback((args) => {\n const activeId = args.active?.id != null ? String(args.active.id) : null\n if (!activeId) {\n const pointer = pointerWithin(args)\n return pointer.length > 0 ? pointer : rectIntersection(args)\n }\n // **v15.8 Bug 2 fix**(對齊 user「PRD-004 拉起儘管同位置放開後一定 reorder」):\n // 預設 dnd-kit `pointerWithin` 排除 active 自身,fallback `rectIntersection` 找最近\n // next row → cursor 仍在 source row 內 但 over=next row → reorder 觸發。\n // Fix:cursor 仍在 source row vertical range 內 → return [](no over → no indicator\n // → onDragEnd over=null → noop)。User 必須 cursor 真正離開 source row vertical 範圍\n // 才視為「想 reorder」,對齊 user 的「沒動就不該 reorder」直覺。\n const activeRect = args.active?.rect.current.initial\n const cursor = args.pointerCoordinates\n if (cursor && activeRect && cursor.y >= activeRect.top && cursor.y <= activeRect.bottom) {\n return []\n }\n const activeParent = parentMap.get(activeId)\n // 過濾 droppable container collection — 只保留 same parent siblings(且不含 active 本身)\n const filtered = args.droppableContainers.filter(c => {\n const cid = String(c.id)\n if (cid === activeId) return false\n const cParent = parentMap.get(cid)\n if (cParent === undefined) return false // 非 row droppable\n return cParent === activeParent\n })\n const filteredArgs = { ...args, droppableContainers: filtered }\n const pointer = pointerWithin(filteredArgs)\n if (pointer.length > 0) return pointer\n // **v15.8 fix**(virtualized list dnd-kit droppableRects stale issue):\n // virtualized rows position 由 virtualizer transform:translateY 動態套,但 dnd-kit\n // measure droppable 在 mount 瞬間(rows 還沒 transform → 全 rect at top=100)+ 不\n // re-measure(MeasuringStrategy.Always 沒效)→ stale rects → rectIntersection 永遠\n // 0 over。Fix:fallback 用 cursor.y 對 DOM querySelector 找 row whose live\n // boundingClientRect 包含 cursor.y(同 parent siblings,排除 active)。\n if (cursor) {\n // **codex P2 fix(2026-05-07)**:scope 到 active table root + 同時驗 X 邊界。\n // 之前 document-wide query + cursor.y-only match → 多 DataTable 同頁(side-by-side\n // panels with overlapping Y ranges)會把 cursor 不在當前 table 卻 Y 帶相同的 row\n // 認成 over,觸發錯誤 reorder indicator/commit。Fix:limit 到 tableRef.current 的\n // sortable rows + 同時驗 cursor 在 row's X bounds 內。\n const tableScope = tableRef.current ?? document\n const liveRows = Array.from(tableScope.querySelectorAll<HTMLElement>('[role=\"row\"][data-sortable-row-id]'))\n .filter(el => el.dataset.sortableRowId !== activeId)\n .filter(el => {\n const cParent = parentMap.get(el.dataset.sortableRowId ?? '')\n return cParent === activeParent\n })\n for (const el of liveRows) {\n const r = el.getBoundingClientRect()\n if (\n cursor.y >= r.top && cursor.y <= r.bottom &&\n cursor.x >= r.left && cursor.x <= r.right\n ) {\n const rowId = el.dataset.sortableRowId\n const cont = filtered.find(c => String(c.id) === rowId)\n if (cont) return [{ id: cont.id, data: { droppableContainer: cont, value: 0 } }]\n }\n }\n }\n return rectIntersection(filteredArgs)\n }, [parentMap])\n\n // 2026-05-06 v10 DragOverlay canonical:drag start 時 snapshot source row outerHTML(strip\n // absolute / transform / opacity / data-* + reset width to natural width)→ render in\n // DragOverlay portal。Source row scroll out-of-viewport unmount 也不影響(canvas 視覺已 detach)。\n // 移除 windowed sticky range extractor — 不再需要 mount-pin source row,DragOverlay decoupled。\n // Atlassian / dnd-kit canonical:「If your useDraggable items are within a virtualized list,\n // you will absolutely want to use a drag overlay, since the original drag source can unmount\n // while dragging as the virtualized container is scrolled.」(GitHub #1674 / docs/api-documentation/draggable/drag-overlay)\n const [dragOverlayHtml, setDragOverlayHtml] = React.useState<string | null>(null)\n const [dragOverlayWidth, setDragOverlayWidth] = React.useState<number | null>(null)\n // 2026-05-06 v11:column reorder 共用 drag overlay state — `dragType` 區分 row vs column\n // **v15.9 移除 dragType state**:之前用來條件套 row drag modifier,現在三 scenario\n // 都無 modifier(SSOT 一致),drag type 只在 handler 內部用 active.data.current.type 取即可。\n const [, setActiveDragColId] = React.useState<string | null>(null)\n const handleDragStart = React.useCallback((e: { active: { id: string | number; data: { current?: { type?: 'row' | 'column'; columnId?: string } } } }) => {\n const id = String(e.active.id)\n const type = e.active.data?.current?.type ?? 'row'\n setInvalidDropActive(false)\n // v15.3:drag 啟動清掉非 source row 的 data-hovered(避免其他 row 殘留 hover bg + drag button)。\n // **保留 source row 的 hover** — 對齊 Linear / Jira「source 維持 active 視覺」world-class canonical。\n if (type === 'row') {\n tableRef.current?.querySelectorAll<HTMLElement>('[data-hovered]').forEach((el) => {\n const rowId = el.dataset.sortableRowId\n if (rowId !== id) delete el.dataset.hovered\n })\n } else {\n tableRef.current?.querySelectorAll<HTMLElement>('[data-hovered]').forEach((el) => delete el.dataset.hovered)\n }\n if (type === 'column') {\n // Column drag:snapshot header cell visual,strip transform/inline-styles\n const colId = e.active.data?.current?.columnId ?? id\n setActiveDragColId(colId)\n const headerEl = document.querySelector<HTMLElement>(`[role=\"columnheader\"][data-column-id=\"${colId}\"]`)\n if (headerEl) {\n const clone = headerEl.cloneNode(true) as HTMLElement\n clone.style.position = 'static'\n clone.style.transform = 'none'\n clone.style.transition = 'none'\n clone.style.opacity = '1'\n clone.style.zIndex = ''\n clone.style.width = `${headerEl.offsetWidth}px`\n // Strip resize handle clone(避免重複疊在 overlay 上)\n clone.querySelectorAll('[role=\"separator\"][aria-orientation=\"vertical\"]').forEach(n => n.remove())\n setDragOverlayHtml(clone.outerHTML)\n setDragOverlayWidth(headerEl.offsetWidth)\n }\n } else {\n setActiveDragId(id)\n // **v15.4 SSOT**:reconstructFullRowGhost 跨 pinned 區域(left/center/right)\n // 重組完整 row ghost,確保 cursor 在 ghost 內部維持與 mousedown 時相對位置一致\n // (對齊 user directive「ghost 跟 cursor 維持固定相對位置」+ Linear / Notion / Jira)\n const ghost = reconstructFullRowGhost(id, tableRef.current)\n if (ghost) {\n setDragOverlayHtml(ghost.html)\n setDragOverlayWidth(ghost.width)\n }\n }\n }, [])\n\n // SSOT helpers `isReorderNoop` + `reconstructFullRowGhost` 已搬到 `lib/drag-visual.ts`\n // —— TreeView / DataTable row / DataTable column drag 三處 consumer 共享同一 invariant。\n\n const handleDragOver = React.useCallback((e: { active: { id: string | number; data?: { current?: { type?: 'row' | 'column' } } }; over: { id: string | number } | null }) => {\n const { active, over } = e\n if (!active) return\n if (!over) {\n // 無 valid same-parent over → invalid drop signal(配合 v2 cross-parent visual)\n if (!invalidRef.current) setInvalidDropActive(true)\n setDropIndicator(null)\n return\n }\n if (invalidRef.current) setInvalidDropActive(false)\n if (active.id === over.id) { setDropIndicator(null); return }\n // Drop indicator(2026-05-06 v14.6 row + column 統一 SSOT pattern):\n // 用 active vs over 在 sortable items 的相對位置判 before/after。\n // (Notion canonical:source 在 target 之前 → drop after / source 在 target 之後 → drop before)\n const dragType = active.data?.current?.type ?? 'row'\n if (dragType === 'column') {\n const activeIdx = reorderableColumnIdsRef.current.indexOf(String(active.id))\n const overIdx = reorderableColumnIdsRef.current.indexOf(String(over.id))\n if (activeIdx === -1 || overIdx === -1) { setDropIndicator(null); return }\n const side: 'before' | 'after' = activeIdx < overIdx ? 'after' : 'before'\n // **v15.3 noop suppress**:drop position 等同原位 → 不顯 indicator(對齊 handleDragEnd noop guard)\n if (isReorderNoop(activeIdx, overIdx, side)) { setDropIndicator(null); return }\n setDropIndicator({ id: String(over.id), side, type: 'column' })\n } else {\n // Row drag — 用 allRowIds 算位置(只 same-parent siblings,跨 parent collisionDetection 已過濾)\n const activeIdx = allRowIds.indexOf(String(active.id))\n const overIdx = allRowIds.indexOf(String(over.id))\n if (activeIdx === -1 || overIdx === -1) { setDropIndicator(null); return }\n const side: 'before' | 'after' = activeIdx < overIdx ? 'after' : 'before'\n if (isReorderNoop(activeIdx, overIdx, side)) { setDropIndicator(null); return }\n setDropIndicator({ id: String(over.id), side, type: 'row' })\n }\n }, [allRowIds, isReorderNoop])\n\n const handleDragCancel = React.useCallback(() => {\n setActiveDragId(null)\n setActiveDragColId(null)\n setInvalidDropActive(false)\n setDragOverlayHtml(null)\n setDragOverlayWidth(null)\n setDropIndicator(null)\n }, [])\n\n // Reorderable column ids(non-locked,non-system) — 用 TanStack runtime visible order\n // **v14.10 fix**:之前用 columnsWithSelection 的 declaration order,user 控的 columnOrder\n // state(tableOptions.state.columnOrder)被忽略 → side('before'/'after')算錯 → drop 落\n // 在錯誤位置(user 報「Stock 移不到 Category/Price 之間」root cause)。\n // 改用 `table.getVisibleLeafColumns()` 拿 live visual order(已套 columnPinning + columnOrder)。\n const reorderableColumnIds = React.useMemo(() => {\n return table.getVisibleLeafColumns()\n .map(c => c.id)\n .filter(id => id && !isSystemColumn(id))\n .filter(id => {\n const meta = table.getColumn(id)?.columnDef.meta as { locked?: boolean } | undefined\n return !meta?.locked\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [table, columnsWithSelection, tableOptions?.state?.columnOrder])\n // Sync ref(handleDragOver closure 抓不到最新 reorderableColumnIds)\n React.useEffect(() => { reorderableColumnIdsRef.current = reorderableColumnIds }, [reorderableColumnIds])\n\n const handleDragEnd = React.useCallback((e: DragEndEvent) => {\n const { active, over } = e\n const type = (active.data?.current as { type?: 'row' | 'column' } | undefined)?.type ?? 'row'\n setActiveDragId(null)\n setActiveDragColId(null)\n setInvalidDropActive(false)\n setDragOverlayHtml(null)\n setDragOverlayWidth(null)\n setDropIndicator(null)\n if (!over || active.id === over.id) return\n const sourceId = String(active.id)\n const targetId = String(over.id)\n\n if (type === 'column') {\n // Column reorder:用 reorderableColumnIds 算 before/after\n const oldIdx = reorderableColumnIds.indexOf(sourceId)\n const newIdx = reorderableColumnIds.indexOf(targetId)\n if (oldIdx === -1 || newIdx === -1) return\n const position: 'before' | 'after' = oldIdx < newIdx ? 'after' : 'before'\n // **v15.3 noop guard SSOT**(共用 isReorderNoop helper)\n if (isReorderNoop(oldIdx, newIdx, position)) return\n // 2026-05-12 Q1 fix(user 抓「column 一拉起來就一定要換位置」)— Material X / AG Grid\n // column reorder canonical:cursor 必須過 next column **50% midpoint** 才換,沒過 → snap back。\n // dnd-kit 預設 over=column-under-pointer 一拉到鄰格就 reorder。加 midpoint threshold 對齊\n // 世界級 column reorder UX。對齊 row drag noop SSOT(`isReorderNoop`)+ Material X\n // `columnReorder` midpoint canonical(https://mui.com/x/react-data-grid/column-ordering/)。\n const activeRect = active.rect.current.translated ?? active.rect.current.initial\n const overRect = over.rect\n if (activeRect && overRect) {\n const ghostCenter = activeRect.left + activeRect.width / 2\n const targetCenter = overRect.left + overRect.width / 2\n // Moving right(oldIdx < newIdx):ghost 必過 target center 才換\n if (oldIdx < newIdx && ghostCenter < targetCenter) return\n // Moving left(oldIdx > newIdx):ghost 必過 target center(從右側)才換\n if (oldIdx > newIdx && ghostCenter > targetCenter) return\n }\n onColumnReorder?.(sourceId, targetId, position)\n return\n }\n\n // Row reorder(原邏輯)\n if (parentMap.get(sourceId) !== parentMap.get(targetId)) return\n const parentId = parentMap.get(sourceId)\n const siblings = allRowIds.filter(id => parentMap.get(id) === parentId)\n const oldIdx = siblings.indexOf(sourceId)\n const newIdx = siblings.indexOf(targetId)\n if (oldIdx === -1 || newIdx === -1) return\n const position: 'before' | 'after' = oldIdx < newIdx ? 'after' : 'before'\n if (isReorderNoop(oldIdx, newIdx, position)) return\n onRowReorder?.(sourceId, targetId, position)\n }, [allRowIds, parentMap, onRowReorder, onColumnReorder, reorderableColumnIds, isReorderNoop])\n\n // 2026-05-06 v11:column reorder collision detection — drag column 時 droppable filter\n // 只保留 column id(避免 over 觸發 row);drag row 走 sameParent canonical。\n // v14.8:換 pointerWithin + rectIntersection composite(對齊 dnd-kit official canonical)\n // 解 user 報「ghost 出來但 indicator 沒 / 不能 reorder」snap-back 同類問題。\n const dndCollisionDetection: CollisionDetection = React.useCallback((args) => {\n const activeData = args.active?.data?.current as { type?: 'row' | 'column' } | undefined\n if (activeData?.type === 'column') {\n const filtered = args.droppableContainers.filter(c => {\n const cData = c.data?.current as { type?: 'row' | 'column' } | undefined\n return cData?.type === 'column' && c.id !== args.active?.id\n })\n const filteredArgs = { ...args, droppableContainers: filtered }\n const pointer = pointerWithin(filteredArgs)\n return pointer.length > 0 ? pointer : rectIntersection(filteredArgs)\n }\n return sameParentCollisionDetection(args)\n }, [sameParentCollisionDetection])\n\n const wrapWithDnd = (node: React.ReactNode): React.ReactNode => {\n if (!enableRowDrag && !enableColumnReorder) return node\n return (\n <DndContext\n sensors={dndSensors}\n // **v15.8 fix**:virtualized rows mount/unmount 期間 droppable rect cache stale →\n // rectIntersection 找不到 over → indicator/reorder 不 fire。改 `Always` 每次 collision\n // detection 都 re-measure droppables(SSOT 對齊 dnd-kit virtualized list canonical)。\n measuring={{ droppable: { strategy: MeasuringStrategy.Always } }}\n collisionDetection={dndCollisionDetection}\n // **v15.11 Ghost-cursor SSOT 復活**:\n // - `snapToCursorModifier`(drag-visual.ts):ghost top-left 永遠對齊 cursor 位置,\n // 保證「ghost 跟 cursor 維持初始 mousedown 時的相對位置」(M17 SSOT idea)。\n // v15.7 → v15.8 撤回原因是 `rectIntersection` collision 用 transform 後的\n // active.rect 找不到 over → 拖不動。v15.10 collision 改用 **DOM-based 直查\n // live row rects(忽略 active.rect)**,modifier 偏移 transform 不再影響\n // collision detection,可安全再用。\n // - 三 drag scenario(row / column / TreeView)現在都 ghost-跟-cursor 對齊,\n // user directive「ghost-cursor SSOT」一致。\n modifiers={[snapToCursorModifier]}\n onDragStart={handleDragStart}\n onDragOver={handleDragOver}\n onDragCancel={handleDragCancel}\n onDragEnd={handleDragEnd}\n >\n {/* v15.0 Path B:無 SortableContext(useDraggable + useDroppable 各自獨立,不需 sort context)。\n 無 auto-shift visual reorder — source 留原位,indicator 顯 drop preview。 */}\n {node}\n {/* DragOverlay portal — row 跟 column 都用同一個 overlay state(dragOverlayHtml /\n dragOverlayWidth),onDragStart 依 type 截不同 source DOM 寫入 state。 */}\n <DragOverlay dropAnimation={null}>\n {dragOverlayHtml ? (\n <div\n style={{ width: dragOverlayWidth ?? undefined }}\n className=\"bg-surface-raised shadow-[var(--elevation-200)] rounded-md border border-border pointer-events-none\"\n dangerouslySetInnerHTML={{ __html: dragOverlayHtml }}\n />\n ) : null}\n </DragOverlay>\n </DndContext>\n )\n }\n\n if (enabled && mode === 'single') {\n return (\n <RadioGroupPrimitive.Root\n value={selection[0] ?? ''}\n onValueChange={(v) => v && setSelection([v])}\n >\n {wrapWithDnd(tableContent)}\n </RadioGroupPrimitive.Root>\n )\n }\n return wrapWithDnd(tableContent)\n}\n\nexport const DataTable = React.forwardRef(DataTableInner) as <TData>(\n props: DataTableProps<TData> & { ref?: React.ForwardedRef<HTMLDivElement> }\n) => React.ReactElement\n\n// any-allow: generic-constrained forwardRef cannot set displayName through typed API without erasing generic\n;(DataTable as any).displayName = 'DataTable'\n// Story auto-compile metadata — Phase 1 mechanical migration(2026-04-24)\n// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs\nexport const dataTableMeta = {\n component: 'DataTable',\n family: null, // non-family composite / overlay / layout\n variants: {\n\n },\n sizes: {\n\n },\n states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],\n tokens: {\n bg: ['bg-muted', 'bg-neutral-hover', 'bg-surface'],\n fg: ['text-fg-muted', 'text-fg-secondary', 'text-foreground'],\n ring: [],\n },\n} as const\n\nexport { dataTableVariants }\n"],"names":["_a","_b","_c","XIcon","FilterIcon","pointer","oldIdx","newIdx","position"],"mappings":"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"}
|