@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,66 @@
|
|
|
1
|
+
import { createForm, type EntityFormDefinition, type WidgetEntry } from '@thomasfosterau/effect-forms-svelte';
|
|
2
|
+
import type { HTMLFormAttributes } from 'svelte/elements';
|
|
3
|
+
type Store = ReturnType<typeof createForm>;
|
|
4
|
+
/** The props a widget entry receives: its definition's `props()` shape, owned by the form library. */
|
|
5
|
+
type WidgetProps = ReturnType<WidgetEntry['props']>;
|
|
6
|
+
interface Props extends Omit<HTMLFormAttributes, 'action' | 'method' | 'children'> {
|
|
7
|
+
/** The form definition from `defineEntityForm`. */
|
|
8
|
+
definition: EntityFormDefinition;
|
|
9
|
+
/** Which of the definition’s entry sets to render. */
|
|
10
|
+
mode: 'create' | 'update';
|
|
11
|
+
/** Where Cancel goes. Omitted renders no cancel link. */
|
|
12
|
+
cancelHref?: string | undefined;
|
|
13
|
+
/** A named action (`?/addItem`). Omitted posts to the page's default action. */
|
|
14
|
+
action?: string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* All-string initial values: an edit page's current values, or a create page's pre-filled FK.
|
|
17
|
+
* @defaultValue `{}`
|
|
18
|
+
*/
|
|
19
|
+
initial?: Readonly<Record<string, string>> | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Initial rows per `rows` widget key (a contributor list's current credits).
|
|
22
|
+
* @defaultValue `{}`
|
|
23
|
+
*/
|
|
24
|
+
initialRows?: Readonly<Record<string, readonly unknown[]>> | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Render-time extra props per widget key (a picker's load-resolved `options`).
|
|
27
|
+
* @defaultValue `{}`
|
|
28
|
+
*/
|
|
29
|
+
fieldProps?: Readonly<Record<string, Readonly<WidgetProps>>> | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* The spreadable `<form>` attributes for this store.
|
|
32
|
+
* @defaultValue the store's own `form.props`
|
|
33
|
+
*/
|
|
34
|
+
enhance?: ((form: Store) => Store['props']) | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Text of the cancel link.
|
|
37
|
+
* @defaultValue `'Cancel'`
|
|
38
|
+
*/
|
|
39
|
+
cancelLabel?: string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Submit button text while the form is submitting.
|
|
42
|
+
* @defaultValue `'Saving…'`
|
|
43
|
+
*/
|
|
44
|
+
pendingLabel?: string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* The empty option of a select entry.
|
|
47
|
+
* @defaultValue `'Choose…'`
|
|
48
|
+
*/
|
|
49
|
+
selectPlaceholder?: string | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Read out after a required field’s label.
|
|
52
|
+
* @defaultValue `'(required)'` (from `FormField`)
|
|
53
|
+
*/
|
|
54
|
+
requiredLabel?: string | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Form-level messages from outside the store — a server action's failure
|
|
57
|
+
* message that carries no form state (`page.form?.message`, wrapped in an
|
|
58
|
+
* array). Rendered in the same `FormErrors` block as the store's own root
|
|
59
|
+
* errors, after them, one `role="alert"` each. The text is shown as given.
|
|
60
|
+
*/
|
|
61
|
+
messages?: readonly string[] | undefined;
|
|
62
|
+
}
|
|
63
|
+
/** Renders an `@thomasfosterau/effect-forms-svelte` `defineEntityForm` definition through this library’s field primitives. */
|
|
64
|
+
declare const EntityForm: import("svelte").Component<Props, {}, "">;
|
|
65
|
+
type EntityForm = ReturnType<typeof EntityForm>;
|
|
66
|
+
export default EntityForm;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
The submit and cancel row that closes a form.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
FormActions — the submit / cancel row that closes a form.
|
|
6
|
+
|
|
7
|
+
ARIA contract: the submit control is a real `type="submit"` button, so
|
|
8
|
+
Enter in any field still submits the form. While `pending` it is disabled
|
|
9
|
+
AND `aria-busy="true"` (disabled alone says "you may not"; busy says "it is
|
|
10
|
+
already happening") and its label swaps to `pendingLabel` — the button
|
|
11
|
+
keeps a name throughout, which a spinner-only state would not.
|
|
12
|
+
|
|
13
|
+
Cancel is a LINK, not a button: it navigates away, and a reader should be
|
|
14
|
+
able to see where to before they commit to it.
|
|
15
|
+
-->
|
|
16
|
+
<script lang="ts">import Button from "../ui/Button.svelte";
|
|
17
|
+
import LinkButton from "../ui/LinkButton.svelte";
|
|
18
|
+
let { submitLabel = "Save", pendingLabel = "Saving…", pending = false, disabled = false, tone = "primary", cancelHref, cancelLabel = "Cancel", children, class: className, ...rest } = $props();
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<div {...rest} class={['flex flex-wrap items-center gap-3 pt-2', className]}>
|
|
22
|
+
<Button type="submit" {tone} loading={pending} {disabled}>
|
|
23
|
+
{pending ? pendingLabel : submitLabel}
|
|
24
|
+
</Button>
|
|
25
|
+
{#if cancelHref !== undefined}
|
|
26
|
+
<LinkButton href={cancelHref} variant="ghost" disabled={pending}>{cancelLabel}</LinkButton>
|
|
27
|
+
{/if}
|
|
28
|
+
{@render children?.()}
|
|
29
|
+
</div>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import type { Tone } from '../ui/tones.ts';
|
|
4
|
+
interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
5
|
+
/**
|
|
6
|
+
* Idle label of the submit button.
|
|
7
|
+
* @defaultValue `'Save'`
|
|
8
|
+
*/
|
|
9
|
+
submitLabel?: string | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Label while the form is in flight.
|
|
12
|
+
* @defaultValue `'Saving…'`
|
|
13
|
+
*/
|
|
14
|
+
pendingLabel?: string | undefined;
|
|
15
|
+
/** The form is being submitted. */
|
|
16
|
+
pending?: boolean | undefined;
|
|
17
|
+
/** Extra disable condition — a required picker still empty, say. */
|
|
18
|
+
disabled?: boolean | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Colour of the submit button.
|
|
21
|
+
* @defaultValue `'primary'`
|
|
22
|
+
*/
|
|
23
|
+
tone?: Tone | undefined;
|
|
24
|
+
/** Where cancel goes. Omit for a form with no cancel affordance. */
|
|
25
|
+
cancelHref?: string | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Text of the cancel control.
|
|
28
|
+
* @defaultValue `'Cancel'`
|
|
29
|
+
*/
|
|
30
|
+
cancelLabel?: string | undefined;
|
|
31
|
+
/** Extra controls, rendered after cancel. */
|
|
32
|
+
children?: Snippet<[]> | undefined;
|
|
33
|
+
}
|
|
34
|
+
/** The submit and cancel row that closes a form. */
|
|
35
|
+
declare const FormActions: import("svelte").Component<Props, {}, "">;
|
|
36
|
+
type FormActions = ReturnType<typeof FormActions>;
|
|
37
|
+
export default FormActions;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
The whole-form messages that belong to the submission rather than to any one field.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
FormErrors — the whole-form messages: the ones that belong to the
|
|
6
|
+
submission rather than to any one field ("That name is already taken",
|
|
7
|
+
"Your session expired").
|
|
8
|
+
|
|
9
|
+
ARIA contract: one `Alert` per message, each `live="assertive"`. Assertive
|
|
10
|
+
is right here and would be wrong for page furniture: these appear in
|
|
11
|
+
response to something the reader just did, and the next thing they will do
|
|
12
|
+
is try again. Nothing is rendered while the list is empty, so the alert is
|
|
13
|
+
inserted — and therefore announced — exactly when there is something to say.
|
|
14
|
+
-->
|
|
15
|
+
<script lang="ts">import Alert from "../ui/Alert.svelte";
|
|
16
|
+
let { messages, tone = "error", class: className } = $props();
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
{#each messages ?? [] as message, index (index)}
|
|
20
|
+
<Alert {tone} live="assertive" class={className}>{message}</Alert>
|
|
21
|
+
{/each}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StatusTone } from '../ui/tones.ts';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** Whole-form messages. */
|
|
4
|
+
messages?: readonly string[] | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* Colour of the alert.
|
|
7
|
+
* @defaultValue `'error'`
|
|
8
|
+
*/
|
|
9
|
+
tone?: StatusTone | undefined;
|
|
10
|
+
/** Extra classes, merged last. */
|
|
11
|
+
class?: string | undefined;
|
|
12
|
+
}
|
|
13
|
+
/** The whole-form messages that belong to the submission rather than to any one field. */
|
|
14
|
+
declare const FormErrors: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type FormErrors = ReturnType<typeof FormErrors>;
|
|
16
|
+
export default FormErrors;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A fixed value posted with the form and never edited.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
HiddenField — a fixed value posted with the form and never edited: the
|
|
6
|
+
parent id a create form hangs its row off, a command discriminator, a
|
|
7
|
+
redirect target.
|
|
8
|
+
|
|
9
|
+
It is a component rather than a bare `<input type="hidden">` so that a form
|
|
10
|
+
described declaratively (a list of fields) can include one without dropping
|
|
11
|
+
out of that description, and so the value passes through one place that
|
|
12
|
+
stringifies it.
|
|
13
|
+
|
|
14
|
+
ARIA contract: none, deliberately — a hidden input is not in the
|
|
15
|
+
accessibility tree, and anything a reader needs to KNOW about does not
|
|
16
|
+
belong in one.
|
|
17
|
+
-->
|
|
18
|
+
<script lang="ts">let { name, value, ...rest } = $props();
|
|
19
|
+
export {};
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<input {...rest} type="hidden" {name} value={String(value)} />
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
2
|
+
interface Props extends Omit<HTMLInputAttributes, 'type' | 'value'> {
|
|
3
|
+
/** The posted field name. */
|
|
4
|
+
name: string;
|
|
5
|
+
/** The posted value. */
|
|
6
|
+
value: string | number;
|
|
7
|
+
}
|
|
8
|
+
/** A fixed value posted with the form and never edited. */
|
|
9
|
+
declare const HiddenField: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type HiddenField = ReturnType<typeof HiddenField>;
|
|
11
|
+
export default HiddenField;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
The site search box: a `<search>` landmark around a GET form that works without JavaScript.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
SearchForm — the site search box: a `<search>` landmark around a GET form
|
|
6
|
+
that works with no JavaScript at all.
|
|
7
|
+
|
|
8
|
+
Method GET on purpose. A search is a request for a REPRESENTATION, so its
|
|
9
|
+
result should be a URL people can bookmark, share and go back to; a POST
|
|
10
|
+
would make the results page un-linkable and re-submit on refresh.
|
|
11
|
+
|
|
12
|
+
ARIA contract: `<search>` is the landmark (so "go to search" reaches it
|
|
13
|
+
without an `aria-label` per instance), the visible label is visually hidden
|
|
14
|
+
but real — `for`/`id`, not a `placeholder`, which disappears the moment
|
|
15
|
+
someone types and is not a name at all — and the submit button carries its
|
|
16
|
+
own text rather than an icon alone.
|
|
17
|
+
|
|
18
|
+
`action` resolves through the components context, so an app with a base path
|
|
19
|
+
or a locale prefix gets the right URL without this file knowing about either.
|
|
20
|
+
-->
|
|
21
|
+
<script lang="ts">import { getComponentsContext } from "../context.svelte.js";
|
|
22
|
+
import Button from "../ui/Button.svelte";
|
|
23
|
+
let { action, name = "q", value = $bindable(""), label = "Search", submitLabel = "Search", placeholder, required = true, class: className, ...rest } = $props();
|
|
24
|
+
const context = getComponentsContext();
|
|
25
|
+
const resolved = $derived(context.href(action));
|
|
26
|
+
const uid = $props.id();
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<search class={['block', className]}>
|
|
30
|
+
<form {...rest} action={resolved} method="get" class="join w-full">
|
|
31
|
+
<label class="sr-only" for={uid}>{label}</label>
|
|
32
|
+
<input
|
|
33
|
+
id={uid}
|
|
34
|
+
class="input join-item w-full"
|
|
35
|
+
type="search"
|
|
36
|
+
{name}
|
|
37
|
+
{placeholder}
|
|
38
|
+
{required}
|
|
39
|
+
bind:value
|
|
40
|
+
/>
|
|
41
|
+
<Button type="submit" tone="primary" class="join-item">{submitLabel}</Button>
|
|
42
|
+
</form>
|
|
43
|
+
</search>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { HTMLFormAttributes } from 'svelte/elements';
|
|
2
|
+
interface Props extends Omit<HTMLFormAttributes, 'action' | 'method'> {
|
|
3
|
+
/** Where the search submits — an app path, resolved through the context. */
|
|
4
|
+
action: string;
|
|
5
|
+
/**
|
|
6
|
+
* The query parameter's name.
|
|
7
|
+
* @defaultValue `'q'`
|
|
8
|
+
*/
|
|
9
|
+
name?: string | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* The query. Bindable.
|
|
12
|
+
* @defaultValue `''`
|
|
13
|
+
*/
|
|
14
|
+
value?: string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Accessible name of the field.
|
|
17
|
+
* @defaultValue `'Search'`
|
|
18
|
+
*/
|
|
19
|
+
label?: string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Text of the submit button.
|
|
22
|
+
* @defaultValue `'Search'`
|
|
23
|
+
*/
|
|
24
|
+
submitLabel?: string | undefined;
|
|
25
|
+
/** Placeholder in the field. */
|
|
26
|
+
placeholder?: string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Refuse to submit an empty query.
|
|
29
|
+
* @defaultValue `true`
|
|
30
|
+
*/
|
|
31
|
+
required?: boolean | undefined;
|
|
32
|
+
}
|
|
33
|
+
/** The site search box: a `<search>` landmark around a GET form that works without JavaScript. */
|
|
34
|
+
declare const SearchForm: import("svelte").Component<Props, {}, "value">;
|
|
35
|
+
type SearchForm = ReturnType<typeof SearchForm>;
|
|
36
|
+
export default SearchForm;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@thomasfosterau/components/entity-form` — the renderer for
|
|
3
|
+
* `@thomasfosterau/effect-forms-svelte`'s `defineEntityForm` definitions.
|
|
4
|
+
*
|
|
5
|
+
* A separate entry point, and the only one that reaches Effect:
|
|
6
|
+
* `@thomasfosterau/effect-forms-svelte` (and, through it, `effect`) is an
|
|
7
|
+
* OPTIONAL peer of this package, needed exactly when this entry is imported.
|
|
8
|
+
* Deliberately NOT re-exported from the `forms` family or the root barrel.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
export { default as EntityForm } from './EntityForm.svelte';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@thomasfosterau/components/entity-form` — the renderer for
|
|
3
|
+
* `@thomasfosterau/effect-forms-svelte`'s `defineEntityForm` definitions.
|
|
4
|
+
*
|
|
5
|
+
* A separate entry point, and the only one that reaches Effect:
|
|
6
|
+
* `@thomasfosterau/effect-forms-svelte` (and, through it, `effect`) is an
|
|
7
|
+
* OPTIONAL peer of this package, needed exactly when this entry is imported.
|
|
8
|
+
* Deliberately NOT re-exported from the `forms` family or the root barrel.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
export { default as EntityForm } from './EntityForm.svelte';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* forms — the pieces of a form that are not one control: the whole-form error
|
|
3
|
+
* list, the submit row, a hidden command field, and the site search form.
|
|
4
|
+
*
|
|
5
|
+
* Everything field-level lives in `fields/`. The split is by who owns the
|
|
6
|
+
* message: a `FormErrors` message has no field to attach to, and a
|
|
7
|
+
* `FormActions` row belongs to the form rather than to anything in it.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
export { default as FormActions } from './FormActions.svelte';
|
|
12
|
+
export { default as FormErrors } from './FormErrors.svelte';
|
|
13
|
+
export { default as HiddenField } from './HiddenField.svelte';
|
|
14
|
+
export { default as SearchForm } from './SearchForm.svelte';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* forms — the pieces of a form that are not one control: the whole-form error
|
|
3
|
+
* list, the submit row, a hidden command field, and the site search form.
|
|
4
|
+
*
|
|
5
|
+
* Everything field-level lives in `fields/`. The split is by who owns the
|
|
6
|
+
* message: a `FormErrors` message has no field to attach to, and a
|
|
7
|
+
* `FormActions` row belongs to the form rather than to anything in it.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
export { default as FormActions } from './FormActions.svelte';
|
|
12
|
+
export { default as FormErrors } from './FormErrors.svelte';
|
|
13
|
+
export { default as HiddenField } from './HiddenField.svelte';
|
|
14
|
+
export { default as SearchForm } from './SearchForm.svelte';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A hotkey trigger as daisyUI `kbd` chips: ⌘ K for `'$mod+k'`, G then P for `['g', 'p']`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
HotkeyBadge — a hotkey trigger rendered as daisyUI `kbd` chips: ⌘ K for
|
|
6
|
+
`'$mod+k'`, G then P for `['g', 'p']`. Used by the command palette's rows
|
|
7
|
+
and by the hotkey help overlay.
|
|
8
|
+
|
|
9
|
+
`$mod` resolves to ⌘ / Ctrl only AFTER hydration. The server cannot know the
|
|
10
|
+
reader's platform, so server-rendered output always shows `controlLabel` and
|
|
11
|
+
a Mac corrects itself on mount; resolving it during render instead would be
|
|
12
|
+
a hydration mismatch on every Mac. That is why `apple` is `$state` written
|
|
13
|
+
from an `$effect` rather than a `$derived`.
|
|
14
|
+
|
|
15
|
+
ARIA contract: the chips are `<kbd>` elements, which is the element for user
|
|
16
|
+
input, and the separator between sequential keys is real text
|
|
17
|
+
(`thenLabel`) — not a bare "→" — so "G then P" is announced as an
|
|
18
|
+
instruction rather than as two loose letters. The badge contributes no name
|
|
19
|
+
of its own: it is read as part of the row it labels.
|
|
20
|
+
-->
|
|
21
|
+
<script lang="ts">import { isApplePlatform, triggerDisplay } from "./match.js";
|
|
22
|
+
let { trigger, commandLabel = "⌘", controlLabel = "Ctrl", thenLabel = "then", class: className, ...rest } = $props();
|
|
23
|
+
const display = $derived(triggerDisplay(trigger));
|
|
24
|
+
// Resolved client-side to avoid an SSR/client hydration mismatch.
|
|
25
|
+
let apple = $state(false);
|
|
26
|
+
$effect(() => {
|
|
27
|
+
apple = isApplePlatform();
|
|
28
|
+
});
|
|
29
|
+
const modLabel = $derived(apple ? commandLabel : controlLabel);
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<span {...rest} class={['inline-flex shrink-0 items-center gap-1', className]}>
|
|
33
|
+
{#each display.keys as key, index (index)}
|
|
34
|
+
{#if index > 0 && display.sequential}
|
|
35
|
+
<span class="text-base-content/50 text-xs">{thenLabel}</span>
|
|
36
|
+
{/if}
|
|
37
|
+
<kbd class="kbd kbd-sm">{key === '$mod' ? modLabel : key}</kbd>
|
|
38
|
+
{/each}
|
|
39
|
+
</span>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
import type { HotkeyTrigger } from './types.ts';
|
|
3
|
+
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
4
|
+
/** The trigger to render — a chord (`'$mod+k'`) or a sequence (`['g','p']`). */
|
|
5
|
+
trigger: HotkeyTrigger;
|
|
6
|
+
/**
|
|
7
|
+
* What `$mod` reads as on Apple platforms.
|
|
8
|
+
* @defaultValue `'⌘'`
|
|
9
|
+
*/
|
|
10
|
+
commandLabel?: string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* What `$mod` reads as everywhere else, and during server rendering.
|
|
13
|
+
* @defaultValue `'Ctrl'`
|
|
14
|
+
*/
|
|
15
|
+
controlLabel?: string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Read between the keys of a sequence.
|
|
18
|
+
* @defaultValue `'then'`
|
|
19
|
+
*/
|
|
20
|
+
thenLabel?: string | undefined;
|
|
21
|
+
}
|
|
22
|
+
/** A hotkey trigger as daisyUI `kbd` chips: ⌘ K for `'$mod+k'`, G then P for `['g', 'p']`. */
|
|
23
|
+
declare const HotkeyBadge: import("svelte").Component<Props, {}, "">;
|
|
24
|
+
type HotkeyBadge = ReturnType<typeof HotkeyBadge>;
|
|
25
|
+
export default HotkeyBadge;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
The `?` overlay listing every hotkey the viewer can press right now, grouped into this page and everywhere.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
HotkeyHelpDialog — the `?` overlay: every hotkey the current viewer can
|
|
6
|
+
press right now, grouped into "This page" and "Everywhere", with
|
|
7
|
+
platform-aware key chips.
|
|
8
|
+
|
|
9
|
+
The list is read live from the registry rather than passed in, so it can
|
|
10
|
+
never drift from what `HotkeyProvider` would actually match: role-gated
|
|
11
|
+
actions are already absent, and a page's registrations disappear with the
|
|
12
|
+
page. Opening and closing is the registry's `helpOpen`, which is what a
|
|
13
|
+
registered action toggles.
|
|
14
|
+
|
|
15
|
+
ARIA contract: it is this library's `Dialog`, so bits-ui owns the modal —
|
|
16
|
+
`aria-modal`, the focus trap, Escape, the focus return — and `title` is the
|
|
17
|
+
dialog's accessible name. Each section is a `<section>` with a heading, and
|
|
18
|
+
each hotkey a list item pairing the action's label with its `HotkeyBadge`,
|
|
19
|
+
so the reading order is "what it does, then what to press".
|
|
20
|
+
-->
|
|
21
|
+
<script lang="ts">import Dialog from "../feedback/Dialog.svelte";
|
|
22
|
+
import { getHotkeyRegistry } from "./context.svelte.js";
|
|
23
|
+
import HotkeyBadge from "./HotkeyBadge.svelte";
|
|
24
|
+
let { title = "Keyboard shortcuts", closeLabel = "Close", emptyLabel = "No keyboard shortcuts are available on this page.", groupLabels = {
|
|
25
|
+
page: "This page",
|
|
26
|
+
global: "Everywhere"
|
|
27
|
+
}, commandLabel, controlLabel, thenLabel } = $props();
|
|
28
|
+
const registry = getHotkeyRegistry();
|
|
29
|
+
const sections = $derived([{
|
|
30
|
+
heading: groupLabels.page,
|
|
31
|
+
entries: registry.hotkeys.filter((entry) => entry.scope === "page")
|
|
32
|
+
}, {
|
|
33
|
+
heading: groupLabels.global,
|
|
34
|
+
entries: registry.hotkeys.filter((entry) => entry.scope === "global")
|
|
35
|
+
}].filter((section) => section.entries.length > 0));
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
{#snippet hotkeyRow(entry: RegisteredAction)}
|
|
39
|
+
<li class="flex items-center justify-between gap-4 py-1.5">
|
|
40
|
+
<span class="text-base-content text-sm">{entry.action.label}</span>
|
|
41
|
+
{#if entry.action.trigger !== undefined}
|
|
42
|
+
<HotkeyBadge trigger={entry.action.trigger} {commandLabel} {controlLabel} {thenLabel} />
|
|
43
|
+
{/if}
|
|
44
|
+
</li>
|
|
45
|
+
{/snippet}
|
|
46
|
+
|
|
47
|
+
<Dialog
|
|
48
|
+
bind:open={() => registry.helpOpen, (open) => (registry.helpOpen = open)}
|
|
49
|
+
{title}
|
|
50
|
+
{closeLabel}
|
|
51
|
+
>
|
|
52
|
+
{#if registry.hotkeys.length === 0}
|
|
53
|
+
<p class="text-base-content/70 text-sm leading-6">{emptyLabel}</p>
|
|
54
|
+
{:else}
|
|
55
|
+
{#each sections as section (section.heading)}
|
|
56
|
+
<section class="mt-4 first:mt-0">
|
|
57
|
+
<h3 class="text-base-content/70 text-xs font-semibold tracking-wide uppercase">
|
|
58
|
+
{section.heading}
|
|
59
|
+
</h3>
|
|
60
|
+
<ul class="divide-base-300 mt-2 divide-y">
|
|
61
|
+
{#each section.entries as entry (entry.action.id)}
|
|
62
|
+
{@render hotkeyRow(entry)}
|
|
63
|
+
{/each}
|
|
64
|
+
</ul>
|
|
65
|
+
</section>
|
|
66
|
+
{/each}
|
|
67
|
+
{/if}
|
|
68
|
+
</Dialog>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
/**
|
|
3
|
+
* The dialog's accessible name.
|
|
4
|
+
* @defaultValue `'Keyboard shortcuts'`
|
|
5
|
+
*/
|
|
6
|
+
title?: string | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* Accessible name of the corner close button.
|
|
9
|
+
* @defaultValue `'Close'`
|
|
10
|
+
*/
|
|
11
|
+
closeLabel?: string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Shown when nothing with a trigger is registered.
|
|
14
|
+
* @defaultValue `'No keyboard shortcuts are available on this page.'`
|
|
15
|
+
*/
|
|
16
|
+
emptyLabel?: string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Section headings, in render order.
|
|
19
|
+
* @defaultValue `{ page: 'This page', global: 'Everywhere' }`
|
|
20
|
+
*/
|
|
21
|
+
groupLabels?: {
|
|
22
|
+
page: string;
|
|
23
|
+
global: string;
|
|
24
|
+
} | undefined;
|
|
25
|
+
/** What `$mod` reads as on Apple platforms. */
|
|
26
|
+
commandLabel?: string | undefined;
|
|
27
|
+
/** What `$mod` reads as everywhere else. */
|
|
28
|
+
controlLabel?: string | undefined;
|
|
29
|
+
/** Read between the keys of a sequence. */
|
|
30
|
+
thenLabel?: string | undefined;
|
|
31
|
+
}
|
|
32
|
+
/** The `?` overlay listing every hotkey the viewer can press right now, grouped into this page and everywhere. */
|
|
33
|
+
declare const HotkeyHelpDialog: import("svelte").Component<Props, {}, "">;
|
|
34
|
+
type HotkeyHelpDialog = ReturnType<typeof HotkeyHelpDialog>;
|
|
35
|
+
export default HotkeyHelpDialog;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
The single global `keydown` listener that drives the hotkey registry; hotkeys never fire while the reader is typing.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
HotkeyProvider — the single global `keydown` listener that drives the hotkey
|
|
6
|
+
registry. Owns the sequence buffer (for `g p`-style triggers) and enforces
|
|
7
|
+
the editable-target guard, so hotkeys never fire while the reader is typing
|
|
8
|
+
in a form field or a rich-text editor.
|
|
9
|
+
|
|
10
|
+
Render once, from the root layout, inside the component that called
|
|
11
|
+
`createHotkeyRegistry()`. It renders nothing.
|
|
12
|
+
|
|
13
|
+
ARIA contract: none of its own — it has no markup. What it owes assistive
|
|
14
|
+
technology is negative: it must never steal a keystroke from a control that
|
|
15
|
+
needs it, which is what the editable-target guard and the
|
|
16
|
+
"`paletteOpen` / `helpOpen` suppress everything but `allowInEditable`" rule
|
|
17
|
+
are for. bits-ui owns keyboard interaction inside its own dialogs.
|
|
18
|
+
|
|
19
|
+
Not on a bits-ui primitive because there is no primitive for this: it is a
|
|
20
|
+
document-level key router over an app-owned registry, not a widget.
|
|
21
|
+
-->
|
|
22
|
+
<script lang="ts">import { getHotkeyRegistry } from "./context.svelte.js";
|
|
23
|
+
import { SEQUENCE_TIMEOUT_MS, hasChordModifier, isEditableTarget, isSequenceKey, matchChord, matchSequence } from "./match.js";
|
|
24
|
+
const registry = getHotkeyRegistry();
|
|
25
|
+
let sequenceBuffer = [];
|
|
26
|
+
let sequenceTimer;
|
|
27
|
+
function clearSequence() {
|
|
28
|
+
sequenceBuffer = [];
|
|
29
|
+
if (sequenceTimer !== undefined) clearTimeout(sequenceTimer);
|
|
30
|
+
sequenceTimer = undefined;
|
|
31
|
+
}
|
|
32
|
+
function armSequenceTimeout() {
|
|
33
|
+
if (sequenceTimer !== undefined) clearTimeout(sequenceTimer);
|
|
34
|
+
sequenceTimer = setTimeout(clearSequence, SEQUENCE_TIMEOUT_MS);
|
|
35
|
+
}
|
|
36
|
+
function activate(action, event) {
|
|
37
|
+
event.preventDefault();
|
|
38
|
+
clearSequence();
|
|
39
|
+
void action.run();
|
|
40
|
+
}
|
|
41
|
+
// The keyboard event router. The chord / sequence / suppression branching is
|
|
42
|
+
// inherently branchy; splitting it would scatter the buffer state machine
|
|
43
|
+
// across helpers and hurt readability more than the branch count does.
|
|
44
|
+
function onKeydown(event) {
|
|
45
|
+
// While a hotkey-owned dialog is open, or focus sits in an editable
|
|
46
|
+
// element, only `allowInEditable` actions (the palette toggle) may fire —
|
|
47
|
+
// bits-ui owns keyboard interaction inside its dialogs, and typing must
|
|
48
|
+
// never trigger actions.
|
|
49
|
+
const suppressed = registry.paletteOpen || registry.helpOpen || isEditableTarget(event.target);
|
|
50
|
+
const actions = suppressed ? registry.active.filter((entry) => entry.action.allowInEditable) : registry.active;
|
|
51
|
+
if (hasChordModifier(event)) {
|
|
52
|
+
const action = matchChord(event, actions);
|
|
53
|
+
if (action !== undefined) activate(action, event);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// Plain keys: ignore non-printable keys (Escape, arrows, bare modifiers,
|
|
57
|
+
// F-keys) entirely — they neither fire nor disturb a pending sequence.
|
|
58
|
+
if (!isSequenceKey(event)) return;
|
|
59
|
+
if (suppressed) {
|
|
60
|
+
clearSequence();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// Try extending the pending sequence first, then restarting from this key
|
|
64
|
+
// alone, so a stray prefix never swallows a fresh trigger.
|
|
65
|
+
let hit;
|
|
66
|
+
for (const candidate of [[...sequenceBuffer, event.key], [event.key]]) {
|
|
67
|
+
const match = matchSequence(candidate, actions);
|
|
68
|
+
if (match.exact !== undefined || match.isPrefix) {
|
|
69
|
+
hit = {
|
|
70
|
+
candidate,
|
|
71
|
+
match
|
|
72
|
+
};
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (hit === undefined) {
|
|
77
|
+
clearSequence();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (hit.match.exact !== undefined) {
|
|
81
|
+
activate(hit.match.exact, event);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
sequenceBuffer = hit.candidate;
|
|
85
|
+
armSequenceTimeout();
|
|
86
|
+
}
|
|
87
|
+
$effect(() => () => {
|
|
88
|
+
if (sequenceTimer !== undefined) clearTimeout(sequenceTimer);
|
|
89
|
+
});
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<svelte:window onkeydown={onKeydown} />
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** The single global `keydown` listener that drives the hotkey registry; hotkeys never fire while the reader is typing. */
|
|
2
|
+
declare const HotkeyProvider: import("svelte").Component<Record<string, never>, {}, "">;
|
|
3
|
+
type HotkeyProvider = ReturnType<typeof HotkeyProvider>;
|
|
4
|
+
export default HotkeyProvider;
|