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,415 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { zabiCommonStrings } from "../util/zabi-strings.js";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
5
|
+
import X from "@lucide/svelte/icons/x";
|
|
6
|
+
import { cn } from "../util/cn.js";
|
|
7
|
+
import {
|
|
8
|
+
OVERLAY_CHROME,
|
|
9
|
+
OVERLAY_TITLE_2XL,
|
|
10
|
+
OVERLAY_TITLE_HYPHENS,
|
|
11
|
+
OVERLAY_TITLE_WRAP,
|
|
12
|
+
textIsEnlarged,
|
|
13
|
+
} from "../util/overlay-chrome.js";
|
|
14
|
+
import {
|
|
15
|
+
focusFirstElement,
|
|
16
|
+
getFocusableElements,
|
|
17
|
+
joinOverlayStack,
|
|
18
|
+
recoverStrayFocus,
|
|
19
|
+
returnFocus,
|
|
20
|
+
saveFocus,
|
|
21
|
+
} from "../util/focus-utils.js";
|
|
22
|
+
import {
|
|
23
|
+
followKeyboard,
|
|
24
|
+
lockBodyScroll,
|
|
25
|
+
registerOverlayFooter,
|
|
26
|
+
registerOverlayHeader,
|
|
27
|
+
trapTabKey,
|
|
28
|
+
} from "../util/overlay.js";
|
|
29
|
+
import { TOUCH_HIT_AREA } from "../util/touch-target.js";
|
|
30
|
+
import { portal as portalTo } from "../util/portal.js";
|
|
31
|
+
import { generateId } from "../util/ssr-safe.js";
|
|
32
|
+
import {
|
|
33
|
+
resolveDrawerEdge,
|
|
34
|
+
type DrawerCloseReason,
|
|
35
|
+
type DrawerSide,
|
|
36
|
+
type DrawerSize,
|
|
37
|
+
} from "../util/drawer.js";
|
|
38
|
+
|
|
39
|
+
/** Other attributes (`id`, `data-*`, ...) land on the `role="dialog"` panel. */
|
|
40
|
+
type Props = Omit<
|
|
41
|
+
HTMLAttributes<HTMLDivElement>,
|
|
42
|
+
// `onclose` is also a DOM event handler; ours carries a reason instead.
|
|
43
|
+
"class" | "title" | "onclose" | "onkeydown"
|
|
44
|
+
> & {
|
|
45
|
+
isOpen?: boolean;
|
|
46
|
+
/** Heading of the drawer, and its accessible name. */
|
|
47
|
+
title: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
/**
|
|
50
|
+
* The edge the drawer slides in from. `left` and `right` are physical;
|
|
51
|
+
* `start` and `end` follow the writing direction.
|
|
52
|
+
*/
|
|
53
|
+
side?: DrawerSide;
|
|
54
|
+
/** Panel width. On a phone the panel is never wider than the screen. */
|
|
55
|
+
size?: DrawerSize;
|
|
56
|
+
/**
|
|
57
|
+
* Render the overlay in `document.body`, so an ancestor with a
|
|
58
|
+
* transform, filter or clipped overflow cannot trap it; pass `false`
|
|
59
|
+
* to render in place. The theme class belongs on `<html>` or `<body>`;
|
|
60
|
+
* set lower, it does not reach a portalled drawer.
|
|
61
|
+
*/
|
|
62
|
+
portal?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* When false, Escape, a backdrop click and the close button do not
|
|
65
|
+
* close the drawer. Focus stays trapped, and setting `isOpen` yourself
|
|
66
|
+
* still closes it.
|
|
67
|
+
*/
|
|
68
|
+
dismissible?: boolean;
|
|
69
|
+
/** Fired when the drawer closes itself, with what the user did. */
|
|
70
|
+
onclose?: (detail: { reason: DrawerCloseReason }) => void;
|
|
71
|
+
/**
|
|
72
|
+
* Hears every keydown in the drawer, after the drawer has handled
|
|
73
|
+
* Escape. The Tab cycle is kept either way.
|
|
74
|
+
*/
|
|
75
|
+
onkeydown?: (event: KeyboardEvent) => void;
|
|
76
|
+
/** Accessible name of the close button. */
|
|
77
|
+
closeLabel?: string;
|
|
78
|
+
/**
|
|
79
|
+
* CSS selector, looked up inside the panel, of the control that takes
|
|
80
|
+
* focus when the drawer opens (a search field, say). Without it, or
|
|
81
|
+
* with no match, the first control does: the close button.
|
|
82
|
+
*/
|
|
83
|
+
initialFocus?: string;
|
|
84
|
+
/** Extra classes for the dialog panel. */
|
|
85
|
+
class?: string;
|
|
86
|
+
children?: Snippet;
|
|
87
|
+
/** Pinned to the bottom of the panel, below the scrolling content. */
|
|
88
|
+
footer?: Snippet;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
let {
|
|
92
|
+
isOpen = $bindable<Exclude<Props["isOpen"], undefined>>(),
|
|
93
|
+
title,
|
|
94
|
+
description = "",
|
|
95
|
+
side = "right",
|
|
96
|
+
size = "md",
|
|
97
|
+
portal = true,
|
|
98
|
+
dismissible = true,
|
|
99
|
+
onclose,
|
|
100
|
+
onkeydown,
|
|
101
|
+
closeLabel: closeLabelGiven,
|
|
102
|
+
initialFocus,
|
|
103
|
+
class: className = "",
|
|
104
|
+
children,
|
|
105
|
+
footer,
|
|
106
|
+
...restProps
|
|
107
|
+
}: Props = $props();
|
|
108
|
+
|
|
109
|
+
/** Words many components share: a `ZabiStringsProvider` above this one may give them; else English. */
|
|
110
|
+
const common = zabiCommonStrings();
|
|
111
|
+
const closeLabel = $derived(closeLabelGiven ?? common().close);
|
|
112
|
+
|
|
113
|
+
// No fallback on a bindable prop: Svelte refuses `bind:…={undefined}` on
|
|
114
|
+
// one that has a fallback (`props_invalid_value`), and a page that throws
|
|
115
|
+
// while it hydrates never becomes interactive. The default is applied
|
|
116
|
+
// here instead: at once, for the server and the first render, and again
|
|
117
|
+
// whenever a parent hands back `undefined`.
|
|
118
|
+
const applyDefaults = () => {
|
|
119
|
+
if (isOpen === undefined) isOpen = false;
|
|
120
|
+
};
|
|
121
|
+
applyDefaults();
|
|
122
|
+
$effect.pre(applyDefaults);
|
|
123
|
+
|
|
124
|
+
// Used only where --duration-moderate cannot be read.
|
|
125
|
+
const SLIDE_MS = 200;
|
|
126
|
+
|
|
127
|
+
const titleId = generateId("drawer-title");
|
|
128
|
+
const descriptionId = generateId("drawer-description");
|
|
129
|
+
|
|
130
|
+
let panel = $state<HTMLDivElement>();
|
|
131
|
+
let scroller = $state<HTMLDivElement>();
|
|
132
|
+
let footerElement = $state<HTMLDivElement>();
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Read as the overlay opens: with the text enlarged, a long word in the
|
|
136
|
+
* title is hyphenated before it is cut (util/overlay-chrome.ts).
|
|
137
|
+
*/
|
|
138
|
+
let enlargedText = $state(false);
|
|
139
|
+
$effect(() => {
|
|
140
|
+
if (isOpen) enlargedText = textIsEnlarged();
|
|
141
|
+
});
|
|
142
|
+
let headerElement = $state<HTMLDivElement>();
|
|
143
|
+
let focusActive = false;
|
|
144
|
+
/**
|
|
145
|
+
* True when the content is taller than its box and holds nothing that can
|
|
146
|
+
* take focus. Only then is the scrolling box itself a Tab stop, so the
|
|
147
|
+
* keyboard can scroll it; content with a control in it is reached, and
|
|
148
|
+
* scrolled, through that control.
|
|
149
|
+
*/
|
|
150
|
+
let scrollerNeedsFocus = $state(false);
|
|
151
|
+
/** Position among the open overlays; lifts a drawer opened later above the earlier ones. */
|
|
152
|
+
let depth = $state(0);
|
|
153
|
+
|
|
154
|
+
/** `100%` is the overlay, which is the viewport: the cap for phones. */
|
|
155
|
+
const sizeClasses = $derived(
|
|
156
|
+
{
|
|
157
|
+
"sm": "w-[min(100%,20rem)]",
|
|
158
|
+
"md": "w-[min(100%,28rem)]",
|
|
159
|
+
"lg": "w-[min(100%,42rem)]",
|
|
160
|
+
}[size] ?? "w-[min(100%,28rem)]",
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
/** The edge the panel is attached to. The rim comes from the material. */
|
|
164
|
+
const sideClasses = $derived(
|
|
165
|
+
{
|
|
166
|
+
"left": "left-0",
|
|
167
|
+
"right": "right-0",
|
|
168
|
+
"start": "start-0",
|
|
169
|
+
"end": "end-0",
|
|
170
|
+
}[side] ?? "right-0",
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
function close(reason: DrawerCloseReason) {
|
|
174
|
+
if (!dismissible) return;
|
|
175
|
+
isOpen = false;
|
|
176
|
+
if (focusActive) {
|
|
177
|
+
focusActive = false;
|
|
178
|
+
returnFocus();
|
|
179
|
+
}
|
|
180
|
+
onclose?.({ reason });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** `200ms`, `0.2s` or `0s` to milliseconds; the fallback when it is not a time. */
|
|
184
|
+
function parseDuration(value: string): number {
|
|
185
|
+
const match = /^\s*(-?\d*\.?\d+)(ms|s)\s*$/.exec(value);
|
|
186
|
+
if (!match) return SLIDE_MS;
|
|
187
|
+
const ms = parseFloat(match[1]) * (match[2] === "s" ? 1000 : 1);
|
|
188
|
+
return ms >= 0 ? ms : SLIDE_MS;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Slides the panel in from its edge. Skipped where motion is unwanted or unsupported. */
|
|
192
|
+
function slideIn(container: HTMLElement) {
|
|
193
|
+
if (typeof container.animate !== "function") return;
|
|
194
|
+
if (
|
|
195
|
+
typeof window.matchMedia === "function" &&
|
|
196
|
+
window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
197
|
+
) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const rtl = getComputedStyle(container).direction === "rtl";
|
|
201
|
+
const from = resolveDrawerEdge(side, rtl) === "left" ? "-100%" : "100%";
|
|
202
|
+
// Read from the element so a theme that overrides the tokens is followed.
|
|
203
|
+
const style = getComputedStyle(container);
|
|
204
|
+
const duration = parseDuration(style.getPropertyValue("--duration-moderate"));
|
|
205
|
+
const easing = style.getPropertyValue("--ease-out").trim() || "ease-out";
|
|
206
|
+
const frames = [{ transform: `translateX(${from})` }, { transform: "translateX(0)" }];
|
|
207
|
+
try {
|
|
208
|
+
container.animate(frames, { duration, easing });
|
|
209
|
+
} catch {
|
|
210
|
+
container.animate(frames, { duration, easing: "ease-out" });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
$effect(() => {
|
|
215
|
+
const box = scroller;
|
|
216
|
+
if (!isOpen || !box) {
|
|
217
|
+
scrollerNeedsFocus = false;
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const measure = () => {
|
|
221
|
+
scrollerNeedsFocus =
|
|
222
|
+
box.scrollHeight > box.clientHeight &&
|
|
223
|
+
getFocusableElements(box).length === 0;
|
|
224
|
+
};
|
|
225
|
+
measure();
|
|
226
|
+
// The answer changes with the viewport and with the content.
|
|
227
|
+
const resize =
|
|
228
|
+
typeof ResizeObserver === "function" ? new ResizeObserver(measure) : undefined;
|
|
229
|
+
resize?.observe(box);
|
|
230
|
+
const mutation = new MutationObserver(measure);
|
|
231
|
+
mutation.observe(box, { childList: true, subtree: true, characterData: true });
|
|
232
|
+
return () => {
|
|
233
|
+
resize?.disconnect();
|
|
234
|
+
mutation.disconnect();
|
|
235
|
+
};
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
$effect(() => {
|
|
239
|
+
const container = panel;
|
|
240
|
+
if (isOpen && container) {
|
|
241
|
+
saveFocus();
|
|
242
|
+
focusActive = true;
|
|
243
|
+
const unlockScroll = lockBodyScroll();
|
|
244
|
+
const overlay = joinOverlayStack(container);
|
|
245
|
+
depth = overlay.depth;
|
|
246
|
+
slideIn(container);
|
|
247
|
+
const t = setTimeout(() => {
|
|
248
|
+
// Something inside has taken focus already (a field that
|
|
249
|
+
// focuses itself as it mounts): leave it there. `initialFocus`
|
|
250
|
+
// is the consumer saying where focus goes, so it still decides.
|
|
251
|
+
const active = document.activeElement;
|
|
252
|
+
const inside = !!active && active !== container && container.contains(active);
|
|
253
|
+
if (inside && !(initialFocus && container.querySelector(initialFocus))) return;
|
|
254
|
+
focusFirstElement(container, initialFocus);
|
|
255
|
+
}, 0);
|
|
256
|
+
// If the focused control is disabled or removed, focus lands on
|
|
257
|
+
// `<body>`; take Tab and Escape back from there.
|
|
258
|
+
const stopRecovery = recoverStrayFocus(container, {
|
|
259
|
+
onEscape: () => close("escape"),
|
|
260
|
+
});
|
|
261
|
+
// Where the on-screen keyboard covers the page, the overlay
|
|
262
|
+
// keeps to what is left above it.
|
|
263
|
+
const stopKeyboard = container.parentElement
|
|
264
|
+
? followKeyboard(container.parentElement)
|
|
265
|
+
: undefined;
|
|
266
|
+
return () => {
|
|
267
|
+
clearTimeout(t);
|
|
268
|
+
stopRecovery();
|
|
269
|
+
stopKeyboard?.();
|
|
270
|
+
overlay.leave();
|
|
271
|
+
unlockScroll();
|
|
272
|
+
if (focusActive) {
|
|
273
|
+
focusActive = false;
|
|
274
|
+
returnFocus();
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// For the toast stack, which stays off a pinned footer.
|
|
281
|
+
$effect(() => {
|
|
282
|
+
const pinned = footerElement;
|
|
283
|
+
if (!isOpen || !pinned) return;
|
|
284
|
+
return registerOverlayFooter(pinned);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// And the header, with the close button, which the stack starts below.
|
|
288
|
+
$effect(() => {
|
|
289
|
+
const top = headerElement;
|
|
290
|
+
if (!isOpen || !top) return;
|
|
291
|
+
return registerOverlayHeader(top);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
function handleBackdropClick(event: Event) {
|
|
295
|
+
if (event.target === event.currentTarget) close("backdrop");
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function handleKeydown(event: KeyboardEvent) {
|
|
299
|
+
// `defaultPrevented` means a nested dialog already handled the key.
|
|
300
|
+
// Prevented here even when not dismissible, so a dialog underneath
|
|
301
|
+
// does not take the Escape as its own.
|
|
302
|
+
if (event.key === "Escape" && !event.defaultPrevented) {
|
|
303
|
+
event.preventDefault();
|
|
304
|
+
close("escape");
|
|
305
|
+
}
|
|
306
|
+
// The caller's handler, as in Modal: it listens, the trap on the
|
|
307
|
+
// panel is separate and cannot be replaced by it.
|
|
308
|
+
onkeydown?.(event);
|
|
309
|
+
}
|
|
310
|
+
</script>
|
|
311
|
+
|
|
312
|
+
{#if isOpen}
|
|
313
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
314
|
+
<!-- `overflow-clip`, not `hidden` (as in BottomSheet): a clipped box is a
|
|
315
|
+
scroll container nobody can scroll, and WebKit scrolls one to a focused
|
|
316
|
+
element while the panel is still off screen. -->
|
|
317
|
+
<div
|
|
318
|
+
class="group/overlay fixed inset-0 z-modal overflow-clip {dismissible ? 'cursor-pointer' : 'cursor-default'} bg-overlay"
|
|
319
|
+
style:z-index={depth > 0 ? `calc(var(--z-modal) + ${depth})` : undefined}
|
|
320
|
+
data-overlay-depth={depth}
|
|
321
|
+
use:portalTo={portal}
|
|
322
|
+
onclick={handleBackdropClick}
|
|
323
|
+
onkeydown={handleKeydown}
|
|
324
|
+
role="presentation"
|
|
325
|
+
>
|
|
326
|
+
<div
|
|
327
|
+
bind:this={panel}
|
|
328
|
+
class={cn(
|
|
329
|
+
// The glass is a layer behind the content (`::before`), not a filter on
|
|
330
|
+
// the panel: a backdrop-filter would make the panel the containing
|
|
331
|
+
// block of every fixed-position popover inside it.
|
|
332
|
+
"material-layer-thick absolute inset-y-0 flex cursor-default flex-col",
|
|
333
|
+
// Above the home indicator: the last row, or the footer, ends
|
|
334
|
+
// where a finger can reach it. Over a keyboard that is under
|
|
335
|
+
// the keyboard.
|
|
336
|
+
"pb-[env(safe-area-inset-bottom,0px)] group-data-keyboard-open/overlay:pb-0",
|
|
337
|
+
sizeClasses,
|
|
338
|
+
sideClasses,
|
|
339
|
+
className,
|
|
340
|
+
)}
|
|
341
|
+
role="dialog"
|
|
342
|
+
aria-modal="true"
|
|
343
|
+
aria-labelledby={titleId}
|
|
344
|
+
aria-describedby={description ? descriptionId : undefined}
|
|
345
|
+
tabindex="-1"
|
|
346
|
+
data-side={side}
|
|
347
|
+
{...restProps}
|
|
348
|
+
onkeydown={(event) => trapTabKey(panel, event)}
|
|
349
|
+
>
|
|
350
|
+
<!-- Chrome: laid out in px, with a title that stops at 1.3 times its
|
|
351
|
+
size (util/overlay-chrome.ts). -->
|
|
352
|
+
<div
|
|
353
|
+
bind:this={headerElement}
|
|
354
|
+
class="flex items-start justify-between gap-4 px-6 pb-3 pt-6 {OVERLAY_CHROME}"
|
|
355
|
+
>
|
|
356
|
+
<div class="min-w-0 flex-1">
|
|
357
|
+
<h2
|
|
358
|
+
id={titleId}
|
|
359
|
+
class="{OVERLAY_TITLE_2XL} font-normal tracking-normal text-headline {OVERLAY_TITLE_WRAP} {enlargedText ? OVERLAY_TITLE_HYPHENS : ''}"
|
|
360
|
+
>
|
|
361
|
+
{title}
|
|
362
|
+
</h2>
|
|
363
|
+
{#if description}
|
|
364
|
+
<p id={descriptionId} class="mt-1 text-sm text-description">
|
|
365
|
+
{description}
|
|
366
|
+
</p>
|
|
367
|
+
{/if}
|
|
368
|
+
</div>
|
|
369
|
+
<!-- `aria-disabled`, not `disabled` or removed: the button may hold focus when `dismissible` turns false, and a disabled or missing element would drop focus out of the trap. -->
|
|
370
|
+
<!-- On a touch screen the hit area grows to 44px around the
|
|
371
|
+
same 32px box. The 6px it adds each way stays inside the
|
|
372
|
+
header's padding and the 16px gap to the title. -->
|
|
373
|
+
<button
|
|
374
|
+
type="button"
|
|
375
|
+
onclick={() => close("close-button")}
|
|
376
|
+
class="focus-ring relative flex size-8 shrink-0 items-center justify-center rounded-control text-description transition-colors motion-reduce:transition-none {TOUCH_HIT_AREA} {dismissible
|
|
377
|
+
? 'cursor-pointer hover:bg-surface-overlay-hover hover:text-headline active:bg-surface-active'
|
|
378
|
+
: 'cursor-not-allowed opacity-50'}"
|
|
379
|
+
aria-label={closeLabel}
|
|
380
|
+
aria-disabled={dismissible ? undefined : "true"}
|
|
381
|
+
>
|
|
382
|
+
<X size={20} aria-hidden="true" />
|
|
383
|
+
</button>
|
|
384
|
+
</div>
|
|
385
|
+
|
|
386
|
+
<!-- `pt-1`: a scroll container clips, and the focus ring of a
|
|
387
|
+
first control needs the room. -->
|
|
388
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
389
|
+
<div
|
|
390
|
+
bind:this={scroller}
|
|
391
|
+
class={cn(
|
|
392
|
+
"min-h-0 flex-1 overflow-y-auto px-[24px] pb-[24px] pt-[4px]",
|
|
393
|
+
// Inset: a ring outside the box would be cut off at
|
|
394
|
+
// the screen edge the drawer sits on.
|
|
395
|
+
scrollerNeedsFocus &&
|
|
396
|
+
"focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-focus-ring",
|
|
397
|
+
)}
|
|
398
|
+
tabindex={scrollerNeedsFocus ? 0 : undefined}
|
|
399
|
+
role={scrollerNeedsFocus ? "group" : undefined}
|
|
400
|
+
aria-labelledby={scrollerNeedsFocus ? titleId : undefined}
|
|
401
|
+
>
|
|
402
|
+
{@render children?.()}
|
|
403
|
+
</div>
|
|
404
|
+
|
|
405
|
+
{#if footer}
|
|
406
|
+
<div
|
|
407
|
+
bind:this={footerElement}
|
|
408
|
+
class="flex shrink-0 justify-end gap-[12px] border-t border-border-overlay px-[24px] py-[16px]"
|
|
409
|
+
>
|
|
410
|
+
{@render footer()}
|
|
411
|
+
</div>
|
|
412
|
+
{/if}
|
|
413
|
+
</div>
|
|
414
|
+
</div>
|
|
415
|
+
{/if}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Snippet } from "svelte";
|
|
2
|
+
import type { HTMLAttributes } from "svelte/elements";
|
|
3
|
+
import { type DrawerCloseReason, type DrawerSide, type DrawerSize } from "../util/drawer.js";
|
|
4
|
+
/** Other attributes (`id`, `data-*`, ...) land on the `role="dialog"` panel. */
|
|
5
|
+
type Props = Omit<HTMLAttributes<HTMLDivElement>, "class" | "title" | "onclose" | "onkeydown"> & {
|
|
6
|
+
isOpen?: boolean;
|
|
7
|
+
/** Heading of the drawer, and its accessible name. */
|
|
8
|
+
title: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
/**
|
|
11
|
+
* The edge the drawer slides in from. `left` and `right` are physical;
|
|
12
|
+
* `start` and `end` follow the writing direction.
|
|
13
|
+
*/
|
|
14
|
+
side?: DrawerSide;
|
|
15
|
+
/** Panel width. On a phone the panel is never wider than the screen. */
|
|
16
|
+
size?: DrawerSize;
|
|
17
|
+
/**
|
|
18
|
+
* Render the overlay in `document.body`, so an ancestor with a
|
|
19
|
+
* transform, filter or clipped overflow cannot trap it; pass `false`
|
|
20
|
+
* to render in place. The theme class belongs on `<html>` or `<body>`;
|
|
21
|
+
* set lower, it does not reach a portalled drawer.
|
|
22
|
+
*/
|
|
23
|
+
portal?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* When false, Escape, a backdrop click and the close button do not
|
|
26
|
+
* close the drawer. Focus stays trapped, and setting `isOpen` yourself
|
|
27
|
+
* still closes it.
|
|
28
|
+
*/
|
|
29
|
+
dismissible?: boolean;
|
|
30
|
+
/** Fired when the drawer closes itself, with what the user did. */
|
|
31
|
+
onclose?: (detail: {
|
|
32
|
+
reason: DrawerCloseReason;
|
|
33
|
+
}) => void;
|
|
34
|
+
/**
|
|
35
|
+
* Hears every keydown in the drawer, after the drawer has handled
|
|
36
|
+
* Escape. The Tab cycle is kept either way.
|
|
37
|
+
*/
|
|
38
|
+
onkeydown?: (event: KeyboardEvent) => void;
|
|
39
|
+
/** Accessible name of the close button. */
|
|
40
|
+
closeLabel?: string;
|
|
41
|
+
/**
|
|
42
|
+
* CSS selector, looked up inside the panel, of the control that takes
|
|
43
|
+
* focus when the drawer opens (a search field, say). Without it, or
|
|
44
|
+
* with no match, the first control does: the close button.
|
|
45
|
+
*/
|
|
46
|
+
initialFocus?: string;
|
|
47
|
+
/** Extra classes for the dialog panel. */
|
|
48
|
+
class?: string;
|
|
49
|
+
children?: Snippet;
|
|
50
|
+
/** Pinned to the bottom of the panel, below the scrolling content. */
|
|
51
|
+
footer?: Snippet;
|
|
52
|
+
};
|
|
53
|
+
declare const Drawer: import("svelte").Component<Props, {}, "isOpen">;
|
|
54
|
+
type Drawer = ReturnType<typeof Drawer>;
|
|
55
|
+
export default Drawer;
|