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,157 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
import { type AppShellNavigationContext, type AppShellNavigationMode } from "../util/app-shell.js";
|
|
4
|
+
/**
|
|
5
|
+
* The layout of a phone app: a bar at the top, content that scrolls, a
|
|
6
|
+
* tab bar at the bottom, and none of it under the notch or the home
|
|
7
|
+
* indicator.
|
|
8
|
+
*
|
|
9
|
+
* The shell is exactly as tall as the visible screen (`100dvh`, so the
|
|
10
|
+
* browser's own bars are accounted for) and only the middle scrolls. The
|
|
11
|
+
* header stays at the top of that scrolling area. The footer lies over
|
|
12
|
+
* the bottom of it, so content passes beneath both bars: they are the
|
|
13
|
+
* page colour at rest and turn to glass once content is under them.
|
|
14
|
+
*
|
|
15
|
+
* ```svelte
|
|
16
|
+
* <AppShell>
|
|
17
|
+
* {#snippet header()}
|
|
18
|
+
* <AppBar title="Quizrundan" collapseOnScroll />
|
|
19
|
+
* {/snippet}
|
|
20
|
+
* <div class="p-4">…</div>
|
|
21
|
+
* {#snippet footer()}
|
|
22
|
+
* <BottomTabBar {items} active={page.url.pathname} />
|
|
23
|
+
* {/snippet}
|
|
24
|
+
* </AppShell>
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* Two custom properties on the host say how much of the screen the bars
|
|
28
|
+
* take, safe areas included, so anything inside the shell can stay clear
|
|
29
|
+
* of them:
|
|
30
|
+
*
|
|
31
|
+
* - `--app-shell-top-inset`: the height of the header (with an `AppBar`
|
|
32
|
+
* `largeTitle`, the height it condenses to);
|
|
33
|
+
* - `--app-shell-bottom-inset`: the height of the footer.
|
|
34
|
+
*
|
|
35
|
+
* Without a bar the value is the safe-area inset alone. With a footer the
|
|
36
|
+
* content takes the bottom inset as padding and the scroller as
|
|
37
|
+
* `scroll-padding-bottom`, so the end of the content and a focused field
|
|
38
|
+
* clear the footer.
|
|
39
|
+
*
|
|
40
|
+
* A third, on the scroller, is for what sits in the content and has to
|
|
41
|
+
* stay above the footer (`StickyActionBar` and `UnsavedChangesBar` read it):
|
|
42
|
+
*
|
|
43
|
+
* - `--app-shell-footer-overlay`: the bottom inset when a footer lies over
|
|
44
|
+
* the scroller, `0px` when there is no footer.
|
|
45
|
+
*
|
|
46
|
+
* The host also says where content is: `data-scrolled-top="true"` once it
|
|
47
|
+
* has scrolled under the header, `data-scrolled-bottom="true"` while it
|
|
48
|
+
* passes under the footer (both `"false"` on the server and before the
|
|
49
|
+
* first measurement). The bars read the same state.
|
|
50
|
+
*
|
|
51
|
+
* To let the consumer choose what stays, compose the header from
|
|
52
|
+
* `AppShellHeaderPart`s: each says `sticky` (the default) or `sticky={false}`
|
|
53
|
+
* and scrolls away with the content, so a bar can leave while the filter
|
|
54
|
+
* row stays, or a large title can go while the bar and the tabs stay. The
|
|
55
|
+
* shell measures the parts to stack the ones that stick, reports only
|
|
56
|
+
* what is stuck as `--app-shell-top-inset` and `scroll-padding-top`, and
|
|
57
|
+
* puts the glass and the hairline under the lowest one. Without parts the
|
|
58
|
+
* header is one block that sticks, as before.
|
|
59
|
+
*
|
|
60
|
+
* With `canvas` the shell is painted with the page colour and the brand
|
|
61
|
+
* wash (`bg-canvas`), and the header bar rests transparent so the wash
|
|
62
|
+
* shows through it.
|
|
63
|
+
*
|
|
64
|
+
* The host is the containing block for anything positioned inside it, and such an element
|
|
65
|
+
* does not scroll with the content, so a floating button above the tab bar
|
|
66
|
+
* is `absolute` with `bottom: calc(var(--app-shell-bottom-inset) + 1rem)`.
|
|
67
|
+
*
|
|
68
|
+
* While the shell is mounted the same two properties are also set on
|
|
69
|
+
* `<html>`, so an overlay that is moved to `document.body` (a sheet, a
|
|
70
|
+
* toast) can read them too. With more than one shell on the page, the one
|
|
71
|
+
* mounted last is the one mirrored there.
|
|
72
|
+
*
|
|
73
|
+
* With `navigation` the shell holds one navigation that is drawn as tabs
|
|
74
|
+
* over the bottom of the screen on a phone, a rail on a tablet and a
|
|
75
|
+
* sidebar on a desktop, and the app writes one layout, not three
|
|
76
|
+
* (`AppNavigation` is the ready-made content). The snippet is rendered
|
|
77
|
+
* once and only CSS moves it, so the server's markup is right at every
|
|
78
|
+
* width and nothing jumps when scripts load. As tabs it lies over the
|
|
79
|
+
* bottom like `footer` (the footer then sits directly above it); as a
|
|
80
|
+
* rail or sidebar it is a full-height column at the inline start, and the
|
|
81
|
+
* header, content and footer take the rest. The host says which with
|
|
82
|
+
* `data-navigation-placement`, and the bottom inset counts the tabs, so a
|
|
83
|
+
* sticky action bar or a floating button clears them too.
|
|
84
|
+
*
|
|
85
|
+
* ```svelte
|
|
86
|
+
* <AppShell>
|
|
87
|
+
* {#snippet header()}<AppBar title="Quizrundan" largeTitle />{/snippet}
|
|
88
|
+
* {#snippet navigation()}<AppNavigation {items} active={page.url.pathname} />{/snippet}
|
|
89
|
+
* <div class="p-4">…</div>
|
|
90
|
+
* </AppShell>
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* One more custom property: `--app-shell-start-inset`, the width of the
|
|
94
|
+
* rail or sidebar (`0px` as tabs), also mirrored onto `<html>`.
|
|
95
|
+
*
|
|
96
|
+
* With `flushTop` and no `header` the content starts at the top edge of
|
|
97
|
+
* the screen, under the status bar, so a block of colour at the top of it
|
|
98
|
+
* can run there. The content then handles the safe area itself: pad by
|
|
99
|
+
* `--app-shell-top-inset`, or let an `AppBar position="static"` in the
|
|
100
|
+
* block do it.
|
|
101
|
+
*/
|
|
102
|
+
type Props = Omit<HTMLAttributes<HTMLDivElement>, "class" | "style"> & {
|
|
103
|
+
/**
|
|
104
|
+
* The top bar, an `AppBar`. It handles the safe area above it. Or
|
|
105
|
+
* several `AppShellHeaderPart`s, each of which sticks or scrolls away.
|
|
106
|
+
*/
|
|
107
|
+
header?: Snippet;
|
|
108
|
+
/** The scrolling content, rendered in the element `contentElement` names. */
|
|
109
|
+
children?: Snippet;
|
|
110
|
+
/**
|
|
111
|
+
* The element around the content. `main` when the shell is the page,
|
|
112
|
+
* which is what it is for. A page has one `<main>`: use `div` for a
|
|
113
|
+
* shell that sits inside another one, such as a preview in a page of
|
|
114
|
+
* its own.
|
|
115
|
+
*/
|
|
116
|
+
contentElement?: "main" | "div";
|
|
117
|
+
/**
|
|
118
|
+
* The bottom bar, a `BottomTabBar`. It lies over the bottom of the
|
|
119
|
+
* scrolling area and handles the safe area below it.
|
|
120
|
+
*/
|
|
121
|
+
footer?: Snippet;
|
|
122
|
+
/**
|
|
123
|
+
* Paints the shell with the page colour and the brand wash (`bg-canvas`)
|
|
124
|
+
* instead of the plain page colour, and lets the wash show through the
|
|
125
|
+
* header bar at rest.
|
|
126
|
+
*/
|
|
127
|
+
canvas?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* One navigation, drawn as tabs, a rail or a sidebar by
|
|
130
|
+
* `navigationPlacement`. Rendered once, first in the DOM: the Tab order
|
|
131
|
+
* is navigation, header, content. `placement` is the forced value, or
|
|
132
|
+
* in `auto` what the viewport says once mounted (`tabs` on the server
|
|
133
|
+
* and before mount); use it only to render different markup per
|
|
134
|
+
* placement, since the layout itself is CSS and right without it.
|
|
135
|
+
*/
|
|
136
|
+
navigation?: Snippet<[AppShellNavigationContext]>;
|
|
137
|
+
/**
|
|
138
|
+
* Where the `navigation` goes. `auto` follows the viewport in CSS:
|
|
139
|
+
* tabs below 48rem (768px), a rail from 48rem, a sidebar from 64rem
|
|
140
|
+
* (1024px). The others apply at every width.
|
|
141
|
+
*/
|
|
142
|
+
navigationPlacement?: AppShellNavigationMode;
|
|
143
|
+
/**
|
|
144
|
+
* Without a `header`, leaves out the padding the content has for the
|
|
145
|
+
* status bar and the notch, so it starts at the top of the screen and
|
|
146
|
+
* handles the safe area itself. `--app-shell-top-inset` keeps its
|
|
147
|
+
* value. With a `header` it does nothing: the header covers the safe
|
|
148
|
+
* area.
|
|
149
|
+
*/
|
|
150
|
+
flushTop?: boolean;
|
|
151
|
+
class?: string;
|
|
152
|
+
/** Added after the two custom properties the shell sets. */
|
|
153
|
+
style?: string;
|
|
154
|
+
};
|
|
155
|
+
declare const AppShell: import("svelte").Component<Props, {}, "">;
|
|
156
|
+
type AppShell = ReturnType<typeof AppShell>;
|
|
157
|
+
export default AppShell;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from "svelte";
|
|
3
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
4
|
+
import { getAppShell, markAppShell } from "../util/app-shell.js";
|
|
5
|
+
import { cn } from "../util/cn.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* One part of an `AppShell` header, and the choice of whether it stays at
|
|
9
|
+
* the top of the screen or scrolls away with the content.
|
|
10
|
+
*
|
|
11
|
+
* Put the parts side by side in the shell's `header` snippet, in the order
|
|
12
|
+
* they are drawn: an `AppBar`, a search field, a row of filter chips,
|
|
13
|
+
* tabs, anything. The shell leaves a header without parts as it was (the
|
|
14
|
+
* whole header sticks).
|
|
15
|
+
*
|
|
16
|
+
* ```svelte
|
|
17
|
+
* <AppShell>
|
|
18
|
+
* {#snippet header()}
|
|
19
|
+
* <AppShellHeaderPart sticky={false}><AppBar title="Quizzes" /></AppShellHeaderPart>
|
|
20
|
+
* <AppShellHeaderPart class="px-4 py-2"><FilterChips /></AppShellHeaderPart>
|
|
21
|
+
* {/snippet}
|
|
22
|
+
* …
|
|
23
|
+
* </AppShell>
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* A part that sticks is in the flow like any other, so nothing is measured
|
|
27
|
+
* to make a part that does not stick leave: it is content. Parts that
|
|
28
|
+
* stick stack under one another in the order of the document, with no gap
|
|
29
|
+
* and no overlap, however many parts that do not stick are between them.
|
|
30
|
+
* The shell measures the heights to place them, and reports only what
|
|
31
|
+
* covers content at that moment as `--app-shell-top-inset` (so
|
|
32
|
+
* `scroll-padding-top`, a focused field and an anchor clear exactly the
|
|
33
|
+
* stuck parts).
|
|
34
|
+
*
|
|
35
|
+
* The parts look like one surface: the page colour at rest, glass and one
|
|
36
|
+
* hairline under the lowest stuck part once content is under it. The
|
|
37
|
+
* status bar is covered by whatever is topmost: an `AppBar` pads for it
|
|
38
|
+
* itself, any other first part gets the padding, and a part that sticks
|
|
39
|
+
* further down has a strip of the same surface above it.
|
|
40
|
+
*
|
|
41
|
+
* Keep the parts that stick short: with more than 40% of the screen
|
|
42
|
+
* covered (landscape, 200% text), the lower ones stop sticking and scroll
|
|
43
|
+
* with the content (`data-released`).
|
|
44
|
+
*
|
|
45
|
+
* An `AppBar` with `largeTitle` condenses inside its part as it does in a
|
|
46
|
+
* header without parts. `collapseOnScroll` is for a header without parts;
|
|
47
|
+
* in a part that sticks it leaves its space behind.
|
|
48
|
+
*/
|
|
49
|
+
type Props = Omit<HTMLAttributes<HTMLDivElement>, "class"> & {
|
|
50
|
+
/** The part's content. */
|
|
51
|
+
children?: Snippet;
|
|
52
|
+
/**
|
|
53
|
+
* Stays at the top of the screen under the parts that stick above it
|
|
54
|
+
* (`true`, the default), or scrolls away with the content (`false`).
|
|
55
|
+
*/
|
|
56
|
+
sticky?: boolean;
|
|
57
|
+
class?: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
let { children, sticky = true, class: className = "", ...restProps }: Props = $props();
|
|
61
|
+
|
|
62
|
+
const shell = getAppShell();
|
|
63
|
+
|
|
64
|
+
/** How far this part sticks above the top: a large title's row (px), told by the `AppBar` inside it. */
|
|
65
|
+
let overscroll = $state(0);
|
|
66
|
+
|
|
67
|
+
// The bars inside report to this part, not to the shell: the part is the thing that sticks.
|
|
68
|
+
if (shell) {
|
|
69
|
+
markAppShell({
|
|
70
|
+
get scrolledTop() {
|
|
71
|
+
return shell.scrolledTop;
|
|
72
|
+
},
|
|
73
|
+
get scrolledBottom() {
|
|
74
|
+
return shell.scrolledBottom;
|
|
75
|
+
},
|
|
76
|
+
get footerOverlays() {
|
|
77
|
+
return shell.footerOverlays;
|
|
78
|
+
},
|
|
79
|
+
get footerHeight() {
|
|
80
|
+
return shell.footerHeight;
|
|
81
|
+
},
|
|
82
|
+
get navigationPlacement() {
|
|
83
|
+
return shell.navigationPlacement;
|
|
84
|
+
},
|
|
85
|
+
setHeaderOverscroll(px) {
|
|
86
|
+
overscroll = px > 0 ? px : 0;
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<!-- The glass and the hairline are the bar surface (`material-bar`). It is left
|
|
93
|
+
off a part that holds an `AppBar`, which has its own; the stylesheet below also
|
|
94
|
+
takes the hairline off every stuck part but the lowest. -->
|
|
95
|
+
<div
|
|
96
|
+
data-app-shell-part
|
|
97
|
+
data-sticky={String(sticky)}
|
|
98
|
+
data-overscroll={overscroll > 0 ? overscroll : undefined}
|
|
99
|
+
data-scrolled-under={sticky ? String(shell?.scrolledTop ?? false) : undefined}
|
|
100
|
+
class={cn("shrink-0", sticky && "material-bar", className)}
|
|
101
|
+
{...restProps}
|
|
102
|
+
>
|
|
103
|
+
{@render children?.()}
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
<style>
|
|
107
|
+
/*
|
|
108
|
+
* Global on purpose: the rules read the shell's own markup (the header
|
|
109
|
+
* wrapper, the strip) and the part's siblings, and a scoped class would
|
|
110
|
+
* not reach an AppBar inside it.
|
|
111
|
+
*
|
|
112
|
+
* A part that sticks. The offset is written by the shell once it has
|
|
113
|
+
* measured (`--app-shell-part-top`); until then, on the server and without
|
|
114
|
+
* scripts, the first part sticks at 0 (it is the top, or an AppBar that
|
|
115
|
+
* pads the status bar itself) or under the status bar strip, and a later
|
|
116
|
+
* one under an estimate of an AppBar.
|
|
117
|
+
*/
|
|
118
|
+
:global([data-app-shell-part][data-sticky="true"]:not([data-released])) {
|
|
119
|
+
position: sticky;
|
|
120
|
+
z-index: var(--z-sticky);
|
|
121
|
+
top: var(--app-shell-part-top, env(safe-area-inset-top, 0px));
|
|
122
|
+
}
|
|
123
|
+
:global([data-app-shell-header] > [data-app-shell-part][data-sticky="true"]:not([data-released]):first-child),
|
|
124
|
+
:global([data-app-shell-part][data-sticky="true"]:not([data-released]):has([data-appbar])) {
|
|
125
|
+
top: var(--app-shell-part-top, 0px);
|
|
126
|
+
}
|
|
127
|
+
:global(
|
|
128
|
+
[data-app-shell-part][data-sticky="true"]:not([data-released])
|
|
129
|
+
~ [data-app-shell-part][data-sticky="true"]:not([data-released])
|
|
130
|
+
) {
|
|
131
|
+
top: var(--app-shell-part-top, calc(56px + env(safe-area-inset-top, 0px)));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Released on a short screen: the surface goes with the stickiness. */
|
|
135
|
+
:global([data-app-shell-part][data-released]::before) {
|
|
136
|
+
display: none;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* An AppBar inside has the surface already. */
|
|
140
|
+
:global([data-app-shell-part]:has([data-appbar])::before) {
|
|
141
|
+
display: none;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* One surface, one hairline: only the lowest stuck part draws it (in forced colours too). */
|
|
145
|
+
:global(
|
|
146
|
+
[data-app-shell-part][data-sticky="true"]:not([data-released]):has(
|
|
147
|
+
~ [data-app-shell-part][data-sticky="true"]:not([data-released])
|
|
148
|
+
)::before
|
|
149
|
+
),
|
|
150
|
+
:global(
|
|
151
|
+
[data-app-shell-part][data-sticky="true"]:not([data-released]):has(
|
|
152
|
+
~ [data-app-shell-part][data-sticky="true"]:not([data-released])
|
|
153
|
+
)
|
|
154
|
+
.material-bar::before
|
|
155
|
+
) {
|
|
156
|
+
border-color: transparent !important;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* The first part reaches the top of the screen: it clears the status bar, unless an AppBar does. */
|
|
160
|
+
:global([data-app-shell-header] > [data-app-shell-part]:first-child:not(:has([data-appbar]))) {
|
|
161
|
+
padding-top: env(safe-area-inset-top, 0px);
|
|
162
|
+
}
|
|
163
|
+
</style>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
/**
|
|
4
|
+
* One part of an `AppShell` header, and the choice of whether it stays at
|
|
5
|
+
* the top of the screen or scrolls away with the content.
|
|
6
|
+
*
|
|
7
|
+
* Put the parts side by side in the shell's `header` snippet, in the order
|
|
8
|
+
* they are drawn: an `AppBar`, a search field, a row of filter chips,
|
|
9
|
+
* tabs, anything. The shell leaves a header without parts as it was (the
|
|
10
|
+
* whole header sticks).
|
|
11
|
+
*
|
|
12
|
+
* ```svelte
|
|
13
|
+
* <AppShell>
|
|
14
|
+
* {#snippet header()}
|
|
15
|
+
* <AppShellHeaderPart sticky={false}><AppBar title="Quizzes" /></AppShellHeaderPart>
|
|
16
|
+
* <AppShellHeaderPart class="px-4 py-2"><FilterChips /></AppShellHeaderPart>
|
|
17
|
+
* {/snippet}
|
|
18
|
+
* …
|
|
19
|
+
* </AppShell>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* A part that sticks is in the flow like any other, so nothing is measured
|
|
23
|
+
* to make a part that does not stick leave: it is content. Parts that
|
|
24
|
+
* stick stack under one another in the order of the document, with no gap
|
|
25
|
+
* and no overlap, however many parts that do not stick are between them.
|
|
26
|
+
* The shell measures the heights to place them, and reports only what
|
|
27
|
+
* covers content at that moment as `--app-shell-top-inset` (so
|
|
28
|
+
* `scroll-padding-top`, a focused field and an anchor clear exactly the
|
|
29
|
+
* stuck parts).
|
|
30
|
+
*
|
|
31
|
+
* The parts look like one surface: the page colour at rest, glass and one
|
|
32
|
+
* hairline under the lowest stuck part once content is under it. The
|
|
33
|
+
* status bar is covered by whatever is topmost: an `AppBar` pads for it
|
|
34
|
+
* itself, any other first part gets the padding, and a part that sticks
|
|
35
|
+
* further down has a strip of the same surface above it.
|
|
36
|
+
*
|
|
37
|
+
* Keep the parts that stick short: with more than 40% of the screen
|
|
38
|
+
* covered (landscape, 200% text), the lower ones stop sticking and scroll
|
|
39
|
+
* with the content (`data-released`).
|
|
40
|
+
*
|
|
41
|
+
* An `AppBar` with `largeTitle` condenses inside its part as it does in a
|
|
42
|
+
* header without parts. `collapseOnScroll` is for a header without parts;
|
|
43
|
+
* in a part that sticks it leaves its space behind.
|
|
44
|
+
*/
|
|
45
|
+
type Props = Omit<HTMLAttributes<HTMLDivElement>, "class"> & {
|
|
46
|
+
/** The part's content. */
|
|
47
|
+
children?: Snippet;
|
|
48
|
+
/**
|
|
49
|
+
* Stays at the top of the screen under the parts that stick above it
|
|
50
|
+
* (`true`, the default), or scrolls away with the content (`false`).
|
|
51
|
+
*/
|
|
52
|
+
sticky?: boolean;
|
|
53
|
+
class?: string;
|
|
54
|
+
};
|
|
55
|
+
declare const AppShellHeaderPart: import("svelte").Component<Props, {}, "">;
|
|
56
|
+
type AppShellHeaderPart = ReturnType<typeof AppShellHeaderPart>;
|
|
57
|
+
export default AppShellHeaderPart;
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { mergeStrings } from "../util/ready-made-strings.js";
|
|
3
|
+
import { zabiStringsFor } from "../util/zabi-strings.js";
|
|
2
4
|
import SidebarPanel, {
|
|
3
5
|
type SidebarPanelItem,
|
|
4
6
|
} from "./SidebarPanel.svelte";
|
|
5
7
|
import { generateId } from "../util/ssr-safe.js";
|
|
6
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
DEFAULT_SIDEBAR_ACCOUNT_PANEL_STRINGS,
|
|
10
|
+
type SidebarAccountPanelStrings,
|
|
11
|
+
} from "../util/sidebar.js";
|
|
12
|
+
import {
|
|
13
|
+
getThemeMode,
|
|
14
|
+
isThemeDark,
|
|
15
|
+
setThemeMode,
|
|
16
|
+
THEME_MODES,
|
|
17
|
+
type ThemeMode,
|
|
18
|
+
} from "../util/theme-mode.js";
|
|
19
|
+
import LogOut from "@lucide/svelte/icons/log-out";
|
|
20
|
+
import Monitor from "@lucide/svelte/icons/monitor";
|
|
21
|
+
import Moon from "@lucide/svelte/icons/moon";
|
|
22
|
+
import Sun from "@lucide/svelte/icons/sun";
|
|
23
|
+
import User from "@lucide/svelte/icons/user";
|
|
7
24
|
|
|
8
25
|
interface Props {
|
|
9
26
|
/** Extra classes for the host element. */
|
|
@@ -18,6 +35,23 @@
|
|
|
18
35
|
showLogout?: boolean;
|
|
19
36
|
isLightMode?: boolean;
|
|
20
37
|
onThemeToggle?: (nextIsLightMode: boolean) => void;
|
|
38
|
+
/**
|
|
39
|
+
* `"two"` (the default): the theme row flips `isLightMode` and calls
|
|
40
|
+
* `onThemeToggle`; the app switches the page. `"three"`: the row
|
|
41
|
+
* steps through system, light and dark, switches the page itself
|
|
42
|
+
* (`data-theme` on `<html>`, as ThemeToggle does) and calls
|
|
43
|
+
* `onThemeModeChange`.
|
|
44
|
+
*/
|
|
45
|
+
themeModes?: "two" | "three";
|
|
46
|
+
/** With `themeModes="three"`: called with the mode the row has switched to. */
|
|
47
|
+
onThemeModeChange?: (mode: ThemeMode) => void;
|
|
48
|
+
/**
|
|
49
|
+
* With `themeModes="three"`: the `localStorage` key the choice is kept
|
|
50
|
+
* under. Default `"theme"`, as ThemeToggle; `null` keeps nothing.
|
|
51
|
+
*/
|
|
52
|
+
themeStorageKey?: string | null;
|
|
53
|
+
/** Every word the panel says by itself, for another language. `logoutLabel` is its own prop. */
|
|
54
|
+
strings?: Partial<SidebarAccountPanelStrings>;
|
|
21
55
|
onLogout?: () => void;
|
|
22
56
|
onAccount?: () => void;
|
|
23
57
|
onClose?: () => void;
|
|
@@ -34,8 +68,12 @@
|
|
|
34
68
|
logoutLabel = "Log out",
|
|
35
69
|
showThemeToggle = true,
|
|
36
70
|
showLogout = true,
|
|
37
|
-
isLightMode = $bindable(
|
|
71
|
+
isLightMode = $bindable<Exclude<Props["isLightMode"], undefined>>(),
|
|
38
72
|
onThemeToggle,
|
|
73
|
+
themeModes = "two",
|
|
74
|
+
onThemeModeChange,
|
|
75
|
+
themeStorageKey,
|
|
76
|
+
strings,
|
|
39
77
|
onLogout,
|
|
40
78
|
onAccount,
|
|
41
79
|
onClose,
|
|
@@ -44,24 +82,70 @@
|
|
|
44
82
|
...restProps
|
|
45
83
|
}: Props = $props();
|
|
46
84
|
|
|
85
|
+
// No fallback on a bindable prop: Svelte refuses `bind:…={undefined}` on
|
|
86
|
+
// one that has a fallback (`props_invalid_value`), and a page that throws
|
|
87
|
+
// while it hydrates never becomes interactive. The default is applied
|
|
88
|
+
// here instead: at once, for the server and the first render, and again
|
|
89
|
+
// whenever a parent hands back `undefined`.
|
|
90
|
+
const applyDefaults = () => {
|
|
91
|
+
if (isLightMode === undefined) isLightMode = false;
|
|
92
|
+
};
|
|
93
|
+
applyDefaults();
|
|
94
|
+
$effect.pre(applyDefaults);
|
|
95
|
+
|
|
47
96
|
let selectedItemId = $state("");
|
|
48
97
|
|
|
98
|
+
/** The app-wide words for this component, from a `ZabiStringsProvider` above it, if there is one. */
|
|
99
|
+
const provided = zabiStringsFor("sidebarAccountPanel");
|
|
100
|
+
const text = $derived(mergeStrings(DEFAULT_SIDEBAR_ACCOUNT_PANEL_STRINGS, provided(), strings));
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* With three modes: the page's mode, read when the panel mounts, after
|
|
104
|
+
* each step, and when something else switches the page (a ThemeToggle in
|
|
105
|
+
* the bar, the app's own script) while the panel is there.
|
|
106
|
+
*/
|
|
107
|
+
let themeMode = $state<ThemeMode>("light");
|
|
108
|
+
$effect(() => {
|
|
109
|
+
if (themeModes !== "three") return;
|
|
110
|
+
themeMode = getThemeMode();
|
|
111
|
+
if (typeof MutationObserver === "undefined") return;
|
|
112
|
+
const observer = new MutationObserver(() => {
|
|
113
|
+
themeMode = getThemeMode();
|
|
114
|
+
});
|
|
115
|
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class", "data-theme"] });
|
|
116
|
+
return () => observer.disconnect();
|
|
117
|
+
});
|
|
118
|
+
|
|
49
119
|
const items = $derived.by((): SidebarPanelItem[] => {
|
|
50
120
|
const list: SidebarPanelItem[] = [
|
|
51
121
|
{
|
|
52
122
|
id: "account",
|
|
53
|
-
label:
|
|
123
|
+
label: text.account,
|
|
54
124
|
description: profileName,
|
|
55
125
|
icon: User,
|
|
56
126
|
},
|
|
57
127
|
];
|
|
58
128
|
|
|
59
|
-
if (showThemeToggle) {
|
|
129
|
+
if (showThemeToggle && themeModes === "three") {
|
|
60
130
|
list.push({
|
|
61
131
|
id: "theme",
|
|
62
|
-
label:
|
|
63
|
-
description:
|
|
64
|
-
|
|
132
|
+
label: text.theme,
|
|
133
|
+
description:
|
|
134
|
+
themeMode === "auto"
|
|
135
|
+
? text.systemMode
|
|
136
|
+
: themeMode === "light"
|
|
137
|
+
? text.lightMode
|
|
138
|
+
: text.darkMode,
|
|
139
|
+
badgeText:
|
|
140
|
+
themeMode === "auto" ? text.system : themeMode === "light" ? text.light : text.dark,
|
|
141
|
+
icon: themeMode === "auto" ? Monitor : themeMode === "light" ? Sun : Moon,
|
|
142
|
+
});
|
|
143
|
+
} else if (showThemeToggle) {
|
|
144
|
+
list.push({
|
|
145
|
+
id: "theme",
|
|
146
|
+
label: text.theme,
|
|
147
|
+
description: isLightMode ? text.lightMode : text.darkMode,
|
|
148
|
+
badgeText: isLightMode ? text.light : text.dark,
|
|
65
149
|
icon: isLightMode ? Sun : Moon,
|
|
66
150
|
});
|
|
67
151
|
}
|
|
@@ -70,7 +154,7 @@
|
|
|
70
154
|
list.push({
|
|
71
155
|
id: "logout",
|
|
72
156
|
label: logoutLabel,
|
|
73
|
-
description:
|
|
157
|
+
description: text.signOut,
|
|
74
158
|
icon: LogOut,
|
|
75
159
|
});
|
|
76
160
|
}
|
|
@@ -79,6 +163,16 @@
|
|
|
79
163
|
});
|
|
80
164
|
|
|
81
165
|
function toggleTheme(): void {
|
|
166
|
+
if (themeModes === "three") {
|
|
167
|
+
// From where the page is now, which another control may have changed.
|
|
168
|
+
const current = getThemeMode();
|
|
169
|
+
const next = THEME_MODES[(THEME_MODES.indexOf(current) + 1) % THEME_MODES.length];
|
|
170
|
+
setThemeMode(next, themeStorageKey === undefined ? {} : { storageKey: themeStorageKey });
|
|
171
|
+
themeMode = next;
|
|
172
|
+
isLightMode = !isThemeDark();
|
|
173
|
+
onThemeModeChange?.(next);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
82
176
|
isLightMode = !isLightMode;
|
|
83
177
|
onThemeToggle?.(isLightMode);
|
|
84
178
|
}
|
|
@@ -102,14 +196,15 @@
|
|
|
102
196
|
class={className}
|
|
103
197
|
role="dialog"
|
|
104
198
|
aria-modal="false"
|
|
105
|
-
aria-label=
|
|
199
|
+
aria-label={text.panelLabel}
|
|
106
200
|
{...restProps}
|
|
107
201
|
>
|
|
108
202
|
<SidebarPanel
|
|
109
|
-
title=
|
|
203
|
+
title={text.title}
|
|
110
204
|
subtitle={profileEmail}
|
|
111
|
-
ariaLabel=
|
|
112
|
-
closeLabel=
|
|
205
|
+
ariaLabel={text.panelLabel}
|
|
206
|
+
closeLabel={text.closeLabel}
|
|
207
|
+
selectLabel={text.listLabel}
|
|
113
208
|
{widthClass}
|
|
114
209
|
{variant}
|
|
115
210
|
showSearch={false}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type SidebarAccountPanelStrings } from "../util/sidebar.js";
|
|
2
|
+
import { type ThemeMode } from "../util/theme-mode.js";
|
|
1
3
|
interface Props {
|
|
2
4
|
/** Extra classes for the host element. */
|
|
3
5
|
class?: string;
|
|
@@ -11,6 +13,23 @@ interface Props {
|
|
|
11
13
|
showLogout?: boolean;
|
|
12
14
|
isLightMode?: boolean;
|
|
13
15
|
onThemeToggle?: (nextIsLightMode: boolean) => void;
|
|
16
|
+
/**
|
|
17
|
+
* `"two"` (the default): the theme row flips `isLightMode` and calls
|
|
18
|
+
* `onThemeToggle`; the app switches the page. `"three"`: the row
|
|
19
|
+
* steps through system, light and dark, switches the page itself
|
|
20
|
+
* (`data-theme` on `<html>`, as ThemeToggle does) and calls
|
|
21
|
+
* `onThemeModeChange`.
|
|
22
|
+
*/
|
|
23
|
+
themeModes?: "two" | "three";
|
|
24
|
+
/** With `themeModes="three"`: called with the mode the row has switched to. */
|
|
25
|
+
onThemeModeChange?: (mode: ThemeMode) => void;
|
|
26
|
+
/**
|
|
27
|
+
* With `themeModes="three"`: the `localStorage` key the choice is kept
|
|
28
|
+
* under. Default `"theme"`, as ThemeToggle; `null` keeps nothing.
|
|
29
|
+
*/
|
|
30
|
+
themeStorageKey?: string | null;
|
|
31
|
+
/** Every word the panel says by itself, for another language. `logoutLabel` is its own prop. */
|
|
32
|
+
strings?: Partial<SidebarAccountPanelStrings>;
|
|
14
33
|
onLogout?: () => void;
|
|
15
34
|
onAccount?: () => void;
|
|
16
35
|
onClose?: () => void;
|