@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,86 @@
|
|
|
1
|
+
import { type OgImageCard } from './og-image.ts';
|
|
2
|
+
import type { AlternateLink, FeedLink, HeadImage, OpenGraphType, Robots, SchemaPageType, TwitterCard } from './types.ts';
|
|
3
|
+
interface Props {
|
|
4
|
+
/** The page title. Blank renders `siteName` alone. */
|
|
5
|
+
title: string;
|
|
6
|
+
/** Appended to every title as `"<title><titleSeparator><siteName>"`, and emitted as `og:site_name`. */
|
|
7
|
+
siteName?: string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Between the title and `siteName`.
|
|
10
|
+
* @defaultValue `' | '`
|
|
11
|
+
*/
|
|
12
|
+
titleSeparator?: string | undefined;
|
|
13
|
+
/** Meta and Open Graph description. */
|
|
14
|
+
description?: string | null | undefined;
|
|
15
|
+
/** Meta keywords. */
|
|
16
|
+
keywords?: readonly string[] | undefined;
|
|
17
|
+
/** The Schema.org page type — only used to derive `og:type`. */
|
|
18
|
+
type?: SchemaPageType | undefined;
|
|
19
|
+
/** An explicit `og:type`; wins over the one derived from `type`. */
|
|
20
|
+
openGraphType?: OpenGraphType | undefined;
|
|
21
|
+
/** An explicit canonical URL. Wins over `pathname`. */
|
|
22
|
+
canonical?: string | undefined;
|
|
23
|
+
/** The current path, resolved through `canonicalHref` into the canonical URL. */
|
|
24
|
+
pathname?: string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Resolves an app-relative path to an absolute URL on the production origin.
|
|
27
|
+
* @defaultValue the components context’s `href`
|
|
28
|
+
*/
|
|
29
|
+
canonicalHref?: ((path: string) => string) | undefined;
|
|
30
|
+
/** Explicit `hreflang` alternates. Wins over `locales`. */
|
|
31
|
+
alternates?: readonly AlternateLink[] | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* The site's locales. Each, plus `x-default`, becomes an `hreflang`
|
|
34
|
+
* alternate pointing at the canonical URL — the right signal for a site
|
|
35
|
+
* whose UI chrome is localised but whose URLs are not. A site with
|
|
36
|
+
* per-locale URLs passes `alternates` instead.
|
|
37
|
+
*/
|
|
38
|
+
locales?: readonly string[] | undefined;
|
|
39
|
+
/** `og:locale`, in Open Graph's `language_TERRITORY` form. */
|
|
40
|
+
ogLocale?: string | undefined;
|
|
41
|
+
/** An RSS, Atom or JSON Feed link. */
|
|
42
|
+
feed?: FeedLink | undefined;
|
|
43
|
+
/** The robots directive. */
|
|
44
|
+
robots?: Robots | undefined;
|
|
45
|
+
/** An explicit share image. Wins over `shareCard` and `defaultImage`. */
|
|
46
|
+
image?: HeadImage | undefined;
|
|
47
|
+
/** Build a per-page share card URL with {@link ogImageUrl}. */
|
|
48
|
+
shareCard?: OgImageCard | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Where the share-card renderer is mounted.
|
|
51
|
+
* @defaultValue `/og`
|
|
52
|
+
*/
|
|
53
|
+
shareCardPath?: string | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* The share card's alt text.
|
|
56
|
+
* @defaultValue `"<card title> — <siteName>"`, or the card title alone when `siteName` is unset or empty
|
|
57
|
+
*/
|
|
58
|
+
shareCardAlt?: ((card: OgImageCard) => string) | undefined;
|
|
59
|
+
/** The share image when neither `image` nor `shareCard` gives one. */
|
|
60
|
+
defaultImage?: HeadImage | undefined;
|
|
61
|
+
/** `article:published_time`. */
|
|
62
|
+
published?: Date | undefined;
|
|
63
|
+
/** `article:modified_time`. */
|
|
64
|
+
modified?: Date | undefined;
|
|
65
|
+
/** `article:section`. Blank is treated as absent. */
|
|
66
|
+
section?: string | undefined;
|
|
67
|
+
/** `article:tag`, one per entry. */
|
|
68
|
+
tags?: readonly string[] | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* The Twitter / X card type.
|
|
71
|
+
* @defaultValue `'summary_large_image'`
|
|
72
|
+
*/
|
|
73
|
+
twitterCard?: TwitterCard | undefined;
|
|
74
|
+
/** The site’s Twitter / X handle. */
|
|
75
|
+
twitterSite?: string | undefined;
|
|
76
|
+
/** The author’s Twitter / X handle. */
|
|
77
|
+
twitterCreator?: string | undefined;
|
|
78
|
+
/** The previous page in a paginated series (`rel="prev"`). */
|
|
79
|
+
prevUrl?: string | undefined;
|
|
80
|
+
/** The next page in a paginated series (`rel="next"`). */
|
|
81
|
+
nextUrl?: string | undefined;
|
|
82
|
+
}
|
|
83
|
+
/** Per-page `<head>` metadata: title, description, canonical URL, `hreflang` alternates, Open Graph and Twitter / X tags, `article:*` and pagination links. */
|
|
84
|
+
declare const Head: import("svelte").Component<Props, {}, "">;
|
|
85
|
+
type Head = ReturnType<typeof Head>;
|
|
86
|
+
export default Head;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
One Schema.org JSON-LD node as an XSS-safe `<script type="application/ld+json">` block in `<svelte:head>`.
|
|
3
|
+
-->
|
|
4
|
+
<script lang="ts">/**
|
|
5
|
+
* Emits one Schema.org JSON-LD graph node as a
|
|
6
|
+
* `<script type="application/ld+json">` block in `<svelte:head>`.
|
|
7
|
+
*
|
|
8
|
+
* The JSON goes through {@link serializeJsonLd}, which escapes `<`, `>`,
|
|
9
|
+
* `&`, U+2028 and U+2029, so authored content can neither close the script
|
|
10
|
+
* element nor open an HTML comment inside it and inject markup. `data` of
|
|
11
|
+
* `null` / `undefined` renders nothing, so a builder that
|
|
12
|
+
* may have nothing to emit (a degenerate breadcrumb trail) can be wired
|
|
13
|
+
* without a call-site `{#if}`.
|
|
14
|
+
*/
|
|
15
|
+
import { serializeJsonLd } from "./json-ld.js";
|
|
16
|
+
let { data } = $props();
|
|
17
|
+
// The closing tag is split so neither the Svelte compiler nor an HTML
|
|
18
|
+
// parser reading this file sees it as the end of the component's own
|
|
19
|
+
// `<script>`.
|
|
20
|
+
const open = "<script type=\"application/ld+json\">";
|
|
21
|
+
const close = "<" + "/script>";
|
|
22
|
+
const block = $derived(data === null || data === undefined ? undefined : open + serializeJsonLd(data) + close);
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<svelte:head>
|
|
26
|
+
{#if block !== undefined}
|
|
27
|
+
<!-- Escaped by serializeJsonLd: `<`, `>` and `&` cannot appear unescaped. -->
|
|
28
|
+
{@html block}
|
|
29
|
+
{/if}
|
|
30
|
+
</svelte:head>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emits one Schema.org JSON-LD graph node as a
|
|
3
|
+
* `<script type="application/ld+json">` block in `<svelte:head>`.
|
|
4
|
+
*
|
|
5
|
+
* The JSON goes through {@link serializeJsonLd}, which escapes `<`, `>`,
|
|
6
|
+
* `&`, U+2028 and U+2029, so authored content can neither close the script
|
|
7
|
+
* element nor open an HTML comment inside it and inject markup. `data` of
|
|
8
|
+
* `null` / `undefined` renders nothing, so a builder that
|
|
9
|
+
* may have nothing to emit (a degenerate breadcrumb trail) can be wired
|
|
10
|
+
* without a call-site `{#if}`.
|
|
11
|
+
*/
|
|
12
|
+
import { type JsonLdObject } from './json-ld.ts';
|
|
13
|
+
interface Props {
|
|
14
|
+
/** The node to serialise; nothing is emitted for `null` or `undefined`. */
|
|
15
|
+
data: JsonLdObject | null | undefined;
|
|
16
|
+
}
|
|
17
|
+
/** One Schema.org JSON-LD node as an XSS-safe `<script type="application/ld+json">` block in `<svelte:head>`. */
|
|
18
|
+
declare const JsonLd: import("svelte").Component<Props, {}, "">;
|
|
19
|
+
type JsonLd = ReturnType<typeof JsonLd>;
|
|
20
|
+
export default JsonLd;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@thomasfosterau/components/seo` — per-page `<head>` metadata and
|
|
3
|
+
* structured data. A separate entry point: it renders only into
|
|
4
|
+
* `<svelte:head>`, and a consumer that manages its own head never loads it.
|
|
5
|
+
*
|
|
6
|
+
* `<Head>` emits the title, canonical, `hreflang`, Open Graph and Twitter /
|
|
7
|
+
* X tags; `<JsonLd>` emits one XSS-safe JSON-LD block; `serializeJsonLd` is
|
|
8
|
+
* the escaping serialiser underneath it; `ogImageUrl` builds the
|
|
9
|
+
* content-addressed share-card URL `<Head>` emits, with the param names and
|
|
10
|
+
* caps a card renderer reads back.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
export { default as Head } from './Head.svelte';
|
|
15
|
+
export { default as JsonLd } from './JsonLd.svelte';
|
|
16
|
+
export { serializeJsonLd, type JsonLdObject } from './json-ld.ts';
|
|
17
|
+
export { OG_IMAGE_HEIGHT, OG_IMAGE_WIDTH, OG_SUBTITLE_MAX_LENGTH, OG_SUBTITLE_PARAM, OG_TITLE_MAX_LENGTH, OG_TITLE_PARAM, OG_VERSION_PARAM, ogImageUrl, type OgImageCard, type OgImageUrlOptions, } from './og-image.ts';
|
|
18
|
+
export type { AlternateLink, FeedLink, HeadImage, OpenGraphType, Robots, SchemaPageType, TwitterCard, } from './types.ts';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@thomasfosterau/components/seo` — per-page `<head>` metadata and
|
|
3
|
+
* structured data. A separate entry point: it renders only into
|
|
4
|
+
* `<svelte:head>`, and a consumer that manages its own head never loads it.
|
|
5
|
+
*
|
|
6
|
+
* `<Head>` emits the title, canonical, `hreflang`, Open Graph and Twitter /
|
|
7
|
+
* X tags; `<JsonLd>` emits one XSS-safe JSON-LD block; `serializeJsonLd` is
|
|
8
|
+
* the escaping serialiser underneath it; `ogImageUrl` builds the
|
|
9
|
+
* content-addressed share-card URL `<Head>` emits, with the param names and
|
|
10
|
+
* caps a card renderer reads back.
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
export { default as Head } from './Head.svelte';
|
|
15
|
+
export { default as JsonLd } from './JsonLd.svelte';
|
|
16
|
+
export { serializeJsonLd } from "./json-ld.js";
|
|
17
|
+
export { OG_IMAGE_HEIGHT, OG_IMAGE_WIDTH, OG_SUBTITLE_MAX_LENGTH, OG_SUBTITLE_PARAM, OG_TITLE_MAX_LENGTH, OG_TITLE_PARAM, OG_VERSION_PARAM, ogImageUrl, } from "./og-image.js";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialising Schema.org JSON-LD for a `<script type="application/ld+json">`
|
|
3
|
+
* block.
|
|
4
|
+
*
|
|
5
|
+
* `JSON.stringify` already escapes `"` inside strings. What it leaves is the
|
|
6
|
+
* HTML parser: an authored title containing `</script>` would close the
|
|
7
|
+
* embedding script element and inject whatever follows. `<`, `>` and `&` are
|
|
8
|
+
* therefore replaced with their `\u` escapes — JSON parsers read them
|
|
9
|
+
* identically, so the structured-data consumer sees the original text — and so
|
|
10
|
+
* are U+2028 / U+2029, which are legal in JSON strings but line terminators in
|
|
11
|
+
* JavaScript (OWASP / Google's JSON-in-HTML guidance).
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* A JSON-LD graph node with its top-level `@context`.
|
|
17
|
+
*
|
|
18
|
+
* Deliberately loose: the library does not take `schema-dts` (or any
|
|
19
|
+
* vocabulary) as a dependency. `WithContext<Thing>` from `schema-dts` (a type
|
|
20
|
+
* alias, so it satisfies the index signature) is assignable to it, so an app
|
|
21
|
+
* that type-checks its builders against the real vocabulary can hand the
|
|
22
|
+
* result straight to {@link serializeJsonLd} or `<JsonLd>`.
|
|
23
|
+
*/
|
|
24
|
+
export type JsonLdObject = {
|
|
25
|
+
readonly '@context': unknown;
|
|
26
|
+
readonly [property: string]: unknown;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Serialise a JSON-LD object to a string safe to embed in a
|
|
30
|
+
* `<script type="application/ld+json">` block. The output is valid JSON that
|
|
31
|
+
* round-trips through `JSON.parse` to the input.
|
|
32
|
+
*/
|
|
33
|
+
export declare function serializeJsonLd(data: JsonLdObject): string;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialising Schema.org JSON-LD for a `<script type="application/ld+json">`
|
|
3
|
+
* block.
|
|
4
|
+
*
|
|
5
|
+
* `JSON.stringify` already escapes `"` inside strings. What it leaves is the
|
|
6
|
+
* HTML parser: an authored title containing `</script>` would close the
|
|
7
|
+
* embedding script element and inject whatever follows. `<`, `>` and `&` are
|
|
8
|
+
* therefore replaced with their `\u` escapes — JSON parsers read them
|
|
9
|
+
* identically, so the structured-data consumer sees the original text — and so
|
|
10
|
+
* are U+2028 / U+2029, which are legal in JSON strings but line terminators in
|
|
11
|
+
* JavaScript (OWASP / Google's JSON-in-HTML guidance).
|
|
12
|
+
*
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
const LINE_SEPARATOR = new RegExp(String.fromCharCode(0x2028), 'g');
|
|
16
|
+
const PARAGRAPH_SEPARATOR = new RegExp(String.fromCharCode(0x2029), 'g');
|
|
17
|
+
/**
|
|
18
|
+
* Serialise a JSON-LD object to a string safe to embed in a
|
|
19
|
+
* `<script type="application/ld+json">` block. The output is valid JSON that
|
|
20
|
+
* round-trips through `JSON.parse` to the input.
|
|
21
|
+
*/
|
|
22
|
+
export function serializeJsonLd(data) {
|
|
23
|
+
return JSON.stringify(data)
|
|
24
|
+
.replace(/</g, '\\u003C')
|
|
25
|
+
.replace(/>/g, '\\u003E')
|
|
26
|
+
.replace(/&/g, '\\u0026')
|
|
27
|
+
.replace(LINE_SEPARATOR, '\\u2028')
|
|
28
|
+
.replace(PARAGRAPH_SEPARATOR, '\\u2029');
|
|
29
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The content-addressed Open Graph share-image URL builder.
|
|
3
|
+
*
|
|
4
|
+
* Shared by `<Head>` (which emits the URL as `og:image`) and whatever renders
|
|
5
|
+
* the card (an app route or Worker reading the same query params), so the
|
|
6
|
+
* producer and the consumer of the URL can never disagree on the param names
|
|
7
|
+
* or the length caps — import the constants below on both sides.
|
|
8
|
+
*
|
|
9
|
+
* The URL is **content-addressed**: the title and description ride in the
|
|
10
|
+
* query, and a `v` token derived from the content's last-modified instant
|
|
11
|
+
* changes the whole URL whenever the content changes. A new URL is how the
|
|
12
|
+
* image cache-busts — link-preview scrapers (Facebook, LinkedIn, federated
|
|
13
|
+
* servers) cache aggressively and only re-fetch a URL they have not seen, so
|
|
14
|
+
* the version token is load-bearing, not cosmetic.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
/** Query param carrying the card title. */
|
|
19
|
+
export declare const OG_TITLE_PARAM = "t";
|
|
20
|
+
/** Query param carrying the card's second line (the page description). */
|
|
21
|
+
export declare const OG_SUBTITLE_PARAM = "d";
|
|
22
|
+
/** Query param carrying the cache-busting version token. */
|
|
23
|
+
export declare const OG_VERSION_PARAM = "v";
|
|
24
|
+
/**
|
|
25
|
+
* Longest title, in characters, carried in a share-card URL. A renderer
|
|
26
|
+
* should re-apply this cap (and `OG_SUBTITLE_MAX_LENGTH`) defensively; here
|
|
27
|
+
* they keep the emitted URL short.
|
|
28
|
+
*/
|
|
29
|
+
export declare const OG_TITLE_MAX_LENGTH = 120;
|
|
30
|
+
/** Longest description, in characters, carried in a share-card URL; see `OG_TITLE_MAX_LENGTH`. */
|
|
31
|
+
export declare const OG_SUBTITLE_MAX_LENGTH = 200;
|
|
32
|
+
/** Share-card width in pixels — the 1.91:1 Open Graph standard, with `OG_IMAGE_HEIGHT`. */
|
|
33
|
+
export declare const OG_IMAGE_WIDTH = 1200;
|
|
34
|
+
/** Share-card height in pixels; see `OG_IMAGE_WIDTH`. */
|
|
35
|
+
export declare const OG_IMAGE_HEIGHT = 630;
|
|
36
|
+
/** What a per-page share card is built from. */
|
|
37
|
+
export interface OgImageCard {
|
|
38
|
+
/** The page title — the card headline. A blank title builds no URL. */
|
|
39
|
+
readonly title: string;
|
|
40
|
+
/** Optional second line (the page description). */
|
|
41
|
+
readonly description?: string | null | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* A stable, opaque identity for the page (a content UUID, a slug), used only
|
|
44
|
+
* to build the readable `<slug>.png` path segment. Never rendered.
|
|
45
|
+
*/
|
|
46
|
+
readonly id: string;
|
|
47
|
+
/**
|
|
48
|
+
* The content's last-modified instant, or anything that changes when the
|
|
49
|
+
* card should. Drives the version token; absent or unparseable, the URL is
|
|
50
|
+
* keyed by title + description alone.
|
|
51
|
+
*/
|
|
52
|
+
readonly updatedAt?: Date | string | number | null | undefined;
|
|
53
|
+
}
|
|
54
|
+
/** How `ogImageUrl` turns a card into an absolute URL: the href resolver and the renderer's mount path. */
|
|
55
|
+
export interface OgImageUrlOptions {
|
|
56
|
+
/**
|
|
57
|
+
* Resolves the card's path to the href emitted — the production origin, so
|
|
58
|
+
* the URL is absolute (`og:image` must be). `<Head>` passes its
|
|
59
|
+
* `canonicalHref`, which defaults to the components context's `href`.
|
|
60
|
+
* Defaults to the identity.
|
|
61
|
+
*/
|
|
62
|
+
readonly href?: ((path: string) => string) | undefined;
|
|
63
|
+
/** The path the card renderer is mounted at. Default `/og`. */
|
|
64
|
+
readonly basePath?: string | undefined;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Build the `og:image` URL for a page's share card: `<basePath>/<slug>.png`
|
|
68
|
+
* resolved through `href`, with the title, description and version token in
|
|
69
|
+
* the query. Returns `undefined` for a blank title, so the caller falls back
|
|
70
|
+
* to its default share image.
|
|
71
|
+
*/
|
|
72
|
+
export declare function ogImageUrl(card: OgImageCard, options?: OgImageUrlOptions): string | undefined;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The content-addressed Open Graph share-image URL builder.
|
|
3
|
+
*
|
|
4
|
+
* Shared by `<Head>` (which emits the URL as `og:image`) and whatever renders
|
|
5
|
+
* the card (an app route or Worker reading the same query params), so the
|
|
6
|
+
* producer and the consumer of the URL can never disagree on the param names
|
|
7
|
+
* or the length caps — import the constants below on both sides.
|
|
8
|
+
*
|
|
9
|
+
* The URL is **content-addressed**: the title and description ride in the
|
|
10
|
+
* query, and a `v` token derived from the content's last-modified instant
|
|
11
|
+
* changes the whole URL whenever the content changes. A new URL is how the
|
|
12
|
+
* image cache-busts — link-preview scrapers (Facebook, LinkedIn, federated
|
|
13
|
+
* servers) cache aggressively and only re-fetch a URL they have not seen, so
|
|
14
|
+
* the version token is load-bearing, not cosmetic.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
/** Query param carrying the card title. */
|
|
19
|
+
export const OG_TITLE_PARAM = 't';
|
|
20
|
+
/** Query param carrying the card's second line (the page description). */
|
|
21
|
+
export const OG_SUBTITLE_PARAM = 'd';
|
|
22
|
+
/** Query param carrying the cache-busting version token. */
|
|
23
|
+
export const OG_VERSION_PARAM = 'v';
|
|
24
|
+
/**
|
|
25
|
+
* Longest title, in characters, carried in a share-card URL. A renderer
|
|
26
|
+
* should re-apply this cap (and `OG_SUBTITLE_MAX_LENGTH`) defensively; here
|
|
27
|
+
* they keep the emitted URL short.
|
|
28
|
+
*/
|
|
29
|
+
export const OG_TITLE_MAX_LENGTH = 120;
|
|
30
|
+
/** Longest description, in characters, carried in a share-card URL; see `OG_TITLE_MAX_LENGTH`. */
|
|
31
|
+
export const OG_SUBTITLE_MAX_LENGTH = 200;
|
|
32
|
+
/** Share-card width in pixels — the 1.91:1 Open Graph standard, with `OG_IMAGE_HEIGHT`. */
|
|
33
|
+
export const OG_IMAGE_WIDTH = 1200;
|
|
34
|
+
/** Share-card height in pixels; see `OG_IMAGE_WIDTH`. */
|
|
35
|
+
export const OG_IMAGE_HEIGHT = 630;
|
|
36
|
+
/**
|
|
37
|
+
* Reduce an identity to a short URL-safe slug. Cosmetic — a renderer should
|
|
38
|
+
* ignore it — so an empty or garbage id collapses to a stable fallback rather
|
|
39
|
+
* than an invalid path.
|
|
40
|
+
*/
|
|
41
|
+
const toSlug = (id) => {
|
|
42
|
+
const slug = id
|
|
43
|
+
.toLowerCase()
|
|
44
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
45
|
+
.replace(/^-+|-+$/g, '')
|
|
46
|
+
.slice(0, 64);
|
|
47
|
+
return slug === '' ? 'page' : slug;
|
|
48
|
+
};
|
|
49
|
+
/** Epoch milliseconds of `updatedAt`, or `undefined` when absent or unparseable. */
|
|
50
|
+
const versionToken = (updatedAt) => {
|
|
51
|
+
if (updatedAt === null || updatedAt === undefined)
|
|
52
|
+
return undefined;
|
|
53
|
+
const time = updatedAt instanceof Date
|
|
54
|
+
? updatedAt.getTime()
|
|
55
|
+
: typeof updatedAt === 'number'
|
|
56
|
+
? updatedAt
|
|
57
|
+
: Date.parse(updatedAt);
|
|
58
|
+
return Number.isFinite(time) ? String(time) : undefined;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Build the `og:image` URL for a page's share card: `<basePath>/<slug>.png`
|
|
62
|
+
* resolved through `href`, with the title, description and version token in
|
|
63
|
+
* the query. Returns `undefined` for a blank title, so the caller falls back
|
|
64
|
+
* to its default share image.
|
|
65
|
+
*/
|
|
66
|
+
export function ogImageUrl(card, options = {}) {
|
|
67
|
+
const title = card.title.trim();
|
|
68
|
+
if (title === '')
|
|
69
|
+
return undefined;
|
|
70
|
+
const params = new URLSearchParams();
|
|
71
|
+
params.set(OG_TITLE_PARAM, title.slice(0, OG_TITLE_MAX_LENGTH));
|
|
72
|
+
const description = card.description?.trim();
|
|
73
|
+
if (description !== undefined && description !== '') {
|
|
74
|
+
params.set(OG_SUBTITLE_PARAM, description.slice(0, OG_SUBTITLE_MAX_LENGTH));
|
|
75
|
+
}
|
|
76
|
+
const version = versionToken(card.updatedAt);
|
|
77
|
+
if (version !== undefined)
|
|
78
|
+
params.set(OG_VERSION_PARAM, version);
|
|
79
|
+
const basePath = (options.basePath ?? '/og').replace(/\/+$/, '');
|
|
80
|
+
const href = options.href ?? ((path) => path);
|
|
81
|
+
return `${href(`${basePath}/${toSlug(card.id)}.png`)}?${params.toString()}`;
|
|
82
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The data shapes `<Head>` takes.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
/** The Open Graph `og:type` values `<Head>` emits. */
|
|
7
|
+
export type OpenGraphType = 'website' | 'article' | 'profile';
|
|
8
|
+
/**
|
|
9
|
+
* The Schema.org page types `<Head>` understands, used only to derive
|
|
10
|
+
* `og:type` when `openGraphType` is not given (so it is never empty).
|
|
11
|
+
*/
|
|
12
|
+
export type SchemaPageType = 'WebPage' | 'WebSite' | 'CollectionPage' | 'Article' | 'BlogPosting' | 'ProfilePage';
|
|
13
|
+
/** The Twitter / X card variants. */
|
|
14
|
+
export type TwitterCard = 'summary' | 'summary_large_image';
|
|
15
|
+
/** A social preview image. `url` must be absolute. */
|
|
16
|
+
export interface HeadImage {
|
|
17
|
+
readonly url: string;
|
|
18
|
+
readonly alt?: string | undefined;
|
|
19
|
+
readonly width?: number | undefined;
|
|
20
|
+
readonly height?: number | undefined;
|
|
21
|
+
/** The MIME type, e.g. `image/png`. */
|
|
22
|
+
readonly type?: string | undefined;
|
|
23
|
+
}
|
|
24
|
+
/** One `<link rel="alternate" hreflang>`. */
|
|
25
|
+
export interface AlternateLink {
|
|
26
|
+
readonly href: string;
|
|
27
|
+
/** A BCP 47 tag, or `x-default`. */
|
|
28
|
+
readonly lang: string;
|
|
29
|
+
}
|
|
30
|
+
/** The `robots` meta directive. Both default to `true`. */
|
|
31
|
+
export interface Robots {
|
|
32
|
+
readonly index?: boolean | undefined;
|
|
33
|
+
readonly follow?: boolean | undefined;
|
|
34
|
+
}
|
|
35
|
+
/** A feed advertised with `<link rel="alternate">`. */
|
|
36
|
+
export interface FeedLink {
|
|
37
|
+
/** App-relative path, resolved through `canonicalHref` like the canonical URL. */
|
|
38
|
+
readonly path: string;
|
|
39
|
+
/** The feed's title. Default `'Latest changes'`. */
|
|
40
|
+
readonly title?: string | undefined;
|
|
41
|
+
/** The feed's MIME type. Default `application/feed+json` (JSON Feed 1.1). */
|
|
42
|
+
readonly type?: string | undefined;
|
|
43
|
+
}
|
package/dist/theme.css
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The library's design tokens: two daisyUI themes, `light` and `dark`, that
|
|
3
|
+
* every component in this package renders on.
|
|
4
|
+
*
|
|
5
|
+
* Shipped as the package's `./theme.css` export and imported by BOTH
|
|
6
|
+
* consumers — an application's CSS entry, and Storybook's
|
|
7
|
+
* `.storybook/preview.css` relatively — so there is exactly one copy of every
|
|
8
|
+
* token.
|
|
9
|
+
*
|
|
10
|
+
* **This is the whole styling vocabulary.** A component here reaches for a
|
|
11
|
+
* semantic name — `bg-base-200`, `text-error`, `btn-primary` — and never for
|
|
12
|
+
* a raw palette class (`bg-green-700`), a hex, or an `oklch()` of its own. Two
|
|
13
|
+
* vocabularies for one palette is how a design system drifts.
|
|
14
|
+
*
|
|
15
|
+
* The values below are DELIBERATELY NEUTRAL: an achromatic surface ramp and a
|
|
16
|
+
* single mid-slate brand hue, so the library looks like nothing in particular
|
|
17
|
+
* out of the box. They are a starting point, not a brand. An application
|
|
18
|
+
* overrides them by declaring its own `light` / `dark` themes after importing
|
|
19
|
+
* this file, or by naming its own themes entirely and never importing it.
|
|
20
|
+
*/
|
|
21
|
+
@plugin "daisyui/theme" {
|
|
22
|
+
name: 'light';
|
|
23
|
+
default: true;
|
|
24
|
+
color-scheme: light;
|
|
25
|
+
/* Surfaces: a neutral off-white ramp. */
|
|
26
|
+
--color-base-100: oklch(100% 0 0);
|
|
27
|
+
--color-base-200: oklch(96% 0 0);
|
|
28
|
+
--color-base-300: oklch(91% 0 0);
|
|
29
|
+
--color-base-content: oklch(22% 0 0);
|
|
30
|
+
/* Brand: slate. Replace these four pairs, not the surface ramp. */
|
|
31
|
+
--color-primary: oklch(45% 0.03 260);
|
|
32
|
+
--color-primary-content: oklch(98% 0 0);
|
|
33
|
+
--color-secondary: oklch(55% 0.02 260);
|
|
34
|
+
--color-secondary-content: oklch(98% 0 0);
|
|
35
|
+
--color-accent: oklch(60% 0.02 260);
|
|
36
|
+
--color-accent-content: oklch(98% 0 0);
|
|
37
|
+
--color-neutral: oklch(30% 0 0);
|
|
38
|
+
--color-neutral-content: oklch(96% 0 0);
|
|
39
|
+
/* Status: blue / green / amber / red, at their conventional roles. */
|
|
40
|
+
--color-info: oklch(62.3% 0.214 259.815);
|
|
41
|
+
--color-info-content: oklch(97% 0.01 260);
|
|
42
|
+
--color-success: oklch(59.6% 0.145 163.225);
|
|
43
|
+
--color-success-content: oklch(97% 0.02 163);
|
|
44
|
+
--color-warning: oklch(76.9% 0.188 70.08);
|
|
45
|
+
--color-warning-content: oklch(28% 0.07 70);
|
|
46
|
+
--color-error: oklch(57.7% 0.245 27.325);
|
|
47
|
+
--color-error-content: oklch(97% 0.01 27);
|
|
48
|
+
--radius-selector: 1rem;
|
|
49
|
+
--radius-field: 0.375rem;
|
|
50
|
+
--radius-box: 0.75rem;
|
|
51
|
+
--size-selector: 0.25rem;
|
|
52
|
+
--size-field: 0.25rem;
|
|
53
|
+
--border: 1px;
|
|
54
|
+
--depth: 1;
|
|
55
|
+
--noise: 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@plugin "daisyui/theme" {
|
|
59
|
+
name: 'dark';
|
|
60
|
+
prefersdark: true;
|
|
61
|
+
color-scheme: dark;
|
|
62
|
+
/* Surfaces: the same ramp inverted — not a different ramp. */
|
|
63
|
+
--color-base-100: oklch(18% 0 0);
|
|
64
|
+
--color-base-200: oklch(22% 0 0);
|
|
65
|
+
--color-base-300: oklch(28% 0 0);
|
|
66
|
+
--color-base-content: oklch(95% 0 0);
|
|
67
|
+
/* Brand: the light theme's hue, stepped for a dark surface rather than
|
|
68
|
+
flipped — a colour that clears contrast on white rarely clears it on
|
|
69
|
+
near-black. */
|
|
70
|
+
--color-primary: oklch(72% 0.04 260);
|
|
71
|
+
--color-primary-content: oklch(20% 0.01 260);
|
|
72
|
+
--color-secondary: oklch(66% 0.03 260);
|
|
73
|
+
--color-secondary-content: oklch(20% 0.01 260);
|
|
74
|
+
--color-accent: oklch(70% 0.03 260);
|
|
75
|
+
--color-accent-content: oklch(20% 0.01 260);
|
|
76
|
+
--color-neutral: oklch(26% 0 0);
|
|
77
|
+
--color-neutral-content: oklch(92% 0 0);
|
|
78
|
+
--color-info: oklch(70.7% 0.165 254.624);
|
|
79
|
+
--color-info-content: oklch(20% 0.05 255);
|
|
80
|
+
--color-success: oklch(76.5% 0.177 163.223);
|
|
81
|
+
--color-success-content: oklch(20% 0.05 163);
|
|
82
|
+
--color-warning: oklch(82.8% 0.189 84.429);
|
|
83
|
+
--color-warning-content: oklch(25% 0.07 84);
|
|
84
|
+
--color-error: oklch(70.4% 0.191 22.216);
|
|
85
|
+
--color-error-content: oklch(20% 0.05 22);
|
|
86
|
+
--radius-selector: 1rem;
|
|
87
|
+
--radius-field: 0.375rem;
|
|
88
|
+
--radius-box: 0.75rem;
|
|
89
|
+
--size-selector: 0.25rem;
|
|
90
|
+
--size-field: 0.25rem;
|
|
91
|
+
--border: 1px;
|
|
92
|
+
--depth: 1;
|
|
93
|
+
--noise: 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* ────────────────────────────────────────────────────────────────────────────
|
|
97
|
+
* Categorical chart slots — appended block, owned by `charts/`.
|
|
98
|
+
*
|
|
99
|
+
* The one part of the palette a component reads as a raw custom property
|
|
100
|
+
* rather than through a Tailwind class, because a series colour is chosen by
|
|
101
|
+
* INDEX at runtime and Tailwind only emits classes it can see spelled out.
|
|
102
|
+
*
|
|
103
|
+
* Four slots, and **validated rather than chosen by eye**: the figures below
|
|
104
|
+
* were measured against the two themes above (`--color-base-100` is
|
|
105
|
+
* `oklch(100% 0 0)` → #ffffff in light, `oklch(18% 0 0)` → #121212 in dark),
|
|
106
|
+
* with dichromacy simulated by the Machado (2009) severity-1.0 matrices on
|
|
107
|
+
* linear sRGB and separation as Euclidean ΔE in OKLab ×100.
|
|
108
|
+
*
|
|
109
|
+
* light — #008236 #4f39f6 #e17100 #155dfc
|
|
110
|
+
* contrast on the surface 4.94 / 6.44 / 3.19 / 5.26 : 1
|
|
111
|
+
* worst ADJACENT pair: normal ΔE 37.6, simulated-dichromat ΔE 8.3
|
|
112
|
+
* dark — #00a63e #615fff #e17100 #155dfc
|
|
113
|
+
* contrast on the surface 5.85 / 4.11 / 5.89 / 3.58 : 1
|
|
114
|
+
* worst ADJACENT pair: normal ΔE 38.6, simulated-dichromat ΔE 9.8
|
|
115
|
+
*
|
|
116
|
+
* Every slot clears 3:1 against its own surface; every adjacent pair clears the
|
|
117
|
+
* ΔE ≥ 15 normal-vision floor and the ΔE ≥ 8 dichromat floor in both modes.
|
|
118
|
+
* The dark set is STEPPED for the dark surface, not flipped: slots 1 and 2 move
|
|
119
|
+
* one step lighter, slots 3 and 4 already sit inside both modes' bands.
|
|
120
|
+
*
|
|
121
|
+
* Three rules the slots exist to make keepable:
|
|
122
|
+
*
|
|
123
|
+
* - **Order is the safety mechanism.** The gates above are measured on ADJACENT
|
|
124
|
+
* pairs, which is what a line, bar or stack puts side by side. Re-ordering
|
|
125
|
+
* the slots invalidates the measurement — slots 2 and 4 (indigo and blue) are
|
|
126
|
+
* ΔE 2.7 apart in light and 0.4 in dark under simulated dichromacy, so a
|
|
127
|
+
* chart that puts them side by side has no colour difference for that reader
|
|
128
|
+
* at all.
|
|
129
|
+
* - **Four is the cap, and three is the cap for a form that compares EVERY
|
|
130
|
+
* pair at once** (a scatter, a choropleth, a pie). A fifth series is a design
|
|
131
|
+
* problem — fold it into an "other" series, or facet — never a generated hue.
|
|
132
|
+
* `Chart` draws a fifth in `--color-neutral` and names it in the legend
|
|
133
|
+
* rather than inventing one. Even at three, the 1↔3 pair falls to ΔE 4.9
|
|
134
|
+
* under protanopia, which is the reason `Chart`'s `sr-only` data table is
|
|
135
|
+
* always in the DOM: colour is the fast path, never the only one.
|
|
136
|
+
* - **Status colours are not series colours.** `--color-success` / `-warning` /
|
|
137
|
+
* `-error` mean a STATE, and slot 3 is deliberately amber-600 rather than the
|
|
138
|
+
* amber-500 that IS `--color-warning`, so a series can never impersonate one.
|
|
139
|
+
*
|
|
140
|
+
* A consumer replacing the two themes above should replace these four with
|
|
141
|
+
* their own measured set, in the same order.
|
|
142
|
+
* ──────────────────────────────────────────────────────────────────────────── */
|
|
143
|
+
:root {
|
|
144
|
+
/*
|
|
145
|
+
* One declaration per slot, not one per mode: `light-dark()` resolves against
|
|
146
|
+
* the `color-scheme` each daisyUI theme already sets — `light` on the `light`
|
|
147
|
+
* theme, `dark` on the `dark` one, and on whichever the OS asks for by
|
|
148
|
+
* default. Writing the dark set out a second time under `[data-theme]` and a
|
|
149
|
+
* third under `prefers-color-scheme` is how two of the three drift apart.
|
|
150
|
+
*/
|
|
151
|
+
--color-chart-1: light-dark(
|
|
152
|
+
oklch(52.7% 0.154 150.069),
|
|
153
|
+
oklch(62.7% 0.194 149.214)
|
|
154
|
+
); /* green-700 / -600 */
|
|
155
|
+
--color-chart-2: light-dark(
|
|
156
|
+
oklch(51.1% 0.262 276.966),
|
|
157
|
+
oklch(58.5% 0.233 277.117)
|
|
158
|
+
); /* indigo-600 / -500 */
|
|
159
|
+
--color-chart-3: oklch(66.6% 0.179 58.318); /* amber-600, inside both bands */
|
|
160
|
+
--color-chart-4: oklch(54.6% 0.245 262.881); /* blue-600, inside both bands */
|
|
161
|
+
}
|