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
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
2
|
+
import type { SizeVariant } from "../types/variants.js";
|
|
3
|
+
import type { DateFieldStrings } from "../util/temporal-field.js";
|
|
4
|
+
/**
|
|
5
|
+
* A date, picked with the device's own date picker and styled like Input.
|
|
6
|
+
*
|
|
7
|
+
* It is a native `<input type="date">`: an iPhone shows its wheels or
|
|
8
|
+
* calendar, Android its calendar, a desktop browser its own. `value` is
|
|
9
|
+
* always `YYYY-MM-DD`, or `""` while empty, whatever the field shows.
|
|
10
|
+
*
|
|
11
|
+
* What the field shows is the browser's decision, unless it has a
|
|
12
|
+
* `locale`: without one, the date is in the format of the browser or
|
|
13
|
+
* device, not of the page, and no attribute changes that. To show a date
|
|
14
|
+
* as text in the page's language, use `formatDate`:
|
|
15
|
+
*
|
|
16
|
+
* ```svelte
|
|
17
|
+
* <DateField label="Date" bind:value={date} min="2026-01-01" />
|
|
18
|
+
* <p>{formatDate(date, "sv")}</p> <!-- 6 okt. 2026 -->
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* With `locale`, the field shows the value in that language and its own
|
|
22
|
+
* picker opens: a Calendar in a BottomSheet (at every width), with Clear
|
|
23
|
+
* unless the field is `required`. Until the page has run, and without
|
|
24
|
+
* scripts, it is the native input as above and submits as before; once
|
|
25
|
+
* it has, the native input stays as the form control, out of sight, and a
|
|
26
|
+
* button in its place shows the date. `picker="native"` opens the
|
|
27
|
+
* platform's own picker instead.
|
|
28
|
+
*
|
|
29
|
+
* ```svelte
|
|
30
|
+
* <DateField label="Datum" locale="sv" bind:value format={{ weekday: "short", day: "numeric", month: "short" }} />
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* Other attributes (`autocomplete`, `data-*`, `onchange`, ...) land on the
|
|
34
|
+
* `<input>`.
|
|
35
|
+
*/
|
|
36
|
+
type Props = Omit<HTMLInputAttributes, "class" | "type" | "value" | "size" | "min" | "max" | "step" | "required" | "disabled" | "readonly" | "id" | "name"> & {
|
|
37
|
+
/** Omit to auto-generate; pair with FormField's `id` when used inside FormField. */
|
|
38
|
+
id?: string;
|
|
39
|
+
/** The date as `YYYY-MM-DD`, or `""` while empty. Supports `bind:value`. */
|
|
40
|
+
value?: string;
|
|
41
|
+
/** Name the value is submitted under in a form. */
|
|
42
|
+
name?: string;
|
|
43
|
+
label?: string;
|
|
44
|
+
/** True when FormField supplies the visible `<label>`. */
|
|
45
|
+
hideLabel?: boolean;
|
|
46
|
+
/** Help text under the field, read out with it. */
|
|
47
|
+
hint?: string;
|
|
48
|
+
/** An error under the field. It marks the field invalid and is announced. */
|
|
49
|
+
error?: string;
|
|
50
|
+
/** Earliest date that can be picked, as `YYYY-MM-DD`. */
|
|
51
|
+
min?: string;
|
|
52
|
+
/** Latest date that can be picked, as `YYYY-MM-DD`. */
|
|
53
|
+
max?: string;
|
|
54
|
+
/** Steps between dates that can be picked, in days. */
|
|
55
|
+
step?: number | "any";
|
|
56
|
+
required?: boolean;
|
|
57
|
+
disabled?: boolean;
|
|
58
|
+
/** Shows the value without letting it be changed; it is still submitted. */
|
|
59
|
+
readonly?: boolean;
|
|
60
|
+
/** Height, on the scale Input and Button use. At least 44px on a touch screen. */
|
|
61
|
+
size?: SizeVariant;
|
|
62
|
+
/** Extra classes for the `<input>`. */
|
|
63
|
+
class?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Language of the field, as a BCP 47 tag (`sv`, `en-GB`) or a list of them. With it the
|
|
66
|
+
* field shows the value in that language, whatever the browser's is, and opens the
|
|
67
|
+
* library's own picker; see above. Left out, the field is the native input.
|
|
68
|
+
*/
|
|
69
|
+
locale?: string | string[];
|
|
70
|
+
/** With `locale`: how the value is shown, as options of `Intl.DateTimeFormat`. Default: what formatDate gives for the locale. */
|
|
71
|
+
format?: Intl.DateTimeFormatOptions;
|
|
72
|
+
/** With `locale`: shown in the placeholder colour while the field is empty. */
|
|
73
|
+
placeholder?: string;
|
|
74
|
+
/** With `locale`: `library` (default) opens the library's calendar in a sheet; `native` opens the platform's own picker. */
|
|
75
|
+
picker?: "library" | "native";
|
|
76
|
+
/** With `locale`: the words the field says; replace any of them to translate. */
|
|
77
|
+
strings?: Partial<DateFieldStrings>;
|
|
78
|
+
};
|
|
79
|
+
declare const DateField: import("svelte").Component<Props, {}, "value">;
|
|
80
|
+
type DateField = ReturnType<typeof DateField>;
|
|
81
|
+
export default DateField;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import CheckCircle from "@lucide/svelte/icons/circle-check-big";
|
|
3
|
+
import AlertCircle from "@lucide/svelte/icons/circle-alert";
|
|
4
|
+
import AlertTriangle from "@lucide/svelte/icons/triangle-alert";
|
|
5
|
+
import { cn } from "../util/cn.js";
|
|
6
|
+
import { fieldHintId, fieldMessageId, type FieldMessageState } from "../util/field.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The text under a field: its status message and its hint. Internal: it is
|
|
10
|
+
* not exported from the package. Input, Textarea and Select render it, and
|
|
11
|
+
* DateField and TimeField through Input, so the markup, the ids and the
|
|
12
|
+
* way a message is announced are the same in all of them.
|
|
13
|
+
*
|
|
14
|
+
* The ids are the ones `fieldDescribedBy` lists on the control.
|
|
15
|
+
*/
|
|
16
|
+
interface Props {
|
|
17
|
+
/** Id of the control the text belongs to. */
|
|
18
|
+
fieldId: string;
|
|
19
|
+
/** From `fieldMessageState`. */
|
|
20
|
+
status: FieldMessageState;
|
|
21
|
+
hint?: string;
|
|
22
|
+
/** Distance from the control, and between the two: Textarea and Select sit 4px closer. */
|
|
23
|
+
gap?: "mt-1" | "mt-2";
|
|
24
|
+
/** Extra classes for the status message. */
|
|
25
|
+
messageClass?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let { fieldId, status, hint = "", gap = "mt-2", messageClass = "" }: Props = $props();
|
|
29
|
+
|
|
30
|
+
// Message text uses the `-text` step (700), which clears 4.5:1 on a page
|
|
31
|
+
// surface; the solid fill step (600) is for fills, not for small text.
|
|
32
|
+
const toneClass = $derived(
|
|
33
|
+
status.variant === "error"
|
|
34
|
+
? "text-error-text"
|
|
35
|
+
: status.variant === "success"
|
|
36
|
+
? "text-success-text"
|
|
37
|
+
: status.variant === "warning"
|
|
38
|
+
? "text-warning-text"
|
|
39
|
+
: "text-description",
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const Icon = $derived(
|
|
43
|
+
status.variant === "error"
|
|
44
|
+
? AlertCircle
|
|
45
|
+
: status.variant === "success"
|
|
46
|
+
? CheckCircle
|
|
47
|
+
: status.variant === "warning"
|
|
48
|
+
? AlertTriangle
|
|
49
|
+
: null,
|
|
50
|
+
);
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
{#if status.showMessage}
|
|
54
|
+
<p
|
|
55
|
+
id={fieldMessageId(fieldId)}
|
|
56
|
+
class={cn("flex items-center gap-2 text-sm", gap, toneClass, messageClass)}
|
|
57
|
+
role={status.variant === "error" ? "alert" : "status"}
|
|
58
|
+
aria-live={status.variant === "error" ? "assertive" : "polite"}
|
|
59
|
+
>
|
|
60
|
+
{#if Icon}
|
|
61
|
+
<Icon size={14} class="shrink-0" />
|
|
62
|
+
{/if}
|
|
63
|
+
<span>{status.message}</span>
|
|
64
|
+
</p>
|
|
65
|
+
{/if}
|
|
66
|
+
{#if status.showHint}
|
|
67
|
+
<!-- Not a live region: a hint is there from the start and is read with the field. -->
|
|
68
|
+
<p id={fieldHintId(fieldId)} class={cn("text-sm text-description", gap)}>{hint}</p>
|
|
69
|
+
{/if}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type FieldMessageState } from "../util/field.js";
|
|
2
|
+
/**
|
|
3
|
+
* The text under a field: its status message and its hint. Internal: it is
|
|
4
|
+
* not exported from the package. Input, Textarea and Select render it, and
|
|
5
|
+
* DateField and TimeField through Input, so the markup, the ids and the
|
|
6
|
+
* way a message is announced are the same in all of them.
|
|
7
|
+
*
|
|
8
|
+
* The ids are the ones `fieldDescribedBy` lists on the control.
|
|
9
|
+
*/
|
|
10
|
+
interface Props {
|
|
11
|
+
/** Id of the control the text belongs to. */
|
|
12
|
+
fieldId: string;
|
|
13
|
+
/** From `fieldMessageState`. */
|
|
14
|
+
status: FieldMessageState;
|
|
15
|
+
hint?: string;
|
|
16
|
+
/** Distance from the control, and between the two: Textarea and Select sit 4px closer. */
|
|
17
|
+
gap?: "mt-1" | "mt-2";
|
|
18
|
+
/** Extra classes for the status message. */
|
|
19
|
+
messageClass?: string;
|
|
20
|
+
}
|
|
21
|
+
declare const FieldMessages: import("svelte").Component<Props, {}, "">;
|
|
22
|
+
type FieldMessages = ReturnType<typeof FieldMessages>;
|
|
23
|
+
export default FieldMessages;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Component } from "svelte";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
import Plus from "@lucide/svelte/icons/plus";
|
|
5
|
+
import { findScrollParent, isInsideAppShell } from "../util/app-shell.js";
|
|
6
|
+
import { cn } from "../util/cn.js";
|
|
7
|
+
import { reserveScrollPaddingBottom } from "../util/scroll-padding.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The one main thing to do on a screen, as a round button that floats over
|
|
11
|
+
* the content: new quiz, compose, add.
|
|
12
|
+
*
|
|
13
|
+
* Inside an `AppShell` it is placed against the shell, 16px above the tab
|
|
14
|
+
* bar. On its own it is fixed to the screen, 16px above the home
|
|
15
|
+
* indicator; if something else is fixed to the bottom there (a
|
|
16
|
+
* `BottomTabBar` on its own), say how tall it is with
|
|
17
|
+
* `--fab-bottom-offset` on the button or any ancestor:
|
|
18
|
+
*
|
|
19
|
+
* ```svelte
|
|
20
|
+
* <FloatingActionButton
|
|
21
|
+
* label="New quiz"
|
|
22
|
+
* onclick={create}
|
|
23
|
+
* style="--fab-bottom-offset: 64px"
|
|
24
|
+
* />
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* It lies over the content, so the last row would stay under it at the
|
|
28
|
+
* end of the page. Give the content room to scroll clear: `pb-24` (96px)
|
|
29
|
+
* on the list covers the button and its margins.
|
|
30
|
+
*
|
|
31
|
+
* While it is mounted it sets `scroll-padding-bottom` on what scrolls
|
|
32
|
+
* under it (the shell's content, or the page) to the height it takes
|
|
33
|
+
* from the bottom, so a row that takes keyboard focus is scrolled clear
|
|
34
|
+
* of the button and not left half under it.
|
|
35
|
+
*/
|
|
36
|
+
type Props = Omit<HTMLAttributes<HTMLElement>, "class"> & {
|
|
37
|
+
/** What the button does. Its accessible name, and its text when `extended`. */
|
|
38
|
+
label: string;
|
|
39
|
+
/** An icon component, as `@lucide/svelte` icons are. A plus sign by default. */
|
|
40
|
+
icon?: Component<{ size?: number; class?: string }>;
|
|
41
|
+
/** Shows the label as text beside the icon. */
|
|
42
|
+
extended?: boolean;
|
|
43
|
+
/** Makes it a link to this address. Without it, it is a button. */
|
|
44
|
+
href?: string;
|
|
45
|
+
/**
|
|
46
|
+
* The bottom corner it sits in. `bottom-end` is the right in a
|
|
47
|
+
* left-to-right page and the left in a right-to-left one.
|
|
48
|
+
*/
|
|
49
|
+
position?: "bottom-end" | "bottom-start" | "bottom-center";
|
|
50
|
+
class?: string;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
let {
|
|
54
|
+
label,
|
|
55
|
+
icon,
|
|
56
|
+
extended = false,
|
|
57
|
+
href,
|
|
58
|
+
position = "bottom-end",
|
|
59
|
+
class: className = "",
|
|
60
|
+
...restProps
|
|
61
|
+
}: Props = $props();
|
|
62
|
+
|
|
63
|
+
const inShell = isInsideAppShell();
|
|
64
|
+
const Icon = $derived(icon ?? Plus);
|
|
65
|
+
|
|
66
|
+
let host = $state<HTMLElement>();
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The browser scrolls a focused control into view, to the edge of the
|
|
70
|
+
* scroll container: under this button, which lies over that edge. The
|
|
71
|
+
* room it takes, from its top edge to the bottom of the container, is
|
|
72
|
+
* reserved through the helper the bars use, so the largest request wins.
|
|
73
|
+
*/
|
|
74
|
+
$effect(() => {
|
|
75
|
+
const button = host;
|
|
76
|
+
if (!button) return;
|
|
77
|
+
const scroller = findScrollParent(button);
|
|
78
|
+
const reservation = reserveScrollPaddingBottom(scroller ?? document.documentElement);
|
|
79
|
+
const reserve = () => {
|
|
80
|
+
const top = button.getBoundingClientRect().top;
|
|
81
|
+
const bottom = scroller
|
|
82
|
+
? scroller.getBoundingClientRect().bottom
|
|
83
|
+
: document.documentElement.clientHeight;
|
|
84
|
+
// No layout (a test DOM, a hidden button): nothing to keep clear of.
|
|
85
|
+
reservation.set(button.offsetHeight > 0 ? Math.max(0, Math.ceil(bottom - top)) : 0);
|
|
86
|
+
};
|
|
87
|
+
reserve();
|
|
88
|
+
const observer =
|
|
89
|
+
typeof ResizeObserver === "function" ? new ResizeObserver(reserve) : undefined;
|
|
90
|
+
observer?.observe(button);
|
|
91
|
+
if (scroller) observer?.observe(scroller);
|
|
92
|
+
window.addEventListener("resize", reserve);
|
|
93
|
+
return () => {
|
|
94
|
+
observer?.disconnect();
|
|
95
|
+
window.removeEventListener("resize", reserve);
|
|
96
|
+
reservation.release();
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 16px from the edges, in px: a margin that grew with the text size would
|
|
102
|
+
* push the button into the content it floats over. The side clears a
|
|
103
|
+
* notch in landscape, whichever side that is on.
|
|
104
|
+
*/
|
|
105
|
+
const positionClasses = $derived(
|
|
106
|
+
{
|
|
107
|
+
"bottom-end":
|
|
108
|
+
"end-[calc(16px+max(env(safe-area-inset-left,0px),env(safe-area-inset-right,0px)))]",
|
|
109
|
+
"bottom-start":
|
|
110
|
+
"start-[calc(16px+max(env(safe-area-inset-left,0px),env(safe-area-inset-right,0px)))]",
|
|
111
|
+
// Not `left-1/2` with a shift back: that leaves the button half
|
|
112
|
+
// the width to lay its label out in.
|
|
113
|
+
"bottom-center": "inset-x-0 mx-auto w-fit",
|
|
114
|
+
}[position] ??
|
|
115
|
+
"end-[calc(16px+max(env(safe-area-inset-left,0px),env(safe-area-inset-right,0px)))]",
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const classes = $derived(
|
|
119
|
+
cn(
|
|
120
|
+
"focus-ring z-sticky inline-flex cursor-pointer items-center justify-center gap-2 rounded-pill no-underline shadow-lg select-none",
|
|
121
|
+
// Round: 56px in px, like the 24px icon in it, so it does not
|
|
122
|
+
// double with the text size and cover twice the content.
|
|
123
|
+
// Extended: it holds text, so its height follows the text; it
|
|
124
|
+
// grows sideways, and downwards if the label wraps.
|
|
125
|
+
extended ? "min-h-14 min-w-14" : "size-[56px]",
|
|
126
|
+
// Transparent until forced-colors mode draws it: the fill is gone there.
|
|
127
|
+
"border border-transparent",
|
|
128
|
+
"bg-action-primary bg-control-gradient text-action-primary",
|
|
129
|
+
"transition-[background-color,scale] duration-(--duration-base) active:scale-[0.96] motion-reduce:transition-none motion-reduce:active:scale-100",
|
|
130
|
+
extended ? "px-5 py-2 text-sm font-medium" : "p-0",
|
|
131
|
+
// Never wider than the screen it floats on, margins included.
|
|
132
|
+
"[max-inline-size:calc(100%_-_32px)]",
|
|
133
|
+
inShell
|
|
134
|
+
? "absolute bottom-[calc(var(--app-shell-bottom-inset,0px)+var(--fab-bottom-offset,0px)+16px)]"
|
|
135
|
+
: "fixed bottom-[calc(env(safe-area-inset-bottom,0px)+var(--fab-bottom-offset,0px)+16px)]",
|
|
136
|
+
positionClasses,
|
|
137
|
+
className,
|
|
138
|
+
),
|
|
139
|
+
);
|
|
140
|
+
</script>
|
|
141
|
+
|
|
142
|
+
{#snippet content()}
|
|
143
|
+
<!-- Decorative: the label names the button, shown or not. -->
|
|
144
|
+
<span class="flex size-[24px] shrink-0" aria-hidden="true">
|
|
145
|
+
<Icon size={24} />
|
|
146
|
+
</span>
|
|
147
|
+
{#if extended}
|
|
148
|
+
<span class="min-w-0 [overflow-wrap:anywhere]">{label}</span>
|
|
149
|
+
{/if}
|
|
150
|
+
{/snippet}
|
|
151
|
+
|
|
152
|
+
{#if href !== undefined}
|
|
153
|
+
<a
|
|
154
|
+
bind:this={host}
|
|
155
|
+
{href}
|
|
156
|
+
class={classes}
|
|
157
|
+
aria-label={extended ? undefined : label}
|
|
158
|
+
data-position={position}
|
|
159
|
+
data-toast-clear
|
|
160
|
+
{...restProps}
|
|
161
|
+
>
|
|
162
|
+
{@render content()}
|
|
163
|
+
</a>
|
|
164
|
+
{:else}
|
|
165
|
+
<button
|
|
166
|
+
bind:this={host}
|
|
167
|
+
type="button"
|
|
168
|
+
class={classes}
|
|
169
|
+
aria-label={extended ? undefined : label}
|
|
170
|
+
data-position={position}
|
|
171
|
+
data-toast-clear
|
|
172
|
+
{...restProps}
|
|
173
|
+
>
|
|
174
|
+
{@render content()}
|
|
175
|
+
</button>
|
|
176
|
+
{/if}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Component } from "svelte";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
/**
|
|
4
|
+
* The one main thing to do on a screen, as a round button that floats over
|
|
5
|
+
* the content: new quiz, compose, add.
|
|
6
|
+
*
|
|
7
|
+
* Inside an `AppShell` it is placed against the shell, 16px above the tab
|
|
8
|
+
* bar. On its own it is fixed to the screen, 16px above the home
|
|
9
|
+
* indicator; if something else is fixed to the bottom there (a
|
|
10
|
+
* `BottomTabBar` on its own), say how tall it is with
|
|
11
|
+
* `--fab-bottom-offset` on the button or any ancestor:
|
|
12
|
+
*
|
|
13
|
+
* ```svelte
|
|
14
|
+
* <FloatingActionButton
|
|
15
|
+
* label="New quiz"
|
|
16
|
+
* onclick={create}
|
|
17
|
+
* style="--fab-bottom-offset: 64px"
|
|
18
|
+
* />
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* It lies over the content, so the last row would stay under it at the
|
|
22
|
+
* end of the page. Give the content room to scroll clear: `pb-24` (96px)
|
|
23
|
+
* on the list covers the button and its margins.
|
|
24
|
+
*
|
|
25
|
+
* While it is mounted it sets `scroll-padding-bottom` on what scrolls
|
|
26
|
+
* under it (the shell's content, or the page) to the height it takes
|
|
27
|
+
* from the bottom, so a row that takes keyboard focus is scrolled clear
|
|
28
|
+
* of the button and not left half under it.
|
|
29
|
+
*/
|
|
30
|
+
type Props = Omit<HTMLAttributes<HTMLElement>, "class"> & {
|
|
31
|
+
/** What the button does. Its accessible name, and its text when `extended`. */
|
|
32
|
+
label: string;
|
|
33
|
+
/** An icon component, as `@lucide/svelte` icons are. A plus sign by default. */
|
|
34
|
+
icon?: Component<{
|
|
35
|
+
size?: number;
|
|
36
|
+
class?: string;
|
|
37
|
+
}>;
|
|
38
|
+
/** Shows the label as text beside the icon. */
|
|
39
|
+
extended?: boolean;
|
|
40
|
+
/** Makes it a link to this address. Without it, it is a button. */
|
|
41
|
+
href?: string;
|
|
42
|
+
/**
|
|
43
|
+
* The bottom corner it sits in. `bottom-end` is the right in a
|
|
44
|
+
* left-to-right page and the left in a right-to-left one.
|
|
45
|
+
*/
|
|
46
|
+
position?: "bottom-end" | "bottom-start" | "bottom-center";
|
|
47
|
+
class?: string;
|
|
48
|
+
};
|
|
49
|
+
declare const FloatingActionButton: Component<Props, {}, "">;
|
|
50
|
+
type FloatingActionButton = ReturnType<typeof FloatingActionButton>;
|
|
51
|
+
export default FloatingActionButton;
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import type { Snippet } from "svelte";
|
|
3
3
|
import type { HTMLAttributes } from "svelte/elements";
|
|
4
4
|
import { cn } from "../util/cn.js";
|
|
5
|
+
import type { OnFillTone } from "../types/variants.js";
|
|
6
|
+
import { displayVoice } from "../util/display-voice.js";
|
|
5
7
|
|
|
6
8
|
/** Semantic heading level — also the default visual size. */
|
|
7
9
|
type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
@@ -16,6 +18,19 @@
|
|
|
16
18
|
size?: HeadingLevel;
|
|
17
19
|
/** Heading text. Ignored when `children` is provided. */
|
|
18
20
|
text?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Text colour. `headline` (the default) is for a page or a card. On a
|
|
23
|
+
* filled block use `inherit` (the block's own colour), `on-brand` or
|
|
24
|
+
* `on-accent`.
|
|
25
|
+
*/
|
|
26
|
+
tone?: "headline" | OnFillTone;
|
|
27
|
+
/**
|
|
28
|
+
* `heading` is the document heading voice. `display` is the second
|
|
29
|
+
* face (`--font-family-display`) with larger steps, for a hero, a
|
|
30
|
+
* score or a big number; its weight and tracking are the custom
|
|
31
|
+
* properties `--zabi-display-weight` and `--zabi-display-tracking`.
|
|
32
|
+
*/
|
|
33
|
+
variant?: "heading" | "display";
|
|
19
34
|
class?: string;
|
|
20
35
|
children?: Snippet;
|
|
21
36
|
};
|
|
@@ -24,13 +39,21 @@
|
|
|
24
39
|
level = 1,
|
|
25
40
|
size,
|
|
26
41
|
text = "",
|
|
42
|
+
tone = "headline",
|
|
43
|
+
variant = "heading",
|
|
27
44
|
class: className = "",
|
|
28
45
|
children,
|
|
29
46
|
...restProps
|
|
30
47
|
}: Props = $props();
|
|
31
48
|
|
|
49
|
+
const toneClasses: Record<"headline" | OnFillTone, string> = {
|
|
50
|
+
headline: "text-headline",
|
|
51
|
+
inherit: "text-inherit",
|
|
52
|
+
"on-brand": "text-on-brand",
|
|
53
|
+
"on-accent": "text-on-accent",
|
|
54
|
+
};
|
|
55
|
+
|
|
32
56
|
const visualSize = $derived(size ?? level);
|
|
33
|
-
const Tag = $derived(`h${level}`);
|
|
34
57
|
|
|
35
58
|
/**
|
|
36
59
|
* Display sizes tighten as they grow. Untracked 36px type with default
|
|
@@ -47,21 +70,56 @@
|
|
|
47
70
|
6: "text-base leading-6 font-semibold",
|
|
48
71
|
};
|
|
49
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Display steps: 60px (48 on a phone), 48 (36), 36 (30), 30, 24, 20. Weight and tracking come from
|
|
75
|
+
* `displayVoice`, so no size carries its own.
|
|
76
|
+
*/
|
|
77
|
+
const displaySizeClasses: Record<HeadingLevel, string> = {
|
|
78
|
+
1: "text-5xl sm:text-6xl leading-[1.0]",
|
|
79
|
+
2: "text-4xl sm:text-5xl leading-[1.05]",
|
|
80
|
+
3: "text-3xl sm:text-4xl leading-[1.1]",
|
|
81
|
+
4: "text-3xl leading-[1.2]",
|
|
82
|
+
5: "text-2xl leading-[1.2]",
|
|
83
|
+
6: "text-xl leading-[1.2]",
|
|
84
|
+
};
|
|
85
|
+
|
|
50
86
|
const headingClasses = $derived(
|
|
51
|
-
|
|
87
|
+
variant === "display"
|
|
88
|
+
? cn(
|
|
89
|
+
`${toneClasses[tone] ?? toneClasses.headline} font-display text-balance ${displayVoice} ${displaySizeClasses[visualSize] ?? displaySizeClasses[6]} ${className}`,
|
|
90
|
+
)
|
|
91
|
+
: cn(`${toneClasses[tone] ?? toneClasses.headline} ${sizeClasses[visualSize] ?? sizeClasses[6]} ${className}`),
|
|
52
92
|
);
|
|
53
93
|
</script>
|
|
54
94
|
|
|
55
95
|
<!--
|
|
56
|
-
The font family comes from `--font-family-
|
|
96
|
+
The font family comes from `--font-family-heading`, which the theme applies
|
|
97
|
+
to h1–h6 in its base layer and which defaults to `--font-family-sans`. This
|
|
57
98
|
component used to carry its own `font-family: "Nunito Sans"` in a local
|
|
58
99
|
<style> block, which meant a consumer who rebranded the font token got a
|
|
59
100
|
rebranded body and Nunito Sans headings.
|
|
60
101
|
-->
|
|
61
|
-
|
|
102
|
+
{#snippet content()}
|
|
62
103
|
{#if children}
|
|
63
104
|
{@render children()}
|
|
64
105
|
{:else}
|
|
65
106
|
{text}
|
|
66
107
|
{/if}
|
|
67
|
-
|
|
108
|
+
{/snippet}
|
|
109
|
+
|
|
110
|
+
<!-- One branch per level, not a dynamic element: hydration takes a dynamic
|
|
111
|
+
element out and puts it back, which blurs a control inside it that the user
|
|
112
|
+
had already tabbed to. -->
|
|
113
|
+
{#if level === 1}
|
|
114
|
+
<h1 class={headingClasses} {...restProps}>{@render content()}</h1>
|
|
115
|
+
{:else if level === 2}
|
|
116
|
+
<h2 class={headingClasses} {...restProps}>{@render content()}</h2>
|
|
117
|
+
{:else if level === 3}
|
|
118
|
+
<h3 class={headingClasses} {...restProps}>{@render content()}</h3>
|
|
119
|
+
{:else if level === 4}
|
|
120
|
+
<h4 class={headingClasses} {...restProps}>{@render content()}</h4>
|
|
121
|
+
{:else if level === 5}
|
|
122
|
+
<h5 class={headingClasses} {...restProps}>{@render content()}</h5>
|
|
123
|
+
{:else}
|
|
124
|
+
<h6 class={headingClasses} {...restProps}>{@render content()}</h6>
|
|
125
|
+
{/if}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Snippet } from "svelte";
|
|
2
2
|
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
import type { OnFillTone } from "../types/variants.js";
|
|
3
4
|
/** Semantic heading level — also the default visual size. */
|
|
4
5
|
type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
5
6
|
type Props = Omit<HTMLAttributes<HTMLHeadingElement>, "class"> & {
|
|
@@ -12,6 +13,19 @@ type Props = Omit<HTMLAttributes<HTMLHeadingElement>, "class"> & {
|
|
|
12
13
|
size?: HeadingLevel;
|
|
13
14
|
/** Heading text. Ignored when `children` is provided. */
|
|
14
15
|
text?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Text colour. `headline` (the default) is for a page or a card. On a
|
|
18
|
+
* filled block use `inherit` (the block's own colour), `on-brand` or
|
|
19
|
+
* `on-accent`.
|
|
20
|
+
*/
|
|
21
|
+
tone?: "headline" | OnFillTone;
|
|
22
|
+
/**
|
|
23
|
+
* `heading` is the document heading voice. `display` is the second
|
|
24
|
+
* face (`--font-family-display`) with larger steps, for a hero, a
|
|
25
|
+
* score or a big number; its weight and tracking are the custom
|
|
26
|
+
* properties `--zabi-display-weight` and `--zabi-display-tracking`.
|
|
27
|
+
*/
|
|
28
|
+
variant?: "heading" | "display";
|
|
15
29
|
class?: string;
|
|
16
30
|
children?: Snippet;
|
|
17
31
|
};
|