@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,920 +0,0 @@
1
- <!--
2
- List — see specs/components/show/List.spec.md
3
- 基础子集:dataSource + renderItem、header/footer(string|Snippet)、bordered/split、
4
- loading(骨架/spinner)、empty、loadMore(内置按钮/自定义)、grid 网格布局。
5
- pagination:复用 Pagination 组件,对 dataSource 切片渲染当页(受控 current 不回写,红线 #1)。
6
- 进阶子集:
7
- - 虚拟化(virtualized):大数据只渲染视口内行,复用 core fixedRange/dynamicRange/
8
- scrollOffsetForIndex(与 VirtualList 同一套区间数学)。命令式滚动监听 + rAF 节流 +
9
- cleanup(红线 #3);区间/总高纯 $derived,仅依赖本地 $state(红线 #2)。virtualized
10
- 与 grid/pagination 互斥(优先生效,对全量 dataSource 虚拟化)。
11
- - selectable('single'|'multiple'):行可选,选中态受控 selectedKeys + onSelectionChange,
12
- 不回写仅回调(红线 #1)。容器 role=listbox(multiple 时 aria-multiselectable),
13
- 行 role=option + aria-selected。shift 连选(multiple)。
14
- - 声明式 List.Item / List.Item.Meta:不传 dataSource 时渲染 children(内嵌 <List.Item>),
15
- 通过 context 暴露 selectable 状态给子项(getter 保持响应性,子项不写 $state,避免
16
- effect 自循环——红线 #2)。
17
- -->
18
- <script lang="ts" generics="T">
19
- import { untrack, type Snippet } from 'svelte';
20
- import {
21
- fixedRange,
22
- buildOffsets,
23
- totalFromOffsets,
24
- dynamicRange,
25
- scrollOffsetForIndex,
26
- toggleSelection,
27
- rangeSelection,
28
- useLiveAnnouncer,
29
- type ScrollAlign,
30
- type ListKey,
31
- } from '@chenzy-design/core';
32
- import Empty from '../empty/Empty.svelte';
33
- import { Button } from '../button/index.js';
34
- import { Pagination } from '../pagination/index.js';
35
- import { useLocale } from '../locale-provider/index.js';
36
- import { setListContext } from './context.js';
37
-
38
- type ListSize = 'small' | 'default' | 'large';
39
- type GridConfig = number | { column?: number; gutter?: number };
40
- type SelectableMode = false | 'single' | 'multiple';
41
- type VirtualConfig = {
42
- /** 行高(px),默认 40;传 'auto' 启用动态测高。 */
43
- itemSize?: number | 'auto';
44
- /** 动态测高初始估算行高(px)。 */
45
- estimatedItemSize?: number;
46
- /** 视口高度(px 数字,或 CSS 字符串如 '60vh')。 */
47
- height: number | string;
48
- /** 上下缓冲行数,默认 3。 */
49
- overscan?: number;
50
- };
51
-
52
- // 泛型组件 props 用内联类型而非具名 interface Props:在 declaration:true 下,
53
- // 引用泛型参数 T 的具名 interface 会被当作私有名泄漏进生成的 .d.ts 公共签名而报错。
54
- let {
55
- dataSource = [],
56
- renderItem,
57
- rowKey = 'key',
58
- size = 'default',
59
- bordered = false,
60
- split = true,
61
- header,
62
- footer,
63
- loading = false,
64
- loadingSkeleton = false,
65
- skeletonCount = 3,
66
- emptyContent,
67
- grid,
68
- loadMore,
69
- onLoadMore,
70
- loadingMore = false,
71
- hasMore = false,
72
- pagination,
73
- virtualized = false,
74
- selectable = false,
75
- selectedKeys,
76
- defaultSelectedKeys = [],
77
- onSelectionChange,
78
- ariaLabel,
79
- children,
80
- layout = 'vertical',
81
- onListScroll,
82
- class: className = '',
83
- }: {
84
- dataSource?: T[];
85
- renderItem?: Snippet<[item: T, index: number]>;
86
- rowKey?: string | ((item: T) => string | number);
87
- size?: ListSize;
88
- bordered?: boolean;
89
- split?: boolean;
90
- header?: string | Snippet;
91
- footer?: string | Snippet;
92
- loading?: boolean;
93
- loadingSkeleton?: boolean;
94
- skeletonCount?: number;
95
- emptyContent?: string | Snippet;
96
- /** 网格布局:列数或 { column, gutter } */
97
- grid?: GridConfig;
98
- /** 自定义底部加载区(优先于内置按钮) */
99
- loadMore?: Snippet;
100
- /** 内置「加载更多」按钮回调 */
101
- onLoadMore?: () => void;
102
- /** 内置按钮 loading 态 */
103
- loadingMore?: boolean;
104
- /** 是否还有更多(控制内置按钮显隐) */
105
- hasMore?: boolean;
106
- /** 分页:复用 Pagination,对 dataSource 切片渲染当页(与 loadMore 互斥,优先生效) */
107
- pagination?:
108
- | false
109
- | {
110
- pageSize?: number;
111
- current?: number;
112
- defaultCurrent?: number;
113
- onChange?: (page: number) => void;
114
- };
115
- /** 虚拟化:大数据只渲染视口内行(与 grid/pagination 互斥,优先生效)。 */
116
- virtualized?: false | VirtualConfig;
117
- /** 行可选:'single' 单选 / 'multiple' 多选。 */
118
- selectable?: SelectableMode;
119
- /** 受控选中 key 集合(不回写,仅 onSelectionChange 回调,红线 #1)。 */
120
- selectedKeys?: ListKey[];
121
- /** 非受控初始选中 key 集合。 */
122
- defaultSelectedKeys?: ListKey[];
123
- /** 选中态变更回调(受控/非受控均触发)。 */
124
- onSelectionChange?: (
125
- keys: ListKey[],
126
- info: { item: T | undefined; key: ListKey; selected: boolean },
127
- ) => void;
128
- /** selectable 模式 listbox 容器可访问名(缺省回退 i18n List.selectableLabel)。 */
129
- ariaLabel?: string;
130
- /** 声明式用法:内嵌 <List.Item>(不传 dataSource 时生效)。 */
131
- children?: Snippet;
132
- /** 整体布局方向:'vertical'(默认)每 item 内容纵向排列;'horizontal' 横向排列。 */
133
- layout?: 'horizontal' | 'vertical';
134
- /** 列表容器滚动事件。 */
135
- onListScroll?: (e: Event) => void;
136
- class?: string;
137
- } = $props();
138
-
139
- const loc = useLocale();
140
- // 单例 live region(polite):selectable 模式选中/取消时播报(红线 #3:命令式)。
141
- const announcer = useLiveAnnouncer();
142
-
143
- function isSnippet(v: unknown): v is Snippet {
144
- return typeof v === 'function';
145
- }
146
-
147
- function keyOf(item: T, index: number): string | number {
148
- if (typeof rowKey === 'function') return rowKey(item);
149
- const rec = item as unknown as Record<string, unknown>;
150
- const k = rec?.[rowKey];
151
- if (typeof k === 'string' || typeof k === 'number') return k;
152
- return index;
153
- }
154
-
155
- // 声明式用法:未传 dataSource 且存在 children(内嵌 <List.Item>)。优先级低于 dataSource。
156
- const useDeclarative = $derived(dataSource.length === 0 && children != null);
157
-
158
- const isEmpty = $derived(!loading && !useDeclarative && dataSource.length === 0);
159
- const skeletonRows = $derived(Array.from({ length: Math.max(0, skeletonCount) }, (_, i) => i));
160
-
161
- // --- selectable 选中态:受控 selectedKeys 不回写,本地 inner 兜底(红线 #1) ---
162
- const selectMode = $derived<'single' | 'multiple' | null>(
163
- selectable === 'single' || selectable === 'multiple' ? selectable : null,
164
- );
165
- const isSelectControlled = $derived(selectedKeys !== undefined);
166
- let innerSelected = $state<ListKey[]>(untrack(() => [...defaultSelectedKeys]));
167
- // 当前选中集合(受控优先);用 Set 做 O(1) 命中判定(红线 #2:纯派生)。
168
- const selectedSet = $derived<ReadonlySet<ListKey>>(
169
- new Set(selectedKeys !== undefined ? selectedKeys : innerSelected),
170
- );
171
- // shift 连选锚点(普通簿记变量,不参与 render 响应式)。
172
- let anchorIndex = -1;
173
-
174
- function keyToItem(key: ListKey): T | undefined {
175
- for (let i = 0; i < dataSource.length; i += 1) {
176
- const it = dataSource[i]!;
177
- if (keyOf(it, i) === key) return it;
178
- }
179
- return undefined;
180
- }
181
-
182
- // 命令式选中切换:算出下一集合 → 仅回调 onSelectionChange(受控不回写,红线 #1)。
183
- function toggleKey(key: ListKey, shiftKey: boolean): void {
184
- if (!selectMode) return;
185
- let next: Set<ListKey>;
186
- if (shiftKey && selectMode === 'multiple' && anchorIndex >= 0) {
187
- const orderedKeys = dataSource.map((it, i) => keyOf(it, i));
188
- const targetIndex = orderedKeys.indexOf(key);
189
- next = rangeSelection(selectedSet, orderedKeys, anchorIndex, targetIndex);
190
- } else {
191
- next = toggleSelection(selectedSet, key, selectMode);
192
- // 仅非 shift 单击更新锚点。
193
- if (selectMode === 'multiple') {
194
- anchorIndex = dataSource.findIndex((it, i) => keyOf(it, i) === key);
195
- }
196
- }
197
- const selected = next.has(key);
198
- if (!isSelectControlled) innerSelected = [...next];
199
- onSelectionChange?.([...next], { item: keyToItem(key), key, selected });
200
- // polite 播报当前操作项的选中/取消状态。label 取常见文本字段,回退到 key。
201
- const label = selectionLabel(key);
202
- announcer.announce(
203
- loc().t(selected ? 'List.selectAnnounce' : 'List.deselectAnnounce', { label }),
204
- );
205
- }
206
-
207
- // 选中播报用可读名:优先 item 的字符串本体或 label/title/name 字段,回退到 key。
208
- function selectionLabel(key: ListKey): string {
209
- const item = keyToItem(key);
210
- if (typeof item === 'string' || typeof item === 'number') return String(item);
211
- const rec = item as unknown as Record<string, unknown> | undefined;
212
- const text = rec?.label ?? rec?.title ?? rec?.name;
213
- if (typeof text === 'string' || typeof text === 'number') return String(text);
214
- return String(key);
215
- }
216
-
217
- // 向声明式 <List.Item> 暴露 selectable 状态(getter 保持响应性;红线 #2:子项不写 $state)。
218
- setListContext({
219
- getSelectable: () => selectable,
220
- isSelected: (key) => selectedSet.has(key),
221
- toggle: (key, shiftKey) => toggleKey(key, shiftKey),
222
- getSize: () => size,
223
- rowTabindex: (key) => itemTabindex(key),
224
- onRowKeydown: (e, key) => onItemKeydown(e, key),
225
- onRowFocus: (key) => onRowFocus(key),
226
- });
227
-
228
- // --- 虚拟化几何(复用 core 区间数学;红线 #2/#3) ---
229
- const virtualOn = $derived(virtualized !== false && virtualized !== undefined);
230
- const vCfg = $derived<VirtualConfig>(
231
- virtualized && virtualized !== undefined
232
- ? virtualized
233
- : { height: 400 },
234
- );
235
- const vDynamic = $derived(virtualOn && vCfg.itemSize === 'auto');
236
- const vItemSize = $derived(typeof vCfg.itemSize === 'number' ? vCfg.itemSize : 40);
237
- const vEstimated = $derived(vCfg.estimatedItemSize ?? 40);
238
- const vOverscan = $derived(vCfg.overscan ?? 3);
239
- const vHeightStyle = $derived(
240
- typeof vCfg.height === 'number' ? `${vCfg.height}px` : vCfg.height,
241
- );
242
-
243
- // viewport 元素普通引用(bind:this),不参与响应式几何读取。
244
- let viewportEl = $state<HTMLDivElement | null>(null);
245
- // 本地响应式状态:仅由命令式回调 / ResizeObserver 写入,render 期只读。
246
- let vScrollTop = $state(0);
247
- let vMeasuredH = $state(0);
248
- let vHeights = $state<Record<number, number>>({});
249
- let vRafId = 0;
250
-
251
- // 有效视口高:number 直接用,字符串用测量值。
252
- const vViewportH = $derived(
253
- typeof vCfg.height === 'number' ? vCfg.height : vMeasuredH,
254
- );
255
-
256
- // dynamic:合并实测/估算每项高度 → 前缀和 offsets(render-safe,仅依赖 $state)。
257
- const vOffsets = $derived.by(() => {
258
- if (!vDynamic) return [] as number[];
259
- const arr = new Array<number>(dataSource.length);
260
- for (let i = 0; i < dataSource.length; i += 1) arr[i] = vHeights[i] ?? vEstimated;
261
- return buildOffsets(arr);
262
- });
263
- const vTotalHeight = $derived(
264
- vDynamic ? totalFromOffsets(vOffsets) : dataSource.length * vItemSize,
265
- );
266
- const vRange = $derived(
267
- vDynamic
268
- ? dynamicRange(vOffsets, vScrollTop, vViewportH, vOverscan)
269
- : fixedRange(vScrollTop, vViewportH, vItemSize, dataSource.length, vOverscan),
270
- );
271
- const vStart = $derived(vRange.startIndex);
272
- const vEnd = $derived(vRange.endIndex);
273
- const vVisible = $derived(dataSource.slice(vStart, vEnd));
274
-
275
- function vItemOffset(index: number): number {
276
- if (vDynamic) return vOffsets[index] ?? index * vEstimated;
277
- return index * vItemSize;
278
- }
279
- function vItemMainSize(index: number): number {
280
- if (vDynamic) return vHeights[index] ?? vEstimated;
281
- return vItemSize;
282
- }
283
- function vItemStyle(index: number): string {
284
- const off = vItemOffset(index);
285
- if (vDynamic) return `transform:translateY(${off}px)`;
286
- return `transform:translateY(${off}px); block-size:${vItemSize}px`;
287
- }
288
-
289
- /**
290
- * 命令式滚动到指定索引项(红线 #3:直接写 DOM scrollTop,非 render 期)。
291
- */
292
- export function scrollToIndex(
293
- index: number,
294
- opts?: { align?: ScrollAlign },
295
- ): void {
296
- const el = viewportEl;
297
- if (!el || !virtualOn || dataSource.length === 0) return;
298
- const i = Math.max(0, Math.min(dataSource.length - 1, Math.floor(index)));
299
- const totalMain = vDynamic ? totalFromOffsets(vOffsets) : dataSource.length * vItemSize;
300
- const target = scrollOffsetForIndex(
301
- vItemOffset(i),
302
- vItemMainSize(i),
303
- el.clientHeight,
304
- totalMain,
305
- opts?.align ?? 'start',
306
- );
307
- el.scrollTop = target;
308
- vScrollTop = target;
309
- }
310
-
311
- // 虚拟化滚动监听(命令式 + rAF 节流 + cleanup;红线 #3)。
312
- $effect(() => {
313
- const el = viewportEl;
314
- if (!el || !virtualOn) return;
315
- function onScroll() {
316
- if (vRafId) return;
317
- vRafId = requestAnimationFrame(() => {
318
- vRafId = 0;
319
- if (el) vScrollTop = el.scrollTop;
320
- });
321
- }
322
- el.addEventListener('scroll', onScroll, { passive: true });
323
- return () => {
324
- el.removeEventListener('scroll', onScroll);
325
- if (vRafId) {
326
- cancelAnimationFrame(vRafId);
327
- vRafId = 0;
328
- }
329
- };
330
- });
331
-
332
- // 视口高度测量:仅 height 非数字(字符串)时启用 ResizeObserver。
333
- $effect(() => {
334
- const el = viewportEl;
335
- if (!el || !virtualOn || typeof vCfg.height === 'number') return;
336
- vMeasuredH = el.clientHeight;
337
- const ro = new ResizeObserver((entries) => {
338
- for (const entry of entries) vMeasuredH = entry.contentRect.height;
339
- });
340
- ro.observe(el);
341
- return () => ro.disconnect();
342
- });
343
-
344
- // dynamic 行高实测 + 偏移补偿(命令式 ResizeObserver,cleanup disconnect;红线 #2/#3)。
345
- $effect(() => {
346
- const el = viewportEl;
347
- if (!el || !virtualOn || !vDynamic) return;
348
- void vVisible; // 依赖渲染行集合变化重建 observer。
349
-
350
- function measure(node: Element) {
351
- const idx = Number((node as HTMLElement).dataset.vindex);
352
- if (Number.isNaN(idx)) return;
353
- const h = (node as HTMLElement).getBoundingClientRect().height;
354
- if (h <= 0) return;
355
- const prev = vHeights[idx];
356
- if (prev !== undefined && Math.abs(prev - h) < 0.5) return;
357
- const before = prev ?? vEstimated;
358
- const delta = h - before;
359
- vHeights[idx] = h;
360
- if (delta !== 0 && el && vItemOffset(idx) < vScrollTop) {
361
- el.scrollTop += delta;
362
- vScrollTop = el.scrollTop;
363
- }
364
- }
365
-
366
- const ro = new ResizeObserver((entries) => {
367
- for (const entry of entries) measure(entry.target);
368
- });
369
- const rows = el.querySelectorAll<HTMLElement>('[data-vindex]');
370
- rows.forEach((node) => {
371
- measure(node);
372
- ro.observe(node);
373
- });
374
- return () => ro.disconnect();
375
- });
376
-
377
- // selectable 行点击/键盘(dataSource 模式用;声明式由 List.Item 自身处理)。
378
- function onRowActivate(item: T, index: number, shiftKey: boolean): void {
379
- toggleKey(keyOf(item, index), shiftKey);
380
- }
381
-
382
- // --- roving tabindex(a11y §6 / Listbox APG):selectable 行组为单一 Tab 停靠点。 ---
383
- // rootEl 普通引用(bind:this),命令式 focus() 用,非 render 期读 DOM;
384
- // 声明式 / 虚拟化 / 普通三种渲染路径的行都带 data-list-key,统一按 DOM 顺序漫游
385
- // (红线 #2:不用 $state 数组收集子项,避免 effect 自循环)。
386
- let rootEl = $state<HTMLElement | null>(null);
387
- // 当前焦点行的 key;null = 尚无焦点 -> 首行作为 Tab 停靠点。
388
- let focusedRowKey = $state<ListKey | null>(null);
389
-
390
- // selectable 模式下行的有序 key 列表(用于 roving 首末 / PageUp/Down 计算)。
391
- const rowKeys = $derived<ListKey[]>(
392
- selectMode ? dataSource.map((it, i) => keyOf(it, i)) : [],
393
- );
394
-
395
- // 纯派生 tabindex:焦点行(或无焦点时首行)为 0,其余 -1(红线 #2:render 期只读)。
396
- function rowTabindex(key: ListKey): 0 | -1 {
397
- if (!selectMode) return 0;
398
- return (focusedRowKey ?? rowKeys[0]) === key ? 0 : -1;
399
- }
400
-
401
- function focusRowByKey(key: ListKey): void {
402
- rootEl
403
- ?.querySelector<HTMLElement>(
404
- `[data-list-key="${CSS.escape(String(key))}"]`,
405
- )
406
- ?.focus();
407
- }
408
-
409
- // DOM 顺序的行 key 列表(声明式 <List.Item> 用:行不在 dataSource 内,按 DOM 漫游)。
410
- function domRowKeys(): string[] {
411
- if (!rootEl) return [];
412
- return [...rootEl.querySelectorAll<HTMLElement>('[data-list-key]')].map(
413
- (el) => el.dataset.listKey ?? '',
414
- );
415
- }
416
-
417
- // 翻一屏的行数(虚拟化按可视区估算,否则固定 10 行兜底)。
418
- function pageStep(): number {
419
- if (virtualOn && vItemSize > 0) {
420
- return Math.max(1, Math.floor(vViewportH / vItemSize));
421
- }
422
- return 10;
423
- }
424
-
425
- // 行 keydown:↑↓ roving、Home/End 跳首末、PageUp/Down 翻屏、Space/Enter 激活。
426
- // Shift+↑↓(multiple)连选。命令式 focus() 在事件回调(非 render 期)。
427
- function onRowKeydown(e: KeyboardEvent, item: T, index: number): void {
428
- const key = keyOf(item, index);
429
- if (e.key === ' ' || e.key === 'Enter') {
430
- e.preventDefault();
431
- onRowActivate(item, index, e.shiftKey);
432
- return;
433
- }
434
- if (!selectMode) return;
435
- const keys = rowKeys;
436
- if (keys.length === 0) return;
437
- const cur = keys.indexOf(key);
438
- let target = -1;
439
- if (e.key === 'ArrowDown') target = Math.min(keys.length - 1, cur + 1);
440
- else if (e.key === 'ArrowUp') target = Math.max(0, cur - 1);
441
- else if (e.key === 'Home') target = 0;
442
- else if (e.key === 'End') target = keys.length - 1;
443
- else if (e.key === 'PageDown') target = Math.min(keys.length - 1, cur + pageStep());
444
- else if (e.key === 'PageUp') target = Math.max(0, cur - pageStep());
445
- else return;
446
- e.preventDefault();
447
- const targetKey = keys[target];
448
- if (targetKey == null) return;
449
- focusedRowKey = targetKey;
450
- // multiple 模式 Shift+方向键:移动焦点同时连选(范围以锚点为基准)。
451
- if (e.shiftKey && selectMode === 'multiple') {
452
- toggleKey(targetKey, true);
453
- }
454
- focusRowByKey(targetKey);
455
- }
456
- function onRowFocus(key: ListKey): void {
457
- focusedRowKey = key;
458
- }
459
-
460
- // 声明式 <List.Item> keydown:按 DOM 顺序 roving(行不在 dataSource 内)。
461
- // Space/Enter 由 List.Item 自身的 activate 处理,这里只管方向键 / Home/End / PageUp/Down。
462
- function onItemKeydown(e: KeyboardEvent, key: ListKey): void {
463
- if (!selectMode) return;
464
- const keys = domRowKeys();
465
- if (keys.length === 0) return;
466
- const cur = keys.indexOf(String(key));
467
- if (cur < 0) return;
468
- let target = -1;
469
- if (e.key === 'ArrowDown') target = Math.min(keys.length - 1, cur + 1);
470
- else if (e.key === 'ArrowUp') target = Math.max(0, cur - 1);
471
- else if (e.key === 'Home') target = 0;
472
- else if (e.key === 'End') target = keys.length - 1;
473
- else if (e.key === 'PageDown') target = Math.min(keys.length - 1, cur + pageStep());
474
- else if (e.key === 'PageUp') target = Math.max(0, cur - pageStep());
475
- else return;
476
- e.preventDefault();
477
- const targetKey = keys[target];
478
- if (targetKey == null) return;
479
- focusedRowKey = targetKey;
480
- if (e.shiftKey && selectMode === 'multiple') toggleKey(targetKey, true);
481
- focusRowByKey(targetKey);
482
- }
483
- // 声明式行 tabindex:焦点行 / 首个 DOM 行为 0,其余 -1(红线 #2:render 期只读)。
484
- // 挂载前 rootEl 为空、DOM 顺序未知,回退为 0 保证可 Tab 进入;挂载后由 DOM 查询收敛为单一停靠点。
485
- function itemTabindex(key: ListKey): 0 | -1 {
486
- if (!selectMode) return 0;
487
- if (focusedRowKey != null) return focusedRowKey === key ? 0 : -1;
488
- const keys = domRowKeys();
489
- if (keys.length === 0) return 0;
490
- return keys[0] === String(key) ? 0 : -1;
491
- }
492
-
493
- // --- 分页:受控 current 不回写 (红线 #1),本地 inner 兜底 ---
494
- const paginationOn = $derived(pagination !== undefined && pagination !== false);
495
- const pageSize = $derived(pagination ? (pagination.pageSize ?? 10) : 10);
496
- const isPageControlled = $derived(!!pagination && pagination.current !== undefined);
497
- let innerPage = $state(untrack(() => (pagination ? (pagination.defaultCurrent ?? 1) : 1)));
498
- const currentPage = $derived(
499
- pagination && pagination.current !== undefined ? pagination.current : innerPage,
500
- );
501
- // 当前页切片数据;未分页时为全量。
502
- const pagedData = $derived.by<T[]>(() => {
503
- if (!paginationOn) return dataSource;
504
- const start = (currentPage - 1) * pageSize;
505
- return dataSource.slice(start, start + pageSize);
506
- });
507
- function onPageChange(page: number) {
508
- if (!isPageControlled) innerPage = page;
509
- if (pagination) pagination.onChange?.(page);
510
- }
511
-
512
- // grid 布局:解析列数/间距,生成 inline CSS(CSS grid)。
513
- const gridOn = $derived(grid !== undefined);
514
- const gridColumn = $derived(
515
- typeof grid === 'number' ? grid : (grid?.column ?? 4),
516
- );
517
- const gridGutter = $derived(
518
- typeof grid === 'object' ? (grid.gutter ?? 16) : 16,
519
- );
520
- const gridStyle = $derived(
521
- gridOn
522
- ? `display:grid;grid-template-columns:repeat(${gridColumn},minmax(0,1fr));gap:${gridGutter}px`
523
- : undefined,
524
- );
525
-
526
- const cls = $derived(
527
- [
528
- 'cd-list',
529
- `cd-list--${size}`,
530
- bordered && 'cd-list--bordered',
531
- split && 'cd-list--split',
532
- selectMode && 'cd-list--selectable',
533
- layout === 'horizontal' && 'cd-list--horizontal',
534
- className,
535
- ]
536
- .filter(Boolean)
537
- .join(' '),
538
- );
539
-
540
- // selectable 列表语义:role=listbox(multiple 时 aria-multiselectable),否则原生 list。
541
- const itemsRole = $derived(selectMode ? 'listbox' : undefined);
542
- const itemsMultiselect = $derived(selectMode === 'multiple' ? true : undefined);
543
- // listbox 可访问名(aria-input-field-name):缺省回退 i18n。非 selectable 时不设。
544
- const itemsLabel = $derived(
545
- selectMode ? (ariaLabel ?? loc().t('List.selectableLabel')) : undefined,
546
- );
547
- </script>
548
-
549
- <!--
550
- selectable 行的勾选指示器:纯视觉(aria-hidden + 无 input),避免 option 内嵌可聚焦控件
551
- 导致 axe nested-interactive。选中态由行 aria-selected 表达,勾选/取消走行的 Space/Enter。
552
- -->
553
- {#snippet selectorMark(sel: boolean)}
554
- <span class="cd-list__item-selector" aria-hidden="true">
555
- <span class="cd-list__check" class:cd-list__check--on={sel}>
556
- {#if sel}
557
- <svg viewBox="0 0 16 16" width="10" height="10" focusable="false">
558
- <path
559
- fill="none"
560
- stroke="currentColor"
561
- stroke-width="2"
562
- stroke-linecap="round"
563
- stroke-linejoin="round"
564
- d="M3.5 8.5 6.5 11.5 12.5 4.5"
565
- />
566
- </svg>
567
- {/if}
568
- </span>
569
- </span>
570
- {/snippet}
571
-
572
- <div class={cls} aria-busy={loading || undefined} bind:this={rootEl} onscroll={onListScroll}>
573
- {#if header !== undefined}
574
- <div class="cd-list__header">
575
- {#if isSnippet(header)}{@render header()}{:else}{header}{/if}
576
- </div>
577
- {/if}
578
-
579
- <div class="cd-list__body">
580
- {#if loading && loadingSkeleton}
581
- <ul class="cd-list__items" aria-hidden="true">
582
- {#each skeletonRows as i (i)}
583
- <li class="cd-list__item cd-list__item--skeleton">
584
- <span class="cd-list__skeleton-bar"></span>
585
- </li>
586
- {/each}
587
- </ul>
588
- {:else if loading}
589
- <div class="cd-list__spinner-wrap">
590
- <span class="cd-list__spinner" aria-hidden="true"></span>
591
- </div>
592
- {:else if isEmpty}
593
- <div class="cd-list__empty">
594
- {#if isSnippet(emptyContent)}
595
- {@render emptyContent()}
596
- {:else if emptyContent !== undefined}
597
- {emptyContent}
598
- {:else}
599
- <Empty image="noData" />
600
- {/if}
601
- </div>
602
- {:else if useDeclarative}
603
- <!-- 声明式:渲染内嵌 <List.Item>(selectable 状态经 context 下发)。 -->
604
- <ul
605
- class="cd-list__items"
606
- role={itemsRole}
607
- aria-multiselectable={itemsMultiselect}
608
- aria-label={itemsLabel}
609
- >
610
- {@render children?.()}
611
- </ul>
612
- {:else if virtualOn}
613
- <!-- 虚拟化:仅渲染视口内行,复用 core 区间数学;命令式滚动监听(红线 #2/#3)。 -->
614
- <div
615
- class="cd-list__virtual"
616
- bind:this={viewportEl}
617
- role={itemsRole ?? 'list'}
618
- aria-multiselectable={itemsMultiselect}
619
- aria-label={itemsLabel}
620
- style={`block-size:${vHeightStyle}; overflow:auto`}
621
- >
622
- <div class="cd-list__virtual-spacer" style={`block-size:${vTotalHeight}px`}>
623
- {#each vVisible as item, i (keyOf(item, vStart + i))}
624
- {@const index = vStart + i}
625
- {@const k = keyOf(item, index)}
626
- {@const sel = selectMode ? selectedSet.has(k) : false}
627
- <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
628
- <div
629
- class="cd-list__item cd-list__virtual-item"
630
- class:cd-list__item--selectable={!!selectMode}
631
- class:cd-list__item--selected={sel}
632
- data-vindex={index}
633
- data-list-key={selectMode ? k : undefined}
634
- role={selectMode ? 'option' : 'listitem'}
635
- aria-selected={selectMode ? sel : undefined}
636
- aria-setsize={dataSource.length}
637
- aria-posinset={index + 1}
638
- tabindex={selectMode ? rowTabindex(k) : undefined}
639
- style={vItemStyle(index)}
640
- onclick={selectMode ? (e) => onRowActivate(item, index, e.shiftKey) : undefined}
641
- onkeydown={selectMode ? (e) => onRowKeydown(e, item, index) : undefined}
642
- onfocus={selectMode ? () => onRowFocus(k) : undefined}
643
- >
644
- {#if selectMode}
645
- {@render selectorMark(sel)}
646
- {/if}
647
- <div class="cd-list__item-content">
648
- {#if renderItem}{@render renderItem(item, index)}{/if}
649
- </div>
650
- </div>
651
- {/each}
652
- </div>
653
- </div>
654
- {:else}
655
- <ul
656
- class="cd-list__items"
657
- class:cd-list__items--grid={gridOn}
658
- style={gridStyle}
659
- role={itemsRole}
660
- aria-multiselectable={itemsMultiselect}
661
- aria-label={itemsLabel}
662
- >
663
- {#each pagedData as item, index (keyOf(item, index))}
664
- {@const realIndex = paginationOn ? (currentPage - 1) * pageSize + index : index}
665
- {@const k = keyOf(item, realIndex)}
666
- {@const sel = selectMode ? selectedSet.has(k) : false}
667
- {#if selectMode}
668
- <li
669
- class="cd-list__item cd-list__item--selectable"
670
- class:cd-list__item--selected={sel}
671
- class:cd-list__item--grid={gridOn}
672
- data-list-key={k}
673
- role="option"
674
- aria-selected={sel}
675
- tabindex={rowTabindex(k)}
676
- onclick={(e) => onRowActivate(item, realIndex, e.shiftKey)}
677
- onkeydown={(e) => onRowKeydown(e, item, realIndex)}
678
- onfocus={() => onRowFocus(k)}
679
- >
680
- {@render selectorMark(sel)}
681
- <div class="cd-list__item-content">
682
- {#if renderItem}{@render renderItem(item, realIndex)}{/if}
683
- </div>
684
- </li>
685
- {:else}
686
- <li class="cd-list__item" class:cd-list__item--grid={gridOn}>
687
- {#if renderItem}{@render renderItem(item, realIndex)}{/if}
688
- </li>
689
- {/if}
690
- {/each}
691
- </ul>
692
-
693
- {#if paginationOn}
694
- <div class="cd-list__pagination">
695
- <Pagination
696
- total={dataSource.length}
697
- currentPage={currentPage}
698
- {pageSize}
699
- size={size === 'large' ? 'default' : size}
700
- onChange={onPageChange}
701
- />
702
- </div>
703
- {:else if loadMore}
704
- <div class="cd-list__load-more">{@render loadMore()}</div>
705
- {:else if onLoadMore !== undefined && (hasMore || loadingMore)}
706
- <div class="cd-list__load-more">
707
- <Button
708
- loading={loadingMore}
709
- disabled={!hasMore && !loadingMore}
710
- onclick={() => onLoadMore?.()}
711
- >
712
- {loc().t('List.loadMore')}
713
- </Button>
714
- </div>
715
- {/if}
716
- {/if}
717
- </div>
718
-
719
- {#if footer !== undefined}
720
- <div class="cd-list__footer">
721
- {#if isSnippet(footer)}{@render footer()}{:else}{footer}{/if}
722
- </div>
723
- {/if}
724
- </div>
725
-
726
- <style>
727
- .cd-list {
728
- background: var(--cd-list-bg);
729
- color: var(--cd-list-item-color);
730
- --cd-list-pad-y: var(--cd-list-item-padding);
731
- }
732
- .cd-list--small {
733
- --cd-list-pad-y: var(--cd-list-item-padding-small);
734
- }
735
- .cd-list--bordered {
736
- border: 1px solid var(--cd-list-border);
737
- border-radius: var(--cd-list-radius);
738
- overflow: hidden;
739
- }
740
-
741
- /* horizontal layout: item 内容横向排列 */
742
- .cd-list--horizontal .cd-list__item {
743
- display: flex;
744
- flex-direction: row;
745
- align-items: flex-start;
746
- gap: var(--cd-spacing-3, 12px);
747
- }
748
-
749
- .cd-list__header {
750
- padding-block: var(--cd-list-pad-y);
751
- padding-inline: var(--cd-list-item-padding);
752
- color: var(--cd-list-header-color);
753
- border-block-end: 1px solid var(--cd-list-split-color);
754
- }
755
- .cd-list__footer {
756
- padding-block: var(--cd-list-pad-y);
757
- padding-inline: var(--cd-list-item-padding);
758
- border-block-start: 1px solid var(--cd-list-split-color);
759
- }
760
-
761
- .cd-list__items {
762
- margin: 0;
763
- padding: 0;
764
- list-style: none;
765
- }
766
- .cd-list__item {
767
- padding-block: var(--cd-list-pad-y);
768
- padding-inline: var(--cd-list-item-padding);
769
- }
770
- .cd-list--split .cd-list__item + .cd-list__item {
771
- border-block-start: 1px solid var(--cd-list-split-color);
772
- }
773
- /* grid 模式:取消 split 分隔线与行内边距,由 grid gap 控制间距 */
774
- .cd-list__items--grid {
775
- padding-block: var(--cd-list-pad-y);
776
- }
777
- .cd-list--split .cd-list__item--grid + .cd-list__item--grid {
778
- border-block-start: none;
779
- }
780
- .cd-list__item--grid {
781
- padding: 0;
782
- }
783
-
784
- /* selectable 行:内置 checkbox + 主内容横向布局,选中/hover/focus 强调。 */
785
- .cd-list__item--selectable {
786
- display: flex;
787
- align-items: flex-start;
788
- gap: var(--cd-spacing-2, 8px);
789
- cursor: pointer;
790
- outline: none;
791
- }
792
- .cd-list__item--selectable:hover {
793
- background: var(--cd-color-fill-0, rgba(0, 0, 0, 0.03));
794
- }
795
- .cd-list__item--selectable:focus-visible {
796
- box-shadow: inset 0 0 0 2px var(--cd-color-primary, #0066ff);
797
- }
798
- .cd-list__item--selected {
799
- background: var(--cd-color-primary-light-default, rgba(0, 102, 255, 0.1));
800
- }
801
- .cd-list__item-selector {
802
- flex: none;
803
- display: flex;
804
- align-items: center;
805
- pointer-events: none;
806
- }
807
- /* 纯视觉勾选框(无 input;选中态走行 aria-selected,避免 nested-interactive)。 */
808
- .cd-list__check {
809
- display: inline-flex;
810
- align-items: center;
811
- justify-content: center;
812
- flex: none;
813
- inline-size: 16px;
814
- block-size: 16px;
815
- border: 1px solid var(--cd-color-border);
816
- border-radius: var(--cd-radius-small, 4px);
817
- color: var(--cd-color-bg-0, #fff);
818
- background: var(--cd-color-bg-0, #fff);
819
- }
820
- .cd-list__check--on {
821
- background: var(--cd-color-primary, #0066ff);
822
- border-color: var(--cd-color-primary, #0066ff);
823
- }
824
- .cd-list__item-content {
825
- flex: 1;
826
- min-inline-size: 0;
827
- }
828
-
829
- /* 虚拟化:视口自身滚动,撑高占位 + 绝对定位行。 */
830
- .cd-list__virtual {
831
- position: relative;
832
- inline-size: 100%;
833
- scrollbar-color: var(--cd-virtual-list-scrollbar, currentColor) transparent;
834
- }
835
- .cd-list__virtual-spacer {
836
- position: relative;
837
- inline-size: 100%;
838
- }
839
- .cd-list__virtual-item {
840
- position: absolute;
841
- inset-block-start: 0;
842
- inset-inline: 0;
843
- }
844
-
845
- .cd-list__load-more {
846
- display: flex;
847
- justify-content: center;
848
- padding-block: var(--cd-list-item-padding);
849
- }
850
- .cd-list__pagination {
851
- display: flex;
852
- justify-content: flex-end;
853
- padding-block: var(--cd-list-item-padding);
854
- padding-inline: var(--cd-list-item-padding);
855
- }
856
-
857
- .cd-list__empty {
858
- padding-block: var(--cd-list-item-padding);
859
- display: flex;
860
- justify-content: center;
861
- }
862
-
863
- .cd-list__spinner-wrap {
864
- display: flex;
865
- align-items: center;
866
- justify-content: center;
867
- padding-block: calc(var(--cd-list-item-padding) * 2);
868
- }
869
- .cd-list__spinner {
870
- inline-size: 1.5em;
871
- block-size: 1.5em;
872
- border: 2px solid var(--cd-list-split-color);
873
- border-block-start-color: var(--cd-color-primary, currentColor);
874
- border-radius: var(--cd-radius-full);
875
- animation: cd-list-spin 0.7s linear infinite;
876
- }
877
-
878
- .cd-list__skeleton-bar {
879
- display: block;
880
- block-size: 1em;
881
- inline-size: 100%;
882
- border-radius: var(--cd-radius-small);
883
- background: var(--cd-list-split-color);
884
- position: relative;
885
- overflow: hidden;
886
- }
887
- .cd-list__skeleton-bar::after {
888
- content: '';
889
- position: absolute;
890
- inset: 0;
891
- transform: translateX(-100%);
892
- background: linear-gradient(
893
- 90deg,
894
- transparent,
895
- var(--cd-list-bg),
896
- transparent
897
- );
898
- animation: cd-list-shimmer 1.2s ease-in-out infinite;
899
- }
900
-
901
- @keyframes cd-list-spin {
902
- to {
903
- transform: rotate(360deg);
904
- }
905
- }
906
- @keyframes cd-list-shimmer {
907
- 100% {
908
- transform: translateX(100%);
909
- }
910
- }
911
-
912
- @media (prefers-reduced-motion: reduce) {
913
- .cd-list__spinner {
914
- animation: none;
915
- }
916
- .cd-list__skeleton-bar::after {
917
- animation: none;
918
- }
919
- }
920
- </style>