@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 @@
1
+ {"version":3,"file":"select-menu.d.ts","sourceRoot":"","sources":["../../../src/components/SelectMenu/select-menu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAA;AAa1E;;;;;;;;;;;;;;GAcG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;CACd;AAED,KAAK,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAIjC,MAAM,WAAW,eAAe;IAC9B,WAAW;IACX,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,gCAAgC;IAChC,MAAM,CAAC,EAAE,qBAAqB,EAAE,CAAA;IAEhC,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAA;IAChC,mBAAmB;IACnB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,CAAA;IAElD,WAAW;IACX,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,YAAY;IACZ,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa;IACb,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAEvC,oBAAoB;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,sBAAsB;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,YAAY;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB,SAAS;IACT,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,WAAW;IACX,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,CAAA;IACvB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,iBAAiB;IACjB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,sGAAsG;IACtG,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,yBAAyB;IACzB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAEtC,2CAA2C;IAC3C,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAA;IAC3D,4EAA4E;IAC5E,eAAe,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IAEpC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAMD,QAAA,MAAM,UAAU,qFA0Rd,CAAA;AAMF,eAAO,MAAM,cAAc;;;;;;;;;;;CAejB,CAAA;AAEV,OAAO,EAAE,UAAU,EAAE,CAAA"}
@@ -0,0 +1,239 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { Search, Plus } from "lucide-react";
4
+ import { cn } from "../../lib/utils.js";
5
+ import { Popover, PopoverTrigger, PopoverContent } from "../Popover/popover.js";
6
+ import { Command, CommandList, CommandEmpty, CommandSeparator, CommandGroup, CommandItem } from "../Command/command.js";
7
+ import { Command as Command$1 } from "cmdk";
8
+ import { MenuItem, MenuFooter } from "../Menu/menu-item.js";
9
+ import { Empty } from "../Empty/empty.js";
10
+ import { CircularProgress } from "../CircularProgress/circular-progress.js";
11
+ import { OVERLAY_SIDE_OFFSET } from "../../tokens/elevation/overlay-geometry.js";
12
+ import { getMenuListMinHeight } from "../Field/field-types.js";
13
+ import { RowSizeProvider, ICON_SIZE } from "../../patterns/element-anatomy/item-anatomy.js";
14
+ import { clearSelection, applySelectAll } from "../../lib/multi-select-ordering.js";
15
+ const SelectMenu = React.forwardRef(function SelectMenu2({
16
+ options,
17
+ groups,
18
+ value,
19
+ onValueChange,
20
+ multiple = false,
21
+ searchable = false,
22
+ creatable = false,
23
+ onCreate,
24
+ createLabel = (q) => `直接使用「${q}」`,
25
+ children,
26
+ searchPlaceholder = "搜尋…",
27
+ // i18n-allow: DS default; consumer override via searchPlaceholder prop
28
+ emptyText = "沒有符合的選項",
29
+ // i18n-allow: DS default; consumer override via emptyText prop
30
+ loading = false,
31
+ size = "md",
32
+ align = "start",
33
+ minRows = 3,
34
+ minWidth,
35
+ open: controlledOpen,
36
+ defaultOpen,
37
+ onOpenChange: controlledOnOpenChange,
38
+ renderLabel,
39
+ onOpenAutoFocus,
40
+ contentId,
41
+ className
42
+ }, _ref) {
43
+ const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false);
44
+ const open = controlledOpen ?? internalOpen;
45
+ const setOpen = controlledOnOpenChange ?? setInternalOpen;
46
+ const [search, setSearch] = React.useState("");
47
+ const selectedValues = React.useMemo(() => {
48
+ if (value == null) return [];
49
+ return Array.isArray(value) ? value : [value];
50
+ }, [value]);
51
+ const isSelected = React.useCallback(
52
+ (v) => selectedValues.includes(v),
53
+ [selectedValues]
54
+ );
55
+ const handleSelect = React.useCallback(
56
+ (optionValue) => {
57
+ if (multiple) {
58
+ const next = isSelected(optionValue) ? selectedValues.filter((v) => v !== optionValue) : [...selectedValues, optionValue];
59
+ onValueChange == null ? void 0 : onValueChange(next);
60
+ } else {
61
+ onValueChange == null ? void 0 : onValueChange(optionValue);
62
+ setOpen(false);
63
+ }
64
+ },
65
+ [multiple, selectedValues, isSelected, onValueChange, setOpen]
66
+ );
67
+ const selectableOptions = React.useMemo(
68
+ () => options.filter((o) => !o.disabled),
69
+ [options]
70
+ );
71
+ const allState = React.useMemo(() => {
72
+ if (!multiple) return false;
73
+ const count = selectableOptions.filter((o) => isSelected(o.value)).length;
74
+ if (count === 0) return false;
75
+ if (count === selectableOptions.length) return true;
76
+ return "indeterminate";
77
+ }, [multiple, selectableOptions, isSelected]);
78
+ const handleSelectAll = React.useCallback(() => {
79
+ if (!multiple) return;
80
+ if (allState === true) {
81
+ onValueChange == null ? void 0 : onValueChange(clearSelection());
82
+ } else {
83
+ onValueChange == null ? void 0 : onValueChange(applySelectAll(selectedValues, selectableOptions.map((o) => o.value)));
84
+ }
85
+ }, [multiple, allState, selectableOptions, selectedValues, onValueChange]);
86
+ const showCreate = React.useMemo(() => {
87
+ if (!creatable || !search.trim()) return false;
88
+ return !options.some(
89
+ (o) => o.label.toLowerCase() === search.trim().toLowerCase()
90
+ );
91
+ }, [creatable, search, options]);
92
+ const groupedOptions = React.useMemo(() => {
93
+ if (!(groups == null ? void 0 : groups.length)) return [{ key: "__default", label: "", options }];
94
+ const grouped = groups.map((g) => ({
95
+ ...g,
96
+ options: options.filter((o) => o.group === g.key)
97
+ }));
98
+ const ungrouped = options.filter((o) => !o.group);
99
+ if (ungrouped.length) {
100
+ grouped.unshift({ key: "__default", label: "", options: ungrouped });
101
+ }
102
+ return grouped;
103
+ }, [groups, options]);
104
+ React.useEffect(() => {
105
+ if (!open) setSearch("");
106
+ }, [open]);
107
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
108
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children }),
109
+ /* @__PURE__ */ jsx(RowSizeProvider, { value: size, children: /* @__PURE__ */ jsx(
110
+ PopoverContent,
111
+ {
112
+ id: contentId,
113
+ className: cn(
114
+ "p-0 w-auto rounded-lg border border-border bg-surface-raised overflow-hidden",
115
+ className
116
+ ),
117
+ style: {
118
+ boxShadow: "var(--elevation-200)",
119
+ minWidth: minWidth ?? "max(var(--radix-popover-trigger-width), 15rem)"
120
+ },
121
+ align,
122
+ sideOffset: OVERLAY_SIDE_OFFSET,
123
+ onOpenAutoFocus,
124
+ onInteractOutside: (e) => {
125
+ const target = e.detail.originalEvent.target;
126
+ if (target == null ? void 0 : target.closest("[data-radix-popper-content-wrapper]")) {
127
+ e.preventDefault();
128
+ }
129
+ },
130
+ children: /* @__PURE__ */ jsxs(Command, { shouldFilter: searchable, className: "bg-transparent", children: [
131
+ searchable && /* @__PURE__ */ jsxs("div", { className: cn(
132
+ "flex items-center gap-2 px-3 py-1 border-b border-divider",
133
+ size === "lg" ? "min-h-[calc(var(--field-height-lg)+8px)]" : size === "sm" ? "min-h-[calc(var(--field-height-sm)+8px)]" : "min-h-[calc(var(--field-height-md)+8px)]"
134
+ ), children: [
135
+ /* @__PURE__ */ jsx(Search, { size: ICON_SIZE[size], className: "shrink-0 text-fg-muted", "aria-hidden": true }),
136
+ /* @__PURE__ */ jsx(
137
+ Command$1.Input,
138
+ {
139
+ placeholder: searchPlaceholder,
140
+ value: search,
141
+ onValueChange: setSearch,
142
+ className: cn(
143
+ "flex w-full bg-transparent outline-none placeholder:text-fg-muted",
144
+ // M24 disabled state precedence:disabled 時 placeholder 切 fg-disabled(audit dim 34)
145
+ "disabled:placeholder:text-fg-disabled disabled:text-fg-disabled disabled:cursor-not-allowed",
146
+ size === "lg" ? "text-body-lg leading-compact" : "text-body leading-compact"
147
+ )
148
+ }
149
+ )
150
+ ] }),
151
+ /* @__PURE__ */ jsxs(CommandList, { className: "relative", children: [
152
+ /* @__PURE__ */ jsx(
153
+ CommandEmpty,
154
+ {
155
+ className: "flex items-center justify-center",
156
+ style: { minHeight: getMenuListMinHeight(size, minRows) },
157
+ children: loading ? /* @__PURE__ */ jsx(Empty, { icon: /* @__PURE__ */ jsx(CircularProgress, { size: 48 }), className: "py-6" }) : /* @__PURE__ */ jsx(Empty, { description: emptyText, className: "py-6" })
158
+ }
159
+ ),
160
+ groupedOptions.map((group, gi) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
161
+ gi > 0 && /* @__PURE__ */ jsx(CommandSeparator, {}),
162
+ /* @__PURE__ */ jsxs(CommandGroup, { className: "p-0 py-2", children: [
163
+ group.label && /* @__PURE__ */ jsx(MenuItem, { size, header: true, children: group.label }),
164
+ group.options.map((opt) => /* @__PURE__ */ jsx(
165
+ CommandItem,
166
+ {
167
+ value: opt.label,
168
+ keywords: opt.description ? [opt.description] : void 0,
169
+ disabled: opt.disabled,
170
+ onSelect: () => handleSelect(opt.value),
171
+ className: "p-0 rounded-none data-[selected=true]:bg-transparent",
172
+ children: /* @__PURE__ */ jsx(
173
+ MenuItem,
174
+ {
175
+ size,
176
+ startIcon: opt.icon,
177
+ avatar: opt.avatar,
178
+ description: opt.description,
179
+ checkbox: multiple,
180
+ checked: isSelected(opt.value),
181
+ selected: !multiple && isSelected(opt.value),
182
+ disabled: opt.disabled,
183
+ children: renderLabel ? renderLabel(opt) : opt.label
184
+ }
185
+ )
186
+ },
187
+ opt.value
188
+ ))
189
+ ] })
190
+ ] }, group.key)),
191
+ showCreate && /* @__PURE__ */ jsxs(Fragment, { children: [
192
+ /* @__PURE__ */ jsx(CommandSeparator, {}),
193
+ /* @__PURE__ */ jsx(CommandGroup, { className: "p-0 py-2", children: /* @__PURE__ */ jsx(
194
+ CommandItem,
195
+ {
196
+ value: search,
197
+ onSelect: () => {
198
+ onCreate == null ? void 0 : onCreate(search.trim());
199
+ setSearch("");
200
+ },
201
+ className: "p-0 rounded-none data-[selected=true]:bg-transparent",
202
+ children: /* @__PURE__ */ jsx(MenuItem, { size, startIcon: Plus, children: createLabel(search.trim()) })
203
+ }
204
+ ) })
205
+ ] })
206
+ ] }),
207
+ multiple && selectableOptions.length > 0 && !search && /* @__PURE__ */ jsx(MenuFooter, { children: /* @__PURE__ */ jsx(
208
+ MenuItem,
209
+ {
210
+ size,
211
+ checkbox: true,
212
+ checked: allState,
213
+ onClick: handleSelectAll,
214
+ children: "全部"
215
+ }
216
+ ) })
217
+ ] })
218
+ }
219
+ ) })
220
+ ] });
221
+ });
222
+ SelectMenu.displayName = "SelectMenu";
223
+ const selectMenuMeta = {
224
+ component: "SelectMenu",
225
+ family: 4,
226
+ variants: {},
227
+ sizes: {},
228
+ states: ["default", "hover", "active", "focus-visible", "disabled"],
229
+ tokens: {
230
+ bg: ["bg-surface-raised", "bg-transparent"],
231
+ fg: ["text-fg-muted"],
232
+ ring: []
233
+ }
234
+ };
235
+ export {
236
+ SelectMenu,
237
+ selectMenuMeta
238
+ };
239
+ //# sourceMappingURL=select-menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-menu.js","sources":["../../../src/components/SelectMenu/select-menu.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 { Plus, Search } from 'lucide-react'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport type { AvatarData } from '@/design-system/components/Avatar/avatar'\nimport { Popover, PopoverContent, PopoverTrigger } from '@/design-system/components/Popover/popover'\nimport { Command, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator } from '@/design-system/components/Command/command'\nimport { Command as CommandPrimitive } from 'cmdk'\nimport { MenuItem, MenuFooter } from '@/design-system/components/Menu/menu-item'\nimport { Empty } from '@/design-system/components/Empty/empty'\nimport { CircularProgress } from '@/design-system/components/CircularProgress/circular-progress'\nimport { OVERLAY_SIDE_OFFSET } from '@/design-system/tokens/elevation/overlay-geometry'\nimport { getMenuListMinHeight } from '@/design-system/components/Field/field-types'\nimport { RowSizeProvider } from '@/design-system/patterns/element-anatomy/item-anatomy'\nimport { applySelectAll, clearSelection } from '@/design-system/lib/multi-select-ordering'\nimport { ICON_SIZE } from '@/design-system/tokens/uiSize/icon-size'\n\n/**\n * SelectMenu — Popover + Command 組成的完整下拉選單\n *\n * ── 功能 ──\n * 單選 / 多選、搜尋過濾、分組、可建立新選項(creatable)\n * 多選有 footer「全部」checkbox\n *\n * ── 架構 ──\n * Popover(浮動容器)\n * └── Command(cmdk,搜尋 + 鍵盤導覽)\n * ├── CommandInput(搜尋框)\n * ├── CommandList(選項列表)\n * │ └── CommandGroup → MenuItem\n * └── Footer(多選全選)\n */\n\n// ── Types ──\n\nexport interface SelectMenuOption {\n value: string\n label: string\n description?: string\n icon?: LucideIcon\n avatar?: AvatarData\n disabled?: boolean\n group?: string\n}\n\nexport interface SelectMenuGroupConfig {\n key: string\n label: string\n}\n\ntype SizeKey = 'sm' | 'md' | 'lg'\n\n// ── Component ──\n\nexport interface SelectMenuProps {\n /** 選項列表 */\n options: SelectMenuOption[]\n /** 群組定義(key 對應 option.group) */\n groups?: SelectMenuGroupConfig[]\n\n /** 當前值(單選 string,多選 string[]) */\n value?: string | string[] | null\n /** 值變更 callback */\n onValueChange?: (value: string | string[]) => void\n\n /** 多選模式 */\n multiple?: boolean\n /** 顯示搜尋框 */\n searchable?: boolean\n /** 可建立新選項 */\n creatable?: boolean\n /** 建立新選項 callback */\n onCreate?: (value: string) => void\n /** creatable 的 label 格式,預設 '直接使用「{query}」' */\n createLabel?: (query: string) => string\n\n /** 觸發元件(asChild) */\n children: React.ReactNode\n /** 搜尋框 placeholder */\n searchPlaceholder?: string\n /** 空選項提示 */\n emptyText?: string\n /** Loading 狀態(2026-05-15 audit B fix per user verbatim「dropdown 隨時可開,讀取在 panel 中間 CircularProgress」)\n * true → render `<Empty icon={<CircularProgress size={48}/>} description={loadingText} />` 取代 options;\n * trigger 不變,user 隨時可開 dropdown。對齊 MUI Autocomplete `loadingText` dropdown-body + Ant Select\n * loading idiom + DS 既有 `empty.spec.md:182` 「全頁 loading = Empty + CircularProgress compose」SSOT。\n */\n loading?: boolean\n\n /** 尺寸 */\n size?: SizeKey\n /** 對齊方式 */\n align?: 'start' | 'end'\n /** 列表最少顯示幾行選項高度(預設 3),影響空狀態最小高度 */\n minRows?: number\n /** 最小寬度(px),預設跟隨觸發元件 */\n minWidth?: number\n\n /** 受控 open 狀態 */\n open?: boolean\n /** 預設打開(uncontrolled initial state)— 2026-05-15 audit Dim 26 V1 fix per user verbatim「A:1」approval */\n defaultOpen?: boolean\n /** open 狀態變更 callback */\n onOpenChange?: (open: boolean) => void\n\n /** 自訂選項 label 渲染(預設渲染 option.label 純文字) */\n renderLabel?: (option: SelectMenuOption) => React.ReactNode\n /** 攔截 PopoverContent 的 onOpenAutoFocus(如 Select searchable 需阻止 focus 搶走) */\n onOpenAutoFocus?: (e: Event) => void\n\n /**\n * Popover 內容容器的 DOM id。Combobox / 自定 trigger 用 `aria-controls` 指向此 id 時,\n * 需傳入相同 id 讓 AT 能找到對應的 listbox。\n */\n contentId?: string\n\n className?: string\n}\n\n// shadcn canonical:forwardRef + displayName 統一。SelectMenu 是 Popover + Command\n// composite,自身無 DOM host(trigger 由 consumer 以 asChild children 提供),ref 簽名\n// 保留但不附著(consumer 想取 trigger DOM 直接在 children 上自己 ref)。className 合併到\n// PopoverContent(contextually 最接近 user-facing surface)。\nconst SelectMenu = React.forwardRef<HTMLElement, SelectMenuProps>(function SelectMenu({\n options,\n groups,\n value,\n onValueChange,\n multiple = false,\n searchable = false,\n creatable = false,\n onCreate,\n createLabel = (q) => `直接使用「${q}」`,\n children,\n searchPlaceholder = '搜尋…', // i18n-allow: DS default; consumer override via searchPlaceholder prop\n emptyText = '沒有符合的選項', // i18n-allow: DS default; consumer override via emptyText prop\n loading = false,\n size = 'md',\n align = 'start',\n minRows = 3,\n minWidth,\n open: controlledOpen,\n defaultOpen,\n onOpenChange: controlledOnOpenChange,\n renderLabel,\n onOpenAutoFocus,\n contentId,\n className,\n}, _ref) {\n // ── State ──\n const [internalOpen, setInternalOpen] = React.useState(defaultOpen ?? false)\n const open = controlledOpen ?? internalOpen\n const setOpen = controlledOnOpenChange ?? setInternalOpen\n const [search, setSearch] = React.useState('')\n\n // ── Value helpers ──\n const selectedValues = React.useMemo<string[]>(() => {\n if (value == null) return []\n return Array.isArray(value) ? value : [value]\n }, [value])\n\n const isSelected = React.useCallback(\n (v: string) => selectedValues.includes(v),\n [selectedValues]\n )\n\n const handleSelect = React.useCallback(\n (optionValue: string) => {\n if (multiple) {\n const next = isSelected(optionValue)\n ? selectedValues.filter((v) => v !== optionValue)\n : [...selectedValues, optionValue]\n onValueChange?.(next)\n } else {\n onValueChange?.(optionValue)\n setOpen(false)\n }\n },\n [multiple, selectedValues, isSelected, onValueChange, setOpen]\n )\n\n // ── Multi-select: select all ──\n const selectableOptions = React.useMemo(\n () => options.filter((o) => !o.disabled),\n [options]\n )\n\n const allState: boolean | 'indeterminate' = React.useMemo(() => {\n if (!multiple) return false\n const count = selectableOptions.filter((o) => isSelected(o.value)).length\n if (count === 0) return false\n if (count === selectableOptions.length) return true\n return 'indeterminate'\n }, [multiple, selectableOptions, isSelected])\n\n // 2026-05-16 SSOT canonical fix(Claude+Codex M31 Round 4 共識 + user verbatim「就照你們\n // 的共識做到完美確保有 SSOT」):\n //\n // 原 fully-replace `selectableOptions.map(v)` = source order reset,但**Ant Design 跨元件 grep\n // 證據顯示 source-reset 沒 Ant precedent**(Transfer + Table rowSelection 都是 preserve+append)。\n // 改 `applySelectAll(selectedValues, all)` SSOT primitive 對齊 Ant Transfer canonical:\n // `Array.from(new Set([...prevKeys, ...keys]))` — preserve existing + append unselected。\n //\n // SSOT in `@/design-system/lib/multi-select-ordering` — 未來新 multi-select with Select All\n // footer 必 consume 此 primitive(hook `check_select_all_canonical.sh` 機械強制),\n // 不再各自 reimplement → 防 ordering policy drift。\n const handleSelectAll = React.useCallback(() => {\n if (!multiple) return\n if (allState === true) {\n onValueChange?.(clearSelection())\n } else {\n onValueChange?.(applySelectAll(selectedValues, selectableOptions.map((o) => o.value)))\n }\n }, [multiple, allState, selectableOptions, selectedValues, onValueChange])\n\n // ── Creatable ──\n const showCreate = React.useMemo(() => {\n if (!creatable || !search.trim()) return false\n return !options.some(\n (o) => o.label.toLowerCase() === search.trim().toLowerCase()\n )\n }, [creatable, search, options])\n\n // ── Grouping ──\n const groupedOptions = React.useMemo(() => {\n if (!groups?.length) return [{ key: '__default', label: '', options }]\n const grouped = groups.map((g) => ({\n ...g,\n options: options.filter((o) => o.group === g.key),\n }))\n const ungrouped = options.filter((o) => !o.group)\n if (ungrouped.length) {\n grouped.unshift({ key: '__default', label: '', options: ungrouped })\n }\n return grouped\n }, [groups, options])\n\n // ── Reset search on close ──\n React.useEffect(() => {\n if (!open) setSearch('')\n }, [open])\n\n // RowSizeProvider 讓 PopoverContent 子樹內任何 <ItemIcon> / <ItemAvatar> /\n // <ItemInlineAction> 都自動讀到對的 size,跟 SidebarProvider / TreeView 同一條規則。\n // (注:Popover 透過 Portal 渲染,context 仍然會跨 portal 傳遞——React context 是 tree-based\n // 不是 DOM-based,Portal 不影響 context propagation)\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <RowSizeProvider value={size}>\n <PopoverContent\n id={contentId}\n // w-auto override PopoverContent default w-72(rich-popover canonical)— SelectMenu 走「跟 trigger 同寬」\n // canonical(spec L72)。minWidth = max(trigger-width, 240px sensible-min)— 對齊 shadcn / Material / Ant\n // select dropdown 共識(2026-05-04 D1 verify SelectMenu spec implementation)。\n className={cn(\n 'p-0 w-auto rounded-lg border border-border bg-surface-raised overflow-hidden',\n className\n )}\n style={{\n boxShadow: 'var(--elevation-200)',\n minWidth: minWidth ?? 'max(var(--radix-popover-trigger-width), 15rem)',\n }}\n align={align}\n sideOffset={OVERLAY_SIDE_OFFSET}\n onOpenAutoFocus={onOpenAutoFocus}\n // **2026-05-07 v15.16 nested portal fix**:Tag dismiss inside trigger\n // 區的 OverflowIndicator HoverCard popup(獨立 Radix portal,DOM 不在\n // PopoverContent 內)— Radix DismissableLayer document-level outside\n // detection 跨 portal 視為「outside」→ SelectMenu 被誤關閉。\n // 攔 `onPointerDownOutside`,檢查 click target 是否在另一個 Radix portal\n // 內,是 → preventDefault 取消 close。對齊 Ant Design Select multiSelect\n // tagRender 行為(連續移除不關 dropdown)。\n // SSOT propagation:fix 在 SelectMenu level → Combobox / 其他 SelectMenu\n // consumer 自動受益。\n // **2026-05-07 v15.16 nested portal fix**:Tag dismiss inside trigger 區的\n // OverflowIndicator HoverCard popup(獨立 Radix portal,DOM 不在 SelectMenu\n // PopoverContent 內)— Radix DismissableLayer document-level pointerdown +\n // focusin 偵測「outside」→ SelectMenu 被誤關閉。\n // 攔 `onInteractOutside`(統一 pointerdown + focusin),檢查 click target 是否\n // 在另一個 Radix portal wrapper(`[data-radix-popper-content-wrapper]`),\n // 是 → preventDefault 取消 close。對齊 Ant Design Select multiSelect tagRender\n // 行為(連續移除不關 dropdown)。\n // SSOT propagation:fix 在 SelectMenu level → Combobox / 所有 SelectMenu\n // consumer 自動受益。\n onInteractOutside={(e) => {\n const target = e.detail.originalEvent.target as HTMLElement | null\n if (target?.closest('[data-radix-popper-content-wrapper]')) {\n e.preventDefault()\n }\n }}\n >\n <Command shouldFilter={searchable} className=\"bg-transparent\">\n {searchable && (\n <div className={cn(\n 'flex items-center gap-2 px-3 py-1 border-b border-divider',\n size === 'lg' ? 'min-h-[calc(var(--field-height-lg)+8px)]'\n : size === 'sm' ? 'min-h-[calc(var(--field-height-sm)+8px)]'\n : 'min-h-[calc(var(--field-height-md)+8px)]',\n )}>\n <Search size={ICON_SIZE[size as 'sm' | 'md' | 'lg']} className=\"shrink-0 text-fg-muted\" aria-hidden />\n <CommandPrimitive.Input\n placeholder={searchPlaceholder}\n value={search}\n onValueChange={setSearch}\n className={cn(\n 'flex w-full bg-transparent outline-none placeholder:text-fg-muted',\n // M24 disabled state precedence:disabled 時 placeholder 切 fg-disabled(audit dim 34)\n 'disabled:placeholder:text-fg-disabled disabled:text-fg-disabled disabled:cursor-not-allowed',\n size === 'lg' ? 'text-body-lg leading-compact' : 'text-body leading-compact',\n )}\n />\n </div>\n )}\n {/* **2026-05-07 v15.13 R2 fix**:minHeight 從 CommandList 搬到 CommandEmpty。\n 原本 CommandList 永遠套 `minHeight = field-height × minRows + 16px`,結果\n user 過濾出 < minRows 個 match 時 list 底下空一片(eg. 打 'c' 出 2 個 match\n 卻撐高到 3 row 容量,1 row 留白)。 Fix:只有 empty state 才需要 minHeight 撐\n 起 placeholder 視覺;有 results 時 CommandList 自然 fit content。 */}\n <CommandList className=\"relative\">\n <CommandEmpty\n className=\"flex items-center justify-center\"\n style={{ minHeight: getMenuListMinHeight(size, minRows) }}\n >\n {loading\n ? <Empty icon={<CircularProgress size={48}/>} className=\"py-6\" />\n : <Empty description={emptyText} className=\"py-6\" />}\n </CommandEmpty>\n\n {groupedOptions.map((group, gi) => (\n <React.Fragment key={group.key}>\n {gi > 0 && <CommandSeparator />}\n <CommandGroup className=\"p-0 py-2\">\n {group.label && (\n <MenuItem size={size} header>{group.label}</MenuItem>\n )}\n {group.options.map((opt) => (\n <CommandItem\n key={opt.value}\n value={opt.label}\n keywords={opt.description ? [opt.description] : undefined}\n disabled={opt.disabled}\n onSelect={() => handleSelect(opt.value)}\n className=\"p-0 rounded-none data-[selected=true]:bg-transparent\"\n >\n <MenuItem\n size={size}\n startIcon={opt.icon}\n avatar={opt.avatar}\n description={opt.description}\n checkbox={multiple}\n checked={isSelected(opt.value)}\n selected={!multiple && isSelected(opt.value)}\n disabled={opt.disabled}\n >\n {renderLabel ? renderLabel(opt) : opt.label}\n </MenuItem>\n </CommandItem>\n ))}\n </CommandGroup>\n </React.Fragment>\n ))}\n\n {/* Creatable item */}\n {showCreate && (\n <>\n <CommandSeparator />\n <CommandGroup className=\"p-0 py-2\">\n <CommandItem\n value={search}\n onSelect={() => {\n onCreate?.(search.trim())\n setSearch('')\n }}\n className=\"p-0 rounded-none data-[selected=true]:bg-transparent\"\n >\n <MenuItem size={size} startIcon={Plus}>\n {createLabel(search.trim())}\n </MenuItem>\n </CommandItem>\n </CommandGroup>\n </>\n )}\n </CommandList>\n\n {/* Multi-select footer: Select All\n - 沒有選項時不顯示(selectableOptions.length === 0)\n - 搜尋有文字時不顯示(search 非空 = 使用者在找特定項目,「全選」沒意義) */}\n {multiple && selectableOptions.length > 0 && !search && (\n <MenuFooter>\n <MenuItem\n size={size}\n checkbox\n checked={allState}\n onClick={handleSelectAll}\n >\n 全部\n </MenuItem>\n </MenuFooter>\n )}\n </Command>\n </PopoverContent>\n </RowSizeProvider>\n </Popover>\n )\n})\n\nSelectMenu.displayName = 'SelectMenu'\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 selectMenuMeta = {\n component: 'SelectMenu',\n family: 4,\n variants: {\n\n },\n sizes: {\n\n },\n states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],\n tokens: {\n bg: ['bg-surface-raised', 'bg-transparent'],\n fg: ['text-fg-muted'],\n ring: [],\n },\n} as const\n\nexport { SelectMenu }\n"],"names":["SelectMenu","CommandPrimitive"],"mappings":";;;;;;;;;;;;;;AA4HA,MAAM,aAAa,MAAM,WAAyC,SAASA,YAAW;AAAA,EACpF;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX,aAAa;AAAA,EACb,YAAY;AAAA,EACZ;AAAA,EACA,cAAc,CAAC,MAAM,QAAQ,CAAC;AAAA,EAC9B;AAAA,EACA,oBAAoB;AAAA;AAAA,EACpB,YAAY;AAAA;AAAA,EACZ,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAG,MAAM;AAEP,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAS,eAAe,KAAK;AAC3E,QAAM,OAAO,kBAAkB;AAC/B,QAAM,UAAU,0BAA0B;AAC1C,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE;AAG7C,QAAM,iBAAiB,MAAM,QAAkB,MAAM;AACnD,QAAI,SAAS,KAAM,QAAO,CAAA;AAC1B,WAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAAA,EAC9C,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,aAAa,MAAM;AAAA,IACvB,CAAC,MAAc,eAAe,SAAS,CAAC;AAAA,IACxC,CAAC,cAAc;AAAA,EAAA;AAGjB,QAAM,eAAe,MAAM;AAAA,IACzB,CAAC,gBAAwB;AACvB,UAAI,UAAU;AACZ,cAAM,OAAO,WAAW,WAAW,IAC/B,eAAe,OAAO,CAAC,MAAM,MAAM,WAAW,IAC9C,CAAC,GAAG,gBAAgB,WAAW;AACnC,uDAAgB;AAAA,MAClB,OAAO;AACL,uDAAgB;AAChB,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAAA,IACA,CAAC,UAAU,gBAAgB,YAAY,eAAe,OAAO;AAAA,EAAA;AAI/D,QAAM,oBAAoB,MAAM;AAAA,IAC9B,MAAM,QAAQ,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ;AAAA,IACvC,CAAC,OAAO;AAAA,EAAA;AAGV,QAAM,WAAsC,MAAM,QAAQ,MAAM;AAC9D,QAAI,CAAC,SAAU,QAAO;AACtB,UAAM,QAAQ,kBAAkB,OAAO,CAAC,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE;AACnE,QAAI,UAAU,EAAG,QAAO;AACxB,QAAI,UAAU,kBAAkB,OAAQ,QAAO;AAC/C,WAAO;AAAA,EACT,GAAG,CAAC,UAAU,mBAAmB,UAAU,CAAC;AAa5C,QAAM,kBAAkB,MAAM,YAAY,MAAM;AAC9C,QAAI,CAAC,SAAU;AACf,QAAI,aAAa,MAAM;AACrB,qDAAgB;IAClB,OAAO;AACL,qDAAgB,eAAe,gBAAgB,kBAAkB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAAA,IACtF;AAAA,EACF,GAAG,CAAC,UAAU,UAAU,mBAAmB,gBAAgB,aAAa,CAAC;AAGzE,QAAM,aAAa,MAAM,QAAQ,MAAM;AACrC,QAAI,CAAC,aAAa,CAAC,OAAO,KAAA,EAAQ,QAAO;AACzC,WAAO,CAAC,QAAQ;AAAA,MACd,CAAC,MAAM,EAAE,MAAM,kBAAkB,OAAO,KAAA,EAAO,YAAA;AAAA,IAAY;AAAA,EAE/D,GAAG,CAAC,WAAW,QAAQ,OAAO,CAAC;AAG/B,QAAM,iBAAiB,MAAM,QAAQ,MAAM;AACzC,QAAI,EAAC,iCAAQ,QAAQ,QAAO,CAAC,EAAE,KAAK,aAAa,OAAO,IAAI,SAAS;AACrE,UAAM,UAAU,OAAO,IAAI,CAAC,OAAO;AAAA,MACjC,GAAG;AAAA,MACH,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG;AAAA,IAAA,EAChD;AACF,UAAM,YAAY,QAAQ,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK;AAChD,QAAI,UAAU,QAAQ;AACpB,cAAQ,QAAQ,EAAE,KAAK,aAAa,OAAO,IAAI,SAAS,WAAW;AAAA,IACrE;AACA,WAAO;AAAA,EACT,GAAG,CAAC,QAAQ,OAAO,CAAC;AAGpB,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,KAAM,WAAU,EAAE;AAAA,EACzB,GAAG,CAAC,IAAI,CAAC;AAMT,SACE,qBAAC,SAAA,EAAQ,MAAY,cAAc,SACjC,UAAA;AAAA,IAAA,oBAAC,gBAAA,EAAe,SAAO,MAAE,SAAA,CAAS;AAAA,IAClC,oBAAC,iBAAA,EAAgB,OAAO,MACxB,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,IAAI;AAAA,QAIJ,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QAAA;AAAA,QAEF,OAAO;AAAA,UACL,WAAW;AAAA,UACX,UAAU,YAAY;AAAA,QAAA;AAAA,QAExB;AAAA,QACA,YAAY;AAAA,QACZ;AAAA,QAoBA,mBAAmB,CAAC,MAAM;AACxB,gBAAM,SAAS,EAAE,OAAO,cAAc;AACtC,cAAI,iCAAQ,QAAQ,wCAAwC;AAC1D,cAAE,eAAA;AAAA,UACJ;AAAA,QACF;AAAA,QAEA,UAAA,qBAAC,SAAA,EAAQ,cAAc,YAAY,WAAU,kBAC1C,UAAA;AAAA,UAAA,cACC,qBAAC,SAAI,WAAW;AAAA,YACd;AAAA,YACA,SAAS,OAAO,6CACZ,SAAS,OAAO,6CAChB;AAAA,UAAA,GAEJ,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAO,MAAM,UAAU,IAA0B,GAAG,WAAU,0BAAyB,eAAW,MAAC;AAAA,YACpG;AAAA,cAACC,UAAiB;AAAA,cAAjB;AAAA,gBACC,aAAa;AAAA,gBACb,OAAO;AAAA,gBACP,eAAe;AAAA,gBACf,WAAW;AAAA,kBACT;AAAA;AAAA,kBAEA;AAAA,kBACA,SAAS,OAAO,iCAAiC;AAAA,gBAAA;AAAA,cACnD;AAAA,YAAA;AAAA,UACF,GACF;AAAA,UAOF,qBAAC,aAAA,EAAY,WAAU,YACrB,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,WAAW,qBAAqB,MAAM,OAAO,EAAA;AAAA,gBAErD,oBACG,oBAAC,OAAA,EAAM,MAAM,oBAAC,oBAAiB,MAAM,GAAA,CAAG,GAAI,WAAU,QAAO,IAC7D,oBAAC,SAAM,aAAa,WAAW,WAAU,OAAA,CAAO;AAAA,cAAA;AAAA,YAAA;AAAA,YAGrD,eAAe,IAAI,CAAC,OAAO,OAC1B,qBAAC,MAAM,UAAN,EACE,UAAA;AAAA,cAAA,KAAK,yBAAM,kBAAA,CAAA,CAAiB;AAAA,cAC7B,qBAAC,cAAA,EAAa,WAAU,YACrB,UAAA;AAAA,gBAAA,MAAM,SACL,oBAAC,UAAA,EAAS,MAAY,QAAM,MAAE,gBAAM,MAAA,CAAM;AAAA,gBAE3C,MAAM,QAAQ,IAAI,CAAC,QAClB;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBAEC,OAAO,IAAI;AAAA,oBACX,UAAU,IAAI,cAAc,CAAC,IAAI,WAAW,IAAI;AAAA,oBAChD,UAAU,IAAI;AAAA,oBACd,UAAU,MAAM,aAAa,IAAI,KAAK;AAAA,oBACtC,WAAU;AAAA,oBAEV,UAAA;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC;AAAA,wBACA,WAAW,IAAI;AAAA,wBACf,QAAQ,IAAI;AAAA,wBACZ,aAAa,IAAI;AAAA,wBACjB,UAAU;AAAA,wBACV,SAAS,WAAW,IAAI,KAAK;AAAA,wBAC7B,UAAU,CAAC,YAAY,WAAW,IAAI,KAAK;AAAA,wBAC3C,UAAU,IAAI;AAAA,wBAEb,UAAA,cAAc,YAAY,GAAG,IAAI,IAAI;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBACxC;AAAA,kBAlBK,IAAI;AAAA,gBAAA,CAoBZ;AAAA,cAAA,EAAA,CACH;AAAA,YAAA,KA7BmB,MAAM,GA8B3B,CACD;AAAA,YAGA,cACC,qBAAA,UAAA,EACE,UAAA;AAAA,cAAA,oBAAC,kBAAA,EAAiB;AAAA,cAClB,oBAAC,cAAA,EAAa,WAAU,YACtB,UAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,OAAO;AAAA,kBACP,UAAU,MAAM;AACd,yDAAW,OAAO;AAClB,8BAAU,EAAE;AAAA,kBACd;AAAA,kBACA,WAAU;AAAA,kBAEV,UAAA,oBAAC,YAAS,MAAY,WAAW,MAC9B,UAAA,YAAY,OAAO,KAAA,CAAM,EAAA,CAC5B;AAAA,gBAAA;AAAA,cAAA,EACF,CACF;AAAA,YAAA,EAAA,CACF;AAAA,UAAA,GAEJ;AAAA,UAKC,YAAY,kBAAkB,SAAS,KAAK,CAAC,8BAC3C,YAAA,EACC,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC;AAAA,cACA,UAAQ;AAAA,cACR,SAAS;AAAA,cACT,SAAS;AAAA,cACV,UAAA;AAAA,YAAA;AAAA,UAAA,EAED,CACF;AAAA,QAAA,EAAA,CAEJ;AAAA,MAAA;AAAA,IAAA,EACF,CACA;AAAA,EAAA,GACF;AAEJ,CAAC;AAED,WAAW,cAAc;AAIlB,MAAM,iBAAiB;AAAA,EAC5B,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,UAAU,CAAA;AAAA,EAGV,OAAO,CAAA;AAAA,EAGP,QAAQ,CAAC,WAAW,SAAS,UAAU,iBAAiB,UAAU;AAAA,EAClE,QAAQ;AAAA,IACN,IAAI,CAAC,qBAAqB,gBAAgB;AAAA,IAC1C,IAAI,CAAC,eAAe;AAAA,IACpB,MAAM,CAAA;AAAA,EAAC;AAEX;"}
@@ -0,0 +1,69 @@
1
+ import * as React from 'react';
2
+ import { type VariantProps } from 'class-variance-authority';
3
+ import type { LucideIcon } from 'lucide-react';
4
+ import { type AvatarData } from '../../components/Avatar/avatar';
5
+ export declare const selectionItemStyles: (props?: ({
6
+ size?: "sm" | "md" | "lg" | null | undefined;
7
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
+ export interface SelectionItemProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof selectionItemStyles> {
9
+ /** Checkbox 或 RadioGroupItem 元素(永遠存在,永遠 inline 對齊) */
10
+ control: React.ReactNode;
11
+ /** Label 文字 */
12
+ label: React.ReactNode;
13
+ /** 描述文字(fg-secondary;reading mode 永遠 14px) */
14
+ description?: React.ReactNode;
15
+ /**
16
+ * 可選的左側 icon(在 control 之後、label 之前)。LucideIcon 型別,元件內部控制尺寸
17
+ * (16/16/20px @ sm/md/lg)。**永遠 inline 對齊第一行 label**(icon ≤24px)。
18
+ * 與 `avatar` 互斥。
19
+ */
20
+ icon?: LucideIcon;
21
+ /**
22
+ * 可選的左側 avatar(在 control 之後、label 之前)。`AvatarData` 資料型別,元件內部渲染 Avatar。
23
+ * 尺寸由 `description` 自動決定(跟 MenuItem 同 convention):
24
+ * - 無 desc → inline(20/24/24px),跟 control 同步在 label 第一行
25
+ * - 有 desc → block(32/32/40px),跟 control 同步在 text block center
26
+ *
27
+ * Block 模式時 **control(checkbox/radio)也一起走 block 高度**——兩者都在
28
+ * text block center,不會歪斜。與 `icon` 互斥。
29
+ */
30
+ avatar?: AvatarData;
31
+ /** htmlFor(label 指向 control 的 id) */
32
+ htmlFor?: string;
33
+ /** disabled 狀態影響 label 顏色 */
34
+ disabled?: boolean;
35
+ /**
36
+ * Label 最大行數(line-clamp 截斷)。
37
+ *
38
+ * - `undefined`(預設 prop 值未傳)→ 套用元件預設 `'none'`(form 欄位允許任意長度)
39
+ * - 數字 → 截斷到該行數
40
+ * - `'none'` → 明確不截斷(語意等同預設)
41
+ *
42
+ * 為什麼用 `'none'` 而不是 `undefined`?React props 的 destructure default 在
43
+ * `undefined` 時會接管,要明確覆寫必須用非 undefined 的 sentinel。
44
+ */
45
+ labelMaxLines?: number | 'none';
46
+ /**
47
+ * Description 最大行數。預設 `'none'`(不截)。
48
+ */
49
+ descMaxLines?: number | 'none';
50
+ className?: string;
51
+ }
52
+ declare const SelectionItem: React.ForwardRefExoticComponent<SelectionItemProps & React.RefAttributes<HTMLDivElement>>;
53
+ export declare const selectionItemMeta: {
54
+ readonly component: "SelectionItem";
55
+ readonly family: 2;
56
+ readonly variants: {};
57
+ readonly sizes: {
58
+ readonly sm: {};
59
+ readonly md: {};
60
+ readonly lg: {};
61
+ };
62
+ readonly defaultSize: "md";
63
+ readonly states: readonly ["default", "hover", "selected", "focus-visible", "disabled"];
64
+ readonly tokens: {
65
+ readonly fg: readonly ["text-foreground", "text-fg-secondary", "text-fg-disabled"];
66
+ };
67
+ };
68
+ export { SelectionItem };
69
+ //# sourceMappingURL=selection-item.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection-item.d.ts","sourceRoot":"","sources":["../../../src/components/SelectionControl/selection-item.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,0CAA0C,CAAA;AAyBlF,eAAO,MAAM,mBAAmB;;8EAc/B,CAAA;AA2BD,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,YAAY,CAAC,OAAO,mBAAmB,CAAC;IACxH,sDAAsD;IACtD,OAAO,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,eAAe;IACf,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,8CAA8C;IAC9C,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC/B;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAmFD,QAAA,MAAM,aAAa,2FA4ClB,CAAA;AAID,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;CAcpB,CAAA;AAEV,OAAO,EAAE,aAAa,EAAE,CAAA"}
@@ -0,0 +1,142 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cva } from "class-variance-authority";
4
+ import { cn } from "../../lib/utils.js";
5
+ import { Avatar } from "../Avatar/avatar.js";
6
+ import { AVATAR_SIZE, ICON_SIZE } from "../../patterns/element-anatomy/item-anatomy.js";
7
+ const selectionItemStyles = cva(
8
+ "flex items-start gap-2",
9
+ {
10
+ variants: {
11
+ size: {
12
+ sm: "text-body py-[calc((var(--field-height-sm)_-_1lh)_/_2)]",
13
+ md: "text-body py-[calc((var(--field-height-md)_-_1lh)_/_2)]",
14
+ lg: "text-body-lg py-[calc((var(--field-height-lg)_-_1lh)_/_2)]"
15
+ }
16
+ },
17
+ defaultVariants: {
18
+ size: "md"
19
+ }
20
+ }
21
+ );
22
+ const AVATAR_PX = AVATAR_SIZE;
23
+ const blockAlignClass = {
24
+ sm: "h-[calc(1lh+var(--item-gap-label-desc-reading)+var(--font-body-size)*1.5)]",
25
+ md: "h-[calc(1lh+var(--item-gap-label-desc-reading)+var(--font-body-size)*1.5)]",
26
+ lg: "h-[calc(1lh+var(--item-gap-label-desc-reading-lg)+var(--font-body-size)*1.5)]"
27
+ };
28
+ function lineClampClass(maxLines) {
29
+ if (maxLines === "none" || !maxLines) return "";
30
+ if (maxLines === 1) return "line-clamp-1";
31
+ if (maxLines === 2) return "line-clamp-2";
32
+ if (maxLines === 3) return "line-clamp-3";
33
+ if (maxLines === 4) return "line-clamp-4";
34
+ if (maxLines === 5) return "line-clamp-5";
35
+ if (maxLines === 6) return "line-clamp-6";
36
+ return "";
37
+ }
38
+ function PrefixSlot({ icon: Icon, avatar, sizeKey, alignClass, avatarPx, disabled }) {
39
+ if (!Icon && !avatar) return null;
40
+ return /* @__PURE__ */ jsxs("div", { className: cn(alignClass, "flex items-center shrink-0"), children: [
41
+ Icon && /* @__PURE__ */ jsx(
42
+ Icon,
43
+ {
44
+ size: ICON_SIZE[sizeKey],
45
+ className: cn("shrink-0", disabled && "text-fg-disabled"),
46
+ "aria-hidden": true
47
+ }
48
+ ),
49
+ !Icon && avatar && /* @__PURE__ */ jsx(Avatar, { src: avatar.src, alt: avatar.alt, color: avatar.color, hoverCard: avatar.hoverCard, size: avatarPx })
50
+ ] });
51
+ }
52
+ function ContentSlot({ htmlFor, disabled, label, description, sizeKey, labelClampClass, descClampClass }) {
53
+ return /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
54
+ /* @__PURE__ */ jsx(
55
+ "label",
56
+ {
57
+ htmlFor,
58
+ className: cn(
59
+ "cursor-pointer block break-words",
60
+ labelClampClass,
61
+ disabled ? "text-fg-disabled cursor-not-allowed" : "text-foreground"
62
+ ),
63
+ children: label
64
+ }
65
+ ),
66
+ description && /* @__PURE__ */ jsx(
67
+ "p",
68
+ {
69
+ className: cn(
70
+ sizeKey === "lg" ? "mt-[var(--item-gap-label-desc-reading-lg)]" : "mt-[var(--item-gap-label-desc-reading)]",
71
+ "break-words",
72
+ descClampClass,
73
+ disabled ? "text-fg-disabled" : "text-fg-secondary"
74
+ ),
75
+ style: { fontSize: "var(--font-body-size)" },
76
+ children: description
77
+ }
78
+ )
79
+ ] });
80
+ }
81
+ const SelectionItem = React.forwardRef(
82
+ ({
83
+ control,
84
+ label,
85
+ description,
86
+ icon: Icon,
87
+ avatar,
88
+ htmlFor,
89
+ disabled,
90
+ size,
91
+ labelMaxLines = "none",
92
+ descMaxLines = "none",
93
+ className,
94
+ ...props
95
+ }, ref) => {
96
+ const sizeKey = size ?? "md";
97
+ if (process.env.NODE_ENV !== "production" && Icon && avatar) {
98
+ console.warn("[SelectionItem] `icon` 和 `avatar` 互斥,只會渲染 icon。");
99
+ }
100
+ const useBlock = !!avatar && !Icon && !!description && AVATAR_PX.block[sizeKey] > 24;
101
+ const avatarPx = useBlock ? AVATAR_PX.block[sizeKey] : AVATAR_PX.inline[sizeKey];
102
+ const alignClass = useBlock ? blockAlignClass[sizeKey] : "h-[1lh]";
103
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn(selectionItemStyles({ size }), className), ...props, children: [
104
+ /* @__PURE__ */ jsx("div", { className: cn(alignClass, "flex items-center shrink-0"), children: control }),
105
+ /* @__PURE__ */ jsx(PrefixSlot, { icon: Icon, avatar, sizeKey, alignClass, avatarPx, disabled }),
106
+ /* @__PURE__ */ jsx(
107
+ ContentSlot,
108
+ {
109
+ htmlFor,
110
+ disabled,
111
+ label,
112
+ description,
113
+ sizeKey,
114
+ labelClampClass: lineClampClass(labelMaxLines),
115
+ descClampClass: lineClampClass(descMaxLines)
116
+ }
117
+ )
118
+ ] });
119
+ }
120
+ );
121
+ SelectionItem.displayName = "SelectionItem";
122
+ const selectionItemMeta = {
123
+ component: "SelectionItem",
124
+ family: 2,
125
+ variants: {},
126
+ sizes: {
127
+ sm: {},
128
+ md: {},
129
+ lg: {}
130
+ },
131
+ defaultSize: "md",
132
+ states: ["default", "hover", "selected", "focus-visible", "disabled"],
133
+ tokens: {
134
+ fg: ["text-foreground", "text-fg-secondary", "text-fg-disabled"]
135
+ }
136
+ };
137
+ export {
138
+ SelectionItem,
139
+ selectionItemMeta,
140
+ selectionItemStyles
141
+ };
142
+ //# sourceMappingURL=selection-item.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection-item.js","sources":["../../../src/components/SelectionControl/selection-item.tsx"],"sourcesContent":["import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport type { LucideIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Avatar, type AvatarData } from '@/design-system/components/Avatar/avatar'\nimport { ICON_SIZE, AVATAR_SIZE } from '@/design-system/patterns/element-anatomy/item-anatomy'\n\n// ── Selection Item Styles ───────────────────────────────────────────────────\n// Checkbox 和 RadioGroup 共用的 item 佈局。\n//\n// 結構(item-anatomy.spec.md 4-slot 模型):\n// [control] [optional prefix(icon|avatar)] [content(label/desc)] [optional suffix]\n//\n// padding 公式:py = (field-height - 1lh) / 2\n// - 單行時 item 高度 = field-height(對齊同 size 的 Input)\n// - 多行時 padding 不變(文字間距一致)\n// - density 切換時 field-height 自動調整,padding 跟著算\n//\n// 容器設 text-body / text-body-lg 建立 1lh context(div 上正常繼承)。\n//\n// ── 為什麼 NOT 消費 ROW_PADDING_BY_SIZE(item-anatomy.tsx SSOT,2026-04-24 consolidation)──\n// menu / sidebar / tree 3 cva 統一消費 ROW_PADDING_BY_SIZE;SelectionItem 刻意不消費,\n// 因 typography 不同(mode 差異,非 drift):\n// - ROW_PADDING_BY_SIZE:`text-body leading-compact`(scanning mode,緊湊)\n// - SelectionItem:`text-body`(**無 leading-compact** — reading mode,Checkbox/Radio 搭配\n// 較長 label + description,需預設 1.5 leading 而非 1.3 compact)\n// py 公式本身相同 — 若 field-height token 變動,本檔需手動同步(contained,由本註解 anchor 追)。\n\n// code-quality-allow: dead-export — public API surface — consumer-exposed for future use\nexport const selectionItemStyles = cva(\n 'flex items-start gap-2',\n {\n variants: {\n size: {\n sm: 'text-body py-[calc((var(--field-height-sm)_-_1lh)_/_2)]',\n md: 'text-body py-[calc((var(--field-height-md)_-_1lh)_/_2)]',\n lg: 'text-body-lg py-[calc((var(--field-height-lg)_-_1lh)_/_2)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n)\n\ntype SizeKey = 'sm' | 'md' | 'lg'\n\n// Avatar 尺寸 + Icon 尺寸從 item-layout module 共用,不在此 re-declare(避免漂移)\n// AVATAR_SIZE / ICON_SIZE 都是 item-layout 的 canonical 常數。\n//\n// SelectionItem 跟 MenuItem 的差異:SelectionItem 有 control(checkbox/radio)。\n// block 模式時 **control 跟 prefix 一起走 block 高度**——兩者都在 text block center,\n// 維持「selection + identity」是一組的視覺語意,不會歪斜。\nconst AVATAR_PX = AVATAR_SIZE\n\n// ── Block 對齊容器 ──\n// sm/md: reading mode (body 14/1.5 + body 14/1.5) — gap token `reading`\n// lg: reading-lg mode (body-lg 16/1.5 + body 14/1.5) — gap token `reading-lg`\n// desc 永遠 body(14) line-height;`1lh` 會 resolve 到 label 的 line-height(sm/md=21, lg=24)\nconst blockAlignClass: Record<SizeKey, string> = {\n sm: 'h-[calc(1lh+var(--item-gap-label-desc-reading)+var(--font-body-size)*1.5)]',\n md: 'h-[calc(1lh+var(--item-gap-label-desc-reading)+var(--font-body-size)*1.5)]',\n lg: 'h-[calc(1lh+var(--item-gap-label-desc-reading-lg)+var(--font-body-size)*1.5)]',\n}\n\n// ── Selection Item ──────────────────────────────────────────────────────────\n// 通用 item 行:control + 可選 prefix(icon/avatar) + label + description。\n// control 永遠包在 h-[1lh] 容器內,對齊第一行 label。\n// prefix 走 24px 閾值規則,各自獨立對齊。\n\nexport interface SelectionItemProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof selectionItemStyles> {\n /** Checkbox 或 RadioGroupItem 元素(永遠存在,永遠 inline 對齊) */\n control: React.ReactNode\n /** Label 文字 */\n label: React.ReactNode\n /** 描述文字(fg-secondary;reading mode 永遠 14px) */\n description?: React.ReactNode\n /**\n * 可選的左側 icon(在 control 之後、label 之前)。LucideIcon 型別,元件內部控制尺寸\n * (16/16/20px @ sm/md/lg)。**永遠 inline 對齊第一行 label**(icon ≤24px)。\n * 與 `avatar` 互斥。\n */\n icon?: LucideIcon\n /**\n * 可選的左側 avatar(在 control 之後、label 之前)。`AvatarData` 資料型別,元件內部渲染 Avatar。\n * 尺寸由 `description` 自動決定(跟 MenuItem 同 convention):\n * - 無 desc → inline(20/24/24px),跟 control 同步在 label 第一行\n * - 有 desc → block(32/32/40px),跟 control 同步在 text block center\n *\n * Block 模式時 **control(checkbox/radio)也一起走 block 高度**——兩者都在\n * text block center,不會歪斜。與 `icon` 互斥。\n */\n avatar?: AvatarData\n /** htmlFor(label 指向 control 的 id) */\n htmlFor?: string\n /** disabled 狀態影響 label 顏色 */\n disabled?: boolean\n /**\n * Label 最大行數(line-clamp 截斷)。\n *\n * - `undefined`(預設 prop 值未傳)→ 套用元件預設 `'none'`(form 欄位允許任意長度)\n * - 數字 → 截斷到該行數\n * - `'none'` → 明確不截斷(語意等同預設)\n *\n * 為什麼用 `'none'` 而不是 `undefined`?React props 的 destructure default 在\n * `undefined` 時會接管,要明確覆寫必須用非 undefined 的 sentinel。\n */\n labelMaxLines?: number | 'none'\n /**\n * Description 最大行數。預設 `'none'`(不截)。\n */\n descMaxLines?: number | 'none'\n className?: string\n}\n\n/** 把 maxLines 轉成 line-clamp class;'none' / 0 → 空字串 */\nfunction lineClampClass(maxLines: number | 'none'): string {\n if (maxLines === 'none' || !maxLines) return ''\n if (maxLines === 1) return 'line-clamp-1'\n if (maxLines === 2) return 'line-clamp-2'\n if (maxLines === 3) return 'line-clamp-3'\n if (maxLines === 4) return 'line-clamp-4'\n if (maxLines === 5) return 'line-clamp-5'\n if (maxLines === 6) return 'line-clamp-6'\n return ''\n}\n\n// ── PrefixSlot — 24px 閾值規則 ──\n// icon(永遠 ≤24px)→ inline;avatar + 無 desc → inline;avatar + 有 desc → block(centered on text block)\ntype PrefixSlotProps = {\n icon: LucideIcon | undefined\n avatar: AvatarData | undefined\n sizeKey: SizeKey\n alignClass: string\n avatarPx: number\n disabled: boolean | undefined\n}\nfunction PrefixSlot({ icon: Icon, avatar, sizeKey, alignClass, avatarPx, disabled }: PrefixSlotProps) {\n if (!Icon && !avatar) return null\n return (\n <div className={cn(alignClass, 'flex items-center shrink-0')}>\n {Icon && (\n <Icon\n size={ICON_SIZE[sizeKey]}\n className={cn('shrink-0', disabled && 'text-fg-disabled')}\n aria-hidden\n />\n )}\n {!Icon && avatar && (\n <Avatar src={avatar.src} alt={avatar.alt} color={avatar.color} hoverCard={avatar.hoverCard} size={avatarPx} />\n )}\n </div>\n )\n}\n\n// ── ContentSlot — label + optional description ──\n// inline-style fontSize 繞 tailwind-merge 把 text-body / text-fg-secondary 誤判同組衝突的 bug\ntype ContentSlotProps = {\n htmlFor: string | undefined\n disabled: boolean | undefined\n label: React.ReactNode\n description: React.ReactNode | undefined\n sizeKey: SizeKey\n labelClampClass: string\n descClampClass: string\n}\nfunction ContentSlot({ htmlFor, disabled, label, description, sizeKey, labelClampClass, descClampClass }: ContentSlotProps) {\n return (\n <div className=\"min-w-0 flex-1\">\n <label\n htmlFor={htmlFor}\n className={cn(\n 'cursor-pointer block break-words',\n labelClampClass,\n disabled ? 'text-fg-disabled cursor-not-allowed' : 'text-foreground',\n )}\n >\n {label}\n </label>\n {description && (\n <p\n className={cn(\n sizeKey === 'lg' ? 'mt-[var(--item-gap-label-desc-reading-lg)]' : 'mt-[var(--item-gap-label-desc-reading)]',\n 'break-words',\n descClampClass,\n disabled ? 'text-fg-disabled' : 'text-fg-secondary',\n )}\n style={{ fontSize: 'var(--font-body-size)' }}\n >\n {description}\n </p>\n )}\n </div>\n )\n}\n\nconst SelectionItem = React.forwardRef<HTMLDivElement, SelectionItemProps>(\n (\n {\n control,\n label,\n description,\n icon: Icon,\n avatar,\n htmlFor,\n disabled,\n size,\n labelMaxLines = 'none',\n descMaxLines = 'none',\n className,\n ...props\n },\n ref\n ) => {\n const sizeKey: SizeKey = size ?? 'md'\n if (process.env.NODE_ENV !== 'production' && Icon && avatar) {\n // eslint-disable-next-line no-console\n console.warn('[SelectionItem] `icon` 和 `avatar` 互斥,只會渲染 icon。')\n }\n // Block 對齊:control 跟 prefix(avatar)一起走 block 高度,「selection + identity」視覺單元不歪斜\n const useBlock = !!avatar && !Icon && !!description && AVATAR_PX.block[sizeKey] > 24\n const avatarPx = useBlock ? AVATAR_PX.block[sizeKey] : AVATAR_PX.inline[sizeKey]\n const alignClass = useBlock ? blockAlignClass[sizeKey] : 'h-[1lh]'\n\n return (\n <div ref={ref} className={cn(selectionItemStyles({ size }), className)} {...props}>\n <div className={cn(alignClass, 'flex items-center shrink-0')}>{control}</div>\n <PrefixSlot icon={Icon} avatar={avatar} sizeKey={sizeKey} alignClass={alignClass} avatarPx={avatarPx} disabled={disabled} />\n <ContentSlot\n htmlFor={htmlFor}\n disabled={disabled}\n label={label}\n description={description}\n sizeKey={sizeKey}\n labelClampClass={lineClampClass(labelMaxLines)}\n descClampClass={lineClampClass(descMaxLines)}\n />\n </div>\n )\n }\n)\nSelectionItem.displayName = 'SelectionItem'\n\n// Story auto-compile metadata — Phase 1+2 migration\nexport const selectionItemMeta = {\n component: 'SelectionItem',\n family: 2,\n variants: {},\n sizes: {\n sm: {},\n md: {},\n lg: {},\n },\n defaultSize: 'md',\n states: ['default', 'hover', 'selected', 'focus-visible', 'disabled'],\n tokens: {\n fg: ['text-foreground', 'text-fg-secondary', 'text-fg-disabled'],\n },\n} as const\n\nexport { SelectionItem }\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import * as React from "react";
2
+ import * as SeparatorPrimitive from "@radix-ui/react-separator";
3
+ declare const Separator: React.ForwardRefExoticComponent<Omit<SeparatorPrimitive.SeparatorProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
4
+ export declare const separatorMeta: {
5
+ readonly component: "Separator";
6
+ readonly family: null;
7
+ readonly variants: {};
8
+ readonly sizes: {};
9
+ readonly states: readonly ["default", "hover", "active", "focus-visible", "disabled"];
10
+ readonly tokens: {
11
+ readonly bg: readonly [];
12
+ readonly fg: readonly [];
13
+ readonly ring: readonly [];
14
+ };
15
+ };
16
+ export { Separator };
17
+ //# sourceMappingURL=separator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separator.d.ts","sourceRoot":"","sources":["../../../src/components/Separator/separator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,kBAAkB,MAAM,2BAA2B,CAAA;AAI/D,QAAA,MAAM,SAAS,6JAoBd,CAAA;AAKD,eAAO,MAAM,aAAa;;;;;;;;;;;CAehB,CAAA;AAEV,OAAO,EAAE,SAAS,EAAE,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import * as SeparatorPrimitive from "@radix-ui/react-separator";
4
+ import { cn } from "../../lib/utils.js";
5
+ const Separator = React.forwardRef(
6
+ ({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx(
7
+ SeparatorPrimitive.Root,
8
+ {
9
+ ref,
10
+ decorative,
11
+ orientation,
12
+ className: cn(
13
+ "shrink-0 bg-divider",
14
+ orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
15
+ className
16
+ ),
17
+ ...props
18
+ }
19
+ )
20
+ );
21
+ Separator.displayName = "Separator";
22
+ const separatorMeta = {
23
+ component: "Separator",
24
+ family: null,
25
+ // non-family composite / overlay / layout
26
+ variants: {},
27
+ sizes: {},
28
+ states: ["default", "hover", "active", "focus-visible", "disabled"],
29
+ tokens: {
30
+ bg: [],
31
+ fg: [],
32
+ ring: []
33
+ }
34
+ };
35
+ export {
36
+ Separator,
37
+ separatorMeta
38
+ };
39
+ //# sourceMappingURL=separator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"separator.js","sources":["../../../src/components/Separator/separator.tsx"],"sourcesContent":["import * as React from \"react\"\nimport * as SeparatorPrimitive from \"@radix-ui/react-separator\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Separator = React.forwardRef<\n React.ElementRef<typeof SeparatorPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\n>(\n (\n { className, orientation = \"horizontal\", decorative = true, ...props },\n ref\n ) => (\n <SeparatorPrimitive.Root\n ref={ref}\n decorative={decorative}\n orientation={orientation}\n className={cn(\n \"shrink-0 bg-divider\",\n orientation === \"horizontal\" ? \"h-px w-full\" : \"h-full w-px\",\n className\n )}\n {...props}\n />\n )\n)\nSeparator.displayName = \"Separator\"\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 separatorMeta = {\n component: 'Separator',\n family: null, // non-family composite / overlay / layout\n variants: {\n\n },\n sizes: {\n\n },\n states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],\n tokens: {\n bg: [],\n fg: [],\n ring: [],\n },\n} as const\n\nexport { Separator }\n"],"names":[],"mappings":";;;;AAKA,MAAM,YAAY,MAAM;AAAA,EAItB,CACE,EAAE,WAAW,cAAc,cAAc,aAAa,MAAM,GAAG,SAC/D,QAEA;AAAA,IAAC,mBAAmB;AAAA,IAAnB;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA,gBAAgB,eAAe,gBAAgB;AAAA,QAC/C;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AACA,UAAU,cAAc;AAIjB,MAAM,gBAAgB;AAAA,EAC3B,WAAW;AAAA,EACX,QAAQ;AAAA;AAAA,EACR,UAAU,CAAA;AAAA,EAGV,OAAO,CAAA;AAAA,EAGP,QAAQ,CAAC,WAAW,SAAS,UAAU,iBAAiB,UAAU;AAAA,EAClE,QAAQ;AAAA,IACN,IAAI,CAAA;AAAA,IACJ,IAAI,CAAA;AAAA,IACJ,MAAM,CAAA;AAAA,EAAC;AAEX;"}