zabi-components 8.0.0 → 9.0.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/CHANGELOG.md +2935 -0
- package/README.md +243 -10
- package/THEME.md +162 -332
- package/THEMING.md +1419 -259
- package/dist/atoms/ActionPanel.svelte +15 -5
- package/dist/atoms/Avatar.svelte +120 -0
- package/dist/atoms/Avatar.svelte.d.ts +46 -0
- package/dist/atoms/Badge.svelte +71 -13
- package/dist/atoms/Badge.svelte.d.ts +8 -2
- package/dist/atoms/Block.svelte +74 -0
- package/dist/atoms/Block.svelte.d.ts +29 -0
- package/dist/atoms/Button.svelte +217 -30
- package/dist/atoms/Button.svelte.d.ts +33 -4
- package/dist/atoms/Card.svelte +182 -26
- package/dist/atoms/Card.svelte.d.ts +55 -3
- package/dist/atoms/CardHeader.svelte +16 -4
- package/dist/atoms/Checkbox.svelte +81 -21
- package/dist/atoms/Checkbox.svelte.d.ts +31 -2
- package/dist/atoms/Chip.svelte +351 -0
- package/dist/atoms/Chip.svelte.d.ts +57 -0
- package/dist/atoms/CodeBlock.svelte +20 -2
- package/dist/atoms/CodeBlock.svelte.d.ts +4 -0
- package/dist/atoms/CodeField.svelte +385 -0
- package/dist/atoms/CodeField.svelte.d.ts +61 -0
- package/dist/atoms/ColorPicker.svelte +260 -49
- package/dist/atoms/ColorPicker.svelte.d.ts +3 -0
- package/dist/atoms/Container.svelte +16 -8
- package/dist/atoms/DateField.svelte +145 -0
- package/dist/atoms/DateField.svelte.d.ts +81 -0
- package/dist/atoms/FieldMessages.svelte +69 -0
- package/dist/atoms/FieldMessages.svelte.d.ts +23 -0
- package/dist/atoms/FloatingActionButton.svelte +176 -0
- package/dist/atoms/FloatingActionButton.svelte.d.ts +51 -0
- package/dist/atoms/Heading.svelte +63 -5
- package/dist/atoms/Heading.svelte.d.ts +14 -0
- package/dist/atoms/IconButton.svelte +294 -26
- package/dist/atoms/IconButton.svelte.d.ts +62 -4
- package/dist/atoms/Input.svelte +259 -53
- package/dist/atoms/Input.svelte.d.ts +33 -2
- package/dist/atoms/List.svelte +5 -1
- package/dist/atoms/ListItem.svelte +70 -13
- package/dist/atoms/ListItem.svelte.d.ts +11 -0
- package/dist/atoms/PickerField.svelte +239 -0
- package/dist/atoms/PickerField.svelte.d.ts +67 -0
- package/dist/atoms/Progress.svelte +99 -19
- package/dist/atoms/Progress.svelte.d.ts +15 -1
- package/dist/atoms/Radio.svelte +51 -3
- package/dist/atoms/Radio.svelte.d.ts +30 -2
- package/dist/atoms/Rating.svelte +620 -0
- package/dist/atoms/Rating.svelte.d.ts +77 -0
- package/dist/atoms/Select.svelte +438 -98
- package/dist/atoms/Select.svelte.d.ts +61 -3
- package/dist/atoms/SelectionControl.svelte +193 -23
- package/dist/atoms/SelectionControl.svelte.d.ts +29 -3
- package/dist/atoms/Skeleton.svelte +114 -18
- package/dist/atoms/Skeleton.svelte.d.ts +30 -3
- package/dist/atoms/SkeletonGroup.svelte +43 -0
- package/dist/atoms/SkeletonGroup.svelte.d.ts +20 -0
- package/dist/atoms/Slider.svelte +344 -0
- package/dist/atoms/Slider.svelte.d.ts +40 -0
- package/dist/atoms/Sparkline.svelte +109 -0
- package/dist/atoms/Sparkline.svelte.d.ts +27 -0
- package/dist/atoms/SpeechBubble.svelte +187 -0
- package/dist/atoms/SpeechBubble.svelte.d.ts +33 -0
- package/dist/atoms/Spinner.svelte +57 -0
- package/dist/atoms/Spinner.svelte.d.ts +19 -0
- package/dist/atoms/Stat.svelte +72 -0
- package/dist/atoms/Stat.svelte.d.ts +19 -0
- package/dist/atoms/Table.svelte +151 -6
- package/dist/atoms/Table.svelte.d.ts +15 -3
- package/dist/atoms/TemporalField.svelte +472 -0
- package/dist/atoms/TemporalField.svelte.d.ts +48 -0
- package/dist/atoms/Text.svelte +23 -11
- package/dist/atoms/Text.svelte.d.ts +6 -3
- package/dist/atoms/Textarea.svelte +150 -44
- package/dist/atoms/Textarea.svelte.d.ts +35 -2
- package/dist/atoms/ThemeToggle.svelte +223 -44
- package/dist/atoms/ThemeToggle.svelte.d.ts +26 -3
- package/dist/atoms/TimeColumn.svelte +150 -0
- package/dist/atoms/TimeColumn.svelte.d.ts +25 -0
- package/dist/atoms/TimeField.svelte +151 -0
- package/dist/atoms/TimeField.svelte.d.ts +85 -0
- package/dist/atoms/Toast.svelte +22 -8
- package/dist/atoms/Toast.svelte.d.ts +2 -0
- package/dist/atoms/Toggle.svelte +98 -14
- package/dist/atoms/Toggle.svelte.d.ts +26 -2
- package/dist/atoms/Tooltip.svelte +528 -24
- package/dist/atoms/Tooltip.svelte.d.ts +18 -0
- package/dist/atoms/ZabiStringsProvider.svelte +45 -0
- package/dist/atoms/ZabiStringsProvider.svelte.d.ts +27 -0
- package/dist/atoms/index.d.ts +38 -0
- package/dist/atoms/index.js +29 -0
- package/dist/atoms/selection-control.styles.d.ts +47 -5
- package/dist/atoms/selection-control.styles.js +52 -10
- package/dist/components/atoms/index.d.ts +38 -0
- package/dist/components/atoms/index.d.ts.map +1 -1
- package/dist/components/atoms/selection-control.styles.d.ts +47 -5
- package/dist/components/atoms/selection-control.styles.d.ts.map +1 -1
- package/dist/components/index.d.ts +104 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/map.d.ts +11 -0
- package/dist/components/map.d.ts.map +1 -0
- package/dist/components/molecules/index.d.ts +51 -0
- package/dist/components/molecules/index.d.ts.map +1 -1
- package/dist/components/molecules/toast-store.d.ts +83 -7
- package/dist/components/molecules/toast-store.d.ts.map +1 -1
- package/dist/components/organisms/index.d.ts +10 -0
- package/dist/components/organisms/index.d.ts.map +1 -1
- package/dist/components/types/variants.d.ts +24 -1
- package/dist/components/types/variants.d.ts.map +1 -1
- package/dist/components/util/app-shell.d.ts +79 -0
- package/dist/components/util/app-shell.d.ts.map +1 -0
- package/dist/components/util/avatar.d.ts +39 -0
- package/dist/components/util/avatar.d.ts.map +1 -0
- package/dist/components/util/bottom-sheet.d.ts +30 -0
- package/dist/components/util/bottom-sheet.d.ts.map +1 -0
- package/dist/components/util/bottom-tab-bar.d.ts +41 -0
- package/dist/components/util/bottom-tab-bar.d.ts.map +1 -0
- package/dist/components/util/calendar.d.ts +56 -0
- package/dist/components/util/calendar.d.ts.map +1 -0
- package/dist/components/util/chart.d.ts +140 -0
- package/dist/components/util/chart.d.ts.map +1 -0
- package/dist/components/util/chip.d.ts +66 -0
- package/dist/components/util/chip.d.ts.map +1 -0
- package/dist/components/util/cn.d.ts.map +1 -1
- package/dist/components/util/code-field.d.ts +63 -0
- package/dist/components/util/code-field.d.ts.map +1 -0
- package/dist/components/util/collapsible.d.ts +64 -0
- package/dist/components/util/collapsible.d.ts.map +1 -0
- package/dist/components/util/confirm-dialog.d.ts +12 -0
- package/dist/components/util/confirm-dialog.d.ts.map +1 -0
- package/dist/components/util/date.d.ts +96 -0
- package/dist/components/util/date.d.ts.map +1 -0
- package/dist/components/util/display-voice.d.ts +10 -0
- package/dist/components/util/display-voice.d.ts.map +1 -0
- package/dist/components/util/drawer.d.ts +13 -0
- package/dist/components/util/drawer.d.ts.map +1 -0
- package/dist/components/util/dropdown.d.ts +47 -0
- package/dist/components/util/dropdown.d.ts.map +1 -0
- package/dist/components/util/field-control.d.ts +30 -0
- package/dist/components/util/field-control.d.ts.map +1 -0
- package/dist/components/util/field.d.ts +45 -0
- package/dist/components/util/field.d.ts.map +1 -0
- package/dist/components/util/fit-in-viewport.d.ts +201 -0
- package/dist/components/util/fit-in-viewport.d.ts.map +1 -0
- package/dist/components/util/focus-utils.d.ts +77 -2
- package/dist/components/util/focus-utils.d.ts.map +1 -1
- package/dist/components/util/hydration.d.ts +45 -0
- package/dist/components/util/hydration.d.ts.map +1 -0
- package/dist/components/util/keyboard-inset.d.ts +18 -0
- package/dist/components/util/keyboard-inset.d.ts.map +1 -0
- package/dist/components/util/map-view.d.ts +144 -0
- package/dist/components/util/map-view.d.ts.map +1 -0
- package/dist/components/util/media-grid.d.ts +51 -0
- package/dist/components/util/media-grid.d.ts.map +1 -0
- package/dist/components/util/media.d.ts +6 -0
- package/dist/components/util/media.d.ts.map +1 -0
- package/dist/components/util/overlay-chrome.d.ts +53 -0
- package/dist/components/util/overlay-chrome.d.ts.map +1 -0
- package/dist/components/util/overlay.d.ts +72 -0
- package/dist/components/util/overlay.d.ts.map +1 -0
- package/dist/components/util/photo.d.ts +234 -0
- package/dist/components/util/photo.d.ts.map +1 -0
- package/dist/components/util/portal.d.ts +23 -0
- package/dist/components/util/portal.d.ts.map +1 -0
- package/dist/components/util/progress.d.ts +19 -0
- package/dist/components/util/progress.d.ts.map +1 -0
- package/dist/components/util/pull-to-refresh.d.ts +27 -0
- package/dist/components/util/pull-to-refresh.d.ts.map +1 -0
- package/dist/components/util/radio-keys.d.ts +25 -0
- package/dist/components/util/radio-keys.d.ts.map +1 -0
- package/dist/components/util/rating.d.ts +23 -0
- package/dist/components/util/rating.d.ts.map +1 -0
- package/dist/components/util/ready-made-strings.d.ts +77 -0
- package/dist/components/util/ready-made-strings.d.ts.map +1 -0
- package/dist/components/util/scroll-edge.d.ts +33 -0
- package/dist/components/util/scroll-edge.d.ts.map +1 -0
- package/dist/components/util/scroll-padding.d.ts +20 -0
- package/dist/components/util/scroll-padding.d.ts.map +1 -0
- package/dist/components/util/segmented-control.d.ts +16 -0
- package/dist/components/util/segmented-control.d.ts.map +1 -0
- package/dist/components/util/select.d.ts +41 -0
- package/dist/components/util/select.d.ts.map +1 -0
- package/dist/components/util/sheet-drag.d.ts +84 -0
- package/dist/components/util/sheet-drag.d.ts.map +1 -0
- package/dist/components/util/sidebar.d.ts +63 -0
- package/dist/components/util/sidebar.d.ts.map +1 -0
- package/dist/components/util/skeleton.d.ts +15 -0
- package/dist/components/util/skeleton.d.ts.map +1 -0
- package/dist/components/util/sliding-indicator.d.ts +25 -0
- package/dist/components/util/sliding-indicator.d.ts.map +1 -0
- package/dist/components/util/sortable-list.d.ts +65 -0
- package/dist/components/util/sortable-list.d.ts.map +1 -0
- package/dist/components/util/stepper.d.ts +40 -0
- package/dist/components/util/stepper.d.ts.map +1 -0
- package/dist/components/util/swipeable-list-item.d.ts +36 -0
- package/dist/components/util/swipeable-list-item.d.ts.map +1 -0
- package/dist/components/util/temporal-field.d.ts +89 -0
- package/dist/components/util/temporal-field.d.ts.map +1 -0
- package/dist/components/util/theme-mode.d.ts +80 -0
- package/dist/components/util/theme-mode.d.ts.map +1 -0
- package/dist/components/util/toaster.d.ts +133 -0
- package/dist/components/util/toaster.d.ts.map +1 -0
- package/dist/components/util/tone-surface.d.ts +34 -0
- package/dist/components/util/tone-surface.d.ts.map +1 -0
- package/dist/components/util/tooltip.d.ts +10 -0
- package/dist/components/util/tooltip.d.ts.map +1 -0
- package/dist/components/util/top-navbar.d.ts +35 -0
- package/dist/components/util/top-navbar.d.ts.map +1 -0
- package/dist/components/util/touch-target.d.ts +31 -0
- package/dist/components/util/touch-target.d.ts.map +1 -0
- package/dist/components/util/zabi-strings.d.ts +142 -0
- package/dist/components/util/zabi-strings.d.ts.map +1 -0
- package/dist/create-theme/cli.js +173 -0
- package/dist/create-theme/index.d.ts +190 -0
- package/dist/create-theme/index.js +1034 -0
- package/dist/create-theme/lib/ramp-math.js +128 -0
- package/dist/create-theme/lib/resolve.js +238 -0
- package/dist/create-theme/theme-data.js +2644 -0
- package/dist/index.d.ts +104 -2
- package/dist/index.js +75 -2
- package/dist/map.d.ts +10 -0
- package/dist/map.js +9 -0
- package/dist/molecules/Alert.svelte +63 -16
- package/dist/molecules/Alert.svelte.d.ts +14 -1
- package/dist/molecules/AppBar.svelte +674 -0
- package/dist/molecules/AppBar.svelte.d.ts +131 -0
- package/dist/molecules/AvatarGroup.svelte +116 -0
- package/dist/molecules/AvatarGroup.svelte.d.ts +40 -0
- package/dist/molecules/BarChart.svelte +381 -0
- package/dist/molecules/BarChart.svelte.d.ts +45 -0
- package/dist/molecules/BottomSheet.svelte +608 -0
- package/dist/molecules/BottomSheet.svelte.d.ts +109 -0
- package/dist/molecules/BottomTabBar.svelte +403 -0
- package/dist/molecules/BottomTabBar.svelte.d.ts +98 -0
- package/dist/molecules/Calendar.svelte +597 -0
- package/dist/molecules/Calendar.svelte.d.ts +72 -0
- package/dist/molecules/ChipGroup.svelte +325 -0
- package/dist/molecules/ChipGroup.svelte.d.ts +41 -0
- package/dist/molecules/Collapsible.svelte +347 -0
- package/dist/molecules/Collapsible.svelte.d.ts +61 -0
- package/dist/molecules/CollapsibleGroup.svelte +136 -0
- package/dist/molecules/CollapsibleGroup.svelte.d.ts +14 -0
- package/dist/molecules/ComponentDemo.svelte +16 -4
- package/dist/molecules/ComponentDemo.svelte.d.ts +3 -0
- package/dist/molecules/ConfirmDialog.svelte +257 -0
- package/dist/molecules/ConfirmDialog.svelte.d.ts +58 -0
- package/dist/molecules/ContactForm.svelte +34 -17
- package/dist/molecules/ContactForm.svelte.d.ts +8 -0
- package/dist/molecules/Drawer.svelte +415 -0
- package/dist/molecules/Drawer.svelte.d.ts +55 -0
- package/dist/molecules/Dropdown.svelte +517 -48
- package/dist/molecules/Dropdown.svelte.d.ts +47 -6
- package/dist/molecules/DropdownItem.svelte +122 -0
- package/dist/molecules/DropdownItem.svelte.d.ts +28 -0
- package/dist/molecules/EmptyState.svelte +55 -10
- package/dist/molecules/EmptyState.svelte.d.ts +8 -0
- package/dist/molecules/FormField.svelte +9 -1
- package/dist/molecules/FormField.svelte.d.ts +2 -0
- package/dist/molecules/Header.svelte +1 -1
- package/dist/molecules/ImageUpload.svelte +492 -69
- package/dist/molecules/ImageUpload.svelte.d.ts +82 -2
- package/dist/molecules/LineChart.svelte +459 -0
- package/dist/molecules/LineChart.svelte.d.ts +53 -0
- package/dist/molecules/MapView.svelte +565 -0
- package/dist/molecules/MapView.svelte.d.ts +88 -0
- package/dist/molecules/MediaGrid.svelte +527 -0
- package/dist/molecules/MediaGrid.svelte.d.ts +77 -0
- package/dist/molecules/Modal.svelte +293 -72
- package/dist/molecules/Modal.svelte.d.ts +51 -2
- package/dist/molecules/NavigationMenuContent.svelte +58 -1
- package/dist/molecules/NavigationMenuItem.svelte +0 -1
- package/dist/molecules/NavigationMenuLink.svelte +1 -1
- package/dist/molecules/NavigationMenuList.svelte +10 -3
- package/dist/molecules/NavigationMenuTrigger.svelte +2 -2
- package/dist/molecules/Page.svelte +32 -2
- package/dist/molecules/Page.svelte.d.ts +11 -0
- package/dist/molecules/PhotoGrid.svelte +523 -0
- package/dist/molecules/PhotoGrid.svelte.d.ts +73 -0
- package/dist/molecules/PhotoViewer.svelte +1213 -0
- package/dist/molecules/PhotoViewer.svelte.d.ts +74 -0
- package/dist/molecules/PieChart.svelte +421 -0
- package/dist/molecules/PieChart.svelte.d.ts +51 -0
- package/dist/molecules/PropsTable.svelte +22 -10
- package/dist/molecules/PropsTable.svelte.d.ts +3 -0
- package/dist/molecules/PullToRefresh.svelte +263 -0
- package/dist/molecules/PullToRefresh.svelte.d.ts +52 -0
- package/dist/molecules/RadioGroup.svelte +72 -18
- package/dist/molecules/RadioGroup.svelte.d.ts +19 -3
- package/dist/molecules/Section.svelte +1 -1
- package/dist/molecules/SegmentedControl.svelte +456 -0
- package/dist/molecules/SegmentedControl.svelte.d.ts +40 -0
- package/dist/molecules/SidebarBrandHeader.svelte +11 -1
- package/dist/molecules/SidebarBrandHeader.svelte.d.ts +3 -0
- package/dist/molecules/SidebarFooter.svelte +30 -7
- package/dist/molecules/SidebarFooter.svelte.d.ts +3 -0
- package/dist/molecules/SidebarNavSection.svelte +1 -1
- package/dist/molecules/SlideUp.svelte +220 -61
- package/dist/molecules/SlideUp.svelte.d.ts +26 -0
- package/dist/molecules/SortableList.svelte +633 -0
- package/dist/molecules/SortableList.svelte.d.ts +69 -0
- package/dist/molecules/Stepper.svelte +562 -0
- package/dist/molecules/Stepper.svelte.d.ts +39 -0
- package/dist/molecules/StickyActionBar.svelte +250 -0
- package/dist/molecules/StickyActionBar.svelte.d.ts +78 -0
- package/dist/molecules/SwipeableListItem.svelte +334 -0
- package/dist/molecules/SwipeableListItem.svelte.d.ts +54 -0
- package/dist/molecules/Tabs.svelte +310 -9
- package/dist/molecules/Tabs.svelte.d.ts +7 -0
- package/dist/molecules/Toaster.svelte +514 -5
- package/dist/molecules/Toaster.svelte.d.ts +153 -2
- package/dist/molecules/ToasterToast.svelte +495 -77
- package/dist/molecules/ToasterToast.svelte.d.ts +15 -0
- package/dist/molecules/UnsavedChangesBar.svelte +223 -0
- package/dist/molecules/UnsavedChangesBar.svelte.d.ts +43 -0
- package/dist/molecules/index.d.ts +51 -0
- package/dist/molecules/index.js +31 -0
- package/dist/molecules/toast-store.d.ts +83 -7
- package/dist/molecules/toast-store.js +25 -1
- package/dist/organisms/AppNavigation.svelte +440 -0
- package/dist/organisms/AppNavigation.svelte.d.ts +72 -0
- package/dist/organisms/AppShell.svelte +696 -0
- package/dist/organisms/AppShell.svelte.d.ts +157 -0
- package/dist/organisms/AppShellHeaderPart.svelte +163 -0
- package/dist/organisms/AppShellHeaderPart.svelte.d.ts +57 -0
- package/dist/organisms/SidebarAccountPanel.svelte +107 -12
- package/dist/organisms/SidebarAccountPanel.svelte.d.ts +19 -0
- package/dist/organisms/SidebarNavigation.svelte +111 -43
- package/dist/organisms/SidebarNavigation.svelte.d.ts +29 -1
- package/dist/organisms/SidebarPanel.svelte +34 -17
- package/dist/organisms/SidebarPanel.svelte.d.ts +1 -0
- package/dist/organisms/SidebarShell.svelte +164 -14
- package/dist/organisms/SidebarShell.svelte.d.ts +56 -2
- package/dist/organisms/TopNavbar.svelte +353 -39
- package/dist/organisms/TopNavbar.svelte.d.ts +47 -0
- package/dist/organisms/TopNavbarSheetContent.svelte +145 -0
- package/dist/organisms/TopNavbarSheetContent.svelte.d.ts +24 -0
- package/dist/organisms/index.d.ts +10 -0
- package/dist/organisms/index.js +7 -0
- package/dist/types/components.d.ts +21 -1
- package/dist/types/components.d.ts.map +1 -1
- package/dist/types/index.d.ts +1093 -26
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/variants.ts +28 -1
- package/dist/util/app-shell.d.ts +78 -0
- package/dist/util/app-shell.js +97 -0
- package/dist/util/avatar.d.ts +38 -0
- package/dist/util/avatar.js +52 -0
- package/dist/util/bottom-sheet.d.ts +29 -0
- package/dist/util/bottom-sheet.js +43 -0
- package/dist/util/bottom-tab-bar.d.ts +40 -0
- package/dist/util/bottom-tab-bar.js +54 -0
- package/dist/util/calendar.d.ts +55 -0
- package/dist/util/calendar.js +74 -0
- package/dist/util/chart.d.ts +139 -0
- package/dist/util/chart.js +305 -0
- package/dist/util/chip.d.ts +65 -0
- package/dist/util/chip.js +58 -0
- package/dist/util/cn.js +28 -2
- package/dist/util/code-field.d.ts +62 -0
- package/dist/util/code-field.js +112 -0
- package/dist/util/collapsible.d.ts +63 -0
- package/dist/util/collapsible.js +23 -0
- package/dist/util/confirm-dialog.d.ts +11 -0
- package/dist/util/confirm-dialog.js +2 -0
- package/dist/util/date.d.ts +95 -0
- package/dist/util/date.js +237 -0
- package/dist/util/display-voice.d.ts +9 -0
- package/dist/util/display-voice.js +9 -0
- package/dist/util/drawer.d.ts +12 -0
- package/dist/util/drawer.js +7 -0
- package/dist/util/dropdown.d.ts +46 -0
- package/dist/util/dropdown.js +21 -0
- package/dist/util/field-control.d.ts +29 -0
- package/dist/util/field-control.js +32 -0
- package/dist/util/field.d.ts +44 -0
- package/dist/util/field.js +38 -0
- package/dist/util/fit-in-viewport.d.ts +200 -0
- package/dist/util/fit-in-viewport.js +399 -0
- package/dist/util/focus-utils.d.ts +77 -2
- package/dist/util/focus-utils.js +186 -9
- package/dist/util/hydration.d.ts +44 -0
- package/dist/util/hydration.js +58 -0
- package/dist/util/keyboard-inset.d.ts +17 -0
- package/dist/util/keyboard-inset.js +53 -0
- package/dist/util/map-view.d.ts +143 -0
- package/dist/util/map-view.js +121 -0
- package/dist/util/media-grid.d.ts +50 -0
- package/dist/util/media-grid.js +81 -0
- package/dist/util/media.d.ts +5 -0
- package/dist/util/media.js +10 -0
- package/dist/util/overlay-chrome.d.ts +52 -0
- package/dist/util/overlay-chrome.js +56 -0
- package/dist/util/overlay.d.ts +71 -0
- package/dist/util/overlay.js +240 -0
- package/dist/util/photo.d.ts +233 -0
- package/dist/util/photo.js +209 -0
- package/dist/util/portal.d.ts +22 -0
- package/dist/util/portal.js +50 -0
- package/dist/util/progress.d.ts +18 -0
- package/dist/util/progress.js +17 -0
- package/dist/util/pull-to-refresh.d.ts +26 -0
- package/dist/util/pull-to-refresh.js +30 -0
- package/dist/util/radio-keys.d.ts +24 -0
- package/dist/util/radio-keys.js +49 -0
- package/dist/util/rating.d.ts +22 -0
- package/dist/util/rating.js +26 -0
- package/dist/util/ready-made-strings.d.ts +76 -0
- package/dist/util/ready-made-strings.js +67 -0
- package/dist/util/scroll-edge.d.ts +32 -0
- package/dist/util/scroll-edge.js +87 -0
- package/dist/util/scroll-padding.d.ts +19 -0
- package/dist/util/scroll-padding.js +44 -0
- package/dist/util/segmented-control.d.ts +15 -0
- package/dist/util/segmented-control.js +1 -0
- package/dist/util/select.d.ts +40 -0
- package/dist/util/select.js +63 -0
- package/dist/util/sheet-drag.d.ts +83 -0
- package/dist/util/sheet-drag.js +311 -0
- package/dist/util/sidebar.d.ts +62 -0
- package/dist/util/sidebar.js +38 -0
- package/dist/util/skeleton.d.ts +14 -0
- package/dist/util/skeleton.js +22 -0
- package/dist/util/sliding-indicator.d.ts +24 -0
- package/dist/util/sliding-indicator.js +44 -0
- package/dist/util/sortable-list.d.ts +64 -0
- package/dist/util/sortable-list.js +53 -0
- package/dist/util/stepper.d.ts +39 -0
- package/dist/util/stepper.js +38 -0
- package/dist/util/swipeable-list-item.d.ts +35 -0
- package/dist/util/swipeable-list-item.js +32 -0
- package/dist/util/temporal-field.d.ts +88 -0
- package/dist/util/temporal-field.js +136 -0
- package/dist/util/theme-mode.d.ts +79 -0
- package/dist/util/theme-mode.js +121 -0
- package/dist/util/toaster.d.ts +132 -0
- package/dist/util/toaster.js +130 -0
- package/dist/util/tone-surface.d.ts +33 -0
- package/dist/util/tone-surface.js +35 -0
- package/dist/util/tooltip.d.ts +9 -0
- package/dist/util/tooltip.js +18 -0
- package/dist/util/top-navbar.d.ts +34 -0
- package/dist/util/top-navbar.js +28 -0
- package/dist/util/touch-target.d.ts +30 -0
- package/dist/util/touch-target.js +30 -0
- package/dist/util/zabi-strings.d.ts +141 -0
- package/dist/util/zabi-strings.js +105 -0
- package/dist/zabi-components-colors.css +11 -2
- package/dist/zabi-components-theme-dark-only.css +870 -258
- package/dist/zabi-components-theme-dark.css +870 -258
- package/dist/zabi-components-theme-only.css +2419 -368
- package/dist/zabi-components-theme.css +2419 -368
- package/dist/zabi-components.css +6032 -711
- package/docs/lucide-icons.md +40 -17
- package/docs/theme-imports.md +81 -11
- package/package.json +45 -8
|
@@ -1,16 +1,62 @@
|
|
|
1
|
-
|
|
1
|
+
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
2
|
+
import { type SelectPresentation, type SelectStrings } from "../util/select.js";
|
|
3
|
+
/**
|
|
4
|
+
* Other attributes (`data-*`, `aria-*`, `onfocus`, ...) land on the
|
|
5
|
+
* trigger, which is a `<button>`: it is the control that takes focus and
|
|
6
|
+
* that the label names.
|
|
7
|
+
*
|
|
8
|
+
* The server's HTML also carries a native `<select>` with the same
|
|
9
|
+
* options. Until the component has mounted, and for good where there are
|
|
10
|
+
* no scripts, that is the control: it is what is seen, pressed and
|
|
11
|
+
* submitted. Once mounted the trigger and the list take over, and the
|
|
12
|
+
* native select stays, out of sight and out of reach, as the form control
|
|
13
|
+
* (`name`, `required`), kept at the same value. With
|
|
14
|
+
* `presentation="native"` it is the control throughout.
|
|
15
|
+
*/
|
|
16
|
+
type Props = Omit<HTMLButtonAttributes, "class" | "value" | "name" | "disabled" | "type" | "onchange" | "onclick" | "aria-describedby" | "children"> & {
|
|
2
17
|
/** Extra classes for the host element. */
|
|
3
18
|
class?: string;
|
|
19
|
+
/** Id of the trigger. Omit to auto-generate. */
|
|
20
|
+
id?: string;
|
|
4
21
|
value?: string | number | undefined;
|
|
5
22
|
options?: Array<{
|
|
6
23
|
value: string | number;
|
|
7
24
|
label: string;
|
|
8
25
|
disabled?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The language of the label, as a BCP 47 tag (`"en"`), when it is
|
|
28
|
+
* not the page's (WCAG 3.1.2). Set on the option's row, on the
|
|
29
|
+
* trigger's text while it is chosen, and on the native `<option>`.
|
|
30
|
+
*/
|
|
31
|
+
lang?: string;
|
|
9
32
|
}>;
|
|
10
33
|
searchable?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* The component's own texts, for another language. Whatever is left
|
|
36
|
+
* out keeps its English default. The six older props for single texts
|
|
37
|
+
* (`placeholder`, `searchPlaceholder`, `noResultsText`,
|
|
38
|
+
* `loadingText`, `emptyStateTitle`, `emptyStateDescription`) win
|
|
39
|
+
* over it.
|
|
40
|
+
*/
|
|
41
|
+
strings?: Partial<SelectStrings>;
|
|
11
42
|
searchPlaceholder?: string;
|
|
12
43
|
maxMenuHeight?: string;
|
|
13
44
|
menuWidth?: string;
|
|
45
|
+
/**
|
|
46
|
+
* How the list is shown. `auto`: in a BottomSheet on a phone (a touch
|
|
47
|
+
* screen narrower than 640px), under the trigger everywhere else.
|
|
48
|
+
* `popover` and `sheet` are always the one or the other. `native`:
|
|
49
|
+
* only the browser's own `<select>`, styled as the field, with the
|
|
50
|
+
* platform's picker. It shows the options' labels and nothing else:
|
|
51
|
+
* no search field, and none of the loading or empty states.
|
|
52
|
+
*/
|
|
53
|
+
presentation?: SelectPresentation;
|
|
54
|
+
/**
|
|
55
|
+
* In a sheet, a short list (up to six options) without a search field
|
|
56
|
+
* gets a sheet as tall as the list, not half the screen. `false`
|
|
57
|
+
* keeps the half-height sheet.
|
|
58
|
+
*/
|
|
59
|
+
sheetFit?: boolean;
|
|
14
60
|
noResultsText?: string;
|
|
15
61
|
isLoading?: boolean;
|
|
16
62
|
loadingText?: string;
|
|
@@ -19,16 +65,28 @@ interface Props {
|
|
|
19
65
|
emptyStateActionLabel?: string;
|
|
20
66
|
placeholder?: string;
|
|
21
67
|
label?: string;
|
|
22
|
-
/**
|
|
68
|
+
/** The name the chosen value is submitted under, by the native `<select>`. */
|
|
23
69
|
name?: string;
|
|
70
|
+
/**
|
|
71
|
+
* The form is not sent while nothing is chosen. Checked by the
|
|
72
|
+
* browser on the native `<select>`; once mounted, the browser's own
|
|
73
|
+
* message is shown under the field and focus goes to the trigger.
|
|
74
|
+
*/
|
|
24
75
|
required?: boolean;
|
|
25
76
|
disabled?: boolean;
|
|
26
77
|
size?: "sm" | "md" | "lg";
|
|
27
78
|
variant?: "default" | "success" | "warning" | "error";
|
|
79
|
+
/** Status text under the field. Shown with a `success`, `warning` or `error` variant; for neutral help, use `hint`. */
|
|
28
80
|
message?: string;
|
|
81
|
+
/** Help text under the field, read out with it. */
|
|
82
|
+
hint?: string;
|
|
83
|
+
/** An error under the field. It marks the field invalid and is announced; it wins over `variant` and `message`. */
|
|
84
|
+
error?: string;
|
|
29
85
|
onchange?: (event: Event) => void;
|
|
30
86
|
onEmptyStateAction?: () => void;
|
|
31
|
-
|
|
87
|
+
/** Ids of other elements that describe the field. The hint and the message are added after them. */
|
|
88
|
+
"aria-describedby"?: string | null;
|
|
89
|
+
};
|
|
32
90
|
declare const Select: import("svelte").Component<Props, {}, "value">;
|
|
33
91
|
type Select = ReturnType<typeof Select>;
|
|
34
92
|
export default Select;
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type
|
|
2
|
+
import { onMount, tick, type Snippet } from "svelte";
|
|
3
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
3
4
|
import { generateId } from "../util/ssr-safe.js";
|
|
4
5
|
import { cn } from "../util/cn.js";
|
|
6
|
+
import { groupBinding } from "../util/hydration.js";
|
|
7
|
+
import { fieldDescribedBy, fieldMessageState } from "../util/field.js";
|
|
8
|
+
import type { SemanticVariant } from "../types/variants.js";
|
|
9
|
+
import FieldMessages from "./FieldMessages.svelte";
|
|
5
10
|
import {
|
|
11
|
+
SELECTION_CONTROL_INPUT,
|
|
6
12
|
SELECTION_CONTROL_LABEL_ROW,
|
|
7
13
|
selectionControlRingOverlayClasses,
|
|
8
14
|
selectionControlShellClasses,
|
|
@@ -17,7 +23,10 @@
|
|
|
17
23
|
disabled: boolean;
|
|
18
24
|
};
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
type Props = Omit<
|
|
27
|
+
HTMLInputAttributes,
|
|
28
|
+
"class" | "id" | "name" | "value" | "disabled" | "checked" | "type" | "onchange"
|
|
29
|
+
> & {
|
|
21
30
|
/** Extra classes for the host element. */
|
|
22
31
|
class?: string;
|
|
23
32
|
id?: string;
|
|
@@ -33,7 +42,31 @@
|
|
|
33
42
|
onChange?: (event: Event) => void;
|
|
34
43
|
onchange?: (event: Event) => void;
|
|
35
44
|
mark?: Snippet<[SelectionControlMarkProps]>;
|
|
36
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Drawn inside the one label, between the control and the label text,
|
|
47
|
+
* as decoration for the name `label` already gives. A leading image
|
|
48
|
+
* should have an empty alt: the label names the row.
|
|
49
|
+
*/
|
|
50
|
+
leading?: Snippet;
|
|
51
|
+
/**
|
|
52
|
+
* A line under the label, tied to the input with `aria-describedby`.
|
|
53
|
+
* It is not part of the name: the label names the control.
|
|
54
|
+
*/
|
|
55
|
+
description?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Where the control sits in the row. `end` puts it after the leading,
|
|
58
|
+
* the label and the description, at the far edge; the row is still
|
|
59
|
+
* one label and fills the width it is given.
|
|
60
|
+
*/
|
|
61
|
+
controlPosition?: "start" | "end";
|
|
62
|
+
variant?: SemanticVariant;
|
|
63
|
+
/** Status text under the control. Shown with a `success`, `warning` or `error` variant; for neutral help, use `hint`. */
|
|
64
|
+
message?: string;
|
|
65
|
+
/** Help text under the control, read out with it. */
|
|
66
|
+
hint?: string;
|
|
67
|
+
/** An error under the control. It marks the input invalid and is announced; it wins over `variant` and `message`. */
|
|
68
|
+
error?: string;
|
|
69
|
+
};
|
|
37
70
|
|
|
38
71
|
let {
|
|
39
72
|
class: className = "",
|
|
@@ -46,26 +79,111 @@
|
|
|
46
79
|
disabled = false,
|
|
47
80
|
loading = false,
|
|
48
81
|
defaultChecked = false,
|
|
49
|
-
checked = $bindable(
|
|
82
|
+
checked = $bindable<Exclude<Props["checked"], undefined>>(),
|
|
50
83
|
onChange,
|
|
51
84
|
onchange,
|
|
52
85
|
mark,
|
|
86
|
+
leading,
|
|
87
|
+
description,
|
|
88
|
+
controlPosition = "start",
|
|
89
|
+
variant = "default",
|
|
90
|
+
message = "",
|
|
91
|
+
hint = "",
|
|
92
|
+
error = "",
|
|
53
93
|
...restProps
|
|
54
94
|
}: Props = $props();
|
|
55
95
|
|
|
96
|
+
// No fallback on a bindable prop: Svelte refuses `bind:…={undefined}` on
|
|
97
|
+
// one that has a fallback (`props_invalid_value`), and a page that throws
|
|
98
|
+
// while it hydrates never becomes interactive. The default is applied
|
|
99
|
+
// here instead: at once, for the server and the first render, and again
|
|
100
|
+
// whenever a parent hands back `undefined`.
|
|
101
|
+
const applyDefaults = () => {
|
|
102
|
+
if (checked === undefined) checked = defaultChecked;
|
|
103
|
+
};
|
|
104
|
+
applyDefaults();
|
|
105
|
+
$effect.pre(applyDefaults);
|
|
106
|
+
|
|
56
107
|
/** Call once per mount — `generateId()` in `$derived` would churn ids every tick. */
|
|
57
108
|
const fallbackId = generateId("selection-control");
|
|
58
109
|
const controlId = $derived(idProp ?? fallbackId);
|
|
59
110
|
const isDisabled = $derived(disabled || loading);
|
|
60
111
|
|
|
61
|
-
const
|
|
112
|
+
const descriptionId = $derived(`${controlId}-description`);
|
|
113
|
+
const status = $derived(fieldMessageState({ variant, message, hint, error }));
|
|
114
|
+
const hasFieldText = $derived(status.showMessage || status.showHint);
|
|
115
|
+
// The caller's ids, then the description, the hint and the message.
|
|
116
|
+
const describedBy = $derived(
|
|
117
|
+
fieldDescribedBy(
|
|
118
|
+
controlId,
|
|
119
|
+
status,
|
|
120
|
+
[restProps["aria-describedby"], description ? descriptionId : undefined]
|
|
121
|
+
.filter(Boolean)
|
|
122
|
+
.join(" "),
|
|
123
|
+
),
|
|
124
|
+
);
|
|
125
|
+
// `aria-invalid` is not supported by the radio role: a radio's error is said by its description.
|
|
126
|
+
const invalid = $derived(status.variant === "error" ? "true" : undefined);
|
|
62
127
|
|
|
63
|
-
|
|
128
|
+
// With a description the row is two lines: the box sits at the top, as in RadioGroup.
|
|
129
|
+
// At the end the control is moved by `order`, so the markup and what a
|
|
130
|
+
// screen reader meets first are the same in both positions.
|
|
131
|
+
const controlAtEnd = $derived(controlPosition === "end");
|
|
132
|
+
const labelWrapperClasses = $derived(
|
|
133
|
+
cn(SELECTION_CONTROL_LABEL_ROW, description && "items-start", controlAtEnd && "min-w-0 flex-1"),
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const controlContainerClasses = $derived(
|
|
137
|
+
cn(selectionControlShellClasses(shape), description && "mt-0.5", controlAtEnd && "order-last"),
|
|
138
|
+
);
|
|
139
|
+
const labelTextClasses = $derived(controlAtEnd ? "min-w-0 flex-1" : "");
|
|
64
140
|
|
|
65
141
|
const controlRingClasses = $derived(selectionControlRingOverlayClasses(shape));
|
|
66
142
|
|
|
143
|
+
let input: HTMLInputElement | undefined = $state();
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* The input is bound, so a tick made before the page hydrated is kept:
|
|
147
|
+
* Svelte's binding finds the input changed and hands its state over here
|
|
148
|
+
* instead of overwriting it (see util/hydration.ts). A form reset arrives
|
|
149
|
+
* the same way.
|
|
150
|
+
*
|
|
151
|
+
* A choice that is adopted like that came without a `change` event that
|
|
152
|
+
* anything heard, and a parent that only listens (`onchange`, no
|
|
153
|
+
* `bind:checked`) would never learn of it. So while the component
|
|
154
|
+
* settles, a change made through the binding is noted, and reported once
|
|
155
|
+
* with a real `change` event on the input: the callbacks get the event
|
|
156
|
+
* they always get, and a form around the control hears it too.
|
|
157
|
+
*/
|
|
158
|
+
let settling = true;
|
|
159
|
+
let adopted = false;
|
|
160
|
+
|
|
161
|
+
function take(next: boolean) {
|
|
162
|
+
if (next === !!checked) return;
|
|
163
|
+
checked = next;
|
|
164
|
+
if (settling) adopted = true;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** What a single radio's group is bound to: its own value while it is checked. */
|
|
168
|
+
const NOT_CHOSEN = {};
|
|
169
|
+
const radio = groupBinding<unknown>(
|
|
170
|
+
() => (checked ? value : NOT_CHOSEN),
|
|
171
|
+
(chosen) => take(chosen === value),
|
|
172
|
+
() => take(false),
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
onMount(() => {
|
|
176
|
+
// The bindings adopt in a microtask of their own, queued before this one.
|
|
177
|
+
void tick().then(() => {
|
|
178
|
+
settling = false;
|
|
179
|
+
if (adopted) input?.dispatchEvent(new Event("change", { bubbles: true }));
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
67
183
|
function handleChange(event: Event) {
|
|
68
184
|
if (isDisabled) return;
|
|
185
|
+
// A real change is its own report: nothing is left to tell.
|
|
186
|
+
adopted = false;
|
|
69
187
|
const target = event.target as HTMLInputElement;
|
|
70
188
|
checked = target.checked;
|
|
71
189
|
onChange?.(event);
|
|
@@ -73,30 +191,82 @@
|
|
|
73
191
|
}
|
|
74
192
|
</script>
|
|
75
193
|
|
|
76
|
-
|
|
194
|
+
{#snippet row()}
|
|
77
195
|
<label for={controlId} class={labelWrapperClasses}>
|
|
78
196
|
<span class={controlContainerClasses}>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
197
|
+
<!-- One branch per type: a binding needs a type it can read. -->
|
|
198
|
+
{#if type === "checkbox"}
|
|
199
|
+
<input
|
|
200
|
+
bind:this={input}
|
|
201
|
+
type="checkbox"
|
|
202
|
+
id={controlId}
|
|
203
|
+
{name}
|
|
204
|
+
{value}
|
|
205
|
+
bind:checked={() => !!checked, take}
|
|
206
|
+
disabled={isDisabled}
|
|
207
|
+
class={SELECTION_CONTROL_INPUT}
|
|
208
|
+
aria-busy={loading ? "true" : undefined}
|
|
209
|
+
onchange={handleChange}
|
|
210
|
+
{...restProps}
|
|
211
|
+
aria-describedby={describedBy}
|
|
212
|
+
aria-invalid={invalid ?? restProps["aria-invalid"]}
|
|
213
|
+
/>
|
|
214
|
+
{:else}
|
|
215
|
+
<input
|
|
216
|
+
bind:this={input}
|
|
217
|
+
type="radio"
|
|
218
|
+
id={controlId}
|
|
219
|
+
{name}
|
|
220
|
+
{value}
|
|
221
|
+
bind:group={radio.value}
|
|
222
|
+
disabled={isDisabled}
|
|
223
|
+
class={SELECTION_CONTROL_INPUT}
|
|
224
|
+
aria-busy={loading ? "true" : undefined}
|
|
225
|
+
onchange={handleChange}
|
|
226
|
+
{...restProps}
|
|
227
|
+
aria-describedby={describedBy}
|
|
228
|
+
/>
|
|
229
|
+
{/if}
|
|
91
230
|
<span class={controlRingClasses}></span>
|
|
92
231
|
{#if mark}
|
|
93
|
-
{@render mark({ checked, loading, disabled: isDisabled })}
|
|
232
|
+
{@render mark({ checked: !!checked, loading, disabled: isDisabled })}
|
|
94
233
|
{/if}
|
|
95
234
|
</span>
|
|
96
|
-
{#if
|
|
97
|
-
<span class="
|
|
235
|
+
{#if leading}
|
|
236
|
+
<span class="inline-flex shrink-0 items-center">
|
|
237
|
+
{@render leading()}
|
|
238
|
+
</span>
|
|
239
|
+
{/if}
|
|
240
|
+
{#if description}
|
|
241
|
+
<span class={cn("flex flex-col gap-1", labelTextClasses)}>
|
|
242
|
+
<span class="text-sm font-medium text-label">
|
|
243
|
+
{label}
|
|
244
|
+
</span>
|
|
245
|
+
<!-- aria-hidden keeps it out of the name; aria-describedby still reads it. -->
|
|
246
|
+
<span id={descriptionId} class="text-sm text-description" aria-hidden="true">
|
|
247
|
+
{description}
|
|
248
|
+
</span>
|
|
249
|
+
</span>
|
|
250
|
+
{:else if label}
|
|
251
|
+
<span class={cn("text-sm font-medium text-label", labelTextClasses)}>
|
|
98
252
|
{label}
|
|
99
253
|
</span>
|
|
100
254
|
{/if}
|
|
101
255
|
</label>
|
|
102
|
-
|
|
256
|
+
{/snippet}
|
|
257
|
+
|
|
258
|
+
{#if hasFieldText}
|
|
259
|
+
<div class={cn("flex flex-col", className)}>
|
|
260
|
+
<div class="flex items-center gap-2">
|
|
261
|
+
{@render row()}
|
|
262
|
+
</div>
|
|
263
|
+
<!-- Under the label text: the box is 20px and the gap 8px. With the box at the end, from the row's edge. -->
|
|
264
|
+
<div class={controlAtEnd ? "" : "ps-7"}>
|
|
265
|
+
<FieldMessages fieldId={controlId} {status} {hint} gap="mt-1" />
|
|
266
|
+
</div>
|
|
267
|
+
</div>
|
|
268
|
+
{:else}
|
|
269
|
+
<div class={cn("flex items-center gap-2", className)}>
|
|
270
|
+
{@render row()}
|
|
271
|
+
</div>
|
|
272
|
+
{/if}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Snippet } from "svelte";
|
|
2
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
3
|
+
import type { SemanticVariant } from "../types/variants.js";
|
|
2
4
|
import { type SelectionControlShape } from "./selection-control.styles";
|
|
3
5
|
type SelectionControlType = "checkbox" | "radio";
|
|
4
6
|
export type SelectionControlMarkProps = {
|
|
@@ -6,7 +8,7 @@ export type SelectionControlMarkProps = {
|
|
|
6
8
|
loading: boolean;
|
|
7
9
|
disabled: boolean;
|
|
8
10
|
};
|
|
9
|
-
|
|
11
|
+
type Props = Omit<HTMLInputAttributes, "class" | "id" | "name" | "value" | "disabled" | "checked" | "type" | "onchange"> & {
|
|
10
12
|
/** Extra classes for the host element. */
|
|
11
13
|
class?: string;
|
|
12
14
|
id?: string;
|
|
@@ -22,7 +24,31 @@ interface Props {
|
|
|
22
24
|
onChange?: (event: Event) => void;
|
|
23
25
|
onchange?: (event: Event) => void;
|
|
24
26
|
mark?: Snippet<[SelectionControlMarkProps]>;
|
|
25
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Drawn inside the one label, between the control and the label text,
|
|
29
|
+
* as decoration for the name `label` already gives. A leading image
|
|
30
|
+
* should have an empty alt: the label names the row.
|
|
31
|
+
*/
|
|
32
|
+
leading?: Snippet;
|
|
33
|
+
/**
|
|
34
|
+
* A line under the label, tied to the input with `aria-describedby`.
|
|
35
|
+
* It is not part of the name: the label names the control.
|
|
36
|
+
*/
|
|
37
|
+
description?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Where the control sits in the row. `end` puts it after the leading,
|
|
40
|
+
* the label and the description, at the far edge; the row is still
|
|
41
|
+
* one label and fills the width it is given.
|
|
42
|
+
*/
|
|
43
|
+
controlPosition?: "start" | "end";
|
|
44
|
+
variant?: SemanticVariant;
|
|
45
|
+
/** Status text under the control. Shown with a `success`, `warning` or `error` variant; for neutral help, use `hint`. */
|
|
46
|
+
message?: string;
|
|
47
|
+
/** Help text under the control, read out with it. */
|
|
48
|
+
hint?: string;
|
|
49
|
+
/** An error under the control. It marks the input invalid and is announced; it wins over `variant` and `message`. */
|
|
50
|
+
error?: string;
|
|
51
|
+
};
|
|
26
52
|
declare const SelectionControl: import("svelte").Component<Props, {}, "checked">;
|
|
27
53
|
type SelectionControl = ReturnType<typeof SelectionControl>;
|
|
28
54
|
export default SelectionControl;
|
|
@@ -1,56 +1,152 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
|
|
2
4
|
import { cn } from "../util/cn.js";
|
|
5
|
+
import { mergeStrings } from "../util/ready-made-strings.js";
|
|
6
|
+
import {
|
|
7
|
+
DEFAULT_SKELETON_STRINGS,
|
|
8
|
+
inSkeletonGroup,
|
|
9
|
+
skeletonLineCount,
|
|
10
|
+
type SkeletonStrings,
|
|
11
|
+
} from "../util/skeleton.js";
|
|
12
|
+
import { zabiStringsFor } from "../util/zabi-strings.js";
|
|
3
13
|
|
|
4
14
|
type Variant = "text" | "circle" | "block";
|
|
15
|
+
type Tone = "neutral" | "on-color";
|
|
5
16
|
|
|
6
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Anything else a `div` takes (`id`, `data-testid`, `style`, `aria-*`) goes to the piece, or to the
|
|
19
|
+
* paragraph's wrapper with `lines`. `role`, `aria-busy`, `aria-hidden` and `data-skeleton` are set by
|
|
20
|
+
* the component and are not overridden.
|
|
21
|
+
*/
|
|
22
|
+
type Props = Omit<HTMLAttributes<HTMLDivElement>, "class" | "role" | "aria-busy" | "aria-hidden"> & {
|
|
7
23
|
variant?: Variant;
|
|
8
24
|
/** CSS length or px number; omit to use variant default (circle stays square). */
|
|
9
25
|
width?: string | number;
|
|
10
|
-
/** CSS length or px number; omit for variant default height. */
|
|
26
|
+
/** CSS length or px number; omit for variant default height. With `lines`, the height of each line. */
|
|
11
27
|
height?: string | number;
|
|
12
28
|
class?: string;
|
|
29
|
+
/** The status label. Defaults to the provider's `skeleton.label`, then "Loading…". */
|
|
13
30
|
"aria-label"?: string;
|
|
14
|
-
|
|
31
|
+
/** Overrides for the built-in strings. */
|
|
32
|
+
strings?: Partial<SkeletonStrings>;
|
|
33
|
+
/**
|
|
34
|
+
* Draws the piece only: no role, no label, hidden from assistive tech.
|
|
35
|
+
* For a piece beside a status of your own. A piece under a `SkeletonGroup` is decorative already.
|
|
36
|
+
*/
|
|
37
|
+
decorative?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* "neutral" is the quiet fill for a page or a card. "on-color" is the label colour of
|
|
40
|
+
* the surface it sits on at a low strength, for a brand, accent or fill block (`on-brand`,
|
|
41
|
+
* `on-accent`, `on-fill`, a `Card` with `tone`), in light and dark.
|
|
42
|
+
*/
|
|
43
|
+
tone?: Tone;
|
|
44
|
+
/**
|
|
45
|
+
* Text variant only: draws this many lines (1 to 20) as one placeholder, the last one shorter.
|
|
46
|
+
* `class` and `width` then apply to the whole paragraph, `height` to each line.
|
|
47
|
+
*/
|
|
48
|
+
lines?: number;
|
|
49
|
+
};
|
|
15
50
|
|
|
16
51
|
let {
|
|
17
52
|
variant = "text",
|
|
18
53
|
width,
|
|
19
54
|
height,
|
|
20
55
|
class: className = "",
|
|
21
|
-
"aria-label": ariaLabel
|
|
56
|
+
"aria-label": ariaLabel,
|
|
57
|
+
strings,
|
|
58
|
+
decorative = false,
|
|
59
|
+
tone = "neutral",
|
|
60
|
+
lines,
|
|
61
|
+
style,
|
|
62
|
+
...restProps
|
|
22
63
|
}: Props = $props();
|
|
23
64
|
|
|
65
|
+
/** The app-wide words for this component, from a `ZabiStringsProvider` above it, if there is one. */
|
|
66
|
+
const provided = zabiStringsFor("skeleton");
|
|
67
|
+
const text = $derived(mergeStrings(DEFAULT_SKELETON_STRINGS, provided(), strings));
|
|
68
|
+
|
|
69
|
+
const grouped = inSkeletonGroup();
|
|
70
|
+
const hidden = $derived(decorative || grouped);
|
|
71
|
+
|
|
24
72
|
const radius: Record<Variant, string> = {
|
|
25
73
|
text: "rounded-control",
|
|
26
74
|
circle: "rounded-full",
|
|
27
75
|
block: "rounded-control",
|
|
28
76
|
};
|
|
29
77
|
|
|
78
|
+
/**
|
|
79
|
+
* The variant's own box, at zero specificity (`:where()`): any size class at
|
|
80
|
+
* the call site wins over it in the stylesheet, whether `cn()` knows its name
|
|
81
|
+
* (`size-14`) or not (`size-sticker`, an app's own step).
|
|
82
|
+
*/
|
|
30
83
|
const defaultShape: Record<Variant, string> = {
|
|
31
|
-
text: "w-full h-3",
|
|
32
|
-
circle: "w-10 aspect-square",
|
|
33
|
-
block: "w-full h-32",
|
|
84
|
+
text: "[:where(&)]:w-full [:where(&)]:h-3",
|
|
85
|
+
circle: "[:where(&)]:w-10 aspect-square",
|
|
86
|
+
block: "[:where(&)]:w-full [:where(&)]:h-32",
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const fill: Record<Tone, string> = {
|
|
90
|
+
neutral: "bg-neutral-subtle",
|
|
91
|
+
"on-color": "bg-skeleton-on-color",
|
|
34
92
|
};
|
|
35
93
|
|
|
36
94
|
function toSize(value: string | number): string {
|
|
37
95
|
return typeof value === "number" ? `${value}px` : value;
|
|
38
96
|
}
|
|
39
97
|
|
|
98
|
+
/** The component's own inline styles first, then the caller's `style`, which wins where both set a property. */
|
|
99
|
+
function joinStyles(...parts: Array<string | null | undefined>): string | undefined {
|
|
100
|
+
const joined = parts
|
|
101
|
+
.filter(Boolean)
|
|
102
|
+
.map((part) => String(part).replace(/;\s*$/, ""))
|
|
103
|
+
.join("; ");
|
|
104
|
+
return joined || undefined;
|
|
105
|
+
}
|
|
106
|
+
|
|
40
107
|
const inlineStyle = $derived(
|
|
41
|
-
|
|
108
|
+
joinStyles(
|
|
42
109
|
width !== undefined ? `width: ${toSize(width)}` : null,
|
|
43
110
|
height !== undefined ? `height: ${toSize(height)}` : null,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
.join("; "),
|
|
111
|
+
style,
|
|
112
|
+
),
|
|
47
113
|
);
|
|
114
|
+
|
|
115
|
+
const lineCount = $derived(variant === "text" ? skeletonLineCount(lines) : 0);
|
|
116
|
+
const lineStyle = $derived(height !== undefined ? `height: ${toSize(height)}` : undefined);
|
|
117
|
+
const wrapperStyle = $derived(joinStyles(width !== undefined ? `width: ${toSize(width)}` : null, style));
|
|
118
|
+
const pieceClass = $derived(cn("animate-pulse motion-reduce:animate-none", fill[tone], radius.text));
|
|
48
119
|
</script>
|
|
49
120
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
121
|
+
{#if lineCount > 0}
|
|
122
|
+
<div
|
|
123
|
+
{...restProps}
|
|
124
|
+
class={cn("flex w-full flex-col gap-2", className)}
|
|
125
|
+
style={wrapperStyle}
|
|
126
|
+
data-skeleton-paragraph
|
|
127
|
+
role={hidden ? undefined : "status"}
|
|
128
|
+
aria-busy={hidden ? undefined : "true"}
|
|
129
|
+
aria-label={hidden ? undefined : (ariaLabel ?? text.label)}
|
|
130
|
+
aria-hidden={hidden ? "true" : undefined}
|
|
131
|
+
>
|
|
132
|
+
{#each { length: lineCount } as _, index (index)}
|
|
133
|
+
<div
|
|
134
|
+
class={cn(pieceClass, "h-3", index === lineCount - 1 && lineCount > 1 ? "w-3/5" : "w-full")}
|
|
135
|
+
style={lineStyle}
|
|
136
|
+
data-skeleton="text"
|
|
137
|
+
data-skeleton-line
|
|
138
|
+
></div>
|
|
139
|
+
{/each}
|
|
140
|
+
</div>
|
|
141
|
+
{:else}
|
|
142
|
+
<div
|
|
143
|
+
{...restProps}
|
|
144
|
+
class={cn("animate-pulse motion-reduce:animate-none", fill[tone], defaultShape[variant], radius[variant], className)}
|
|
145
|
+
style={inlineStyle}
|
|
146
|
+
data-skeleton={variant}
|
|
147
|
+
role={hidden ? undefined : "status"}
|
|
148
|
+
aria-busy={hidden ? undefined : "true"}
|
|
149
|
+
aria-label={hidden ? undefined : (ariaLabel ?? text.label)}
|
|
150
|
+
aria-hidden={hidden ? "true" : undefined}
|
|
151
|
+
></div>
|
|
152
|
+
{/if}
|
|
@@ -1,13 +1,40 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
2
|
+
import { type SkeletonStrings } from "../util/skeleton.js";
|
|
1
3
|
type Variant = "text" | "circle" | "block";
|
|
2
|
-
|
|
4
|
+
type Tone = "neutral" | "on-color";
|
|
5
|
+
/**
|
|
6
|
+
* Anything else a `div` takes (`id`, `data-testid`, `style`, `aria-*`) goes to the piece, or to the
|
|
7
|
+
* paragraph's wrapper with `lines`. `role`, `aria-busy`, `aria-hidden` and `data-skeleton` are set by
|
|
8
|
+
* the component and are not overridden.
|
|
9
|
+
*/
|
|
10
|
+
type Props = Omit<HTMLAttributes<HTMLDivElement>, "class" | "role" | "aria-busy" | "aria-hidden"> & {
|
|
3
11
|
variant?: Variant;
|
|
4
12
|
/** CSS length or px number; omit to use variant default (circle stays square). */
|
|
5
13
|
width?: string | number;
|
|
6
|
-
/** CSS length or px number; omit for variant default height. */
|
|
14
|
+
/** CSS length or px number; omit for variant default height. With `lines`, the height of each line. */
|
|
7
15
|
height?: string | number;
|
|
8
16
|
class?: string;
|
|
17
|
+
/** The status label. Defaults to the provider's `skeleton.label`, then "Loading…". */
|
|
9
18
|
"aria-label"?: string;
|
|
10
|
-
|
|
19
|
+
/** Overrides for the built-in strings. */
|
|
20
|
+
strings?: Partial<SkeletonStrings>;
|
|
21
|
+
/**
|
|
22
|
+
* Draws the piece only: no role, no label, hidden from assistive tech.
|
|
23
|
+
* For a piece beside a status of your own. A piece under a `SkeletonGroup` is decorative already.
|
|
24
|
+
*/
|
|
25
|
+
decorative?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* "neutral" is the quiet fill for a page or a card. "on-color" is the label colour of
|
|
28
|
+
* the surface it sits on at a low strength, for a brand, accent or fill block (`on-brand`,
|
|
29
|
+
* `on-accent`, `on-fill`, a `Card` with `tone`), in light and dark.
|
|
30
|
+
*/
|
|
31
|
+
tone?: Tone;
|
|
32
|
+
/**
|
|
33
|
+
* Text variant only: draws this many lines (1 to 20) as one placeholder, the last one shorter.
|
|
34
|
+
* `class` and `width` then apply to the whole paragraph, `height` to each line.
|
|
35
|
+
*/
|
|
36
|
+
lines?: number;
|
|
37
|
+
};
|
|
11
38
|
declare const Skeleton: import("svelte").Component<Props, {}, "">;
|
|
12
39
|
type Skeleton = ReturnType<typeof Skeleton>;
|
|
13
40
|
export default Skeleton;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../util/cn.js";
|
|
6
|
+
import { mergeStrings } from "../util/ready-made-strings.js";
|
|
7
|
+
import { DEFAULT_SKELETON_STRINGS, provideSkeletonGroup, type SkeletonStrings } from "../util/skeleton.js";
|
|
8
|
+
import { zabiStringsFor } from "../util/zabi-strings.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* One loading status for a set of `Skeleton` pieces. The group is the
|
|
12
|
+
* `role="status"` region with the label; every `Skeleton` inside it is
|
|
13
|
+
* hidden from assistive tech, so a screen's eight pieces are announced
|
|
14
|
+
* once, not eight times.
|
|
15
|
+
*/
|
|
16
|
+
type Props = Omit<HTMLAttributes<HTMLDivElement>, "class" | "role" | "aria-busy"> & {
|
|
17
|
+
/** The status label. Defaults to the provider's `skeleton.label`, then "Loading…". */
|
|
18
|
+
"aria-label"?: string;
|
|
19
|
+
/** Overrides for the built-in strings. */
|
|
20
|
+
strings?: Partial<SkeletonStrings>;
|
|
21
|
+
class?: string;
|
|
22
|
+
children?: Snippet;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
let { "aria-label": ariaLabel, strings, class: className = "", children, ...restProps }: Props = $props();
|
|
26
|
+
|
|
27
|
+
provideSkeletonGroup();
|
|
28
|
+
|
|
29
|
+
/** The app-wide words for this component, from a `ZabiStringsProvider` above it, if there is one. */
|
|
30
|
+
const provided = zabiStringsFor("skeleton");
|
|
31
|
+
const text = $derived(mergeStrings(DEFAULT_SKELETON_STRINGS, provided(), strings));
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<div
|
|
35
|
+
{...restProps}
|
|
36
|
+
class={cn(className)}
|
|
37
|
+
role="status"
|
|
38
|
+
aria-busy="true"
|
|
39
|
+
aria-label={ariaLabel ?? text.label}
|
|
40
|
+
data-skeleton-group
|
|
41
|
+
>
|
|
42
|
+
{@render children?.()}
|
|
43
|
+
</div>
|