@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.
- package/dist/components.json +1 -1
- package/package.json +7 -8
- package/src/_floating/use-floating.ts +0 -208
- package/src/anchor/Anchor.a11y.test.ts +0 -49
- package/src/anchor/Anchor.kbd.test.ts +0 -70
- package/src/anchor/Anchor.svelte +0 -359
- package/src/anchor/AnchorKbdFixture.svelte +0 -24
- package/src/anchor/index.ts +0 -3
- package/src/anchor/meta.ts +0 -70
- package/src/anchor/types.ts +0 -8
- package/src/autocomplete/AutoComplete.a11y.test.ts +0 -49
- package/src/autocomplete/AutoComplete.kbd.test.ts +0 -69
- package/src/autocomplete/AutoComplete.svelte +0 -706
- package/src/autocomplete/AutoCompleteKbdFixture.svelte +0 -24
- package/src/autocomplete/index.ts +0 -2
- package/src/autocomplete/meta.ts +0 -41
- package/src/avatar/Avatar.a11y.test.ts +0 -37
- package/src/avatar/Avatar.svelte +0 -315
- package/src/avatar/AvatarGroup.svelte +0 -142
- package/src/avatar/context.ts +0 -21
- package/src/avatar/index.ts +0 -10
- package/src/avatar/meta.ts +0 -73
- package/src/back-top/BackTop.a11y.test.ts +0 -40
- package/src/back-top/BackTop.svelte +0 -314
- package/src/back-top/index.ts +0 -2
- package/src/back-top/meta.ts +0 -108
- package/src/badge/Badge.a11y.test.ts +0 -35
- package/src/badge/Badge.svelte +0 -328
- package/src/badge/BadgeA11yFixture.svelte +0 -18
- package/src/badge/index.ts +0 -2
- package/src/badge/meta.ts +0 -62
- package/src/banner/Banner.a11y.test.ts +0 -48
- package/src/banner/Banner.svelte +0 -368
- package/src/banner/index.ts +0 -3
- package/src/banner/meta.ts +0 -121
- package/src/breadcrumb/Breadcrumb.a11y.test.ts +0 -35
- package/src/breadcrumb/Breadcrumb.kbd.test.ts +0 -45
- package/src/breadcrumb/Breadcrumb.svelte +0 -414
- package/src/breadcrumb/BreadcrumbKbdFixture.svelte +0 -23
- package/src/breadcrumb/Item.svelte +0 -77
- package/src/breadcrumb/context.ts +0 -27
- package/src/breadcrumb/index.ts +0 -21
- package/src/breadcrumb/meta.ts +0 -128
- package/src/breadcrumb/types.ts +0 -4
- package/src/button/Button.a11y.test.ts +0 -54
- package/src/button/Button.svelte +0 -176
- package/src/button/index.ts +0 -2
- package/src/button/meta.ts +0 -28
- package/src/calendar/Calendar.a11y.test.ts +0 -51
- package/src/calendar/Calendar.kbd.test.ts +0 -59
- package/src/calendar/Calendar.svelte +0 -1344
- package/src/calendar/CalendarKbdFixture.svelte +0 -23
- package/src/calendar/index.ts +0 -3
- package/src/calendar/meta.ts +0 -117
- package/src/card/Card.a11y.test.ts +0 -38
- package/src/card/Card.svelte +0 -341
- package/src/card/CardMeta.svelte +0 -60
- package/src/card/index.ts +0 -8
- package/src/card/meta.ts +0 -83
- package/src/carousel/Carousel.a11y.test.ts +0 -53
- package/src/carousel/Carousel.kbd.test.ts +0 -67
- package/src/carousel/Carousel.svelte +0 -806
- package/src/carousel/CarouselA11yFixture.svelte +0 -25
- package/src/carousel/CarouselKbdFixture.svelte +0 -24
- package/src/carousel/index.ts +0 -2
- package/src/carousel/meta.ts +0 -74
- package/src/cascader/Cascader.a11y.test.ts +0 -59
- package/src/cascader/Cascader.kbd.test.ts +0 -56
- package/src/cascader/Cascader.svelte +0 -1570
- package/src/cascader/CascaderKbdFixture.svelte +0 -31
- package/src/cascader/index.ts +0 -3
- package/src/cascader/meta.ts +0 -57
- package/src/cascader/types.ts +0 -9
- package/src/checkbox/Checkbox.svelte +0 -281
- package/src/checkbox/CheckboxGroup.a11y.test.ts +0 -43
- package/src/checkbox/CheckboxGroup.kbd.test.ts +0 -40
- package/src/checkbox/CheckboxGroup.svelte +0 -122
- package/src/checkbox/CheckboxGroupKbdFixture.svelte +0 -20
- package/src/checkbox/context.ts +0 -31
- package/src/checkbox/index.ts +0 -4
- package/src/checkbox/meta.ts +0 -67
- package/src/collapse/Collapse.a11y.test.ts +0 -53
- package/src/collapse/Collapse.kbd.test.ts +0 -89
- package/src/collapse/Collapse.svelte +0 -406
- package/src/collapse/CollapseA11yFixture.svelte +0 -27
- package/src/collapse/CollapseKbdFixture.svelte +0 -25
- package/src/collapse/CollapsePanel.svelte +0 -102
- package/src/collapse/context.ts +0 -54
- package/src/collapse/index.ts +0 -17
- package/src/collapse/meta.ts +0 -79
- package/src/collapse/types.ts +0 -5
- package/src/color-picker/ColorPicker.a11y.test.ts +0 -60
- package/src/color-picker/ColorPicker.kbd.test.ts +0 -73
- package/src/color-picker/ColorPicker.svelte +0 -985
- package/src/color-picker/ColorPickerKbdFixture.svelte +0 -25
- package/src/color-picker/index.ts +0 -2
- package/src/color-picker/meta.ts +0 -47
- package/src/config-provider/ConfigProvider.svelte +0 -227
- package/src/config-provider/context.ts +0 -29
- package/src/config-provider/index.ts +0 -48
- package/src/config-provider/meta.ts +0 -128
- package/src/date-picker/DatePicker.a11y.test.ts +0 -45
- package/src/date-picker/DatePicker.kbd.test.ts +0 -71
- package/src/date-picker/DatePicker.svelte +0 -1798
- package/src/date-picker/DatePickerKbdFixture.svelte +0 -26
- package/src/date-picker/RangePicker.kbd.test.ts +0 -69
- package/src/date-picker/RangePicker.svelte +0 -775
- package/src/date-picker/RangePickerKbdFixture.svelte +0 -30
- package/src/date-picker/index.ts +0 -4
- package/src/date-picker/meta.ts +0 -67
- package/src/date-picker/range-meta.ts +0 -44
- package/src/descriptions/Descriptions.a11y.test.ts +0 -33
- package/src/descriptions/Descriptions.svelte +0 -287
- package/src/descriptions/DescriptionsItem.svelte +0 -43
- package/src/descriptions/context.ts +0 -21
- package/src/descriptions/index.ts +0 -16
- package/src/descriptions/meta.ts +0 -45
- package/src/descriptions/types.ts +0 -6
- package/src/divider/Divider.a11y.test.ts +0 -23
- package/src/divider/Divider.svelte +0 -154
- package/src/divider/index.ts +0 -2
- package/src/divider/meta.ts +0 -23
- package/src/drawer/Drawer.a11y.test.ts +0 -41
- package/src/drawer/Drawer.kbd.test.ts +0 -67
- package/src/drawer/Drawer.svelte +0 -554
- package/src/drawer/DrawerKbdFixture.svelte +0 -28
- package/src/drawer/index.ts +0 -2
- package/src/drawer/meta.ts +0 -127
- package/src/dropdown/Dropdown.a11y.test.ts +0 -46
- package/src/dropdown/Dropdown.kbd.test.ts +0 -56
- package/src/dropdown/Dropdown.svelte +0 -573
- package/src/dropdown/DropdownA11yFixture.svelte +0 -24
- package/src/dropdown/DropdownDivider.svelte +0 -17
- package/src/dropdown/DropdownItem.svelte +0 -127
- package/src/dropdown/DropdownItemNode.svelte +0 -355
- package/src/dropdown/DropdownKbdFixture.svelte +0 -26
- package/src/dropdown/DropdownMenu.svelte +0 -24
- package/src/dropdown/DropdownSubMenu.svelte +0 -212
- package/src/dropdown/DropdownTitle.svelte +0 -34
- package/src/dropdown/context.ts +0 -13
- package/src/dropdown/index.ts +0 -36
- package/src/dropdown/meta.ts +0 -97
- package/src/dropdown/types.test.ts +0 -50
- package/src/dropdown/types.ts +0 -67
- package/src/empty/Empty.a11y.test.ts +0 -24
- package/src/empty/Empty.svelte +0 -304
- package/src/empty/index.ts +0 -2
- package/src/empty/meta.ts +0 -41
- package/src/form/Field.svelte +0 -492
- package/src/form/FieldArray.svelte +0 -75
- package/src/form/Form.a11y.test.ts +0 -39
- package/src/form/Form.svelte +0 -243
- package/src/form/FormA11yFixture.svelte +0 -31
- package/src/form/FormCascader.svelte +0 -82
- package/src/form/FormCheckbox.svelte +0 -83
- package/src/form/FormDatePicker.svelte +0 -80
- package/src/form/FormErrorMessage.svelte +0 -44
- package/src/form/FormInput.svelte +0 -95
- package/src/form/FormLabel.svelte +0 -46
- package/src/form/FormRadio.svelte +0 -83
- package/src/form/FormRating.svelte +0 -85
- package/src/form/FormSection.svelte +0 -45
- package/src/form/FormSelect.svelte +0 -96
- package/src/form/FormSlider.svelte +0 -95
- package/src/form/FormSlot.svelte +0 -51
- package/src/form/FormSwitch.svelte +0 -82
- package/src/form/FormTagInput.svelte +0 -79
- package/src/form/FormTreeSelect.svelte +0 -85
- package/src/form/FormUpload.svelte +0 -92
- package/src/form/context.ts +0 -47
- package/src/form/index.ts +0 -22
- package/src/form/meta.ts +0 -85
- package/src/grid/Col.svelte +0 -142
- package/src/grid/Grid.a11y.test.ts +0 -14
- package/src/grid/GridA11yFixture.svelte +0 -12
- package/src/grid/Row.svelte +0 -116
- package/src/grid/index.ts +0 -3
- package/src/grid/meta.ts +0 -72
- package/src/grid/use-breakpoint.svelte.ts +0 -48
- package/src/highlight/Highlight.a11y.test.ts +0 -25
- package/src/highlight/Highlight.svelte +0 -99
- package/src/highlight/index.ts +0 -2
- package/src/highlight/meta.ts +0 -80
- package/src/icon/Icon.svelte +0 -156
- package/src/icon/index.ts +0 -2
- package/src/icon/meta.ts +0 -41
- package/src/image/Image.a11y.test.ts +0 -30
- package/src/image/Image.svelte +0 -387
- package/src/image/ImagePreview.kbd.test.ts +0 -52
- package/src/image/ImagePreview.svelte +0 -309
- package/src/image/ImagePreviewGroup.svelte +0 -93
- package/src/image/ImagePreviewKbdFixture.svelte +0 -32
- package/src/image/context.ts +0 -26
- package/src/image/index.ts +0 -15
- package/src/image/meta.ts +0 -131
- package/src/index.ts +0 -208
- package/src/input/Input.a11y.test.ts +0 -58
- package/src/input/Input.svelte +0 -505
- package/src/input/index.ts +0 -2
- package/src/input/meta.ts +0 -40
- package/src/input-number/InputNumber.a11y.test.ts +0 -43
- package/src/input-number/InputNumber.kbd.test.ts +0 -41
- package/src/input-number/InputNumber.svelte +0 -674
- package/src/input-number/InputNumberKbdFixture.svelte +0 -15
- package/src/input-number/index.ts +0 -2
- package/src/input-number/meta.ts +0 -65
- package/src/layout/Content.svelte +0 -37
- package/src/layout/Footer.svelte +0 -49
- package/src/layout/Header.svelte +0 -46
- package/src/layout/Layout.a11y.test.ts +0 -34
- package/src/layout/Layout.svelte +0 -60
- package/src/layout/LayoutA11yFixture.svelte +0 -21
- package/src/layout/Sider.svelte +0 -207
- package/src/layout/index.ts +0 -26
- package/src/layout/meta.ts +0 -116
- package/src/list/List.a11y.test.ts +0 -69
- package/src/list/List.bench.ts +0 -26
- package/src/list/List.kbd.test.ts +0 -71
- package/src/list/List.svelte +0 -920
- package/src/list/ListA11yFixture.svelte +0 -38
- package/src/list/ListBenchFixture.svelte +0 -22
- package/src/list/ListItem.svelte +0 -175
- package/src/list/ListKbdFixture.svelte +0 -31
- package/src/list/ListMeta.svelte +0 -73
- package/src/list/context.ts +0 -39
- package/src/list/index.ts +0 -21
- package/src/list/meta.ts +0 -99
- package/src/locale-provider/LocaleProvider.svelte +0 -110
- package/src/locale-provider/context.ts +0 -22
- package/src/locale-provider/index.ts +0 -21
- package/src/locale-provider/meta.ts +0 -93
- package/src/locale-provider/use-locale.ts +0 -25
- package/src/lottie-icon/LottieIcon.svelte +0 -330
- package/src/lottie-icon/index.ts +0 -9
- package/src/lottie-icon/meta.ts +0 -162
- package/src/menu/Menu.a11y.test.ts +0 -54
- package/src/menu/Menu.kbd.test.ts +0 -69
- package/src/menu/Menu.svelte +0 -762
- package/src/menu/MenuKbdFixture.svelte +0 -22
- package/src/menu/MenuPopupNode.svelte +0 -525
- package/src/menu/index.ts +0 -4
- package/src/menu/meta.ts +0 -137
- package/src/menu/types.ts +0 -120
- package/src/meta.test.ts +0 -173
- package/src/modal/ConfirmModal.svelte +0 -173
- package/src/modal/Modal.a11y.test.ts +0 -46
- package/src/modal/Modal.kbd.test.ts +0 -65
- package/src/modal/Modal.svelte +0 -511
- package/src/modal/ModalKbdFixture.svelte +0 -24
- package/src/modal/command.svelte.ts +0 -103
- package/src/modal/index.ts +0 -30
- package/src/modal/meta.ts +0 -165
- package/src/modal/z-stack.ts +0 -26
- package/src/notification/NotificationContainer.svelte +0 -192
- package/src/notification/NotificationItem.a11y.test.ts +0 -73
- package/src/notification/NotificationItem.svelte +0 -368
- package/src/notification/index.ts +0 -9
- package/src/notification/meta.ts +0 -120
- package/src/notification/store.ts +0 -191
- package/src/overflow-list/OverflowList.a11y.test.ts +0 -46
- package/src/overflow-list/OverflowList.kbd.test.ts +0 -34
- package/src/overflow-list/OverflowList.svelte +0 -539
- package/src/overflow-list/OverflowListA11yFixture.svelte +0 -22
- package/src/overflow-list/OverflowListKbdFixture.svelte +0 -21
- package/src/overflow-list/index.ts +0 -2
- package/src/overflow-list/meta.ts +0 -138
- package/src/pagination/Pagination.a11y.test.ts +0 -62
- package/src/pagination/Pagination.kbd.test.ts +0 -66
- package/src/pagination/Pagination.svelte +0 -428
- package/src/pagination/PaginationKbdFixture.svelte +0 -15
- package/src/pagination/index.ts +0 -2
- package/src/pagination/meta.ts +0 -73
- package/src/popconfirm/Popconfirm.a11y.test.ts +0 -46
- package/src/popconfirm/Popconfirm.kbd.test.ts +0 -42
- package/src/popconfirm/Popconfirm.svelte +0 -724
- package/src/popconfirm/PopconfirmA11yFixture.svelte +0 -34
- package/src/popconfirm/PopconfirmKbdFixture.svelte +0 -17
- package/src/popconfirm/index.ts +0 -2
- package/src/popconfirm/meta.ts +0 -200
- package/src/popover/Popover.a11y.test.ts +0 -58
- package/src/popover/Popover.kbd.test.ts +0 -42
- package/src/popover/Popover.svelte +0 -643
- package/src/popover/PopoverA11yFixture.svelte +0 -35
- package/src/popover/PopoverKbdFixture.svelte +0 -18
- package/src/popover/index.ts +0 -2
- package/src/popover/meta.ts +0 -103
- package/src/progress/Progress.a11y.test.ts +0 -37
- package/src/progress/Progress.svelte +0 -423
- package/src/progress/index.ts +0 -3
- package/src/progress/meta.ts +0 -132
- package/src/radio/Radio.svelte +0 -330
- package/src/radio/RadioGroup.a11y.test.ts +0 -43
- package/src/radio/RadioGroup.kbd.test.ts +0 -75
- package/src/radio/RadioGroup.svelte +0 -199
- package/src/radio/RadioGroupKbdFixture.svelte +0 -21
- package/src/radio/context.ts +0 -42
- package/src/radio/index.ts +0 -4
- package/src/radio/meta.ts +0 -68
- package/src/rating/Rating.a11y.test.ts +0 -41
- package/src/rating/Rating.kbd.test.ts +0 -48
- package/src/rating/Rating.svelte +0 -407
- package/src/rating/RatingKbdFixture.svelte +0 -15
- package/src/rating/index.ts +0 -2
- package/src/rating/meta.ts +0 -40
- package/src/resize-observer/ResizeObserver.svelte +0 -169
- package/src/resize-observer/action.ts +0 -80
- package/src/resize-observer/index.ts +0 -9
- package/src/resize-observer/meta.ts +0 -102
- package/src/scroll-list/ScrollColumn.svelte +0 -592
- package/src/scroll-list/ScrollList.svelte +0 -257
- package/src/scroll-list/index.ts +0 -4
- package/src/scroll-list/meta.ts +0 -93
- package/src/scroll-list/types.ts +0 -18
- package/src/select/Select.a11y.test.ts +0 -59
- package/src/select/Select.kbd.test.ts +0 -59
- package/src/select/Select.svelte +0 -1155
- package/src/select/SelectKbdFixture.svelte +0 -29
- package/src/select/index.ts +0 -3
- package/src/select/meta.ts +0 -78
- package/src/select/types.ts +0 -2
- package/src/side-sheet/SideSheet.a11y.test.ts +0 -53
- package/src/side-sheet/SideSheet.kbd.test.ts +0 -63
- package/src/side-sheet/SideSheet.svelte +0 -659
- package/src/side-sheet/SideSheetKbdFixture.svelte +0 -30
- package/src/side-sheet/index.ts +0 -2
- package/src/side-sheet/meta.ts +0 -116
- package/src/skeleton/Skeleton.a11y.test.ts +0 -35
- package/src/skeleton/Skeleton.svelte +0 -131
- package/src/skeleton/SkeletonAvatar.svelte +0 -82
- package/src/skeleton/SkeletonButton.svelte +0 -90
- package/src/skeleton/SkeletonImage.svelte +0 -100
- package/src/skeleton/SkeletonParagraph.svelte +0 -103
- package/src/skeleton/SkeletonTitle.svelte +0 -74
- package/src/skeleton/context.ts +0 -11
- package/src/skeleton/index.ts +0 -8
- package/src/skeleton/meta.ts +0 -65
- package/src/slider/Slider.a11y.test.ts +0 -44
- package/src/slider/Slider.kbd.test.ts +0 -74
- package/src/slider/Slider.svelte +0 -716
- package/src/slider/SliderKbdFixture.svelte +0 -21
- package/src/slider/index.ts +0 -2
- package/src/slider/meta.ts +0 -55
- package/src/space/Space.a11y.test.ts +0 -22
- package/src/space/Space.svelte +0 -109
- package/src/space/SpaceA11yFixture.svelte +0 -17
- package/src/space/index.ts +0 -2
- package/src/space/meta.ts +0 -27
- package/src/spin/Spin.a11y.test.ts +0 -29
- package/src/spin/Spin.svelte +0 -293
- package/src/spin/SpinA11yFixture.svelte +0 -18
- package/src/spin/index.ts +0 -2
- package/src/spin/meta.ts +0 -72
- package/src/steps/Steps.a11y.test.ts +0 -39
- package/src/steps/Steps.kbd.test.ts +0 -73
- package/src/steps/Steps.svelte +0 -392
- package/src/steps/StepsKbdFixture.svelte +0 -21
- package/src/steps/index.ts +0 -3
- package/src/steps/meta.ts +0 -59
- package/src/steps/types.ts +0 -8
- package/src/switch/Switch.a11y.test.ts +0 -46
- package/src/switch/Switch.kbd.test.ts +0 -40
- package/src/switch/Switch.svelte +0 -310
- package/src/switch/SwitchKbdFixture.svelte +0 -22
- package/src/switch/index.ts +0 -2
- package/src/switch/meta.ts +0 -44
- package/src/table/Table.a11y.test.ts +0 -70
- package/src/table/Table.bench.ts +0 -51
- package/src/table/Table.kbd.test.ts +0 -94
- package/src/table/Table.svelte +0 -2327
- package/src/table/TableKbdFixture.svelte +0 -35
- package/src/table/grid-nav.test.ts +0 -173
- package/src/table/grid-nav.ts +0 -146
- package/src/table/index.ts +0 -13
- package/src/table/meta.ts +0 -121
- package/src/table/types.ts +0 -133
- package/src/tabs/TabPane.svelte +0 -92
- package/src/tabs/Tabs.a11y.test.ts +0 -47
- package/src/tabs/Tabs.kbd.test.ts +0 -74
- package/src/tabs/Tabs.svelte +0 -1128
- package/src/tabs/TabsA11yFixture.svelte +0 -20
- package/src/tabs/TabsKbdFixture.svelte +0 -25
- package/src/tabs/context.ts +0 -43
- package/src/tabs/index.ts +0 -14
- package/src/tabs/meta.ts +0 -152
- package/src/tabs/types.ts +0 -6
- package/src/tag/Tag.a11y.test.ts +0 -33
- package/src/tag/Tag.svelte +0 -366
- package/src/tag/TagA11yFixture.svelte +0 -18
- package/src/tag/index.ts +0 -2
- package/src/tag/meta.ts +0 -92
- package/src/tag-input/TagInput.a11y.test.ts +0 -41
- package/src/tag-input/TagInput.svelte +0 -544
- package/src/tag-input/index.ts +0 -2
- package/src/tag-input/meta.ts +0 -43
- package/src/tag-input/reorder.test.ts +0 -59
- package/src/tag-input/reorder.ts +0 -41
- package/src/test-utils/LocaleHarness.svelte +0 -29
- package/src/test-utils/a11y.ts +0 -108
- package/src/test-utils/kbd.ts +0 -52
- package/src/textarea/TextArea.a11y.test.ts +0 -44
- package/src/textarea/TextArea.svelte +0 -420
- package/src/textarea/index.ts +0 -2
- package/src/textarea/meta.ts +0 -104
- package/src/time-picker/TimePicker.a11y.test.ts +0 -45
- package/src/time-picker/TimePicker.kbd.test.ts +0 -70
- package/src/time-picker/TimePicker.svelte +0 -1023
- package/src/time-picker/TimePickerKbdFixture.svelte +0 -23
- package/src/time-picker/index.ts +0 -2
- package/src/time-picker/meta.ts +0 -64
- package/src/timeline/Timeline.a11y.test.ts +0 -54
- package/src/timeline/Timeline.svelte +0 -599
- package/src/timeline/TimelineItem.svelte +0 -164
- package/src/timeline/context.ts +0 -28
- package/src/timeline/index.ts +0 -16
- package/src/timeline/meta.ts +0 -129
- package/src/timeline/types.ts +0 -9
- package/src/toast/Toast.a11y.test.ts +0 -67
- package/src/toast/ToastContainer.svelte +0 -184
- package/src/toast/ToastItem.svelte +0 -247
- package/src/toast/index.ts +0 -9
- package/src/toast/live-region.ts +0 -78
- package/src/toast/meta.ts +0 -95
- package/src/toast/store.ts +0 -187
- package/src/tooltip/Tooltip.a11y.test.ts +0 -41
- package/src/tooltip/Tooltip.kbd.test.ts +0 -37
- package/src/tooltip/Tooltip.svelte +0 -416
- package/src/tooltip/TooltipA11yFixture.svelte +0 -31
- package/src/tooltip/TooltipKbdFixture.svelte +0 -16
- package/src/tooltip/index.ts +0 -2
- package/src/tooltip/meta.ts +0 -59
- package/src/tooltip/placement.ts +0 -6
- package/src/transfer/Transfer.a11y.test.ts +0 -63
- package/src/transfer/Transfer.kbd.test.ts +0 -75
- package/src/transfer/Transfer.svelte +0 -1451
- package/src/transfer/TransferKbdFixture.svelte +0 -23
- package/src/transfer/group.test.ts +0 -55
- package/src/transfer/group.ts +0 -61
- package/src/transfer/index.ts +0 -3
- package/src/transfer/meta.ts +0 -55
- package/src/transfer/reorder.test.ts +0 -52
- package/src/transfer/reorder.ts +0 -42
- package/src/transfer/tree.test.ts +0 -44
- package/src/transfer/tree.ts +0 -52
- package/src/transfer/types.ts +0 -32
- package/src/tree/Tree.a11y.test.ts +0 -63
- package/src/tree/Tree.kbd.test.ts +0 -91
- package/src/tree/Tree.svelte +0 -1500
- package/src/tree/TreeKbdFixture.svelte +0 -30
- package/src/tree/index.ts +0 -3
- package/src/tree/meta.ts +0 -152
- package/src/tree-select/TreeSelect.a11y.test.ts +0 -52
- package/src/tree-select/TreeSelect.kbd.test.ts +0 -53
- package/src/tree-select/TreeSelect.svelte +0 -1611
- package/src/tree-select/TreeSelectKbdFixture.svelte +0 -20
- package/src/tree-select/index.ts +0 -3
- package/src/tree-select/meta.ts +0 -73
- package/src/tree-select/types.ts +0 -11
- package/src/tree-select/virtual.test.ts +0 -104
- package/src/typography/Link.svelte +0 -120
- package/src/typography/Paragraph.svelte +0 -92
- package/src/typography/Text.svelte +0 -93
- package/src/typography/Title.svelte +0 -91
- package/src/typography/Typography.a11y.test.ts +0 -34
- package/src/typography/TypographyA11yFixture.svelte +0 -27
- package/src/typography/TypographyBase.svelte +0 -807
- package/src/typography/index.ts +0 -16
- package/src/typography/meta.ts +0 -158
- package/src/upload/Upload.a11y.test.ts +0 -58
- package/src/upload/Upload.svelte +0 -1094
- package/src/upload/UploadA11yFixture.svelte +0 -23
- package/src/upload/index.ts +0 -3
- package/src/upload/meta.ts +0 -64
- package/src/upload/types.ts +0 -16
- package/src/virtual-list/VirtualList.svelte +0 -401
- package/src/virtual-list/index.ts +0 -2
- package/src/virtual-list/meta.ts +0 -106
package/src/checkbox/meta.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Machine-readable component metadata for AI/docs consumption.
|
|
3
|
-
* See specs/00-foundation/ai-friendly.spec.md.
|
|
4
|
-
*/
|
|
5
|
-
export const meta = {
|
|
6
|
-
name: 'Checkbox',
|
|
7
|
-
category: 'input',
|
|
8
|
-
description: '多选框,可独立使用或置于 CheckboxGroup 中管理一组选项,支持半选态。',
|
|
9
|
-
props: [
|
|
10
|
-
{ name: 'checked', type: 'boolean', default: 'undefined', desc: '受控选中;提供则为受控' },
|
|
11
|
-
{ name: 'defaultChecked', type: 'boolean', default: 'false', desc: '非受控初始选中' },
|
|
12
|
-
{ name: 'indeterminate', type: 'boolean', default: 'false', desc: '半选态(视觉横线)' },
|
|
13
|
-
{ name: 'value', type: 'string | number', default: 'undefined', desc: 'Group 内的标识值' },
|
|
14
|
-
{ name: 'disabled', type: 'boolean', default: 'false' },
|
|
15
|
-
{ name: 'size', type: "'small'|'default'|'large'", default: 'default' },
|
|
16
|
-
{ name: 'status', type: "'default'|'warning'|'error'", default: 'default' },
|
|
17
|
-
{
|
|
18
|
-
name: 'type',
|
|
19
|
-
type: "'default'|'card'|'pureCard'",
|
|
20
|
-
default: 'default',
|
|
21
|
-
desc: '展示形态;card 带边框背景且整卡为命中区,pureCard 无边框。Group 透传,单项可覆盖',
|
|
22
|
-
},
|
|
23
|
-
{ name: 'name', type: 'string', default: 'undefined' },
|
|
24
|
-
{ name: 'extra', type: 'string', default: 'undefined', desc: '辅助说明,aria-describedby 关联' },
|
|
25
|
-
{ name: 'id', type: 'string', default: 'useId()' },
|
|
26
|
-
{ name: 'onChange', type: '(checked: boolean) => void', default: 'undefined' },
|
|
27
|
-
{ name: 'children', type: 'Snippet', default: 'undefined', desc: '标签内容' },
|
|
28
|
-
],
|
|
29
|
-
group: {
|
|
30
|
-
name: 'CheckboxGroup',
|
|
31
|
-
props: [
|
|
32
|
-
{ name: 'value', type: '(string|number)[]', default: 'undefined', desc: '受控选中集合' },
|
|
33
|
-
{ name: 'defaultValue', type: '(string|number)[]', default: '[]' },
|
|
34
|
-
{
|
|
35
|
-
name: 'options',
|
|
36
|
-
type: 'Array<string|number|{label,value,disabled?,extra?}>',
|
|
37
|
-
default: 'undefined',
|
|
38
|
-
},
|
|
39
|
-
{ name: 'disabled', type: 'boolean', default: 'false' },
|
|
40
|
-
{ name: 'size', type: "'small'|'default'|'large'", default: 'default' },
|
|
41
|
-
{
|
|
42
|
-
name: 'status',
|
|
43
|
-
type: "'default'|'warning'|'error'",
|
|
44
|
-
default: 'default',
|
|
45
|
-
desc: '统一校验态透传子项,单项可覆盖',
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
name: 'type',
|
|
49
|
-
type: "'default'|'card'|'pureCard'",
|
|
50
|
-
default: 'default',
|
|
51
|
-
desc: '统一展示形态透传子项',
|
|
52
|
-
},
|
|
53
|
-
{ name: 'name', type: 'string', default: 'undefined' },
|
|
54
|
-
{ name: 'direction', type: "'horizontal'|'vertical'", default: 'horizontal' },
|
|
55
|
-
{ name: 'onChange', type: '(v: (string|number)[]) => void', default: 'undefined' },
|
|
56
|
-
{ name: 'children', type: 'Snippet', default: 'undefined' },
|
|
57
|
-
{ name: 'ariaLabel', type: 'string', default: 'undefined', desc: '无可见标题时的可访问名(role=group)' },
|
|
58
|
-
{ name: 'ariaLabelledby', type: 'string', default: 'undefined', desc: '关联组可见标题 id(优先于 ariaLabel)' },
|
|
59
|
-
],
|
|
60
|
-
},
|
|
61
|
-
a11y: {
|
|
62
|
-
role: 'checkbox',
|
|
63
|
-
keyboard: ['Space'],
|
|
64
|
-
notes: ['隐藏原生 input', 'indeterminate 用 DOM 属性', 'extra 经 aria-describedby 关联'],
|
|
65
|
-
},
|
|
66
|
-
tokens: ['--cd-checkbox-*', '--cd-focus-ring', '--cd-motion-*', '--cd-spacing-*'],
|
|
67
|
-
} as const;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// Collapse a11y:折叠面板(APG Accordion)。
|
|
2
|
-
// Header 外层 role=heading + aria-level;触发器为原生 button + aria-expanded;
|
|
3
|
-
// button aria-controls 指向内容 region,region aria-labelledby 指回 header。
|
|
4
|
-
// 用数据驱动夹具(CollapseA11yFixture)渲染真实 region,使 aria-controls 不悬空。
|
|
5
|
-
import { describe, it, expect } from 'vitest';
|
|
6
|
-
import { renderWithLocale, expectNoAxeViolations } from '../test-utils/a11y.js';
|
|
7
|
-
import CollapseFixture from './CollapseA11yFixture.svelte';
|
|
8
|
-
|
|
9
|
-
describe('Collapse a11y', () => {
|
|
10
|
-
it('默认渲染:role=heading + button aria-expanded + region 关联,无 axe violations', async () => {
|
|
11
|
-
const { container } = renderWithLocale(CollapseFixture, {});
|
|
12
|
-
|
|
13
|
-
// 每个 panel 的 Header 外层为 role=heading + aria-level。
|
|
14
|
-
const headings = container.querySelectorAll('[role="heading"]');
|
|
15
|
-
expect(headings.length).toBe(3);
|
|
16
|
-
expect(headings[0]?.getAttribute('aria-level')).toBe('3');
|
|
17
|
-
|
|
18
|
-
// 触发器为原生 button,aria-expanded 标记展开态(默认全收起)。
|
|
19
|
-
const headerBtns = container.querySelectorAll('button.cd-collapse__header');
|
|
20
|
-
expect(headerBtns.length).toBe(3);
|
|
21
|
-
expect(headerBtns[0]?.getAttribute('aria-expanded')).toBe('false');
|
|
22
|
-
|
|
23
|
-
// aria-controls 指向真实存在的 region,region aria-labelledby 指回 header。
|
|
24
|
-
const controls = headerBtns[0]?.getAttribute('aria-controls');
|
|
25
|
-
expect(controls).toBeTruthy();
|
|
26
|
-
const region = controls ? container.ownerDocument.getElementById(controls!) : null;
|
|
27
|
-
expect(region?.getAttribute('role')).toBe('region');
|
|
28
|
-
expect(region?.getAttribute('aria-labelledby')).toBe(headerBtns[0]?.id);
|
|
29
|
-
|
|
30
|
-
await expectNoAxeViolations(container);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('defaultActiveKey 展开:对应 header aria-expanded=true,region 非 hidden', async () => {
|
|
34
|
-
const { container } = renderWithLocale(CollapseFixture, {
|
|
35
|
-
props: { defaultActiveKey: 'a' },
|
|
36
|
-
});
|
|
37
|
-
const headerBtns = container.querySelectorAll('button.cd-collapse__header');
|
|
38
|
-
expect(headerBtns[0]?.getAttribute('aria-expanded')).toBe('true');
|
|
39
|
-
const controls = headerBtns[0]?.getAttribute('aria-controls');
|
|
40
|
-
const region = controls ? container.ownerDocument.getElementById(controls!) : null;
|
|
41
|
-
expect(region?.hasAttribute('hidden')).toBe(false);
|
|
42
|
-
await expectNoAxeViolations(container);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('roving tabindex:仅一个 Header 为 Tab 停靠点(tabindex=0),其余 -1', async () => {
|
|
46
|
-
const { container } = renderWithLocale(CollapseFixture, {});
|
|
47
|
-
const headerBtns = [...container.querySelectorAll('button.cd-collapse__header')];
|
|
48
|
-
const zero = headerBtns.filter((b) => b.getAttribute('tabindex') === '0');
|
|
49
|
-
// 首个未禁用 Header 为停靠点;禁用项(第三个)从 roving 中排除。
|
|
50
|
-
expect(zero.length).toBe(1);
|
|
51
|
-
await expectNoAxeViolations(container);
|
|
52
|
-
});
|
|
53
|
-
});
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
// Collapse 键盘 e2e(browser project / 真实 chromium)。
|
|
2
|
-
// APG Accordion:Header 组为单一 Tab 停靠点,roving(真实焦点)。
|
|
3
|
-
// 测真实焦点移动 + Enter/Space 展开——jsdom 测不了(命令式 focus() 不可靠):
|
|
4
|
-
// 1. roving 单停靠点:Tab 进入只停在一个 Header(其余 tabindex=-1,默认首个)。
|
|
5
|
-
// 2. ↑↓ 真实移动焦点到相邻 Header(无 wrap:clamp,源码 nextRovingIndex(...,false))。
|
|
6
|
-
// 3. Home/End 跳首/末 Header。
|
|
7
|
-
// 4. Enter / Space 展开当前焦点 Header(aria-expanded=true)。
|
|
8
|
-
//
|
|
9
|
-
// 真实焦点断言用 page locator 的 .toHaveFocus()。
|
|
10
|
-
import { describe, it, expect } from 'vitest';
|
|
11
|
-
import { page } from 'vitest/browser';
|
|
12
|
-
import { renderKbdFixture, userEvent } from '../test-utils/kbd.js';
|
|
13
|
-
import CollapseKbdFixture from './CollapseKbdFixture.svelte';
|
|
14
|
-
|
|
15
|
-
function loc(el: Element) {
|
|
16
|
-
return page.elementLocator(el);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
describe('Collapse 键盘 e2e(accordion header roving,真实焦点)', () => {
|
|
20
|
-
it('Tab 单停靠点 + ↑↓ 移动焦点(clamp)+ Home/End', async () => {
|
|
21
|
-
const { baseElement } = renderKbdFixture(CollapseKbdFixture);
|
|
22
|
-
|
|
23
|
-
const headers = Array.from(
|
|
24
|
-
baseElement.querySelectorAll<HTMLElement>('.cd-collapse__header[data-collapse-key]'),
|
|
25
|
-
);
|
|
26
|
-
expect(headers.length).toBe(3);
|
|
27
|
-
const [h1, h2, h3] = headers as [HTMLElement, HTMLElement, HTMLElement];
|
|
28
|
-
|
|
29
|
-
// 1. roving 单停靠点:默认首个 Header 为 tabindex=0,其余 -1。
|
|
30
|
-
expect(headers.filter((el) => el.tabIndex === 0).length).toBe(1);
|
|
31
|
-
expect(h1.tabIndex).toBe(0);
|
|
32
|
-
|
|
33
|
-
const before = baseElement.querySelector('[data-testid="before"]') as HTMLElement;
|
|
34
|
-
before.focus();
|
|
35
|
-
await expect.element(loc(before)).toHaveFocus();
|
|
36
|
-
await userEvent.tab();
|
|
37
|
-
await expect.element(loc(h1)).toHaveFocus();
|
|
38
|
-
|
|
39
|
-
// 2. ↓ 移动焦点到下一 Header(真实焦点 + 停靠点同步)。
|
|
40
|
-
await userEvent.keyboard('{ArrowDown}');
|
|
41
|
-
await expect.element(loc(h2)).toHaveFocus();
|
|
42
|
-
expect(h2.tabIndex).toBe(0);
|
|
43
|
-
expect(h1.tabIndex).toBe(-1);
|
|
44
|
-
|
|
45
|
-
await userEvent.keyboard('{ArrowDown}');
|
|
46
|
-
await expect.element(loc(h3)).toHaveFocus();
|
|
47
|
-
|
|
48
|
-
// 无 wrap:末项再 ↓ 停在末项(clamp)。
|
|
49
|
-
await userEvent.keyboard('{ArrowDown}');
|
|
50
|
-
await expect.element(loc(h3)).toHaveFocus();
|
|
51
|
-
|
|
52
|
-
// ↑ 回退;首项再 ↑ 停在首项(clamp)。
|
|
53
|
-
await userEvent.keyboard('{ArrowUp}');
|
|
54
|
-
await expect.element(loc(h2)).toHaveFocus();
|
|
55
|
-
await userEvent.keyboard('{ArrowUp}');
|
|
56
|
-
await expect.element(loc(h1)).toHaveFocus();
|
|
57
|
-
await userEvent.keyboard('{ArrowUp}');
|
|
58
|
-
await expect.element(loc(h1)).toHaveFocus();
|
|
59
|
-
|
|
60
|
-
// 3. Home/End 跳首/末。
|
|
61
|
-
await userEvent.keyboard('{End}');
|
|
62
|
-
await expect.element(loc(h3)).toHaveFocus();
|
|
63
|
-
await userEvent.keyboard('{Home}');
|
|
64
|
-
await expect.element(loc(h1)).toHaveFocus();
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('Enter / Space 展开当前焦点 Header(aria-expanded)', async () => {
|
|
68
|
-
const { baseElement } = renderKbdFixture(CollapseKbdFixture);
|
|
69
|
-
|
|
70
|
-
const headers = Array.from(
|
|
71
|
-
baseElement.querySelectorAll<HTMLElement>('.cd-collapse__header[data-collapse-key]'),
|
|
72
|
-
);
|
|
73
|
-
const [h1, h2] = headers as [HTMLElement, HTMLElement];
|
|
74
|
-
|
|
75
|
-
h1.focus();
|
|
76
|
-
await expect.element(loc(h1)).toHaveFocus();
|
|
77
|
-
expect(h1.getAttribute('aria-expanded')).toBe('false');
|
|
78
|
-
|
|
79
|
-
// Enter 展开当前 Header(原生 button 触发 onclick → toggle)。
|
|
80
|
-
await userEvent.keyboard('{Enter}');
|
|
81
|
-
await expect.element(loc(h1)).toHaveAttribute('aria-expanded', 'true');
|
|
82
|
-
|
|
83
|
-
// 移到下一 Header,Space 展开(非 accordion,可同时展开)。
|
|
84
|
-
await userEvent.keyboard('{ArrowDown}');
|
|
85
|
-
await expect.element(loc(h2)).toHaveFocus();
|
|
86
|
-
await userEvent.keyboard(' ');
|
|
87
|
-
await expect.element(loc(h2)).toHaveAttribute('aria-expanded', 'true');
|
|
88
|
-
});
|
|
89
|
-
});
|
|
@@ -1,406 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
Collapse — see specs/components/show/Collapse.spec.md
|
|
3
|
-
两种用法择一(与 Timeline / Form 复合组件同模式):
|
|
4
|
-
- 数据驱动:传 panels 数组(向后兼容,行为完全不变)。
|
|
5
|
-
- 声明式:不传 panels,改在 children 内写 <Collapse.Panel itemKey header>...</Collapse.Panel>。
|
|
6
|
-
父子状态经 context.ts 传递:父提供展开态派生函数 + toggle 回调,子 Panel 消费判断自身
|
|
7
|
-
展开/渲染与点击切换。两模式渲染同一套 .cd-collapse__item 结构,故声明式复用父级全部
|
|
8
|
-
grid 动画 / 箭头 / 边框样式(样式用 .cd-collapse :global(.cd-collapse__*) 跨子组件作用域)。
|
|
9
|
-
|
|
10
|
-
红线遵守:
|
|
11
|
-
#1 受控 activeKey 不回写 prop:isControlled = $derived(prop !== undefined),
|
|
12
|
-
内部 SvelteSet $state 兜底,current = $derived(...),变更只 onChange(声明式同样经 toggle 落实)。
|
|
13
|
-
#2 展开状态用本地 SvelteSet $state,不依赖挂载 registry,render 期不读 effect 写入的数组;
|
|
14
|
-
isActive/shouldRender 为纯派生函数,经 context 传给子 Panel 只读。
|
|
15
|
-
#3 展开动画用 CSS grid-template-rows 0fr↔1fr 过渡,不 JS 测量 DOM 几何。
|
|
16
|
-
-->
|
|
17
|
-
<script lang="ts">
|
|
18
|
-
import type { Snippet } from 'svelte';
|
|
19
|
-
import { SvelteSet } from 'svelte/reactivity';
|
|
20
|
-
import { useId, nextRovingIndex, rovingKeyFromEvent } from '@chenzy-design/core';
|
|
21
|
-
import type { CollapsePanel } from './types.js';
|
|
22
|
-
import { setCollapseContext } from './context.js';
|
|
23
|
-
|
|
24
|
-
type Size = 'small' | 'default' | 'large';
|
|
25
|
-
type IconPosition = 'left' | 'right';
|
|
26
|
-
|
|
27
|
-
interface Props {
|
|
28
|
-
panels?: CollapsePanel[];
|
|
29
|
-
activeKey?: string | string[];
|
|
30
|
-
defaultActiveKey?: string | string[];
|
|
31
|
-
accordion?: boolean;
|
|
32
|
-
size?: Size;
|
|
33
|
-
expandIconPosition?: IconPosition;
|
|
34
|
-
bordered?: boolean;
|
|
35
|
-
disabled?: boolean;
|
|
36
|
-
motion?: boolean;
|
|
37
|
-
/** Header 包裹元素的 aria-level(role=heading),默认 3。 */
|
|
38
|
-
headingLevel?: number;
|
|
39
|
-
/** 首次展开后才渲染面板内容 */
|
|
40
|
-
lazyRender?: boolean;
|
|
41
|
-
/** 展开过的面板内容保留 DOM(收起后不卸载),与 lazyRender 配合 */
|
|
42
|
-
keepDOM?: boolean;
|
|
43
|
-
onChange?: (keys: string[]) => void;
|
|
44
|
-
/** 某面板被展开后触发(spec §4:on:expand)。 */
|
|
45
|
-
onExpand?: (detail: { key: string }) => void;
|
|
46
|
-
/** 某面板被收起后触发(spec §4:on:collapse)。 */
|
|
47
|
-
onCollapse?: (detail: { key: string }) => void;
|
|
48
|
-
/** Header 被点击时触发(spec §4:on:headerClick,在 disabled 拦截前发出,可用于埋点)。 */
|
|
49
|
-
onHeaderClick?: (detail: { key: string; event: MouseEvent }) => void;
|
|
50
|
-
/** 自定义展开图标,替换默认箭头 SVG;参数为 {isExpanded: boolean}。 */
|
|
51
|
-
expandIcon?: Snippet<[{ isExpanded: boolean }]>;
|
|
52
|
-
/**
|
|
53
|
-
* 数据驱动模式:按 key 渲染面板内容 Snippet<[{ key }]>。
|
|
54
|
-
* 声明式模式(不传 panels):内嵌 <Collapse.Panel> 列表,普通 Snippet。
|
|
55
|
-
*/
|
|
56
|
-
children?: Snippet<[{ key: string }]> | Snippet;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
let {
|
|
60
|
-
panels = [],
|
|
61
|
-
activeKey,
|
|
62
|
-
defaultActiveKey,
|
|
63
|
-
accordion = false,
|
|
64
|
-
size = 'default',
|
|
65
|
-
expandIconPosition = 'right',
|
|
66
|
-
bordered = true,
|
|
67
|
-
disabled = false,
|
|
68
|
-
motion = true,
|
|
69
|
-
headingLevel = 3,
|
|
70
|
-
lazyRender = false,
|
|
71
|
-
keepDOM = true,
|
|
72
|
-
onChange,
|
|
73
|
-
onExpand,
|
|
74
|
-
onCollapse,
|
|
75
|
-
onHeaderClick,
|
|
76
|
-
expandIcon,
|
|
77
|
-
children,
|
|
78
|
-
}: Props = $props();
|
|
79
|
-
|
|
80
|
-
const idBase = useId('cd-collapse');
|
|
81
|
-
|
|
82
|
-
function normalize(value: string | string[] | undefined): string[] {
|
|
83
|
-
if (value === undefined) return [];
|
|
84
|
-
return Array.isArray(value) ? value : [value];
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function getInitialKeys(): SvelteSet<string> {
|
|
88
|
-
return new SvelteSet(normalize(defaultActiveKey));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// 红线 #1: 受控判定 + 内部 SvelteSet 兜底
|
|
92
|
-
const isControlled = $derived(activeKey !== undefined);
|
|
93
|
-
// 红线 #2: 本地 SvelteSet $state,不依赖挂载 registry
|
|
94
|
-
const innerKeys = $state<SvelteSet<string>>(getInitialKeys());
|
|
95
|
-
|
|
96
|
-
// 受控时读 prop(归一化),非受控读本地 set
|
|
97
|
-
const currentKeys = $derived<string[]>(
|
|
98
|
-
isControlled ? normalize(activeKey) : [...innerKeys],
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
// 记录曾展开过的面板(lazyRender + keepDOM 用)。初值为初始展开集。
|
|
102
|
-
const everExpanded = $state<SvelteSet<string>>(getInitialEverExpanded());
|
|
103
|
-
function getInitialEverExpanded(): SvelteSet<string> {
|
|
104
|
-
return new SvelteSet(normalize(defaultActiveKey ?? activeKey));
|
|
105
|
-
}
|
|
106
|
-
// 当前激活的也并入「曾展开」(受控场景:active 推进 everExpanded,effect 内写不在 render 期)。
|
|
107
|
-
$effect(() => {
|
|
108
|
-
for (const k of currentKeys) everExpanded.add(k);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
function isActive(key: string): boolean {
|
|
112
|
-
return currentKeys.includes(key);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// 渲染策略:
|
|
116
|
-
// - 非 lazyRender:始终渲染(内容常驻,配合 grid 动画)。
|
|
117
|
-
// - lazyRender + keepDOM:首次展开才渲染,之后保留 DOM。
|
|
118
|
-
// - lazyRender 非 keepDOM:仅当前展开渲染(收起卸载)。
|
|
119
|
-
function shouldRender(key: string): boolean {
|
|
120
|
-
if (!lazyRender) return true;
|
|
121
|
-
return keepDOM ? everExpanded.has(key) : isActive(key);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function toggle(key: string, panelDisabled?: boolean) {
|
|
125
|
-
if (disabled || panelDisabled) return;
|
|
126
|
-
|
|
127
|
-
const isOpen = currentKeys.includes(key);
|
|
128
|
-
let nextArr: string[];
|
|
129
|
-
if (isOpen) {
|
|
130
|
-
nextArr = currentKeys.filter((k) => k !== key);
|
|
131
|
-
} else if (accordion) {
|
|
132
|
-
nextArr = [key];
|
|
133
|
-
} else {
|
|
134
|
-
nextArr = [...currentKeys, key];
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// 红线 #1: 受控不回写 prop,仅 onChange;非受控更新本地 set
|
|
138
|
-
if (!isControlled) {
|
|
139
|
-
innerKeys.clear();
|
|
140
|
-
for (const k of nextArr) innerKeys.add(k);
|
|
141
|
-
}
|
|
142
|
-
onChange?.(nextArr);
|
|
143
|
-
// spec §4:展开/收起后分别发出 on:expand / on:collapse(key 级语义事件)。
|
|
144
|
-
if (isOpen) onCollapse?.({ key });
|
|
145
|
-
else onExpand?.({ key });
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// spec §4 on:headerClick:Header 被点击即发出(在 disabled 拦截前,可用于埋点),
|
|
149
|
-
// 随后再走 toggle(disabled / panelDisabled 在 toggle 内拦截,不影响本事件发出)。
|
|
150
|
-
function headerClick(event: MouseEvent, key: string, panelDisabled?: boolean) {
|
|
151
|
-
onHeaderClick?.({ key, event });
|
|
152
|
-
toggle(key, panelDisabled);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const cls = $derived(
|
|
156
|
-
[
|
|
157
|
-
'cd-collapse',
|
|
158
|
-
`cd-collapse--${size}`,
|
|
159
|
-
`cd-collapse--icon-${expandIconPosition}`,
|
|
160
|
-
bordered && 'cd-collapse--bordered',
|
|
161
|
-
disabled && 'cd-collapse--disabled',
|
|
162
|
-
motion && 'cd-collapse--motion',
|
|
163
|
-
]
|
|
164
|
-
.filter(Boolean)
|
|
165
|
-
.join(' '),
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
// 声明式优先级低于 panels:仅在未传 panels 时渲染 children 内的 <Collapse.Panel>。
|
|
169
|
-
const useDeclarative = $derived(panels.length === 0 && children != null);
|
|
170
|
-
|
|
171
|
-
// --- roving tabindex(a11y §6 / APG Accordion):Header 组为单一 Tab 停靠点。 ---
|
|
172
|
-
// rootEl 普通引用(bind:this),命令式 focus() 用,非 render 期读 DOM;
|
|
173
|
-
// 声明式 <Collapse.Panel> 也渲染进同一 rootEl,故按 DOM 顺序统一漫游(红线 #2:
|
|
174
|
-
// 不用 $state 数组收集子项,避免 effect 自循环)。
|
|
175
|
-
let rootEl = $state<HTMLElement | null>(null);
|
|
176
|
-
// 当前焦点 Header 的 key;null = 尚无焦点 -> 首个未禁用 Header 作为 Tab 停靠点。
|
|
177
|
-
let focusedKey = $state<string | null>(null);
|
|
178
|
-
|
|
179
|
-
// 查询 rootEl 下所有未禁用的 Header 按钮(DOM 顺序),roving 在其中漫游。
|
|
180
|
-
function focusableHeaders(): HTMLButtonElement[] {
|
|
181
|
-
if (!rootEl) return [];
|
|
182
|
-
return [
|
|
183
|
-
...rootEl.querySelectorAll<HTMLButtonElement>(
|
|
184
|
-
'.cd-collapse__header[data-collapse-key]:not([disabled])',
|
|
185
|
-
),
|
|
186
|
-
];
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// 纯派生 tabindex:焦点 Header(或无焦点时首个未禁用 Header)为 0,其余 -1。
|
|
190
|
-
// 不在 render 期写 $state(红线 #2)。整体 disabled 时所有 Header tabindex=-1。
|
|
191
|
-
function headerTabindex(key: string, panelDisabled?: boolean): 0 | -1 {
|
|
192
|
-
if (disabled || panelDisabled) return -1;
|
|
193
|
-
if (focusedKey != null) return focusedKey === key ? 0 : -1;
|
|
194
|
-
// 无焦点:首个未禁用 Header 为停靠点。数据驱动模式下用 panels 推断首个可聚焦项。
|
|
195
|
-
const firstKey = firstFocusableKey();
|
|
196
|
-
return firstKey === key ? 0 : -1;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// 首个未禁用 Header 的 key:数据驱动用 panels 派生;声明式回退到 DOM 查询。
|
|
200
|
-
function firstFocusableKey(): string | undefined {
|
|
201
|
-
if (panels.length > 0) {
|
|
202
|
-
return panels.find((p) => !(disabled || p.disabled))?.key;
|
|
203
|
-
}
|
|
204
|
-
return focusableHeaders()[0]?.dataset.collapseKey;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function focusHeaderByKey(key: string): void {
|
|
208
|
-
rootEl
|
|
209
|
-
?.querySelector<HTMLElement>(
|
|
210
|
-
`.cd-collapse__header[data-collapse-key="${CSS.escape(key)}"]`,
|
|
211
|
-
)
|
|
212
|
-
?.focus();
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Header keydown:↑↓ roving(纯函数 nextRovingIndex 派生,跳过禁用项)、Home/End 跳首尾。
|
|
216
|
-
// Enter/Space 交给原生 <button>(向后兼容 toggle)。
|
|
217
|
-
function onHeaderKeydown(e: KeyboardEvent, key: string): void {
|
|
218
|
-
const intent = rovingKeyFromEvent(e.key);
|
|
219
|
-
if (!intent) return;
|
|
220
|
-
const headers = focusableHeaders();
|
|
221
|
-
if (headers.length === 0) return;
|
|
222
|
-
e.preventDefault();
|
|
223
|
-
const keys = headers.map((h) => h.dataset.collapseKey ?? '');
|
|
224
|
-
const cur = keys.indexOf(key);
|
|
225
|
-
const next = nextRovingIndex(cur, keys.length, intent, false);
|
|
226
|
-
const nextKey = keys[next];
|
|
227
|
-
if (nextKey) {
|
|
228
|
-
focusedKey = nextKey;
|
|
229
|
-
focusHeaderByKey(nextKey);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function onHeaderFocus(key: string): void {
|
|
234
|
-
focusedKey = key;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// 经 context 暴露给子 Panel:全部 getter / 纯派生函数,红线 #1#2 落实在父级。
|
|
238
|
-
setCollapseContext({
|
|
239
|
-
isActive,
|
|
240
|
-
shouldRender,
|
|
241
|
-
toggle,
|
|
242
|
-
headerClick,
|
|
243
|
-
getDisabled: () => disabled,
|
|
244
|
-
getSize: () => size,
|
|
245
|
-
getIconPosition: () => expandIconPosition,
|
|
246
|
-
getIdBase: () => idBase,
|
|
247
|
-
getHeadingLevel: () => headingLevel,
|
|
248
|
-
headerTabindex,
|
|
249
|
-
onHeaderKeydown,
|
|
250
|
-
onHeaderFocus,
|
|
251
|
-
getExpandIcon: () => expandIcon,
|
|
252
|
-
});
|
|
253
|
-
</script>
|
|
254
|
-
|
|
255
|
-
<div class={cls} bind:this={rootEl}>
|
|
256
|
-
{#if useDeclarative}
|
|
257
|
-
{@render (children as Snippet)?.()}
|
|
258
|
-
{:else}
|
|
259
|
-
{#each panels as panel (panel.key)}
|
|
260
|
-
{@const active = isActive(panel.key)}
|
|
261
|
-
{@const itemDisabled = disabled || panel.disabled}
|
|
262
|
-
{@const headerId = `${idBase}-h-${panel.key}`}
|
|
263
|
-
{@const regionId = `${idBase}-r-${panel.key}`}
|
|
264
|
-
<div class="cd-collapse__item" class:cd-collapse__item--active={active}>
|
|
265
|
-
<!-- APG Accordion:Header 触发器外层 role=heading + aria-level。 -->
|
|
266
|
-
<span role="heading" aria-level={headingLevel} class="cd-collapse__heading">
|
|
267
|
-
<button
|
|
268
|
-
type="button"
|
|
269
|
-
id={headerId}
|
|
270
|
-
class="cd-collapse__header"
|
|
271
|
-
data-collapse-key={panel.key}
|
|
272
|
-
aria-expanded={active}
|
|
273
|
-
aria-controls={regionId}
|
|
274
|
-
aria-disabled={itemDisabled || undefined}
|
|
275
|
-
disabled={itemDisabled || undefined}
|
|
276
|
-
tabindex={headerTabindex(panel.key, panel.disabled)}
|
|
277
|
-
onclick={(e) => headerClick(e, panel.key, panel.disabled)}
|
|
278
|
-
onkeydown={(e) => onHeaderKeydown(e, panel.key)}
|
|
279
|
-
onfocus={() => onHeaderFocus(panel.key)}
|
|
280
|
-
>
|
|
281
|
-
{#if expandIcon}
|
|
282
|
-
<span class="cd-collapse__arrow" class:cd-collapse__arrow--open={active} aria-hidden="true">
|
|
283
|
-
{@render expandIcon({ isExpanded: active })}
|
|
284
|
-
</span>
|
|
285
|
-
{:else}
|
|
286
|
-
<span class="cd-collapse__arrow" class:cd-collapse__arrow--open={active} aria-hidden="true">
|
|
287
|
-
<svg viewBox="0 0 16 16" width="12" height="12" focusable="false">
|
|
288
|
-
<path fill="currentColor" d="M6 4l4 4-4 4V4Z" />
|
|
289
|
-
</svg>
|
|
290
|
-
</span>
|
|
291
|
-
{/if}
|
|
292
|
-
<span class="cd-collapse__title">{panel.header}</span>
|
|
293
|
-
</button>
|
|
294
|
-
</span>
|
|
295
|
-
<div
|
|
296
|
-
id={regionId}
|
|
297
|
-
class="cd-collapse__region"
|
|
298
|
-
role="region"
|
|
299
|
-
aria-labelledby={headerId}
|
|
300
|
-
hidden={!active}
|
|
301
|
-
>
|
|
302
|
-
<div class="cd-collapse__region-inner">
|
|
303
|
-
<div class="cd-collapse__content">
|
|
304
|
-
{#if shouldRender(panel.key)}
|
|
305
|
-
{@render (children as Snippet<[{ key: string }]>)?.({ key: panel.key })}
|
|
306
|
-
{/if}
|
|
307
|
-
</div>
|
|
308
|
-
</div>
|
|
309
|
-
</div>
|
|
310
|
-
</div>
|
|
311
|
-
{/each}
|
|
312
|
-
{/if}
|
|
313
|
-
</div>
|
|
314
|
-
|
|
315
|
-
<style>
|
|
316
|
-
/*
|
|
317
|
-
.cd-collapse 根(<div>)保留组件作用域哈希;其下各 .cd-collapse__* 后代用 :global 包裹,
|
|
318
|
-
使同一套结构样式既覆盖本组件 panels 渲染的 .cd-collapse__item,也覆盖 <Collapse.Panel>
|
|
319
|
-
在子组件作用域内渲染的相同结构(参考 Timeline)。
|
|
320
|
-
*/
|
|
321
|
-
.cd-collapse {
|
|
322
|
-
inline-size: 100%;
|
|
323
|
-
}
|
|
324
|
-
.cd-collapse--bordered {
|
|
325
|
-
border: 1px solid var(--cd-collapse-border);
|
|
326
|
-
border-radius: var(--cd-radius-1);
|
|
327
|
-
}
|
|
328
|
-
.cd-collapse :global(.cd-collapse__item + .cd-collapse__item) {
|
|
329
|
-
border-block-start: 1px solid var(--cd-collapse-border);
|
|
330
|
-
}
|
|
331
|
-
/* role=heading 包裹元素:消除 inline 默认行为,让内部 button 占满宽度。 */
|
|
332
|
-
.cd-collapse :global(.cd-collapse__heading) {
|
|
333
|
-
display: block;
|
|
334
|
-
margin: 0;
|
|
335
|
-
font: inherit;
|
|
336
|
-
}
|
|
337
|
-
.cd-collapse :global(.cd-collapse__header) {
|
|
338
|
-
display: flex;
|
|
339
|
-
align-items: center;
|
|
340
|
-
gap: var(--cd-spacing-2);
|
|
341
|
-
inline-size: 100%;
|
|
342
|
-
padding: var(--cd-collapse-header-padding);
|
|
343
|
-
border: none;
|
|
344
|
-
background: transparent;
|
|
345
|
-
color: var(--cd-collapse-header-color);
|
|
346
|
-
font: inherit;
|
|
347
|
-
text-align: start;
|
|
348
|
-
cursor: pointer;
|
|
349
|
-
}
|
|
350
|
-
.cd-collapse :global(.cd-collapse__header:hover:not(:disabled)) {
|
|
351
|
-
background: var(--cd-collapse-header-bg-hover);
|
|
352
|
-
}
|
|
353
|
-
.cd-collapse :global(.cd-collapse__header:focus-visible) {
|
|
354
|
-
outline: none;
|
|
355
|
-
box-shadow: var(--cd-focus-ring);
|
|
356
|
-
}
|
|
357
|
-
.cd-collapse :global(.cd-collapse__header:disabled) {
|
|
358
|
-
color: var(--cd-color-text-3);
|
|
359
|
-
cursor: not-allowed;
|
|
360
|
-
}
|
|
361
|
-
.cd-collapse--icon-right :global(.cd-collapse__header) {
|
|
362
|
-
flex-direction: row-reverse;
|
|
363
|
-
}
|
|
364
|
-
.cd-collapse--icon-right :global(.cd-collapse__title) {
|
|
365
|
-
flex: 1 1 auto;
|
|
366
|
-
}
|
|
367
|
-
.cd-collapse :global(.cd-collapse__arrow) {
|
|
368
|
-
display: inline-flex;
|
|
369
|
-
align-items: center;
|
|
370
|
-
justify-content: center;
|
|
371
|
-
flex: 0 0 auto;
|
|
372
|
-
color: var(--cd-collapse-arrow-color);
|
|
373
|
-
transition: transform var(--cd-collapse-motion-duration) var(--cd-motion-ease-standard);
|
|
374
|
-
}
|
|
375
|
-
.cd-collapse :global(.cd-collapse__arrow--open) {
|
|
376
|
-
transform: rotate(90deg);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/* 红线 #3: CSS grid-template-rows 0fr↔1fr 过渡,不 JS 测高 */
|
|
380
|
-
.cd-collapse :global(.cd-collapse__region) {
|
|
381
|
-
display: grid;
|
|
382
|
-
grid-template-rows: 1fr;
|
|
383
|
-
}
|
|
384
|
-
.cd-collapse :global(.cd-collapse__region[hidden]) {
|
|
385
|
-
display: grid;
|
|
386
|
-
grid-template-rows: 0fr;
|
|
387
|
-
}
|
|
388
|
-
.cd-collapse--motion :global(.cd-collapse__region) {
|
|
389
|
-
transition: grid-template-rows var(--cd-collapse-motion-duration) var(--cd-motion-ease-standard);
|
|
390
|
-
}
|
|
391
|
-
.cd-collapse :global(.cd-collapse__region-inner) {
|
|
392
|
-
overflow: hidden;
|
|
393
|
-
min-block-size: 0;
|
|
394
|
-
}
|
|
395
|
-
.cd-collapse :global(.cd-collapse__content) {
|
|
396
|
-
padding: var(--cd-collapse-content-padding);
|
|
397
|
-
color: var(--cd-collapse-content-color);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
@media (prefers-reduced-motion: reduce) {
|
|
401
|
-
.cd-collapse--motion :global(.cd-collapse__region),
|
|
402
|
-
.cd-collapse :global(.cd-collapse__arrow) {
|
|
403
|
-
transition: none;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
</style>
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
仅供 Collapse.a11y.test.ts 使用的测试夹具:数据驱动 panels + children Snippet 渲染面板内容,
|
|
3
|
-
使 header button 的 aria-controls 指向真实存在的 region(axe aria-valid-attr-value 通过)。
|
|
4
|
-
-->
|
|
5
|
-
<script lang="ts">
|
|
6
|
-
import { Collapse } from './index.js';
|
|
7
|
-
import type { CollapsePanel } from './types.js';
|
|
8
|
-
|
|
9
|
-
interface Props {
|
|
10
|
-
accordion?: boolean;
|
|
11
|
-
disabled?: boolean;
|
|
12
|
-
defaultActiveKey?: string | string[];
|
|
13
|
-
}
|
|
14
|
-
let { accordion = false, disabled = false, defaultActiveKey = [] }: Props = $props();
|
|
15
|
-
|
|
16
|
-
const panels: CollapsePanel[] = [
|
|
17
|
-
{ key: 'a', header: 'Section A' },
|
|
18
|
-
{ key: 'b', header: 'Section B' },
|
|
19
|
-
{ key: 'c', header: 'Section C', disabled: true },
|
|
20
|
-
];
|
|
21
|
-
</script>
|
|
22
|
-
|
|
23
|
-
<Collapse {panels} {accordion} {disabled} {defaultActiveKey}>
|
|
24
|
-
{#snippet children({ key })}
|
|
25
|
-
<p>Content for {key}</p>
|
|
26
|
-
{/snippet}
|
|
27
|
-
</Collapse>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
仅供 Collapse.kbd.test.ts(browser project)使用的键盘 e2e 夹具。
|
|
3
|
-
数据驱动 panels;Header 组为单一 Tab 停靠点(roving,真实焦点)。
|
|
4
|
-
前后各放按钮验证 Tab 进入只停靠单个 Header、Tab 出去落到 after。
|
|
5
|
-
-->
|
|
6
|
-
<script lang="ts">
|
|
7
|
-
import { LocaleProvider } from '../locale-provider/index.js';
|
|
8
|
-
import Collapse from './Collapse.svelte';
|
|
9
|
-
|
|
10
|
-
const panels = [
|
|
11
|
-
{ key: 'p1', header: 'Panel One' },
|
|
12
|
-
{ key: 'p2', header: 'Panel Two' },
|
|
13
|
-
{ key: 'p3', header: 'Panel Three' },
|
|
14
|
-
];
|
|
15
|
-
</script>
|
|
16
|
-
|
|
17
|
-
<LocaleProvider locale="en_US">
|
|
18
|
-
<button type="button" data-testid="before">before</button>
|
|
19
|
-
<Collapse {panels}>
|
|
20
|
-
{#snippet children({ key }: { key: string })}
|
|
21
|
-
<p>content {key}</p>
|
|
22
|
-
{/snippet}
|
|
23
|
-
</Collapse>
|
|
24
|
-
<button type="button" data-testid="after">after</button>
|
|
25
|
-
</LocaleProvider>
|