@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,21 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
import { type ChipSize } from './tones.ts';
|
|
3
|
+
interface Props extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
|
4
|
+
/** The short code shown in the chip. */
|
|
5
|
+
label: string;
|
|
6
|
+
/** The expansion, rendered as the `<abbr>` title. */
|
|
7
|
+
title?: string | undefined;
|
|
8
|
+
/** When set, the chip is a link to the subject's page. */
|
|
9
|
+
href?: string | undefined;
|
|
10
|
+
/** A CSS custom-property name the app's theme declares (`--party-alp`). */
|
|
11
|
+
colourToken?: string | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* daisyUI size step.
|
|
14
|
+
* @defaultValue `'md'`
|
|
15
|
+
*/
|
|
16
|
+
size?: ChipSize | undefined;
|
|
17
|
+
}
|
|
18
|
+
/** A colour swatch beside a short code, for legends, result rows and filter lists. */
|
|
19
|
+
declare const Chip: import("svelte").Component<Props, {}, "">;
|
|
20
|
+
type Chip = ReturnType<typeof Chip>;
|
|
21
|
+
export default Chip;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A destructive action behind a two-step inline confirmation.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
ConfirmButton — a destructive action behind a two-step inline confirm.
|
|
6
|
+
|
|
7
|
+
Inline rather than a dialog, deliberately: the confirmation replaces the
|
|
8
|
+
button in place, so nothing is torn out of the reading order, focus is not
|
|
9
|
+
trapped, and the page behind it does not need an overlay. Use
|
|
10
|
+
`ConfirmDialog` instead when the confirmation itself needs to carry content
|
|
11
|
+
(a form, a list of what will be destroyed).
|
|
12
|
+
|
|
13
|
+
ARIA contract: the failure surface is an `Alert` with `live="assertive"` —
|
|
14
|
+
the reader pressed a button and nothing visible happened, so the reason has
|
|
15
|
+
to interrupt. Both buttons are `disabled` while the action is in flight, and
|
|
16
|
+
the confirm button swaps its text to `pendingLabel` rather than emptying
|
|
17
|
+
itself, so its accessible name never disappears mid-press.
|
|
18
|
+
|
|
19
|
+
`action` is a plain promise-returning prop — no Effect in this library. A
|
|
20
|
+
rejection with an `Error` shows that error's message (the caller's own
|
|
21
|
+
wording, usually from the server); anything else shows `failureMessage`.
|
|
22
|
+
On success, `redirectTo` navigates through the components context, so an
|
|
23
|
+
app gets client-side routing and this component stays ignorant of it.
|
|
24
|
+
-->
|
|
25
|
+
<script lang="ts">import { getComponentsContext } from "../context.svelte.js";
|
|
26
|
+
import Alert from "./Alert.svelte";
|
|
27
|
+
import Button from "./Button.svelte";
|
|
28
|
+
let { action, idleLabel = "Delete", confirmLabel = "Confirm", cancelLabel = "Cancel", pendingLabel = "Working…", confirmMessage = "Are you sure? This cannot be undone.", failureMessage = "That didn’t work. Try again.", tone = "error", redirectTo, class: className } = $props();
|
|
29
|
+
const context = getComponentsContext();
|
|
30
|
+
let confirming = $state(false);
|
|
31
|
+
let pending = $state(false);
|
|
32
|
+
let errorMessage = $state(undefined);
|
|
33
|
+
const beginConfirmation = () => {
|
|
34
|
+
errorMessage = undefined;
|
|
35
|
+
confirming = true;
|
|
36
|
+
};
|
|
37
|
+
const cancelConfirmation = () => {
|
|
38
|
+
if (pending) return;
|
|
39
|
+
errorMessage = undefined;
|
|
40
|
+
confirming = false;
|
|
41
|
+
};
|
|
42
|
+
const confirmAction = async () => {
|
|
43
|
+
pending = true;
|
|
44
|
+
errorMessage = undefined;
|
|
45
|
+
try {
|
|
46
|
+
await action();
|
|
47
|
+
confirming = false;
|
|
48
|
+
if (redirectTo !== undefined) await context.navigate(context.href(redirectTo));
|
|
49
|
+
} catch (error) {
|
|
50
|
+
errorMessage = error instanceof Error ? error.message : failureMessage;
|
|
51
|
+
} finally {
|
|
52
|
+
pending = false;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<div class={['space-y-2', className]}>
|
|
58
|
+
{#if confirming}
|
|
59
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
60
|
+
<p class="text-sm">{confirmMessage}</p>
|
|
61
|
+
<Button {tone} disabled={pending} loading={pending} onclick={confirmAction}>
|
|
62
|
+
{pending ? pendingLabel : confirmLabel}
|
|
63
|
+
</Button>
|
|
64
|
+
<Button variant="ghost" disabled={pending} onclick={cancelConfirmation}>
|
|
65
|
+
{cancelLabel}
|
|
66
|
+
</Button>
|
|
67
|
+
</div>
|
|
68
|
+
{:else}
|
|
69
|
+
<Button {tone} onclick={beginConfirmation}>{idleLabel}</Button>
|
|
70
|
+
{/if}
|
|
71
|
+
|
|
72
|
+
{#if errorMessage !== undefined}
|
|
73
|
+
<Alert tone="error" live="assertive">{errorMessage}</Alert>
|
|
74
|
+
{/if}
|
|
75
|
+
</div>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Tone } from './tones.ts';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** The destructive action itself. */
|
|
4
|
+
action: () => Promise<unknown>;
|
|
5
|
+
/**
|
|
6
|
+
* The resting button's text.
|
|
7
|
+
* @defaultValue `'Delete'`
|
|
8
|
+
*/
|
|
9
|
+
idleLabel?: string | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* The confirm button's text.
|
|
12
|
+
* @defaultValue `'Confirm'`
|
|
13
|
+
*/
|
|
14
|
+
confirmLabel?: string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* The cancel button's text.
|
|
17
|
+
* @defaultValue `'Cancel'`
|
|
18
|
+
*/
|
|
19
|
+
cancelLabel?: string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* The confirm button's text while the action is in flight.
|
|
22
|
+
* @defaultValue `'Working…'`
|
|
23
|
+
*/
|
|
24
|
+
pendingLabel?: string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* The question shown beside the confirm and cancel buttons.
|
|
27
|
+
* @defaultValue `'Are you sure? This cannot be undone.'`
|
|
28
|
+
*/
|
|
29
|
+
confirmMessage?: string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Shown when the action rejects with something that is not an `Error`.
|
|
32
|
+
* @defaultValue `'That didn’t work. Try again.'`
|
|
33
|
+
*/
|
|
34
|
+
failureMessage?: string | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Tone of the idle and confirm buttons.
|
|
37
|
+
* @defaultValue `'error'`
|
|
38
|
+
*/
|
|
39
|
+
tone?: Tone | undefined;
|
|
40
|
+
/** Navigated to through the components context once `action` resolves. */
|
|
41
|
+
redirectTo?: string | undefined;
|
|
42
|
+
/** Extra classes, merged last. */
|
|
43
|
+
class?: string | undefined;
|
|
44
|
+
}
|
|
45
|
+
/** A destructive action behind a two-step inline confirmation. */
|
|
46
|
+
declare const ConfirmButton: import("svelte").Component<Props, {}, "">;
|
|
47
|
+
type ConfirmButton = ReturnType<typeof ConfirmButton>;
|
|
48
|
+
export default ConfirmButton;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A menu that opens at the pointer on a right-click (or long-press) of a region, on bits-ui's `ContextMenu`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
ContextMenu — the actions for one thing (a row in a list, a node on a
|
|
6
|
+
canvas, an image), opened where the reader right-clicks it, long-presses it
|
|
7
|
+
on touch, or presses Shift+F10 / the Menu key while it has focus. Built on
|
|
8
|
+
bits-ui's `ContextMenu`, which owns the menu at the pointer, roving focus,
|
|
9
|
+
typeahead, → / ← for submenus, Escape and outside click to close, and focus
|
|
10
|
+
return. Its children are the same `MenuItem`, `MenuSeparator`,
|
|
11
|
+
`MenuCheckboxItem`, `MenuRadioGroup` / `MenuRadioItem` and `MenuSub` that a
|
|
12
|
+
`DropdownMenu` takes; this component lends them the bits-ui parts through
|
|
13
|
+
context (`menu-parts/`).
|
|
14
|
+
|
|
15
|
+
Never the only route to an action. A context menu is invisible until it is
|
|
16
|
+
summoned, and touch screen-reader users (and many keyboard users) never
|
|
17
|
+
discover it. Put every action somewhere visible too: a row's "More"
|
|
18
|
+
`DropdownMenu`, a toolbar.
|
|
19
|
+
|
|
20
|
+
The region is the caller's own element: the `trigger` snippet receives
|
|
21
|
+
`props` to spread onto it. Those props make it focusable (`tabindex="0"`,
|
|
22
|
+
which a natively focusable element does not mind; pass a `tabindex` of your
|
|
23
|
+
own after the spread to override it), because browsers fire `contextmenu`
|
|
24
|
+
for the keyboard only on the focused element. Shift+F10 and the Menu key
|
|
25
|
+
are handled here rather than left to the browser, so they open the menu at
|
|
26
|
+
the region's corner the same way everywhere.
|
|
27
|
+
|
|
28
|
+
ARIA contract: the content is `role="menu"` named by `label`; the daisyUI
|
|
29
|
+
`menu` `<ul>` and its `<li>`s are `role="none"`, exactly as in
|
|
30
|
+
`DropdownMenu`, so `role="menu"` owns its items. `disabled` lets the
|
|
31
|
+
browser's own context menu show instead.
|
|
32
|
+
|
|
33
|
+
Not part of the root barrel: it is its own entry,
|
|
34
|
+
`@thomasfosterau/components/context-menu`, so the menu runtime loads only on
|
|
35
|
+
the pages that use it.
|
|
36
|
+
-->
|
|
37
|
+
<script lang="ts">import { ContextMenu } from "bits-ui";
|
|
38
|
+
import { menuParts } from "./menu-parts/parts.js";
|
|
39
|
+
import { setMenuParts } from "./menu-parts/menu-parts.js";
|
|
40
|
+
let { label, open = $bindable(false), disabled = false, class: className, trigger, children } = $props();
|
|
41
|
+
setMenuParts(menuParts("context"));
|
|
42
|
+
// Shift+F10 and the Menu key: open at the region's bottom-left corner by
|
|
43
|
+
// dispatching the `contextmenu` event bits-ui's trigger listens for.
|
|
44
|
+
// `preventDefault` stops the browser from generating its own as well.
|
|
45
|
+
const openFromKeyboard = (event) => {
|
|
46
|
+
if (disabled) return;
|
|
47
|
+
const isMenuKey = event.key === "ContextMenu" || event.shiftKey && event.key === "F10";
|
|
48
|
+
if (!isMenuKey) return;
|
|
49
|
+
event.preventDefault();
|
|
50
|
+
const region = event.currentTarget;
|
|
51
|
+
if (!(region instanceof HTMLElement)) return;
|
|
52
|
+
const rect = region.getBoundingClientRect();
|
|
53
|
+
region.dispatchEvent(new MouseEvent("contextmenu", {
|
|
54
|
+
bubbles: true,
|
|
55
|
+
cancelable: true,
|
|
56
|
+
clientX: rect.left,
|
|
57
|
+
clientY: rect.bottom
|
|
58
|
+
}));
|
|
59
|
+
};
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<ContextMenu.Root bind:open>
|
|
63
|
+
<ContextMenu.Trigger {disabled} tabindex={0} onkeydown={openFromKeyboard}>
|
|
64
|
+
{#snippet child({ props })}
|
|
65
|
+
{@render trigger({ props })}
|
|
66
|
+
{/snippet}
|
|
67
|
+
</ContextMenu.Trigger>
|
|
68
|
+
<ContextMenu.Portal>
|
|
69
|
+
<ContextMenu.Content aria-label={label} class="z-50">
|
|
70
|
+
<ul role="none" class={['menu bg-base-100 rounded-box w-56 p-2 shadow-md', className]}>
|
|
71
|
+
{@render children()}
|
|
72
|
+
</ul>
|
|
73
|
+
</ContextMenu.Content>
|
|
74
|
+
</ContextMenu.Portal>
|
|
75
|
+
</ContextMenu.Root>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ContextMenu } from 'bits-ui';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
interface Props {
|
|
4
|
+
/** Accessible name of the open menu ("Actions for Rosa canina"). */
|
|
5
|
+
label: string;
|
|
6
|
+
/** Whether the menu is open. Bindable. */
|
|
7
|
+
open?: boolean | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Turn the menu off; the browser's own context menu shows instead.
|
|
10
|
+
* @defaultValue `false`
|
|
11
|
+
*/
|
|
12
|
+
disabled?: boolean | undefined;
|
|
13
|
+
/** Extra classes on the `<ul class="menu">`. */
|
|
14
|
+
class?: string | undefined;
|
|
15
|
+
/** The region the menu belongs to — the caller's own element, spreading `props`. */
|
|
16
|
+
trigger: Snippet<[{
|
|
17
|
+
props: Record<string, unknown>;
|
|
18
|
+
}]>;
|
|
19
|
+
/** The menu's items. */
|
|
20
|
+
children: Snippet<[]>;
|
|
21
|
+
}
|
|
22
|
+
/** A menu that opens at the pointer on a right-click (or long-press) of a region, on bits-ui's `ContextMenu`. */
|
|
23
|
+
declare const ContextMenu: import("svelte").Component<Props, {}, "open">;
|
|
24
|
+
type ContextMenu = ReturnType<typeof ContextMenu>;
|
|
25
|
+
export default ContextMenu;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A native `<details>` wearing daisyUI’s `collapse`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
Disclosure — a native `<details>` wearing daisyUI's `collapse`.
|
|
6
|
+
|
|
7
|
+
Hand-rolled disclosure is one of the most commonly broken widgets on the
|
|
8
|
+
web, and it does not need to be built: `<details>`/`<summary>` already give
|
|
9
|
+
a focusable trigger, the expanded/collapsed state, keyboard activation and
|
|
10
|
+
— on a modern browser — find-in-page inside the collapsed content, which no
|
|
11
|
+
JavaScript implementation matches. So this is NOT on bits-ui: there is
|
|
12
|
+
nothing for a primitive to add.
|
|
13
|
+
|
|
14
|
+
ARIA contract: the platform's. `<summary>` is the button, `open` is the
|
|
15
|
+
state, and no `aria-expanded` is written by hand (the browser maps it, and
|
|
16
|
+
a second copy can only be wrong). `open` is bindable, so a caller can drive
|
|
17
|
+
the state, and the four apps' "open this section because its form failed"
|
|
18
|
+
case is a one-line binding.
|
|
19
|
+
|
|
20
|
+
Exclusive groups are native too: give several `Disclosure`s the same
|
|
21
|
+
`name` (spread onto `<details>`) and the browser keeps at most one open.
|
|
22
|
+
What a `Disclosure` cannot carry is a heading, because `<summary>`'s
|
|
23
|
+
children are presentational, so a heading inside it drops out of the
|
|
24
|
+
heading tree. For a stack of headed sections, or a bindable "which one is
|
|
25
|
+
open", use `Accordion`.
|
|
26
|
+
-->
|
|
27
|
+
<script lang="ts">import { collapseVariant } from "./tones.js";
|
|
28
|
+
let { open = $bindable(false), title, variant = "arrow", contentClass, children, class: className, ...rest } = $props();
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<details
|
|
32
|
+
{...rest}
|
|
33
|
+
bind:open
|
|
34
|
+
class={['collapse border-base-300 bg-base-100 border', collapseVariant[variant], className]}
|
|
35
|
+
>
|
|
36
|
+
<summary class="collapse-title font-medium">
|
|
37
|
+
{#if typeof title === 'string'}
|
|
38
|
+
{title}
|
|
39
|
+
{:else}
|
|
40
|
+
{@render title()}
|
|
41
|
+
{/if}
|
|
42
|
+
</summary>
|
|
43
|
+
<div class={['collapse-content', contentClass]}>
|
|
44
|
+
{@render children()}
|
|
45
|
+
</div>
|
|
46
|
+
</details>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLDetailsAttributes } from 'svelte/elements';
|
|
3
|
+
import { type DisclosureVariant } from './tones.ts';
|
|
4
|
+
interface Props extends Omit<HTMLDetailsAttributes, 'title' | 'open'> {
|
|
5
|
+
/** Whether the section is expanded. Bindable. */
|
|
6
|
+
open?: boolean | undefined;
|
|
7
|
+
/** The summary — its own text, or a snippet for richer markup. */
|
|
8
|
+
title: string | Snippet<[]>;
|
|
9
|
+
/**
|
|
10
|
+
* The expand indicator: an arrow, a plus, or none.
|
|
11
|
+
* @defaultValue `'arrow'`
|
|
12
|
+
*/
|
|
13
|
+
variant?: DisclosureVariant | undefined;
|
|
14
|
+
/** Extra classes on the `collapse-content` wrapper. */
|
|
15
|
+
contentClass?: string | undefined;
|
|
16
|
+
/** The content revealed when open. */
|
|
17
|
+
children: Snippet<[]>;
|
|
18
|
+
}
|
|
19
|
+
/** A native `<details>` wearing daisyUI’s `collapse`. */
|
|
20
|
+
declare const Disclosure: import("svelte").Component<Props, {}, "open">;
|
|
21
|
+
type Disclosure = ReturnType<typeof Disclosure>;
|
|
22
|
+
export default Disclosure;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A horizontal or vertical rule between content, optionally labelled ("or"), in daisyUI's `divider` styles.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
Divider — a rule between sections or side-by-side items, optionally with a
|
|
6
|
+
short label on it ("or" between two sign-in methods).
|
|
7
|
+
|
|
8
|
+
Hand-rolled, not on bits-ui's `Separator` (AGENTS.md asks for the reason):
|
|
9
|
+
that primitive's whole contribution is `role="separator"` +
|
|
10
|
+
`aria-orientation`, or `role="none"` when decorative — two attributes,
|
|
11
|
+
written here directly, with no bits-ui on the always-loaded path.
|
|
12
|
+
|
|
13
|
+
ARIA contract:
|
|
14
|
+
- Unlabelled: `role="separator"`; vertical adds
|
|
15
|
+
`aria-orientation="vertical"` (horizontal is the implicit default). It
|
|
16
|
+
is a `<div>`, not a native `<hr>`, because daisyUI draws the rule with
|
|
17
|
+
`::before` / `::after`, which a void `<hr>` cannot render.
|
|
18
|
+
- Labelled: NOT a separator. A non-focusable separator's children are
|
|
19
|
+
presentational, so the label would be lost to assistive technology. The
|
|
20
|
+
wrapper is `role="none"` and the text reads in flow — "Sign in with a
|
|
21
|
+
passkey / or / Continue with email" (WAI-ARIA 1.2, separator).
|
|
22
|
+
- `decorative`: `aria-hidden="true"`, nothing announced.
|
|
23
|
+
|
|
24
|
+
Not `MenuSeparator`, which must be an `<li>` inside a menu and defers to
|
|
25
|
+
bits-ui's menu separator for roving focus; use that one inside `Menu`.
|
|
26
|
+
-->
|
|
27
|
+
<script lang="ts">import { dividerAlign, dividerOrientation, dividerTone } from "./tones.js";
|
|
28
|
+
let { orientation = "horizontal", decorative = false, align = "center", tone, children, class: className, ...rest } = $props();
|
|
29
|
+
const classes = $derived([
|
|
30
|
+
"divider",
|
|
31
|
+
dividerOrientation[orientation],
|
|
32
|
+
dividerAlign[align],
|
|
33
|
+
tone !== undefined && dividerTone[tone],
|
|
34
|
+
className
|
|
35
|
+
]);
|
|
36
|
+
const role = $derived(decorative || children !== undefined ? "none" : "separator");
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<div
|
|
40
|
+
{...rest}
|
|
41
|
+
{role}
|
|
42
|
+
aria-orientation={role === 'separator' && orientation === 'vertical' ? 'vertical' : undefined}
|
|
43
|
+
aria-hidden={decorative ? 'true' : undefined}
|
|
44
|
+
class={classes}
|
|
45
|
+
>
|
|
46
|
+
{#if children}<span>{@render children()}</span>{/if}
|
|
47
|
+
</div>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { type DividerAlign, type Tone } from './tones.ts';
|
|
4
|
+
interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
5
|
+
/**
|
|
6
|
+
* Which way the rule runs: `vertical` sits between side-by-side items.
|
|
7
|
+
* @defaultValue `'horizontal'`
|
|
8
|
+
*/
|
|
9
|
+
orientation?: 'horizontal' | 'vertical' | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* The rule marks no real boundary: hide it from assistive technology.
|
|
12
|
+
* @defaultValue `false`
|
|
13
|
+
*/
|
|
14
|
+
decorative?: boolean | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Where a label sits along the rule.
|
|
17
|
+
* @defaultValue `'center'`
|
|
18
|
+
*/
|
|
19
|
+
align?: DividerAlign | undefined;
|
|
20
|
+
/** Semantic colour of the rule. */
|
|
21
|
+
tone?: Tone | undefined;
|
|
22
|
+
/** Short text on the rule ("or"). */
|
|
23
|
+
children?: Snippet<[]> | undefined;
|
|
24
|
+
}
|
|
25
|
+
/** A horizontal or vertical rule between content, optionally labelled ("or"), in daisyUI's `divider` styles. */
|
|
26
|
+
declare const Divider: import("svelte").Component<Props, {}, "">;
|
|
27
|
+
type Divider = ReturnType<typeof Divider>;
|
|
28
|
+
export default Divider;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
An application menu behind a trigger — a bits-ui dropdown of `MenuItem`s styled as a daisyUI `menu`.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
DropdownMenu — an application menu: bits-ui's `DropdownMenu`, which owns
|
|
6
|
+
`aria-haspopup`/`aria-expanded` on the trigger, arrow-key roving focus,
|
|
7
|
+
typeahead, Escape to close and focus return. The daisyUI `menu` styling is
|
|
8
|
+
applied to a `<ul>` INSIDE the content; that list and its items' `<li>`
|
|
9
|
+
wrappers carry `role="none"` so the presentation layer does not come
|
|
10
|
+
between `role="menu"` and its `role="menuitem"` children in the
|
|
11
|
+
accessibility tree.
|
|
12
|
+
|
|
13
|
+
It is a separate component from `Menu` (site navigation) so that bits-ui's
|
|
14
|
+
dropdown runtime is reached only by an app that actually renders a
|
|
15
|
+
dropdown: `Menu`, `MenuItem`, `MenuSeparator` and `Sidebar` import nothing
|
|
16
|
+
from bits-ui (#129). The children are the same `MenuItem` /
|
|
17
|
+
`MenuSeparator` a `Menu` takes; this component lends them its bits-ui item
|
|
18
|
+
and separator parts through context (`menu-parts/menu-parts.ts`), and
|
|
19
|
+
the same for `MenuCheckboxItem`, `MenuRadioGroup`, `MenuRadioItem` and
|
|
20
|
+
`MenuSub`.
|
|
21
|
+
-->
|
|
22
|
+
<script lang="ts">import { DropdownMenu } from "bits-ui";
|
|
23
|
+
import { menuParts } from "./menu-parts/parts.js";
|
|
24
|
+
import { setMenuParts } from "./menu-parts/menu-parts.js";
|
|
25
|
+
let { label, open = $bindable(false), side = "bottom", align = "end", class: className, trigger, children } = $props();
|
|
26
|
+
setMenuParts(menuParts("dropdown"));
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<DropdownMenu.Root bind:open>
|
|
30
|
+
{#if trigger}
|
|
31
|
+
<DropdownMenu.Trigger>
|
|
32
|
+
{#snippet child({ props })}
|
|
33
|
+
{@render trigger({ props })}
|
|
34
|
+
{/snippet}
|
|
35
|
+
</DropdownMenu.Trigger>
|
|
36
|
+
{/if}
|
|
37
|
+
<DropdownMenu.Portal>
|
|
38
|
+
<DropdownMenu.Content {side} {align} sideOffset={8} aria-label={label} class="z-50">
|
|
39
|
+
<ul role="none" class={['menu bg-base-100 rounded-box w-56 p-2 shadow-md', className]}>
|
|
40
|
+
{@render children()}
|
|
41
|
+
</ul>
|
|
42
|
+
</DropdownMenu.Content>
|
|
43
|
+
</DropdownMenu.Portal>
|
|
44
|
+
</DropdownMenu.Root>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { DropdownMenu } from 'bits-ui';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
interface Props {
|
|
4
|
+
/** Accessible name of the open menu. */
|
|
5
|
+
label: string;
|
|
6
|
+
/** Whether the menu is open. Bindable. */
|
|
7
|
+
open?: boolean | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Which side of the trigger the menu opens on.
|
|
10
|
+
* @defaultValue `'bottom'`
|
|
11
|
+
*/
|
|
12
|
+
side?: 'top' | 'right' | 'bottom' | 'left' | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Alignment against the trigger.
|
|
15
|
+
* @defaultValue `'end'`
|
|
16
|
+
*/
|
|
17
|
+
align?: 'start' | 'center' | 'end' | undefined;
|
|
18
|
+
/** Extra classes on the `<ul class="menu">`. */
|
|
19
|
+
class?: string | undefined;
|
|
20
|
+
/** The trigger — the caller's own element, spreading `props`. */
|
|
21
|
+
trigger?: Snippet<[{
|
|
22
|
+
props: Record<string, unknown>;
|
|
23
|
+
}]> | undefined;
|
|
24
|
+
/** The `MenuItem`s. */
|
|
25
|
+
children: Snippet<[]>;
|
|
26
|
+
}
|
|
27
|
+
/** An application menu behind a trigger — a bits-ui dropdown of `MenuItem`s styled as a daisyUI `menu`. */
|
|
28
|
+
declare const DropdownMenu: import("svelte").Component<Props, {}, "open">;
|
|
29
|
+
type DropdownMenu = ReturnType<typeof DropdownMenu>;
|
|
30
|
+
export default DropdownMenu;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
The quiet card an index or result list shows instead of a bare empty list: a heading, optional copy, icon and call to action.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
EmptyState — the quiet card an index or a result list shows instead of a
|
|
6
|
+
bare empty `<ul>`: a heading, optional supporting copy, an optional icon
|
|
7
|
+
above and an optional call to action below.
|
|
8
|
+
|
|
9
|
+
Content-first, not a hero. "Nothing here" is a normal state of a healthy
|
|
10
|
+
page, and the surface it is drawn on is the same `Card` every other block
|
|
11
|
+
on the page uses, so an empty list does not look like a failure.
|
|
12
|
+
|
|
13
|
+
ARIA contract: `title` is a real heading at `headingLevel` (`h2` by
|
|
14
|
+
default), so a reader navigating by headings finds out the section is empty
|
|
15
|
+
instead of finding nothing at all. The icon is decorative and hidden.
|
|
16
|
+
-->
|
|
17
|
+
<script lang="ts">import Card from "./Card.svelte";
|
|
18
|
+
let { title, description, headingLevel = 2, icon, action, class: className, ...rest } = $props();
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<Card
|
|
22
|
+
{...rest}
|
|
23
|
+
as="div"
|
|
24
|
+
class={className}
|
|
25
|
+
bodyClass="items-center gap-2 p-8 text-center sm:p-10"
|
|
26
|
+
>
|
|
27
|
+
{#if icon}
|
|
28
|
+
<div class="text-base-content/50 mb-2" aria-hidden="true">{@render icon()}</div>
|
|
29
|
+
{/if}
|
|
30
|
+
<svelte:element this={`h${headingLevel}`} class="text-2xl font-semibold">{title}</svelte:element>
|
|
31
|
+
{#if description !== undefined}
|
|
32
|
+
<p class="text-base-content/70 max-w-prose leading-7">{description}</p>
|
|
33
|
+
{/if}
|
|
34
|
+
{#if action}
|
|
35
|
+
<div class="mt-2">{@render action()}</div>
|
|
36
|
+
{/if}
|
|
37
|
+
</Card>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import type { HeadingLevel } from './tones.ts';
|
|
4
|
+
interface Props extends HTMLAttributes<HTMLElement> {
|
|
5
|
+
/** Short, direct heading for the empty surface ("No results yet"). */
|
|
6
|
+
title: string;
|
|
7
|
+
/** Supporting copy explaining the state or the next step. */
|
|
8
|
+
description?: string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* The heading level, so the page outline stays intact.
|
|
11
|
+
* @defaultValue `2`
|
|
12
|
+
*/
|
|
13
|
+
headingLevel?: HeadingLevel | undefined;
|
|
14
|
+
/** Decorative icon rendered above the heading. */
|
|
15
|
+
icon?: Snippet<[]> | undefined;
|
|
16
|
+
/** Call to action — a button or a link — rendered under the copy. */
|
|
17
|
+
action?: Snippet<[]> | undefined;
|
|
18
|
+
}
|
|
19
|
+
/** The quiet card an index or result list shows instead of a bare empty list: a heading, optional copy, icon and call to action. */
|
|
20
|
+
declare const EmptyState: import("svelte").Component<Props, {}, "">;
|
|
21
|
+
type EmptyState = ReturnType<typeof EmptyState>;
|
|
22
|
+
export default EmptyState;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A link off the site that opens in a new tab with the right `rel`, and says so to assistive technology.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
ExternalLink — a link off the site, with the `rel` decision made for the
|
|
6
|
+
call site.
|
|
7
|
+
|
|
8
|
+
The `rel` is the reason this is a component and not four lines of markup.
|
|
9
|
+
An address a member typed into their own profile is untrusted outbound
|
|
10
|
+
linkage and carries `nofollow`; a resolver URL the site itself composed
|
|
11
|
+
from a recorded identifier (an ORCID, a DOI) is not, and carries only
|
|
12
|
+
`noreferrer`. The distinction is invisible when it is wrong, which is
|
|
13
|
+
exactly the kind of thing that should not be retyped per page. Hence
|
|
14
|
+
`untrusted` defaults to `true`: the safe answer is the one you get by not
|
|
15
|
+
thinking about it.
|
|
16
|
+
|
|
17
|
+
ARIA contract: `target="_blank"` always pairs with `noreferrer`, and the
|
|
18
|
+
new tab is ANNOUNCED — a visually hidden "(opens in a new tab)" after the
|
|
19
|
+
text, so a screen-reader user learns what a sighted user learns from the
|
|
20
|
+
icon. The icon itself is `aria-hidden`; it says nothing the text does not.
|
|
21
|
+
-->
|
|
22
|
+
<script lang="ts">import { ExternalLink as ExternalLinkIcon } from "@lucide/svelte";
|
|
23
|
+
import { linkVariant } from "./tones.js";
|
|
24
|
+
import VisuallyHidden from "./VisuallyHidden.svelte";
|
|
25
|
+
let { href, variant = "muted", untrusted = true, showIcon = true, newTabLabel = "(opens in a new tab)", children, class: className, ...rest } = $props();
|
|
26
|
+
</script>
|
|
27
|
+
|
|
28
|
+
<a
|
|
29
|
+
{...rest}
|
|
30
|
+
{href}
|
|
31
|
+
target="_blank"
|
|
32
|
+
rel={untrusted ? 'noreferrer nofollow' : 'noreferrer'}
|
|
33
|
+
class={['inline-flex items-center gap-1', linkVariant[variant], className]}
|
|
34
|
+
>
|
|
35
|
+
{@render children()}
|
|
36
|
+
<VisuallyHidden>{newTabLabel}</VisuallyHidden>
|
|
37
|
+
{#if showIcon}<ExternalLinkIcon class="size-3.5 shrink-0" aria-hidden="true" />{/if}
|
|
38
|
+
</a>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAnchorAttributes } from 'svelte/elements';
|
|
3
|
+
import { type LinkVariant } from './tones.ts';
|
|
4
|
+
interface Props extends Omit<HTMLAnchorAttributes, 'href'> {
|
|
5
|
+
/** The absolute URL. */
|
|
6
|
+
href: string;
|
|
7
|
+
/**
|
|
8
|
+
* The link weight.
|
|
9
|
+
* @defaultValue `'muted'`
|
|
10
|
+
*/
|
|
11
|
+
variant?: LinkVariant | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Whether the destination is user-supplied. `true` (the default) adds
|
|
14
|
+
* `nofollow`; pass `false` only for an address this site composed itself.
|
|
15
|
+
* @defaultValue `true`
|
|
16
|
+
*/
|
|
17
|
+
untrusted?: boolean | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Show the trailing new-tab icon.
|
|
20
|
+
* @defaultValue `true`
|
|
21
|
+
*/
|
|
22
|
+
showIcon?: boolean | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* The announcement appended to the link text, for assistive technology.
|
|
25
|
+
* @defaultValue `'(opens in a new tab)'`
|
|
26
|
+
*/
|
|
27
|
+
newTabLabel?: string | undefined;
|
|
28
|
+
/** The link text; the new-tab notice is appended for assistive technology. */
|
|
29
|
+
children: Snippet<[]>;
|
|
30
|
+
}
|
|
31
|
+
/** A link off the site that opens in a new tab with the right `rel`, and says so to assistive technology. */
|
|
32
|
+
declare const ExternalLink: import("svelte").Component<Props, {}, "">;
|
|
33
|
+
type ExternalLink = ReturnType<typeof ExternalLink>;
|
|
34
|
+
export default ExternalLink;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A heading at any level with a stable `id`, optionally with a copyable anchor link.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
Heading — a section heading at any level, with a stable `id` so the section
|
|
6
|
+
is addressable: a table of contents, a "copy link to this section" anchor,
|
|
7
|
+
a URL fragment someone pasted into a message.
|
|
8
|
+
|
|
9
|
+
ARIA contract: a real `<h1>`–`<h6>` at the level the caller names. The level
|
|
10
|
+
is a PROP and not a consequence of the styling, because the outline is a
|
|
11
|
+
document structure and the type scale is a visual one; `class` overrides the
|
|
12
|
+
latter without touching the former. `scroll-mt` keeps a hash target clear of
|
|
13
|
+
a sticky header. The anchor link, when shown, has a real accessible name
|
|
14
|
+
(`anchorLabel`); the `#` glyph beside it is decorative.
|
|
15
|
+
|
|
16
|
+
The id is derived from `children` AT RENDER when `children` is a string —
|
|
17
|
+
not measured from the mounted element in an `$effect`, which is how the
|
|
18
|
+
original did it and which means the server renders a heading with
|
|
19
|
+
no id at all and every in-page link is dead until hydration. A snippet's
|
|
20
|
+
text is not knowable before render, so a snippet heading that wants an
|
|
21
|
+
anchor must be given an explicit `id`; without one the anchor is omitted
|
|
22
|
+
rather than pointing at nothing.
|
|
23
|
+
-->
|
|
24
|
+
<script lang="ts">import { slugify } from "./slug.js";
|
|
25
|
+
import VisuallyHidden from "./VisuallyHidden.svelte";
|
|
26
|
+
let { level, id, anchor = false, anchorLabel = "Link to this section", children, class: className, ...rest } = $props();
|
|
27
|
+
const headingId = $derived(id ?? (typeof children === "string" ? slugify(children) : undefined));
|
|
28
|
+
const levelClasses = {
|
|
29
|
+
1: "mt-8 mb-6 text-3xl sm:text-4xl",
|
|
30
|
+
2: "mt-6 mb-4 text-2xl sm:text-3xl",
|
|
31
|
+
3: "mt-5 mb-3 text-xl sm:text-2xl",
|
|
32
|
+
4: "mt-4 mb-3 text-lg sm:text-xl",
|
|
33
|
+
5: "mt-4 mb-2 text-base sm:text-lg",
|
|
34
|
+
6: "mt-3 mb-2 text-sm sm:text-base"
|
|
35
|
+
};
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<svelte:element
|
|
39
|
+
this={`h${level}`}
|
|
40
|
+
{...rest}
|
|
41
|
+
id={headingId}
|
|
42
|
+
class={['group scroll-mt-16 font-bold', levelClasses[level], className]}
|
|
43
|
+
>
|
|
44
|
+
{#if typeof children === 'string'}
|
|
45
|
+
{children}
|
|
46
|
+
{:else}
|
|
47
|
+
{@render children()}
|
|
48
|
+
{/if}
|
|
49
|
+
{#if anchor && headingId !== undefined}
|
|
50
|
+
<a
|
|
51
|
+
href={`#${headingId}`}
|
|
52
|
+
class="link link-hover text-base-content/40 ml-2 opacity-0 transition-opacity focus:opacity-100 group-hover:opacity-100"
|
|
53
|
+
>
|
|
54
|
+
<span aria-hidden="true">#</span>
|
|
55
|
+
<VisuallyHidden>{anchorLabel}</VisuallyHidden>
|
|
56
|
+
</a>
|
|
57
|
+
{/if}
|
|
58
|
+
</svelte:element>
|