@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,322 @@
1
+ // @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.
2
+ import * as React from 'react'
3
+ import { Paperclip, CircleCheck, XCircle, Download, RotateCw } from 'lucide-react'
4
+ import { cn } from '@/lib/utils'
5
+ import { Avatar } from '@/design-system/components/Avatar/avatar'
6
+ import { Button } from '@/design-system/components/Button/button'
7
+ import { ProgressBar } from '@/design-system/components/ProgressBar/progress-bar'
8
+ import { ItemContent, ItemPrefix } from '@/design-system/patterns/element-anatomy/item-anatomy'
9
+
10
+ /**
11
+ * FileItem โ€” ๆช”ๆกˆ้กฏ็คบ / ไธŠๅ‚ณ้€ฒๅบฆ
12
+ *
13
+ * Typography: ้–ฑ่ฎ€ๆจกๅผ โ€” text-body (14px) ้ ่จญ่กŒ้ซ˜ (1.5)
14
+ *
15
+ * ๅ…ฉ็จฎ mode๏ผˆ็ฒพ็ฐก vs ๅฎŒๆ•ดๅ…งๅฎนๅ‘ˆ็พ๏ผ‰:
16
+ *
17
+ * compact๏ผˆโ˜… default๏ผ‰: Paperclip 16px ๅœจๅทฆใ€‚ๅณๅด content + barใ€‚
18
+ * py = gap = 4px (gap-1)๏ผŒๅฐ็จฑใ€‚
19
+ * description ๅชๆœ‰ error ๆ‰้กฏ็คบใ€‚
20
+ * bar ่ทŸๆ–‡ๅญ—ๅทฆ้‚Šๅฐ้ฝŠ๏ผˆๅœจ icon ๅณ้‚Š็š„ column ๅ…ง๏ผ‰ใ€‚
21
+ *
22
+ * rich: Avatar 48px square ๅœจๅทฆ๏ผˆ้กฏ็คบๆช”ๆกˆๅ…งๅฎน็ธฎๅœ–๏ผ‰ใ€‚ๅณๅด content + barใ€‚
23
+ * ๅคš่กŒ description๏ผˆsize / status message๏ผ‰ใ€‚
24
+ * ๆœ‰ bar โ†’ justify-between๏ผˆbar ๅบ•้ƒจๅฐ้ฝŠ avatar๏ผ‰
25
+ * ็„ก bar โ†’ justify-center๏ผˆๆ–‡ๅญ—ๅž‚็›ด็ฝฎไธญๅฐ้ฝŠ avatar๏ผ‰
26
+ *
27
+ * status ๅฏ้ธใ€‚ไธๅ‚ณ = ๅทฒไธŠๅ‚ณๆช”ๆกˆ๏ผˆ็„ก bar๏ผŒๅฏ้ปžๆ“Šไธ‹่ผ‰๏ผ‰ใ€‚
28
+ * onClick โ†’ hover:bg-neutral-hover + cursor-pointerใ€‚
29
+ */
30
+
31
+ const STATUS_ICON = {
32
+ completed: { icon: CircleCheck, color: 'text-success' },
33
+ error: { icon: XCircle, color: 'text-error' },
34
+ } as const
35
+
36
+ // ProgressBar status ๆ˜ ๅฐ„:uploading=inProgress(่—) / completed=success(็ถ ) / error=error(็ด…)
37
+ // ่ˆ‡ ProgressBar ๅ…ƒไปถ็š„ status prop ๅฐ้ฝŠ,ไธ้œ€ๅ†็ถญ่ญท PROGRESS_COLOR ๆœฌๅœฐ mapใ€‚
38
+ const PROGRESS_STATUS_MAP = {
39
+ uploading: 'inProgress',
40
+ completed: 'success',
41
+ error: 'error',
42
+ } as const
43
+
44
+ const AVATAR_SIZE = 48
45
+ const ICON_PX = 16
46
+
47
+ export interface FileItemProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
48
+ name: string
49
+ /**
50
+ * ๅ…ฉ็จฎๅ‘ˆ็พ mode๏ผˆ็ฒพ็ฐก vs ๅฎŒๆ•ด๏ผ‰๏ผš
51
+ * - `compact`๏ผˆ้ ่จญ๏ผ‰๏ผšpaperclip + filename ๅ–ฎ่กŒ inline
52
+ * - `rich`๏ผš็ธฎๅœ– + ๆช”ๅ + size + status + progress ็š„ๅฎŒๆ•ด card ๅ‘ˆ็พ
53
+ */
54
+ mode?: 'compact' | 'rich'
55
+ status?: 'uploading' | 'completed' | 'error'
56
+ progress?: number
57
+ /** rich mode: ๆช”ๆกˆๅคงๅฐใ€็‹€ๆ…‹่จŠๆฏใ€‚compact: ๅชๆœ‰ error ๆ‰้กฏ็คบใ€‚ ReactNode ๆ”ฏๆด inline clickable link(ๅฆ‚ใ€ŒView logใ€)ใ€‚ */
58
+ description?: React.ReactNode
59
+ thumbnailSrc?: string
60
+ actions?: React.ReactNode
61
+ onClick?: () => void
62
+ /**
63
+ * Hover ๅ‹•ไฝœ(passive ็‹€ๆ…‹ icon ่ฎŠไบ’ๅ‹• button ็š„ UX):
64
+ * - `onDownload`:ๆœ‰ๅ€ผๆ™‚,`status="completed"` ็š„็ถ  โœ“ icon ๅœจ row hover ๆ™‚
65
+ * ๆ›ๆˆ Download โ†“ button;click ่งธ็™ผ onDownloadใ€‚็„กๅ€ผไฟๆŒ passive ็ถ  โœ“ใ€‚
66
+ * - `onRetry`:ๆœ‰ๅ€ผๆ™‚,`status="error"` ็š„็ด… โœ— icon ๅœจ row hover ๆ™‚ๆ›ๆˆ RotateCw โŸฒ
67
+ * button;click ่งธ็™ผ onRetryใ€‚็„กๅ€ผไฟๆŒ passive ็ด… โœ—ใ€‚
68
+ *
69
+ * ไธ–็•Œ็ดšๅฐ็…ง:Gmail / Slack / Dropbox ้™„ไปถ็š„ passive ็‹€ๆ…‹ โ†’ hover ่ฎŠ action
70
+ * ็š„ UX,ไฝฟ็”จ่€…็Ÿฅ้“ๆช”ๆกˆ็‹€ๆ…‹ไธ”่ƒฝ็ซ‹ๅณ่กŒๅ‹•ใ€‚
71
+ */
72
+ onDownload?: () => void
73
+ onRetry?: () => void
74
+ }
75
+
76
+ // code-quality-allow: long-function โ€” foundational composite main body โ€” ๆ‹† sub-fn ๆœƒ่ค‡้›œๅŒ– local state / ref / context binding
77
+ const FileItem = React.forwardRef<HTMLDivElement, FileItemProps>(
78
+ (
79
+ {
80
+ name,
81
+ mode = 'compact',
82
+ status,
83
+ progress = 0,
84
+ description,
85
+ thumbnailSrc,
86
+ actions,
87
+ onClick,
88
+ onDownload,
89
+ onRetry,
90
+ className,
91
+ ...props
92
+ },
93
+ ref,
94
+ ) => {
95
+ const isRich = mode === 'rich'
96
+ const hasStatus = !!status
97
+ const statusConfig = status && status !== 'uploading' ? STATUS_ICON[status] : null
98
+ const progressWidth = status === 'completed' ? 100 : progress
99
+
100
+ // compact ๅชๆœ‰ error ๆ‰้กฏ็คบ description
101
+ const showDesc = isRich ? !!description : (status === 'error' && !!description)
102
+
103
+ // Hover ่กŒ็‚บ canonical(2026-04-23 user ๆ กๆบ–):**FileItem ๆฐธไธ้กฏ็คบ hover-bg**ใ€‚
104
+ // ไธ‰็จฎๅž‹ๆ…‹้ƒฝๆœ‰ๆฐธไน… visual anchor:rich = border card / compact Type B = bg-secondary /
105
+ // compact Type A = ๅบ•้ƒจ progress bar(ๅˆ†้š”็ทšๅž‹ affordance)โ€”โ€”ๅ†ๅŠ  hover-bg ๆ˜ฏ
106
+ // double-emphasis,่ฆ–่ฆบ้›œใ€‚ไธ–็•Œ็ดšๅ…ฑ่ญ˜(Slack / Notion / Figma / Gmail ็š†็„ก hover-bg):
107
+ // permanent-anchored ๅ…ƒไปถ hover ๅช้  cursor + action icon fade / border highlight,
108
+ // ไธ้  row bgใ€‚onClick ๅญ˜ๅœจๆ™‚ๅช็ตฆ `cursor-pointer`,affordance ้  cursor + ้ปžๆ“Š่กŒ็‚บๆœฌ่บซใ€‚
109
+ const hoverClass = onClick ? 'cursor-pointer' : ''
110
+
111
+ // ๆถˆ่ฒป ProgressBar ๅ…ƒไปถ(SSOT);ไธๅ†่‡ช roll barใ€‚
112
+ // height override:compact mode ็”จ 2px(ๆฅตๅฏ†้›† row layout),rich mode ็”จ้ ่จญ 4pxใ€‚
113
+ // ้€™ๆ˜ฏ ProgressBar `height` prop ็š„ๅ”ฏไธ€ๅˆๆณ• consumer(่ฆ‹ progress-bar.tsx docblock)ใ€‚
114
+ // a11y(2026-04-25 axe aria-progressbar-name):aria-label ็”จ file name ไฝœ contextใ€‚
115
+ const progressBar = hasStatus ? (
116
+ <ProgressBar
117
+ value={progressWidth}
118
+ status={PROGRESS_STATUS_MAP[status!]}
119
+ height={isRich ? undefined : 2}
120
+ aria-label={`${name} ไธŠๅ‚ณ้€ฒๅบฆ`}
121
+ />
122
+ ) : null
123
+
124
+ // suffix ๅฐ้ฝŠ label ็ฌฌไธ€่กŒ(item-anatomyใ€Œ24px ้–พๅ€ผๅฐ้ฝŠ่ฆๅ‰‡ใ€ๅฐ suffix canonical):
125
+ // icons 16 โ‰ค 24 ๅฑฌๅฐ suffix,็ตฑไธ€ `h-[1lh]` inline,ไธๅ›  desc wrap ๆ”นๅ…ฌๅผใ€‚
126
+ // ๅ…ฉ mode ๅŒๅ…ฌๅผ,่ทŸ item-anatomy ไธ€่‡ดใ€‚
127
+ const suffixAlign = 'h-[1lh]'
128
+
129
+ // Status slot ๅนพไฝ•(2026-04-23 user ็ตฑไธ€):rich + compact ้ƒฝ็”จ `var(--field-height-xs)`(24)
130
+ // ๅฎนๅ™จ,่ฃก้ข Button xs iconOnly variant="text"(auto data-unbounded)ใ€‚
131
+ // Compact ไธๅฝฑ้Ÿฟ row ้ซ˜ๅบฆ = suffix wrapper ็š„ data-unbounded CSS ่ฎ“ Button layout
132
+ // ๆ”ถๆ–‚ๅˆฐ 1lh(ๅŒ compact row ๅ…งๅฎน้ซ˜),่ฆ–่ฆบ/touch target ไป 24ใ€‚
133
+ const slotHw = 'var(--field-height-xs)'
134
+
135
+ const hoverAction =
136
+ status === 'completed' && onDownload ? { icon: Download, onClick: onDownload, label: 'ไธ‹่ผ‰' } :
137
+ status === 'error' && onRetry ? { icon: RotateCw, onClick: onRetry, label: '้‡่ฉฆ' } :
138
+ null
139
+
140
+ const statusSlot = statusConfig ? (
141
+ <span
142
+ data-unbounded="true"
143
+ className="relative inline-flex items-center justify-center shrink-0"
144
+ style={{ width: slotHw, height: slotHw }}
145
+ >
146
+ {/* Passive ็‹€ๆ…‹ icon:้ ่จญๅฏ่ฆ‹;่‹ฅๆœ‰ hover-swap,row-hover ๆ™‚ๆทกๅ‡บ */}
147
+ <statusConfig.icon
148
+ size={ICON_PX}
149
+ className={cn(
150
+ 'shrink-0 transition-opacity',
151
+ statusConfig.color,
152
+ hoverAction && 'group-hover/row:opacity-0',
153
+ )}
154
+ aria-hidden
155
+ />
156
+ {/* Active action:row-hover ๆ™‚ๆทกๅ…ฅ(rich + compact ๅŒ Button xs ็ตฑไธ€) */}
157
+ {hoverAction && (
158
+ <Button
159
+ variant="text"
160
+ size="xs"
161
+ iconOnly
162
+ startIcon={hoverAction.icon}
163
+ aria-label={hoverAction.label}
164
+ onClick={(e) => { e.stopPropagation(); hoverAction.onClick() }}
165
+ className="absolute inset-0 opacity-0 group-hover/row:opacity-100 transition-opacity"
166
+ />
167
+ )}
168
+ </span>
169
+ ) : null
170
+
171
+ const suffix = (
172
+ <div
173
+ className={cn(
174
+ 'flex items-center gap-2 shrink-0',
175
+ suffixAlign,
176
+ // data-unbounded chrome-canonical trick:let Button xs (24) live inside h-[1lh]
177
+ // wrapper(compact ~18.2 / rich ~18.2 scanning)without pushing row heightใ€‚
178
+ // ่ฆ–่ฆบ/hit area ไป 24,layout footprint ๆ”ถๆ–‚ๅˆฐ 1lhใ€‚ๅŒ overlay-surface
179
+ // ็š„ SurfaceHeader dismiss canonical(2026-04-22 v5)ใ€‚
180
+ // **child selector `[&>[data-unbounded]]`(้ž descendant)**:ๅช้‡ๅฐ suffix
181
+ // wrapper **็›ดๆŽฅๅญๅ…ƒ็ด **(statusSlot spanใ€actions Button)ๅฅ— margin,
182
+ // ้ฟๅ… status slot ๅ…ง้ƒจ hover-swap Button(nested)ไนŸๅฅ—้€ ๆˆ layout ่ทณๅ‹•ใ€‚
183
+ '[&>[data-unbounded]]:my-[calc((1lh-var(--field-height-xs))/2)]',
184
+ )}
185
+ >
186
+ {status === 'uploading' && isRich && (
187
+ <span className="text-fg-secondary tabular-nums">{progress}%</span>
188
+ )}
189
+ {statusSlot}
190
+ {actions}
191
+ </div>
192
+ )
193
+
194
+ // content row โ€” ๆถˆ่ฒป ItemContent primitive(ๅฐ่ฃ label + desc + mt-gap token SSOT)ใ€‚
195
+ // ๅ…ฉ mode ๅ…ฑ็”จ:primitive ๆ”น โ†’ ๅ…ฉ mode ๅŒๆญฅ,ไธ้œ€ grepใ€‚
196
+ // typography:scanning mode(2026-04-23 user ๆŒ‡็คบ)โ€”โ€” label body(14/1.3) + desc caption(12/1.3);
197
+ // row ๆœฌ่บซๅŠ  `leading-compact` ้…ๅˆ scanning idiom(ๅŒ MenuItem row)ใ€‚
198
+ const contentRow = (
199
+ <div className="flex items-start gap-2">
200
+ <ItemContent
201
+ label={name}
202
+ description={showDesc ? description : undefined}
203
+ mode="scanning"
204
+ descriptionTone={status === 'error' ? 'error' : 'secondary'}
205
+ />
206
+ {suffix}
207
+ </div>
208
+ )
209
+
210
+ // a11y(2026-04-25 nested-interactive fix):FileItem row ๅซ inner interactive
211
+ // (hover-swap action button / ProgressBar / Avatar hoverCard trigger)ใ€‚ๅŽŸๆœฌ
212
+ // role='button' + tabIndex=0 ๆ•ดๅˆ—ๅฏ้ต็›ค้ปž,่ˆ‡ inner buttons ๆง‹ๆˆ nested-interactive
213
+ // (axe serious)ใ€‚็งป้™ค row ๅฑค button semantic โ†’ mouse ไปๅฏ้ปž(onClick ไฟ็•™),
214
+ // ้ต็›ค user ็›ดๆŽฅ tab ๅˆฐ inner primary actionใ€‚Trade-off:ๅคฑๅŽปใ€Œๆ•ดๅˆ— Enter ้–‹ๅ•Ÿใ€
215
+ // ไฝ†ๆปฟ่ถณ WCAG;ไธ–็•Œ็ดšๅฐ็…ง:Slack message row / Notion page row ๅŒๆจกๅผ โ€” row ๅช
216
+ // mouse ้ปž,inner ๆœ‰ explicit ๆŒ‰้ˆ•่ฒ ่ฒฌ้ต็›คใ€‚
217
+ const rowA11y = {}
218
+
219
+ // Compact ้œๆ…‹่ƒŒๆ™ฏ(AR20):็„ก้€ฒๅบฆๆข โ†’ ้กฏ็คบ `bg-secondary`(= neutral-3)ไฝœใ€Œๆช”ๆกˆๅทฒไธŠๅ‚ณ /
220
+ // ้œๆ…‹ๅˆ—่กจใ€่ฆ–่ฆบๅ€้š”,่ทŸใ€ŒไธŠๅ‚ณไธญ(ๆœ‰ progress bar)ใ€ๅฐ็…งใ€‚hover ไธๆ”น bg(่ฆ‹ไธŠๆ–น
221
+ // hoverClass canonical:FileItem ๆฐธไธ้กฏ็คบ hover-bg)ใ€‚
222
+ // **็‚บไป€้บผ bg-secondary ไธ bg-neutral-3**:`bg-neutral-3` ไธๆ˜ฏๅˆๆณ• Tailwind utility
223
+ // (primitive token `--color-neutral-3` ๆฒ’็ถ“ `@theme inline` ๆฉ‹ๆŽฅ);`bg-secondary`
224
+ // ๆ˜ฏ semantic token ๆฉ‹ๆŽฅ็š„ utility(่ฆ‹ `tokens/color/semantic.css`@theme inline),
225
+ // ๅบ•่‰ฒๅŒๆจฃๆŒ‡ๅ‘ `--color-neutral-3`ใ€‚ๅฐ้ฝŠ Badge low / ProgressBar track SSOTใ€‚
226
+ const compactStaticBg = !progressBar ? 'bg-secondary' : ''
227
+
228
+ // โ”€โ”€ rich(ๅซ็ธฎๅœ–ๅฎŒๆ•ดๅ‘ˆ็พ)โ€”โ€”AR17 canonical:ๅŠ ้‚Šๆก† + gap-2 โ”€โ”€
229
+ // Rich mode ๆ˜ฏใ€Œๆช”ๆกˆ cardใ€้ขจๆ ผ,ๅค–ๆก†่ฎ“ๆฏๅ€‹ row ่ฆ–่ฆบไธŠๆ˜ฏ็จ็ซ‹ card
230
+ // (Slack / Notion / Linear attachment ๆ…ฃไพ‹)
231
+ if (isRich) {
232
+ return (
233
+ <div
234
+ ref={ref}
235
+ className={cn(
236
+ 'group/row flex items-start gap-2 px-3 py-3 w-full text-body leading-compact transition-colors',
237
+ 'border border-divider rounded-md bg-surface',
238
+ hoverClass,
239
+ className,
240
+ )}
241
+ onClick={onClick}
242
+ {...rowA11y}
243
+ {...props}
244
+ >
245
+ <Avatar src={thumbnailSrc} alt={name} size={AVATAR_SIZE} shape="square" className="shrink-0" />
246
+ {/* Rich layout invariant(2026-04-23 user ๆ กๆบ–):
247
+ - content col minHeight = AVATAR_SIZE(48),็ขบไฟ 1-line desc ๆ™‚ๅ…งๅฎน โ‰ฅ avatar ้ซ˜
248
+ - `justify-between`(ๆœ‰ bar)/`justify-center`(็„ก bar):
249
+ * 1-line desc:label ้ ‚ + progress bar ๅบ• **่‡ชๅ‹•ๅฐ้ฝŠ avatar ้ ‚/ๅบ•**
250
+ * ็„ก bar:content ๅž‚็›ด center ๅฐ้ฝŠ avatar ไธญ
251
+ - `gap-2`:desc โ†” progress bar **่‡ณๅฐ‘ 8px gap**(multi-line desc ๆ™‚ bar ๆบขๅ‡บไปไฟ 8px)
252
+ - row `items-start`:avatar top-align ไฝœ่ฆ–่ฆบๅผ•ๅฐŽ(tight-stack box ๅ…ง item ้‚Š็•Œ) */}
253
+ <div
254
+ className={cn(
255
+ 'flex flex-col flex-1 min-w-0 gap-2',
256
+ progressBar ? 'justify-between' : 'justify-center',
257
+ )}
258
+ style={{ minHeight: AVATAR_SIZE }}
259
+ >
260
+ {contentRow}
261
+ {progressBar}
262
+ </div>
263
+ </div>
264
+ )
265
+ }
266
+
267
+ // โ”€โ”€ compact: py-2 ๅฐ็จฑ, bar absolute ๅบ•้ƒจ โ”€โ”€
268
+ return (
269
+ <div
270
+ ref={ref}
271
+ className={cn(
272
+ 'group/row relative flex items-start gap-2 px-3 py-2 w-full text-body leading-compact transition-colors rounded-md',
273
+ compactStaticBg,
274
+ hoverClass,
275
+ className,
276
+ )}
277
+ onClick={onClick}
278
+ {...rowA11y}
279
+ {...props}
280
+ >
281
+ <ItemPrefix>
282
+ <Paperclip size={ICON_PX} className="shrink-0 text-fg-muted" aria-hidden />
283
+ </ItemPrefix>
284
+ {/* Compact ๅ…ฑ็”จ contentRow(via ItemContent primitive SSOT)โ€”โ€” ๅ…ˆๅ‰ inline
285
+ hand-craft ๅฐŽ่‡ด compact labelโ†”desc gap ่ทŸ rich ไธๅŒๆญฅใ€‚shared contentRow
286
+ ไฟ่ญ‰ๅ…ฉ mode ไฟฎ primitive ไธ€่™•ๅ…จๅŒๆญฅใ€‚ */}
287
+ <div className="flex flex-col flex-1 min-w-0">
288
+ {contentRow}
289
+ </div>
290
+
291
+ {/* ProgressBar: absolute ๅบ•้ƒจ, left ๅฐ้ฝŠ label(่ทณ้Ž icon + gap) */}
292
+ {progressBar && (
293
+ <div className="absolute bottom-0 right-3" style={{ left: `calc(0.75rem + ${ICON_PX}px + 0.5rem)` }}>
294
+ {progressBar}
295
+ </div>
296
+ )}
297
+ </div>
298
+ )
299
+ },
300
+ )
301
+ FileItem.displayName = 'FileItem'
302
+
303
+ // Story auto-compile metadata โ€” Phase 1 mechanical migration(2026-04-24)
304
+ // Phase 2 fill needed: purpose descriptions + when rationale + world-class refs
305
+ export const fileItemMeta = {
306
+ component: 'FileItem',
307
+ family: 2,
308
+ variants: {
309
+
310
+ },
311
+ sizes: {
312
+
313
+ },
314
+ states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
315
+ tokens: {
316
+ bg: ['bg-neutral-hover', 'bg-secondary', 'bg-surface'],
317
+ fg: ['text-fg-muted', 'text-fg-secondary'],
318
+ ring: [],
319
+ },
320
+ } as const
321
+
322
+ export { FileItem }
@@ -0,0 +1,326 @@
1
+ // @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.
2
+ import * as React from 'react'
3
+ import { Upload as UploadIcon, X } from 'lucide-react'
4
+ import { cn } from '@/lib/utils'
5
+ import { Empty } from '@/design-system/components/Empty/empty'
6
+ import { CircularProgress } from '@/design-system/components/CircularProgress/circular-progress'
7
+ import { FileItem } from '@/design-system/components/FileItem/file-item'
8
+ import { Button } from '@/design-system/components/Button/button'
9
+
10
+ /**
11
+ * FileUpload โ€” ๆ‹–ๆ”พ / ้ปžๆ“ŠไธŠๅ‚ณๅ€ๅกŠ
12
+ *
13
+ * ไธ–็•Œ็ดšๅฐ็…ง:Ant Design `Upload.Dragger`ใ€Polaris `DropZone`ใ€Material community MUI-File-Inputใ€‚
14
+ * ่ˆ‡ๆœฌ DS ๆ—ขๆœ‰ FileItem(้กฏ็คบๅทฒไธŠๅ‚ณๆช”ๆกˆ)้…ๅฐ โ€” ้€™่ฃก ownใ€ŒไธŠๅ‚ณ่งธ็™ผ + ๆ‹–ๆ”พๅตๆธฌใ€,
15
+ * ไธŠๅ‚ณๅพŒ็š„ๆช”ๆกˆๆธ…ๅ–ฎ้กฏ็คบไบค็ตฆ consumer ็”จ FileItem ๆธฒๆŸ“ใ€‚
16
+ *
17
+ * โ”€โ”€ 4 ็‹€ๆ…‹ โ”€โ”€
18
+ * idle (default) โ€” border-dashed border-divider bg-surface
19
+ * drag-over โ€” border-dashed border-primary bg-primary-subtle
20
+ * loading โ€” ไธŠๅ‚ณไธญ(async)้กฏ็คบ CircularProgress,้˜ปๆ“‹ๆ–ฐไบ’ๅ‹•
21
+ * disabled โ€” opacity-disabled pointer-events-none
22
+ *
23
+ * โ”€โ”€ children ๆ’ๆงฝ โ”€โ”€
24
+ * ้ ่จญๆธฒๆŸ“ `<Empty icon={Upload} title description />` โ€” ้‡็”จ Empty ๅ…ƒไปถ own
25
+ * ็š„ใ€Œicon + title + description ๅž‚็›ดๅฑ…ไธญใ€SSOT ้ฟๅ…่ฆ–่ฆบๆผ‚็งปใ€‚Empty ๆ”นๅญ—้ซ” /
26
+ * gap / icon ๅฐบๅฏธๆ™‚ FileUpload ่‡ชๅ‹•่ทŸ้€ฒใ€‚่‹ฅ consumer ๅ‚ณ children ๅ‰‡ๆ•ดๅ€‹่ฆ†ๅฏซใ€‚
27
+ *
28
+ * โ”€โ”€ API โ”€โ”€
29
+ * onUpload: ไฝฟ็”จ่€…้ธๅ–ๆˆ–ๆ‹–ๆ”พๆช”ๆกˆๆ™‚่งธ็™ผ,ๅ›žๅ‚ณ File[](่‡ณๅฐ‘ 1 ๅ€‹)ใ€‚
30
+ * multiple: ๅ…่จฑๅคšๆช”ใ€‚้ ่จญ false(ๅ–ฎๆช”)ใ€‚
31
+ * accept: MIME filter(ไพ‹ "image/*,.pdf"),ๅ‚ณ็ตฆ <input type=file>ใ€‚
32
+ * maxSize: ๅ–ฎๆช”ๆœ€ๅคง bytes;่ถ…้Ž้œ้ป˜ๅฟฝ็•ฅ(consumer ่‹ฅ้œ€่ฆ้Œฏ่ชคๆ็คบ,่ตฐ onReject)ใ€‚
33
+ * onReject: ่ขซ maxSize / accept ๆ“‹ไธ‹็š„ๆช”ๆกˆ(ๆไพ›้Œฏ่ชค่จŠๆฏ้กฏ็คบๆฉŸๆœƒ)ใ€‚
34
+ */
35
+
36
+ /**
37
+ * Uploaded / uploading file status item(for `files` prop)ใ€‚
38
+ * Consumer ๆŒ state(progress / status),FileUpload ๅช่ฒ ่ฒฌๆธฒๆŸ“ใ€‚
39
+ */
40
+ export interface FileUploadStatus {
41
+ id: string
42
+ name: string
43
+ /** bytes */
44
+ size?: number
45
+ /** Upload ้€ฒๅบฆ(0-100)โ€” uploading ๆ™‚้กฏ็คบ progress bar */
46
+ progress?: number
47
+ status?: 'uploading' | 'completed' | 'error'
48
+ /** Error ่จŠๆฏ / size ็ญ‰ description */
49
+ description?: React.ReactNode
50
+ /** Thumbnail URL for rich mode */
51
+ thumbnailSrc?: string
52
+ }
53
+
54
+ export interface FileUploadProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onDrop'> {
55
+ onUpload?: (files: File[]) => void
56
+ onReject?: (files: File[], reason: 'size' | 'type') => void
57
+ multiple?: boolean
58
+ accept?: string
59
+ maxSize?: number
60
+ disabled?: boolean
61
+ /**
62
+ * Loading ็‹€ๆ…‹(async ไธŠๅ‚ณ / ไผบๆœๅ™จ่™•็†ไธญ)ใ€‚
63
+ * - ้กฏ็คบ CircularProgress ๅ–ไปฃ้ ่จญ Empty ๅ…งๅฎน
64
+ * - ้˜ปๆ“‹ๆ–ฐ้ปžๆ“Š / drag ไบ‹ไปถ(้ฟๅ… double-submit)
65
+ * - ๅฎฃๅ‘Š `aria-busy="true"` ่ฎ“ screen reader ๆ„Ÿ็Ÿฅ่™•็†ไธญ
66
+ * - Consumer ่ฒ ่ฒฌๅœจไธŠๅ‚ณๅฎŒๆˆๅพŒ่‡ชๅทฑๅˆ‡ๅ›ž `loading={false}`
67
+ */
68
+ loading?: boolean
69
+ /** Loading ็‹€ๆ…‹็š„ๆ–‡ๅญ—ๆจ™้กŒ(้ ่จญใ€ŒไธŠๅ‚ณไธญโ€ฆใ€) */
70
+ loadingTitle?: string
71
+ /** ๆจ™้กŒๆ–‡ๅญ—(้ ่จญใ€ŒClick or drag file here to uploadใ€) */
72
+ title?: string
73
+ /** ่ชชๆ˜Žๆ–‡ๅญ—(้ ่จญใ€ŒSupport for a single or bulk uploadใ€) */
74
+ description?: string
75
+ /** ่‹ฅๅ‚ณๅ…ฅ children,่ฆ†ๅฏซ้ ่จญ Empty ็ตๆง‹ */
76
+ children?: React.ReactNode
77
+ /**
78
+ * Uploaded / uploading ๆช”ๆกˆๆธ…ๅ–ฎใ€‚ๅ‚ณๅ…ฅ โ†’ FileUpload ๅœจ drop zone ไธ‹ๆ–นๆธฒๆŸ“ๅˆ—่กจใ€‚
79
+ * ไธๅ‚ณ โ†’ ไธ้กฏ็คบ(consumer ๅฏ่‡ช่กŒ็”จ FileItem ็ต„ๆˆ,pre-2026-04-24 ่กŒ็‚บ)ใ€‚
80
+ * ๆฏ้ …ๆœ‰ status ็‹€ๆ…‹ๆœƒๅฐๆ‡‰ icon:
81
+ * - `uploading`:CircularProgress(+ progress bar ่‹ฅ progress ็ตฆ)
82
+ * - `completed`:็ถ ่‰ฒ โœ“(success ็‹€ๆ…‹่ฆ–่ฆบ็ขบ่ช)
83
+ * - `error`:็ด…่‰ฒ โœ—(+ description ้กฏ็คบ้Œฏ่ชค่จŠๆฏ)
84
+ */
85
+ files?: FileUploadStatus[]
86
+ /** File list ๆฏ้ …้กฏ็คบๆจกๅผใ€‚Default: 'compact'(ๅ–ฎ่กŒ);'rich' = ๅซ thumbnail / size / progress bar */
87
+ fileListMode?: 'compact' | 'rich'
88
+ /** File list ็งป้™ค callbackใ€‚ๆœ‰ๅ€ผ โ†’ ๆฏ้ …ๅณๅด้กฏ็คบ X dismiss button;็„ก โ†’ ไธๅฏ็งป้™ค(view-only) */
89
+ onRemove?: (id: string) => void
90
+ /** File list dismiss button ARIA label templateใ€‚้ ่จญ `็งป้™ค {name}`ใ€‚For i18n. */
91
+ removeAriaLabel?: (name: string) => string
92
+ }
93
+
94
+ // code-quality-allow: long-function โ€” foundational composite main body โ€” ๆ‹† sub-fn ๆœƒ่ค‡้›œๅŒ– local state / ref / context binding
95
+ const FileUpload = React.forwardRef<HTMLDivElement, FileUploadProps>(
96
+ (
97
+ {
98
+ onUpload,
99
+ onReject,
100
+ multiple = false,
101
+ accept,
102
+ maxSize,
103
+ disabled = false,
104
+ loading = false,
105
+ loadingTitle = 'ไธŠๅ‚ณไธญโ€ฆ', // i18n-allow: DS default; consumer override via loadingTitle prop
106
+ title = 'Click or drag file here to upload', // i18n-allow: DS default; consumer override via title prop
107
+ description = multiple ? 'Support for a single or bulk upload' : 'Support for a single file upload', // i18n-allow: DS default; consumer override via description prop
108
+ children,
109
+ files,
110
+ fileListMode = 'compact',
111
+ onRemove,
112
+ removeAriaLabel = (name: string) => `็งป้™ค ${name}`, // i18n-allow: DS default; consumer override via removeAriaLabel prop
113
+ className,
114
+ onClick,
115
+ ...props
116
+ },
117
+ ref,
118
+ ) => {
119
+ const inputRef = React.useRef<HTMLInputElement>(null)
120
+ const [isDragOver, setDragOver] = React.useState(false)
121
+
122
+ const filterAndDispatch = (files: FileList | null) => {
123
+ if (!files || files.length === 0) return
124
+ const accepted: File[] = []
125
+ const rejectedBySize: File[] = []
126
+ const rejectedByType: File[] = []
127
+
128
+ Array.from(files).forEach((f) => {
129
+ if (maxSize != null && f.size > maxSize) {
130
+ rejectedBySize.push(f)
131
+ return
132
+ }
133
+ if (accept && !matchAccept(f, accept)) {
134
+ rejectedByType.push(f)
135
+ return
136
+ }
137
+ accepted.push(f)
138
+ })
139
+
140
+ if (rejectedBySize.length) onReject?.(rejectedBySize, 'size')
141
+ if (rejectedByType.length) onReject?.(rejectedByType, 'type')
142
+ if (accepted.length) onUpload?.(multiple ? accepted : accepted.slice(0, 1))
143
+ }
144
+
145
+ const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
146
+ if (!disabled) inputRef.current?.click()
147
+ onClick?.(e)
148
+ }
149
+
150
+ // State ๅ„ชๅ…ˆๅบ:disabled > loading > drag-over > idle(disabled ๆœ€็กฌ,loading ๆฌกไน‹)
151
+ const state = disabled ? 'disabled' : loading ? 'loading' : isDragOver ? 'drag-over' : 'idle'
152
+ const isBlocked = disabled || loading
153
+
154
+ const hasFiles = Array.isArray(files) && files.length > 0
155
+
156
+ const fileListNode = hasFiles ? (
157
+ <ul
158
+ className={cn(
159
+ // stack vertically with consistent gap;bg-surface ๅœจๅฎนๅ™จๅค–็š„ chrome / consumer bg ไน‹ไธŠ
160
+ 'flex flex-col gap-2 w-full',
161
+ 'mt-3',
162
+ )}
163
+ aria-label="Uploaded files"
164
+ >
165
+ {files!.map((f) => (
166
+ <li key={f.id} className="list-none">
167
+ <FileItem
168
+ mode={fileListMode}
169
+ name={f.name}
170
+ status={f.status}
171
+ progress={f.progress}
172
+ description={f.description ?? (f.size != null ? formatBytes(f.size) : undefined)}
173
+ thumbnailSrc={f.thumbnailSrc}
174
+ actions={
175
+ onRemove ? (
176
+ // Collection remove(per-file)โ€” ไธๆ˜ฏ dismiss surface,ๆ•…ไธๅฅ— `dismiss` propใ€‚
177
+ // ่ฆ–่ฆบ่ˆ‡ dismiss ไธ€่‡ด(text variant + fg-muted dim)โ€” ๅฐ้ฝŠ inline-action.spec.md
178
+ // ใ€ŒDismiss canonical โ€” X close onlyใ€L249-251:onRemove callback ไธ่งธ็™ผ dismiss propใ€‚
179
+ <Button
180
+ iconOnly
181
+ variant="text"
182
+ size="xs"
183
+ startIcon={X}
184
+ aria-label={removeAriaLabel(f.name)}
185
+ onClick={(e) => {
186
+ e.stopPropagation()
187
+ onRemove(f.id)
188
+ }}
189
+ className="text-fg-muted hover:text-foreground"
190
+ />
191
+ ) : undefined
192
+ }
193
+ />
194
+ </li>
195
+ ))}
196
+ </ul>
197
+ ) : null
198
+
199
+ return (
200
+ <div ref={ref} className={cn('w-full', hasFiles && 'flex flex-col')}>
201
+ <div
202
+ role="button"
203
+ tabIndex={isBlocked ? -1 : 0}
204
+ aria-disabled={disabled || undefined}
205
+ aria-busy={loading || undefined}
206
+ data-state={state}
207
+ onClick={handleClick}
208
+ onKeyDown={(e) => {
209
+ if (isBlocked) return
210
+ if (e.key === 'Enter' || e.key === ' ') {
211
+ e.preventDefault()
212
+ inputRef.current?.click()
213
+ }
214
+ }}
215
+ onDragEnter={(e) => {
216
+ if (isBlocked) return
217
+ e.preventDefault()
218
+ setDragOver(true)
219
+ }}
220
+ onDragLeave={(e) => {
221
+ if (isBlocked) return
222
+ e.preventDefault()
223
+ setDragOver(false)
224
+ }}
225
+ onDragOver={(e) => {
226
+ if (isBlocked) return
227
+ e.preventDefault()
228
+ }}
229
+ onDrop={(e) => {
230
+ if (isBlocked) return
231
+ e.preventDefault()
232
+ setDragOver(false)
233
+ filterAndDispatch(e.dataTransfer.files)
234
+ }}
235
+ className={cn(
236
+ // ๅฏฌๅบฆ w-full ๅกซๆปฟ consumer ๅฎนๅ™จ(user ๆ˜Ž็คบใ€Œๅฏฌๅบฆๅกซๆปฟใ€);้ซ˜ๅบฆ็”ฑ padding + ๅ…งๅฎน็‰ฉๆฑบๅฎš(ไธๅ›บๅฎš h)
237
+ 'flex flex-col items-center justify-center gap-2 text-center w-full',
238
+ // ๅฐ็จฑ padding p-[var(--layout-space-loose)]:ๅ››้‚Š็ญ‰่ท,density-aware(md=24px / lg=32px),ๅฐ้ฝŠ DS chrome padding canonicalใ€‚
239
+ // ไธๅ†็กฌๅฏซ px-6 py-10(ไธๅฐ็จฑ+้ž token)ใ€‚ๅ…งๅฎน็‰ฉ(icon + title + description)ๅž‚็›ดๅ †็–Š็”ฑ gap-2 ๆŽงๅˆถ
240
+ 'rounded-md border-2 border-dashed p-[var(--layout-space-loose)]',
241
+ 'cursor-pointer transition-colors',
242
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
243
+ // idle
244
+ 'border-divider bg-surface hover:bg-neutral-hover',
245
+ // drag-over
246
+ 'data-[state=drag-over]:border-primary data-[state=drag-over]:bg-primary-subtle data-[state=drag-over]:hover:bg-primary-subtle',
247
+ // loading(้˜ปๆ“‹ๆ–ฐไบ’ๅ‹•ไฝ†ไธ opacity-disabled โ€” ้ฟๅ…่ทŸ disabled ่ฆ–่ฆบๆ’ž,ไฟๆŒใ€Œ่™•็†ไธญใ€่ชžๆ„)
248
+ 'data-[state=loading]:cursor-progress data-[state=loading]:pointer-events-none',
249
+ // disabled
250
+ 'data-[state=disabled]:opacity-disabled data-[state=disabled]:pointer-events-none data-[state=disabled]:cursor-not-allowed',
251
+ className,
252
+ )}
253
+ {...props}
254
+ >
255
+ <input
256
+ ref={inputRef}
257
+ type="file"
258
+ className="hidden"
259
+ multiple={multiple}
260
+ accept={accept}
261
+ disabled={disabled}
262
+ onChange={(e) => filterAndDispatch(e.target.files)}
263
+ />
264
+ {loading ? (
265
+ <Empty
266
+ icon={<CircularProgress size={48} />}
267
+ title={loadingTitle}
268
+ />
269
+ ) : (
270
+ children ?? (
271
+ <Empty
272
+ icon={UploadIcon}
273
+ title={title}
274
+ description={description}
275
+ />
276
+ )
277
+ )}
278
+ </div>
279
+ {fileListNode}
280
+ </div>
281
+ )
282
+ },
283
+ )
284
+ FileUpload.displayName = 'FileUpload'
285
+
286
+ // โ”€โ”€ helper: bytes formatter โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
287
+ function formatBytes(n: number): string {
288
+ if (n < 1024) return `${n} B`
289
+ if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`
290
+ if (n < 1024 * 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(1)} MB`
291
+ return `${(n / (1024 * 1024 * 1024)).toFixed(1)} GB`
292
+ }
293
+
294
+ // โ”€โ”€ helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
295
+
296
+ function matchAccept(file: File, accept: string): boolean {
297
+ const patterns = accept.split(',').map((s) => s.trim().toLowerCase())
298
+ const fileName = file.name.toLowerCase()
299
+ const fileType = file.type.toLowerCase()
300
+ return patterns.some((p) => {
301
+ if (p.startsWith('.')) return fileName.endsWith(p) // ๅ‰ฏๆช”ๅ e.g. ".pdf"
302
+ if (p.endsWith('/*')) return fileType.startsWith(p.slice(0, -1)) // e.g. "image/*"
303
+ return fileType === p // ๅฎŒๆ•ด MIME
304
+ })
305
+ }
306
+
307
+ // Story auto-compile metadata โ€” Phase 1 mechanical migration(2026-04-24)
308
+ // Phase 2 fill needed: purpose descriptions + when rationale + world-class refs
309
+ export const fileUploadMeta = {
310
+ component: 'FileUpload',
311
+ family: null, // non-family composite / overlay / layout
312
+ variants: {
313
+
314
+ },
315
+ sizes: {
316
+
317
+ },
318
+ states: ['default', 'hover', 'active', 'focus-visible', 'disabled'],
319
+ tokens: {
320
+ bg: ['bg-neutral-hover', 'bg-primary-subtle', 'bg-surface'],
321
+ fg: [],
322
+ ring: ['ring-ring'],
323
+ },
324
+ } as const
325
+
326
+ export { FileUpload }