@chenzy-design/svelte 0.1.0 → 0.2.0

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 (476) hide show
  1. package/dist/components.json +1 -1
  2. package/package.json +7 -8
  3. package/src/_floating/use-floating.ts +0 -208
  4. package/src/anchor/Anchor.a11y.test.ts +0 -49
  5. package/src/anchor/Anchor.kbd.test.ts +0 -70
  6. package/src/anchor/Anchor.svelte +0 -359
  7. package/src/anchor/AnchorKbdFixture.svelte +0 -24
  8. package/src/anchor/index.ts +0 -3
  9. package/src/anchor/meta.ts +0 -70
  10. package/src/anchor/types.ts +0 -8
  11. package/src/autocomplete/AutoComplete.a11y.test.ts +0 -49
  12. package/src/autocomplete/AutoComplete.kbd.test.ts +0 -69
  13. package/src/autocomplete/AutoComplete.svelte +0 -706
  14. package/src/autocomplete/AutoCompleteKbdFixture.svelte +0 -24
  15. package/src/autocomplete/index.ts +0 -2
  16. package/src/autocomplete/meta.ts +0 -41
  17. package/src/avatar/Avatar.a11y.test.ts +0 -37
  18. package/src/avatar/Avatar.svelte +0 -315
  19. package/src/avatar/AvatarGroup.svelte +0 -142
  20. package/src/avatar/context.ts +0 -21
  21. package/src/avatar/index.ts +0 -10
  22. package/src/avatar/meta.ts +0 -73
  23. package/src/back-top/BackTop.a11y.test.ts +0 -40
  24. package/src/back-top/BackTop.svelte +0 -314
  25. package/src/back-top/index.ts +0 -2
  26. package/src/back-top/meta.ts +0 -108
  27. package/src/badge/Badge.a11y.test.ts +0 -35
  28. package/src/badge/Badge.svelte +0 -328
  29. package/src/badge/BadgeA11yFixture.svelte +0 -18
  30. package/src/badge/index.ts +0 -2
  31. package/src/badge/meta.ts +0 -62
  32. package/src/banner/Banner.a11y.test.ts +0 -48
  33. package/src/banner/Banner.svelte +0 -368
  34. package/src/banner/index.ts +0 -3
  35. package/src/banner/meta.ts +0 -121
  36. package/src/breadcrumb/Breadcrumb.a11y.test.ts +0 -35
  37. package/src/breadcrumb/Breadcrumb.kbd.test.ts +0 -45
  38. package/src/breadcrumb/Breadcrumb.svelte +0 -414
  39. package/src/breadcrumb/BreadcrumbKbdFixture.svelte +0 -23
  40. package/src/breadcrumb/Item.svelte +0 -77
  41. package/src/breadcrumb/context.ts +0 -27
  42. package/src/breadcrumb/index.ts +0 -21
  43. package/src/breadcrumb/meta.ts +0 -128
  44. package/src/breadcrumb/types.ts +0 -4
  45. package/src/button/Button.a11y.test.ts +0 -54
  46. package/src/button/Button.svelte +0 -176
  47. package/src/button/index.ts +0 -2
  48. package/src/button/meta.ts +0 -28
  49. package/src/calendar/Calendar.a11y.test.ts +0 -51
  50. package/src/calendar/Calendar.kbd.test.ts +0 -59
  51. package/src/calendar/Calendar.svelte +0 -1344
  52. package/src/calendar/CalendarKbdFixture.svelte +0 -23
  53. package/src/calendar/index.ts +0 -3
  54. package/src/calendar/meta.ts +0 -117
  55. package/src/card/Card.a11y.test.ts +0 -38
  56. package/src/card/Card.svelte +0 -341
  57. package/src/card/CardMeta.svelte +0 -60
  58. package/src/card/index.ts +0 -8
  59. package/src/card/meta.ts +0 -83
  60. package/src/carousel/Carousel.a11y.test.ts +0 -53
  61. package/src/carousel/Carousel.kbd.test.ts +0 -67
  62. package/src/carousel/Carousel.svelte +0 -806
  63. package/src/carousel/CarouselA11yFixture.svelte +0 -25
  64. package/src/carousel/CarouselKbdFixture.svelte +0 -24
  65. package/src/carousel/index.ts +0 -2
  66. package/src/carousel/meta.ts +0 -74
  67. package/src/cascader/Cascader.a11y.test.ts +0 -59
  68. package/src/cascader/Cascader.kbd.test.ts +0 -56
  69. package/src/cascader/Cascader.svelte +0 -1570
  70. package/src/cascader/CascaderKbdFixture.svelte +0 -31
  71. package/src/cascader/index.ts +0 -3
  72. package/src/cascader/meta.ts +0 -57
  73. package/src/cascader/types.ts +0 -9
  74. package/src/checkbox/Checkbox.svelte +0 -281
  75. package/src/checkbox/CheckboxGroup.a11y.test.ts +0 -43
  76. package/src/checkbox/CheckboxGroup.kbd.test.ts +0 -40
  77. package/src/checkbox/CheckboxGroup.svelte +0 -122
  78. package/src/checkbox/CheckboxGroupKbdFixture.svelte +0 -20
  79. package/src/checkbox/context.ts +0 -31
  80. package/src/checkbox/index.ts +0 -4
  81. package/src/checkbox/meta.ts +0 -67
  82. package/src/collapse/Collapse.a11y.test.ts +0 -53
  83. package/src/collapse/Collapse.kbd.test.ts +0 -89
  84. package/src/collapse/Collapse.svelte +0 -406
  85. package/src/collapse/CollapseA11yFixture.svelte +0 -27
  86. package/src/collapse/CollapseKbdFixture.svelte +0 -25
  87. package/src/collapse/CollapsePanel.svelte +0 -102
  88. package/src/collapse/context.ts +0 -54
  89. package/src/collapse/index.ts +0 -17
  90. package/src/collapse/meta.ts +0 -79
  91. package/src/collapse/types.ts +0 -5
  92. package/src/color-picker/ColorPicker.a11y.test.ts +0 -60
  93. package/src/color-picker/ColorPicker.kbd.test.ts +0 -73
  94. package/src/color-picker/ColorPicker.svelte +0 -985
  95. package/src/color-picker/ColorPickerKbdFixture.svelte +0 -25
  96. package/src/color-picker/index.ts +0 -2
  97. package/src/color-picker/meta.ts +0 -47
  98. package/src/config-provider/ConfigProvider.svelte +0 -227
  99. package/src/config-provider/context.ts +0 -29
  100. package/src/config-provider/index.ts +0 -48
  101. package/src/config-provider/meta.ts +0 -128
  102. package/src/date-picker/DatePicker.a11y.test.ts +0 -45
  103. package/src/date-picker/DatePicker.kbd.test.ts +0 -71
  104. package/src/date-picker/DatePicker.svelte +0 -1798
  105. package/src/date-picker/DatePickerKbdFixture.svelte +0 -26
  106. package/src/date-picker/RangePicker.kbd.test.ts +0 -69
  107. package/src/date-picker/RangePicker.svelte +0 -775
  108. package/src/date-picker/RangePickerKbdFixture.svelte +0 -30
  109. package/src/date-picker/index.ts +0 -4
  110. package/src/date-picker/meta.ts +0 -67
  111. package/src/date-picker/range-meta.ts +0 -44
  112. package/src/descriptions/Descriptions.a11y.test.ts +0 -33
  113. package/src/descriptions/Descriptions.svelte +0 -287
  114. package/src/descriptions/DescriptionsItem.svelte +0 -43
  115. package/src/descriptions/context.ts +0 -21
  116. package/src/descriptions/index.ts +0 -16
  117. package/src/descriptions/meta.ts +0 -45
  118. package/src/descriptions/types.ts +0 -6
  119. package/src/divider/Divider.a11y.test.ts +0 -23
  120. package/src/divider/Divider.svelte +0 -154
  121. package/src/divider/index.ts +0 -2
  122. package/src/divider/meta.ts +0 -23
  123. package/src/drawer/Drawer.a11y.test.ts +0 -41
  124. package/src/drawer/Drawer.kbd.test.ts +0 -67
  125. package/src/drawer/Drawer.svelte +0 -554
  126. package/src/drawer/DrawerKbdFixture.svelte +0 -28
  127. package/src/drawer/index.ts +0 -2
  128. package/src/drawer/meta.ts +0 -127
  129. package/src/dropdown/Dropdown.a11y.test.ts +0 -46
  130. package/src/dropdown/Dropdown.kbd.test.ts +0 -56
  131. package/src/dropdown/Dropdown.svelte +0 -573
  132. package/src/dropdown/DropdownA11yFixture.svelte +0 -24
  133. package/src/dropdown/DropdownDivider.svelte +0 -17
  134. package/src/dropdown/DropdownItem.svelte +0 -127
  135. package/src/dropdown/DropdownItemNode.svelte +0 -355
  136. package/src/dropdown/DropdownKbdFixture.svelte +0 -26
  137. package/src/dropdown/DropdownMenu.svelte +0 -24
  138. package/src/dropdown/DropdownSubMenu.svelte +0 -212
  139. package/src/dropdown/DropdownTitle.svelte +0 -34
  140. package/src/dropdown/context.ts +0 -13
  141. package/src/dropdown/index.ts +0 -36
  142. package/src/dropdown/meta.ts +0 -97
  143. package/src/dropdown/types.test.ts +0 -50
  144. package/src/dropdown/types.ts +0 -67
  145. package/src/empty/Empty.a11y.test.ts +0 -24
  146. package/src/empty/Empty.svelte +0 -304
  147. package/src/empty/index.ts +0 -2
  148. package/src/empty/meta.ts +0 -41
  149. package/src/form/Field.svelte +0 -492
  150. package/src/form/FieldArray.svelte +0 -75
  151. package/src/form/Form.a11y.test.ts +0 -39
  152. package/src/form/Form.svelte +0 -243
  153. package/src/form/FormA11yFixture.svelte +0 -31
  154. package/src/form/FormCascader.svelte +0 -82
  155. package/src/form/FormCheckbox.svelte +0 -83
  156. package/src/form/FormDatePicker.svelte +0 -80
  157. package/src/form/FormErrorMessage.svelte +0 -44
  158. package/src/form/FormInput.svelte +0 -95
  159. package/src/form/FormLabel.svelte +0 -46
  160. package/src/form/FormRadio.svelte +0 -83
  161. package/src/form/FormRating.svelte +0 -85
  162. package/src/form/FormSection.svelte +0 -45
  163. package/src/form/FormSelect.svelte +0 -96
  164. package/src/form/FormSlider.svelte +0 -95
  165. package/src/form/FormSlot.svelte +0 -51
  166. package/src/form/FormSwitch.svelte +0 -82
  167. package/src/form/FormTagInput.svelte +0 -79
  168. package/src/form/FormTreeSelect.svelte +0 -85
  169. package/src/form/FormUpload.svelte +0 -92
  170. package/src/form/context.ts +0 -47
  171. package/src/form/index.ts +0 -22
  172. package/src/form/meta.ts +0 -85
  173. package/src/grid/Col.svelte +0 -142
  174. package/src/grid/Grid.a11y.test.ts +0 -14
  175. package/src/grid/GridA11yFixture.svelte +0 -12
  176. package/src/grid/Row.svelte +0 -116
  177. package/src/grid/index.ts +0 -3
  178. package/src/grid/meta.ts +0 -72
  179. package/src/grid/use-breakpoint.svelte.ts +0 -48
  180. package/src/highlight/Highlight.a11y.test.ts +0 -25
  181. package/src/highlight/Highlight.svelte +0 -99
  182. package/src/highlight/index.ts +0 -2
  183. package/src/highlight/meta.ts +0 -80
  184. package/src/icon/Icon.svelte +0 -156
  185. package/src/icon/index.ts +0 -2
  186. package/src/icon/meta.ts +0 -41
  187. package/src/image/Image.a11y.test.ts +0 -30
  188. package/src/image/Image.svelte +0 -387
  189. package/src/image/ImagePreview.kbd.test.ts +0 -52
  190. package/src/image/ImagePreview.svelte +0 -309
  191. package/src/image/ImagePreviewGroup.svelte +0 -93
  192. package/src/image/ImagePreviewKbdFixture.svelte +0 -32
  193. package/src/image/context.ts +0 -26
  194. package/src/image/index.ts +0 -15
  195. package/src/image/meta.ts +0 -131
  196. package/src/index.ts +0 -208
  197. package/src/input/Input.a11y.test.ts +0 -58
  198. package/src/input/Input.svelte +0 -505
  199. package/src/input/index.ts +0 -2
  200. package/src/input/meta.ts +0 -40
  201. package/src/input-number/InputNumber.a11y.test.ts +0 -43
  202. package/src/input-number/InputNumber.kbd.test.ts +0 -41
  203. package/src/input-number/InputNumber.svelte +0 -674
  204. package/src/input-number/InputNumberKbdFixture.svelte +0 -15
  205. package/src/input-number/index.ts +0 -2
  206. package/src/input-number/meta.ts +0 -65
  207. package/src/layout/Content.svelte +0 -37
  208. package/src/layout/Footer.svelte +0 -49
  209. package/src/layout/Header.svelte +0 -46
  210. package/src/layout/Layout.a11y.test.ts +0 -34
  211. package/src/layout/Layout.svelte +0 -60
  212. package/src/layout/LayoutA11yFixture.svelte +0 -21
  213. package/src/layout/Sider.svelte +0 -207
  214. package/src/layout/index.ts +0 -26
  215. package/src/layout/meta.ts +0 -116
  216. package/src/list/List.a11y.test.ts +0 -69
  217. package/src/list/List.bench.ts +0 -26
  218. package/src/list/List.kbd.test.ts +0 -71
  219. package/src/list/List.svelte +0 -920
  220. package/src/list/ListA11yFixture.svelte +0 -38
  221. package/src/list/ListBenchFixture.svelte +0 -22
  222. package/src/list/ListItem.svelte +0 -175
  223. package/src/list/ListKbdFixture.svelte +0 -31
  224. package/src/list/ListMeta.svelte +0 -73
  225. package/src/list/context.ts +0 -39
  226. package/src/list/index.ts +0 -21
  227. package/src/list/meta.ts +0 -99
  228. package/src/locale-provider/LocaleProvider.svelte +0 -110
  229. package/src/locale-provider/context.ts +0 -22
  230. package/src/locale-provider/index.ts +0 -21
  231. package/src/locale-provider/meta.ts +0 -93
  232. package/src/locale-provider/use-locale.ts +0 -25
  233. package/src/lottie-icon/LottieIcon.svelte +0 -330
  234. package/src/lottie-icon/index.ts +0 -9
  235. package/src/lottie-icon/meta.ts +0 -162
  236. package/src/menu/Menu.a11y.test.ts +0 -54
  237. package/src/menu/Menu.kbd.test.ts +0 -69
  238. package/src/menu/Menu.svelte +0 -762
  239. package/src/menu/MenuKbdFixture.svelte +0 -22
  240. package/src/menu/MenuPopupNode.svelte +0 -525
  241. package/src/menu/index.ts +0 -4
  242. package/src/menu/meta.ts +0 -137
  243. package/src/menu/types.ts +0 -120
  244. package/src/meta.test.ts +0 -173
  245. package/src/modal/ConfirmModal.svelte +0 -173
  246. package/src/modal/Modal.a11y.test.ts +0 -46
  247. package/src/modal/Modal.kbd.test.ts +0 -65
  248. package/src/modal/Modal.svelte +0 -511
  249. package/src/modal/ModalKbdFixture.svelte +0 -24
  250. package/src/modal/command.svelte.ts +0 -103
  251. package/src/modal/index.ts +0 -30
  252. package/src/modal/meta.ts +0 -165
  253. package/src/modal/z-stack.ts +0 -26
  254. package/src/notification/NotificationContainer.svelte +0 -192
  255. package/src/notification/NotificationItem.a11y.test.ts +0 -73
  256. package/src/notification/NotificationItem.svelte +0 -368
  257. package/src/notification/index.ts +0 -9
  258. package/src/notification/meta.ts +0 -120
  259. package/src/notification/store.ts +0 -191
  260. package/src/overflow-list/OverflowList.a11y.test.ts +0 -46
  261. package/src/overflow-list/OverflowList.kbd.test.ts +0 -34
  262. package/src/overflow-list/OverflowList.svelte +0 -539
  263. package/src/overflow-list/OverflowListA11yFixture.svelte +0 -22
  264. package/src/overflow-list/OverflowListKbdFixture.svelte +0 -21
  265. package/src/overflow-list/index.ts +0 -2
  266. package/src/overflow-list/meta.ts +0 -138
  267. package/src/pagination/Pagination.a11y.test.ts +0 -62
  268. package/src/pagination/Pagination.kbd.test.ts +0 -66
  269. package/src/pagination/Pagination.svelte +0 -428
  270. package/src/pagination/PaginationKbdFixture.svelte +0 -15
  271. package/src/pagination/index.ts +0 -2
  272. package/src/pagination/meta.ts +0 -73
  273. package/src/popconfirm/Popconfirm.a11y.test.ts +0 -46
  274. package/src/popconfirm/Popconfirm.kbd.test.ts +0 -42
  275. package/src/popconfirm/Popconfirm.svelte +0 -724
  276. package/src/popconfirm/PopconfirmA11yFixture.svelte +0 -34
  277. package/src/popconfirm/PopconfirmKbdFixture.svelte +0 -17
  278. package/src/popconfirm/index.ts +0 -2
  279. package/src/popconfirm/meta.ts +0 -200
  280. package/src/popover/Popover.a11y.test.ts +0 -58
  281. package/src/popover/Popover.kbd.test.ts +0 -42
  282. package/src/popover/Popover.svelte +0 -643
  283. package/src/popover/PopoverA11yFixture.svelte +0 -35
  284. package/src/popover/PopoverKbdFixture.svelte +0 -18
  285. package/src/popover/index.ts +0 -2
  286. package/src/popover/meta.ts +0 -103
  287. package/src/progress/Progress.a11y.test.ts +0 -37
  288. package/src/progress/Progress.svelte +0 -423
  289. package/src/progress/index.ts +0 -3
  290. package/src/progress/meta.ts +0 -132
  291. package/src/radio/Radio.svelte +0 -330
  292. package/src/radio/RadioGroup.a11y.test.ts +0 -43
  293. package/src/radio/RadioGroup.kbd.test.ts +0 -75
  294. package/src/radio/RadioGroup.svelte +0 -199
  295. package/src/radio/RadioGroupKbdFixture.svelte +0 -21
  296. package/src/radio/context.ts +0 -42
  297. package/src/radio/index.ts +0 -4
  298. package/src/radio/meta.ts +0 -68
  299. package/src/rating/Rating.a11y.test.ts +0 -41
  300. package/src/rating/Rating.kbd.test.ts +0 -48
  301. package/src/rating/Rating.svelte +0 -407
  302. package/src/rating/RatingKbdFixture.svelte +0 -15
  303. package/src/rating/index.ts +0 -2
  304. package/src/rating/meta.ts +0 -40
  305. package/src/resize-observer/ResizeObserver.svelte +0 -169
  306. package/src/resize-observer/action.ts +0 -80
  307. package/src/resize-observer/index.ts +0 -9
  308. package/src/resize-observer/meta.ts +0 -102
  309. package/src/scroll-list/ScrollColumn.svelte +0 -592
  310. package/src/scroll-list/ScrollList.svelte +0 -257
  311. package/src/scroll-list/index.ts +0 -4
  312. package/src/scroll-list/meta.ts +0 -93
  313. package/src/scroll-list/types.ts +0 -18
  314. package/src/select/Select.a11y.test.ts +0 -59
  315. package/src/select/Select.kbd.test.ts +0 -59
  316. package/src/select/Select.svelte +0 -1155
  317. package/src/select/SelectKbdFixture.svelte +0 -29
  318. package/src/select/index.ts +0 -3
  319. package/src/select/meta.ts +0 -78
  320. package/src/select/types.ts +0 -2
  321. package/src/side-sheet/SideSheet.a11y.test.ts +0 -53
  322. package/src/side-sheet/SideSheet.kbd.test.ts +0 -63
  323. package/src/side-sheet/SideSheet.svelte +0 -659
  324. package/src/side-sheet/SideSheetKbdFixture.svelte +0 -30
  325. package/src/side-sheet/index.ts +0 -2
  326. package/src/side-sheet/meta.ts +0 -116
  327. package/src/skeleton/Skeleton.a11y.test.ts +0 -35
  328. package/src/skeleton/Skeleton.svelte +0 -131
  329. package/src/skeleton/SkeletonAvatar.svelte +0 -82
  330. package/src/skeleton/SkeletonButton.svelte +0 -90
  331. package/src/skeleton/SkeletonImage.svelte +0 -100
  332. package/src/skeleton/SkeletonParagraph.svelte +0 -103
  333. package/src/skeleton/SkeletonTitle.svelte +0 -74
  334. package/src/skeleton/context.ts +0 -11
  335. package/src/skeleton/index.ts +0 -8
  336. package/src/skeleton/meta.ts +0 -65
  337. package/src/slider/Slider.a11y.test.ts +0 -44
  338. package/src/slider/Slider.kbd.test.ts +0 -74
  339. package/src/slider/Slider.svelte +0 -716
  340. package/src/slider/SliderKbdFixture.svelte +0 -21
  341. package/src/slider/index.ts +0 -2
  342. package/src/slider/meta.ts +0 -55
  343. package/src/space/Space.a11y.test.ts +0 -22
  344. package/src/space/Space.svelte +0 -109
  345. package/src/space/SpaceA11yFixture.svelte +0 -17
  346. package/src/space/index.ts +0 -2
  347. package/src/space/meta.ts +0 -27
  348. package/src/spin/Spin.a11y.test.ts +0 -29
  349. package/src/spin/Spin.svelte +0 -293
  350. package/src/spin/SpinA11yFixture.svelte +0 -18
  351. package/src/spin/index.ts +0 -2
  352. package/src/spin/meta.ts +0 -72
  353. package/src/steps/Steps.a11y.test.ts +0 -39
  354. package/src/steps/Steps.kbd.test.ts +0 -73
  355. package/src/steps/Steps.svelte +0 -392
  356. package/src/steps/StepsKbdFixture.svelte +0 -21
  357. package/src/steps/index.ts +0 -3
  358. package/src/steps/meta.ts +0 -59
  359. package/src/steps/types.ts +0 -8
  360. package/src/switch/Switch.a11y.test.ts +0 -46
  361. package/src/switch/Switch.kbd.test.ts +0 -40
  362. package/src/switch/Switch.svelte +0 -310
  363. package/src/switch/SwitchKbdFixture.svelte +0 -22
  364. package/src/switch/index.ts +0 -2
  365. package/src/switch/meta.ts +0 -44
  366. package/src/table/Table.a11y.test.ts +0 -70
  367. package/src/table/Table.bench.ts +0 -51
  368. package/src/table/Table.kbd.test.ts +0 -94
  369. package/src/table/Table.svelte +0 -2327
  370. package/src/table/TableKbdFixture.svelte +0 -35
  371. package/src/table/grid-nav.test.ts +0 -173
  372. package/src/table/grid-nav.ts +0 -146
  373. package/src/table/index.ts +0 -13
  374. package/src/table/meta.ts +0 -121
  375. package/src/table/types.ts +0 -133
  376. package/src/tabs/TabPane.svelte +0 -92
  377. package/src/tabs/Tabs.a11y.test.ts +0 -47
  378. package/src/tabs/Tabs.kbd.test.ts +0 -74
  379. package/src/tabs/Tabs.svelte +0 -1128
  380. package/src/tabs/TabsA11yFixture.svelte +0 -20
  381. package/src/tabs/TabsKbdFixture.svelte +0 -25
  382. package/src/tabs/context.ts +0 -43
  383. package/src/tabs/index.ts +0 -14
  384. package/src/tabs/meta.ts +0 -152
  385. package/src/tabs/types.ts +0 -6
  386. package/src/tag/Tag.a11y.test.ts +0 -33
  387. package/src/tag/Tag.svelte +0 -366
  388. package/src/tag/TagA11yFixture.svelte +0 -18
  389. package/src/tag/index.ts +0 -2
  390. package/src/tag/meta.ts +0 -92
  391. package/src/tag-input/TagInput.a11y.test.ts +0 -41
  392. package/src/tag-input/TagInput.svelte +0 -544
  393. package/src/tag-input/index.ts +0 -2
  394. package/src/tag-input/meta.ts +0 -43
  395. package/src/tag-input/reorder.test.ts +0 -59
  396. package/src/tag-input/reorder.ts +0 -41
  397. package/src/test-utils/LocaleHarness.svelte +0 -29
  398. package/src/test-utils/a11y.ts +0 -108
  399. package/src/test-utils/kbd.ts +0 -52
  400. package/src/textarea/TextArea.a11y.test.ts +0 -44
  401. package/src/textarea/TextArea.svelte +0 -420
  402. package/src/textarea/index.ts +0 -2
  403. package/src/textarea/meta.ts +0 -104
  404. package/src/time-picker/TimePicker.a11y.test.ts +0 -45
  405. package/src/time-picker/TimePicker.kbd.test.ts +0 -70
  406. package/src/time-picker/TimePicker.svelte +0 -1023
  407. package/src/time-picker/TimePickerKbdFixture.svelte +0 -23
  408. package/src/time-picker/index.ts +0 -2
  409. package/src/time-picker/meta.ts +0 -64
  410. package/src/timeline/Timeline.a11y.test.ts +0 -54
  411. package/src/timeline/Timeline.svelte +0 -599
  412. package/src/timeline/TimelineItem.svelte +0 -164
  413. package/src/timeline/context.ts +0 -28
  414. package/src/timeline/index.ts +0 -16
  415. package/src/timeline/meta.ts +0 -129
  416. package/src/timeline/types.ts +0 -9
  417. package/src/toast/Toast.a11y.test.ts +0 -67
  418. package/src/toast/ToastContainer.svelte +0 -184
  419. package/src/toast/ToastItem.svelte +0 -247
  420. package/src/toast/index.ts +0 -9
  421. package/src/toast/live-region.ts +0 -78
  422. package/src/toast/meta.ts +0 -95
  423. package/src/toast/store.ts +0 -187
  424. package/src/tooltip/Tooltip.a11y.test.ts +0 -41
  425. package/src/tooltip/Tooltip.kbd.test.ts +0 -37
  426. package/src/tooltip/Tooltip.svelte +0 -416
  427. package/src/tooltip/TooltipA11yFixture.svelte +0 -31
  428. package/src/tooltip/TooltipKbdFixture.svelte +0 -16
  429. package/src/tooltip/index.ts +0 -2
  430. package/src/tooltip/meta.ts +0 -59
  431. package/src/tooltip/placement.ts +0 -6
  432. package/src/transfer/Transfer.a11y.test.ts +0 -63
  433. package/src/transfer/Transfer.kbd.test.ts +0 -75
  434. package/src/transfer/Transfer.svelte +0 -1451
  435. package/src/transfer/TransferKbdFixture.svelte +0 -23
  436. package/src/transfer/group.test.ts +0 -55
  437. package/src/transfer/group.ts +0 -61
  438. package/src/transfer/index.ts +0 -3
  439. package/src/transfer/meta.ts +0 -55
  440. package/src/transfer/reorder.test.ts +0 -52
  441. package/src/transfer/reorder.ts +0 -42
  442. package/src/transfer/tree.test.ts +0 -44
  443. package/src/transfer/tree.ts +0 -52
  444. package/src/transfer/types.ts +0 -32
  445. package/src/tree/Tree.a11y.test.ts +0 -63
  446. package/src/tree/Tree.kbd.test.ts +0 -91
  447. package/src/tree/Tree.svelte +0 -1500
  448. package/src/tree/TreeKbdFixture.svelte +0 -30
  449. package/src/tree/index.ts +0 -3
  450. package/src/tree/meta.ts +0 -152
  451. package/src/tree-select/TreeSelect.a11y.test.ts +0 -52
  452. package/src/tree-select/TreeSelect.kbd.test.ts +0 -53
  453. package/src/tree-select/TreeSelect.svelte +0 -1611
  454. package/src/tree-select/TreeSelectKbdFixture.svelte +0 -20
  455. package/src/tree-select/index.ts +0 -3
  456. package/src/tree-select/meta.ts +0 -73
  457. package/src/tree-select/types.ts +0 -11
  458. package/src/tree-select/virtual.test.ts +0 -104
  459. package/src/typography/Link.svelte +0 -120
  460. package/src/typography/Paragraph.svelte +0 -92
  461. package/src/typography/Text.svelte +0 -93
  462. package/src/typography/Title.svelte +0 -91
  463. package/src/typography/Typography.a11y.test.ts +0 -34
  464. package/src/typography/TypographyA11yFixture.svelte +0 -27
  465. package/src/typography/TypographyBase.svelte +0 -807
  466. package/src/typography/index.ts +0 -16
  467. package/src/typography/meta.ts +0 -158
  468. package/src/upload/Upload.a11y.test.ts +0 -58
  469. package/src/upload/Upload.svelte +0 -1094
  470. package/src/upload/UploadA11yFixture.svelte +0 -23
  471. package/src/upload/index.ts +0 -3
  472. package/src/upload/meta.ts +0 -64
  473. package/src/upload/types.ts +0 -16
  474. package/src/virtual-list/VirtualList.svelte +0 -401
  475. package/src/virtual-list/index.ts +0 -2
  476. package/src/virtual-list/meta.ts +0 -106
@@ -1,1094 +0,0 @@
1
- <!--
2
- Upload — see specs/components/input/Upload.spec.md
3
- Basic subset: file selection (click + drag) + file list (name/size/status/remove).
4
- Controlled / uncontrolled `value`. 真实上传:有 action 且无 customRequest 时,
5
- 选文件后自动 XHR 上传(uploading→进度→success/error),customRequest 优先;
6
- XHR 句柄存 Map,remove/卸载时 abort。uploading 时渲染 Progress(line)。
7
- listType=image/picture-card:缩略图预览(item.url 优先,否则 file → objectURL,移除/卸载 revoke)。
8
- concurrency 并发上限(0=不限,超出排队、完成补位,core createUploadQueue 调度);
9
- beforeUpload 异步校验/转换(false/reject 跳过该文件,返回 File 替换,true 正常上传)。
10
- directory:input 命令式加 webkitdirectory,可递归选择整个目录(保留 relativePath)。
11
- minSize/maxSize:core validateFileSize 纯函数校验(单位 KB),超限标 error + i18n 提示。
12
- -->
13
- <script lang="ts">
14
- import type { Snippet } from 'svelte';
15
- import {
16
- useId,
17
- useLiveAnnouncer,
18
- computeUploadPercent,
19
- isUploadOk,
20
- createUploadQueue,
21
- resolveBeforeUpload,
22
- validateFileSize,
23
- type BeforeUploadResult,
24
- } from '@chenzy-design/core';
25
- import { useLocale } from '../locale-provider/index.js';
26
- import { Progress } from '../progress/index.js';
27
- import type { UploadFileItem } from './types.js';
28
-
29
- interface Props {
30
- value?: UploadFileItem[];
31
- defaultValue?: UploadFileItem[];
32
- accept?: string;
33
- multiple?: boolean;
34
- /** 上传整个目录(input 加 webkitdirectory,递归选择目录下所有文件)。 */
35
- directory?: boolean;
36
- limit?: number;
37
- /** Max size per file, in KB. */
38
- maxSize?: number;
39
- /** Min size per file, in KB. 小于此值的文件校验失败(error)。 */
40
- minSize?: number;
41
- disabled?: boolean;
42
- /**
43
- * 组件级尺寸(触发按钮/列表项),与其它表单控件一致。
44
- * 注意:区别于每个文件项的 file.size(字节体积)。
45
- */
46
- size?: 'small' | 'default' | 'large';
47
- /**
48
- * 组件级校验态(表单联动),影响上传区/边框色。
49
- * 注意:区别于每个文件项的 file.status(ready/uploading/error 上传进度态)。
50
- */
51
- status?: 'default' | 'warning' | 'error';
52
- listType?: 'text' | 'image' | 'picture-card' | 'none';
53
- drag?: boolean;
54
- /** 上传地址;提供且无 customRequest 时选文件后自动 XHR 上传 */
55
- action?: string;
56
- /** 表单字段名,默认 'file' */
57
- uploadName?: string;
58
- /** 额外请求头 */
59
- headers?: Record<string, string>;
60
- /** 随文件一起提交的额外字段 */
61
- uploadData?: Record<string, string>;
62
- /** 同时进行的上传数上限;0/不传=不限(受控调度,超出排队,完成补位) */
63
- concurrency?: number;
64
- /**
65
- * 每个文件上传前调用:返回 false / reject 跳过该文件(移除);
66
- * 返回 File 替换为该文件(如压缩后);返回 true / resolve 正常上传。异步会被 await。
67
- */
68
- beforeUpload?: (file: File, fileList: File[]) => BeforeUploadResult | Promise<BeforeUploadResult>;
69
- /** 自定义上传实现(优先于 action)。返回 Promise 时受 concurrency 调度(完成才释放槽位)。 */
70
- customRequest?: (item: UploadFileItem) => void | Promise<void>;
71
- onChange?: (list: UploadFileItem[]) => void;
72
- onExceed?: (files: File[]) => void;
73
- onSuccess?: (response: string, item: UploadFileItem) => void;
74
- onError?: (item: UploadFileItem) => void;
75
- children?: Snippet;
76
- /** 上传失败是否显示重试按钮。默认 true */
77
- showRetry?: boolean;
78
- /** 是否允许替换已有文件(单文件模式下显示"替换"而不是"添加")。默认 false */
79
- showReplace?: boolean;
80
- /** 是否显示批量清除按钮。默认 false */
81
- showClear?: boolean;
82
- /** 清除按钮点击回调 */
83
- onClear?: () => void;
84
- /** 文件列表标题文字;false 则不渲染。默认 undefined(不渲染) */
85
- fileListTitle?: string | false;
86
- /** 文件名超长是否展示 Tooltip(简单实现:title 属性)。true=展示 title;false=不展示。默认 true */
87
- showTooltip?: boolean;
88
- /** 上传区提示内容(文字或 Snippet) */
89
- prompt?: string | Snippet;
90
- /** 提示位置:left/right 为水平排列,bottom 为下方。默认 'bottom' */
91
- promptPosition?: 'left' | 'right' | 'bottom';
92
- /** 拖拽放下回调 */
93
- onDrop?: (e: DragEvent, files: File[], rejectFiles: File[]) => void;
94
- /** 打开文件选择弹窗时回调 */
95
- onOpenFileDialog?: () => void;
96
- /** 预览图点击回调(image/picture-card listType) */
97
- onPreviewClick?: (fileItem: UploadFileItem) => void;
98
- /** accept 校验失败(文件类型不符)的回调 */
99
- onAcceptInvalid?: (files: File[]) => void;
100
- /** 重试回调 */
101
- onRetry?: (file: UploadFileItem) => void;
102
- /** 大小校验失败回调 */
103
- onSizeError?: (file: UploadFileItem, validResult: 'max' | 'min') => void;
104
- /** 校验失败统一文案(覆盖 i18n 默认文案) */
105
- validateMessage?: string;
106
- /** XHR withCredentials(跨域凭证) */
107
- withCredentials?: boolean;
108
- /** 上传前文件转换(async,返回转换后的 File) */
109
- transformFile?: (file: File) => Promise<File>;
110
- /** 拖拽区自定义图标 Snippet */
111
- dragIcon?: Snippet;
112
- /** 拖拽区主文案(Snippet 或 string) */
113
- dragMainText?: string | Snippet;
114
- /** 拖拽区副文案(Snippet 或 string) */
115
- dragSubText?: string | Snippet;
116
- /** 粘贴添加文件(监听 document paste) */
117
- addOnPasting?: boolean;
118
- /** 触发热点位置(拖拽区时无效)。'start'=前置,'end'=后置,'none'=隐藏触发器。默认 'start' */
119
- hotSpotLocation?: 'start' | 'end' | 'none';
120
- }
121
-
122
- let {
123
- value,
124
- defaultValue = [],
125
- accept,
126
- multiple = false,
127
- directory = false,
128
- limit,
129
- maxSize,
130
- minSize,
131
- disabled = false,
132
- size = 'default',
133
- status = 'default',
134
- listType = 'text',
135
- drag = false,
136
- action,
137
- uploadName = 'file',
138
- headers,
139
- uploadData,
140
- concurrency = 0,
141
- beforeUpload,
142
- customRequest,
143
- onChange,
144
- onExceed,
145
- onSuccess,
146
- onError,
147
- children,
148
- showRetry = true,
149
- showReplace = false,
150
- showClear = false,
151
- onClear,
152
- fileListTitle,
153
- showTooltip = true,
154
- prompt,
155
- promptPosition = 'bottom',
156
- onDrop,
157
- onOpenFileDialog,
158
- onPreviewClick,
159
- onAcceptInvalid,
160
- onRetry,
161
- onSizeError,
162
- validateMessage,
163
- withCredentials = false,
164
- transformFile,
165
- dragIcon,
166
- dragMainText,
167
- dragSubText,
168
- addOnPasting = false,
169
- hotSpotLocation = 'start',
170
- }: Props = $props();
171
-
172
- const loc = useLocale();
173
- // 屏幕阅读器播报(spec §6):进度 polite(节流,避免每 1% 刷屏),成功 polite、失败 assertive。
174
- // 命令式调用在 XHR 事件回调里(非 render 期),符合红线 #3。
175
- const announcer = useLiveAnnouncer();
176
- // 每个文件上次播报的进度档(每 25% 一档),避免逐 % 重复播报。
177
- const announcedBucket = new Map<string, number>();
178
-
179
- const isControlled = $derived(value !== undefined);
180
- let inner = $state<UploadFileItem[]>(getInitialValue());
181
- // Controlled (`value=`): parent owns the list; we never write the prop, only
182
- // propagate via `onChange`. Uncontrolled: keep our own state in sync.
183
- const current = $derived(isControlled ? (value ?? []) : inner);
184
-
185
- function getInitialValue(): UploadFileItem[] {
186
- return [...defaultValue];
187
- }
188
-
189
- let inputEl: HTMLInputElement | null = null;
190
-
191
- // 进行中的 XHR 句柄(uid → xhr),remove/卸载时 abort。
192
- const xhrMap = new Map<string, XMLHttpRequest>();
193
-
194
- // 并发调度队列:concurrency 变化时重建(新文件用新上限,进行中的 XHR 不受影响)。
195
- // concurrency<=0 时不限,行为与未接入队列前一致。
196
- const queue = $derived(createUploadQueue(concurrency));
197
-
198
- // 卸载标记:避免卸载后仍向已 abort 的 XHR/已移除项回写状态。
199
- let mounted = true;
200
-
201
- // image/picture-card 预览:本地缓存 file → objectURL(uid → url),移除/卸载 revoke。
202
- const objectUrls = new Map<string, string>();
203
- const isImageList = $derived(listType === 'image' || listType === 'picture-card');
204
- function previewUrl(item: UploadFileItem): string | undefined {
205
- if (item.url) return item.url;
206
- if (!item.file) return undefined;
207
- let u = objectUrls.get(item.uid);
208
- if (u === undefined) {
209
- u = URL.createObjectURL(item.file);
210
- objectUrls.set(item.uid, u);
211
- }
212
- return u;
213
- }
214
- function revokeUrl(uid: string) {
215
- const u = objectUrls.get(uid);
216
- if (u !== undefined) {
217
- URL.revokeObjectURL(u);
218
- objectUrls.delete(uid);
219
- }
220
- }
221
-
222
- // 按 uid 局部更新某个文件项(不破坏受控/非受控约定,走 commit)。
223
- function patchItem(uid: string, patch: Partial<UploadFileItem>) {
224
- commit(current.map((it) => (it.uid === uid ? { ...it, ...patch } : it)));
225
- }
226
-
227
- // directory 是非标准 input 属性(webkitdirectory),Svelte 模板不直接支持,
228
- // 故命令式 toggle(红线 #3)。directory 变化时同步增删。
229
- $effect(() => {
230
- if (!inputEl) return;
231
- inputEl.toggleAttribute('webkitdirectory', directory);
232
- });
233
-
234
- // 卸载时中止所有进行中的上传 + 释放预览 objectURL。
235
- $effect(() => {
236
- return () => {
237
- mounted = false;
238
- for (const xhr of xhrMap.values()) xhr.abort();
239
- xhrMap.clear();
240
- for (const u of objectUrls.values()) URL.revokeObjectURL(u);
241
- objectUrls.clear();
242
- announcedBucket.clear();
243
- };
244
- });
245
-
246
- // 粘贴监听:addOnPasting 时挂载 document paste。
247
- $effect(() => {
248
- if (!addOnPasting || disabled) return;
249
- function handlePaste(e: ClipboardEvent) {
250
- const items = e.clipboardData?.items;
251
- if (!items) return;
252
- const files: File[] = [];
253
- for (const item of Array.from(items)) {
254
- if (item.kind === 'file') {
255
- const f = item.getAsFile();
256
- if (f) files.push(f);
257
- }
258
- }
259
- if (files.length > 0) addFiles(files);
260
- }
261
- document.addEventListener('paste', handlePaste);
262
- return () => document.removeEventListener('paste', handlePaste);
263
- });
264
-
265
- // 进度播报节流:每跨过一个 25% 档位才播一次(25/50/75),避免逐 % 刷屏。
266
- // 0% 与 100% 不在此播报(开始无意义、完成走 success 文案)。
267
- function announceProgress(item: UploadFileItem, percent: number) {
268
- const bucket = Math.floor(percent / 25);
269
- if (bucket <= 0 || bucket >= 4) return;
270
- if (announcedBucket.get(item.uid) === bucket) return;
271
- announcedBucket.set(item.uid, bucket);
272
- announcer.announce(loc().t('Upload.announceUploading', { name: item.name, percent }));
273
- }
274
-
275
- // XHR 上传单个文件项:uploading → onprogress 更新 percent → success/error。
276
- // 返回 Promise,在 load/error/abort 任一终态 resolve,供并发队列释放槽位。
277
- function uploadItem(item: UploadFileItem, file: File): Promise<void> {
278
- return new Promise<void>((resolve) => {
279
- if (!action) {
280
- resolve();
281
- return;
282
- }
283
- const xhr = new XMLHttpRequest();
284
- xhrMap.set(item.uid, xhr);
285
- patchItem(item.uid, { status: 'uploading', percent: 0 });
286
-
287
- let settled = false;
288
- const done = () => {
289
- if (settled) return;
290
- settled = true;
291
- resolve();
292
- };
293
-
294
- xhr.upload.onprogress = (e) => {
295
- if (e.lengthComputable) {
296
- const percent = computeUploadPercent(e.loaded, e.total);
297
- patchItem(item.uid, { percent });
298
- announceProgress(item, percent);
299
- }
300
- };
301
- xhr.onload = () => {
302
- xhrMap.delete(item.uid);
303
- announcedBucket.delete(item.uid);
304
- if (isUploadOk(xhr.status)) {
305
- patchItem(item.uid, { status: 'success', percent: 100 });
306
- // 完成必播(polite,不抢断)。
307
- announcer.announce(loc().t('Upload.announceSuccess', { name: item.name }));
308
- onSuccess?.(xhr.responseText, item);
309
- } else {
310
- patchItem(item.uid, { status: 'error' });
311
- // 失败必播(assertive,立即打断)。
312
- announcer.announce(loc().t('Upload.announceError', { name: item.name }), 'assertive');
313
- onError?.(item);
314
- }
315
- done();
316
- };
317
- xhr.onerror = () => {
318
- xhrMap.delete(item.uid);
319
- announcedBucket.delete(item.uid);
320
- patchItem(item.uid, { status: 'error' });
321
- announcer.announce(loc().t('Upload.announceError', { name: item.name }), 'assertive');
322
- onError?.(item);
323
- done();
324
- };
325
- // abort(remove/卸载)也要释放槽位,否则队列卡死。
326
- xhr.onabort = () => {
327
- xhrMap.delete(item.uid);
328
- announcedBucket.delete(item.uid);
329
- done();
330
- };
331
-
332
- const form = new FormData();
333
- form.append(uploadName, file, item.name);
334
- if (uploadData) {
335
- for (const [k, v] of Object.entries(uploadData)) form.append(k, v);
336
- }
337
- xhr.open('POST', action);
338
- if (withCredentials) xhr.withCredentials = true;
339
- if (headers) {
340
- for (const [k, v] of Object.entries(headers)) xhr.setRequestHeader(k, v);
341
- }
342
- xhr.send(form);
343
- });
344
- }
345
-
346
- /** Format a byte count: <1KiB → B, <1MiB → KB, else MB (1 decimal). */
347
- function formatSize(bytes: number): string {
348
- if (bytes < 1024) return `${bytes} B`;
349
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
350
- return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
351
- }
352
-
353
- function commit(next: UploadFileItem[]) {
354
- if (!isControlled) inner = next;
355
- onChange?.(next);
356
- }
357
-
358
- /** accept 过滤:返回通过和拒绝两组文件。 */
359
- function filterByAccept(files: File[]): { accepted: File[]; rejected: File[] } {
360
- if (!accept) return { accepted: files, rejected: [] };
361
- const acceptList = accept.split(',').map((s) => s.trim().toLowerCase());
362
- const accepted: File[] = [];
363
- const rejected: File[] = [];
364
- for (const f of files) {
365
- const ext = '.' + f.name.split('.').pop()!.toLowerCase();
366
- const mime = f.type.toLowerCase();
367
- const ok = acceptList.some((a) => {
368
- if (a.startsWith('.')) return ext === a;
369
- if (a.endsWith('/*')) return mime.startsWith(a.slice(0, -1));
370
- return mime === a;
371
- });
372
- if (ok) accepted.push(f);
373
- else rejected.push(f);
374
- }
375
- return { accepted, rejected };
376
- }
377
-
378
- function buildItem(file: File): UploadFileItem {
379
- // 纯函数校验大小(KB),min/max 同源;超限 → error + 本地化提示。
380
- const sizeError = validateFileSize(file.size, { minSize, maxSize });
381
- // 目录上传时浏览器在 webkitRelativePath 上保留相对路径(如 dir/sub/a.txt)。
382
- const relativePath = (file as File & { webkitRelativePath?: string }).webkitRelativePath;
383
- const item: UploadFileItem = {
384
- uid: useId('cd-upload'),
385
- name: file.name,
386
- size: file.size,
387
- status: sizeError ? 'error' : 'ready',
388
- file,
389
- };
390
- if (relativePath) item.relativePath = relativePath;
391
- if (sizeError) {
392
- const limitKB = sizeError === 'max' ? maxSize! : minSize!;
393
- item.error = validateMessage ?? loc().t(sizeError === 'max' ? 'Upload.sizeError' : 'Upload.minSizeError', {
394
- size: formatSize(limitKB * 1024),
395
- });
396
- }
397
- return item;
398
- }
399
-
400
- function addFiles(fileList: FileList | File[]) {
401
- if (disabled) return;
402
- const allFiles = Array.from(fileList);
403
- if (allFiles.length === 0) return;
404
-
405
- // accept 校验
406
- const { accepted: afterAccept, rejected } = filterByAccept(allFiles);
407
- if (rejected.length > 0) onAcceptInvalid?.(rejected);
408
- if (afterAccept.length === 0) return;
409
-
410
- let accepted = afterAccept;
411
- if (limit !== undefined) {
412
- const room = limit - current.length;
413
- if (room <= 0) {
414
- onExceed?.(accepted);
415
- return;
416
- }
417
- if (accepted.length > room) {
418
- onExceed?.(accepted.slice(room));
419
- accepted = accepted.slice(0, room);
420
- }
421
- }
422
-
423
- const newItems = accepted.map(buildItem);
424
- commit([...current, ...newItems]);
425
-
426
- // onSizeError 回调:大小校验失败项通知外部
427
- for (const item of newItems) {
428
- if (item.status === 'error' && item.file) {
429
- const result = validateFileSize(item.file.size, { minSize, maxSize });
430
- if (result) onSizeError?.(item, result);
431
- }
432
- }
433
-
434
- // beforeUpload 通过的项才进队列受 concurrency 调度。
435
- // customRequest 完全接管;否则有 action 时自动 XHR 上传。仅处理无尺寸错误的项。
436
- for (const item of newItems) {
437
- if (item.status === 'error' || !item.file) continue;
438
- dispatch(item, item.file, accepted);
439
- }
440
- }
441
-
442
- // 单个文件的上传派发:先跑(可能异步的)beforeUpload,通过后入队受并发调度。
443
- async function dispatch(item: UploadFileItem, original: File, fileList: File[]) {
444
- let file = original;
445
- if (beforeUpload) {
446
- let result: BeforeUploadResult;
447
- try {
448
- result = await beforeUpload(original, fileList);
449
- } catch {
450
- // reject 视为拒绝该文件。
451
- result = false;
452
- }
453
- if (!mounted) return;
454
- // 上传开始前可能已被手动移除。
455
- if (!current.some((it) => it.uid === item.uid)) return;
456
- const decision = resolveBeforeUpload(original, result);
457
- if (!decision.upload) {
458
- // 跳过该文件:从列表移除(受控仅 onChange,不回写)。
459
- remove(item.uid);
460
- return;
461
- }
462
- file = decision.file ?? original;
463
- if (file !== original) patchItem(item.uid, { name: file.name, size: file.size, file });
464
- }
465
- if (!mounted) return;
466
-
467
- // transformFile:上传前文件转换
468
- if (transformFile) {
469
- file = await transformFile(file);
470
- if (!mounted) return;
471
- patchItem(item.uid, { name: file.name, size: file.size, file });
472
- }
473
-
474
- // 入队受 concurrency 调度:customRequest 返回 Promise 时队列会 await 其完成
475
- // 来释放槽位(同步返回则立即释放,由其自管生命周期);否则由队列 await XHR。
476
- queue.add(() => {
477
- if (!mounted) return;
478
- if (!current.some((it) => it.uid === item.uid)) return;
479
- if (customRequest) {
480
- return customRequest({ ...item, file });
481
- }
482
- if (action) return uploadItem(item, file);
483
- });
484
- }
485
-
486
- function remove(uid: string) {
487
- if (disabled) return;
488
- const xhr = xhrMap.get(uid);
489
- if (xhr) {
490
- xhr.abort();
491
- xhrMap.delete(uid);
492
- }
493
- revokeUrl(uid);
494
- announcedBucket.delete(uid);
495
- commit(current.filter((item) => item.uid !== uid));
496
- }
497
-
498
- /** 重试失败项:重置状态后重新派发上传。 */
499
- function retryItem(item: UploadFileItem) {
500
- onRetry?.(item);
501
- if (!item.file) return;
502
- // Drop `percent` and `error` keys entirely (exactOptionalPropertyTypes: true requires
503
- // omission rather than explicit undefined assignment).
504
- commit(current.map((it) => {
505
- if (it.uid !== item.uid) return it;
506
- const { percent: _p, error: _e, ...rest } = it;
507
- return { ...rest, status: 'ready' };
508
- }));
509
- dispatch(item, item.file, [item.file]);
510
- }
511
-
512
- /** 清除所有文件:中止进行中的上传,释放 objectURL,清空列表。 */
513
- function clearAll() {
514
- if (disabled) return;
515
- for (const xhr of xhrMap.values()) xhr.abort();
516
- xhrMap.clear();
517
- for (const u of objectUrls.values()) URL.revokeObjectURL(u);
518
- objectUrls.clear();
519
- announcedBucket.clear();
520
- commit([]);
521
- onClear?.();
522
- }
523
-
524
- function openPicker() {
525
- if (disabled) return;
526
- onOpenFileDialog?.();
527
- inputEl?.click();
528
- }
529
-
530
- function handleInputChange(e: Event & { currentTarget: HTMLInputElement }) {
531
- const fl = e.currentTarget.files;
532
- if (fl) addFiles(fl);
533
- // Reset so selecting the same file again re-fires change.
534
- e.currentTarget.value = '';
535
- }
536
-
537
- function handleDrop(e: DragEvent) {
538
- e.preventDefault();
539
- if (disabled) return;
540
- const dt = e.dataTransfer;
541
- if (dt?.files && dt.files.length > 0) {
542
- const files = Array.from(dt.files);
543
- // accept 过滤
544
- const { accepted, rejected } = filterByAccept(files);
545
- onDrop?.(e, files, rejected);
546
- if (accepted.length > 0) addFiles(accepted);
547
- }
548
- }
549
-
550
- function handleDragKeydown(e: KeyboardEvent) {
551
- if (e.key === 'Enter' || e.key === ' ') {
552
- e.preventDefault();
553
- openPicker();
554
- }
555
- }
556
-
557
- // 是否水平布局 prompt(left 或 right)
558
- const promptRow = $derived(promptPosition === 'left' || promptPosition === 'right');
559
- </script>
560
-
561
- <div
562
- class="cd-upload cd-upload--{size} cd-upload--{status}"
563
- class:cd-upload--disabled={disabled}
564
- data-status={status !== 'default' ? status : undefined}
565
- >
566
- <input
567
- bind:this={inputEl}
568
- class="cd-upload__input"
569
- type="file"
570
- {accept}
571
- {multiple}
572
- {disabled}
573
- tabindex="-1"
574
- aria-hidden="true"
575
- onchange={handleInputChange}
576
- />
577
-
578
- {#snippet triggerArea()}
579
- <div
580
- class="cd-upload__trigger-wrap"
581
- class:cd-upload__trigger-wrap--row={promptRow}
582
- class:cd-upload__trigger-wrap--row-reverse={promptPosition === 'left'}
583
- >
584
- {#if drag}
585
- <div
586
- class="cd-upload__dragger"
587
- role="button"
588
- tabindex={disabled ? -1 : 0}
589
- aria-disabled={disabled || undefined}
590
- ondragover={(e) => e.preventDefault()}
591
- ondrop={handleDrop}
592
- onclick={openPicker}
593
- onkeydown={handleDragKeydown}
594
- >
595
- {#if children}
596
- {@render children()}
597
- {:else}
598
- {#if dragIcon}{@render dragIcon()}{/if}
599
- {#if dragMainText}
600
- <span class="cd-upload__dragger-main">
601
- {#if typeof dragMainText === 'string'}{dragMainText}{:else}{@render dragMainText()}{/if}
602
- </span>
603
- {:else}
604
- <span class="cd-upload__dragger-text">{loc().t('Upload.draggerText')}</span>
605
- {/if}
606
- {#if dragSubText}
607
- <span class="cd-upload__dragger-sub">
608
- {#if typeof dragSubText === 'string'}{dragSubText}{:else}{@render dragSubText()}{/if}
609
- </span>
610
- {/if}
611
- {/if}
612
- </div>
613
- {:else}
614
- <button type="button" class="cd-upload__trigger" {disabled} onclick={openPicker}>
615
- {#if children}
616
- {@render children()}
617
- {:else}
618
- {loc().t('Upload.trigger')}
619
- {/if}
620
- </button>
621
- {/if}
622
-
623
- {#if prompt}
624
- <div class="cd-upload__prompt">
625
- {#if typeof prompt === 'string'}{prompt}{:else}{@render prompt()}{/if}
626
- </div>
627
- {/if}
628
- </div>
629
- {/snippet}
630
-
631
- {#if hotSpotLocation !== 'none' && hotSpotLocation !== 'end'}
632
- {@render triggerArea()}
633
- {/if}
634
-
635
- {#if showClear && current.length > 0}
636
- <button
637
- type="button"
638
- class="cd-upload__clear-btn"
639
- {disabled}
640
- onclick={clearAll}
641
- >清除全部</button>
642
- {/if}
643
-
644
- {#if listType === 'text' && current.length > 0}
645
- {#if fileListTitle !== false && fileListTitle}
646
- <div class="cd-upload__list-title">{fileListTitle}</div>
647
- {/if}
648
- <ul class="cd-upload__list">
649
- {#each current as item (item.uid)}
650
- <li class="cd-upload__item" class:cd-upload__item--error={item.status === 'error'}>
651
- <div class="cd-upload__item-main">
652
- <span
653
- class="cd-upload__item-name"
654
- title={showTooltip !== false ? item.name : undefined}
655
- >{item.name}</span>
656
- <span class="cd-upload__item-size">{formatSize(item.size)}</span>
657
- {#if item.status !== 'uploading'}
658
- <span class="cd-upload__item-status">{item.error ?? item.status}</span>
659
- {/if}
660
- {#if item.status === 'error' && showRetry !== false}
661
- <button
662
- type="button"
663
- class="cd-upload__retry-btn"
664
- {disabled}
665
- onclick={() => retryItem(item)}
666
- >重试</button>
667
- {/if}
668
- <button
669
- type="button"
670
- class="cd-upload__item-remove"
671
- aria-label={loc().t('Upload.remove')}
672
- {disabled}
673
- onclick={() => remove(item.uid)}
674
- >
675
- &times;
676
- </button>
677
- </div>
678
- {#if item.status === 'uploading'}
679
- <Progress
680
- percent={item.percent ?? 0}
681
- size="small"
682
- ariaLabel={loc().t('Upload.uploadingProgress', { name: item.name })}
683
- />
684
- {/if}
685
- </li>
686
- {/each}
687
- </ul>
688
- {/if}
689
-
690
- {#if isImageList && current.length > 0}
691
- <ul
692
- class="cd-upload__grid"
693
- class:cd-upload__grid--card={listType === 'picture-card'}
694
- >
695
- {#each current as item (item.uid)}
696
- {@const url = previewUrl(item)}
697
- <li
698
- class="cd-upload__card"
699
- class:cd-upload__card--error={item.status === 'error'}
700
- class:cd-upload__card--uploading={item.status === 'uploading'}
701
- >
702
- {#if url}
703
- {#if onPreviewClick}
704
- <button
705
- type="button"
706
- class="cd-upload__thumb-btn"
707
- aria-label={item.name}
708
- onclick={() => onPreviewClick(item)}
709
- >
710
- <img class="cd-upload__thumb" src={url} alt="" aria-hidden="true" />
711
- </button>
712
- {:else}
713
- <img class="cd-upload__thumb" src={url} alt={item.name} />
714
- {/if}
715
- {:else}
716
- <span class="cd-upload__thumb cd-upload__thumb--placeholder" aria-hidden="true"></span>
717
- {/if}
718
- {#if item.status === 'uploading'}
719
- <div class="cd-upload__card-progress">
720
- <Progress
721
- percent={item.percent ?? 0}
722
- size="small"
723
- ariaLabel={loc().t('Upload.uploadingProgress', { name: item.name })}
724
- />
725
- </div>
726
- {/if}
727
- <div class="cd-upload__card-overlay">
728
- <span class="cd-upload__card-name">{item.name}</span>
729
- <button
730
- type="button"
731
- class="cd-upload__card-remove"
732
- aria-label={loc().t('Upload.remove')}
733
- {disabled}
734
- onclick={() => remove(item.uid)}
735
- >
736
- &times;
737
- </button>
738
- </div>
739
- </li>
740
- {/each}
741
- </ul>
742
- {/if}
743
-
744
- {#if hotSpotLocation === 'end'}
745
- {@render triggerArea()}
746
- {/if}
747
- </div>
748
-
749
- <style>
750
- .cd-upload {
751
- display: flex;
752
- flex-direction: column;
753
- gap: var(--cd-spacing-3);
754
- color: var(--cd-color-text-0);
755
- }
756
- .cd-upload__input {
757
- position: absolute;
758
- inline-size: 1px;
759
- block-size: 1px;
760
- padding: 0;
761
- margin: 0;
762
- overflow: hidden;
763
- clip-path: inset(50%);
764
- white-space: nowrap;
765
- border: 0;
766
- }
767
- .cd-upload__trigger-wrap {
768
- display: flex;
769
- flex-direction: column;
770
- gap: var(--cd-spacing-2);
771
- }
772
- .cd-upload__trigger-wrap--row {
773
- flex-direction: row;
774
- align-items: center;
775
- }
776
- .cd-upload__trigger-wrap--row-reverse {
777
- flex-direction: row-reverse;
778
- }
779
- .cd-upload__prompt {
780
- color: var(--cd-color-text-2);
781
- font-size: var(--cd-font-size-1);
782
- }
783
- .cd-upload__trigger {
784
- align-self: flex-start;
785
- display: inline-flex;
786
- align-items: center;
787
- gap: var(--cd-spacing-2);
788
- height: var(--cd-button-height-default);
789
- padding-inline: var(--cd-button-padding-x);
790
- background: var(--cd-color-fill-0);
791
- color: var(--cd-color-text-0);
792
- border: 1px solid var(--cd-color-border);
793
- border-radius: var(--cd-button-radius);
794
- font-size: var(--cd-button-font-size);
795
- cursor: pointer;
796
- }
797
- .cd-upload__trigger:focus-visible {
798
- outline: none;
799
- box-shadow: var(--cd-focus-ring);
800
- }
801
- /* 组件级 size:触发按钮高度/字号档(区别于 file.size 体积)。 */
802
- .cd-upload--small .cd-upload__trigger {
803
- height: var(--cd-button-height-small);
804
- font-size: var(--cd-font-size-1);
805
- }
806
- .cd-upload--large .cd-upload__trigger {
807
- height: var(--cd-button-height-large);
808
- font-size: var(--cd-font-size-3);
809
- }
810
- .cd-upload__trigger:disabled {
811
- cursor: not-allowed;
812
- opacity: 0.5;
813
- }
814
- .cd-upload__dragger {
815
- display: flex;
816
- flex-direction: column;
817
- align-items: center;
818
- justify-content: center;
819
- padding-block: var(--cd-spacing-6);
820
- padding-inline: var(--cd-spacing-4);
821
- background: var(--cd-upload-dragger-bg);
822
- border: 1px dashed var(--cd-upload-dragger-border);
823
- border-radius: var(--cd-upload-dragger-radius);
824
- color: var(--cd-color-text-2);
825
- cursor: pointer;
826
- transition: border-color var(--cd-motion-duration-fast) var(--cd-motion-ease-standard);
827
- }
828
- .cd-upload__dragger:hover,
829
- .cd-upload__dragger:focus-visible {
830
- border-color: var(--cd-upload-dragger-border-active);
831
- }
832
- .cd-upload__dragger:focus-visible {
833
- outline: none;
834
- box-shadow: var(--cd-focus-ring);
835
- }
836
- .cd-upload--disabled .cd-upload__dragger {
837
- cursor: not-allowed;
838
- opacity: 0.5;
839
- }
840
- /* 组件级 size:拖拽区内边距/字号档。 */
841
- .cd-upload--small .cd-upload__dragger {
842
- padding-block: var(--cd-spacing-4);
843
- font-size: var(--cd-font-size-1);
844
- }
845
- .cd-upload--large .cd-upload__dragger {
846
- padding-block: var(--cd-spacing-8, var(--cd-spacing-6));
847
- font-size: var(--cd-font-size-3);
848
- }
849
- /* 组件级 status:校验态影响上传区/卡片边框色(区别于 file.status 进度态)。 */
850
- .cd-upload--warning .cd-upload__dragger {
851
- border-color: var(--cd-upload-border-warning, var(--cd-color-warning));
852
- }
853
- .cd-upload--error .cd-upload__dragger {
854
- border-color: var(--cd-upload-border-error, var(--cd-color-danger));
855
- }
856
- .cd-upload--warning .cd-upload__trigger {
857
- border-color: var(--cd-upload-border-warning, var(--cd-color-warning));
858
- }
859
- .cd-upload--error .cd-upload__trigger {
860
- border-color: var(--cd-upload-border-error, var(--cd-color-danger));
861
- }
862
- .cd-upload--warning .cd-upload__card,
863
- .cd-upload--error .cd-upload__card {
864
- border-color: var(--cd-upload-border-warning, var(--cd-color-warning));
865
- }
866
- .cd-upload--error .cd-upload__card {
867
- border-color: var(--cd-upload-border-error, var(--cd-color-danger));
868
- }
869
- .cd-upload__list-title {
870
- font-size: var(--cd-font-size-1);
871
- color: var(--cd-color-text-1);
872
- font-weight: 500;
873
- margin-block-end: var(--cd-spacing-1);
874
- }
875
- .cd-upload__list {
876
- display: flex;
877
- flex-direction: column;
878
- gap: var(--cd-spacing-1);
879
- margin: 0;
880
- padding: 0;
881
- list-style: none;
882
- }
883
- .cd-upload__item {
884
- display: flex;
885
- flex-direction: column;
886
- gap: var(--cd-spacing-1);
887
- padding-block: var(--cd-spacing-1);
888
- padding-inline: var(--cd-spacing-2);
889
- border-radius: var(--cd-radius-1);
890
- }
891
- .cd-upload__item-main {
892
- display: flex;
893
- align-items: center;
894
- gap: var(--cd-spacing-2);
895
- }
896
- .cd-upload__item:hover {
897
- background: var(--cd-upload-item-bg-hover);
898
- }
899
- .cd-upload__item--error {
900
- color: var(--cd-upload-item-color-error);
901
- }
902
- .cd-upload__item-name {
903
- flex: 1 1 auto;
904
- min-inline-size: 0;
905
- overflow: hidden;
906
- text-overflow: ellipsis;
907
- white-space: nowrap;
908
- }
909
- .cd-upload__item-size,
910
- .cd-upload__item-status {
911
- flex: 0 0 auto;
912
- color: var(--cd-color-text-2);
913
- font-size: var(--cd-font-size-1);
914
- }
915
- .cd-upload__item--error .cd-upload__item-status {
916
- color: var(--cd-upload-item-color-error);
917
- }
918
- .cd-upload__item-remove {
919
- flex: 0 0 auto;
920
- display: inline-flex;
921
- align-items: center;
922
- justify-content: center;
923
- padding: 0;
924
- border: none;
925
- background: transparent;
926
- color: var(--cd-color-text-2);
927
- cursor: pointer;
928
- border-radius: var(--cd-radius-1);
929
- font-size: var(--cd-font-size-3);
930
- line-height: 1;
931
- }
932
- .cd-upload__item-remove:hover {
933
- color: var(--cd-color-text-0);
934
- }
935
- .cd-upload__item-remove:focus-visible {
936
- outline: none;
937
- box-shadow: var(--cd-focus-ring);
938
- }
939
- .cd-upload__item-remove:disabled {
940
- cursor: not-allowed;
941
- opacity: 0.5;
942
- }
943
- .cd-upload__retry-btn {
944
- flex: 0 0 auto;
945
- display: inline-flex;
946
- align-items: center;
947
- padding: 0 var(--cd-spacing-1);
948
- border: none;
949
- background: transparent;
950
- color: var(--cd-color-primary);
951
- cursor: pointer;
952
- font-size: var(--cd-font-size-1);
953
- border-radius: var(--cd-radius-1);
954
- }
955
- .cd-upload__retry-btn:hover {
956
- text-decoration: underline;
957
- }
958
- .cd-upload__retry-btn:disabled {
959
- cursor: not-allowed;
960
- opacity: 0.5;
961
- }
962
- .cd-upload__clear-btn {
963
- align-self: flex-end;
964
- display: inline-flex;
965
- align-items: center;
966
- gap: var(--cd-spacing-1);
967
- padding: var(--cd-spacing-1) var(--cd-spacing-2);
968
- border: none;
969
- background: transparent;
970
- color: var(--cd-color-text-2);
971
- cursor: pointer;
972
- font-size: var(--cd-font-size-1);
973
- border-radius: var(--cd-radius-1);
974
- }
975
- .cd-upload__clear-btn:hover {
976
- color: var(--cd-color-danger);
977
- background: var(--cd-color-fill-1);
978
- }
979
- .cd-upload__clear-btn:disabled {
980
- cursor: not-allowed;
981
- opacity: 0.5;
982
- }
983
- .cd-upload__dragger-main {
984
- display: block;
985
- font-size: var(--cd-font-size-2);
986
- color: var(--cd-color-text-1);
987
- }
988
- .cd-upload__dragger-sub {
989
- display: block;
990
- font-size: var(--cd-font-size-1);
991
- color: var(--cd-color-text-2);
992
- }
993
-
994
- /* --- image / picture-card 缩略图网格 --- */
995
- .cd-upload__grid {
996
- display: flex;
997
- flex-wrap: wrap;
998
- gap: var(--cd-spacing-2);
999
- margin: 0;
1000
- padding: 0;
1001
- list-style: none;
1002
- }
1003
- .cd-upload__card {
1004
- position: relative;
1005
- inline-size: 96px;
1006
- block-size: 96px;
1007
- border: 1px solid var(--cd-color-border);
1008
- border-radius: var(--cd-radius-2);
1009
- overflow: hidden;
1010
- background: var(--cd-color-fill-0);
1011
- }
1012
- .cd-upload__card--error {
1013
- border-color: var(--cd-upload-item-color-error, var(--cd-color-danger));
1014
- }
1015
- .cd-upload__thumb-btn {
1016
- display: block;
1017
- inline-size: 100%;
1018
- block-size: 100%;
1019
- padding: 0;
1020
- border: none;
1021
- background: transparent;
1022
- cursor: pointer;
1023
- }
1024
- .cd-upload__thumb-btn:focus-visible {
1025
- outline: none;
1026
- box-shadow: var(--cd-focus-ring);
1027
- }
1028
- .cd-upload__thumb {
1029
- inline-size: 100%;
1030
- block-size: 100%;
1031
- object-fit: cover;
1032
- display: block;
1033
- }
1034
- .cd-upload__thumb--placeholder {
1035
- background: var(--cd-color-fill-1);
1036
- }
1037
- .cd-upload__card-progress {
1038
- position: absolute;
1039
- inset-inline: var(--cd-spacing-1);
1040
- inset-block-end: var(--cd-spacing-1);
1041
- }
1042
- .cd-upload__card-overlay {
1043
- position: absolute;
1044
- inset-block-start: 0;
1045
- inset-inline: 0;
1046
- display: flex;
1047
- align-items: center;
1048
- gap: var(--cd-spacing-1);
1049
- padding: var(--cd-spacing-1);
1050
- background: linear-gradient(to bottom, rgba(0, 0, 0, 0.55), transparent);
1051
- opacity: 0;
1052
- transition: opacity var(--cd-motion-duration-fast) var(--cd-motion-ease-standard);
1053
- }
1054
- .cd-upload__card:hover .cd-upload__card-overlay,
1055
- .cd-upload__card:focus-within .cd-upload__card-overlay {
1056
- opacity: 1;
1057
- }
1058
- .cd-upload__card-name {
1059
- flex: 1 1 auto;
1060
- min-inline-size: 0;
1061
- overflow: hidden;
1062
- text-overflow: ellipsis;
1063
- white-space: nowrap;
1064
- color: #fff;
1065
- font-size: var(--cd-font-size-1);
1066
- }
1067
- .cd-upload__card-remove {
1068
- flex: 0 0 auto;
1069
- display: inline-flex;
1070
- align-items: center;
1071
- justify-content: center;
1072
- padding: 0;
1073
- inline-size: 1.25rem;
1074
- block-size: 1.25rem;
1075
- border: none;
1076
- background: transparent;
1077
- color: #fff;
1078
- cursor: pointer;
1079
- font-size: var(--cd-font-size-3);
1080
- line-height: 1;
1081
- }
1082
- .cd-upload__card-remove:focus-visible {
1083
- outline: none;
1084
- box-shadow: var(--cd-focus-ring);
1085
- }
1086
- @media (prefers-reduced-motion: reduce) {
1087
- .cd-upload__card-overlay {
1088
- transition: none;
1089
- }
1090
- .cd-upload__dragger {
1091
- transition: none;
1092
- }
1093
- }
1094
- </style>