@qijenchen/design-system 0.1.0-beta.145 → 0.1.0-beta.147

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (576) hide show
  1. package/dist/components/Accordion/accordion.d.ts +1 -1
  2. package/dist/components/Accordion/accordion.d.ts.map +1 -1
  3. package/dist/components/Accordion/accordion.js +8 -3
  4. package/dist/components/Accordion/accordion.js.map +1 -1
  5. package/dist/components/AccountMenu/account-menu.d.ts.map +1 -1
  6. package/dist/components/AccountMenu/account-menu.js.map +1 -1
  7. package/dist/components/AgentPanel/agent-panel-fab.d.ts +7 -1
  8. package/dist/components/AgentPanel/agent-panel-fab.d.ts.map +1 -1
  9. package/dist/components/AgentPanel/agent-panel-fab.js +36 -14
  10. package/dist/components/AgentPanel/agent-panel-fab.js.map +1 -1
  11. package/dist/components/AgentPanel/agent-panel-logo.d.ts +3 -3
  12. package/dist/components/AgentPanel/agent-panel-logo.js.map +1 -1
  13. package/dist/components/AgentPanel/agent-panel.d.ts +1 -1
  14. package/dist/components/AgentPanel/agent-panel.d.ts.map +1 -1
  15. package/dist/components/AgentPanel/agent-panel.js +28 -22
  16. package/dist/components/AgentPanel/agent-panel.js.map +1 -1
  17. package/dist/components/AppShell/app-shell.d.ts +1 -1
  18. package/dist/components/AppShell/app-shell.js +1 -1
  19. package/dist/components/AppShell/app-shell.js.map +1 -1
  20. package/dist/components/Avatar/avatar.d.ts +95 -1
  21. package/dist/components/Avatar/avatar.d.ts.map +1 -1
  22. package/dist/components/Avatar/avatar.js +106 -15
  23. package/dist/components/Avatar/avatar.js.map +1 -1
  24. package/dist/components/Avatar/index.js +14 -2
  25. package/dist/components/Breadcrumb/breadcrumb.d.ts +4 -2
  26. package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
  27. package/dist/components/Breadcrumb/breadcrumb.js +2 -2
  28. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
  29. package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -1
  30. package/dist/components/BulkActionBar/bulk-action-bar.js +27 -2
  31. package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -1
  32. package/dist/components/Button/button.d.ts +2 -2
  33. package/dist/components/Button/button.d.ts.map +1 -1
  34. package/dist/components/Button/button.js +118 -22
  35. package/dist/components/Button/button.js.map +1 -1
  36. package/dist/components/Calendar/calendar.d.ts +34 -10
  37. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  38. package/dist/components/Calendar/calendar.js +210 -36
  39. package/dist/components/Calendar/calendar.js.map +1 -1
  40. package/dist/components/Carousel/carousel.d.ts +1 -1
  41. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  42. package/dist/components/Carousel/carousel.js +3 -2
  43. package/dist/components/Carousel/carousel.js.map +1 -1
  44. package/dist/components/Chart/chart.d.ts +1 -0
  45. package/dist/components/Chart/chart.d.ts.map +1 -1
  46. package/dist/components/Chart/chart.js +8 -0
  47. package/dist/components/Chart/chart.js.map +1 -1
  48. package/dist/components/Checkbox/checkbox.d.ts +1 -1
  49. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  50. package/dist/components/Checkbox/checkbox.js +10 -2
  51. package/dist/components/Checkbox/checkbox.js.map +1 -1
  52. package/dist/components/Chip/chip.d.ts +1 -1
  53. package/dist/components/Chip/chip.d.ts.map +1 -1
  54. package/dist/components/Chip/chip.js +4 -2
  55. package/dist/components/Chip/chip.js.map +1 -1
  56. package/dist/components/Combobox/combobox.d.ts +1 -1
  57. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  58. package/dist/components/Combobox/combobox.js +37 -11
  59. package/dist/components/Combobox/combobox.js.map +1 -1
  60. package/dist/components/Command/command.d.ts +1 -1
  61. package/dist/components/Command/command.d.ts.map +1 -1
  62. package/dist/components/Command/command.js +106 -8
  63. package/dist/components/Command/command.js.map +1 -1
  64. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  65. package/dist/components/DataTable/cell-registry.js +3 -2
  66. package/dist/components/DataTable/cell-registry.js.map +1 -1
  67. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts.map +1 -1
  68. package/dist/components/DataTable/data-table-column-visibility-panel.js +24 -24
  69. package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -1
  70. package/dist/components/DataTable/data-table-interaction-layer.d.ts +2 -1
  71. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  72. package/dist/components/DataTable/data-table-interaction-layer.js +3 -4
  73. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  74. package/dist/components/DataTable/data-table-sort-manager.d.ts.map +1 -1
  75. package/dist/components/DataTable/data-table-sort-manager.js +20 -20
  76. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -1
  77. package/dist/components/DataTable/data-table.d.ts +8 -5
  78. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  79. package/dist/components/DataTable/data-table.js +197 -71
  80. package/dist/components/DataTable/data-table.js.map +1 -1
  81. package/dist/components/DateGrid/date-grid.d.ts +1 -1
  82. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  83. package/dist/components/DateGrid/date-grid.js +358 -225
  84. package/dist/components/DateGrid/date-grid.js.map +1 -1
  85. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  86. package/dist/components/DatePicker/date-picker.js +16 -1
  87. package/dist/components/DatePicker/date-picker.js.map +1 -1
  88. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  89. package/dist/components/Dialog/dialog.js +55 -43
  90. package/dist/components/Dialog/dialog.js.map +1 -1
  91. package/dist/components/DropdownMenu/dropdown-menu-keyboard.d.ts +86 -0
  92. package/dist/components/DropdownMenu/dropdown-menu-keyboard.d.ts.map +1 -0
  93. package/dist/components/DropdownMenu/dropdown-menu-keyboard.js +172 -0
  94. package/dist/components/DropdownMenu/dropdown-menu-keyboard.js.map +1 -0
  95. package/dist/components/DropdownMenu/dropdown-menu.d.ts +6 -1
  96. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  97. package/dist/components/DropdownMenu/dropdown-menu.js +50 -39
  98. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  99. package/dist/components/Field/field-context.d.ts +4 -0
  100. package/dist/components/Field/field-context.d.ts.map +1 -1
  101. package/dist/components/Field/field-context.js +1 -2
  102. package/dist/components/Field/field-context.js.map +1 -1
  103. package/dist/components/Field/field-edit-keys.d.ts +8 -0
  104. package/dist/components/Field/field-edit-keys.d.ts.map +1 -1
  105. package/dist/components/Field/field-edit-keys.js +3 -0
  106. package/dist/components/Field/field-edit-keys.js.map +1 -1
  107. package/dist/components/Field/field-wrapper.d.ts +18 -1
  108. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  109. package/dist/components/Field/field-wrapper.js +39 -10
  110. package/dist/components/Field/field-wrapper.js.map +1 -1
  111. package/dist/components/Field/field.d.ts +3 -2
  112. package/dist/components/Field/field.d.ts.map +1 -1
  113. package/dist/components/Field/field.js +2 -1
  114. package/dist/components/Field/field.js.map +1 -1
  115. package/dist/components/FileItem/file-item.d.ts +26 -2
  116. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  117. package/dist/components/FileItem/file-item.js +82 -25
  118. package/dist/components/FileItem/file-item.js.map +1 -1
  119. package/dist/components/FileItem/index.js +4 -2
  120. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  121. package/dist/components/FileUpload/file-upload.d.ts.map +1 -1
  122. package/dist/components/FileUpload/file-upload.js +132 -55
  123. package/dist/components/FileUpload/file-upload.js.map +1 -1
  124. package/dist/components/FileViewer/file-viewer.d.ts +1 -1
  125. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  126. package/dist/components/FileViewer/file-viewer.js +9 -4
  127. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  128. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -1
  129. package/dist/components/InlineEdit/inline-edit.js +1 -1
  130. package/dist/components/InlineEdit/inline-edit.js.map +1 -1
  131. package/dist/components/Input/input.d.ts.map +1 -1
  132. package/dist/components/Input/input.js +6 -1
  133. package/dist/components/Input/input.js.map +1 -1
  134. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  135. package/dist/components/LinkInput/link-input.js +20 -4
  136. package/dist/components/LinkInput/link-input.js.map +1 -1
  137. package/dist/components/Notice/notice.js +1 -1
  138. package/dist/components/Notice/notice.js.map +1 -1
  139. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  140. package/dist/components/NumberInput/number-input.js +6 -1
  141. package/dist/components/NumberInput/number-input.js.map +1 -1
  142. package/dist/components/OverflowIndicator/index.js +2 -1
  143. package/dist/components/OverflowIndicator/overflow-indicator.d.ts +19 -1
  144. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  145. package/dist/components/OverflowIndicator/overflow-indicator.js +47 -27
  146. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  147. package/dist/components/Pagination/pagination.d.ts +1 -1
  148. package/dist/components/Pagination/pagination.js +1 -1
  149. package/dist/components/Pagination/pagination.js.map +1 -1
  150. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts +7 -6
  151. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts.map +1 -1
  152. package/dist/components/PeoplePicker/avatar-stack-overflow.js +6 -7
  153. package/dist/components/PeoplePicker/avatar-stack-overflow.js.map +1 -1
  154. package/dist/components/PeoplePicker/people-picker-helpers.d.ts.map +1 -1
  155. package/dist/components/PeoplePicker/people-picker-helpers.js +1 -1
  156. package/dist/components/PeoplePicker/people-picker-helpers.js.map +1 -1
  157. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  158. package/dist/components/PeoplePicker/people-picker.js +2 -2
  159. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  160. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  161. package/dist/components/PeoplePicker/person-display.js +26 -28
  162. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  163. package/dist/components/ProfileCard/profile-card.d.ts.map +1 -1
  164. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  165. package/dist/components/RadioGroup/radio-group.d.ts +1 -1
  166. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  167. package/dist/components/RadioGroup/radio-group.js +10 -4
  168. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  169. package/dist/components/Rating/rating.d.ts +28 -6
  170. package/dist/components/Rating/rating.d.ts.map +1 -1
  171. package/dist/components/Rating/rating.js +97 -80
  172. package/dist/components/Rating/rating.js.map +1 -1
  173. package/dist/components/ScrollArea/scroll-area.d.ts +1 -1
  174. package/dist/components/ScrollArea/scroll-area.js +1 -1
  175. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  176. package/dist/components/SegmentedControl/segmented-control.d.ts +1 -1
  177. package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -1
  178. package/dist/components/SegmentedControl/segmented-control.js +3 -2
  179. package/dist/components/SegmentedControl/segmented-control.js.map +1 -1
  180. package/dist/components/Select/select.d.ts.map +1 -1
  181. package/dist/components/Select/select.js +15 -8
  182. package/dist/components/Select/select.js.map +1 -1
  183. package/dist/components/SelectMenu/index.js +2 -1
  184. package/dist/components/SelectMenu/index.js.map +1 -1
  185. package/dist/components/SelectMenu/select-menu-keyboard.d.ts +59 -0
  186. package/dist/components/SelectMenu/select-menu-keyboard.d.ts.map +1 -0
  187. package/dist/components/SelectMenu/select-menu-keyboard.js +107 -0
  188. package/dist/components/SelectMenu/select-menu-keyboard.js.map +1 -0
  189. package/dist/components/SelectMenu/select-menu.d.ts +1 -22
  190. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  191. package/dist/components/SelectMenu/select-menu.js +18 -34
  192. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  193. package/dist/components/SelectionControl/selection-item.d.ts.map +1 -1
  194. package/dist/components/SelectionControl/selection-item.js +1 -0
  195. package/dist/components/SelectionControl/selection-item.js.map +1 -1
  196. package/dist/components/Sidebar/sidebar.d.ts +7 -9
  197. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  198. package/dist/components/Sidebar/sidebar.js +171 -50
  199. package/dist/components/Sidebar/sidebar.js.map +1 -1
  200. package/dist/components/Slider/slider.d.ts +1 -1
  201. package/dist/components/Slider/slider.d.ts.map +1 -1
  202. package/dist/components/Slider/slider.js +9 -4
  203. package/dist/components/Slider/slider.js.map +1 -1
  204. package/dist/components/Steps/steps.d.ts.map +1 -1
  205. package/dist/components/Steps/steps.js +54 -26
  206. package/dist/components/Steps/steps.js.map +1 -1
  207. package/dist/components/Switch/switch.d.ts +1 -1
  208. package/dist/components/Switch/switch.d.ts.map +1 -1
  209. package/dist/components/Switch/switch.js +7 -2
  210. package/dist/components/Switch/switch.js.map +1 -1
  211. package/dist/components/Tabs/tabs.d.ts +1 -1
  212. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  213. package/dist/components/Tabs/tabs.js +39 -4
  214. package/dist/components/Tabs/tabs.js.map +1 -1
  215. package/dist/components/Tag/tag.d.ts +1 -1
  216. package/dist/components/Tag/tag.d.ts.map +1 -1
  217. package/dist/components/Tag/tag.js +3 -2
  218. package/dist/components/Tag/tag.js.map +1 -1
  219. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  220. package/dist/components/Textarea/textarea.js +8 -2
  221. package/dist/components/Textarea/textarea.js.map +1 -1
  222. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  223. package/dist/components/TimePicker/time-columns.js +8 -4
  224. package/dist/components/TimePicker/time-columns.js.map +1 -1
  225. package/dist/components/TimePicker/time-picker.d.ts +1 -1
  226. package/dist/components/TimePicker/time-picker.js +1 -1
  227. package/dist/components/TimePicker/time-picker.js.map +1 -1
  228. package/dist/components/TreeView/tree-view.d.ts +9 -5
  229. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  230. package/dist/components/TreeView/tree-view.js +266 -214
  231. package/dist/components/TreeView/tree-view.js.map +1 -1
  232. package/dist/hooks/use-input-modality.d.ts +12 -17
  233. package/dist/hooks/use-input-modality.d.ts.map +1 -1
  234. package/dist/hooks/use-input-modality.js +4 -34
  235. package/dist/hooks/use-input-modality.js.map +1 -1
  236. package/dist/hooks/use-overflow-items.d.ts.map +1 -1
  237. package/dist/hooks/use-overflow-items.js +2 -0
  238. package/dist/hooks/use-overflow-items.js.map +1 -1
  239. package/dist/hooks/use-truncated.d.ts.map +1 -1
  240. package/dist/hooks/use-truncated.js.map +1 -1
  241. package/dist/index.d.ts +3 -0
  242. package/dist/index.d.ts.map +1 -1
  243. package/dist/index.js +23 -3
  244. package/dist/index.js.map +1 -1
  245. package/dist/lib/drag-announcements.d.ts +32 -0
  246. package/dist/lib/drag-announcements.d.ts.map +1 -1
  247. package/dist/lib/drag-announcements.js +39 -1
  248. package/dist/lib/drag-announcements.js.map +1 -1
  249. package/dist/lib/focus-after-trigger.d.ts +45 -0
  250. package/dist/lib/focus-after-trigger.d.ts.map +1 -0
  251. package/dist/lib/focus-after-trigger.js +66 -0
  252. package/dist/lib/focus-after-trigger.js.map +1 -0
  253. package/dist/lib/overlay-coexistence.js +1 -1
  254. package/dist/lib/roving-list-keyboard.d.ts +208 -0
  255. package/dist/lib/roving-list-keyboard.d.ts.map +1 -0
  256. package/dist/lib/roving-list-keyboard.js +174 -0
  257. package/dist/lib/roving-list-keyboard.js.map +1 -0
  258. package/dist/lib/utils.d.ts.map +1 -1
  259. package/dist/lib/utils.js +6 -1
  260. package/dist/lib/utils.js.map +1 -1
  261. package/dist/patterns/element-anatomy/item-anatomy.d.ts +4 -4
  262. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  263. package/dist/patterns/element-anatomy/item-anatomy.js +14 -4
  264. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  265. package/dist/patterns/horizontal-overflow/horizontal-overflow.d.ts.map +1 -1
  266. package/dist/patterns/horizontal-overflow/horizontal-overflow.js +25 -0
  267. package/dist/patterns/horizontal-overflow/horizontal-overflow.js.map +1 -1
  268. package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -1
  269. package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -1
  270. package/dist/tokens/categorical-color.d.ts +6 -1
  271. package/dist/tokens/categorical-color.d.ts.map +1 -1
  272. package/dist/tokens/categorical-color.js.map +1 -1
  273. package/dist/tokens/uiSize/icon-size.d.ts +1 -1
  274. package/dist/tokens/uiSize/stack-gap.d.ts +18 -0
  275. package/dist/tokens/uiSize/stack-gap.d.ts.map +1 -0
  276. package/dist/tokens/uiSize/stack-gap.js +5 -0
  277. package/dist/tokens/uiSize/stack-gap.js.map +1 -0
  278. package/ds-canonical/fork/codex/agents/skills/performance-audit/SKILL.md +1 -1
  279. package/ds-canonical/fork/codex/hooks.json +1 -1
  280. package/ds-canonical/fork/consumer/lock.json +17 -14
  281. package/ds-canonical/fork/consumer/managed-files/423729840acdd43c812f17c245b871716c6b60f76e4d3e94864d0e34a815bf8d.blob +9 -0
  282. package/ds-canonical/fork/consumer/managed-files/46f10bc55cdfdf834d0749eebff42ea0bb8576f361b36d2b6ba1851354c50150.blob +47 -9
  283. package/ds-canonical/fork/consumer/managed-files/5a0d134a2645114c8caac20458070b00a7f0fd55b3e8805b7325cb4cf52fa15e.blob +110 -0
  284. package/ds-canonical/fork/consumer/managed-files/5af0a46760af338d51fd0f7950675f8e97f7d2f09386b8818fcd7a58e6654e75.blob +790 -0
  285. package/ds-canonical/fork/consumer/managed-files/68bfcddff9c4a16388c248cd34fb66163e9e64b3d809a48ef3984f6ae4ff6d12.blob +211 -0
  286. package/ds-canonical/fork/consumer/managed-files/7eb6cc60abfdabaf6617c336058fad1454ccde08889295767bfd9b7fd153cc6e.blob +45 -6
  287. package/ds-canonical/fork/consumer/managed-files/92e4828cdcb96ff0d01daa16f6885f24045a8e72820665650f2a1890dc3a446c.blob +42 -2
  288. package/ds-canonical/fork/consumer/managed-files/ab072e7f2eca51f0e18a5e18c4b333260ee5d219a12cc6df5bb2d683f0b2734d.blob +27 -1
  289. package/ds-canonical/fork/consumer/managed-files/e71c65f45c6af7ce12b6b3c0d8028f185da5b719e2050c9b2a6b243d41ae4878.blob +62 -14
  290. package/ds-canonical/fork/governance.lock +41 -17
  291. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +16 -4
  292. package/ds-canonical/fork/hooks/check_consumer_code_quality.sh +3 -1
  293. package/ds-canonical/fork/hooks/check_pattern_invariants.sh +13 -9
  294. package/ds-canonical/fork/launchers/settings-hooks.json +1 -1
  295. package/ds-canonical/fork/manifest.json +17 -11
  296. package/ds-canonical/fork/providers/claude/skills/performance-audit/SKILL.md +1 -1
  297. package/ds-canonical/fork/providers/codex/hook-config.json +1 -1
  298. package/ds-canonical/fork/providers/codex/skills/performance-audit/SKILL.md +1 -1
  299. package/ds-canonical/fork/skills/performance-audit/SKILL.md +1 -1
  300. package/ds-canonical/hooks/check_consumer_app_invariants.sh +16 -4
  301. package/ds-canonical/hooks/check_consumer_code_quality.sh +3 -1
  302. package/ds-canonical/hooks/check_datatable_invariants.sh +4 -1
  303. package/ds-canonical/hooks/check_pattern_invariants.sh +13 -9
  304. package/ds-canonical/hooks/check_plugin_fork_health.sh +8 -1
  305. package/ds-canonical/hooks/check_propose_discipline.sh +8 -1
  306. package/ds-canonical/hooks/check_storybook_addon_packaging.sh +8 -1
  307. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +64 -2
  308. package/ds-canonical/hooks/lib/_overlay_handcraft.sh +5 -2
  309. package/ds-canonical/hooks/registrations.json +12 -7
  310. package/ds-canonical/hooks/session_start_governance_check.sh +16 -0
  311. package/ds-canonical/hooks/tests/test_check_consumer_app_invariants.sh +25 -0
  312. package/ds-canonical/hooks/tests/test_check_consumer_code_quality.sh +4 -0
  313. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +14 -0
  314. package/ds-canonical/hooks/tests/test_check_datatable_invariants.sh +24 -0
  315. package/ds-canonical/hooks/tests/test_check_overlay_handcraft.sh +32 -0
  316. package/ds-canonical/hooks/tests/test_check_pattern_invariants.sh +59 -0
  317. package/ds-canonical/hooks/tests/test_check_plugin_fork_health.sh +32 -1
  318. package/ds-canonical/hooks/tests/test_check_propose_discipline.sh +21 -0
  319. package/ds-canonical/hooks/tests/test_check_storybook_addon_packaging.sh +21 -0
  320. package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +97 -0
  321. package/ds-canonical/hooks/tests/test_session_start_governance_check.sh +49 -0
  322. package/ds-canonical/references/README.md +12 -6
  323. package/ds-canonical/references/drag-canonical.md +3 -1
  324. package/ds-canonical/references/focus-canonical.md +26 -13
  325. package/ds-canonical/references/governance-audit-coverage.md +1 -1
  326. package/ds-canonical/references/hit-area-canonical.md +361 -0
  327. package/ds-canonical/references/item-anatomy-recipe.md +4 -2
  328. package/ds-canonical/references/keyboard-model-canonical.md +559 -0
  329. package/ds-canonical/rules/meta-patterns.md +4 -4
  330. package/ds-canonical/rules/self-verify.md +4 -4
  331. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +1 -1
  332. package/ds-canonical/skills/design-system-audit/references/historical-bugs.md +96 -0
  333. package/ds-canonical/skills/knowledge-prune/SKILL.md +4 -1
  334. package/ds-canonical/skills/performance-audit/SKILL.md +1 -1
  335. package/ds-story-manifest.json +19 -7
  336. package/llms-full.txt +2 -2
  337. package/llms.txt +2 -2
  338. package/package.json +3 -1
  339. package/src/components/Accordion/accordion.anatomy.stories.tsx +3 -3
  340. package/src/components/Accordion/accordion.spec.md +1 -1
  341. package/src/components/Accordion/accordion.tsx +8 -3
  342. package/src/components/AccountMenu/account-menu.spec.md +2 -3
  343. package/src/components/AccountMenu/account-menu.tsx +0 -1
  344. package/src/components/AgentPanel/agent-decision-card.spec.md +88 -0
  345. package/src/components/AgentPanel/agent-panel-fab.spec.md +151 -0
  346. package/src/components/AgentPanel/agent-panel-fab.tsx +67 -24
  347. package/src/components/AgentPanel/agent-panel-logo.spec.md +87 -0
  348. package/src/components/AgentPanel/agent-panel-logo.tsx +3 -3
  349. package/src/components/AgentPanel/agent-panel.anatomy.stories.tsx +1 -1
  350. package/src/components/AgentPanel/agent-panel.principles.stories.tsx +1 -1
  351. package/src/components/AgentPanel/agent-panel.spec.md +30 -275
  352. package/src/components/AgentPanel/agent-panel.stories.tsx +113 -8
  353. package/src/components/AgentPanel/agent-panel.tsx +59 -22
  354. package/src/components/Alert/alert.anatomy.stories.tsx +1 -1
  355. package/src/components/AppShell/app-shell.tsx +1 -1
  356. package/src/components/AspectRatio/aspect-ratio.anatomy.stories.tsx +10 -15
  357. package/src/components/Avatar/avatar.anatomy.stories.tsx +23 -26
  358. package/src/components/Avatar/avatar.principles.stories.tsx +10 -10
  359. package/src/components/Avatar/avatar.spec.md +45 -6
  360. package/src/components/Avatar/avatar.stories.tsx +8 -8
  361. package/src/components/Avatar/avatar.tsx +227 -21
  362. package/src/components/Badge/badge.anatomy.stories.tsx +16 -21
  363. package/src/components/Breadcrumb/breadcrumb.anatomy.stories.tsx +3 -3
  364. package/src/components/Breadcrumb/breadcrumb.spec.md +3 -3
  365. package/src/components/Breadcrumb/breadcrumb.tsx +5 -3
  366. package/src/components/BulkActionBar/bulk-action-bar.anatomy.stories.tsx +1 -1
  367. package/src/components/BulkActionBar/bulk-action-bar.principles.stories.tsx +1 -1
  368. package/src/components/BulkActionBar/bulk-action-bar.spec.md +1 -0
  369. package/src/components/BulkActionBar/bulk-action-bar.stories.tsx +57 -2
  370. package/src/components/BulkActionBar/bulk-action-bar.tsx +32 -2
  371. package/src/components/Button/button.anatomy.stories.tsx +174 -33
  372. package/src/components/Button/button.spec.md +23 -8
  373. package/src/components/Button/button.tsx +116 -21
  374. package/src/components/Calendar/calendar.anatomy.stories.tsx +34 -11
  375. package/src/components/Calendar/calendar.principles.stories.tsx +44 -1
  376. package/src/components/Calendar/calendar.spec.md +97 -20
  377. package/src/components/Calendar/calendar.stories.tsx +101 -4
  378. package/src/components/Calendar/calendar.tsx +379 -74
  379. package/src/components/Carousel/carousel.anatomy.stories.tsx +16 -17
  380. package/src/components/Carousel/carousel.spec.md +48 -2
  381. package/src/components/Carousel/carousel.tsx +9 -3
  382. package/src/components/Chart/chart.anatomy.stories.tsx +7 -5
  383. package/src/components/Chart/chart.spec.md +32 -7
  384. package/src/components/Chart/chart.tsx +9 -0
  385. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +21 -28
  386. package/src/components/Checkbox/checkbox.spec.md +4 -2
  387. package/src/components/Checkbox/checkbox.tsx +10 -2
  388. package/src/components/Chip/chip.anatomy.stories.tsx +1 -1
  389. package/src/components/Chip/chip.spec.md +2 -1
  390. package/src/components/Chip/chip.tsx +4 -2
  391. package/src/components/Combobox/combobox.anatomy.stories.tsx +30 -37
  392. package/src/components/Combobox/combobox.spec.md +11 -3
  393. package/src/components/Combobox/combobox.tsx +43 -12
  394. package/src/components/Command/command.spec.md +11 -0
  395. package/src/components/Command/command.tsx +143 -10
  396. package/src/components/DataTable/cell-registry.tsx +5 -1
  397. package/src/components/DataTable/data-table-column-visibility-panel.tsx +5 -6
  398. package/src/components/DataTable/data-table-interaction-layer.tsx +27 -14
  399. package/src/components/DataTable/data-table-known-defects.spec.md +72 -0
  400. package/src/components/DataTable/data-table-scroll-performance.spec.md +295 -0
  401. package/src/components/DataTable/data-table-sort-manager.tsx +5 -6
  402. package/src/components/DataTable/data-table.anatomy.stories.tsx +1 -1
  403. package/src/components/DataTable/data-table.css +64 -0
  404. package/src/components/DataTable/data-table.spec.md +70 -346
  405. package/src/components/DataTable/data-table.stories.tsx +56 -9
  406. package/src/components/DataTable/data-table.tsx +392 -103
  407. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +2 -2
  408. package/src/components/DateGrid/date-grid.spec.md +163 -1
  409. package/src/components/DateGrid/date-grid.tsx +270 -7
  410. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +18 -27
  411. package/src/components/DatePicker/date-picker.spec.md +6 -2
  412. package/src/components/DatePicker/date-picker.tsx +20 -1
  413. package/src/components/Dialog/dialog.spec.md +6 -2
  414. package/src/components/Dialog/dialog.stories.tsx +18 -9
  415. package/src/components/Dialog/dialog.tsx +83 -48
  416. package/src/components/DropdownMenu/dropdown-menu-keyboard.ts +255 -0
  417. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +32 -33
  418. package/src/components/DropdownMenu/dropdown-menu.spec.md +18 -5
  419. package/src/components/DropdownMenu/dropdown-menu.stories.tsx +58 -1
  420. package/src/components/DropdownMenu/dropdown-menu.tsx +70 -33
  421. package/src/components/Empty/empty.spec.md +1 -2
  422. package/src/components/Field/field-context.ts +9 -4
  423. package/src/components/Field/field-controls.spec.md +5 -2
  424. package/src/components/Field/field-edit-keys.ts +12 -0
  425. package/src/components/Field/field-wrapper.tsx +76 -10
  426. package/src/components/Field/field.anatomy.stories.tsx +1 -1
  427. package/src/components/Field/field.spec.md +11 -6
  428. package/src/components/Field/field.stories.tsx +24 -1
  429. package/src/components/Field/field.tsx +10 -4
  430. package/src/components/FileItem/file-item.anatomy.stories.tsx +20 -10
  431. package/src/components/FileItem/file-item.principles.stories.tsx +14 -7
  432. package/src/components/FileItem/file-item.spec.md +50 -48
  433. package/src/components/FileItem/file-item.stories.tsx +41 -28
  434. package/src/components/FileItem/file-item.tsx +184 -50
  435. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +11 -15
  436. package/src/components/FileUpload/file-upload.spec.md +27 -1
  437. package/src/components/FileUpload/file-upload.stories.tsx +33 -0
  438. package/src/components/FileUpload/file-upload.tsx +173 -43
  439. package/src/components/FileViewer/file-viewer.tsx +9 -4
  440. package/src/components/HoverCard/hover-card.stories.tsx +2 -2
  441. package/src/components/InlineEdit/inline-edit.spec.md +2 -0
  442. package/src/components/InlineEdit/inline-edit.tsx +8 -3
  443. package/src/components/Input/input.anatomy.stories.tsx +23 -31
  444. package/src/components/Input/input.spec.md +11 -0
  445. package/src/components/Input/input.tsx +6 -1
  446. package/src/components/LinkInput/link-input.anatomy.stories.tsx +18 -21
  447. package/src/components/LinkInput/link-input.principles.stories.tsx +4 -4
  448. package/src/components/LinkInput/link-input.spec.md +12 -1
  449. package/src/components/LinkInput/link-input.tsx +37 -4
  450. package/src/components/Menu/menu-item.anatomy.stories.tsx +50 -56
  451. package/src/components/Menu/menu-item.spec.md +1 -1
  452. package/src/components/Menu/menu-item.stories.tsx +48 -42
  453. package/src/components/Notice/notice.anatomy.stories.tsx +8 -16
  454. package/src/components/Notice/notice.spec.md +1 -1
  455. package/src/components/Notice/notice.tsx +1 -1
  456. package/src/components/NumberInput/number-input.anatomy.stories.tsx +21 -28
  457. package/src/components/NumberInput/number-input.spec.md +2 -0
  458. package/src/components/NumberInput/number-input.tsx +8 -1
  459. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +28 -48
  460. package/src/components/OverflowIndicator/overflow-indicator.spec.md +13 -1
  461. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +12 -9
  462. package/src/components/OverflowIndicator/overflow-indicator.tsx +32 -12
  463. package/src/components/Pagination/pagination.spec.md +1 -0
  464. package/src/components/Pagination/pagination.tsx +1 -1
  465. package/src/components/PeoplePicker/avatar-stack-overflow.ts +14 -13
  466. package/src/components/PeoplePicker/people-picker-helpers.ts +5 -2
  467. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +1 -1
  468. package/src/components/PeoplePicker/people-picker.spec.md +4 -2
  469. package/src/components/PeoplePicker/people-picker.tsx +1 -4
  470. package/src/components/PeoplePicker/person-display.tsx +45 -28
  471. package/src/components/Popover/popover.anatomy.stories.tsx +1 -1
  472. package/src/components/Popover/popover.principles.stories.tsx +3 -12
  473. package/src/components/Popover/popover.spec.md +7 -3
  474. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +1 -1
  475. package/src/components/ProfileCard/profile-card.spec.md +1 -1
  476. package/src/components/ProfileCard/profile-card.tsx +0 -3
  477. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +11 -21
  478. package/src/components/ProgressBar/progress-bar.spec.md +1 -1
  479. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +17 -24
  480. package/src/components/RadioGroup/radio-group.spec.md +1 -1
  481. package/src/components/RadioGroup/radio-group.tsx +22 -4
  482. package/src/components/Rating/rating.anatomy.stories.tsx +131 -124
  483. package/src/components/Rating/rating.principles.stories.tsx +69 -43
  484. package/src/components/Rating/rating.spec.md +142 -63
  485. package/src/components/Rating/rating.stories.tsx +11 -15
  486. package/src/components/Rating/rating.tsx +131 -117
  487. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  488. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +6 -3
  489. package/src/components/ScrollArea/scroll-area.spec.md +3 -1
  490. package/src/components/ScrollArea/scroll-area.stories.tsx +5 -2
  491. package/src/components/ScrollArea/scroll-area.tsx +1 -1
  492. package/src/components/SegmentedControl/segmented-control.anatomy.stories.tsx +1 -1
  493. package/src/components/SegmentedControl/segmented-control.spec.md +2 -2
  494. package/src/components/SegmentedControl/segmented-control.tsx +3 -2
  495. package/src/components/Select/select.anatomy.stories.tsx +26 -35
  496. package/src/components/Select/select.spec.md +4 -3
  497. package/src/components/Select/select.tsx +11 -4
  498. package/src/components/SelectMenu/select-menu-keyboard.ts +218 -0
  499. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +6 -17
  500. package/src/components/SelectMenu/select-menu.spec.md +12 -4
  501. package/src/components/SelectMenu/select-menu.tsx +21 -56
  502. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +9 -33
  503. package/src/components/SelectionControl/selection-item.spec.md +2 -2
  504. package/src/components/SelectionControl/selection-item.tsx +3 -1
  505. package/src/components/Separator/separator.stories.tsx +4 -4
  506. package/src/components/Sheet/sheet.principles.stories.tsx +31 -13
  507. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +1 -1
  508. package/src/components/Sidebar/sidebar.spec.md +73 -6
  509. package/src/components/Sidebar/sidebar.stories.tsx +82 -4
  510. package/src/components/Sidebar/sidebar.tsx +281 -64
  511. package/src/components/Skeleton/skeleton.spec.md +1 -1
  512. package/src/components/Slider/slider.anatomy.stories.tsx +1 -1
  513. package/src/components/Slider/slider.spec.md +6 -5
  514. package/src/components/Slider/slider.tsx +13 -8
  515. package/src/components/Steps/steps-state-visuals.spec.md +157 -0
  516. package/src/components/Steps/steps.anatomy.stories.tsx +1 -0
  517. package/src/components/Steps/steps.spec.md +59 -142
  518. package/src/components/Steps/steps.stories.tsx +1 -1
  519. package/src/components/Steps/steps.tsx +125 -33
  520. package/src/components/Switch/switch.spec.md +3 -3
  521. package/src/components/Switch/switch.tsx +6 -1
  522. package/src/components/Tabs/tabs.spec.md +5 -1
  523. package/src/components/Tabs/tabs.tsx +42 -3
  524. package/src/components/Tag/tag.anatomy.stories.tsx +24 -28
  525. package/src/components/Tag/tag.spec.md +10 -11
  526. package/src/components/Tag/tag.tsx +3 -3
  527. package/src/components/Textarea/textarea.tsx +7 -1
  528. package/src/components/TimePicker/time-columns.tsx +9 -4
  529. package/src/components/TimePicker/time-picker.spec.md +4 -1
  530. package/src/components/TimePicker/time-picker.tsx +1 -1
  531. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +6 -15
  532. package/src/components/Tooltip/tooltip.principles.stories.tsx +4 -16
  533. package/src/components/Tooltip/tooltip.spec.md +2 -1
  534. package/src/components/TreeView/tree-view.anatomy.stories.tsx +35 -13
  535. package/src/components/TreeView/tree-view.spec.md +67 -38
  536. package/src/components/TreeView/tree-view.stories.tsx +221 -12
  537. package/src/components/TreeView/tree-view.tsx +463 -356
  538. package/src/hooks/use-input-modality.ts +17 -46
  539. package/src/hooks/use-overflow-items.ts +4 -0
  540. package/src/hooks/use-truncated.ts +3 -2
  541. package/src/index.ts +17 -0
  542. package/src/lib/README.md +2 -0
  543. package/src/lib/drag-announcements.ts +78 -0
  544. package/src/lib/focus-after-trigger.ts +102 -0
  545. package/src/lib/roving-list-keyboard.ts +400 -0
  546. package/src/lib/utils.ts +5 -0
  547. package/src/patterns/action-bar/action-bar.spec.md +2 -0
  548. package/src/patterns/element-anatomy/inline-action.spec.md +16 -12
  549. package/src/patterns/element-anatomy/item-anatomy.spec.md +98 -6
  550. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +75 -70
  551. package/src/patterns/element-anatomy/item-anatomy.tsx +17 -6
  552. package/src/patterns/element-anatomy/truncated-text.spec.md +1 -0
  553. package/src/patterns/header-canonical/header-canonical.spec.md +3 -2
  554. package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +2 -0
  555. package/src/patterns/horizontal-overflow/horizontal-overflow.stories.tsx +36 -0
  556. package/src/patterns/horizontal-overflow/horizontal-overflow.tsx +28 -0
  557. package/src/patterns/overlay-surface/overlay-chrome-sizing.spec.md +180 -0
  558. package/src/patterns/overlay-surface/overlay-surface.spec.md +8 -162
  559. package/src/patterns/overlay-surface/overlay-surface.tsx +5 -3
  560. package/src/patterns/resize-handle/resize-handle.spec.md +3 -3
  561. package/src/styles/base.css +1 -1
  562. package/src/tokens/categorical-color.ts +6 -1
  563. package/src/tokens/color/color.spec.md +91 -24
  564. package/src/tokens/color/color.stories.tsx +50 -2
  565. package/src/tokens/color/primitives.css +41 -38
  566. package/src/tokens/color/semantic.css +105 -36
  567. package/src/tokens/layoutSpace/layoutSpace.spec.md +2 -0
  568. package/src/tokens/motion/motion.spec.md +31 -8
  569. package/src/tokens/orphan-tokens.spec.md +1 -1
  570. package/src/tokens/uiSize/icon-size.ts +1 -1
  571. package/src/tokens/uiSize/stack-gap.ts +17 -0
  572. package/src/tokens/uiSize/uiSize.css +12 -0
  573. package/src/tokens/uiSize/uiSize.spec.md +17 -16
  574. package/src/tokens/uiSize/uiSize.stories.tsx +1 -1
  575. package/dist/node_modules/aria-hidden/dist/es2015/index.js +0 -147
  576. package/dist/node_modules/aria-hidden/dist/es2015/index.js.map +0 -1
@@ -1,14 +1,15 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { ChevronLeft, ChevronRight, Plus } from "lucide-react";
4
- import { startOfMonth, endOfMonth, startOfWeek, endOfWeek, eachDayOfInterval, isSameMonth, isSameDay, format, subMonths, addMonths } from "date-fns";
4
+ import { startOfMonth, endOfMonth, startOfWeek, endOfWeek, eachDayOfInterval, startOfDay, isSameMonth, format, isSameDay, subMonths, addMonths, addDays } from "date-fns";
5
5
  import { cn } from "../../lib/utils.js";
6
- import { CAT_ACCENT, CAT_EVENT } from "../../tokens/categorical-color.js";
6
+ import { CAT_SUBTLE, CAT_EVENT, CAT_ACCENT } from "../../tokens/categorical-color.js";
7
7
  import { Button } from "../Button/button.js";
8
8
  import { TruncatedText } from "../../patterns/element-anatomy/truncated-text.js";
9
9
  import { Tooltip, TooltipTrigger, TooltipContent } from "../Tooltip/tooltip.js";
10
10
  import { useTruncated } from "../../hooks/use-truncated.js";
11
11
  const EVENT_COLOR_CLASSES = CAT_EVENT;
12
+ const EVENT_STATIC_COLOR_CLASSES = CAT_SUBTLE;
12
13
  const EVENT_ALLDAY_ACCENT = CAT_ACCENT;
13
14
  function coerceDate(value) {
14
15
  if (value instanceof Date) return value;
@@ -20,39 +21,56 @@ function coerceDate(value) {
20
21
  return new Date(value);
21
22
  }
22
23
  const MAX_TILES_PER_CELL = 3;
24
+ function dayKey(date) {
25
+ return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
26
+ }
23
27
  function MonthEventTile({
24
28
  event,
25
29
  colorClass,
30
+ readOnlyEvents,
26
31
  onEventClick
27
32
  }) {
28
33
  const { ref: truncationRef, isTruncated } = useTruncated({ deps: [event.title] });
34
+ const tileBase = "rounded-md px-1.5 py-0.5 text-caption truncate";
29
35
  return (
30
- // 恆 wrap、未截斷 open={false} 靜默(truncated-text.spec.md always-wrap:條件 wrap 會 remount 丟 RO 訂閱)
36
+ // 恆 wrap、未截斷 open={false} 靜默(truncated-text.spec.md always-wrap:條件 wrap 會 remount 丟 RO 訂閱)。
37
+ // 唯讀方塊照樣掛:截斷提示是「資訊揭露」,不是點擊回饋(tooltip.spec.md「截斷文字 → tooltip」不分可不可點)。
31
38
  /* @__PURE__ */ jsxs(Tooltip, { open: isTruncated ? void 0 : false, children: [
32
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
39
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: !readOnlyEvents ? /* @__PURE__ */ jsx(
33
40
  "div",
34
41
  {
35
42
  role: "button",
36
- tabIndex: 0,
43
+ tabIndex: -1,
44
+ "data-calendar-tile": "",
37
45
  onClick: (e) => {
38
46
  e.stopPropagation();
39
- onEventClick == null ? void 0 : onEventClick(event);
47
+ onEventClick(event);
40
48
  },
41
49
  onKeyDown: (e) => {
42
50
  if (e.key === "Enter" || e.key === " ") {
43
51
  e.preventDefault();
44
- onEventClick == null ? void 0 : onEventClick(event);
52
+ onEventClick(event);
45
53
  }
46
54
  },
47
55
  "aria-label": `事件:${event.title}`,
48
56
  className: cn(
49
- "rounded-md px-1.5 py-0.5 text-caption truncate cursor-pointer transition-colors",
50
- // 2026-05-31 #22:事件 tile 是 focusable(tabIndex=0 role=button)但原無 focus ring
51
- // → WCAG 2.4.7 不合規。補 focus-visible ring 對齊日期格按鈕。
57
+ // hover 底色瞬間切換,不寫 transition-colors(tokens/motion/motion.spec.md「hover 回饋不做過渡」,user 2026-09-10 拍板)。
58
+ // hover 底色在 colorClass 裡(tokens/categorical-color.ts CAT_EVENT 的 hover:bg-…),2026-09-10 全庫落地時
59
+ // hover-instant 閘看不到 .ts 裡的 class 字串,這格因此漏掉;2026-09-25 補拿掉。
60
+ tileBase,
61
+ "cursor-pointer",
62
+ // 焦點:tile 由格內導覽(F2 進格)取得焦點。框**往內**畫:事件方塊之間 gap-0.5 = 2px,往外 +2px 會壓到上下相鄰的方塊
63
+ //(focus-canonical.md「套回實測值驗證」Calendar 事件 tile 列:內 −2px;與下方自訂 tile 的 wrapper 同一條)。
64
+ // 2026-09-29 前這裡沒寫 class、走全域外描邊,與正本相反(待辦總帳 N46「內建事件方塊鍵盤框往內」)。
65
+ "focus-visible:focus-ring-inset",
52
66
  colorClass
53
67
  ),
54
68
  children: /* @__PURE__ */ jsx("span", { ref: truncationRef, className: "block truncate", children: event.title })
55
69
  }
70
+ ) : (
71
+ // 唯讀方塊(readOnlyEvents):不是按鈕、不進格內導覽(沒有 data-calendar-tile,F2 找不到它)、游標不變。
72
+ // 不寫 aria-label:沒有角色的 div 禁止命名(ARIA 1.2 generic 的 name prohibited),事件標題就是它的文字內容。
73
+ /* @__PURE__ */ jsx("div", { className: cn(tileBase, colorClass), children: /* @__PURE__ */ jsx("span", { ref: truncationRef, className: "block truncate", children: event.title }) })
56
74
  ) }),
57
75
  /* @__PURE__ */ jsx(TooltipContent, { children: event.title })
58
76
  ] })
@@ -64,7 +82,9 @@ const Calendar = React.forwardRef(function Calendar2({
64
82
  onReferenceDateChange,
65
83
  today: todayProp,
66
84
  events = [],
85
+ readOnlyEvents,
67
86
  onEventClick,
87
+ readOnlyDates,
68
88
  onDateClick,
69
89
  onCreateEvent,
70
90
  weekStartsOn = 0,
@@ -83,6 +103,8 @@ const Calendar = React.forwardRef(function Calendar2({
83
103
  // i18n-allow: DS default; consumer override via createLabel prop
84
104
  ...props
85
105
  }, ref) {
106
+ const datesInteractive = !readOnlyDates;
107
+ const eventTileMode = readOnlyEvents ? { readOnlyEvents: true } : { onEventClick };
86
108
  const resolvedToday = todayProp ?? /* @__PURE__ */ new Date();
87
109
  const [internalRef, setInternalRef] = React.useState(
88
110
  () => new Date((defaultReferenceDate ?? resolvedToday).getTime())
@@ -141,6 +163,115 @@ const Calendar = React.forwardRef(function Calendar2({
141
163
  }
142
164
  return map;
143
165
  }, [events, days]);
166
+ const gridRef = React.useRef(null);
167
+ const pendingFocusIso = React.useRef(null);
168
+ const [focusedDateState, setFocusedDateState] = React.useState(null);
169
+ const todayDayMs = startOfDay(resolvedToday).getTime();
170
+ const anchorDate = React.useMemo(
171
+ () => isSameMonth(todayDayMs, refDate) ? new Date(todayDayMs) : startOfMonth(refDate),
172
+ [todayDayMs, refDate]
173
+ );
174
+ const gridFirstMs = days.length > 0 ? startOfDay(days[0]).getTime() : 0;
175
+ const gridLastMs = days.length > 0 ? startOfDay(days[days.length - 1]).getTime() : 0;
176
+ const isRendered = React.useCallback(
177
+ (date) => {
178
+ const ms = startOfDay(date).getTime();
179
+ return ms >= gridFirstMs && ms <= gridLastMs;
180
+ },
181
+ [gridFirstMs, gridLastMs]
182
+ );
183
+ const focusedDate = focusedDateState !== null && isRendered(focusedDateState) ? focusedDateState : anchorDate;
184
+ React.useLayoutEffect(() => {
185
+ var _a, _b;
186
+ const iso = pendingFocusIso.current;
187
+ if (iso === null) return;
188
+ pendingFocusIso.current = null;
189
+ (_b = (_a = gridRef.current) == null ? void 0 : _a.querySelector(`[data-calendar-day="${iso}"]`)) == null ? void 0 : _b.focus();
190
+ });
191
+ const moveFocusToDay = React.useCallback(
192
+ (next) => {
193
+ const target = startOfDay(next);
194
+ setFocusedDateState(target);
195
+ if (!isRendered(target)) setRefDate(target);
196
+ pendingFocusIso.current = format(target, "yyyy-MM-dd");
197
+ },
198
+ [isRendered, setRefDate]
199
+ );
200
+ const dayStopOf = (cell) => cell.matches("[data-calendar-day]") ? cell : cell.querySelector("[data-calendar-day]");
201
+ const handleGridKeyDown = (event) => {
202
+ const target = event.target;
203
+ const cell = target == null ? void 0 : target.closest('[role="gridcell"]');
204
+ if (!target || !cell) return;
205
+ const tile = target.closest("[data-calendar-tile]");
206
+ if (tile) {
207
+ const tiles = Array.from(cell.querySelectorAll("[data-calendar-tile]"));
208
+ const index = tiles.indexOf(tile);
209
+ let nextNode;
210
+ switch (event.key) {
211
+ case "Escape":
212
+ case "F2":
213
+ nextNode = dayStopOf(cell);
214
+ break;
215
+ case "ArrowDown":
216
+ case "ArrowRight":
217
+ nextNode = tiles[Math.min(index + 1, tiles.length - 1)];
218
+ break;
219
+ case "ArrowUp":
220
+ case "ArrowLeft":
221
+ nextNode = tiles[Math.max(index - 1, 0)];
222
+ break;
223
+ default:
224
+ return;
225
+ }
226
+ event.preventDefault();
227
+ event.stopPropagation();
228
+ nextNode == null ? void 0 : nextNode.focus();
229
+ return;
230
+ }
231
+ const dayValue = target.getAttribute("data-calendar-day");
232
+ if (dayValue === null) return;
233
+ if (event.key === "F2" || event.key === "Enter" && !datesInteractive) {
234
+ const firstTile = cell.querySelector("[data-calendar-tile]");
235
+ if (firstTile === null) return;
236
+ event.preventDefault();
237
+ event.stopPropagation();
238
+ firstTile.focus();
239
+ return;
240
+ }
241
+ const current = coerceDate(dayValue);
242
+ let next;
243
+ switch (event.key) {
244
+ case "ArrowRight":
245
+ next = addDays(current, 1);
246
+ break;
247
+ case "ArrowLeft":
248
+ next = addDays(current, -1);
249
+ break;
250
+ case "ArrowDown":
251
+ next = addDays(current, 7);
252
+ break;
253
+ case "ArrowUp":
254
+ next = addDays(current, -7);
255
+ break;
256
+ case "Home":
257
+ next = startOfWeek(current, { weekStartsOn });
258
+ break;
259
+ case "End":
260
+ next = endOfWeek(current, { weekStartsOn });
261
+ break;
262
+ case "PageUp":
263
+ next = addMonths(current, event.shiftKey ? -12 : -1);
264
+ break;
265
+ case "PageDown":
266
+ next = addMonths(current, event.shiftKey ? 12 : 1);
267
+ break;
268
+ default:
269
+ return;
270
+ }
271
+ event.preventDefault();
272
+ event.stopPropagation();
273
+ moveFocusToDay(next);
274
+ };
144
275
  const handleToday = () => setRefDate(new Date(resolvedToday.getTime()));
145
276
  const handlePrev = () => setRefDate(subMonths(refDate, 1));
146
277
  const handleNext = () => setRefDate(addMonths(refDate, 1));
@@ -188,7 +319,7 @@ const Calendar = React.forwardRef(function Calendar2({
188
319
  )
189
320
  ] }),
190
321
  /* @__PURE__ */ jsx("h2", { className: "text-body-lg font-medium text-foreground flex-1 min-w-0 truncate ml-2", children: /* @__PURE__ */ jsx(TruncatedText, { display: "block", children: monthTitle }) }),
191
- onCreateEvent && /* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", startIcon: Plus, onClick: onCreateEvent, children: createLabel })
322
+ /* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", startIcon: Plus, onClick: onCreateEvent, children: createLabel })
192
323
  ]
193
324
  }
194
325
  ),
@@ -203,75 +334,118 @@ const Calendar = React.forwardRef(function Calendar2({
203
334
  /* @__PURE__ */ jsx(
204
335
  "div",
205
336
  {
337
+ ref: gridRef,
206
338
  className: "grid grid-cols-7 flex-1 min-h-0",
207
339
  role: "grid",
208
340
  "aria-label": `月行事曆,${monthTitle}`,
341
+ onKeyDown: handleGridKeyDown,
209
342
  children: Array.from({ length: Math.ceil(days.length / 7) }, (_, rowIdx) => /* @__PURE__ */ jsx("div", { role: "row", style: { display: "contents" }, children: days.slice(rowIdx * 7, rowIdx * 7 + 7).map((date) => {
210
343
  const inMonth = isSameMonth(date, refDate);
211
344
  const isToday = isSameDay(date, resolvedToday);
212
- const dayEvents = eventsByDate.get(`${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`) ?? [];
345
+ const dayEvents = eventsByDate.get(dayKey(date)) ?? [];
213
346
  const visibleEvents = dayEvents.slice(0, MAX_TILES_PER_CELL);
214
347
  const overflowCount = dayEvents.length - visibleEvents.length;
348
+ const dayStop = {
349
+ "aria-label": `${format(date, "yyyy-MM-dd")},${dayEvents.length} 個事件`,
350
+ // roving tabindex:整個格陣只有這一個(= 目前焦點日)進 Tab 序列,其餘 -1。
351
+ // APG Date Picker Dialog 逐字:「only one button in the calendar grid is in the Tab sequence」。
352
+ "data-calendar-day": format(date, "yyyy-MM-dd"),
353
+ tabIndex: isSameDay(date, focusedDate) ? 0 : -1,
354
+ // 焦點用任何方式落到某一天(Tab 進來 / 滑鼠點 / 程式化)都把停靠點同步過去,
355
+ // 免得下次 Tab 回來停在別天。
356
+ onFocus: () => setFocusedDateState(date)
357
+ };
358
+ const dayNumberClass = cn(
359
+ // 焦點框往外(= 不寫)。2026-09-10 重量:日期數字鈕(24×24)在格子裡是**置中**的,不是撐滿 ——
360
+ // 上 6 / 下 4(下方是同格的事件容器)/ 左 128 / 右 7,最小 4.00 = canonical「算放得下」。
361
+ // 2026-09-07 那句「往外會壓到隔壁格」量的是**格子**邊界不是鈕的鄰居;真正貼邊的是事件方塊
362
+ //(彼此 gap-0.5 = 2px),那一處往內(內建 tile 與自訂 tile 的 wrapper 都寫 focus-ring-inset)。
363
+ "inline-flex items-center justify-center min-w-6 h-6 rounded-full text-body font-medium",
364
+ isToday && "px-2 bg-info text-on-emphasis",
365
+ // 非當月 = 淡字 `fg-muted`,**不是** `fg-disabled`:這天跟當月格同一種可點性(可點就一樣可點,唯讀就一樣唯讀),
366
+ // 只是不在焦點月份(同 DateGrid「鄰月日子」的淡字,date-grid.spec.md outside 列;disabled 字色留給真的不可操作)。
367
+ !isToday && !inMonth && "text-fg-muted"
368
+ );
215
369
  return (
216
370
  // 2026-06-11 a11y(user 拍板 2c 修 code):cell 從 <button role="gridcell"> 改非互動容器 —
217
371
  // W3C button 語義禁止互動後代,cell 內含 role="button" 事件 tile = nested-interactive 違規。
218
372
  // 對齊 Google Calendar:gridcell = 容器,日期數字按鈕 = 日期級 keyboard 入口,tile 各自為 button。
219
373
  // div onClick 保留滑鼠「點 cell 空白處等同點日期」便利(keyboard 走日期數字按鈕,功能等價)。
374
+ // 點格內空白處也把**鍵盤位置**帶過來(2026-09-29,待辦總帳 N46):停靠點(roving tabindex)搬到這一天、
375
+ // 焦點落在這一天的日期鈕 —— 之後 Tab 回來停在剛點的那天、consumer 開的對話框關掉後焦點也回到它;
376
+ // 2026-09-29 前只有點到日期數字鈕才會(它是原生 button,瀏覽器自己給焦點),點空白處停靠點留在別天。
377
+ // 同一條規則 DataTable 試算表已做(「滑鼠點到哪一格,鍵盤位置就跟到哪一格」,data-table.spec.md「試算表模式」)。
378
+ //
379
+ // **日期格唯讀(readOnlyDates)時**(2026-09-26,待辦總帳 L8 / C15):格子不接點擊、不亮,日期數字只是文字;
380
+ // 格子裡於是只剩文字(與可點的事件方塊,若有)→ 依 APG Grid「A cell contains text or a single graphic and
381
+ // grid navigation keys set focus on the cell」,鍵盤停靠點改成**格子本身**(dayStop 掛在這裡),
382
+ // 方向鍵 / Home / End / PageUp / PageDown 照舊。格與格之間沒有縫,焦點框往內畫(focus-canonical「問題二」)。
220
383
  /* @__PURE__ */ jsxs(
221
384
  "div",
222
385
  {
223
386
  role: "gridcell",
224
- onClick: () => onDateClick == null ? void 0 : onDateClick(date),
387
+ ...datesInteractive ? {
388
+ onClick: (e) => {
389
+ var _a;
390
+ (_a = dayStopOf(e.currentTarget)) == null ? void 0 : _a.focus({ preventScroll: true });
391
+ setFocusedDateState(date);
392
+ onDateClick(date);
393
+ }
394
+ } : dayStop,
225
395
  className: cn(
226
396
  "flex flex-col gap-1 min-h-28 p-1.5 text-left",
227
397
  "border-r border-b border-divider last:border-r-0",
228
398
  "[&:nth-child(7n)]:border-r-0",
229
399
  // hover 底色瞬間切換,不做過渡(user 2026-09-10 拍板「第三題改成全部瞬間」;SSOT = tokens/motion/motion.spec.md「hover 回饋不做過渡」)
230
- "hover:bg-neutral-hover",
231
- !inMonth && "bg-muted"
400
+ // 非當月格**不加底色**(2026-09-25 user 選「可以,拿掉底色 (Recommended)」,選項由 AI 提供):它跟當月格一樣可點(onDateClick = 在這天新增),
401
+ // 底色一律透明,所以滑過與當月格同一個滑過色。先前的 `bg-muted` 是「不可操作」的 token,放在可點的格上
402
+ // 讓滑過反而變淺(淺 #F5F5F5 → #FAFAFA)。非當月只靠日期數字的淡字區分,見下方日期鈕與 spec「Outside day cell」。
403
+ // 唯讀的格不亮:點了沒反應就不給滑過回饋(color.spec.md「Hover 換色配對總則」;待辦總帳 L8)。
404
+ datesInteractive && "hover:bg-neutral-hover",
405
+ // 點得到(點整格 = 在這天新增)→ 手形游標(hit-area-canonical.md 滑過原則一-3;先前只有日期數字鈕是手形,
406
+ // 格子空白處滑過會亮、點了會新增,游標卻是箭頭)
407
+ datesInteractive && "cursor-pointer",
408
+ !datesInteractive && "focus-visible:focus-ring-inset"
232
409
  ),
233
410
  children: [
234
- /* @__PURE__ */ jsx("div", { className: "flex items-start justify-end", children: /* @__PURE__ */ jsx(
411
+ /* @__PURE__ */ jsx("div", { className: "flex items-start justify-end", children: datesInteractive ? /* @__PURE__ */ jsx(
235
412
  "button",
236
413
  {
237
414
  type: "button",
238
- "aria-label": `${format(date, "yyyy-MM-dd")},${dayEvents.length} 個事件`,
415
+ ...dayStop,
239
416
  onClick: (e) => {
240
417
  e.stopPropagation();
241
- onDateClick == null ? void 0 : onDateClick(date);
418
+ onDateClick(date);
242
419
  },
243
- className: cn(
244
- // 焦點框往外(= 不寫)。2026-09-10 重量:日期數字鈕(24×24)在格子裡是**置中**的,不是撐滿 ——
245
- // 上 6 / 下 4(下方是同格的事件容器)/ 左 128 / 右 7,最小 4.00 = canonical「算放得下」。
246
- // 2026-09-07 那句「往外會壓到隔壁格」量的是**格子**邊界不是鈕的鄰居;真正貼邊的是事件方塊
247
- //(彼此 gap-0.5 = 2px),那一處仍然往內(見下方 :435)。
248
- "inline-flex items-center justify-center min-w-6 h-6 rounded-full text-body font-medium",
249
- isToday && "px-2 bg-info text-on-emphasis",
250
- !isToday && !inMonth && "text-fg-disabled"
251
- ),
420
+ className: dayNumberClass,
252
421
  children: format(date, "d")
253
422
  }
254
- ) }),
423
+ ) : /* @__PURE__ */ jsx("span", { className: dayNumberClass, children: format(date, "d") }) }),
255
424
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 min-h-0", children: [
256
425
  visibleEvents.map((event) => {
257
426
  const ec = event.color ?? "blue";
258
- const colorClass = event.allDay ? cn(EVENT_COLOR_CLASSES[ec], EVENT_ALLDAY_ACCENT[ec], "font-medium") : EVENT_COLOR_CLASSES[ec];
427
+ const hueClass = readOnlyEvents ? EVENT_STATIC_COLOR_CLASSES[ec] : EVENT_COLOR_CLASSES[ec];
428
+ const colorClass = event.allDay ? cn(hueClass, EVENT_ALLDAY_ACCENT[ec], "font-medium") : hueClass;
259
429
  if (renderEventTile) {
260
- return /* @__PURE__ */ jsx(
430
+ return readOnlyEvents ? (
431
+ // 唯讀:只包一層排版用的 div —— 不是按鈕、不進格內導覽(沒有 data-calendar-tile)、沒有焦點框
432
+ /* @__PURE__ */ jsx("div", { children: renderEventTile(event) }, event.id)
433
+ ) : /* @__PURE__ */ jsx(
261
434
  "div",
262
435
  {
263
436
  role: "button",
264
- tabIndex: 0,
437
+ tabIndex: -1,
438
+ "data-calendar-tile": "",
265
439
  "aria-label": `事件:${event.title}`,
266
440
  onClick: (e) => {
267
441
  e.stopPropagation();
268
- onEventClick == null ? void 0 : onEventClick(event);
442
+ onEventClick(event);
269
443
  },
270
444
  onKeyDown: (e) => {
271
445
  if (e.key === "Enter" || e.key === " ") {
272
446
  e.preventDefault();
273
447
  e.stopPropagation();
274
- onEventClick == null ? void 0 : onEventClick(event);
448
+ onEventClick(event);
275
449
  }
276
450
  },
277
451
  className: "rounded-md focus-visible:focus-ring-inset",
@@ -285,7 +459,7 @@ const Calendar = React.forwardRef(function Calendar2({
285
459
  {
286
460
  event,
287
461
  colorClass,
288
- onEventClick
462
+ ...eventTileMode
289
463
  },
290
464
  event.id
291
465
  );
@@ -319,8 +493,8 @@ const calendarMeta = {
319
493
  states: ["default", "hover", "focus-visible", "disabled"],
320
494
  tokens: {
321
495
  bg: ["bg-muted", "bg-neutral-hover", "bg-info", "bg-surface"],
322
- fg: ["text-fg-disabled", "text-fg-muted", "text-foreground"],
323
- ring: ["ring-ring"]
496
+ fg: ["text-fg-muted", "text-foreground"],
497
+ ring: ["focus-ring-inset", "--ring"]
324
498
  }
325
499
  };
326
500
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"calendar.js","sources":["../../../src/components/Calendar/calendar.tsx"],"sourcesContent":["// @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.\nimport * as React from 'react'\nimport { ChevronLeft, ChevronRight, Plus } from 'lucide-react'\nimport {\n startOfMonth,\n endOfMonth,\n startOfWeek,\n endOfWeek,\n eachDayOfInterval,\n format,\n isSameMonth,\n isSameDay,\n addMonths,\n subMonths,\n} from 'date-fns'\nimport { cn } from '@/lib/utils'\nimport { CAT_EVENT, CAT_ACCENT, type CategoricalHue } from '@/design-system/tokens/categorical-color'\nimport { Button } from '@/design-system/components/Button/button'\nimport { TruncatedText } from '@/design-system/patterns/element-anatomy/truncated-text'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/design-system/components/Tooltip/tooltip'\nimport { useTruncated } from '@/design-system/hooks/use-truncated'\n\n/**\n * Calendar — 月事件檢視 canvas\n *\n * 定位:看事件的 page-level canvas,對齊 Notion Calendar / Google Calendar。\n * 完整 spec 見 `calendar.spec.md`。\n *\n * ── Layout Family ──\n * 非 4-Family,屬 page-composite(多區塊 Toolbar + Grid + EventTile)。\n *\n * ── Implemented scope ──\n * 月 view(toolbar / grid / event tile / today highlight / outside days)。未實作的\n * week/day/size/drag 能力不預佔公開 prop 或 disabled control。\n *\n * ── 與 DatePicker 的區分 ──\n * DatePicker 是「選日期」form control;Calendar 是「看事件」page canvas。\n * 名字相近但職責完全不同,spec 頂段明示分界。\n */\n\n// ── Types ──────────────────────────────────────────────────────────────────\n\nexport interface CalendarEvent {\n id: string\n title: string\n /** ISO 字串 \"YYYY-MM-DD\"(all-day)或 \"YYYY-MM-DDTHH:mm\"(timed) */\n start: string | Date\n end: string | Date\n allDay?: boolean\n /**\n * 事件類別色(categorical 色相,1:1 對 `--color-{hue}-*`)。**消費 categorical-color SSOT**,\n * 與 Tag / Avatar 共用同一組 12 色相。2026-06-04 修:原 `orange` 與 `red` 都誤接 deep-orange;\n * 改消費 SSOT 後 orange→`--color-orange-*`、red→`--color-red-*`(品牌紅 hue 25),各自獨立。\n */\n color?: CategoricalHue\n metadata?: Record<string, unknown>\n}\n\nexport interface CalendarProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'> {\n /** 聚焦日期(月 view 的那個月) */\n referenceDate?: Date\n defaultReferenceDate?: Date\n onReferenceDateChange?: (date: Date) => void\n /**\n * 「今天」的時間來源。預設為呼叫端當下時間;傳入可讓 SSR、測試與視覺快照完全\n * deterministic。此值同時擁有 today highlight、Today button target,以及未提供\n * referenceDate/defaultReferenceDate 時的初始月份。\n */\n today?: Date\n\n /** 事件資料 */\n events?: CalendarEvent[]\n\n /** 點 event tile 回調 */\n onEventClick?: (event: CalendarEvent) => void\n /** 點月 cell 回調(用於新增) */\n onDateClick?: (date: Date) => void\n /** 點新事件 CTA 回調 */\n onCreateEvent?: () => void\n\n /** 0 = Sunday, 1 = Monday。預設 0(對齊 Google Calendar 美系預設) */\n weekStartsOn?: 0 | 1\n\n /** 自訂 event tile 渲染 */\n renderEventTile?: (event: CalendarEvent) => React.ReactNode\n\n className?: string\n\n /** locale(預設 'en-US') */\n locale?: string\n\n /** ARIA labels for chrome controls. Override for i18n. */\n prevAriaLabel?: string\n nextAriaLabel?: string\n /** 月份導覽 <nav> landmark 的 aria-label。Override for i18n. */\n navAriaLabel?: string\n todayLabel?: string\n /** 「新事件」CTA 文字。Override for i18n。CTA 僅在傳 `onCreateEvent` 時渲染(spec Toolbar 段)。 */\n createLabel?: string\n}\n\n// ── Event tile color tokens ─────────────────────────────────────────────────\n// **消費 categorical-color SSOT**(CAT_EVENT = subtle 底 + hover step-2;CAT_ACCENT = 左側 step-6\n// 實心條),與 Tag / Avatar 共用 12 色相,key X 一律對 `--color-X-*`(1:1)。\n// 2026-06-01 allDay:全天事件 = 淡底 tile + 左側實心 accent 條 + medium,視覺區分「全天長條」vs\n// 有時間事件;用 accent border 而非 solid fill 保文字對比安全。對齊 Google Calendar / Outlook 慣例。\nconst EVENT_COLOR_CLASSES = CAT_EVENT\nconst EVENT_ALLDAY_ACCENT = CAT_ACCENT\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\nfunction coerceDate(value: string | Date): Date {\n if (value instanceof Date) return value\n // date-only ISO(\"YYYY-MM-DD\")用本地午夜建構,不走 new Date(str)。\n // 原因:`new Date('2026-06-15')` 按 UTC 午夜解析,而 eventsByDate 分桶以本地\n // getFullYear/Month/Date 讀取 → 負 UTC 時區(西半球)的 all-day 事件被移到前一天\n // (真實 timezone bug)。手動 split 建本地 Date,與分桶的本地讀取一致。\n // 含時間的字串(YYYY-MM-DDTHH:mm,無 offset)ES 規範本就以本地解析,走原生 new Date()。\n const dateOnly = /^\\d{4}-\\d{2}-\\d{2}$/.exec(value)\n if (dateOnly) {\n const [y, m, d] = value.split('-').map(Number)\n return new Date(y, m - 1, d)\n }\n return new Date(value)\n}\n\n// eventsOnDate(per-cell 全 events 掃描)已由 eventsByDate bucketing memo 取代並移除\n// (2026-07-06 D3 perf;留著會觸發 noUnusedLocals TS6133)。\n\n// ── Component ──────────────────────────────────────────────────────────────\n\nconst MAX_TILES_PER_CELL = 3\n\n// 預設事件 tile 抽出 component:截斷 tooltip 需 useTruncated(hook 不能在 map callback 內)。\n// 截斷 → tooltip 顯完整標題(tooltip.spec.md:32,僅實際截斷時);tile 是 interactive host\n// (role=button,hover 直達)→ trigger = tile 本體、量測內層文字 span — useTruncated 自組\n// pattern(truncated-text.spec.md「trigger 需自控」指定解;範本 inline-edit.tsx:251 + tag.tsx)。\nfunction MonthEventTile({\n event,\n colorClass,\n onEventClick,\n}: {\n event: CalendarEvent\n colorClass: string\n onEventClick?: (event: CalendarEvent) => void\n}) {\n const { ref: truncationRef, isTruncated } = useTruncated<HTMLSpanElement>({ deps: [event.title] })\n return (\n // 恆 wrap、未截斷 open={false} 靜默(truncated-text.spec.md always-wrap:條件 wrap 會 remount 丟 RO 訂閱)\n <Tooltip open={isTruncated ? undefined : false}>\n <TooltipTrigger asChild>\n <div\n role=\"button\"\n tabIndex={0}\n onClick={(e) => {\n e.stopPropagation()\n onEventClick?.(event)\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n onEventClick?.(event)\n }\n }}\n aria-label={`事件:${event.title}`}\n className={cn(\n 'rounded-md px-1.5 py-0.5 text-caption truncate cursor-pointer transition-colors',\n // 2026-05-31 #22:事件 tile 是 focusable(tabIndex=0 role=button)但原無 focus ring\n // → WCAG 2.4.7 不合規。補 focus-visible ring 對齊日期格按鈕。\n colorClass,\n )}\n >\n <span ref={truncationRef} className=\"block truncate\">{event.title}</span>\n </div>\n </TooltipTrigger>\n <TooltipContent>{event.title}</TooltipContent>\n </Tooltip>\n )\n}\n\nconst Calendar = React.forwardRef<HTMLDivElement, CalendarProps>(function Calendar({\n referenceDate: referenceDateProp,\n defaultReferenceDate,\n onReferenceDateChange,\n today: todayProp,\n events = [],\n onEventClick,\n onDateClick,\n onCreateEvent,\n weekStartsOn = 0,\n renderEventTile,\n className,\n locale = 'en-US',\n prevAriaLabel = '上個月', // i18n-allow: DS default; consumer override via prevAriaLabel prop\n nextAriaLabel = '下個月', // i18n-allow: DS default; consumer override via nextAriaLabel prop\n navAriaLabel = '行事曆月份導覽', // i18n-allow: DS default; consumer override via navAriaLabel prop\n todayLabel = '今天', // i18n-allow: DS default; consumer override via todayLabel prop\n createLabel = '新事件', // i18n-allow: DS default; consumer override via createLabel prop\n ...props\n}, ref) {\n const resolvedToday = todayProp ?? new Date()\n // Controlled / uncontrolled refDate\n const [internalRef, setInternalRef] = React.useState<Date>(\n () => new Date((defaultReferenceDate ?? resolvedToday).getTime()),\n )\n const refDate = referenceDateProp ?? internalRef\n const setRefDate = React.useCallback(\n (next: Date) => {\n if (referenceDateProp === undefined) setInternalRef(next)\n onReferenceDateChange?.(next)\n },\n [referenceDateProp, onReferenceDateChange],\n )\n\n // Build month grid\n const days = React.useMemo(() => {\n const monthStart = startOfMonth(refDate)\n const monthEnd = endOfMonth(refDate)\n const gridStart = startOfWeek(monthStart, { weekStartsOn })\n const gridEnd = endOfWeek(monthEnd, { weekStartsOn })\n return eachDayOfInterval({ start: gridStart, end: gridEnd })\n }, [refDate, weekStartsOn])\n\n // 2026-07-06 D3 perf:formatter 依 locale memo(對齊 weekdayNames 既有做法),避免每 render 重建\n // Intl.DateTimeFormat(已知貴的 constructor);.format(refDate) 每 render 仍執行(cheap)。\n const monthTitleFormatter = React.useMemo(\n () => new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'long' }),\n [locale],\n )\n const monthTitle = monthTitleFormatter.format(refDate)\n\n const weekdayNames = React.useMemo(() => {\n // 取 `days[0..6]` 的名字(gridStart 開始 7 天,正好一週)\n return days.slice(0, 7).map((d) =>\n new Intl.DateTimeFormat(locale, { weekday: 'short' }).format(d),\n )\n }, [days, locale])\n\n // 2026-07-06 D3 perf:原每 render 對 42 cells 各跑 eventsOnDate 全 events filter = O(42×N) +\n // 每比較配 ~5 個 Date;數百-上千 events(行事曆真實規模)單次 render 數十 ms,且父層任何 re-render\n // 全額重付。改 useMemo 單趟 bucket:每 event 只 parse 一次,展開 [start..end](clamp 到可見 grid,\n // 避免長跨度 event 展開爆量)寫入 date→events Map,順便完成 allDay 排序。cell 內改 O(1) map.get。行為 Δ=0。\n const eventsByDate = React.useMemo(() => {\n const map = new Map<string, CalendarEvent[]>()\n if (days.length === 0) return map\n const first = days[0]\n const last = days[days.length - 1]\n const gridStart = new Date(first.getFullYear(), first.getMonth(), first.getDate()).getTime()\n const gridEnd = new Date(last.getFullYear(), last.getMonth(), last.getDate()).getTime()\n for (const e of events) {\n const start = coerceDate(e.start)\n const end = coerceDate(e.end)\n const eEnd = new Date(end.getFullYear(), end.getMonth(), end.getDate()).getTime()\n let sMs = new Date(start.getFullYear(), start.getMonth(), start.getDate()).getTime()\n if (eEnd < gridStart || sMs > gridEnd) continue // 可見窗外對 42 cells 無貢獻\n if (sMs < gridStart) sMs = gridStart\n const lastMs = Math.min(eEnd, gridEnd)\n const cursor = new Date(sMs)\n while (cursor.getTime() <= lastMs) {\n const key = `${cursor.getFullYear()}-${cursor.getMonth() + 1}-${cursor.getDate()}`\n const bucket = map.get(key)\n if (bucket) bucket.push(e)\n else map.set(key, [e])\n cursor.setDate(cursor.getDate() + 1)\n }\n }\n // allDay 排前(對齊 Google Calendar 全天列在上;V8 stable sort 保 events 原序 → 與舊 per-cell 一致)\n for (const bucket of map.values()) {\n bucket.sort((a, b) => Number(b.allDay ?? false) - Number(a.allDay ?? false))\n }\n return map\n }, [events, days])\n\n const handleToday = () => setRefDate(new Date(resolvedToday.getTime()))\n const handlePrev = () => setRefDate(subMonths(refDate, 1))\n const handleNext = () => setRefDate(addMonths(refDate, 1))\n\n return (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col w-full h-full bg-surface rounded-md border border-divider overflow-hidden',\n className,\n )}\n {...props}\n >\n {/* Toolbar:[◀] [今天] [▶] title [+ new] */}\n <div\n className={cn(\n 'flex items-center gap-2 shrink-0 border-b border-divider',\n 'px-[var(--layout-space-loose)] py-[var(--layout-space-tight)]',\n )}\n >\n {/* 月份導覽 landmark:prev / 今天 / next 包成 <nav> 給 SR landmark 導航(per calendar.spec.md a11y 段) */}\n <nav className=\"flex items-center gap-2\" aria-label={navAriaLabel}>\n <Button\n variant=\"text\"\n size=\"sm\"\n iconOnly\n startIcon={ChevronLeft}\n aria-label={prevAriaLabel}\n onClick={handlePrev}\n />\n <Button variant=\"tertiary\" size=\"sm\" onClick={handleToday}>\n {todayLabel}\n </Button>\n <Button\n variant=\"text\"\n size=\"sm\"\n iconOnly\n startIcon={ChevronRight}\n aria-label={nextAriaLabel}\n onClick={handleNext}\n />\n </nav>\n\n <h2 className=\"text-body-lg font-medium text-foreground flex-1 min-w-0 truncate ml-2\">\n {/* 2026-07-28:截斷必附 tooltip(tooltip.spec.md「截斷 → tooltip,僅實際截斷時顯示」)——\n 窄 toolbar 下標題被裁掉沒有補救路徑。display=\"block\":h2 是 block container。 */}\n <TruncatedText display=\"block\">{monthTitle}</TruncatedText>\n </h2>\n\n {onCreateEvent && (\n <Button variant=\"primary\" size=\"sm\" startIcon={Plus} onClick={onCreateEvent}>\n {createLabel}\n </Button>\n )}\n </div>\n\n {/* Weekday header */}\n <div className=\"grid grid-cols-7 border-b border-divider bg-muted\">\n {weekdayNames.map((name, i) => (\n <div\n key={i}\n // 2026-09-07 修(user 抓「為何星期標題要用那麼淺的顏色?」):\n // 原本是 `text-caption text-fg-muted font-normal`(12px / 45% 灰 / 細體)。\n // **DS 早就有 canonical 而且方向相反** —— `date-grid.spec.md:151`「Weekday header canonical」\n //(2026-05-03 user audit):`text-foreground text-body font-medium`,理由是\n // 「weekday 列標跟 caption 同視覺權重,都屬 calendar header 區,**不弱化**」,\n // 而且明文「**撤銷 v3 用 `fg-secondary font-normal` 的 mistake(M23)**」。\n // Calendar 這版比那個已被撤銷的版本**還弱**,是漂移不是設計選擇\n //(calendar.spec.md 沒有另訂星期排版,所以那條是唯一 canonical)。\n // 在本元件內也是孤例:月份標題 `text-body-lg font-medium`、日期數字 `text-body font-medium`,\n // 只有星期標題是 12px 細灰。\n className=\"px-2 py-1.5 text-body text-foreground font-medium text-center\"\n >\n {name}\n </div>\n ))}\n </div>\n\n {/* Month grid:7 cols, ~5-6 rows。a11y(2026-04-25):WAI-ARIA grid 要求 row > gridcell\n 階層,chunk days 7 一組,wrap 成 role='row'(display:contents 保 CSS grid 佈局)。 */}\n <div\n className=\"grid grid-cols-7 flex-1 min-h-0\"\n role=\"grid\"\n aria-label={`月行事曆,${monthTitle}`}\n >\n {Array.from({ length: Math.ceil(days.length / 7) }, (_, rowIdx) => (\n <div key={rowIdx} role=\"row\" style={{ display: 'contents' }}>\n {days.slice(rowIdx * 7, rowIdx * 7 + 7).map((date) => {\n const inMonth = isSameMonth(date, refDate)\n const isToday = isSameDay(date, resolvedToday)\n // 2026-06-01 allDay:全天事件排 cell 頂端(對齊 Google Calendar 全天列在上)——\n // 排序已在 eventsByDate bucketing memo 內完成(D3 perf),cell 內 O(1) 查表\n const dayEvents = eventsByDate.get(`${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`) ?? []\n const visibleEvents = dayEvents.slice(0, MAX_TILES_PER_CELL)\n const overflowCount = dayEvents.length - visibleEvents.length\n\n return (\n // 2026-06-11 a11y(user 拍板 2c 修 code):cell 從 <button role=\"gridcell\"> 改非互動容器 —\n // W3C button 語義禁止互動後代,cell 內含 role=\"button\" 事件 tile = nested-interactive 違規。\n // 對齊 Google Calendar:gridcell = 容器,日期數字按鈕 = 日期級 keyboard 入口,tile 各自為 button。\n // div onClick 保留滑鼠「點 cell 空白處等同點日期」便利(keyboard 走日期數字按鈕,功能等價)。\n <div\n key={date.toISOString()}\n role=\"gridcell\"\n onClick={() => onDateClick?.(date)}\n className={cn(\n 'flex flex-col gap-1 min-h-28 p-1.5 text-left',\n 'border-r border-b border-divider last:border-r-0',\n '[&:nth-child(7n)]:border-r-0',\n // hover 底色瞬間切換,不做過渡(user 2026-09-10 拍板「第三題改成全部瞬間」;SSOT = tokens/motion/motion.spec.md「hover 回饋不做過渡」)\n 'hover:bg-neutral-hover',\n !inMonth && 'bg-muted',\n )}\n >\n {/* Date number = keyboard 入口;今天/平日統一 24px 圓形 hit-area(WCAG 2.5.8 ≥24,\n 今天 pill 本就 24px,平日跟齊 → 跨 cell 數字光學對齊) */}\n <div className=\"flex items-start justify-end\">\n <button\n type=\"button\"\n aria-label={`${format(date, 'yyyy-MM-dd')},${dayEvents.length} 個事件`}\n onClick={(e) => {\n e.stopPropagation()\n onDateClick?.(date)\n }}\n className={cn(\n // 焦點框往外(= 不寫)。2026-09-10 重量:日期數字鈕(24×24)在格子裡是**置中**的,不是撐滿 ——\n // 上 6 / 下 4(下方是同格的事件容器)/ 左 128 / 右 7,最小 4.00 = canonical「算放得下」。\n // 2026-09-07 那句「往外會壓到隔壁格」量的是**格子**邊界不是鈕的鄰居;真正貼邊的是事件方塊\n //(彼此 gap-0.5 = 2px),那一處仍然往內(見下方 :435)。\n 'inline-flex items-center justify-center min-w-6 h-6 rounded-full text-body font-medium',\n isToday && 'px-2 bg-info text-on-emphasis',\n !isToday && !inMonth && 'text-fg-disabled',\n )}\n >\n {format(date, 'd')}\n </button>\n </div>\n\n {/* Event tiles */}\n <div className=\"flex flex-col gap-0.5 min-h-0\">\n {visibleEvents.map((event) => {\n const ec = event.color ?? 'blue'\n // 2026-06-01 allDay:淡底 + 左 accent 條 + medium = 「全天長條」視覺(區分有時間事件)\n const colorClass = event.allDay\n ? cn(EVENT_COLOR_CLASSES[ec], EVENT_ALLDAY_ACCENT[ec], 'font-medium')\n : EVENT_COLOR_CLASSES[ec]\n if (renderEventTile) {\n return (\n <div\n key={event.id}\n role=\"button\"\n tabIndex={0}\n aria-label={`事件:${event.title}`}\n onClick={(e) => {\n e.stopPropagation()\n onEventClick?.(event)\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n e.stopPropagation()\n onEventClick?.(event)\n }\n }}\n // 內描邊:事件方塊之間 gap-0.5(2px),往外 +2px 會壓到上下相鄰的方塊\n className=\"rounded-md focus-visible:focus-ring-inset\"\n >\n {renderEventTile(event)}\n </div>\n )\n }\n return (\n <MonthEventTile\n key={event.id}\n event={event}\n colorClass={colorClass}\n onEventClick={onEventClick}\n />\n )\n })}\n {overflowCount > 0 && (\n <div className=\"text-caption text-fg-muted px-1.5\">\n +{overflowCount} more\n </div>\n )}\n </div>\n </div>\n )\n })}\n </div>\n ))}\n </div>\n </div>\n )\n})\nCalendar.displayName = \"Calendar\"\n\n// Story auto-compile metadata — Phase 1 mechanical migration(2026-04-24)\n// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs\nexport const calendarMeta = {\n component: 'Calendar',\n family: null, // non-family composite / overlay / layout\n variants: {\n\n },\n sizes: {\n\n },\n // 'active' 移除 — 日期格按壓視覺屬 DateGrid(其 meta 已 −active);nav 按壓屬內嵌 Button(2026-07-07 詞彙統一 DS-wide 按壓訊號盤點:檔內 0 active: utility / 0 *-active token)。\n states: ['default', 'hover', 'focus-visible', 'disabled'],\n tokens: {\n bg: ['bg-muted', 'bg-neutral-hover', 'bg-info', 'bg-surface'],\n fg: ['text-fg-disabled', 'text-fg-muted', 'text-foreground'],\n ring: ['ring-ring'],\n },\n} as const\n\nexport { Calendar }\n"],"names":["Calendar"],"mappings":"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"}
1
+ {"version":3,"file":"calendar.js","sources":["../../../src/components/Calendar/calendar.tsx"],"sourcesContent":["// @benchmark-unverified-blanket: file-level retraction per M22 (d) — claims herein not individually URL-cited; treat as unverified visual/usage rumor unless retrofit per-claim. Hook escape preserved.\nimport * as React from 'react'\nimport { ChevronLeft, ChevronRight, Plus } from 'lucide-react'\nimport {\n startOfMonth,\n endOfMonth,\n startOfWeek,\n endOfWeek,\n eachDayOfInterval,\n format,\n isSameMonth,\n isSameDay,\n addDays,\n addMonths,\n subMonths,\n startOfDay,\n} from 'date-fns'\nimport { cn } from '@/lib/utils'\nimport { CAT_EVENT, CAT_SUBTLE, CAT_ACCENT, type CategoricalHue } from '@/design-system/tokens/categorical-color'\nimport { Button } from '@/design-system/components/Button/button'\nimport { TruncatedText } from '@/design-system/patterns/element-anatomy/truncated-text'\nimport { Tooltip, TooltipContent, TooltipTrigger } from '@/design-system/components/Tooltip/tooltip'\nimport { useTruncated } from '@/design-system/hooks/use-truncated'\n\n/**\n * Calendar — 月事件檢視 canvas\n *\n * 定位:看事件的 page-level canvas,對齊 Notion Calendar / Google Calendar。\n * 完整 spec 見 `calendar.spec.md`。\n *\n * ── Layout Family ──\n * 非 4-Family,屬 page-composite(多區塊 Toolbar + Grid + EventTile)。\n *\n * ── Implemented scope ──\n * 月 view(toolbar / grid / event tile / today highlight / outside days)。未實作的\n * week/day/size/drag 能力不預佔公開 prop 或 disabled control。\n *\n * ── 與 DatePicker 的區分 ──\n * DatePicker 是「選日期」form control;Calendar 是「看事件」page canvas。\n * 名字相近但職責完全不同,spec 頂段明示分界。\n */\n\n// ── Types ──────────────────────────────────────────────────────────────────\n\nexport interface CalendarEvent {\n id: string\n title: string\n /** ISO 字串 \"YYYY-MM-DD\"(all-day)或 \"YYYY-MM-DDTHH:mm\"(timed) */\n start: string | Date\n end: string | Date\n allDay?: boolean\n /**\n * 事件類別色(categorical 色相,1:1 對 `--color-{hue}-*`)。**消費 categorical-color SSOT**,\n * 與 Tag / Avatar 共用同一組 12 色相。2026-06-04 修:原 `orange` 與 `red` 都誤接 deep-orange;\n * 改消費 SSOT 後 orange→`--color-orange-*`、red→`--color-red-*`(品牌紅 hue 25),各自獨立。\n */\n color?: CategoricalHue\n metadata?: Record<string, unknown>\n}\n\n// ── 日期格 / 事件方塊:可點或唯讀(2026-09-26,待辦總帳 L8 / C15;calendar.spec.md「日期格與事件方塊:可點或唯讀」)──\n// 兩者各自二擇一,由型別層逼出來 —— 不拿「回調有沒有傳」當渲染閘(meta-patterns M23(f)):\n// 可點(預設)= 必傳回調;長成可點的樣子(按鈕、滑過換色、手形游標、Enter / Space)。\n// 唯讀 = 寫 `readOnlyDates` / `readOnlyEvents`、**不可以**傳回調;不是按鈕、滑過不變、游標不變。\n// 先前(2026-09-25 批次)把兩個回調改成無條件必填,等於規定月曆一定可點,與「沒有新增功能的月曆格子不亮」相反(C15),已撤回。\n// 命名:沿用 DS 既有的 `readOnly`(Rating `readOnly`「唯讀:…不響應 hover / click / 鍵盤」、Field 家族 readonly 模式),\n// 加上作用對象 —— 日期格與事件方塊是兩個獨立的點擊目標,要能分開宣告(內容排程月曆:事件點得開、日子不能點來新增)。\n\n/** 日期格(整格 + 日期數字)可點與否。不單獨匯出:consumer 一律用 CalendarProps(root barrel 只列 CalendarProps / CalendarEvent)。 */\ntype CalendarDateCellProps =\n | {\n /** 日期格唯讀:不可點、不亮、日期數字不是按鈕;鍵盤仍可在格陣內走動(焦點改停在格子本身)。 */\n readOnlyDates?: false\n /** 點月 cell / 日期數字鈕回調(用於在這天新增)。日期格可點時**必填**:元件沒有內建的「新增」行為(spec「禁止事項」:不自動開表單)。 */\n onDateClick: (date: Date) => void\n }\n | {\n /** 日期格唯讀:不可點、不亮、日期數字不是按鈕;鍵盤仍可在格陣內走動(焦點改停在格子本身)。宣告了就不可以傳 `onDateClick`。 */\n readOnlyDates: true\n onDateClick?: never\n }\n\n/** 事件方塊可點與否。同上,不單獨匯出;MonthEventTile 也吃這一份。 */\ntype CalendarEventTileProps =\n | {\n /** 事件方塊唯讀:不可點、不亮、不是按鈕(只顯示事件,例如公司假日這類沒有詳情可開的標記)。 */\n readOnlyEvents?: false\n /** 點 event tile 回調。事件方塊可點時**必填**:元件沒有內建的「打開事件」行為。 */\n onEventClick: (event: CalendarEvent) => void\n }\n | {\n /** 事件方塊唯讀:不可點、不亮、不是按鈕(只顯示事件)。宣告了就不可以傳 `onEventClick`。 */\n readOnlyEvents: true\n onEventClick?: never\n }\n\ninterface CalendarOwnProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSelect'> {\n /** 聚焦日期(月 view 的那個月) */\n referenceDate?: Date\n defaultReferenceDate?: Date\n onReferenceDateChange?: (date: Date) => void\n /**\n * 「今天」的時間來源。預設為呼叫端當下時間;傳入可讓 SSR、測試與視覺快照完全\n * deterministic。此值同時擁有 today highlight、Today button target,以及未提供\n * referenceDate/defaultReferenceDate 時的初始月份。\n */\n today?: Date\n\n /** 事件資料 */\n events?: CalendarEvent[]\n\n /**\n * 右上角「新事件」CTA 的回調 —— 全域新增入口,恆渲染;日期能不能新增由新增流程自己擋,不由這顆鈕的有無表達\n *(user 2026-09-29:「右上角那是全域新增,表示點了之後要先選了日期才能新增啊,那肯定會擋住不能新增的日期啊」)。\n * 元件沒有內建的「新增」行為,所以必填:meta-patterns M23(f)—— 固定元素不以 callback 有無當渲染閘、\n * 無內建 fallback 的 callback 必填。唯讀月曆(`readOnlyDates` / `readOnlyEvents`)一樣要傳。\n */\n onCreateEvent: () => void\n\n /** 0 = Sunday, 1 = Monday。預設 0(對齊 Google Calendar 美系預設) */\n weekStartsOn?: 0 | 1\n\n /** 自訂 event tile 渲染 */\n renderEventTile?: (event: CalendarEvent) => React.ReactNode\n\n className?: string\n\n /** locale(預設 'en-US') */\n locale?: string\n\n /** ARIA labels for chrome controls. Override for i18n. */\n prevAriaLabel?: string\n nextAriaLabel?: string\n /** 月份導覽 <nav> landmark 的 aria-label。Override for i18n. */\n navAriaLabel?: string\n todayLabel?: string\n /** 「新事件」CTA 文字。Override for i18n。CTA 是 toolbar 的固定元素、恆渲染(spec Toolbar 段;`onCreateEvent` 必填)。 */\n createLabel?: string\n}\n\nexport type CalendarProps = CalendarOwnProps & CalendarDateCellProps & CalendarEventTileProps\n\n// ── Event tile color tokens ─────────────────────────────────────────────────\n// **消費 categorical-color SSOT**(CAT_EVENT = subtle 底 + hover step-2;CAT_ACCENT = 左側 step-6\n// 實心條),與 Tag / Avatar 共用 12 色相,key X 一律對 `--color-X-*`(1:1)。\n// 2026-06-01 allDay:全天事件 = 淡底 tile + 左側實心 accent 條 + medium,視覺區分「全天長條」vs\n// 有時間事件;用 accent border 而非 solid fill 保文字對比安全。對齊 Google Calendar / Outlook 慣例。\nconst EVENT_COLOR_CLASSES = CAT_EVENT\n// 唯讀事件方塊(readOnlyEvents):同一組靜止色、**不帶滑過** —— CAT_SUBTLE 就是 CAT_EVENT 去掉 `hover:bg-…-2` 那一段\n//(categorical-color.ts CAT_SUBTLE vs CAT_EVENT,同色相同 step-1 底 / step-7 字),也就是 Tag 那種靜態類別標籤。\n// 點了沒反應的東西不給滑過回饋(color.spec.md「Hover 換色配對總則」:只有「點了會有反應」的元素才有底色的滑過回饋;待辦總帳 L8)。\nconst EVENT_STATIC_COLOR_CLASSES = CAT_SUBTLE\nconst EVENT_ALLDAY_ACCENT = CAT_ACCENT\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\nfunction coerceDate(value: string | Date): Date {\n if (value instanceof Date) return value\n // date-only ISO(\"YYYY-MM-DD\")用本地午夜建構,不走 new Date(str)。\n // 原因:`new Date('2026-06-15')` 按 UTC 午夜解析,而 eventsByDate 分桶以本地\n // getFullYear/Month/Date 讀取 → 負 UTC 時區(西半球)的 all-day 事件被移到前一天\n // (真實 timezone bug)。手動 split 建本地 Date,與分桶的本地讀取一致。\n // 含時間的字串(YYYY-MM-DDTHH:mm,無 offset)ES 規範本就以本地解析,走原生 new Date()。\n const dateOnly = /^\\d{4}-\\d{2}-\\d{2}$/.exec(value)\n if (dateOnly) {\n const [y, m, d] = value.split('-').map(Number)\n return new Date(y, m - 1, d)\n }\n return new Date(value)\n}\n\n// eventsOnDate(per-cell 全 events 掃描)已由 eventsByDate bucketing memo 取代並移除\n// (2026-07-06 D3 perf;留著會觸發 noUnusedLocals TS6133)。\n\n// ── Component ──────────────────────────────────────────────────────────────\n\nconst MAX_TILES_PER_CELL = 3\n\n// 「同一天」的唯一鍵。eventsByDate 分桶與 grid 焦點都用它,兩邊不得各寫一式。\nfunction dayKey(date: Date): string {\n return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`\n}\n\n// 預設事件 tile 抽出 component:截斷 tooltip 需 useTruncated(hook 不能在 map callback 內)。\n// 截斷 → tooltip 顯完整標題(tooltip.spec.md:32,僅實際截斷時);tile 是 interactive host\n// (role=button,hover 直達)→ trigger = tile 本體、量測內層文字 span — useTruncated 自組\n// pattern(truncated-text.spec.md「trigger 需自控」指定解;範本 inline-edit.tsx:251 + tag.tsx)。\nfunction MonthEventTile({\n event,\n colorClass,\n readOnlyEvents,\n onEventClick,\n}: {\n event: CalendarEvent\n /** 已依可點 / 唯讀選好的色(可點 = CAT_EVENT 帶滑過;唯讀 = CAT_SUBTLE 不帶),見 Calendar 本體 */\n colorClass: string\n} & CalendarEventTileProps) {\n // 與 Calendar 公開 props 同一份二擇一契約(CalendarEventTileProps):分支看明示的 readOnlyEvents,不看回調在不在(M23(f))\n const { ref: truncationRef, isTruncated } = useTruncated<HTMLSpanElement>({ deps: [event.title] })\n const tileBase = 'rounded-md px-1.5 py-0.5 text-caption truncate'\n return (\n // 恆 wrap、未截斷 open={false} 靜默(truncated-text.spec.md always-wrap:條件 wrap 會 remount 丟 RO 訂閱)。\n // 唯讀方塊照樣掛:截斷提示是「資訊揭露」,不是點擊回饋(tooltip.spec.md「截斷文字 → tooltip」不分可不可點)。\n <Tooltip open={isTruncated ? undefined : false}>\n <TooltipTrigger asChild>\n {!readOnlyEvents ? (\n <div\n role=\"button\"\n // 2026-09-24:tile 從 tabIndex=0 改 -1。role=\"grid\" 要求整個格陣只有一個 Tab 停靠點\n //(W3C APG Grid Pattern「only one element in the entire grid is included in the tab sequence」),\n // 原本一個月 35 格 × (1 日期鈕 + 3 tile) 是幾十個停靠點 = 與 grid 語意相反。\n // tile 改由格內導覽抵達(F2 進格、Escape 出格),詳 calendar.spec.md「A11y 預設」。\n tabIndex={-1}\n data-calendar-tile=\"\"\n onClick={(e) => {\n e.stopPropagation()\n onEventClick(event)\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n onEventClick(event)\n }\n }}\n aria-label={`事件:${event.title}`}\n className={cn(\n // hover 底色瞬間切換,不寫 transition-colors(tokens/motion/motion.spec.md「hover 回饋不做過渡」,user 2026-09-10 拍板)。\n // hover 底色在 colorClass 裡(tokens/categorical-color.ts CAT_EVENT 的 hover:bg-…),2026-09-10 全庫落地時\n // hover-instant 閘看不到 .ts 裡的 class 字串,這格因此漏掉;2026-09-25 補拿掉。\n tileBase,\n 'cursor-pointer',\n // 焦點:tile 由格內導覽(F2 進格)取得焦點。框**往內**畫:事件方塊之間 gap-0.5 = 2px,往外 +2px 會壓到上下相鄰的方塊\n //(focus-canonical.md「套回實測值驗證」Calendar 事件 tile 列:內 −2px;與下方自訂 tile 的 wrapper 同一條)。\n // 2026-09-29 前這裡沒寫 class、走全域外描邊,與正本相反(待辦總帳 N46「內建事件方塊鍵盤框往內」)。\n 'focus-visible:focus-ring-inset',\n colorClass,\n )}\n >\n <span ref={truncationRef} className=\"block truncate\">{event.title}</span>\n </div>\n ) : (\n // 唯讀方塊(readOnlyEvents):不是按鈕、不進格內導覽(沒有 data-calendar-tile,F2 找不到它)、游標不變。\n // 不寫 aria-label:沒有角色的 div 禁止命名(ARIA 1.2 generic 的 name prohibited),事件標題就是它的文字內容。\n <div className={cn(tileBase, colorClass)}>\n <span ref={truncationRef} className=\"block truncate\">{event.title}</span>\n </div>\n )}\n </TooltipTrigger>\n <TooltipContent>{event.title}</TooltipContent>\n </Tooltip>\n )\n}\n\nconst Calendar = React.forwardRef<HTMLDivElement, CalendarProps>(function Calendar({\n referenceDate: referenceDateProp,\n defaultReferenceDate,\n onReferenceDateChange,\n today: todayProp,\n events = [],\n readOnlyEvents,\n onEventClick,\n readOnlyDates,\n onDateClick,\n onCreateEvent,\n weekStartsOn = 0,\n renderEventTile,\n className,\n locale = 'en-US',\n prevAriaLabel = '上個月', // i18n-allow: DS default; consumer override via prevAriaLabel prop\n nextAriaLabel = '下個月', // i18n-allow: DS default; consumer override via nextAriaLabel prop\n navAriaLabel = '行事曆月份導覽', // i18n-allow: DS default; consumer override via navAriaLabel prop\n todayLabel = '今天', // i18n-allow: DS default; consumer override via todayLabel prop\n createLabel = '新事件', // i18n-allow: DS default; consumer override via createLabel prop\n ...props\n}, ref) {\n // 可點與否只看明示的 readOnlyDates / readOnlyEvents(M23(f);型別層保證沒宣告唯讀時回調一定在,\n // 見 CalendarDateCellProps / CalendarEventTileProps)。\n const datesInteractive = !readOnlyDates\n // 事件方塊的二擇一契約原樣交給 MonthEventTile(同一份型別,不在這裡另寫一套判斷)\n const eventTileMode: CalendarEventTileProps = readOnlyEvents ? { readOnlyEvents: true } : { onEventClick }\n const resolvedToday = todayProp ?? new Date()\n // Controlled / uncontrolled refDate\n const [internalRef, setInternalRef] = React.useState<Date>(\n () => new Date((defaultReferenceDate ?? resolvedToday).getTime()),\n )\n const refDate = referenceDateProp ?? internalRef\n const setRefDate = React.useCallback(\n (next: Date) => {\n if (referenceDateProp === undefined) setInternalRef(next)\n onReferenceDateChange?.(next)\n },\n [referenceDateProp, onReferenceDateChange],\n )\n\n // Build month grid\n const days = React.useMemo(() => {\n const monthStart = startOfMonth(refDate)\n const monthEnd = endOfMonth(refDate)\n const gridStart = startOfWeek(monthStart, { weekStartsOn })\n const gridEnd = endOfWeek(monthEnd, { weekStartsOn })\n return eachDayOfInterval({ start: gridStart, end: gridEnd })\n }, [refDate, weekStartsOn])\n\n // 2026-07-06 D3 perf:formatter 依 locale memo(對齊 weekdayNames 既有做法),避免每 render 重建\n // Intl.DateTimeFormat(已知貴的 constructor);.format(refDate) 每 render 仍執行(cheap)。\n const monthTitleFormatter = React.useMemo(\n () => new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'long' }),\n [locale],\n )\n const monthTitle = monthTitleFormatter.format(refDate)\n\n const weekdayNames = React.useMemo(() => {\n // 取 `days[0..6]` 的名字(gridStart 開始 7 天,正好一週)\n return days.slice(0, 7).map((d) =>\n new Intl.DateTimeFormat(locale, { weekday: 'short' }).format(d),\n )\n }, [days, locale])\n\n // 2026-07-06 D3 perf:原每 render 對 42 cells 各跑 eventsOnDate 全 events filter = O(42×N) +\n // 每比較配 ~5 個 Date;數百-上千 events(行事曆真實規模)單次 render 數十 ms,且父層任何 re-render\n // 全額重付。改 useMemo 單趟 bucket:每 event 只 parse 一次,展開 [start..end](clamp 到可見 grid,\n // 避免長跨度 event 展開爆量)寫入 date→events Map,順便完成 allDay 排序。cell 內改 O(1) map.get。行為 Δ=0。\n const eventsByDate = React.useMemo(() => {\n const map = new Map<string, CalendarEvent[]>()\n if (days.length === 0) return map\n const first = days[0]\n const last = days[days.length - 1]\n const gridStart = new Date(first.getFullYear(), first.getMonth(), first.getDate()).getTime()\n const gridEnd = new Date(last.getFullYear(), last.getMonth(), last.getDate()).getTime()\n for (const e of events) {\n const start = coerceDate(e.start)\n const end = coerceDate(e.end)\n const eEnd = new Date(end.getFullYear(), end.getMonth(), end.getDate()).getTime()\n let sMs = new Date(start.getFullYear(), start.getMonth(), start.getDate()).getTime()\n if (eEnd < gridStart || sMs > gridEnd) continue // 可見窗外對 42 cells 無貢獻\n if (sMs < gridStart) sMs = gridStart\n const lastMs = Math.min(eEnd, gridEnd)\n const cursor = new Date(sMs)\n while (cursor.getTime() <= lastMs) {\n const key = `${cursor.getFullYear()}-${cursor.getMonth() + 1}-${cursor.getDate()}`\n const bucket = map.get(key)\n if (bucket) bucket.push(e)\n else map.set(key, [e])\n cursor.setDate(cursor.getDate() + 1)\n }\n }\n // allDay 排前(對齊 Google Calendar 全天列在上;V8 stable sort 保 events 原序 → 與舊 per-cell 一致)\n for (const bucket of map.values()) {\n bucket.sort((a, b) => Number(b.allDay ?? false) - Number(a.allDay ?? false))\n }\n return map\n }, [events, days])\n\n // ── Grid 鍵盤(APG Data Grid;2026-09-24 補實作)───────────────────────────\n // 本元件宣告 role=\"grid\" 就必須真的實作那套鍵盤 —— 只寫角色不接方向鍵 = 對輔助科技的空頭承諾\n //(SSOT:`ds-canonical/references/keyboard-model-canonical.md`「鐵律」)。按鍵表的逐字出處與\n // 每一條的取捨理由寫在 `calendar.spec.md`「A11y 預設」,此處不重述第二份。\n //\n // 模型 = roving tabindex(不是 aria-activedescendant):格內那顆日期 <button> 是真焦點,\n // SR 因此會報「按鈕」。APG 逐字:「A cell contains one widget whose operation does not require\n // arrow keys and grid navigation keys set focus on that widget. Examples of such widgets include\n // link, button, ...」;參考實作 APG Date Picker Dialog 的 setFocusDay() 也是 dayNode.tabIndex = -1 /\n // 命中日 = 0。\n const gridRef = React.useRef<HTMLDivElement | null>(null)\n const pendingFocusIso = React.useRef<string | null>(null)\n const [focusedDateState, setFocusedDateState] = React.useState<Date | null>(null)\n\n // Tab 進來時停在哪一天:今天在這個月就是今天,否則這個月 1 號\n //(APG Date Picker Dialog 範例:「If no date has been selected, places focus on the current date.」)。\n // 相依用「今天 00:00 的毫秒數」(primitive),不用 resolvedToday 物件:沒傳 `today` 時它每次 render 都是\n // 新的 new Date(),拿物件當相依 = memo 每次都重算(eslint exhaustive-deps 抓的就是這個)。\n // 不把 new Date() 包進 useMemo 凍在掛載時:行事曆分頁常掛好幾天,跨過午夜「今天」的 pill、Today 鈕目標\n // 都要在下一次 render 跟著走(react-day-picker 9.14 DayPicker.js:131 同樣每次 render 重取 today)。\n const todayDayMs = startOfDay(resolvedToday).getTime()\n const anchorDate = React.useMemo(\n () => (isSameMonth(todayDayMs, refDate) ? new Date(todayDayMs) : startOfMonth(refDate)),\n [todayDayMs, refDate],\n )\n // 已畫出來的日期範圍(含上/下月 outside day —— 本元件的 outside day 是有事件、可點的真格,\n // 與 APG 範例把 outside day 清空 disable 的做法不同,所以「跨月」的界線是格陣邊界而非月份邊界)。\n const gridFirstMs = days.length > 0 ? startOfDay(days[0]).getTime() : 0\n const gridLastMs = days.length > 0 ? startOfDay(days[days.length - 1]).getTime() : 0\n const isRendered = React.useCallback(\n (date: Date) => {\n const ms = startOfDay(date).getTime()\n return ms >= gridFirstMs && ms <= gridLastMs\n },\n [gridFirstMs, gridLastMs],\n )\n // 停靠點恆為「畫得出來的那一天」:換月後掉出格陣的舊值自動回落 anchor,\n // 保證任何一刻**剛好一顆**日期鈕 tabIndex=0(不會 0 顆,也不會 2 顆)。\n const focusedDate = focusedDateState !== null && isRendered(focusedDateState) ? focusedDateState : anchorDate\n\n // 換月那一步的目標鈕是下一次 render 才存在,所以焦點在 render 後、paint 前補上。\n React.useLayoutEffect(() => {\n const iso = pendingFocusIso.current\n if (iso === null) return\n pendingFocusIso.current = null\n gridRef.current?.querySelector<HTMLElement>(`[data-calendar-day=\"${iso}\"]`)?.focus()\n })\n\n const moveFocusToDay = React.useCallback(\n (next: Date) => {\n const target = startOfDay(next)\n setFocusedDateState(target)\n // 落在已畫出來的格(含 outside day)→ 月份不動;掉出格陣才換月,\n // 換完月它必定被畫出來 → 「跨月移動時焦點落到正確的那一天」恆成立。\n if (!isRendered(target)) setRefDate(target)\n pendingFocusIso.current = format(target, 'yyyy-MM-dd')\n },\n [isRendered, setRefDate],\n )\n\n // 一格的「日期停靠點」:日期格可點時是格內的日期數字鈕,唯讀時是格子本身(見下方 gridcell 的註解)。\n // 兩種都掛 `data-calendar-day`;querySelector 不含自己,所以先看格子本身。\n const dayStopOf = (cell: HTMLElement) =>\n cell.matches('[data-calendar-day]') ? cell : cell.querySelector<HTMLElement>('[data-calendar-day]')\n\n const handleGridKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const target = event.target as HTMLElement | null\n const cell = target?.closest<HTMLElement>('[role=\"gridcell\"]')\n if (!target || !cell) return\n const tile = target.closest<HTMLElement>('[data-calendar-tile]')\n\n // ── 格內模式:grid navigation 已停用,方向鍵改在格內的 widget 之間走 ──\n // APG「Editing and Navigating Inside a Cell」逐字:「Right Arrow or Down Arrow: If the cell\n // contains multiple widgets, moves focus to the next widget inside the cell」/「Escape: restores\n // grid navigation.」\n if (tile) {\n const tiles = Array.from(cell.querySelectorAll<HTMLElement>('[data-calendar-tile]'))\n const index = tiles.indexOf(tile)\n let nextNode: HTMLElement | null | undefined\n switch (event.key) {\n case 'Escape':\n case 'F2':\n nextNode = dayStopOf(cell)\n break\n case 'ArrowDown':\n case 'ArrowRight':\n nextNode = tiles[Math.min(index + 1, tiles.length - 1)]\n break\n case 'ArrowUp':\n case 'ArrowLeft':\n nextNode = tiles[Math.max(index - 1, 0)]\n break\n default:\n return\n }\n event.preventDefault()\n event.stopPropagation()\n nextNode?.focus()\n return\n }\n\n const dayValue = target.getAttribute('data-calendar-day')\n if (dayValue === null) return\n\n // F2 = 進格(APG:「F2: ... If the cell contains one or more widgets, places focus on the first\n // widget.」)。日期格可點時不用 Enter 當進格鍵,因為在月曆格陣裡 Enter 已經是「啟用這一天」——\n // APG Date Picker Dialog 的 Date Grid 把 Space/Enter 指派給選日期。兩者都是 APG 明文列的\n // 慣例,這裡取不會互相蓋掉的那一組。\n // 日期格唯讀時焦點在格子本身、格子沒有主要動作 → Enter 也是進格(跨元件規則\n // `ds-canonical/references/keyboard-model-canonical.md`「`Enter` 恆為「啟動焦點上的東西」—— 焦點在格上時那就等於進格」,\n // 與 DataTable 檢視態儲存格同一條;不是另立的例外)。\n if (event.key === 'F2' || (event.key === 'Enter' && !datesInteractive)) {\n const firstTile = cell.querySelector<HTMLElement>('[data-calendar-tile]')\n if (firstTile === null) return\n event.preventDefault()\n event.stopPropagation()\n firstTile.focus()\n return\n }\n\n const current = coerceDate(dayValue)\n let next: Date\n switch (event.key) {\n case 'ArrowRight':\n next = addDays(current, 1)\n break\n case 'ArrowLeft':\n next = addDays(current, -1)\n break\n case 'ArrowDown':\n next = addDays(current, 7)\n break\n case 'ArrowUp':\n next = addDays(current, -7)\n break\n case 'Home':\n next = startOfWeek(current, { weekStartsOn })\n break\n case 'End':\n next = endOfWeek(current, { weekStartsOn })\n break\n case 'PageUp':\n // date-fns addMonths 溢位自動夾到當月最後一天,正好等於 APG 的\n //「If that day does not exist, moves focus to the last day of the month.」\n next = addMonths(current, event.shiftKey ? -12 : -1)\n break\n case 'PageDown':\n next = addMonths(current, event.shiftKey ? 12 : 1)\n break\n default:\n return\n }\n event.preventDefault()\n event.stopPropagation()\n moveFocusToDay(next)\n }\n\n const handleToday = () => setRefDate(new Date(resolvedToday.getTime()))\n const handlePrev = () => setRefDate(subMonths(refDate, 1))\n const handleNext = () => setRefDate(addMonths(refDate, 1))\n\n return (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col w-full h-full bg-surface rounded-md border border-divider overflow-hidden',\n className,\n )}\n {...props}\n >\n {/* Toolbar:[◀] [今天] [▶] title [+ new] */}\n <div\n className={cn(\n 'flex items-center gap-2 shrink-0 border-b border-divider',\n 'px-[var(--layout-space-loose)] py-[var(--layout-space-tight)]',\n )}\n >\n {/* 月份導覽 landmark:prev / 今天 / next 包成 <nav> 給 SR landmark 導航(per calendar.spec.md a11y 段) */}\n <nav className=\"flex items-center gap-2\" aria-label={navAriaLabel}>\n <Button\n variant=\"text\"\n size=\"sm\"\n iconOnly\n startIcon={ChevronLeft}\n aria-label={prevAriaLabel}\n onClick={handlePrev}\n />\n <Button variant=\"tertiary\" size=\"sm\" onClick={handleToday}>\n {todayLabel}\n </Button>\n <Button\n variant=\"text\"\n size=\"sm\"\n iconOnly\n startIcon={ChevronRight}\n aria-label={nextAriaLabel}\n onClick={handleNext}\n />\n </nav>\n\n <h2 className=\"text-body-lg font-medium text-foreground flex-1 min-w-0 truncate ml-2\">\n {/* 2026-07-28:截斷必附 tooltip(tooltip.spec.md「截斷 → tooltip,僅實際截斷時顯示」)——\n 窄 toolbar 下標題被裁掉沒有補救路徑。display=\"block\":h2 是 block container。 */}\n <TruncatedText display=\"block\">{monthTitle}</TruncatedText>\n </h2>\n\n {/* 全域新增入口:toolbar 固定元素、恆渲染(M23(f);2026-09-29 前寫成 `{onCreateEvent && …}`,唯讀月曆就沒這顆鈕 —— 已撤回,\n 日期能不能新增由新增流程自己擋,不由鈕的有無表達,user 2026-09-29 原話見 CalendarOwnProps.onCreateEvent) */}\n <Button variant=\"primary\" size=\"sm\" startIcon={Plus} onClick={onCreateEvent}>\n {createLabel}\n </Button>\n </div>\n\n {/* Weekday header */}\n <div className=\"grid grid-cols-7 border-b border-divider bg-muted\">\n {weekdayNames.map((name, i) => (\n <div\n key={i}\n // 2026-09-07 修(user 抓「為何星期標題要用那麼淺的顏色?」):\n // 原本是 `text-caption text-fg-muted font-normal`(12px / 45% 灰 / 細體)。\n // **DS 早就有 canonical 而且方向相反** —— `date-grid.spec.md:151`「Weekday header canonical」\n //(2026-05-03 user audit):`text-foreground text-body font-medium`,理由是\n // 「weekday 列標跟 caption 同視覺權重,都屬 calendar header 區,**不弱化**」,\n // 而且明文「**撤銷 v3 用 `fg-secondary font-normal` 的 mistake(M23)**」。\n // Calendar 這版比那個已被撤銷的版本**還弱**,是漂移不是設計選擇\n //(calendar.spec.md 沒有另訂星期排版,所以那條是唯一 canonical)。\n // 在本元件內也是孤例:月份標題 `text-body-lg font-medium`、日期數字 `text-body font-medium`,\n // 只有星期標題是 12px 細灰。\n className=\"px-2 py-1.5 text-body text-foreground font-medium text-center\"\n >\n {name}\n </div>\n ))}\n </div>\n\n {/* Month grid:7 cols, ~5-6 rows。a11y(2026-04-25):WAI-ARIA grid 要求 row > gridcell\n 階層,chunk days 7 一組,wrap 成 role='row'(display:contents 保 CSS grid 佈局)。 */}\n <div\n ref={gridRef}\n className=\"grid grid-cols-7 flex-1 min-h-0\"\n role=\"grid\"\n aria-label={`月行事曆,${monthTitle}`}\n // grid navigation 掛在格陣上(事件委派):日期鈕與事件方塊都在這棵子樹裡,\n // 焦點在哪一層由 handler 自己判,不必每顆鈕各掛一份 handler。\n onKeyDown={handleGridKeyDown}\n >\n {Array.from({ length: Math.ceil(days.length / 7) }, (_, rowIdx) => (\n <div key={rowIdx} role=\"row\" style={{ display: 'contents' }}>\n {days.slice(rowIdx * 7, rowIdx * 7 + 7).map((date) => {\n const inMonth = isSameMonth(date, refDate)\n const isToday = isSameDay(date, resolvedToday)\n // 2026-06-01 allDay:全天事件排 cell 頂端(對齊 Google Calendar 全天列在上)——\n // 排序已在 eventsByDate bucketing memo 內完成(D3 perf),cell 內 O(1) 查表\n const dayEvents = eventsByDate.get(dayKey(date)) ?? []\n const visibleEvents = dayEvents.slice(0, MAX_TILES_PER_CELL)\n const overflowCount = dayEvents.length - visibleEvents.length\n // 這一天的鍵盤停靠點屬性(roving tabindex):可點時掛在日期數字鈕上,唯讀時掛在格子本身。\n // 兩處共用同一組屬性,只換掛的位置 —— handleGridKeyDown / moveFocusToDay 只認 data-calendar-day。\n const dayStop = {\n 'aria-label': `${format(date, 'yyyy-MM-dd')},${dayEvents.length} 個事件`,\n // roving tabindex:整個格陣只有這一個(= 目前焦點日)進 Tab 序列,其餘 -1。\n // APG Date Picker Dialog 逐字:「only one button in the calendar grid is in the Tab sequence」。\n 'data-calendar-day': format(date, 'yyyy-MM-dd'),\n tabIndex: isSameDay(date, focusedDate) ? 0 : -1,\n // 焦點用任何方式落到某一天(Tab 進來 / 滑鼠點 / 程式化)都把停靠點同步過去,\n // 免得下次 Tab 回來停在別天。\n onFocus: () => setFocusedDateState(date),\n }\n const dayNumberClass = cn(\n // 焦點框往外(= 不寫)。2026-09-10 重量:日期數字鈕(24×24)在格子裡是**置中**的,不是撐滿 ——\n // 上 6 / 下 4(下方是同格的事件容器)/ 左 128 / 右 7,最小 4.00 = canonical「算放得下」。\n // 2026-09-07 那句「往外會壓到隔壁格」量的是**格子**邊界不是鈕的鄰居;真正貼邊的是事件方塊\n //(彼此 gap-0.5 = 2px),那一處往內(內建 tile 與自訂 tile 的 wrapper 都寫 focus-ring-inset)。\n 'inline-flex items-center justify-center min-w-6 h-6 rounded-full text-body font-medium',\n isToday && 'px-2 bg-info text-on-emphasis',\n // 非當月 = 淡字 `fg-muted`,**不是** `fg-disabled`:這天跟當月格同一種可點性(可點就一樣可點,唯讀就一樣唯讀),\n // 只是不在焦點月份(同 DateGrid「鄰月日子」的淡字,date-grid.spec.md outside 列;disabled 字色留給真的不可操作)。\n !isToday && !inMonth && 'text-fg-muted',\n )\n\n return (\n // 2026-06-11 a11y(user 拍板 2c 修 code):cell 從 <button role=\"gridcell\"> 改非互動容器 —\n // W3C button 語義禁止互動後代,cell 內含 role=\"button\" 事件 tile = nested-interactive 違規。\n // 對齊 Google Calendar:gridcell = 容器,日期數字按鈕 = 日期級 keyboard 入口,tile 各自為 button。\n // div onClick 保留滑鼠「點 cell 空白處等同點日期」便利(keyboard 走日期數字按鈕,功能等價)。\n // 點格內空白處也把**鍵盤位置**帶過來(2026-09-29,待辦總帳 N46):停靠點(roving tabindex)搬到這一天、\n // 焦點落在這一天的日期鈕 —— 之後 Tab 回來停在剛點的那天、consumer 開的對話框關掉後焦點也回到它;\n // 2026-09-29 前只有點到日期數字鈕才會(它是原生 button,瀏覽器自己給焦點),點空白處停靠點留在別天。\n // 同一條規則 DataTable 試算表已做(「滑鼠點到哪一格,鍵盤位置就跟到哪一格」,data-table.spec.md「試算表模式」)。\n //\n // **日期格唯讀(readOnlyDates)時**(2026-09-26,待辦總帳 L8 / C15):格子不接點擊、不亮,日期數字只是文字;\n // 格子裡於是只剩文字(與可點的事件方塊,若有)→ 依 APG Grid「A cell contains text or a single graphic and\n // grid navigation keys set focus on the cell」,鍵盤停靠點改成**格子本身**(dayStop 掛在這裡),\n // 方向鍵 / Home / End / PageUp / PageDown 照舊。格與格之間沒有縫,焦點框往內畫(focus-canonical「問題二」)。\n <div\n key={date.toISOString()}\n role=\"gridcell\"\n {...(datesInteractive\n ? {\n onClick: (e: React.MouseEvent<HTMLDivElement>) => {\n // 日期鈕與事件方塊自己的 onClick 都 stopPropagation,走到這裡一定是格內空白處\n dayStopOf(e.currentTarget)?.focus({ preventScroll: true })\n setFocusedDateState(date)\n onDateClick(date)\n },\n }\n : dayStop)}\n className={cn(\n 'flex flex-col gap-1 min-h-28 p-1.5 text-left',\n 'border-r border-b border-divider last:border-r-0',\n '[&:nth-child(7n)]:border-r-0',\n // hover 底色瞬間切換,不做過渡(user 2026-09-10 拍板「第三題改成全部瞬間」;SSOT = tokens/motion/motion.spec.md「hover 回饋不做過渡」)\n // 非當月格**不加底色**(2026-09-25 user 選「可以,拿掉底色 (Recommended)」,選項由 AI 提供):它跟當月格一樣可點(onDateClick = 在這天新增),\n // 底色一律透明,所以滑過與當月格同一個滑過色。先前的 `bg-muted` 是「不可操作」的 token,放在可點的格上\n // 讓滑過反而變淺(淺 #F5F5F5 → #FAFAFA)。非當月只靠日期數字的淡字區分,見下方日期鈕與 spec「Outside day cell」。\n // 唯讀的格不亮:點了沒反應就不給滑過回饋(color.spec.md「Hover 換色配對總則」;待辦總帳 L8)。\n datesInteractive && 'hover:bg-neutral-hover',\n // 點得到(點整格 = 在這天新增)→ 手形游標(hit-area-canonical.md 滑過原則一-3;先前只有日期數字鈕是手形,\n // 格子空白處滑過會亮、點了會新增,游標卻是箭頭)\n datesInteractive && 'cursor-pointer',\n !datesInteractive && 'focus-visible:focus-ring-inset',\n )}\n >\n {/* Date number = keyboard 入口。24px 圓盒的來源是**今天 pill 本身就是 24 高**,平日跟齊\n → 跨 cell 數字落在同一條光學基線。**不是**因為某條最小點擊尺寸 —— 先前這裡寫的\n 「WCAG 2.5.8 ≥24」已於 2026-09-24 撤回:本 DS 以滑鼠精度為前提,不拿觸控尺寸建議當依據\n (owner = `ds-canonical/references/hit-area-canonical.md`「本 DS 不採納觸控尺寸建議」)。\n 命中與懸停的相等關係成立在 **cell** 這一層:懸停回饋是整格的 `hover:bg-neutral-hover`\n (上方 gridcell 的 className),而整格 div 的 onClick 就是同一個 onDateClick → 懸停形狀 ≡ 命中區。\n 這顆鈕本身沒有任何 hover 樣式(實測掃全部 stylesheet:0 條 :hover 規則命中它),\n 平日底色恆為透明,所以它不是另一個獨立目標,而是同一個目標的鍵盤入口 + 焦點框幾何;\n 它完全落在宿主格內、動作與宿主相同,不會生出隱形帶也搶不走別人的點擊。\n 實測(1280×900,md,團隊行事曆 story):平日鈕盒 24.00×24.00、背景 rgba(0,0,0,0)、\n 數字字面 6.58×17;今天鈕 31.30×24.00(px-2)、bg-info;格 178×155.80,\n hover 前後格底色 rgba(0,0,0,0) → oklch(0 0 0 / 0.02),鈕底色兩次都是透明。\n 規格 → `calendar.spec.md`「Cell 規則」的「命中區」條。\n 唯讀的格:日期數字是同一個盒、同一組字級與今天 pill,只是 <span>(不是按鈕、沒有手形游標) */}\n <div className=\"flex items-start justify-end\">\n {datesInteractive ? (\n <button\n type=\"button\"\n {...dayStop}\n onClick={(e) => {\n e.stopPropagation()\n onDateClick(date)\n }}\n className={dayNumberClass}\n >\n {format(date, 'd')}\n </button>\n ) : (\n <span className={dayNumberClass}>{format(date, 'd')}</span>\n )}\n </div>\n\n {/* Event tiles */}\n <div className=\"flex flex-col gap-0.5 min-h-0\">\n {visibleEvents.map((event) => {\n const ec = event.color ?? 'blue'\n // 可點的方塊帶滑過(CAT_EVENT),唯讀的不帶(CAT_SUBTLE);兩者同色相同底同字,見檔頭 EVENT_STATIC_COLOR_CLASSES\n const hueClass = readOnlyEvents ? EVENT_STATIC_COLOR_CLASSES[ec] : EVENT_COLOR_CLASSES[ec]\n // 2026-06-01 allDay:淡底 + 左 accent 條 + medium = 「全天長條」視覺(區分有時間事件)\n const colorClass = event.allDay\n ? cn(hueClass, EVENT_ALLDAY_ACCENT[ec], 'font-medium')\n : hueClass\n if (renderEventTile) {\n // 自訂視覺也照同一份可點 / 唯讀契約:外層 wrapper 由本元件 own(spec「A11y 預設」renderEventTile 段)\n return readOnlyEvents ? (\n // 唯讀:只包一層排版用的 div —— 不是按鈕、不進格內導覽(沒有 data-calendar-tile)、沒有焦點框\n <div key={event.id}>{renderEventTile(event)}</div>\n ) : (\n <div\n key={event.id}\n role=\"button\"\n // 與內建 tile 同一條:grid 單一 Tab 停靠點,自訂 tile 也不得自己是停靠點\n tabIndex={-1}\n data-calendar-tile=\"\"\n aria-label={`事件:${event.title}`}\n onClick={(e) => {\n e.stopPropagation()\n onEventClick(event)\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n e.stopPropagation()\n onEventClick(event)\n }\n }}\n // 內描邊:事件方塊之間 gap-0.5(2px),往外 +2px 會壓到上下相鄰的方塊\n className=\"rounded-md focus-visible:focus-ring-inset\"\n >\n {renderEventTile(event)}\n </div>\n )\n }\n return (\n <MonthEventTile\n key={event.id}\n event={event}\n colorClass={colorClass}\n {...eventTileMode}\n />\n )\n })}\n {overflowCount > 0 && (\n <div className=\"text-caption text-fg-muted px-1.5\">\n +{overflowCount} more\n </div>\n )}\n </div>\n </div>\n )\n })}\n </div>\n ))}\n </div>\n </div>\n )\n})\nCalendar.displayName = \"Calendar\"\n\n// Story auto-compile metadata — Phase 1 mechanical migration(2026-04-24)\n// Phase 2 fill needed: purpose descriptions + when rationale + world-class refs\nexport const calendarMeta = {\n component: 'Calendar',\n family: null, // non-family composite / overlay / layout\n variants: {\n\n },\n sizes: {\n\n },\n // 'active' 移除 — 日期格按壓視覺屬 DateGrid(其 meta 已 −active);nav 按壓屬內嵌 Button(2026-07-07 詞彙統一 DS-wide 按壓訊號盤點:檔內 0 active: utility / 0 *-active token)。\n states: ['default', 'hover', 'focus-visible', 'disabled'],\n tokens: {\n bg: ['bg-muted', 'bg-neutral-hover', 'bg-info', 'bg-surface'],\n fg: ['text-fg-muted', 'text-foreground'],\n ring: ['focus-ring-inset', '--ring'],\n },\n} as const\n\nexport { Calendar }\n"],"names":["Calendar"],"mappings":"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"}
@@ -60,7 +60,7 @@ export declare const carouselMeta: {
60
60
  readonly tokens: {
61
61
  readonly bg: readonly [];
62
62
  readonly fg: readonly [];
63
- readonly ring: readonly ["ring-ring"];
63
+ readonly ring: readonly ["--ring"];
64
64
  };
65
65
  };
66
66
  export { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext, CarouselDots, type CarouselApi, };
@@ -1 +1 @@
1
- {"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["../../../src/components/Carousel/carousel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,gBAAgB,EAAE,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAKlF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,KAAK,WAAW,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAA;AAC1C,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAChE,KAAK,eAAe,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAA;AAC/C,KAAK,cAAc,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAA;AAE9C,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,eAAe,CAAA;IACtB,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAA;IACvC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,CAAA;CACpC;AAyBD,QAAA,MAAM,QAAQ,6HAkHb,CAAA;AAKD,QAAA,MAAM,eAAe,6GA4BnB,CAAA;AAGF,UAAU,yBAA0B,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC9E,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,QAAA,MAAM,YAAY,kGAqBjB,CAAA;AA4BD,QAAA,MAAM,gBAAgB;IAbpB,0EAA0E;uBACvD,MAAM;2CAwD1B,CAAA;AAID,QAAA,MAAM,YAAY;IA7DhB,0EAA0E;uBACvD,MAAM;2CAqG1B,CAAA;AAKD,QAAA,MAAM,YAAY,6GAuDhB,CAAA;AAKF,eAAO,MAAM,YAAY;;;;;;;;;;;CAiBf,CAAA;AAEV,OAAO,EACL,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,KAAK,WAAW,GACjB,CAAA"}
1
+ {"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["../../../src/components/Carousel/carousel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,gBAAgB,EAAE,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAMlF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,KAAK,WAAW,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAA;AAC1C,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAChE,KAAK,eAAe,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAA;AAC/C,KAAK,cAAc,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAA;AAE9C,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,eAAe,CAAA;IACtB,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAA;IACvC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,KAAK,IAAI,CAAA;CACpC;AAyBD,QAAA,MAAM,QAAQ,6HAsHb,CAAA;AAKD,QAAA,MAAM,eAAe,6GA4BnB,CAAA;AAGF,UAAU,yBAA0B,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAC9E,sDAAsD;IACtD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,QAAA,MAAM,YAAY,kGAqBjB,CAAA;AA6BD,QAAA,MAAM,gBAAgB;IAZpB,0EAA0E;uBACvD,MAAM;2CAuD1B,CAAA;AAID,QAAA,MAAM,YAAY;IA5DhB,0EAA0E;uBACvD,MAAM;2CAoG1B,CAAA;AAKD,QAAA,MAAM,YAAY,6GAuDhB,CAAA;AAKF,eAAO,MAAM,YAAY;;;;;;;;;;;CAiBf,CAAA;AAEV,OAAO,EACL,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,KAAK,WAAW,GACjB,CAAA"}