@qijenchen/design-system 0.1.0-beta.145 → 0.1.0-beta.147
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/dist/components/Accordion/accordion.d.ts +1 -1
- package/dist/components/Accordion/accordion.d.ts.map +1 -1
- package/dist/components/Accordion/accordion.js +8 -3
- package/dist/components/Accordion/accordion.js.map +1 -1
- package/dist/components/AccountMenu/account-menu.d.ts.map +1 -1
- package/dist/components/AccountMenu/account-menu.js.map +1 -1
- package/dist/components/AgentPanel/agent-panel-fab.d.ts +7 -1
- package/dist/components/AgentPanel/agent-panel-fab.d.ts.map +1 -1
- package/dist/components/AgentPanel/agent-panel-fab.js +36 -14
- package/dist/components/AgentPanel/agent-panel-fab.js.map +1 -1
- package/dist/components/AgentPanel/agent-panel-logo.d.ts +3 -3
- package/dist/components/AgentPanel/agent-panel-logo.js.map +1 -1
- package/dist/components/AgentPanel/agent-panel.d.ts +1 -1
- package/dist/components/AgentPanel/agent-panel.d.ts.map +1 -1
- package/dist/components/AgentPanel/agent-panel.js +28 -22
- package/dist/components/AgentPanel/agent-panel.js.map +1 -1
- package/dist/components/AppShell/app-shell.d.ts +1 -1
- package/dist/components/AppShell/app-shell.js +1 -1
- package/dist/components/AppShell/app-shell.js.map +1 -1
- package/dist/components/Avatar/avatar.d.ts +95 -1
- package/dist/components/Avatar/avatar.d.ts.map +1 -1
- package/dist/components/Avatar/avatar.js +106 -15
- package/dist/components/Avatar/avatar.js.map +1 -1
- package/dist/components/Avatar/index.js +14 -2
- package/dist/components/Breadcrumb/breadcrumb.d.ts +4 -2
- package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js +2 -2
- package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -1
- package/dist/components/BulkActionBar/bulk-action-bar.js +27 -2
- package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
- package/dist/components/Button/button.d.ts +2 -2
- package/dist/components/Button/button.d.ts.map +1 -1
- package/dist/components/Button/button.js +118 -22
- package/dist/components/Button/button.js.map +1 -1
- package/dist/components/Calendar/calendar.d.ts +34 -10
- package/dist/components/Calendar/calendar.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.js +210 -36
- package/dist/components/Calendar/calendar.js.map +1 -1
- package/dist/components/Carousel/carousel.d.ts +1 -1
- package/dist/components/Carousel/carousel.d.ts.map +1 -1
- package/dist/components/Carousel/carousel.js +3 -2
- package/dist/components/Carousel/carousel.js.map +1 -1
- package/dist/components/Chart/chart.d.ts +1 -0
- package/dist/components/Chart/chart.d.ts.map +1 -1
- package/dist/components/Chart/chart.js +8 -0
- package/dist/components/Chart/chart.js.map +1 -1
- package/dist/components/Checkbox/checkbox.d.ts +1 -1
- package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox.js +10 -2
- package/dist/components/Checkbox/checkbox.js.map +1 -1
- package/dist/components/Chip/chip.d.ts +1 -1
- package/dist/components/Chip/chip.d.ts.map +1 -1
- package/dist/components/Chip/chip.js +4 -2
- package/dist/components/Chip/chip.js.map +1 -1
- package/dist/components/Combobox/combobox.d.ts +1 -1
- package/dist/components/Combobox/combobox.d.ts.map +1 -1
- package/dist/components/Combobox/combobox.js +37 -11
- package/dist/components/Combobox/combobox.js.map +1 -1
- package/dist/components/Command/command.d.ts +1 -1
- package/dist/components/Command/command.d.ts.map +1 -1
- package/dist/components/Command/command.js +106 -8
- package/dist/components/Command/command.js.map +1 -1
- package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
- package/dist/components/DataTable/cell-registry.js +3 -2
- package/dist/components/DataTable/cell-registry.js.map +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.js +24 -24
- package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.d.ts +2 -1
- package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.js +3 -4
- package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
- package/dist/components/DataTable/data-table-sort-manager.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-sort-manager.js +20 -20
- package/dist/components/DataTable/data-table-sort-manager.js.map +1 -1
- package/dist/components/DataTable/data-table.d.ts +8 -5
- package/dist/components/DataTable/data-table.d.ts.map +1 -1
- package/dist/components/DataTable/data-table.js +197 -71
- package/dist/components/DataTable/data-table.js.map +1 -1
- package/dist/components/DateGrid/date-grid.d.ts +1 -1
- package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
- package/dist/components/DateGrid/date-grid.js +358 -225
- package/dist/components/DateGrid/date-grid.js.map +1 -1
- package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
- package/dist/components/DatePicker/date-picker.js +16 -1
- package/dist/components/DatePicker/date-picker.js.map +1 -1
- package/dist/components/Dialog/dialog.d.ts.map +1 -1
- package/dist/components/Dialog/dialog.js +55 -43
- package/dist/components/Dialog/dialog.js.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu-keyboard.d.ts +86 -0
- package/dist/components/DropdownMenu/dropdown-menu-keyboard.d.ts.map +1 -0
- package/dist/components/DropdownMenu/dropdown-menu-keyboard.js +172 -0
- package/dist/components/DropdownMenu/dropdown-menu-keyboard.js.map +1 -0
- package/dist/components/DropdownMenu/dropdown-menu.d.ts +6 -1
- package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.js +50 -39
- package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
- package/dist/components/Field/field-context.d.ts +4 -0
- package/dist/components/Field/field-context.d.ts.map +1 -1
- package/dist/components/Field/field-context.js +1 -2
- package/dist/components/Field/field-context.js.map +1 -1
- package/dist/components/Field/field-edit-keys.d.ts +8 -0
- package/dist/components/Field/field-edit-keys.d.ts.map +1 -1
- package/dist/components/Field/field-edit-keys.js +3 -0
- package/dist/components/Field/field-edit-keys.js.map +1 -1
- package/dist/components/Field/field-wrapper.d.ts +18 -1
- package/dist/components/Field/field-wrapper.d.ts.map +1 -1
- package/dist/components/Field/field-wrapper.js +39 -10
- package/dist/components/Field/field-wrapper.js.map +1 -1
- package/dist/components/Field/field.d.ts +3 -2
- package/dist/components/Field/field.d.ts.map +1 -1
- package/dist/components/Field/field.js +2 -1
- package/dist/components/Field/field.js.map +1 -1
- package/dist/components/FileItem/file-item.d.ts +26 -2
- package/dist/components/FileItem/file-item.d.ts.map +1 -1
- package/dist/components/FileItem/file-item.js +82 -25
- package/dist/components/FileItem/file-item.js.map +1 -1
- package/dist/components/FileItem/index.js +4 -2
- package/dist/components/FileUpload/file-upload.d.ts +1 -1
- package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
- package/dist/components/FileUpload/file-upload.js +132 -55
- package/dist/components/FileUpload/file-upload.js.map +1 -1
- package/dist/components/FileViewer/file-viewer.d.ts +1 -1
- package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
- package/dist/components/FileViewer/file-viewer.js +9 -4
- package/dist/components/FileViewer/file-viewer.js.map +1 -1
- package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -1
- package/dist/components/InlineEdit/inline-edit.js +1 -1
- package/dist/components/InlineEdit/inline-edit.js.map +1 -1
- package/dist/components/Input/input.d.ts.map +1 -1
- package/dist/components/Input/input.js +6 -1
- package/dist/components/Input/input.js.map +1 -1
- package/dist/components/LinkInput/link-input.d.ts.map +1 -1
- package/dist/components/LinkInput/link-input.js +20 -4
- package/dist/components/LinkInput/link-input.js.map +1 -1
- package/dist/components/Notice/notice.js +1 -1
- package/dist/components/Notice/notice.js.map +1 -1
- package/dist/components/NumberInput/number-input.d.ts.map +1 -1
- package/dist/components/NumberInput/number-input.js +6 -1
- package/dist/components/NumberInput/number-input.js.map +1 -1
- package/dist/components/OverflowIndicator/index.js +2 -1
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts +19 -1
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.js +47 -27
- package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
- package/dist/components/Pagination/pagination.d.ts +1 -1
- package/dist/components/Pagination/pagination.js +1 -1
- package/dist/components/Pagination/pagination.js.map +1 -1
- package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts +7 -6
- package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts.map +1 -1
- package/dist/components/PeoplePicker/avatar-stack-overflow.js +6 -7
- package/dist/components/PeoplePicker/avatar-stack-overflow.js.map +1 -1
- package/dist/components/PeoplePicker/people-picker-helpers.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker-helpers.js +1 -1
- package/dist/components/PeoplePicker/people-picker-helpers.js.map +1 -1
- package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker.js +2 -2
- package/dist/components/PeoplePicker/people-picker.js.map +1 -1
- package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
- package/dist/components/PeoplePicker/person-display.js +26 -28
- package/dist/components/PeoplePicker/person-display.js.map +1 -1
- package/dist/components/ProfileCard/profile-card.d.ts.map +1 -1
- package/dist/components/ProfileCard/profile-card.js.map +1 -1
- package/dist/components/RadioGroup/radio-group.d.ts +1 -1
- package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
- package/dist/components/RadioGroup/radio-group.js +10 -4
- package/dist/components/RadioGroup/radio-group.js.map +1 -1
- package/dist/components/Rating/rating.d.ts +28 -6
- package/dist/components/Rating/rating.d.ts.map +1 -1
- package/dist/components/Rating/rating.js +97 -80
- package/dist/components/Rating/rating.js.map +1 -1
- package/dist/components/ScrollArea/scroll-area.d.ts +1 -1
- package/dist/components/ScrollArea/scroll-area.js +1 -1
- package/dist/components/ScrollArea/scroll-area.js.map +1 -1
- package/dist/components/SegmentedControl/segmented-control.d.ts +1 -1
- package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -1
- package/dist/components/SegmentedControl/segmented-control.js +3 -2
- package/dist/components/SegmentedControl/segmented-control.js.map +1 -1
- package/dist/components/Select/select.d.ts.map +1 -1
- package/dist/components/Select/select.js +15 -8
- package/dist/components/Select/select.js.map +1 -1
- package/dist/components/SelectMenu/index.js +2 -1
- package/dist/components/SelectMenu/index.js.map +1 -1
- package/dist/components/SelectMenu/select-menu-keyboard.d.ts +59 -0
- package/dist/components/SelectMenu/select-menu-keyboard.d.ts.map +1 -0
- package/dist/components/SelectMenu/select-menu-keyboard.js +107 -0
- package/dist/components/SelectMenu/select-menu-keyboard.js.map +1 -0
- package/dist/components/SelectMenu/select-menu.d.ts +1 -22
- package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
- package/dist/components/SelectMenu/select-menu.js +18 -34
- package/dist/components/SelectMenu/select-menu.js.map +1 -1
- package/dist/components/SelectionControl/selection-item.d.ts.map +1 -1
- package/dist/components/SelectionControl/selection-item.js +1 -0
- package/dist/components/SelectionControl/selection-item.js.map +1 -1
- package/dist/components/Sidebar/sidebar.d.ts +7 -9
- package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
- package/dist/components/Sidebar/sidebar.js +171 -50
- package/dist/components/Sidebar/sidebar.js.map +1 -1
- package/dist/components/Slider/slider.d.ts +1 -1
- package/dist/components/Slider/slider.d.ts.map +1 -1
- package/dist/components/Slider/slider.js +9 -4
- package/dist/components/Slider/slider.js.map +1 -1
- package/dist/components/Steps/steps.d.ts.map +1 -1
- package/dist/components/Steps/steps.js +54 -26
- package/dist/components/Steps/steps.js.map +1 -1
- package/dist/components/Switch/switch.d.ts +1 -1
- package/dist/components/Switch/switch.d.ts.map +1 -1
- package/dist/components/Switch/switch.js +7 -2
- package/dist/components/Switch/switch.js.map +1 -1
- package/dist/components/Tabs/tabs.d.ts +1 -1
- package/dist/components/Tabs/tabs.d.ts.map +1 -1
- package/dist/components/Tabs/tabs.js +39 -4
- package/dist/components/Tabs/tabs.js.map +1 -1
- package/dist/components/Tag/tag.d.ts +1 -1
- package/dist/components/Tag/tag.d.ts.map +1 -1
- package/dist/components/Tag/tag.js +3 -2
- package/dist/components/Tag/tag.js.map +1 -1
- package/dist/components/Textarea/textarea.d.ts.map +1 -1
- package/dist/components/Textarea/textarea.js +8 -2
- package/dist/components/Textarea/textarea.js.map +1 -1
- package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
- package/dist/components/TimePicker/time-columns.js +8 -4
- package/dist/components/TimePicker/time-columns.js.map +1 -1
- package/dist/components/TimePicker/time-picker.d.ts +1 -1
- package/dist/components/TimePicker/time-picker.js +1 -1
- package/dist/components/TimePicker/time-picker.js.map +1 -1
- package/dist/components/TreeView/tree-view.d.ts +9 -5
- package/dist/components/TreeView/tree-view.d.ts.map +1 -1
- package/dist/components/TreeView/tree-view.js +266 -214
- package/dist/components/TreeView/tree-view.js.map +1 -1
- package/dist/hooks/use-input-modality.d.ts +12 -17
- package/dist/hooks/use-input-modality.d.ts.map +1 -1
- package/dist/hooks/use-input-modality.js +4 -34
- package/dist/hooks/use-input-modality.js.map +1 -1
- package/dist/hooks/use-overflow-items.d.ts.map +1 -1
- package/dist/hooks/use-overflow-items.js +2 -0
- package/dist/hooks/use-overflow-items.js.map +1 -1
- package/dist/hooks/use-truncated.d.ts.map +1 -1
- package/dist/hooks/use-truncated.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/drag-announcements.d.ts +32 -0
- package/dist/lib/drag-announcements.d.ts.map +1 -1
- package/dist/lib/drag-announcements.js +39 -1
- package/dist/lib/drag-announcements.js.map +1 -1
- package/dist/lib/focus-after-trigger.d.ts +45 -0
- package/dist/lib/focus-after-trigger.d.ts.map +1 -0
- package/dist/lib/focus-after-trigger.js +66 -0
- package/dist/lib/focus-after-trigger.js.map +1 -0
- package/dist/lib/overlay-coexistence.js +1 -1
- package/dist/lib/roving-list-keyboard.d.ts +208 -0
- package/dist/lib/roving-list-keyboard.d.ts.map +1 -0
- package/dist/lib/roving-list-keyboard.js +174 -0
- package/dist/lib/roving-list-keyboard.js.map +1 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +6 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.d.ts +4 -4
- package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.js +14 -4
- package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
- package/dist/patterns/horizontal-overflow/horizontal-overflow.d.ts.map +1 -1
- package/dist/patterns/horizontal-overflow/horizontal-overflow.js +25 -0
- package/dist/patterns/horizontal-overflow/horizontal-overflow.js.map +1 -1
- package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -1
- package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -1
- package/dist/tokens/categorical-color.d.ts +6 -1
- package/dist/tokens/categorical-color.d.ts.map +1 -1
- package/dist/tokens/categorical-color.js.map +1 -1
- package/dist/tokens/uiSize/icon-size.d.ts +1 -1
- package/dist/tokens/uiSize/stack-gap.d.ts +18 -0
- package/dist/tokens/uiSize/stack-gap.d.ts.map +1 -0
- package/dist/tokens/uiSize/stack-gap.js +5 -0
- package/dist/tokens/uiSize/stack-gap.js.map +1 -0
- package/ds-canonical/fork/codex/agents/skills/performance-audit/SKILL.md +1 -1
- package/ds-canonical/fork/codex/hooks.json +1 -1
- package/ds-canonical/fork/consumer/lock.json +17 -14
- package/ds-canonical/fork/consumer/managed-files/423729840acdd43c812f17c245b871716c6b60f76e4d3e94864d0e34a815bf8d.blob +9 -0
- package/ds-canonical/fork/consumer/managed-files/46f10bc55cdfdf834d0749eebff42ea0bb8576f361b36d2b6ba1851354c50150.blob +47 -9
- package/ds-canonical/fork/consumer/managed-files/5a0d134a2645114c8caac20458070b00a7f0fd55b3e8805b7325cb4cf52fa15e.blob +110 -0
- package/ds-canonical/fork/consumer/managed-files/5af0a46760af338d51fd0f7950675f8e97f7d2f09386b8818fcd7a58e6654e75.blob +790 -0
- package/ds-canonical/fork/consumer/managed-files/68bfcddff9c4a16388c248cd34fb66163e9e64b3d809a48ef3984f6ae4ff6d12.blob +211 -0
- package/ds-canonical/fork/consumer/managed-files/7eb6cc60abfdabaf6617c336058fad1454ccde08889295767bfd9b7fd153cc6e.blob +45 -6
- package/ds-canonical/fork/consumer/managed-files/92e4828cdcb96ff0d01daa16f6885f24045a8e72820665650f2a1890dc3a446c.blob +42 -2
- package/ds-canonical/fork/consumer/managed-files/ab072e7f2eca51f0e18a5e18c4b333260ee5d219a12cc6df5bb2d683f0b2734d.blob +27 -1
- package/ds-canonical/fork/consumer/managed-files/e71c65f45c6af7ce12b6b3c0d8028f185da5b719e2050c9b2a6b243d41ae4878.blob +62 -14
- package/ds-canonical/fork/governance.lock +41 -17
- package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +16 -4
- package/ds-canonical/fork/hooks/check_consumer_code_quality.sh +3 -1
- package/ds-canonical/fork/hooks/check_pattern_invariants.sh +13 -9
- package/ds-canonical/fork/launchers/settings-hooks.json +1 -1
- package/ds-canonical/fork/manifest.json +17 -11
- package/ds-canonical/fork/providers/claude/skills/performance-audit/SKILL.md +1 -1
- package/ds-canonical/fork/providers/codex/hook-config.json +1 -1
- package/ds-canonical/fork/providers/codex/skills/performance-audit/SKILL.md +1 -1
- package/ds-canonical/fork/skills/performance-audit/SKILL.md +1 -1
- package/ds-canonical/hooks/check_consumer_app_invariants.sh +16 -4
- package/ds-canonical/hooks/check_consumer_code_quality.sh +3 -1
- package/ds-canonical/hooks/check_datatable_invariants.sh +4 -1
- package/ds-canonical/hooks/check_pattern_invariants.sh +13 -9
- package/ds-canonical/hooks/check_plugin_fork_health.sh +8 -1
- package/ds-canonical/hooks/check_propose_discipline.sh +8 -1
- package/ds-canonical/hooks/check_storybook_addon_packaging.sh +8 -1
- package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +64 -2
- package/ds-canonical/hooks/lib/_overlay_handcraft.sh +5 -2
- package/ds-canonical/hooks/registrations.json +12 -7
- package/ds-canonical/hooks/session_start_governance_check.sh +16 -0
- package/ds-canonical/hooks/tests/test_check_consumer_app_invariants.sh +25 -0
- package/ds-canonical/hooks/tests/test_check_consumer_code_quality.sh +4 -0
- package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +14 -0
- package/ds-canonical/hooks/tests/test_check_datatable_invariants.sh +24 -0
- package/ds-canonical/hooks/tests/test_check_overlay_handcraft.sh +32 -0
- package/ds-canonical/hooks/tests/test_check_pattern_invariants.sh +59 -0
- package/ds-canonical/hooks/tests/test_check_plugin_fork_health.sh +32 -1
- package/ds-canonical/hooks/tests/test_check_propose_discipline.sh +21 -0
- package/ds-canonical/hooks/tests/test_check_storybook_addon_packaging.sh +21 -0
- package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +97 -0
- package/ds-canonical/hooks/tests/test_session_start_governance_check.sh +49 -0
- package/ds-canonical/references/README.md +12 -6
- package/ds-canonical/references/drag-canonical.md +3 -1
- package/ds-canonical/references/focus-canonical.md +26 -13
- package/ds-canonical/references/governance-audit-coverage.md +1 -1
- package/ds-canonical/references/hit-area-canonical.md +361 -0
- package/ds-canonical/references/item-anatomy-recipe.md +4 -2
- package/ds-canonical/references/keyboard-model-canonical.md +559 -0
- package/ds-canonical/rules/meta-patterns.md +4 -4
- package/ds-canonical/rules/self-verify.md +4 -4
- package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +1 -1
- package/ds-canonical/skills/design-system-audit/references/historical-bugs.md +96 -0
- package/ds-canonical/skills/knowledge-prune/SKILL.md +4 -1
- package/ds-canonical/skills/performance-audit/SKILL.md +1 -1
- package/ds-story-manifest.json +19 -7
- package/llms-full.txt +2 -2
- package/llms.txt +2 -2
- package/package.json +3 -1
- package/src/components/Accordion/accordion.anatomy.stories.tsx +3 -3
- package/src/components/Accordion/accordion.spec.md +1 -1
- package/src/components/Accordion/accordion.tsx +8 -3
- package/src/components/AccountMenu/account-menu.spec.md +2 -3
- package/src/components/AccountMenu/account-menu.tsx +0 -1
- package/src/components/AgentPanel/agent-decision-card.spec.md +88 -0
- package/src/components/AgentPanel/agent-panel-fab.spec.md +151 -0
- package/src/components/AgentPanel/agent-panel-fab.tsx +67 -24
- package/src/components/AgentPanel/agent-panel-logo.spec.md +87 -0
- package/src/components/AgentPanel/agent-panel-logo.tsx +3 -3
- package/src/components/AgentPanel/agent-panel.anatomy.stories.tsx +1 -1
- package/src/components/AgentPanel/agent-panel.principles.stories.tsx +1 -1
- package/src/components/AgentPanel/agent-panel.spec.md +30 -275
- package/src/components/AgentPanel/agent-panel.stories.tsx +113 -8
- package/src/components/AgentPanel/agent-panel.tsx +59 -22
- package/src/components/Alert/alert.anatomy.stories.tsx +1 -1
- package/src/components/AppShell/app-shell.tsx +1 -1
- package/src/components/AspectRatio/aspect-ratio.anatomy.stories.tsx +10 -15
- package/src/components/Avatar/avatar.anatomy.stories.tsx +23 -26
- package/src/components/Avatar/avatar.principles.stories.tsx +10 -10
- package/src/components/Avatar/avatar.spec.md +45 -6
- package/src/components/Avatar/avatar.stories.tsx +8 -8
- package/src/components/Avatar/avatar.tsx +227 -21
- package/src/components/Badge/badge.anatomy.stories.tsx +16 -21
- package/src/components/Breadcrumb/breadcrumb.anatomy.stories.tsx +3 -3
- package/src/components/Breadcrumb/breadcrumb.spec.md +3 -3
- package/src/components/Breadcrumb/breadcrumb.tsx +5 -3
- package/src/components/BulkActionBar/bulk-action-bar.anatomy.stories.tsx +1 -1
- package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +1 -1
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +1 -0
- package/src/components/BulkActionBar/bulk-action-bar.stories.tsx +57 -2
- package/src/components/BulkActionBar/bulk-action-bar.tsx +32 -2
- package/src/components/Button/button.anatomy.stories.tsx +174 -33
- package/src/components/Button/button.spec.md +23 -8
- package/src/components/Button/button.tsx +116 -21
- package/src/components/Calendar/calendar.anatomy.stories.tsx +34 -11
- package/src/components/Calendar/calendar.principles.stories.tsx +44 -1
- package/src/components/Calendar/calendar.spec.md +97 -20
- package/src/components/Calendar/calendar.stories.tsx +101 -4
- package/src/components/Calendar/calendar.tsx +379 -74
- package/src/components/Carousel/carousel.anatomy.stories.tsx +16 -17
- package/src/components/Carousel/carousel.spec.md +48 -2
- package/src/components/Carousel/carousel.tsx +9 -3
- package/src/components/Chart/chart.anatomy.stories.tsx +7 -5
- package/src/components/Chart/chart.spec.md +32 -7
- package/src/components/Chart/chart.tsx +9 -0
- package/src/components/Checkbox/checkbox.anatomy.stories.tsx +21 -28
- package/src/components/Checkbox/checkbox.spec.md +4 -2
- package/src/components/Checkbox/checkbox.tsx +10 -2
- package/src/components/Chip/chip.anatomy.stories.tsx +1 -1
- package/src/components/Chip/chip.spec.md +2 -1
- package/src/components/Chip/chip.tsx +4 -2
- package/src/components/Combobox/combobox.anatomy.stories.tsx +30 -37
- package/src/components/Combobox/combobox.spec.md +11 -3
- package/src/components/Combobox/combobox.tsx +43 -12
- package/src/components/Command/command.spec.md +11 -0
- package/src/components/Command/command.tsx +143 -10
- package/src/components/DataTable/cell-registry.tsx +5 -1
- package/src/components/DataTable/data-table-column-visibility-panel.tsx +5 -6
- package/src/components/DataTable/data-table-interaction-layer.tsx +27 -14
- package/src/components/DataTable/data-table-known-defects.spec.md +72 -0
- package/src/components/DataTable/data-table-scroll-performance.spec.md +295 -0
- package/src/components/DataTable/data-table-sort-manager.tsx +5 -6
- package/src/components/DataTable/data-table.anatomy.stories.tsx +1 -1
- package/src/components/DataTable/data-table.css +64 -0
- package/src/components/DataTable/data-table.spec.md +70 -346
- package/src/components/DataTable/data-table.stories.tsx +56 -9
- package/src/components/DataTable/data-table.tsx +392 -103
- package/src/components/DateGrid/date-grid.anatomy.stories.tsx +2 -2
- package/src/components/DateGrid/date-grid.spec.md +163 -1
- package/src/components/DateGrid/date-grid.tsx +270 -7
- package/src/components/DatePicker/date-picker.anatomy.stories.tsx +18 -27
- package/src/components/DatePicker/date-picker.spec.md +6 -2
- package/src/components/DatePicker/date-picker.tsx +20 -1
- package/src/components/Dialog/dialog.spec.md +6 -2
- package/src/components/Dialog/dialog.stories.tsx +18 -9
- package/src/components/Dialog/dialog.tsx +83 -48
- package/src/components/DropdownMenu/dropdown-menu-keyboard.ts +255 -0
- package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +32 -33
- package/src/components/DropdownMenu/dropdown-menu.spec.md +18 -5
- package/src/components/DropdownMenu/dropdown-menu.stories.tsx +58 -1
- package/src/components/DropdownMenu/dropdown-menu.tsx +70 -33
- package/src/components/Empty/empty.spec.md +1 -2
- package/src/components/Field/field-context.ts +9 -4
- package/src/components/Field/field-controls.spec.md +5 -2
- package/src/components/Field/field-edit-keys.ts +12 -0
- package/src/components/Field/field-wrapper.tsx +76 -10
- package/src/components/Field/field.anatomy.stories.tsx +1 -1
- package/src/components/Field/field.spec.md +11 -6
- package/src/components/Field/field.stories.tsx +24 -1
- package/src/components/Field/field.tsx +10 -4
- package/src/components/FileItem/file-item.anatomy.stories.tsx +20 -10
- package/src/components/FileItem/file-item.principles.stories.tsx +14 -7
- package/src/components/FileItem/file-item.spec.md +50 -48
- package/src/components/FileItem/file-item.stories.tsx +41 -28
- package/src/components/FileItem/file-item.tsx +184 -50
- package/src/components/FileUpload/file-upload.anatomy.stories.tsx +11 -15
- package/src/components/FileUpload/file-upload.spec.md +27 -1
- package/src/components/FileUpload/file-upload.stories.tsx +33 -0
- package/src/components/FileUpload/file-upload.tsx +173 -43
- package/src/components/FileViewer/file-viewer.tsx +9 -4
- package/src/components/HoverCard/hover-card.stories.tsx +2 -2
- package/src/components/InlineEdit/inline-edit.spec.md +2 -0
- package/src/components/InlineEdit/inline-edit.tsx +8 -3
- package/src/components/Input/input.anatomy.stories.tsx +23 -31
- package/src/components/Input/input.spec.md +11 -0
- package/src/components/Input/input.tsx +6 -1
- package/src/components/LinkInput/link-input.anatomy.stories.tsx +18 -21
- package/src/components/LinkInput/link-input.principles.stories.tsx +4 -4
- package/src/components/LinkInput/link-input.spec.md +12 -1
- package/src/components/LinkInput/link-input.tsx +37 -4
- package/src/components/Menu/menu-item.anatomy.stories.tsx +50 -56
- package/src/components/Menu/menu-item.spec.md +1 -1
- package/src/components/Menu/menu-item.stories.tsx +48 -42
- package/src/components/Notice/notice.anatomy.stories.tsx +8 -16
- package/src/components/Notice/notice.spec.md +1 -1
- package/src/components/Notice/notice.tsx +1 -1
- package/src/components/NumberInput/number-input.anatomy.stories.tsx +21 -28
- package/src/components/NumberInput/number-input.spec.md +2 -0
- package/src/components/NumberInput/number-input.tsx +8 -1
- package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +28 -48
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +13 -1
- package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +12 -9
- package/src/components/OverflowIndicator/overflow-indicator.tsx +32 -12
- package/src/components/Pagination/pagination.spec.md +1 -0
- package/src/components/Pagination/pagination.tsx +1 -1
- package/src/components/PeoplePicker/avatar-stack-overflow.ts +14 -13
- package/src/components/PeoplePicker/people-picker-helpers.ts +5 -2
- package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +1 -1
- package/src/components/PeoplePicker/people-picker.spec.md +4 -2
- package/src/components/PeoplePicker/people-picker.tsx +1 -4
- package/src/components/PeoplePicker/person-display.tsx +45 -28
- package/src/components/Popover/popover.anatomy.stories.tsx +1 -1
- package/src/components/Popover/popover.principles.stories.tsx +3 -12
- package/src/components/Popover/popover.spec.md +7 -3
- package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +1 -1
- package/src/components/ProfileCard/profile-card.spec.md +1 -1
- package/src/components/ProfileCard/profile-card.tsx +0 -3
- package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +11 -21
- package/src/components/ProgressBar/progress-bar.spec.md +1 -1
- package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +17 -24
- package/src/components/RadioGroup/radio-group.spec.md +1 -1
- package/src/components/RadioGroup/radio-group.tsx +22 -4
- package/src/components/Rating/rating.anatomy.stories.tsx +131 -124
- package/src/components/Rating/rating.principles.stories.tsx +69 -43
- package/src/components/Rating/rating.spec.md +142 -63
- package/src/components/Rating/rating.stories.tsx +11 -15
- package/src/components/Rating/rating.tsx +131 -117
- package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.principles.stories.tsx +6 -3
- package/src/components/ScrollArea/scroll-area.spec.md +3 -1
- package/src/components/ScrollArea/scroll-area.stories.tsx +5 -2
- package/src/components/ScrollArea/scroll-area.tsx +1 -1
- package/src/components/SegmentedControl/segmented-control.anatomy.stories.tsx +1 -1
- package/src/components/SegmentedControl/segmented-control.spec.md +2 -2
- package/src/components/SegmentedControl/segmented-control.tsx +3 -2
- package/src/components/Select/select.anatomy.stories.tsx +26 -35
- package/src/components/Select/select.spec.md +4 -3
- package/src/components/Select/select.tsx +11 -4
- package/src/components/SelectMenu/select-menu-keyboard.ts +218 -0
- package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +6 -17
- package/src/components/SelectMenu/select-menu.spec.md +12 -4
- package/src/components/SelectMenu/select-menu.tsx +21 -56
- package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +9 -33
- package/src/components/SelectionControl/selection-item.spec.md +2 -2
- package/src/components/SelectionControl/selection-item.tsx +3 -1
- package/src/components/Separator/separator.stories.tsx +4 -4
- package/src/components/Sheet/sheet.principles.stories.tsx +31 -13
- package/src/components/Sidebar/sidebar.anatomy.stories.tsx +1 -1
- package/src/components/Sidebar/sidebar.spec.md +73 -6
- package/src/components/Sidebar/sidebar.stories.tsx +82 -4
- package/src/components/Sidebar/sidebar.tsx +281 -64
- package/src/components/Skeleton/skeleton.spec.md +1 -1
- package/src/components/Slider/slider.anatomy.stories.tsx +1 -1
- package/src/components/Slider/slider.spec.md +6 -5
- package/src/components/Slider/slider.tsx +13 -8
- package/src/components/Steps/steps-state-visuals.spec.md +157 -0
- package/src/components/Steps/steps.anatomy.stories.tsx +1 -0
- package/src/components/Steps/steps.spec.md +59 -142
- package/src/components/Steps/steps.stories.tsx +1 -1
- package/src/components/Steps/steps.tsx +125 -33
- package/src/components/Switch/switch.spec.md +3 -3
- package/src/components/Switch/switch.tsx +6 -1
- package/src/components/Tabs/tabs.spec.md +5 -1
- package/src/components/Tabs/tabs.tsx +42 -3
- package/src/components/Tag/tag.anatomy.stories.tsx +24 -28
- package/src/components/Tag/tag.spec.md +10 -11
- package/src/components/Tag/tag.tsx +3 -3
- package/src/components/Textarea/textarea.tsx +7 -1
- package/src/components/TimePicker/time-columns.tsx +9 -4
- package/src/components/TimePicker/time-picker.spec.md +4 -1
- package/src/components/TimePicker/time-picker.tsx +1 -1
- package/src/components/Tooltip/tooltip.anatomy.stories.tsx +6 -15
- package/src/components/Tooltip/tooltip.principles.stories.tsx +4 -16
- package/src/components/Tooltip/tooltip.spec.md +2 -1
- package/src/components/TreeView/tree-view.anatomy.stories.tsx +35 -13
- package/src/components/TreeView/tree-view.spec.md +67 -38
- package/src/components/TreeView/tree-view.stories.tsx +221 -12
- package/src/components/TreeView/tree-view.tsx +463 -356
- package/src/hooks/use-input-modality.ts +17 -46
- package/src/hooks/use-overflow-items.ts +4 -0
- package/src/hooks/use-truncated.ts +3 -2
- package/src/index.ts +17 -0
- package/src/lib/README.md +2 -0
- package/src/lib/drag-announcements.ts +78 -0
- package/src/lib/focus-after-trigger.ts +102 -0
- package/src/lib/roving-list-keyboard.ts +400 -0
- package/src/lib/utils.ts +5 -0
- package/src/patterns/action-bar/action-bar.spec.md +2 -0
- package/src/patterns/element-anatomy/inline-action.spec.md +16 -12
- package/src/patterns/element-anatomy/item-anatomy.spec.md +98 -6
- package/src/patterns/element-anatomy/item-anatomy.stories.tsx +75 -70
- package/src/patterns/element-anatomy/item-anatomy.tsx +17 -6
- package/src/patterns/element-anatomy/truncated-text.spec.md +1 -0
- package/src/patterns/header-canonical/header-canonical.spec.md +3 -2
- package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +2 -0
- package/src/patterns/horizontal-overflow/horizontal-overflow.stories.tsx +36 -0
- package/src/patterns/horizontal-overflow/horizontal-overflow.tsx +28 -0
- package/src/patterns/overlay-surface/overlay-chrome-sizing.spec.md +180 -0
- package/src/patterns/overlay-surface/overlay-surface.spec.md +8 -162
- package/src/patterns/overlay-surface/overlay-surface.tsx +5 -3
- package/src/patterns/resize-handle/resize-handle.spec.md +3 -3
- package/src/styles/base.css +1 -1
- package/src/tokens/categorical-color.ts +6 -1
- package/src/tokens/color/color.spec.md +91 -24
- package/src/tokens/color/color.stories.tsx +50 -2
- package/src/tokens/color/primitives.css +41 -38
- package/src/tokens/color/semantic.css +105 -36
- package/src/tokens/layoutSpace/layoutSpace.spec.md +2 -0
- package/src/tokens/motion/motion.spec.md +31 -8
- package/src/tokens/orphan-tokens.spec.md +1 -1
- package/src/tokens/uiSize/icon-size.ts +1 -1
- package/src/tokens/uiSize/stack-gap.ts +17 -0
- package/src/tokens/uiSize/uiSize.css +12 -0
- package/src/tokens/uiSize/uiSize.spec.md +17 -16
- package/src/tokens/uiSize/uiSize.stories.tsx +1 -1
- package/dist/node_modules/aria-hidden/dist/es2015/index.js +0 -147
- package/dist/node_modules/aria-hidden/dist/es2015/index.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-panel.js","sources":["../../../src/components/AgentPanel/agent-panel.tsx"],"sourcesContent":["// code-quality-allow: file-size foundational composite family(9 元件一家族檔,同 Sidebar 前例)\n/**\n * AgentPanel 家族 — 智慧代理面板(9 元件;附屬資產 AgentLogo/AgentFab 另檔)。\n *\n * ── 消費的 SSOT ──\n * - 容器:右側欄=bg-surface + border-l border-divider(app-shell aside 前例);\n * 寬 --agent-panel-width(uiSize.css;可拖拉 360–640 且 ≤50vw,把手=ResizeHandle pattern,\n * 鍵盤等價=WAI-ARIA separator 同 DataTable 欄寬慣例);開合 --motion-duration-surface。\n * - 標題列:ChromeHeader(header-canonical;chrome 內控件一律 sm);品牌區=gap-2+24 標誌;\n * 標題+chevron=單一複合觸發鈕:**原生 `<button>`,不包 Button 殼**(Button 會多出左 9 / 右 5 內距\n * 與 28 高的懸停底,見 agent-panel.spec.md「禁用 Button 殼」);語意仍同 Polaris disclosure /\n * Combobox 觸發器,chevron=裝飾性指示(inline-action.spec.md Q1);\n * ButtonDivider 於 gap-2 cluster(action-bar 規則 3)。\n * **固定構件恆渲染**:+ / × / 標題觸發鈕不隨 callback 有無消失(2026-09-02 根因修正)。\n * - 歷史浮層:Popover+Command+MenuItem,列組裝逐字照 select-menu.tsx 原型(外層 CommandItem 單一\n * 互動 owner、內層 MenuItem role=presentation 透明、群組 heading、CommandSeparator、Empty);\n * 行內動作=ItemSuffix hoverReveal + ItemInlineAction(懸停/鍵盤 focus-visible 浮出);思考列=CircularProgress 16。\n * - 訊息:氣泡 bg-secondary/rounded-md/8/12;附件=Chip assist 分支(chip.spec.md),相互 4;\n * 輪距 40=8+24(Button text xs)+8。\n * - 思考塊:Radix Collapsible+animate-accordion(base.css;Sidebar 同法);chevron=accordion 慣例\n * (裝飾指示、色同 Select 觸發器 chevron);微光僅標題+最新行(agent-panel.css);完成步驟 fg-secondary。\n * - 輸入盒:欄位家族內距(--field-control-py-md/--field-px/text-body;32 等高鐵律);\n * 附件列=Tag md 單列 + OverflowIndicator(+N,useOverflowIndices 量測);送出/停止=Button primary xs。\n * - 決策卡:SurfaceHeader(compact)+SurfaceFooter(overlay-surface);選項=灰底卡(--secondary、\n * rounded-md、內距 8/12、整卡可點)包 RadioGroup md(Popover all-sm 律之拍板豁免;footer 鈕 sm 守律);\n * 一題一問步進(跳過 / 上一題 / 下一題 / 送出);N>1 才顯示「n / N」小標;淡入+下滑 --motion-duration-overlay。\n * - 改名/刪除:Dialog(header md+X;body Field+Input;footer md 鈕;刪除=primary+danger;\n * form-validation:儲存 dirty 規則、空名 blur 顯錯;Esc=Dialog 取消)。\n * - 空狀態:Empty icon slot 接 AgentLogo 招喚態。\n * 全表:agent-panel.spec.md。\n */\nimport * as React from 'react'\nimport * as CollapsiblePrimitive from '@radix-ui/react-collapsible'\nimport {\n createLucideIcon,\n ArrowUp,\n ChevronDown,\n Copy,\n MessageSquare,\n Pencil,\n Plus,\n ThumbsDown,\n ThumbsUp,\n Trash2,\n X as XIcon,\n} from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { useOverlayCoexistence, CoexistenceMask } from '@/design-system/lib/overlay-coexistence'\n\n/**\n * 停止實心正方:12/24 grid(= Material Symbols `stop` 480/960)→ 8px @ Button icon 16。\n * lucide Square 填滿後 20/24 = 13.3px,比 ArrowUp/Plus(14/24 線稿)視覺偏重,故自繪\n * (2026-09-02 user 抓「太巨大」;rx 1.5 ≈ Carbon 2/20、lucide 2/18 圓角比例)。\n */\nconst StopFilled = createLucideIcon('StopFilled', [\n ['rect', { x: '6', y: '6', width: '12', height: '12', rx: '1.5', fill: 'currentColor', stroke: 'none', key: 'stop' }],\n])\nimport { Button } from '@/design-system/components/Button/button'\nimport { ButtonDivider } from '@/design-system/components/Button/button-group'\nimport { ChromeHeader } from '@/design-system/patterns/header-canonical/chrome-header'\nimport { TruncatedText } from '@/design-system/patterns/element-anatomy/truncated-text'\nimport { fieldChromeStyles } from '@/design-system/components/Field/field-wrapper'\nimport {\n SurfaceHeader,\n SurfaceFooter,\n COMPACT_HEADER_SLOT,\n} from '@/design-system/patterns/overlay-surface/overlay-surface'\nimport {\n Popover,\n PopoverTrigger,\n PopoverContent,\n} from '@/design-system/components/Popover/popover'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/design-system/components/Command/command'\nimport { MenuItem } from '@/design-system/components/Menu/menu-item'\nimport {\n ItemInlineAction,\n ItemSuffix,\n} from '@/design-system/patterns/element-anatomy/item-anatomy'\nimport { ResizeHandle } from '@/design-system/patterns/resize-handle/resize-handle'\nimport { ICON_SIZE } from '@/design-system/tokens/uiSize/icon-size'\nimport { useOverflowIndices } from '@/design-system/patterns/horizontal-overflow/horizontal-overflow'\nimport { OverflowIndicator } from '@/design-system/components/OverflowIndicator/overflow-indicator'\nimport { CircularProgress } from '@/design-system/components/CircularProgress/circular-progress'\nimport { RadioGroup, RadioGroupItem } from '@/design-system/components/RadioGroup/radio-group'\nimport { Checkbox } from '@/design-system/components/Checkbox/checkbox'\nimport { CheckboxGroup } from '@/design-system/components/Checkbox/checkbox-group'\nimport { SelectionItem } from '@/design-system/components/SelectionControl/selection-item'\nimport { Chip } from '@/design-system/components/Chip/chip'\nimport { Tag } from '@/design-system/components/Tag/tag'\nimport { Input } from '@/design-system/components/Input/input'\nimport { Field, FieldLabel, FieldError } from '@/design-system/components/Field/field'\nimport {\n Dialog,\n DialogBody,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/design-system/components/Dialog/dialog'\nimport { ScrollArea } from '@/design-system/components/ScrollArea/scroll-area'\nimport { AgentLogo, type AgentLogoState } from './agent-panel-logo'\nimport './agent-panel.css'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 1. AgentPanel(容器;可拖拉寬度)\n * ──────────────────────────────────────────────────────────────────────── */\n\n/** 拖拉寬度界限(spec「AgentPanel」節;token 鏡像:--agent-panel-width-min / -max)。 */\nconst PANEL_WIDTH_DEFAULT = 400\nconst PANEL_WIDTH_MIN = 360\nconst PANEL_WIDTH_MAX = 640\nconst PANEL_RESIZE_KEY_STEP = 16\n\n/**\n * 並排時面板寬的上限,由**容器寬**推導。\n *\n * 三個已定的量互鎖(2026-09-07 G3):\n * 面板 ≥ 360(`PANEL_WIDTH_MIN`)\n * 面板 ≤ 舞台的 3/5(user 2026-09-07 裁示 #5:「50% 基準由視窗改舞台」定了「一半」;2026-09-09 放寬到 3/5,見下)\n * 並排時 舞台 = 容器 − 面板\n * 三條合起來:面板 ≤ (容器 − 面板) × 3/5 ⇒ **面板 ≤ 容器 × 3/8**。\n * 再套下限 360 ⇒ **並排只在容器 ≥ 960 時成立**;更窄就翻成蓋板(見 `resolveIsOverlay`)。\n * 2026-09-09 user 拍板「我覺得 960px 作為 agent 蓋板的斷點應該可以」:把 2026-09-07 的「面板 ≤ 舞台一半」放寬到 3/5(舞台 600 = Material\n * medium 視窗下緣、DataTable 5 欄各 120px),360 下限不動;原本三鎖的唯一解 1080 因此變成 960。\n *\n * 為什麼不是量視窗:面板住在容器裡,不是住在視窗裡。視窗 1920 但容器只有 800 的版面\n * (側欄 + 主內容 + 面板)用視窗算會給出 640 的上限,面板一寬舞台就被擠爆。\n *\n * clampPanelWidth 與 ResizeHandle 的 `max`(→ aria-valuemax)**必須讀同一個函式** ——\n * 2026-09-07 G5:先前 `max` 寫死 640,螢幕閱讀器念的數字與實際停的位置不一樣。\n */\nfunction resolvePanelWidthMax(containerPx: number) {\n // 還沒佈局(0)時不能拿去算,否則會鎖進最小值且不再復原(同 person-display 的 <=0 守衛)\n if (!containerPx || containerPx <= 0) return PANEL_WIDTH_MAX\n return Math.min(PANEL_WIDTH_MAX, Math.max(Math.floor(containerPx * 3 / 8), PANEL_WIDTH_MIN))\n}\n\n/** 容器窄到並排放不下(面板 360 之後舞台會不足面板兩倍)→ 翻成蓋板:覆蓋宿主、左留視窗內距、底下鋪遮罩。 */\nfunction resolveIsOverlay(containerPx: number) {\n if (!containerPx || containerPx <= 0) return false\n return containerPx < AGENT_PANEL_SIDE_BY_SIDE_MIN_CONTAINER\n}\n\n/**\n * 並排斷點:容器至少要這麼寬,面板才放得下且舞台仍有面板的 5/3(360 × 8/3 = 960)。\n * 匯出讓消費端可以用同一個數字排版,不必自己抄一個 960。\n */\nexport const AGENT_PANEL_SIDE_BY_SIDE_MIN_CONTAINER = Math.ceil(PANEL_WIDTH_MIN * 8 / 3)\n\n/** 面板形態:並排(flex 兄弟)或蓋板(absolute 覆蓋宿主、左留 `--layout-space-viewport-inset`);同時標在根節點 `data-agent-panel-mode`。 */\nexport type AgentPanelMode = 'side-by-side' | 'overlay'\n\nfunction clampPanelWidth(width: number, containerPx: number) {\n return Math.min(Math.max(width, PANEL_WIDTH_MIN), resolvePanelWidthMax(containerPx))\n}\n\nexport interface AgentPanelProps extends React.HTMLAttributes<HTMLDivElement> {\n /** 面板開合;false 時不渲染(關閉後由 AgentFab 承接入口,兩者互斥)。 */\n open?: boolean\n /** 受控寬度(px);省略=非受控,起於 defaultWidth。 */\n width?: number\n /** 非受控初始寬;預設 --agent-panel-width 400。 */\n defaultWidth?: number\n /** 寬度變更時回報(**拖曳中每一格都發**,受控 consumer 才有即時回饋)。 */\n onWidthChange?: (width: number) => void\n /** 拖拉放開 / 鍵盤一步結束時回報一次(要落地儲存的接這個;DS 不持久化,產品自存)。 */\n onWidthCommit?: (width: number) => void\n /** 可拖拉(左緣把手);預設 true。Sheet 承載時同樣可拖。 */\n resizable?: boolean\n /**\n * 蓋板態(容器 < 960,面板覆蓋宿主)仍要可用的節點 —— 與 Dialog 的 `persistentElements` 同一份契約、\n * 同一支 primitive(`lib/overlay-coexistence.ts`)。v14 條 B 說的「宿主暫不可操作」只講**宿主**;\n * 宿主之外的瀏覽器 chrome(網址列、上一頁 / 下一頁、重新整理)不是宿主,蓋板時不得被抑制\n * (2026-09-09 user:「範例變成滿版狀態時,上面那虛擬的網址列完全無法點擊」)。\n * 並排態不抑制任何東西,此 prop 無作用。面板自己永遠在保留集合裡,不必傳。\n */\n persistentElements?: () => Element[]\n /**\n * 形態(並排 / 蓋板)改變時回報;量到容器之後才發第一次,之後只在形態真的翻轉時發。\n * 用途:蓋板態下「代理內導向舞台的動作」(內部連結、有網址的 modal)要把代理收成入口鈕、讓舞台顯示目標\n * (v14 條 B,2026-09-09 user 推翻「抽屜保持開啟」的 AI 推導)。**面板不知道連結**,所以收合是消費端的責任:\n * 用這個回呼記住目前形態,在自己的內部導航裡「蓋板且開著 → `onOpenChange(false)`」;並排態不收。\n * 詳 spec「與 app 的推擠與斷點」蓋板小節。\n */\n onModeChange?: (mode: AgentPanelMode) => void\n /**\n * 蓋板態下**點擊面板外的遮罩**時通知消費端關閉面板(2026-09-17 user 裁示,取代 2026-09-16 的「點了不關」)。\n *\n * 命名依據 `ds-canonical/references/props-naming.md`:`onClose` = 「關閉 overlay session —— 浮層關閉回背景」,\n * 與 Dialog / Sheet / Popover / FileViewer 同一個名字同一個語意(不是 `onDismiss`,那是「暫時訊息被忽略」)。\n *\n * **面板不自己關**:`open` 一直是消費端控的(同 `onModeChange` 那段的分工),所以這裡只發通知。\n * 並排態沒有遮罩,此 prop 無作用。\n *\n * **必填,不是可選**(2026-09-18 修正):第一版寫成 `onClose?:`,理由是「向後相容,既有 consumer 一行都不用改」——\n * 結果就是**沒傳的那些照舊點了不關**,而全庫最像產品的那則範例(`agent-panel.stories.tsx` 的 URL 註冊表示意)剛好沒傳,\n * 於是使用者在預覽站上點遮罩「根本沒有任何反應」(2026-09-18 user 回報)。這正是本家族已經立過的規矩:\n * spec §2「固定 anatomy 恆渲染」與 M23(f)「可省略 callback ≠ 可省略行為 —— 無內建行為的 callback 一律必填 prop(型別層擋)」。\n * 面板自己關不了(`open` 住在 `AgentPanelDock`),所以它沒有內建 fallback → 必填。機械閘:`scripts/agent-panel-fixed-anatomy-invariant.mjs`。\n */\n onClose: () => void\n}\n\nconst AgentPanel = React.forwardRef<HTMLDivElement, AgentPanelProps>(\n (\n {\n open = true,\n onClose,\n width,\n defaultWidth = PANEL_WIDTH_DEFAULT,\n onWidthChange,\n onWidthCommit,\n resizable = true,\n persistentElements,\n onModeChange,\n className,\n style,\n children,\n ...props\n },\n ref,\n ) => {\n // 量**容器**(面板的父層)而不是視窗:面板住在容器裡。用 ResizeObserver 而不是\n // window resize —— 版面可能因為側欄收合、分頁切換而改變,那些都不會發 window resize。\n // aria-valuemax 也吃這個值(G5:先前寫死 640,螢幕閱讀器念的與實際停的位置不一樣)。\n const rootRef = React.useRef<HTMLDivElement | null>(null)\n const hostRef = React.useRef<HTMLElement | null>(null)\n const [containerPx, setContainerPx] = React.useState(0)\n const [selfVisible, setSelfVisible] = React.useState(false)\n React.useLayoutEffect(() => {\n // 往上找到**第一個有盒子的**祖先。直接抓 parentElement 會踩到兩種「沒有盒子」的包層:\n // `display: contents` —— AgentPanelDock 為了「關閉時不卸載」包的那層(2026-09-07 踩過)\n // `display: none` —— **同一個包層在面板關閉時的樣子**(2026-09-08 跨模型審查抓到)\n // 第一版只跳過 contents,於是「初始關閉 → 打開」這條路量到的是 display:none 那層,\n // clientWidth = 0 → `if (w > 0)` 永不觸發 → containerPx 卡在 0\n // → 上限永遠 640、蓋板永不觸發。實測 800px 容器仍並排 400px。\n // **這是 G2(keep-mounted)與 G3(容器斷點)互相踩到:兩支閘各自都綠,合起來才壞。**\n const resolveHost = () => {\n let node = rootRef.current?.parentElement ?? null\n while (node && (getComputedStyle(node).display === 'contents' || getComputedStyle(node).display === 'none')) {\n node = node.parentElement\n }\n return node\n }\n let host = resolveHost()\n let ro: ResizeObserver | null = null\n const measure = () => {\n // **每次都重新解析宿主**:面板從關閉變成開啟時,原本 `display: none` 的包層會變成\n // `contents`,真正的宿主因此改變。這個 effect 是空依賴、不會重跑,\n // 所以重綁只能發生在這裡 —— 否則打開之後永遠量著開啟前解析到的那個節點。\n const next = resolveHost()\n if (next !== host) {\n if (host && ro) ro.unobserve(host)\n host = next\n if (host && ro) ro.observe(host)\n }\n hostRef.current = host\n // 面板自己有沒有版面:Dock 關閉時是 display:none,那時**不能**保持整頁抑制(R3 反例:\n // 窄版 Panel 隱藏後背景仍 inert)。\n setSelfVisible((rootRef.current?.clientWidth ?? 0) > 0)\n const w = host?.clientWidth ?? 0\n // 沒有版面時量到的 0 不代表任何事,不拿去更新(同 person-display / AgentConversation)\n if (w > 0) setContainerPx(w)\n }\n ro = new ResizeObserver(measure)\n if (host) ro.observe(host)\n // 也觀察面板自己:它從隱藏變可見時尺寸 0 → N,藉此觸發上面的重綁。\n if (rootRef.current) ro.observe(rootRef.current)\n measure()\n return () => ro?.disconnect()\n }, [])\n const widthMax = resolvePanelWidthMax(containerPx)\n const isOverlay = resolveIsOverlay(containerPx)\n const mode: AgentPanelMode = isOverlay ? 'overlay' : 'side-by-side'\n // 形態回報:**量到容器才發**(containerPx 初值 0 會被 resolveIsOverlay 讀成蓋板,那不是形態、是還沒量);\n // 回呼走 ref,消費端傳 inline 箭頭函式也不會每次 render 重發。\n const onModeChangeRef = React.useRef(onModeChange)\n onModeChangeRef.current = onModeChange\n const measured = containerPx > 0\n React.useEffect(() => {\n if (measured) onModeChangeRef.current?.(mode)\n }, [mode, measured])\n\n // v14 條 B:「窄螢幕以抽屜覆蓋宿主(左留視窗內距、底下鋪遮罩),**宿主暫不可操作**」\n //(遮罩的點擊行為 2026-09-17 改為關閉面板,見下方 showScrim 與 `onClose`)。\n // 「覆蓋 + 遮罩」是視覺、「不可操作」是行為 —— 兩件事,只做前者的話鍵盤照樣走得進去。\n // 實測(2026-09-08 跨模型審查)蓋板態下宿主 20 個控件有 19 個仍可聚焦,Enter 會執行。\n //\n // 用共用的並存 primitive 而不是「對兄弟節點設 inert」:兄弟迴圈只涵蓋宿主 DOM 裡的節點,\n // **body portal 出去的浮層(Dialog / FileViewer)完全不在裡面** ——\n // 窄版時那個 modal 會既蓋在上面又可以操作,兩條都違反條 B。\n // `suppressOthers([面板])` 是「保留這一塊、其餘全部抑制」,portal 出去的也照樣被抑制。\n // 保留集合 = 面板自己 + 呼叫端指定的宿主外常駐區(瀏覽器 chrome 等;見 `persistentElements` 說明)。\n // 蓋板態的遮罩也在保留集合裡:它必須**接住**留白處的指標(不被 suppressOthers 設成 inert),否則點擊會穿過去\n // 打到底下 modal 的外部點擊偵測、把 modal 關掉(2026-09-16 user:「點擊露出的遮罩會關閉 agent panel 底下的 modal」)。\n // 它在算洞時不會把自己或別的遮罩當洞(overlay-coexistence.ts boxes():遮罩不是洞)。\n const scrimRef = React.useRef<HTMLDivElement | null>(null)\n const keepPanel = React.useCallback(\n () => [rootRef.current as Element | null, scrimRef.current as Element | null, ...(persistentElements?.() ?? [])].filter((el): el is Element => !!el),\n [persistentElements],\n )\n // **量到之前不要動手**:`containerPx` 初值是 0,而 `resolveIsOverlay(0)` 會回 true\n // (0 < 960)。若不加這個條件,面板一掛載就先把整頁(含同時開著的對話框)抑制掉,\n // 等量測回來才解除 —— 實測那一下足以讓對話框帶著 inert 卡住,框內按鈕永遠 focus 不進去。\n // 量到 0 本來就不代表任何事(同 measure 裡的 `if (w > 0)` 那條)。\n useOverlayCoexistence(containerPx > 0 && isOverlay && selfVisible, keepPanel)\n\n // Esc 的作用域封閉在焦點所在區(`agent-panel.spec.md:545` 三條表,2026-09-07 訂):\n // 焦點在面板內、面板內開著浮層 → 關那個最內層浮層,面板不動\n // 焦點在面板內、面板內沒有浮層 → **什麼都不關**\n // 焦點在面板外 → 關該區自己的浮層,**不跨區碰面板**\n // 但 Radix 的 `useEscapeKeydown` 在 **document 上用 capture** 監聽,\n // `dismissable-layer.tsx` 只把 Esc 送給「疊最上層」而**不看焦點在哪一區**。\n // 後果:舞台上開著 modal 時,在 agent 輸入框打字按 Esc 會關掉那個 modal —— 正是跨區。\n //\n // 攔法:掛在 **`window`** 的 capture 階段。捕獲順序是 window → document → …,\n // 所以它一定跑在 Radix 的 document capture 之前 —— 這是**結構上的先後**,\n // 不是「誰先註冊誰先跑」那種靠掛載順序的僥倖。\n // (第一版掛在 document 上,實測失敗:Dialog 在 JSX 裡排在面板前面,\n // 它的監聽先註冊、先跑、先 dismiss,我的 preventDefault 根本來不及。)\n // Radix 的 handler 寫著 `if (!event.defaultPrevented && onDismiss)` —— 看到已被\n // preventDefault 就不會 dismiss。不用 `stopImmediatePropagation`,那會連別人的合法處理一起吃掉。\n //\n // 會搶焦點的浮層(Popover / DropdownMenu / Dialog)因為焦點已經不在面板內,\n // 這裡不攔,它們照樣被自己的 layer 關掉 —— 那正是第一列要的行為。\n React.useEffect(() => {\n const onKeyDownCapture = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return\n const panel = rootRef.current\n const active = document.activeElement\n if (!panel || !active || !panel.contains(active)) return\n // 面板內若正開著 Tooltip(不搶焦點的浮層),這一下 Esc 該關它(spec:545 第一列),\n // 不能被我們吃掉 —— R3 實測 Tooltip 的 Esc 因此失效。\n if (document.querySelector('[role=\"tooltip\"]')) return\n event.preventDefault()\n }\n window.addEventListener('keydown', onKeyDownCapture, { capture: true })\n return () => window.removeEventListener('keydown', onKeyDownCapture, { capture: true })\n }, [])\n const [uncontrolledWidth, setUncontrolledWidth] = React.useState(defaultWidth)\n const resolvedWidth = clampPanelWidth(width ?? uncontrolledWidth, containerPx)\n\n const applyWidth = React.useCallback(\n (next: number, commit: boolean) => {\n const clamped = clampPanelWidth(next, containerPx)\n if (width === undefined) setUncontrolledWidth(clamped)\n // 每一格都發 onWidthChange:受控 consumer 才有拖曳中的即時回饋(原本只在放開時發 = 整段拖曳畫面不動);\n // 放開 / 鍵盤一步再發 onWidthCommit,要落地儲存的接這個。\n onWidthChange?.(clamped)\n if (commit) onWidthCommit?.(clamped)\n },\n [width, onWidthChange, onWidthCommit, containerPx],\n )\n\n if (!open) return null\n // 蓋板態的遮罩(2026-09-16 user:「底下會有滿版的遮罩,若點擊到該遮罩不會有任何反應…單純只是用來讓使用者知道 agent panel 底下還有東西」):\n // 重用 Dialog 並存時的同一支 `CoexistenceMask`(z-30、`--overlay`、替 persistentElements 挖洞),不手刻第二份遮罩(M17 / M23)。\n // - `absolute`:遮罩跟面板一樣覆蓋**容器**,不是視窗(spec「量的是容器不是視窗」;tailwind-merge 讓它覆掉預設的 `fixed`);\n // - 遮罩**接住**指標:點留白處 = 點到遮罩本身(→ `onClose`,見下)。第一版寫成 `pointer-events-none`,點擊穿過去\n // 打到底下並存 modal 的外部點擊偵測、把 modal 關掉(2026-09-16 user 第二次回報);所以它要在保留集合裡(不被設 inert)\n // 而且 Dialog 的並存遮罩算洞時把它當「遮罩不是洞」跳過(overlay-coexistence.ts `boxes()`),否則常駐殼裡多了一張全舞台的盒子,\n // Dialog 的遮罩會被整張挖空(2026-09-09 入口鈕裁切圖層的同款根因)。modal 的外部點擊守衛(createPersistentGuard)看到\n // 目標在保留區子樹裡就不關 —— 遮罩是常駐殼的子節點,自然在裡面。\n // - 只在量到容器且真的是蓋板時渲染(與 useOverlayCoexistence 的啟用條件同一組);\n // - 是面板根節點的**兄弟**不是子節點:根節點 z-[45] 自成堆疊脈絡,放進去遮罩就會壓過並存 modal(z-40),違反 dialog.spec 層級梯。\n // 幾何與「點遮罩關閉面板」由 `scripts/agent-panel-breakpoint.mjs` 機械守住;\n // 「`onClose` 必填、不得以 callback 有無當行為閘」由 `scripts/agent-panel-fixed-anatomy-invariant.mjs` 守住。\n const showScrim = containerPx > 0 && isOverlay && selfVisible\n return (\n <>\n {showScrim && (\n <CoexistenceMask\n ref={scrimRef}\n keep={keepPanel}\n data-agent-panel-scrim=\"\"\n // 點遮罩關面板(2026-09-17 user 裁示,取代 2026-09-16 的「點了不關」;兩條裁示逐字都在 spec 的來源總帳)。\n // 這一改讓它**回到** DS 既有的浮層語言:`../Dialog/dialog.spec.md`「Overlay click:點擊 overlay 關閉」、\n // 「洞外點下去是外部點擊 → 關閉(modal 語意)」—— 先前的「點了不關」才是那條線上的例外。\n // 並存 modal 時只關面板、modal 留著(2026-09-17 user 選 a 案):遮罩在面板的保留集合裡,\n // 並存 modal 的外部點擊守衛看到目標落在保留區子樹內就不關,所以並存邏輯一行都不用動;\n // 面板收掉後 modal 自然完整露出。鍵盤路徑不受影響(Esc 照舊)。\n onClick={onClose}\n className=\"absolute animate-in fade-in-0 duration-[var(--motion-duration-surface)] motion-reduce:animate-none\"\n />\n )}\n <div\n ref={(node) => {\n rootRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n }}\n role=\"complementary\"\n aria-label=\"智慧代理\" // i18n-allow: DS 預設,props 展開在後可覆寫\n // 蓋板態要讓 AT 知道它現在是蓋在內容上的一層,不是並排的一欄\n data-agent-panel-mode={mode}\n className={cn(\n 'relative flex h-full min-h-0 shrink-0 flex-col overflow-hidden bg-surface',\n // 2026-09-07 G3:容器窄到並排放不下(< 960;2026-09-09 由 1080 放寬)就翻成蓋板。\n // 2026-09-16 user 裁示:蓋板不再蓋滿 —— 上下右貼齊容器、左邊留 Dialog 同一顆 `--layout-space-viewport-inset`(48px),\n // 底下鋪遮罩讓人知道面板下面還有東西(遮罩見上方 showScrim)。「蓋滿」原是 v14 條 B 的字,同日改字(v14 來源總帳 2026-09-16)。\n // 用 absolute 而不是把宿主推走:蓋板本來就不該改變底下內容的版面,\n // 而且回到寬螢幕時宿主不需要重新排版(避免來回切換時內容跳動)。\n // z-[60] 而不是 z-20:v14 條 B 的推導第 4 題「窄螢幕,agent 點有 URL 的 Modal →\n // 宿主開啟 Modal;agent 抽屜保持開啟,**Modal 在被蓋住的宿主區**」——\n // modal 必須在 agent **後方**。Dialog 是 body portal 且 `z-50`(dialog.tsx:46/113),\n // 而這個面板的祖先是 `position:relative; z-index:auto`(不建立堆疊脈絡),\n // 所以它直接跟 z-50 比大小 —— 用 z-20 會反過來被 modal 蓋住(2026-09-08 實測)。\n // 兩者的大小關係由 `scripts/agent-panel-breakpoint.mjs` 機械守住,不靠這行註解。\n // z-[45]:高於**並存面**(Dialog/FileViewer 有 persistentElements 時 z-40 —— v14 推導第 4 題\n // 「窄螢幕,URL Modal 在被蓋住的宿主區」),低於**一般確認框**(z-50 —— 條 A「沒有 URL 的\n // Modal 阻擋其餘介面,包含 agent」)。第一版寫 z-[60] 把所有 Dialog 都壓在下面,\n // 連確認框也被面板蓋住(R3 實測),那是把「URL Modal 在後方」錯推成「所有 Dialog 在後方」。\n // 蓋板 = 遮蓋型浮層:底色與陰影跟 Sheet 同一組(sheet.tsx `bg-surface-raised shadow-[var(--elevation-200)]`)——\n // `--surface` 在深色模式是半透明(semantic.css「非遮蓋型容器」),蓋在宿主上會讓底下文字透出來;\n // `--elevation-300` 不存在(最高階 200),舊寫法等於沒有陰影、留白處看到的是硬切線(2026-09-16 驗證抓到)。\n isOverlay && 'absolute inset-y-0 right-0 left-[var(--layout-space-viewport-inset)] z-[45] bg-surface-raised shadow-[var(--elevation-200)]',\n // 分隔線只有一個 owner:可拖時由 ResizeHandle 的 1px line 擁有(DataTable 欄間同款,hover/拖曳會變色);\n // 不可拖才由容器畫 border-l(app-shell aside 前例)。兩者並存 = 2px 粗線(2026-09-02 user 抓到)。\n !resizable && !isOverlay && 'border-l border-divider',\n 'animate-in fade-in-0 slide-in-from-right-4 duration-[var(--motion-duration-surface)] motion-reduce:animate-none',\n className,\n )}\n // 蓋板態寬度 = 容器 − 左內距(由上面的 inset-y-0 / right-0 / left-[inset] 決定),不吃拖曳出來的值(拖曳把手在蓋板態也不渲染)\n style={{ ...(isOverlay ? null : { width: resolvedWidth }), ...style }}\n {...props}\n >\n {resizable && !isOverlay && (\n // 同一顆 ResizeHandle 擁有視覺 / 拖拉 / 鍵盤 / ARIA(DataTable 欄寬同元件,2026-09-02 SSOT 收斂);\n // 面板寬 clamp(360–640 且 ≤50vw)由 applyWidth 負責。\n <ResizeHandle\n direction=\"horizontal\"\n position=\"start\"\n value={resolvedWidth}\n min={PANEL_WIDTH_MIN}\n max={widthMax}\n step={PANEL_RESIZE_KEY_STEP}\n ariaLabel=\"調整面板寬度\" // i18n-allow: DS 預設文案\n className=\"z-10\"\n onValueChange={(next) => applyWidth(next, false)}\n onValueCommit={(next) => applyWidth(next, true)}\n />\n )}\n {children}\n </div>\n </>\n )\n },\n)\nAgentPanel.displayName = 'AgentPanel'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 2. AgentPanelHeader(標題列)+ 歷史浮層 / 改名 / 刪除\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentConversationSummary {\n id: string\n title: string\n /** 分組標題(如「今天」「過去 7 天」);同組相鄰排列。 */\n group?: string\n /** 代理仍在回覆:列首圖示原地換 CircularProgress 16,等寬等高不動版面。 */\n thinking?: boolean\n}\n\nexport interface AgentPanelHeaderProps\n extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {\n /** 目前對話標題(標題本身=歷史浮層觸發鈕)。 */\n title: string\n /** 歷史浮層搜尋 placeholder(i18n override)。 */\n historySearchPlaceholder?: string\n /** 歷史浮層無結果文案(i18n override)。 */\n historyEmptyText?: string\n /** 標誌狀態(代理思考中傳 \"think\")。 */\n logoState?: AgentLogoState\n /** 歷史對話清單;空清單=浮層顯示無結果(觸發鈕恆在)。 */\n conversations?: AgentConversationSummary[]\n /** 目前對話 id(歷史清單高亮)。 */\n activeConversationId?: string\n /** 目前對話尚無已送出訊息=本身就是新對話 → 「+ 新對話」停用。 */\n conversationEmpty?: boolean\n /** 歷史浮層初始開啟(展示/快照用;M15 OpenSnapshot)。 */\n defaultHistoryOpen?: boolean\n onSelectConversation?: (id: string) => void\n /** 改名確認(Dialog 流程由元件內建)。 */\n onRenameConversation?: (id: string, title: string) => void\n /**\n * 刪除確認(Dialog 流程由元件內建)。consumer 契約:刪的是目前對話 → 切到最近一則;\n * 全部刪光 → 面板回空狀態(spec「附:歷史浮層」)。\n */\n onDeleteConversation?: (id: string) => void\n /** 固定構件:+ 恆渲染,主流程無內建行為 → 必填。 */\n onNewConversation: () => void\n /** 固定構件:× 恆渲染,面板 open 是 consumer state → 必填。 */\n onClose: () => void\n}\n\n/** 歷史列(select-menu.tsx 原型):外層 CommandItem 單一互動 owner;內層 MenuItem 純視覺。 */\nfunction HistoryRow({\n conversation,\n selected,\n onSelect,\n onRename,\n onDelete,\n}: {\n conversation: AgentConversationSummary\n selected: boolean\n onSelect: () => void\n onRename: () => void\n onDelete: () => void\n}) {\n return (\n <CommandItem\n value={conversation.id}\n keywords={[conversation.title]}\n onSelect={onSelect}\n // 游標與選中的長相全部由 CommandItem 統一畫(指標模態底色 / 鍵盤模態畫框 / 選中底色釘住;\n // focus-canonical 規則二 + item-anatomy「選中 × 互動疊加」);本列只交 `selected`,不再手刻一份\n //(2026-09-09 之前這裡自己寫了一份 not-hover:focus-ring-inset,與 CommandItem 重複)。\n selected={selected}\n className=\"group/menu-item\"\n >\n <MenuItem\n labelMaxLines={1}\n role=\"presentation\"\n selected={selected}\n className=\"!bg-transparent hover:!bg-transparent\"\n startContent={\n conversation.thinking ? (\n <CircularProgress size={16} aria-label=\"回覆中\" /> // i18n-allow: DS 預設\n ) : (\n <MessageSquare size={16} aria-hidden className=\"text-fg-muted\" />\n )\n }\n endContent={\n // 行內動作恆在 DOM(鍵盤 Tab 可達);懸停/focus-visible 淡入=ItemSuffix hoverReveal SSOT。\n /* MenuItem 的 endContent slot 內再包 ItemSuffix 只為 hoverReveal(opacity 淡入);兩層同盒\n (h-[1lh] items-center ml-auto gap-2),不疊任何位移——非 drift(2026-09-02 覆核實測)。 */\n <ItemSuffix hoverReveal hoverGroup=\"menu-item\">\n {/* Enter/Space 在行內動作上 = 啟動該動作(stopPropagation 擋掉 cmdk 的 Enter=選列)。 */}\n <span\n className=\"contents\"\n onKeyDown={(e) => {\n const target = e.target as HTMLElement\n if ((e.key === 'Enter' || e.key === ' ') && target.closest('button')) {\n e.preventDefault()\n e.stopPropagation()\n target.closest('button')?.click()\n }\n }}\n >\n <ItemInlineAction\n action={{\n icon: Pencil,\n label: '改名', // i18n-allow: DS 預設文案(Dialog「關閉」同前例)\n onClick: (e) => {\n e?.stopPropagation()\n onRename()\n },\n }}\n />\n <ItemInlineAction\n action={{\n icon: Trash2,\n label: '刪除', // i18n-allow: DS 預設文案(Dialog「關閉」同前例)\n onClick: (e) => {\n e?.stopPropagation()\n onDelete()\n },\n }}\n />\n </span>\n </ItemSuffix>\n }\n >\n {conversation.title}\n </MenuItem>\n </CommandItem>\n )\n}\n\nconst AgentPanelHeader = React.forwardRef<HTMLElement, AgentPanelHeaderProps>(\n (\n {\n title,\n logoState = 'still',\n historySearchPlaceholder = '搜尋對話', // i18n-allow: DS 預設文案,prop 可覆寫\n historyEmptyText = '沒有對話', // i18n-allow: DS 預設文案(2026-09-08 一句到底,對應 No options;沒有對話與搜尋無結果共用),prop 可覆寫\n conversations = [],\n activeConversationId,\n conversationEmpty = false,\n defaultHistoryOpen = false,\n onSelectConversation,\n onRenameConversation,\n onDeleteConversation,\n onNewConversation,\n onClose,\n className,\n ...props\n },\n ref,\n ) => {\n const [historyOpen, setHistoryOpen] = React.useState(defaultHistoryOpen)\n const [renameTarget, setRenameTarget] = React.useState<AgentConversationSummary | null>(null)\n const [deleteTarget, setDeleteTarget] = React.useState<AgentConversationSummary | null>(null)\n const triggerRef = React.useRef<HTMLButtonElement>(null)\n /** Dialog 關閉後焦點回歷史觸發鈕(Popover 已因焦點外移關閉;WCAG 2.4.3)。 */\n // Dialog 關閉後焦點:歷史浮層仍開 → 交給 Radix 還原到觸發它的行內動作(改名/刪除);浮層已關\n // → 延到下一個 macrotask 回標題觸發(晚於 FocusScope 還原到已消失元素 → body 的動作,2026-09-02 實測)。\n const historyOpenRef = React.useRef(historyOpen)\n historyOpenRef.current = historyOpen\n // 觸發器失去版面時關掉歷史浮層(2026-09-10 實測兩條路徑):宿主用 display:none 收起 keep-mounted 的面板\n // (AgentPanelDock,路由切換 / 全域快捷鍵這類不經指標與焦點的關閉)、或 Storybook 把整頁 docs 藏起來 —— 浮層 portal 到 body\n // 不會跟著消失,Radix 對 0×0 的錨點會把它定位到視窗左上角 (0, 8),焦點還留在裡面。ResizeObserver 在元素變成\n // display:none 時會回報 0×0;掛上時的第一次回呼帶真實尺寸,可見的觸發器不會被誤關。\n React.useEffect(() => {\n const el = triggerRef.current\n if (!historyOpen || !el || typeof ResizeObserver === 'undefined') return\n const ro = new ResizeObserver(() => {\n if (el.getClientRects().length === 0) setHistoryOpen(false)\n })\n ro.observe(el)\n return () => ro.disconnect()\n }, [historyOpen])\n const returnFocus = () => {\n window.setTimeout(() => {\n if (historyOpenRef.current) return\n triggerRef.current?.focus({ preventScroll: true })\n }, 0)\n }\n\n const groups = React.useMemo(() => {\n const order: string[] = []\n const byGroup = new Map<string, AgentConversationSummary[]>()\n for (const item of conversations) {\n const key = item.group ?? ''\n if (!byGroup.has(key)) {\n byGroup.set(key, [])\n order.push(key)\n }\n byGroup.get(key)!.push(item)\n }\n return order.map((key) => ({ label: key, items: byGroup.get(key)! }))\n }, [conversations])\n\n // 標題群 ↔ 動作群 gap = loose(2026-09-02 user 拍板:chevron 與右側按鈕至少 --layout-space-loose;\n // ChromeHeader 預設 gap-2 是 slot 內間距,長標題截斷時 chevron 會貼到 28px 圖示鈕被讀成同一群)。\n return (\n <ChromeHeader ref={ref} className={cn('gap-[var(--layout-space-loose)] bg-surface', className)} {...props}>\n <div className=\"flex min-w-0 flex-1 items-center gap-2\">\n <AgentLogo state={logoState} size={24} />\n <Popover open={historyOpen} onOpenChange={setHistoryOpen}>\n <PopoverTrigger asChild>\n {/* 標題+chevron 複合觸發:幾何沿用品牌區前例(238cdf91:gap-2 / 零 padding);\n **chevron 是 20 不是 16** —— 標題是 text-body-lg,依「字級↔icon tier」對齊 ICON_SIZE.lg\n (見下方 ChevronDown 的註解與 spec「箭頭 20」);chevron 純指示、fg-muted 靜色、\n 無懸停底(同 AgentThinking 標題列);原生 button 承接 Radix Slot props。 */}\n <button\n ref={triggerRef}\n type=\"button\"\n aria-haspopup=\"dialog\"\n aria-expanded={historyOpen}\n className={cn(\n 'flex min-w-0 max-w-full cursor-pointer items-center gap-2 p-0 text-left',\n 'rounded-sm ',\n )}\n >\n {/* 單行截斷 → 截斷時才顯 tooltip 補全(tooltip.spec.md:32;引擎 truncated-text.spec.md),\n 禁手刻 truncate span。 */}\n <TruncatedText className=\"text-body-lg font-medium\">{title}</TruncatedText>\n {/* 指示 chevron 與 Select 觸發器逐字同款:同色 text-fg-muted、同線粗、同「字級↔icon tier」\n (標題 text-body-lg = Select lg → ICON_SIZE.lg 20)、開啟時 rotate-180。 */}\n <ChevronDown\n size={ICON_SIZE.lg}\n aria-hidden\n className={cn('shrink-0 text-fg-muted transition-transform motion-reduce:duration-0', historyOpen && 'rotate-180')}\n />\n </button>\n </PopoverTrigger>\n {/* 寬度 = Popover canonical w-72(288;popover.tsx 預設,不另訂):介於 ChatGPT 側欄 260 /\n Claude 側欄 290(2026-09-02 實測),且在面板最窄 360 時仍容得下(標題左緣起 312)。\n 與觸發點距 = OVERLAY_SIDE_OFFSET 8(elevation.spec.md)。 */}\n <PopoverContent\n align=\"start\"\n aria-label=\"歷史對話\" // i18n-allow: DS 預設文案\n className=\"overflow-hidden p-0\"\n >\n <Command label=\"歷史對話\">\n {/* 搜尋列幾何 = CommandInput SSOT(2026-09-08 刪掉這裡的第二份 py/h 覆寫) */}\n <CommandInput\n placeholder={historySearchPlaceholder}\n aria-label={historySearchPlaceholder}\n />\n <CommandEmpty>{historyEmptyText}</CommandEmpty>\n <CommandList label=\"對話\">\n {groups.map(({ label, items }) => (\n <React.Fragment key={label || '(ungrouped)'}>\n <CommandGroup\n heading={label ? <MenuItem header>{label}</MenuItem> : undefined}\n >\n {items.map((conversation) => (\n <HistoryRow\n key={conversation.id}\n conversation={conversation}\n selected={conversation.id === activeConversationId}\n onSelect={() => {\n onSelectConversation?.(conversation.id)\n setHistoryOpen(false)\n }}\n onRename={() => setRenameTarget(conversation)}\n onDelete={() => setDeleteTarget(conversation)}\n />\n ))}\n </CommandGroup>\n </React.Fragment>\n ))}\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"text\"\n size=\"sm\"\n iconOnly\n startIcon={Plus}\n aria-label=\"新對話\" // i18n-allow: DS 預設文案(Dialog「關閉」同前例)\n disabled={conversationEmpty}\n onClick={onNewConversation}\n />\n <ButtonDivider />\n <Button dismiss size=\"sm\" startIcon={XIcon} aria-label=\"關閉面板\" onClick={onClose} />\n </div>\n {renameTarget && (\n <AgentRenameDialog\n conversation={renameTarget}\n onOpenChange={(next) => {\n if (!next) {\n setRenameTarget(null)\n returnFocus()\n }\n }}\n onConfirm={(nextTitle) => {\n onRenameConversation?.(renameTarget.id, nextTitle)\n setRenameTarget(null)\n returnFocus()\n }}\n />\n )}\n {deleteTarget && (\n <Dialog\n open\n onOpenChange={(next) => {\n if (!next) {\n setDeleteTarget(null)\n returnFocus()\n }\n }}\n >\n {/* 確認框/短表單:autoHeight 隨內容(dialog.spec.md 高度行為)、寬 440(DS 五個確認框 story 慣例)。 */}\n <DialogContent autoHeight maxWidth={440}>\n <DialogHeader>\n <DialogTitle>刪除對話</DialogTitle>\n </DialogHeader>\n <DialogBody>\n 確定刪除「{deleteTarget.title}」?此動作立即生效且不可復原。\n </DialogBody>\n <DialogFooter>\n <Button variant=\"tertiary\" onClick={() => { setDeleteTarget(null); returnFocus() }}>\n 取消\n </Button>\n <Button\n variant=\"primary\"\n danger\n onClick={() => {\n onDeleteConversation?.(deleteTarget.id)\n setDeleteTarget(null)\n returnFocus()\n }}\n >\n 刪除\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )}\n </ChromeHeader>\n )\n },\n)\nAgentPanelHeader.displayName = 'AgentPanelHeader'\n\n/** 改名 Dialog:Field+Input 預填全選;儲存=更新類 dirty 規則;空名 blur 顯錯;Esc=Dialog 取消。 */\nfunction AgentRenameDialog({\n conversation,\n onOpenChange,\n onConfirm,\n}: {\n conversation: AgentConversationSummary\n onOpenChange: (open: boolean) => void\n onConfirm: (title: string) => void\n}) {\n const [value, setValue] = React.useState(conversation.title)\n const [touched, setTouched] = React.useState(false)\n const trimmed = value.trim()\n const dirty = trimmed !== conversation.title\n const empty = trimmed.length === 0\n const showError = touched && empty\n const commit = () => {\n setTouched(true)\n if (empty || !dirty) return\n onConfirm(trimmed)\n }\n return (\n <Dialog open onOpenChange={onOpenChange}>\n {/* 確認框/短表單:autoHeight 隨內容(dialog.spec.md 高度行為)、寬 440(DS 五個確認框 story 慣例)。 */}\n <DialogContent autoHeight maxWidth={440}>\n <DialogHeader>\n <DialogTitle>改名對話</DialogTitle>\n </DialogHeader>\n <DialogBody>\n <Field required invalid={showError}>\n <FieldLabel>名稱</FieldLabel>\n <Input\n value={value}\n error={showError}\n onChange={(e) => setValue(e.target.value)}\n onFocus={(e) => e.currentTarget.select()}\n onBlur={() => setTouched(true)}\n onKeyDown={(e) => {\n // form-validation:Enter=等同 blur(觸發驗證並提交);Esc 由 Dialog 承接=取消。\n if (e.key === 'Enter') {\n e.preventDefault()\n commit()\n }\n }}\n />\n {showError && <FieldError>名稱不可空白</FieldError>}\n </Field>\n </DialogBody>\n <DialogFooter>\n <Button variant=\"tertiary\" onClick={() => onOpenChange(false)}>\n 取消\n </Button>\n <Button variant=\"primary\" disabled={!dirty || empty} onClick={commit}>\n 儲存\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 3. AgentConversation(訊息卷軸區)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport type AgentConversationProps = React.HTMLAttributes<HTMLDivElement>\n\n/** 最後一則代理訊息的工具列常駐(其餘懸停);由 AgentConversation 判定,consumer 不設(SSOT)。 */\nconst LastAgentMessageContext = React.createContext<boolean>(false)\n\nconst AgentConversation = React.forwardRef<HTMLDivElement, AgentConversationProps>(\n ({ className, children, ...props }, ref) => {\n // 找最後一則 role=\"agent\" 的直接子訊息:它的工具列常駐,其他訊息懸停才顯(spec「AgentToolbar」)。\n const items = React.Children.toArray(children)\n let lastAgentIndex = -1\n items.forEach((child, index) => {\n if (React.isValidElement<AgentMessageProps>(child) && child.type === AgentMessage && (child.props.role ?? 'agent') === 'agent') {\n lastAgentIndex = index\n }\n })\n // 自動捲到最新:掛載時與訊息數增加時捲到底(使用者若已往上捲離底部 > 40px 則不打擾;\n // ChatGPT / Claude 皆「貼底跟隨、離底不搶」);全家族一致,consumer 不自接。\n const logRef = React.useRef<HTMLDivElement | null>(null)\n React.useImperativeHandle(ref, () => logRef.current as HTMLDivElement)\n const wasNearBottomRef = React.useRef(true)\n // 上次在「面板看得見」時停在哪 —— 用來在面板從隱藏回來時把位置補回去(spec E 條「閱讀位置保存」)。\n const savedTopRef = React.useRef<number | null>(null)\n React.useLayoutEffect(() => {\n const log = logRef.current\n const viewport = log?.closest<HTMLElement>('[data-radix-scroll-area-viewport]')\n if (!log || !viewport) return\n // 2026-09-07 G2:面板關閉時走 `display:none`(不再卸載)。實測祖先被 display:none 之後\n // **瀏覽器會把捲動位置歸零**,而且 ResizeObserver 會以 0×0 觸發一次 ——\n // 那一刻量到的 scrollHeight / clientHeight / scrollTop 全是 0,拿去更新狀態就會\n // 把「使用者剛剛在哪」洗成「貼在底部」。所以兩個 handler 都先擋掉沒有版面的情況,\n // 這跟 person-display 的 `availablePx <= 0 → 不更新` 是同一條原則:\n // **沒有版面時量到的數字不代表任何事,不能拿來做決定。**\n const hasLayout = () => viewport.clientHeight > 0\n const stick = () => {\n if (!hasLayout()) return\n if (wasNearBottomRef.current) { viewport.scrollTop = viewport.scrollHeight; return }\n // 從隱藏回來:位置被歸零了,補回上次看得見時的位置。\n // 只在「現在是 0、而且記得的不是 0」時才補 —— 使用者本來就停在頂端時 saved 也是 0,不會誤補。\n if (savedTopRef.current !== null && savedTopRef.current > 0 && viewport.scrollTop === 0) {\n viewport.scrollTop = savedTopRef.current\n }\n }\n stick()\n const onScroll = () => {\n if (!hasLayout()) return\n savedTopRef.current = viewport.scrollTop\n wasNearBottomRef.current = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight <= 40\n }\n viewport.addEventListener('scroll', onScroll, { passive: true })\n // 量**內容高度**而不是訊息則數:代理回覆是串流寫進同一則訊息的,則數不變但高度一直長,\n // 只看則數會讓整段回覆期間都不跟隨(ChatGPT / Claude 皆貼底跟隨)。\n const ro = new ResizeObserver(stick)\n ro.observe(log)\n return () => {\n viewport.removeEventListener('scroll', onScroll)\n ro.disconnect()\n }\n }, [])\n return (\n // 捲軸必用 ScrollArea(跨 OS 一致;Dialog body 同法)。\n <ScrollArea fillX className=\"min-h-0 flex-1\">\n <div\n ref={logRef}\n role=\"log\"\n aria-live=\"polite\"\n className={cn(\n // 輪距 40 = 8 + 24(工具列)+ 8;懸停工具列絕對定位於輪距內,出現不推擠。\n // 底部 = --layout-space-bottom 48:最後內容(常駐工具列)→ 輸入盒動作(送出)= layoutSpace 規則 4\n // 「內容 → action button = bottom」(layoutSpace.spec.md L118;2026-09-02 user 抓工具列貼輸入盒)。\n 'flex flex-col gap-10 p-[var(--layout-space-loose)] pb-[var(--layout-space-bottom)]',\n className,\n )}\n {...props}\n >\n {items.map((child, index) => (\n <LastAgentMessageContext.Provider key={(React.isValidElement(child) && child.key) || index} value={index === lastAgentIndex}>\n {child}\n </LastAgentMessageContext.Provider>\n ))}\n </div>\n </ScrollArea>\n )\n },\n)\nAgentConversation.displayName = 'AgentConversation'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 4. AgentMessage(訊息)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentAttachment {\n id: string\n label: string\n}\n\nexport interface AgentMessageProps extends React.HTMLAttributes<HTMLDivElement> {\n /** 訊息角色:user=我方氣泡靠右;agent=無氣泡全寬。 */\n role?: 'user' | 'agent'\n /** 氣泡內文字上方的附件(送出後視覺=Chip assist 分支)。 */\n attachments?: AgentAttachment[]\n onAttachmentClick?: (attachment: AgentAttachment) => void\n /** 訊息工具列(AgentToolbar);絕對定位於輪距內。 */\n toolbar?: React.ReactNode\n}\n\nconst AgentMessage = React.forwardRef<HTMLDivElement, AgentMessageProps>(\n (\n { role = 'agent', attachments, onAttachmentClick, toolbar, className, children, ...props },\n ref,\n ) => {\n const isUser = role === 'user'\n return (\n <div\n ref={ref}\n className={cn('group/agent-message relative', isUser && 'flex justify-end', className)}\n {...props}\n >\n <div\n className={cn(\n 'text-body text-foreground',\n isUser\n ? [\n 'max-w-[85%] rounded-md bg-secondary px-3 py-2',\n 'animate-in fade-in-0 slide-in-from-bottom-2 duration-[var(--motion-duration-overlay)] motion-reduce:animate-none',\n ]\n : 'w-full [&_a]:text-primary [&_a:hover]:text-primary-hover [&_a]:underline-offset-2 [&_a]:underline' // spec:151 長文閱讀需要底線可掃描(2026-09-08 從 hover 才畫改回恆畫),\n )}\n >\n {attachments && attachments.length > 0 && (\n // chip 相互垂直/水平 4(=Combobox 內 Tag 區間距;2026-09-02 拍板)。\n <div className=\"mb-2 flex flex-wrap gap-1\">\n {attachments.map((attachment) => (\n <Chip\n key={attachment.id}\n variant=\"assist\"\n aria-label={`附件:${attachment.label}`}\n onClick={() => onAttachmentClick?.(attachment)}\n >\n {attachment.label}\n </Chip>\n ))}\n </div>\n )}\n {children}\n </div>\n {toolbar}\n </div>\n )\n },\n)\nAgentMessage.displayName = 'AgentMessage'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 5. AgentThinking(思考塊)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentThinkingProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** 進行中:標題「思考中」+微光;完成:「思考過程」靜態。 */\n thinking?: boolean\n /** 已完成的步驟(靜態,fg-secondary)。 */\n steps?: React.ReactNode[]\n /** 正在寫入的最新一行(僅此行與標題套微光)。 */\n currentStep?: React.ReactNode\n /** 開合(未受控時:回覆中自動展開、回覆完自動收合)。 */\n open?: boolean\n onOpenChange?: (open: boolean) => void\n}\n\nconst AgentThinking = React.forwardRef<HTMLDivElement, AgentThinkingProps>(\n ({ thinking = false, steps, currentStep, open, onOpenChange, className, ...props }, ref) => {\n // 非受控:AI 回覆中自動展開、回覆完自動收合(拍板;三套元件庫一致慣例)。\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(thinking)\n React.useEffect(() => {\n if (open === undefined) setUncontrolledOpen(thinking)\n }, [thinking, open])\n const resolvedOpen = open ?? uncontrolledOpen\n const handleOpenChange = (next: boolean) => {\n setUncontrolledOpen(next)\n onOpenChange?.(next)\n }\n return (\n <CollapsiblePrimitive.Root\n ref={ref}\n open={resolvedOpen}\n onOpenChange={handleOpenChange}\n className={cn('text-body', className)}\n {...props}\n >\n <CollapsiblePrimitive.Trigger\n className={cn(\n 'group/agent-thinking flex cursor-pointer items-center gap-1 text-fg-secondary hover:text-foreground',\n // 焦點框往外(= 什麼都不寫,吃 styles/base.css 全域規則)。\n // 2026-09-10 翻案:原本寫「往外 +2px 實測會壓到下方展開的思考內容(overflow-hidden 的 collapsible)」——\n // 那句沒有量過。實測(展開與收合、1440 / 700 / 420 三種寬、三個實例):上 40 / 右 322 / 下 8 / 左 15,\n // **四周最小 8px**,往外只需要 4px。那個 collapsible 的外框確實從標題底邊 0px 開始,但它是**兄弟節點**\n //(不裁任何東西)而且背景全透明,裡面第一個真的畫出線的元素在 8px 外 —— 依 focus-canonical「問題二」\n // 的「正當障礙」定義(會碰撞的鄰居或會切掉框的邊界),透明的兄弟盒不是障礙。\n 'rounded-sm',\n )}\n >\n <span className={cn(thinking && 'agent-shimmer')}>\n {thinking ? '思考中' : '思考過程'}\n </span>\n {/* chevron=裝飾指示(accordion 慣例),不吃微光;色同 Select 觸發器 chevron(fg-muted)。 */}\n <ChevronDown\n size={16}\n aria-hidden\n className=\"shrink-0 text-fg-muted transition-transform duration-[var(--motion-duration-overlay)] motion-reduce:duration-0 group-data-[state=open]/agent-thinking:rotate-180\"\n />\n </CollapsiblePrimitive.Trigger>\n <CollapsiblePrimitive.Content\n className=\"overflow-hidden data-[state=open]:animate-collapsible-down data-[state=closed]:animate-collapsible-up motion-reduce:animate-none\"\n >\n {/* 完成步驟=fg-secondary(2026-09-02 拍板;原 muted 太淺);微光行基色由 agent-panel.css 自管。 */}\n <div className=\"mt-2 flex flex-col gap-1 border-l border-divider pl-3 text-fg-secondary\">\n {steps?.map((step, index) => <div key={index}>{step}</div>)}\n {currentStep != null && (\n <div className={cn(thinking && 'agent-shimmer')}>{currentStep}</div>\n )}\n </div>\n </CollapsiblePrimitive.Content>\n </CollapsiblePrimitive.Root>\n )\n },\n)\nAgentThinking.displayName = 'AgentThinking'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 6. AgentToolbar(訊息工具列;固定 anatomy 恆渲染)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentToolbarProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * 常駐顯示。預設由 AgentConversation 判定:代理**最後一則**常駐,其餘懸停淡入(SSOT,consumer 不需設);\n * 只在 AgentConversation 之外單獨使用時才需手動指定。\n */\n pinned?: boolean\n // 固定 anatomy:三顆鈕恆渲染且沒有內建行為 → 型別層必填,少接就編譯不過(M23(f):\n // 「無內建行為的 callback 一律必填 prop」;可選會變成點了沒反應的死鈕)。\n onCopy: () => void\n onLike: () => void\n onDislike: () => void\n}\n\nconst AgentToolbar = React.forwardRef<HTMLDivElement, AgentToolbarProps>(\n ({ pinned: pinnedProp, onCopy, onLike, onDislike, className, children, ...props }, ref) => {\n const pinnedFromConversation = React.useContext(LastAgentMessageContext)\n const pinned = pinnedProp ?? pinnedFromConversation\n return (\n <div\n ref={ref}\n className={cn(\n 'mt-2 flex h-6 items-center gap-2',\n 'transition-opacity duration-[var(--motion-duration-overlay)] motion-reduce:transition-none',\n // 常駐(最後一則)= 在流內佔位,底部才能守 --layout-space-bottom;懸停顯示 = 絕對定位於輪距內,\n // 出現/消失完全不推擠版面(輪距 40 ≥ 8+24+8)。\n pinned\n ? 'relative opacity-100'\n : 'absolute left-0 top-full opacity-0 group-hover/agent-message:opacity-100 focus-within:opacity-100',\n className,\n )}\n {...props}\n >\n <Button variant=\"text\" size=\"xs\" iconOnly startIcon={Copy} aria-label=\"複製\" onClick={onCopy} />\n <ButtonDivider />\n <Button variant=\"text\" size=\"xs\" iconOnly startIcon={ThumbsUp} aria-label=\"讚\" onClick={onLike} />\n <Button variant=\"text\" size=\"xs\" iconOnly startIcon={ThumbsDown} aria-label=\"倒讚\" onClick={onDislike} />\n {children}\n </div>\n )\n },\n)\nAgentToolbar.displayName = 'AgentToolbar'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 7. AgentPromptInput(複合輸入盒;固定 anatomy 恆渲染)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentPromptAttachment {\n id: string\n label: string\n}\n\nexport interface AgentPromptInputProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSubmit'> {\n value: string\n onValueChange: (value: string) => void\n /** 送出(Enter / 送出鈕);無內建行為 → 必填。 */\n onSubmit: () => void\n /** 代理進行中:送出鈕同位換停止(實心正方),0.15s 淡切。 */\n busy?: boolean\n onStop?: () => void\n /** 輸入中附件(Tag md 恆帶 ×;超寬 +N;送出後於訊息內轉 Chip assist 視覺)。 */\n attachments?: AgentPromptAttachment[]\n /** 固定構件:每個 Tag 的 × 恆渲染 → 必填。 */\n onRemoveAttachment: (attachment: AgentPromptAttachment) => void\n /** 固定構件:工具列 + 恆渲染 → 必填。 */\n onAddAttachment: () => void\n placeholder?: string\n}\n\n/** 附件單列 + 超寬 +N(useOverflowIndices 量測;Combobox 多選 Tag 區同族)。 */\nfunction PromptAttachmentRow({\n attachments,\n onRemove,\n}: {\n attachments: AgentPromptAttachment[]\n onRemove: (attachment: AgentPromptAttachment) => void\n}) {\n const { containerRef, registerItem, overflowIndices } = useOverflowIndices<HTMLDivElement>({\n reserveTriggerWidth: 48,\n })\n const hidden = new Set(overflowIndices)\n const hiddenItems = attachments.filter((_, i) => hidden.has(i))\n return (\n // 附件列 28:Tag 相互間距 4、距內緣 4;單列不換行,溢出以 +N 收納。\n // 被藏的 Tag 留在 flow 內、排到 +N 之後(order-last)並隱形:useOverflowIndices 每次重量都拿得到\n // 真實位置(抽離 flow 會在放寬時被誤判「可見」而失去 +N,2026-09-02 實測)。\n <div ref={containerRef} className=\"flex items-center gap-1 overflow-hidden px-1 pt-1\">\n {attachments.map((attachment, index) => (\n <div\n key={attachment.id}\n ref={registerItem(index)}\n className={cn('shrink-0', hidden.has(index) && 'invisible order-last')}\n >\n <Tag size=\"md\" onRemove={() => onRemove(attachment)}>\n {attachment.label}\n </Tag>\n </div>\n ))}\n {hiddenItems.length > 0 && (\n <OverflowIndicator count={hiddenItems.length} shape=\"tag\" size=\"md\">\n {hiddenItems.map((attachment) => (\n <Tag key={attachment.id} size=\"md\" onRemove={() => onRemove(attachment)}>\n {attachment.label}\n </Tag>\n ))}\n </OverflowIndicator>\n )}\n </div>\n )\n}\n\nconst AgentPromptInput = React.forwardRef<HTMLDivElement, AgentPromptInputProps>(\n (\n {\n value,\n onValueChange,\n onSubmit,\n busy = false,\n onStop,\n attachments = [],\n onRemoveAttachment,\n onAddAttachment,\n placeholder = '輸入訊息…',\n className,\n ...props\n },\n ref,\n ) => {\n const canSubmit = value.trim().length > 0\n const submit = () => {\n if (busy || !canSubmit) return\n onSubmit()\n }\n return (\n <div\n ref={ref}\n className={cn(\n 'm-[var(--layout-space-loose)] mt-0 shrink-0 rounded-md',\n // 外框互動 = Field 家族 default chrome SSOT(field-wrapper.tsx fieldChromeStyles:單行 wrapper /\n // Textarea / 複合輸入盒三宿主同一份 compounds):hover 一階 border-hover、focus-within 主色;\n // 2026-09-02 user 抓「跟 Textarea 不一樣」→ 收斂為單一住所,禁自刻。\n fieldChromeStyles({ mode: 'edit', variant: 'default', error: false }),\n className,\n )}\n {...props}\n >\n {attachments.length > 0 && (\n <PromptAttachmentRow attachments={attachments} onRemove={onRemoveAttachment} />\n )}\n <textarea\n value={value}\n onChange={(e) => onValueChange(e.target.value)}\n onKeyDown={(e) => {\n // 按 Enter 送出、Shift+Enter 換行(拍板)。\n if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault()\n submit()\n }\n }}\n rows={1}\n placeholder={placeholder}\n aria-label=\"訊息\"\n className={cn(\n // 欄位家族內距:單行 32 等高鐵律((欄高−1lh)/2−1 + --field-px)。\n // @focus-suppress B — B Field 家族輸入控件;承擔者:指示器是輸入盒外框\n 'block w-full resize-none bg-transparent outline-none',\n 'px-[var(--field-px)] py-[var(--field-control-py-md)] text-body text-foreground',\n 'placeholder:text-fg-muted',\n 'field-sizing-content max-h-40',\n )}\n />\n <div className=\"flex h-10 items-center justify-between px-2\">\n <Button\n variant=\"text\"\n size=\"xs\"\n iconOnly\n startIcon={Plus}\n aria-label=\"新增附件\"\n onClick={onAddAttachment}\n />\n {busy ? (\n <Button\n variant=\"primary\"\n size=\"xs\"\n iconOnly\n startIcon={StopFilled}\n aria-label=\"停止生成\"\n onClick={() => onStop?.()}\n className=\"animate-in fade-in-0 duration-[var(--motion-duration-overlay)] motion-reduce:animate-none\"\n />\n ) : (\n <Button\n variant=\"primary\"\n size=\"xs\"\n iconOnly\n startIcon={ArrowUp}\n aria-label=\"送出\"\n disabled={!canSubmit}\n onClick={submit}\n className=\"animate-in fade-in-0 duration-[var(--motion-duration-overlay)] motion-reduce:animate-none\"\n />\n )}\n </div>\n </div>\n )\n },\n)\nAgentPromptInput.displayName = 'AgentPromptInput'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 8. AgentDecisionCard(決策卡;一題一問步進)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentDecisionOption {\n value: string\n /** 單行、≤10 字、無句尾標點、說「選了會怎樣」(產題守則 5)。 */\n label: string\n /** 一行差異描述:單句、無句號、同題比同一維度(產題守則 6)。 */\n description: string\n}\n\nexport interface AgentDecisionQuestion {\n id: string\n /** 題目=一句完整問句、以「?」結尾、句內點名決策對象(產題守則 3)。 */\n label: string\n /** 2-4 具名選項(不含「其他」;「其他」由元件必備附加,產題守則 4/7)。 */\n options: AgentDecisionOption[]\n /** 預選推薦解;省略=第一項;元件在該項 label 後加「(建議)」(產題守則 8)。 */\n defaultValue?: string\n /** 不可逆/安全/法律/稱謂類題:不預選(產題守則 8 例外);複選題恆不預選。 */\n noDefault?: boolean\n /** 答案本質可複選才開(產題守則 10):改 CheckboxGroup、不預選、值以 `\\n` 連接。 */\n multiSelect?: boolean\n}\n\nexport interface AgentDecisionCardProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSubmit' | 'title'> {\n /** ≤3 題;一題一問步進,N>1 時標題列顯示「n / N」。 */\n questions: AgentDecisionQuestion[]\n /** 全部作答後送出:answers[questionId] = 選項值或「其他」文字(複選以 `\\n` 連接)。 */\n onSubmit?: (answers: Record<string, string>) => void\n /** 跳過=採預設值繼續(Skip 鈕與 header × 同一行為);回傳目前預設/已選值。 */\n onSkip?: (answers: Record<string, string>) => void\n}\n\nconst OTHER_VALUE = '__agent_decision_other__'\nconst OTHER_LABEL = '其他'\nconst RECOMMENDED_SUFFIX = '(建議)'\nconst MULTI_JOIN = '\\n'\n\n/** 產題守則機械層(agent-panel.spec.md §8 ⚙ 條):DEV 只警告不阻擋,內容規則靠稽核。 */\nfunction warnDecisionRules(questions: AgentDecisionQuestion[]) {\n const warn = (msg: string) => console.warn(`[AgentDecisionCard] 產題守則:${msg}`)\n if (questions.length === 0 || questions.length > 3) warn(`題數 1–3(收到 ${questions.length})。`)\n for (const q of questions) {\n if (!/[??]$/.test(q.label.trim())) warn(`題目必是完整問句、以「?」結尾(${q.id}:「${q.label}」)。`)\n if (q.options.length < 2 || q.options.length > 4) warn(`每題 2–4 個具名選項(${q.id} 有 ${q.options.length})。`)\n for (const o of q.options) {\n if (/\\n/.test(o.label) || o.label.length > 10) warn(`選項標籤單行且 ≤10 字(${q.id}:「${o.label}」)。`)\n if (/[,,;;.。!!]$/.test(o.label)) warn(`選項標籤無句尾標點(${q.id}:「${o.label}」)。`)\n if (/\\(建議\\)|\\(建議\\)|\\(Recommended\\)/i.test(o.label)) warn(`「(建議)」由元件標,勿寫進標籤(${q.id}:「${o.label}」)。`)\n if (!o.description?.trim()) warn(`每個具名選項必附一行差異描述(${q.id}:「${o.label}」)。`)\n else if (/\\n/.test(o.description) || /[。.]$/.test(o.description.trim())) warn(`描述單句、無句號(${q.id}:「${o.label}」)。`)\n if (/^(其他|other)$/i.test(o.label.trim()) || o.value === OTHER_VALUE) warn(`「其他」由元件附加,勿自列(${q.id})。`)\n }\n if (q.multiSelect && q.defaultValue) warn(`複選題不預選(${q.id})。`)\n if (!q.multiSelect && !q.noDefault) {\n const def = q.defaultValue ?? q.options[0]?.value\n if (q.defaultValue && !q.options.some((o) => o.value === q.defaultValue)) warn(`defaultValue 必是選項之一(${q.id})。`)\n if (def !== q.options[0]?.value) warn(`推薦解必排第一(${q.id})。`)\n }\n }\n}\n\nfunction initialAnswer(q: AgentDecisionQuestion) {\n if (q.multiSelect || q.noDefault) return ''\n return q.defaultValue ?? q.options[0]?.value ?? ''\n}\n\n/** 複選值 = 已勾選 value 集合(含 OTHER_VALUE),以 `\\n` 連接存於 answers。 */\nconst splitMulti = (v: string | undefined) => (v ? v.split(MULTI_JOIN).filter(Boolean) : [])\n\nconst AgentDecisionCard = React.forwardRef<HTMLDivElement, AgentDecisionCardProps>(\n ({ questions, onSubmit, onSkip, className, ...props }, ref) => {\n const titleId = React.useId()\n const otherInputId = React.useId()\n const optionIdBase = React.useId()\n if (import.meta.env?.DEV) warnDecisionRules(questions)\n const [step, setStep] = React.useState(0)\n const [answers, setAnswers] = React.useState<Record<string, string>>(() =>\n Object.fromEntries(questions.map((q) => [q.id, initialAnswer(q)])),\n )\n const [otherText, setOtherText] = React.useState<Record<string, string>>({})\n const resolveOne = (q: AgentDecisionQuestion) => {\n const other = (otherText[q.id] ?? '').trim()\n if (q.multiSelect) {\n return splitMulti(answers[q.id])\n .map((v) => (v === OTHER_VALUE ? other : v))\n .filter(Boolean)\n .join(MULTI_JOIN)\n }\n return answers[q.id] === OTHER_VALUE ? other : (answers[q.id] ?? '')\n }\n const resolvedAnswers = () =>\n Object.fromEntries(questions.map((q) => [q.id, resolveOne(q)])) as Record<string, string>\n const total = questions.length\n const question = questions[Math.min(step, total - 1)]\n const isLast = step >= total - 1\n const select = (value: string) => setAnswers((prev) => ({ ...prev, [question.id]: value }))\n const toggle = (value: string, checked: boolean) =>\n setAnswers((prev) => {\n const set = new Set(splitMulti(prev[question.id]))\n if (checked) set.add(value)\n else set.delete(value)\n return { ...prev, [question.id]: [...set].join(MULTI_JOIN) }\n })\n const skip = () => onSkip?.(resolvedAnswers())\n\n if (!question) return null\n const multi = Boolean(question.multiSelect)\n const selectedSet = new Set(multi ? splitMulti(answers[question.id]) : [answers[question.id]])\n const otherSelected = selectedSet.has(OTHER_VALUE)\n // 「其他」選中而文字為空 → 不得前進/送出(產題守則 7);複選一項未勾 → 亦不得前進。\n const canAdvance =\n (!otherSelected || (otherText[question.id] ?? '').trim() !== '') &&\n // 複選至少一項;單選必須有值 —— noDefault 的單選初值是空字串,沒補這一條會送出空答案。\n (multi ? selectedSet.size > 0 : (answers[question.id] ?? '') !== '')\n const recommendedValue =\n !multi && !question.noDefault ? (question.defaultValue ?? question.options[0]?.value) : undefined\n const optionLabel = (option: AgentDecisionOption | { value: string; label: string }) =>\n option.value === recommendedValue ? `${option.label}${RECOMMENDED_SUFFIX}` : option.label\n const allOptions = [...question.options, { value: OTHER_VALUE, label: OTHER_LABEL }]\n const renderOtherInput = () => (\n // 「其他」卡:常駐 32 高輸入格;label 行框↔Input 8(mt-2);距卡右/下各 12(卡 px 12;卡 py 8 + mb 4);\n // 左縮排 24 = radio 16 + gap 8,與 label 對齊(Polaris ChoiceChildren 同款)。\n <div className=\"mb-1 mt-2 pl-6\">\n <Input\n id={otherInputId}\n value={otherText[question.id] ?? ''}\n placeholder=\"輸入其他選項\"\n aria-label=\"其他(自由輸入)\"\n aria-describedby={titleId}\n onFocus={() => (multi ? toggle(OTHER_VALUE, true) : select(OTHER_VALUE))}\n onChange={(e) => setOtherText((prev) => ({ ...prev, [question.id]: e.target.value }))}\n onClick={(e) => e.stopPropagation()}\n />\n </div>\n )\n // 滑鼠/觸控點整張「其他」卡 → 聚焦輸入格(明確指向意圖);鍵盤方向鍵選中不搶焦點(APG radio roving),Tab 一步即到。\n const focusOtherInput = () =>\n window.setTimeout(() => (document.getElementById(otherInputId) as HTMLInputElement | null)?.focus(), 0)\n // 灰底選項卡 = 唯一行距 owner(py 8);SelectionItem 自帶 py((32−1lh)/2=5.5)歸零,避免 double padding\n // (checkbox.spec.md 零外部 gap 鐵律的反向:間距只能有一個 owner)。\n const cardClass = 'cursor-pointer rounded-md bg-secondary px-3 py-2'\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-labelledby={titleId}\n className={cn(\n // 繼承 Popover surface:rounded-lg/border/elevation-200;改寫:無下圓角、貼底。\n 'absolute inset-x-0 bottom-0 z-10 flex flex-col overflow-hidden',\n 'rounded-t-lg rounded-b-none border border-b-0 border-border bg-surface-raised',\n 'shadow-[var(--elevation-200)]',\n 'animate-in fade-in-0 slide-in-from-bottom-2 duration-[var(--motion-duration-overlay)] motion-reduce:animate-none',\n className,\n )}\n {...props}\n >\n {/* 標題列:N>1 時小標「n / N」+ 題目 + ×(跳過);改寫:header 下無分隔線。 */}\n <SurfaceHeader className={cn(COMPACT_HEADER_SLOT, 'items-start justify-between border-b-0')}>\n <div className=\"flex min-w-0 flex-1 flex-col\">\n {total > 1 && (\n <span className=\"text-caption font-medium text-fg-secondary\">\n {step + 1} / {total}\n </span>\n )}\n <span id={titleId} className=\"text-body font-medium text-foreground\">\n {question.label}\n </span>\n </div>\n <Button dismiss size=\"sm\" startIcon={XIcon} aria-label=\"跳過\" onClick={skip} />\n </SurfaceHeader>\n {/* body:上下無內距、左右 16;選項=灰底卡 gap 8(整卡可點;拍板樣張,本地包裝不抽通用元件);捲軸必用 ScrollArea。 */}\n <ScrollArea fillX className=\"min-h-0\">\n {multi ? (\n <CheckboxGroup\n key={question.id}\n aria-labelledby={titleId}\n className=\"flex flex-col gap-2 px-[var(--layout-space-loose)]\"\n >\n {allOptions.map((option) => {\n const isOther = option.value === OTHER_VALUE\n const checked = selectedSet.has(option.value)\n return (\n <div\n key={option.value}\n data-state={checked ? 'checked' : 'unchecked'}\n className={cardClass}\n onClick={() => {\n toggle(option.value, !checked)\n if (isOther && !checked) focusOtherInput()\n }}\n >\n <SelectionItem\n size=\"md\"\n className=\"py-0\"\n htmlFor={`${optionIdBase}-${option.value}`}\n control={\n <Checkbox\n id={`${optionIdBase}-${option.value}`}\n size=\"md\"\n checked={checked}\n onCheckedChange={(next) => toggle(option.value, next === true)}\n onClick={(e) => e.stopPropagation()}\n aria-controls={isOther ? otherInputId : undefined}\n />\n }\n label={optionLabel(option)}\n description={isOther ? undefined : (option as AgentDecisionOption).description}\n />\n {isOther && renderOtherInput()}\n </div>\n )\n })}\n </CheckboxGroup>\n ) : (\n <RadioGroup\n key={question.id}\n value={answers[question.id] ?? ''}\n onValueChange={select}\n aria-labelledby={titleId}\n className=\"flex flex-col gap-2 px-[var(--layout-space-loose)]\"\n >\n {allOptions.map((option) => {\n const isOther = option.value === OTHER_VALUE\n const checked = selectedSet.has(option.value)\n return (\n <div\n key={option.value}\n data-state={checked ? 'checked' : 'unchecked'}\n className={cardClass}\n onClick={() => {\n select(option.value)\n if (isOther) focusOtherInput()\n }}\n >\n <SelectionItem\n size=\"md\"\n className=\"py-0\"\n htmlFor={`${optionIdBase}-${option.value}`}\n control={\n <RadioGroupItem\n id={`${optionIdBase}-${option.value}`}\n value={option.value}\n size=\"md\"\n aria-controls={isOther ? otherInputId : undefined}\n />\n }\n label={optionLabel(option)}\n description={isOther ? undefined : (option as AgentDecisionOption).description}\n />\n {isOther && renderOtherInput()}\n </div>\n )\n })}\n </RadioGroup>\n )}\n </ScrollArea>\n {/* footer:第一題=跳過(用預設繼續)、第二題起=上一題(答案保留;Material Stepper Back / GOV.UK Back 同款);\n 右=下一題 / 送出(末題);鈕 sm 守 Popover all-sm 律;無上分隔線;× 恆為跳過。 */}\n <SurfaceFooter className=\"border-t-0\">\n {step > 0 ? (\n <Button variant=\"tertiary\" size=\"sm\" onClick={() => setStep((s) => Math.max(0, s - 1))}>\n 上一題\n </Button>\n ) : (\n <Button variant=\"tertiary\" size=\"sm\" onClick={skip}>\n 跳過\n </Button>\n )}\n {isLast ? (\n <Button variant=\"primary\" size=\"sm\" disabled={!canAdvance} onClick={() => onSubmit?.(resolvedAnswers())}>\n 送出\n </Button>\n ) : (\n <Button variant=\"primary\" size=\"sm\" disabled={!canAdvance} onClick={() => setStep((s) => s + 1)}>\n 下一題\n </Button>\n )}\n </SurfaceFooter>\n </div>\n )\n },\n)\nAgentDecisionCard.displayName = 'AgentDecisionCard'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 9. AgentDecisionSummary(決策回執)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentDecisionSummaryProps extends React.HTMLAttributes<HTMLDivElement> {\n /** [問題, 答案] 配對(靜態回執)。 */\n entries: Array<{ question: string; answer: string }>\n}\n\nconst AgentDecisionSummary = React.forwardRef<HTMLDivElement, AgentDecisionSummaryProps>(\n ({ entries, className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col gap-2 rounded-md border border-border px-3 py-2 text-body',\n className,\n )}\n {...props}\n >\n {entries.map(({ question, answer }, index) => (\n <div key={index} className=\"flex flex-col\">\n <span className=\"text-fg-secondary\">{question}</span>\n <span className=\"text-foreground\">{answer}</span>\n </div>\n ))}\n </div>\n ),\n)\nAgentDecisionSummary.displayName = 'AgentDecisionSummary'\n\nexport {\n AgentPanel,\n AgentPanelHeader,\n AgentConversation,\n AgentMessage,\n AgentThinking,\n AgentToolbar,\n AgentPromptInput,\n AgentDecisionCard,\n AgentDecisionSummary,\n PANEL_WIDTH_DEFAULT as AGENT_PANEL_WIDTH_DEFAULT,\n PANEL_WIDTH_MIN as AGENT_PANEL_WIDTH_MIN,\n PANEL_WIDTH_MAX as AGENT_PANEL_WIDTH_MAX,\n}\n"],"names":["XIcon","_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agent-panel.js","sources":["../../../src/components/AgentPanel/agent-panel.tsx"],"sourcesContent":["// code-quality-allow: file-size foundational composite family(9 元件一家族檔,同 Sidebar 前例)\n/**\n * AgentPanel 家族 — 智慧代理面板(9 元件;附屬資產 AgentLogo/AgentFab 另檔)。\n *\n * ── 消費的 SSOT ──\n * - 容器:右側欄=bg-surface + border-l border-divider(app-shell aside 前例);\n * 寬 --agent-panel-width(uiSize.css;可拖拉 360–640 且 ≤50vw,把手=ResizeHandle pattern,\n * 鍵盤等價=WAI-ARIA separator 同 DataTable 欄寬慣例);開合 --motion-duration-surface。\n * - 標題列:ChromeHeader(header-canonical;chrome 內控件一律 sm);品牌區=gap-2+24 標誌;\n * 標題+chevron=單一複合觸發鈕:**原生 `<button>`,不包 Button 殼**(Button 會多出左 9 / 右 5 內距\n * 與 28 高的懸停底,見 agent-panel.spec.md「禁用 Button 殼」);語意仍同 Polaris disclosure /\n * Combobox 觸發器,chevron=裝飾性指示(inline-action.spec.md Q1);\n * ButtonDivider 於 gap-2 cluster(action-bar 規則 3)。\n * **固定構件恆渲染**:+ / × / 標題觸發鈕不隨 callback 有無消失(2026-09-02 根因修正)。\n * - 歷史浮層:Popover+Command+MenuItem,列組裝逐字照 select-menu.tsx 原型(外層 CommandItem 單一\n * 互動 owner、內層 MenuItem role=presentation 透明、群組 heading、CommandSeparator、Empty);\n * 行內動作=ItemSuffix hoverReveal + ItemInlineAction(懸停/鍵盤 focus-visible 浮出);思考列=CircularProgress 16。\n * - 訊息:氣泡 bg-secondary/rounded-md/8/12;附件=Chip assist 分支(chip.spec.md),相互 4;\n * 輪距 40=8+24(Button text xs)+8。\n * - 思考塊:Radix Collapsible+animate-accordion(base.css;Sidebar 同法);chevron=accordion 慣例\n * (裝飾指示、色同 Select 觸發器 chevron);微光僅標題+最新行(agent-panel.css);完成步驟 fg-secondary。\n * - 輸入盒:欄位家族內距(--field-control-py-md/--field-px/text-body;32 等高鐵律);\n * 附件列=Tag md 單列 + OverflowIndicator(+N,useOverflowIndices 量測);送出/停止=Button primary xs。\n * - 決策卡:SurfaceHeader(compact)+SurfaceFooter(overlay-surface);選項=灰底卡(--secondary、\n * rounded-md、內距 8/12、整卡可點)包 RadioGroup md(Popover all-sm 律之拍板豁免;footer 鈕 sm 守律);\n * 一題一問步進(跳過 / 上一題 / 下一題 / 送出);N>1 才顯示「n / N」小標;淡入+下滑 --motion-duration-overlay。\n * - 改名/刪除:Dialog(header md+X;body Field+Input;footer md 鈕;刪除=primary+danger;\n * form-validation:儲存 dirty 規則、空名 blur 顯錯;Esc=Dialog 取消)。\n * - 空狀態:Empty icon slot 接 AgentLogo 招喚態。\n * 全表:agent-panel.spec.md。\n */\nimport * as React from 'react'\nimport * as CollapsiblePrimitive from '@radix-ui/react-collapsible'\nimport {\n createLucideIcon,\n ArrowUp,\n ChevronDown,\n Copy,\n MessageSquare,\n Pencil,\n Plus,\n ThumbsDown,\n ThumbsUp,\n Trash2,\n X as XIcon,\n} from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { useOverlayCoexistence, CoexistenceMask } from '@/design-system/lib/overlay-coexistence'\nimport { useCursorMover } from '@/design-system/hooks/use-input-modality'\n\n/**\n * 停止實心正方:12/24 grid(= Material Symbols `stop` 480/960)→ 8px @ Button icon 16。\n * lucide Square 填滿後 20/24 = 13.3px,比 ArrowUp/Plus(14/24 線稿)視覺偏重,故自繪\n * (2026-09-02 user 抓「太巨大」;rx 1.5 ≈ Carbon 2/20、lucide 2/18 圓角比例)。\n */\nconst StopFilled = createLucideIcon('StopFilled', [\n ['rect', { x: '6', y: '6', width: '12', height: '12', rx: '1.5', fill: 'currentColor', stroke: 'none', key: 'stop' }],\n])\nimport { Button } from '@/design-system/components/Button/button'\nimport { ButtonDivider } from '@/design-system/components/Button/button-group'\nimport { ChromeHeader } from '@/design-system/patterns/header-canonical/chrome-header'\nimport { TruncatedText } from '@/design-system/patterns/element-anatomy/truncated-text'\nimport { fieldChromeStyles } from '@/design-system/components/Field/field-wrapper'\nimport {\n SurfaceHeader,\n SurfaceFooter,\n COMPACT_HEADER_SLOT,\n} from '@/design-system/patterns/overlay-surface/overlay-surface'\nimport {\n Popover,\n PopoverTrigger,\n PopoverContent,\n} from '@/design-system/components/Popover/popover'\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from '@/design-system/components/Command/command'\nimport { MenuItem } from '@/design-system/components/Menu/menu-item'\nimport {\n ItemInlineAction,\n ItemSuffix,\n} from '@/design-system/patterns/element-anatomy/item-anatomy'\nimport { ResizeHandle } from '@/design-system/patterns/resize-handle/resize-handle'\nimport { ICON_SIZE } from '@/design-system/tokens/uiSize/icon-size'\nimport { useOverflowIndices } from '@/design-system/patterns/horizontal-overflow/horizontal-overflow'\nimport { OverflowIndicator } from '@/design-system/components/OverflowIndicator/overflow-indicator'\nimport { CircularProgress } from '@/design-system/components/CircularProgress/circular-progress'\nimport { RadioGroup, RadioGroupItem } from '@/design-system/components/RadioGroup/radio-group'\nimport { Checkbox } from '@/design-system/components/Checkbox/checkbox'\nimport { CheckboxGroup } from '@/design-system/components/Checkbox/checkbox-group'\nimport { SelectionItem } from '@/design-system/components/SelectionControl/selection-item'\nimport { Chip } from '@/design-system/components/Chip/chip'\nimport { Tag } from '@/design-system/components/Tag/tag'\nimport { Input } from '@/design-system/components/Input/input'\nimport { Field, FieldLabel, FieldError } from '@/design-system/components/Field/field'\nimport {\n Dialog,\n DialogBody,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@/design-system/components/Dialog/dialog'\nimport { ScrollArea } from '@/design-system/components/ScrollArea/scroll-area'\nimport { AgentLogo, type AgentLogoState } from './agent-panel-logo'\nimport './agent-panel.css'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 1. AgentPanel(容器;可拖拉寬度)\n * ──────────────────────────────────────────────────────────────────────── */\n\n/** 拖拉寬度界限(spec「AgentPanel」節;token 鏡像:--agent-panel-width-min / -max)。 */\nconst PANEL_WIDTH_DEFAULT = 400\nconst PANEL_WIDTH_MIN = 360\nconst PANEL_WIDTH_MAX = 640\nconst PANEL_RESIZE_KEY_STEP = 16\n\n/**\n * 並排時面板寬的上限,由**容器寬**推導。\n *\n * 三個已定的量互鎖(2026-09-07 G3):\n * 面板 ≥ 360(`PANEL_WIDTH_MIN`)\n * 面板 ≤ 舞台的 3/5(user 2026-09-07 裁示 #5:「50% 基準由視窗改舞台」定了「一半」;2026-09-09 放寬到 3/5,見下)\n * 並排時 舞台 = 容器 − 面板\n * 三條合起來:面板 ≤ (容器 − 面板) × 3/5 ⇒ **面板 ≤ 容器 × 3/8**。\n * 再套下限 360 ⇒ **並排只在容器 ≥ 960 時成立**;更窄就翻成蓋板(見 `resolveIsOverlay`)。\n * 2026-09-09 user 拍板「我覺得 960px 作為 agent 蓋板的斷點應該可以」:把 2026-09-07 的「面板 ≤ 舞台一半」放寬到 3/5(舞台 600 = Material\n * medium 視窗下緣、DataTable 5 欄各 120px),360 下限不動;原本三鎖的唯一解 1080 因此變成 960。\n *\n * 為什麼不是量視窗:面板住在容器裡,不是住在視窗裡。視窗 1920 但容器只有 800 的版面\n * (側欄 + 主內容 + 面板)用視窗算會給出 640 的上限,面板一寬舞台就被擠爆。\n *\n * clampPanelWidth 與 ResizeHandle 的 `max`(→ aria-valuemax)**必須讀同一個函式** ——\n * 2026-09-07 G5:先前 `max` 寫死 640,螢幕閱讀器念的數字與實際停的位置不一樣。\n */\nfunction resolvePanelWidthMax(containerPx: number) {\n // 還沒佈局(0)時不能拿去算,否則會鎖進最小值且不再復原(同 person-display 的 <=0 守衛)\n if (!containerPx || containerPx <= 0) return PANEL_WIDTH_MAX\n return Math.min(PANEL_WIDTH_MAX, Math.max(Math.floor(containerPx * 3 / 8), PANEL_WIDTH_MIN))\n}\n\n/** 容器窄到並排放不下(面板 360 之後舞台會不足面板兩倍)→ 翻成蓋板:覆蓋宿主、左留視窗內距、底下鋪遮罩。 */\nfunction resolveIsOverlay(containerPx: number) {\n if (!containerPx || containerPx <= 0) return false\n return containerPx < AGENT_PANEL_SIDE_BY_SIDE_MIN_CONTAINER\n}\n\n/**\n * 並排斷點:容器至少要這麼寬,面板才放得下且舞台仍有面板的 5/3(360 × 8/3 = 960)。\n * 匯出讓消費端可以用同一個數字排版,不必自己抄一個 960。\n */\nexport const AGENT_PANEL_SIDE_BY_SIDE_MIN_CONTAINER = Math.ceil(PANEL_WIDTH_MIN * 8 / 3)\n\n/** 面板形態:並排(flex 兄弟)或蓋板(absolute 覆蓋宿主、左留 `--layout-space-viewport-inset`);同時標在根節點 `data-agent-panel-mode`。 */\nexport type AgentPanelMode = 'side-by-side' | 'overlay'\n\nfunction clampPanelWidth(width: number, containerPx: number) {\n return Math.min(Math.max(width, PANEL_WIDTH_MIN), resolvePanelWidthMax(containerPx))\n}\n\nexport interface AgentPanelProps extends React.HTMLAttributes<HTMLDivElement> {\n /** 面板開合;false 時不渲染(關閉後由 AgentFab 承接入口,兩者互斥)。 */\n open?: boolean\n /** 受控寬度(px);省略=非受控,起於 defaultWidth。 */\n width?: number\n /** 非受控初始寬;預設 --agent-panel-width 400。 */\n defaultWidth?: number\n /** 寬度變更時回報(**拖曳中每一格都發**,受控 consumer 才有即時回饋)。 */\n onWidthChange?: (width: number) => void\n /** 拖拉放開 / 鍵盤一步結束時回報一次(要落地儲存的接這個;DS 不持久化,產品自存)。 */\n onWidthCommit?: (width: number) => void\n /** 可拖拉(左緣把手);預設 true。Sheet 承載時同樣可拖。 */\n resizable?: boolean\n /**\n * 蓋板態(容器 < 960,面板覆蓋宿主)仍要可用的節點 —— 與 Dialog 的 `persistentElements` 同一份契約、\n * 同一支 primitive(`lib/overlay-coexistence.ts`)。v14 條 B 說的「宿主暫不可操作」只講**宿主**;\n * 宿主之外的瀏覽器 chrome(網址列、上一頁 / 下一頁、重新整理)不是宿主,蓋板時不得被抑制\n * (2026-09-09 user:「範例變成滿版狀態時,上面那虛擬的網址列完全無法點擊」)。\n * 並排態不抑制任何東西,此 prop 無作用。面板自己永遠在保留集合裡,不必傳。\n */\n persistentElements?: () => Element[]\n /**\n * 形態(並排 / 蓋板)改變時回報;量到容器之後才發第一次,之後只在形態真的翻轉時發。\n * 用途:蓋板態下「代理內導向舞台的動作」(內部連結、有網址的 modal)要把代理收成入口鈕、讓舞台顯示目標\n * (v14 條 B,2026-09-09 user 推翻「抽屜保持開啟」的 AI 推導)。**面板不知道連結**,所以收合是消費端的責任:\n * 用這個回呼記住目前形態,在自己的內部導航裡「蓋板且開著 → `onOpenChange(false)`」;並排態不收。\n * 詳 spec「與 app 的推擠與斷點」蓋板小節。\n */\n onModeChange?: (mode: AgentPanelMode) => void\n /**\n * 蓋板態下**點擊面板外的遮罩**時通知消費端關閉面板(2026-09-17 user 裁示,取代 2026-09-16 的「點了不關」)。\n *\n * 命名依據 `ds-canonical/references/props-naming.md`:`onClose` = 「關閉 overlay session —— 浮層關閉回背景」,\n * 與 Dialog / Sheet / Popover / FileViewer 同一個名字同一個語意(不是 `onDismiss`,那是「暫時訊息被忽略」)。\n *\n * **面板不自己關**:`open` 一直是消費端控的(同 `onModeChange` 那段的分工),所以這裡只發通知。\n * 並排態沒有遮罩,此 prop 無作用。\n *\n * **必填,不是可選**(2026-09-18 修正):第一版寫成 `onClose?:`,理由是「向後相容,既有 consumer 一行都不用改」——\n * 結果就是**沒傳的那些照舊點了不關**,而全庫最像產品的那則範例(`agent-panel.stories.tsx` 的 URL 註冊表示意)剛好沒傳,\n * 於是使用者在預覽站上點遮罩「根本沒有任何反應」(2026-09-18 user 回報)。這正是本家族已經立過的規矩:\n * spec §2「固定 anatomy 恆渲染」與 M23(f)「可省略 callback ≠ 可省略行為 —— 無內建行為的 callback 一律必填 prop(型別層擋)」。\n * 面板自己關不了(`open` 住在 `AgentPanelDock`),所以它沒有內建 fallback → 必填。機械閘:`scripts/agent-panel-fixed-anatomy-invariant.mjs`。\n */\n onClose: () => void\n}\n\nconst AgentPanel = React.forwardRef<HTMLDivElement, AgentPanelProps>(\n (\n {\n open = true,\n onClose,\n width,\n defaultWidth = PANEL_WIDTH_DEFAULT,\n onWidthChange,\n onWidthCommit,\n resizable = true,\n persistentElements,\n onModeChange,\n className,\n style,\n children,\n ...props\n },\n ref,\n ) => {\n // 量**容器**(面板的父層)而不是視窗:面板住在容器裡。用 ResizeObserver 而不是\n // window resize —— 版面可能因為側欄收合、分頁切換而改變,那些都不會發 window resize。\n // aria-valuemax 也吃這個值(G5:先前寫死 640,螢幕閱讀器念的與實際停的位置不一樣)。\n const rootRef = React.useRef<HTMLDivElement | null>(null)\n const hostRef = React.useRef<HTMLElement | null>(null)\n const [containerPx, setContainerPx] = React.useState(0)\n const [selfVisible, setSelfVisible] = React.useState(false)\n React.useLayoutEffect(() => {\n // 往上找到**第一個有盒子的**祖先。直接抓 parentElement 會踩到兩種「沒有盒子」的包層:\n // `display: contents` —— AgentPanelDock 為了「關閉時不卸載」包的那層(2026-09-07 踩過)\n // `display: none` —— **同一個包層在面板關閉時的樣子**(2026-09-08 跨模型審查抓到)\n // 第一版只跳過 contents,於是「初始關閉 → 打開」這條路量到的是 display:none 那層,\n // clientWidth = 0 → `if (w > 0)` 永不觸發 → containerPx 卡在 0\n // → 上限永遠 640、蓋板永不觸發。實測 800px 容器仍並排 400px。\n // **這是 G2(keep-mounted)與 G3(容器斷點)互相踩到:兩支閘各自都綠,合起來才壞。**\n const resolveHost = () => {\n let node = rootRef.current?.parentElement ?? null\n while (node && (getComputedStyle(node).display === 'contents' || getComputedStyle(node).display === 'none')) {\n node = node.parentElement\n }\n return node\n }\n let host = resolveHost()\n let ro: ResizeObserver | null = null\n const measure = () => {\n // **每次都重新解析宿主**:面板從關閉變成開啟時,原本 `display: none` 的包層會變成\n // `contents`,真正的宿主因此改變。這個 effect 是空依賴、不會重跑,\n // 所以重綁只能發生在這裡 —— 否則打開之後永遠量著開啟前解析到的那個節點。\n const next = resolveHost()\n if (next !== host) {\n if (host && ro) ro.unobserve(host)\n host = next\n if (host && ro) ro.observe(host)\n }\n hostRef.current = host\n // 面板自己有沒有版面:Dock 關閉時是 display:none,那時**不能**保持整頁抑制(R3 反例:\n // 窄版 Panel 隱藏後背景仍 inert)。\n setSelfVisible((rootRef.current?.clientWidth ?? 0) > 0)\n const w = host?.clientWidth ?? 0\n // 沒有版面時量到的 0 不代表任何事,不拿去更新(同 person-display / AgentConversation)\n if (w > 0) setContainerPx(w)\n }\n ro = new ResizeObserver(measure)\n if (host) ro.observe(host)\n // 也觀察面板自己:它從隱藏變可見時尺寸 0 → N,藉此觸發上面的重綁。\n if (rootRef.current) ro.observe(rootRef.current)\n measure()\n return () => ro?.disconnect()\n }, [])\n const widthMax = resolvePanelWidthMax(containerPx)\n const isOverlay = resolveIsOverlay(containerPx)\n const mode: AgentPanelMode = isOverlay ? 'overlay' : 'side-by-side'\n // 形態回報:**量到容器才發**(containerPx 初值 0 會被 resolveIsOverlay 讀成蓋板,那不是形態、是還沒量);\n // 回呼走 ref,消費端傳 inline 箭頭函式也不會每次 render 重發。\n const onModeChangeRef = React.useRef(onModeChange)\n onModeChangeRef.current = onModeChange\n const measured = containerPx > 0\n React.useEffect(() => {\n if (measured) onModeChangeRef.current?.(mode)\n }, [mode, measured])\n\n // v14 條 B:「窄螢幕以抽屜覆蓋宿主(左留視窗內距、底下鋪遮罩),**宿主暫不可操作**」\n //(遮罩的點擊行為 2026-09-17 改為關閉面板,見下方 showScrim 與 `onClose`)。\n // 「覆蓋 + 遮罩」是視覺、「不可操作」是行為 —— 兩件事,只做前者的話鍵盤照樣走得進去。\n // 實測(2026-09-08 跨模型審查)蓋板態下宿主 20 個控件有 19 個仍可聚焦,Enter 會執行。\n //\n // 用共用的並存 primitive 而不是「對兄弟節點設 inert」:兄弟迴圈只涵蓋宿主 DOM 裡的節點,\n // **body portal 出去的浮層(Dialog / FileViewer)完全不在裡面** ——\n // 窄版時那個 modal 會既蓋在上面又可以操作,兩條都違反條 B。\n // `suppressOthers([面板])` 是「保留這一塊、其餘全部抑制」,portal 出去的也照樣被抑制。\n // 保留集合 = 面板自己 + 呼叫端指定的宿主外常駐區(瀏覽器 chrome 等;見 `persistentElements` 說明)。\n // 蓋板態的遮罩也在保留集合裡:它必須**接住**留白處的指標(不被 suppressOthers 設成 inert),否則點擊會穿過去\n // 打到底下 modal 的外部點擊偵測、把 modal 關掉(2026-09-16 user:「點擊露出的遮罩會關閉 agent panel 底下的 modal」)。\n // 它在算洞時不會把自己或別的遮罩當洞(overlay-coexistence.ts boxes():遮罩不是洞)。\n const scrimRef = React.useRef<HTMLDivElement | null>(null)\n const keepPanel = React.useCallback(\n () => [rootRef.current as Element | null, scrimRef.current as Element | null, ...(persistentElements?.() ?? [])].filter((el): el is Element => !!el),\n [persistentElements],\n )\n // **量到之前不要動手**:`containerPx` 初值是 0,而 `resolveIsOverlay(0)` 會回 true\n // (0 < 960)。若不加這個條件,面板一掛載就先把整頁(含同時開著的對話框)抑制掉,\n // 等量測回來才解除 —— 實測那一下足以讓對話框帶著 inert 卡住,框內按鈕永遠 focus 不進去。\n // 量到 0 本來就不代表任何事(同 measure 裡的 `if (w > 0)` 那條)。\n useOverlayCoexistence(containerPx > 0 && isOverlay && selfVisible, keepPanel)\n\n // Esc 的作用域封閉在焦點所在區(`agent-panel.spec.md`「Esc 與關閉語意」三條表,2026-09-07 訂):\n // 焦點在面板內、面板內開著浮層 → 關那個最內層浮層,面板不動\n // 焦點在面板內、面板內沒有浮層 → **什麼都不關**\n // 焦點在面板外 → 關該區自己的浮層,**不跨區碰面板**\n // 但 Radix 的 `useEscapeKeydown` 在 **document 上用 capture** 監聽,\n // `dismissable-layer.tsx` 只把 Esc 送給「疊最上層」而**不看焦點在哪一區**。\n // 後果:舞台上開著 modal 時,在 agent 輸入框打字按 Esc 會關掉那個 modal —— 正是跨區。\n //\n // 攔法:掛在 **`window`** 的 capture 階段。捕獲順序是 window → document → …,\n // 所以它一定跑在 Radix 的 document capture 之前 —— 這是**結構上的先後**,\n // 不是「誰先註冊誰先跑」那種靠掛載順序的僥倖。\n // (第一版掛在 document 上,實測失敗:Dialog 在 JSX 裡排在面板前面,\n // 它的監聽先註冊、先跑、先 dismiss,我的 preventDefault 根本來不及。)\n // Radix 的 handler 寫著 `if (!event.defaultPrevented && onDismiss)` —— 看到已被\n // preventDefault 就不會 dismiss。不用 `stopImmediatePropagation`,那會連別人的合法處理一起吃掉。\n //\n // 會搶焦點的浮層(Popover / DropdownMenu / Dialog)因為焦點已經不在面板內,\n // 這裡不攔,它們照樣被自己的 layer 關掉 —— 那正是第一列要的行為。\n React.useEffect(() => {\n const onKeyDownCapture = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return\n const panel = rootRef.current\n const active = document.activeElement\n if (!panel || !active || !panel.contains(active)) return\n // 面板內若正開著 Tooltip(不搶焦點的浮層),這一下 Esc 該關它(spec:545 第一列),\n // 不能被我們吃掉 —— R3 實測 Tooltip 的 Esc 因此失效。\n if (document.querySelector('[role=\"tooltip\"]')) return\n event.preventDefault()\n }\n window.addEventListener('keydown', onKeyDownCapture, { capture: true })\n return () => window.removeEventListener('keydown', onKeyDownCapture, { capture: true })\n }, [])\n const [uncontrolledWidth, setUncontrolledWidth] = React.useState(defaultWidth)\n const resolvedWidth = clampPanelWidth(width ?? uncontrolledWidth, containerPx)\n\n const applyWidth = React.useCallback(\n (next: number, commit: boolean) => {\n const clamped = clampPanelWidth(next, containerPx)\n if (width === undefined) setUncontrolledWidth(clamped)\n // 每一格都發 onWidthChange:受控 consumer 才有拖曳中的即時回饋(原本只在放開時發 = 整段拖曳畫面不動);\n // 放開 / 鍵盤一步再發 onWidthCommit,要落地儲存的接這個。\n onWidthChange?.(clamped)\n if (commit) onWidthCommit?.(clamped)\n },\n [width, onWidthChange, onWidthCommit, containerPx],\n )\n\n if (!open) return null\n // 蓋板態的遮罩(2026-09-16 user:「底下會有滿版的遮罩,若點擊到該遮罩不會有任何反應…單純只是用來讓使用者知道 agent panel 底下還有東西」):\n // 重用 Dialog 並存時的同一支 `CoexistenceMask`(z-30、`--overlay`、替 persistentElements 挖洞),不手刻第二份遮罩(M17 / M23)。\n // - `absolute`:遮罩跟面板一樣覆蓋**容器**,不是視窗(spec「量的是容器不是視窗」;tailwind-merge 讓它覆掉預設的 `fixed`);\n // - 遮罩**接住**指標:點留白處 = 點到遮罩本身(→ `onClose`,見下)。第一版寫成 `pointer-events-none`,點擊穿過去\n // 打到底下並存 modal 的外部點擊偵測、把 modal 關掉(2026-09-16 user 第二次回報);所以它要在保留集合裡(不被設 inert)\n // 而且 Dialog 的並存遮罩算洞時把它當「遮罩不是洞」跳過(overlay-coexistence.ts `boxes()`),否則常駐殼裡多了一張全舞台的盒子,\n // Dialog 的遮罩會被整張挖空(2026-09-09 入口鈕裁切圖層的同款根因)。modal 的外部點擊守衛(createPersistentGuard)看到\n // 目標在保留區子樹裡就不關 —— 遮罩是常駐殼的子節點,自然在裡面。\n // - 只在量到容器且真的是蓋板時渲染(與 useOverlayCoexistence 的啟用條件同一組);\n // - 是面板根節點的**兄弟**不是子節點:根節點 z-[45] 自成堆疊脈絡,放進去遮罩就會壓過並存 modal(z-40),違反 dialog.spec 層級梯。\n // 幾何與「點遮罩關閉面板」由 `scripts/agent-panel-breakpoint.mjs` 機械守住;\n // 「`onClose` 必填、不得以 callback 有無當行為閘」由 `scripts/agent-panel-fixed-anatomy-invariant.mjs` 守住。\n const showScrim = containerPx > 0 && isOverlay && selfVisible\n return (\n <>\n {showScrim && (\n <CoexistenceMask\n ref={scrimRef}\n keep={keepPanel}\n data-agent-panel-scrim=\"\"\n // 點遮罩關面板(2026-09-17 user 裁示,取代 2026-09-16 的「點了不關」;兩條裁示逐字都在 spec 的來源總帳)。\n // 這一改讓它**回到** DS 既有的浮層語言:`../Dialog/dialog.spec.md`「Overlay click:點擊 overlay 關閉」、\n // 「洞外點下去是外部點擊 → 關閉(modal 語意)」—— 先前的「點了不關」才是那條線上的例外。\n // 並存 modal 時只關面板、modal 留著(2026-09-17 user 選 a 案):遮罩在面板的保留集合裡,\n // 並存 modal 的外部點擊守衛看到目標落在保留區子樹內就不關,所以並存邏輯一行都不用動;\n // 面板收掉後 modal 自然完整露出。鍵盤路徑不受影響(Esc 照舊)。\n onClick={onClose}\n className=\"absolute animate-in fade-in-0 duration-[var(--motion-duration-surface)] motion-reduce:animate-none\"\n />\n )}\n <div\n ref={(node) => {\n rootRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node\n }}\n role=\"complementary\"\n aria-label=\"智慧代理\" // i18n-allow: DS 預設,props 展開在後可覆寫\n // 蓋板態要讓 AT 知道它現在是蓋在內容上的一層,不是並排的一欄\n data-agent-panel-mode={mode}\n className={cn(\n // 不再 `overflow-hidden`(2026-09-29,待辦總帳 OE1;DataTable 表頭格 2026-09-10 AD63 同一條):它會把左緣把手\n // 跨到宿主那側的外側 3px 裁掉,7px 命中區只剩面板內的 4px 可點 —— resize-handle.spec.md「命中區」明寫\n // 消費端容器不得用 overflow:hidden 裁到它、要壓 flex `min-width:auto` 改 `min-w-0`。橫向不裁;縱向改 `overflow-y-clip`\n // (與 overflow-x:visible 並存不會被升成 auto、不成為捲動容器),讓貼底浮層的 slide-in 仍照舊被面板底緣裁住。\n // 閘:`scripts/agent-panel-breakpoint.mjs`「OE1 把手外側」(左緣外 2px 必命中把手;對照組注入 overflow:hidden 必紅)。\n 'relative flex h-full min-h-0 min-w-0 shrink-0 flex-col overflow-y-clip bg-surface',\n // 2026-09-07 G3:容器窄到並排放不下(< 960;2026-09-09 由 1080 放寬)就翻成蓋板。\n // 2026-09-16 user 裁示:蓋板不再蓋滿 —— 上下右貼齊容器、左邊留 Dialog 同一顆 `--layout-space-viewport-inset`(48px),\n // 底下鋪遮罩讓人知道面板下面還有東西(遮罩見上方 showScrim)。「蓋滿」原是 v14 條 B 的字,同日改字(v14 來源總帳 2026-09-16)。\n // 用 absolute 而不是把宿主推走:蓋板本來就不該改變底下內容的版面,\n // 而且回到寬螢幕時宿主不需要重新排版(避免來回切換時內容跳動)。\n // z-[60] 而不是 z-20:v14 條 B 的推導第 4 題「窄螢幕,agent 點有 URL 的 Modal →\n // 宿主開啟 Modal;agent 抽屜保持開啟,**Modal 在被蓋住的宿主區**」——\n // modal 必須在 agent **後方**。Dialog 是 body portal 且 `z-50`(dialog.tsx:46/113),\n // 而這個面板的祖先是 `position:relative; z-index:auto`(不建立堆疊脈絡),\n // 所以它直接跟 z-50 比大小 —— 用 z-20 會反過來被 modal 蓋住(2026-09-08 實測)。\n // 兩者的大小關係由 `scripts/agent-panel-breakpoint.mjs` 機械守住,不靠這行註解。\n // z-[45]:高於**並存面**(Dialog/FileViewer 有 persistentElements 時 z-40 —— v14 推導第 4 題\n // 「窄螢幕,URL Modal 在被蓋住的宿主區」),低於**一般確認框**(z-50 —— 條 A「沒有 URL 的\n // Modal 阻擋其餘介面,包含 agent」)。第一版寫 z-[60] 把所有 Dialog 都壓在下面,\n // 連確認框也被面板蓋住(R3 實測),那是把「URL Modal 在後方」錯推成「所有 Dialog 在後方」。\n // 蓋板 = 遮蓋型浮層:底色與陰影跟 Sheet 同一組(sheet.tsx `bg-surface-raised shadow-[var(--elevation-200)]`)——\n // `--surface` 在深色模式是半透明(semantic.css「非遮蓋型容器」),蓋在宿主上會讓底下文字透出來;\n // `--elevation-300` 不存在(最高階 200),舊寫法等於沒有陰影、留白處看到的是硬切線(2026-09-16 驗證抓到)。\n isOverlay && 'absolute inset-y-0 right-0 left-[var(--layout-space-viewport-inset)] z-[45] bg-surface-raised shadow-[var(--elevation-200)]',\n // 分隔線只有一個 owner:可拖時由 ResizeHandle 的 1px line 擁有(DataTable 欄間同款,hover/拖曳會變色);\n // 不可拖才由容器畫 border-l(app-shell aside 前例)。兩者並存 = 2px 粗線(2026-09-02 user 抓到)。\n !resizable && !isOverlay && 'border-l border-divider',\n 'animate-in fade-in-0 slide-in-from-right-4 duration-[var(--motion-duration-surface)] motion-reduce:animate-none',\n className,\n )}\n // 蓋板態寬度 = 容器 − 左內距(由上面的 inset-y-0 / right-0 / left-[inset] 決定),不吃拖曳出來的值(拖曳把手在蓋板態也不渲染)\n style={{ ...(isOverlay ? null : { width: resolvedWidth }), ...style }}\n {...props}\n >\n {resizable && !isOverlay && (\n // 同一顆 ResizeHandle 擁有視覺 / 拖拉 / 鍵盤 / ARIA(DataTable 欄寬同元件,2026-09-02 SSOT 收斂);\n // 面板寬 clamp(360–640 且 ≤50vw)由 applyWidth 負責。\n <ResizeHandle\n direction=\"horizontal\"\n position=\"start\"\n value={resolvedWidth}\n min={PANEL_WIDTH_MIN}\n max={widthMax}\n step={PANEL_RESIZE_KEY_STEP}\n ariaLabel=\"調整面板寬度\" // i18n-allow: DS 預設文案\n className=\"z-10\"\n onValueChange={(next) => applyWidth(next, false)}\n onValueCommit={(next) => applyWidth(next, true)}\n />\n )}\n {children}\n </div>\n </>\n )\n },\n)\nAgentPanel.displayName = 'AgentPanel'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 2. AgentPanelHeader(標題列)+ 歷史浮層 / 改名 / 刪除\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentConversationSummary {\n id: string\n title: string\n /** 分組標題(如「今天」「過去 7 天」);同組相鄰排列。 */\n group?: string\n /** 代理仍在回覆:列首圖示原地換 CircularProgress 16,等寬等高不動版面。 */\n thinking?: boolean\n}\n\nexport interface AgentPanelHeaderProps\n extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {\n /** 目前對話標題(標題本身=歷史浮層觸發鈕)。 */\n title: string\n /** 歷史浮層搜尋 placeholder(i18n override)。 */\n historySearchPlaceholder?: string\n /** 歷史浮層無結果文案(i18n override)。 */\n historyEmptyText?: string\n /** 標誌狀態(代理思考中傳 \"think\")。 */\n logoState?: AgentLogoState\n /** 歷史對話清單;空清單=浮層顯示無結果(觸發鈕恆在)。 */\n conversations?: AgentConversationSummary[]\n /** 目前對話 id(歷史清單高亮)。 */\n activeConversationId?: string\n /** 目前對話尚無已送出訊息=本身就是新對話 → 「+ 新對話」停用。 */\n conversationEmpty?: boolean\n /** 歷史浮層初始開啟(展示/快照用;M15 OpenSnapshot)。 */\n defaultHistoryOpen?: boolean\n onSelectConversation?: (id: string) => void\n /** 改名確認(Dialog 流程由元件內建)。 */\n onRenameConversation?: (id: string, title: string) => void\n /**\n * 刪除確認(Dialog 流程由元件內建)。consumer 契約:刪的是目前對話 → 切到最近一則;\n * 全部刪光 → 面板回空狀態(spec「附:歷史浮層」)。\n */\n onDeleteConversation?: (id: string) => void\n /** 固定構件:+ 恆渲染,主流程無內建行為 → 必填。 */\n onNewConversation: () => void\n /** 固定構件:× 恆渲染,面板 open 是 consumer state → 必填。 */\n onClose: () => void\n}\n\n// ── 鍵盤:歷史列上的「改名 / 刪除」(2026-09-25 待辦總帳 B9「路線乙」)──\n// 決策出處 = governance/planning/2026-09-25-interaction-and-hover-remediation.md B9(該列點名「AI 面板對話紀錄列」),\n// user 逐字(附條件同意,條件查證成立記在同列):「確定建議符合我們一致的設計語言且不違背世界級的設計就照建議」。\n// 鍵盤路整條由 Command 本身提供(command.tsx routeCommandRowKeys,判定 = lib/roving-list-keyboard.ts:列裡的鈕 -1、→ 進 / ← 回 /\n// ↑↓ Tab 回搜尋框、Enter / Space 屬於那顆鈕),SelectMenu 的人員頭像走同一份;本檔只負責「鍵盤反白這一列時浮出改名 / 刪除」(見 HistoryRow)。\n// 按鍵表住 agent-panel.spec.md「附:歷史浮層」與 command.spec.md「A11y」。2026-09-25 前:每一列的改名 / 刪除都在 Tab 路上(4 列 = 8 站)。\n\n/** 歷史列(select-menu.tsx 原型):外層 CommandItem 單一互動 owner;內層 MenuItem 純視覺。 */\nfunction HistoryRow({\n conversation,\n selected,\n onSelect,\n onRename,\n onDelete,\n}: {\n conversation: AgentConversationSummary\n selected: boolean\n onSelect: () => void\n onRename: () => void\n onDelete: () => void\n}) {\n // 鍵盤反白停在這一列時浮出改名 / 刪除(keyboard-model-canonical「列上有小按鈕的一串」:鍵盤走到的那顆鈕要看得見;\n // cmdk 清單的「焦點在這一項」就是鍵盤反白,AI 推導,見上方段落)。只在反白是鍵盤搬的時候 —— 滑鼠搬的反白就是滑鼠正停著的列,\n // group-hover 本來就浮出;滑鼠離開清單後 cmdk 仍留著反白,不額外讓那一列的鈕常駐(滑鼠畫面不變)。\n const cursorByKeyboard = useCursorMover() === 'keyboard'\n return (\n <CommandItem\n value={conversation.id}\n keywords={[conversation.title]}\n onSelect={onSelect}\n // 游標與選中的長相全部由 CommandItem 統一畫(指標模態底色 / 鍵盤模態畫框 / 選中底色釘住;\n // focus-canonical 規則二 + item-anatomy「選中 × 互動疊加」);本列只交 `selected`,不再手刻一份\n //(2026-09-09 之前這裡自己寫了一份 not-hover:focus-ring-inset,與 CommandItem 重複)。\n selected={selected}\n className=\"group/menu-item\"\n >\n <MenuItem\n labelMaxLines={1}\n role=\"presentation\"\n selected={selected}\n className=\"!bg-transparent hover:!bg-transparent\"\n startContent={\n conversation.thinking ? (\n <CircularProgress size={16} aria-label=\"回覆中\" /> // i18n-allow: DS 預設\n ) : (\n <MessageSquare size={16} aria-hidden className=\"text-fg-muted\" />\n )\n }\n endContent={\n // 行內動作恆在 DOM;鍵盤用 → 進得去、不在 Tab 路上(B9,Command 的 routeCommandRowKeys 提供);\n // 懸停/focus-visible 瞬間出現(不淡入,待辦總帳 L9)=ItemSuffix hoverReveal SSOT,鍵盤反白這一列時也浮出(cursorByKeyboard)。\n /* MenuItem 的 endContent slot 內再包 ItemSuffix 只為 hoverReveal(opacity 0→1,瞬間);兩層同盒\n (h-[1lh] items-center ml-auto gap-2),不疊任何位移——非 drift(2026-09-02 覆核實測)。 */\n <ItemSuffix\n hoverReveal\n hoverGroup=\"menu-item\"\n className={cursorByKeyboard ? 'group-data-[selected=true]/menu-item:opacity-100' : undefined}\n >\n {/* Enter/Space 在行內動作上 = 啟動該動作、不選列 —— 由 Command 根的 routeCommandRowKeys 統一處理\n (2026-09-26 之前這裡另寫了一份 onKeyDown 做同一件事,兩份並存;待辦總帳〇節「按鍵規則合併」收回 command.tsx)。\n data-history-row-actions = 量測腳本找「這一列自己的鈕」的錨點。 */}\n <span className=\"contents\" data-history-row-actions=\"\">\n <ItemInlineAction\n action={{\n icon: Pencil,\n label: '改名', // i18n-allow: DS 預設文案(Dialog「關閉」同前例)\n onClick: (e) => {\n e?.stopPropagation()\n onRename()\n },\n }}\n />\n <ItemInlineAction\n action={{\n icon: Trash2,\n label: '刪除', // i18n-allow: DS 預設文案(Dialog「關閉」同前例)\n onClick: (e) => {\n e?.stopPropagation()\n onDelete()\n },\n }}\n />\n </span>\n </ItemSuffix>\n }\n >\n {conversation.title}\n </MenuItem>\n </CommandItem>\n )\n}\n\nconst AgentPanelHeader = React.forwardRef<HTMLElement, AgentPanelHeaderProps>(\n (\n {\n title,\n logoState = 'still',\n historySearchPlaceholder = '搜尋對話', // i18n-allow: DS 預設文案,prop 可覆寫\n historyEmptyText = '沒有對話', // i18n-allow: DS 預設文案(2026-09-08 一句到底,對應 No options;沒有對話與搜尋無結果共用),prop 可覆寫\n conversations = [],\n activeConversationId,\n conversationEmpty = false,\n defaultHistoryOpen = false,\n onSelectConversation,\n onRenameConversation,\n onDeleteConversation,\n onNewConversation,\n onClose,\n className,\n ...props\n },\n ref,\n ) => {\n const [historyOpen, setHistoryOpen] = React.useState(defaultHistoryOpen)\n const [renameTarget, setRenameTarget] = React.useState<AgentConversationSummary | null>(null)\n const [deleteTarget, setDeleteTarget] = React.useState<AgentConversationSummary | null>(null)\n const triggerRef = React.useRef<HTMLButtonElement>(null)\n /** Dialog 關閉後焦點回歷史觸發鈕(Popover 已因焦點外移關閉;WCAG 2.4.3)。 */\n // Dialog 關閉後焦點:歷史浮層仍開 → 交給 Radix 還原到觸發它的行內動作(改名/刪除);浮層已關\n // → 延到下一個 macrotask 回標題觸發(晚於 FocusScope 還原到已消失元素 → body 的動作,2026-09-02 實測)。\n const historyOpenRef = React.useRef(historyOpen)\n historyOpenRef.current = historyOpen\n // 觸發器失去版面時關掉歷史浮層(2026-09-10 實測兩條路徑):宿主用 display:none 收起 keep-mounted 的面板\n // (AgentPanelDock,路由切換 / 全域快捷鍵這類不經指標與焦點的關閉)、或 Storybook 把整頁 docs 藏起來 —— 浮層 portal 到 body\n // 不會跟著消失,Radix 對 0×0 的錨點會把它定位到視窗左上角 (0, 8),焦點還留在裡面。ResizeObserver 在元素變成\n // display:none 時會回報 0×0;掛上時的第一次回呼帶真實尺寸,可見的觸發器不會被誤關。\n React.useEffect(() => {\n const el = triggerRef.current\n if (!historyOpen || !el || typeof ResizeObserver === 'undefined') return\n const ro = new ResizeObserver(() => {\n if (el.getClientRects().length === 0) setHistoryOpen(false)\n })\n ro.observe(el)\n return () => ro.disconnect()\n }, [historyOpen])\n const returnFocus = () => {\n window.setTimeout(() => {\n if (historyOpenRef.current) return\n triggerRef.current?.focus({ preventScroll: true })\n }, 0)\n }\n\n const groups = React.useMemo(() => {\n const order: string[] = []\n const byGroup = new Map<string, AgentConversationSummary[]>()\n for (const item of conversations) {\n const key = item.group ?? ''\n if (!byGroup.has(key)) {\n byGroup.set(key, [])\n order.push(key)\n }\n byGroup.get(key)!.push(item)\n }\n return order.map((key) => ({ label: key, items: byGroup.get(key)! }))\n }, [conversations])\n\n // 標題群 ↔ 動作群 gap = loose(2026-09-02 user 拍板:chevron 與右側按鈕至少 --layout-space-loose;\n // ChromeHeader 預設 gap-2 是 slot 內間距,長標題截斷時 chevron 會貼到 28px 圖示鈕被讀成同一群)。\n return (\n <ChromeHeader ref={ref} className={cn('gap-[var(--layout-space-loose)] bg-surface', className)} {...props}>\n <div className=\"flex min-w-0 flex-1 items-center gap-2\">\n <AgentLogo state={logoState} size={24} />\n <Popover open={historyOpen} onOpenChange={setHistoryOpen}>\n <PopoverTrigger asChild>\n {/* 標題+chevron 複合觸發:幾何沿用品牌區前例(238cdf91:gap-2 / 零 padding);\n **chevron 是 20 不是 16** —— 標題是 text-body-lg,依「字級↔icon tier」對齊 ICON_SIZE.lg\n (見下方 ChevronDown 的註解與 spec「箭頭 20」);chevron 純指示、fg-muted 靜色、\n 無懸停底(同 AgentThinking 標題列);原生 button 承接 Radix Slot props。 */}\n <button\n ref={triggerRef}\n type=\"button\"\n aria-haspopup=\"dialog\"\n aria-expanded={historyOpen}\n className={cn(\n 'flex min-w-0 max-w-full cursor-pointer items-center gap-2 p-0 text-left',\n 'rounded-sm ',\n )}\n >\n {/* 單行截斷 → 截斷時才顯 tooltip 補全(tooltip.spec.md:32;引擎 truncated-text.spec.md),\n 禁手刻 truncate span。 */}\n <TruncatedText className=\"text-body-lg font-medium\">{title}</TruncatedText>\n {/* 指示 chevron 與 Select 觸發器逐字同款:同色 text-fg-muted、同線粗、同「字級↔icon tier」\n (標題 text-body-lg = Select lg → ICON_SIZE.lg 20)、開啟時 rotate-180。 */}\n <ChevronDown\n size={ICON_SIZE.lg}\n aria-hidden\n className={cn('shrink-0 text-fg-muted transition-transform motion-reduce:duration-0', historyOpen && 'rotate-180')}\n />\n </button>\n </PopoverTrigger>\n {/* 寬度 = Popover canonical w-72(288;popover.tsx 預設,不另訂):介於 ChatGPT 側欄 260 /\n Claude 側欄 290(2026-09-02 實測),且在面板最窄 360 時仍容得下(標題左緣起 312)。\n 與觸發點距 = OVERLAY_SIDE_OFFSET 8(elevation.spec.md)。 */}\n <PopoverContent\n align=\"start\"\n aria-label=\"歷史對話\" // i18n-allow: DS 預設文案\n className=\"overflow-hidden p-0\"\n >\n <Command label=\"歷史對話\">\n {/* 搜尋列幾何 = CommandInput SSOT(2026-09-08 刪掉這裡的第二份 py/h 覆寫) */}\n <CommandInput\n placeholder={historySearchPlaceholder}\n aria-label={historySearchPlaceholder}\n />\n <CommandEmpty>{historyEmptyText}</CommandEmpty>\n <CommandList label=\"對話\">\n {groups.map(({ label, items }) => (\n <React.Fragment key={label || '(ungrouped)'}>\n <CommandGroup\n heading={label ? <MenuItem header>{label}</MenuItem> : undefined}\n >\n {items.map((conversation) => (\n <HistoryRow\n key={conversation.id}\n conversation={conversation}\n selected={conversation.id === activeConversationId}\n onSelect={() => {\n onSelectConversation?.(conversation.id)\n setHistoryOpen(false)\n }}\n onRename={() => setRenameTarget(conversation)}\n onDelete={() => setDeleteTarget(conversation)}\n />\n ))}\n </CommandGroup>\n </React.Fragment>\n ))}\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n </div>\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"text\"\n size=\"sm\"\n iconOnly\n startIcon={Plus}\n aria-label=\"新對話\" // i18n-allow: DS 預設文案(Dialog「關閉」同前例)\n disabled={conversationEmpty}\n onClick={onNewConversation}\n />\n <ButtonDivider />\n <Button dismiss size=\"sm\" startIcon={XIcon} aria-label=\"關閉面板\" onClick={onClose} />\n </div>\n {renameTarget && (\n <AgentRenameDialog\n conversation={renameTarget}\n onOpenChange={(next) => {\n if (!next) {\n setRenameTarget(null)\n returnFocus()\n }\n }}\n onConfirm={(nextTitle) => {\n onRenameConversation?.(renameTarget.id, nextTitle)\n setRenameTarget(null)\n returnFocus()\n }}\n />\n )}\n {deleteTarget && (\n <Dialog\n open\n onOpenChange={(next) => {\n if (!next) {\n setDeleteTarget(null)\n returnFocus()\n }\n }}\n >\n {/* 確認框/短表單:autoHeight 隨內容(dialog.spec.md 高度行為)、寬 440(DS 五個確認框 story 慣例)。 */}\n <DialogContent autoHeight maxWidth={440}>\n <DialogHeader>\n <DialogTitle>刪除對話</DialogTitle>\n </DialogHeader>\n <DialogBody>\n 確定刪除「{deleteTarget.title}」?此動作立即生效且不可復原。\n </DialogBody>\n <DialogFooter>\n <Button variant=\"tertiary\" onClick={() => { setDeleteTarget(null); returnFocus() }}>\n 取消\n </Button>\n <Button\n variant=\"primary\"\n danger\n onClick={() => {\n onDeleteConversation?.(deleteTarget.id)\n setDeleteTarget(null)\n returnFocus()\n }}\n >\n 刪除\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )}\n </ChromeHeader>\n )\n },\n)\nAgentPanelHeader.displayName = 'AgentPanelHeader'\n\n/** 改名 Dialog:Field+Input 預填全選;儲存=更新類 dirty 規則;空名 blur 顯錯;Esc=Dialog 取消。 */\nfunction AgentRenameDialog({\n conversation,\n onOpenChange,\n onConfirm,\n}: {\n conversation: AgentConversationSummary\n onOpenChange: (open: boolean) => void\n onConfirm: (title: string) => void\n}) {\n const [value, setValue] = React.useState(conversation.title)\n const [touched, setTouched] = React.useState(false)\n const trimmed = value.trim()\n const dirty = trimmed !== conversation.title\n const empty = trimmed.length === 0\n const showError = touched && empty\n const commit = () => {\n setTouched(true)\n if (empty || !dirty) return\n onConfirm(trimmed)\n }\n return (\n <Dialog open onOpenChange={onOpenChange}>\n {/* 確認框/短表單:autoHeight 隨內容(dialog.spec.md 高度行為)、寬 440(DS 五個確認框 story 慣例)。 */}\n <DialogContent autoHeight maxWidth={440}>\n <DialogHeader>\n <DialogTitle>改名對話</DialogTitle>\n </DialogHeader>\n <DialogBody>\n <Field required invalid={showError}>\n <FieldLabel>名稱</FieldLabel>\n <Input\n value={value}\n error={showError}\n onChange={(e) => setValue(e.target.value)}\n onFocus={(e) => e.currentTarget.select()}\n onBlur={() => setTouched(true)}\n onKeyDown={(e) => {\n // form-validation:Enter=等同 blur(觸發驗證並提交);Esc 由 Dialog 承接=取消。\n if (e.key === 'Enter') {\n e.preventDefault()\n commit()\n }\n }}\n />\n {showError && <FieldError>名稱不可空白</FieldError>}\n </Field>\n </DialogBody>\n <DialogFooter>\n <Button variant=\"tertiary\" onClick={() => onOpenChange(false)}>\n 取消\n </Button>\n <Button variant=\"primary\" disabled={!dirty || empty} onClick={commit}>\n 儲存\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 3. AgentConversation(訊息卷軸區)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport type AgentConversationProps = React.HTMLAttributes<HTMLDivElement>\n\n/** 最後一則代理訊息的工具列常駐(其餘懸停);由 AgentConversation 判定,consumer 不設(SSOT)。 */\nconst LastAgentMessageContext = React.createContext<boolean>(false)\n\nconst AgentConversation = React.forwardRef<HTMLDivElement, AgentConversationProps>(\n ({ className, children, ...props }, ref) => {\n // 找最後一則 role=\"agent\" 的直接子訊息:它的工具列常駐,其他訊息懸停才顯(spec「AgentToolbar」)。\n const items = React.Children.toArray(children)\n let lastAgentIndex = -1\n items.forEach((child, index) => {\n if (React.isValidElement<AgentMessageProps>(child) && child.type === AgentMessage && (child.props.role ?? 'agent') === 'agent') {\n lastAgentIndex = index\n }\n })\n // 自動捲到最新:掛載時與訊息數增加時捲到底(使用者若已往上捲離底部 > 40px 則不打擾;\n // ChatGPT / Claude 皆「貼底跟隨、離底不搶」);全家族一致,consumer 不自接。\n const logRef = React.useRef<HTMLDivElement | null>(null)\n React.useImperativeHandle(ref, () => logRef.current as HTMLDivElement)\n const wasNearBottomRef = React.useRef(true)\n // 上次在「面板看得見」時停在哪 —— 用來在面板從隱藏回來時把位置補回去(spec E 條「閱讀位置保存」)。\n const savedTopRef = React.useRef<number | null>(null)\n React.useLayoutEffect(() => {\n const log = logRef.current\n const viewport = log?.closest<HTMLElement>('[data-radix-scroll-area-viewport]')\n if (!log || !viewport) return\n // 2026-09-07 G2:面板關閉時走 `display:none`(不再卸載)。實測祖先被 display:none 之後\n // **瀏覽器會把捲動位置歸零**,而且 ResizeObserver 會以 0×0 觸發一次 ——\n // 那一刻量到的 scrollHeight / clientHeight / scrollTop 全是 0,拿去更新狀態就會\n // 把「使用者剛剛在哪」洗成「貼在底部」。所以兩個 handler 都先擋掉沒有版面的情況,\n // 這跟 person-display 的 `availablePx <= 0 → 不更新` 是同一條原則:\n // **沒有版面時量到的數字不代表任何事,不能拿來做決定。**\n const hasLayout = () => viewport.clientHeight > 0\n const stick = () => {\n if (!hasLayout()) return\n if (wasNearBottomRef.current) { viewport.scrollTop = viewport.scrollHeight; return }\n // 從隱藏回來:位置被歸零了,補回上次看得見時的位置。\n // 只在「現在是 0、而且記得的不是 0」時才補 —— 使用者本來就停在頂端時 saved 也是 0,不會誤補。\n if (savedTopRef.current !== null && savedTopRef.current > 0 && viewport.scrollTop === 0) {\n viewport.scrollTop = savedTopRef.current\n }\n }\n stick()\n const onScroll = () => {\n if (!hasLayout()) return\n savedTopRef.current = viewport.scrollTop\n wasNearBottomRef.current = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight <= 40\n }\n viewport.addEventListener('scroll', onScroll, { passive: true })\n // 量**內容高度**而不是訊息則數:代理回覆是串流寫進同一則訊息的,則數不變但高度一直長,\n // 只看則數會讓整段回覆期間都不跟隨(ChatGPT / Claude 皆貼底跟隨)。\n const ro = new ResizeObserver(stick)\n ro.observe(log)\n return () => {\n viewport.removeEventListener('scroll', onScroll)\n ro.disconnect()\n }\n }, [])\n return (\n // 捲軸必用 ScrollArea(跨 OS 一致;Dialog body 同法)。\n <ScrollArea fillX className=\"min-h-0 flex-1\">\n <div\n ref={logRef}\n role=\"log\"\n aria-live=\"polite\"\n className={cn(\n // 輪距 40 = 8 + 24(工具列)+ 8;懸停工具列絕對定位於輪距內,出現不推擠。\n // 底部 = --layout-space-bottom 48:最後內容(常駐工具列)→ 輸入盒動作(送出)= layoutSpace 規則 4\n // 「內容 → action button = bottom」(layoutSpace.spec.md L118;2026-09-02 user 抓工具列貼輸入盒)。\n 'flex flex-col gap-10 p-[var(--layout-space-loose)] pb-[var(--layout-space-bottom)]',\n className,\n )}\n {...props}\n >\n {items.map((child, index) => (\n <LastAgentMessageContext.Provider key={(React.isValidElement(child) && child.key) || index} value={index === lastAgentIndex}>\n {child}\n </LastAgentMessageContext.Provider>\n ))}\n </div>\n </ScrollArea>\n )\n },\n)\nAgentConversation.displayName = 'AgentConversation'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 4. AgentMessage(訊息)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentAttachment {\n id: string\n label: string\n}\n\nexport interface AgentMessageProps extends React.HTMLAttributes<HTMLDivElement> {\n /** 訊息角色:user=我方氣泡靠右;agent=無氣泡全寬。 */\n role?: 'user' | 'agent'\n /** 氣泡內文字上方的附件(送出後視覺=Chip assist 分支)。 */\n attachments?: AgentAttachment[]\n onAttachmentClick?: (attachment: AgentAttachment) => void\n /** 訊息工具列(AgentToolbar);絕對定位於輪距內。 */\n toolbar?: React.ReactNode\n}\n\nconst AgentMessage = React.forwardRef<HTMLDivElement, AgentMessageProps>(\n (\n { role = 'agent', attachments, onAttachmentClick, toolbar, className, children, ...props },\n ref,\n ) => {\n const isUser = role === 'user'\n return (\n <div\n ref={ref}\n className={cn('group/agent-message relative', isUser && 'flex justify-end', className)}\n {...props}\n >\n <div\n className={cn(\n 'text-body text-foreground',\n isUser\n ? [\n 'max-w-[85%] rounded-md bg-secondary px-3 py-2',\n 'animate-in fade-in-0 slide-in-from-bottom-2 duration-[var(--motion-duration-overlay)] motion-reduce:animate-none',\n ]\n : 'w-full [&_a]:text-primary [&_a:hover]:text-primary-hover [&_a]:underline-offset-2 [&_a]:underline' // spec:151 長文閱讀需要底線可掃描(2026-09-08 從 hover 才畫改回恆畫),\n )}\n >\n {attachments && attachments.length > 0 && (\n // chip 相互垂直/水平 4(=Combobox 內 Tag 區間距;2026-09-02 拍板)。\n <div className=\"mb-2 flex flex-wrap gap-1\">\n {attachments.map((attachment) => (\n <Chip\n key={attachment.id}\n variant=\"assist\"\n aria-label={`附件:${attachment.label}`}\n onClick={() => onAttachmentClick?.(attachment)}\n >\n {attachment.label}\n </Chip>\n ))}\n </div>\n )}\n {children}\n </div>\n {toolbar}\n </div>\n )\n },\n)\nAgentMessage.displayName = 'AgentMessage'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 5. AgentThinking(思考塊)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentThinkingProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {\n /** 進行中:標題「思考中」+微光;完成:「思考過程」靜態。 */\n thinking?: boolean\n /** 已完成的步驟(靜態,fg-secondary)。 */\n steps?: React.ReactNode[]\n /** 正在寫入的最新一行(僅此行與標題套微光)。 */\n currentStep?: React.ReactNode\n /** 開合(未受控時:回覆中自動展開、回覆完自動收合)。 */\n open?: boolean\n onOpenChange?: (open: boolean) => void\n}\n\nconst AgentThinking = React.forwardRef<HTMLDivElement, AgentThinkingProps>(\n ({ thinking = false, steps, currentStep, open, onOpenChange, className, ...props }, ref) => {\n // 非受控:AI 回覆中自動展開、回覆完自動收合(拍板;三套元件庫一致慣例)。\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(thinking)\n React.useEffect(() => {\n if (open === undefined) setUncontrolledOpen(thinking)\n }, [thinking, open])\n const resolvedOpen = open ?? uncontrolledOpen\n const handleOpenChange = (next: boolean) => {\n setUncontrolledOpen(next)\n onOpenChange?.(next)\n }\n return (\n <CollapsiblePrimitive.Root\n ref={ref}\n open={resolvedOpen}\n onOpenChange={handleOpenChange}\n className={cn('text-body', className)}\n {...props}\n >\n <CollapsiblePrimitive.Trigger\n className={cn(\n 'group/agent-thinking flex cursor-pointer items-center gap-1 text-fg-secondary hover:text-foreground',\n // 焦點框往外(= 什麼都不寫,吃 styles/base.css 全域規則)。\n // 2026-09-10 翻案:原本寫「往外 +2px 實測會壓到下方展開的思考內容(overflow-hidden 的 collapsible)」——\n // 那句沒有量過。實測(展開與收合、1440 / 700 / 420 三種寬、三個實例):上 40 / 右 322 / 下 8 / 左 15,\n // **四周最小 8px**,往外只需要 4px。那個 collapsible 的外框確實從標題底邊 0px 開始,但它是**兄弟節點**\n //(不裁任何東西)而且背景全透明,裡面第一個真的畫出線的元素在 8px 外 —— 依 focus-canonical「問題二」\n // 的「正當障礙」定義(會碰撞的鄰居或會切掉框的邊界),透明的兄弟盒不是障礙。\n 'rounded-sm',\n )}\n >\n <span className={cn(thinking && 'agent-shimmer')}>\n {thinking ? '思考中' : '思考過程'}\n </span>\n {/* chevron=裝飾指示(accordion 慣例),不吃微光;色同 Select 觸發器 chevron(fg-muted)。 */}\n <ChevronDown\n size={16}\n aria-hidden\n className=\"shrink-0 text-fg-muted transition-transform duration-[var(--motion-duration-overlay)] motion-reduce:duration-0 group-data-[state=open]/agent-thinking:rotate-180\"\n />\n </CollapsiblePrimitive.Trigger>\n <CollapsiblePrimitive.Content\n className=\"overflow-hidden data-[state=open]:animate-collapsible-down data-[state=closed]:animate-collapsible-up motion-reduce:animate-none\"\n >\n {/* 完成步驟=fg-secondary(2026-09-02 拍板;原 muted 太淺);微光行基色由 agent-panel.css 自管。 */}\n <div className=\"mt-2 flex flex-col gap-1 border-l border-divider pl-3 text-fg-secondary\">\n {steps?.map((step, index) => <div key={index}>{step}</div>)}\n {currentStep != null && (\n <div className={cn(thinking && 'agent-shimmer')}>{currentStep}</div>\n )}\n </div>\n </CollapsiblePrimitive.Content>\n </CollapsiblePrimitive.Root>\n )\n },\n)\nAgentThinking.displayName = 'AgentThinking'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 6. AgentToolbar(訊息工具列;固定 anatomy 恆渲染)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentToolbarProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * 常駐顯示。預設由 AgentConversation 判定:代理**最後一則**常駐,其餘懸停時瞬間出現(SSOT,consumer 不需設);\n * 只在 AgentConversation 之外單獨使用時才需手動指定。\n */\n pinned?: boolean\n // 固定 anatomy:三顆鈕恆渲染且沒有內建行為 → 型別層必填,少接就編譯不過(M23(f):\n // 「無內建行為的 callback 一律必填 prop」;可選會變成點了沒反應的死鈕)。\n onCopy: () => void\n onLike: () => void\n onDislike: () => void\n}\n\nconst AgentToolbar = React.forwardRef<HTMLDivElement, AgentToolbarProps>(\n ({ pinned: pinnedProp, onCopy, onLike, onDislike, className, children, ...props }, ref) => {\n const pinnedFromConversation = React.useContext(LastAgentMessageContext)\n const pinned = pinnedProp ?? pinnedFromConversation\n return (\n <div\n ref={ref}\n className={cn(\n // 懸停/鍵盤聚焦時「出現」是滑過造成的變化 → 瞬間出現、不淡入(user 2026-09-26 對「全部瞬間」延伸(AI 的題目名)答「確定這樣才是一致設計語言就做」到所有滑過造成的變化;\n // SSOT = tokens/motion/motion.spec.md「hover 回饋不做過渡」;待辦總帳 L9)。訊息進場的淡入是另一件事(內容出現),不在此。\n 'mt-2 flex h-6 items-center gap-2',\n // 常駐(最後一則)= 在流內佔位,底部才能守 --layout-space-bottom;懸停顯示 = 絕對定位於輪距內,\n // 出現/消失完全不推擠版面(輪距 40 ≥ 8+24+8)。\n pinned\n ? 'relative opacity-100'\n : 'absolute left-0 top-full opacity-0 group-hover/agent-message:opacity-100 focus-within:opacity-100',\n className,\n )}\n {...props}\n >\n <Button variant=\"text\" size=\"xs\" iconOnly startIcon={Copy} aria-label=\"複製\" onClick={onCopy} />\n <ButtonDivider />\n <Button variant=\"text\" size=\"xs\" iconOnly startIcon={ThumbsUp} aria-label=\"讚\" onClick={onLike} />\n <Button variant=\"text\" size=\"xs\" iconOnly startIcon={ThumbsDown} aria-label=\"倒讚\" onClick={onDislike} />\n {children}\n </div>\n )\n },\n)\nAgentToolbar.displayName = 'AgentToolbar'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 7. AgentPromptInput(複合輸入盒;固定 anatomy 恆渲染)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentPromptAttachment {\n id: string\n label: string\n}\n\nexport interface AgentPromptInputProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSubmit'> {\n value: string\n onValueChange: (value: string) => void\n /** 送出(Enter / 送出鈕);無內建行為 → 必填。 */\n onSubmit: () => void\n /** 代理進行中:送出鈕同位換停止(實心正方),0.15s 淡切。 */\n busy?: boolean\n onStop?: () => void\n /** 輸入中附件(Tag md 恆帶 ×;超寬 +N;送出後於訊息內轉 Chip assist 視覺)。 */\n attachments?: AgentPromptAttachment[]\n /** 固定構件:每個 Tag 的 × 恆渲染 → 必填。 */\n onRemoveAttachment: (attachment: AgentPromptAttachment) => void\n /** 固定構件:工具列 + 恆渲染 → 必填。 */\n onAddAttachment: () => void\n placeholder?: string\n}\n\n/** 附件單列 + 超寬 +N(useOverflowIndices 量測;Combobox 多選 Tag 區同族)。 */\nfunction PromptAttachmentRow({\n attachments,\n onRemove,\n}: {\n attachments: AgentPromptAttachment[]\n onRemove: (attachment: AgentPromptAttachment) => void\n}) {\n const { containerRef, registerItem, overflowIndices } = useOverflowIndices<HTMLDivElement>({\n reserveTriggerWidth: 48,\n })\n const hidden = new Set(overflowIndices)\n const hiddenItems = attachments.filter((_, i) => hidden.has(i))\n return (\n // 附件列 28:Tag 相互間距 4、距內緣 4;單列不換行,溢出以 +N 收納。\n // 被藏的 Tag 留在 flow 內、排到 +N 之後(order-last)並隱形:useOverflowIndices 每次重量都拿得到\n // 真實位置(抽離 flow 會在放寬時被誤判「可見」而失去 +N,2026-09-02 實測)。\n <div ref={containerRef} className=\"flex items-center gap-1 overflow-hidden px-1 pt-1\">\n {attachments.map((attachment, index) => (\n <div\n key={attachment.id}\n ref={registerItem(index)}\n className={cn('shrink-0', hidden.has(index) && 'invisible order-last')}\n >\n <Tag size=\"md\" onRemove={() => onRemove(attachment)}>\n {attachment.label}\n </Tag>\n </div>\n ))}\n {hiddenItems.length > 0 && (\n <OverflowIndicator count={hiddenItems.length} shape=\"tag\" size=\"md\">\n {hiddenItems.map((attachment) => (\n <Tag key={attachment.id} size=\"md\" onRemove={() => onRemove(attachment)}>\n {attachment.label}\n </Tag>\n ))}\n </OverflowIndicator>\n )}\n </div>\n )\n}\n\nconst AgentPromptInput = React.forwardRef<HTMLDivElement, AgentPromptInputProps>(\n (\n {\n value,\n onValueChange,\n onSubmit,\n busy = false,\n onStop,\n attachments = [],\n onRemoveAttachment,\n onAddAttachment,\n placeholder = '輸入訊息…',\n className,\n ...props\n },\n ref,\n ) => {\n const canSubmit = value.trim().length > 0\n const submit = () => {\n if (busy || !canSubmit) return\n onSubmit()\n }\n return (\n <div\n ref={ref}\n className={cn(\n 'm-[var(--layout-space-loose)] mt-0 shrink-0 rounded-md',\n // 外框互動 = Field 家族 default chrome SSOT(field-wrapper.tsx fieldChromeStyles:單行 wrapper /\n // Textarea / 複合輸入盒三宿主同一份 compounds):hover 一階 border-hover、focus-within 主色;\n // 2026-09-02 user 抓「跟 Textarea 不一樣」→ 收斂為單一住所,禁自刻。\n fieldChromeStyles({ mode: 'edit', variant: 'default', error: false }),\n className,\n )}\n {...props}\n >\n {attachments.length > 0 && (\n <PromptAttachmentRow attachments={attachments} onRemove={onRemoveAttachment} />\n )}\n <textarea\n value={value}\n onChange={(e) => onValueChange(e.target.value)}\n onKeyDown={(e) => {\n // 按 Enter 送出、Shift+Enter 換行(拍板)。\n if (e.key === 'Enter' && !e.shiftKey && !e.nativeEvent.isComposing) {\n e.preventDefault()\n submit()\n }\n }}\n rows={1}\n placeholder={placeholder}\n aria-label=\"訊息\"\n className={cn(\n // 欄位家族內距:單行 32 等高鐵律((欄高−1lh)/2−1 + --field-px)。\n // @focus-suppress B — B Field 家族輸入控件;承擔者:指示器是輸入盒外框\n 'block w-full resize-none bg-transparent outline-none',\n 'px-[var(--field-px)] py-[var(--field-control-py-md)] text-body text-foreground',\n 'placeholder:text-fg-muted',\n 'field-sizing-content max-h-40',\n )}\n />\n <div className=\"flex h-10 items-center justify-between px-2\">\n <Button\n variant=\"text\"\n size=\"xs\"\n iconOnly\n startIcon={Plus}\n aria-label=\"新增附件\"\n onClick={onAddAttachment}\n />\n {busy ? (\n <Button\n variant=\"primary\"\n size=\"xs\"\n iconOnly\n startIcon={StopFilled}\n aria-label=\"停止生成\"\n onClick={() => onStop?.()}\n className=\"animate-in fade-in-0 duration-[var(--motion-duration-overlay)] motion-reduce:animate-none\"\n />\n ) : (\n <Button\n variant=\"primary\"\n size=\"xs\"\n iconOnly\n startIcon={ArrowUp}\n aria-label=\"送出\"\n disabled={!canSubmit}\n onClick={submit}\n className=\"animate-in fade-in-0 duration-[var(--motion-duration-overlay)] motion-reduce:animate-none\"\n />\n )}\n </div>\n </div>\n )\n },\n)\nAgentPromptInput.displayName = 'AgentPromptInput'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 8. AgentDecisionCard(決策卡;一題一問步進)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentDecisionOption {\n value: string\n /** 單行、≤10 字、無句尾標點、說「選了會怎樣」(產題守則 5)。 */\n label: string\n /** 一行差異描述:單句、無句號、同題比同一維度(產題守則 6)。 */\n description: string\n}\n\nexport interface AgentDecisionQuestion {\n id: string\n /** 題目=一句完整問句、以「?」結尾、句內點名決策對象(產題守則 3)。 */\n label: string\n /** 2-4 具名選項(不含「其他」;「其他」由元件必備附加,產題守則 4/7)。 */\n options: AgentDecisionOption[]\n /** 預選推薦解;省略=第一項;元件在該項 label 後加「(建議)」(產題守則 8)。 */\n defaultValue?: string\n /** 不可逆/安全/法律/稱謂類題:不預選(產題守則 8 例外);複選題恆不預選。 */\n noDefault?: boolean\n /** 答案本質可複選才開(產題守則 10):改 CheckboxGroup、不預選、值以 `\\n` 連接。 */\n multiSelect?: boolean\n}\n\nexport interface AgentDecisionCardProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSubmit' | 'title'> {\n /** ≤3 題;一題一問步進,N>1 時標題列顯示「n / N」。 */\n questions: AgentDecisionQuestion[]\n /** 全部作答後送出:answers[questionId] = 選項值或「其他」文字(複選以 `\\n` 連接)。 */\n onSubmit?: (answers: Record<string, string>) => void\n /** 跳過=採預設值繼續(Skip 鈕與 header × 同一行為);回傳目前預設/已選值。 */\n onSkip?: (answers: Record<string, string>) => void\n}\n\nconst OTHER_VALUE = '__agent_decision_other__'\nconst OTHER_LABEL = '其他'\nconst RECOMMENDED_SUFFIX = '(建議)'\nconst MULTI_JOIN = '\\n'\n\n/** 產題守則機械層(agent-decision-card.spec.md §8「產題守則」⚙ 條):DEV 只警告不阻擋,內容規則靠稽核。 */\nfunction warnDecisionRules(questions: AgentDecisionQuestion[]) {\n const warn = (msg: string) => console.warn(`[AgentDecisionCard] 產題守則:${msg}`)\n if (questions.length === 0 || questions.length > 3) warn(`題數 1–3(收到 ${questions.length})。`)\n for (const q of questions) {\n if (!/[??]$/.test(q.label.trim())) warn(`題目必是完整問句、以「?」結尾(${q.id}:「${q.label}」)。`)\n if (q.options.length < 2 || q.options.length > 4) warn(`每題 2–4 個具名選項(${q.id} 有 ${q.options.length})。`)\n for (const o of q.options) {\n if (/\\n/.test(o.label) || o.label.length > 10) warn(`選項標籤單行且 ≤10 字(${q.id}:「${o.label}」)。`)\n if (/[,,;;.。!!]$/.test(o.label)) warn(`選項標籤無句尾標點(${q.id}:「${o.label}」)。`)\n if (/\\(建議\\)|\\(建議\\)|\\(Recommended\\)/i.test(o.label)) warn(`「(建議)」由元件標,勿寫進標籤(${q.id}:「${o.label}」)。`)\n if (!o.description?.trim()) warn(`每個具名選項必附一行差異描述(${q.id}:「${o.label}」)。`)\n else if (/\\n/.test(o.description) || /[。.]$/.test(o.description.trim())) warn(`描述單句、無句號(${q.id}:「${o.label}」)。`)\n if (/^(其他|other)$/i.test(o.label.trim()) || o.value === OTHER_VALUE) warn(`「其他」由元件附加,勿自列(${q.id})。`)\n }\n if (q.multiSelect && q.defaultValue) warn(`複選題不預選(${q.id})。`)\n if (!q.multiSelect && !q.noDefault) {\n const def = q.defaultValue ?? q.options[0]?.value\n if (q.defaultValue && !q.options.some((o) => o.value === q.defaultValue)) warn(`defaultValue 必是選項之一(${q.id})。`)\n if (def !== q.options[0]?.value) warn(`推薦解必排第一(${q.id})。`)\n }\n }\n}\n\nfunction initialAnswer(q: AgentDecisionQuestion) {\n if (q.multiSelect || q.noDefault) return ''\n return q.defaultValue ?? q.options[0]?.value ?? ''\n}\n\n/** 複選值 = 已勾選 value 集合(含 OTHER_VALUE),以 `\\n` 連接存於 answers。 */\nconst splitMulti = (v: string | undefined) => (v ? v.split(MULTI_JOIN).filter(Boolean) : [])\n\n/**\n * 選項卡的滑過(2026-09-26 user 同意;待辦總帳 B12;規則住 agent-decision-card.spec.md「8. AgentDecisionCard」選項卡條):\n * 指標在整張卡的任何位置 → 卡內的圓(複選是方框)照它被自己的 `<label for>` 滑過時的樣子變色;卡片灰底、字色都不變。\n * 原本的轉發是 HTML 自己做的(指標在 label 上,label 綁定的控件也算 :hover),範圍只到 SelectionItem 那個 label。\n * 整張卡不能改成 <label> 來借這個轉發:卡內已有 SelectionItem 的 label、<div> 與「其他」輸入格,都違反 label 的內容規定。\n * 所以用 DS 既有的「外層具名群組帶動內層」寫法(item-anatomy.tsx 的 `hoverGroup`):卡片掛 `group/agent-option`,\n * 控件把**它自己的** `hover:` 配對原樣接到群組滑過上。下面兩串逐條鏡射 owner,不新增任何顏色:\n * Radio ← radio-group.tsx `radioItemVariants` 的 `hover:border-border-hover` 與 `data-[state=checked]:hover:…` 兩行\n * Checkbox ← checkbox.tsx `checkboxVariants` 的 `hover:border-border-hover` 與 `data-[state=checked]:hover:…` 兩行\n * (indeterminate 那行不鏡射:選項卡不會半選)\n * owner 的 hover 配對一改,這裡必須同一次改動跟著改。\n * 不帶 owner 的停用 / 唯讀守衛:決策卡的選項沒有停用或唯讀(AgentDecisionOption 無此欄);日後要加,守衛必一起鏡射。\n */\nconst OPTION_RADIO_HOVER =\n 'group-hover/agent-option:border-border-hover data-[state=checked]:group-hover/agent-option:border-primary-hover data-[state=checked]:group-hover/agent-option:text-primary-hover'\nconst OPTION_CHECKBOX_HOVER =\n 'group-hover/agent-option:border-border-hover data-[state=checked]:group-hover/agent-option:bg-primary-hover data-[state=checked]:group-hover/agent-option:border-primary-hover'\n\nconst AgentDecisionCard = React.forwardRef<HTMLDivElement, AgentDecisionCardProps>(\n ({ questions, onSubmit, onSkip, className, ...props }, ref) => {\n const titleId = React.useId()\n const otherInputId = React.useId()\n const optionIdBase = React.useId()\n if (import.meta.env?.DEV) warnDecisionRules(questions)\n const [step, setStep] = React.useState(0)\n const [answers, setAnswers] = React.useState<Record<string, string>>(() =>\n Object.fromEntries(questions.map((q) => [q.id, initialAnswer(q)])),\n )\n const [otherText, setOtherText] = React.useState<Record<string, string>>({})\n const resolveOne = (q: AgentDecisionQuestion) => {\n const other = (otherText[q.id] ?? '').trim()\n if (q.multiSelect) {\n return splitMulti(answers[q.id])\n .map((v) => (v === OTHER_VALUE ? other : v))\n .filter(Boolean)\n .join(MULTI_JOIN)\n }\n return answers[q.id] === OTHER_VALUE ? other : (answers[q.id] ?? '')\n }\n const resolvedAnswers = () =>\n Object.fromEntries(questions.map((q) => [q.id, resolveOne(q)])) as Record<string, string>\n const total = questions.length\n const question = questions[Math.min(step, total - 1)]\n const isLast = step >= total - 1\n const select = (value: string) => setAnswers((prev) => ({ ...prev, [question.id]: value }))\n const toggle = (value: string, checked: boolean) =>\n setAnswers((prev) => {\n const set = new Set(splitMulti(prev[question.id]))\n if (checked) set.add(value)\n else set.delete(value)\n return { ...prev, [question.id]: [...set].join(MULTI_JOIN) }\n })\n const skip = () => onSkip?.(resolvedAnswers())\n\n if (!question) return null\n const multi = Boolean(question.multiSelect)\n const selectedSet = new Set(multi ? splitMulti(answers[question.id]) : [answers[question.id]])\n const otherSelected = selectedSet.has(OTHER_VALUE)\n // 「其他」選中而文字為空 → 不得前進/送出(產題守則 7);複選一項未勾 → 亦不得前進。\n const canAdvance =\n (!otherSelected || (otherText[question.id] ?? '').trim() !== '') &&\n // 複選至少一項;單選必須有值 —— noDefault 的單選初值是空字串,沒補這一條會送出空答案。\n (multi ? selectedSet.size > 0 : (answers[question.id] ?? '') !== '')\n const recommendedValue =\n !multi && !question.noDefault ? (question.defaultValue ?? question.options[0]?.value) : undefined\n const optionLabel = (option: AgentDecisionOption | { value: string; label: string }) =>\n option.value === recommendedValue ? `${option.label}${RECOMMENDED_SUFFIX}` : option.label\n const allOptions = [...question.options, { value: OTHER_VALUE, label: OTHER_LABEL }]\n const renderOtherInput = () => (\n // 「其他」卡:常駐 32 高輸入格;label 行框↔Input 8(mt-2);距卡右/下各 12(卡 px 12;卡 py 8 + mb 4);\n // 左縮排 24 = radio 16 + gap 8,與 label 對齊(Polaris ChoiceChildren 同款)。\n <div className=\"mb-1 mt-2 pl-6\">\n <Input\n id={otherInputId}\n value={otherText[question.id] ?? ''}\n placeholder=\"輸入其他選項\"\n aria-label=\"其他(自由輸入)\"\n aria-describedby={titleId}\n onFocus={() => (multi ? toggle(OTHER_VALUE, true) : select(OTHER_VALUE))}\n onChange={(e) => setOtherText((prev) => ({ ...prev, [question.id]: e.target.value }))}\n onClick={(e) => e.stopPropagation()}\n />\n </div>\n )\n // 滑鼠/觸控點整張「其他」卡 → 聚焦輸入格(明確指向意圖);鍵盤方向鍵選中不搶焦點(APG radio roving),Tab 一步即到。\n const focusOtherInput = () =>\n window.setTimeout(() => (document.getElementById(otherInputId) as HTMLInputElement | null)?.focus(), 0)\n // 灰底選項卡 = 唯一行距 owner(py 8);SelectionItem 自帶 py((32−1lh)/2=5.5)歸零,避免 double padding\n // (checkbox.spec.md 零外部 gap 鐵律的反向:間距只能有一個 owner)。\n // 滑過:卡片 = 具名群組 `group/agent-option`,自己不掛任何滑過樣式,只帶動卡內控件(OPTION_RADIO_HOVER /\n // OPTION_CHECKBOX_HOVER,理由與鏡射來源見其上方註解)。命中區 = 整卡 onClick = 滑過回饋的範圍。\n const cardClass = 'group/agent-option cursor-pointer rounded-md bg-secondary px-3 py-2'\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-labelledby={titleId}\n className={cn(\n // 繼承 Popover surface:rounded-lg/border/elevation-200;改寫:無下圓角、貼底。\n 'absolute inset-x-0 bottom-0 z-10 flex flex-col overflow-hidden',\n 'rounded-t-lg rounded-b-none border border-b-0 border-border bg-surface-raised',\n 'shadow-[var(--elevation-200)]',\n 'animate-in fade-in-0 slide-in-from-bottom-2 duration-[var(--motion-duration-overlay)] motion-reduce:animate-none',\n className,\n )}\n {...props}\n >\n {/* 標題列:N>1 時小標「n / N」+ 題目 + ×(跳過);改寫:header 下無分隔線。 */}\n <SurfaceHeader className={cn(COMPACT_HEADER_SLOT, 'items-start justify-between border-b-0')}>\n <div className=\"flex min-w-0 flex-1 flex-col\">\n {total > 1 && (\n <span className=\"text-caption font-medium text-fg-secondary\">\n {step + 1} / {total}\n </span>\n )}\n <span id={titleId} className=\"text-body font-medium text-foreground\">\n {question.label}\n </span>\n </div>\n <Button dismiss size=\"sm\" startIcon={XIcon} aria-label=\"跳過\" onClick={skip} />\n </SurfaceHeader>\n {/* body:上下無內距、左右 16;選項=灰底卡 gap 8(整卡可點;拍板樣張,本地包裝不抽通用元件);捲軸必用 ScrollArea。 */}\n <ScrollArea fillX className=\"min-h-0\">\n {multi ? (\n <CheckboxGroup\n key={question.id}\n aria-labelledby={titleId}\n className=\"flex flex-col gap-2 px-[var(--layout-space-loose)]\"\n >\n {allOptions.map((option) => {\n const isOther = option.value === OTHER_VALUE\n const checked = selectedSet.has(option.value)\n return (\n <div\n key={option.value}\n data-state={checked ? 'checked' : 'unchecked'}\n className={cardClass}\n onClick={() => {\n toggle(option.value, !checked)\n if (isOther && !checked) focusOtherInput()\n }}\n >\n <SelectionItem\n size=\"md\"\n className=\"py-0\"\n htmlFor={`${optionIdBase}-${option.value}`}\n control={\n <Checkbox\n id={`${optionIdBase}-${option.value}`}\n size=\"md\"\n checked={checked}\n onCheckedChange={(next) => toggle(option.value, next === true)}\n onClick={(e) => e.stopPropagation()}\n aria-controls={isOther ? otherInputId : undefined}\n className={OPTION_CHECKBOX_HOVER}\n />\n }\n label={optionLabel(option)}\n description={isOther ? undefined : (option as AgentDecisionOption).description}\n />\n {isOther && renderOtherInput()}\n </div>\n )\n })}\n </CheckboxGroup>\n ) : (\n <RadioGroup\n key={question.id}\n value={answers[question.id] ?? ''}\n onValueChange={select}\n aria-labelledby={titleId}\n className=\"flex flex-col gap-2 px-[var(--layout-space-loose)]\"\n >\n {allOptions.map((option) => {\n const isOther = option.value === OTHER_VALUE\n const checked = selectedSet.has(option.value)\n return (\n <div\n key={option.value}\n data-state={checked ? 'checked' : 'unchecked'}\n className={cardClass}\n onClick={() => {\n select(option.value)\n if (isOther) focusOtherInput()\n }}\n >\n <SelectionItem\n size=\"md\"\n className=\"py-0\"\n htmlFor={`${optionIdBase}-${option.value}`}\n control={\n <RadioGroupItem\n id={`${optionIdBase}-${option.value}`}\n value={option.value}\n size=\"md\"\n aria-controls={isOther ? otherInputId : undefined}\n className={OPTION_RADIO_HOVER}\n />\n }\n label={optionLabel(option)}\n description={isOther ? undefined : (option as AgentDecisionOption).description}\n />\n {isOther && renderOtherInput()}\n </div>\n )\n })}\n </RadioGroup>\n )}\n </ScrollArea>\n {/* footer:第一題=跳過(用預設繼續)、第二題起=上一題(答案保留;Material Stepper Back / GOV.UK Back 同款);\n 右=下一題 / 送出(末題);鈕 sm 守 Popover all-sm 律;無上分隔線;× 恆為跳過。 */}\n <SurfaceFooter className=\"border-t-0\">\n {step > 0 ? (\n <Button variant=\"tertiary\" size=\"sm\" onClick={() => setStep((s) => Math.max(0, s - 1))}>\n 上一題\n </Button>\n ) : (\n <Button variant=\"tertiary\" size=\"sm\" onClick={skip}>\n 跳過\n </Button>\n )}\n {isLast ? (\n <Button variant=\"primary\" size=\"sm\" disabled={!canAdvance} onClick={() => onSubmit?.(resolvedAnswers())}>\n 送出\n </Button>\n ) : (\n <Button variant=\"primary\" size=\"sm\" disabled={!canAdvance} onClick={() => setStep((s) => s + 1)}>\n 下一題\n </Button>\n )}\n </SurfaceFooter>\n </div>\n )\n },\n)\nAgentDecisionCard.displayName = 'AgentDecisionCard'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * 9. AgentDecisionSummary(決策回執)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentDecisionSummaryProps extends React.HTMLAttributes<HTMLDivElement> {\n /** [問題, 答案] 配對(靜態回執)。 */\n entries: Array<{ question: string; answer: string }>\n}\n\nconst AgentDecisionSummary = React.forwardRef<HTMLDivElement, AgentDecisionSummaryProps>(\n ({ entries, className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col gap-2 rounded-md border border-border px-3 py-2 text-body',\n className,\n )}\n {...props}\n >\n {entries.map(({ question, answer }, index) => (\n <div key={index} className=\"flex flex-col\">\n <span className=\"text-fg-secondary\">{question}</span>\n <span className=\"text-foreground\">{answer}</span>\n </div>\n ))}\n </div>\n ),\n)\nAgentDecisionSummary.displayName = 'AgentDecisionSummary'\n\nexport {\n AgentPanel,\n AgentPanelHeader,\n AgentConversation,\n AgentMessage,\n AgentThinking,\n AgentToolbar,\n AgentPromptInput,\n AgentDecisionCard,\n AgentDecisionSummary,\n PANEL_WIDTH_DEFAULT as AGENT_PANEL_WIDTH_DEFAULT,\n PANEL_WIDTH_MIN as AGENT_PANEL_WIDTH_MIN,\n PANEL_WIDTH_MAX as AGENT_PANEL_WIDTH_MAX,\n}\n"],"names":["XIcon","_a"],"mappings":"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"}
|
|
@@ -82,7 +82,7 @@ export declare const appShellMeta: {
|
|
|
82
82
|
readonly bg: readonly ["bg-canvas", "bg-surface"];
|
|
83
83
|
readonly fg: readonly ["text-foreground"];
|
|
84
84
|
readonly border: readonly ["border-divider"];
|
|
85
|
-
readonly ring: readonly ["ring-
|
|
85
|
+
readonly ring: readonly ["focus-ring-inset", "--ring"];
|
|
86
86
|
};
|
|
87
87
|
readonly defaultVariant: undefined;
|
|
88
88
|
readonly defaultSize: undefined;
|