@drawnagency/primitives 0.1.112 → 0.1.114
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/README.md +1 -1
- package/dist/auth/cookies.d.ts +39 -0
- package/dist/auth/cookies.d.ts.map +1 -1
- package/dist/auth/index.js +3 -3
- package/dist/auth/types.d.ts +1 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/{chunk-GPPVYLEI.js → chunk-45FA7Z55.js} +1 -1
- package/dist/{chunk-REDDTTGJ.js → chunk-4Y2JQQZL.js} +19 -1
- package/dist/chunk-5GFACGSN.js +6 -0
- package/dist/chunk-5KSAS4VY.js +275 -0
- package/dist/{chunk-5KNXTMUC.js → chunk-7SAAJVDE.js} +408 -28
- package/dist/{chunk-S2L3BPLS.js → chunk-7SX42OP4.js} +1 -1
- package/dist/{chunk-GGXZZ77Z.js → chunk-AASEGXNT.js} +18 -1
- package/dist/{chunk-WKZ7OENC.js → chunk-BQ5TZZUE.js} +5 -1
- package/dist/chunk-DIMDRBFK.js +11 -0
- package/dist/{chunk-WUJ3XNFI.js → chunk-GGYY3JQJ.js} +19 -24
- package/dist/{chunk-VLPELTPI.js → chunk-IP2SEBAJ.js} +5 -1
- package/dist/{chunk-IINIZBQB.js → chunk-JCDZAFX2.js} +30 -10
- package/dist/chunk-JR24U7FJ.js +120 -0
- package/dist/{chunk-SW6PCQQD.js → chunk-KQA772WQ.js} +2 -1
- package/dist/{chunk-Z2LO4PSQ.js → chunk-N3G7DOU3.js} +609 -61
- package/dist/chunk-OAGJBCSH.js +67 -0
- package/dist/{chunk-VT3PYGVW.js → chunk-PLANHXS7.js} +191 -61
- package/dist/{chunk-OGGZ5AXT.js → chunk-PNSCDBU7.js} +38 -56
- package/dist/{chunk-HSXMOS5Q.js → chunk-PTY2RG2K.js} +5 -2
- package/dist/{chunk-EPWBPIV6.js → chunk-PZPGJZRG.js} +9 -8
- package/dist/{chunk-P3ZNCHW7.js → chunk-QHMKIODQ.js} +19 -5
- package/dist/{chunk-HBULBDGP.js → chunk-S37DZPHW.js} +1 -1
- package/dist/{chunk-4I5OO5UB.js → chunk-TEOAKGZA.js} +0 -1
- package/dist/chunk-VUYCRBJK.js +174 -0
- package/dist/{chunk-4RNF2DRG.js → chunk-XDEPXTBY.js} +0 -2
- package/dist/{chunk-3SZNUCXI.js → chunk-Y5QECJX7.js} +223 -16
- package/dist/collab/rebase.d.ts +2 -1
- package/dist/collab/rebase.d.ts.map +1 -1
- package/dist/collab/rebase.js +20 -5
- package/dist/components/brandguide/ColorsEditable.d.ts.map +1 -1
- package/dist/components/chat/ChatPanel.d.ts.map +1 -1
- package/dist/components/chat/ChatWidget.d.ts.map +1 -1
- package/dist/components/docfile/DocFilePane.d.ts.map +1 -1
- package/dist/components/editor/ChildBlockWrapper.d.ts.map +1 -1
- package/dist/components/editor/ConflictDialog.d.ts.map +1 -1
- package/dist/components/editor/DragHandle.d.ts +12 -2
- package/dist/components/editor/DragHandle.d.ts.map +1 -1
- package/dist/components/editor/DropEdgeIndicator.d.ts +15 -6
- package/dist/components/editor/DropEdgeIndicator.d.ts.map +1 -1
- package/dist/components/editor/NavGroupRow.d.ts +4 -1
- package/dist/components/editor/NavGroupRow.d.ts.map +1 -1
- package/dist/components/editor/PagesModal.d.ts.map +1 -1
- package/dist/components/editor/SectionWrapper.d.ts +1 -1
- package/dist/components/editor/SectionWrapper.d.ts.map +1 -1
- package/dist/components/editor/SettingsForm.d.ts.map +1 -1
- package/dist/components/editor/TagIndicator.d.ts +15 -0
- package/dist/components/editor/TagIndicator.d.ts.map +1 -0
- package/dist/components/editor/index.js +148 -77
- package/dist/components/primitives/DocumentDropZone.d.ts +1 -1
- package/dist/components/primitives/EditableGrid.d.ts.map +1 -1
- package/dist/components/primitives/EditableList.d.ts.map +1 -1
- package/dist/components/primitives/HeadingSection.d.ts +4 -1
- package/dist/components/primitives/HeadingSection.d.ts.map +1 -1
- package/dist/components/primitives/ResolvedMedia.d.ts +5 -1
- package/dist/components/primitives/ResolvedMedia.d.ts.map +1 -1
- package/dist/components/primitives/{defineHeadingSection.d.ts → define-heading-section.d.ts} +1 -1
- package/dist/components/primitives/define-heading-section.d.ts.map +1 -0
- package/dist/components/primitives/{gridDrop.d.ts → grid-drop.d.ts} +1 -1
- package/dist/components/primitives/grid-drop.d.ts.map +1 -0
- package/dist/components/primitives/index.d.ts +1 -1
- package/dist/components/primitives/index.d.ts.map +1 -1
- package/dist/components/primitives/index.js +17 -154
- package/dist/components/sections/Button/CTAButton.d.ts.map +1 -1
- package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts +2 -6
- package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts.map +1 -1
- package/dist/components/sections/DoDontMedia/index.d.ts +8 -0
- package/dist/components/sections/DoDontMedia/index.d.ts.map +1 -1
- package/dist/components/sections/IconList/IconList.d.ts +2 -1
- package/dist/components/sections/IconList/IconList.d.ts.map +1 -1
- package/dist/components/sections/IconList/IconListSettings.d.ts +2 -1
- package/dist/components/sections/IconList/IconListSettings.d.ts.map +1 -1
- package/dist/components/sections/IconList/index.d.ts +1 -0
- package/dist/components/sections/IconList/index.d.ts.map +1 -1
- package/dist/components/sections/Media/MediaBlock.d.ts +2 -1
- package/dist/components/sections/Media/MediaBlock.d.ts.map +1 -1
- package/dist/components/sections/Media/index.d.ts +8 -0
- package/dist/components/sections/Media/index.d.ts.map +1 -1
- package/dist/components/sections/Reference/ReferenceList.d.ts +35 -0
- package/dist/components/sections/Reference/ReferenceList.d.ts.map +1 -0
- package/dist/components/sections/Reference/ReferenceSettings.d.ts +12 -0
- package/dist/components/sections/Reference/ReferenceSettings.d.ts.map +1 -0
- package/dist/components/sections/Reference/index.d.ts +9 -0
- package/dist/components/sections/Reference/index.d.ts.map +1 -0
- package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts +38 -0
- package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts.map +1 -0
- package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts +20 -0
- package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts.map +1 -0
- package/dist/components/sections/SectionSummary/index.d.ts +33 -0
- package/dist/components/sections/SectionSummary/index.d.ts.map +1 -0
- package/dist/components/sections/all-sections.d.ts +53 -0
- package/dist/components/sections/all-sections.d.ts.map +1 -1
- package/dist/components/sections/brand-guide.d.ts +41 -2
- package/dist/components/sections/brand-guide.d.ts.map +1 -1
- package/dist/components/sections/brand-guide.js +12 -10
- package/dist/components/sections/core-sections.d.ts +14 -0
- package/dist/components/sections/core-sections.d.ts.map +1 -1
- package/dist/components/sections/register-schemas.js +19 -17
- package/dist/components/sections/register.js +19 -17
- package/dist/components/shared/BrandSwatchesContext.d.ts +9 -0
- package/dist/components/shared/BrandSwatchesContext.d.ts.map +1 -0
- package/dist/components/shared/Button.d.ts +11 -3
- package/dist/components/shared/Button.d.ts.map +1 -1
- package/dist/components/shared/Checkbox.d.ts +6 -0
- package/dist/components/shared/Checkbox.d.ts.map +1 -1
- package/dist/components/shared/ConfirmDialog.d.ts +25 -0
- package/dist/components/shared/ConfirmDialog.d.ts.map +1 -0
- package/dist/components/shared/ConfirmInline.d.ts +25 -0
- package/dist/components/shared/ConfirmInline.d.ts.map +1 -0
- package/dist/components/shared/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/shared/Fab.d.ts +11 -2
- package/dist/components/shared/Fab.d.ts.map +1 -1
- package/dist/components/shared/FabStack.d.ts +22 -0
- package/dist/components/shared/FabStack.d.ts.map +1 -0
- package/dist/components/shared/HistoryChangesModal.d.ts.map +1 -1
- package/dist/components/shared/HistoryPopover.d.ts.map +1 -1
- package/dist/components/shared/ImageBackgroundField.d.ts +9 -0
- package/dist/components/shared/ImageBackgroundField.d.ts.map +1 -0
- package/dist/components/shared/{UploadRejectionAlert.d.ts → InlineAlert.d.ts} +4 -2
- package/dist/components/shared/InlineAlert.d.ts.map +1 -0
- package/dist/components/shared/Input.d.ts +10 -0
- package/dist/components/shared/Input.d.ts.map +1 -1
- package/dist/components/shared/Navigation.d.ts +1 -0
- package/dist/components/shared/Navigation.d.ts.map +1 -1
- package/dist/components/shared/Notice.d.ts +10 -0
- package/dist/components/shared/Notice.d.ts.map +1 -0
- package/dist/components/shared/Popover.d.ts.map +1 -1
- package/dist/components/shared/ReferenceSourcesContext.d.ts +25 -0
- package/dist/components/shared/ReferenceSourcesContext.d.ts.map +1 -0
- package/dist/components/shared/Select.d.ts +3 -2
- package/dist/components/shared/Select.d.ts.map +1 -1
- package/dist/components/shared/SplitButton.d.ts.map +1 -1
- package/dist/components/shared/SummaryAnchorsContext.d.ts +10 -0
- package/dist/components/shared/SummaryAnchorsContext.d.ts.map +1 -0
- package/dist/components/shared/Textarea.d.ts +7 -0
- package/dist/components/shared/Textarea.d.ts.map +1 -1
- package/dist/components/shared/ToolbarFrame.d.ts +17 -0
- package/dist/components/shared/ToolbarFrame.d.ts.map +1 -0
- package/dist/components/shared/copy.d.ts +13 -0
- package/dist/components/shared/copy.d.ts.map +1 -0
- package/dist/components/shared/icons.d.ts +0 -12
- package/dist/components/shared/icons.d.ts.map +1 -1
- package/dist/components/shell/AudienceDetailsPanel.d.ts +7 -1
- package/dist/components/shell/AudienceDetailsPanel.d.ts.map +1 -1
- package/dist/components/shell/AudienceRow.d.ts.map +1 -1
- package/dist/components/shell/BugReportFAB.d.ts +7 -1
- package/dist/components/shell/BugReportFAB.d.ts.map +1 -1
- package/dist/components/shell/CredentialList.d.ts.map +1 -1
- package/dist/components/shell/DocInspector.d.ts.map +1 -1
- package/dist/components/shell/DocumentEditorOverlay.d.ts.map +1 -1
- package/dist/components/shell/EditorContext.d.ts +4 -0
- package/dist/components/shell/EditorContext.d.ts.map +1 -1
- package/dist/components/shell/EditorLoginForm.d.ts.map +1 -1
- package/dist/components/shell/EditorModal.d.ts.map +1 -1
- package/dist/components/shell/EditorShell.d.ts.map +1 -1
- package/dist/components/shell/HistoryToolbar.d.ts.map +1 -1
- package/dist/components/shell/MediaFolderTile.d.ts +4 -1
- package/dist/components/shell/MediaFolderTile.d.ts.map +1 -1
- package/dist/components/shell/MediaLibraryModal.d.ts.map +1 -1
- package/dist/components/shell/RestoreModal.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsChatbot.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsDisplay.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsModal.d.ts +3 -1
- package/dist/components/shell/SiteSettingsModal.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsTags.d.ts +13 -0
- package/dist/components/shell/SiteSettingsTags.d.ts.map +1 -0
- package/dist/components/shell/SiteSettingsUsers.d.ts.map +1 -1
- package/dist/components/shell/ViewerLoginForm.d.ts.map +1 -1
- package/dist/components/shell/{blockMoveDispatch.d.ts → block-move-dispatch.d.ts} +1 -1
- package/dist/components/shell/block-move-dispatch.d.ts.map +1 -0
- package/dist/components/shell/reference-sources.d.ts +22 -0
- package/dist/components/shell/reference-sources.d.ts.map +1 -0
- package/dist/deck/index.d.ts +2 -2
- package/dist/deck/index.d.ts.map +1 -1
- package/dist/deck/index.js +1 -3
- package/dist/deck-builder/index.js +11 -18
- package/dist/document/index.d.ts +2 -2
- package/dist/document/index.d.ts.map +1 -1
- package/dist/hooks/useBlockDnd.d.ts +11 -0
- package/dist/hooks/useBlockDnd.d.ts.map +1 -1
- package/dist/hooks/useBuildStatus.d.ts +1 -1
- package/dist/hooks/useBuildStatus.d.ts.map +1 -1
- package/dist/hooks/useDocumentUploads.d.ts +1 -1
- package/dist/hooks/useDocumentUploads.d.ts.map +1 -1
- package/dist/hooks/useEditorPersistence.d.ts +5 -1
- package/dist/hooks/useEditorPersistence.d.ts.map +1 -1
- package/dist/hooks/useEditorPublish.d.ts +2 -2
- package/dist/hooks/useEditorPublish.d.ts.map +1 -1
- package/dist/hooks/useNotice.d.ts +19 -0
- package/dist/hooks/useNotice.d.ts.map +1 -0
- package/dist/hooks/useSortableNavRow.d.ts +11 -0
- package/dist/hooks/useSortableNavRow.d.ts.map +1 -1
- package/dist/hooks/useSortableRow.d.ts +11 -0
- package/dist/hooks/useSortableRow.d.ts.map +1 -1
- package/dist/hooks/useStackedEscape.d.ts +32 -0
- package/dist/hooks/useStackedEscape.d.ts.map +1 -0
- package/dist/index.js +67 -49
- package/dist/lib/audience-secret.js +2 -2
- package/dist/lib/block-dnd.d.ts +5 -0
- package/dist/lib/block-dnd.d.ts.map +1 -1
- package/dist/lib/block-move.d.ts.map +1 -1
- package/dist/lib/brand-swatches.d.ts +12 -0
- package/dist/lib/brand-swatches.d.ts.map +1 -0
- package/dist/lib/container-ops.d.ts +3 -2
- package/dist/lib/container-ops.d.ts.map +1 -1
- package/dist/lib/dexie.d.ts.map +1 -1
- package/dist/lib/dexie.js +9 -1
- package/dist/lib/env.d.ts +4 -0
- package/dist/lib/env.d.ts.map +1 -1
- package/dist/lib/env.js +5 -3
- package/dist/lib/events.d.ts +1 -2
- package/dist/lib/events.d.ts.map +1 -1
- package/dist/lib/image-background.d.ts +8 -0
- package/dist/lib/image-background.d.ts.map +1 -0
- package/dist/lib/index-ops.js +3 -3
- package/dist/lib/index.d.ts +6 -4
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +29 -21
- package/dist/lib/loader.d.ts +21 -7
- package/dist/lib/loader.d.ts.map +1 -1
- package/dist/lib/nav-tree.d.ts +1 -0
- package/dist/lib/nav-tree.d.ts.map +1 -1
- package/dist/lib/nav.d.ts +38 -0
- package/dist/lib/nav.d.ts.map +1 -1
- package/dist/lib/platform-broker.d.ts +4 -2
- package/dist/lib/platform-broker.d.ts.map +1 -1
- package/dist/lib/platform-broker.js +21 -13
- package/dist/lib/reference-type.d.ts +2 -0
- package/dist/lib/reference-type.d.ts.map +1 -0
- package/dist/lib/reference-validation.d.ts +31 -0
- package/dist/lib/reference-validation.d.ts.map +1 -0
- package/dist/lib/reference-validation.js +39 -0
- package/dist/lib/references.d.ts +74 -0
- package/dist/lib/references.d.ts.map +1 -0
- package/dist/lib/registry.d.ts +35 -0
- package/dist/lib/registry.d.ts.map +1 -1
- package/dist/lib/{safeRedirect.d.ts → safe-redirect.d.ts} +1 -1
- package/dist/lib/safe-redirect.d.ts.map +1 -0
- package/dist/lib/tags.d.ts +58 -0
- package/dist/lib/tags.d.ts.map +1 -0
- package/dist/lib/theme-vars.d.ts +9 -0
- package/dist/lib/theme-vars.d.ts.map +1 -1
- package/dist/media/index.d.ts +1 -1
- package/dist/media/index.d.ts.map +1 -1
- package/dist/media/index.js +8 -4
- package/dist/media/resolve.d.ts +2 -0
- package/dist/media/resolve.d.ts.map +1 -1
- package/dist/media/utils.d.ts +2 -0
- package/dist/media/utils.d.ts.map +1 -1
- package/dist/media/{videoPoster.d.ts → video-poster.d.ts} +1 -1
- package/dist/media/video-poster.d.ts.map +1 -0
- package/dist/schemas/audience.js +2 -2
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +14 -8
- package/dist/schemas/shared.d.ts +26 -0
- package/dist/schemas/shared.d.ts.map +1 -1
- package/dist/schemas/site-config.d.ts +7 -0
- package/dist/schemas/site-config.d.ts.map +1 -1
- package/dist/schemas/tags.d.ts +27 -0
- package/dist/schemas/tags.d.ts.map +1 -0
- package/dist/storage/index.js +1 -1
- package/dist/types/database.d.ts +8 -0
- package/dist/types/database.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/auth/cookies.ts +111 -0
- package/src/auth/types.ts +1 -0
- package/src/collab/rebase.ts +26 -2
- package/src/components/brandguide/ColorSwatchSettings.tsx +1 -1
- package/src/components/brandguide/ColorsEditable.tsx +1 -0
- package/src/components/chat/ChatPanel.tsx +2 -3
- package/src/components/chat/ChatWidget.tsx +7 -7
- package/src/components/docfile/DocFilePane.tsx +4 -12
- package/src/components/editor/ChildBlockWrapper.tsx +13 -19
- package/src/components/editor/ConflictDialog.tsx +27 -35
- package/src/components/editor/DeleteButton.tsx +2 -2
- package/src/components/editor/DragHandle.tsx +16 -3
- package/src/components/editor/DropEdgeIndicator.tsx +36 -10
- package/src/components/editor/InsertButton.tsx +2 -2
- package/src/components/editor/NavGroupRow.tsx +43 -14
- package/src/components/editor/PagesModal.tsx +99 -26
- package/src/components/editor/SectionWrapper.tsx +64 -23
- package/src/components/editor/SettingsButton.tsx +2 -2
- package/src/components/editor/SettingsForm.tsx +19 -2
- package/src/components/editor/StatusIndicator.tsx +4 -4
- package/src/components/editor/TagIndicator.tsx +80 -0
- package/src/components/primitives/DocumentDropZone.tsx +1 -1
- package/src/components/primitives/EditableGrid.tsx +15 -14
- package/src/components/primitives/EditableList.tsx +27 -74
- package/src/components/primitives/HeadingSection.tsx +5 -2
- package/src/components/primitives/ResolvedMedia.tsx +13 -0
- package/src/components/primitives/{defineHeadingSection.tsx → define-heading-section.tsx} +1 -0
- package/src/components/primitives/index.ts +1 -1
- package/src/components/primitives/useEditablePlainText.ts +5 -5
- package/src/components/sections/Button/CTAButton.tsx +3 -1
- package/src/components/sections/DoDontMedia/DoDontMediaBlock.tsx +4 -4
- package/src/components/sections/DoDontMedia/index.tsx +12 -3
- package/src/components/sections/IconList/DoDontToggle.tsx +2 -2
- package/src/components/sections/IconList/IconList.tsx +70 -37
- package/src/components/sections/IconList/IconListSettings.tsx +55 -17
- package/src/components/sections/IconList/index.tsx +10 -3
- package/src/components/sections/LinkHeading/index.tsx +1 -1
- package/src/components/sections/Media/MediaBlock.tsx +13 -2
- package/src/components/sections/Media/index.tsx +12 -4
- package/src/components/sections/Reference/ReferenceList.tsx +214 -0
- package/src/components/sections/Reference/ReferenceSettings.tsx +159 -0
- package/src/components/sections/Reference/index.tsx +47 -0
- package/src/components/sections/SectionSummary/SectionSummaryBlock.tsx +476 -0
- package/src/components/sections/SectionSummary/SectionSummarySettings.tsx +126 -0
- package/src/components/sections/SectionSummary/index.tsx +149 -0
- package/src/components/sections/SubHeading/index.tsx +1 -1
- package/src/components/sections/SubSubHeading/index.tsx +1 -1
- package/src/components/sections/brand-guide.ts +4 -3
- package/src/components/sections/core-sections.ts +2 -0
- package/src/components/shared/BrandSwatchesContext.ts +13 -0
- package/src/components/shared/Button.tsx +47 -34
- package/src/components/shared/Checkbox.tsx +21 -12
- package/src/components/shared/ConfirmDialog.tsx +87 -0
- package/src/components/shared/ConfirmInline.tsx +90 -0
- package/src/components/shared/ErrorBoundary.tsx +6 -18
- package/src/components/shared/Fab.tsx +15 -5
- package/src/components/shared/FabStack.tsx +28 -0
- package/src/components/shared/HistoryChangesModal.tsx +43 -41
- package/src/components/shared/HistoryPopover.tsx +7 -20
- package/src/components/shared/ImageBackgroundField.tsx +92 -0
- package/src/components/shared/{UploadRejectionAlert.tsx → InlineAlert.tsx} +21 -5
- package/src/components/shared/Input.tsx +23 -7
- package/src/components/shared/Navigation.tsx +48 -35
- package/src/components/shared/Notice.tsx +59 -0
- package/src/components/shared/Popover.tsx +7 -11
- package/src/components/shared/ReferenceSourcesContext.ts +27 -0
- package/src/components/shared/Select.tsx +5 -2
- package/src/components/shared/SplitButton.tsx +11 -17
- package/src/components/shared/SummaryAnchorsContext.ts +11 -0
- package/src/components/shared/Textarea.tsx +17 -2
- package/src/components/shared/ToolbarFrame.tsx +28 -0
- package/src/components/shared/VideoSourceField.tsx +1 -1
- package/src/components/shared/copy.ts +18 -0
- package/src/components/shared/icons.tsx +1 -17
- package/src/components/shell/AudienceAddForm.tsx +2 -2
- package/src/components/shell/AudienceDetailsPanel.tsx +23 -5
- package/src/components/shell/AudienceRow.tsx +22 -15
- package/src/components/shell/BugReportFAB.tsx +50 -40
- package/src/components/shell/CredentialList.tsx +33 -13
- package/src/components/shell/DocInspector.tsx +3 -12
- package/src/components/shell/DocumentEditorOverlay.tsx +33 -23
- package/src/components/shell/EditorContext.tsx +7 -0
- package/src/components/shell/EditorLoginForm.tsx +26 -36
- package/src/components/shell/EditorModal.tsx +8 -10
- package/src/components/shell/EditorShell.tsx +499 -339
- package/src/components/shell/HistoryToolbar.tsx +24 -26
- package/src/components/shell/MediaFolderTile.tsx +8 -3
- package/src/components/shell/MediaLibraryModal.tsx +59 -60
- package/src/components/shell/ProcessingIndicator.tsx +2 -2
- package/src/components/shell/RestoreModal.tsx +17 -16
- package/src/components/shell/SetPasswordForm.tsx +3 -3
- package/src/components/shell/SiteSettingsChatbot.tsx +61 -42
- package/src/components/shell/SiteSettingsDisplay.tsx +20 -21
- package/src/components/shell/SiteSettingsModal.tsx +24 -2
- package/src/components/shell/SiteSettingsTags.tsx +143 -0
- package/src/components/shell/SiteSettingsUsers.tsx +85 -28
- package/src/components/shell/SiteSettingsViewerAccess.tsx +2 -2
- package/src/components/shell/ViewerLoginForm.tsx +5 -4
- package/src/components/shell/reference-sources.ts +36 -0
- package/src/deck/index.ts +2 -2
- package/src/document/index.ts +2 -2
- package/src/hooks/useBlockDnd.ts +11 -0
- package/src/hooks/useBuildStatus.ts +53 -6
- package/src/hooks/useDocumentUploads.ts +1 -1
- package/src/hooks/useEditorPersistence.ts +141 -35
- package/src/hooks/useEditorPublish.ts +18 -27
- package/src/hooks/useMediaPipeline.ts +1 -1
- package/src/hooks/useNotice.ts +45 -0
- package/src/hooks/useSortableNavRow.ts +11 -0
- package/src/hooks/useSortableRow.ts +22 -2
- package/src/hooks/useStackedEscape.ts +62 -0
- package/src/lib/block-dnd.ts +6 -1
- package/src/lib/block-move.ts +3 -0
- package/src/lib/brand-swatches.ts +32 -0
- package/src/lib/container-ops.ts +5 -3
- package/src/lib/dexie.ts +15 -1
- package/src/lib/env.ts +9 -0
- package/src/lib/events.ts +1 -2
- package/src/lib/image-background.ts +31 -0
- package/src/lib/index.ts +5 -4
- package/src/lib/loader.ts +54 -55
- package/src/lib/nav-tree.ts +71 -0
- package/src/lib/nav.ts +196 -36
- package/src/lib/platform-broker.ts +32 -14
- package/src/lib/reference-type.ts +3 -0
- package/src/lib/reference-validation.ts +69 -0
- package/src/lib/references.ts +130 -0
- package/src/lib/registry.ts +37 -0
- package/src/lib/tags.ts +148 -0
- package/src/lib/theme-vars.ts +23 -0
- package/src/media/index.ts +1 -1
- package/src/media/resolve.ts +3 -1
- package/src/media/utils.ts +18 -0
- package/src/media/{videoPoster.ts → video-poster.ts} +2 -2
- package/src/schemas/index.ts +1 -0
- package/src/schemas/shared.ts +24 -1
- package/src/schemas/site-config.ts +9 -1
- package/src/schemas/tags.ts +33 -0
- package/src/storage/types.ts +1 -1
- package/src/types/database.ts +6 -0
- package/dist/chunk-BR4MIPTM.js +0 -138
- package/dist/chunk-DNY72JZN.js +0 -86
- package/dist/chunk-F2LYQPXV.js +0 -77
- package/dist/chunk-TALRVOGO.js +0 -128
- package/dist/components/primitives/defineHeadingSection.d.ts.map +0 -1
- package/dist/components/primitives/gridDrop.d.ts.map +0 -1
- package/dist/components/shared/UploadRejectionAlert.d.ts.map +0 -1
- package/dist/components/shell/BuildStatusIndicator.d.ts +0 -7
- package/dist/components/shell/BuildStatusIndicator.d.ts.map +0 -1
- package/dist/components/shell/blockMoveDispatch.d.ts.map +0 -1
- package/dist/hooks/index.d.ts +0 -9
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/lib/grid.d.ts +0 -2
- package/dist/lib/grid.d.ts.map +0 -1
- package/dist/lib/safeRedirect.d.ts.map +0 -1
- package/dist/media/videoPoster.d.ts.map +0 -1
- package/src/components/brandguide/ColorSwatchSettings.d.ts.map +0 -1
- package/src/components/brandguide/Colors.d.ts.map +0 -1
- package/src/components/primitives/CustomParagraph.d.ts.map +0 -1
- package/src/components/primitives/EditableGrid.d.ts.map +0 -1
- package/src/components/primitives/EditablePlainText.d.ts.map +0 -1
- package/src/components/primitives/EditableRichText.d.ts.map +0 -1
- package/src/components/primitives/HeadingSection.d.ts.map +0 -1
- package/src/components/primitives/IconPicker.d.ts.map +0 -1
- package/src/components/primitives/LinkPopover.d.ts.map +0 -1
- package/src/components/primitives/MediaSettingsForms.d.ts.map +0 -1
- package/src/components/primitives/ResolvedMedia.d.ts.map +0 -1
- package/src/components/primitives/RichTextToolbar.d.ts.map +0 -1
- package/src/components/primitives/tiptap-presets.d.ts.map +0 -1
- package/src/components/primitives/useEditableCollection.d.ts.map +0 -1
- package/src/components/primitives/useEditablePlainText.d.ts.map +0 -1
- package/src/components/primitives/useEditableRichText.d.ts.map +0 -1
- package/src/components/sections/Button/CTAButton.d.ts.map +0 -1
- package/src/components/sections/Button/index.d.ts.map +0 -1
- package/src/components/sections/Colors/index.d.ts.map +0 -1
- package/src/components/sections/IconList/IconList.d.ts.map +0 -1
- package/src/components/sections/IconList/IconListSettings.d.ts.map +0 -1
- package/src/components/sections/IconList/index.d.ts.map +0 -1
- package/src/components/sections/LinkHeading/index.d.ts.map +0 -1
- package/src/components/sections/Prose/Prose.d.ts.map +0 -1
- package/src/components/sections/Prose/index.d.ts.map +0 -1
- package/src/components/sections/SubHeading/index.d.ts.map +0 -1
- package/src/components/sections/SubSubHeading/index.d.ts.map +0 -1
- package/src/components/sections/register-schemas.d.ts.map +0 -1
- package/src/components/shared/Button.d.ts.map +0 -1
- package/src/components/shared/Checkbox.d.ts.map +0 -1
- package/src/components/shared/FormLabel.d.ts.map +0 -1
- package/src/components/shared/IconButton.d.ts.map +0 -1
- package/src/components/shared/Input.d.ts.map +0 -1
- package/src/components/shared/Select.d.ts.map +0 -1
- package/src/components/shared/icons.d.ts.map +0 -1
- package/src/components/shell/BuildStatusIndicator.tsx +0 -59
- package/src/components/shell/MediaLibraryContext.d.ts.map +0 -1
- package/src/hooks/index.ts +0 -8
- package/src/hooks/useResolvedMedia.d.ts.map +0 -1
- package/src/lib/cn.d.ts.map +0 -1
- package/src/lib/grid.d.ts.map +0 -1
- package/src/lib/grid.ts +0 -7
- package/src/lib/icons.d.ts.map +0 -1
- package/src/lib/loader.d.ts.map +0 -1
- package/src/lib/nav.d.ts.map +0 -1
- package/src/lib/registry.d.ts.map +0 -1
- package/src/lib/sanitize.d.ts.map +0 -1
- package/src/media/github.d.ts.map +0 -1
- package/src/media/index.d.ts.map +0 -1
- package/src/media/queue.d.ts.map +0 -1
- package/src/media/resolve.d.ts.map +0 -1
- package/src/media/types.d.ts.map +0 -1
- package/src/media/utils.d.ts.map +0 -1
- package/src/media/videoPoster.d.ts.map +0 -1
- package/src/schemas/auth.d.ts.map +0 -1
- package/src/schemas/media-grid-options.d.ts.map +0 -1
- package/src/schemas/media.d.ts.map +0 -1
- package/src/schemas/sections.d.ts.map +0 -1
- package/src/schemas/shared.d.ts.map +0 -1
- package/src/schemas/site-config.d.ts.map +0 -1
- /package/dist/{chunk-B7VBSE5X.js → chunk-3JDTXOIG.js} +0 -0
- /package/dist/{chunk-CXZ5YJG4.js → chunk-L45X7DKX.js} +0 -0
- /package/src/components/primitives/{gridDrop.ts → grid-drop.ts} +0 -0
- /package/src/components/shell/{blockMoveDispatch.ts → block-move-dispatch.ts} +0 -0
- /package/src/lib/{safeRedirect.ts → safe-redirect.ts} +0 -0
package/src/lib/tags.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { TagEntry } from "../schemas/tags";
|
|
2
|
+
import type { SiteIndex } from "../schemas/site-config";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Repair the tag sidecar against the current section set.
|
|
6
|
+
*
|
|
7
|
+
* Total, pure, and idempotent — the same contract as reconcileNav, for the same
|
|
8
|
+
* reason: tags.json survives writers that do not know it exists, so it can name
|
|
9
|
+
* sections an older writer (or an agent) has since deleted, and the repair has
|
|
10
|
+
* to happen on read rather than by rejecting content. It is deliberately NOT a
|
|
11
|
+
* schema refinement: parse-rejecting content would leave the editor unable to
|
|
12
|
+
* load the site it needs to repair it.
|
|
13
|
+
*
|
|
14
|
+
* Drops assignments to sections absent from `sections`, duplicate section ids
|
|
15
|
+
* within a tag, duplicate tag ids (first wins), and tags with no usable id. A
|
|
16
|
+
* tag with no assignments left is KEPT — the registry outlives its sections.
|
|
17
|
+
* Every entry is rebuilt key by key, so the output always parses as a
|
|
18
|
+
* TagsFile and never shares structure with the input (the editor holds this in
|
|
19
|
+
* React state, where a shared array would let a later edit mutate prior state).
|
|
20
|
+
*/
|
|
21
|
+
export function reconcileTags(entries: TagEntry[], sections: SiteIndex["sections"]): TagEntry[] {
|
|
22
|
+
const entryList = Array.isArray(entries) ? entries : [];
|
|
23
|
+
const validIds = new Set(sections && typeof sections === "object" ? Object.keys(sections) : []);
|
|
24
|
+
|
|
25
|
+
const seenTagIds = new Set<string>();
|
|
26
|
+
const result: TagEntry[] = [];
|
|
27
|
+
for (const entry of entryList) {
|
|
28
|
+
if (!entry || typeof entry !== "object") continue;
|
|
29
|
+
if (typeof entry.id !== "string" || entry.id === "" || seenTagIds.has(entry.id)) continue;
|
|
30
|
+
seenTagIds.add(entry.id);
|
|
31
|
+
|
|
32
|
+
const claimed = Array.isArray(entry.sectionIds) ? entry.sectionIds : [];
|
|
33
|
+
const sectionIds: string[] = [];
|
|
34
|
+
for (const id of claimed) {
|
|
35
|
+
if (typeof id === "string" && validIds.has(id) && !sectionIds.includes(id)) sectionIds.push(id);
|
|
36
|
+
}
|
|
37
|
+
result.push({ id: entry.id, label: typeof entry.label === "string" ? entry.label : "", sectionIds });
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The ONLY sanctioned way to read the tags. Always reconciles, so callers never
|
|
44
|
+
* reason about whether index.tags is present, stale, or names deleted sections.
|
|
45
|
+
*/
|
|
46
|
+
export function siteTags(index: SiteIndex): TagEntry[] {
|
|
47
|
+
return reconcileTags(index.tags ?? [], index.sections);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Display fallback for blank tag labels — mirrors groupDisplayLabel. */
|
|
51
|
+
export function tagDisplayLabel(label: string): string {
|
|
52
|
+
return label || "Untitled tag";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** The tag already using this name (case- and whitespace-insensitive) — what
|
|
56
|
+
* an inline create reuses, and what the registry refuses to duplicate. */
|
|
57
|
+
export function findTagByLabel(tags: TagEntry[], label: string): TagEntry | null {
|
|
58
|
+
const wanted = label.trim().toLowerCase();
|
|
59
|
+
if (!wanted) return null;
|
|
60
|
+
return tags.find((t) => t.label.trim().toLowerCase() === wanted) ?? null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function addTag(index: SiteIndex, id: string, label: string, sectionId?: string): SiteIndex {
|
|
64
|
+
const tags = siteTags(index);
|
|
65
|
+
if (tags.some((t) => t.id === id)) return { ...index, tags };
|
|
66
|
+
return { ...index, tags: reconcileTags([...tags, { id, label, sectionIds: sectionId ? [sectionId] : [] }], index.sections) };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function renameTag(index: SiteIndex, id: string, label: string): SiteIndex {
|
|
70
|
+
return { ...index, tags: siteTags(index).map((t) => (t.id === id ? { ...t, label } : t)) };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function deleteTag(index: SiteIndex, id: string): SiteIndex {
|
|
74
|
+
return { ...index, tags: siteTags(index).filter((t) => t.id !== id) };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function setSectionTagged(index: SiteIndex, sectionId: string, tagId: string, tagged: boolean): SiteIndex {
|
|
78
|
+
return {
|
|
79
|
+
...index,
|
|
80
|
+
tags: siteTags(index).map((t) => {
|
|
81
|
+
if (t.id !== tagId) return t;
|
|
82
|
+
const without = t.sectionIds.filter((id) => id !== sectionId);
|
|
83
|
+
return { ...t, sectionIds: tagged ? [...without, sectionId] : without };
|
|
84
|
+
}),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Three-way merge of the tag sidecar for the collab rebase.
|
|
90
|
+
*
|
|
91
|
+
* Nav's rebase rule is "the remote's persisted tree wins", which is safe there
|
|
92
|
+
* because grouping is edited rarely. Tags are edited from every section's
|
|
93
|
+
* chrome, so the same rule would silently drop unsaved tagging whenever a peer
|
|
94
|
+
* saved anything at all. Instead, local edits are diffed against the clean
|
|
95
|
+
* baseline (`base`) and replayed onto the remote:
|
|
96
|
+
* - a tag created locally is appended; one deleted locally is dropped;
|
|
97
|
+
* - a local rename wins, otherwise the remote label stands;
|
|
98
|
+
* - per (tag, section) pair, a local add or remove is replayed;
|
|
99
|
+
* - a tag the REMOTE deleted stays deleted, local assignments included —
|
|
100
|
+
* persisted state beats unsaved edits to a tag that no longer exists.
|
|
101
|
+
* With no baseline to diff against, the remote wins (nav's rule). A remote with
|
|
102
|
+
* no tags at all (an older server that does not attach the sidecar) leaves the
|
|
103
|
+
* local tags intact rather than wiping them. Inputs are never mutated; the
|
|
104
|
+
* result is not reconciled — readers do that through siteTags.
|
|
105
|
+
*/
|
|
106
|
+
export function mergeTags(args: {
|
|
107
|
+
base: TagEntry[] | undefined;
|
|
108
|
+
local: TagEntry[] | undefined;
|
|
109
|
+
remote: TagEntry[] | undefined;
|
|
110
|
+
}): TagEntry[] | undefined {
|
|
111
|
+
const { base, local, remote } = args;
|
|
112
|
+
if (remote === undefined) return local?.map((t) => ({ ...t, sectionIds: [...t.sectionIds] }));
|
|
113
|
+
if (base === undefined || local === undefined) return remote.map((t) => ({ ...t, sectionIds: [...t.sectionIds] }));
|
|
114
|
+
|
|
115
|
+
// First occurrence wins, matching reconcileTags — `base` is an unreconciled
|
|
116
|
+
// server read, and a last-wins map would invent a diff against a duplicate.
|
|
117
|
+
const firstById = (tags: TagEntry[]) => {
|
|
118
|
+
const byId = new Map<string, TagEntry>();
|
|
119
|
+
for (const t of tags) if (!byId.has(t.id)) byId.set(t.id, t);
|
|
120
|
+
return byId;
|
|
121
|
+
};
|
|
122
|
+
const baseById = firstById(base);
|
|
123
|
+
const localById = firstById(local);
|
|
124
|
+
const remoteIds = new Set(remote.map((t) => t.id));
|
|
125
|
+
|
|
126
|
+
const result: TagEntry[] = [];
|
|
127
|
+
for (const r of remote) {
|
|
128
|
+
const b = baseById.get(r.id);
|
|
129
|
+
const l = localById.get(r.id);
|
|
130
|
+
if (b && !l) continue; // deleted locally
|
|
131
|
+
const members = [...r.sectionIds];
|
|
132
|
+
let label = r.label;
|
|
133
|
+
if (b && l) {
|
|
134
|
+
if (l.label !== b.label) label = l.label;
|
|
135
|
+
for (const id of l.sectionIds) if (!b.sectionIds.includes(id) && !members.includes(id)) members.push(id);
|
|
136
|
+
for (const id of b.sectionIds) {
|
|
137
|
+
if (l.sectionIds.includes(id)) continue;
|
|
138
|
+
const at = members.indexOf(id);
|
|
139
|
+
if (at !== -1) members.splice(at, 1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
result.push({ id: r.id, label, sectionIds: members });
|
|
143
|
+
}
|
|
144
|
+
for (const l of local) {
|
|
145
|
+
if (!remoteIds.has(l.id) && !baseById.has(l.id)) result.push({ ...l, sectionIds: [...l.sectionIds] });
|
|
146
|
+
}
|
|
147
|
+
return result;
|
|
148
|
+
}
|
package/src/lib/theme-vars.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { SiteConfig } from "../schemas/site-config";
|
|
2
2
|
import { suggestAccessibleOn } from "./contrast";
|
|
3
|
+
import { cornerRadiusValue } from "./corner-radius";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Computes the CSS value for the brand `--color-primary` / `--color-primary-contrast`
|
|
@@ -50,3 +51,25 @@ export function onPrimaryVarValue(c?: Partial<ThemeColorConfig> | null): string
|
|
|
50
51
|
const dark = c?.primaryColorDark ? suggestAccessibleOn(c.primaryColorDark) : null;
|
|
51
52
|
return lightDark(light, dark, c?.darkMode === "optional");
|
|
52
53
|
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The full inline `<html style>` string both `Layout.astro` and
|
|
57
|
+
* `LoginLayout.astro` set at SSR time — one assembly point for the 9 custom
|
|
58
|
+
* properties instead of the same template literal copied into both files.
|
|
59
|
+
* Byte-for-byte identical to what those files built inline before this
|
|
60
|
+
* existed; changing the property order or defaults here is a client-facing
|
|
61
|
+
* change to every site's `<html>` tag, not a refactor.
|
|
62
|
+
*/
|
|
63
|
+
export function themeStyle(siteConfig?: SiteConfig | null): string {
|
|
64
|
+
return (
|
|
65
|
+
`--color-primary: ${primaryVarValue(siteConfig)}; ` +
|
|
66
|
+
`--color-primary-contrast: ${accentVarValue(siteConfig)}; ` +
|
|
67
|
+
`--color-on-primary: ${onPrimaryVarValue(siteConfig)}; ` +
|
|
68
|
+
`--font-heading: ${siteConfig?.headingFont ?? "system-ui"}, system-ui, sans-serif; ` +
|
|
69
|
+
`--font-body: ${siteConfig?.bodyFont ?? "system-ui"}, system-ui, sans-serif; ` +
|
|
70
|
+
`--heading-text-transform: ${siteConfig?.uppercaseHeadings !== false ? "uppercase" : "none"}; ` +
|
|
71
|
+
`--subheading-text-transform: ${siteConfig?.uppercaseSubheadings !== false ? "uppercase" : "none"}; ` +
|
|
72
|
+
`--nav-text-transform: ${siteConfig?.uppercaseNavHeadings !== false ? "uppercase" : "none"}; ` +
|
|
73
|
+
`--radius-outer: ${cornerRadiusValue(siteConfig?.cornerRadius)};`
|
|
74
|
+
);
|
|
75
|
+
}
|
package/src/media/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ export * from "./provider";
|
|
|
5
5
|
export * from "./utils";
|
|
6
6
|
export * from "./queue";
|
|
7
7
|
export * from "./resolve";
|
|
8
|
-
export { generateVideoPoster } from "./
|
|
8
|
+
export { generateVideoPoster } from "./video-poster";
|
|
9
9
|
export { composePreviewImage, type PreviewImageInputs } from "./compose-preview";
|
|
10
10
|
|
|
11
11
|
const MEDIA_KEY = Symbol.for("@drawnagency/primitives/media");
|
package/src/media/resolve.ts
CHANGED
|
@@ -105,6 +105,7 @@ export interface ResolvedLogo {
|
|
|
105
105
|
darkUrl: string | null;
|
|
106
106
|
invertInDark: boolean;
|
|
107
107
|
showInNav: boolean;
|
|
108
|
+
hideTitle: boolean;
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
/**
|
|
@@ -117,7 +118,7 @@ export interface ResolvedLogo {
|
|
|
117
118
|
* both those tags resolve to `tag: "img"`.
|
|
118
119
|
*/
|
|
119
120
|
export function resolveLogo(
|
|
120
|
-
logo: { light: { imageId: string }; dark: { imageId: string } | null; invertInDark: boolean; showInNav: boolean } | null,
|
|
121
|
+
logo: { light: { imageId: string }; dark: { imageId: string } | null; invertInDark: boolean; showInNav: boolean; hideTitle: boolean } | null,
|
|
121
122
|
manifest: MediaManifest,
|
|
122
123
|
provider: MediaProvider,
|
|
123
124
|
): ResolvedLogo | null {
|
|
@@ -131,5 +132,6 @@ export function resolveLogo(
|
|
|
131
132
|
darkUrl,
|
|
132
133
|
invertInDark: logo.invertInDark,
|
|
133
134
|
showInNav: logo.showInNav,
|
|
135
|
+
hideTitle: logo.hideTitle,
|
|
134
136
|
};
|
|
135
137
|
}
|
package/src/media/utils.ts
CHANGED
|
@@ -48,6 +48,24 @@ export function mimeToExt(mime: string): string {
|
|
|
48
48
|
return MIME_TO_EXT[mime] ?? "bin";
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
// Editor preview URL for a library item, matching what /api/media/[id] serves:
|
|
52
|
+
// SVGs carry kind "image" but have no webp variants, only original.svg; rasters
|
|
53
|
+
// get their smallest variant; animated and video items get their playable
|
|
54
|
+
// original (a <video> src, not a still). Null for a raster with no variants.
|
|
55
|
+
export function mediaThumbnailUrl(item: MediaItem): string | null {
|
|
56
|
+
if (item.mimeType === "image/svg+xml" || item.kind !== "image") {
|
|
57
|
+
return `/api/media/${item.id}/original.${mimeToExt(item.mimeType)}`;
|
|
58
|
+
}
|
|
59
|
+
if (item.variants.length === 0) return null;
|
|
60
|
+
const smallest = item.variants.reduce((a, b) => (a.width < b.width ? a : b));
|
|
61
|
+
return `/api/media/${item.id}/${smallest.width}.webp`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// For <img>-only previews (cover, logo): null unless the item is a still image.
|
|
65
|
+
export function imageThumbnailUrl(item: MediaItem | undefined): string | null {
|
|
66
|
+
return item?.kind === "image" ? mediaThumbnailUrl(item) : null;
|
|
67
|
+
}
|
|
68
|
+
|
|
51
69
|
export function displayFilenameExt(mime: string): string {
|
|
52
70
|
const ext = MIME_TO_EXT[mime];
|
|
53
71
|
return ext ? `.${ext}` : "";
|
|
@@ -26,7 +26,7 @@ export function generateVideoPoster(
|
|
|
26
26
|
}, 10_000);
|
|
27
27
|
|
|
28
28
|
video.addEventListener("error", () => {
|
|
29
|
-
safeReject(new Error("
|
|
29
|
+
safeReject(new Error("Couldn't load video for poster generation"));
|
|
30
30
|
}, { once: true });
|
|
31
31
|
|
|
32
32
|
video.muted = true;
|
|
@@ -56,7 +56,7 @@ export function generateVideoPoster(
|
|
|
56
56
|
settled = true;
|
|
57
57
|
cleanup();
|
|
58
58
|
if (!posterBlob) {
|
|
59
|
-
reject(new Error("
|
|
59
|
+
reject(new Error("Couldn't create poster blob"));
|
|
60
60
|
return;
|
|
61
61
|
}
|
|
62
62
|
resolve({ posterBlob, width: w, height: h, duration: video.duration });
|
package/src/schemas/index.ts
CHANGED
package/src/schemas/shared.ts
CHANGED
|
@@ -38,7 +38,7 @@ const BaseMediaRef = z.object({
|
|
|
38
38
|
.union([z.string(), z.array(z.string())])
|
|
39
39
|
.optional()
|
|
40
40
|
.describe("Optional caption: a single string, or multiple lines as an array of strings."),
|
|
41
|
-
background: z.string().optional().describe("
|
|
41
|
+
background: z.string().optional().describe("Legacy; not rendered. For a backdrop behind a media section's image, use the section's options.background."),
|
|
42
42
|
invertFrom: z
|
|
43
43
|
.string()
|
|
44
44
|
.optional()
|
|
@@ -91,6 +91,29 @@ export const HexColorSchema = z
|
|
|
91
91
|
.string()
|
|
92
92
|
.regex(/^#[0-9a-fA-F]{6}$/, "must be a 6-digit hex color");
|
|
93
93
|
|
|
94
|
+
const ImageBackgroundSurfaceSchema = z.enum(["none", "light", "dark"]);
|
|
95
|
+
export type ImageBackgroundSurface = z.infer<typeof ImageBackgroundSurfaceSchema>;
|
|
96
|
+
|
|
97
|
+
/** Per-placement backdrop painted behind an image (e.g. a dark plate under a
|
|
98
|
+
* white transparent logo). Absent = no backdrop. */
|
|
99
|
+
export const ImageBackgroundSchema = z.discriminatedUnion("mode", [
|
|
100
|
+
z.object({
|
|
101
|
+
mode: z.literal("theme").describe("Pick a site surface separately for light and dark mode."),
|
|
102
|
+
light: ImageBackgroundSurfaceSchema.describe(
|
|
103
|
+
"Backdrop in light mode: 'none', the site's light surface, or its dark surface.",
|
|
104
|
+
),
|
|
105
|
+
dark: ImageBackgroundSurfaceSchema.describe(
|
|
106
|
+
"Backdrop in dark mode: 'none', the site's light surface, or its dark surface.",
|
|
107
|
+
),
|
|
108
|
+
}),
|
|
109
|
+
z.object({
|
|
110
|
+
mode: z.literal("custom").describe("Use one custom color in both modes."),
|
|
111
|
+
color: HexColorSchema.describe("One backdrop color for both light and dark mode, as a 6-digit hex."),
|
|
112
|
+
}),
|
|
113
|
+
]);
|
|
114
|
+
|
|
115
|
+
export type ImageBackground = z.infer<typeof ImageBackgroundSchema>;
|
|
116
|
+
|
|
94
117
|
// Font-family names are interpolated raw into the `style` attribute on <html>
|
|
95
118
|
// (`--font-heading: ${headingFont}, ...`). Astro HTML-escapes the attribute, so
|
|
96
119
|
// the residual risk is CSS-declaration injection via `;`/`{}`. Allow only the
|
|
@@ -7,6 +7,7 @@ import { CORNER_RADIUS_OPTIONS } from "../lib/corner-radius";
|
|
|
7
7
|
// document options block onto PageSchema.
|
|
8
8
|
import { documentOptionsSchema } from "../document/engine/settings";
|
|
9
9
|
import type { NavEntry } from "./nav";
|
|
10
|
+
import type { TagEntry } from "./tags";
|
|
10
11
|
|
|
11
12
|
export const StatusSchema = z.enum(["draft", "live", "archived", "published"]).transform(
|
|
12
13
|
(val) => val === "published" ? "live" as const : val,
|
|
@@ -176,8 +177,12 @@ export const IndexSchema = RawIndexSchema.transform(normalizeRawIndex).pipe(Cano
|
|
|
176
177
|
* index.json. It is optional because most SiteIndex values (tests, legacy
|
|
177
178
|
* content, partial writes) have no nav — reads go through navEntries(), which
|
|
178
179
|
* reconciles a missing nav into a flat one.
|
|
180
|
+
*
|
|
181
|
+
* `tags` follows the same rules for the src/content/tags.json sidecar; read it
|
|
182
|
+
* only through siteTags() (lib/tags.ts). Absent means "not loaded", which every
|
|
183
|
+
* writer treats as "leave tags.json alone" — not as "no tags".
|
|
179
184
|
*/
|
|
180
|
-
export type SiteIndex = z.infer<typeof CanonicalIndexSchema> & { nav?: NavEntry[] };
|
|
185
|
+
export type SiteIndex = z.infer<typeof CanonicalIndexSchema> & { nav?: NavEntry[]; tags?: TagEntry[] };
|
|
181
186
|
|
|
182
187
|
/** Parse + normalize any raw index (legacy or canonical) to the canonical shape. */
|
|
183
188
|
export function normalizeSiteIndex(raw: unknown): SiteIndex {
|
|
@@ -292,6 +297,9 @@ export const SiteConfigSchema = z.object({
|
|
|
292
297
|
dark: z.object({ imageId: z.string() }).nullable().default(null),
|
|
293
298
|
invertInDark: z.boolean().default(false),
|
|
294
299
|
showInNav: z.boolean().default(true),
|
|
300
|
+
// A nav logo stands in for the site name by default; the toggle is for
|
|
301
|
+
// wordmark-less logos that still need the name spelled out.
|
|
302
|
+
hideTitle: z.boolean().default(true),
|
|
295
303
|
})
|
|
296
304
|
.nullable()
|
|
297
305
|
.default(null),
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The site's section tags, persisted to `src/content/tags.json`.
|
|
5
|
+
*
|
|
6
|
+
* A sidecar for the same reason nav.json is (see schemas/nav.ts): an older
|
|
7
|
+
* writer re-serializes the Zod-parsed index and silently deletes any key it
|
|
8
|
+
* does not know, so tags must never be a key on index.json or a section file.
|
|
9
|
+
*
|
|
10
|
+
* Each tag owns its assignments (`sectionIds`), so deleting a tag removes it
|
|
11
|
+
* from every section by construction; a deleted section is pruned by
|
|
12
|
+
* `reconcileTags` (lib/tags.ts). Array order is the registry's display order.
|
|
13
|
+
*/
|
|
14
|
+
export const TagEntrySchema = z.object({
|
|
15
|
+
id: z.string().min(1),
|
|
16
|
+
/** May be blank — agent-authored files can omit it; UI falls back to "Untitled tag". */
|
|
17
|
+
label: z.string().catch(""),
|
|
18
|
+
// Everything but `id` repairs rather than rejects. A rejected entry marks the
|
|
19
|
+
// read degraded, and a degraded tags.json refuses EVERY tags write until
|
|
20
|
+
// someone fixes the file by hand — far too heavy a price for one blank id in
|
|
21
|
+
// one tag's list, which reconcileTags would drop anyway.
|
|
22
|
+
sectionIds: z
|
|
23
|
+
.array(z.unknown())
|
|
24
|
+
.catch([])
|
|
25
|
+
.transform((ids) => ids.filter((id): id is string => typeof id === "string" && id !== "")),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const TagsFileSchema = z.object({
|
|
29
|
+
tags: z.array(TagEntrySchema),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export type TagEntry = z.infer<typeof TagEntrySchema>;
|
|
33
|
+
export type TagsFile = z.infer<typeof TagsFileSchema>;
|
package/src/storage/types.ts
CHANGED
|
@@ -86,7 +86,7 @@ export interface StorageProvider {
|
|
|
86
86
|
*/
|
|
87
87
|
export class IdempotencyLookupUnavailableError extends Error {
|
|
88
88
|
constructor(override readonly cause?: unknown) {
|
|
89
|
-
super("
|
|
89
|
+
super("Couldn't search draft history for the idempotency key");
|
|
90
90
|
this.name = "IdempotencyLookupUnavailableError";
|
|
91
91
|
}
|
|
92
92
|
}
|
package/src/types/database.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// GENERATED by Supabase CLI — do not edit by hand.
|
|
2
|
+
// Regenerate with `pnpm generate-types` after every migration.
|
|
1
3
|
export type Json =
|
|
2
4
|
| string
|
|
3
5
|
| number
|
|
@@ -847,6 +849,10 @@ export type Database = {
|
|
|
847
849
|
Args: { p_site_id: string; p_user_id: string }
|
|
848
850
|
Returns: undefined
|
|
849
851
|
}
|
|
852
|
+
set_site_user_role: {
|
|
853
|
+
Args: { p_role: string; p_site_id: string; p_user_id: string }
|
|
854
|
+
Returns: undefined
|
|
855
|
+
}
|
|
850
856
|
}
|
|
851
857
|
Enums: {
|
|
852
858
|
[_ in never]: never
|
package/dist/chunk-BR4MIPTM.js
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FormLabel,
|
|
3
|
-
Input
|
|
4
|
-
} from "./chunk-TALRVOGO.js";
|
|
5
|
-
import {
|
|
6
|
-
cn
|
|
7
|
-
} from "./chunk-7EOSDFS3.js";
|
|
8
|
-
|
|
9
|
-
// src/components/shared/PagesContext.tsx
|
|
10
|
-
import { createContext, useContext } from "react";
|
|
11
|
-
var PagesContext = createContext({ pages: [], getPageHeadings: () => [] });
|
|
12
|
-
function usePages() {
|
|
13
|
-
return useContext(PagesContext);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// src/components/shared/Select.tsx
|
|
17
|
-
import { useId } from "react";
|
|
18
|
-
import { ChevronDown } from "lucide-react";
|
|
19
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
20
|
-
function Select({
|
|
21
|
-
label,
|
|
22
|
-
value,
|
|
23
|
-
onChange,
|
|
24
|
-
options,
|
|
25
|
-
disabled,
|
|
26
|
-
className,
|
|
27
|
-
selectClassName
|
|
28
|
-
}) {
|
|
29
|
-
const id = useId();
|
|
30
|
-
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
31
|
-
label && /* @__PURE__ */ jsx(FormLabel, { htmlFor: id, children: label }),
|
|
32
|
-
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
33
|
-
/* @__PURE__ */ jsx(
|
|
34
|
-
"select",
|
|
35
|
-
{
|
|
36
|
-
id,
|
|
37
|
-
value,
|
|
38
|
-
onChange: (e) => onChange(e.target.value),
|
|
39
|
-
disabled,
|
|
40
|
-
className: cn(
|
|
41
|
-
"w-full appearance-none rounded border border-base-200 bg-base py-2 pr-8 pl-3 text-sm text-base-contrast",
|
|
42
|
-
"focus:border-base-contrast focus:outline-none focus:ring-1 focus:ring-base-contrast",
|
|
43
|
-
disabled && "cursor-not-allowed opacity-50",
|
|
44
|
-
selectClassName
|
|
45
|
-
),
|
|
46
|
-
children: options.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
|
|
47
|
-
}
|
|
48
|
-
),
|
|
49
|
-
/* @__PURE__ */ jsx(
|
|
50
|
-
ChevronDown,
|
|
51
|
-
{
|
|
52
|
-
size: 14,
|
|
53
|
-
className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 text-base-contrast-light"
|
|
54
|
-
}
|
|
55
|
-
)
|
|
56
|
-
] })
|
|
57
|
-
] });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// src/components/shared/LinkField.tsx
|
|
61
|
-
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
62
|
-
var TARGET_OPTIONS = [
|
|
63
|
-
{ label: "Same tab (_self)", value: "_self" },
|
|
64
|
-
{ label: "New tab (_blank)", value: "_blank" }
|
|
65
|
-
];
|
|
66
|
-
function LinkField({ label, value, onChange }) {
|
|
67
|
-
const { pages, getPageHeadings } = usePages();
|
|
68
|
-
const isInternal = value.kind === "internal";
|
|
69
|
-
function setMode(kind) {
|
|
70
|
-
if (kind === value.kind) return;
|
|
71
|
-
onChange(kind === "external" ? { kind: "external", href: "", target: value.target } : { kind: "internal", pageId: "", anchorSectionId: null, target: "_self" });
|
|
72
|
-
}
|
|
73
|
-
const pageId = isInternal ? value.pageId : "";
|
|
74
|
-
const headings = pageId ? getPageHeadings(pageId) : [];
|
|
75
|
-
return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-3", children: [
|
|
76
|
-
/* @__PURE__ */ jsx2(FormLabel, { children: label }),
|
|
77
|
-
/* @__PURE__ */ jsx2("div", { className: "flex gap-2", role: "tablist", children: ["internal", "external"].map((kind) => /* @__PURE__ */ jsx2(
|
|
78
|
-
"button",
|
|
79
|
-
{
|
|
80
|
-
type: "button",
|
|
81
|
-
role: "tab",
|
|
82
|
-
"aria-selected": value.kind === kind,
|
|
83
|
-
onClick: () => setMode(kind),
|
|
84
|
-
className: cn(
|
|
85
|
-
"cursor-pointer rounded border px-3 py-1 text-sm capitalize",
|
|
86
|
-
value.kind === kind ? "border-primary bg-primary text-primary-contrast" : "border-base-200 text-base-contrast"
|
|
87
|
-
),
|
|
88
|
-
children: kind === "external" ? "External URL" : "Internal page"
|
|
89
|
-
},
|
|
90
|
-
kind
|
|
91
|
-
)) }),
|
|
92
|
-
value.kind === "external" ? /* @__PURE__ */ jsx2(
|
|
93
|
-
Input,
|
|
94
|
-
{
|
|
95
|
-
label: "URL",
|
|
96
|
-
value: value.href,
|
|
97
|
-
placeholder: "https://...",
|
|
98
|
-
onChange: (href) => onChange({ kind: "external", href, target: value.target })
|
|
99
|
-
}
|
|
100
|
-
) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
101
|
-
/* @__PURE__ */ jsx2(
|
|
102
|
-
Select,
|
|
103
|
-
{
|
|
104
|
-
label: "Page",
|
|
105
|
-
value: value.pageId,
|
|
106
|
-
options: [{ label: "Select a page\u2026", value: "" }, ...pages.map((p) => ({ label: p.title, value: p.id }))],
|
|
107
|
-
onChange: (pid) => onChange({ kind: "internal", pageId: pid, anchorSectionId: null, target: value.target })
|
|
108
|
-
}
|
|
109
|
-
),
|
|
110
|
-
/* @__PURE__ */ jsx2(
|
|
111
|
-
Select,
|
|
112
|
-
{
|
|
113
|
-
label: "Section",
|
|
114
|
-
value: value.anchorSectionId ?? "",
|
|
115
|
-
disabled: !pageId,
|
|
116
|
-
options: [{ label: "None (top of page)", value: "" }, ...headings.map((h) => ({ label: h.label, value: h.id }))],
|
|
117
|
-
onChange: (anchor) => onChange({ kind: "internal", pageId, anchorSectionId: anchor || null, target: value.target })
|
|
118
|
-
}
|
|
119
|
-
)
|
|
120
|
-
] }),
|
|
121
|
-
value.kind === "external" && /* @__PURE__ */ jsx2(
|
|
122
|
-
Select,
|
|
123
|
-
{
|
|
124
|
-
label: "Opens in",
|
|
125
|
-
value: value.target,
|
|
126
|
-
options: TARGET_OPTIONS,
|
|
127
|
-
onChange: (t) => onChange({ ...value, target: t })
|
|
128
|
-
}
|
|
129
|
-
)
|
|
130
|
-
] });
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export {
|
|
134
|
-
PagesContext,
|
|
135
|
-
usePages,
|
|
136
|
-
Select,
|
|
137
|
-
LinkField
|
|
138
|
-
};
|
package/dist/chunk-DNY72JZN.js
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getContainerChildren
|
|
3
|
-
} from "./chunk-CXZ5YJG4.js";
|
|
4
|
-
import {
|
|
5
|
-
getSection
|
|
6
|
-
} from "./chunk-FTPETWXE.js";
|
|
7
|
-
|
|
8
|
-
// src/lib/nav.ts
|
|
9
|
-
function toSectionId(text) {
|
|
10
|
-
const slug = text.normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/^-+|-+$/g, "");
|
|
11
|
-
if (slug) return slug;
|
|
12
|
-
let hash = 0;
|
|
13
|
-
for (let i = 0; i < text.length; i++) {
|
|
14
|
-
hash = (hash << 5) - hash + text.charCodeAt(i) | 0;
|
|
15
|
-
}
|
|
16
|
-
return `section-${Math.abs(hash).toString(36)}`;
|
|
17
|
-
}
|
|
18
|
-
function flattenForNav(sections) {
|
|
19
|
-
const flat = [];
|
|
20
|
-
const walk = (loaded) => {
|
|
21
|
-
flat.push(loaded);
|
|
22
|
-
for (const child of getContainerChildren(loaded.section)) {
|
|
23
|
-
walk({ section: child, meta: loaded.meta });
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
sections.forEach(walk);
|
|
27
|
-
return flat;
|
|
28
|
-
}
|
|
29
|
-
function generateNavLinks(sections, registry) {
|
|
30
|
-
const nav = [];
|
|
31
|
-
let currentParent = null;
|
|
32
|
-
let currentChild = null;
|
|
33
|
-
const lookupRole = (type) => {
|
|
34
|
-
const def = registry ? registry.getSection(type) : getSection(type);
|
|
35
|
-
return def?.navRole;
|
|
36
|
-
};
|
|
37
|
-
for (const { section, meta } of flattenForNav(sections)) {
|
|
38
|
-
const content = section.content;
|
|
39
|
-
if (!content.heading) continue;
|
|
40
|
-
const role = lookupRole(section.type);
|
|
41
|
-
if (!role) continue;
|
|
42
|
-
if (role === "h1") {
|
|
43
|
-
if (content.excludeFromNav) {
|
|
44
|
-
currentParent = null;
|
|
45
|
-
currentChild = null;
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
currentParent = {
|
|
49
|
-
href: `#${toSectionId(content.heading)}`,
|
|
50
|
-
label: content.heading,
|
|
51
|
-
status: meta.status,
|
|
52
|
-
children: []
|
|
53
|
-
};
|
|
54
|
-
currentChild = null;
|
|
55
|
-
nav.push(currentParent);
|
|
56
|
-
} else if (role === "h2") {
|
|
57
|
-
if (content.excludeFromNav) {
|
|
58
|
-
currentChild = null;
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
if (!currentParent) continue;
|
|
62
|
-
currentChild = {
|
|
63
|
-
href: `#${toSectionId(content.heading)}`,
|
|
64
|
-
label: content.heading,
|
|
65
|
-
status: meta.status,
|
|
66
|
-
children: []
|
|
67
|
-
};
|
|
68
|
-
currentParent.children.push(currentChild);
|
|
69
|
-
} else if (role === "h3") {
|
|
70
|
-
if (content.excludeFromNav) continue;
|
|
71
|
-
if (!currentChild) continue;
|
|
72
|
-
currentChild.children.push({
|
|
73
|
-
href: `#${toSectionId(content.heading)}`,
|
|
74
|
-
label: content.heading,
|
|
75
|
-
status: meta.status,
|
|
76
|
-
children: []
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return nav;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export {
|
|
84
|
-
toSectionId,
|
|
85
|
-
generateNavLinks
|
|
86
|
-
};
|