zabi-components 8.0.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2935 -0
- package/README.md +243 -10
- package/THEME.md +162 -332
- package/THEMING.md +1419 -259
- package/dist/atoms/ActionPanel.svelte +15 -5
- package/dist/atoms/Avatar.svelte +120 -0
- package/dist/atoms/Avatar.svelte.d.ts +46 -0
- package/dist/atoms/Badge.svelte +71 -13
- package/dist/atoms/Badge.svelte.d.ts +8 -2
- package/dist/atoms/Block.svelte +74 -0
- package/dist/atoms/Block.svelte.d.ts +29 -0
- package/dist/atoms/Button.svelte +217 -30
- package/dist/atoms/Button.svelte.d.ts +33 -4
- package/dist/atoms/Card.svelte +182 -26
- package/dist/atoms/Card.svelte.d.ts +55 -3
- package/dist/atoms/CardHeader.svelte +16 -4
- package/dist/atoms/Checkbox.svelte +81 -21
- package/dist/atoms/Checkbox.svelte.d.ts +31 -2
- package/dist/atoms/Chip.svelte +351 -0
- package/dist/atoms/Chip.svelte.d.ts +57 -0
- package/dist/atoms/CodeBlock.svelte +20 -2
- package/dist/atoms/CodeBlock.svelte.d.ts +4 -0
- package/dist/atoms/CodeField.svelte +385 -0
- package/dist/atoms/CodeField.svelte.d.ts +61 -0
- package/dist/atoms/ColorPicker.svelte +260 -49
- package/dist/atoms/ColorPicker.svelte.d.ts +3 -0
- package/dist/atoms/Container.svelte +16 -8
- package/dist/atoms/DateField.svelte +145 -0
- package/dist/atoms/DateField.svelte.d.ts +81 -0
- package/dist/atoms/FieldMessages.svelte +69 -0
- package/dist/atoms/FieldMessages.svelte.d.ts +23 -0
- package/dist/atoms/FloatingActionButton.svelte +176 -0
- package/dist/atoms/FloatingActionButton.svelte.d.ts +51 -0
- package/dist/atoms/Heading.svelte +63 -5
- package/dist/atoms/Heading.svelte.d.ts +14 -0
- package/dist/atoms/IconButton.svelte +294 -26
- package/dist/atoms/IconButton.svelte.d.ts +62 -4
- package/dist/atoms/Input.svelte +259 -53
- package/dist/atoms/Input.svelte.d.ts +33 -2
- package/dist/atoms/List.svelte +5 -1
- package/dist/atoms/ListItem.svelte +70 -13
- package/dist/atoms/ListItem.svelte.d.ts +11 -0
- package/dist/atoms/PickerField.svelte +239 -0
- package/dist/atoms/PickerField.svelte.d.ts +67 -0
- package/dist/atoms/Progress.svelte +99 -19
- package/dist/atoms/Progress.svelte.d.ts +15 -1
- package/dist/atoms/Radio.svelte +51 -3
- package/dist/atoms/Radio.svelte.d.ts +30 -2
- package/dist/atoms/Rating.svelte +620 -0
- package/dist/atoms/Rating.svelte.d.ts +77 -0
- package/dist/atoms/Select.svelte +438 -98
- package/dist/atoms/Select.svelte.d.ts +61 -3
- package/dist/atoms/SelectionControl.svelte +193 -23
- package/dist/atoms/SelectionControl.svelte.d.ts +29 -3
- package/dist/atoms/Skeleton.svelte +114 -18
- package/dist/atoms/Skeleton.svelte.d.ts +30 -3
- package/dist/atoms/SkeletonGroup.svelte +43 -0
- package/dist/atoms/SkeletonGroup.svelte.d.ts +20 -0
- package/dist/atoms/Slider.svelte +344 -0
- package/dist/atoms/Slider.svelte.d.ts +40 -0
- package/dist/atoms/Sparkline.svelte +109 -0
- package/dist/atoms/Sparkline.svelte.d.ts +27 -0
- package/dist/atoms/SpeechBubble.svelte +187 -0
- package/dist/atoms/SpeechBubble.svelte.d.ts +33 -0
- package/dist/atoms/Spinner.svelte +57 -0
- package/dist/atoms/Spinner.svelte.d.ts +19 -0
- package/dist/atoms/Stat.svelte +72 -0
- package/dist/atoms/Stat.svelte.d.ts +19 -0
- package/dist/atoms/Table.svelte +151 -6
- package/dist/atoms/Table.svelte.d.ts +15 -3
- package/dist/atoms/TemporalField.svelte +472 -0
- package/dist/atoms/TemporalField.svelte.d.ts +48 -0
- package/dist/atoms/Text.svelte +23 -11
- package/dist/atoms/Text.svelte.d.ts +6 -3
- package/dist/atoms/Textarea.svelte +150 -44
- package/dist/atoms/Textarea.svelte.d.ts +35 -2
- package/dist/atoms/ThemeToggle.svelte +223 -44
- package/dist/atoms/ThemeToggle.svelte.d.ts +26 -3
- package/dist/atoms/TimeColumn.svelte +150 -0
- package/dist/atoms/TimeColumn.svelte.d.ts +25 -0
- package/dist/atoms/TimeField.svelte +151 -0
- package/dist/atoms/TimeField.svelte.d.ts +85 -0
- package/dist/atoms/Toast.svelte +22 -8
- package/dist/atoms/Toast.svelte.d.ts +2 -0
- package/dist/atoms/Toggle.svelte +98 -14
- package/dist/atoms/Toggle.svelte.d.ts +26 -2
- package/dist/atoms/Tooltip.svelte +528 -24
- package/dist/atoms/Tooltip.svelte.d.ts +18 -0
- package/dist/atoms/ZabiStringsProvider.svelte +45 -0
- package/dist/atoms/ZabiStringsProvider.svelte.d.ts +27 -0
- package/dist/atoms/index.d.ts +38 -0
- package/dist/atoms/index.js +29 -0
- package/dist/atoms/selection-control.styles.d.ts +47 -5
- package/dist/atoms/selection-control.styles.js +52 -10
- package/dist/components/atoms/index.d.ts +38 -0
- package/dist/components/atoms/index.d.ts.map +1 -1
- package/dist/components/atoms/selection-control.styles.d.ts +47 -5
- package/dist/components/atoms/selection-control.styles.d.ts.map +1 -1
- package/dist/components/index.d.ts +104 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/map.d.ts +11 -0
- package/dist/components/map.d.ts.map +1 -0
- package/dist/components/molecules/index.d.ts +51 -0
- package/dist/components/molecules/index.d.ts.map +1 -1
- package/dist/components/molecules/toast-store.d.ts +83 -7
- package/dist/components/molecules/toast-store.d.ts.map +1 -1
- package/dist/components/organisms/index.d.ts +10 -0
- package/dist/components/organisms/index.d.ts.map +1 -1
- package/dist/components/types/variants.d.ts +24 -1
- package/dist/components/types/variants.d.ts.map +1 -1
- package/dist/components/util/app-shell.d.ts +79 -0
- package/dist/components/util/app-shell.d.ts.map +1 -0
- package/dist/components/util/avatar.d.ts +39 -0
- package/dist/components/util/avatar.d.ts.map +1 -0
- package/dist/components/util/bottom-sheet.d.ts +30 -0
- package/dist/components/util/bottom-sheet.d.ts.map +1 -0
- package/dist/components/util/bottom-tab-bar.d.ts +41 -0
- package/dist/components/util/bottom-tab-bar.d.ts.map +1 -0
- package/dist/components/util/calendar.d.ts +56 -0
- package/dist/components/util/calendar.d.ts.map +1 -0
- package/dist/components/util/chart.d.ts +140 -0
- package/dist/components/util/chart.d.ts.map +1 -0
- package/dist/components/util/chip.d.ts +66 -0
- package/dist/components/util/chip.d.ts.map +1 -0
- package/dist/components/util/cn.d.ts.map +1 -1
- package/dist/components/util/code-field.d.ts +63 -0
- package/dist/components/util/code-field.d.ts.map +1 -0
- package/dist/components/util/collapsible.d.ts +64 -0
- package/dist/components/util/collapsible.d.ts.map +1 -0
- package/dist/components/util/confirm-dialog.d.ts +12 -0
- package/dist/components/util/confirm-dialog.d.ts.map +1 -0
- package/dist/components/util/date.d.ts +96 -0
- package/dist/components/util/date.d.ts.map +1 -0
- package/dist/components/util/display-voice.d.ts +10 -0
- package/dist/components/util/display-voice.d.ts.map +1 -0
- package/dist/components/util/drawer.d.ts +13 -0
- package/dist/components/util/drawer.d.ts.map +1 -0
- package/dist/components/util/dropdown.d.ts +47 -0
- package/dist/components/util/dropdown.d.ts.map +1 -0
- package/dist/components/util/field-control.d.ts +30 -0
- package/dist/components/util/field-control.d.ts.map +1 -0
- package/dist/components/util/field.d.ts +45 -0
- package/dist/components/util/field.d.ts.map +1 -0
- package/dist/components/util/fit-in-viewport.d.ts +201 -0
- package/dist/components/util/fit-in-viewport.d.ts.map +1 -0
- package/dist/components/util/focus-utils.d.ts +77 -2
- package/dist/components/util/focus-utils.d.ts.map +1 -1
- package/dist/components/util/hydration.d.ts +45 -0
- package/dist/components/util/hydration.d.ts.map +1 -0
- package/dist/components/util/keyboard-inset.d.ts +18 -0
- package/dist/components/util/keyboard-inset.d.ts.map +1 -0
- package/dist/components/util/map-view.d.ts +144 -0
- package/dist/components/util/map-view.d.ts.map +1 -0
- package/dist/components/util/media-grid.d.ts +51 -0
- package/dist/components/util/media-grid.d.ts.map +1 -0
- package/dist/components/util/media.d.ts +6 -0
- package/dist/components/util/media.d.ts.map +1 -0
- package/dist/components/util/overlay-chrome.d.ts +53 -0
- package/dist/components/util/overlay-chrome.d.ts.map +1 -0
- package/dist/components/util/overlay.d.ts +72 -0
- package/dist/components/util/overlay.d.ts.map +1 -0
- package/dist/components/util/photo.d.ts +234 -0
- package/dist/components/util/photo.d.ts.map +1 -0
- package/dist/components/util/portal.d.ts +23 -0
- package/dist/components/util/portal.d.ts.map +1 -0
- package/dist/components/util/progress.d.ts +19 -0
- package/dist/components/util/progress.d.ts.map +1 -0
- package/dist/components/util/pull-to-refresh.d.ts +27 -0
- package/dist/components/util/pull-to-refresh.d.ts.map +1 -0
- package/dist/components/util/radio-keys.d.ts +25 -0
- package/dist/components/util/radio-keys.d.ts.map +1 -0
- package/dist/components/util/rating.d.ts +23 -0
- package/dist/components/util/rating.d.ts.map +1 -0
- package/dist/components/util/ready-made-strings.d.ts +77 -0
- package/dist/components/util/ready-made-strings.d.ts.map +1 -0
- package/dist/components/util/scroll-edge.d.ts +33 -0
- package/dist/components/util/scroll-edge.d.ts.map +1 -0
- package/dist/components/util/scroll-padding.d.ts +20 -0
- package/dist/components/util/scroll-padding.d.ts.map +1 -0
- package/dist/components/util/segmented-control.d.ts +16 -0
- package/dist/components/util/segmented-control.d.ts.map +1 -0
- package/dist/components/util/select.d.ts +41 -0
- package/dist/components/util/select.d.ts.map +1 -0
- package/dist/components/util/sheet-drag.d.ts +84 -0
- package/dist/components/util/sheet-drag.d.ts.map +1 -0
- package/dist/components/util/sidebar.d.ts +63 -0
- package/dist/components/util/sidebar.d.ts.map +1 -0
- package/dist/components/util/skeleton.d.ts +15 -0
- package/dist/components/util/skeleton.d.ts.map +1 -0
- package/dist/components/util/sliding-indicator.d.ts +25 -0
- package/dist/components/util/sliding-indicator.d.ts.map +1 -0
- package/dist/components/util/sortable-list.d.ts +65 -0
- package/dist/components/util/sortable-list.d.ts.map +1 -0
- package/dist/components/util/stepper.d.ts +40 -0
- package/dist/components/util/stepper.d.ts.map +1 -0
- package/dist/components/util/swipeable-list-item.d.ts +36 -0
- package/dist/components/util/swipeable-list-item.d.ts.map +1 -0
- package/dist/components/util/temporal-field.d.ts +89 -0
- package/dist/components/util/temporal-field.d.ts.map +1 -0
- package/dist/components/util/theme-mode.d.ts +80 -0
- package/dist/components/util/theme-mode.d.ts.map +1 -0
- package/dist/components/util/toaster.d.ts +133 -0
- package/dist/components/util/toaster.d.ts.map +1 -0
- package/dist/components/util/tone-surface.d.ts +34 -0
- package/dist/components/util/tone-surface.d.ts.map +1 -0
- package/dist/components/util/tooltip.d.ts +10 -0
- package/dist/components/util/tooltip.d.ts.map +1 -0
- package/dist/components/util/top-navbar.d.ts +35 -0
- package/dist/components/util/top-navbar.d.ts.map +1 -0
- package/dist/components/util/touch-target.d.ts +31 -0
- package/dist/components/util/touch-target.d.ts.map +1 -0
- package/dist/components/util/zabi-strings.d.ts +142 -0
- package/dist/components/util/zabi-strings.d.ts.map +1 -0
- package/dist/create-theme/cli.js +173 -0
- package/dist/create-theme/index.d.ts +190 -0
- package/dist/create-theme/index.js +1034 -0
- package/dist/create-theme/lib/ramp-math.js +128 -0
- package/dist/create-theme/lib/resolve.js +238 -0
- package/dist/create-theme/theme-data.js +2644 -0
- package/dist/index.d.ts +104 -2
- package/dist/index.js +75 -2
- package/dist/map.d.ts +10 -0
- package/dist/map.js +9 -0
- package/dist/molecules/Alert.svelte +63 -16
- package/dist/molecules/Alert.svelte.d.ts +14 -1
- package/dist/molecules/AppBar.svelte +674 -0
- package/dist/molecules/AppBar.svelte.d.ts +131 -0
- package/dist/molecules/AvatarGroup.svelte +116 -0
- package/dist/molecules/AvatarGroup.svelte.d.ts +40 -0
- package/dist/molecules/BarChart.svelte +381 -0
- package/dist/molecules/BarChart.svelte.d.ts +45 -0
- package/dist/molecules/BottomSheet.svelte +608 -0
- package/dist/molecules/BottomSheet.svelte.d.ts +109 -0
- package/dist/molecules/BottomTabBar.svelte +403 -0
- package/dist/molecules/BottomTabBar.svelte.d.ts +98 -0
- package/dist/molecules/Calendar.svelte +597 -0
- package/dist/molecules/Calendar.svelte.d.ts +72 -0
- package/dist/molecules/ChipGroup.svelte +325 -0
- package/dist/molecules/ChipGroup.svelte.d.ts +41 -0
- package/dist/molecules/Collapsible.svelte +347 -0
- package/dist/molecules/Collapsible.svelte.d.ts +61 -0
- package/dist/molecules/CollapsibleGroup.svelte +136 -0
- package/dist/molecules/CollapsibleGroup.svelte.d.ts +14 -0
- package/dist/molecules/ComponentDemo.svelte +16 -4
- package/dist/molecules/ComponentDemo.svelte.d.ts +3 -0
- package/dist/molecules/ConfirmDialog.svelte +257 -0
- package/dist/molecules/ConfirmDialog.svelte.d.ts +58 -0
- package/dist/molecules/ContactForm.svelte +34 -17
- package/dist/molecules/ContactForm.svelte.d.ts +8 -0
- package/dist/molecules/Drawer.svelte +415 -0
- package/dist/molecules/Drawer.svelte.d.ts +55 -0
- package/dist/molecules/Dropdown.svelte +517 -48
- package/dist/molecules/Dropdown.svelte.d.ts +47 -6
- package/dist/molecules/DropdownItem.svelte +122 -0
- package/dist/molecules/DropdownItem.svelte.d.ts +28 -0
- package/dist/molecules/EmptyState.svelte +55 -10
- package/dist/molecules/EmptyState.svelte.d.ts +8 -0
- package/dist/molecules/FormField.svelte +9 -1
- package/dist/molecules/FormField.svelte.d.ts +2 -0
- package/dist/molecules/Header.svelte +1 -1
- package/dist/molecules/ImageUpload.svelte +492 -69
- package/dist/molecules/ImageUpload.svelte.d.ts +82 -2
- package/dist/molecules/LineChart.svelte +459 -0
- package/dist/molecules/LineChart.svelte.d.ts +53 -0
- package/dist/molecules/MapView.svelte +565 -0
- package/dist/molecules/MapView.svelte.d.ts +88 -0
- package/dist/molecules/MediaGrid.svelte +527 -0
- package/dist/molecules/MediaGrid.svelte.d.ts +77 -0
- package/dist/molecules/Modal.svelte +293 -72
- package/dist/molecules/Modal.svelte.d.ts +51 -2
- package/dist/molecules/NavigationMenuContent.svelte +58 -1
- package/dist/molecules/NavigationMenuItem.svelte +0 -1
- package/dist/molecules/NavigationMenuLink.svelte +1 -1
- package/dist/molecules/NavigationMenuList.svelte +10 -3
- package/dist/molecules/NavigationMenuTrigger.svelte +2 -2
- package/dist/molecules/Page.svelte +32 -2
- package/dist/molecules/Page.svelte.d.ts +11 -0
- package/dist/molecules/PhotoGrid.svelte +523 -0
- package/dist/molecules/PhotoGrid.svelte.d.ts +73 -0
- package/dist/molecules/PhotoViewer.svelte +1213 -0
- package/dist/molecules/PhotoViewer.svelte.d.ts +74 -0
- package/dist/molecules/PieChart.svelte +421 -0
- package/dist/molecules/PieChart.svelte.d.ts +51 -0
- package/dist/molecules/PropsTable.svelte +22 -10
- package/dist/molecules/PropsTable.svelte.d.ts +3 -0
- package/dist/molecules/PullToRefresh.svelte +263 -0
- package/dist/molecules/PullToRefresh.svelte.d.ts +52 -0
- package/dist/molecules/RadioGroup.svelte +72 -18
- package/dist/molecules/RadioGroup.svelte.d.ts +19 -3
- package/dist/molecules/Section.svelte +1 -1
- package/dist/molecules/SegmentedControl.svelte +456 -0
- package/dist/molecules/SegmentedControl.svelte.d.ts +40 -0
- package/dist/molecules/SidebarBrandHeader.svelte +11 -1
- package/dist/molecules/SidebarBrandHeader.svelte.d.ts +3 -0
- package/dist/molecules/SidebarFooter.svelte +30 -7
- package/dist/molecules/SidebarFooter.svelte.d.ts +3 -0
- package/dist/molecules/SidebarNavSection.svelte +1 -1
- package/dist/molecules/SlideUp.svelte +220 -61
- package/dist/molecules/SlideUp.svelte.d.ts +26 -0
- package/dist/molecules/SortableList.svelte +633 -0
- package/dist/molecules/SortableList.svelte.d.ts +69 -0
- package/dist/molecules/Stepper.svelte +562 -0
- package/dist/molecules/Stepper.svelte.d.ts +39 -0
- package/dist/molecules/StickyActionBar.svelte +250 -0
- package/dist/molecules/StickyActionBar.svelte.d.ts +78 -0
- package/dist/molecules/SwipeableListItem.svelte +334 -0
- package/dist/molecules/SwipeableListItem.svelte.d.ts +54 -0
- package/dist/molecules/Tabs.svelte +310 -9
- package/dist/molecules/Tabs.svelte.d.ts +7 -0
- package/dist/molecules/Toaster.svelte +514 -5
- package/dist/molecules/Toaster.svelte.d.ts +153 -2
- package/dist/molecules/ToasterToast.svelte +495 -77
- package/dist/molecules/ToasterToast.svelte.d.ts +15 -0
- package/dist/molecules/UnsavedChangesBar.svelte +223 -0
- package/dist/molecules/UnsavedChangesBar.svelte.d.ts +43 -0
- package/dist/molecules/index.d.ts +51 -0
- package/dist/molecules/index.js +31 -0
- package/dist/molecules/toast-store.d.ts +83 -7
- package/dist/molecules/toast-store.js +25 -1
- package/dist/organisms/AppNavigation.svelte +440 -0
- package/dist/organisms/AppNavigation.svelte.d.ts +72 -0
- package/dist/organisms/AppShell.svelte +696 -0
- package/dist/organisms/AppShell.svelte.d.ts +157 -0
- package/dist/organisms/AppShellHeaderPart.svelte +163 -0
- package/dist/organisms/AppShellHeaderPart.svelte.d.ts +57 -0
- package/dist/organisms/SidebarAccountPanel.svelte +107 -12
- package/dist/organisms/SidebarAccountPanel.svelte.d.ts +19 -0
- package/dist/organisms/SidebarNavigation.svelte +111 -43
- package/dist/organisms/SidebarNavigation.svelte.d.ts +29 -1
- package/dist/organisms/SidebarPanel.svelte +34 -17
- package/dist/organisms/SidebarPanel.svelte.d.ts +1 -0
- package/dist/organisms/SidebarShell.svelte +164 -14
- package/dist/organisms/SidebarShell.svelte.d.ts +56 -2
- package/dist/organisms/TopNavbar.svelte +353 -39
- package/dist/organisms/TopNavbar.svelte.d.ts +47 -0
- package/dist/organisms/TopNavbarSheetContent.svelte +145 -0
- package/dist/organisms/TopNavbarSheetContent.svelte.d.ts +24 -0
- package/dist/organisms/index.d.ts +10 -0
- package/dist/organisms/index.js +7 -0
- package/dist/types/components.d.ts +21 -1
- package/dist/types/components.d.ts.map +1 -1
- package/dist/types/index.d.ts +1093 -26
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/variants.ts +28 -1
- package/dist/util/app-shell.d.ts +78 -0
- package/dist/util/app-shell.js +97 -0
- package/dist/util/avatar.d.ts +38 -0
- package/dist/util/avatar.js +52 -0
- package/dist/util/bottom-sheet.d.ts +29 -0
- package/dist/util/bottom-sheet.js +43 -0
- package/dist/util/bottom-tab-bar.d.ts +40 -0
- package/dist/util/bottom-tab-bar.js +54 -0
- package/dist/util/calendar.d.ts +55 -0
- package/dist/util/calendar.js +74 -0
- package/dist/util/chart.d.ts +139 -0
- package/dist/util/chart.js +305 -0
- package/dist/util/chip.d.ts +65 -0
- package/dist/util/chip.js +58 -0
- package/dist/util/cn.js +28 -2
- package/dist/util/code-field.d.ts +62 -0
- package/dist/util/code-field.js +112 -0
- package/dist/util/collapsible.d.ts +63 -0
- package/dist/util/collapsible.js +23 -0
- package/dist/util/confirm-dialog.d.ts +11 -0
- package/dist/util/confirm-dialog.js +2 -0
- package/dist/util/date.d.ts +95 -0
- package/dist/util/date.js +237 -0
- package/dist/util/display-voice.d.ts +9 -0
- package/dist/util/display-voice.js +9 -0
- package/dist/util/drawer.d.ts +12 -0
- package/dist/util/drawer.js +7 -0
- package/dist/util/dropdown.d.ts +46 -0
- package/dist/util/dropdown.js +21 -0
- package/dist/util/field-control.d.ts +29 -0
- package/dist/util/field-control.js +32 -0
- package/dist/util/field.d.ts +44 -0
- package/dist/util/field.js +38 -0
- package/dist/util/fit-in-viewport.d.ts +200 -0
- package/dist/util/fit-in-viewport.js +399 -0
- package/dist/util/focus-utils.d.ts +77 -2
- package/dist/util/focus-utils.js +186 -9
- package/dist/util/hydration.d.ts +44 -0
- package/dist/util/hydration.js +58 -0
- package/dist/util/keyboard-inset.d.ts +17 -0
- package/dist/util/keyboard-inset.js +53 -0
- package/dist/util/map-view.d.ts +143 -0
- package/dist/util/map-view.js +121 -0
- package/dist/util/media-grid.d.ts +50 -0
- package/dist/util/media-grid.js +81 -0
- package/dist/util/media.d.ts +5 -0
- package/dist/util/media.js +10 -0
- package/dist/util/overlay-chrome.d.ts +52 -0
- package/dist/util/overlay-chrome.js +56 -0
- package/dist/util/overlay.d.ts +71 -0
- package/dist/util/overlay.js +240 -0
- package/dist/util/photo.d.ts +233 -0
- package/dist/util/photo.js +209 -0
- package/dist/util/portal.d.ts +22 -0
- package/dist/util/portal.js +50 -0
- package/dist/util/progress.d.ts +18 -0
- package/dist/util/progress.js +17 -0
- package/dist/util/pull-to-refresh.d.ts +26 -0
- package/dist/util/pull-to-refresh.js +30 -0
- package/dist/util/radio-keys.d.ts +24 -0
- package/dist/util/radio-keys.js +49 -0
- package/dist/util/rating.d.ts +22 -0
- package/dist/util/rating.js +26 -0
- package/dist/util/ready-made-strings.d.ts +76 -0
- package/dist/util/ready-made-strings.js +67 -0
- package/dist/util/scroll-edge.d.ts +32 -0
- package/dist/util/scroll-edge.js +87 -0
- package/dist/util/scroll-padding.d.ts +19 -0
- package/dist/util/scroll-padding.js +44 -0
- package/dist/util/segmented-control.d.ts +15 -0
- package/dist/util/segmented-control.js +1 -0
- package/dist/util/select.d.ts +40 -0
- package/dist/util/select.js +63 -0
- package/dist/util/sheet-drag.d.ts +83 -0
- package/dist/util/sheet-drag.js +311 -0
- package/dist/util/sidebar.d.ts +62 -0
- package/dist/util/sidebar.js +38 -0
- package/dist/util/skeleton.d.ts +14 -0
- package/dist/util/skeleton.js +22 -0
- package/dist/util/sliding-indicator.d.ts +24 -0
- package/dist/util/sliding-indicator.js +44 -0
- package/dist/util/sortable-list.d.ts +64 -0
- package/dist/util/sortable-list.js +53 -0
- package/dist/util/stepper.d.ts +39 -0
- package/dist/util/stepper.js +38 -0
- package/dist/util/swipeable-list-item.d.ts +35 -0
- package/dist/util/swipeable-list-item.js +32 -0
- package/dist/util/temporal-field.d.ts +88 -0
- package/dist/util/temporal-field.js +136 -0
- package/dist/util/theme-mode.d.ts +79 -0
- package/dist/util/theme-mode.js +121 -0
- package/dist/util/toaster.d.ts +132 -0
- package/dist/util/toaster.js +130 -0
- package/dist/util/tone-surface.d.ts +33 -0
- package/dist/util/tone-surface.js +35 -0
- package/dist/util/tooltip.d.ts +9 -0
- package/dist/util/tooltip.js +18 -0
- package/dist/util/top-navbar.d.ts +34 -0
- package/dist/util/top-navbar.js +28 -0
- package/dist/util/touch-target.d.ts +30 -0
- package/dist/util/touch-target.js +30 -0
- package/dist/util/zabi-strings.d.ts +141 -0
- package/dist/util/zabi-strings.js +105 -0
- package/dist/zabi-components-colors.css +11 -2
- package/dist/zabi-components-theme-dark-only.css +870 -258
- package/dist/zabi-components-theme-dark.css +870 -258
- package/dist/zabi-components-theme-only.css +2419 -368
- package/dist/zabi-components-theme.css +2419 -368
- package/dist/zabi-components.css +6032 -711
- package/docs/lucide-icons.md +40 -17
- package/docs/theme-imports.md +81 -11
- package/package.json +45 -8
|
@@ -1,6 +1,18 @@
|
|
|
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 Input from "./Input.svelte";
|
|
3
|
-
import { onMount,
|
|
5
|
+
import { onMount, tick } from "svelte";
|
|
6
|
+
import { isInsideToastRegion } from "../util/focus-utils.js";
|
|
7
|
+
import {
|
|
8
|
+
measurePlacement,
|
|
9
|
+
watchViewport,
|
|
10
|
+
type PanelPlacement,
|
|
11
|
+
} from "../util/fit-in-viewport.js";
|
|
12
|
+
import {
|
|
13
|
+
DEFAULT_COLOR_PICKER_STRINGS,
|
|
14
|
+
type ColorPickerStrings,
|
|
15
|
+
} from "../util/ready-made-strings.js";
|
|
4
16
|
|
|
5
17
|
interface Props {
|
|
6
18
|
/** Extra classes for the host element. */
|
|
@@ -9,23 +21,79 @@
|
|
|
9
21
|
label?: string;
|
|
10
22
|
disabled?: boolean;
|
|
11
23
|
placeholder?: string;
|
|
24
|
+
/** The accessible names of its parts, for another language. */
|
|
25
|
+
strings?: Partial<ColorPickerStrings>;
|
|
12
26
|
onchange?: (event: Event) => void;
|
|
13
27
|
}
|
|
14
28
|
|
|
15
29
|
let {
|
|
16
30
|
class: className = "",
|
|
17
|
-
value = $bindable
|
|
31
|
+
value = $bindable<Exclude<Props["value"], undefined>>(),
|
|
18
32
|
label = "",
|
|
19
33
|
disabled = false,
|
|
20
34
|
placeholder = "#000000",
|
|
35
|
+
strings,
|
|
21
36
|
onchange,
|
|
22
37
|
...restProps
|
|
23
38
|
}: Props = $props();
|
|
24
39
|
|
|
40
|
+
// No fallback on a bindable prop: Svelte refuses `bind:…={undefined}` on
|
|
41
|
+
// one that has a fallback (`props_invalid_value`), and a page that throws
|
|
42
|
+
// while it hydrates never becomes interactive. The default is applied
|
|
43
|
+
// here instead: at once, for the server and the first render, and again
|
|
44
|
+
// whenever a parent hands back `undefined`.
|
|
45
|
+
const applyDefaults = () => {
|
|
46
|
+
if (value === undefined) value = "";
|
|
47
|
+
};
|
|
48
|
+
applyDefaults();
|
|
49
|
+
$effect.pre(applyDefaults);
|
|
50
|
+
|
|
51
|
+
/** The app-wide words for this component, from a `ZabiStringsProvider` above it, if there is one. */
|
|
52
|
+
const provided = zabiStringsFor("colorPicker");
|
|
53
|
+
const text = $derived(mergeStrings(DEFAULT_COLOR_PICKER_STRINGS, provided(), strings));
|
|
54
|
+
|
|
25
55
|
let isOpen = $state(false);
|
|
26
|
-
|
|
56
|
+
/** The pointer that is down on the colour map, if one is. */
|
|
57
|
+
let dragPointer: number | null = null;
|
|
27
58
|
let pickerContainer: HTMLDivElement | undefined;
|
|
28
|
-
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Where the popover is. It hangs from the right edge of the swatch and is
|
|
62
|
+
* 20rem wide, so with the swatch in the left half of a phone screen it ran
|
|
63
|
+
* off the left edge. It is slid back to 8px from the edge, narrowed when
|
|
64
|
+
* it is wider than the screen, and placed against the viewport when a box
|
|
65
|
+
* that scrolls around it would cut it off (`fixed`). A popover that fits
|
|
66
|
+
* is not touched.
|
|
67
|
+
*/
|
|
68
|
+
let popoverElement = $state<HTMLDivElement | null>(null);
|
|
69
|
+
let placed = $state<PanelPlacement | null>(null);
|
|
70
|
+
|
|
71
|
+
$effect(() => {
|
|
72
|
+
const panel = popoverElement;
|
|
73
|
+
const anchor = panel?.parentElement;
|
|
74
|
+
if (!isOpen || !panel || !anchor) {
|
|
75
|
+
placed = null;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const update = () => {
|
|
79
|
+
// `top-12` is 3rem from the top of the box around the swatch,
|
|
80
|
+
// which can be a little taller than the swatch: the gap is what
|
|
81
|
+
// is left under that box, so the popover is where the class puts it.
|
|
82
|
+
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
|
|
83
|
+
const gap = rem * 3 - anchor.getBoundingClientRect().height;
|
|
84
|
+
placed = measurePlacement(
|
|
85
|
+
anchor,
|
|
86
|
+
panel,
|
|
87
|
+
{ block: "bottom", inline: "end" },
|
|
88
|
+
// Placed with `right`, in either writing direction, and always below.
|
|
89
|
+
{ margin: 8, gap, flipBlock: false, flipInline: false, rtl: false },
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
update();
|
|
93
|
+
return watchViewport(update, panel);
|
|
94
|
+
});
|
|
95
|
+
let colorMap = $state<HTMLCanvasElement | undefined>();
|
|
96
|
+
let swatchButton: HTMLButtonElement | undefined;
|
|
29
97
|
let colorMapContainer: HTMLDivElement | undefined;
|
|
30
98
|
|
|
31
99
|
// Working color in HSL (h: 0–360; s, l: 0–100).
|
|
@@ -108,9 +176,7 @@
|
|
|
108
176
|
const variant = $derived(value && !isValidHex(value) ? "error" : "default");
|
|
109
177
|
|
|
110
178
|
const message = $derived(
|
|
111
|
-
value && !isValidHex(value)
|
|
112
|
-
? "Please enter a valid hex color (e.g., #ff0000 or #f00)"
|
|
113
|
-
: "",
|
|
179
|
+
value && !isValidHex(value) ? text.invalidHex : "",
|
|
114
180
|
);
|
|
115
181
|
|
|
116
182
|
function handleInput(event: Event) {
|
|
@@ -142,7 +208,7 @@
|
|
|
142
208
|
commitCurrentValue(event);
|
|
143
209
|
}
|
|
144
210
|
|
|
145
|
-
async function togglePicker() {
|
|
211
|
+
async function togglePicker(event?: MouseEvent) {
|
|
146
212
|
if (!disabled) {
|
|
147
213
|
if (isOpen) {
|
|
148
214
|
commitCurrentValue(new Event("change"));
|
|
@@ -151,13 +217,41 @@
|
|
|
151
217
|
if (isOpen && value && isValidHex(value)) {
|
|
152
218
|
updateFromHex(value);
|
|
153
219
|
}
|
|
154
|
-
|
|
220
|
+
// A click from the keyboard has no pointer (`detail` is 0): focus
|
|
221
|
+
// goes in, to the first stop of the popover. A press keeps it.
|
|
222
|
+
if (isOpen && event && event.detail === 0) {
|
|
155
223
|
await tick();
|
|
156
|
-
|
|
224
|
+
saturationInput?.focus({ preventScroll: true });
|
|
157
225
|
}
|
|
158
226
|
}
|
|
159
227
|
}
|
|
160
228
|
|
|
229
|
+
/** Escape inside the popover, or on the swatch while it is open: close, and back to the swatch. */
|
|
230
|
+
function handleEscape(event: KeyboardEvent) {
|
|
231
|
+
if (event.key !== "Escape" || !isOpen) return;
|
|
232
|
+
// Consumed here: a Modal or Drawer around the picker stays open.
|
|
233
|
+
event.stopPropagation();
|
|
234
|
+
event.preventDefault();
|
|
235
|
+
commitCurrentValue(new Event("change"));
|
|
236
|
+
isOpen = false;
|
|
237
|
+
swatchButton?.focus({ preventScroll: true });
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// The map is drawn for the hue it is open at, and again for any change of
|
|
241
|
+
// it: the hue slider, a typed hex, or a `value` set from outside.
|
|
242
|
+
$effect(() => {
|
|
243
|
+
void hue;
|
|
244
|
+
if (isOpen && colorMap) drawColorMap();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// A `value` changed from outside while open (not the one the sliders just made).
|
|
248
|
+
$effect(() => {
|
|
249
|
+
if (!isOpen || !value || !isValidHex(value)) return;
|
|
250
|
+
if (expandHex(value).toLowerCase() !== hslToHex(hue, saturation, lightness)) {
|
|
251
|
+
updateFromHex(value);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
161
255
|
function drawColorMap() {
|
|
162
256
|
if (!colorMap) return;
|
|
163
257
|
const ctx = colorMap.getContext("2d");
|
|
@@ -177,34 +271,93 @@
|
|
|
177
271
|
}
|
|
178
272
|
}
|
|
179
273
|
|
|
180
|
-
|
|
181
|
-
|
|
274
|
+
/**
|
|
275
|
+
* The colour map: saturation across, lightness up.
|
|
276
|
+
*
|
|
277
|
+
* It is two sliders on one surface, and is built as that: two visually
|
|
278
|
+
* hidden `<input type="range">`, which is what a screen reader, a switch
|
|
279
|
+
* and a voice command already know how to name, read and set ("Saturation,
|
|
280
|
+
* slider, 50%"). A single element cannot say it: `role="slider"` has one
|
|
281
|
+
* value, and an unnamed `role="button"`, which this was, has none.
|
|
282
|
+
*
|
|
283
|
+
* For the keyboard the two act as one map. Left and right move
|
|
284
|
+
* saturation and up and down lightness, from whichever slider has focus,
|
|
285
|
+
* and focus goes to the one that moved, so its new value is what is
|
|
286
|
+
* read out. Shift moves by ten. Only the first is a Tab stop.
|
|
287
|
+
*
|
|
288
|
+
* The surface takes pointer events, so a finger and a pen work as a mouse
|
|
289
|
+
* does; it used to listen for `mousedown` alone. The whole surface is the
|
|
290
|
+
* target (the mark on it is not something to hit), and `touch-none`
|
|
291
|
+
* keeps a drag on it from scrolling the page.
|
|
292
|
+
*/
|
|
293
|
+
let saturationInput = $state<HTMLInputElement | null>(null);
|
|
294
|
+
let lightnessInput = $state<HTMLInputElement | null>(null);
|
|
295
|
+
|
|
296
|
+
const percent = (value: number) => Math.max(0, Math.min(100, Math.round(value)));
|
|
297
|
+
|
|
298
|
+
function setFromPoint(event: PointerEvent) {
|
|
299
|
+
if (!colorMapContainer) return;
|
|
182
300
|
const rect = colorMapContainer.getBoundingClientRect();
|
|
183
|
-
|
|
184
|
-
|
|
301
|
+
if (rect.width === 0 || rect.height === 0) return;
|
|
302
|
+
saturation = percent(((event.clientX - rect.left) / rect.width) * 100);
|
|
303
|
+
lightness = percent(100 - ((event.clientY - rect.top) / rect.height) * 100);
|
|
304
|
+
updateHexFromHsl();
|
|
305
|
+
}
|
|
185
306
|
|
|
186
|
-
|
|
187
|
-
|
|
307
|
+
function handleMapPointerDown(event: PointerEvent) {
|
|
308
|
+
if (event.pointerType === "mouse" && event.button !== 0) return;
|
|
309
|
+
dragPointer = event.pointerId;
|
|
310
|
+
try {
|
|
311
|
+
colorMapContainer?.setPointerCapture(event.pointerId);
|
|
312
|
+
} catch {
|
|
313
|
+
/* a test DOM, or a pointer that is already gone */
|
|
314
|
+
}
|
|
315
|
+
setFromPoint(event);
|
|
316
|
+
// The keys carry on from where the pointer left it.
|
|
317
|
+
saturationInput?.focus({ preventScroll: true });
|
|
318
|
+
// Not a text selection, and not a second focus change from the press itself.
|
|
319
|
+
event.preventDefault();
|
|
320
|
+
}
|
|
188
321
|
|
|
189
|
-
|
|
190
|
-
|
|
322
|
+
function handleMapPointerMove(event: PointerEvent) {
|
|
323
|
+
if (dragPointer !== event.pointerId) return;
|
|
324
|
+
setFromPoint(event);
|
|
191
325
|
}
|
|
192
326
|
|
|
193
|
-
function
|
|
194
|
-
if (
|
|
195
|
-
|
|
327
|
+
function handleMapPointerUp(event: PointerEvent) {
|
|
328
|
+
if (dragPointer !== event.pointerId) return;
|
|
329
|
+
dragPointer = null;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function handleMapKeydown(event: KeyboardEvent) {
|
|
333
|
+
const step = event.shiftKey ? 10 : 1;
|
|
334
|
+
const across = event.key === "ArrowRight" ? step : event.key === "ArrowLeft" ? -step : 0;
|
|
335
|
+
const up = event.key === "ArrowUp" ? step : event.key === "ArrowDown" ? -step : 0;
|
|
336
|
+
if (across === 0 && up === 0) return;
|
|
337
|
+
// The slider's own handling would move the focused one for all four keys.
|
|
338
|
+
event.preventDefault();
|
|
339
|
+
if (across !== 0) {
|
|
340
|
+
saturation = percent(saturation + across);
|
|
341
|
+
saturationInput?.focus({ preventScroll: true });
|
|
342
|
+
} else {
|
|
343
|
+
lightness = percent(lightness + up);
|
|
344
|
+
lightnessInput?.focus({ preventScroll: true });
|
|
196
345
|
}
|
|
346
|
+
updateHexFromHsl();
|
|
197
347
|
}
|
|
198
348
|
|
|
199
|
-
|
|
200
|
-
|
|
349
|
+
/** Home, End, Page Up and Down, and what assistive technology sets: the slider's own value. */
|
|
350
|
+
function handleMapInput(axis: "saturation" | "lightness", event: Event) {
|
|
351
|
+
const next = percent(Number((event.currentTarget as HTMLInputElement).value));
|
|
352
|
+
if (axis === "saturation") saturation = next;
|
|
353
|
+
else lightness = next;
|
|
354
|
+
updateHexFromHsl();
|
|
201
355
|
}
|
|
202
356
|
|
|
203
357
|
function handleHueChange(event: Event) {
|
|
204
358
|
const target = event.target as HTMLInputElement;
|
|
205
359
|
hue = parseInt(target.value);
|
|
206
360
|
updateHexFromHsl();
|
|
207
|
-
drawColorMap();
|
|
208
361
|
}
|
|
209
362
|
|
|
210
363
|
function setPickerContainer(node: HTMLDivElement) {
|
|
@@ -241,11 +394,13 @@
|
|
|
241
394
|
}
|
|
242
395
|
|
|
243
396
|
function handleClickOutside(event: MouseEvent) {
|
|
397
|
+
// A toast lies over the panel; a press on it is for the toast.
|
|
398
|
+
if (isInsideToastRegion(event.target)) return;
|
|
244
399
|
if (
|
|
245
400
|
pickerContainer &&
|
|
246
401
|
!pickerContainer.contains(event.target as Node) &&
|
|
247
402
|
!(event.target as HTMLElement).closest(
|
|
248
|
-
|
|
403
|
+
"[data-color-picker-open]",
|
|
249
404
|
)
|
|
250
405
|
) {
|
|
251
406
|
commitCurrentValue(new Event("change"));
|
|
@@ -258,19 +413,22 @@
|
|
|
258
413
|
updateFromHex(value);
|
|
259
414
|
}
|
|
260
415
|
window.addEventListener("mousedown", handleClickOutside);
|
|
261
|
-
window.addEventListener("mouseup", handleMouseUp);
|
|
262
|
-
window.addEventListener("mousemove", handleColorMapDrag);
|
|
263
|
-
});
|
|
264
416
|
|
|
265
|
-
|
|
266
|
-
window.
|
|
267
|
-
|
|
268
|
-
|
|
417
|
+
// Teardown is returned from onMount rather than registered with
|
|
418
|
+
// onDestroy: onDestroy also runs on the server, where there is no window.
|
|
419
|
+
return () => {
|
|
420
|
+
window.removeEventListener("mousedown", handleClickOutside);
|
|
421
|
+
};
|
|
269
422
|
});
|
|
270
423
|
|
|
271
424
|
const displayColor = $derived(value && isValidHex(value) ? value : placeholder);
|
|
272
425
|
const pickerIndicatorX = $derived(`${saturation}%`);
|
|
273
426
|
const pickerIndicatorY = $derived(`${100 - lightness}%`);
|
|
427
|
+
/** What a slider of the map says: its own value, and the colour the two make. */
|
|
428
|
+
const mapValueText = (value: number) => `${Math.round(value)}%, ${hslToHex(hue, saturation, lightness)}`;
|
|
429
|
+
/** A ring around a surface whose slider has keyboard focus: the sliders themselves are not drawn. */
|
|
430
|
+
const RING_WITHIN =
|
|
431
|
+
"has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-focus-ring";
|
|
274
432
|
</script>
|
|
275
433
|
|
|
276
434
|
<div class={className} {...restProps}>
|
|
@@ -285,7 +443,7 @@
|
|
|
285
443
|
{message}
|
|
286
444
|
oninput={handleInput}
|
|
287
445
|
onblur={handleBlur}
|
|
288
|
-
aria-label=
|
|
446
|
+
aria-label={label ? undefined : text.hexInput}
|
|
289
447
|
/>
|
|
290
448
|
</div>
|
|
291
449
|
<div class="relative shrink-0 mt-6">
|
|
@@ -293,48 +451,101 @@
|
|
|
293
451
|
type="button"
|
|
294
452
|
onclick={togglePicker}
|
|
295
453
|
{disabled}
|
|
296
|
-
class="focus-ring w-11 h-11 rounded-control border-2 border-card shrink-0 cursor-pointer hover:ring-2 hover:ring-border transition-colors disabled:cursor-not-allowed disabled:opacity-50"
|
|
454
|
+
class="focus-ring w-11 h-11 rounded-control border-2 border-card shrink-0 cursor-pointer hover:ring-2 hover:ring-border active:ring-2 active:ring-border-strong transition-colors disabled:cursor-not-allowed disabled:opacity-50"
|
|
297
455
|
style="background-color: {displayColor};"
|
|
298
|
-
aria-label=
|
|
456
|
+
aria-label={label ? `${label}, ${text.open}` : text.open}
|
|
457
|
+
bind:this={swatchButton}
|
|
458
|
+
onkeydown={handleEscape}
|
|
299
459
|
aria-expanded={isOpen}
|
|
460
|
+
data-color-picker-open
|
|
300
461
|
></button>
|
|
301
462
|
|
|
302
463
|
{#if isOpen}
|
|
303
464
|
<div
|
|
304
465
|
use:setPickerContainer
|
|
305
|
-
|
|
466
|
+
bind:this={popoverElement}
|
|
467
|
+
class="absolute top-12 right-0 z-popover border border-border-overlay bg-surface-overlay rounded-overlay shadow-lg p-4 w-80"
|
|
468
|
+
style:position={placed?.fixed ? "fixed" : undefined}
|
|
469
|
+
style:top={placed?.fixed ? `${placed.fixed.top}px` : undefined}
|
|
470
|
+
style:left={placed?.fixed ? `${placed.fixed.left}px` : undefined}
|
|
471
|
+
style:right={placed?.fixed
|
|
472
|
+
? "auto"
|
|
473
|
+
: placed && placed.inlineOffset !== 0
|
|
474
|
+
? `${placed.inlineOffset}px`
|
|
475
|
+
: undefined}
|
|
476
|
+
style:width={placed?.fixed ? `${placed.fixed.width}px` : undefined}
|
|
477
|
+
style:max-width={placed && placed.maxWidth !== null ? `${placed.maxWidth}px` : undefined}
|
|
306
478
|
role="dialog"
|
|
307
|
-
aria-label=
|
|
479
|
+
aria-label={text.picker}
|
|
480
|
+
tabindex="-1"
|
|
481
|
+
onkeydown={handleEscape}
|
|
308
482
|
>
|
|
309
483
|
<div class="space-y-4">
|
|
484
|
+
<!-- The sliders inside are the controls; the pointer
|
|
485
|
+
handlers are on the surface they share. -->
|
|
486
|
+
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
310
487
|
<div
|
|
311
488
|
use:setColorMapContainer
|
|
312
|
-
class="relative w-full h-48 rounded-container
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
|
|
489
|
+
class="relative w-full h-48 rounded-container cursor-crosshair touch-none select-none {RING_WITHIN}"
|
|
490
|
+
role="group"
|
|
491
|
+
data-sheet-no-drag
|
|
492
|
+
aria-label={text.area}
|
|
493
|
+
onpointerdown={handleMapPointerDown}
|
|
494
|
+
onpointermove={handleMapPointerMove}
|
|
495
|
+
onpointerup={handleMapPointerUp}
|
|
496
|
+
onpointercancel={handleMapPointerUp}
|
|
319
497
|
>
|
|
320
498
|
<canvas
|
|
321
499
|
use:setColorMap
|
|
322
500
|
width={256}
|
|
323
501
|
height={192}
|
|
324
|
-
class="w-full h-full"
|
|
502
|
+
class="w-full h-full rounded-container"
|
|
325
503
|
></canvas>
|
|
504
|
+
<input
|
|
505
|
+
bind:this={saturationInput}
|
|
506
|
+
type="range"
|
|
507
|
+
min="0"
|
|
508
|
+
max="100"
|
|
509
|
+
step="1"
|
|
510
|
+
value={saturation}
|
|
511
|
+
class="sr-only"
|
|
512
|
+
aria-label={text.saturation}
|
|
513
|
+
aria-valuetext={mapValueText(saturation)}
|
|
514
|
+
oninput={(event) => handleMapInput("saturation", event)}
|
|
515
|
+
onkeydown={handleMapKeydown}
|
|
516
|
+
/>
|
|
517
|
+
<input
|
|
518
|
+
bind:this={lightnessInput}
|
|
519
|
+
type="range"
|
|
520
|
+
min="0"
|
|
521
|
+
max="100"
|
|
522
|
+
step="1"
|
|
523
|
+
value={lightness}
|
|
524
|
+
tabindex="-1"
|
|
525
|
+
class="sr-only"
|
|
526
|
+
aria-label={text.lightness}
|
|
527
|
+
aria-orientation="vertical"
|
|
528
|
+
aria-valuetext={mapValueText(lightness)}
|
|
529
|
+
oninput={(event) => handleMapInput("lightness", event)}
|
|
530
|
+
onkeydown={handleMapKeydown}
|
|
531
|
+
/>
|
|
532
|
+
<!-- White with a dark edge: seen on the white corner of the map as on the black. -->
|
|
326
533
|
<div
|
|
327
|
-
class="absolute w-4 h-4 border-2 border-white rounded-full shadow-
|
|
534
|
+
class="absolute w-4 h-4 border-2 border-white rounded-full shadow-[0_0_0_1px_rgba(0,0,0,0.6)] pointer-events-none transform -translate-x-1/2 -translate-y-1/2"
|
|
328
535
|
style="left: {pickerIndicatorX}; top: {pickerIndicatorY};"
|
|
329
536
|
></div>
|
|
330
537
|
</div>
|
|
331
538
|
|
|
332
539
|
<div class="space-y-2">
|
|
540
|
+
<!-- A real slider, drawn by the two layers around
|
|
541
|
+
it. It is transparent, so the ring for keyboard
|
|
542
|
+
focus is on this box; and the box is a finger tall
|
|
543
|
+
on a touch screen, where 24px was not. -->
|
|
333
544
|
<div
|
|
334
|
-
class="relative h-6 rounded-control
|
|
545
|
+
class="relative h-6 pointer-coarse:h-11 rounded-control {RING_WITHIN}"
|
|
335
546
|
>
|
|
336
547
|
<div
|
|
337
|
-
class="absolute inset-0"
|
|
548
|
+
class="absolute inset-0 rounded-control"
|
|
338
549
|
style="background: linear-gradient(to right, hsl(0,100%,50%), hsl(60,100%,50%), hsl(120,100%,50%), hsl(180,100%,50%), hsl(240,100%,50%), hsl(300,100%,50%), hsl(360,100%,50%));"
|
|
339
550
|
></div>
|
|
340
551
|
<input
|
|
@@ -344,7 +555,7 @@
|
|
|
344
555
|
value={hue}
|
|
345
556
|
oninput={handleHueChange}
|
|
346
557
|
class="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
|
|
347
|
-
aria-label=
|
|
558
|
+
aria-label={text.hue}
|
|
348
559
|
/>
|
|
349
560
|
<div
|
|
350
561
|
class="absolute top-0 bottom-0 w-3 bg-card shadow-sm pointer-events-none my-px rounded-full border border-base-950"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ColorPickerStrings } from "../util/ready-made-strings.js";
|
|
1
2
|
interface Props {
|
|
2
3
|
/** Extra classes for the host element. */
|
|
3
4
|
class?: string;
|
|
@@ -5,6 +6,8 @@ interface Props {
|
|
|
5
6
|
label?: string;
|
|
6
7
|
disabled?: boolean;
|
|
7
8
|
placeholder?: string;
|
|
9
|
+
/** The accessible names of its parts, for another language. */
|
|
10
|
+
strings?: Partial<ColorPickerStrings>;
|
|
8
11
|
onchange?: (event: Event) => void;
|
|
9
12
|
}
|
|
10
13
|
declare const ColorPicker: import("svelte").Component<Props, {}, "value">;
|
|
@@ -28,13 +28,21 @@
|
|
|
28
28
|
'2xl': 'max-w-screen-2xl',
|
|
29
29
|
full: 'max-w-full',
|
|
30
30
|
};
|
|
31
|
+
|
|
32
|
+
const classes = $derived(
|
|
33
|
+
cn('mx-auto w-full', maxClass[maxWidth], padded ? 'px-4 sm:px-6' : '', className),
|
|
34
|
+
);
|
|
31
35
|
</script>
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
|
|
37
|
+
<!-- One branch per tag, not `<svelte:element>`: hydration takes a dynamic
|
|
38
|
+
element out and puts it back, which blurs a control inside it that the user
|
|
39
|
+
had already tabbed to. -->
|
|
40
|
+
{#if Tag === 'section'}
|
|
41
|
+
<section class={classes}>{@render children?.()}</section>
|
|
42
|
+
{:else if Tag === 'main'}
|
|
43
|
+
<main class={classes}>{@render children?.()}</main>
|
|
44
|
+
{:else if Tag === 'article'}
|
|
45
|
+
<article class={classes}>{@render children?.()}</article>
|
|
46
|
+
{:else}
|
|
47
|
+
<div class={classes}>{@render children?.()}</div>
|
|
48
|
+
{/if}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLInputAttributes } from "svelte/elements";
|
|
3
|
+
import type { SizeVariant } from "../types/variants.js";
|
|
4
|
+
import type { DateFieldStrings } from "../util/temporal-field.js";
|
|
5
|
+
import TemporalField from "./TemporalField.svelte";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A date, picked with the device's own date picker and styled like Input.
|
|
9
|
+
*
|
|
10
|
+
* It is a native `<input type="date">`: an iPhone shows its wheels or
|
|
11
|
+
* calendar, Android its calendar, a desktop browser its own. `value` is
|
|
12
|
+
* always `YYYY-MM-DD`, or `""` while empty, whatever the field shows.
|
|
13
|
+
*
|
|
14
|
+
* What the field shows is the browser's decision, unless it has a
|
|
15
|
+
* `locale`: without one, the date is in the format of the browser or
|
|
16
|
+
* device, not of the page, and no attribute changes that. To show a date
|
|
17
|
+
* as text in the page's language, use `formatDate`:
|
|
18
|
+
*
|
|
19
|
+
* ```svelte
|
|
20
|
+
* <DateField label="Date" bind:value={date} min="2026-01-01" />
|
|
21
|
+
* <p>{formatDate(date, "sv")}</p> <!-- 6 okt. 2026 -->
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* With `locale`, the field shows the value in that language and its own
|
|
25
|
+
* picker opens: a Calendar in a BottomSheet (at every width), with Clear
|
|
26
|
+
* unless the field is `required`. Until the page has run, and without
|
|
27
|
+
* scripts, it is the native input as above and submits as before; once
|
|
28
|
+
* it has, the native input stays as the form control, out of sight, and a
|
|
29
|
+
* button in its place shows the date. `picker="native"` opens the
|
|
30
|
+
* platform's own picker instead.
|
|
31
|
+
*
|
|
32
|
+
* ```svelte
|
|
33
|
+
* <DateField label="Datum" locale="sv" bind:value format={{ weekday: "short", day: "numeric", month: "short" }} />
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* Other attributes (`autocomplete`, `data-*`, `onchange`, ...) land on the
|
|
37
|
+
* `<input>`.
|
|
38
|
+
*/
|
|
39
|
+
type Props = Omit<
|
|
40
|
+
HTMLInputAttributes,
|
|
41
|
+
"class" | "type" | "value" | "size" | "min" | "max" | "step" | "required" | "disabled" | "readonly" | "id" | "name"
|
|
42
|
+
> & {
|
|
43
|
+
/** Omit to auto-generate; pair with FormField's `id` when used inside FormField. */
|
|
44
|
+
id?: string;
|
|
45
|
+
/** The date as `YYYY-MM-DD`, or `""` while empty. Supports `bind:value`. */
|
|
46
|
+
value?: string;
|
|
47
|
+
/** Name the value is submitted under in a form. */
|
|
48
|
+
name?: string;
|
|
49
|
+
label?: string;
|
|
50
|
+
/** True when FormField supplies the visible `<label>`. */
|
|
51
|
+
hideLabel?: boolean;
|
|
52
|
+
/** Help text under the field, read out with it. */
|
|
53
|
+
hint?: string;
|
|
54
|
+
/** An error under the field. It marks the field invalid and is announced. */
|
|
55
|
+
error?: string;
|
|
56
|
+
/** Earliest date that can be picked, as `YYYY-MM-DD`. */
|
|
57
|
+
min?: string;
|
|
58
|
+
/** Latest date that can be picked, as `YYYY-MM-DD`. */
|
|
59
|
+
max?: string;
|
|
60
|
+
/** Steps between dates that can be picked, in days. */
|
|
61
|
+
step?: number | "any";
|
|
62
|
+
required?: boolean;
|
|
63
|
+
disabled?: boolean;
|
|
64
|
+
/** Shows the value without letting it be changed; it is still submitted. */
|
|
65
|
+
readonly?: boolean;
|
|
66
|
+
/** Height, on the scale Input and Button use. At least 44px on a touch screen. */
|
|
67
|
+
size?: SizeVariant;
|
|
68
|
+
/** Extra classes for the `<input>`. */
|
|
69
|
+
class?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Language of the field, as a BCP 47 tag (`sv`, `en-GB`) or a list of them. With it the
|
|
72
|
+
* field shows the value in that language, whatever the browser's is, and opens the
|
|
73
|
+
* library's own picker; see above. Left out, the field is the native input.
|
|
74
|
+
*/
|
|
75
|
+
locale?: string | string[];
|
|
76
|
+
/** With `locale`: how the value is shown, as options of `Intl.DateTimeFormat`. Default: what formatDate gives for the locale. */
|
|
77
|
+
format?: Intl.DateTimeFormatOptions;
|
|
78
|
+
/** With `locale`: shown in the placeholder colour while the field is empty. */
|
|
79
|
+
placeholder?: string;
|
|
80
|
+
/** With `locale`: `library` (default) opens the library's calendar in a sheet; `native` opens the platform's own picker. */
|
|
81
|
+
picker?: "library" | "native";
|
|
82
|
+
/** With `locale`: the words the field says; replace any of them to translate. */
|
|
83
|
+
strings?: Partial<DateFieldStrings>;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
let {
|
|
87
|
+
id,
|
|
88
|
+
value = $bindable<Exclude<Props["value"], undefined>>(),
|
|
89
|
+
name = "",
|
|
90
|
+
label = "",
|
|
91
|
+
hideLabel = false,
|
|
92
|
+
hint = "",
|
|
93
|
+
error = "",
|
|
94
|
+
min,
|
|
95
|
+
max,
|
|
96
|
+
step,
|
|
97
|
+
required = false,
|
|
98
|
+
disabled = false,
|
|
99
|
+
readonly = false,
|
|
100
|
+
size = "md",
|
|
101
|
+
class: className = "",
|
|
102
|
+
locale,
|
|
103
|
+
format,
|
|
104
|
+
placeholder,
|
|
105
|
+
picker = "library",
|
|
106
|
+
strings,
|
|
107
|
+
...restProps
|
|
108
|
+
}: Props = $props();
|
|
109
|
+
|
|
110
|
+
// No fallback on a bindable prop: Svelte refuses `bind:…={undefined}` on
|
|
111
|
+
// one that has a fallback (`props_invalid_value`), and a page that throws
|
|
112
|
+
// while it hydrates never becomes interactive. The default is applied
|
|
113
|
+
// here instead: at once, for the server and the first render, and again
|
|
114
|
+
// whenever a parent hands back `undefined`.
|
|
115
|
+
const applyDefaults = () => {
|
|
116
|
+
if (value === undefined) value = "";
|
|
117
|
+
};
|
|
118
|
+
applyDefaults();
|
|
119
|
+
$effect.pre(applyDefaults);
|
|
120
|
+
</script>
|
|
121
|
+
|
|
122
|
+
<TemporalField
|
|
123
|
+
kind="date"
|
|
124
|
+
{id}
|
|
125
|
+
bind:value
|
|
126
|
+
{name}
|
|
127
|
+
{label}
|
|
128
|
+
{hideLabel}
|
|
129
|
+
{hint}
|
|
130
|
+
{error}
|
|
131
|
+
{min}
|
|
132
|
+
{max}
|
|
133
|
+
{step}
|
|
134
|
+
{required}
|
|
135
|
+
{disabled}
|
|
136
|
+
{readonly}
|
|
137
|
+
{size}
|
|
138
|
+
class={className}
|
|
139
|
+
{locale}
|
|
140
|
+
{format}
|
|
141
|
+
{placeholder}
|
|
142
|
+
{picker}
|
|
143
|
+
{strings}
|
|
144
|
+
{...restProps}
|
|
145
|
+
/>
|