@qijenchen/design-system 0.1.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. package/README.md +163 -0
  2. package/dist/components/Accordion/accordion.d.ts +37 -0
  3. package/dist/components/Accordion/accordion.d.ts.map +1 -0
  4. package/dist/components/Accordion/accordion.js +78 -0
  5. package/dist/components/Accordion/accordion.js.map +1 -0
  6. package/dist/components/Alert/alert.d.ts +47 -0
  7. package/dist/components/Alert/alert.d.ts.map +1 -0
  8. package/dist/components/Alert/alert.js +132 -0
  9. package/dist/components/Alert/alert.js.map +1 -0
  10. package/dist/components/AppShell/_demo-helpers.d.ts +49 -0
  11. package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -0
  12. package/dist/components/AppShell/app-shell.d.ts +76 -0
  13. package/dist/components/AppShell/app-shell.d.ts.map +1 -0
  14. package/dist/components/AppShell/app-shell.js +214 -0
  15. package/dist/components/AppShell/app-shell.js.map +1 -0
  16. package/dist/components/AspectRatio/aspect-ratio.d.ts +40 -0
  17. package/dist/components/AspectRatio/aspect-ratio.d.ts.map +1 -0
  18. package/dist/components/AspectRatio/aspect-ratio.js +23 -0
  19. package/dist/components/AspectRatio/aspect-ratio.js.map +1 -0
  20. package/dist/components/Avatar/avatar.d.ts +85 -0
  21. package/dist/components/Avatar/avatar.d.ts.map +1 -0
  22. package/dist/components/Avatar/avatar.js +195 -0
  23. package/dist/components/Avatar/avatar.js.map +1 -0
  24. package/dist/components/Badge/badge.d.ts +43 -0
  25. package/dist/components/Badge/badge.d.ts.map +1 -0
  26. package/dist/components/Badge/badge.js +69 -0
  27. package/dist/components/Badge/badge.js.map +1 -0
  28. package/dist/components/Breadcrumb/breadcrumb.d.ts +163 -0
  29. package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -0
  30. package/dist/components/Breadcrumb/breadcrumb.js +300 -0
  31. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -0
  32. package/dist/components/BulkActionBar/bulk-action-bar.d.ts +46 -0
  33. package/dist/components/BulkActionBar/bulk-action-bar.d.ts.map +1 -0
  34. package/dist/components/BulkActionBar/bulk-action-bar.js +78 -0
  35. package/dist/components/BulkActionBar/bulk-action-bar.js.map +1 -0
  36. package/dist/components/Button/button-group.d.ts +49 -0
  37. package/dist/components/Button/button-group.d.ts.map +1 -0
  38. package/dist/components/Button/button-group.js +46 -0
  39. package/dist/components/Button/button-group.js.map +1 -0
  40. package/dist/components/Button/button.d.ts +203 -0
  41. package/dist/components/Button/button.d.ts.map +1 -0
  42. package/dist/components/Button/button.js +309 -0
  43. package/dist/components/Button/button.js.map +1 -0
  44. package/dist/components/Calendar/calendar.d.ts +81 -0
  45. package/dist/components/Calendar/calendar.d.ts.map +1 -0
  46. package/dist/components/Calendar/calendar.js +282 -0
  47. package/dist/components/Calendar/calendar.js.map +1 -0
  48. package/dist/components/Carousel/carousel.d.ts +61 -0
  49. package/dist/components/Carousel/carousel.d.ts.map +1 -0
  50. package/dist/components/Carousel/carousel.js +276 -0
  51. package/dist/components/Carousel/carousel.js.map +1 -0
  52. package/dist/components/Chart/chart.d.ts +94 -0
  53. package/dist/components/Chart/chart.d.ts.map +1 -0
  54. package/dist/components/Chart/chart.js +233 -0
  55. package/dist/components/Chart/chart.js.map +1 -0
  56. package/dist/components/Checkbox/checkbox-group.d.ts +58 -0
  57. package/dist/components/Checkbox/checkbox-group.d.ts.map +1 -0
  58. package/dist/components/Checkbox/checkbox-group.js +28 -0
  59. package/dist/components/Checkbox/checkbox-group.js.map +1 -0
  60. package/dist/components/Checkbox/checkbox.d.ts +73 -0
  61. package/dist/components/Checkbox/checkbox.d.ts.map +1 -0
  62. package/dist/components/Checkbox/checkbox.js +125 -0
  63. package/dist/components/Checkbox/checkbox.js.map +1 -0
  64. package/dist/components/Chip/chip.d.ts +54 -0
  65. package/dist/components/Chip/chip.d.ts.map +1 -0
  66. package/dist/components/Chip/chip.js +224 -0
  67. package/dist/components/Chip/chip.js.map +1 -0
  68. package/dist/components/CircularProgress/circular-progress.d.ts +40 -0
  69. package/dist/components/CircularProgress/circular-progress.d.ts.map +1 -0
  70. package/dist/components/CircularProgress/circular-progress.js +118 -0
  71. package/dist/components/CircularProgress/circular-progress.js.map +1 -0
  72. package/dist/components/Coachmark/coachmark.d.ts +100 -0
  73. package/dist/components/Coachmark/coachmark.d.ts.map +1 -0
  74. package/dist/components/Coachmark/coachmark.js +107 -0
  75. package/dist/components/Coachmark/coachmark.js.map +1 -0
  76. package/dist/components/Combobox/combobox.d.ts +150 -0
  77. package/dist/components/Combobox/combobox.d.ts.map +1 -0
  78. package/dist/components/Combobox/combobox.js +595 -0
  79. package/dist/components/Combobox/combobox.js.map +1 -0
  80. package/dist/components/Command/command.d.ts +106 -0
  81. package/dist/components/Command/command.d.ts.map +1 -0
  82. package/dist/components/Command/command.js +123 -0
  83. package/dist/components/Command/command.js.map +1 -0
  84. package/dist/components/DataTable/active-editor-controller.d.ts +66 -0
  85. package/dist/components/DataTable/active-editor-controller.d.ts.map +1 -0
  86. package/dist/components/DataTable/cell-registry.d.ts +37 -0
  87. package/dist/components/DataTable/cell-registry.d.ts.map +1 -0
  88. package/dist/components/DataTable/cell-registry.js +377 -0
  89. package/dist/components/DataTable/cell-registry.js.map +1 -0
  90. package/dist/components/DataTable/column-types.d.ts +145 -0
  91. package/dist/components/DataTable/column-types.d.ts.map +1 -0
  92. package/dist/components/DataTable/column-types.js +17 -0
  93. package/dist/components/DataTable/column-types.js.map +1 -0
  94. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +49 -0
  95. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts.map +1 -0
  96. package/dist/components/DataTable/data-table-filter-panel.d.ts +30 -0
  97. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -0
  98. package/dist/components/DataTable/data-table-interaction-layer.d.ts +78 -0
  99. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -0
  100. package/dist/components/DataTable/data-table-interaction-layer.js +220 -0
  101. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -0
  102. package/dist/components/DataTable/data-table-sort-manager.d.ts +19 -0
  103. package/dist/components/DataTable/data-table-sort-manager.d.ts.map +1 -0
  104. package/dist/components/DataTable/data-table.d.ts +181 -0
  105. package/dist/components/DataTable/data-table.d.ts.map +1 -0
  106. package/dist/components/DataTable/data-table.js +1851 -0
  107. package/dist/components/DataTable/data-table.js.map +1 -0
  108. package/dist/components/DataTable/filter-operators.d.ts +116 -0
  109. package/dist/components/DataTable/filter-operators.d.ts.map +1 -0
  110. package/dist/components/DataTable/filter-tree.d.ts +66 -0
  111. package/dist/components/DataTable/filter-tree.d.ts.map +1 -0
  112. package/dist/components/DataTable/lib/column-meta.d.ts +49 -0
  113. package/dist/components/DataTable/lib/column-meta.d.ts.map +1 -0
  114. package/dist/components/DateGrid/date-grid.d.ts +61 -0
  115. package/dist/components/DateGrid/date-grid.d.ts.map +1 -0
  116. package/dist/components/DateGrid/date-grid.js +168 -0
  117. package/dist/components/DateGrid/date-grid.js.map +1 -0
  118. package/dist/components/DatePicker/date-picker.d.ts +119 -0
  119. package/dist/components/DatePicker/date-picker.d.ts.map +1 -0
  120. package/dist/components/DatePicker/date-picker.js +743 -0
  121. package/dist/components/DatePicker/date-picker.js.map +1 -0
  122. package/dist/components/DescriptionList/description-list.d.ts +60 -0
  123. package/dist/components/DescriptionList/description-list.d.ts.map +1 -0
  124. package/dist/components/DescriptionList/description-list.js +77 -0
  125. package/dist/components/DescriptionList/description-list.js.map +1 -0
  126. package/dist/components/Dialog/dialog.d.ts +54 -0
  127. package/dist/components/Dialog/dialog.d.ts.map +1 -0
  128. package/dist/components/Dialog/dialog.js +151 -0
  129. package/dist/components/Dialog/dialog.js.map +1 -0
  130. package/dist/components/DropdownMenu/dropdown-menu.d.ts +111 -0
  131. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -0
  132. package/dist/components/DropdownMenu/dropdown-menu.js +288 -0
  133. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -0
  134. package/dist/components/Empty/empty.d.ts +40 -0
  135. package/dist/components/Empty/empty.d.ts.map +1 -0
  136. package/dist/components/Empty/empty.js +66 -0
  137. package/dist/components/Empty/empty.js.map +1 -0
  138. package/dist/components/Field/field-context.d.ts +77 -0
  139. package/dist/components/Field/field-context.d.ts.map +1 -0
  140. package/dist/components/Field/field-context.js +37 -0
  141. package/dist/components/Field/field-context.js.map +1 -0
  142. package/dist/components/Field/field-types.d.ts +5 -0
  143. package/dist/components/Field/field-types.d.ts.map +1 -0
  144. package/dist/components/Field/field-types.js +13 -0
  145. package/dist/components/Field/field-types.js.map +1 -0
  146. package/dist/components/Field/field-wrapper.d.ts +17 -0
  147. package/dist/components/Field/field-wrapper.d.ts.map +1 -0
  148. package/dist/components/Field/field-wrapper.js +252 -0
  149. package/dist/components/Field/field-wrapper.js.map +1 -0
  150. package/dist/components/Field/field.d.ts +127 -0
  151. package/dist/components/Field/field.d.ts.map +1 -0
  152. package/dist/components/Field/field.js +295 -0
  153. package/dist/components/Field/field.js.map +1 -0
  154. package/dist/components/FieldControlGroup/field-control-group.d.ts +74 -0
  155. package/dist/components/FieldControlGroup/field-control-group.d.ts.map +1 -0
  156. package/dist/components/FieldControlGroup/field-control-group.js +62 -0
  157. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -0
  158. package/dist/components/FileItem/file-item.d.ts +44 -0
  159. package/dist/components/FileItem/file-item.d.ts.map +1 -0
  160. package/dist/components/FileItem/file-item.js +202 -0
  161. package/dist/components/FileItem/file-item.js.map +1 -0
  162. package/dist/components/FileUpload/file-upload.d.ts +97 -0
  163. package/dist/components/FileUpload/file-upload.d.ts.map +1 -0
  164. package/dist/components/FileUpload/file-upload.js +231 -0
  165. package/dist/components/FileUpload/file-upload.js.map +1 -0
  166. package/dist/components/FileViewer/file-viewer-types.d.ts +73 -0
  167. package/dist/components/FileViewer/file-viewer-types.d.ts.map +1 -0
  168. package/dist/components/FileViewer/file-viewer.d.ts +82 -0
  169. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -0
  170. package/dist/components/FileViewer/file-viewer.js +752 -0
  171. package/dist/components/FileViewer/file-viewer.js.map +1 -0
  172. package/dist/components/FileViewer/image-renderer.d.ts +9 -0
  173. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -0
  174. package/dist/components/FileViewer/image-renderer.js +165 -0
  175. package/dist/components/FileViewer/image-renderer.js.map +1 -0
  176. package/dist/components/HoverCard/hover-card.d.ts +30 -0
  177. package/dist/components/HoverCard/hover-card.d.ts.map +1 -0
  178. package/dist/components/HoverCard/hover-card.js +61 -0
  179. package/dist/components/HoverCard/hover-card.js.map +1 -0
  180. package/dist/components/Input/input.d.ts +72 -0
  181. package/dist/components/Input/input.d.ts.map +1 -0
  182. package/dist/components/Input/input.js +148 -0
  183. package/dist/components/Input/input.js.map +1 -0
  184. package/dist/components/LinkInput/link-input.d.ts +46 -0
  185. package/dist/components/LinkInput/link-input.d.ts.map +1 -0
  186. package/dist/components/LinkInput/link-input.js +215 -0
  187. package/dist/components/LinkInput/link-input.js.map +1 -0
  188. package/dist/components/Menu/menu-item.d.ts +83 -0
  189. package/dist/components/Menu/menu-item.d.ts.map +1 -0
  190. package/dist/components/Menu/menu-item.js +209 -0
  191. package/dist/components/Menu/menu-item.js.map +1 -0
  192. package/dist/components/NameCard/name-card.d.ts +85 -0
  193. package/dist/components/NameCard/name-card.d.ts.map +1 -0
  194. package/dist/components/NameCard/name-card.js +153 -0
  195. package/dist/components/NameCard/name-card.js.map +1 -0
  196. package/dist/components/Notice/notice.d.ts +69 -0
  197. package/dist/components/Notice/notice.d.ts.map +1 -0
  198. package/dist/components/Notice/notice.js +121 -0
  199. package/dist/components/Notice/notice.js.map +1 -0
  200. package/dist/components/NumberInput/number-input.d.ts +57 -0
  201. package/dist/components/NumberInput/number-input.d.ts.map +1 -0
  202. package/dist/components/NumberInput/number-input.js +131 -0
  203. package/dist/components/NumberInput/number-input.js.map +1 -0
  204. package/dist/components/OverflowIndicator/overflow-indicator.d.ts +23 -0
  205. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -0
  206. package/dist/components/OverflowIndicator/overflow-indicator.js +111 -0
  207. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -0
  208. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts +57 -0
  209. package/dist/components/PeoplePicker/avatar-stack-overflow.d.ts.map +1 -0
  210. package/dist/components/PeoplePicker/avatar-stack-overflow.js +35 -0
  211. package/dist/components/PeoplePicker/avatar-stack-overflow.js.map +1 -0
  212. package/dist/components/PeoplePicker/people-picker-helpers.d.ts +7 -0
  213. package/dist/components/PeoplePicker/people-picker-helpers.d.ts.map +1 -0
  214. package/dist/components/PeoplePicker/people-picker-helpers.js +25 -0
  215. package/dist/components/PeoplePicker/people-picker-helpers.js.map +1 -0
  216. package/dist/components/PeoplePicker/people-picker.d.ts +77 -0
  217. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -0
  218. package/dist/components/PeoplePicker/people-picker.js +263 -0
  219. package/dist/components/PeoplePicker/people-picker.js.map +1 -0
  220. package/dist/components/PeoplePicker/person-display.d.ts +66 -0
  221. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -0
  222. package/dist/components/PeoplePicker/person-display.js +203 -0
  223. package/dist/components/PeoplePicker/person-display.js.map +1 -0
  224. package/dist/components/Popover/popover.d.ts +50 -0
  225. package/dist/components/Popover/popover.d.ts.map +1 -0
  226. package/dist/components/Popover/popover.js +113 -0
  227. package/dist/components/Popover/popover.js.map +1 -0
  228. package/dist/components/ProgressBar/progress-bar.d.ts +37 -0
  229. package/dist/components/ProgressBar/progress-bar.d.ts.map +1 -0
  230. package/dist/components/ProgressBar/progress-bar.js +86 -0
  231. package/dist/components/ProgressBar/progress-bar.js.map +1 -0
  232. package/dist/components/RadioGroup/radio-group.d.ts +78 -0
  233. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -0
  234. package/dist/components/RadioGroup/radio-group.js +153 -0
  235. package/dist/components/RadioGroup/radio-group.js.map +1 -0
  236. package/dist/components/Rating/rating.d.ts +46 -0
  237. package/dist/components/Rating/rating.d.ts.map +1 -0
  238. package/dist/components/Rating/rating.js +179 -0
  239. package/dist/components/Rating/rating.js.map +1 -0
  240. package/dist/components/ScrollArea/scroll-area.d.ts +45 -0
  241. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -0
  242. package/dist/components/ScrollArea/scroll-area.js +65 -0
  243. package/dist/components/ScrollArea/scroll-area.js.map +1 -0
  244. package/dist/components/SegmentedControl/segmented-control.d.ts +102 -0
  245. package/dist/components/SegmentedControl/segmented-control.d.ts.map +1 -0
  246. package/dist/components/SegmentedControl/segmented-control.js +171 -0
  247. package/dist/components/SegmentedControl/segmented-control.js.map +1 -0
  248. package/dist/components/Select/select.d.ts +102 -0
  249. package/dist/components/Select/select.d.ts.map +1 -0
  250. package/dist/components/Select/select.js +435 -0
  251. package/dist/components/Select/select.js.map +1 -0
  252. package/dist/components/SelectMenu/select-menu.d.ts +103 -0
  253. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -0
  254. package/dist/components/SelectMenu/select-menu.js +239 -0
  255. package/dist/components/SelectMenu/select-menu.js.map +1 -0
  256. package/dist/components/SelectionControl/selection-item.d.ts +69 -0
  257. package/dist/components/SelectionControl/selection-item.d.ts.map +1 -0
  258. package/dist/components/SelectionControl/selection-item.js +142 -0
  259. package/dist/components/SelectionControl/selection-item.js.map +1 -0
  260. package/dist/components/Separator/separator.d.ts +17 -0
  261. package/dist/components/Separator/separator.d.ts.map +1 -0
  262. package/dist/components/Separator/separator.js +39 -0
  263. package/dist/components/Separator/separator.js.map +1 -0
  264. package/dist/components/Sheet/sheet.d.ts +56 -0
  265. package/dist/components/Sheet/sheet.d.ts.map +1 -0
  266. package/dist/components/Sheet/sheet.js +145 -0
  267. package/dist/components/Sheet/sheet.js.map +1 -0
  268. package/dist/components/Sidebar/sidebar.d.ts +195 -0
  269. package/dist/components/Sidebar/sidebar.d.ts.map +1 -0
  270. package/dist/components/Sidebar/sidebar.js +826 -0
  271. package/dist/components/Sidebar/sidebar.js.map +1 -0
  272. package/dist/components/Skeleton/skeleton.d.ts +16 -0
  273. package/dist/components/Skeleton/skeleton.d.ts.map +1 -0
  274. package/dist/components/Skeleton/skeleton.js +30 -0
  275. package/dist/components/Skeleton/skeleton.js.map +1 -0
  276. package/dist/components/Slider/slider.d.ts +48 -0
  277. package/dist/components/Slider/slider.d.ts.map +1 -0
  278. package/dist/components/Slider/slider.js +108 -0
  279. package/dist/components/Slider/slider.js.map +1 -0
  280. package/dist/components/Steps/steps.d.ts +71 -0
  281. package/dist/components/Steps/steps.d.ts.map +1 -0
  282. package/dist/components/Steps/steps.js +583 -0
  283. package/dist/components/Steps/steps.js.map +1 -0
  284. package/dist/components/Switch/switch.d.ts +112 -0
  285. package/dist/components/Switch/switch.d.ts.map +1 -0
  286. package/dist/components/Switch/switch.js +179 -0
  287. package/dist/components/Switch/switch.js.map +1 -0
  288. package/dist/components/Tabs/tabs.d.ts +104 -0
  289. package/dist/components/Tabs/tabs.d.ts.map +1 -0
  290. package/dist/components/Tabs/tabs.js +316 -0
  291. package/dist/components/Tabs/tabs.js.map +1 -0
  292. package/dist/components/Tag/tag.d.ts +86 -0
  293. package/dist/components/Tag/tag.d.ts.map +1 -0
  294. package/dist/components/Tag/tag.js +172 -0
  295. package/dist/components/Tag/tag.js.map +1 -0
  296. package/dist/components/Textarea/textarea.d.ts +74 -0
  297. package/dist/components/Textarea/textarea.d.ts.map +1 -0
  298. package/dist/components/Textarea/textarea.js +224 -0
  299. package/dist/components/Textarea/textarea.js.map +1 -0
  300. package/dist/components/TimePicker/time-columns.d.ts +46 -0
  301. package/dist/components/TimePicker/time-columns.d.ts.map +1 -0
  302. package/dist/components/TimePicker/time-columns.js +173 -0
  303. package/dist/components/TimePicker/time-columns.js.map +1 -0
  304. package/dist/components/TimePicker/time-picker.d.ts +94 -0
  305. package/dist/components/TimePicker/time-picker.d.ts.map +1 -0
  306. package/dist/components/TimePicker/time-picker.js +253 -0
  307. package/dist/components/TimePicker/time-picker.js.map +1 -0
  308. package/dist/components/Toast/toast.d.ts +61 -0
  309. package/dist/components/Toast/toast.d.ts.map +1 -0
  310. package/dist/components/Toast/toast.js +76 -0
  311. package/dist/components/Toast/toast.js.map +1 -0
  312. package/dist/components/Tooltip/tooltip.d.ts +20 -0
  313. package/dist/components/Tooltip/tooltip.d.ts.map +1 -0
  314. package/dist/components/Tooltip/tooltip.js +53 -0
  315. package/dist/components/Tooltip/tooltip.js.map +1 -0
  316. package/dist/components/TreeView/tree-view.d.ts +166 -0
  317. package/dist/components/TreeView/tree-view.d.ts.map +1 -0
  318. package/dist/components/TreeView/tree-view.js +617 -0
  319. package/dist/components/TreeView/tree-view.js.map +1 -0
  320. package/dist/hooks/use-controllable.d.ts +16 -0
  321. package/dist/hooks/use-controllable.d.ts.map +1 -0
  322. package/dist/hooks/use-controllable.js +26 -0
  323. package/dist/hooks/use-controllable.js.map +1 -0
  324. package/dist/hooks/use-is-narrow-viewport.d.ts +2 -0
  325. package/dist/hooks/use-is-narrow-viewport.d.ts.map +1 -0
  326. package/dist/hooks/use-is-narrow-viewport.js +19 -0
  327. package/dist/hooks/use-is-narrow-viewport.js.map +1 -0
  328. package/dist/hooks/use-is-touch-device.d.ts +8 -0
  329. package/dist/hooks/use-is-touch-device.d.ts.map +1 -0
  330. package/dist/hooks/use-is-touch-device.js +16 -0
  331. package/dist/hooks/use-is-touch-device.js.map +1 -0
  332. package/dist/hooks/use-overflow-items.d.ts +124 -0
  333. package/dist/hooks/use-overflow-items.d.ts.map +1 -0
  334. package/dist/hooks/use-overflow-items.js +97 -0
  335. package/dist/hooks/use-overflow-items.js.map +1 -0
  336. package/dist/index.d.ts +74 -0
  337. package/dist/index.d.ts.map +1 -0
  338. package/dist/index.js +371 -0
  339. package/dist/index.js.map +1 -0
  340. package/dist/lib/drag-visual.d.ts +158 -0
  341. package/dist/lib/drag-visual.d.ts.map +1 -0
  342. package/dist/lib/drag-visual.js +96 -0
  343. package/dist/lib/drag-visual.js.map +1 -0
  344. package/dist/lib/i18n/i18n-context.d.ts +105 -0
  345. package/dist/lib/i18n/i18n-context.d.ts.map +1 -0
  346. package/dist/lib/multi-select-ordering.d.ts +54 -0
  347. package/dist/lib/multi-select-ordering.d.ts.map +1 -0
  348. package/dist/lib/multi-select-ordering.js +13 -0
  349. package/dist/lib/multi-select-ordering.js.map +1 -0
  350. package/dist/lib/utils.d.ts +12 -0
  351. package/dist/lib/utils.d.ts.map +1 -0
  352. package/dist/lib/utils.js +79 -0
  353. package/dist/lib/utils.js.map +1 -0
  354. package/dist/patterns/element-anatomy/item-anatomy.d.ts +370 -0
  355. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -0
  356. package/dist/patterns/element-anatomy/item-anatomy.js +272 -0
  357. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -0
  358. package/dist/patterns/header-canonical/chrome-header.d.ts +80 -0
  359. package/dist/patterns/header-canonical/chrome-header.d.ts.map +1 -0
  360. package/dist/patterns/header-canonical/chrome-header.js +75 -0
  361. package/dist/patterns/header-canonical/chrome-header.js.map +1 -0
  362. package/dist/patterns/horizontal-overflow/horizontal-overflow.d.ts +101 -0
  363. package/dist/patterns/horizontal-overflow/horizontal-overflow.d.ts.map +1 -0
  364. package/dist/patterns/horizontal-overflow/horizontal-overflow.js +105 -0
  365. package/dist/patterns/horizontal-overflow/horizontal-overflow.js.map +1 -0
  366. package/dist/patterns/overlay-surface/overlay-surface.d.ts +28 -0
  367. package/dist/patterns/overlay-surface/overlay-surface.d.ts.map +1 -0
  368. package/dist/patterns/overlay-surface/overlay-surface.js +85 -0
  369. package/dist/patterns/overlay-surface/overlay-surface.js.map +1 -0
  370. package/dist/patterns/resize-handle/resize-handle.d.ts +102 -0
  371. package/dist/patterns/resize-handle/resize-handle.d.ts.map +1 -0
  372. package/dist/patterns/resize-handle/resize-handle.js +74 -0
  373. package/dist/patterns/resize-handle/resize-handle.js.map +1 -0
  374. package/dist/react-day-picker.css +457 -0
  375. package/dist/stories-helpers/anatomy/anatomy-utils.d.ts +40 -0
  376. package/dist/stories-helpers/anatomy/anatomy-utils.d.ts.map +1 -0
  377. package/dist/tokens/elevation/overlay-geometry.d.ts +12 -0
  378. package/dist/tokens/elevation/overlay-geometry.d.ts.map +1 -0
  379. package/dist/tokens/elevation/overlay-geometry.js +7 -0
  380. package/dist/tokens/elevation/overlay-geometry.js.map +1 -0
  381. package/dist/tokens/motion/motion.d.ts +15 -0
  382. package/dist/tokens/motion/motion.d.ts.map +1 -0
  383. package/dist/tokens/motion/motion.js +9 -0
  384. package/dist/tokens/motion/motion.js.map +1 -0
  385. package/dist/tokens/uiSize/icon-size.d.ts +53 -0
  386. package/dist/tokens/uiSize/icon-size.d.ts.map +1 -0
  387. package/package.json +92 -0
  388. package/src/README.md +32 -0
  389. package/src/components/Accordion/accordion.tsx +104 -0
  390. package/src/components/Alert/alert.tsx +188 -0
  391. package/src/components/AppShell/_demo-helpers.tsx +198 -0
  392. package/src/components/AppShell/app-shell.tsx +364 -0
  393. package/src/components/AspectRatio/aspect-ratio.tsx +58 -0
  394. package/src/components/Avatar/avatar.tsx +368 -0
  395. package/src/components/Badge/badge.tsx +104 -0
  396. package/src/components/Breadcrumb/breadcrumb.tsx +619 -0
  397. package/src/components/BulkActionBar/bulk-action-bar.tsx +156 -0
  398. package/src/components/Button/button-group.tsx +96 -0
  399. package/src/components/Button/button.tsx +539 -0
  400. package/src/components/Calendar/calendar.tsx +411 -0
  401. package/src/components/Carousel/carousel.tsx +371 -0
  402. package/src/components/Chart/chart.tsx +376 -0
  403. package/src/components/Checkbox/checkbox-group.tsx +94 -0
  404. package/src/components/Checkbox/checkbox.tsx +237 -0
  405. package/src/components/Chip/chip.tsx +359 -0
  406. package/src/components/CircularProgress/circular-progress.tsx +204 -0
  407. package/src/components/Coachmark/coachmark.tsx +255 -0
  408. package/src/components/Combobox/combobox.tsx +826 -0
  409. package/src/components/Command/command.tsx +187 -0
  410. package/src/components/DataTable/active-editor-controller.ts +72 -0
  411. package/src/components/DataTable/cell-registry.tsx +520 -0
  412. package/src/components/DataTable/column-types.ts +180 -0
  413. package/src/components/DataTable/data-table-column-visibility-panel.tsx +261 -0
  414. package/src/components/DataTable/data-table-filter-panel.tsx +813 -0
  415. package/src/components/DataTable/data-table-interaction-layer.tsx +483 -0
  416. package/src/components/DataTable/data-table-sort-manager.tsx +210 -0
  417. package/src/components/DataTable/data-table.css +165 -0
  418. package/src/components/DataTable/data-table.tsx +2924 -0
  419. package/src/components/DataTable/filter-operators.ts +225 -0
  420. package/src/components/DataTable/filter-tree.ts +313 -0
  421. package/src/components/DataTable/lib/column-meta.ts +79 -0
  422. package/src/components/DateGrid/date-grid.tsx +209 -0
  423. package/src/components/DatePicker/date-picker.tsx +1114 -0
  424. package/src/components/DescriptionList/description-list.tsx +141 -0
  425. package/src/components/Dialog/dialog.tsx +267 -0
  426. package/src/components/DropdownMenu/dropdown-menu.tsx +475 -0
  427. package/src/components/Empty/empty.tsx +108 -0
  428. package/src/components/Field/field-context.ts +136 -0
  429. package/src/components/Field/field-types.ts +52 -0
  430. package/src/components/Field/field-wrapper.tsx +348 -0
  431. package/src/components/Field/field.tsx +535 -0
  432. package/src/components/FieldControlGroup/field-control-group.tsx +136 -0
  433. package/src/components/FileItem/file-item.tsx +322 -0
  434. package/src/components/FileUpload/file-upload.tsx +326 -0
  435. package/src/components/FileViewer/file-viewer-types.ts +76 -0
  436. package/src/components/FileViewer/file-viewer.tsx +1065 -0
  437. package/src/components/FileViewer/image-renderer.tsx +256 -0
  438. package/src/components/HoverCard/hover-card.tsx +79 -0
  439. package/src/components/Input/input.tsx +233 -0
  440. package/src/components/LinkInput/link-input.tsx +304 -0
  441. package/src/components/Menu/menu-item.tsx +334 -0
  442. package/src/components/NameCard/name-card.tsx +319 -0
  443. package/src/components/Notice/notice.tsx +196 -0
  444. package/src/components/NumberInput/number-input.tsx +203 -0
  445. package/src/components/OverflowIndicator/overflow-indicator.tsx +156 -0
  446. package/src/components/PeoplePicker/avatar-stack-overflow.ts +100 -0
  447. package/src/components/PeoplePicker/people-picker-helpers.ts +76 -0
  448. package/src/components/PeoplePicker/people-picker.tsx +455 -0
  449. package/src/components/PeoplePicker/person-display.tsx +358 -0
  450. package/src/components/Popover/popover.tsx +183 -0
  451. package/src/components/ProgressBar/progress-bar.tsx +157 -0
  452. package/src/components/README.md +58 -0
  453. package/src/components/RadioGroup/radio-group.tsx +261 -0
  454. package/src/components/Rating/rating.tsx +295 -0
  455. package/src/components/ScrollArea/scroll-area.tsx +110 -0
  456. package/src/components/SegmentedControl/segmented-control.tsx +304 -0
  457. package/src/components/Select/select.tsx +658 -0
  458. package/src/components/SelectMenu/select-menu.tsx +430 -0
  459. package/src/components/SelectionControl/selection-item.tsx +261 -0
  460. package/src/components/Separator/separator.tsx +48 -0
  461. package/src/components/Sheet/sheet.tsx +240 -0
  462. package/src/components/Sidebar/sidebar.tsx +1280 -0
  463. package/src/components/Skeleton/skeleton.tsx +35 -0
  464. package/src/components/Slider/slider.tsx +158 -0
  465. package/src/components/Steps/steps.tsx +850 -0
  466. package/src/components/Switch/switch.tsx +285 -0
  467. package/src/components/Tabs/tabs.tsx +515 -0
  468. package/src/components/Tag/tag.tsx +246 -0
  469. package/src/components/Textarea/textarea.tsx +280 -0
  470. package/src/components/TimePicker/time-columns.tsx +260 -0
  471. package/src/components/TimePicker/time-picker.tsx +419 -0
  472. package/src/components/Toast/toast.tsx +129 -0
  473. package/src/components/Tooltip/tooltip.tsx +68 -0
  474. package/src/components/TreeView/tree-view.tsx +1031 -0
  475. package/src/hooks/use-controllable.ts +40 -0
  476. package/src/hooks/use-is-narrow-viewport.ts +19 -0
  477. package/src/hooks/use-is-touch-device.ts +21 -0
  478. package/src/hooks/use-overflow-items.ts +256 -0
  479. package/src/index.ts +85 -0
  480. package/src/lib/README.md +82 -0
  481. package/src/lib/drag-visual.ts +272 -0
  482. package/src/lib/i18n/README.md +60 -0
  483. package/src/lib/i18n/i18n-context.tsx +129 -0
  484. package/src/lib/multi-select-ordering.ts +61 -0
  485. package/src/lib/utils.ts +93 -0
  486. package/src/patterns/README.md +67 -0
  487. package/src/patterns/element-anatomy/item-anatomy.tsx +744 -0
  488. package/src/patterns/header-canonical/chrome-header.tsx +175 -0
  489. package/src/patterns/header-canonical/header-canonical.css +27 -0
  490. package/src/patterns/horizontal-overflow/horizontal-overflow.tsx +217 -0
  491. package/src/patterns/overlay-surface/overlay-surface.tsx +191 -0
  492. package/src/patterns/resize-handle/resize-handle.tsx +188 -0
  493. package/src/stories-helpers/anatomy/anatomy-utils.tsx +64 -0
  494. package/src/styles/preset.css +31 -0
  495. package/src/styles/tokens.css +35 -0
  496. package/src/tokens/README.md +53 -0
  497. package/src/tokens/color/primitives.css +429 -0
  498. package/src/tokens/color/semantic.css +539 -0
  499. package/src/tokens/elevation/overlay-geometry.ts +13 -0
  500. package/src/tokens/layoutSpace/layoutSpace.css +36 -0
  501. package/src/tokens/motion/motion.css +30 -0
  502. package/src/tokens/motion/motion.ts +17 -0
  503. package/src/tokens/opacity/opacity.css +23 -0
  504. package/src/tokens/radius/radius.css +19 -0
  505. package/src/tokens/typography/typography.css +118 -0
  506. package/src/tokens/uiSize/icon-size.ts +52 -0
  507. package/src/tokens/uiSize/uiSize.css +125 -0
@@ -0,0 +1,175 @@
1
+ import * as React from 'react'
2
+ import { cn } from '@/lib/utils'
3
+
4
+ /**
5
+ * @internal — DS-internal primitive(2026-05-23 per `.claude/rules/ui-development.md` Public vs Internal canonical)。
6
+ * end-user app 直接 render `<ChromeHeader />` 無 functioning UI;由 Sidebar / FileViewer / Dialog / Sheet / Popover 等 DS 元件 wrap 消費。
7
+ *
8
+ * ChromeHeader — Fixed-height chrome header primitive(Layout Family B,header-canonical.spec.md)
9
+ *
10
+ * ── 定位 ──
11
+ * Page chrome 級 header 共用 primitive。封裝重複 contract:
12
+ * flex items-center gap-2 shrink-0 h-[var(--chrome-header-height)] border-b border-divider px-[var(--layout-space-loose)]
13
+ *
14
+ * Consumers:Sidebar / FileViewer Toolbar / FileViewer InfoPanel / 未來 page top bar / Drawer
15
+ * 跟 SurfaceHeader(overlay padding-based)是兩個並存家族(per header-canonical.spec.md L23-30)。
16
+ *
17
+ * ── 實作基礎 ──
18
+ * 消費:--chrome-header-height(48/56 density-responsive)/ --layout-space-loose / border-divider
19
+ * 對應 pattern:patterns/header-canonical
20
+ *
21
+ * ── 消費的 SSOT ──
22
+ * - tokens: [--chrome-header-height, --layout-space-loose, --divider]
23
+ * - patterns: [header-canonical(本 pattern), overlay-surface(姊妹 SurfaceHeader)]
24
+ * - spec refs: patterns/header-canonical/header-canonical.spec.md(L23-30 家族區分 / W1 border / W3 tabs size / Layer 3 ChromeHeader API)
25
+ *
26
+ * ── API(per M31 codex 比稿 Step 5 — narrow API,避免 M21 prop variant 風險)──
27
+ * withTabs?: boolean(預設 false)
28
+ * true → 移除自身 border-b,delegate paint 給 TabsList(per W1「Header semantic owner / TabsList paint owner in withTabs state」)
29
+ * lockDensity?: 'inherit' | 'lg'(預設 'inherit')
30
+ * 'inherit' → 跟 page density(html[data-density] 自動)
31
+ * 'lg' → 強制 lg(viewer-fullscreen-chrome escape hatch,FileViewer 永遠 lg-equivalent design intent)
32
+ *
33
+ * 不開:density?: 'md' | 'lg' 自由 prop。M21 違反 — 任意 density 等於 cva-on-pattern。
34
+ */
35
+ export interface ChromeHeaderProps
36
+ extends React.HTMLAttributes<HTMLElement> {
37
+ /**
38
+ * 是否內含 Tabs。
39
+ * true(無 tabsSlot)→ 移除自身 border-b,consumer 自畫。
40
+ * 若提供 tabsSlot,自動 column mode + auto suppress border。
41
+ * 對應 patterns/header-canonical/header-canonical.spec.md W1
42
+ */
43
+ withTabs?: boolean
44
+ /**
45
+ * Tabs row slot(2026-05-18 加 per W2/W4 真實能用 + user-mandated fix)。
46
+ * 提供時 ChromeHeader 自動 column 結構:
47
+ * row 1 = children(h-chrome-header-height 固定,px-loose,跟 single-row 模式同)
48
+ * row 2 = tabsSlot 包在 `<div px-loose border-b border-divider>`
49
+ * ↑ wrapper 提供 W2 padding inheritance + W1 全寬 paint(一條線)
50
+ *
51
+ * Consumer 傳:`tabsSlot={<TabsList>...</TabsList>}`,TabsContent 放 ChromeHeader 之外。
52
+ * Standalone Tabs(無 chrome header)該直接用 `<TabsList>` 不需 wrapper。
53
+ *
54
+ * 提供 tabsSlot 自動 withTabs=true,不需另傳 prop。
55
+ */
56
+ tabsSlot?: React.ReactNode
57
+ /**
58
+ * 是否鎖死 lg density(viewer-fullscreen chrome 用)。
59
+ * 'inherit'(預設)→ 跟 page density
60
+ * 'lg' → 強制 chrome-header-height lg(56)
61
+ * 對應 patterns/header-canonical/header-canonical.spec.md Layer 3 API
62
+ */
63
+ lockDensity?: 'inherit' | 'lg'
64
+ /**
65
+ * Leading rail slot(2026-05-21 ship per AppShell primary-header globalHeader 用例,
66
+ * codex M31 Layer C 建議 codify into ChromeHeader API):
67
+ * 固定寬度 = `var(--sidebar-width-icon)` 的左邊容器,內 `justify-center` 排列。
68
+ *
69
+ * 用途:primary-header globalHeader 左側 SidebarTrigger,跟 sidebar 收合 icon 完美水平對齊
70
+ * (sidebar 收合 width = sidebar-width-icon,toggle container 同寬 = toggle center x = sidebar
71
+ * collapsed icon center x = perfect alignment)。
72
+ *
73
+ * 對齊 GitHub global nav 左側固定寬度 logo 區 / Slack thin workspace rail 慣例。
74
+ * 提供時自動結構:
75
+ * row1: [leadingRail (width=sidebar-width-icon)] [children (px-loose flex-1)]
76
+ * 不提供時 fallback 預設 single-row(全 px-loose)。
77
+ *
78
+ * 與 tabsSlot 互斥(tabsSlot 啟動 column mode,本 prop 不生效)。
79
+ */
80
+ leadingRail?: React.ReactNode
81
+ }
82
+
83
+ export const ChromeHeader = React.forwardRef<HTMLElement, ChromeHeaderProps>(
84
+ (
85
+ { className, withTabs, tabsSlot, lockDensity = 'inherit', leadingRail, children, ...props },
86
+ ref,
87
+ ) => {
88
+ const hasTabs = tabsSlot != null || withTabs === true
89
+
90
+ // Column mode(tabsSlot 提供時)— per W2 + W4
91
+ // 2026-05-20:`<div>` → `<header>`(HTML5 sectional content 允許 multiple `<header>`,
92
+ // page-level / sectional 都 a11y safe;統一 element contract 消除「何時用 header / 何時用 div」
93
+ // 的 consumer drift)。 對應 header-canonical.spec.md 「Element canonical」段。
94
+ if (tabsSlot != null) {
95
+ return (
96
+ <header
97
+ ref={ref}
98
+ data-density={lockDensity === 'lg' ? 'lg' : undefined}
99
+ className={cn('flex flex-col shrink-0', className)}
100
+ {...props}
101
+ >
102
+ {/* Row 1:header content(固定高度,跟 single-row 模式同 visual)*/}
103
+ <div
104
+ className={cn(
105
+ 'flex items-center gap-2',
106
+ 'h-[var(--chrome-header-height)]',
107
+ 'px-[var(--layout-space-loose)]',
108
+ )}
109
+ >
110
+ {children}
111
+ </div>
112
+ {/* Row 2:tabsSlot wrapper — TabsList 全 dialog 寬 + 內 px-loose inset triggers
113
+ 2026-05-18 v3 fix(同 SurfaceHeader,per user verbatim「分隔線寬度應該要填滿整個
114
+ dialog」+「就這樣做」approval):TabsList 自己 px-loose 內 padding 而非 wrapper
115
+ 提供,讓 TabsList border-b 延展全 dialog 寬。對齊 `tabs.spec.md:199` 既有 canonical。*/}
116
+ <div className="[&>[role=tablist]]:w-full [&>[role=tablist]]:px-[var(--layout-space-loose)]">
117
+ {tabsSlot}
118
+ </div>
119
+ </header>
120
+ )
121
+ }
122
+
123
+ // Leading rail mode(2026-05-21 ship per AppShell primary-header globalHeader):
124
+ // [leadingRail (width=sidebar-width-icon, justify-center)] [children (flex-1 px-loose)]
125
+ // 整 header 仍 fixed-height chrome-header-height + border-b。Rail 容器無 padding(內元素
126
+ // 透過 sidebar-width-icon 幾何自然居中,跟 sidebar 收合 icon center x 對齊)。
127
+ if (leadingRail != null) {
128
+ return (
129
+ <header
130
+ ref={ref}
131
+ data-density={lockDensity === 'lg' ? 'lg' : undefined}
132
+ className={cn(
133
+ 'flex items-center shrink-0',
134
+ 'h-[var(--chrome-header-height)]',
135
+ !hasTabs && 'border-b border-divider',
136
+ className,
137
+ )}
138
+ {...props}
139
+ >
140
+ {/* Rail:固定寬度 = sidebar-width-icon,內容 justify-center 居中(toggle center x
141
+ = rail 寬度的中點 = sidebar 收合 icon center x = 完美 vertical 對齊)
142
+ 2026-05-21 v2 user 抓:rail 右側加 `border-r border-divider`,sidebar 收合到
143
+ icon mode 時 rail 右 border = sidebar 右 border 連成一線(visual continuity)。 */}
144
+ <div className="flex w-[var(--sidebar-width-icon)] shrink-0 items-center justify-center border-r border-divider">
145
+ {leadingRail}
146
+ </div>
147
+ {/* Main:flex-1 + px-loose(沿用 header 既有左右 padding canonical)+ gap-2 */}
148
+ <div className="flex flex-1 items-center gap-2 min-w-0 px-[var(--layout-space-loose)]">
149
+ {children}
150
+ </div>
151
+ </header>
152
+ )
153
+ }
154
+
155
+ // Single-row(預設 + withTabs=true 但無 tabsSlot 的 backward compat)
156
+ return (
157
+ <header
158
+ ref={ref}
159
+ data-density={lockDensity === 'lg' ? 'lg' : undefined}
160
+ className={cn(
161
+ 'flex items-center gap-2 shrink-0',
162
+ 'h-[var(--chrome-header-height)]',
163
+ 'px-[var(--layout-space-loose)]',
164
+ // W1:無 tabs 自畫 border;withTabs=true(無 tabsSlot)consumer 自畫
165
+ !hasTabs && 'border-b border-divider',
166
+ className,
167
+ )}
168
+ {...props}
169
+ >
170
+ {children}
171
+ </header>
172
+ )
173
+ },
174
+ )
175
+ ChromeHeader.displayName = 'ChromeHeader'
@@ -0,0 +1,27 @@
1
+ /* Header canonical pattern local tokens(per DataTable data-table.css 既有 local-token pattern):
2
+ ─────────────────────────────────────────────────────────
3
+ Token 加入 rationale(per CLAUDE.md governance principle):
4
+ SSOT canonical value + 多 consumer 需 sync 即可加 local token,
5
+ 不必硬卡 Rule of 3(清既有重複 vs spec canonical 給程式表達 是兩件事)。
6
+
7
+ --chrome-header-avatar-size:
8
+ Chrome header brand mark avatar canonical(per `header-canonical.spec.md` 4.5
9
+ + 5-DS 共識:Linear / Notion / Figma / Slack / Polaris chrome header brand mark
10
+ 皆固定 24px,不 density-scale 也不 row-size-scale)。
11
+
12
+ Chrome header **不是 row context**(per `item-anatomy.spec.md:535` scope 限定
13
+ 段)— chrome header 內 avatar 用 raw `<Avatar size={24}>`,**不用 `<ItemAvatar>`**。
14
+
15
+ Consumers(2,需 sync):
16
+ 1. WorkspaceBrand demo(`_demo-helpers.tsx`)hardcode `<Avatar size={24}>` + comment cite token
17
+ 2. SidebarHeader 收合 padding 公式:
18
+ calc((var(--sidebar-width-icon) - var(--chrome-header-avatar-size)) / 2)
19
+
20
+ **Sync invariant**:Token 值 + WorkspaceBrand `size={24}` literal + AVATAR_SIZE.inline.md
21
+ (`item-anatomy.tsx:93`)三者必同 24。改 spec canonical 時 grep
22
+ `--chrome-header-avatar-size` + `chrome header avatar canonical` 雙向找 sync 點。
23
+ ───────────────────────────────────────────────────────── */
24
+
25
+ :root {
26
+ --chrome-header-avatar-size: 1.5rem; /* 24px */
27
+ }
@@ -0,0 +1,217 @@
1
+ /**
2
+ * @internal — DS-internal primitive module(2026-05-23 per `.claude/rules/ui-development.md` Public vs Internal canonical)。
3
+ * end-user app 直接 import 無 functioning UI;由 Tabs / ChipGroup 等 DS 元件 wrap 消費 hook + helper components。
4
+ */
5
+ // @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.
6
+ import * as React from 'react'
7
+ import { ChevronDown, ChevronLeft, ChevronRight } from 'lucide-react'
8
+ import { cn } from '@/lib/utils'
9
+ import { Button } from '@/design-system/components/Button/button'
10
+ import {
11
+ useScrollEdges,
12
+ useOverflowIndices,
13
+ } from '@/design-system/hooks/use-overflow-items'
14
+
15
+ /**
16
+ * Horizontal Overflow — canonical primitives + helpers
17
+ *
18
+ * 詳細設計原則與消費規則見 `horizontal-overflow.spec.md`。
19
+ *
20
+ * ── 核心規則 ──
21
+ * 所有 horizontal overflow 的 affordance 一律是 `<Button variant="text" size="sm" iconOnly>`。
22
+ * 無論內容是 Tab / Chip / Step / SegmentedControl item,overflow trigger 永遠同一套。
23
+ * 這是工具層,跟業務層(內容)解耦,不該跟內容爭視覺重量。
24
+ *
25
+ * ── 為什麼存在 ──
26
+ * 過去 Tabs 和 Chip 兩邊各自 copy-paste `ScrollArrow` / `buildFadeMask` / 常數,
27
+ * 導致 Chip menu trigger 漂移成 chip-shape(違反 mental model)。本 module 是
28
+ * single source of truth,消除複製帶來的漂移空間。
29
+ */
30
+
31
+ // ── Constants ─────────────────────────────────────────────────────────────
32
+
33
+ /** Fade mask 漸變寬度(px)*/
34
+ // code-quality-allow: dead-export — public constant — DS API surface,consumer 可引(即使當前 internal-only)
35
+ export const FADE_WIDTH = 16
36
+
37
+ /**
38
+ * Scroll arrow 預留的按鈕區寬度(px)。
39
+ * 值對齊 `field-height-sm` 在 lg density 下的最大值(32px),確保 arrow button
40
+ * 在任何 density 都能完整容納 Button text sm iconOnly。
41
+ */
42
+ export const ARROW_BUTTON_WIDTH = 32
43
+
44
+ /** 點一次 scroll arrow 滑動 80% 容器寬度 */
45
+ // code-quality-allow: dead-export — public constant — DS API surface,consumer 可引(即使當前 internal-only)
46
+ export const SCROLL_PAGE_RATIO = 0.8
47
+
48
+ // ── Helpers ───────────────────────────────────────────────────────────────
49
+
50
+ interface BuildFadeMaskArgs {
51
+ canScroll: boolean
52
+ atStart: boolean
53
+ atEnd: boolean
54
+ /**
55
+ * 預留給 scroll arrow button 的寬度(px)。
56
+ * - Scroll 模式:傳 `ARROW_BUTTON_WIDTH`,fade 會延伸到 arrow 底下,
57
+ * 避免「透明 button icon 跟 item 文字視覺打架」(Material 3 scrim 原理)
58
+ * - Menu 模式:傳 0,沒有 arrow,fade 直接從容器邊緣開始
59
+ */
60
+ reserveArrowWidth?: number
61
+ }
62
+
63
+ /**
64
+ * 計算 fade mask 的 `linear-gradient` 字串。
65
+ *
66
+ * 回傳 `undefined` 時代表「不需要 mask」(內容沒溢出),消費者該讓 `maskImage`
67
+ * 等於 undefined 讓 CSS 恢復正常渲染。
68
+ */
69
+ export function buildFadeMask({
70
+ canScroll,
71
+ atStart,
72
+ atEnd,
73
+ reserveArrowWidth = 0,
74
+ }: BuildFadeMaskArgs): string | undefined {
75
+ if (!canScroll) return undefined
76
+ const stops: string[] = []
77
+ if (!atStart) {
78
+ if (reserveArrowWidth > 0) {
79
+ stops.push('transparent 0')
80
+ stops.push(`transparent ${reserveArrowWidth}px`)
81
+ stops.push(`black ${reserveArrowWidth + FADE_WIDTH}px`)
82
+ } else {
83
+ stops.push('transparent 0')
84
+ stops.push(`black ${FADE_WIDTH}px`)
85
+ }
86
+ } else {
87
+ stops.push('black 0')
88
+ }
89
+ if (!atEnd) {
90
+ if (reserveArrowWidth > 0) {
91
+ stops.push(`black calc(100% - ${reserveArrowWidth + FADE_WIDTH}px)`)
92
+ stops.push(`transparent calc(100% - ${reserveArrowWidth}px)`)
93
+ stops.push('transparent 100%')
94
+ } else {
95
+ stops.push(`black calc(100% - ${FADE_WIDTH}px)`)
96
+ stops.push('transparent 100%')
97
+ }
98
+ } else {
99
+ stops.push('black 100%')
100
+ }
101
+ return `linear-gradient(to right, ${stops.join(', ')})`
102
+ }
103
+
104
+ /**
105
+ * Scroll by page helper。接收 scrollRef 回傳一個 `scrollByPage(direction)` 函式,
106
+ * 呼叫後以 smooth 動畫橫向滑動 `clientWidth × SCROLL_PAGE_RATIO`。
107
+ *
108
+ * 使用 useCallback 並以 scrollRef 為 dependency,確保消費者可以安全把回傳函式
109
+ * 傳給 `<OverflowScrollArrow onClick>`。
110
+ */
111
+ export function useScrollByPage<T extends HTMLElement>(
112
+ scrollRef: React.RefObject<T | null>,
113
+ ): (direction: 'left' | 'right') => void {
114
+ return React.useCallback(
115
+ (direction: 'left' | 'right') => {
116
+ const el = scrollRef.current
117
+ if (!el) return
118
+ el.scrollBy({
119
+ left: el.clientWidth * SCROLL_PAGE_RATIO * (direction === 'left' ? -1 : 1),
120
+ behavior: 'smooth',
121
+ })
122
+ },
123
+ [scrollRef],
124
+ )
125
+ }
126
+
127
+ // ── Primitives ────────────────────────────────────────────────────────────
128
+
129
+ export interface OverflowScrollArrowProps {
130
+ direction: 'left' | 'right'
131
+ onClick: () => void
132
+ /**
133
+ * 覆寫 aria-label(預設為「向左捲動」/「向右捲動」)。
134
+ * 一般情況不需要傳——預設繁中 label 對所有水平捲動情境都成立。
135
+ */
136
+ 'aria-label'?: string
137
+ }
138
+
139
+ /**
140
+ * Scroll arrow button — canonical horizontal overflow affordance。
141
+ *
142
+ * **絕對定位**在容器的 `left-0` / `right-0`,使用 `pointer-events-none` 外層 +
143
+ * `pointer-events-auto` 內層,讓 fade mask 下方仍可橫向滑動(arrow 只接受點
144
+ * 自身的 click)。
145
+ *
146
+ * Root 是 `<Button variant="text" size="sm" iconOnly>`——跟 Tabs / Chip /
147
+ * 未來所有消費者共用同一個按鈕視覺。
148
+ */
149
+ export const OverflowScrollArrow: React.FC<OverflowScrollArrowProps> = ({
150
+ direction,
151
+ onClick,
152
+ 'aria-label': ariaLabel,
153
+ }) => {
154
+ const defaultLabel = direction === 'left' ? '向左捲動' : '向右捲動' // i18n-allow: DS default; consumer override via aria-label prop
155
+ return (
156
+ <div
157
+ className={cn(
158
+ 'absolute top-0 bottom-0 flex items-center pointer-events-none z-10',
159
+ direction === 'left' ? 'left-0' : 'right-0',
160
+ )}
161
+ >
162
+ <div className="pointer-events-auto">
163
+ <Button
164
+ variant="text"
165
+ size="sm"
166
+ iconOnly
167
+ startIcon={direction === 'left' ? ChevronLeft : ChevronRight}
168
+ aria-label={ariaLabel ?? defaultLabel}
169
+ onClick={onClick}
170
+ />
171
+ </div>
172
+ </div>
173
+ )
174
+ }
175
+
176
+ export interface OverflowMenuTriggerButtonProps
177
+ extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
178
+ /**
179
+ * Accessible label。消費者應傳入有語境的 label,例如
180
+ * `"頁籤選單(共 5 個)"` 或 `"分類選單(共 8 個)"`。必填。
181
+ */
182
+ 'aria-label': string
183
+ }
184
+
185
+ /**
186
+ * Menu trigger button — canonical overflow menu affordance。
187
+ *
188
+ * Root 是 `<Button variant="text" size="sm" iconOnly startIcon={ChevronDown}>`。
189
+ * **forwardRef + props spread** 讓 Radix `<DropdownMenuTrigger asChild>` 可以
190
+ * 接管 onClick / aria-expanded / data-state 等 attributes。
191
+ *
192
+ * ── 為什麼不包 DropdownMenu ──
193
+ * Menu 的內容(items)取決於消費者的資料結構(Tab 用 DropdownMenuItem + selected,
194
+ * Chip 用 DropdownMenuCheckboxItem),所以只提供 trigger button,消費者自己
195
+ * 把 `<DropdownMenu> <DropdownMenuTrigger asChild> <OverflowMenuTriggerButton /> ... </DropdownMenu>`
196
+ * 串起來。
197
+ */
198
+ export const OverflowMenuTriggerButton = React.forwardRef<
199
+ HTMLButtonElement,
200
+ OverflowMenuTriggerButtonProps
201
+ >(({ 'aria-label': ariaLabel, ...props }, ref) => (
202
+ <Button
203
+ ref={ref}
204
+ variant="text"
205
+ size="sm"
206
+ iconOnly
207
+ startIcon={ChevronDown}
208
+ aria-label={ariaLabel}
209
+ {...props}
210
+ />
211
+ ))
212
+ OverflowMenuTriggerButton.displayName = 'OverflowMenuTriggerButton'
213
+
214
+ // ── Hook re-exports ──────────────────────────────────────────────────────
215
+ // 讓消費者只從本 module import 所有 overflow 相關的 API。
216
+
217
+ export { useScrollEdges, useOverflowIndices }
@@ -0,0 +1,191 @@
1
+ import * as React from 'react'
2
+ import { cn } from '@/lib/utils'
3
+
4
+ /**
5
+ * @internal — DS-internal primitive(2026-05-23 per `.claude/rules/ui-development.md` Public vs Internal canonical)。
6
+ * end-user app 直接 import 無 functioning UI;由 Dialog / Sheet / Popover / HoverCard / Coachmark 等 DS overlay 元件 wrap 消費。
7
+ *
8
+ * Overlay Surface primitives — Dialog / Popover / Sheet 共用結構化 sub-components。
9
+ *
10
+ * 抽象這層避免各自硬寫 padding / border 導致漂移。有特殊行為(Dialog Close 按鈕 /
11
+ * viewport-fill 高度)由 consumer 額外包裝,不污染 primitive。
12
+ *
13
+ * ── Header / Footer 高度 canonical(2026-04-22 v3 校準,user intent 精確實作)──
14
+ * **Padding-based sizing**:`py-[var(--layout-space-tight)]`,高度 = max(child) + 2×tight
15
+ * 不用 fixed `min-h`(先前誤用 min-h-chrome-header-height 會讓 bounded button 被鎖死在 48
16
+ * slot 失去自然高度,違反 user 意圖)。
17
+ *
18
+ * 對齊 `--chrome-header-height`(48/56)的**條件**:header 只放 unbounded 控件(close X /
19
+ * text variant button,**native sm + v5 unbounded trick layout 佔位 24**):
20
+ * header = 24 + 2×tight = 48 md / 56 lg ✓。
21
+ *
22
+ * 若 header 塞 **bounded 控件**(primary / tertiary with bg/border):header 自然長高
23
+ * (sm 28 + 2×12 = 52 md),因 bounded 按鈕有視覺邊界,padding 不會顯得過大 — 這是預期的。
24
+ *
25
+ * ── Unbounded controls 在 header canonical(v5 trick,2026-04-22)──
26
+ * Dismiss X(always unbounded)+ text variant header action → **`size="sm"` native**
27
+ * + SurfaceHeader CSS 自動套負 my trick(對 `[data-unbounded]`),layout 佔位縮回 24
28
+ * (xs 等同)。Rationale:button native size 跟 touch target 保留 sm(a11y 最小 24+ hit
29
+ * target,視覺 render 仍 28/32),layout 佔位精確匹配 chrome-header-height 幾何。詳
30
+ * `overlay-surface.spec.md`「Chrome dismiss size canonical」。
31
+ *
32
+ * **Notification banner family**(Notice / Alert / Toast,fixed `px-4 py-3` variant,
33
+ * 無 padding-based header)→ dismiss 用 `size="xs"` explicit(24 固定,無 trick)。
34
+ *
35
+ * ── Token 規則 ──
36
+ * horizontal padding: `px-[var(--layout-space-loose)]`
37
+ * vertical padding: `py-[var(--layout-space-tight)]`
38
+ * 分隔線: `border-{b|t} border-divider`
39
+ *
40
+ * ── Body ──
41
+ * Body padding-based(content area),`px-[var(--layout-space-loose)] py-[var(--layout-space-tight)]`。
42
+ * Dialog / Sheet body 走 ScrollArea + chrome padding(`px-loose pt-tight pb-bottom`)。
43
+ * List-as-region 場景(menu / Cmd+K)由 consumer 用 className override 撤 chrome padding +
44
+ * 自管 list outer wrapper(詳 overlay-surface.spec.md「List-as-region in overlay body」)。
45
+ */
46
+
47
+ // Chrome-slot layout trick(2026-04-22 v5,2026-05-04 重思 parameterize):
48
+ // **所有 unbounded control**(Button with `data-unbounded="true"` — Button 自動在 variant="text" 或 dismiss
49
+ // 時標記)的 **native size 不變**(sm: 28 md / 32 lg),但 **layout 佔位** via 負 `my` 縮成 `--chrome-slot-h`。
50
+ //
51
+ // **Slot height = header title 的 line-height**(讓 button 不 dominate,title 自然撐 header)
52
+ // - Default `var(--field-height-xs)` = 24,匹配 Dialog/Sheet text-body-lg (16 × 1.5 = 24)
53
+ // - Popover/Coachmark override `--chrome-slot-h: 1.25rem` (20),匹配 text-body (14 × 1.5 ≈ 21,floor 20)
54
+ //
55
+ // Header 永遠 padding-based(無 min-h),但因 slot ≤ title line-height,header 高度由 title 主導:
56
+ // - Dialog: max(24 title, 24 slot) + py-tight(12*2)= 48 ✓ chrome-header-height
57
+ // - Popover: max(21 title, 20 slot) + py-tight(12*2)= 45 ✓ 自然輕量
58
+ // Q10 穩定性:title-only / title+button / refresh in/out 全 case header 高度 = title + py(slot 不 dominate)
59
+ //
60
+ // 負 my 公式:(slot - native) / 2,density-aware:
61
+ // Dialog md: (24 - 28) / 2 = -2px; lg: (24 - 32) / 2 = -4px
62
+ // Popover md: (20 - 28) / 2 = -4px
63
+ const CHROME_UNBOUNDED_SLOT = '[&_[data-unbounded]]:my-[calc((var(--chrome-slot-h,var(--field-height-xs))-var(--field-height-sm))/2)]'
64
+
65
+ export interface SurfaceHeaderProps
66
+ extends React.HTMLAttributes<HTMLDivElement> {
67
+ /**
68
+ * 是否內含 Tabs。
69
+ * true(無 tabsSlot)→ 移除自身 border-b。
70
+ * 若提供 tabsSlot,自動 column mode + auto suppress border(不需手動傳 withTabs=true)。
71
+ * 對齊 patterns/header-canonical/header-canonical.spec.md W1
72
+ * 「Header semantic owner / TabsList paint owner in withTabs state」。
73
+ */
74
+ withTabs?: boolean
75
+ /**
76
+ * Tabs row slot(2026-05-18 加 per header-canonical.spec.md W2/W4 真實能用 + user-mandated fix)。
77
+ * 提供時 SurfaceHeader 自動 column 結構:
78
+ * row 1 = children(title + actions/dismiss,px-loose py-tight)
79
+ * row 2 = tabsSlot 包在 `<div px-loose border-b border-divider>`
80
+ * ↑ wrapper 提供 W2 padding inheritance + 全寬 paint(W1 視覺一條線)
81
+ *
82
+ * Consumer 傳:`tabsSlot={<TabsList>...</TabsList>}`,TabsContent 仍放 DialogBody 內。
83
+ * `<Tabs>` root 必須 wrap 整 DialogContent(Radix TabsList ↔ TabsContent 同 root 連動)。
84
+ *
85
+ * 提供 tabsSlot 自動 withTabs=true,不需另傳 prop。
86
+ */
87
+ tabsSlot?: React.ReactNode
88
+ }
89
+
90
+ export const SurfaceHeader = React.forwardRef<
91
+ HTMLDivElement,
92
+ SurfaceHeaderProps
93
+ >(({ className, withTabs, tabsSlot, children, ...props }, ref) => {
94
+ // tabsSlot 提供 → 自動 withTabs(consumer 不需手動兩個 prop)
95
+ const hasTabs = tabsSlot != null || withTabs === true
96
+
97
+ // Column mode(tabsSlot 提供時)— 對應 header-canonical.spec.md W2 + W4
98
+ if (tabsSlot != null) {
99
+ return (
100
+ <div
101
+ ref={ref}
102
+ className={cn('flex flex-col shrink-0', className)}
103
+ {...props}
104
+ >
105
+ {/* Row 1:header content row(原 single-row behavior 不變,但 border-b 撤掉,row 2 wrapper 接管 paint)*/}
106
+ <div
107
+ className={cn(
108
+ 'flex items-center gap-2',
109
+ 'px-[var(--layout-space-loose)] py-[var(--layout-space-tight)]',
110
+ CHROME_UNBOUNDED_SLOT,
111
+ )}
112
+ >
113
+ {children}
114
+ </div>
115
+ {/* Row 2:tabsSlot wrapper — TabsList 全 dialog 寬 + 內 px-loose padding inset triggers
116
+ 2026-05-18 v3 fix(user verbatim approval「你確定這樣是世界級的設計且符合我們一致的設計
117
+ 語言和 SSOT...就這樣做」):
118
+ - v1: wrapper border + TabsList border = 雙線(W1 違反)
119
+ - v2: wrapper px-loose + TabsList w-full inside = border 只跨 dialog - 2×px-loose
120
+ (不到 dialog 邊 user 抓「分隔線寬度應該要填滿整個 dialog」)
121
+ - v3(本):wrapper 不 inset,TabsList 自己 px-loose 內 padding inset triggers
122
+ → TabsList border-b 延展全 dialog 寬,triggers 對齊 header content
123
+ 對齊既有 `tabs.spec.md:199`「TabsList 自身 border-b border-border 延展全 header 寬,因
124
+ TabsList wrapper 是 block-level full-width」+ `:187-189`「selected 底線從 TabsList
125
+ gray border 位置長出來」+ GitHub Primer UnderlineNav / Ant Design line type / Mantine
126
+ default 共識(全派 TabsList 自畫 full-width underline)。*/}
127
+ <div className="[&>[role=tablist]]:w-full [&>[role=tablist]]:px-[var(--layout-space-loose)]">
128
+ {tabsSlot}
129
+ </div>
130
+ </div>
131
+ )
132
+ }
133
+
134
+ // Padding-based(預設) — Dialog/Sheet 用 body-lg title (16/24),自然撐 max(24 title, 24 button slot) = 24
135
+ // → header = 24 + py-tight 12×2 = 48 chrome-header-height ✓ 穩定無需 min-h
136
+ // Popover 等輕量 chrome 走 PopoverHeader override(min-h-10 + py-2 = 40,內 24 匹配 button slot)
137
+ //
138
+ // withTabs=true(無 tabsSlot,backward compat):移除 border-b,consumer 自畫
139
+ return (
140
+ <div
141
+ ref={ref}
142
+ className={cn(
143
+ 'flex items-center gap-2 shrink-0',
144
+ !hasTabs && 'border-b border-divider',
145
+ 'px-[var(--layout-space-loose)] py-[var(--layout-space-tight)]',
146
+ CHROME_UNBOUNDED_SLOT,
147
+ className,
148
+ )}
149
+ {...props}
150
+ >
151
+ {children}
152
+ </div>
153
+ )
154
+ })
155
+ SurfaceHeader.displayName = 'SurfaceHeader'
156
+
157
+ export const SurfaceBody = React.forwardRef<
158
+ HTMLDivElement,
159
+ React.HTMLAttributes<HTMLDivElement>
160
+ >(({ className, ...props }, ref) => (
161
+ // 2026-05-04 viewport-aware scroll canonical:
162
+ // parent(PopoverContent / HoverCardContent / Dialog / Sheet)是 flex flex-col + max-h + overflow-hidden
163
+ // header / footer shrink-0;Body flex-1 min-h-0 overflow-y-auto → 視窗太小時 body 內 scroll
164
+ // 非 flex-col parent 內 flex-1/min-h-0 no-op,backward compat
165
+ <div
166
+ ref={ref}
167
+ className={cn(
168
+ 'flex-1 min-h-0 overflow-y-auto',
169
+ 'px-[var(--layout-space-loose)] py-[var(--layout-space-tight)]',
170
+ className,
171
+ )}
172
+ {...props}
173
+ />
174
+ ))
175
+ SurfaceBody.displayName = 'SurfaceBody'
176
+
177
+ export const SurfaceFooter = React.forwardRef<
178
+ HTMLDivElement,
179
+ React.HTMLAttributes<HTMLDivElement>
180
+ >(({ className, ...props }, ref) => (
181
+ <div
182
+ ref={ref}
183
+ className={cn(
184
+ 'flex items-center justify-end gap-2 shrink-0 border-t border-divider',
185
+ 'px-[var(--layout-space-loose)] py-[var(--layout-space-tight)]',
186
+ className,
187
+ )}
188
+ {...props}
189
+ />
190
+ ))
191
+ SurfaceFooter.displayName = 'SurfaceFooter'