@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,1798 +0,0 @@
1
- <!--
2
- DatePicker — see specs/components/input/DatePicker.spec.md
3
- 基础子集: 单选 type='date' 日历面板 / type='dateTime' 日期+时间。Token-driven, a11y-correct, 受控/非受控。
4
- 本地化全部走 Intl.DateTimeFormat (不手拼日期串)。dateTime 复用 TimePicker 的时/分/秒列逻辑。
5
- disabledTime: dateTime 时/分/秒列按日期禁用值置灰跳过;presets: 面板侧边快捷日期按钮。
6
- format: 传 token 串(YYYY/MM/DD/HH/mm/ss)时,触发器变可输入文本框,显示与手输解析均走
7
- core 的 formatDate/parseDateString 纯函数(红线 #2);不传则沿用 Intl.DateTimeFormat 显示(向后兼容)。
8
- -->
9
- <script lang="ts">
10
- import { tick, type Snippet } from 'svelte';
11
- import { useId, useDismiss, useFocusTrap, isSameDay, startOfDay, addMonths, getMonthGrid, weekdayOrder, gridFocusMove, formatDate, parseDateString, type GridFocusKey } from '@chenzy-design/core';
12
- import { useLocale } from '../locale-provider/index.js';
13
-
14
- type Size = 'small' | 'default' | 'large';
15
- type Status = 'default' | 'warning' | 'error';
16
- type WeekStart = 0 | 1 | 2 | 3 | 4 | 5 | 6;
17
- type PickerType = 'date' | 'dateTime' | 'month' | 'year';
18
- type CSSProperties = Record<string, string | number>;
19
- type PresetPosition = 'left' | 'right' | 'top' | 'bottom';
20
-
21
- // 时间列禁用配置 (Semi/AntD 风格):按当前日期返回各列禁用值
22
- interface DisabledTime {
23
- disabledHours?: () => number[];
24
- disabledMinutes?: (hour: number) => number[];
25
- disabledSeconds?: (hour: number, minute: number) => number[];
26
- }
27
-
28
- // 快捷日期项:value 可为 Date 或惰性求值函数 (点击时才计算,如「今天」)
29
- interface Preset {
30
- label: string;
31
- value: Date | (() => Date);
32
- }
33
-
34
- interface DayStatus {
35
- isSelected: boolean;
36
- isToday: boolean;
37
- isDisabled: boolean;
38
- isInMonth: boolean;
39
- }
40
-
41
- interface Props {
42
- type?: PickerType;
43
- value?: Date | Date[] | null;
44
- defaultValue?: Date | Date[] | null;
45
- open?: boolean;
46
- defaultOpen?: boolean;
47
- placeholder?: string;
48
- size?: Size;
49
- status?: Status;
50
- disabled?: boolean;
51
- clearable?: boolean;
52
- disabledDate?: (date: Date) => boolean;
53
- disabledTime?: (date: Date) => DisabledTime;
54
- presets?: Preset[];
55
- weekStart?: WeekStart;
56
- showSecond?: boolean;
57
- locale?: string;
58
- /** token 格式串 (YYYY/MM/DD/HH/mm/ss)。传入则触发器变可输入文本框,显示+手输解析按此格式。 */
59
- format?: string;
60
- onChange?: (v: Date | Date[] | null) => void;
61
- onOpenChange?: (open: boolean) => void;
62
- /** 手动键入解析失败 (editable 模式)。 */
63
- onParseError?: (e: { text: string }) => void;
64
- /** 可见年月切换 (头部导航)。 */
65
- onPanelChange?: (e: { panelDate: Date }) => void;
66
- /** 点击快捷选项。 */
67
- onPresetClick?: (e: { preset: Preset }) => void;
68
- /** 点击清除。 */
69
- onClear?: (e: Record<string, never>) => void;
70
- /** 点击确认按钮 (dateTime / needConfirm)。 */
71
- onConfirm?: (e: { value: Date | Date[] | null }) => void;
72
- /** 触发器获得焦点。 */
73
- onFocus?: (e: FocusEvent) => void;
74
- /** 触发器失去焦点。 */
75
- onBlur?: (e: FocusEvent) => void;
76
- ariaLabel?: string;
77
- /** 用 Snippet 自定义范围分隔符,优先于 rangeSeparator 字符串。 */
78
- rangeSeparatorNode?: Snippet;
79
- /** 选完月/年后自动切换到日视图(默认 true)。 */
80
- autoSwitchDate?: boolean;
81
- /** 浮层自动调整位置防溢出(默认 true)。 */
82
- autoAdjustOverflow?: boolean;
83
- /** 范围模式下在面板内嵌输入框(默认 false)。 */
84
- insetInput?: boolean;
85
- /** 浮层弹出位置(默认 'bottomLeft')。 */
86
- position?: string;
87
- /** 触发器与浮层间距。 */
88
- spacing?: number;
89
- /** 浮层挂载容器。 */
90
- getPopupContainer?: () => HTMLElement;
91
- /** weekStart 别名。 */
92
- weekStartsOn?: WeekStart;
93
- /** 点击取消按钮。 */
94
- onCancel?: (date: Date | Date[] | null, dateStr: string) => void;
95
- /** onChange 参数改为 dateFirst(仅声明,透传语义)。 */
96
- onChangeWithDateFirst?: boolean;
97
- /** 点击外部关闭时触发。 */
98
- onClickOutSide?: (e: MouseEvent) => void;
99
-
100
- // --- 外观类 ---
101
- /** 无边框模式 */
102
- borderless?: boolean;
103
- /** 面板尺寸 compact 时面板更紧凑 */
104
- density?: 'default' | 'compact';
105
- /** 触发器前缀内容,渲染在 input 左侧 */
106
- prefix?: Snippet | string;
107
- /** 自定义清除按钮图标 */
108
- clearIcon?: Snippet;
109
- /** 是否显示清除按钮(默认 true,受 clearable 控制) */
110
- showClear?: boolean;
111
- /** 输入框 readonly 属性 */
112
- inputReadOnly?: boolean;
113
- /** 输入框内联样式 */
114
- inputStyle?: CSSProperties | string;
115
- /** 挂载时自动聚焦 */
116
- autoFocus?: boolean;
117
-
118
- // --- 浮层类 ---
119
- /** 下拉浮层 className */
120
- dropdownClassName?: string;
121
- /** 下拉浮层样式 */
122
- dropdownStyle?: CSSProperties | string;
123
- /** 浮层溢出冗余值 */
124
- dropdownMargin?: number | { x?: number; y?: number };
125
- /** 浮层 z-index(默认 1030) */
126
- zIndex?: number;
127
- /** 面板展开动画,false 时添加 cd-date-picker--no-motion(默认 true) */
128
- motion?: boolean;
129
- /** 聚焦时阻止滚动 */
130
- preventScroll?: boolean;
131
- /** 阻止浮层点击事件冒泡(默认 true) */
132
- stopPropagation?: boolean;
133
-
134
- // --- 插槽类 ---
135
- /** 面板顶部额外区域 */
136
- topSlot?: Snippet;
137
- /** 面板底部额外区域 */
138
- bottomSlot?: Snippet;
139
- /** 面板左侧额外区域 */
140
- leftSlot?: Snippet;
141
- /** 面板右侧额外区域 */
142
- rightSlot?: Snippet;
143
-
144
- // --- 日期范围增强 ---
145
- /** 多选(仅 type='date'),value 变为 Date[] */
146
- multiple?: boolean;
147
- /** multiple=true 时最多选择数量 */
148
- max?: number;
149
- /** 范围日期分隔符(默认 '~') */
150
- rangeSeparator?: string;
151
- /** 单击选择范围的起始偏移 */
152
- startDateOffset?: (date: Date) => Date;
153
- /** 单击选择范围的结束偏移 */
154
- endDateOffset?: (date: Date) => Date;
155
- /** 年份滚轮最小年 */
156
- startYear?: number;
157
- /** 年份滚轮最大年 */
158
- endYear?: number;
159
- /** 范围选择双面板同步切换月份(默认 false) */
160
- syncSwitchMonth?: boolean;
161
-
162
- // --- 自定义渲染 ---
163
- /** 自定义日期单元格内容 */
164
- renderDate?: Snippet<[{ day: number; fullDate: string }]>;
165
- /** 完全自定义日期格子 */
166
- renderFullDate?: Snippet<[{ day: number; fullDate: string; dayStatus: DayStatus }]>;
167
- /** 完全自定义触发器 */
168
- triggerRender?: Snippet<[{ value: Date | Date[] | null; placeholder: string }]>;
169
-
170
- // --- 时间相关 ---
171
- /** 透传给内部 TimePicker 的参数 */
172
- timePickerOpts?: Record<string, unknown>;
173
- /** 隐藏禁止的时间选项 */
174
- hideDisabledOptions?: boolean;
175
- /** 禁止时间选择 */
176
- disabledTimePicker?: boolean;
177
- /** dateTime/dateTimeRange 时需要点击确认才写入 */
178
- needConfirm?: boolean;
179
-
180
- // --- 快捷选项 ---
181
- /** 快捷选项列表位置(默认 'bottom') */
182
- presetPosition?: PresetPosition;
183
-
184
- // --- 年月滚轮配置 ---
185
- /** 透传给年月 ScrollList 的参数 */
186
- yearAndMonthOpts?: { yearCyclic?: boolean; monthCyclic?: boolean } | Record<string, unknown>;
187
- }
188
-
189
- let {
190
- type = 'date',
191
- value,
192
- defaultValue = null,
193
- open,
194
- defaultOpen = false,
195
- placeholder,
196
- size = 'default',
197
- status = 'default',
198
- disabled = false,
199
- clearable = true,
200
- disabledDate,
201
- disabledTime,
202
- presets,
203
- weekStart = 0,
204
- showSecond = true,
205
- locale = 'zh-CN',
206
- format,
207
- onChange,
208
- onOpenChange,
209
- onParseError,
210
- onPanelChange,
211
- onPresetClick,
212
- onClear,
213
- onConfirm,
214
- onFocus,
215
- onBlur,
216
- ariaLabel,
217
- rangeSeparatorNode,
218
- rangeSeparator = '~',
219
- autoSwitchDate = true,
220
- autoAdjustOverflow = true,
221
- insetInput = false,
222
- position = 'bottomLeft',
223
- spacing,
224
- getPopupContainer,
225
- weekStartsOn,
226
- yearAndMonthOpts,
227
- onCancel,
228
- onChangeWithDateFirst = false,
229
- onClickOutSide,
230
- // 外观类
231
- borderless = false,
232
- density = 'default',
233
- prefix,
234
- clearIcon,
235
- showClear: showClearProp = true,
236
- inputReadOnly = false,
237
- inputStyle,
238
- autoFocus = false,
239
- // 浮层类
240
- dropdownClassName,
241
- dropdownStyle,
242
- dropdownMargin,
243
- zIndex = 1030,
244
- motion = true,
245
- preventScroll = false,
246
- stopPropagation = true,
247
- // 插槽类
248
- topSlot,
249
- bottomSlot,
250
- leftSlot,
251
- rightSlot,
252
- // 日期范围增强
253
- multiple = false,
254
- max,
255
- startDateOffset,
256
- endDateOffset,
257
- startYear,
258
- endYear,
259
- syncSwitchMonth = false,
260
- // 自定义渲染
261
- renderDate,
262
- renderFullDate,
263
- triggerRender,
264
- // 时间相关
265
- timePickerOpts,
266
- hideDisabledOptions = false,
267
- disabledTimePicker = false,
268
- needConfirm = false,
269
- // 快捷选项
270
- presetPosition = 'bottom',
271
- }: Props = $props();
272
-
273
- const isDateTime = $derived(type === 'dateTime');
274
- const isMonth = $derived(type === 'month');
275
- const isYear = $derived(type === 'year');
276
-
277
- // weekStartsOn 是 weekStart 的别名,weekStart 优先
278
- const effWeekStart = $derived(weekStart ?? weekStartsOn ?? 0);
279
-
280
- const loc = useLocale();
281
-
282
- const dialogId = useId('cd-date-picker-panel');
283
- // 日期网格容器 id(aria-activedescendant 指向其中的 cell id 前缀)
284
- const gridId = useId('cd-date-picker-grid');
285
-
286
- // --- 受控 value (红线 #1): 不无条件回写 value,仅 onChange ---
287
- const isValueControlled = $derived(value !== undefined);
288
-
289
- // multiple 模式下 value 为 Date[],单选为 Date | null
290
- function getInitialValue(): Date | Date[] | null {
291
- if (multiple) {
292
- if (Array.isArray(defaultValue)) return defaultValue;
293
- if (defaultValue instanceof Date) return [defaultValue];
294
- return [];
295
- }
296
- if (Array.isArray(defaultValue)) return defaultValue[0] ?? null;
297
- return defaultValue ?? null;
298
- }
299
-
300
- let innerValue = $state<Date | Date[] | null>(getInitialValue());
301
- const current = $derived<Date | Date[] | null>(isValueControlled ? (value ?? null) : innerValue);
302
-
303
- // 单一 Date 视图(multiple 时取第一个,非 multiple 直接用)
304
- const currentSingle = $derived<Date | null>(
305
- Array.isArray(current) ? (current[0] ?? null) : current,
306
- );
307
-
308
- function setValue(next: Date | Date[] | null) {
309
- if (!isValueControlled) innerValue = next;
310
- onChange?.(next);
311
- }
312
-
313
- // --- 受控 open (红线 #1): 不无条件回写 open,仅 onOpenChange ---
314
- const isOpenControlled = $derived(open !== undefined);
315
- let innerOpen = $state(getInitialOpen());
316
- const isOpen = $derived(isOpenControlled ? !!open : innerOpen);
317
-
318
- function getInitialOpen(): boolean {
319
- return defaultOpen;
320
- }
321
-
322
- function setOpen(next: boolean) {
323
- if (next === isOpen) return;
324
- if (!isOpenControlled) innerOpen = next;
325
- onOpenChange?.(next);
326
- }
327
-
328
- function toggleOpen() {
329
- if (disabled) return;
330
- setOpen(!isOpen);
331
- }
332
-
333
- // --- 面板游标月份 (本地 $state),打开时同步到 value/today 月份 ---
334
- const today = startOfDay(new Date());
335
- // 初始化游标用 defaultValue(不依赖 $derived 的 currentSingle 避免 state_referenced_locally)
336
- const _initCursorDate: Date | null = Array.isArray(defaultValue)
337
- ? (defaultValue[0] ?? null)
338
- : (defaultValue instanceof Date ? defaultValue : null);
339
- let cursor = $state(startOfDay(_initCursorDate ?? new Date()));
340
-
341
- // 当面板打开时把游标对齐到当前选中值(或今天)所在月份
342
- $effect(() => {
343
- if (isOpen) {
344
- cursor = startOfDay(currentSingle ?? new Date());
345
- }
346
- });
347
-
348
- // --- needConfirm 暂存值:点确认才写入 ---
349
- let pendingValue = $state<Date | Date[] | null>(null);
350
-
351
- $effect(() => {
352
- if (isOpen) {
353
- pendingValue = current;
354
- }
355
- });
356
-
357
- // --- Intl 本地化格式化器 (不手拼日期串) ---
358
- const triggerFormat = $derived(
359
- new Intl.DateTimeFormat(
360
- locale,
361
- isYear
362
- ? { year: 'numeric' }
363
- : isMonth
364
- ? { year: 'numeric', month: '2-digit' }
365
- : {
366
- year: 'numeric',
367
- month: '2-digit',
368
- day: '2-digit',
369
- ...(isDateTime
370
- ? { hour: '2-digit', minute: '2-digit', second: showSecond ? '2-digit' : undefined, hour12: false }
371
- : {}),
372
- },
373
- ),
374
- );
375
- const headerFormat = $derived(
376
- new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'long' }),
377
- );
378
- // 仅年份的头部文案 (month 面板头部 / year 面板基准)
379
- const yearFormat = $derived(new Intl.DateTimeFormat(locale, { year: 'numeric' }));
380
- // 月格短名 (month 面板 12 格)
381
- const monthShortFormat = $derived(new Intl.DateTimeFormat(locale, { month: 'short' }));
382
- const weekdayFormat = $derived(new Intl.DateTimeFormat(locale, { weekday: 'short' }));
383
- // 完整星期名 (columnheader aria-label,朗读用)
384
- const weekdayLongFormat = $derived(new Intl.DateTimeFormat(locale, { weekday: 'long' }));
385
-
386
- // format 串优先用 core 纯函数序列化;否则沿用 Intl (向后兼容)
387
- function formatSingle(d: Date | null): string {
388
- if (!d) return '';
389
- return format ? formatDate(d, format) : triggerFormat.format(d);
390
- }
391
-
392
- const formattedValue = $derived(
393
- multiple
394
- ? (Array.isArray(current) ? current.map(formatSingle).join(` ${rangeSeparator} `) : '')
395
- : formatSingle(currentSingle),
396
- );
397
- const displayText = $derived(formattedValue || (placeholder ?? loc().t('DatePicker.placeholder')));
398
-
399
- // --- 可输入模式 (format 串):本地草稿文本 + 按格式解析 ---
400
- const editable = $derived(!!format && !multiple);
401
- let inputText = $state('');
402
- // 非编辑期同步草稿到受控显示值 (打开输入时让用户继续编辑当前文本)
403
- $effect(() => {
404
- if (!editable) return;
405
- inputText = formattedValue;
406
- });
407
-
408
- function commitInput() {
409
- if (!editable || !format) return;
410
- const raw = inputText.trim();
411
- if (raw === '') {
412
- if (currentSingle !== null) setValue(null);
413
- return;
414
- }
415
- const parsed = parseDateString(raw, format);
416
- if (parsed && !(disabledDate?.(parsed) ?? false)) {
417
- setValue(combine(parsed));
418
- } else {
419
- // 解析失败:回退到当前值的规范文本
420
- inputText = formattedValue;
421
- onParseError?.({ text: raw });
422
- }
423
- }
424
-
425
- function onInputKeydown(e: KeyboardEvent) {
426
- if (disabled) return;
427
- if (e.key === 'Enter') {
428
- e.preventDefault();
429
- commitInput();
430
- setOpen(false);
431
- } else if (e.key === 'ArrowDown' && !isOpen) {
432
- e.preventDefault();
433
- setOpen(true);
434
- } else if (e.key === 'Escape' && isOpen) {
435
- e.preventDefault();
436
- inputText = formattedValue;
437
- setOpen(false);
438
- }
439
- }
440
-
441
- // --- 十年范围 (year 面板):以 cursor 年所在的十年起点对齐 ---
442
- const decadeStart = $derived(Math.floor(cursor.getFullYear() / 10) * 10);
443
- const headerText = $derived(
444
- isYear
445
- ? `${decadeStart}-${decadeStart + 9}`
446
- : isMonth
447
- ? yearFormat.format(cursor)
448
- : headerFormat.format(cursor),
449
- );
450
-
451
- // month 面板 12 个月格 (用 cursor 年份 + 0..11 月)
452
- const monthCells = $derived(
453
- Array.from({ length: 12 }, (_, m) => {
454
- const date = new Date(cursor.getFullYear(), m, 1);
455
- return { date, label: monthShortFormat.format(date), month: m };
456
- }),
457
- );
458
-
459
- // year 面板格子:前后各留 1 个邻十年年份用于占位,共 12 格
460
- const yearCells = $derived(
461
- Array.from({ length: 12 }, (_, i) => {
462
- const year = decadeStart - 1 + i;
463
- const date = new Date(year, 0, 1);
464
- const inRange = (startYear === undefined || year >= startYear) && (endYear === undefined || year <= endYear);
465
- return { date, year, inDecade: year >= decadeStart && year <= decadeStart + 9, inRange };
466
- }),
467
- );
468
-
469
- // 星期名: 用 weekdayOrder + 一个已知周日基准 (2023-01-01 是星期日) 经 Intl 本地化
470
- const weekdayNames = $derived(
471
- weekdayOrder(effWeekStart).map((dow) => weekdayFormat.format(new Date(2023, 0, 1 + dow))),
472
- );
473
- // 完整星期名 (columnheader aria-label),顺序与 weekdayNames 一致
474
- const weekdayLongNames = $derived(
475
- weekdayOrder(effWeekStart).map((dow) => weekdayLongFormat.format(new Date(2023, 0, 1 + dow))),
476
- );
477
-
478
- // 面板内键盘高亮日 (highlight 为本地 $state;aria-activedescendant 指向它)
479
- let highlight = $state<Date | null>(null);
480
-
481
- const grid = $derived(getMonthGrid(cursor, effWeekStart));
482
- // 6×7 行结构 (role=row / gridcell)。getMonthGrid 固定返回 42 格。
483
- const weekRows = $derived(
484
- Array.from({ length: 6 }, (_, r) => grid.slice(r * 7, r * 7 + 7)),
485
- );
486
- // 每个日期格的稳定 id(aria-activedescendant 指向当前高亮格)
487
- function cellId(date: Date): string {
488
- return `${gridId}-${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
489
- }
490
- // 当前高亮格 id(aria-activedescendant)
491
- const activeCellId = $derived(highlight ? cellId(highlight) : undefined);
492
-
493
- // showClear 综合判断:clearable & !disabled & 有值 & showClearProp=true
494
- const showClearDerived = $derived(
495
- clearable &&
496
- showClearProp &&
497
- !disabled &&
498
- (multiple ? (Array.isArray(current) && current.length > 0) : currentSingle !== null),
499
- );
500
-
501
- // 头部导航切换可见年月:更新游标并通知 onPanelChange(红线 #1:panelDate 是面板视图态,非 value)
502
- function setCursor(next: Date) {
503
- cursor = next;
504
- onPanelChange?.({ panelDate: next });
505
- }
506
- function prevMonth() {
507
- setCursor(addMonths(cursor, -1));
508
- }
509
- function nextMonth() {
510
- setCursor(addMonths(cursor, 1));
511
- }
512
- // month 面板:切年(±12 个月)
513
- function prevYear() {
514
- setCursor(addMonths(cursor, -12));
515
- }
516
- function nextYear() {
517
- setCursor(addMonths(cursor, 12));
518
- }
519
- // year 面板:切十年
520
- function prevDecade() {
521
- setCursor(new Date(cursor.getFullYear() - 10, cursor.getMonth(), 1));
522
- }
523
- function nextDecade() {
524
- setCursor(new Date(cursor.getFullYear() + 10, cursor.getMonth(), 1));
525
- }
526
-
527
- // 选中某个月:保留年+月,归一到该月 1 号起始
528
- function selectMonth(date: Date) {
529
- if (disabledDate?.(date)) return;
530
- setValue(startOfDay(date));
531
- setOpen(false);
532
- }
533
- // 选中某一年:归一到该年 1 月 1 号起始
534
- function selectYear(date: Date) {
535
- if (disabledDate?.(date)) return;
536
- setValue(startOfDay(date));
537
- setOpen(false);
538
- }
539
-
540
- // 头部导航按面板类型分派(month=切年, year=切十年, 其它=切月)
541
- const onPrev = $derived(isYear ? prevDecade : isMonth ? prevYear : prevMonth);
542
- const onNext = $derived(isYear ? nextDecade : isMonth ? nextYear : nextMonth);
543
- const prevLabel = $derived(
544
- isYear
545
- ? loc().t('DatePicker.prevDecade')
546
- : isMonth
547
- ? loc().t('DatePicker.prevYear')
548
- : loc().t('DatePicker.prevMonth'),
549
- );
550
- const nextLabel = $derived(
551
- isYear
552
- ? loc().t('DatePicker.nextDecade')
553
- : isMonth
554
- ? loc().t('DatePicker.nextYear')
555
- : loc().t('DatePicker.nextMonth'),
556
- );
557
-
558
- // --- 时间部分 (dateTime):复用 TimePicker 的列逻辑 ---
559
- const selectedHour = $derived(currentSingle ? currentSingle.getHours() : 0);
560
- const selectedMinute = $derived(currentSingle ? currentSingle.getMinutes() : 0);
561
- const selectedSecond = $derived(currentSingle ? currentSingle.getSeconds() : 0);
562
-
563
- const hours = Array.from({ length: 24 }, (_, i) => i);
564
- const minutes = Array.from({ length: 60 }, (_, i) => i);
565
- const seconds = Array.from({ length: 60 }, (_, i) => i);
566
-
567
- function pad2(n: number): string {
568
- return n < 10 ? `0${n}` : `${n}`;
569
- }
570
-
571
- // --- disabledTime (dateTime):按当前日期解析各列禁用值集合 ---
572
- // 基准日期取当前选中值(无则今天);时/分依赖已选时分以联动下游列。
573
- const disabledTimeCfg = $derived(
574
- isDateTime && disabledTime ? disabledTime(currentSingle ?? today) : undefined,
575
- );
576
- const disabledHourSet = $derived(new Set(disabledTimeCfg?.disabledHours?.() ?? []));
577
- const disabledMinuteSet = $derived(
578
- new Set(disabledTimeCfg?.disabledMinutes?.(selectedHour) ?? []),
579
- );
580
- const disabledSecondSet = $derived(
581
- new Set(disabledTimeCfg?.disabledSeconds?.(selectedHour, selectedMinute) ?? []),
582
- );
583
-
584
- // 合并指定日期与已有时分秒 (dateTime 保留时间,date 归零到当天起始)
585
- function combine(date: Date): Date {
586
- if (!isDateTime) return startOfDay(date);
587
- const next = new Date(date);
588
- next.setHours(selectedHour, selectedMinute, selectedSecond, 0);
589
- return next;
590
- }
591
-
592
- function selectDate(date: Date) {
593
- if (disabledDate?.(date)) return;
594
-
595
- if (multiple) {
596
- const arr = Array.isArray(current) ? [...current] : [];
597
- const idx = arr.findIndex((d) => isSameDay(d, date));
598
- let next: Date[];
599
- if (idx >= 0) {
600
- // 取消选中
601
- next = arr.filter((_, i) => i !== idx);
602
- } else {
603
- // 新增选中(max 限制)
604
- if (max !== undefined && arr.length >= max) return;
605
- next = [...arr, startOfDay(date)];
606
- }
607
- if (needConfirm) {
608
- pendingValue = next;
609
- } else {
610
- setValue(next);
611
- }
612
- return;
613
- }
614
-
615
- const combined = combine(date);
616
- if (needConfirm) {
617
- pendingValue = combined;
618
- // dateTime needConfirm:选日期后保留面板
619
- } else {
620
- setValue(combined);
621
- // dateTime:选日期后保留面板,让用户继续选时间,点确定再关
622
- if (!isDateTime) setOpen(false);
623
- }
624
- }
625
-
626
- function selectToday() {
627
- if (disabledDate?.(today)) return;
628
- if (isMonth) {
629
- setValue(startOfDay(new Date(today.getFullYear(), today.getMonth(), 1)));
630
- setOpen(false);
631
- return;
632
- }
633
- if (isYear) {
634
- setValue(startOfDay(new Date(today.getFullYear(), 0, 1)));
635
- setOpen(false);
636
- return;
637
- }
638
- setValue(combine(today));
639
- if (!isDateTime) setOpen(false);
640
- }
641
-
642
- // 时间列:基于 current(无则今天)写入 h/m/s,不关面板
643
- function commitTime(h: number, m: number, s: number) {
644
- const base = currentSingle ? new Date(currentSingle) : startOfDay(today);
645
- base.setHours(h, m, s, 0);
646
- if (needConfirm) {
647
- pendingValue = base;
648
- } else {
649
- setValue(base);
650
- }
651
- }
652
- function pickHour(h: number) {
653
- if (disabledHourSet.has(h)) return;
654
- commitTime(h, selectedMinute, selectedSecond);
655
- }
656
- function pickMinute(m: number) {
657
- if (disabledMinuteSet.has(m)) return;
658
- commitTime(selectedHour, m, selectedSecond);
659
- }
660
- function pickSecond(s: number) {
661
- if (disabledSecondSet.has(s)) return;
662
- commitTime(selectedHour, selectedMinute, s);
663
- }
664
-
665
- // --- presets:点击快捷项直接选中 (惰性 value 即时求值) ---
666
- function selectPreset(preset: Preset) {
667
- onPresetClick?.({ preset });
668
- const date = typeof preset.value === 'function' ? preset.value() : preset.value;
669
- if (disabledDate?.(date)) return;
670
- if (isMonth) {
671
- setValue(startOfDay(new Date(date.getFullYear(), date.getMonth(), 1)));
672
- setOpen(false);
673
- return;
674
- }
675
- if (isYear) {
676
- setValue(startOfDay(new Date(date.getFullYear(), 0, 1)));
677
- setOpen(false);
678
- return;
679
- }
680
- // dateTime:连带时间一起选中;date:归零到当天起始。
681
- setValue(isDateTime ? new Date(date) : startOfDay(date));
682
- setOpen(false);
683
- }
684
-
685
- function confirm() {
686
- const val = needConfirm ? pendingValue : current;
687
- onConfirm?.({ value: val });
688
- if (needConfirm && pendingValue !== null) {
689
- setValue(pendingValue);
690
- }
691
- setOpen(false);
692
- }
693
-
694
- function cancelConfirm() {
695
- const dateStr = Array.isArray(current)
696
- ? current.map(formatSingle).join(` ${rangeSeparator} `)
697
- : formatSingle(currentSingle);
698
- onCancel?.(current, dateStr);
699
- pendingValue = current;
700
- setOpen(false);
701
- }
702
-
703
- // 时间列容器引用 (红线 #3: 普通 bind:this,scrollIntoView 命令式调用)
704
- let hourCol = $state<HTMLUListElement | null>(null);
705
- let minuteCol = $state<HTMLUListElement | null>(null);
706
- let secondCol = $state<HTMLUListElement | null>(null);
707
-
708
- function scrollColToSelected(col: HTMLUListElement | null) {
709
- if (!col) return;
710
- const target = col.querySelector<HTMLElement>('[aria-selected="true"]');
711
- target?.scrollIntoView({ block: 'center' });
712
- }
713
-
714
- // 打开时把时间列各自滚到选中项 (命令式,不放响应式 attachment)
715
- $effect(() => {
716
- if (!isOpen || !isDateTime) return;
717
- void tick().then(() => {
718
- scrollColToSelected(hourCol);
719
- scrollColToSelected(minuteCol);
720
- if (showSecond) scrollColToSelected(secondCol);
721
- });
722
- });
723
-
724
- function clear(e: MouseEvent) {
725
- e.stopPropagation();
726
- if (disabled) return;
727
- const emptyVal = multiple ? [] : null;
728
- setValue(emptyVal);
729
- onClear?.({});
730
- }
731
-
732
- function onTriggerKeydown(e: KeyboardEvent) {
733
- if (disabled) return;
734
- switch (e.key) {
735
- case 'Enter':
736
- case ' ':
737
- e.preventDefault();
738
- setOpen(true);
739
- break;
740
- case 'ArrowDown':
741
- e.preventDefault();
742
- if (!isOpen) setOpen(true);
743
- break;
744
- case 'Escape':
745
- if (isOpen) {
746
- e.preventDefault();
747
- setOpen(false);
748
- }
749
- break;
750
- default:
751
- break;
752
- }
753
- }
754
-
755
- // 打开时把高亮对齐当前选中值或今天,关闭清空
756
- $effect(() => {
757
- if (isOpen) {
758
- highlight = startOfDay(currentSingle ?? today);
759
- } else {
760
- highlight = null;
761
- }
762
- });
763
-
764
- // 把高亮移到 next,并让游标随动到 next 所在月份(跨月自动翻页)
765
- function setHighlight(next: Date) {
766
- highlight = startOfDay(next);
767
- cursor = startOfDay(new Date(next.getFullYear(), next.getMonth(), 1));
768
- }
769
-
770
- const GRID_NAV_KEYS = new Set<string>([
771
- 'ArrowLeft',
772
- 'ArrowRight',
773
- 'ArrowUp',
774
- 'ArrowDown',
775
- 'PageUp',
776
- 'PageDown',
777
- 'Home',
778
- 'End',
779
- ]);
780
-
781
- // 日期网格键盘导航 (WAI-ARIA grid,红线 #2:方向用纯 gridFocusMove 派生)
782
- // 方向键 ∓1 天 / ∓1 周;Home/End 本周首末;PageUp/Down ∓1 月;Shift+PageUp/Down ∓1 年。
783
- function onGridKeydown(e: KeyboardEvent) {
784
- const key = e.key;
785
- if (key === 'Enter' || key === ' ') {
786
- e.preventDefault();
787
- if (highlight) selectDate(highlight);
788
- return;
789
- }
790
- if (key === 'Escape') {
791
- e.preventDefault();
792
- setOpen(false);
793
- return;
794
- }
795
- const base = highlight ?? today;
796
- // Shift+PageUp/Down:切年(gridFocusMove 不含年级,组件层 ±12 月)
797
- if (e.shiftKey && (key === 'PageUp' || key === 'PageDown')) {
798
- e.preventDefault();
799
- setHighlight(addMonths(base, key === 'PageUp' ? -12 : 12));
800
- return;
801
- }
802
- if (!GRID_NAV_KEYS.has(key)) return;
803
- e.preventDefault();
804
- const next = gridFocusMove(base, key as GridFocusKey, 'month', effWeekStart);
805
- if (next) setHighlight(next);
806
- }
807
-
808
- // --- useDismiss (红线 #3): 绑定放进 $effect,open 时绑、cleanup 解绑 ---
809
- let rootEl = $state<HTMLDivElement | null>(null);
810
- // 浮层 + 日期网格容器引用 (focus trap / 进场落焦,红线 #3 命令式 + cleanup)
811
- let panelEl = $state<HTMLDivElement | null>(null);
812
- let gridEl = $state<HTMLDivElement | null>(null);
813
- let triggerEl = $state<HTMLButtonElement | HTMLInputElement | null>(null);
814
-
815
- // autoFocus: 挂载后聚焦触发器
816
- $effect(() => {
817
- if (autoFocus && triggerEl) {
818
- void tick().then(() => {
819
- triggerEl?.focus({ preventScroll });
820
- });
821
- }
822
- });
823
-
824
- $effect(() => {
825
- if (!isOpen || !rootEl) return;
826
- // onClickOutSide 额外监听
827
- function handleDocClick(e: MouseEvent) {
828
- if (rootEl && !rootEl.contains(e.target as Node)) {
829
- onClickOutSide?.(e);
830
- }
831
- }
832
- if (onClickOutSide) {
833
- document.addEventListener('click', handleDocClick, true);
834
- }
835
- const cleanup = useDismiss(rootEl, {
836
- onDismiss: () => setOpen(false),
837
- escape: true,
838
- outsideClick: true,
839
- });
840
- return () => {
841
- if (onClickOutSide) {
842
- document.removeEventListener('click', handleDocClick, true);
843
- }
844
- cleanup?.();
845
- };
846
- });
847
-
848
- // --- focus trap (红线 #3): 打开时困住 Tab,关闭归还焦点到触发器;进场落焦到日期网格 ---
849
- $effect(() => {
850
- if (!isOpen || !panelEl) return;
851
- const trap = useFocusTrap(panelEl, { trapTab: true, returnFocus: true });
852
- trap.activate();
853
- // aria-activedescendant 模型:焦点落在网格容器(非单格),用 tick 等渲染完成
854
- void tick().then(() => {
855
- if (gridEl) gridEl.focus();
856
- });
857
- return () => trap.deactivate();
858
- });
859
-
860
- // onClickOutSide: 监听 document mousedown,点击不在 rootEl 内时触发
861
- $effect(() => {
862
- if (!onClickOutSide) return;
863
- function handler(e: MouseEvent) {
864
- if (rootEl && !rootEl.contains(e.target as Node)) {
865
- onClickOutSide!(e);
866
- }
867
- }
868
- document.addEventListener('mousedown', handler);
869
- return () => document.removeEventListener('mousedown', handler);
870
- });
871
-
872
- // stopPropagation:面板点击阻止冒泡
873
- function onPanelClick(e: MouseEvent) {
874
- if (stopPropagation) e.stopPropagation();
875
- }
876
-
877
- // --- 样式工具函数 ---
878
- function styleToString(s: CSSProperties | string | undefined): string | undefined {
879
- if (!s) return undefined;
880
- if (typeof s === 'string') return s;
881
- return Object.entries(s)
882
- .map(([k, v]) => `${k.replace(/([A-Z])/g, '-$1').toLowerCase()}:${v}`)
883
- .join(';');
884
- }
885
-
886
- const dropdownStyleStr = $derived(styleToString(dropdownStyle));
887
- const inputStyleStr = $derived(styleToString(inputStyle));
888
-
889
- // z-index CSS variable 注入到 panel
890
- const panelStyle = $derived(
891
- [dropdownStyleStr, `z-index:${zIndex}`].filter(Boolean).join(';'),
892
- );
893
-
894
- const cls = $derived(
895
- [
896
- 'cd-date-picker',
897
- `cd-date-picker--${size}`,
898
- `cd-date-picker--${status}`,
899
- disabled && 'cd-date-picker--disabled',
900
- isOpen && 'cd-date-picker--open',
901
- insetInput && 'cd-date-picker--inset-input',
902
- position && `cd-date-picker--${position}`,
903
- borderless && 'cd-date-picker--borderless',
904
- density === 'compact' && 'cd-date-picker--compact',
905
- !motion && 'cd-date-picker--no-motion',
906
- ]
907
- .filter(Boolean)
908
- .join(' '),
909
- );
910
-
911
- // multiple 模式下是否选中某天
912
- function isDateSelected(date: Date): boolean {
913
- if (multiple) {
914
- return Array.isArray(current) && current.some((d) => isSameDay(d, date));
915
- }
916
- return isSameDay(date, currentSingle);
917
- }
918
-
919
- // fullDate 字符串工具
920
- function fullDateStr(date: Date): string {
921
- return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;
922
- }
923
-
924
- // presets 布局:left/right 时垂直在侧边;top/bottom 时水平在上下
925
- const presetsVertical = $derived(presetPosition === 'left' || presetPosition === 'right');
926
- </script>
927
-
928
- <div class={cls} bind:this={rootEl} aria-invalid={status === 'error' || undefined} data-position={position}>
929
- <div class="cd-date-picker__control">
930
- {#if triggerRender}
931
- {@render triggerRender({ value: current, placeholder: placeholder ?? loc().t('DatePicker.placeholder') })}
932
- {:else if editable}
933
- <input
934
- type="text"
935
- class="cd-date-picker__trigger cd-date-picker__input"
936
- role="combobox"
937
- aria-haspopup="dialog"
938
- aria-expanded={isOpen}
939
- aria-controls={dialogId}
940
- aria-label={ariaLabel}
941
- placeholder={placeholder ?? format}
942
- {disabled}
943
- readonly={inputReadOnly}
944
- style={inputStyleStr}
945
- bind:this={triggerEl as HTMLInputElement}
946
- bind:value={inputText}
947
- onclick={() => setOpen(true)}
948
- onkeydown={onInputKeydown}
949
- onfocus={onFocus}
950
- onblur={(e) => {
951
- commitInput();
952
- onBlur?.(e);
953
- }}
954
- />
955
- {:else}
956
- <button
957
- type="button"
958
- class="cd-date-picker__trigger"
959
- aria-haspopup="dialog"
960
- aria-expanded={isOpen}
961
- aria-controls={dialogId}
962
- aria-label={ariaLabel}
963
- {disabled}
964
- style={inputStyleStr}
965
- bind:this={triggerEl as HTMLButtonElement}
966
- onclick={toggleOpen}
967
- onkeydown={onTriggerKeydown}
968
- onfocus={onFocus}
969
- onblur={onBlur}
970
- >
971
- {#if prefix}
972
- <span class="cd-date-picker__prefix">
973
- {#if typeof prefix === 'string'}
974
- {prefix}
975
- {:else}
976
- {@render prefix()}
977
- {/if}
978
- </span>
979
- {/if}
980
- <span class="cd-date-picker__value" class:cd-date-picker__value--placeholder={!formattedValue}>
981
- {displayText}
982
- </span>
983
- </button>
984
- {/if}
985
-
986
- {#if showClearDerived}
987
- <button type="button" class="cd-date-picker__clear" aria-label={loc().t('DatePicker.clear')} onclick={clear}>
988
- {#if clearIcon}
989
- {@render clearIcon()}
990
- {:else}
991
- <svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true" focusable="false">
992
- <path
993
- fill="currentColor"
994
- d="M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1Zm2.5 9.1-1.4 1.4L8 9.4 6.5 11l-1.4-1.4L6.6 8 5.1 6.5 6.5 5.1 8 6.6 9.5 5.1l1.4 1.4L9.4 8l1.1 1.1Z"
995
- />
996
- </svg>
997
- {/if}
998
- </button>
999
- {/if}
1000
-
1001
- <span class="cd-date-picker__icon" aria-hidden="true">
1002
- <svg viewBox="0 0 16 16" width="14" height="14" focusable="false">
1003
- <path
1004
- fill="currentColor"
1005
- d="M5 1v1H3.5A1.5 1.5 0 0 0 2 3.5v9A1.5 1.5 0 0 0 3.5 14h9a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 12.5 2H11V1h-1v1H6V1H5Zm7.5 4.5v7h-9v-7h9Z"
1006
- />
1007
- </svg>
1008
- </span>
1009
- </div>
1010
-
1011
- {#if isOpen}
1012
- <div
1013
- bind:this={panelEl}
1014
- class={['cd-date-picker__panel', dropdownClassName].filter(Boolean).join(' ')}
1015
- class:cd-date-picker__panel--datetime={isDateTime}
1016
- id={dialogId}
1017
- role="dialog"
1018
- aria-modal="false"
1019
- aria-label={loc().t('DatePicker.triggerLabel')}
1020
- tabindex="-1"
1021
- style={panelStyle}
1022
- onclick={onPanelClick}
1023
- onkeydown={undefined}
1024
- >
1025
- {#if topSlot}
1026
- <div class="cd-date-picker__slot cd-date-picker__slot--top">
1027
- {@render topSlot()}
1028
- </div>
1029
- {/if}
1030
-
1031
- <div
1032
- class="cd-date-picker__layout"
1033
- class:cd-date-picker__layout--presets={presets && presets.length > 0}
1034
- class:cd-date-picker__layout--presets-top={presets && presets.length > 0 && presetPosition === 'top'}
1035
- class:cd-date-picker__layout--presets-bottom={presets && presets.length > 0 && presetPosition === 'bottom'}
1036
- class:cd-date-picker__layout--presets-left={presets && presets.length > 0 && presetPosition === 'left'}
1037
- class:cd-date-picker__layout--presets-right={presets && presets.length > 0 && presetPosition === 'right'}
1038
- >
1039
- {#if leftSlot}
1040
- <div class="cd-date-picker__slot cd-date-picker__slot--left">
1041
- {@render leftSlot()}
1042
- </div>
1043
- {/if}
1044
-
1045
- {#if presets && presets.length > 0 && (presetPosition === 'left' || presetPosition === 'top')}
1046
- <div
1047
- class="cd-date-picker__presets"
1048
- class:cd-date-picker__presets--vertical={presetsVertical}
1049
- role="group"
1050
- aria-label={loc().t('DatePicker.triggerLabel')}
1051
- >
1052
- {#each presets as preset, i (i)}
1053
- <button
1054
- type="button"
1055
- class="cd-date-picker__preset"
1056
- onclick={() => selectPreset(preset)}
1057
- >
1058
- {preset.label}
1059
- </button>
1060
- {/each}
1061
- </div>
1062
- {/if}
1063
-
1064
- <div class="cd-date-picker__main">
1065
- <div class="cd-date-picker__body">
1066
- <div class="cd-date-picker__calendar">
1067
- <div class="cd-date-picker__header">
1068
- <button
1069
- type="button"
1070
- class="cd-date-picker__nav"
1071
- aria-label={prevLabel}
1072
- onclick={onPrev}
1073
- >
1074
- <svg viewBox="0 0 16 16" width="12" height="12" aria-hidden="true" focusable="false">
1075
- <path fill="currentColor" d="M10 3.5 5.5 8l4.5 4.5 1-1L7.5 8 11 4.5l-1-1Z" />
1076
- </svg>
1077
- </button>
1078
- <span class="cd-date-picker__title">{headerText}</span>
1079
- <button
1080
- type="button"
1081
- class="cd-date-picker__nav"
1082
- aria-label={nextLabel}
1083
- onclick={onNext}
1084
- >
1085
- <svg viewBox="0 0 16 16" width="12" height="12" aria-hidden="true" focusable="false">
1086
- <path fill="currentColor" d="M6 3.5 5 4.5 8.5 8 5 11.5l1 1L10.5 8 6 3.5Z" />
1087
- </svg>
1088
- </button>
1089
- </div>
1090
-
1091
- {#if isMonth}
1092
- <div class="cd-date-picker__grid cd-date-picker__grid--month" role="grid">
1093
- {#each monthCells as cell (cell.month)}
1094
- {@const isSelected =
1095
- currentSingle !== null &&
1096
- currentSingle.getFullYear() === cell.date.getFullYear() &&
1097
- currentSingle.getMonth() === cell.month}
1098
- {@const isCurrent =
1099
- today.getFullYear() === cell.date.getFullYear() && today.getMonth() === cell.month}
1100
- {@const isDisabled = disabledDate?.(cell.date) ?? false}
1101
- <button
1102
- type="button"
1103
- class="cd-date-picker__cell cd-date-picker__cell--block"
1104
- class:cd-date-picker__cell--selected={isSelected}
1105
- class:cd-date-picker__cell--today={isCurrent}
1106
- role="gridcell"
1107
- aria-selected={isSelected}
1108
- aria-disabled={isDisabled || undefined}
1109
- disabled={isDisabled}
1110
- tabindex={-1}
1111
- onclick={() => selectMonth(cell.date)}
1112
- >
1113
- {cell.label}
1114
- </button>
1115
- {/each}
1116
- </div>
1117
- {:else if isYear}
1118
- <div class="cd-date-picker__grid cd-date-picker__grid--year" role="grid">
1119
- {#each yearCells as cell (cell.year)}
1120
- {@const isSelected = currentSingle !== null && currentSingle.getFullYear() === cell.year}
1121
- {@const isCurrent = today.getFullYear() === cell.year}
1122
- {@const isDisabled = (disabledDate?.(cell.date) ?? false) || !cell.inRange}
1123
- <button
1124
- type="button"
1125
- class="cd-date-picker__cell cd-date-picker__cell--block"
1126
- class:cd-date-picker__cell--muted={!cell.inDecade}
1127
- class:cd-date-picker__cell--selected={isSelected}
1128
- class:cd-date-picker__cell--today={isCurrent}
1129
- role="gridcell"
1130
- aria-selected={isSelected}
1131
- aria-disabled={isDisabled || undefined}
1132
- disabled={isDisabled}
1133
- tabindex={-1}
1134
- onclick={() => selectYear(cell.date)}
1135
- >
1136
- {cell.year}
1137
- </button>
1138
- {/each}
1139
- </div>
1140
- {:else}
1141
- <!-- WAI-ARIA grid:role=grid 容器 (aria-activedescendant 指当前高亮格)
1142
- + 表头行 columnheader + 每周一行 row,格 role=gridcell。
1143
- 焦点落在容器,方向键经 onGridKeydown → gridFocusMove 移动高亮 (红线 #2)。 -->
1144
- <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
1145
- <div
1146
- bind:this={gridEl}
1147
- class="cd-date-picker__grid"
1148
- role="grid"
1149
- tabindex="0"
1150
- aria-activedescendant={activeCellId}
1151
- aria-label={headerText}
1152
- onkeydown={onGridKeydown}
1153
- >
1154
- <div class="cd-date-picker__row cd-date-picker__row--head" role="row">
1155
- {#each weekdayNames as name, i (i)}
1156
- <span class="cd-date-picker__weekday" role="columnheader" aria-label={weekdayLongNames[i]}>
1157
- {name}
1158
- </span>
1159
- {/each}
1160
- </div>
1161
- {#each weekRows as row, wi (wi)}
1162
- <div class="cd-date-picker__row" role="row">
1163
- {#each row as cell (cell.date.getTime())}
1164
- {@const isSelected = isDateSelected(cell.date)}
1165
- {@const isToday = isSameDay(cell.date, today)}
1166
- {@const isHighlight = isSameDay(cell.date, highlight)}
1167
- {@const isDisabled = disabledDate?.(cell.date) ?? false}
1168
- {@const dayStatus = { isSelected, isToday, isDisabled, isInMonth: cell.inMonth }}
1169
- <button
1170
- type="button"
1171
- id={cellId(cell.date)}
1172
- class="cd-date-picker__cell"
1173
- class:cd-date-picker__cell--muted={!cell.inMonth}
1174
- class:cd-date-picker__cell--selected={isSelected}
1175
- class:cd-date-picker__cell--today={isToday}
1176
- class:cd-date-picker__cell--highlight={isHighlight}
1177
- role="gridcell"
1178
- aria-selected={isSelected}
1179
- aria-disabled={isDisabled || undefined}
1180
- disabled={isDisabled}
1181
- tabindex={-1}
1182
- onclick={() => selectDate(cell.date)}
1183
- >
1184
- {#if renderFullDate}
1185
- {@render renderFullDate({ day: cell.date.getDate(), fullDate: fullDateStr(cell.date), dayStatus })}
1186
- {:else if renderDate}
1187
- {@render renderDate({ day: cell.date.getDate(), fullDate: fullDateStr(cell.date) })}
1188
- {:else}
1189
- {cell.date.getDate()}
1190
- {/if}
1191
- </button>
1192
- {/each}
1193
- </div>
1194
- {/each}
1195
- </div>
1196
- {/if}
1197
- </div>
1198
-
1199
- {#if isDateTime && !disabledTimePicker}
1200
- <div class="cd-date-picker__time">
1201
- <ul class="cd-date-picker__time-col" role="listbox" aria-label={loc().t('TimePicker.hour')} bind:this={hourCol}>
1202
- {#each hours as h (h)}
1203
- {@const isHourDisabled = disabledHourSet.has(h)}
1204
- {#if !(hideDisabledOptions && isHourDisabled)}
1205
- <li
1206
- class="cd-date-picker__time-item"
1207
- class:cd-date-picker__time-item--selected={h === selectedHour}
1208
- class:cd-date-picker__time-item--disabled={isHourDisabled}
1209
- role="option"
1210
- aria-selected={h === selectedHour}
1211
- aria-disabled={isHourDisabled || undefined}
1212
- tabindex="-1"
1213
- onclick={() => pickHour(h)}
1214
- onkeydown={(e) => {
1215
- if (e.key === 'Enter' || e.key === ' ') {
1216
- e.preventDefault();
1217
- pickHour(h);
1218
- }
1219
- }}
1220
- >
1221
- {pad2(h)}
1222
- </li>
1223
- {/if}
1224
- {/each}
1225
- </ul>
1226
- <ul class="cd-date-picker__time-col" role="listbox" aria-label={loc().t('TimePicker.minute')} bind:this={minuteCol}>
1227
- {#each minutes as m (m)}
1228
- {@const isMinuteDisabled = disabledMinuteSet.has(m)}
1229
- {#if !(hideDisabledOptions && isMinuteDisabled)}
1230
- <li
1231
- class="cd-date-picker__time-item"
1232
- class:cd-date-picker__time-item--selected={m === selectedMinute}
1233
- class:cd-date-picker__time-item--disabled={isMinuteDisabled}
1234
- role="option"
1235
- aria-selected={m === selectedMinute}
1236
- aria-disabled={isMinuteDisabled || undefined}
1237
- tabindex="-1"
1238
- onclick={() => pickMinute(m)}
1239
- onkeydown={(e) => {
1240
- if (e.key === 'Enter' || e.key === ' ') {
1241
- e.preventDefault();
1242
- pickMinute(m);
1243
- }
1244
- }}
1245
- >
1246
- {pad2(m)}
1247
- </li>
1248
- {/if}
1249
- {/each}
1250
- </ul>
1251
- {#if showSecond}
1252
- <ul class="cd-date-picker__time-col" role="listbox" aria-label={loc().t('TimePicker.second')} bind:this={secondCol}>
1253
- {#each seconds as s (s)}
1254
- {@const isSecondDisabled = disabledSecondSet.has(s)}
1255
- {#if !(hideDisabledOptions && isSecondDisabled)}
1256
- <li
1257
- class="cd-date-picker__time-item"
1258
- class:cd-date-picker__time-item--selected={s === selectedSecond}
1259
- class:cd-date-picker__time-item--disabled={isSecondDisabled}
1260
- role="option"
1261
- aria-selected={s === selectedSecond}
1262
- aria-disabled={isSecondDisabled || undefined}
1263
- tabindex="-1"
1264
- onclick={() => pickSecond(s)}
1265
- onkeydown={(e) => {
1266
- if (e.key === 'Enter' || e.key === ' ') {
1267
- e.preventDefault();
1268
- pickSecond(s);
1269
- }
1270
- }}
1271
- >
1272
- {pad2(s)}
1273
- </li>
1274
- {/if}
1275
- {/each}
1276
- </ul>
1277
- {/if}
1278
- </div>
1279
- {/if}
1280
- </div>
1281
-
1282
- <div class="cd-date-picker__footer">
1283
- <button type="button" class="cd-date-picker__today" onclick={selectToday}>
1284
- {loc().t('DatePicker.today')}
1285
- </button>
1286
- {#if isDateTime || needConfirm}
1287
- {#if needConfirm}
1288
- <button type="button" class="cd-date-picker__cancel" onclick={cancelConfirm}>
1289
- {loc().t('DatePicker.cancel') ?? '取消'}
1290
- </button>
1291
- {/if}
1292
- <button type="button" class="cd-date-picker__ok" onclick={confirm}>
1293
- {loc().t('TimePicker.confirm')}
1294
- </button>
1295
- {/if}
1296
- </div>
1297
- </div>
1298
-
1299
- {#if presets && presets.length > 0 && (presetPosition === 'right' || presetPosition === 'bottom')}
1300
- <div
1301
- class="cd-date-picker__presets"
1302
- class:cd-date-picker__presets--vertical={presetsVertical}
1303
- role="group"
1304
- aria-label={loc().t('DatePicker.triggerLabel')}
1305
- >
1306
- {#each presets as preset, i (i)}
1307
- <button
1308
- type="button"
1309
- class="cd-date-picker__preset"
1310
- onclick={() => selectPreset(preset)}
1311
- >
1312
- {preset.label}
1313
- </button>
1314
- {/each}
1315
- </div>
1316
- {/if}
1317
-
1318
- {#if rightSlot}
1319
- <div class="cd-date-picker__slot cd-date-picker__slot--right">
1320
- {@render rightSlot()}
1321
- </div>
1322
- {/if}
1323
- </div>
1324
-
1325
- {#if bottomSlot}
1326
- <div class="cd-date-picker__slot cd-date-picker__slot--bottom">
1327
- {@render bottomSlot()}
1328
- </div>
1329
- {/if}
1330
- </div>
1331
- {/if}
1332
- </div>
1333
-
1334
- <style>
1335
- .cd-date-picker {
1336
- position: relative;
1337
- display: inline-flex;
1338
- inline-size: 100%;
1339
- font-size: var(--cd-input-font-size);
1340
- }
1341
- .cd-date-picker__control {
1342
- position: relative;
1343
- inline-size: 100%;
1344
- }
1345
- .cd-date-picker__trigger {
1346
- display: flex;
1347
- align-items: center;
1348
- gap: var(--cd-spacing-2);
1349
- inline-size: 100%;
1350
- block-size: var(--cd-input-height-default);
1351
- padding-inline-start: var(--cd-input-padding-x);
1352
- padding-inline-end: calc(var(--cd-input-padding-x) + 1.25rem);
1353
- background: var(--cd-input-color-bg);
1354
- color: var(--cd-input-color-text);
1355
- border: 1px solid var(--cd-input-border);
1356
- border-radius: var(--cd-input-radius);
1357
- font: inherit;
1358
- text-align: start;
1359
- cursor: pointer;
1360
- transition: border-color var(--cd-motion-duration-fast) var(--cd-motion-ease-standard);
1361
- }
1362
- .cd-date-picker--small .cd-date-picker__trigger {
1363
- block-size: var(--cd-input-height-small);
1364
- font-size: var(--cd-font-size-1);
1365
- }
1366
- .cd-date-picker--large .cd-date-picker__trigger {
1367
- block-size: var(--cd-input-height-large);
1368
- font-size: var(--cd-font-size-3);
1369
- }
1370
- .cd-date-picker__trigger:focus-visible {
1371
- outline: none;
1372
- border-color: var(--cd-input-border-active);
1373
- box-shadow: var(--cd-focus-ring);
1374
- }
1375
- .cd-date-picker--open .cd-date-picker__trigger {
1376
- border-color: var(--cd-input-border-active);
1377
- }
1378
- .cd-date-picker--warning .cd-date-picker__trigger {
1379
- border-color: var(--cd-input-border-warning);
1380
- }
1381
- .cd-date-picker--error .cd-date-picker__trigger {
1382
- border-color: var(--cd-input-border-error);
1383
- }
1384
- .cd-date-picker--disabled .cd-date-picker__trigger {
1385
- background: var(--cd-color-fill-0);
1386
- color: var(--cd-color-text-3);
1387
- cursor: not-allowed;
1388
- }
1389
- /* borderless 模式 */
1390
- .cd-date-picker--borderless .cd-date-picker__trigger {
1391
- border-color: transparent;
1392
- background: transparent;
1393
- }
1394
- /* compact 密度 */
1395
- .cd-date-picker--compact .cd-date-picker__panel {
1396
- padding: var(--cd-spacing-2);
1397
- }
1398
- .cd-date-picker--compact .cd-date-picker__cell {
1399
- inline-size: calc(var(--cd-date-picker-cell-size) * 0.85);
1400
- block-size: calc(var(--cd-date-picker-cell-size) * 0.85);
1401
- font-size: var(--cd-font-size-1);
1402
- }
1403
- .cd-date-picker--compact .cd-date-picker__weekday {
1404
- block-size: calc(var(--cd-date-picker-cell-size) * 0.85);
1405
- font-size: var(--cd-font-size-0);
1406
- }
1407
- /* no-motion */
1408
- .cd-date-picker--no-motion .cd-date-picker__panel {
1409
- animation: none;
1410
- }
1411
- .cd-date-picker__value {
1412
- flex: 1 1 auto;
1413
- overflow: hidden;
1414
- white-space: nowrap;
1415
- text-overflow: ellipsis;
1416
- }
1417
- .cd-date-picker__value--placeholder {
1418
- color: var(--cd-input-color-placeholder);
1419
- }
1420
- .cd-date-picker__prefix {
1421
- flex: 0 0 auto;
1422
- color: var(--cd-color-text-2);
1423
- }
1424
- /* format 可输入模式:原生 input 复用 trigger 外观 */
1425
- .cd-date-picker__input::placeholder {
1426
- color: var(--cd-input-color-placeholder);
1427
- }
1428
- .cd-date-picker__input:disabled {
1429
- background: var(--cd-color-fill-0);
1430
- color: var(--cd-color-text-3);
1431
- cursor: not-allowed;
1432
- }
1433
- .cd-date-picker__clear,
1434
- .cd-date-picker__icon {
1435
- position: absolute;
1436
- inset-block-start: 50%;
1437
- inset-inline-end: var(--cd-input-padding-x);
1438
- transform: translateY(-50%);
1439
- display: inline-flex;
1440
- align-items: center;
1441
- justify-content: center;
1442
- color: var(--cd-color-text-2);
1443
- pointer-events: none;
1444
- }
1445
- .cd-date-picker__clear {
1446
- padding: 0;
1447
- border: none;
1448
- background: var(--cd-input-color-bg);
1449
- cursor: pointer;
1450
- opacity: 0;
1451
- pointer-events: auto;
1452
- transition: opacity var(--cd-motion-duration-fast) var(--cd-motion-ease-standard);
1453
- }
1454
- .cd-date-picker__control:hover .cd-date-picker__clear,
1455
- .cd-date-picker__clear:focus-visible {
1456
- opacity: 1;
1457
- }
1458
- .cd-date-picker__clear:focus-visible {
1459
- outline: none;
1460
- box-shadow: var(--cd-focus-ring);
1461
- border-radius: var(--cd-radius-1);
1462
- }
1463
- .cd-date-picker__clear:hover {
1464
- color: var(--cd-color-text-0);
1465
- }
1466
- .cd-date-picker__panel {
1467
- position: absolute;
1468
- inset-block-start: calc(100% + var(--cd-spacing-1));
1469
- inset-inline-start: 0;
1470
- z-index: var(--cd-date-picker-panel-z, 1030);
1471
- padding: var(--cd-spacing-3);
1472
- background: var(--cd-date-picker-panel-bg);
1473
- border-radius: var(--cd-date-picker-panel-radius);
1474
- box-shadow: var(--cd-date-picker-panel-shadow);
1475
- }
1476
- .cd-date-picker__panel:focus-visible {
1477
- outline: none;
1478
- }
1479
- /* 顶部/底部插槽 */
1480
- .cd-date-picker__slot--top {
1481
- margin-block-end: var(--cd-spacing-2);
1482
- }
1483
- .cd-date-picker__slot--bottom {
1484
- margin-block-start: var(--cd-spacing-2);
1485
- }
1486
- .cd-date-picker__slot--left {
1487
- margin-inline-end: var(--cd-spacing-2);
1488
- }
1489
- .cd-date-picker__slot--right {
1490
- margin-inline-start: var(--cd-spacing-2);
1491
- }
1492
- .cd-date-picker__layout {
1493
- display: flex;
1494
- align-items: stretch;
1495
- }
1496
- /* presets top/bottom 时竖向排列整体 */
1497
- .cd-date-picker__layout--presets-top,
1498
- .cd-date-picker__layout--presets-bottom {
1499
- flex-direction: column;
1500
- }
1501
- .cd-date-picker__main {
1502
- display: flex;
1503
- flex-direction: column;
1504
- flex: 1 1 auto;
1505
- }
1506
- .cd-date-picker__presets {
1507
- display: flex;
1508
- flex-direction: column;
1509
- gap: var(--cd-spacing-1);
1510
- margin-inline-end: var(--cd-spacing-3);
1511
- padding-inline-end: var(--cd-spacing-3);
1512
- border-inline-end: 1px solid var(--cd-color-border);
1513
- min-inline-size: 5rem;
1514
- }
1515
- /* top/bottom 时横向排列 presets */
1516
- .cd-date-picker__presets:not(.cd-date-picker__presets--vertical) {
1517
- flex-direction: row;
1518
- flex-wrap: wrap;
1519
- margin-inline-end: 0;
1520
- padding-inline-end: 0;
1521
- border-inline-end: none;
1522
- margin-block-end: var(--cd-spacing-2);
1523
- padding-block-end: var(--cd-spacing-2);
1524
- border-block-end: 1px solid var(--cd-color-border);
1525
- min-inline-size: unset;
1526
- }
1527
- /* right 侧预设:切换 margin/border 方向 */
1528
- .cd-date-picker__layout--presets-right .cd-date-picker__presets {
1529
- margin-inline-end: 0;
1530
- padding-inline-end: 0;
1531
- border-inline-end: none;
1532
- margin-inline-start: var(--cd-spacing-3);
1533
- padding-inline-start: var(--cd-spacing-3);
1534
- border-inline-start: 1px solid var(--cd-color-border);
1535
- }
1536
- /* bottom 预sets */
1537
- .cd-date-picker__layout--presets-bottom .cd-date-picker__presets {
1538
- margin-block-end: 0;
1539
- padding-block-end: 0;
1540
- border-block-end: none;
1541
- margin-block-start: var(--cd-spacing-2);
1542
- padding-block-start: var(--cd-spacing-2);
1543
- border-block-start: 1px solid var(--cd-color-border);
1544
- }
1545
- .cd-date-picker__preset {
1546
- padding-inline: var(--cd-spacing-2);
1547
- padding-block: var(--cd-spacing-1);
1548
- border: none;
1549
- border-radius: var(--cd-radius-1);
1550
- background: transparent;
1551
- color: var(--cd-color-text-0);
1552
- font: inherit;
1553
- text-align: start;
1554
- white-space: nowrap;
1555
- cursor: pointer;
1556
- transition: background var(--cd-motion-duration-fast) var(--cd-motion-ease-standard);
1557
- }
1558
- .cd-date-picker__preset:hover {
1559
- background: var(--cd-date-picker-cell-bg-hover);
1560
- color: var(--cd-color-primary);
1561
- }
1562
- .cd-date-picker__preset:focus-visible {
1563
- outline: none;
1564
- box-shadow: var(--cd-focus-ring);
1565
- }
1566
- .cd-date-picker__body {
1567
- display: flex;
1568
- align-items: stretch;
1569
- }
1570
- .cd-date-picker__time {
1571
- display: flex;
1572
- margin-inline-start: var(--cd-spacing-2);
1573
- padding-inline-start: var(--cd-spacing-2);
1574
- border-inline-start: 1px solid var(--cd-color-border);
1575
- }
1576
- .cd-date-picker__time-col {
1577
- inline-size: var(--cd-time-picker-time-col-width);
1578
- block-size: calc(var(--cd-time-picker-time-item-height) * 7);
1579
- margin: 0;
1580
- padding: 0;
1581
- overflow-y: auto;
1582
- list-style: none;
1583
- scrollbar-width: thin;
1584
- }
1585
- .cd-date-picker__time-col + .cd-date-picker__time-col {
1586
- border-inline-start: 1px solid var(--cd-color-border);
1587
- }
1588
- .cd-date-picker__time-item {
1589
- display: flex;
1590
- align-items: center;
1591
- justify-content: center;
1592
- block-size: var(--cd-time-picker-time-item-height);
1593
- color: var(--cd-color-text-0);
1594
- cursor: pointer;
1595
- transition: background var(--cd-motion-duration-fast) var(--cd-motion-ease-standard);
1596
- }
1597
- .cd-date-picker__time-item:hover {
1598
- background: var(--cd-date-picker-cell-bg-hover);
1599
- }
1600
- .cd-date-picker__time-item:focus-visible {
1601
- outline: none;
1602
- box-shadow: var(--cd-focus-ring);
1603
- }
1604
- .cd-date-picker__time-item--selected,
1605
- .cd-date-picker__time-item--selected:hover {
1606
- background: var(--cd-date-picker-cell-bg-selected);
1607
- color: var(--cd-date-picker-cell-color-selected);
1608
- }
1609
- .cd-date-picker__time-item--disabled,
1610
- .cd-date-picker__time-item--disabled:hover {
1611
- color: var(--cd-color-text-3);
1612
- cursor: not-allowed;
1613
- background: transparent;
1614
- }
1615
- .cd-date-picker__ok {
1616
- padding-inline: var(--cd-spacing-2);
1617
- padding-block: var(--cd-spacing-1);
1618
- border: none;
1619
- border-radius: var(--cd-radius-1);
1620
- background: var(--cd-color-primary);
1621
- color: var(--cd-color-white, #fff);
1622
- font: inherit;
1623
- cursor: pointer;
1624
- }
1625
- .cd-date-picker__ok:hover {
1626
- background: var(--cd-color-primary-hover, var(--cd-color-primary));
1627
- }
1628
- .cd-date-picker__ok:focus-visible {
1629
- outline: none;
1630
- box-shadow: var(--cd-focus-ring);
1631
- }
1632
- .cd-date-picker__cancel {
1633
- padding-inline: var(--cd-spacing-2);
1634
- padding-block: var(--cd-spacing-1);
1635
- border: 1px solid var(--cd-color-border);
1636
- border-radius: var(--cd-radius-1);
1637
- background: transparent;
1638
- color: var(--cd-color-text-0);
1639
- font: inherit;
1640
- cursor: pointer;
1641
- }
1642
- .cd-date-picker__cancel:hover {
1643
- border-color: var(--cd-color-primary);
1644
- color: var(--cd-color-primary);
1645
- }
1646
- .cd-date-picker__cancel:focus-visible {
1647
- outline: none;
1648
- box-shadow: var(--cd-focus-ring);
1649
- }
1650
- .cd-date-picker__header {
1651
- display: flex;
1652
- align-items: center;
1653
- justify-content: space-between;
1654
- gap: var(--cd-spacing-2);
1655
- margin-block-end: var(--cd-spacing-2);
1656
- }
1657
- .cd-date-picker__title {
1658
- flex: 1 1 auto;
1659
- text-align: center;
1660
- color: var(--cd-date-picker-header-color);
1661
- font-weight: var(--cd-font-weight-medium);
1662
- }
1663
- .cd-date-picker__nav {
1664
- display: inline-flex;
1665
- align-items: center;
1666
- justify-content: center;
1667
- flex: 0 0 auto;
1668
- inline-size: var(--cd-date-picker-cell-size);
1669
- block-size: var(--cd-date-picker-cell-size);
1670
- padding: 0;
1671
- border: none;
1672
- background: transparent;
1673
- color: var(--cd-color-text-2);
1674
- border-radius: var(--cd-date-picker-cell-radius);
1675
- cursor: pointer;
1676
- }
1677
- .cd-date-picker__nav:hover {
1678
- background: var(--cd-date-picker-cell-bg-hover);
1679
- color: var(--cd-color-text-0);
1680
- }
1681
- .cd-date-picker__nav:focus-visible {
1682
- outline: none;
1683
- box-shadow: var(--cd-focus-ring);
1684
- }
1685
- /* 日期网格:role=grid 容器纵向堆行,每行 7 列 */
1686
- .cd-date-picker__grid {
1687
- display: flex;
1688
- flex-direction: column;
1689
- gap: 2px;
1690
- }
1691
- .cd-date-picker__grid:focus-visible {
1692
- outline: none;
1693
- }
1694
- .cd-date-picker__row {
1695
- display: grid;
1696
- grid-template-columns: repeat(7, var(--cd-date-picker-cell-size));
1697
- gap: 2px;
1698
- }
1699
- /* month/year 面板:3 列大格 (仍用 grid 容器) */
1700
- .cd-date-picker__grid--month,
1701
- .cd-date-picker__grid--year {
1702
- display: grid;
1703
- grid-template-columns: repeat(3, 1fr);
1704
- gap: var(--cd-spacing-1);
1705
- inline-size: calc(var(--cd-date-picker-cell-size) * 7 + 2px * 6);
1706
- }
1707
- .cd-date-picker__cell--block {
1708
- inline-size: auto;
1709
- padding-inline: var(--cd-spacing-2);
1710
- block-size: calc(var(--cd-date-picker-cell-size) * 1.4);
1711
- }
1712
- .cd-date-picker__weekday {
1713
- display: inline-flex;
1714
- align-items: center;
1715
- justify-content: center;
1716
- block-size: var(--cd-date-picker-cell-size);
1717
- color: var(--cd-date-picker-weekday-color);
1718
- font-size: var(--cd-font-size-1);
1719
- }
1720
- .cd-date-picker__cell {
1721
- display: inline-flex;
1722
- align-items: center;
1723
- justify-content: center;
1724
- inline-size: var(--cd-date-picker-cell-size);
1725
- block-size: var(--cd-date-picker-cell-size);
1726
- padding: 0;
1727
- border: none;
1728
- background: transparent;
1729
- color: var(--cd-color-text-0);
1730
- border-radius: var(--cd-date-picker-cell-radius);
1731
- font: inherit;
1732
- cursor: pointer;
1733
- transition: background var(--cd-motion-duration-fast) var(--cd-motion-ease-standard);
1734
- }
1735
- .cd-date-picker__cell:hover {
1736
- background: var(--cd-date-picker-cell-bg-hover);
1737
- }
1738
- .cd-date-picker__cell:focus-visible {
1739
- outline: none;
1740
- box-shadow: var(--cd-focus-ring);
1741
- }
1742
- .cd-date-picker__cell--muted {
1743
- color: var(--cd-date-picker-cell-color-muted);
1744
- }
1745
- .cd-date-picker__cell--today {
1746
- border-block-end: 2px solid var(--cd-date-picker-cell-bg-selected);
1747
- }
1748
- .cd-date-picker__cell--highlight {
1749
- background: var(--cd-date-picker-cell-bg-hover);
1750
- }
1751
- .cd-date-picker__cell--selected,
1752
- .cd-date-picker__cell--selected:hover {
1753
- background: var(--cd-date-picker-cell-bg-selected);
1754
- color: var(--cd-date-picker-cell-color-selected);
1755
- }
1756
- .cd-date-picker__cell:disabled {
1757
- color: var(--cd-color-text-3);
1758
- cursor: not-allowed;
1759
- background: transparent;
1760
- }
1761
- .cd-date-picker__footer {
1762
- display: flex;
1763
- align-items: center;
1764
- justify-content: center;
1765
- gap: var(--cd-spacing-2);
1766
- margin-block-start: var(--cd-spacing-2);
1767
- padding-block-start: var(--cd-spacing-2);
1768
- border-block-start: 1px solid var(--cd-color-border);
1769
- }
1770
- .cd-date-picker__panel--datetime .cd-date-picker__footer,
1771
- .cd-date-picker__footer:has(.cd-date-picker__ok) {
1772
- justify-content: space-between;
1773
- }
1774
- .cd-date-picker__today {
1775
- padding: 0;
1776
- border: none;
1777
- background: transparent;
1778
- color: var(--cd-color-primary);
1779
- font: inherit;
1780
- cursor: pointer;
1781
- }
1782
- .cd-date-picker__today:hover {
1783
- text-decoration: underline;
1784
- }
1785
- .cd-date-picker__today:focus-visible {
1786
- outline: none;
1787
- box-shadow: var(--cd-focus-ring);
1788
- border-radius: var(--cd-radius-1);
1789
- }
1790
- @media (prefers-reduced-motion: reduce) {
1791
- .cd-date-picker__trigger,
1792
- .cd-date-picker__clear,
1793
- .cd-date-picker__cell,
1794
- .cd-date-picker__preset {
1795
- transition: none;
1796
- }
1797
- }
1798
- </style>