@thomasfosterau/components 0.0.0 → 0.2.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/LICENSE +21 -0
- package/README.md +241 -56
- package/dist/canvas/VectorCanvas.svelte +320 -0
- package/dist/canvas/VectorCanvas.svelte.d.ts +105 -0
- package/dist/canvas/history.d.ts +105 -0
- package/dist/canvas/history.js +147 -0
- package/dist/canvas/index.d.ts +15 -0
- package/dist/canvas/index.js +14 -0
- package/dist/canvas/types.d.ts +91 -0
- package/dist/canvas/types.js +13 -0
- package/dist/canvas/utils.d.ts +66 -0
- package/dist/canvas/utils.js +114 -0
- package/dist/charts/Chart.svelte +300 -0
- package/dist/charts/Chart.svelte.d.ts +50 -0
- package/dist/charts/index.d.ts +11 -0
- package/dist/charts/index.js +10 -0
- package/dist/charts/types.d.ts +28 -0
- package/dist/charts/types.js +6 -0
- package/dist/citations/BookCitation.svelte +53 -0
- package/dist/citations/BookCitation.svelte.d.ts +41 -0
- package/dist/citations/ChapterCitation.svelte +38 -0
- package/dist/citations/ChapterCitation.svelte.d.ts +50 -0
- package/dist/citations/Citation.svelte +47 -0
- package/dist/citations/Citation.svelte.d.ts +24 -0
- package/dist/citations/CreditList.svelte +69 -0
- package/dist/citations/CreditList.svelte.d.ts +47 -0
- package/dist/citations/DOILink.svelte +28 -0
- package/dist/citations/DOILink.svelte.d.ts +19 -0
- package/dist/citations/Footnote.svelte +39 -0
- package/dist/citations/Footnote.svelte.d.ts +17 -0
- package/dist/citations/FootnoteList.svelte +36 -0
- package/dist/citations/FootnoteList.svelte.d.ts +21 -0
- package/dist/citations/ISBNLink.svelte +29 -0
- package/dist/citations/ISBNLink.svelte.d.ts +19 -0
- package/dist/citations/ISSNLink.svelte +29 -0
- package/dist/citations/ISSNLink.svelte.d.ts +19 -0
- package/dist/citations/Publisher.svelte +34 -0
- package/dist/citations/Publisher.svelte.d.ts +14 -0
- package/dist/citations/ReferenceList.svelte +53 -0
- package/dist/citations/ReferenceList.svelte.d.ts +21 -0
- package/dist/citations/ReportCitation.svelte +41 -0
- package/dist/citations/ReportCitation.svelte.d.ts +36 -0
- package/dist/citations/ScholarlyArticleCitation.svelte +64 -0
- package/dist/citations/ScholarlyArticleCitation.svelte.d.ts +41 -0
- package/dist/citations/ThesisCitation.svelte +35 -0
- package/dist/citations/ThesisCitation.svelte.d.ts +29 -0
- package/dist/citations/bibliography.svelte.d.ts +55 -0
- package/dist/citations/bibliography.svelte.js +78 -0
- package/dist/citations/citation.d.ts +71 -0
- package/dist/citations/citation.js +121 -0
- package/dist/citations/csl.d.ts +102 -0
- package/dist/citations/csl.js +20 -0
- package/dist/citations/index.d.ts +31 -0
- package/dist/citations/index.js +36 -0
- package/dist/citations/list-format.d.ts +34 -0
- package/dist/citations/list-format.js +40 -0
- package/dist/context.svelte.d.ts +46 -0
- package/dist/context.svelte.js +51 -0
- package/dist/data/ChatBubble.svelte +48 -0
- package/dist/data/ChatBubble.svelte.d.ts +33 -0
- package/dist/data/DataGrid.svelte +150 -0
- package/dist/data/DataGrid.svelte.d.ts +118 -0
- package/dist/data/DescriptionList.svelte +53 -0
- package/dist/data/DescriptionList.svelte.d.ts +26 -0
- package/dist/data/DescriptionRow.svelte +56 -0
- package/dist/data/DescriptionRow.svelte.d.ts +21 -0
- package/dist/data/DiffText.svelte +29 -0
- package/dist/data/DiffText.svelte.d.ts +19 -0
- package/dist/data/ItemList.svelte +80 -0
- package/dist/data/ItemList.svelte.d.ts +52 -0
- package/dist/data/LinkListItem.svelte +46 -0
- package/dist/data/LinkListItem.svelte.d.ts +21 -0
- package/dist/data/MessageThread.svelte +29 -0
- package/dist/data/MessageThread.svelte.d.ts +17 -0
- package/dist/data/Pagination.svelte +136 -0
- package/dist/data/Pagination.svelte.d.ts +79 -0
- package/dist/data/PaginationFooter.svelte +42 -0
- package/dist/data/PaginationFooter.svelte.d.ts +61 -0
- package/dist/data/ResultCount.svelte +27 -0
- package/dist/data/ResultCount.svelte.d.ts +18 -0
- package/dist/data/Table.svelte +151 -0
- package/dist/data/Table.svelte.d.ts +75 -0
- package/dist/data/TreeList.svelte +41 -0
- package/dist/data/TreeList.svelte.d.ts +17 -0
- package/dist/data/TreeListItem.svelte +29 -0
- package/dist/data/TreeListItem.svelte.d.ts +10 -0
- package/dist/data/description-context.d.ts +39 -0
- package/dist/data/description-context.js +36 -0
- package/dist/data/diff.d.ts +14 -0
- package/dist/data/diff.js +10 -0
- package/dist/data/index.d.ts +37 -0
- package/dist/data/index.js +37 -0
- package/dist/data/list-item.d.ts +30 -0
- package/dist/data/list-item.js +19 -0
- package/dist/data/pagination.d.ts +81 -0
- package/dist/data/pagination.js +79 -0
- package/dist/data/table-types.d.ts +71 -0
- package/dist/data/table-types.js +35 -0
- package/dist/feedback/ConfirmDialog.svelte +79 -0
- package/dist/feedback/ConfirmDialog.svelte.d.ts +82 -0
- package/dist/feedback/Dialog.svelte +47 -0
- package/dist/feedback/Dialog.svelte.d.ts +36 -0
- package/dist/feedback/DialogFrame.svelte +64 -0
- package/dist/feedback/DialogFrame.svelte.d.ts +23 -0
- package/dist/feedback/Drawer.svelte +43 -0
- package/dist/feedback/Drawer.svelte.d.ts +43 -0
- package/dist/feedback/LoadingBoundary.svelte +61 -0
- package/dist/feedback/LoadingBoundary.svelte.d.ts +34 -0
- package/dist/feedback/ProgressBar.svelte +46 -0
- package/dist/feedback/ProgressBar.svelte.d.ts +28 -0
- package/dist/feedback/SegmentBar.svelte +83 -0
- package/dist/feedback/SegmentBar.svelte.d.ts +37 -0
- package/dist/feedback/StatTile.svelte +77 -0
- package/dist/feedback/StatTile.svelte.d.ts +50 -0
- package/dist/feedback/Stats.svelte +18 -0
- package/dist/feedback/Stats.svelte.d.ts +16 -0
- package/dist/feedback/Steps.svelte +72 -0
- package/dist/feedback/Steps.svelte.d.ts +61 -0
- package/dist/feedback/Timeline.svelte +86 -0
- package/dist/feedback/Timeline.svelte.d.ts +55 -0
- package/dist/feedback/Toaster.svelte +78 -0
- package/dist/feedback/Toaster.svelte.d.ts +32 -0
- package/dist/feedback/index.d.ts +34 -0
- package/dist/feedback/index.js +29 -0
- package/dist/feedback/sizes.d.ts +41 -0
- package/dist/feedback/sizes.js +69 -0
- package/dist/feedback/toaster.d.ts +48 -0
- package/dist/feedback/toaster.js +29 -0
- package/dist/fields/Calendar.svelte +60 -0
- package/dist/fields/Calendar.svelte.d.ts +11 -0
- package/dist/fields/CalendarMonths.svelte +86 -0
- package/dist/fields/CalendarMonths.svelte.d.ts +30 -0
- package/dist/fields/Checkbox.svelte +33 -0
- package/dist/fields/Checkbox.svelte.d.ts +30 -0
- package/dist/fields/CheckboxGroup.svelte +41 -0
- package/dist/fields/CheckboxGroup.svelte.d.ts +40 -0
- package/dist/fields/Combobox.svelte +229 -0
- package/dist/fields/Combobox.svelte.d.ts +133 -0
- package/dist/fields/DateField.svelte +37 -0
- package/dist/fields/DateField.svelte.d.ts +20 -0
- package/dist/fields/DateInput.svelte +31 -0
- package/dist/fields/DateInput.svelte.d.ts +35 -0
- package/dist/fields/DatePicker.svelte +47 -0
- package/dist/fields/DatePicker.svelte.d.ts +25 -0
- package/dist/fields/DateRangePicker.svelte +70 -0
- package/dist/fields/DateRangePicker.svelte.d.ts +43 -0
- package/dist/fields/Dropzone.svelte +232 -0
- package/dist/fields/Dropzone.svelte.d.ts +103 -0
- package/dist/fields/FieldErrors.svelte +30 -0
- package/dist/fields/FieldErrors.svelte.d.ts +11 -0
- package/dist/fields/Fieldset.svelte +53 -0
- package/dist/fields/Fieldset.svelte.d.ts +27 -0
- package/dist/fields/FileInput.svelte +68 -0
- package/dist/fields/FileInput.svelte.d.ts +39 -0
- package/dist/fields/FormField.svelte +78 -0
- package/dist/fields/FormField.svelte.d.ts +29 -0
- package/dist/fields/ImageInput.svelte +87 -0
- package/dist/fields/ImageInput.svelte.d.ts +45 -0
- package/dist/fields/MultiSelect.svelte +112 -0
- package/dist/fields/MultiSelect.svelte.d.ts +75 -0
- package/dist/fields/NumberField.svelte +190 -0
- package/dist/fields/NumberField.svelte.d.ts +76 -0
- package/dist/fields/PasswordInput.svelte +95 -0
- package/dist/fields/PasswordInput.svelte.d.ts +58 -0
- package/dist/fields/PickerPopover.svelte +47 -0
- package/dist/fields/PickerPopover.svelte.d.ts +16 -0
- package/dist/fields/PinInput.svelte +83 -0
- package/dist/fields/PinInput.svelte.d.ts +66 -0
- package/dist/fields/PushToggle.svelte +93 -0
- package/dist/fields/PushToggle.svelte.d.ts +55 -0
- package/dist/fields/RadioGroup.svelte +88 -0
- package/dist/fields/RadioGroup.svelte.d.ts +41 -0
- package/dist/fields/RangeCalendar.svelte +51 -0
- package/dist/fields/RangeCalendar.svelte.d.ts +23 -0
- package/dist/fields/Rating.svelte +127 -0
- package/dist/fields/Rating.svelte.d.ts +86 -0
- package/dist/fields/SearchInput.svelte +58 -0
- package/dist/fields/SearchInput.svelte.d.ts +33 -0
- package/dist/fields/SegmentGroup.svelte +91 -0
- package/dist/fields/SegmentGroup.svelte.d.ts +20 -0
- package/dist/fields/Select.svelte +36 -0
- package/dist/fields/Select.svelte.d.ts +35 -0
- package/dist/fields/Slider.svelte +194 -0
- package/dist/fields/Slider.svelte.d.ts +100 -0
- package/dist/fields/TagsInput.svelte +256 -0
- package/dist/fields/TagsInput.svelte.d.ts +102 -0
- package/dist/fields/TextInput.svelte +26 -0
- package/dist/fields/TextInput.svelte.d.ts +36 -0
- package/dist/fields/Textarea.svelte +22 -0
- package/dist/fields/Textarea.svelte.d.ts +31 -0
- package/dist/fields/TimeField.svelte +30 -0
- package/dist/fields/TimeField.svelte.d.ts +19 -0
- package/dist/fields/Toggle.svelte +72 -0
- package/dist/fields/Toggle.svelte.d.ts +38 -0
- package/dist/fields/VideoInput.svelte +35 -0
- package/dist/fields/VideoInput.svelte.d.ts +46 -0
- package/dist/fields/calendar-props.d.ts +119 -0
- package/dist/fields/calendar-props.js +51 -0
- package/dist/fields/dates.d.ts +28 -0
- package/dist/fields/dates.js +26 -0
- package/dist/fields/field-types.d.ts +80 -0
- package/dist/fields/field-types.js +92 -0
- package/dist/fields/file-validation.d.ts +30 -0
- package/dist/fields/file-validation.js +51 -0
- package/dist/fields/index.d.ts +43 -0
- package/dist/fields/index.js +42 -0
- package/dist/fields/latest-search.svelte.d.ts +38 -0
- package/dist/fields/latest-search.svelte.js +85 -0
- package/dist/fields/number-format.d.ts +52 -0
- package/dist/fields/number-format.js +89 -0
- package/dist/fields/segmented-field.d.ts +128 -0
- package/dist/fields/segmented-field.js +52 -0
- package/dist/fields/slider-keys.d.ts +21 -0
- package/dist/fields/slider-keys.js +37 -0
- package/dist/formatting/Countdown.svelte +110 -0
- package/dist/formatting/Countdown.svelte.d.ts +35 -0
- package/dist/formatting/DateTime.svelte +35 -0
- package/dist/formatting/DateTime.svelte.d.ts +26 -0
- package/dist/formatting/Duration.svelte +18 -0
- package/dist/formatting/Duration.svelte.d.ts +20 -0
- package/dist/formatting/FormatList.svelte +31 -0
- package/dist/formatting/FormatList.svelte.d.ts +46 -0
- package/dist/formatting/Highlight.svelte +51 -0
- package/dist/formatting/Highlight.svelte.d.ts +19 -0
- package/dist/formatting/Number.svelte +35 -0
- package/dist/formatting/Number.svelte.d.ts +43 -0
- package/dist/formatting/RelativeTime.svelte +69 -0
- package/dist/formatting/RelativeTime.svelte.d.ts +26 -0
- package/dist/formatting/Year.svelte +39 -0
- package/dist/formatting/Year.svelte.d.ts +21 -0
- package/dist/formatting/duration.d.ts +44 -0
- package/dist/formatting/duration.js +125 -0
- package/dist/formatting/index.d.ts +15 -0
- package/dist/formatting/index.js +17 -0
- package/dist/forms/EntityForm.svelte +185 -0
- package/dist/forms/EntityForm.svelte.d.ts +66 -0
- package/dist/forms/FormActions.svelte +29 -0
- package/dist/forms/FormActions.svelte.d.ts +37 -0
- package/dist/forms/FormErrors.svelte +21 -0
- package/dist/forms/FormErrors.svelte.d.ts +16 -0
- package/dist/forms/HiddenField.svelte +22 -0
- package/dist/forms/HiddenField.svelte.d.ts +11 -0
- package/dist/forms/SearchForm.svelte +43 -0
- package/dist/forms/SearchForm.svelte.d.ts +36 -0
- package/dist/forms/entity-form.d.ts +12 -0
- package/dist/forms/entity-form.js +12 -0
- package/dist/forms/index.d.ts +14 -0
- package/dist/forms/index.js +14 -0
- package/dist/hotkeys/HotkeyBadge.svelte +39 -0
- package/dist/hotkeys/HotkeyBadge.svelte.d.ts +25 -0
- package/dist/hotkeys/HotkeyHelpDialog.svelte +68 -0
- package/dist/hotkeys/HotkeyHelpDialog.svelte.d.ts +35 -0
- package/dist/hotkeys/HotkeyProvider.svelte +92 -0
- package/dist/hotkeys/HotkeyProvider.svelte.d.ts +4 -0
- package/dist/hotkeys/context.svelte.d.ts +47 -0
- package/dist/hotkeys/context.svelte.js +72 -0
- package/dist/hotkeys/index.d.ts +28 -0
- package/dist/hotkeys/index.js +27 -0
- package/dist/hotkeys/match.d.ts +65 -0
- package/dist/hotkeys/match.js +135 -0
- package/dist/hotkeys/registry.svelte.d.ts +55 -0
- package/dist/hotkeys/registry.svelte.js +110 -0
- package/dist/hotkeys/types.d.ts +74 -0
- package/dist/hotkeys/types.js +18 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +37 -0
- package/dist/infobox/Infobox.svelte +79 -0
- package/dist/infobox/Infobox.svelte.d.ts +33 -0
- package/dist/infobox/InfoboxHeader.svelte +35 -0
- package/dist/infobox/InfoboxHeader.svelte.d.ts +18 -0
- package/dist/infobox/InfoboxImage.svelte +38 -0
- package/dist/infobox/InfoboxImage.svelte.d.ts +21 -0
- package/dist/infobox/InfoboxRow.svelte +50 -0
- package/dist/infobox/InfoboxRow.svelte.d.ts +25 -0
- package/dist/infobox/InfoboxSection.svelte +24 -0
- package/dist/infobox/InfoboxSection.svelte.d.ts +12 -0
- package/dist/infobox/index.d.ts +21 -0
- package/dist/infobox/index.js +20 -0
- package/dist/infobox/types.d.ts +86 -0
- package/dist/infobox/types.js +27 -0
- package/dist/layout/AppShell.svelte +50 -0
- package/dist/layout/AppShell.svelte.d.ts +28 -0
- package/dist/layout/Breadcrumbs.svelte +52 -0
- package/dist/layout/Breadcrumbs.svelte.d.ts +18 -0
- package/dist/layout/Cluster.svelte +28 -0
- package/dist/layout/Cluster.svelte.d.ts +27 -0
- package/dist/layout/DetailLayout.svelte +50 -0
- package/dist/layout/DetailLayout.svelte.d.ts +19 -0
- package/dist/layout/FilterBar.svelte +40 -0
- package/dist/layout/FilterBar.svelte.d.ts +12 -0
- package/dist/layout/Fits.svelte +27 -0
- package/dist/layout/Fits.svelte.d.ts +13 -0
- package/dist/layout/Flow.svelte +46 -0
- package/dist/layout/Flow.svelte.d.ts +16 -0
- package/dist/layout/Footer.svelte +32 -0
- package/dist/layout/Footer.svelte.d.ts +12 -0
- package/dist/layout/Grid.svelte +23 -0
- package/dist/layout/Grid.svelte.d.ts +26 -0
- package/dist/layout/HStack.svelte +12 -0
- package/dist/layout/HStack.svelte.d.ts +34 -0
- package/dist/layout/Hero.svelte +76 -0
- package/dist/layout/Hero.svelte.d.ts +36 -0
- package/dist/layout/Main.svelte +30 -0
- package/dist/layout/Main.svelte.d.ts +15 -0
- package/dist/layout/Navbar.svelte +68 -0
- package/dist/layout/Navbar.svelte.d.ts +31 -0
- package/dist/layout/PageHeader.svelte +77 -0
- package/dist/layout/PageHeader.svelte.d.ts +33 -0
- package/dist/layout/Section.svelte +72 -0
- package/dist/layout/Section.svelte.d.ts +40 -0
- package/dist/layout/Sidebar.svelte +54 -0
- package/dist/layout/Sidebar.svelte.d.ts +27 -0
- package/dist/layout/Spacer.svelte +12 -0
- package/dist/layout/Spacer.svelte.d.ts +6 -0
- package/dist/layout/Tabs.svelte +85 -0
- package/dist/layout/Tabs.svelte.d.ts +42 -0
- package/dist/layout/VStack.svelte +12 -0
- package/dist/layout/VStack.svelte.d.ts +29 -0
- package/dist/layout/index.d.ts +38 -0
- package/dist/layout/index.js +38 -0
- package/dist/layout/space.d.ts +44 -0
- package/dist/layout/space.js +76 -0
- package/dist/layout/types.d.ts +52 -0
- package/dist/layout/types.js +27 -0
- package/dist/links/ContextLinks.svelte +28 -0
- package/dist/links/ContextLinks.svelte.d.ts +20 -0
- package/dist/links/EmailLink.svelte +26 -0
- package/dist/links/EmailLink.svelte.d.ts +20 -0
- package/dist/links/index.d.ts +7 -0
- package/dist/links/index.js +7 -0
- package/dist/media/Figure.svelte +26 -0
- package/dist/media/Figure.svelte.d.ts +12 -0
- package/dist/media/Image.svelte +76 -0
- package/dist/media/Image.svelte.d.ts +41 -0
- package/dist/media/Video.svelte +65 -0
- package/dist/media/Video.svelte.d.ts +29 -0
- package/dist/media/image-dimensions.d.ts +28 -0
- package/dist/media/image-dimensions.js +34 -0
- package/dist/media/index.d.ts +10 -0
- package/dist/media/index.js +10 -0
- package/dist/search/CommandPalette.svelte +257 -0
- package/dist/search/CommandPalette.svelte.d.ts +59 -0
- package/dist/search/index.d.ts +13 -0
- package/dist/search/index.js +13 -0
- package/dist/search/types.d.ts +40 -0
- package/dist/search/types.js +20 -0
- package/dist/seo/Head.svelte +190 -0
- package/dist/seo/Head.svelte.d.ts +86 -0
- package/dist/seo/JsonLd.svelte +30 -0
- package/dist/seo/JsonLd.svelte.d.ts +20 -0
- package/dist/seo/index.d.ts +18 -0
- package/dist/seo/index.js +17 -0
- package/dist/seo/json-ld.d.ts +33 -0
- package/dist/seo/json-ld.js +29 -0
- package/dist/seo/og-image.d.ts +72 -0
- package/dist/seo/og-image.js +82 -0
- package/dist/seo/types.d.ts +43 -0
- package/dist/seo/types.js +6 -0
- package/dist/theme.css +161 -0
- package/dist/tips/PopoverTip.svelte +80 -0
- package/dist/tips/PopoverTip.svelte.d.ts +33 -0
- package/dist/tips/Tip.svelte +91 -0
- package/dist/tips/Tip.svelte.d.ts +25 -0
- package/dist/tips/index.d.ts +15 -0
- package/dist/tips/index.js +14 -0
- package/dist/tips/tip-stack.d.ts +26 -0
- package/dist/tips/tip-stack.js +37 -0
- package/dist/tips/tip-store.svelte.d.ts +75 -0
- package/dist/tips/tip-store.svelte.js +158 -0
- package/dist/tips/types.d.ts +46 -0
- package/dist/tips/types.js +6 -0
- package/dist/ui/Accordion.svelte +75 -0
- package/dist/ui/Accordion.svelte.d.ts +50 -0
- package/dist/ui/AccordionItem.svelte +73 -0
- package/dist/ui/AccordionItem.svelte.d.ts +18 -0
- package/dist/ui/Alert.svelte +61 -0
- package/dist/ui/Alert.svelte.d.ts +37 -0
- package/dist/ui/Badge.svelte +39 -0
- package/dist/ui/Badge.svelte.d.ts +32 -0
- package/dist/ui/Button.svelte +44 -0
- package/dist/ui/Button.svelte.d.ts +29 -0
- package/dist/ui/ButtonGroup.svelte +24 -0
- package/dist/ui/ButtonGroup.svelte.d.ts +17 -0
- package/dist/ui/Card.svelte +49 -0
- package/dist/ui/Card.svelte.d.ts +44 -0
- package/dist/ui/Chip.svelte +58 -0
- package/dist/ui/Chip.svelte.d.ts +21 -0
- package/dist/ui/ConfirmButton.svelte +75 -0
- package/dist/ui/ConfirmButton.svelte.d.ts +48 -0
- package/dist/ui/ContextMenu.svelte +75 -0
- package/dist/ui/ContextMenu.svelte.d.ts +25 -0
- package/dist/ui/Disclosure.svelte +46 -0
- package/dist/ui/Disclosure.svelte.d.ts +22 -0
- package/dist/ui/Divider.svelte +47 -0
- package/dist/ui/Divider.svelte.d.ts +28 -0
- package/dist/ui/DropdownMenu.svelte +44 -0
- package/dist/ui/DropdownMenu.svelte.d.ts +30 -0
- package/dist/ui/EmptyState.svelte +37 -0
- package/dist/ui/EmptyState.svelte.d.ts +22 -0
- package/dist/ui/ExternalLink.svelte +38 -0
- package/dist/ui/ExternalLink.svelte.d.ts +34 -0
- package/dist/ui/Heading.svelte +58 -0
- package/dist/ui/Heading.svelte.d.ts +22 -0
- package/dist/ui/Link.svelte +34 -0
- package/dist/ui/Link.svelte.d.ts +20 -0
- package/dist/ui/LinkButton.svelte +51 -0
- package/dist/ui/LinkButton.svelte.d.ts +33 -0
- package/dist/ui/Menu.svelte +24 -0
- package/dist/ui/Menu.svelte.d.ts +13 -0
- package/dist/ui/MenuCheckboxItem.svelte +33 -0
- package/dist/ui/MenuCheckboxItem.svelte.d.ts +20 -0
- package/dist/ui/MenuItem.svelte +73 -0
- package/dist/ui/MenuItem.svelte.d.ts +21 -0
- package/dist/ui/MenuRadioGroup.svelte +25 -0
- package/dist/ui/MenuRadioGroup.svelte.d.ts +20 -0
- package/dist/ui/MenuRadioItem.svelte +20 -0
- package/dist/ui/MenuRadioItem.svelte.d.ts +15 -0
- package/dist/ui/MenuSeparator.svelte +27 -0
- package/dist/ui/MenuSeparator.svelte.d.ts +8 -0
- package/dist/ui/MenuSub.svelte +24 -0
- package/dist/ui/MenuSub.svelte.d.ts +15 -0
- package/dist/ui/Popover.svelte +63 -0
- package/dist/ui/Popover.svelte.d.ts +40 -0
- package/dist/ui/ShareButton.svelte +64 -0
- package/dist/ui/ShareButton.svelte.d.ts +39 -0
- package/dist/ui/Skeleton.svelte +43 -0
- package/dist/ui/Skeleton.svelte.d.ts +22 -0
- package/dist/ui/Spinner.svelte +41 -0
- package/dist/ui/Spinner.svelte.d.ts +35 -0
- package/dist/ui/Stack.svelte +36 -0
- package/dist/ui/Stack.svelte.d.ts +48 -0
- package/dist/ui/ThemeToggle.svelte +65 -0
- package/dist/ui/ThemeToggle.svelte.d.ts +24 -0
- package/dist/ui/ToggleButton.svelte +58 -0
- package/dist/ui/ToggleButton.svelte.d.ts +45 -0
- package/dist/ui/ToggleGroup.svelte +142 -0
- package/dist/ui/ToggleGroup.svelte.d.ts +86 -0
- package/dist/ui/Toolbar.svelte +40 -0
- package/dist/ui/Toolbar.svelte.d.ts +20 -0
- package/dist/ui/ToolbarButton.svelte +29 -0
- package/dist/ui/ToolbarButton.svelte.d.ts +21 -0
- package/dist/ui/ToolbarLink.svelte +21 -0
- package/dist/ui/ToolbarLink.svelte.d.ts +12 -0
- package/dist/ui/ToolbarSeparator.svelte +22 -0
- package/dist/ui/ToolbarSeparator.svelte.d.ts +12 -0
- package/dist/ui/ToolbarToggleGroup.svelte +66 -0
- package/dist/ui/ToolbarToggleGroup.svelte.d.ts +52 -0
- package/dist/ui/Tooltip.svelte +54 -0
- package/dist/ui/Tooltip.svelte.d.ts +35 -0
- package/dist/ui/VisuallyHidden.svelte +23 -0
- package/dist/ui/VisuallyHidden.svelte.d.ts +10 -0
- package/dist/ui/accordion-context.d.ts +26 -0
- package/dist/ui/accordion-context.js +23 -0
- package/dist/ui/colour-token.d.ts +41 -0
- package/dist/ui/colour-token.js +49 -0
- package/dist/ui/context-menu.d.ts +13 -0
- package/dist/ui/context-menu.js +13 -0
- package/dist/ui/index.d.ts +63 -0
- package/dist/ui/index.js +62 -0
- package/dist/ui/menu-context.d.ts +20 -0
- package/dist/ui/menu-context.js +22 -0
- package/dist/ui/menu-parts/CheckboxItemPart.svelte +26 -0
- package/dist/ui/menu-parts/CheckboxItemPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/ItemPart.svelte +29 -0
- package/dist/ui/menu-parts/ItemPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/RadioGroupPart.svelte +24 -0
- package/dist/ui/menu-parts/RadioGroupPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/RadioItemPart.svelte +22 -0
- package/dist/ui/menu-parts/RadioItemPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/SeparatorPart.svelte +16 -0
- package/dist/ui/menu-parts/SeparatorPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/SubPart.svelte +28 -0
- package/dist/ui/menu-parts/SubPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/menu-parts.d.ts +104 -0
- package/dist/ui/menu-parts/menu-parts.js +31 -0
- package/dist/ui/menu-parts/parts.d.ts +12 -0
- package/dist/ui/menu-parts/parts.js +27 -0
- package/dist/ui/slug.d.ts +19 -0
- package/dist/ui/slug.js +25 -0
- package/dist/ui/toggle-classes.d.ts +39 -0
- package/dist/ui/toggle-classes.js +36 -0
- package/dist/ui/tones.d.ts +103 -0
- package/dist/ui/tones.js +240 -0
- package/package.json +41 -25
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading an image file's intrinsic pixel dimensions in the browser.
|
|
3
|
+
*
|
|
4
|
+
* A form that uploads an image wants its `width` / `height` alongside the
|
|
5
|
+
* binary, so the page that later renders it can reserve the box on first
|
|
6
|
+
* paint instead of reflowing when it loads — and the browser can decode the
|
|
7
|
+
* file for free the moment it is chosen, where a server would have to.
|
|
8
|
+
* `fields/ImageInput` measures with this; a caller with its own file control
|
|
9
|
+
* uses it directly.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
/** Thrown by {@link imageDimensions} where there is no `createImageBitmap` (on a server). */
|
|
14
|
+
export class ImageDimensionsUnavailable extends Error {
|
|
15
|
+
name = 'ImageDimensionsUnavailable';
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Decode `file` with `createImageBitmap` and return its pixel size.
|
|
19
|
+
*
|
|
20
|
+
* Rejects with {@link ImageDimensionsUnavailable} outside a browser, and with
|
|
21
|
+
* the browser's own error when the file does not decode as an image.
|
|
22
|
+
*/
|
|
23
|
+
export async function imageDimensions(file) {
|
|
24
|
+
if (typeof globalThis.createImageBitmap !== 'function') {
|
|
25
|
+
throw new ImageDimensionsUnavailable('imageDimensions needs createImageBitmap, which only a browser has.');
|
|
26
|
+
}
|
|
27
|
+
const bitmap = await globalThis.createImageBitmap(file);
|
|
28
|
+
try {
|
|
29
|
+
return { width: bitmap.width, height: bitmap.height };
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
bitmap.close();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* media — images, video and figures. See the package README for the family
|
|
3
|
+
* reference.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
export { default as Image } from './Image.svelte';
|
|
8
|
+
export { default as Video } from './Video.svelte';
|
|
9
|
+
export { default as Figure } from './Figure.svelte';
|
|
10
|
+
export { imageDimensions, ImageDimensionsUnavailable, type ImageDimensions, } from './image-dimensions.ts';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* media — images, video and figures. See the package README for the family
|
|
3
|
+
* reference.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
export { default as Image } from './Image.svelte';
|
|
8
|
+
export { default as Video } from './Video.svelte';
|
|
9
|
+
export { default as Figure } from './Figure.svelte';
|
|
10
|
+
export { imageDimensions, ImageDimensionsUnavailable, } from "./image-dimensions.js";
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
The ⌘K / Ctrl+K command palette: bits-ui’s `Command` inside this library’s `Dialog`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
CommandPalette — the ⌘K / Ctrl+K palette: bits-ui's `Command` inside this
|
|
6
|
+
library's `Dialog`.
|
|
7
|
+
|
|
8
|
+
Two sources of rows, either of which may be absent:
|
|
9
|
+
|
|
10
|
+
- **The hotkey registry**, when one is mounted above. `paletteActions` is
|
|
11
|
+
already role-filtered and in registration order, and each row shows its
|
|
12
|
+
trigger as a `HotkeyBadge`, so the palette teaches the keyboard while it
|
|
13
|
+
is used with the mouse. The palette also binds its open state to the
|
|
14
|
+
registry's `paletteOpen`, which is what a registered `$mod+k` action
|
|
15
|
+
toggles.
|
|
16
|
+
- **`items` and `onSearch`**, which need no registry at all. That is what
|
|
17
|
+
makes this usable in an app that wants a palette but not a hotkey system.
|
|
18
|
+
|
|
19
|
+
The search lifecycle is `fields/Combobox`'s, for the same reasons: a
|
|
20
|
+
keystroke does not start a request, `debounceMs` of quiet does; each request
|
|
21
|
+
gets an `AbortController` and starting a new one aborts the last, so a slow
|
|
22
|
+
first response cannot overwrite a fast second one; and the previous rows
|
|
23
|
+
stay on screen while the next request is in flight, because clearing on
|
|
24
|
+
every keystroke makes the list strobe and costs the reader the row they were
|
|
25
|
+
about to pick.
|
|
26
|
+
|
|
27
|
+
`shouldFilter` is off exactly when `onSearch` is given: async rows are
|
|
28
|
+
already the server's answer to the query, and bits-ui re-filtering them
|
|
29
|
+
would hide rows whose match is in a field the label doesn't show. Without
|
|
30
|
+
`onSearch`, bits-ui's own scoring is better than anything here. Registry and
|
|
31
|
+
`items` rows are filtered locally by label in the async case, so they do not
|
|
32
|
+
outlive the query either.
|
|
33
|
+
|
|
34
|
+
ARIA contract: `Dialog`'s (bits-ui: `aria-modal`, the focus trap, Escape,
|
|
35
|
+
the focus return) plus `Command`'s — the input is a `combobox` owning a
|
|
36
|
+
`listbox`, each row an `option`, `aria-activedescendant` follows the arrow
|
|
37
|
+
keys and Enter selects. `label` names the command menu for assistive
|
|
38
|
+
technology and also titles the dialog. The pending row is
|
|
39
|
+
`Command.Loading`, named by `loadingLabel`, so a reader is told the list is
|
|
40
|
+
still settling instead of hearing an empty list.
|
|
41
|
+
-->
|
|
42
|
+
<script lang="ts">import { Command } from "bits-ui";
|
|
43
|
+
import { untrack } from "svelte";
|
|
44
|
+
import { getComponentsContext } from "../context.svelte.js";
|
|
45
|
+
import Dialog from "../feedback/Dialog.svelte";
|
|
46
|
+
import HotkeyBadge from "../hotkeys/HotkeyBadge.svelte";
|
|
47
|
+
import { tryGetHotkeyRegistry } from "../hotkeys/context.svelte.js";
|
|
48
|
+
import Badge from "../ui/Badge.svelte";
|
|
49
|
+
import { defaultCommandGroups } from "./types.js";
|
|
50
|
+
let { open = $bindable(false), label = "Command palette", placeholder = "Type a command or search…", loadingLabel = "Searching…", emptyLabel = "No results", closeLabel = "Close", groups = defaultCommandGroups, items, onSearch, debounceMs = 150, onSelect, item } = $props();
|
|
51
|
+
const context = getComponentsContext();
|
|
52
|
+
const registry = tryGetHotkeyRegistry();
|
|
53
|
+
let query = $state("");
|
|
54
|
+
const trimmedQuery = $derived(query.trim());
|
|
55
|
+
// ── Open state ───────────────────────────────────────────────────
|
|
56
|
+
//
|
|
57
|
+
// With a registry, `paletteOpen` and `open` are two halves of one value:
|
|
58
|
+
// the registered `$mod+k` action writes the registry, a caller may write
|
|
59
|
+
// the prop, and both have to end up agreeing. The trackers below make the
|
|
60
|
+
// sync converge — whichever side changed is copied to the other and both
|
|
61
|
+
// trackers are updated, so the effect's own writes find nothing to do on
|
|
62
|
+
// the re-run.
|
|
63
|
+
let lastOpen = open;
|
|
64
|
+
let lastPaletteOpen = registry?.paletteOpen ?? open;
|
|
65
|
+
$effect(() => {
|
|
66
|
+
if (registry === undefined) return;
|
|
67
|
+
const fromProp = open;
|
|
68
|
+
const fromRegistry = registry.paletteOpen;
|
|
69
|
+
if (fromProp !== lastOpen) {
|
|
70
|
+
lastOpen = fromProp;
|
|
71
|
+
lastPaletteOpen = fromProp;
|
|
72
|
+
registry.paletteOpen = fromProp;
|
|
73
|
+
} else if (fromRegistry !== lastPaletteOpen) {
|
|
74
|
+
lastPaletteOpen = fromRegistry;
|
|
75
|
+
lastOpen = fromRegistry;
|
|
76
|
+
open = fromRegistry;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
// bits-ui's `Dialog` moves focus to the first tabbable child as it opens,
|
|
80
|
+
// which here is the dialog's own close button. A palette has to open with
|
|
81
|
+
// the cursor in its query box — anything else costs the reader a Tab before
|
|
82
|
+
// they can type, and leaves the arrow keys (which `Command` handles on the
|
|
83
|
+
// input) doing nothing. Hence the frame's delay: focusing before the
|
|
84
|
+
// dialog's own focus move would simply be undone.
|
|
85
|
+
let input = $state(null);
|
|
86
|
+
$effect(() => {
|
|
87
|
+
const element = input;
|
|
88
|
+
if (!open || element === null) return;
|
|
89
|
+
const frame = requestAnimationFrame(() => element.focus());
|
|
90
|
+
return () => cancelAnimationFrame(frame);
|
|
91
|
+
});
|
|
92
|
+
const setOpen = (next) => {
|
|
93
|
+
open = next;
|
|
94
|
+
// Closing clears the query: a palette that reopens on the last search is
|
|
95
|
+
// a palette that shows yesterday's answer to today's question.
|
|
96
|
+
if (!next) query = "";
|
|
97
|
+
};
|
|
98
|
+
/** In async mode this component owns filtering, so local rows filter here. */
|
|
99
|
+
const matchesQuery = (candidate) => {
|
|
100
|
+
if (onSearch === undefined || trimmedQuery === "") return true;
|
|
101
|
+
return candidate.label.toLowerCase().includes(trimmedQuery.toLowerCase());
|
|
102
|
+
};
|
|
103
|
+
const registryRows = $derived((registry?.paletteActions ?? []).map((entry) => ({
|
|
104
|
+
item: {
|
|
105
|
+
id: entry.action.id,
|
|
106
|
+
label: entry.action.label,
|
|
107
|
+
group: entry.action.group,
|
|
108
|
+
run: entry.action.run
|
|
109
|
+
},
|
|
110
|
+
trigger: entry.action.trigger
|
|
111
|
+
})));
|
|
112
|
+
const staticRows = $derived((items ?? []).map((candidate) => ({
|
|
113
|
+
item: candidate,
|
|
114
|
+
trigger: undefined
|
|
115
|
+
})));
|
|
116
|
+
let results = $state([]);
|
|
117
|
+
const resultRows = $derived(results.map((candidate) => ({
|
|
118
|
+
item: candidate,
|
|
119
|
+
trigger: undefined
|
|
120
|
+
})));
|
|
121
|
+
const rows = $derived([
|
|
122
|
+
...registryRows,
|
|
123
|
+
...staticRows,
|
|
124
|
+
...resultRows
|
|
125
|
+
].filter((row) => matchesQuery(row.item)));
|
|
126
|
+
const sections = $derived(groups.map((group) => ({
|
|
127
|
+
group,
|
|
128
|
+
rows: rows.filter((row) => row.item.group === group.id)
|
|
129
|
+
})).filter((section) => section.rows.length > 0));
|
|
130
|
+
// ── Async search ─────────────────────────────────────────────────
|
|
131
|
+
let pending = $state(false);
|
|
132
|
+
let timer;
|
|
133
|
+
let inFlight;
|
|
134
|
+
const search = (text) => {
|
|
135
|
+
if (onSearch === undefined) return;
|
|
136
|
+
inFlight?.abort();
|
|
137
|
+
const own = new AbortController();
|
|
138
|
+
inFlight = own;
|
|
139
|
+
pending = true;
|
|
140
|
+
void onSearch(text, own.signal).then((next) => {
|
|
141
|
+
// A superseded request must not write: `inFlight` is the identity
|
|
142
|
+
// check, `signal.aborted` catches the caller aborting its own work.
|
|
143
|
+
if (own.signal.aborted || inFlight !== own) return;
|
|
144
|
+
results = next;
|
|
145
|
+
pending = false;
|
|
146
|
+
}).catch(() => {
|
|
147
|
+
if (own.signal.aborted || inFlight !== own) return;
|
|
148
|
+
pending = false;
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
const cancel = () => {
|
|
152
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
153
|
+
timer = undefined;
|
|
154
|
+
inFlight?.abort();
|
|
155
|
+
inFlight = undefined;
|
|
156
|
+
};
|
|
157
|
+
const emit = (text) => {
|
|
158
|
+
if (onSearch === undefined) return;
|
|
159
|
+
if (text === "") {
|
|
160
|
+
cancel();
|
|
161
|
+
pending = false;
|
|
162
|
+
results = [];
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
166
|
+
timer = setTimeout(() => {
|
|
167
|
+
timer = undefined;
|
|
168
|
+
search(text);
|
|
169
|
+
}, debounceMs);
|
|
170
|
+
};
|
|
171
|
+
// Emit only while the palette is open; closing it emits `''`, which resets
|
|
172
|
+
// the rows and cancels anything in flight.
|
|
173
|
+
$effect(() => {
|
|
174
|
+
const text = open ? trimmedQuery : "";
|
|
175
|
+
untrack(() => emit(text));
|
|
176
|
+
});
|
|
177
|
+
$effect(() => () => cancel());
|
|
178
|
+
const isEmpty = $derived(trimmedQuery.length > 0 && !pending && sections.length === 0);
|
|
179
|
+
// ── Activation ───────────────────────────────────────────────────
|
|
180
|
+
const activate = (candidate) => {
|
|
181
|
+
setOpen(false);
|
|
182
|
+
onSelect?.(candidate);
|
|
183
|
+
if (candidate.run !== undefined) void candidate.run();
|
|
184
|
+
if (candidate.href !== undefined) void context.navigate(context.href(candidate.href));
|
|
185
|
+
};
|
|
186
|
+
</script>
|
|
187
|
+
|
|
188
|
+
{#snippet row(entry: Row)}
|
|
189
|
+
<Command.Item
|
|
190
|
+
value={`${entry.item.group}:${entry.item.id}`}
|
|
191
|
+
keywords={[entry.item.label]}
|
|
192
|
+
onSelect={() => activate(entry.item)}
|
|
193
|
+
class="data-selected:bg-base-200 flex cursor-pointer items-center justify-between gap-4 rounded px-3 py-2"
|
|
194
|
+
>
|
|
195
|
+
{#if item}
|
|
196
|
+
{@render item(entry.item)}
|
|
197
|
+
{:else}
|
|
198
|
+
<span class="flex min-w-0 items-baseline gap-2">
|
|
199
|
+
<span class="truncate text-sm">{entry.item.label}</span>
|
|
200
|
+
{#if entry.item.hint !== undefined}
|
|
201
|
+
<span class="text-base-content/60 truncate text-xs">{entry.item.hint}</span>
|
|
202
|
+
{/if}
|
|
203
|
+
</span>
|
|
204
|
+
{#if entry.trigger !== undefined}
|
|
205
|
+
<HotkeyBadge trigger={entry.trigger} />
|
|
206
|
+
{:else if entry.item.badge !== undefined}
|
|
207
|
+
<Badge size="sm">{entry.item.badge}</Badge>
|
|
208
|
+
{/if}
|
|
209
|
+
{/if}
|
|
210
|
+
</Command.Item>
|
|
211
|
+
{/snippet}
|
|
212
|
+
|
|
213
|
+
<Dialog bind:open={() => open, setOpen} title={label} {closeLabel}>
|
|
214
|
+
<Command.Root shouldFilter={onSearch === undefined} loop {label} class="flex flex-col">
|
|
215
|
+
<Command.Input
|
|
216
|
+
bind:ref={input}
|
|
217
|
+
bind:value={query}
|
|
218
|
+
{placeholder}
|
|
219
|
+
class="input border-base-300 w-full rounded-none border-0 border-b focus:outline-none"
|
|
220
|
+
/>
|
|
221
|
+
<Command.List class="max-h-96 overflow-x-hidden overflow-y-auto pt-2">
|
|
222
|
+
<Command.Viewport>
|
|
223
|
+
{#each sections as section (section.group.id)}
|
|
224
|
+
<Command.Group value={section.group.id}>
|
|
225
|
+
<Command.GroupHeading
|
|
226
|
+
class="text-base-content/70 px-3 pt-3 pb-1 text-xs font-semibold tracking-wide uppercase"
|
|
227
|
+
>
|
|
228
|
+
{section.group.label}
|
|
229
|
+
</Command.GroupHeading>
|
|
230
|
+
<Command.GroupItems>
|
|
231
|
+
{#each section.rows as entry (`${entry.item.group}:${entry.item.id}`)}
|
|
232
|
+
{@render row(entry)}
|
|
233
|
+
{/each}
|
|
234
|
+
</Command.GroupItems>
|
|
235
|
+
</Command.Group>
|
|
236
|
+
{/each}
|
|
237
|
+
|
|
238
|
+
{#if pending && trimmedQuery.length > 0}
|
|
239
|
+
<!-- Through `child` so `aria-label` lands AFTER bits-ui's own
|
|
240
|
+
props: `Command.Loading` hard-codes the English "Loading...",
|
|
241
|
+
and in this library the name of anything is a prop. -->
|
|
242
|
+
<Command.Loading>
|
|
243
|
+
{#snippet child({ props })}
|
|
244
|
+
<div {...props} aria-label={loadingLabel} class="text-base-content/60 px-3 py-2 text-sm">
|
|
245
|
+
{loadingLabel}
|
|
246
|
+
</div>
|
|
247
|
+
{/snippet}
|
|
248
|
+
</Command.Loading>
|
|
249
|
+
{/if}
|
|
250
|
+
|
|
251
|
+
{#if isEmpty}
|
|
252
|
+
<p class="text-base-content/60 px-3 py-6 text-center text-sm">{emptyLabel}</p>
|
|
253
|
+
{/if}
|
|
254
|
+
</Command.Viewport>
|
|
255
|
+
</Command.List>
|
|
256
|
+
</Command.Root>
|
|
257
|
+
</Dialog>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import { type CommandGroup, type CommandItem } from './types.ts';
|
|
3
|
+
interface Props {
|
|
4
|
+
/**
|
|
5
|
+
* Whether the palette is shown. Bindable. Two-way bound to the hotkey
|
|
6
|
+
* registry's `paletteOpen` when a registry is mounted above.
|
|
7
|
+
*/
|
|
8
|
+
open?: boolean | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Names the command menu, and titles the dialog.
|
|
11
|
+
* @defaultValue `'Command palette'`
|
|
12
|
+
*/
|
|
13
|
+
label?: string | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Placeholder in the search field.
|
|
16
|
+
* @defaultValue `'Type a command or search…'`
|
|
17
|
+
*/
|
|
18
|
+
placeholder?: string | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Announced while an `onSearch` request is in flight.
|
|
21
|
+
* @defaultValue `'Searching…'`
|
|
22
|
+
*/
|
|
23
|
+
loadingLabel?: string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Shown when a settled query matched nothing.
|
|
26
|
+
* @defaultValue `'No results'`
|
|
27
|
+
*/
|
|
28
|
+
emptyLabel?: string | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Accessible name of the dialog's close button.
|
|
31
|
+
* @defaultValue `'Close'`
|
|
32
|
+
*/
|
|
33
|
+
closeLabel?: string | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* The sections, in render order. Rows name one by `id`.
|
|
36
|
+
* @defaultValue the exported `defaultCommandGroups`
|
|
37
|
+
*/
|
|
38
|
+
groups?: readonly CommandGroup[] | undefined;
|
|
39
|
+
/** Rows that are always available, registry or no registry. */
|
|
40
|
+
items?: readonly CommandItem[] | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Fetch rows for a query. Debounced by `debounceMs`; `signal` aborts when
|
|
43
|
+
* a newer query supersedes this one, so pass it to `fetch`.
|
|
44
|
+
*/
|
|
45
|
+
onSearch?: ((query: string, signal: AbortSignal) => Promise<readonly CommandItem[]>) | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Quiet period before a search starts, in milliseconds.
|
|
48
|
+
* @defaultValue `150`
|
|
49
|
+
*/
|
|
50
|
+
debounceMs?: number | undefined;
|
|
51
|
+
/** Called when a row is activated, before its own `run` / `href`. */
|
|
52
|
+
onSelect?: ((item: CommandItem) => void) | undefined;
|
|
53
|
+
/** Replace a row's contents. */
|
|
54
|
+
item?: Snippet<[CommandItem]> | undefined;
|
|
55
|
+
}
|
|
56
|
+
/** The ⌘K / Ctrl+K command palette: bits-ui’s `Command` inside this library’s `Dialog`. */
|
|
57
|
+
declare const CommandPalette: import("svelte").Component<Props, {}, "open">;
|
|
58
|
+
type CommandPalette = ReturnType<typeof CommandPalette>;
|
|
59
|
+
export default CommandPalette;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* search — the command palette.
|
|
3
|
+
*
|
|
4
|
+
* One component, because a palette is one thing: a dialog, a query box, and
|
|
5
|
+
* rows from wherever the app has them. It composes `feedback/Dialog` and
|
|
6
|
+
* bits-ui's `Command`, lists the hotkey registry's palette actions when a
|
|
7
|
+
* registry is mounted, and works from `items` / `onSearch` alone when none
|
|
8
|
+
* is.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
export { default as CommandPalette } from './CommandPalette.svelte';
|
|
13
|
+
export { defaultCommandGroups, type CommandGroup, type CommandItem } from './types.ts';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* search — the command palette.
|
|
3
|
+
*
|
|
4
|
+
* One component, because a palette is one thing: a dialog, a query box, and
|
|
5
|
+
* rows from wherever the app has them. It composes `feedback/Dialog` and
|
|
6
|
+
* bits-ui's `Command`, lists the hotkey registry's palette actions when a
|
|
7
|
+
* registry is mounted, and works from `items` / `onSearch` alone when none
|
|
8
|
+
* is.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
export { default as CommandPalette } from './CommandPalette.svelte';
|
|
13
|
+
export { defaultCommandGroups } from "./types.js";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The row and section shapes the command palette renders.
|
|
3
|
+
*
|
|
4
|
+
* A {@link CommandItem} is deliberately not a `CommandAction`: registry
|
|
5
|
+
* actions always run something, whereas a palette row can just as well be a
|
|
6
|
+
* search result that navigates, or a row whose whole behaviour is the
|
|
7
|
+
* caller's `onSelect`. The palette projects registry actions into this shape
|
|
8
|
+
* internally, so one row renderer serves both sources.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/** One row of the command palette: an id, a label, the group it sits in, and what activating it does. */
|
|
13
|
+
export interface CommandItem {
|
|
14
|
+
/** Stable id. Unique within its group; it is what bits-ui ranks and selects on. */
|
|
15
|
+
id: string;
|
|
16
|
+
/** The row's text — what the reader searches for and what is announced. */
|
|
17
|
+
label: string;
|
|
18
|
+
/** Which {@link CommandGroup} the row belongs in, by `id`. */
|
|
19
|
+
group: string;
|
|
20
|
+
/** Muted trailing text: a path, a date, a parent name. */
|
|
21
|
+
hint?: string | undefined;
|
|
22
|
+
/** A short chip on the right — a type, a status. */
|
|
23
|
+
badge?: string | undefined;
|
|
24
|
+
/** What activating the row does. Runs after the palette closes. */
|
|
25
|
+
run?: (() => void | Promise<void>) | undefined;
|
|
26
|
+
/** Where activating the row goes. Resolved through the components context. */
|
|
27
|
+
href?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
/** A palette section: an id rows point at, and the heading it renders. */
|
|
30
|
+
export interface CommandGroup {
|
|
31
|
+
/** What a `CommandItem`'s `group` names. */
|
|
32
|
+
id: string;
|
|
33
|
+
/** The section heading. */
|
|
34
|
+
label: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The sections a palette shows when given none: the two group ids the hotkey
|
|
38
|
+
* registry uses (`actions`, `navigation`), then whatever `onSearch` returns.
|
|
39
|
+
*/
|
|
40
|
+
export declare const defaultCommandGroups: readonly CommandGroup[];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The row and section shapes the command palette renders.
|
|
3
|
+
*
|
|
4
|
+
* A {@link CommandItem} is deliberately not a `CommandAction`: registry
|
|
5
|
+
* actions always run something, whereas a palette row can just as well be a
|
|
6
|
+
* search result that navigates, or a row whose whole behaviour is the
|
|
7
|
+
* caller's `onSelect`. The palette projects registry actions into this shape
|
|
8
|
+
* internally, so one row renderer serves both sources.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* The sections a palette shows when given none: the two group ids the hotkey
|
|
14
|
+
* registry uses (`actions`, `navigation`), then whatever `onSearch` returns.
|
|
15
|
+
*/
|
|
16
|
+
export const defaultCommandGroups = [
|
|
17
|
+
{ id: 'actions', label: 'Actions' },
|
|
18
|
+
{ id: 'navigation', label: 'Go to' },
|
|
19
|
+
{ id: 'results', label: 'Results' },
|
|
20
|
+
];
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
Per-page `<head>` metadata: title, description, canonical URL, `hreflang` alternates, Open Graph and Twitter / X tags, `article:*` and pagination links.
|
|
3
|
+
-->
|
|
4
|
+
<script lang="ts">/**
|
|
5
|
+
* Per-page `<head>` metadata: the title (with an optional site-name
|
|
6
|
+
* suffix), description, keywords, robots directive, canonical URL,
|
|
7
|
+
* `hreflang` alternates, an optional feed link, Open Graph and Twitter / X
|
|
8
|
+
* card tags, the `article:*` family, and `prev` / `next` pagination links.
|
|
9
|
+
*
|
|
10
|
+
* **Canonical on the production origin.** The explicit `canonical` wins;
|
|
11
|
+
* otherwise the page self-references `pathname` resolved through
|
|
12
|
+
* `canonicalHref` (the query is never part of it), so canonical and
|
|
13
|
+
* `og:url` are never empty and a preview host never becomes canonical.
|
|
14
|
+
* `canonicalHref` defaults to the components context's `href` — an app
|
|
15
|
+
* whose `href` returns relative paths passes its own absolute resolver
|
|
16
|
+
* here. `pathname` defaults to `window.location.pathname`, which does not
|
|
17
|
+
* exist during SSR: a SvelteKit app passes `pathname={page.url.pathname}`.
|
|
18
|
+
*
|
|
19
|
+
* **Share image, in precedence order:** an explicit `image`, then a
|
|
20
|
+
* per-page card built from `shareCard` by {@link ogImageUrl}, then
|
|
21
|
+
* `defaultImage` — so every share renders a card when a default is set.
|
|
22
|
+
*
|
|
23
|
+
* **`og:type`** is derived from the Schema.org `type` when `openGraphType`
|
|
24
|
+
* is not given, and the `article:*` tags are emitted only for `article`.
|
|
25
|
+
* **`og:locale`** comes from `ogLocale`, else the context locale with `-`
|
|
26
|
+
* replaced by `_` (`en-AU` → `en_AU`).
|
|
27
|
+
*
|
|
28
|
+
* Every string is a prop: `siteName` has no default (a library cannot know
|
|
29
|
+
* the site), `feed.title` defaults to `'Latest changes'`, and the share
|
|
30
|
+
* card's alt text defaults to `"<title> — <siteName>"` (the title alone without a `siteName`) via `shareCardAlt`.
|
|
31
|
+
*
|
|
32
|
+
* Renders only into `<svelte:head>`; there is no markup in the body.
|
|
33
|
+
*/
|
|
34
|
+
import { getComponentsContext } from "../context.svelte.js";
|
|
35
|
+
import { OG_IMAGE_HEIGHT, OG_IMAGE_WIDTH, ogImageUrl } from "./og-image.js";
|
|
36
|
+
let { title, siteName = undefined, titleSeparator = " | ", description = undefined, keywords = undefined, type = undefined, openGraphType = undefined, canonical = undefined, pathname = undefined, canonicalHref = undefined, alternates = undefined, locales = undefined, ogLocale = undefined, feed = undefined, robots = undefined, image = undefined, shareCard = undefined, shareCardPath = undefined, shareCardAlt = undefined, defaultImage = undefined, published = undefined, modified = undefined, section = undefined, tags = undefined, twitterCard = "summary_large_image", twitterSite = undefined, twitterCreator = undefined, prevUrl = undefined, nextUrl = undefined } = $props();
|
|
37
|
+
const context = getComponentsContext();
|
|
38
|
+
/** Schema.org type → Open Graph type, so `og:type` is never empty. */
|
|
39
|
+
const schemaToOpenGraph = {
|
|
40
|
+
WebPage: "website",
|
|
41
|
+
WebSite: "website",
|
|
42
|
+
CollectionPage: "website",
|
|
43
|
+
Article: "article",
|
|
44
|
+
BlogPosting: "article",
|
|
45
|
+
ProfilePage: "profile"
|
|
46
|
+
};
|
|
47
|
+
const resolveHref = $derived(canonicalHref ?? context.href);
|
|
48
|
+
const resolvedTitle = $derived.by(() => {
|
|
49
|
+
const trimmed = title.trim();
|
|
50
|
+
if (trimmed === "") return siteName ?? "";
|
|
51
|
+
return siteName === undefined || siteName === "" ? trimmed : `${trimmed}${titleSeparator}${siteName}`;
|
|
52
|
+
});
|
|
53
|
+
const resolvedDescription = $derived(description === null || description === undefined || description.trim() === "" ? undefined : description);
|
|
54
|
+
const resolvedCanonical = $derived.by(() => {
|
|
55
|
+
if (canonical !== undefined) return canonical;
|
|
56
|
+
const path = pathname ?? (typeof window === "undefined" ? undefined : window.location.pathname);
|
|
57
|
+
return path === undefined ? undefined : resolveHref(path);
|
|
58
|
+
});
|
|
59
|
+
const resolvedAlternates = $derived.by(() => {
|
|
60
|
+
if (alternates !== undefined) return alternates;
|
|
61
|
+
if (resolvedCanonical === undefined || locales === undefined || locales.length === 0) return [];
|
|
62
|
+
const href = resolvedCanonical;
|
|
63
|
+
return [...locales, "x-default"].map((lang) => ({
|
|
64
|
+
href,
|
|
65
|
+
lang
|
|
66
|
+
}));
|
|
67
|
+
});
|
|
68
|
+
const resolvedOgType = $derived(openGraphType ?? (type === undefined ? "website" : schemaToOpenGraph[type]));
|
|
69
|
+
const resolvedOgLocale = $derived.by(() => {
|
|
70
|
+
if (ogLocale !== undefined) return ogLocale;
|
|
71
|
+
const locale = context.locale();
|
|
72
|
+
const first = typeof locale === "string" ? locale : locale?.[0];
|
|
73
|
+
return first === undefined ? undefined : first.replace(/-/g, "_");
|
|
74
|
+
});
|
|
75
|
+
const cardImage = $derived.by(() => {
|
|
76
|
+
if (image !== undefined || shareCard === undefined) return undefined;
|
|
77
|
+
const url = ogImageUrl(shareCard, {
|
|
78
|
+
href: resolveHref,
|
|
79
|
+
basePath: shareCardPath
|
|
80
|
+
});
|
|
81
|
+
if (url === undefined) return undefined;
|
|
82
|
+
const alt = shareCardAlt?.(shareCard) ?? (siteName === undefined || siteName === "" ? shareCard.title.trim() : `${shareCard.title.trim()} — ${siteName}`);
|
|
83
|
+
return {
|
|
84
|
+
url,
|
|
85
|
+
alt,
|
|
86
|
+
width: OG_IMAGE_WIDTH,
|
|
87
|
+
height: OG_IMAGE_HEIGHT,
|
|
88
|
+
type: "image/png"
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
const resolvedImage = $derived(image ?? cardImage ?? defaultImage);
|
|
92
|
+
const robotsContent = $derived(`${robots?.index ?? true ? "index" : "noindex"}, ${robots?.follow ?? true ? "follow" : "nofollow"}`);
|
|
93
|
+
const resolvedSection = $derived(section?.trim() === "" ? undefined : section);
|
|
94
|
+
</script>
|
|
95
|
+
|
|
96
|
+
{#snippet articleMeta()}
|
|
97
|
+
{#if published !== undefined}
|
|
98
|
+
<meta property="article:published_time" content={published.toISOString()} />
|
|
99
|
+
{/if}
|
|
100
|
+
{#if modified !== undefined}
|
|
101
|
+
<meta property="article:modified_time" content={modified.toISOString()} />
|
|
102
|
+
{/if}
|
|
103
|
+
{#if resolvedSection !== undefined}
|
|
104
|
+
<meta property="article:section" content={resolvedSection} />
|
|
105
|
+
{/if}
|
|
106
|
+
{#each tags ?? [] as tag}
|
|
107
|
+
<meta property="article:tag" content={tag} />
|
|
108
|
+
{/each}
|
|
109
|
+
{/snippet}
|
|
110
|
+
|
|
111
|
+
<svelte:head>
|
|
112
|
+
<title>{resolvedTitle}</title>
|
|
113
|
+
{#if resolvedDescription !== undefined}
|
|
114
|
+
<meta name="description" content={resolvedDescription} />
|
|
115
|
+
{/if}
|
|
116
|
+
{#if keywords !== undefined && keywords.length > 0}
|
|
117
|
+
<meta name="keywords" content={keywords.join(', ')} />
|
|
118
|
+
{/if}
|
|
119
|
+
{#if resolvedCanonical !== undefined}
|
|
120
|
+
<link rel="canonical" href={resolvedCanonical} />
|
|
121
|
+
{/if}
|
|
122
|
+
{#if feed !== undefined}
|
|
123
|
+
<link
|
|
124
|
+
rel="alternate"
|
|
125
|
+
type={feed.type ?? 'application/feed+json'}
|
|
126
|
+
href={resolveHref(feed.path)}
|
|
127
|
+
title={feed.title ?? 'Latest changes'}
|
|
128
|
+
/>
|
|
129
|
+
{/if}
|
|
130
|
+
<meta name="robots" content={robotsContent} />
|
|
131
|
+
|
|
132
|
+
<meta property="og:title" content={resolvedTitle} />
|
|
133
|
+
{#if resolvedCanonical !== undefined}
|
|
134
|
+
<meta property="og:url" content={resolvedCanonical} />
|
|
135
|
+
{/if}
|
|
136
|
+
{#if siteName !== undefined && siteName !== ''}
|
|
137
|
+
<meta property="og:site_name" content={siteName} />
|
|
138
|
+
{/if}
|
|
139
|
+
<meta property="og:type" content={resolvedOgType} />
|
|
140
|
+
{#if resolvedOgLocale !== undefined}
|
|
141
|
+
<meta property="og:locale" content={resolvedOgLocale} />
|
|
142
|
+
{/if}
|
|
143
|
+
{#if resolvedDescription !== undefined}
|
|
144
|
+
<meta property="og:description" content={resolvedDescription} />
|
|
145
|
+
{/if}
|
|
146
|
+
|
|
147
|
+
<meta name="twitter:card" content={twitterCard} />
|
|
148
|
+
{#if twitterSite !== undefined}
|
|
149
|
+
<meta name="twitter:site" content={twitterSite} />
|
|
150
|
+
{/if}
|
|
151
|
+
{#if twitterCreator !== undefined}
|
|
152
|
+
<meta name="twitter:creator" content={twitterCreator} />
|
|
153
|
+
{/if}
|
|
154
|
+
<meta name="twitter:title" content={resolvedTitle} />
|
|
155
|
+
{#if resolvedDescription !== undefined}
|
|
156
|
+
<meta name="twitter:description" content={resolvedDescription} />
|
|
157
|
+
{/if}
|
|
158
|
+
|
|
159
|
+
{#if resolvedImage !== undefined}
|
|
160
|
+
<meta property="og:image" content={resolvedImage.url} />
|
|
161
|
+
<meta name="twitter:image" content={resolvedImage.url} />
|
|
162
|
+
{#if resolvedImage.alt !== undefined && resolvedImage.alt !== ''}
|
|
163
|
+
<meta property="og:image:alt" content={resolvedImage.alt} />
|
|
164
|
+
<meta name="twitter:image:alt" content={resolvedImage.alt} />
|
|
165
|
+
{/if}
|
|
166
|
+
{#if resolvedImage.width !== undefined}
|
|
167
|
+
<meta property="og:image:width" content={String(resolvedImage.width)} />
|
|
168
|
+
{/if}
|
|
169
|
+
{#if resolvedImage.height !== undefined}
|
|
170
|
+
<meta property="og:image:height" content={String(resolvedImage.height)} />
|
|
171
|
+
{/if}
|
|
172
|
+
{#if resolvedImage.type !== undefined}
|
|
173
|
+
<meta property="og:image:type" content={resolvedImage.type} />
|
|
174
|
+
{/if}
|
|
175
|
+
{/if}
|
|
176
|
+
|
|
177
|
+
{#if resolvedOgType === 'article'}
|
|
178
|
+
{@render articleMeta()}
|
|
179
|
+
{/if}
|
|
180
|
+
|
|
181
|
+
{#each resolvedAlternates as alternate}
|
|
182
|
+
<link rel="alternate" href={alternate.href} hreflang={alternate.lang} />
|
|
183
|
+
{/each}
|
|
184
|
+
{#if prevUrl !== undefined}
|
|
185
|
+
<link rel="prev" href={prevUrl} />
|
|
186
|
+
{/if}
|
|
187
|
+
{#if nextUrl !== undefined}
|
|
188
|
+
<link rel="next" href={nextUrl} />
|
|
189
|
+
{/if}
|
|
190
|
+
</svelte:head>
|