@qijenchen/design-system 0.1.0-beta.132 → 0.1.0-beta.134

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.
Files changed (157) hide show
  1. package/dist/components/AgentPanel/agent-panel-fab.d.ts.map +1 -1
  2. package/dist/components/AgentPanel/agent-panel-fab.js +3 -4
  3. package/dist/components/AgentPanel/agent-panel-fab.js.map +1 -1
  4. package/dist/components/AgentPanel/agent-panel.d.ts +18 -2
  5. package/dist/components/AgentPanel/agent-panel.d.ts.map +1 -1
  6. package/dist/components/AgentPanel/agent-panel.js +79 -60
  7. package/dist/components/AgentPanel/agent-panel.js.map +1 -1
  8. package/dist/components/Avatar/avatar.d.ts.map +1 -1
  9. package/dist/components/Avatar/avatar.js +2 -1
  10. package/dist/components/Avatar/avatar.js.map +1 -1
  11. package/dist/components/Combobox/combobox.d.ts +15 -0
  12. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  13. package/dist/components/Combobox/combobox.js +34 -180
  14. package/dist/components/Combobox/combobox.js.map +1 -1
  15. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  16. package/dist/components/DataTable/data-table.js +27 -21
  17. package/dist/components/DataTable/data-table.js.map +1 -1
  18. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  19. package/dist/components/DateGrid/date-grid.js +39 -7
  20. package/dist/components/DateGrid/date-grid.js.map +1 -1
  21. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  22. package/dist/components/DatePicker/date-picker.js +9 -5
  23. package/dist/components/DatePicker/date-picker.js.map +1 -1
  24. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  25. package/dist/components/DropdownMenu/dropdown-menu.js +3 -2
  26. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  27. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  28. package/dist/components/HoverCard/hover-card.js +3 -2
  29. package/dist/components/HoverCard/hover-card.js.map +1 -1
  30. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  31. package/dist/components/Menu/menu-item.js +12 -1
  32. package/dist/components/Menu/menu-item.js.map +1 -1
  33. package/dist/components/PeoplePicker/people-picker.d.ts +4 -0
  34. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  35. package/dist/components/PeoplePicker/people-picker.js +4 -0
  36. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  37. package/dist/components/Popover/popover.d.ts.map +1 -1
  38. package/dist/components/Popover/popover.js +3 -2
  39. package/dist/components/Popover/popover.js.map +1 -1
  40. package/dist/components/SelectMenu/select-menu.d.ts +35 -3
  41. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  42. package/dist/components/SelectMenu/select-menu.js +50 -22
  43. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  44. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  45. package/dist/components/TimePicker/time-picker.js.map +1 -1
  46. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  47. package/dist/components/Tooltip/tooltip.js +3 -2
  48. package/dist/components/Tooltip/tooltip.js.map +1 -1
  49. package/dist/components/TreeView/tree-view.d.ts +1 -1
  50. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  51. package/dist/components/TreeView/tree-view.js +4 -2
  52. package/dist/components/TreeView/tree-view.js.map +1 -1
  53. package/dist/index.js +2 -1
  54. package/dist/lib/overlay-coexistence.d.ts +2 -271
  55. package/dist/lib/overlay-coexistence.d.ts.map +1 -1
  56. package/dist/lib/overlay-coexistence.js +92 -84
  57. package/dist/lib/overlay-coexistence.js.map +1 -1
  58. package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -1
  59. package/dist/patterns/overlay-surface/overlay-surface.js +4 -0
  60. package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -1
  61. package/dist/tokens/elevation/overlay-geometry.d.ts +16 -0
  62. package/dist/tokens/elevation/overlay-geometry.d.ts.map +1 -1
  63. package/dist/tokens/elevation/overlay-geometry.js +2 -0
  64. package/dist/tokens/elevation/overlay-geometry.js.map +1 -1
  65. package/ds-canonical/fork/consumer/lock.json +5 -5
  66. package/ds-canonical/fork/consumer/managed-files/92e4828cdcb96ff0d01daa16f6885f24045a8e72820665650f2a1890dc3a446c.blob +20 -7
  67. package/ds-canonical/fork/governance.lock +4 -4
  68. package/ds-canonical/fork/launchers/approval-evidence.mjs +186 -13
  69. package/ds-canonical/fork/launchers/provider-hook-output-transport.mjs +6 -0
  70. package/ds-canonical/fork/manifest.json +10 -10
  71. package/ds-canonical/hooks/check_field_controls_contracts.sh +1 -1
  72. package/ds-canonical/hooks/check_story_invariants.sh +71 -0
  73. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +4 -1
  74. package/ds-canonical/hooks/lib/approval-evidence.mjs +186 -13
  75. package/ds-canonical/hooks/registrations.json +1 -5
  76. package/ds-canonical/hooks/tests/test_check_story_invariants.sh +93 -0
  77. package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +163 -0
  78. package/ds-canonical/hooks/tests/test_stop_self_audit_push_gate.sh +30 -1
  79. package/ds-canonical/rules/meta-patterns.md +2 -2
  80. package/ds-canonical/rules/story-rules.md +15 -0
  81. package/ds-canonical/skills/design-system-audit/SKILL.md +1 -1
  82. package/ds-story-manifest.json +8 -2
  83. package/package.json +1 -1
  84. package/src/components/AgentPanel/agent-panel-fab.tsx +16 -5
  85. package/src/components/AgentPanel/agent-panel.anatomy.stories.tsx +4 -2
  86. package/src/components/AgentPanel/agent-panel.spec.md +47 -3
  87. package/src/components/AgentPanel/agent-panel.stories.tsx +82 -23
  88. package/src/components/AgentPanel/agent-panel.tsx +116 -60
  89. package/src/components/AppShell/app-shell.stories.tsx +52 -51
  90. package/src/components/Avatar/avatar.spec.md +2 -0
  91. package/src/components/Avatar/avatar.tsx +9 -2
  92. package/src/components/Button/button.spec.md +23 -2
  93. package/src/components/CircularProgress/circular-progress.anatomy.stories.tsx +1 -1
  94. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +1 -1
  95. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +11 -6
  96. package/src/components/Combobox/combobox.anatomy.stories.tsx +7 -10
  97. package/src/components/Combobox/combobox.spec.md +35 -11
  98. package/src/components/Combobox/combobox.stories.tsx +164 -0
  99. package/src/components/Combobox/combobox.tsx +87 -133
  100. package/src/components/Command/command.stories.tsx +1 -1
  101. package/src/components/DataTable/data-table.spec.md +15 -0
  102. package/src/components/DataTable/data-table.stories.tsx +142 -136
  103. package/src/components/DataTable/data-table.tsx +52 -19
  104. package/src/components/DateGrid/date-grid.spec.md +34 -4
  105. package/src/components/DateGrid/date-grid.tsx +42 -8
  106. package/src/components/DatePicker/date-picker.spec.md +14 -1
  107. package/src/components/DatePicker/date-picker.tsx +14 -8
  108. package/src/components/Dialog/dialog.spec.md +4 -1
  109. package/src/components/Dialog/dialog.stories.tsx +31 -22
  110. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +2 -2
  111. package/src/components/DropdownMenu/dropdown-menu.tsx +4 -2
  112. package/src/components/Empty/empty.principles.stories.tsx +1 -1
  113. package/src/components/Field/field-controls.spec.md +1 -1
  114. package/src/components/Field/field.stories.tsx +1 -1
  115. package/src/components/FileItem/file-item.spec.md +1 -1
  116. package/src/components/FileItem/file-item.stories.tsx +20 -7
  117. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +19 -15
  118. package/src/components/HoverCard/hover-card.tsx +4 -2
  119. package/src/components/Menu/menu-item.spec.md +11 -3
  120. package/src/components/Menu/menu-item.tsx +12 -1
  121. package/src/components/Pagination/pagination.principles.stories.tsx +1 -1
  122. package/src/components/PeoplePicker/people-picker.spec.md +2 -2
  123. package/src/components/PeoplePicker/people-picker.tsx +12 -1
  124. package/src/components/Popover/popover.spec.md +5 -3
  125. package/src/components/Popover/popover.stories.tsx +58 -45
  126. package/src/components/Popover/popover.tsx +4 -2
  127. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
  128. package/src/components/SelectMenu/select-menu.spec.md +146 -8
  129. package/src/components/SelectMenu/select-menu.tsx +186 -39
  130. package/src/components/Sidebar/sidebar.spec.md +5 -0
  131. package/src/components/Steps/steps.stories.tsx +3 -3
  132. package/src/components/TimePicker/time-picker.anatomy.stories.tsx +8 -3
  133. package/src/components/TimePicker/time-picker.spec.md +1 -1
  134. package/src/components/TimePicker/time-picker.tsx +7 -4
  135. package/src/components/Toast/toast.stories.tsx +4 -4
  136. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +2 -2
  137. package/src/components/Tooltip/tooltip.spec.md +1 -0
  138. package/src/components/Tooltip/tooltip.stories.tsx +2 -2
  139. package/src/components/Tooltip/tooltip.tsx +5 -2
  140. package/src/components/TreeView/tree-view.tsx +4 -2
  141. package/src/lib/overlay-coexistence.ts +14 -3
  142. package/src/patterns/action-bar/action-bar.spec.md +16 -0
  143. package/src/patterns/element-anatomy/item-anatomy.spec.md +28 -0
  144. package/src/patterns/overlay-surface/overlay-surface.spec.md +134 -5
  145. package/src/patterns/overlay-surface/overlay-surface.tsx +4 -0
  146. package/src/stories-helpers/scene/data-toolbar.tsx +52 -0
  147. package/src/tokens/README.md +2 -0
  148. package/src/tokens/density/density.stories.tsx +37 -32
  149. package/src/tokens/elevation/overlay-geometry.ts +17 -0
  150. package/src/tokens/layoutSpace/layoutSpace.spec.md +2 -2
  151. package/src/tokens/uiSize/uiSize.spec.md +19 -1
  152. package/dist/stories-helpers/anatomy/anatomy-utils.d.ts +0 -40
  153. package/dist/stories-helpers/anatomy/anatomy-utils.d.ts.map +0 -1
  154. package/dist/stories-helpers/overlay/open-overlay-docs.d.ts +0 -41
  155. package/dist/stories-helpers/overlay/open-overlay-docs.d.ts.map +0 -1
  156. package/dist/stories-helpers/scene/simulated-browser.d.ts +0 -37
  157. package/dist/stories-helpers/scene/simulated-browser.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"agent-panel-fab.d.ts","sourceRoot":"","sources":["../../../src/components/AgentPanel/agent-panel-fab.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-panel-fab.d.ts","sourceRoot":"","sources":["../../../src/components/AgentPanel/agent-panel-fab.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAW9B,OAAO,EAGL,KAAK,cAAc,EAOpB,MAAM,oBAAoB,CAAA;AAO3B,MAAM,WAAW,aACf,SAAQ,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAC;IACvE;;;;;OAKG;IACH,SAAS,CAAC,EAAE,cAAc,CAAA;CAC3B;AAiED,QAAA,MAAM,QAAQ,yFA6Bb,CAAA;AAOD;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE9E,mBAAmB;AACnB,eAAO,MAAM,cAAc,EAAE,iBAAoC,CAAA;AAGjE,UAAU,KAAK;IACb,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AACD,UAAU,IAAK,SAAQ,KAAK;IAC1B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AACD,wCAAwC;AACxC,UAAU,KAAK;IACb,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;CACd;AAyFD;;;;;;GAMG;AACH,UAAU,QAAQ;IAChB,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IACxB,sCAAsC;IACtC,SAAS,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,KAAK,iBAAiB,CAAA;CAClE;AAiBD;;;GAGG;AACH,eAAO,MAAM,wBAAwB;;;;2BAjEhB,KAAK;2BACL,KAAK;4BA0DJ,KAAK,MAAM,MAAM,MAAM,MAAM,KAAG,KAAK;2BAPtC,KAAK,KAAK,KAAK,UAAU,QAAQ,GAAG,IAAI,KAAG,QAAQ,GAAG,IAAI;;CAauD,CAAA;AA4KtI;;;;;;GAMG;AACH,KAAK,mBAAmB,GAAG,eAAe,GAAG,gBAAgB,GAAG,eAAe,GAAG,WAAW,GAAG,UAAU,CAAA;AAE1G,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,aAAa,EAAE,WAAW,GAAG,SAAS,GAAG,mBAAmB,CAAC;IAC3G,YAAY;IACZ,SAAS,CAAC,EAAE,iBAAiB,CAAA;IAC7B,wBAAwB;IACxB,gBAAgB,CAAC,EAAE,iBAAiB,CAAA;IACpC,6DAA6D;IAC7D,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,iBAAiB,KAAK,IAAI,CAAA;IAC1D,kCAAkC;IAClC,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAA;IACpD,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,qBAAqB;IACrB,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAClF;AAED,QAAA,MAAM,YAAY,0FAqSjB,CAAA;AAOD,MAAM,WAAW,yBAAyB;IACxC,uDAAuD;IACvD,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,2DAA2D;IAC3D,SAAS,EAAE,cAAc,CAAA;CAC1B;AAED,MAAM,WAAW,mBACf,SAAQ,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;IACrE,6CAA6C;IAC7C,2BAA2B;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,mBAAmB;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,sCAAsC;IACtC,SAAS,CAAC,EAAE,cAAc,CAAA;IAC1B;;;;OAIG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,KAAK,CAAC,SAAS,CAAA;CAChE;AAED;;;;GAIG;AACH,QAAA,MAAM,cAAc,4FAyEnB,CAAA;AAGD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,CAAA"}
@@ -148,11 +148,9 @@ function useSnapDrag(opts) {
148
148
  React.useEffect(() => () => cleanupRef.current(), []);
149
149
  const swallowNextClick = () => {
150
150
  suppressClickRef.current = true;
151
- window.setTimeout(() => {
152
- suppressClickRef.current = false;
153
- }, 0);
154
151
  };
155
152
  const onPointerDown = (e) => {
153
+ suppressClickRef.current = false;
156
154
  if (e.button !== 0) return;
157
155
  if (dragRef.current) return;
158
156
  const host = opts.host();
@@ -208,6 +206,7 @@ function useSnapDrag(opts) {
208
206
  const onUp = (ev) => {
209
207
  const d = dragRef.current;
210
208
  if (!d || ev.pointerId !== d.pointerId) return;
209
+ if (!d.moved && !d.cancelled) onMove(ev);
211
210
  const { moved, cancelled, last } = d;
212
211
  cleanup();
213
212
  if (!moved) return;
@@ -236,7 +235,7 @@ function useSnapDrag(opts) {
236
235
  window.addEventListener("keydown", onKey);
237
236
  };
238
237
  const onClickCapture = (e) => {
239
- if (!suppressClickRef.current) return;
238
+ if (!suppressClickRef.current || e.detail === 0) return;
240
239
  suppressClickRef.current = false;
241
240
  e.preventDefault();
242
241
  e.stopPropagation();
@@ -1 +1 @@
1
- {"version":3,"file":"agent-panel-fab.js","sources":["../../../src/components/AgentPanel/agent-panel-fab.tsx"],"sourcesContent":["/**\n * AgentFab — 智慧代理浮動開關鈕(AgentPanel 家族附屬資產)+ AgentFabDock(「家 ↔ 貼邊」兩態定位殼)。\n *\n * ── 消費的 SSOT ──\n * - 40 圓 = --field-height-lg 於 lg 密度(uiSize.spec.md「lg 密度」表);圓形 iconOnly。\n * - 面 = bg-surface-raised + --elevation-200(elevation.spec.md 配對規則;不寫死白色)。\n * - 外框 = AI 觸發鈕特調:錐形(環向)漸層描邊 2px(整數寬+環向漸層=正圓對稱;\n * spec「FAB」節)。配色兩極 = AgentLogo AGENT_BRAND(= 自家色階 blue-4 / purple-4;\n * 單一數值來源在 agent-panel-logo.tsx,本檔只 import)。\n * - 內置 24 標誌;貼邊態內置 16 標誌(同一造型,無簡化檔)。\n * - **標誌狀態跟著面板裡的代理走**(prop `logoState`,與 AgentPanelHeader 同名;2026-09-03 user 拍板):入口鈕 = 那個對話收起來的樣子,\n * 所以代理在思考時、即使面板關著,入口鈕的標誌也在轉;有新訊 = 招喚態(標誌蓄勢 + 邊框光圈);閒置 = 靜止。\n * 兩種形態(40 圓 / 28 貼邊)都跟。\n * - 動畫:待機=靜止;有新訊=招喚態(標誌本體蓄勢,漣漪由邊框光圈代位:0–35% 貼邊聚亮 →\n * 35% 呼氣起點自邊框射出 r 21→27、寬 2.5、.35→0 → 90% 散盡 → 靜止空拍;與標誌同 dur /\n * 同 keyTimes / 同 swell→settle,同一 commit 掛載 → 同相);懸停=陰影升一級+微放大。\n * - 兩態定位(AgentFabDock;2026-09-03 user 拍板,取代早期的自由座標與 hover 小鈕):只有兩種合法位置 ——\n * 「家」= 40 圓鈕,位置唯一在右下角(離右、下各 loose);「貼邊」= 28 半圓貼右緣,只有 y 可變(右緣帶內)。\n * **用語**:位置 = 家 / 貼邊,區域 = 帶,選單文案 = 縮小按鈕 / 放大按鈕(不再用「收到邊 / 收合 / 小鈕 / 藍框」)。\n * 拖 40 圓鈕:鈕跟著游標;整段拖曳期間右緣帶(寬 36 = --field-height-md;上緣 = 貼邊鈕圓心落在視窗中線,\n * 下緣 = 貼邊鈕底離家頂一個 loose;貼邊區在下半部、永不與家重疊)以 drop-target 底色 + 三邊虛線框標出\n * (貼右緣那側不畫;見 SNAP_ZONE_CLASSES);游標一進帶內,預覽當場變成 28 半圓**貼在右緣、停在放開會落的高度**\n * (帶內所見即所得),放開就落定;放開在帶外 → 飛回家。\n * 拖 28 貼邊鈕:不顯示帶;帶內沿 y 移動;一出帶外當場變回 40 圓、放開飛回家(帶外沒有自由位置)。\n * 兩態點一下都直接開面板;< 8px 位移視為點擊。鍵盤:家 → 貼邊(停在帶底);貼邊 ↑↓ 16px、← / Home 回家;\n * Shift+F10 開選單;拖曳中 Esc 取消。右鍵選單依狀態只給一項(家:縮小按鈕 ArrowRightToLine;貼邊:放大按鈕\n * ArrowLeftFromLine —— 線 = 右緣、箭頭方向 = 鍵盤 → / ← 等價路徑;lucide 官方 tags collapse / expand 鏡像對\n * https://github.com/lucide-icons/lucide/blob/main/icons/arrow-right-to-line.json)。\n * Tooltip 兩態不同:家「問我或推走我」(邀請拖曳)/ 貼邊「開啟智慧代理」(user 2026-09-03:小鈕只寫開啟)。\n * 動作:形態切換 --motion-duration-overlay(150ms,Carbon moderate-01「小型展開、短距離」)、飛回家 / 落點修正\n * --motion-duration-surface(250ms,Atlassian transitions 150–400「較長時長幫助追蹤空間變化」)+ enter 曲線、\n * 帶底色淡入淡出 150ms;prefers-reduced-motion 全部直接落定(motion.spec.md a11y 段;Atlassian / Fluent 同)。\n * 位置由 consumer 受控/非受控(placement / defaultPlacement / onPlacementChange),DS 不寫 storage。\n * - 減動作:光圈屬常駐位移 loop → prefers-reduced-motion 全停(標誌內部自回靜止)。\n */\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/design-system/components/DropdownMenu/dropdown-menu'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/design-system/components/Tooltip/tooltip'\nimport { ArrowLeftFromLine, ArrowRightToLine } from 'lucide-react'\nimport { DRAG_ACTIVATION_DISTANCE_PX } from '@/design-system/lib/drag-visual'\nimport {\n AGENT_BRAND,\n AgentLogo,\n type AgentLogoState,\n BREATH_DUR,\n RIPPLE_KEYTIMES,\n RIPPLE_SPLINES,\n SETTLE,\n useBeginAnimationsOnMount,\n usePrefersReducedMotion,\n} from './agent-panel-logo'\n\n/** 靜止空拍段(值不變)。 */\nconst HOLD = '0 0 1 1'\n/** 環向漸層(同 AgentLogo 兩緞帶代表色;藍在左下 = 220° 起點)。 */\nconst RING_GRADIENT = `conic-gradient(from 220deg, ${AGENT_BRAND.blue}, ${AGENT_BRAND.purple}, ${AGENT_BRAND.blue})`\n\nexport interface AgentFabProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {\n /**\n * 標誌狀態 = **面板裡那個代理當下的狀態**(prop 名與 `AgentPanelHeader.logoState` 一致 —— 產品端同一個變數餵兩邊),面板關著也照跑(2026-09-03 user:「若開啟的 session 是思考中,\n * FAB 的 logo 也應該是思考中」)—— 入口鈕是該對話收起來的樣子,不是另一個獨立的東西:\n * `still` 靜止(閒置)/ `attract` 有新訊(標誌蓄勢 + 邊框光圈)/ `think` 思考中(代理正在回覆,標誌轉動)。\n * 收合成 28 貼邊鈕時同樣跟著跑(尺寸變、狀態不變)。\n */\n logoState?: AgentLogoState\n}\n\n/**\n * 招喚態的邊框光圈(呼吸包絡上的一道外散波)。**兩顆入口鈕共用**:AgentFab 與 AgentFabDock 都渲染它,\n * 否則產品實際用的 AgentFabDock 在有新訊時會完全沒有訊號(標誌的漣漪已被 ripple={false} 關掉,\n * 因為按鈕內放不下)。貼邊態省略(28 半圓貼著視窗邊,波會被切一半)—— 見 spec「AgentFab」節。\n * @internal AgentPanel 家族內部共用。\n */\nfunction FabGlow() {\n const uid = React.useId().replace(/[^a-zA-Z0-9]/g, '')\n const glowId = `${uid}fg`\n const glowRef = React.useRef<SVGSVGElement | null>(null)\n useBeginAnimationsOnMount(glowRef, glowId)\n return (\n <svg\n ref={glowRef}\n width=\"64\"\n height=\"64\"\n viewBox=\"0 0 64 64\"\n aria-hidden\n className=\"pointer-events-none absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2\"\n >\n <defs>\n {/* 光圈=邊框的光外散:與環同兩極、同方位(藍在左下=環 220° 起點)。 */}\n <linearGradient id={glowId} x1=\"0.15\" y1=\"0.85\" x2=\"0.85\" y2=\"0.15\">\n <stop offset=\"0\" stopColor={AGENT_BRAND.blue} />\n <stop offset=\"1\" stopColor={AGENT_BRAND.purple} />\n </linearGradient>\n </defs>\n <circle\n cx=\"32\"\n cy=\"32\"\n r=\"21\"\n fill=\"none\"\n stroke={`url(#${glowId})`}\n strokeWidth=\"2.5\"\n opacity=\"0\"\n >\n <animate\n attributeName=\"r\"\n values=\"21;21;27;27\"\n keyTimes={RIPPLE_KEYTIMES}\n dur={BREATH_DUR}\n begin=\"indefinite\"\n data-begin-on-mount=\"\"\n repeatCount=\"indefinite\"\n calcMode=\"spline\"\n keySplines={`${HOLD};${SETTLE};${HOLD}`}\n />\n <animate\n attributeName=\"opacity\"\n values=\"0;.35;0;0\"\n keyTimes={RIPPLE_KEYTIMES}\n dur={BREATH_DUR}\n begin=\"indefinite\"\n data-begin-on-mount=\"\"\n repeatCount=\"indefinite\"\n calcMode=\"spline\"\n keySplines={RIPPLE_SPLINES}\n />\n </circle>\n </svg>\n )\n}\n\nconst AgentFab = React.forwardRef<HTMLButtonElement, AgentFabProps>(\n ({ logoState = 'still', className, 'aria-label': ariaLabel, ...props }, ref) => {\n const reduced = usePrefersReducedMotion()\n // 光圈只給招喚態(有新訊要人回頭看);思考態的訊號是標誌自己在轉,不加光圈以免兩個 loop 打架。\n const showGlow = logoState === 'attract' && !reduced\n return (\n <span className=\"relative inline-flex\">\n {showGlow && <FabGlow />}\n {/* 漸層環畫在 button 自己身上(2px padding),整個看得見的圓 = 可點區域;環若做在外層 span,外圈 2px 就會是死區。 */}\n <button\n ref={ref}\n type=\"button\"\n aria-label={ariaLabel ?? '開啟智慧代理'} // i18n-allow: DS 預設文案,aria-label prop 可覆寫\n className={cn(\n 'inline-flex size-10 cursor-pointer items-center justify-center rounded-full border-none p-[2px]',\n 'shadow-[var(--elevation-200)] transition-[transform,box-shadow] duration-[var(--motion-duration-overlay)]',\n 'hover:scale-[1.04] hover:shadow-[var(--elevation-200-hover)] motion-reduce:transition-none motion-reduce:hover:scale-100',\n className,\n )}\n style={{ background: RING_GRADIENT }}\n {...props}\n >\n <span className=\"flex h-full w-full items-center justify-center rounded-full bg-surface-raised\">\n <AgentLogo state={logoState} ripple={false} size={24} />\n </span>\n </button>\n </span>\n )\n },\n)\nAgentFab.displayName = 'AgentFab'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * AgentFabDock — 「家 ↔ 貼邊」兩態定位殼:拖曳 + 右緣帶磁吸,所見即所得(spec「AgentFab」節「收到邊」)\n * ──────────────────────────────────────────────────────────────────────── */\n\n/**\n * 位置:home = 40 圓鈕在右下角(位置唯一,不記座標);dock = 28 半圓貼右緣,只記 y(鈕頂到舞台頂,px,\n * 由元件夾在右緣帶內)。沒有第三種位置 —— 放開在帶外一律回家,使用者不可能把鈕拖到難用的地方。\n */\nexport type AgentFabPlacement = { kind: 'home' } | { kind: 'dock'; y: number }\n\n/** 預設位置:家(右下角)。 */\nexport const AGENT_FAB_HOME: AgentFabPlacement = { kind: 'home' }\n\ntype Shape = AgentFabPlacement['kind']\ninterface Point {\n x: number\n y: number\n}\ninterface Rect extends Point {\n w: number\n h: number\n}\n/** 舞台(offsetParent)尺寸與 loose 內距(px)。 */\ninterface Stage {\n w: number\n h: number\n inset: number\n}\n\n/** 主鈕直徑(= --field-height-lg 於 lg 密度 40)。 */\nconst FAB_PX = 40\n/** 貼邊鈕高 / 露出寬(= --field-height-sm 28)。 */\nconst DOCK_PX = 28\n/** 右緣帶寬(= --field-height-md 36;user 2026-09-03 留言由 40 改 36,框比貼邊鈕寬 8px 剛好)。 */\nconst BAND_PX = 36\n/** 拖曳啟動門檻 px(小於視為點擊)。2026-09-07 收斂:與 dnd-kit 那條路共用同一個值。 */\nconst DRAG_THRESHOLD = DRAG_ACTIVATION_DISTANCE_PX\n/** 鍵盤每步 16(同 AgentPanel 調寬步長)。 */\nconst KEY_STEP = 16\n/** 已在區內時再多 16px 才算離開(邊界防抖)。 */\nconst HYSTERESIS = 16\n/**\n * 右緣帶(拖曳中才出現的暫態停靠區)= DS「可放下的區域」配對 `--drop-target` 底 + `--drop-target-border` 虛線框,\n * 貼邊那側不畫、不留圓角(2026-09-03 user 拍板;token 與兩種情境的分工 SSOT 在 color.spec.md「Drop target」段):\n * - 底色半透明(覆蓋在頁面內容上就不能不透明,VS Code theme-color 鐵律),兩模式同一公式,不用 --primary-subtle\n * (那是元件自己的不透明淡底,底下沒有別人的內容)。\n * - 三邊 dashed:dashed = DS 的「可放下的暫時目標」語彙(file-upload.spec.md);貼右緣那側不畫線不留圓角,\n * 與 Sheet / Sidebar / AppShell 側欄 / 貼邊鈕(環只畫露出三邊)同一語言。\n * - 與 FileUpload 常駐拖入區的分工:那邊靜止就看得見、進入合法區只換邊框不填色;這裡憑空出現、需要整區訊號,\n * 而落點回饋由鈕自己的所見即所得預覽承擔。\n */\nconst SNAP_ZONE_CLASSES =\n 'bg-drop-target border-2 border-r-0 border-dashed border-drop-target-border rounded-l-md'\n\n/**\n * 形態表:每個合法位置(placement kind)長什麼樣、標誌多大、Tooltip 出現在哪、招喚要不要畫光圈。\n * 要新增磁吸點(例如鏡像左緣)= 這裡加一列 + `SNAP_ZONES` 加一列 + `AgentFabPlacement` 加一個 kind,\n * 拖曳 / 預覽 / 落定 / 鍵盤流程都不必動 —— 這張表就是「可擴充」的實際載體(spec「區域 → 落點表」)。\n */\ninterface ShapeSpec {\n /** 鈕的外徑(正圓直徑或半圓寬高)。 */\n px: number\n /** 內置標誌尺寸。 */\n logo: number\n /** 外框圓角(貼邊那側不留圓角)。 */\n radius: string\n /** 內面圓角(跟著外框)。 */\n innerRadius: string\n /** Tooltip 出現方向(避開它貼住的那一邊)。 */\n tooltipSide: 'top' | 'left' | 'right' | 'bottom'\n /** 招喚態是否畫邊框光圈(貼邊態省略:半圓貼著視窗邊,波會被切一半)。 */\n glow: boolean\n}\nconst SHAPES: Record<Shape, ShapeSpec> = {\n home: { px: FAB_PX, logo: 24, radius: 'rounded-full', innerRadius: 'rounded-full', tooltipSide: 'top', glow: true },\n dock: { px: DOCK_PX, logo: 16, radius: 'rounded-l-full pr-0', innerRadius: 'rounded-l-full', tooltipSide: 'left', glow: false },\n}\n\nconst clamp = (v: number, min: number, max: number) => Math.min(Math.max(v, min), Math.max(min, max))\n/**\n * 貼邊鈕合法 y(鈕頂)範圍(user 2026-09-03 留言拍板):最高 = 圓心落在視窗中線(dockMinY);最低 = 鈕底離家頂\n * 一個 loose(dockMaxY = 舞台高 − 2·loose − 40 − 28),永不與家重疊、也不壓到分頁列。矮視窗放不下時整帶收成中線一點。\n */\nconst dockMinY = (s: Stage) => Math.floor(s.h / 2 - DOCK_PX / 2)\nconst dockMaxY = (s: Stage) => Math.max(dockMinY(s), s.h - 2 * s.inset - FAB_PX - DOCK_PX)\n/**\n * 兩態的殼左上座標(拖曳引擎用:算抓取偏移與預覽落點)。殼恆為 40 寬、內容靠右:貼邊時 28 鈕靠在殼右緣 = 舞台右緣,\n * 形態過渡(40→28)在殼內縮、右緣不動 → 過渡中不會凸出舞台。\n */\nconst placementXY = (s: Stage, p: AgentFabPlacement): Point =>\n p.kind === 'dock'\n ? { x: s.w - FAB_PX, y: clamp(p.y, dockMinY(s), dockMaxY(s)) }\n : { x: s.w - s.inset - FAB_PX, y: s.h - s.inset - FAB_PX }\n\n/**\n * **靜止時一律用 CSS `right` / `bottom` 從右下角錨定,不用量出來的 `left`**(2026-09-03 user 回報\n * 「小鈕左側點不到」「切 story 回來鈕不見了」的共同根因):\n * 以 `left = 量到的舞台寬 − 40` 定位時,只要量到的寬度比當下版面舊一格(捲軸出現的那一刻),鈕就會凸出可視區,\n * 凸出的那段 `elementFromPoint` 回 null = 點不到;而且鈕自己造成的水平溢出會生出捲軸 → 舞台變窄 → 位置更偏,\n * 量測與版面互相追成迴圈,ResizeObserver 判定 loop 後停手,鈕就卡在出界(或整顆看不見)的狀態。\n * 用 right/bottom 錨定後:x 不需要任何量測,永遠貼齊 padding box 邊緣、不可能溢出;量測只剩「夾 y」與「動畫」用途,\n * 因此**量不到尺寸時也照樣正確顯示**(不再需要 visibility 守衛)。\n */\nconst placementStyle = (s: Stage, p: AgentFabPlacement): React.CSSProperties => {\n if (p.kind === 'dock') {\n const y = s.h > 0 ? clamp(p.y, dockMinY(s), dockMaxY(s)) : Math.max(0, p.y)\n return { left: 'auto', right: 0, top: y, bottom: 'auto' }\n }\n // 家:量到高度就用 top(才能和貼邊態的 top 互相過渡);還沒量到就用 bottom —— 位置一樣正確,只是第一格不做動畫。\n return s.h > 0\n ? { left: 'auto', right: s.inset, top: s.h - s.inset - FAB_PX, bottom: 'auto' }\n : { left: 'auto', right: s.inset, top: 'auto', bottom: s.inset }\n}\nconst inRect = (p: Point, r: Rect, pad: number) =>\n p.x >= r.x - pad && p.x <= r.x + r.w + pad && p.y >= r.y - pad && p.y <= r.y + r.h + pad\n\n/**\n * 磁吸區域表:每列 = 「區域矩形(拖 40 圓鈕時就以底色標出)+ 指標在此區時的落點」。拖曳中的預覽 = 落點本身\n * (帶內所見即所得),放開就落定;指標不在任何區 → 40 圓鈕跟著游標,放開飛回家。判定用**指標**位置\n * (意圖在指尖;Windows Snap 看游標碰邊、Android Bubbles 看拖到關閉區),已在區內時多 16px 遲滯才算離開。\n * 要加磁吸點(鏡像左緣、四角…)只在此表加一列(必要時擴 AgentFabPlacement 的 kind),拖曳 / 預覽 / 底色流程不變\n * (spec「遮擋與貼邊」節「區域 → 落點表」)。\n */\ninterface SnapZone {\n rect: (s: Stage) => Rect\n /** 指標在區內時的落點(y = 指標減去抓取偏移,夾在合法範圍)。 */\n placement: (p: Point, grab: Point, s: Stage) => AgentFabPlacement\n}\nconst SNAP_ZONES: readonly SnapZone[] = [\n {\n // 右緣帶:寬 36,上起中線(鈕圓心)、下到貼邊鈕最低的底邊(= 底色範圍 = 合法 y 範圍);落點 = 28 半圓貼右緣、停在指標高度。\n rect: (s) => ({ x: s.w - BAND_PX, y: dockMinY(s), w: BAND_PX, h: Math.max(0, dockMaxY(s) + DOCK_PX - dockMinY(s)) }),\n placement: (p, grab, s) => ({ kind: 'dock', y: clamp(p.y - Math.min(grab.y, DOCK_PX), dockMinY(s), dockMaxY(s)) }),\n },\n]\nconst findZone = (p: Point, s: Stage, active: SnapZone | null): SnapZone | null =>\n active && inRect(p, active.rect(s), HYSTERESIS) ? active : (SNAP_ZONES.find((z) => inRect(p, z.rect(s), 0)) ?? null)\n/**\n * 拖曳中的指標 → 判區用的舞台座標:x 夾在 [0, 舞台寬](超出右緣讀作右緣),y 不夾(理由見 `useSnapDrag` onMove 註解)。\n * 抽成純函式的原因:onMove 只有在 pointer capture 讓 `clientX` 超出視窗時才會走到「夾」這一步,沒有任何 story\n * 或瀏覽器閘會產生那種座標 —— 規則要有可重跑的證據,只能在這裡直接測(`scripts/test-agent-fab-drag-zones.mjs`)。\n */\nconst dragPoint = (s: Stage, dx: number, dy: number): Point => ({ x: clamp(dx, 0, s.w), y: dy })\n\n/**\n * @internal 拖曳磁吸的純函式與常數(無 DOM),只給 `scripts/test-agent-fab-drag-zones.mjs` 單測消費;\n * 不是 consumer API(root barrel 排除,per-component subpath `export *` 仍看得到)。\n */\nexport const AGENT_FAB_DRAG_INTERNALS = { BAND_PX, DOCK_PX, HYSTERESIS, dockMinY, dockMaxY, dragPoint, findZone, SNAP_ZONES } as const\n\nfunction readPx(el: HTMLElement | null, variable: string, fallback: number) {\n if (!el) return fallback\n const value = Number.parseFloat(getComputedStyle(el).getPropertyValue(variable))\n return Number.isFinite(value) ? value : fallback\n}\n\n/** 拖曳中的暫態:左上座標 + 預覽落點(null = 不在任何磁吸區,放開飛回家)+ 從哪一態拖起(決定顯不顯示帶)。 */\ninterface DragState extends Point {\n placement: AgentFabPlacement | null\n origin: Shape\n}\n\n/**\n * 指標拖曳引擎:門檻、磁吸判定、放開落定、Esc / pointercancel 取消、吞掉拖曳後的 click;外殼只負責畫形狀與帶。\n * 對齊 DS 既有的指標拖曳 canonical(patterns/resize-handle):preventDefault + setPointerCapture + pointerId 過濾 +\n * touch-action none,否則觸控上 pointerdown 後瀏覽器接管捲動、指標移出視窗就收不到 pointerup。\n * 取消語意與放開分離:pointercancel(系統手勢 / 捲動接管)與 Esc 都**不 commit**,位置回到 props。\n */\nfunction useSnapDrag(opts: {\n host: () => HTMLElement | null\n inset: number\n placement: AgentFabPlacement\n commit: (next: AgentFabPlacement) => void\n}) {\n const [drag, setDrag] = React.useState<DragState | null>(null)\n const dragRef = React.useRef<{\n pointerId: number\n startX: number\n startY: number\n moved: boolean\n cancelled: boolean\n zone: SnapZone | null\n last: AgentFabPlacement | null\n } | null>(null)\n const suppressClickRef = React.useRef(false)\n // 卸載時把還掛著的 window listener 收乾淨(拖曳中被卸載 = 路由切換 / 受控 open 翻成 true / story 重掛)。\n const cleanupRef = React.useRef<() => void>(() => {})\n React.useEffect(() => () => cleanupRef.current(), [])\n const swallowNextClick = () => {\n // 拖曳放開後瀏覽器可能緊接著發 click(同元素)→ 吞掉;元素若已換態不會有 click → 下一 tick 清旗標。\n suppressClickRef.current = true\n window.setTimeout(() => {\n suppressClickRef.current = false\n }, 0)\n }\n const onPointerDown = (e: React.PointerEvent<HTMLButtonElement>) => {\n if (e.button !== 0) return\n // 已在拖曳中就忽略:第二次 pointerdown 會覆寫 `dragRef` 與 `cleanupRef`,第一組\n // pointermove/pointerup/pointercancel/keydown 就再也沒人移除(第一顆指標的 `onUp` 會因\n // pointerId 不符直接 return,永遠走不到 cleanup),監聽器會活過元件卸載(2026-09-04 稽核抓到)。\n if (dragRef.current) return\n const host = opts.host()\n if (!host) return\n e.preventDefault()\n const target = e.currentTarget\n try {\n target.setPointerCapture(e.pointerId)\n } catch {\n /* 舊瀏覽器 / 已釋放的指標:退回 window listener 即可 */\n }\n // 座標與渲染同源:absolute 子元素的原點是 padding box,故用 clientLeft/clientTop 與 clientWidth/clientHeight\n // (getBoundingClientRect 是 border-box、含捲軸,兩者混用時只要舞台有邊框或捲軸就會整體偏移)。\n const rect = host.getBoundingClientRect()\n const originX = rect.left + host.clientLeft\n const originY = rect.top + host.clientTop\n const stage: Stage = { w: host.clientWidth, h: host.clientHeight, inset: opts.inset }\n const origin = opts.placement.kind\n const cur = placementXY(stage, opts.placement)\n const grab: Point = { x: e.clientX - originX - cur.x, y: e.clientY - originY - cur.y }\n const onMove = (ev: PointerEvent) => {\n const d = dragRef.current\n if (!d || ev.pointerId !== d.pointerId) return\n // Esc 取消後**不再更新預覽**:`onKey` 只設 `cancelled` 並清掉預覽,刻意不拆監聽(手指還按著,\n // 要等真正放開才結束)。少了這一行的話,下一個 pointermove 就會無條件重畫預覽鈕與右緣帶,\n // 使用者看到的是「按了 Esc 卻只安靜一瞬間」(2026-09-04 稽核抓到)。\n if (d.cancelled) return\n if (!d.moved && Math.hypot(ev.clientX - d.startX, ev.clientY - d.startY) < DRAG_THRESHOLD) return\n d.moved = true\n // 指標的 x 夾在舞台內再判磁吸區(2026-09-04 user 抓到):\n // 右緣帶的矩形右界就是舞台右緣,而指標**可以**跑到視窗外(拖曳有 pointer capture,\n // `clientX` 不受視窗邊界限制)。夾之前,「拖過頭」= 落在帶的右邊 = 判定不在帶內 → 放開飛回家,\n // 但使用者的心智是「我已經推到最右邊了,而且更右邊根本沒有東西」。\n // 夾在舞台內之後,「超出右緣」讀作「就在右緣」,與那個心智一致;往左拖遠仍然正常離開帶\n // (夾的是上界,不是把所有位置都拉進來)。y 不夾 —— 帶的上下確實有合法的「不在帶內」區域。\n // 這條規則由純函式 `dragPoint` 承載,單測 `scripts/test-agent-fab-drag-zones.mjs` 守著\n // (2026-09-05 稽核:修好當天唯一的證據是一次手動合成指標紀錄,拿掉「夾」所有既有閘照樣綠)。\n const p = dragPoint(stage, ev.clientX - originX, ev.clientY - originY)\n d.zone = findZone(p, stage, d.zone)\n if (d.zone) {\n // 所見即所得:預覽就畫在放開會落的位置(貼右緣、指標高度)。\n d.last = d.zone.placement(p, grab, stage)\n setDrag({ ...placementXY(stage, d.last), placement: d.last, origin })\n } else {\n // 帶外:40 圓鈕跟著游標(夾在舞台內),放開飛回家。\n d.last = null\n setDrag({\n x: clamp(p.x - Math.min(grab.x, FAB_PX), 0, stage.w - FAB_PX),\n y: clamp(p.y - Math.min(grab.y, FAB_PX), 0, stage.h - FAB_PX),\n placement: null,\n origin,\n })\n }\n }\n const cleanup = () => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n window.removeEventListener('pointercancel', onCancel)\n window.removeEventListener('keydown', onKey)\n try {\n target.releasePointerCapture(e.pointerId)\n } catch {\n /* 已自動釋放 */\n }\n cleanupRef.current = () => {}\n dragRef.current = null\n setDrag(null)\n }\n const onUp = (ev: PointerEvent) => {\n const d = dragRef.current\n if (!d || ev.pointerId !== d.pointerId) return\n const { moved, cancelled, last } = d\n cleanup()\n if (!moved) return\n // 取消過(Esc)只吞掉這一次 click,不改位置;正常放開才落定。\n swallowNextClick()\n if (!cancelled) opts.commit(last ?? AGENT_FAB_HOME)\n }\n // pointercancel = 互動被系統中止(觸控捲動接管 / 手勢),語意不是放開 → 不 commit。\n const onCancel = (ev: PointerEvent) => {\n const d = dragRef.current\n if (!d || ev.pointerId !== d.pointerId) return\n const moved = d.moved\n cleanup()\n if (moved) swallowNextClick()\n }\n // Esc = 取消拖曳、回原位;但**不拆監聽** —— 使用者手指還按著,要等真正放開才結束(否則那個 click 會漏出去開面板)。\n const onKey = (ev: KeyboardEvent) => {\n const d = dragRef.current\n if (ev.key !== 'Escape' || !d?.moved || d.cancelled) return\n ev.preventDefault()\n d.cancelled = true\n setDrag(null)\n }\n dragRef.current = { pointerId: e.pointerId, startX: e.clientX, startY: e.clientY, moved: false, cancelled: false, zone: null, last: null }\n cleanupRef.current = cleanup\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n window.addEventListener('pointercancel', onCancel)\n window.addEventListener('keydown', onKey)\n }\n const onClickCapture = (e: React.MouseEvent<HTMLButtonElement>) => {\n if (!suppressClickRef.current) return\n suppressClickRef.current = false\n e.preventDefault()\n e.stopPropagation()\n }\n return { drag, onPointerDown, onClickCapture }\n}\n\n/**\n * 本元件**自己必須擁有**、不接受 consumer 覆寫的 button prop。\n * 這些 handler 是拖曳引擎與選單的一部分(門檻判定、吞掉拖曳後的 click、右鍵開選單、鍵盤移動),\n * 被覆寫等於把「點了卻沒開」種回去;而 `disabled` 沒有對應的視覺(鈕長得一模一樣),\n * 傳了只會讓瀏覽器靜靜不派 click —— 型別層直接擋掉,比事後 debug 便宜\n * (兩條都由 2026-09-03 跨模型獨立審查點出)。\n */\ntype FabOwnedButtonProps = 'onPointerDown' | 'onClickCapture' | 'onContextMenu' | 'onKeyDown' | 'disabled'\n\nexport interface AgentFabDockProps extends Omit<AgentFabProps, 'className' | 'onClick' | FabOwnedButtonProps> {\n /** 受控位置。 */\n placement?: AgentFabPlacement\n /** 非受控初始位置;預設家(右下角)。 */\n defaultPlacement?: AgentFabPlacement\n /** 位置變更(拖放 / 鍵盤 / 選單);consumer 自行決定要不要持久化(DS 不寫 storage)。 */\n onPlacementChange?: (placement: AgentFabPlacement) => void\n /** 點擊(開面板);兩態都一段,拖曳超過門檻的放開不觸發。 */\n onClick?: React.MouseEventHandler<HTMLButtonElement>\n /** 定位殼 className(殼為 absolute,舞台需 relative)。 */\n className?: string\n /** 文案(可覆寫供 i18n)。 */\n labels?: { dock?: string; home?: string; tooltip?: string; tooltipDock?: string }\n}\n\nconst AgentFabDock = React.forwardRef<HTMLDivElement, AgentFabDockProps>(\n (\n {\n placement: placementProp,\n defaultPlacement = AGENT_FAB_HOME,\n onPlacementChange,\n onClick,\n className,\n labels,\n logoState = 'still',\n 'aria-label': ariaLabel,\n ...buttonProps\n },\n ref,\n ) => {\n const reduced = usePrefersReducedMotion()\n const [uncontrolled, setUncontrolled] = React.useState<AgentFabPlacement>(defaultPlacement)\n const placement = placementProp ?? uncontrolled\n const setPlacement = React.useCallback(\n (next: AgentFabPlacement) => {\n if (placementProp === undefined) setUncontrolled(next)\n onPlacementChange?.(next)\n },\n [placementProp, onPlacementChange],\n )\n const shellRef = React.useRef<HTMLDivElement | null>(null)\n const buttonRef = React.useRef<HTMLButtonElement | null>(null)\n React.useImperativeHandle(ref, () => shellRef.current as HTMLDivElement)\n const host = () => (shellRef.current?.offsetParent as HTMLElement | null) ?? null\n // 舞台尺寸(offsetParent;ResizeObserver 跟隨)。\n const [size, setSize] = React.useState({ w: 0, h: 0 })\n // 被動 reflow(拖視窗邊界)期間關掉位置過渡,否則鈕會以 250ms 緩動一路拖尾追在角落後面。\n const [reflowing, setReflowing] = React.useState(false)\n React.useLayoutEffect(() => {\n let ro: ResizeObserver | null = null\n let retry: ResizeObserver | null = null\n let reflowTimer = 0\n let first = true\n const attach = () => {\n const el = host()\n if (!el) return false\n const update = () => {\n if (!first) {\n setReflowing(true)\n window.clearTimeout(reflowTimer)\n reflowTimer = window.setTimeout(() => setReflowing(false), 120)\n }\n first = false\n setSize({ w: el.clientWidth, h: el.clientHeight })\n }\n update()\n ro = new ResizeObserver(update)\n ro.observe(el)\n return true\n }\n // 掛載時祖先若是 display:none(收合的分頁 / 尚未啟用的路由),offsetParent 是 null;\n // 改觀察殼自己,等它有尺寸(= 祖先顯示了)再解析一次,否則舞台永遠停在 0×0、鈕停在左上角。\n if (!attach() && shellRef.current) {\n retry = new ResizeObserver(() => {\n if (attach()) {\n retry?.disconnect()\n retry = null\n }\n })\n retry.observe(shellRef.current)\n }\n return () => {\n window.clearTimeout(reflowTimer)\n ro?.disconnect()\n retry?.disconnect()\n }\n }, [])\n // 第一次量到舞台之前不開位置過渡(否則首幀會從預設位置滑進來);位置本身在量到之前就已正確(right/bottom 錨定)。\n const [ready, setReady] = React.useState(false)\n React.useEffect(() => {\n if (size.w > 0) setReady(true)\n }, [size.w])\n const inset = readPx(shellRef.current, '--layout-space-loose', 16)\n const stage: Stage = { w: size.w, h: size.h, inset }\n const { drag, onPointerDown, onClickCapture } = useSnapDrag({ host, inset, placement, commit: setPlacement })\n const [menuOpen, setMenuOpen] = React.useState(false)\n\n const shape: Shape = drag ? (drag.placement?.kind ?? 'home') : placement.kind\n const spec = SHAPES[shape]\n const isDock = shape === 'dock'\n const posStyle: React.CSSProperties = drag\n ? { left: 'auto', right: Math.max(0, stage.w - drag.x - FAB_PX), top: drag.y, bottom: 'auto' }\n : placementStyle(stage, placement)\n /** 帶只在拖 40 圓鈕時可見(拖小鈕不顯示;user 2026-09-03)。 */\n const showZones = drag?.origin === 'home'\n\n const text = {\n dock: labels?.dock ?? '縮小按鈕', // i18n-allow: DS 預設文案(2026-09-03 user 拍板;「按鈕」點名對象,不與內容縮放的「縮小」混淆),labels 可覆寫\n home: labels?.home ?? '放大按鈕', // i18n-allow: DS 預設文案(2026-09-03 user 拍板),labels 可覆寫\n tooltip: labels?.tooltip ?? '問我或推走我', // i18n-allow: DS 預設文案(2026-09-03 user 原話,原「問我或是推我到旁邊」改短),labels 可覆寫\n tooltipDock: labels?.tooltipDock ?? '開啟智慧代理', // i18n-allow: DS 預設文案(小鈕只寫開啟;= aria-label),labels 可覆寫\n }\n const buttonLabel = ariaLabel ?? '開啟智慧代理' // i18n-allow: DS 預設文案,aria-label prop 可覆寫\n\n /** 鍵盤:家 → 貼邊(停在帶底);貼邊 ↑↓ 16px、← / Home 回家;Shift+F10 開選單。 */\n const onKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === 'F10' && e.shiftKey) {\n e.preventDefault()\n setMenuOpen(true)\n return\n }\n if (placement.kind === 'home') {\n if (e.key !== 'ArrowRight') return\n e.preventDefault()\n setPlacement({ kind: 'dock', y: dockMaxY(stage) })\n return\n }\n if (e.key === 'ArrowLeft' || e.key === 'Home') {\n e.preventDefault()\n setPlacement(AGENT_FAB_HOME)\n } else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault()\n const dy = e.key === 'ArrowUp' ? -KEY_STEP : KEY_STEP\n setPlacement({ kind: 'dock', y: clamp(placement.y + dy, dockMinY(stage), dockMaxY(stage)) })\n }\n }\n\n const dragging = drag !== null\n return (\n // 入口鈕整層包在一個與舞台等大的 clip 圖層裡。\n // 為什麼:招喚光圈畫在按鈕**外面** 2px、hover 又放大 1.04,鈕貼齊舞台右緣時這些裝飾會凸出去\n // → 文件被撐寬 → 視窗長出水平捲軸 → clientWidth 少 15 → 連鎖再長出垂直捲軸\n // (2026-09-03 實測:拖到右緣時 scrollWidth−clientWidth 由 0 變 12,兩根捲軸一起出現,放開還留著;\n // 溢出元素就是 FabGlow 的 `absolute left-1/2 top-1/2 -translate-*`)。\n // `overflow-clip` 只裁不捲:它不會變成捲動容器、也不會成為 fixed 的包含塊,所以裝飾在邊緣被切掉\n // (那正是視覺上該有的樣子 —— 光圈被視窗邊緣切一半),而且**任何狀態都不可能再長出捲軸**。\n // 圖層自己 `pointer-events-none`,按鈕仍是 `pointer-events-auto`,命中不受影響。\n <div className=\"pointer-events-none absolute inset-0 overflow-clip\">\n {/* 磁吸區底色:矩形直接來自區域表(邏輯與視覺同一份);淡入淡出 150ms、減動作直接落定;不攔指標。 */}\n {SNAP_ZONES.map((zone, i) => {\n const r = zone.rect(stage)\n return (\n <div\n key={i}\n aria-hidden\n data-agent-fab-zone=\"\"\n className={cn(\n 'pointer-events-none absolute z-10',\n SNAP_ZONE_CLASSES,\n 'transition-opacity duration-[var(--motion-duration-overlay)] motion-reduce:transition-none',\n showZones ? 'opacity-100' : 'opacity-0',\n )}\n // 同樣從右緣錨定(帶永遠貼右緣),避免用量到的 left 造成溢出迴圈。\n style={{ right: 0, top: r.y, width: r.w, height: r.h }}\n />\n )\n })}\n <div\n ref={shellRef}\n data-placement={placement.kind}\n data-shape={shape}\n data-dragging={dragging ? '' : undefined}\n data-snapped={drag?.placement ? '' : undefined}\n className={cn(\n // **殼跟著鈕縮,不再固定 40 寬**(2026-09-04 user 回報「hover 出現 tooltip 的地方點不開」的根因之一):\n // 舊版把殼釘在 40,貼邊時鈕只有 28,左側就多出 12px 既不吃指標、又落在 tooltip 覆蓋範圍內的空白帶\n // (實測:hover 鈕中心 → tooltip 開;往左移 6px → 命中的是底下的表格、tooltip 仍開著;點下去面板不開)。\n // 殼是 `right` 錨定的,寬度縮到內容大小時右緣一樣不動,形態過渡(40→28)照樣不會凸出舞台,\n // 所以固定 40 這件事本來就沒有必要 —— 拿掉之後「殼 = 鈕」,不可能再有看不見的死區。\n 'group/dock pointer-events-none absolute z-20 flex w-fit justify-end',\n // 落點修正 / 飛回家 250ms + enter;拖曳中跟指標不過渡。\n ready && !dragging && !reflowing && !reduced &&\n 'transition-[right,top] duration-[var(--motion-duration-surface)] ease-[var(--motion-easing-enter)]',\n dragging ? 'cursor-grabbing select-none' : 'cursor-grab',\n className,\n )}\n // 舞台尺寸量到前先隱藏(否則首影格會以 0×0 舞台算成左上角再跳到右下角)。\n style={posStyle}\n >\n {/* 招喚態光圈:與獨立 AgentFab 同一顆元件;貼邊態省略(半圓貼邊,波會被切一半)。 */}\n {logoState === 'attract' && !reduced && spec.glow && (\n <span aria-hidden className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <FabGlow />\n </span>\n )}\n <DropdownMenu open={menuOpen} onOpenChange={setMenuOpen} modal={false}>\n {/* 選單只由右鍵 / Shift+F10 開;錨點 = 蓋住鈕的透明 span(pointer-events-none,不攔點擊)。\n 關閉後 Radix 會把焦點還給 trigger,但 trigger 是 aria-hidden 的錨點 → 顯式導回真正的按鈕。 */}\n <DropdownMenuTrigger asChild>\n <span aria-hidden className=\"pointer-events-none absolute inset-0\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n onCloseAutoFocus={(e) => {\n e.preventDefault()\n buttonRef.current?.focus()\n }}\n >\n {placement.kind === 'home' ? (\n <DropdownMenuItem startIcon={ArrowRightToLine} onSelect={() => setPlacement({ kind: 'dock', y: dockMaxY(stage) })}>{text.dock}</DropdownMenuItem>\n ) : (\n <DropdownMenuItem startIcon={ArrowLeftFromLine} onSelect={() => setPlacement(AGENT_FAB_HOME)}>{text.home}</DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n {/* **不加 `disableHoverableContent`**,用 Radix 預設(2026-09-04 定案):\n tooltip 與觸發點恆距 8px(`OVERLAY_SIDE_OFFSET`),兩者不重疊,所以 tooltip 從來就不會\n 擋住這顆鈕的點擊 —— 我一度以為要靠這個旗標才能讓「tooltip 範圍 = 可點範圍」,那是誤判。\n 關掉 hoverable 反而會讓指標一離開 trigger 就立刻關閉,直接命中 WCAG **F95**\n (Failure of SC 1.4.13:content shown on hover not being hoverable)。 */}\n <Tooltip open={dragging ? false : undefined}>\n <TooltipTrigger asChild>\n {/* **命中形狀 ≡ 可視形狀**(2026-09-04 user 拍板原話:\n 「按鈕的視覺 = 觸發事件的範圍 = 會觸發 tooltip 的範圍」)。\n 作法:語意 `<button>` 的尺寸與圓角**都等於可視形狀**(貼邊 28 + `rounded-l-full`、\n 在家 40 + `rounded-full`);漸層環是這一層自己的 2px padding,內層 span 只負責面色,\n 所以按鈕的 border box 邊緣就是使用者看到的邊緣。\n DOM 盒 / 無障礙 target / 命中區 / Radix 錨點四者是同一個形狀。\n\n **不外推**(2026-09-03 曾外推到 40×40,已撤回):外推會生出隱形帶,搶走底下內容的點擊,\n 並把 Radix 錨點推遠(tooltip 離可視形狀 20px 而不是 8px)。\n **也不內縮**:先前寫成「按鈕保持矩形、圓角只畫內層,角落才點得到」——\n 那是把**多**當成修正,使用者要的是相等。\n\n **貼邊鈕壓在別人的捲軸上時,鈕贏**(同日 user 拍板:「按鈕是蓋在表格上,\n fab 通常也都是 z index 最上面的東西」)。實測貼邊鈕與 DataTable 垂直捲軸重疊約 11px,\n 在重疊區以真實滑鼠點擊 → 面板開啟、`scrollTop` 不變。\n 注意 `document.elementFromPoint` **看不到原生捲軸**,這一條只能用真實指標事件驗。 */}\n <button\n type=\"button\"\n className={cn(\n // touch-none:觸控上不讓瀏覽器把 pointerdown 解讀成捲動(同 resize-handle canonical),否則拖曳在手機不可用。\n // **寫上 `spec.radius`,讓命中形狀 = 可視形狀**(2026-09-04 user 拍板:\n // 「按鈕的視覺 = 觸發事件的範圍 = 會觸發 tooltip 的範圍」)。\n // 圓角外的角落看不到,所以也不該點得到 —— 三者恆等,沒有例外可以解釋。\n // 先前寫成「按鈕保持矩形、圓角只畫內層」的理由是「角落才點得到」,那是把\n // **多**當成修正:使用者要的是相等,不是更大。\n // (2026-09-03 曾記錄「貼邊態 dy=±12 時最左 1–3px 點不到」並歸因於圓角命中 ——\n // 複核幾何後那是誤判:D 形在 dy=±12 的高度上,左緣本來就在 x≈6.8 而不是 x=0,\n // 那幾個點原本就在**視覺之外**,不該算死區。)\n 'group/fab pointer-events-auto inline-flex touch-none cursor-[inherit] items-center justify-center border-none bg-transparent p-0',\n spec.radius,\n 'transition-[width,height,transform] duration-[var(--motion-duration-overlay)] ease-[var(--motion-easing-enter)] motion-reduce:transition-none',\n // 懸停微放大掛在**按鈕**上:命中盒與可視形狀一起放大,兩者永遠同步\n // (掛在內層的話,放大後可視會比命中盒大一圈)。值與獨立 AgentFab 同一組。\n !dragging && 'hover:scale-[1.04] motion-reduce:hover:scale-100',\n // 2026-09-07:拿掉 `focus-visible:outline-none` + 內層 span 的 group-ring。\n // 舊註解說「焦點圈要畫在可視形狀上,不是那個沒有圓角的按鈕盒」——\n // 但按鈕上面第 3 行就有 `spec.radius`,而且 `p-0` 讓按鈕盒與可視形狀是**同一個框**,\n // 那個理由早就不成立了。改由全域外描邊直接畫在按鈕上:圓角正確、間隙透明\n // (原本 ring-offset-2 的間隙寫死白色,深色主題會露一圈白)。\n )}\n {...buttonProps}\n // **尺寸寫在 spread 之後**:可視形狀改成 `h-full w-full` 之後,寬高的唯一住所就是這裡;\n // 若排在 `{...buttonProps}` 之前,consumer 傳一個 `style` 就會整個蓋掉 width/height,\n // 按鈕塌成 0×0、內層 100% of 0 也是 0 → 整顆鈕消失(2026-09-04 稽核抓到)。\n // consumer 的其他 style 屬性照樣保留,只有尺寸由本元件擁有。\n style={{ ...buttonProps.style, width: spec.px, height: spec.px }}\n ref={buttonRef}\n aria-label={buttonLabel}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n // 自有 handler 一律放在 spread **之後**:型別已擋(見 FabOwnedButtonProps),\n // 這裡再擋一層執行期(JS consumer / as any 繞過型別)。\n onPointerDown={onPointerDown}\n onKeyDown={onKeyDown}\n onClickCapture={onClickCapture}\n onClick={onClick}\n onContextMenu={(e) => {\n e.preventDefault()\n setMenuOpen(true)\n }}\n >\n {/* 可視形狀:漸層環 = 這一層自己的 2px padding,內層 span 只負責面色。\n 寬高與圓角在兩態間過渡 150ms,拖曳中當場變形 = 所見即所得。 */}\n <span\n aria-hidden\n className={cn(\n 'flex h-full w-full items-center justify-center p-[2px] shadow-[var(--elevation-200)]',\n 'transition-[border-radius,box-shadow] duration-[var(--motion-duration-overlay)] ease-[var(--motion-easing-enter)] motion-reduce:transition-none',\n spec.radius,\n // 陰影升一級(微放大由按鈕負責,見上)。與獨立 AgentFab 同一組 token。\n !dragging && 'group-hover/fab:shadow-[var(--elevation-200-hover)]',\n )}\n style={{ background: RING_GRADIENT }}\n >\n <span className={cn('flex h-full w-full items-center justify-center bg-surface-raised', spec.innerRadius)}>\n <AgentLogo state={logoState} ripple={false} size={spec.logo} />\n </span>\n </span>\n </button>\n </TooltipTrigger>\n <TooltipContent side={spec.tooltipSide}>{isDock ? text.tooltipDock : text.tooltip}</TooltipContent>\n </Tooltip>\n </div>\n </div>\n )\n },\n)\nAgentFabDock.displayName = 'AgentFabDock'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * AgentPanelDock — 「面板 ↔ 入口鈕」互斥外殼(spec「放置與互斥」)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentPanelDockRenderProps {\n /** 關閉面板 → 入口鈕回到上次的位置。接到 AgentPanelHeader 的 onClose。 */\n close: () => void\n /** 目前的代理狀態(與入口鈕標誌同一個值);接到 AgentPanelHeader 的 logoState。 */\n logoState: AgentLogoState\n}\n\nexport interface AgentPanelDockProps\n extends Omit<AgentFabDockProps, 'onClick' | 'children' | 'logoState'> {\n /** 入口鈕位置(受控);省略 = 由本元件保管,面板開關不會忘記(見下方註解)。 */\n /** 面板是否開啟(受控);省略 = 非受控。 */\n open?: boolean\n /** 非受控初始開關;預設開。 */\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** 代理狀態:面板標題列與入口鈕標誌吃同一個值(關著面板也照跑)。 */\n logoState?: AgentLogoState\n /**\n * 面板內容。**關閉時仍然渲染,只是藏起來**(2026-09-07 G2)——\n * 這樣捲動位置、輸入框草稿、展開狀態才留得住(spec E 條「閱讀位置保存」)。\n * 視覺上仍與入口鈕互斥:關著時面板 `display:none`、只看得到入口鈕。\n */\n children: (props: AgentPanelDockRenderProps) => React.ReactNode\n}\n\n/**\n * 面板與入口鈕互斥的唯一住所:開 → 只有面板(× 關閉);關 → 只有入口鈕(點一下開回來),\n * 入口鈕位置與標誌狀態都留在這裡,產品端不必各自寫一份(2026-09-03 user:「所有範例的關閉按鈕都可以加上去了」)。\n * 外層容器需 `relative`(入口鈕以 absolute 定位在其中)。\n */\nconst AgentPanelDock = React.forwardRef<HTMLDivElement, AgentPanelDockProps>(\n (\n {\n open: openProp,\n // v14 條 F:「初次進入、重新整理、新開分頁…均**重新初始化為關閉的新對話**」。\n // 先前預設 true,等於每次進宿主都自動開著 —— 直接牴觸條 F(2026-09-08 跨模型審查抓到)。\n // 要一進來就開著的情境,由消費端顯式傳 `defaultOpen`,不靠 DS 預設。\n defaultOpen = false,\n onOpenChange,\n logoState = 'still',\n children,\n placement: placementProp,\n defaultPlacement = AGENT_FAB_HOME,\n onPlacementChange,\n ...fabProps\n },\n ref,\n ) => {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n const open = openProp ?? uncontrolledOpen\n const setOpen = React.useCallback(\n (next: boolean) => {\n if (openProp === undefined) setUncontrolledOpen(next)\n onOpenChange?.(next)\n },\n [openProp, onOpenChange],\n )\n // 非受控位置**住在這裡**,不能住在 AgentFabDock —— 面板開著時那顆會被卸載,state 會跟著消失,\n // 使用者收到邊、開面板、關面板後鈕就跑回右下角(2026-09-03 稽核抓到)。\n const [uncontrolledPlacement, setUncontrolledPlacement] = React.useState<AgentFabPlacement>(defaultPlacement)\n const placement = placementProp ?? uncontrolledPlacement\n const handlePlacementChange = React.useCallback(\n (next: AgentFabPlacement) => {\n if (placementProp === undefined) setUncontrolledPlacement(next)\n onPlacementChange?.(next)\n },\n [placementProp, onPlacementChange],\n )\n const close = React.useCallback(() => setOpen(false), [setOpen])\n // ── 2026-09-07 G2:關閉時**不再卸載面板**,改成藏起來 ──────────────────────\n //\n // 原本是 `if (open) return children`,關閉的瞬間整個面板連同它的 state 一起消失:\n // 捲到哪、輸入框裡打到一半的字、展開了哪些思考塊,全部歸零。\n // 這讓 spec 的兩條落不了地 —— E 條「閱讀位置保存」與 F 條「初始化為關閉」\n //(初始關閉之後第一次打開會是全新的面板,等於沒有「回到原本在看的地方」可言)。\n //\n // 為什麼是 `display:none` 而不是別的:2026-09-07 真瀏覽器實測四種隱藏方式,\n // **`display:none` 保住 `scrollTop`**(400 → 400)、輸入值保住、而且同時移出\n // tab order 與無障礙樹(隱藏時 `.focus()` 不生效)。`visibility:hidden` 也保狀態\n // 但**仍佔版面**,不能用。\n //\n // 為什麼外面要包一層 `display:contents`:面板通常是 flex/grid 的直接子項,\n // 憑空多一層盒子會改變版面。`display:contents` 讓這層從盒子樹消失,\n // 實測子項寬度與沒有 wrapper 時**逐像素相同**(472px vs 472px)。\n // 用 wrapper 而不是把 `hidden` 交給 render prop:交出去就會有人忘記套。\n return (\n <>\n <div style={{ display: open ? 'contents' : 'none' }}>\n {children({ close, logoState })}\n </div>\n {!open && (\n <AgentFabDock\n ref={ref}\n logoState={logoState}\n placement={placement}\n onPlacementChange={handlePlacementChange}\n onClick={() => setOpen(true)}\n {...fabProps}\n />\n )}\n </>\n )\n },\n)\nAgentPanelDock.displayName = 'AgentPanelDock'\n\nexport { AgentFab, AgentFabDock, AgentPanelDock }\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"agent-panel-fab.js","sources":["../../../src/components/AgentPanel/agent-panel-fab.tsx"],"sourcesContent":["/**\n * AgentFab — 智慧代理浮動開關鈕(AgentPanel 家族附屬資產)+ AgentFabDock(「家 ↔ 貼邊」兩態定位殼)。\n *\n * ── 消費的 SSOT ──\n * - 40 圓 = --field-height-lg 於 lg 密度(uiSize.spec.md「lg 密度」表);圓形 iconOnly。\n * - 面 = bg-surface-raised + --elevation-200(elevation.spec.md 配對規則;不寫死白色)。\n * - 外框 = AI 觸發鈕特調:錐形(環向)漸層描邊 2px(整數寬+環向漸層=正圓對稱;\n * spec「FAB」節)。配色兩極 = AgentLogo AGENT_BRAND(= 自家色階 blue-4 / purple-4;\n * 單一數值來源在 agent-panel-logo.tsx,本檔只 import)。\n * - 內置 24 標誌;貼邊態內置 16 標誌(同一造型,無簡化檔)。\n * - **標誌狀態跟著面板裡的代理走**(prop `logoState`,與 AgentPanelHeader 同名;2026-09-03 user 拍板):入口鈕 = 那個對話收起來的樣子,\n * 所以代理在思考時、即使面板關著,入口鈕的標誌也在轉;有新訊 = 招喚態(標誌蓄勢 + 邊框光圈);閒置 = 靜止。\n * 兩種形態(40 圓 / 28 貼邊)都跟。\n * - 動畫:待機=靜止;有新訊=招喚態(標誌本體蓄勢,漣漪由邊框光圈代位:0–35% 貼邊聚亮 →\n * 35% 呼氣起點自邊框射出 r 21→27、寬 2.5、.35→0 → 90% 散盡 → 靜止空拍;與標誌同 dur /\n * 同 keyTimes / 同 swell→settle,同一 commit 掛載 → 同相);懸停=陰影升一級+微放大。\n * - 兩態定位(AgentFabDock;2026-09-03 user 拍板,取代早期的自由座標與 hover 小鈕):只有兩種合法位置 ——\n * 「家」= 40 圓鈕,位置唯一在右下角(離右、下各 loose);「貼邊」= 28 半圓貼右緣,只有 y 可變(右緣帶內)。\n * **用語**:位置 = 家 / 貼邊,區域 = 帶,選單文案 = 縮小按鈕 / 放大按鈕(不再用「收到邊 / 收合 / 小鈕 / 藍框」)。\n * 拖 40 圓鈕:鈕跟著游標;整段拖曳期間右緣帶(寬 36 = --field-height-md;上緣 = 貼邊鈕圓心落在視窗中線,\n * 下緣 = 貼邊鈕底離家頂一個 loose;貼邊區在下半部、永不與家重疊)以 drop-target 底色 + 三邊虛線框標出\n * (貼右緣那側不畫;見 SNAP_ZONE_CLASSES);游標一進帶內,預覽當場變成 28 半圓**貼在右緣、停在放開會落的高度**\n * (帶內所見即所得),放開就落定;放開在帶外 → 飛回家。\n * 拖 28 貼邊鈕:不顯示帶;帶內沿 y 移動;一出帶外當場變回 40 圓、放開飛回家(帶外沒有自由位置)。\n * 兩態點一下都直接開面板;< 8px 位移視為點擊。鍵盤:家 → 貼邊(停在帶底);貼邊 ↑↓ 16px、← / Home 回家;\n * Shift+F10 開選單;拖曳中 Esc 取消。右鍵選單依狀態只給一項(家:縮小按鈕 ArrowRightToLine;貼邊:放大按鈕\n * ArrowLeftFromLine —— 線 = 右緣、箭頭方向 = 鍵盤 → / ← 等價路徑;lucide 官方 tags collapse / expand 鏡像對\n * https://github.com/lucide-icons/lucide/blob/main/icons/arrow-right-to-line.json)。\n * Tooltip 兩態不同:家「問我或推走我」(邀請拖曳)/ 貼邊「開啟智慧代理」(user 2026-09-03:小鈕只寫開啟)。\n * 動作:形態切換 --motion-duration-overlay(150ms,Carbon moderate-01「小型展開、短距離」)、飛回家 / 落點修正\n * --motion-duration-surface(250ms,Atlassian transitions 150–400「較長時長幫助追蹤空間變化」)+ enter 曲線、\n * 帶底色淡入淡出 150ms;prefers-reduced-motion 全部直接落定(motion.spec.md a11y 段;Atlassian / Fluent 同)。\n * 位置由 consumer 受控/非受控(placement / defaultPlacement / onPlacementChange),DS 不寫 storage。\n * - 減動作:光圈屬常駐位移 loop → prefers-reduced-motion 全停(標誌內部自回靜止)。\n */\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/design-system/components/DropdownMenu/dropdown-menu'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/design-system/components/Tooltip/tooltip'\nimport { ArrowLeftFromLine, ArrowRightToLine } from 'lucide-react'\nimport { DRAG_ACTIVATION_DISTANCE_PX } from '@/design-system/lib/drag-visual'\nimport {\n AGENT_BRAND,\n AgentLogo,\n type AgentLogoState,\n BREATH_DUR,\n RIPPLE_KEYTIMES,\n RIPPLE_SPLINES,\n SETTLE,\n useBeginAnimationsOnMount,\n usePrefersReducedMotion,\n} from './agent-panel-logo'\n\n/** 靜止空拍段(值不變)。 */\nconst HOLD = '0 0 1 1'\n/** 環向漸層(同 AgentLogo 兩緞帶代表色;藍在左下 = 220° 起點)。 */\nconst RING_GRADIENT = `conic-gradient(from 220deg, ${AGENT_BRAND.blue}, ${AGENT_BRAND.purple}, ${AGENT_BRAND.blue})`\n\nexport interface AgentFabProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {\n /**\n * 標誌狀態 = **面板裡那個代理當下的狀態**(prop 名與 `AgentPanelHeader.logoState` 一致 —— 產品端同一個變數餵兩邊),面板關著也照跑(2026-09-03 user:「若開啟的 session 是思考中,\n * FAB 的 logo 也應該是思考中」)—— 入口鈕是該對話收起來的樣子,不是另一個獨立的東西:\n * `still` 靜止(閒置)/ `attract` 有新訊(標誌蓄勢 + 邊框光圈)/ `think` 思考中(代理正在回覆,標誌轉動)。\n * 收合成 28 貼邊鈕時同樣跟著跑(尺寸變、狀態不變)。\n */\n logoState?: AgentLogoState\n}\n\n/**\n * 招喚態的邊框光圈(呼吸包絡上的一道外散波)。**兩顆入口鈕共用**:AgentFab 與 AgentFabDock 都渲染它,\n * 否則產品實際用的 AgentFabDock 在有新訊時會完全沒有訊號(標誌的漣漪已被 ripple={false} 關掉,\n * 因為按鈕內放不下)。貼邊態省略(28 半圓貼著視窗邊,波會被切一半)—— 見 spec「AgentFab」節。\n * @internal AgentPanel 家族內部共用。\n */\nfunction FabGlow() {\n const uid = React.useId().replace(/[^a-zA-Z0-9]/g, '')\n const glowId = `${uid}fg`\n const glowRef = React.useRef<SVGSVGElement | null>(null)\n useBeginAnimationsOnMount(glowRef, glowId)\n return (\n <svg\n ref={glowRef}\n width=\"64\"\n height=\"64\"\n viewBox=\"0 0 64 64\"\n aria-hidden\n className=\"pointer-events-none absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2\"\n >\n <defs>\n {/* 光圈=邊框的光外散:與環同兩極、同方位(藍在左下=環 220° 起點)。 */}\n <linearGradient id={glowId} x1=\"0.15\" y1=\"0.85\" x2=\"0.85\" y2=\"0.15\">\n <stop offset=\"0\" stopColor={AGENT_BRAND.blue} />\n <stop offset=\"1\" stopColor={AGENT_BRAND.purple} />\n </linearGradient>\n </defs>\n <circle\n cx=\"32\"\n cy=\"32\"\n r=\"21\"\n fill=\"none\"\n stroke={`url(#${glowId})`}\n strokeWidth=\"2.5\"\n opacity=\"0\"\n >\n <animate\n attributeName=\"r\"\n values=\"21;21;27;27\"\n keyTimes={RIPPLE_KEYTIMES}\n dur={BREATH_DUR}\n begin=\"indefinite\"\n data-begin-on-mount=\"\"\n repeatCount=\"indefinite\"\n calcMode=\"spline\"\n keySplines={`${HOLD};${SETTLE};${HOLD}`}\n />\n <animate\n attributeName=\"opacity\"\n values=\"0;.35;0;0\"\n keyTimes={RIPPLE_KEYTIMES}\n dur={BREATH_DUR}\n begin=\"indefinite\"\n data-begin-on-mount=\"\"\n repeatCount=\"indefinite\"\n calcMode=\"spline\"\n keySplines={RIPPLE_SPLINES}\n />\n </circle>\n </svg>\n )\n}\n\nconst AgentFab = React.forwardRef<HTMLButtonElement, AgentFabProps>(\n ({ logoState = 'still', className, 'aria-label': ariaLabel, ...props }, ref) => {\n const reduced = usePrefersReducedMotion()\n // 光圈只給招喚態(有新訊要人回頭看);思考態的訊號是標誌自己在轉,不加光圈以免兩個 loop 打架。\n const showGlow = logoState === 'attract' && !reduced\n return (\n <span className=\"relative inline-flex\">\n {showGlow && <FabGlow />}\n {/* 漸層環畫在 button 自己身上(2px padding),整個看得見的圓 = 可點區域;環若做在外層 span,外圈 2px 就會是死區。 */}\n <button\n ref={ref}\n type=\"button\"\n aria-label={ariaLabel ?? '開啟智慧代理'} // i18n-allow: DS 預設文案,aria-label prop 可覆寫\n className={cn(\n 'inline-flex size-10 cursor-pointer items-center justify-center rounded-full border-none p-[2px]',\n 'shadow-[var(--elevation-200)] transition-[transform,box-shadow] duration-[var(--motion-duration-overlay)]',\n 'hover:scale-[1.04] hover:shadow-[var(--elevation-200-hover)] motion-reduce:transition-none motion-reduce:hover:scale-100',\n className,\n )}\n style={{ background: RING_GRADIENT }}\n {...props}\n >\n <span className=\"flex h-full w-full items-center justify-center rounded-full bg-surface-raised\">\n <AgentLogo state={logoState} ripple={false} size={24} />\n </span>\n </button>\n </span>\n )\n },\n)\nAgentFab.displayName = 'AgentFab'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * AgentFabDock — 「家 ↔ 貼邊」兩態定位殼:拖曳 + 右緣帶磁吸,所見即所得(spec「AgentFab」節「收到邊」)\n * ──────────────────────────────────────────────────────────────────────── */\n\n/**\n * 位置:home = 40 圓鈕在右下角(位置唯一,不記座標);dock = 28 半圓貼右緣,只記 y(鈕頂到舞台頂,px,\n * 由元件夾在右緣帶內)。沒有第三種位置 —— 放開在帶外一律回家,使用者不可能把鈕拖到難用的地方。\n */\nexport type AgentFabPlacement = { kind: 'home' } | { kind: 'dock'; y: number }\n\n/** 預設位置:家(右下角)。 */\nexport const AGENT_FAB_HOME: AgentFabPlacement = { kind: 'home' }\n\ntype Shape = AgentFabPlacement['kind']\ninterface Point {\n x: number\n y: number\n}\ninterface Rect extends Point {\n w: number\n h: number\n}\n/** 舞台(offsetParent)尺寸與 loose 內距(px)。 */\ninterface Stage {\n w: number\n h: number\n inset: number\n}\n\n/** 主鈕直徑(= --field-height-lg 於 lg 密度 40)。 */\nconst FAB_PX = 40\n/** 貼邊鈕高 / 露出寬(= --field-height-sm 28)。 */\nconst DOCK_PX = 28\n/** 右緣帶寬(= --field-height-md 36;user 2026-09-03 留言由 40 改 36,框比貼邊鈕寬 8px 剛好)。 */\nconst BAND_PX = 36\n/** 拖曳啟動門檻 px(小於視為點擊)。2026-09-07 收斂:與 dnd-kit 那條路共用同一個值。 */\nconst DRAG_THRESHOLD = DRAG_ACTIVATION_DISTANCE_PX\n/** 鍵盤每步 16(同 AgentPanel 調寬步長)。 */\nconst KEY_STEP = 16\n/** 已在區內時再多 16px 才算離開(邊界防抖)。 */\nconst HYSTERESIS = 16\n/**\n * 右緣帶(拖曳中才出現的暫態停靠區)= DS「可放下的區域」配對 `--drop-target` 底 + `--drop-target-border` 虛線框,\n * 貼邊那側不畫、不留圓角(2026-09-03 user 拍板;token 與兩種情境的分工 SSOT 在 color.spec.md「Drop target」段):\n * - 底色半透明(覆蓋在頁面內容上就不能不透明,VS Code theme-color 鐵律),兩模式同一公式,不用 --primary-subtle\n * (那是元件自己的不透明淡底,底下沒有別人的內容)。\n * - 三邊 dashed:dashed = DS 的「可放下的暫時目標」語彙(file-upload.spec.md);貼右緣那側不畫線不留圓角,\n * 與 Sheet / Sidebar / AppShell 側欄 / 貼邊鈕(環只畫露出三邊)同一語言。\n * - 與 FileUpload 常駐拖入區的分工:那邊靜止就看得見、進入合法區只換邊框不填色;這裡憑空出現、需要整區訊號,\n * 而落點回饋由鈕自己的所見即所得預覽承擔。\n */\nconst SNAP_ZONE_CLASSES =\n 'bg-drop-target border-2 border-r-0 border-dashed border-drop-target-border rounded-l-md'\n\n/**\n * 形態表:每個合法位置(placement kind)長什麼樣、標誌多大、Tooltip 出現在哪、招喚要不要畫光圈。\n * 要新增磁吸點(例如鏡像左緣)= 這裡加一列 + `SNAP_ZONES` 加一列 + `AgentFabPlacement` 加一個 kind,\n * 拖曳 / 預覽 / 落定 / 鍵盤流程都不必動 —— 這張表就是「可擴充」的實際載體(spec「區域 → 落點表」)。\n */\ninterface ShapeSpec {\n /** 鈕的外徑(正圓直徑或半圓寬高)。 */\n px: number\n /** 內置標誌尺寸。 */\n logo: number\n /** 外框圓角(貼邊那側不留圓角)。 */\n radius: string\n /** 內面圓角(跟著外框)。 */\n innerRadius: string\n /** Tooltip 出現方向(避開它貼住的那一邊)。 */\n tooltipSide: 'top' | 'left' | 'right' | 'bottom'\n /** 招喚態是否畫邊框光圈(貼邊態省略:半圓貼著視窗邊,波會被切一半)。 */\n glow: boolean\n}\nconst SHAPES: Record<Shape, ShapeSpec> = {\n home: { px: FAB_PX, logo: 24, radius: 'rounded-full', innerRadius: 'rounded-full', tooltipSide: 'top', glow: true },\n dock: { px: DOCK_PX, logo: 16, radius: 'rounded-l-full pr-0', innerRadius: 'rounded-l-full', tooltipSide: 'left', glow: false },\n}\n\nconst clamp = (v: number, min: number, max: number) => Math.min(Math.max(v, min), Math.max(min, max))\n/**\n * 貼邊鈕合法 y(鈕頂)範圍(user 2026-09-03 留言拍板):最高 = 圓心落在視窗中線(dockMinY);最低 = 鈕底離家頂\n * 一個 loose(dockMaxY = 舞台高 − 2·loose − 40 − 28),永不與家重疊、也不壓到分頁列。矮視窗放不下時整帶收成中線一點。\n */\nconst dockMinY = (s: Stage) => Math.floor(s.h / 2 - DOCK_PX / 2)\nconst dockMaxY = (s: Stage) => Math.max(dockMinY(s), s.h - 2 * s.inset - FAB_PX - DOCK_PX)\n/**\n * 兩態的殼左上座標(拖曳引擎用:算抓取偏移與預覽落點)。殼恆為 40 寬、內容靠右:貼邊時 28 鈕靠在殼右緣 = 舞台右緣,\n * 形態過渡(40→28)在殼內縮、右緣不動 → 過渡中不會凸出舞台。\n */\nconst placementXY = (s: Stage, p: AgentFabPlacement): Point =>\n p.kind === 'dock'\n ? { x: s.w - FAB_PX, y: clamp(p.y, dockMinY(s), dockMaxY(s)) }\n : { x: s.w - s.inset - FAB_PX, y: s.h - s.inset - FAB_PX }\n\n/**\n * **靜止時一律用 CSS `right` / `bottom` 從右下角錨定,不用量出來的 `left`**(2026-09-03 user 回報\n * 「小鈕左側點不到」「切 story 回來鈕不見了」的共同根因):\n * 以 `left = 量到的舞台寬 − 40` 定位時,只要量到的寬度比當下版面舊一格(捲軸出現的那一刻),鈕就會凸出可視區,\n * 凸出的那段 `elementFromPoint` 回 null = 點不到;而且鈕自己造成的水平溢出會生出捲軸 → 舞台變窄 → 位置更偏,\n * 量測與版面互相追成迴圈,ResizeObserver 判定 loop 後停手,鈕就卡在出界(或整顆看不見)的狀態。\n * 用 right/bottom 錨定後:x 不需要任何量測,永遠貼齊 padding box 邊緣、不可能溢出;量測只剩「夾 y」與「動畫」用途,\n * 因此**量不到尺寸時也照樣正確顯示**(不再需要 visibility 守衛)。\n */\nconst placementStyle = (s: Stage, p: AgentFabPlacement): React.CSSProperties => {\n if (p.kind === 'dock') {\n const y = s.h > 0 ? clamp(p.y, dockMinY(s), dockMaxY(s)) : Math.max(0, p.y)\n return { left: 'auto', right: 0, top: y, bottom: 'auto' }\n }\n // 家:量到高度就用 top(才能和貼邊態的 top 互相過渡);還沒量到就用 bottom —— 位置一樣正確,只是第一格不做動畫。\n return s.h > 0\n ? { left: 'auto', right: s.inset, top: s.h - s.inset - FAB_PX, bottom: 'auto' }\n : { left: 'auto', right: s.inset, top: 'auto', bottom: s.inset }\n}\nconst inRect = (p: Point, r: Rect, pad: number) =>\n p.x >= r.x - pad && p.x <= r.x + r.w + pad && p.y >= r.y - pad && p.y <= r.y + r.h + pad\n\n/**\n * 磁吸區域表:每列 = 「區域矩形(拖 40 圓鈕時就以底色標出)+ 指標在此區時的落點」。拖曳中的預覽 = 落點本身\n * (帶內所見即所得),放開就落定;指標不在任何區 → 40 圓鈕跟著游標,放開飛回家。判定用**指標**位置\n * (意圖在指尖;Windows Snap 看游標碰邊、Android Bubbles 看拖到關閉區),已在區內時多 16px 遲滯才算離開。\n * 要加磁吸點(鏡像左緣、四角…)只在此表加一列(必要時擴 AgentFabPlacement 的 kind),拖曳 / 預覽 / 底色流程不變\n * (spec「遮擋與貼邊」節「區域 → 落點表」)。\n */\ninterface SnapZone {\n rect: (s: Stage) => Rect\n /** 指標在區內時的落點(y = 指標減去抓取偏移,夾在合法範圍)。 */\n placement: (p: Point, grab: Point, s: Stage) => AgentFabPlacement\n}\nconst SNAP_ZONES: readonly SnapZone[] = [\n {\n // 右緣帶:寬 36,上起中線(鈕圓心)、下到貼邊鈕最低的底邊(= 底色範圍 = 合法 y 範圍);落點 = 28 半圓貼右緣、停在指標高度。\n rect: (s) => ({ x: s.w - BAND_PX, y: dockMinY(s), w: BAND_PX, h: Math.max(0, dockMaxY(s) + DOCK_PX - dockMinY(s)) }),\n placement: (p, grab, s) => ({ kind: 'dock', y: clamp(p.y - Math.min(grab.y, DOCK_PX), dockMinY(s), dockMaxY(s)) }),\n },\n]\nconst findZone = (p: Point, s: Stage, active: SnapZone | null): SnapZone | null =>\n active && inRect(p, active.rect(s), HYSTERESIS) ? active : (SNAP_ZONES.find((z) => inRect(p, z.rect(s), 0)) ?? null)\n/**\n * 拖曳中的指標 → 判區用的舞台座標:x 夾在 [0, 舞台寬](超出右緣讀作右緣),y 不夾(理由見 `useSnapDrag` onMove 註解)。\n * 抽成純函式的原因:onMove 只有在 pointer capture 讓 `clientX` 超出視窗時才會走到「夾」這一步,沒有任何 story\n * 或瀏覽器閘會產生那種座標 —— 規則要有可重跑的證據,只能在這裡直接測(`scripts/test-agent-fab-drag-zones.mjs`)。\n */\nconst dragPoint = (s: Stage, dx: number, dy: number): Point => ({ x: clamp(dx, 0, s.w), y: dy })\n\n/**\n * @internal 拖曳磁吸的純函式與常數(無 DOM),只給 `scripts/test-agent-fab-drag-zones.mjs` 單測消費;\n * 不是 consumer API(root barrel 排除,per-component subpath `export *` 仍看得到)。\n */\nexport const AGENT_FAB_DRAG_INTERNALS = { BAND_PX, DOCK_PX, HYSTERESIS, dockMinY, dockMaxY, dragPoint, findZone, SNAP_ZONES } as const\n\nfunction readPx(el: HTMLElement | null, variable: string, fallback: number) {\n if (!el) return fallback\n const value = Number.parseFloat(getComputedStyle(el).getPropertyValue(variable))\n return Number.isFinite(value) ? value : fallback\n}\n\n/** 拖曳中的暫態:左上座標 + 預覽落點(null = 不在任何磁吸區,放開飛回家)+ 從哪一態拖起(決定顯不顯示帶)。 */\ninterface DragState extends Point {\n placement: AgentFabPlacement | null\n origin: Shape\n}\n\n/**\n * 指標拖曳引擎:門檻、磁吸判定、放開落定、Esc / pointercancel 取消、吞掉拖曳後的 click;外殼只負責畫形狀與帶。\n * 對齊 DS 既有的指標拖曳 canonical(patterns/resize-handle):preventDefault + setPointerCapture + pointerId 過濾 +\n * touch-action none,否則觸控上 pointerdown 後瀏覽器接管捲動、指標移出視窗就收不到 pointerup。\n * 取消語意與放開分離:pointercancel(系統手勢 / 捲動接管)與 Esc 都**不 commit**,位置回到 props。\n */\nfunction useSnapDrag(opts: {\n host: () => HTMLElement | null\n inset: number\n placement: AgentFabPlacement\n commit: (next: AgentFabPlacement) => void\n}) {\n const [drag, setDrag] = React.useState<DragState | null>(null)\n const dragRef = React.useRef<{\n pointerId: number\n startX: number\n startY: number\n moved: boolean\n cancelled: boolean\n zone: SnapZone | null\n last: AgentFabPlacement | null\n } | null>(null)\n const suppressClickRef = React.useRef(false)\n // 卸載時把還掛著的 window listener 收乾淨(拖曳中被卸載 = 路由切換 / 受控 open 翻成 true / story 重掛)。\n const cleanupRef = React.useRef<() => void>(() => {})\n React.useEffect(() => () => cleanupRef.current(), [])\n const swallowNextClick = () => {\n // 拖曳放開後瀏覽器會對同一顆鈕補發一個 click(pointer capture 讓它一定落在鈕上)→ 必須吞掉,否則「移動」變成「開面板」。\n // 2026-09-16 user:「拖拉 agent panel 的 fab 很容易一不小心就開啟 panel,但我明明就只是要移動它而已」。\n // 舊版(2026-09-02 第一版起)用 setTimeout(0) 清旗標 —— 假設 click 與 pointerup 落在同一個 task;本機 Chromium 確實如此\n // (實測 pointerup → click 0ms),但遠端隔離 / 輸入代理(user 的 Windows 機器把 *.netlify.app 送進 thin client,\n // 見 governance/memory/reference_perf_validation_same_host.md)或任何讓 click 晚一個 task 送達的環境,旗標已清、click 漏過去。\n // 改成**不看時間**:旗標由下一次 pointerdown(新手勢開始)才清;鍵盤合成的 click(detail === 0)永遠放行。\n // 機械閘:scripts/agent-fab-drag-click-invariant.mjs(晚到的 click 必被吞;對照組把旗標清掉必紅)。\n suppressClickRef.current = true\n }\n const onPointerDown = (e: React.PointerEvent<HTMLButtonElement>) => {\n // 新手勢開始:上一段拖曳留下的「吞下一個 click」旗標到此為止(不靠計時器;右鍵 / 第二指也算新手勢)。\n suppressClickRef.current = false\n if (e.button !== 0) return\n // 已在拖曳中就忽略:第二次 pointerdown 會覆寫 `dragRef` 與 `cleanupRef`,第一組\n // pointermove/pointerup/pointercancel/keydown 就再也沒人移除(第一顆指標的 `onUp` 會因\n // pointerId 不符直接 return,永遠走不到 cleanup),監聽器會活過元件卸載(2026-09-04 稽核抓到)。\n if (dragRef.current) return\n const host = opts.host()\n if (!host) return\n e.preventDefault()\n const target = e.currentTarget\n try {\n target.setPointerCapture(e.pointerId)\n } catch {\n /* 舊瀏覽器 / 已釋放的指標:退回 window listener 即可 */\n }\n // 座標與渲染同源:absolute 子元素的原點是 padding box,故用 clientLeft/clientTop 與 clientWidth/clientHeight\n // (getBoundingClientRect 是 border-box、含捲軸,兩者混用時只要舞台有邊框或捲軸就會整體偏移)。\n const rect = host.getBoundingClientRect()\n const originX = rect.left + host.clientLeft\n const originY = rect.top + host.clientTop\n const stage: Stage = { w: host.clientWidth, h: host.clientHeight, inset: opts.inset }\n const origin = opts.placement.kind\n const cur = placementXY(stage, opts.placement)\n const grab: Point = { x: e.clientX - originX - cur.x, y: e.clientY - originY - cur.y }\n const onMove = (ev: PointerEvent) => {\n const d = dragRef.current\n if (!d || ev.pointerId !== d.pointerId) return\n // Esc 取消後**不再更新預覽**:`onKey` 只設 `cancelled` 並清掉預覽,刻意不拆監聽(手指還按著,\n // 要等真正放開才結束)。少了這一行的話,下一個 pointermove 就會無條件重畫預覽鈕與右緣帶,\n // 使用者看到的是「按了 Esc 卻只安靜一瞬間」(2026-09-04 稽核抓到)。\n if (d.cancelled) return\n if (!d.moved && Math.hypot(ev.clientX - d.startX, ev.clientY - d.startY) < DRAG_THRESHOLD) return\n d.moved = true\n // 指標的 x 夾在舞台內再判磁吸區(2026-09-04 user 抓到):\n // 右緣帶的矩形右界就是舞台右緣,而指標**可以**跑到視窗外(拖曳有 pointer capture,\n // `clientX` 不受視窗邊界限制)。夾之前,「拖過頭」= 落在帶的右邊 = 判定不在帶內 → 放開飛回家,\n // 但使用者的心智是「我已經推到最右邊了,而且更右邊根本沒有東西」。\n // 夾在舞台內之後,「超出右緣」讀作「就在右緣」,與那個心智一致;往左拖遠仍然正常離開帶\n // (夾的是上界,不是把所有位置都拉進來)。y 不夾 —— 帶的上下確實有合法的「不在帶內」區域。\n // 這條規則由純函式 `dragPoint` 承載,單測 `scripts/test-agent-fab-drag-zones.mjs` 守著\n // (2026-09-05 稽核:修好當天唯一的證據是一次手動合成指標紀錄,拿掉「夾」所有既有閘照樣綠)。\n const p = dragPoint(stage, ev.clientX - originX, ev.clientY - originY)\n d.zone = findZone(p, stage, d.zone)\n if (d.zone) {\n // 所見即所得:預覽就畫在放開會落的位置(貼右緣、指標高度)。\n d.last = d.zone.placement(p, grab, stage)\n setDrag({ ...placementXY(stage, d.last), placement: d.last, origin })\n } else {\n // 帶外:40 圓鈕跟著游標(夾在舞台內),放開飛回家。\n d.last = null\n setDrag({\n x: clamp(p.x - Math.min(grab.x, FAB_PX), 0, stage.w - FAB_PX),\n y: clamp(p.y - Math.min(grab.y, FAB_PX), 0, stage.h - FAB_PX),\n placement: null,\n origin,\n })\n }\n }\n const cleanup = () => {\n window.removeEventListener('pointermove', onMove)\n window.removeEventListener('pointerup', onUp)\n window.removeEventListener('pointercancel', onCancel)\n window.removeEventListener('keydown', onKey)\n try {\n target.releasePointerCapture(e.pointerId)\n } catch {\n /* 已自動釋放 */\n }\n cleanupRef.current = () => {}\n dragRef.current = null\n setDrag(null)\n }\n const onUp = (ev: PointerEvent) => {\n const d = dragRef.current\n if (!d || ev.pointerId !== d.pointerId) return\n // 拖曳 vs 點擊的判準是「放開點離按下點多遠」,不是「中途收到幾個 pointermove」:輸入代理 / 遠端隔離會把 pointermove\n // 丟掉或合併,只剩 down / up;少了這一步,放開在 80px 外仍被當成點擊,而 pointer capture 又把補發的 click 指回鈕上 →\n // 「移動」變「開面板」(2026-09-16 user 回報;探針:0 個 move、放開在 80px 外 → 舊版開面板)。把放開點走一次同一套\n // 位置計算(門檻 / 磁吸帶 / 預覽落點),讓 moved / last 與有 pointermove 時完全一致。\n if (!d.moved && !d.cancelled) onMove(ev)\n const { moved, cancelled, last } = d\n cleanup()\n if (!moved) return\n // 取消過(Esc)只吞掉這一次 click,不改位置;正常放開才落定。\n swallowNextClick()\n if (!cancelled) opts.commit(last ?? AGENT_FAB_HOME)\n }\n // pointercancel = 互動被系統中止(觸控捲動接管 / 手勢),語意不是放開 → 不 commit。\n const onCancel = (ev: PointerEvent) => {\n const d = dragRef.current\n if (!d || ev.pointerId !== d.pointerId) return\n const moved = d.moved\n cleanup()\n if (moved) swallowNextClick()\n }\n // Esc = 取消拖曳、回原位;但**不拆監聽** —— 使用者手指還按著,要等真正放開才結束(否則那個 click 會漏出去開面板)。\n const onKey = (ev: KeyboardEvent) => {\n const d = dragRef.current\n if (ev.key !== 'Escape' || !d?.moved || d.cancelled) return\n ev.preventDefault()\n d.cancelled = true\n setDrag(null)\n }\n dragRef.current = { pointerId: e.pointerId, startX: e.clientX, startY: e.clientY, moved: false, cancelled: false, zone: null, last: null }\n cleanupRef.current = cleanup\n window.addEventListener('pointermove', onMove)\n window.addEventListener('pointerup', onUp)\n window.addEventListener('pointercancel', onCancel)\n window.addEventListener('keydown', onKey)\n }\n const onClickCapture = (e: React.MouseEvent<HTMLButtonElement>) => {\n // 鍵盤 Enter / Space 合成的 click 是 detail 0:拖完面板仍要能用鍵盤打開,永遠放行。\n if (!suppressClickRef.current || e.detail === 0) return\n suppressClickRef.current = false\n e.preventDefault()\n e.stopPropagation()\n }\n return { drag, onPointerDown, onClickCapture }\n}\n\n/**\n * 本元件**自己必須擁有**、不接受 consumer 覆寫的 button prop。\n * 這些 handler 是拖曳引擎與選單的一部分(門檻判定、吞掉拖曳後的 click、右鍵開選單、鍵盤移動),\n * 被覆寫等於把「點了卻沒開」種回去;而 `disabled` 沒有對應的視覺(鈕長得一模一樣),\n * 傳了只會讓瀏覽器靜靜不派 click —— 型別層直接擋掉,比事後 debug 便宜\n * (兩條都由 2026-09-03 跨模型獨立審查點出)。\n */\ntype FabOwnedButtonProps = 'onPointerDown' | 'onClickCapture' | 'onContextMenu' | 'onKeyDown' | 'disabled'\n\nexport interface AgentFabDockProps extends Omit<AgentFabProps, 'className' | 'onClick' | FabOwnedButtonProps> {\n /** 受控位置。 */\n placement?: AgentFabPlacement\n /** 非受控初始位置;預設家(右下角)。 */\n defaultPlacement?: AgentFabPlacement\n /** 位置變更(拖放 / 鍵盤 / 選單);consumer 自行決定要不要持久化(DS 不寫 storage)。 */\n onPlacementChange?: (placement: AgentFabPlacement) => void\n /** 點擊(開面板);兩態都一段,拖曳超過門檻的放開不觸發。 */\n onClick?: React.MouseEventHandler<HTMLButtonElement>\n /** 定位殼 className(殼為 absolute,舞台需 relative)。 */\n className?: string\n /** 文案(可覆寫供 i18n)。 */\n labels?: { dock?: string; home?: string; tooltip?: string; tooltipDock?: string }\n}\n\nconst AgentFabDock = React.forwardRef<HTMLDivElement, AgentFabDockProps>(\n (\n {\n placement: placementProp,\n defaultPlacement = AGENT_FAB_HOME,\n onPlacementChange,\n onClick,\n className,\n labels,\n logoState = 'still',\n 'aria-label': ariaLabel,\n ...buttonProps\n },\n ref,\n ) => {\n const reduced = usePrefersReducedMotion()\n const [uncontrolled, setUncontrolled] = React.useState<AgentFabPlacement>(defaultPlacement)\n const placement = placementProp ?? uncontrolled\n const setPlacement = React.useCallback(\n (next: AgentFabPlacement) => {\n if (placementProp === undefined) setUncontrolled(next)\n onPlacementChange?.(next)\n },\n [placementProp, onPlacementChange],\n )\n const shellRef = React.useRef<HTMLDivElement | null>(null)\n const buttonRef = React.useRef<HTMLButtonElement | null>(null)\n React.useImperativeHandle(ref, () => shellRef.current as HTMLDivElement)\n const host = () => (shellRef.current?.offsetParent as HTMLElement | null) ?? null\n // 舞台尺寸(offsetParent;ResizeObserver 跟隨)。\n const [size, setSize] = React.useState({ w: 0, h: 0 })\n // 被動 reflow(拖視窗邊界)期間關掉位置過渡,否則鈕會以 250ms 緩動一路拖尾追在角落後面。\n const [reflowing, setReflowing] = React.useState(false)\n React.useLayoutEffect(() => {\n let ro: ResizeObserver | null = null\n let retry: ResizeObserver | null = null\n let reflowTimer = 0\n let first = true\n const attach = () => {\n const el = host()\n if (!el) return false\n const update = () => {\n if (!first) {\n setReflowing(true)\n window.clearTimeout(reflowTimer)\n reflowTimer = window.setTimeout(() => setReflowing(false), 120)\n }\n first = false\n setSize({ w: el.clientWidth, h: el.clientHeight })\n }\n update()\n ro = new ResizeObserver(update)\n ro.observe(el)\n return true\n }\n // 掛載時祖先若是 display:none(收合的分頁 / 尚未啟用的路由),offsetParent 是 null;\n // 改觀察殼自己,等它有尺寸(= 祖先顯示了)再解析一次,否則舞台永遠停在 0×0、鈕停在左上角。\n if (!attach() && shellRef.current) {\n retry = new ResizeObserver(() => {\n if (attach()) {\n retry?.disconnect()\n retry = null\n }\n })\n retry.observe(shellRef.current)\n }\n return () => {\n window.clearTimeout(reflowTimer)\n ro?.disconnect()\n retry?.disconnect()\n }\n }, [])\n // 第一次量到舞台之前不開位置過渡(否則首幀會從預設位置滑進來);位置本身在量到之前就已正確(right/bottom 錨定)。\n const [ready, setReady] = React.useState(false)\n React.useEffect(() => {\n if (size.w > 0) setReady(true)\n }, [size.w])\n const inset = readPx(shellRef.current, '--layout-space-loose', 16)\n const stage: Stage = { w: size.w, h: size.h, inset }\n const { drag, onPointerDown, onClickCapture } = useSnapDrag({ host, inset, placement, commit: setPlacement })\n const [menuOpen, setMenuOpen] = React.useState(false)\n\n const shape: Shape = drag ? (drag.placement?.kind ?? 'home') : placement.kind\n const spec = SHAPES[shape]\n const isDock = shape === 'dock'\n const posStyle: React.CSSProperties = drag\n ? { left: 'auto', right: Math.max(0, stage.w - drag.x - FAB_PX), top: drag.y, bottom: 'auto' }\n : placementStyle(stage, placement)\n /** 帶只在拖 40 圓鈕時可見(拖小鈕不顯示;user 2026-09-03)。 */\n const showZones = drag?.origin === 'home'\n\n const text = {\n dock: labels?.dock ?? '縮小按鈕', // i18n-allow: DS 預設文案(2026-09-03 user 拍板;「按鈕」點名對象,不與內容縮放的「縮小」混淆),labels 可覆寫\n home: labels?.home ?? '放大按鈕', // i18n-allow: DS 預設文案(2026-09-03 user 拍板),labels 可覆寫\n tooltip: labels?.tooltip ?? '問我或推走我', // i18n-allow: DS 預設文案(2026-09-03 user 原話,原「問我或是推我到旁邊」改短),labels 可覆寫\n tooltipDock: labels?.tooltipDock ?? '開啟智慧代理', // i18n-allow: DS 預設文案(小鈕只寫開啟;= aria-label),labels 可覆寫\n }\n const buttonLabel = ariaLabel ?? '開啟智慧代理' // i18n-allow: DS 預設文案,aria-label prop 可覆寫\n\n /** 鍵盤:家 → 貼邊(停在帶底);貼邊 ↑↓ 16px、← / Home 回家;Shift+F10 開選單。 */\n const onKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === 'F10' && e.shiftKey) {\n e.preventDefault()\n setMenuOpen(true)\n return\n }\n if (placement.kind === 'home') {\n if (e.key !== 'ArrowRight') return\n e.preventDefault()\n setPlacement({ kind: 'dock', y: dockMaxY(stage) })\n return\n }\n if (e.key === 'ArrowLeft' || e.key === 'Home') {\n e.preventDefault()\n setPlacement(AGENT_FAB_HOME)\n } else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n e.preventDefault()\n const dy = e.key === 'ArrowUp' ? -KEY_STEP : KEY_STEP\n setPlacement({ kind: 'dock', y: clamp(placement.y + dy, dockMinY(stage), dockMaxY(stage)) })\n }\n }\n\n const dragging = drag !== null\n return (\n // 入口鈕整層包在一個與舞台等大的 clip 圖層裡。\n // 為什麼:招喚光圈畫在按鈕**外面** 2px、hover 又放大 1.04,鈕貼齊舞台右緣時這些裝飾會凸出去\n // → 文件被撐寬 → 視窗長出水平捲軸 → clientWidth 少 15 → 連鎖再長出垂直捲軸\n // (2026-09-03 實測:拖到右緣時 scrollWidth−clientWidth 由 0 變 12,兩根捲軸一起出現,放開還留著;\n // 溢出元素就是 FabGlow 的 `absolute left-1/2 top-1/2 -translate-*`)。\n // `overflow-clip` 只裁不捲:它不會變成捲動容器、也不會成為 fixed 的包含塊,所以裝飾在邊緣被切掉\n // (那正是視覺上該有的樣子 —— 光圈被視窗邊緣切一半),而且**任何狀態都不可能再長出捲軸**。\n // 圖層自己 `pointer-events-none`,按鈕仍是 `pointer-events-auto`,命中不受影響。\n <div className=\"pointer-events-none absolute inset-0 overflow-clip\">\n {/* 磁吸區底色:矩形直接來自區域表(邏輯與視覺同一份);淡入淡出 150ms、減動作直接落定;不攔指標。 */}\n {SNAP_ZONES.map((zone, i) => {\n const r = zone.rect(stage)\n return (\n <div\n key={i}\n aria-hidden\n data-agent-fab-zone=\"\"\n className={cn(\n 'pointer-events-none absolute z-10',\n SNAP_ZONE_CLASSES,\n 'transition-opacity duration-[var(--motion-duration-overlay)] motion-reduce:transition-none',\n showZones ? 'opacity-100' : 'opacity-0',\n )}\n // 同樣從右緣錨定(帶永遠貼右緣),避免用量到的 left 造成溢出迴圈。\n style={{ right: 0, top: r.y, width: r.w, height: r.h }}\n />\n )\n })}\n <div\n ref={shellRef}\n data-placement={placement.kind}\n data-shape={shape}\n data-dragging={dragging ? '' : undefined}\n data-snapped={drag?.placement ? '' : undefined}\n className={cn(\n // **殼跟著鈕縮,不再固定 40 寬**(2026-09-04 user 回報「hover 出現 tooltip 的地方點不開」的根因之一):\n // 舊版把殼釘在 40,貼邊時鈕只有 28,左側就多出 12px 既不吃指標、又落在 tooltip 覆蓋範圍內的空白帶\n // (實測:hover 鈕中心 → tooltip 開;往左移 6px → 命中的是底下的表格、tooltip 仍開著;點下去面板不開)。\n // 殼是 `right` 錨定的,寬度縮到內容大小時右緣一樣不動,形態過渡(40→28)照樣不會凸出舞台,\n // 所以固定 40 這件事本來就沒有必要 —— 拿掉之後「殼 = 鈕」,不可能再有看不見的死區。\n 'group/dock pointer-events-none absolute z-20 flex w-fit justify-end',\n // 落點修正 / 飛回家 250ms + enter;拖曳中跟指標不過渡。\n ready && !dragging && !reflowing && !reduced &&\n 'transition-[right,top] duration-[var(--motion-duration-surface)] ease-[var(--motion-easing-enter)]',\n dragging ? 'cursor-grabbing select-none' : 'cursor-grab',\n className,\n )}\n // 舞台尺寸量到前先隱藏(否則首影格會以 0×0 舞台算成左上角再跳到右下角)。\n style={posStyle}\n >\n {/* 招喚態光圈:與獨立 AgentFab 同一顆元件;貼邊態省略(半圓貼邊,波會被切一半)。 */}\n {logoState === 'attract' && !reduced && spec.glow && (\n <span aria-hidden className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <FabGlow />\n </span>\n )}\n <DropdownMenu open={menuOpen} onOpenChange={setMenuOpen} modal={false}>\n {/* 選單只由右鍵 / Shift+F10 開;錨點 = 蓋住鈕的透明 span(pointer-events-none,不攔點擊)。\n 關閉後 Radix 會把焦點還給 trigger,但 trigger 是 aria-hidden 的錨點 → 顯式導回真正的按鈕。 */}\n <DropdownMenuTrigger asChild>\n <span aria-hidden className=\"pointer-events-none absolute inset-0\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n onCloseAutoFocus={(e) => {\n e.preventDefault()\n buttonRef.current?.focus()\n }}\n >\n {placement.kind === 'home' ? (\n <DropdownMenuItem startIcon={ArrowRightToLine} onSelect={() => setPlacement({ kind: 'dock', y: dockMaxY(stage) })}>{text.dock}</DropdownMenuItem>\n ) : (\n <DropdownMenuItem startIcon={ArrowLeftFromLine} onSelect={() => setPlacement(AGENT_FAB_HOME)}>{text.home}</DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n {/* **不加 `disableHoverableContent`**,用 Radix 預設(2026-09-04 定案):\n tooltip 與觸發點恆距 8px(`OVERLAY_SIDE_OFFSET`),兩者不重疊,所以 tooltip 從來就不會\n 擋住這顆鈕的點擊 —— 我一度以為要靠這個旗標才能讓「tooltip 範圍 = 可點範圍」,那是誤判。\n 關掉 hoverable 反而會讓指標一離開 trigger 就立刻關閉,直接命中 WCAG **F95**\n (Failure of SC 1.4.13:content shown on hover not being hoverable)。 */}\n <Tooltip open={dragging ? false : undefined}>\n <TooltipTrigger asChild>\n {/* **命中形狀 ≡ 可視形狀**(2026-09-04 user 拍板原話:\n 「按鈕的視覺 = 觸發事件的範圍 = 會觸發 tooltip 的範圍」)。\n 作法:語意 `<button>` 的尺寸與圓角**都等於可視形狀**(貼邊 28 + `rounded-l-full`、\n 在家 40 + `rounded-full`);漸層環是這一層自己的 2px padding,內層 span 只負責面色,\n 所以按鈕的 border box 邊緣就是使用者看到的邊緣。\n DOM 盒 / 無障礙 target / 命中區 / Radix 錨點四者是同一個形狀。\n\n **不外推**(2026-09-03 曾外推到 40×40,已撤回):外推會生出隱形帶,搶走底下內容的點擊,\n 並把 Radix 錨點推遠(tooltip 離可視形狀 20px 而不是 8px)。\n **也不內縮**:先前寫成「按鈕保持矩形、圓角只畫內層,角落才點得到」——\n 那是把**多**當成修正,使用者要的是相等。\n\n **貼邊鈕壓在別人的捲軸上時,鈕贏**(同日 user 拍板:「按鈕是蓋在表格上,\n fab 通常也都是 z index 最上面的東西」)。實測貼邊鈕與 DataTable 垂直捲軸重疊約 11px,\n 在重疊區以真實滑鼠點擊 → 面板開啟、`scrollTop` 不變。\n 注意 `document.elementFromPoint` **看不到原生捲軸**,這一條只能用真實指標事件驗。 */}\n <button\n type=\"button\"\n className={cn(\n // touch-none:觸控上不讓瀏覽器把 pointerdown 解讀成捲動(同 resize-handle canonical),否則拖曳在手機不可用。\n // **寫上 `spec.radius`,讓命中形狀 = 可視形狀**(2026-09-04 user 拍板:\n // 「按鈕的視覺 = 觸發事件的範圍 = 會觸發 tooltip 的範圍」)。\n // 圓角外的角落看不到,所以也不該點得到 —— 三者恆等,沒有例外可以解釋。\n // 先前寫成「按鈕保持矩形、圓角只畫內層」的理由是「角落才點得到」,那是把\n // **多**當成修正:使用者要的是相等,不是更大。\n // (2026-09-03 曾記錄「貼邊態 dy=±12 時最左 1–3px 點不到」並歸因於圓角命中 ——\n // 複核幾何後那是誤判:D 形在 dy=±12 的高度上,左緣本來就在 x≈6.8 而不是 x=0,\n // 那幾個點原本就在**視覺之外**,不該算死區。)\n 'group/fab pointer-events-auto inline-flex touch-none cursor-[inherit] items-center justify-center border-none bg-transparent p-0',\n spec.radius,\n 'transition-[width,height,transform] duration-[var(--motion-duration-overlay)] ease-[var(--motion-easing-enter)] motion-reduce:transition-none',\n // 懸停微放大掛在**按鈕**上:命中盒與可視形狀一起放大,兩者永遠同步\n // (掛在內層的話,放大後可視會比命中盒大一圈)。值與獨立 AgentFab 同一組。\n !dragging && 'hover:scale-[1.04] motion-reduce:hover:scale-100',\n // 2026-09-07:拿掉 `focus-visible:outline-none` + 內層 span 的 group-ring。\n // 舊註解說「焦點圈要畫在可視形狀上,不是那個沒有圓角的按鈕盒」——\n // 但按鈕上面第 3 行就有 `spec.radius`,而且 `p-0` 讓按鈕盒與可視形狀是**同一個框**,\n // 那個理由早就不成立了。改由全域外描邊直接畫在按鈕上:圓角正確、間隙透明\n // (原本 ring-offset-2 的間隙寫死白色,深色主題會露一圈白)。\n )}\n {...buttonProps}\n // **尺寸寫在 spread 之後**:可視形狀改成 `h-full w-full` 之後,寬高的唯一住所就是這裡;\n // 若排在 `{...buttonProps}` 之前,consumer 傳一個 `style` 就會整個蓋掉 width/height,\n // 按鈕塌成 0×0、內層 100% of 0 也是 0 → 整顆鈕消失(2026-09-04 稽核抓到)。\n // consumer 的其他 style 屬性照樣保留,只有尺寸由本元件擁有。\n style={{ ...buttonProps.style, width: spec.px, height: spec.px }}\n ref={buttonRef}\n aria-label={buttonLabel}\n aria-haspopup=\"menu\"\n aria-expanded={menuOpen}\n // 自有 handler 一律放在 spread **之後**:型別已擋(見 FabOwnedButtonProps),\n // 這裡再擋一層執行期(JS consumer / as any 繞過型別)。\n onPointerDown={onPointerDown}\n onKeyDown={onKeyDown}\n onClickCapture={onClickCapture}\n onClick={onClick}\n onContextMenu={(e) => {\n e.preventDefault()\n setMenuOpen(true)\n }}\n >\n {/* 可視形狀:漸層環 = 這一層自己的 2px padding,內層 span 只負責面色。\n 寬高與圓角在兩態間過渡 150ms,拖曳中當場變形 = 所見即所得。 */}\n <span\n aria-hidden\n className={cn(\n 'flex h-full w-full items-center justify-center p-[2px] shadow-[var(--elevation-200)]',\n 'transition-[border-radius,box-shadow] duration-[var(--motion-duration-overlay)] ease-[var(--motion-easing-enter)] motion-reduce:transition-none',\n spec.radius,\n // 陰影升一級(微放大由按鈕負責,見上)。與獨立 AgentFab 同一組 token。\n !dragging && 'group-hover/fab:shadow-[var(--elevation-200-hover)]',\n )}\n style={{ background: RING_GRADIENT }}\n >\n <span className={cn('flex h-full w-full items-center justify-center bg-surface-raised', spec.innerRadius)}>\n <AgentLogo state={logoState} ripple={false} size={spec.logo} />\n </span>\n </span>\n </button>\n </TooltipTrigger>\n <TooltipContent side={spec.tooltipSide}>{isDock ? text.tooltipDock : text.tooltip}</TooltipContent>\n </Tooltip>\n </div>\n </div>\n )\n },\n)\nAgentFabDock.displayName = 'AgentFabDock'\n\n/* ────────────────────────────────────────────────────────────────────────────\n * AgentPanelDock — 「面板 ↔ 入口鈕」互斥外殼(spec「放置與互斥」)\n * ──────────────────────────────────────────────────────────────────────── */\n\nexport interface AgentPanelDockRenderProps {\n /** 關閉面板 → 入口鈕回到上次的位置。接到 AgentPanelHeader 的 onClose。 */\n close: () => void\n /** 目前的代理狀態(與入口鈕標誌同一個值);接到 AgentPanelHeader 的 logoState。 */\n logoState: AgentLogoState\n}\n\nexport interface AgentPanelDockProps\n extends Omit<AgentFabDockProps, 'onClick' | 'children' | 'logoState'> {\n /** 入口鈕位置(受控);省略 = 由本元件保管,面板開關不會忘記(見下方註解)。 */\n /** 面板是否開啟(受控);省略 = 非受控。 */\n open?: boolean\n /** 非受控初始開關;預設開。 */\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** 代理狀態:面板標題列與入口鈕標誌吃同一個值(關著面板也照跑)。 */\n logoState?: AgentLogoState\n /**\n * 面板內容。**關閉時仍然渲染,只是藏起來**(2026-09-07 G2)——\n * 這樣捲動位置、輸入框草稿、展開狀態才留得住(spec E 條「閱讀位置保存」)。\n * 視覺上仍與入口鈕互斥:關著時面板 `display:none`、只看得到入口鈕。\n */\n children: (props: AgentPanelDockRenderProps) => React.ReactNode\n}\n\n/**\n * 面板與入口鈕互斥的唯一住所:開 → 只有面板(× 關閉);關 → 只有入口鈕(點一下開回來),\n * 入口鈕位置與標誌狀態都留在這裡,產品端不必各自寫一份(2026-09-03 user:「所有範例的關閉按鈕都可以加上去了」)。\n * 外層容器需 `relative`(入口鈕以 absolute 定位在其中)。\n */\nconst AgentPanelDock = React.forwardRef<HTMLDivElement, AgentPanelDockProps>(\n (\n {\n open: openProp,\n // v14 條 F:「初次進入、重新整理、新開分頁…均**重新初始化為關閉的新對話**」。\n // 先前預設 true,等於每次進宿主都自動開著 —— 直接牴觸條 F(2026-09-08 跨模型審查抓到)。\n // 要一進來就開著的情境,由消費端顯式傳 `defaultOpen`,不靠 DS 預設。\n defaultOpen = false,\n onOpenChange,\n logoState = 'still',\n children,\n placement: placementProp,\n defaultPlacement = AGENT_FAB_HOME,\n onPlacementChange,\n ...fabProps\n },\n ref,\n ) => {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n const open = openProp ?? uncontrolledOpen\n const setOpen = React.useCallback(\n (next: boolean) => {\n if (openProp === undefined) setUncontrolledOpen(next)\n onOpenChange?.(next)\n },\n [openProp, onOpenChange],\n )\n // 非受控位置**住在這裡**,不能住在 AgentFabDock —— 面板開著時那顆會被卸載,state 會跟著消失,\n // 使用者收到邊、開面板、關面板後鈕就跑回右下角(2026-09-03 稽核抓到)。\n const [uncontrolledPlacement, setUncontrolledPlacement] = React.useState<AgentFabPlacement>(defaultPlacement)\n const placement = placementProp ?? uncontrolledPlacement\n const handlePlacementChange = React.useCallback(\n (next: AgentFabPlacement) => {\n if (placementProp === undefined) setUncontrolledPlacement(next)\n onPlacementChange?.(next)\n },\n [placementProp, onPlacementChange],\n )\n const close = React.useCallback(() => setOpen(false), [setOpen])\n // ── 2026-09-07 G2:關閉時**不再卸載面板**,改成藏起來 ──────────────────────\n //\n // 原本是 `if (open) return children`,關閉的瞬間整個面板連同它的 state 一起消失:\n // 捲到哪、輸入框裡打到一半的字、展開了哪些思考塊,全部歸零。\n // 這讓 spec 的兩條落不了地 —— E 條「閱讀位置保存」與 F 條「初始化為關閉」\n //(初始關閉之後第一次打開會是全新的面板,等於沒有「回到原本在看的地方」可言)。\n //\n // 為什麼是 `display:none` 而不是別的:2026-09-07 真瀏覽器實測四種隱藏方式,\n // **`display:none` 保住 `scrollTop`**(400 → 400)、輸入值保住、而且同時移出\n // tab order 與無障礙樹(隱藏時 `.focus()` 不生效)。`visibility:hidden` 也保狀態\n // 但**仍佔版面**,不能用。\n //\n // 為什麼外面要包一層 `display:contents`:面板通常是 flex/grid 的直接子項,\n // 憑空多一層盒子會改變版面。`display:contents` 讓這層從盒子樹消失,\n // 實測子項寬度與沒有 wrapper 時**逐像素相同**(472px vs 472px)。\n // 用 wrapper 而不是把 `hidden` 交給 render prop:交出去就會有人忘記套。\n return (\n <>\n <div style={{ display: open ? 'contents' : 'none' }}>\n {children({ close, logoState })}\n </div>\n {!open && (\n <AgentFabDock\n ref={ref}\n logoState={logoState}\n placement={placement}\n onPlacementChange={handlePlacementChange}\n onClick={() => setOpen(true)}\n {...fabProps}\n />\n )}\n </>\n )\n },\n)\nAgentPanelDock.displayName = 'AgentPanelDock'\n\nexport { AgentFab, AgentFabDock, AgentPanelDock }\n"],"names":["_a"],"mappings":"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"}
@@ -40,7 +40,7 @@ declare const PANEL_WIDTH_MAX = 640;
40
40
  * 匯出讓消費端可以用同一個數字排版,不必自己抄一個 960。
41
41
  */
42
42
  export declare const AGENT_PANEL_SIDE_BY_SIDE_MIN_CONTAINER: number;
43
- /** 面板形態:並排(flex 兄弟)或蓋板(absolute 蓋滿宿主);同時標在根節點 `data-agent-panel-mode`。 */
43
+ /** 面板形態:並排(flex 兄弟)或蓋板(absolute 覆蓋宿主、左留 `--layout-space-viewport-inset`);同時標在根節點 `data-agent-panel-mode`。 */
44
44
  export type AgentPanelMode = 'side-by-side' | 'overlay';
45
45
  export interface AgentPanelProps extends React.HTMLAttributes<HTMLDivElement> {
46
46
  /** 面板開合;false 時不渲染(關閉後由 AgentFab 承接入口,兩者互斥)。 */
@@ -56,7 +56,7 @@ export interface AgentPanelProps extends React.HTMLAttributes<HTMLDivElement> {
56
56
  /** 可拖拉(左緣把手);預設 true。Sheet 承載時同樣可拖。 */
57
57
  resizable?: boolean;
58
58
  /**
59
- * 蓋板態(容器 < 960,面板蓋滿宿主)仍要可用的節點 —— 與 Dialog 的 `persistentElements` 同一份契約、
59
+ * 蓋板態(容器 < 960,面板覆蓋宿主)仍要可用的節點 —— 與 Dialog 的 `persistentElements` 同一份契約、
60
60
  * 同一支 primitive(`lib/overlay-coexistence.ts`)。v14 條 B 說的「宿主暫不可操作」只講**宿主**;
61
61
  * 宿主之外的瀏覽器 chrome(網址列、上一頁 / 下一頁、重新整理)不是宿主,蓋板時不得被抑制
62
62
  * (2026-09-09 user:「範例變成滿版狀態時,上面那虛擬的網址列完全無法點擊」)。
@@ -71,6 +71,22 @@ export interface AgentPanelProps extends React.HTMLAttributes<HTMLDivElement> {
71
71
  * 詳 spec「與 app 的推擠與斷點」蓋板小節。
72
72
  */
73
73
  onModeChange?: (mode: AgentPanelMode) => void;
74
+ /**
75
+ * 蓋板態下**點擊面板外的遮罩**時通知消費端關閉面板(2026-09-17 user 裁示,取代 2026-09-16 的「點了不關」)。
76
+ *
77
+ * 命名依據 `ds-canonical/references/props-naming.md`:`onClose` = 「關閉 overlay session —— 浮層關閉回背景」,
78
+ * 與 Dialog / Sheet / Popover / FileViewer 同一個名字同一個語意(不是 `onDismiss`,那是「暫時訊息被忽略」)。
79
+ *
80
+ * **面板不自己關**:`open` 一直是消費端控的(同 `onModeChange` 那段的分工),所以這裡只發通知。
81
+ * 並排態沒有遮罩,此 prop 無作用。
82
+ *
83
+ * **必填,不是可選**(2026-09-18 修正):第一版寫成 `onClose?:`,理由是「向後相容,既有 consumer 一行都不用改」——
84
+ * 結果就是**沒傳的那些照舊點了不關**,而全庫最像產品的那則範例(`agent-panel.stories.tsx` 的 URL 註冊表示意)剛好沒傳,
85
+ * 於是使用者在預覽站上點遮罩「根本沒有任何反應」(2026-09-18 user 回報)。這正是本家族已經立過的規矩:
86
+ * spec §2「固定 anatomy 恆渲染」與 M23(f)「可省略 callback ≠ 可省略行為 —— 無內建行為的 callback 一律必填 prop(型別層擋)」。
87
+ * 面板自己關不了(`open` 住在 `AgentPanelDock`),所以它沒有內建 fallback → 必填。機械閘:`scripts/agent-panel-fixed-anatomy-invariant.mjs`。
88
+ */
89
+ onClose: () => void;
74
90
  }
75
91
  declare const AgentPanel: React.ForwardRefExoticComponent<AgentPanelProps & React.RefAttributes<HTMLDivElement>>;
76
92
  export interface AgentConversationSummary {
@@ -1 +1 @@
1
- {"version":3,"file":"agent-panel.d.ts","sourceRoot":"","sources":["../../../src/components/AgentPanel/agent-panel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-panel.d.ts","sourceRoot":"","sources":["../../../src/components/AgentPanel/agent-panel.tsx"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA4E9B,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACnE,OAAO,mBAAmB,CAAA;AAM1B,yEAAyE;AACzE,QAAA,MAAM,mBAAmB,MAAM,CAAA;AAC/B,QAAA,MAAM,eAAe,MAAM,CAAA;AAC3B,QAAA,MAAM,eAAe,MAAM,CAAA;AAiC3B;;;GAGG;AACH,eAAO,MAAM,sCAAsC,QAAqC,CAAA;AAExF,6GAA6G;AAC7G,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG,SAAS,CAAA;AAMvD,MAAM,WAAW,eAAgB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC3E,gDAAgD;IAChD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gDAAgD;IAChD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,kDAAkD;IAClD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,OAAO,EAAE,CAAA;IACpC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IAC7C;;;;;;;;;;;;;;OAcG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,QAAA,MAAM,UAAU,wFAoPf,CAAA;AAOD,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,qBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IACxD,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,yCAAyC;IACzC,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,gCAAgC;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,cAAc,CAAA;IAC1B,iCAAiC;IACjC,aAAa,CAAC,EAAE,wBAAwB,EAAE,CAAA;IAC1C,uBAAuB;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,yCAAyC;IACzC,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,oBAAoB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,4BAA4B;IAC5B,oBAAoB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1D;;;OAGG;IACH,oBAAoB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3C,gCAAgC;IAChC,iBAAiB,EAAE,MAAM,IAAI,CAAA;IAC7B,gDAAgD;IAChD,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAsFD,QAAA,MAAM,gBAAgB,2FAiNrB,CAAA;AAoED,MAAM,MAAM,sBAAsB,GAAG,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAA;AAKzE,QAAA,MAAM,iBAAiB,+FA8EtB,CAAA;AAOD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC7E,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACvB,wCAAwC;IACxC,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;IAC/B,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,KAAK,IAAI,CAAA;IACzD,oCAAoC;IACpC,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,QAAA,MAAM,YAAY,0FA4CjB,CAAA;AAOD,MAAM,WAAW,kBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IAC9D,kCAAkC;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,CAAA;IACzB,4BAA4B;IAC5B,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,gCAAgC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;CACvC;AAED,QAAA,MAAM,aAAa,2FAwDlB,CAAA;AAOD,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC7E;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAGhB,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,SAAS,EAAE,MAAM,IAAI,CAAA;CACtB;AAED,QAAA,MAAM,YAAY,0FA2BjB,CAAA;AAOD,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,qBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,CAAC;IAC9D,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,kCAAkC;IAClC,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,qCAAqC;IACrC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,wDAAwD;IACxD,WAAW,CAAC,EAAE,qBAAqB,EAAE,CAAA;IACrC,gCAAgC;IAChC,kBAAkB,EAAE,CAAC,UAAU,EAAE,qBAAqB,KAAK,IAAI,CAAA;IAC/D,2BAA2B;IAC3B,eAAe,EAAE,MAAM,IAAI,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AA4CD,QAAA,MAAM,gBAAgB,8FA+FrB,CAAA;AAOD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAA;IACb,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAA;IACV,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAA;IACb,6CAA6C;IAC7C,OAAO,EAAE,mBAAmB,EAAE,CAAA;IAC9B,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,yDAAyD;IACzD,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,sBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IACxE,qCAAqC;IACrC,SAAS,EAAE,qBAAqB,EAAE,CAAA;IAClC,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAA;IACpD,mDAAmD;IACnD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAA;CACnD;AAuCD,QAAA,MAAM,iBAAiB,+FAoNtB,CAAA;AAOD,MAAM,WAAW,yBAA0B,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACrF,yBAAyB;IACzB,OAAO,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CACrD;AAED,QAAA,MAAM,oBAAoB,kGAkBzB,CAAA;AAGD,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,IAAI,yBAAyB,EAChD,eAAe,IAAI,qBAAqB,EACxC,eAAe,IAAI,qBAAqB,GACzC,CAAA"}