@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,229 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A single-select typeahead over a static list or an asynchronous search, on bits-ui’s `Combobox`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
Combobox — a single-select typeahead over a static list OR an asynchronous
|
|
6
|
+
search, on bits-ui's `Combobox`.
|
|
7
|
+
|
|
8
|
+
The previous generation of this component hand-rolled the APG combobox
|
|
9
|
+
pattern: an `<input role="combobox">`, a `<ul role="listbox">`, an
|
|
10
|
+
`activeIndex`, wrap-around arrow keys, Home/End, and a blur timeout to let a
|
|
11
|
+
pointerdown on an option land before the list closed. All of that is
|
|
12
|
+
bits-ui's here. What is NOT bits-ui's, and is what this file is actually
|
|
13
|
+
about, is the SEARCH LIFECYCLE.
|
|
14
|
+
|
|
15
|
+
The search lifecycle (`latest-search.svelte.ts`, shared with `TagsInput`),
|
|
16
|
+
in the order the problems bite:
|
|
17
|
+
|
|
18
|
+
debounce a keystroke does not start a request; `debounceMs` of
|
|
19
|
+
quiet does.
|
|
20
|
+
latest-wins each request gets an `AbortController`, and starting a
|
|
21
|
+
new one aborts the last. A superseded request is
|
|
22
|
+
cancelled rather than merely ignored, so a slow first
|
|
23
|
+
response cannot overwrite a fast second one.
|
|
24
|
+
stale-while- the previous results stay on screen while the next
|
|
25
|
+
revalidate request is in flight, with `pending` true. Clearing the
|
|
26
|
+
list on every keystroke makes the dropdown strobe and
|
|
27
|
+
costs the reader the thing they were about to pick.
|
|
28
|
+
|
|
29
|
+
ARIA contract: bits-ui gives the input `role="combobox"`,
|
|
30
|
+
`aria-autocomplete="list"`, `aria-expanded` and `aria-activedescendant`
|
|
31
|
+
pointing at the highlighted option; the panel is `role="listbox"` and each
|
|
32
|
+
row `role="option"` with `aria-selected`. The visible `<label>` names the
|
|
33
|
+
input through `for`/`id`; `errorMessage` is a `role="alert"` paragraph the
|
|
34
|
+
input is NOT described by, because a search failure is about the list rather
|
|
35
|
+
than about the value.
|
|
36
|
+
|
|
37
|
+
One behaviour is preserved from the hand-rolled version on purpose:
|
|
38
|
+
**Enter with nothing highlighted must not prevent a wrapping `<form>` from
|
|
39
|
+
submitting.** A search box that sits in a plain GET form has to keep working
|
|
40
|
+
when the list is empty or the reader never opened it. bits-ui's input
|
|
41
|
+
`preventDefault`s Enter whenever the panel is open, so the handler below
|
|
42
|
+
closes the panel first when nothing is highlighted: with the panel closed,
|
|
43
|
+
bits-ui treats Enter as an interaction key and returns without touching the
|
|
44
|
+
event, and the form submits. `highlighted` is tracked through the items'
|
|
45
|
+
own `onHighlight` / `onUnhighlight` callbacks, which is the only place
|
|
46
|
+
bits-ui surfaces it.
|
|
47
|
+
|
|
48
|
+
Note what that means in practice: bits-ui puts the cursor on the first
|
|
49
|
+
candidate as soon as typing produces one, so with matches on screen Enter
|
|
50
|
+
COMMITS. The fall-through happens where it matters — a query that matched
|
|
51
|
+
nothing, or a panel the reader never opened — which is exactly the case a
|
|
52
|
+
no-JS search form depends on.
|
|
53
|
+
|
|
54
|
+
`postedValue="query"` turns the widget into a search box, and changes two
|
|
55
|
+
things. The `name` moves onto the visible `<input>`, so the form posts the
|
|
56
|
+
typed text, and it does so with JavaScript off because the server-rendered
|
|
57
|
+
input is the posted control. And Enter submits the form unless the reader
|
|
58
|
+
MOVED to an option with the keyboard (`navigated`): bits-ui's
|
|
59
|
+
auto-highlight of the first candidate does not count, so typing a query and
|
|
60
|
+
pressing Enter searches for that query instead of opening the first
|
|
61
|
+
suggestion. Clicking an option still commits it.
|
|
62
|
+
-->
|
|
63
|
+
<script lang="ts" generics="T">import { Combobox } from "bits-ui";
|
|
64
|
+
import { inputSize } from "./field-types.js";
|
|
65
|
+
import { LatestSearch } from "./latest-search.svelte.js";
|
|
66
|
+
let { value = $bindable(), items, onSearch, debounceMs = 150, getId, getLabel, getBadge, label, placeholder, name, postedValue = "id", initialQuery, onQueryChange, onSelect, emptyLabel = "No matches", pendingLabel = "Searching…", errorMessage, id: idProp, describedBy = "", labelId: _labelId, invalid = false, required = false, disabled = false, size = "md", class: className, inputClass, hideLabel = false, portal = true, item, footer, empty, ...rest } = $props();
|
|
67
|
+
const uid = $props.id();
|
|
68
|
+
const inputId = $derived(idProp ?? uid);
|
|
69
|
+
// Only the initial value seeds the text; later changes come from typing.
|
|
70
|
+
// svelte-ignore state_referenced_locally
|
|
71
|
+
let query = $state(initialQuery ?? "");
|
|
72
|
+
let open = $state(false);
|
|
73
|
+
const searcher = new LatestSearch(() => onSearch, () => debounceMs);
|
|
74
|
+
const results = $derived(searcher.results);
|
|
75
|
+
const pending = $derived(searcher.pending);
|
|
76
|
+
const searchError = $derived(searcher.error);
|
|
77
|
+
/** The id of the row bits-ui currently has under the cursor, if any. */
|
|
78
|
+
let highlighted = $state();
|
|
79
|
+
/** The reader moved the cursor with the keyboard since they last typed. */
|
|
80
|
+
let navigated = false;
|
|
81
|
+
/** Static mode filters locally; async mode shows whatever last settled. */
|
|
82
|
+
const visible = $derived.by(() => {
|
|
83
|
+
if (onSearch !== undefined) return results;
|
|
84
|
+
const all = items ?? [];
|
|
85
|
+
const needle = query.trim().toLowerCase();
|
|
86
|
+
if (needle === "") return all;
|
|
87
|
+
return all.filter((entry) => getLabel(entry).toLowerCase().includes(needle));
|
|
88
|
+
});
|
|
89
|
+
const selectedLabel = $derived.by(() => {
|
|
90
|
+
if (value === undefined || items === undefined) return undefined;
|
|
91
|
+
const match = items.find((entry) => getId(entry) === value);
|
|
92
|
+
return match === undefined ? undefined : getLabel(match);
|
|
93
|
+
});
|
|
94
|
+
/** Seeds bits-ui's input text once, at mount. */
|
|
95
|
+
const initialText = $derived(selectedLabel ?? initialQuery);
|
|
96
|
+
const postsQuery = $derived(postedValue === "query");
|
|
97
|
+
const visibleError = $derived(errorMessage ?? searchError);
|
|
98
|
+
$effect(() => () => searcher.dispose());
|
|
99
|
+
const typed = (event) => {
|
|
100
|
+
query = event.currentTarget.value;
|
|
101
|
+
navigated = false;
|
|
102
|
+
onQueryChange?.(query);
|
|
103
|
+
if (onSearch === undefined) {
|
|
104
|
+
open = true;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (query.trim() === "") {
|
|
108
|
+
searcher.clear();
|
|
109
|
+
open = false;
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
open = true;
|
|
113
|
+
searcher.schedule(query);
|
|
114
|
+
};
|
|
115
|
+
const navigationKeys = new Set([
|
|
116
|
+
"ArrowDown",
|
|
117
|
+
"ArrowUp",
|
|
118
|
+
"Home",
|
|
119
|
+
"End",
|
|
120
|
+
"PageDown",
|
|
121
|
+
"PageUp"
|
|
122
|
+
]);
|
|
123
|
+
const keydown = (event) => {
|
|
124
|
+
if (navigationKeys.has(event.key)) {
|
|
125
|
+
navigated = true;
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (event.key !== "Enter") return;
|
|
129
|
+
// In query mode a highlight the reader did not move to is bits-ui's
|
|
130
|
+
// auto-highlight, not a choice: treat it as nothing highlighted.
|
|
131
|
+
const committing = highlighted !== undefined && (!postsQuery || navigated);
|
|
132
|
+
if (committing) return;
|
|
133
|
+
// Nothing to commit. Close first so bits-ui's own Enter branch takes the
|
|
134
|
+
// closed path, which returns without `preventDefault` — that is what lets
|
|
135
|
+
// a wrapping form submit.
|
|
136
|
+
open = false;
|
|
137
|
+
};
|
|
138
|
+
</script>
|
|
139
|
+
|
|
140
|
+
<div {...rest} class={['fieldset w-full', className]}>
|
|
141
|
+
<label class={['label', hideLabel && 'sr-only']} for={inputId}>{label}</label>
|
|
142
|
+
|
|
143
|
+
<Combobox.Root
|
|
144
|
+
type="single"
|
|
145
|
+
bind:open
|
|
146
|
+
value={value ?? ''}
|
|
147
|
+
onValueChange={(next) => {
|
|
148
|
+
value = next === '' ? undefined : next;
|
|
149
|
+
if (next === '' || onSelect === undefined) return;
|
|
150
|
+
const chosen = visible.find((entry) => getId(entry) === next);
|
|
151
|
+
if (chosen !== undefined) onSelect(chosen);
|
|
152
|
+
}}
|
|
153
|
+
{disabled}
|
|
154
|
+
{required}
|
|
155
|
+
>
|
|
156
|
+
<Combobox.Input
|
|
157
|
+
id={inputId}
|
|
158
|
+
{...initialText === undefined ? {} : { defaultValue: initialText }}
|
|
159
|
+
{...postsQuery && name !== undefined ? { name } : {}}
|
|
160
|
+
{placeholder}
|
|
161
|
+
autocomplete="off"
|
|
162
|
+
aria-describedby={describedBy === '' ? undefined : describedBy}
|
|
163
|
+
aria-invalid={invalid ? 'true' : undefined}
|
|
164
|
+
oninput={typed}
|
|
165
|
+
onkeydown={keydown}
|
|
166
|
+
class={['input w-full', inputSize[size], invalid && 'input-error', inputClass]}
|
|
167
|
+
/>
|
|
168
|
+
|
|
169
|
+
<Combobox.Portal disabled={!portal}>
|
|
170
|
+
<Combobox.Content
|
|
171
|
+
sideOffset={4}
|
|
172
|
+
class="menu bg-base-100 rounded-box border-base-300 z-50 max-h-72 min-w-64 overflow-auto border p-2 shadow-md"
|
|
173
|
+
>
|
|
174
|
+
<Combobox.Viewport>
|
|
175
|
+
{#each visible as entry (getId(entry))}
|
|
176
|
+
{@const entryId = getId(entry)}
|
|
177
|
+
{@const badge = getBadge?.(entry)}
|
|
178
|
+
<Combobox.Item
|
|
179
|
+
value={entryId}
|
|
180
|
+
label={getLabel(entry)}
|
|
181
|
+
onHighlight={() => (highlighted = entryId)}
|
|
182
|
+
onUnhighlight={() => {
|
|
183
|
+
if (highlighted === entryId) highlighted = undefined;
|
|
184
|
+
}}
|
|
185
|
+
class="rounded-field data-highlighted:bg-base-200 data-disabled:opacity-50 flex cursor-pointer items-center justify-between gap-3 px-3 py-2"
|
|
186
|
+
>
|
|
187
|
+
{#if item}
|
|
188
|
+
{@render item(entry)}
|
|
189
|
+
{:else}
|
|
190
|
+
<span>{getLabel(entry)}</span>
|
|
191
|
+
{#if badge !== undefined}
|
|
192
|
+
<span class="badge badge-ghost badge-sm">{badge}</span>
|
|
193
|
+
{/if}
|
|
194
|
+
{/if}
|
|
195
|
+
</Combobox.Item>
|
|
196
|
+
{/each}
|
|
197
|
+
|
|
198
|
+
{#if visible.length === 0}
|
|
199
|
+
{#if pending}
|
|
200
|
+
<p class="fieldset-label px-3 py-2">{pendingLabel}</p>
|
|
201
|
+
{:else if empty}
|
|
202
|
+
{@render empty({ query })}
|
|
203
|
+
{:else}
|
|
204
|
+
<p class="fieldset-label px-3 py-2">{emptyLabel}</p>
|
|
205
|
+
{/if}
|
|
206
|
+
{/if}
|
|
207
|
+
|
|
208
|
+
{#if footer}
|
|
209
|
+
{@render footer({ query, pending })}
|
|
210
|
+
{/if}
|
|
211
|
+
</Combobox.Viewport>
|
|
212
|
+
</Combobox.Content>
|
|
213
|
+
</Combobox.Portal>
|
|
214
|
+
</Combobox.Root>
|
|
215
|
+
|
|
216
|
+
<!--
|
|
217
|
+
In id mode the posted value is the id, not the typed text: bits-ui's own
|
|
218
|
+
hidden input is not used, because `name` here means "post the selection"
|
|
219
|
+
and nothing else about the widget should depend on it. In query mode the
|
|
220
|
+
visible input above carries `name` instead.
|
|
221
|
+
-->
|
|
222
|
+
{#if name !== undefined && !postsQuery}
|
|
223
|
+
<input type="hidden" {name} value={value ?? ''} />
|
|
224
|
+
{/if}
|
|
225
|
+
|
|
226
|
+
{#if visibleError !== undefined}
|
|
227
|
+
<p class="text-error pt-1 text-sm" role="alert">{visibleError}</p>
|
|
228
|
+
{/if}
|
|
229
|
+
</div>
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { Combobox } from 'bits-ui';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { type FieldSize } from './field-types.ts';
|
|
5
|
+
declare function $$render<T>(): {
|
|
6
|
+
props: Omit<HTMLAttributes<HTMLDivElement>, "class" | "id" | "children"> & {
|
|
7
|
+
/** The selected item's id. */
|
|
8
|
+
value?: string | undefined;
|
|
9
|
+
/** A static list, filtered here by label. Ignored when `onSearch` is set. */
|
|
10
|
+
items?: readonly T[] | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Fetch matches for a query. Debounced by `debounceMs`; `signal` aborts
|
|
13
|
+
* when a newer query supersedes this one, so pass it to `fetch`.
|
|
14
|
+
*/
|
|
15
|
+
onSearch?: ((query: string, signal: AbortSignal) => Promise<readonly T[]>) | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Quiet period before a search starts, in milliseconds.
|
|
18
|
+
* @defaultValue `150`
|
|
19
|
+
*/
|
|
20
|
+
debounceMs?: number | undefined;
|
|
21
|
+
/** The item's stable id — what `value` holds and what the hidden input posts. */
|
|
22
|
+
getId: (item: T) => string;
|
|
23
|
+
/** The item's human-readable text. */
|
|
24
|
+
getLabel: (item: T) => string;
|
|
25
|
+
/** Optional short chip on the right of a row. */
|
|
26
|
+
getBadge?: ((item: T) => string | undefined) | undefined;
|
|
27
|
+
/** Visible label; names the input. */
|
|
28
|
+
label: string;
|
|
29
|
+
/** Placeholder in the input. */
|
|
30
|
+
placeholder?: string | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Posted field name. With `postedValue="id"` it renders a hidden input
|
|
33
|
+
* carrying the selected id; with `postedValue="query"` it goes on the
|
|
34
|
+
* visible input, which posts the typed text.
|
|
35
|
+
*/
|
|
36
|
+
name?: string | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* What the field under `name` posts: the selected item's id, or the typed
|
|
39
|
+
* query text. `'query'` makes the input itself the posted control (so a
|
|
40
|
+
* plain GET search form works with JavaScript off) and makes Enter submit
|
|
41
|
+
* the form unless the reader arrowed to an option.
|
|
42
|
+
* @defaultValue `'id'`
|
|
43
|
+
*/
|
|
44
|
+
postedValue?: "id" | "query" | undefined;
|
|
45
|
+
/** Text in the input at mount, such as the current search. A selected item's label wins. */
|
|
46
|
+
initialQuery?: string | undefined;
|
|
47
|
+
/** Called with the raw input text on every keystroke. */
|
|
48
|
+
onQueryChange?: ((query: string) => void) | undefined;
|
|
49
|
+
/** Called with the item the reader committed (click, or Enter on a highlighted row). */
|
|
50
|
+
onSelect?: ((item: T) => void) | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Shown when a settled search returned nothing.
|
|
53
|
+
* @defaultValue `'No matches'`
|
|
54
|
+
*/
|
|
55
|
+
emptyLabel?: string | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* Shown while the first search for a query is in flight.
|
|
58
|
+
* @defaultValue `'Searching…'`
|
|
59
|
+
*/
|
|
60
|
+
pendingLabel?: string | undefined;
|
|
61
|
+
/** A caller-owned failure, rendered as an alert under the input. */
|
|
62
|
+
errorMessage?: string | undefined;
|
|
63
|
+
/** `FieldControl`: the input's id. */
|
|
64
|
+
id?: string | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* `FieldControl`: ids for `aria-describedby`.
|
|
67
|
+
* @defaultValue `''`
|
|
68
|
+
*/
|
|
69
|
+
describedBy?: string | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* `FieldControl`: the visible label's id. Not used — this control is
|
|
72
|
+
* labelable, so the `FormField`'s `<label for>` already names it; taken
|
|
73
|
+
* here so a spread `FieldControl` does not leak it as an attribute.
|
|
74
|
+
*/
|
|
75
|
+
labelId?: string | undefined;
|
|
76
|
+
/** `FieldControl`: the field is in error. */
|
|
77
|
+
invalid?: boolean | undefined;
|
|
78
|
+
/** `FieldControl`: the field must be filled. */
|
|
79
|
+
required?: boolean | undefined;
|
|
80
|
+
/** Disables the input. */
|
|
81
|
+
disabled?: boolean | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* daisyUI size step.
|
|
84
|
+
* @defaultValue `'md'`
|
|
85
|
+
*/
|
|
86
|
+
size?: FieldSize | undefined;
|
|
87
|
+
/** Extra classes on the root, merged last. */
|
|
88
|
+
class?: string | undefined;
|
|
89
|
+
/** Extra classes on the `<input>`, merged last (e.g. daisyUI `join-item`). */
|
|
90
|
+
inputClass?: string | undefined;
|
|
91
|
+
/** Keep the label as the input's accessible name but hide it visually. */
|
|
92
|
+
hideLabel?: boolean | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Portal the listbox to `<body>`. `false` renders it inside this
|
|
95
|
+
* component's root instead; it still floats over the layout.
|
|
96
|
+
* @defaultValue `true`
|
|
97
|
+
*/
|
|
98
|
+
portal?: boolean | undefined;
|
|
99
|
+
/** Replace a row's contents. */
|
|
100
|
+
item?: Snippet<[T]> | undefined;
|
|
101
|
+
/** Rendered after the rows — a "create this" row, a "see all" link. */
|
|
102
|
+
footer?: Snippet<[{
|
|
103
|
+
query: string;
|
|
104
|
+
pending: boolean;
|
|
105
|
+
}]> | undefined;
|
|
106
|
+
/** Replaces `emptyLabel` when a settled search returned nothing. */
|
|
107
|
+
empty?: Snippet<[{
|
|
108
|
+
query: string;
|
|
109
|
+
}]> | undefined;
|
|
110
|
+
};
|
|
111
|
+
exports: {};
|
|
112
|
+
bindings: "value";
|
|
113
|
+
slots: {};
|
|
114
|
+
events: {};
|
|
115
|
+
};
|
|
116
|
+
declare class __sveltets_Render<T> {
|
|
117
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
118
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
119
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
120
|
+
bindings(): "value";
|
|
121
|
+
exports(): {};
|
|
122
|
+
}
|
|
123
|
+
interface $$IsomorphicComponent {
|
|
124
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
125
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
126
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
127
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
128
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
129
|
+
}
|
|
130
|
+
/** A single-select typeahead over a static list or an asynchronous search, on bits-ui’s `Combobox`. */
|
|
131
|
+
declare const Combobox: $$IsomorphicComponent;
|
|
132
|
+
type Combobox<T> = InstanceType<typeof Combobox<T>>;
|
|
133
|
+
export default Combobox;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
Segmented day / month / year entry on bits-ui `DateField`, in the locale's order.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
DateField — a date typed into segments (day, month, year; optionally hour
|
|
6
|
+
and minute), each a `role="spinbutton"`: digits to type, ↑ / ↓ to step,
|
|
7
|
+
← / → and auto-advance between segments, Backspace to clear. The order
|
|
8
|
+
and separators follow the locale (en-AU day/month/year, en-US
|
|
9
|
+
month/day/year).
|
|
10
|
+
|
|
11
|
+
`DateInput` (the native `<input type="date">`) stays the default for a
|
|
12
|
+
single date on a form. Reach for this when a design needs the same
|
|
13
|
+
control on every browser, or a time as well as a date.
|
|
14
|
+
|
|
15
|
+
ARIA contract: see `SegmentGroup` — a `role="group"` named by the
|
|
16
|
+
`FormField` label through `labelId`, `aria-describedby` its hint and
|
|
17
|
+
errors, `aria-invalid` when in error. With `name`, bits-ui posts the ISO
|
|
18
|
+
value (`2026-10-14`) through a hidden input.
|
|
19
|
+
-->
|
|
20
|
+
<script lang="ts">import { DateField } from "bits-ui";
|
|
21
|
+
import { getComponentsContext } from "../context.svelte.js";
|
|
22
|
+
import { definedProps } from "./calendar-props.js";
|
|
23
|
+
import SegmentGroup from "./SegmentGroup.svelte";
|
|
24
|
+
import { segmentedField } from "./segmented-field.js";
|
|
25
|
+
let { value = $bindable(), minValue, maxValue, granularity = "day", ...shared } = $props();
|
|
26
|
+
const context = getComponentsContext();
|
|
27
|
+
const field = $derived(segmentedField(shared, context.locale()));
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<DateField.Root
|
|
31
|
+
bind:value={() => value as DateValue, (next) => (value = next)}
|
|
32
|
+
{...field.root}
|
|
33
|
+
{...definedProps({ minValue, maxValue })}
|
|
34
|
+
{granularity}
|
|
35
|
+
>
|
|
36
|
+
<SegmentGroup parts={DateField} group={field.group} />
|
|
37
|
+
</DateField.Root>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DateValue } from '@internationalized/date';
|
|
2
|
+
import { DateField } from 'bits-ui';
|
|
3
|
+
import { type SegmentedFieldProps } from './segmented-field.ts';
|
|
4
|
+
interface Props extends SegmentedFieldProps {
|
|
5
|
+
/** The date; `undefined` while empty or incomplete. Bindable. */
|
|
6
|
+
value?: DateValue | undefined;
|
|
7
|
+
/** Earliest valid date. */
|
|
8
|
+
minValue?: DateValue | undefined;
|
|
9
|
+
/** Latest valid date. */
|
|
10
|
+
maxValue?: DateValue | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* The smallest segment shown.
|
|
13
|
+
* @defaultValue `'day'`
|
|
14
|
+
*/
|
|
15
|
+
granularity?: 'day' | 'hour' | 'minute' | 'second' | undefined;
|
|
16
|
+
}
|
|
17
|
+
/** Segmented day / month / year entry on bits-ui `DateField`, in the locale's order. */
|
|
18
|
+
declare const DateField: import("svelte").Component<Props, {}, "value">;
|
|
19
|
+
type DateField = ReturnType<typeof DateField>;
|
|
20
|
+
export default DateField;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A native `<input type="date">` in daisyUI `input` styling, with `FieldControl` wiring.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
DateInput — the native `<input type="date">` in daisyUI `input` styling.
|
|
6
|
+
|
|
7
|
+
`value` holds the ISO calendar date (`YYYY-MM-DD`) the control speaks
|
|
8
|
+
natively, which is also the shape a JSON API's date fields take, so no
|
|
9
|
+
conversion sits between the two.
|
|
10
|
+
|
|
11
|
+
Native on purpose, and the reason is worth stating: bits-ui's `DateField`
|
|
12
|
+
is a segmented control with its own locale handling and its own keyboard
|
|
13
|
+
contract, which is the right answer when a design needs a calendar popover
|
|
14
|
+
and the wrong one for a single date on a form — the platform control is
|
|
15
|
+
keyboard-complete, localises itself, and on a phone opens the system date
|
|
16
|
+
picker that people already know.
|
|
17
|
+
-->
|
|
18
|
+
<script lang="ts">import { inputSize } from "./field-types.js";
|
|
19
|
+
let { value = $bindable(""), min, max, size = "md", invalid = false, describedBy = "", labelId: _labelId, class: className, ...rest } = $props();
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<input
|
|
23
|
+
{...rest}
|
|
24
|
+
type="date"
|
|
25
|
+
bind:value
|
|
26
|
+
{min}
|
|
27
|
+
{max}
|
|
28
|
+
aria-invalid={invalid ? 'true' : undefined}
|
|
29
|
+
aria-describedby={describedBy === '' ? undefined : describedBy}
|
|
30
|
+
class={['input w-full', inputSize[size], invalid && 'input-error', className]}
|
|
31
|
+
/>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
2
|
+
import { type FieldSize } from './field-types.ts';
|
|
3
|
+
interface Props extends Omit<HTMLInputAttributes, 'type' | 'value' | 'size' | 'min' | 'max'> {
|
|
4
|
+
/**
|
|
5
|
+
* ISO calendar date, `YYYY-MM-DD`; empty when unset.
|
|
6
|
+
* @defaultValue `''`
|
|
7
|
+
*/
|
|
8
|
+
value?: string | undefined;
|
|
9
|
+
/** Earliest selectable date, ISO. */
|
|
10
|
+
min?: string | undefined;
|
|
11
|
+
/** Latest selectable date, ISO. */
|
|
12
|
+
max?: string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* daisyUI size step.
|
|
15
|
+
* @defaultValue `'md'`
|
|
16
|
+
*/
|
|
17
|
+
size?: FieldSize | undefined;
|
|
18
|
+
/** `FieldControl`: the field is in error — sets `aria-invalid` and the error style. */
|
|
19
|
+
invalid?: boolean | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* `FieldControl`: space-separated ids for `aria-describedby`.
|
|
22
|
+
* @defaultValue `''`
|
|
23
|
+
*/
|
|
24
|
+
describedBy?: string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* `FieldControl`: the visible label's id. Not used — this control is
|
|
27
|
+
* labelable, so the `FormField`'s `<label for>` already names it; taken
|
|
28
|
+
* here so a spread `FieldControl` does not leak it as an attribute.
|
|
29
|
+
*/
|
|
30
|
+
labelId?: string | undefined;
|
|
31
|
+
}
|
|
32
|
+
/** A native `<input type="date">` in daisyUI `input` styling, with `FieldControl` wiring. */
|
|
33
|
+
declare const DateInput: import("svelte").Component<Props, {}, "value">;
|
|
34
|
+
type DateInput = ReturnType<typeof DateInput>;
|
|
35
|
+
export default DateInput;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A segmented date field with a button that opens a calendar popover, on bits-ui `DatePicker`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
DatePicker — `DateField`'s segments plus a calendar button: type the date,
|
|
6
|
+
or open the month and pick it. Selecting a day closes the popover
|
|
7
|
+
(`closeOnDateSelect`) and returns focus to the button.
|
|
8
|
+
|
|
9
|
+
Reach for it when the reader benefits from seeing the month (which day
|
|
10
|
+
of the week, what is unavailable); for a plain date on a form the
|
|
11
|
+
native `DateInput` remains the default.
|
|
12
|
+
|
|
13
|
+
ARIA contract: the segment group as `DateField` (named by the
|
|
14
|
+
`FormField` label through `labelId`); the trigger and dialog as
|
|
15
|
+
`PickerPopover`; the grid as `Calendar`.
|
|
16
|
+
-->
|
|
17
|
+
<script lang="ts">import { DatePicker } from "bits-ui";
|
|
18
|
+
import { getComponentsContext } from "../context.svelte.js";
|
|
19
|
+
import { definedProps } from "./calendar-props.js";
|
|
20
|
+
import PickerPopover from "./PickerPopover.svelte";
|
|
21
|
+
import SegmentGroup from "./SegmentGroup.svelte";
|
|
22
|
+
import { pickerField } from "./segmented-field.js";
|
|
23
|
+
let { value = $bindable(), open = $bindable(false), minValue, maxValue, granularity = "day", closeOnDateSelect = true, ...shared } = $props();
|
|
24
|
+
const context = getComponentsContext();
|
|
25
|
+
const picker = $derived(pickerField(shared, context.locale()));
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<DatePicker.Root
|
|
29
|
+
bind:value={() => value as DateValue, (next) => (value = next)}
|
|
30
|
+
bind:open
|
|
31
|
+
{...picker.root}
|
|
32
|
+
{...definedProps({ minValue, maxValue })}
|
|
33
|
+
{granularity}
|
|
34
|
+
{closeOnDateSelect}
|
|
35
|
+
>
|
|
36
|
+
<SegmentGroup parts={DatePicker} group={picker.group}>
|
|
37
|
+
{#snippet trailing()}
|
|
38
|
+
<PickerPopover
|
|
39
|
+
parts={DatePicker}
|
|
40
|
+
triggerLabel={picker.triggerLabel}
|
|
41
|
+
calendarLabel={picker.calendarLabel}
|
|
42
|
+
months={picker.months}
|
|
43
|
+
disabled={picker.group.disabled}
|
|
44
|
+
/>
|
|
45
|
+
{/snippet}
|
|
46
|
+
</SegmentGroup>
|
|
47
|
+
</DatePicker.Root>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DateValue } from '@internationalized/date';
|
|
2
|
+
import { DatePicker } from 'bits-ui';
|
|
3
|
+
import { type PickerProps, type SegmentedFieldProps } from './segmented-field.ts';
|
|
4
|
+
interface Props extends SegmentedFieldProps, PickerProps {
|
|
5
|
+
/** The date; `undefined` while empty or incomplete. Bindable. */
|
|
6
|
+
value?: DateValue | undefined;
|
|
7
|
+
/** Earliest valid date. */
|
|
8
|
+
minValue?: DateValue | undefined;
|
|
9
|
+
/** Latest valid date. */
|
|
10
|
+
maxValue?: DateValue | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* The smallest segment shown.
|
|
13
|
+
* @defaultValue `'day'`
|
|
14
|
+
*/
|
|
15
|
+
granularity?: 'day' | 'hour' | 'minute' | 'second' | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Close the popover when a day is picked.
|
|
18
|
+
* @defaultValue `true`
|
|
19
|
+
*/
|
|
20
|
+
closeOnDateSelect?: boolean | undefined;
|
|
21
|
+
}
|
|
22
|
+
/** A segmented date field with a button that opens a calendar popover, on bits-ui `DatePicker`. */
|
|
23
|
+
declare const DatePicker: import("svelte").Component<Props, {}, "value" | "open">;
|
|
24
|
+
type DatePicker = ReturnType<typeof DatePicker>;
|
|
25
|
+
export default DatePicker;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
Two segmented date fields, a start and an end, with a range-calendar popover, on bits-ui `DateRangePicker`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
DateRangePicker — a start and an end date typed into segments, or picked
|
|
6
|
+
as a span on a `RangeCalendar` in a popover. `minDays` / `maxDays`
|
|
7
|
+
constrain the span while it is chosen.
|
|
8
|
+
|
|
9
|
+
ARIA contract: the whole control is one `role="group"` named by the
|
|
10
|
+
`FormField` label (`labelId`) and described by its hint and errors, so
|
|
11
|
+
the error text reaches it (a written-out `group` does not take
|
|
12
|
+
`aria-invalid`; `invalid` draws the error border). Inside it, the two halves are groups named
|
|
13
|
+
`startLabel` / `endLabel`, so a segment reads "day, <label> Start date".
|
|
14
|
+
The dash between them is `aria-hidden`. The trigger and dialog are
|
|
15
|
+
`PickerPopover`'s.
|
|
16
|
+
-->
|
|
17
|
+
<script lang="ts">import { DateRangePicker } from "bits-ui";
|
|
18
|
+
import { getComponentsContext } from "../context.svelte.js";
|
|
19
|
+
import { definedProps } from "./calendar-props.js";
|
|
20
|
+
import { inputSize } from "./field-types.js";
|
|
21
|
+
import PickerPopover from "./PickerPopover.svelte";
|
|
22
|
+
import SegmentGroup from "./SegmentGroup.svelte";
|
|
23
|
+
import { pickerField } from "./segmented-field.js";
|
|
24
|
+
let { value = $bindable(), open = $bindable(false), minValue, maxValue, minDays, maxDays, closeOnRangeSelect = true, startName, endName, startLabel = "Start date", endLabel = "End date", ...shared } = $props();
|
|
25
|
+
const context = getComponentsContext();
|
|
26
|
+
const picker = $derived(pickerField(shared, context.locale()));
|
|
27
|
+
const group = $derived(picker.group);
|
|
28
|
+
const { class: className, ...attributes } = $derived(group.attributes);
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<DateRangePicker.Root
|
|
32
|
+
bind:value={
|
|
33
|
+
() => value ?? { start: undefined, end: undefined },
|
|
34
|
+
(next) => (value = { start: next.start, end: next.end })
|
|
35
|
+
}
|
|
36
|
+
bind:open
|
|
37
|
+
{...picker.root}
|
|
38
|
+
{...definedProps({ minValue, maxValue, minDays, maxDays })}
|
|
39
|
+
{closeOnRangeSelect}
|
|
40
|
+
>
|
|
41
|
+
{#snippet child({ props })}
|
|
42
|
+
<div
|
|
43
|
+
{...attributes}
|
|
44
|
+
{...props}
|
|
45
|
+
{...group.id === undefined ? {} : { id: group.id }}
|
|
46
|
+
role="group"
|
|
47
|
+
aria-labelledby={group.labelId}
|
|
48
|
+
aria-describedby={group.describedBy === '' ? undefined : group.describedBy}
|
|
49
|
+
class={[
|
|
50
|
+
'input inline-flex w-auto items-center gap-0 tabular-nums',
|
|
51
|
+
inputSize[group.size],
|
|
52
|
+
group.invalid && 'input-error',
|
|
53
|
+
'data-invalid:input-error',
|
|
54
|
+
group.disabled && 'opacity-50',
|
|
55
|
+
className,
|
|
56
|
+
]}
|
|
57
|
+
>
|
|
58
|
+
<SegmentGroup parts={DateRangePicker} {group} range={{ type: 'start', label: startLabel, name: startName }} />
|
|
59
|
+
<span aria-hidden="true" class="text-base-content/60 px-1.5">–</span>
|
|
60
|
+
<SegmentGroup parts={DateRangePicker} {group} range={{ type: 'end', label: endLabel, name: endName }} />
|
|
61
|
+
<PickerPopover
|
|
62
|
+
parts={DateRangePicker}
|
|
63
|
+
triggerLabel={picker.triggerLabel}
|
|
64
|
+
calendarLabel={picker.calendarLabel}
|
|
65
|
+
months={picker.months}
|
|
66
|
+
disabled={group.disabled}
|
|
67
|
+
/>
|
|
68
|
+
</div>
|
|
69
|
+
{/snippet}
|
|
70
|
+
</DateRangePicker.Root>
|