@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,35 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A `<data>` element whose text is the `Intl.NumberFormat` rendering and whose `value` attribute keeps the raw number.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
NumberFormat — a `<data>` element whose text is `Intl.NumberFormat`'s
|
|
6
|
+
rendering and whose `value` attribute is the raw number/bigint, so the
|
|
7
|
+
machine-readable figure survives locale formatting.
|
|
8
|
+
|
|
9
|
+
Exported as `NumberFormat` (not `Number`) to avoid shadowing the global.
|
|
10
|
+
|
|
11
|
+
ARIA contract: none beyond native `<data>` semantics — `value` carries the
|
|
12
|
+
machine-readable figure, the rendered text carries the locale-formatted one.
|
|
13
|
+
-->
|
|
14
|
+
<script lang="ts">import { getComponentsContext } from "../context.svelte.js";
|
|
15
|
+
let { value, locales = getComponentsContext().locale(), style = "decimal", unit, unitDisplay = "short", currency, currencyDisplay = "symbol", maximumFractionDigits, minimumFractionDigits, signDisplay, notation, options, ...rest } = $props();
|
|
16
|
+
// The formatter and the formatted string are separate `$derived` values so
|
|
17
|
+
// constructing the (relatively expensive) `Intl.NumberFormat` is skipped
|
|
18
|
+
// when only `value` changes. See PERF-CPU-003 in
|
|
19
|
+
// docs/specs/performance-invariants.md.
|
|
20
|
+
const format = $derived(new Intl.NumberFormat(locales, options ?? {
|
|
21
|
+
style,
|
|
22
|
+
unit,
|
|
23
|
+
unitDisplay,
|
|
24
|
+
currency,
|
|
25
|
+
currencyDisplay,
|
|
26
|
+
maximumFractionDigits,
|
|
27
|
+
minimumFractionDigits,
|
|
28
|
+
signDisplay,
|
|
29
|
+
notation
|
|
30
|
+
}));
|
|
31
|
+
const formatted = $derived(format.format(value));
|
|
32
|
+
const raw = $derived(String(value));
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<data {...rest} value={raw}>{formatted}</data>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { HTMLDataAttributes } from 'svelte/elements';
|
|
2
|
+
interface Props extends Omit<HTMLDataAttributes, 'value'> {
|
|
3
|
+
/** The number to format; the raw value also goes in the `value` attribute. */
|
|
4
|
+
value: number | bigint;
|
|
5
|
+
/**
|
|
6
|
+
* Locale(s) for `Intl` formatting.
|
|
7
|
+
* @defaultValue the components context's `locale()`
|
|
8
|
+
*/
|
|
9
|
+
locales?: string | readonly string[] | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* `Intl.NumberFormat` `style`.
|
|
12
|
+
* @defaultValue `'decimal'`
|
|
13
|
+
*/
|
|
14
|
+
style?: Intl.NumberFormatOptions['style'] | undefined;
|
|
15
|
+
/** The unit when `style` is `unit` (`kilometer`, `percent`). */
|
|
16
|
+
unit?: string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* `Intl.NumberFormat` `unitDisplay`.
|
|
19
|
+
* @defaultValue `'short'`
|
|
20
|
+
*/
|
|
21
|
+
unitDisplay?: Intl.NumberFormatOptions['unitDisplay'] | undefined;
|
|
22
|
+
/** ISO 4217 code when `style` is `currency`. */
|
|
23
|
+
currency?: string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* `Intl.NumberFormat` `currencyDisplay`.
|
|
26
|
+
* @defaultValue `'symbol'`
|
|
27
|
+
*/
|
|
28
|
+
currencyDisplay?: Intl.NumberFormatOptions['currencyDisplay'] | undefined;
|
|
29
|
+
/** `Intl.NumberFormat` `maximumFractionDigits`. */
|
|
30
|
+
maximumFractionDigits?: number | undefined;
|
|
31
|
+
/** `Intl.NumberFormat` `minimumFractionDigits`. */
|
|
32
|
+
minimumFractionDigits?: number | undefined;
|
|
33
|
+
/** `Intl.NumberFormat` `signDisplay`. */
|
|
34
|
+
signDisplay?: Intl.NumberFormatOptions['signDisplay'] | undefined;
|
|
35
|
+
/** `Intl.NumberFormat` `notation`. */
|
|
36
|
+
notation?: Intl.NumberFormatOptions['notation'] | undefined;
|
|
37
|
+
/** Raw `Intl.NumberFormatOptions`; wins over the individual style props when given. */
|
|
38
|
+
options?: Intl.NumberFormatOptions | undefined;
|
|
39
|
+
}
|
|
40
|
+
/** A `<data>` element whose text is the `Intl.NumberFormat` rendering and whose `value` attribute keeps the raw number. */
|
|
41
|
+
declare const Number: import("svelte").Component<Props, {}, "">;
|
|
42
|
+
type Number = ReturnType<typeof Number>;
|
|
43
|
+
export default Number;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
"3 days ago" / "in 2 hours" via `Intl.RelativeTimeFormat`, in the largest unit whose magnitude is at least one.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
RelativeTime — "3 days ago" / "in 2 hours" via `Intl.RelativeTimeFormat`,
|
|
6
|
+
picking the largest unit (seconds → years) whose magnitude is at least one.
|
|
7
|
+
|
|
8
|
+
ARIA contract: none beyond native `<time>` semantics. The absolute instant
|
|
9
|
+
is never hidden — it is both the machine-readable `datetime` and the
|
|
10
|
+
human-readable `title`, so a reader who hovers (or a tool that reads
|
|
11
|
+
`title`) gets the precise moment the relative text is glossing over.
|
|
12
|
+
-->
|
|
13
|
+
<script lang="ts">import { getComponentsContext } from "../context.svelte.js";
|
|
14
|
+
let { value, now, locales = getComponentsContext().locale(), numeric = "auto", style = "long", ...rest } = $props();
|
|
15
|
+
const UNITS = [
|
|
16
|
+
{
|
|
17
|
+
unit: "year",
|
|
18
|
+
ms: 365.25 * 24 * 60 * 60 * 1e3
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
unit: "month",
|
|
22
|
+
ms: 30.44 * 24 * 60 * 60 * 1e3
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
unit: "week",
|
|
26
|
+
ms: 7 * 24 * 60 * 60 * 1e3
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
unit: "day",
|
|
30
|
+
ms: 24 * 60 * 60 * 1e3
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
unit: "hour",
|
|
34
|
+
ms: 60 * 60 * 1e3
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
unit: "minute",
|
|
38
|
+
ms: 60 * 1e3
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
unit: "second",
|
|
42
|
+
ms: 1e3
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
const instant = $derived(new Date(value));
|
|
46
|
+
const reference = $derived(new Date(now ?? Date.now()));
|
|
47
|
+
const diffMs = $derived(instant.getTime() - reference.getTime());
|
|
48
|
+
// Largest unit whose magnitude rounds to at least one; falls back to
|
|
49
|
+
// seconds for anything smaller (e.g. "0 seconds ago" / "in 0 seconds").
|
|
50
|
+
const picked = $derived(UNITS.find((candidate) => Math.abs(diffMs) >= candidate.ms) ?? UNITS[UNITS.length - 1]);
|
|
51
|
+
const roundedValue = $derived(Math.round(diffMs / picked.ms));
|
|
52
|
+
// The formatter and the formatted string are separate `$derived` values so
|
|
53
|
+
// constructing the (relatively expensive) `Intl.RelativeTimeFormat` is
|
|
54
|
+
// skipped when only `value`/`now` change. See PERF-CPU-003 in
|
|
55
|
+
// docs/specs/performance-invariants.md.
|
|
56
|
+
const format = $derived(new Intl.RelativeTimeFormat(locales, {
|
|
57
|
+
numeric,
|
|
58
|
+
style
|
|
59
|
+
}));
|
|
60
|
+
const formatted = $derived(format.format(roundedValue, picked.unit));
|
|
61
|
+
const iso = $derived(instant.toISOString());
|
|
62
|
+
const absoluteFormat = $derived(new Intl.DateTimeFormat(locales, {
|
|
63
|
+
dateStyle: "full",
|
|
64
|
+
timeStyle: "short"
|
|
65
|
+
}));
|
|
66
|
+
const absolute = $derived(absoluteFormat.format(instant));
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<time {...rest} datetime={iso} title={absolute}>{formatted}</time>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { HTMLTimeAttributes } from 'svelte/elements';
|
|
2
|
+
interface Props extends HTMLTimeAttributes {
|
|
3
|
+
/** The instant: a `Date`, epoch milliseconds or an ISO string. */
|
|
4
|
+
value: Date | number | string;
|
|
5
|
+
/** The instant "now" is measured from; defaults to the current wall clock at render. */
|
|
6
|
+
now?: Date | number | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Locale(s) for `Intl` formatting.
|
|
9
|
+
* @defaultValue the components context's `locale()`
|
|
10
|
+
*/
|
|
11
|
+
locales?: string | readonly string[] | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* `Intl.RelativeTimeFormat` `numeric`; `auto` allows "yesterday".
|
|
14
|
+
* @defaultValue `'auto'`
|
|
15
|
+
*/
|
|
16
|
+
numeric?: Intl.RelativeTimeFormatOptions['numeric'] | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* `Intl.RelativeTimeFormat` `style`.
|
|
19
|
+
* @defaultValue `'long'`
|
|
20
|
+
*/
|
|
21
|
+
style?: Intl.RelativeTimeFormatOptions['style'] | undefined;
|
|
22
|
+
}
|
|
23
|
+
/** "3 days ago" / "in 2 hours" via `Intl.RelativeTimeFormat`, in the largest unit whose magnitude is at least one. */
|
|
24
|
+
declare const RelativeTime: import("svelte").Component<Props, {}, "">;
|
|
25
|
+
type RelativeTime = ReturnType<typeof RelativeTime>;
|
|
26
|
+
export default RelativeTime;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A `<time>` element carrying just a year, for dates whose precision really is a year.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
Year — a `<time>` element carrying just a year: `datetime="1925"`, and
|
|
6
|
+
`Intl.DateTimeFormat`'s locale rendering of the year (with its era, when
|
|
7
|
+
asked) as the text. For publication dates, lifespans and anything else whose
|
|
8
|
+
precision really is a year.
|
|
9
|
+
|
|
10
|
+
ARIA contract: none beyond the native `<time>` semantics. `datetime` is a
|
|
11
|
+
valid HTML year string (four or more digits), so the value stays
|
|
12
|
+
machine-readable at the precision it actually has rather than claiming a
|
|
13
|
+
midnight-on-1-January instant.
|
|
14
|
+
|
|
15
|
+
A `number` is a CALENDAR YEAR (`1925`), not an epoch timestamp — that is
|
|
16
|
+
what a caller holding "the year" has. A `Date` or string is read as an
|
|
17
|
+
instant and its UTC year is taken, so a date at midnight UTC never renders
|
|
18
|
+
as the previous year in a timezone west of Greenwich. Years before 1 CE have
|
|
19
|
+
no HTML year string, so for those `datetime` falls back to the ISO instant.
|
|
20
|
+
-->
|
|
21
|
+
<script lang="ts">import { getComponentsContext } from "../context.svelte.js";
|
|
22
|
+
let { value, locales = getComponentsContext().locale(), era, representation = "numeric", ...rest } = $props();
|
|
23
|
+
const instant = $derived.by(() => {
|
|
24
|
+
if (typeof value !== "number") return new Date(value);
|
|
25
|
+
const date = new Date(Date.UTC(2e3, 0, 1));
|
|
26
|
+
date.setUTCFullYear(value);
|
|
27
|
+
return date;
|
|
28
|
+
});
|
|
29
|
+
const format = $derived(new Intl.DateTimeFormat(locales, {
|
|
30
|
+
year: representation,
|
|
31
|
+
era,
|
|
32
|
+
timeZone: "UTC"
|
|
33
|
+
}));
|
|
34
|
+
const formatted = $derived(format.format(instant));
|
|
35
|
+
const year = $derived(instant.getUTCFullYear());
|
|
36
|
+
const datetime = $derived(year >= 1 ? String(year).padStart(4, "0") : instant.toISOString());
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<time {...rest} {datetime}>{formatted}</time>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { HTMLTimeAttributes } from 'svelte/elements';
|
|
2
|
+
interface Props extends HTMLTimeAttributes {
|
|
3
|
+
/** A calendar year, or an instant (its UTC year is used). */
|
|
4
|
+
value: Date | number | string;
|
|
5
|
+
/**
|
|
6
|
+
* Locale(s) for `Intl` formatting.
|
|
7
|
+
* @defaultValue the components context's `locale()`
|
|
8
|
+
*/
|
|
9
|
+
locales?: string | readonly string[] | undefined;
|
|
10
|
+
/** Append the era: `1925 AD`. */
|
|
11
|
+
era?: Intl.DateTimeFormatOptions['era'] | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Four digits or two.
|
|
14
|
+
* @defaultValue `'numeric'`
|
|
15
|
+
*/
|
|
16
|
+
representation?: 'numeric' | '2-digit' | undefined;
|
|
17
|
+
}
|
|
18
|
+
/** A `<time>` element carrying just a year, for dates whose precision really is a year. */
|
|
19
|
+
declare const Year: import("svelte").Component<Props, {}, "">;
|
|
20
|
+
type Year = ReturnType<typeof Year>;
|
|
21
|
+
export default Year;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lengths of time: the value type, its ISO 8601 form for `<time datetime>`,
|
|
3
|
+
* and a locale-aware formatter that `Duration` and `Countdown` share and an
|
|
4
|
+
* app can call in plain TypeScript.
|
|
5
|
+
*
|
|
6
|
+
* `formatDuration` uses `Intl.DurationFormat` where the runtime has it
|
|
7
|
+
* (Baseline 2025) and otherwise composes per-unit `Intl.NumberFormat` unit
|
|
8
|
+
* strings with an `Intl.ListFormat` of `type: 'unit'`, so the fallback is
|
|
9
|
+
* still localised, just less idiomatic.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
/** A length of time; any subset of fields. Mirrors `Intl.DurationFormat`'s input. */
|
|
14
|
+
export interface DurationValue {
|
|
15
|
+
readonly years?: number | undefined;
|
|
16
|
+
readonly months?: number | undefined;
|
|
17
|
+
readonly weeks?: number | undefined;
|
|
18
|
+
readonly days?: number | undefined;
|
|
19
|
+
readonly hours?: number | undefined;
|
|
20
|
+
readonly minutes?: number | undefined;
|
|
21
|
+
readonly seconds?: number | undefined;
|
|
22
|
+
readonly milliseconds?: number | undefined;
|
|
23
|
+
}
|
|
24
|
+
/** How a duration is spelled: `'2 hours, 30 minutes'`, `'2 hr, 30 min'`, `'2h 30m'` or `'2:30:00'`. */
|
|
25
|
+
export type DurationStyle = 'long' | 'short' | 'narrow' | 'digital';
|
|
26
|
+
/**
|
|
27
|
+
* Split milliseconds into days, hours, minutes, seconds and milliseconds,
|
|
28
|
+
* leaving out the zero fields (`9_309_000` → `{ hours: 2, minutes: 35,
|
|
29
|
+
* seconds: 9 }`). Days are the largest unit: months and years have no fixed
|
|
30
|
+
* length. Negative input is treated as zero.
|
|
31
|
+
*/
|
|
32
|
+
export declare function durationFromMilliseconds(ms: number): DurationValue;
|
|
33
|
+
/**
|
|
34
|
+
* The ISO 8601 duration string for `<time datetime>`: `{ hours: 2,
|
|
35
|
+
* minutes: 30 }` → `'PT2H30M'`. Milliseconds join the seconds as a
|
|
36
|
+
* fraction; an empty duration is `'PT0S'`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function toIsoDuration(value: DurationValue): string;
|
|
39
|
+
/**
|
|
40
|
+
* Format a duration for `locales` in `style`, through `Intl.DurationFormat`
|
|
41
|
+
* where available and a localised `NumberFormat` + `ListFormat` composition
|
|
42
|
+
* otherwise.
|
|
43
|
+
*/
|
|
44
|
+
export declare function formatDuration(value: DurationValue, locales?: string | readonly string[], style?: DurationStyle): string;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lengths of time: the value type, its ISO 8601 form for `<time datetime>`,
|
|
3
|
+
* and a locale-aware formatter that `Duration` and `Countdown` share and an
|
|
4
|
+
* app can call in plain TypeScript.
|
|
5
|
+
*
|
|
6
|
+
* `formatDuration` uses `Intl.DurationFormat` where the runtime has it
|
|
7
|
+
* (Baseline 2025) and otherwise composes per-unit `Intl.NumberFormat` unit
|
|
8
|
+
* strings with an `Intl.ListFormat` of `type: 'unit'`, so the fallback is
|
|
9
|
+
* still localised, just less idiomatic.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
/** The fields, largest first, with the `Intl` unit each formats as. */
|
|
14
|
+
const FIELDS = [
|
|
15
|
+
{ field: 'years', unit: 'year' },
|
|
16
|
+
{ field: 'months', unit: 'month' },
|
|
17
|
+
{ field: 'weeks', unit: 'week' },
|
|
18
|
+
{ field: 'days', unit: 'day' },
|
|
19
|
+
{ field: 'hours', unit: 'hour' },
|
|
20
|
+
{ field: 'minutes', unit: 'minute' },
|
|
21
|
+
{ field: 'seconds', unit: 'second' },
|
|
22
|
+
{ field: 'milliseconds', unit: 'millisecond' },
|
|
23
|
+
];
|
|
24
|
+
const SECOND = 1000;
|
|
25
|
+
const MINUTE = 60 * SECOND;
|
|
26
|
+
const HOUR = 60 * MINUTE;
|
|
27
|
+
const DAY = 24 * HOUR;
|
|
28
|
+
/**
|
|
29
|
+
* Split milliseconds into days, hours, minutes, seconds and milliseconds,
|
|
30
|
+
* leaving out the zero fields (`9_309_000` → `{ hours: 2, minutes: 35,
|
|
31
|
+
* seconds: 9 }`). Days are the largest unit: months and years have no fixed
|
|
32
|
+
* length. Negative input is treated as zero.
|
|
33
|
+
*/
|
|
34
|
+
export function durationFromMilliseconds(ms) {
|
|
35
|
+
let rest = Math.max(0, Math.round(ms));
|
|
36
|
+
const parts = {};
|
|
37
|
+
for (const [field, size] of [
|
|
38
|
+
['days', DAY],
|
|
39
|
+
['hours', HOUR],
|
|
40
|
+
['minutes', MINUTE],
|
|
41
|
+
['seconds', SECOND],
|
|
42
|
+
['milliseconds', 1],
|
|
43
|
+
]) {
|
|
44
|
+
const count = Math.floor(rest / size);
|
|
45
|
+
rest -= count * size;
|
|
46
|
+
if (count > 0)
|
|
47
|
+
parts[field] = count;
|
|
48
|
+
}
|
|
49
|
+
return parts;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The ISO 8601 duration string for `<time datetime>`: `{ hours: 2,
|
|
53
|
+
* minutes: 30 }` → `'PT2H30M'`. Milliseconds join the seconds as a
|
|
54
|
+
* fraction; an empty duration is `'PT0S'`.
|
|
55
|
+
*/
|
|
56
|
+
export function toIsoDuration(value) {
|
|
57
|
+
const amount = (field) => value[field] ?? 0;
|
|
58
|
+
const date = [
|
|
59
|
+
amount('years') > 0 ? `${amount('years')}Y` : '',
|
|
60
|
+
amount('months') > 0 ? `${amount('months')}M` : '',
|
|
61
|
+
amount('weeks') > 0 ? `${amount('weeks')}W` : '',
|
|
62
|
+
amount('days') > 0 ? `${amount('days')}D` : '',
|
|
63
|
+
].join('');
|
|
64
|
+
const seconds = amount('seconds') + amount('milliseconds') / 1000;
|
|
65
|
+
const time = [
|
|
66
|
+
amount('hours') > 0 ? `${amount('hours')}H` : '',
|
|
67
|
+
amount('minutes') > 0 ? `${amount('minutes')}M` : '',
|
|
68
|
+
seconds > 0 ? `${Number(seconds.toFixed(3))}S` : '',
|
|
69
|
+
].join('');
|
|
70
|
+
if (date === '' && time === '')
|
|
71
|
+
return 'PT0S';
|
|
72
|
+
return `P${date}${time === '' ? '' : `T${time}`}`;
|
|
73
|
+
}
|
|
74
|
+
/** `Intl.DurationFormat` when the runtime has it. */
|
|
75
|
+
function nativeDurationFormat() {
|
|
76
|
+
const intl = Intl;
|
|
77
|
+
return intl.DurationFormat;
|
|
78
|
+
}
|
|
79
|
+
/** `value` with the `undefined` and zero fields dropped, as `Intl.DurationFormat` wants. */
|
|
80
|
+
function presentFields(value) {
|
|
81
|
+
return Object.fromEntries(FIELDS.filter(({ field }) => (value[field] ?? 0) !== 0).map(({ field }) => [
|
|
82
|
+
field,
|
|
83
|
+
value[field],
|
|
84
|
+
]));
|
|
85
|
+
}
|
|
86
|
+
/** `H:MM:SS` from the hours, minutes and seconds, the larger units folded into hours. */
|
|
87
|
+
function digital(value) {
|
|
88
|
+
const hours = (value.days ?? 0) * 24 + (value.hours ?? 0);
|
|
89
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
90
|
+
return `${hours}:${pad(value.minutes ?? 0)}:${pad(value.seconds ?? 0)}`;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Format a duration for `locales` in `style`, through `Intl.DurationFormat`
|
|
94
|
+
* where available and a localised `NumberFormat` + `ListFormat` composition
|
|
95
|
+
* otherwise.
|
|
96
|
+
*/
|
|
97
|
+
export function formatDuration(value, locales, style = 'short') {
|
|
98
|
+
const present = presentFields(value);
|
|
99
|
+
const Native = nativeDurationFormat();
|
|
100
|
+
if (Native !== undefined) {
|
|
101
|
+
return new Native(locales, { style }).format(present);
|
|
102
|
+
}
|
|
103
|
+
if (style === 'digital')
|
|
104
|
+
return digital(value);
|
|
105
|
+
const unitDisplay = style;
|
|
106
|
+
// A mutable copy: TS6's `Intl.ListFormat` (svelte-check) takes no readonly array.
|
|
107
|
+
const tags = typeof locales === 'object' ? [...locales] : locales;
|
|
108
|
+
const pieces = FIELDS.filter(({ field }) => present[field] !== undefined).map(({ field, unit }) => new Intl.NumberFormat(tags, {
|
|
109
|
+
style: 'unit',
|
|
110
|
+
unit,
|
|
111
|
+
unitDisplay,
|
|
112
|
+
}).format(present[field] ?? 0));
|
|
113
|
+
return new Intl.ListFormat(tags, {
|
|
114
|
+
type: 'unit',
|
|
115
|
+
style: style === 'long' ? 'long' : style === 'short' ? 'short' : 'narrow',
|
|
116
|
+
}).format(pieces.length === 0
|
|
117
|
+
? [
|
|
118
|
+
new Intl.NumberFormat(tags, {
|
|
119
|
+
style: 'unit',
|
|
120
|
+
unit: 'second',
|
|
121
|
+
unitDisplay,
|
|
122
|
+
}).format(0),
|
|
123
|
+
]
|
|
124
|
+
: pieces);
|
|
125
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* formatting — locale-aware rendering of dates, numbers, lists and search
|
|
3
|
+
* highlights. See the package README for the family reference.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
export { default as Countdown } from './Countdown.svelte';
|
|
8
|
+
export { default as DateTime } from './DateTime.svelte';
|
|
9
|
+
export { default as Duration } from './Duration.svelte';
|
|
10
|
+
export * from './duration.ts';
|
|
11
|
+
export { default as NumberFormat } from './Number.svelte';
|
|
12
|
+
export { default as FormatList } from './FormatList.svelte';
|
|
13
|
+
export { default as RelativeTime } from './RelativeTime.svelte';
|
|
14
|
+
export { default as Year } from './Year.svelte';
|
|
15
|
+
export { default as Highlight, tokenise } from './Highlight.svelte';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* formatting — locale-aware rendering of dates, numbers, lists and search
|
|
3
|
+
* highlights. See the package README for the family reference.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
export { default as Countdown } from './Countdown.svelte';
|
|
8
|
+
export { default as DateTime } from './DateTime.svelte';
|
|
9
|
+
export { default as Duration } from './Duration.svelte';
|
|
10
|
+
export * from "./duration.js";
|
|
11
|
+
// `NumberFormat`, not `Number`: a named export called `Number` would shadow
|
|
12
|
+
// the global constructor for anyone importing it by that name.
|
|
13
|
+
export { default as NumberFormat } from './Number.svelte';
|
|
14
|
+
export { default as FormatList } from './FormatList.svelte';
|
|
15
|
+
export { default as RelativeTime } from './RelativeTime.svelte';
|
|
16
|
+
export { default as Year } from './Year.svelte';
|
|
17
|
+
export { default as Highlight, tokenise } from './Highlight.svelte';
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
Renders an `@thomasfosterau/effect-forms-svelte` `defineEntityForm` definition through this library’s field primitives.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
EntityForm — the generic renderer for an `@thomasfosterau/effect-forms-svelte`
|
|
6
|
+
`defineEntityForm` definition: it walks `definition.entriesFor(mode)` and
|
|
7
|
+
renders each entry through this library's field primitives —
|
|
8
|
+
`FormField` + `TextInput` / `DateInput` / `Textarea` / `Select` for scalars
|
|
9
|
+
and selects, and the entry's own component for a bespoke widget (a picker,
|
|
10
|
+
a contributor list), bridged through the widget contract below.
|
|
11
|
+
|
|
12
|
+
The one component of this package that touches Effect, which is why it is a
|
|
13
|
+
separate entry point (`@thomasfosterau/components/entity-form`) with
|
|
14
|
+
`@thomasfosterau/effect-forms-svelte` an OPTIONAL peer: a consumer that
|
|
15
|
+
never imports this entry never installs the form library or `effect`. The
|
|
16
|
+
renderer itself imports only the store (`createForm`) and types.
|
|
17
|
+
|
|
18
|
+
**Seeding.** `definition`, `mode`, `initial` and `initialRows` configure the
|
|
19
|
+
store ONCE, at mount: a form never changes entity or mode mid-flight, and an
|
|
20
|
+
edit page's values must land in the SSR HTML. There is no `$effect`
|
|
21
|
+
re-seeding, so a value typed before hydration is never wiped by a late seed.
|
|
22
|
+
A create form whose command carries a client id gets one minted here, once
|
|
23
|
+
per mount, so a retried submission stays idempotent.
|
|
24
|
+
|
|
25
|
+
**The widget contract.** A widget entry receives, in this order: its
|
|
26
|
+
definition's `props()`, then the caller's `fieldProps[key]`, then the bridge
|
|
27
|
+
— `name`, `value`, `onChange`, `errors`. The bridge is spread LAST, so
|
|
28
|
+
neither of the first two can sever the store binding. A `value` widget
|
|
29
|
+
bridges a string field of the store; a `rows` widget bridges a row list held
|
|
30
|
+
here and serialises it itself (its own hidden input).
|
|
31
|
+
|
|
32
|
+
**Submission.** `enhance(form)` supplies the spreadable `<form>` attributes.
|
|
33
|
+
It defaults to the store's own `form.props` (POST + its progressive
|
|
34
|
+
enhancement); a SvelteKit app passes its `$app/forms`-backed `enhanceForm`,
|
|
35
|
+
which this package cannot import.
|
|
36
|
+
|
|
37
|
+
**Form-level messages.** The store's root errors and the caller's
|
|
38
|
+
`messages` (a failure the store never saw, such as a server action's
|
|
39
|
+
`fail(500, { message })`) share one `FormErrors` block, store errors first.
|
|
40
|
+
|
|
41
|
+
Every string that is not the definition's own (labels, submit labels and
|
|
42
|
+
option labels are its message thunks) is a prop with an English default.
|
|
43
|
+
-->
|
|
44
|
+
<script lang="ts">import { createForm } from "@thomasfosterau/effect-forms-svelte";
|
|
45
|
+
import DateInput from "../fields/DateInput.svelte";
|
|
46
|
+
import FormField from "../fields/FormField.svelte";
|
|
47
|
+
import Select from "../fields/Select.svelte";
|
|
48
|
+
import TextInput from "../fields/TextInput.svelte";
|
|
49
|
+
import Textarea from "../fields/Textarea.svelte";
|
|
50
|
+
import FormActions from "./FormActions.svelte";
|
|
51
|
+
import FormErrors from "./FormErrors.svelte";
|
|
52
|
+
let { definition, mode, cancelHref, action, initial = {}, initialRows = {}, fieldProps = {}, enhance = (form) => form.props, cancelLabel = "Cancel", pendingLabel = "Saving…", selectPlaceholder = "Choose…", requiredLabel, messages, class: className, ...rest } = $props();
|
|
53
|
+
// Configure-once, at mount (see the header): these reads are deliberately
|
|
54
|
+
// not reactive.
|
|
55
|
+
// svelte-ignore state_referenced_locally
|
|
56
|
+
const configured = {
|
|
57
|
+
definition,
|
|
58
|
+
mode,
|
|
59
|
+
initial,
|
|
60
|
+
initialRows
|
|
61
|
+
};
|
|
62
|
+
const baseDefaults = configured.mode === "create" ? configured.definition.createDefaults : configured.definition.updateDefaults;
|
|
63
|
+
const mintedId = configured.mode === "create" && configured.definition.clientId ? { id: crypto.randomUUID() } : undefined;
|
|
64
|
+
const defaults = {
|
|
65
|
+
...baseDefaults,
|
|
66
|
+
...configured.initial,
|
|
67
|
+
...mintedId
|
|
68
|
+
};
|
|
69
|
+
const form = createForm({
|
|
70
|
+
schema: configured.mode === "create" ? configured.definition.createInput : configured.definition.updateInput,
|
|
71
|
+
defaults
|
|
72
|
+
});
|
|
73
|
+
const entries = configured.definition.entriesFor(configured.mode);
|
|
74
|
+
// SAFETY: `defineEntityForm` validated every entry key against the derived
|
|
75
|
+
// all-string input schema. The definition types that schema `Schema.Top`,
|
|
76
|
+
// whose path-typed accessor admits no key (`never`), so the key is asserted
|
|
77
|
+
// into it and the handle typed by this function's own return type.
|
|
78
|
+
const handle = (key) => form.field(key);
|
|
79
|
+
const getField = (key) => handle(key).value ?? "";
|
|
80
|
+
const setField = (key, next) => {
|
|
81
|
+
handle(key).value = next;
|
|
82
|
+
};
|
|
83
|
+
let rows = $state(Object.fromEntries(entries.filter((entry) => entry._tag === "widget" && entry.bridge === "rows").map((entry) => [entry.key, [...configured.initialRows[entry.key] ?? []]])));
|
|
84
|
+
const bridge = (entry) => entry.bridge === "rows" ? {
|
|
85
|
+
name: entry.key,
|
|
86
|
+
value: rows[entry.key] ?? [],
|
|
87
|
+
onChange: (next) => {
|
|
88
|
+
rows[entry.key] = next;
|
|
89
|
+
},
|
|
90
|
+
errors: handle(entry.key).visibleErrors
|
|
91
|
+
} : {
|
|
92
|
+
name: entry.key,
|
|
93
|
+
value: getField(entry.key),
|
|
94
|
+
onChange: (next) => setField(entry.key, next),
|
|
95
|
+
errors: handle(entry.key).visibleErrors
|
|
96
|
+
};
|
|
97
|
+
const selectOptions = (entry) => (configured.definition.fieldFor(entry.key).options ?? []).map((value) => ({
|
|
98
|
+
value,
|
|
99
|
+
label: entry.options.optionLabels[value]?.() ?? value
|
|
100
|
+
}));
|
|
101
|
+
const inputMode = (entry) => entry.options.inputmode ?? (configured.definition.fieldFor(entry.key).kind === "number" ? "numeric" : undefined);
|
|
102
|
+
const showHiddenId = configured.mode === "update" || configured.definition.clientId;
|
|
103
|
+
const submitLabel = $derived(mode === "create" ? definition.submit.create() : definition.submit.update());
|
|
104
|
+
const gated = $derived(entries.some((entry) => entry._tag === "widget" && entry.options.gate === true && getField(entry.key) === ""));
|
|
105
|
+
// The empty path is the form's own (non-field) messages.
|
|
106
|
+
// The caller's `messages` (a server fault with no form state) follow them.
|
|
107
|
+
const rootErrors = $derived([...form.errorsAt([]), ...messages ?? []]);
|
|
108
|
+
const fieldId = (key) => `entity-form-${key}`;
|
|
109
|
+
// The `FormField` wrapper is the same for a select and a scalar entry.
|
|
110
|
+
const fieldAttrs = (entry) => ({
|
|
111
|
+
id: fieldId(entry.key),
|
|
112
|
+
label: entry.options.label(),
|
|
113
|
+
required: entry.options.required === true,
|
|
114
|
+
errors: handle(entry.key).visibleErrors,
|
|
115
|
+
requiredLabel
|
|
116
|
+
});
|
|
117
|
+
</script>
|
|
118
|
+
|
|
119
|
+
<!-- A scalar entry's control: a textarea, a date input or a text input. -->
|
|
120
|
+
{#snippet scalarInput(entry: ScalarEntry, control: FieldControl)}
|
|
121
|
+
{#if entry.multiline}
|
|
122
|
+
<Textarea
|
|
123
|
+
{...control}
|
|
124
|
+
name={entry.key}
|
|
125
|
+
placeholder={entry.options.placeholder?.()}
|
|
126
|
+
bind:value={() => getField(entry.key), (next: string) => setField(entry.key, next)}
|
|
127
|
+
/>
|
|
128
|
+
{:else if entry.options.type === 'date'}
|
|
129
|
+
<DateInput
|
|
130
|
+
{...control}
|
|
131
|
+
name={entry.key}
|
|
132
|
+
bind:value={() => getField(entry.key), (next: string) => setField(entry.key, next)}
|
|
133
|
+
/>
|
|
134
|
+
{:else}
|
|
135
|
+
<TextInput
|
|
136
|
+
{...control}
|
|
137
|
+
name={entry.key}
|
|
138
|
+
type={entry.options.type === 'url' ? 'url' : 'text'}
|
|
139
|
+
inputmode={inputMode(entry)}
|
|
140
|
+
placeholder={entry.options.placeholder?.()}
|
|
141
|
+
bind:value={() => getField(entry.key), (next: string) => setField(entry.key, next)}
|
|
142
|
+
/>
|
|
143
|
+
{/if}
|
|
144
|
+
{/snippet}
|
|
145
|
+
|
|
146
|
+
<form {...rest} {...enhance(form)} {action} class={['space-y-4', className]}>
|
|
147
|
+
{#if showHiddenId}
|
|
148
|
+
<input type="hidden" name="id" value={getField('id')} />
|
|
149
|
+
{/if}
|
|
150
|
+
|
|
151
|
+
<FormErrors messages={rootErrors} />
|
|
152
|
+
|
|
153
|
+
{#each entries as entry (entry.key)}
|
|
154
|
+
{#if entry._tag === 'widget'}
|
|
155
|
+
<entry.component {...entry.props()} {...fieldProps[entry.key] ?? {}} {...bridge(entry)} />
|
|
156
|
+
{:else if entry._tag === 'select'}
|
|
157
|
+
<FormField {...fieldAttrs(entry)}>
|
|
158
|
+
{#snippet children(control)}
|
|
159
|
+
<Select
|
|
160
|
+
{...control}
|
|
161
|
+
name={entry.key}
|
|
162
|
+
options={selectOptions(entry)}
|
|
163
|
+
placeholder={selectPlaceholder}
|
|
164
|
+
bind:value={() => getField(entry.key), (next: string) => setField(entry.key, next)}
|
|
165
|
+
/>
|
|
166
|
+
{/snippet}
|
|
167
|
+
</FormField>
|
|
168
|
+
{:else}
|
|
169
|
+
<FormField {...fieldAttrs(entry)}>
|
|
170
|
+
{#snippet children(control)}
|
|
171
|
+
{@render scalarInput(entry, control)}
|
|
172
|
+
{/snippet}
|
|
173
|
+
</FormField>
|
|
174
|
+
{/if}
|
|
175
|
+
{/each}
|
|
176
|
+
|
|
177
|
+
<FormActions
|
|
178
|
+
{submitLabel}
|
|
179
|
+
{pendingLabel}
|
|
180
|
+
pending={form.submitting}
|
|
181
|
+
disabled={gated}
|
|
182
|
+
{cancelHref}
|
|
183
|
+
{cancelLabel}
|
|
184
|
+
/>
|
|
185
|
+
</form>
|