@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,88 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
One choice from a short, known list, on bits-ui’s `RadioGroup`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
RadioGroup — one choice from a short, known list, on bits-ui's `RadioGroup`.
|
|
6
|
+
|
|
7
|
+
bits-ui owns what is genuinely hard here: the roving tabindex (the group is
|
|
8
|
+
ONE tab stop, and the arrow keys move within it), wrap-around, and the
|
|
9
|
+
`aria-checked` bookkeeping. Hand-rolled radio groups get the tab stop wrong
|
|
10
|
+
almost every time.
|
|
11
|
+
|
|
12
|
+
ARIA contract: bits-ui renders `role="radiogroup"` around `role="radio"`
|
|
13
|
+
buttons, and this adds `aria-orientation` beside the `data-orientation`
|
|
14
|
+
bits-ui sets, so the arrow keys a reader is told to use match the ones that
|
|
15
|
+
work. A `role` element cannot be named by a `<legend>` — the legend names
|
|
16
|
+
the `<fieldset>`, which is a different node — so the group renders its
|
|
17
|
+
question as a heading-ish `<span>` and points `aria-labelledby` at it. That
|
|
18
|
+
is why this is the one field group NOT built on `Fieldset`, and the hint and
|
|
19
|
+
errors hang off the radiogroup element itself through `aria-describedby`.
|
|
20
|
+
It is a whole frame (question, hint, errors), not a control a `FormField`
|
|
21
|
+
wraps, so it keeps its own `legend` rather than taking a `FieldControl`'s
|
|
22
|
+
`labelId`: inside a `FormField` it would render two labels.
|
|
23
|
+
|
|
24
|
+
The marker is drawn rather than delegated to daisyUI's `.radio`, because
|
|
25
|
+
that class styles an `<input type="radio">` through `:checked` and bits-ui's
|
|
26
|
+
radio is a `<button>`. It is two spans of semantic tokens; `checked` comes
|
|
27
|
+
from bits-ui's own snippet prop, so the visual and the accessibility tree
|
|
28
|
+
cannot disagree.
|
|
29
|
+
-->
|
|
30
|
+
<script lang="ts">import { RadioGroup } from "bits-ui";
|
|
31
|
+
import FieldErrors from "./FieldErrors.svelte";
|
|
32
|
+
import { toFieldOptions } from "./field-types.js";
|
|
33
|
+
let { legend, options, value = $bindable(""), orientation = "vertical", name, hint, errors = [], required = false, requiredLabel = "(required)", disabled = false, class: className, ...rest } = $props();
|
|
34
|
+
const uid = $props.id();
|
|
35
|
+
const legendId = `${uid}-legend`;
|
|
36
|
+
const hintId = `${uid}-hint`;
|
|
37
|
+
const errorId = `${uid}-error`;
|
|
38
|
+
const entries = $derived(toFieldOptions(options));
|
|
39
|
+
const invalid = $derived(errors.length > 0);
|
|
40
|
+
const describedBy = $derived([hint === undefined ? "" : hintId, invalid ? errorId : ""].filter((part) => part !== "").join(" "));
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<div {...rest} class={['fieldset', className]}>
|
|
44
|
+
<span id={legendId} class="fieldset-legend">
|
|
45
|
+
{legend}
|
|
46
|
+
{#if required}
|
|
47
|
+
<span class="text-error" aria-hidden="true">*</span>
|
|
48
|
+
<span class="sr-only">{requiredLabel}</span>
|
|
49
|
+
{/if}
|
|
50
|
+
</span>
|
|
51
|
+
<RadioGroup.Root
|
|
52
|
+
bind:value
|
|
53
|
+
{orientation}
|
|
54
|
+
{...name === undefined ? {} : { name }}
|
|
55
|
+
{required}
|
|
56
|
+
{disabled}
|
|
57
|
+
aria-labelledby={legendId}
|
|
58
|
+
aria-orientation={orientation}
|
|
59
|
+
aria-describedby={describedBy === '' ? undefined : describedBy}
|
|
60
|
+
aria-invalid={invalid ? 'true' : undefined}
|
|
61
|
+
class={['flex gap-3', orientation === 'horizontal' ? 'flex-row flex-wrap' : 'flex-col']}
|
|
62
|
+
>
|
|
63
|
+
{#each entries as option (option.value)}
|
|
64
|
+
<RadioGroup.Item
|
|
65
|
+
value={option.value}
|
|
66
|
+
disabled={option.disabled === true}
|
|
67
|
+
class="rounded-field focus-visible:outline-primary flex cursor-pointer items-center gap-3 text-left focus-visible:outline-2 focus-visible:outline-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
|
68
|
+
>
|
|
69
|
+
{#snippet children({ checked })}
|
|
70
|
+
<span
|
|
71
|
+
aria-hidden="true"
|
|
72
|
+
class={[
|
|
73
|
+
'grid size-4 shrink-0 place-items-center rounded-full border-2',
|
|
74
|
+
checked ? 'border-primary' : 'border-base-content/40',
|
|
75
|
+
]}
|
|
76
|
+
>
|
|
77
|
+
{#if checked}<span class="bg-primary size-2 rounded-full"></span>{/if}
|
|
78
|
+
</span>
|
|
79
|
+
<span>{option.label}</span>
|
|
80
|
+
{/snippet}
|
|
81
|
+
</RadioGroup.Item>
|
|
82
|
+
{/each}
|
|
83
|
+
</RadioGroup.Root>
|
|
84
|
+
{#if hint !== undefined}
|
|
85
|
+
<p class="fieldset-label" id={hintId}>{hint}</p>
|
|
86
|
+
{/if}
|
|
87
|
+
<FieldErrors {errors} id={errorId} />
|
|
88
|
+
</div>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { RadioGroup } from 'bits-ui';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { type FieldOptionInput } from './field-types.ts';
|
|
4
|
+
interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
5
|
+
/** The question the options answer; names the group. */
|
|
6
|
+
legend: string;
|
|
7
|
+
/** Full options, or bare strings when value and label are the same. */
|
|
8
|
+
options: readonly FieldOptionInput[];
|
|
9
|
+
/**
|
|
10
|
+
* The chosen value; empty string when nothing is chosen.
|
|
11
|
+
* @defaultValue `''`
|
|
12
|
+
*/
|
|
13
|
+
value?: string | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Lay the options out in a column or a row.
|
|
16
|
+
* @defaultValue `'vertical'`
|
|
17
|
+
*/
|
|
18
|
+
orientation?: 'vertical' | 'horizontal' | undefined;
|
|
19
|
+
/** Posted field name — bits-ui renders the hidden input when it is set. */
|
|
20
|
+
name?: string | undefined;
|
|
21
|
+
/** Guidance rendered under the legend. */
|
|
22
|
+
hint?: string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Validation messages; any at all marks the group invalid.
|
|
25
|
+
* @defaultValue `[]`
|
|
26
|
+
*/
|
|
27
|
+
errors?: readonly string[] | undefined;
|
|
28
|
+
/** Marks the group required and reads `requiredLabel` after the legend. */
|
|
29
|
+
required?: boolean | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Read out after the legend when `required`.
|
|
32
|
+
* @defaultValue `'(required)'`
|
|
33
|
+
*/
|
|
34
|
+
requiredLabel?: string | undefined;
|
|
35
|
+
/** Disables every option. */
|
|
36
|
+
disabled?: boolean | undefined;
|
|
37
|
+
}
|
|
38
|
+
/** One choice from a short, known list, on bits-ui’s `RadioGroup`. */
|
|
39
|
+
declare const RadioGroup: import("svelte").Component<Props, {}, "value">;
|
|
40
|
+
type RadioGroup = ReturnType<typeof RadioGroup>;
|
|
41
|
+
export default RadioGroup;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
An inline, always-visible month grid for picking a start–end date range, on bits-ui's `RangeCalendar`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
RangeCalendar — `Calendar`'s range sibling: the first chosen day starts
|
|
6
|
+
the range, the second ends it, and the days between are drawn as one band.
|
|
7
|
+
`minDays` / `maxDays` bound the length; `excludeDisabled` decides whether a
|
|
8
|
+
range may run across disabled days. It shares everything else — props,
|
|
9
|
+
header, grids, day styling — with `Calendar` (`calendar-props.ts`,
|
|
10
|
+
`CalendarMonths.svelte`), so the ARIA contract is the same: see
|
|
11
|
+
`Calendar`'s header. bits-ui adds `data-range-start` / `-middle` / `-end`
|
|
12
|
+
to the days, which is all the band styling reads.
|
|
13
|
+
|
|
14
|
+
The value is `{ start, end }` of `DateValue`s, either side `undefined`
|
|
15
|
+
while the reader is still choosing.
|
|
16
|
+
-->
|
|
17
|
+
<script lang="ts">import { RangeCalendar } from "bits-ui";
|
|
18
|
+
import { getComponentsContext } from "../context.svelte.js";
|
|
19
|
+
import CalendarMonths from "./CalendarMonths.svelte";
|
|
20
|
+
import { calendarRoot, definedProps } from "./calendar-props.js";
|
|
21
|
+
let { value = $bindable(), month = $bindable(), minDays, maxDays, excludeDisabled = false, ...props } = $props();
|
|
22
|
+
const context = getComponentsContext();
|
|
23
|
+
const shared = $derived(calendarRoot(props, context.locale()));
|
|
24
|
+
const lengths = $derived(definedProps({
|
|
25
|
+
minDays,
|
|
26
|
+
maxDays
|
|
27
|
+
}));
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<RangeCalendar.Root
|
|
31
|
+
{...shared.root}
|
|
32
|
+
{...lengths}
|
|
33
|
+
{excludeDisabled}
|
|
34
|
+
bind:placeholder={
|
|
35
|
+
// Unset, bits-ui picks the value's month or today's.
|
|
36
|
+
() => month as DateValue,
|
|
37
|
+
(next: DateValue) => {
|
|
38
|
+
month = next;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
bind:value={
|
|
42
|
+
() => value ?? { start: undefined, end: undefined },
|
|
43
|
+
(next) => {
|
|
44
|
+
value = next;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
>
|
|
48
|
+
{#snippet children({ months, weekdays })}
|
|
49
|
+
<CalendarMonths parts={RangeCalendar} {...shared.months} {months} {weekdays} />
|
|
50
|
+
{/snippet}
|
|
51
|
+
</RangeCalendar.Root>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DateValue } from '@internationalized/date';
|
|
2
|
+
import { RangeCalendar } from 'bits-ui';
|
|
3
|
+
import { type CalendarBaseProps } from './calendar-props.ts';
|
|
4
|
+
interface Props extends CalendarBaseProps {
|
|
5
|
+
/** `{ start, end }`; either side `undefined` while choosing. Bindable. */
|
|
6
|
+
value?: {
|
|
7
|
+
start: DateValue | undefined;
|
|
8
|
+
end: DateValue | undefined;
|
|
9
|
+
} | undefined;
|
|
10
|
+
/** Shortest allowed range, in days. */
|
|
11
|
+
minDays?: number | undefined;
|
|
12
|
+
/** Longest allowed range, in days. */
|
|
13
|
+
maxDays?: number | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* Refuse a range that would span a disabled day.
|
|
16
|
+
* @defaultValue `false`
|
|
17
|
+
*/
|
|
18
|
+
excludeDisabled?: boolean | undefined;
|
|
19
|
+
}
|
|
20
|
+
/** An inline, always-visible month grid for picking a start–end date range, on bits-ui's `RangeCalendar`. */
|
|
21
|
+
declare const RangeCalendar: import("svelte").Component<Props, {}, "value" | "month">;
|
|
22
|
+
type RangeCalendar = ReturnType<typeof RangeCalendar>;
|
|
23
|
+
export default RangeCalendar;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A score out of N as stars: an input on bits-ui's `RatingGroup` that binds a number (optionally in half steps) and posts under `name`, or, with `readonly`, a static display named "4.5 out of 5".
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
Rating — one component, two branches.
|
|
6
|
+
|
|
7
|
+
Input (the default): bits-ui's `RatingGroup`. Its root is `role="slider"`
|
|
8
|
+
(bits-ui 2.20, `rating-group.svelte.js`) — one Tab stop, with the stars
|
|
9
|
+
`role="presentation"` — so there is no "radio button 4 of 5" with no
|
|
10
|
+
context. There is no APG rating pattern; bits-ui follows the slider one.
|
|
11
|
+
bits-ui supplies the role, `aria-valuenow` / `min` / `max`,
|
|
12
|
+
`aria-valuetext` (from `formatValue` here), `aria-readonly`,
|
|
13
|
+
`aria-disabled`, `aria-required`, the hidden input under `name`, the
|
|
14
|
+
arrow / Home / End / Page keys, digit keys (with `allowHalf`, "3" then
|
|
15
|
+
".5" gives 3.5), and half-step pointer handling. This file adds the
|
|
16
|
+
accessible name, `aria-describedby` and `aria-invalid`.
|
|
17
|
+
|
|
18
|
+
Naming: a `<label for>` cannot name a `div`, so inside a `FormField` the
|
|
19
|
+
root takes `aria-labelledby={labelId}` (`FieldControl.labelId`, #179) and
|
|
20
|
+
`FormField` forwards a label click to it. Outside one, `label` becomes the
|
|
21
|
+
root's `aria-label`.
|
|
22
|
+
|
|
23
|
+
Clearing: bits-ui clears the value to 0 when the first star is clicked
|
|
24
|
+
while the value already equals it (pointer only; no key clears below
|
|
25
|
+
`min`, which is 0). That is left as bits-ui ships it, not hand-patched.
|
|
26
|
+
|
|
27
|
+
Read-only display (`readonly`): plain markup with no bits-ui root mounted —
|
|
28
|
+
`role="img"` with `aria-label={formatValue(value, max)}`, every star
|
|
29
|
+
`aria-hidden`, nothing focusable, nothing posted. It rounds to the nearest
|
|
30
|
+
half star whatever `allowHalf` says, because a display usually shows an
|
|
31
|
+
average ("4.5 out of 5"). The label still says the exact value.
|
|
32
|
+
|
|
33
|
+
Styling: daisyUI's `rating-*` size classes set `--size`; each star is two
|
|
34
|
+
`mask mask-star-2` halves (`mask-half-1` / `mask-half-2`, which flip in
|
|
35
|
+
RTL), filled in the tone's background or left at `bg-base-content/20`.
|
|
36
|
+
daisyUI's `rating` class itself is not used: its `.rating *` rules style
|
|
37
|
+
every descendant, which fights bits-ui's item wrappers.
|
|
38
|
+
-->
|
|
39
|
+
<script lang="ts">import { RatingGroup } from "bits-ui";
|
|
40
|
+
import { backgroundTone } from "../ui/tones.js";
|
|
41
|
+
import { ratingSize } from "./field-types.js";
|
|
42
|
+
let { value = $bindable(0), max = 5, allowHalf = false, readonly = false, hoverPreview = true, formatValue = (score, outOf) => `${score} out of ${outOf}`, name, disabled = false, tone = "warning", size = "md", item, label = "Rating", id: idProp, labelId, describedBy = "", invalid = false, required = false, class: className, ...rest } = $props();
|
|
43
|
+
const uid = $props.id();
|
|
44
|
+
const id = $derived(idProp ?? uid);
|
|
45
|
+
const fill = $derived(backgroundTone[tone]);
|
|
46
|
+
// bits-ui types `name` as a bare optional, so it is omitted rather than passed as `undefined`.
|
|
47
|
+
const nameProp = $derived(name === undefined ? {} : { name });
|
|
48
|
+
/** The display's stars: the value rounded to the nearest half. */
|
|
49
|
+
const displayStates = $derived.by(() => {
|
|
50
|
+
const shown = Math.round(value * 2) / 2;
|
|
51
|
+
return Array.from({ length: max }, (_, index) => {
|
|
52
|
+
if (shown >= index + 1) return "active";
|
|
53
|
+
return shown >= index + .5 ? "partial" : "inactive";
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
{#snippet star(state: StarState)}
|
|
59
|
+
<span aria-hidden="true" class="flex">
|
|
60
|
+
{#if item}
|
|
61
|
+
{@render item({ state })}
|
|
62
|
+
{:else}
|
|
63
|
+
<span
|
|
64
|
+
class={[
|
|
65
|
+
'mask mask-star-2 mask-half-1 h-[calc(var(--size))] w-[calc(var(--size)*0.5)]',
|
|
66
|
+
state === 'inactive' ? 'bg-base-content/20' : fill,
|
|
67
|
+
]}
|
|
68
|
+
></span>
|
|
69
|
+
<span
|
|
70
|
+
class={[
|
|
71
|
+
'mask mask-star-2 mask-half-2 h-[calc(var(--size))] w-[calc(var(--size)*0.5)]',
|
|
72
|
+
state === 'active' ? fill : 'bg-base-content/20',
|
|
73
|
+
]}
|
|
74
|
+
></span>
|
|
75
|
+
{/if}
|
|
76
|
+
</span>
|
|
77
|
+
{/snippet}
|
|
78
|
+
|
|
79
|
+
{#if readonly}
|
|
80
|
+
<div
|
|
81
|
+
{...rest}
|
|
82
|
+
{id}
|
|
83
|
+
role="img"
|
|
84
|
+
aria-label={formatValue(value, max)}
|
|
85
|
+
class={['inline-flex align-middle', ratingSize[size], className]}
|
|
86
|
+
>
|
|
87
|
+
{#each displayStates as state, index (index)}
|
|
88
|
+
{@render star(state)}
|
|
89
|
+
{/each}
|
|
90
|
+
</div>
|
|
91
|
+
{:else}
|
|
92
|
+
<RatingGroup.Root
|
|
93
|
+
{...rest}
|
|
94
|
+
bind:value
|
|
95
|
+
{id}
|
|
96
|
+
{max}
|
|
97
|
+
{allowHalf}
|
|
98
|
+
{hoverPreview}
|
|
99
|
+
{...nameProp}
|
|
100
|
+
{disabled}
|
|
101
|
+
{required}
|
|
102
|
+
aria-valuetext={formatValue}
|
|
103
|
+
aria-label={labelId === undefined ? label : undefined}
|
|
104
|
+
aria-labelledby={labelId}
|
|
105
|
+
aria-describedby={describedBy === '' ? undefined : describedBy}
|
|
106
|
+
aria-invalid={invalid ? 'true' : undefined}
|
|
107
|
+
class={[
|
|
108
|
+
'inline-flex rounded-field align-middle focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary data-[disabled]:opacity-50',
|
|
109
|
+
invalid && 'outline-2 outline-offset-2 outline-error',
|
|
110
|
+
ratingSize[size],
|
|
111
|
+
className,
|
|
112
|
+
]}
|
|
113
|
+
>
|
|
114
|
+
{#snippet children({ items })}
|
|
115
|
+
{#each items as entry (entry.index)}
|
|
116
|
+
<RatingGroup.Item
|
|
117
|
+
index={entry.index}
|
|
118
|
+
class="cursor-pointer data-[disabled]:cursor-not-allowed"
|
|
119
|
+
>
|
|
120
|
+
{#snippet children({ state })}
|
|
121
|
+
{@render star(state)}
|
|
122
|
+
{/snippet}
|
|
123
|
+
</RatingGroup.Item>
|
|
124
|
+
{/each}
|
|
125
|
+
{/snippet}
|
|
126
|
+
</RatingGroup.Root>
|
|
127
|
+
{/if}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Size, type Tone } from '../ui/tones.ts';
|
|
4
|
+
/** How much of one star is filled. */
|
|
5
|
+
type StarState = 'active' | 'partial' | 'inactive';
|
|
6
|
+
interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'dir'> {
|
|
7
|
+
/**
|
|
8
|
+
* The score. Bindable.
|
|
9
|
+
* @defaultValue `0`
|
|
10
|
+
*/
|
|
11
|
+
value?: number | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Number of stars.
|
|
14
|
+
* @defaultValue `5`
|
|
15
|
+
*/
|
|
16
|
+
max?: number | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Allow half-star values (bits-ui `allowHalf`).
|
|
19
|
+
* @defaultValue `false`
|
|
20
|
+
*/
|
|
21
|
+
allowHalf?: boolean | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Render a static, unfocusable display instead of an input.
|
|
24
|
+
* @defaultValue `false`
|
|
25
|
+
*/
|
|
26
|
+
readonly?: boolean | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Preview the hovered value before it is chosen (bits-ui `hoverPreview`).
|
|
29
|
+
* @defaultValue `true`
|
|
30
|
+
*/
|
|
31
|
+
hoverPreview?: boolean | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* The spoken value (the input's `aria-valuetext`); also the display's accessible name.
|
|
34
|
+
* @defaultValue `(value, max) => \`${value} out of ${max}\``
|
|
35
|
+
*/
|
|
36
|
+
formatValue?: ((value: number, max: number) => string) | undefined;
|
|
37
|
+
/** Posts the value under this name (input only). */
|
|
38
|
+
name?: string | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* Blocks keys and clicks, and posts nothing.
|
|
41
|
+
* @defaultValue `false`
|
|
42
|
+
*/
|
|
43
|
+
disabled?: boolean | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Colour of the filled stars.
|
|
46
|
+
* @defaultValue `'warning'`
|
|
47
|
+
*/
|
|
48
|
+
tone?: Tone | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* daisyUI `rating` size step.
|
|
51
|
+
* @defaultValue `'md'`
|
|
52
|
+
*/
|
|
53
|
+
size?: Size | undefined;
|
|
54
|
+
/** Replace the star glyph (a heart, a leaf); receives how much of it is filled. It is rendered inside an `aria-hidden` wrapper. */
|
|
55
|
+
item?: Snippet<[{
|
|
56
|
+
state: StarState;
|
|
57
|
+
}]> | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* Accessible name, for a rating outside a `FormField`; ignored when `labelId` is set.
|
|
60
|
+
* @defaultValue `'Rating'`
|
|
61
|
+
*/
|
|
62
|
+
label?: string | undefined;
|
|
63
|
+
/** `FieldControl`: the root's `id`. Minted when omitted. */
|
|
64
|
+
id?: string | undefined;
|
|
65
|
+
/** `FieldControl`: the visible label's id; the root is `aria-labelledby` it. */
|
|
66
|
+
labelId?: string | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* `FieldControl`: space-separated ids for `aria-describedby`.
|
|
69
|
+
* @defaultValue `''`
|
|
70
|
+
*/
|
|
71
|
+
describedBy?: string | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* `FieldControl`: the field is in error — sets `aria-invalid` and an error outline.
|
|
74
|
+
* @defaultValue `false`
|
|
75
|
+
*/
|
|
76
|
+
invalid?: boolean | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* `FieldControl`: sets `aria-required` and the hidden input's `required`.
|
|
79
|
+
* @defaultValue `false`
|
|
80
|
+
*/
|
|
81
|
+
required?: boolean | undefined;
|
|
82
|
+
}
|
|
83
|
+
/** A score out of N as stars: an input on bits-ui's `RatingGroup` that binds a number (optionally in half steps) and posts under `name`, or, with `readonly`, a static display named "4.5 out of 5". */
|
|
84
|
+
declare const Rating: import("svelte").Component<Props, {}, "value">;
|
|
85
|
+
type Rating = ReturnType<typeof Rating>;
|
|
86
|
+
export default Rating;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A `type="search"` field with a leading icon, a clear button while there is text, and a spinner while `pending`. `name` defaults to `'q'` and `placeholder` to `'Search'`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
SearchInput — a `type="search"` field in daisyUI's composite `input`
|
|
6
|
+
wrapper, with a leading icon, a clear button while there is text, and a
|
|
7
|
+
spinner while `pending`.
|
|
8
|
+
|
|
9
|
+
The wrapper is a `<div>`, not a `<label>`: the clear button lives inside it,
|
|
10
|
+
and a button inside a label is both mis-named (the label's text becomes part
|
|
11
|
+
of ITS name) and label-activated (clicking it also focuses the field). The
|
|
12
|
+
visible label is optional — `label` always supplies the accessible name.
|
|
13
|
+
|
|
14
|
+
ARIA contract: the leading magnifier is `aria-hidden`, because the field's
|
|
15
|
+
own name already says what it is; the clear button is a real button with a
|
|
16
|
+
visually-hidden name rather than a bare glyph; the spinner is `aria-hidden`,
|
|
17
|
+
because a busy state must not change the field's accessible name.
|
|
18
|
+
|
|
19
|
+
`onInput` fires on every keystroke (feed it to whatever debounce the app
|
|
20
|
+
uses) and `onSubmit` on Enter.
|
|
21
|
+
-->
|
|
22
|
+
<script lang="ts">import { Search, X } from "@lucide/svelte";
|
|
23
|
+
import Spinner from "../ui/Spinner.svelte";
|
|
24
|
+
import { inputSize } from "./field-types.js";
|
|
25
|
+
let { label, value = $bindable(""), onInput, onSubmit, onClear, pending = false, clearLabel = "Clear search", size = "md", name = "q", placeholder = "Search", class: className, ...rest } = $props();
|
|
26
|
+
const clear = () => {
|
|
27
|
+
value = "";
|
|
28
|
+
onInput?.("");
|
|
29
|
+
onClear?.();
|
|
30
|
+
};
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<div class={['input w-full', inputSize[size], className]}>
|
|
34
|
+
<Search class="size-4 opacity-60" aria-hidden="true" />
|
|
35
|
+
<input
|
|
36
|
+
{...rest}
|
|
37
|
+
type="search"
|
|
38
|
+
{name}
|
|
39
|
+
{placeholder}
|
|
40
|
+
aria-label={label}
|
|
41
|
+
bind:value
|
|
42
|
+
oninput={() => onInput?.(value)}
|
|
43
|
+
onkeydown={(event) => {
|
|
44
|
+
if (event.key === 'Enter') {
|
|
45
|
+
event.preventDefault();
|
|
46
|
+
onSubmit?.(value);
|
|
47
|
+
}
|
|
48
|
+
}}
|
|
49
|
+
/>
|
|
50
|
+
{#if pending}
|
|
51
|
+
<Spinner decorative size="xs" />
|
|
52
|
+
{:else if value !== ''}
|
|
53
|
+
<button type="button" class="btn btn-ghost btn-xs btn-circle" onclick={clear}>
|
|
54
|
+
<X class="size-3.5" aria-hidden="true" />
|
|
55
|
+
<span class="sr-only">{clearLabel}</span>
|
|
56
|
+
</button>
|
|
57
|
+
{/if}
|
|
58
|
+
</div>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
2
|
+
import { type FieldSize } from './field-types.ts';
|
|
3
|
+
interface Props extends Omit<HTMLInputAttributes, 'type' | 'value' | 'size'> {
|
|
4
|
+
/** Accessible name of the field. */
|
|
5
|
+
label: string;
|
|
6
|
+
/**
|
|
7
|
+
* The query. Bindable.
|
|
8
|
+
* @defaultValue `''`
|
|
9
|
+
*/
|
|
10
|
+
value?: string | undefined;
|
|
11
|
+
/** Fires on every change with the current text. */
|
|
12
|
+
onInput?: ((query: string) => void) | undefined;
|
|
13
|
+
/** Fires on Enter with the current text. */
|
|
14
|
+
onSubmit?: ((query: string) => void) | undefined;
|
|
15
|
+
/** Fires after the clear button empties the field. */
|
|
16
|
+
onClear?: (() => void) | undefined;
|
|
17
|
+
/** A search is in flight. */
|
|
18
|
+
pending?: boolean | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Accessible name of the clear button.
|
|
21
|
+
* @defaultValue `'Clear search'`
|
|
22
|
+
*/
|
|
23
|
+
clearLabel?: string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* daisyUI size step.
|
|
26
|
+
* @defaultValue `'md'`
|
|
27
|
+
*/
|
|
28
|
+
size?: FieldSize | undefined;
|
|
29
|
+
}
|
|
30
|
+
/** A `type="search"` field with a leading icon, a clear button while there is text, and a spinner while `pending`. `name` defaults to `'q'` and `placeholder` to `'Search'`. */
|
|
31
|
+
declare const SearchInput: import("svelte").Component<Props, {}, "value">;
|
|
32
|
+
type SearchInput = ReturnType<typeof SearchInput>;
|
|
33
|
+
export default SearchInput;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
The segment group the bits-ui date and time controls share; internal, not exported.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
SegmentGroup — the `role="group"` of spinbutton segments inside a bits-ui
|
|
6
|
+
`DateField`, `TimeField`, `DatePicker` or `DateRangePicker` root, written
|
|
7
|
+
once for all four. `parts` is the bits-ui namespace in use; each exposes
|
|
8
|
+
`Input` and `Segment` (a range's `Input` also takes `type`).
|
|
9
|
+
|
|
10
|
+
`<label for>` cannot name a `role="group"`, so the group is
|
|
11
|
+
`aria-labelledby` the `FormField`'s label (`labelId`), and each segment is
|
|
12
|
+
labelled by its own part name ("day, ") followed by that label, so a
|
|
13
|
+
reader landing on one hears "day, Sown on". bits-ui would name them from
|
|
14
|
+
its own `Label`, which a `FormField` has no use for, so the segments are
|
|
15
|
+
rendered through their `child` snippet with our `aria-labelledby` last.
|
|
16
|
+
The literal separators ("/", ":") are `aria-hidden`: the spinbutton names
|
|
17
|
+
already say which part is which.
|
|
18
|
+
|
|
19
|
+
Two shapes. By default the group IS the field: the `input` shell, named
|
|
20
|
+
by the label, carrying `describedBy` / `invalid`, with an optional
|
|
21
|
+
`trailing` snippet (the picker's calendar button) inside it. With
|
|
22
|
+
`range`, it is one half of a `DateRangePicker`, whose root draws the
|
|
23
|
+
shell: a bare inline group named by `range.label` ("Start date"), whose
|
|
24
|
+
segments read "day, <label> Start date".
|
|
25
|
+
-->
|
|
26
|
+
<script lang="ts">import { inputSize } from "./field-types.js";
|
|
27
|
+
let { parts, group, range, trailing } = $props();
|
|
28
|
+
const { class: className, ...attributes } = $derived(group.attributes);
|
|
29
|
+
// SAFETY: the namespaces' `Segment`s differ only in the `part` union they
|
|
30
|
+
// accept, and every `part` rendered here comes from the same root's own
|
|
31
|
+
// `segments`, so a TimeField segment is only ever handed a time part.
|
|
32
|
+
const Segment = $derived(parts.Segment);
|
|
33
|
+
// SAFETY: every `Input` takes `id`, `name` and `child`; only the range's
|
|
34
|
+
// also takes `type`, which is passed only when `range` is set, and a range
|
|
35
|
+
// is only ever rendered with `DateRangePicker`'s parts.
|
|
36
|
+
const Input = $derived(parts.Input);
|
|
37
|
+
const inputProps = $derived({
|
|
38
|
+
...group.id === undefined || range !== undefined ? {} : { id: group.id },
|
|
39
|
+
name: (range === undefined ? group.name : range.name) ?? "",
|
|
40
|
+
...range === undefined ? {} : { type: range.type }
|
|
41
|
+
});
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
{#snippet segmentList(segments: readonly { part: string; value: string }[], names: string | undefined)}
|
|
45
|
+
{#each segments as { part, value }, index (index)}
|
|
46
|
+
<Segment part={part as 'literal'}>
|
|
47
|
+
{#snippet child({ props: segmentProps })}
|
|
48
|
+
{#if part === 'literal'}
|
|
49
|
+
<span {...segmentProps} aria-hidden="true" class="text-base-content/60 px-px">{value}</span>
|
|
50
|
+
{:else}
|
|
51
|
+
<span
|
|
52
|
+
{...segmentProps}
|
|
53
|
+
aria-labelledby={names === undefined ? undefined : `${String(segmentProps['id'])} ${names}`}
|
|
54
|
+
class="focus:bg-primary focus:text-primary-content rounded-sm px-0.5 outline-none aria-[valuetext=Empty]:text-base-content/50"
|
|
55
|
+
>{value}</span
|
|
56
|
+
>
|
|
57
|
+
{/if}
|
|
58
|
+
{/snippet}
|
|
59
|
+
</Segment>
|
|
60
|
+
{/each}
|
|
61
|
+
{/snippet}
|
|
62
|
+
|
|
63
|
+
<Input {...inputProps}>
|
|
64
|
+
{#snippet child({ props, segments })}
|
|
65
|
+
{#if range !== undefined}
|
|
66
|
+
{@const ownId = String(props['id'])}
|
|
67
|
+
<div {...props} role="group" aria-label={range.label} class="inline-flex items-center">
|
|
68
|
+
{@render segmentList(segments, [group.labelId, ownId].filter(Boolean).join(' '))}
|
|
69
|
+
</div>
|
|
70
|
+
{:else}
|
|
71
|
+
<div
|
|
72
|
+
{...attributes}
|
|
73
|
+
{...props}
|
|
74
|
+
aria-labelledby={group.labelId}
|
|
75
|
+
aria-describedby={group.describedBy === '' ? undefined : group.describedBy}
|
|
76
|
+
aria-invalid={group.invalid ? 'true' : undefined}
|
|
77
|
+
class={[
|
|
78
|
+
'input inline-flex w-auto items-center gap-0 tabular-nums',
|
|
79
|
+
inputSize[group.size],
|
|
80
|
+
group.invalid && 'input-error',
|
|
81
|
+
'data-invalid:input-error',
|
|
82
|
+
group.disabled && 'opacity-50',
|
|
83
|
+
className,
|
|
84
|
+
]}
|
|
85
|
+
>
|
|
86
|
+
{@render segmentList(segments, group.labelId)}
|
|
87
|
+
{@render trailing?.()}
|
|
88
|
+
</div>
|
|
89
|
+
{/if}
|
|
90
|
+
{/snippet}
|
|
91
|
+
</Input>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { DateField, DatePicker, DateRangePicker, TimeField } from 'bits-ui';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { SegmentGroupOptions } from './segmented-field.ts';
|
|
4
|
+
interface Props {
|
|
5
|
+
/** The bits-ui namespace whose parts to render. */
|
|
6
|
+
parts: typeof DateField | typeof TimeField | typeof DatePicker | typeof DateRangePicker;
|
|
7
|
+
group: SegmentGroupOptions;
|
|
8
|
+
/** One half of a range: which half, its name, and its posted field name. */
|
|
9
|
+
range?: {
|
|
10
|
+
readonly type: 'start' | 'end';
|
|
11
|
+
readonly label: string;
|
|
12
|
+
readonly name?: string | undefined;
|
|
13
|
+
} | undefined;
|
|
14
|
+
/** Rendered inside the shell after the segments (a picker's trigger). */
|
|
15
|
+
trailing?: Snippet<[]> | undefined;
|
|
16
|
+
}
|
|
17
|
+
/** The segment group the bits-ui date and time controls share; internal, not exported. */
|
|
18
|
+
declare const SegmentGroup: import("svelte").Component<Props, {}, "">;
|
|
19
|
+
type SegmentGroup = ReturnType<typeof SegmentGroup>;
|
|
20
|
+
export default SegmentGroup;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A native `<select>` in daisyUI styling over a list of options, with an optional placeholder and `FieldControl` wiring.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
Select — a native `<select>` in daisyUI `select` styling over a list of
|
|
6
|
+
options, with a bindable `value`, an optional placeholder option (disabled,
|
|
7
|
+
selected while `value` is empty) and the `FieldControl` wiring.
|
|
8
|
+
|
|
9
|
+
Native, not bits-ui, and deliberately: a native select is keyboard-complete
|
|
10
|
+
and typeahead-complete without a line of script, and on a phone it opens the
|
|
11
|
+
platform picker. The rich alternative is `Combobox`, which exists for the
|
|
12
|
+
case a select genuinely cannot serve — a list too long to scroll, or one
|
|
13
|
+
that has to be fetched.
|
|
14
|
+
|
|
15
|
+
ARIA contract: the platform's. `describedBy` and `invalid` are the only
|
|
16
|
+
attributes added.
|
|
17
|
+
-->
|
|
18
|
+
<script lang="ts">import { selectSize, toFieldOptions } from "./field-types.js";
|
|
19
|
+
let { options, value = $bindable(""), placeholder, size = "md", invalid = false, describedBy = "", labelId: _labelId, class: className, ...rest } = $props();
|
|
20
|
+
const entries = $derived(toFieldOptions(options));
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<select
|
|
24
|
+
{...rest}
|
|
25
|
+
bind:value
|
|
26
|
+
aria-invalid={invalid ? 'true' : undefined}
|
|
27
|
+
aria-describedby={describedBy === '' ? undefined : describedBy}
|
|
28
|
+
class={['select w-full', selectSize[size], invalid && 'select-error', className]}
|
|
29
|
+
>
|
|
30
|
+
{#if placeholder !== undefined}
|
|
31
|
+
<option value="" disabled>{placeholder}</option>
|
|
32
|
+
{/if}
|
|
33
|
+
{#each entries as option (option.value)}
|
|
34
|
+
<option value={option.value} disabled={option.disabled === true}>{option.label}</option>
|
|
35
|
+
{/each}
|
|
36
|
+
</select>
|