@drawnagency/primitives 0.1.113 → 0.1.115
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/chunk-4WQ36ZP7.js +83 -0
- package/dist/{chunk-REDDTTGJ.js → chunk-4Y2JQQZL.js} +19 -1
- package/dist/chunk-5GFACGSN.js +6 -0
- package/dist/{chunk-AHALSCQH.js → chunk-67P34WNW.js} +76 -131
- package/dist/{chunk-S2L3BPLS.js → chunk-7SX42OP4.js} +1 -1
- package/dist/{chunk-GGXZZ77Z.js → chunk-AASEGXNT.js} +18 -1
- package/dist/chunk-APIJPTFG.js +64 -0
- package/dist/{chunk-WKZ7OENC.js → chunk-BQ5TZZUE.js} +5 -1
- package/dist/chunk-CDBURDPX.js +90 -0
- package/dist/chunk-DFKTF3CH.js +0 -0
- package/dist/chunk-DIMDRBFK.js +11 -0
- package/dist/chunk-DJABADOO.js +131 -0
- package/dist/{chunk-NHN2LSIU.js → chunk-DJOGPSRU.js} +31 -68
- package/dist/{chunk-KR2MHTNJ.js → chunk-FHTKSELX.js} +610 -62
- package/dist/{chunk-WUJ3XNFI.js → chunk-GGYY3JQJ.js} +19 -24
- package/dist/chunk-GNF6KFQ7.js +18 -0
- package/dist/{chunk-FRE2CCLV.js → chunk-HHNPSKPT.js} +5 -79
- package/dist/{chunk-IINIZBQB.js → chunk-JCDZAFX2.js} +30 -10
- package/dist/chunk-JR24U7FJ.js +120 -0
- package/dist/{chunk-BDFTMGCL.js → chunk-JXATNKLV.js} +11 -10
- package/dist/{chunk-SW6PCQQD.js → chunk-KQA772WQ.js} +2 -1
- package/dist/{chunk-6BZ2KNTP.js → chunk-NX7TFHA4.js} +195 -65
- package/dist/{chunk-VWWY5TL5.js → chunk-O37AV27P.js} +14 -75
- package/dist/chunk-RIITGTV3.js +275 -0
- package/dist/{chunk-HBULBDGP.js → chunk-S37DZPHW.js} +1 -1
- package/dist/chunk-S7QRHUWO.js +8 -0
- package/dist/{chunk-Z7W3DQTR.js → chunk-T26HAKW3.js} +424 -42
- package/dist/{chunk-4I5OO5UB.js → chunk-TEOAKGZA.js} +0 -1
- package/dist/{chunk-GPPVYLEI.js → chunk-UUUSJDIG.js} +1 -1
- package/dist/chunk-VY3IFGE3.js +70 -0
- package/dist/chunk-WYOFQHKI.js +176 -0
- package/dist/{chunk-4RNF2DRG.js → chunk-XDEPXTBY.js} +0 -2
- package/dist/{chunk-DS4GCYV2.js → chunk-YV3YSZEB.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 +24 -9
- 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 +150 -79
- 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 +22 -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 +17 -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 +25 -18
- package/dist/components/sections/register.js +25 -18
- 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.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 +10 -17
- 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 +6 -3
- package/dist/hooks/useEditorPublish.d.ts.map +1 -1
- package/dist/hooks/useMediaPipeline.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 +95 -48
- 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 +7 -1
- package/dist/lib/dexie.d.ts.map +1 -1
- package/dist/lib/dexie.js +12 -3
- 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/image-variant-plan.d.ts +42 -0
- package/dist/lib/image-variant-plan.d.ts.map +1 -0
- package/dist/lib/image-variant-plan.js +53 -0
- package/dist/lib/index-ops.d.ts.map +1 -1
- package/dist/lib/index-ops.js +21 -17
- package/dist/lib/index.d.ts +7 -4
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +55 -26
- package/dist/lib/loader.d.ts +25 -12
- package/dist/lib/loader.d.ts.map +1 -1
- package/dist/lib/media-ops.d.ts +73 -0
- package/dist/lib/media-ops.d.ts.map +1 -0
- package/dist/lib/media-ops.js +60 -0
- package/dist/lib/nav-tree.d.ts +7 -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/pages.d.ts +2 -1
- package/dist/lib/pages.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/sidecar-diagnostics.d.ts +20 -0
- package/dist/lib/sidecar-diagnostics.d.ts.map +1 -0
- package/dist/lib/sidecars.d.ts +118 -0
- package/dist/lib/sidecars.d.ts.map +1 -0
- package/dist/lib/sidecars.js +23 -0
- package/dist/lib/slug.d.ts +2 -0
- package/dist/lib/slug.d.ts.map +1 -0
- package/dist/lib/storage-tier.d.ts +17 -0
- package/dist/lib/storage-tier.d.ts.map +1 -0
- package/dist/lib/storage-tier.js +29 -0
- package/dist/lib/tags.d.ts +64 -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 +18 -14
- package/dist/media/queue.d.ts +2 -0
- package/dist/media/queue.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/media/worker.d.ts +1 -35
- package/dist/media/worker.d.ts.map +1 -1
- 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 +25 -13
- package/dist/schemas/media.d.ts +4 -0
- package/dist/schemas/media.d.ts.map +1 -1
- package/dist/schemas/shared.d.ts +26 -0
- package/dist/schemas/shared.d.ts.map +1 -1
- package/dist/schemas/site-config.d.ts +6 -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 +2 -1
- package/dist/storage/memory.d.ts +21 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +129 -0
- package/dist/storage/types.d.ts +9 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/types/database.d.ts.map +1 -1
- package/package.json +26 -1
- package/src/auth/cookies.ts +111 -0
- package/src/collab/rebase.ts +29 -9
- 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 +2 -3
- 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 +22 -17
- 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 +501 -338
- 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 +10 -20
- package/src/components/shell/SiteSettingsModal.tsx +24 -2
- package/src/components/shell/SiteSettingsTags.tsx +143 -0
- package/src/components/shell/SiteSettingsUsers.tsx +36 -26
- 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 +27 -31
- package/src/hooks/useMediaPipeline.ts +30 -24
- 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 +24 -2
- 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/image-variant-plan.ts +92 -0
- package/src/lib/index-ops.ts +9 -18
- package/src/lib/index.ts +20 -4
- package/src/lib/loader.ts +28 -88
- package/src/lib/media-ops.ts +112 -0
- package/src/lib/nav-tree.ts +104 -4
- package/src/lib/nav.ts +196 -36
- package/src/lib/pages.ts +2 -3
- 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/sidecar-diagnostics.ts +29 -0
- package/src/lib/sidecars.ts +221 -0
- package/src/lib/slug.ts +6 -0
- package/src/lib/storage-tier.ts +38 -0
- package/src/lib/tags.ts +165 -0
- package/src/lib/theme-vars.ts +23 -0
- package/src/media/index.ts +1 -1
- package/src/media/queue.ts +3 -0
- package/src/media/utils.ts +19 -1
- package/src/media/{videoPoster.ts → video-poster.ts} +2 -2
- package/src/media/worker.ts +17 -8
- package/src/schemas/index.ts +1 -0
- package/src/schemas/media.ts +7 -2
- package/src/schemas/shared.ts +24 -1
- package/src/schemas/site-config.ts +6 -1
- package/src/schemas/tags.ts +33 -0
- package/src/storage/memory.ts +178 -0
- package/src/storage/types.ts +16 -3
- package/src/types/database.ts +2 -0
- package/dist/chunk-DNY72JZN.js +0 -86
- package/dist/chunk-F2LYQPXV.js +0 -77
- package/dist/chunk-JH762VUH.js +0 -128
- package/dist/chunk-K7DYZXVU.js +0 -138
- 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/loader.ts
CHANGED
|
@@ -3,52 +3,38 @@ import { IndexSchema, type SiteIndex, type SectionMeta } from "../schemas/site-c
|
|
|
3
3
|
import { getAllSchemas } from "./registry";
|
|
4
4
|
import { blockDepth, MAX_BLOCK_DEPTH } from "../schemas/block";
|
|
5
5
|
import { upgradeLegacySection } from "./migrate-sections-transform";
|
|
6
|
-
import {
|
|
6
|
+
import type { NavEntry } from "../schemas/nav";
|
|
7
|
+
import type { TagEntry } from "../schemas/tags";
|
|
8
|
+
import type { SidecarRead } from "./sidecars";
|
|
7
9
|
|
|
8
10
|
export interface LoadedSection {
|
|
9
11
|
section: Section;
|
|
10
12
|
meta: SectionMeta;
|
|
13
|
+
/** Set only on render-time copies a Reference pulled in (resolveReference):
|
|
14
|
+
* the id of that Reference. Never loaded or persisted. */
|
|
15
|
+
referencedBy?: string;
|
|
11
16
|
}
|
|
12
17
|
|
|
13
18
|
export interface SiteContent {
|
|
14
19
|
sections: LoadedSection[];
|
|
15
20
|
index: SiteIndex;
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* nav.json from a degraded read permanently destroys the entries this
|
|
20
|
-
* version dropped. */
|
|
21
|
+
/** A Degraded read of nav.json (see SidecarRead): the returned nav is missing
|
|
22
|
+
* entries, so writers treat it as read-only — wholesale-replacing nav.json
|
|
23
|
+
* from it permanently destroys the entries this version dropped. */
|
|
21
24
|
navDegraded: boolean;
|
|
25
|
+
/** Same contract as navDegraded, for tags.json: a degraded read is
|
|
26
|
+
* read-only for tags. */
|
|
27
|
+
tagsDegraded: boolean;
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* the site. Any drop is reported as `degraded` so write paths can refuse to
|
|
31
|
-
* persist the lossy tree back over the original.
|
|
31
|
+
* The Sidecars a load read, from the Sidecar module's readers. A Sidecar the
|
|
32
|
+
* load did not look for is omitted. Tags then stay unattached ("not loaded":
|
|
33
|
+
* writers leave tags.json alone, where an attached `[]` saved back would delete
|
|
34
|
+
* every tag). Nav is attached as `[]` either way — the editor has no nav gate
|
|
35
|
+
* yet to make "not loaded" safe for nav (exploration B).
|
|
32
36
|
*/
|
|
33
|
-
|
|
34
|
-
if (!navFile) return { entries: [], degraded: false };
|
|
35
|
-
const rawEntries = (navFile as { entries?: unknown }).entries;
|
|
36
|
-
if (!Array.isArray(rawEntries)) {
|
|
37
|
-
console.warn("Invalid nav.json, falling back to a flat navigation");
|
|
38
|
-
return { entries: [], degraded: true };
|
|
39
|
-
}
|
|
40
|
-
const entries: NavEntry[] = [];
|
|
41
|
-
let dropped = 0;
|
|
42
|
-
for (const raw of rawEntries) {
|
|
43
|
-
const result = NavEntrySchema.safeParse(raw);
|
|
44
|
-
if (result.success) entries.push(result.data);
|
|
45
|
-
else dropped++;
|
|
46
|
-
}
|
|
47
|
-
if (dropped > 0) {
|
|
48
|
-
console.warn(`nav.json: dropped ${dropped} entr${dropped === 1 ? "y" : "ies"} this package version cannot represent; navigation is degraded`);
|
|
49
|
-
}
|
|
50
|
-
return { entries, degraded: dropped > 0 };
|
|
51
|
-
}
|
|
37
|
+
export type SidecarReads = { nav?: SidecarRead<NavEntry>; tags?: SidecarRead<TagEntry> };
|
|
52
38
|
|
|
53
39
|
/**
|
|
54
40
|
* Merge a validated index with raw section file contents.
|
|
@@ -58,7 +44,7 @@ function parseNavFile(navFile: unknown): { entries: NavEntry[]; degraded: boolea
|
|
|
58
44
|
export function mergeSiteContent(
|
|
59
45
|
index: SiteIndex,
|
|
60
46
|
sectionFiles: Record<string, unknown>,
|
|
61
|
-
|
|
47
|
+
sidecars: SidecarReads = {},
|
|
62
48
|
): SiteContent {
|
|
63
49
|
const sections: LoadedSection[] = [];
|
|
64
50
|
|
|
@@ -111,8 +97,13 @@ export function mergeSiteContent(
|
|
|
111
97
|
}
|
|
112
98
|
}
|
|
113
99
|
|
|
114
|
-
const nav =
|
|
115
|
-
return {
|
|
100
|
+
const { nav, tags } = sidecars;
|
|
101
|
+
return {
|
|
102
|
+
sections,
|
|
103
|
+
index: { ...index, nav: nav?.entries ?? [], ...(tags ? { tags: tags.entries } : {}) },
|
|
104
|
+
navDegraded: nav?.degraded ?? false,
|
|
105
|
+
tagsDegraded: tags?.degraded ?? false,
|
|
106
|
+
};
|
|
116
107
|
}
|
|
117
108
|
|
|
118
109
|
/**
|
|
@@ -123,7 +114,7 @@ export function mergeSiteContent(
|
|
|
123
114
|
export function loadStaticSiteContent(
|
|
124
115
|
index: SiteIndex,
|
|
125
116
|
sectionGlob: Record<string, unknown>,
|
|
126
|
-
|
|
117
|
+
sidecars: SidecarReads = {},
|
|
127
118
|
): SiteContent {
|
|
128
119
|
const sectionFiles: Record<string, unknown> = {};
|
|
129
120
|
for (const [path, data] of Object.entries(sectionGlob)) {
|
|
@@ -131,56 +122,5 @@ export function loadStaticSiteContent(
|
|
|
131
122
|
const id = filename.replace(".json", "");
|
|
132
123
|
sectionFiles[id] = data;
|
|
133
124
|
}
|
|
134
|
-
return mergeSiteContent(index, sectionFiles,
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Load site content from the filesystem.
|
|
139
|
-
* For use in scripts and tests — Astro pages should use import.meta.glob instead.
|
|
140
|
-
*/
|
|
141
|
-
export async function loadSiteContent(contentDir: string): Promise<SiteContent> {
|
|
142
|
-
const fs = await import("node:fs/promises");
|
|
143
|
-
const path = await import("node:path");
|
|
144
|
-
|
|
145
|
-
const indexPath = path.join(contentDir, "index.json");
|
|
146
|
-
const indexRaw = JSON.parse(await fs.readFile(indexPath, "utf-8"));
|
|
147
|
-
const index = IndexSchema.parse(indexRaw);
|
|
148
|
-
|
|
149
|
-
const sectionFiles: Record<string, unknown> = {};
|
|
150
|
-
for (const id of index.pages.flatMap((p: SiteIndex["pages"][number]) => p.order)) {
|
|
151
|
-
const sectionPath = path.join(contentDir, "sections", `${id}.json`);
|
|
152
|
-
sectionFiles[id] = JSON.parse(await fs.readFile(sectionPath, "utf-8"));
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// nav.json is an optional sidecar — absent (every portal predating page
|
|
156
|
-
// groups) or unreadable must degrade to a flat nav, never fail the load.
|
|
157
|
-
//
|
|
158
|
-
// ABSENT and UNREADABLE are not the same answer, though: absent is the normal
|
|
159
|
-
// case and safe to overwrite, while a present-but-unparseable sidecar holds
|
|
160
|
-
// groups this load cannot see. Collapsing both to `undefined` reported
|
|
161
|
-
// navDegraded: false, so the next nav-touching save wholesale-wrote a flat
|
|
162
|
-
// nav.json over a file that was still hand-recoverable. Mirrors the
|
|
163
|
-
// GitHub-backed loader's navRaw/navFile split in @drawnagency/core.
|
|
164
|
-
let navRaw: string | undefined;
|
|
165
|
-
let readFailed = false;
|
|
166
|
-
try {
|
|
167
|
-
navRaw = await fs.readFile(path.join(contentDir, "nav.json"), "utf-8");
|
|
168
|
-
} catch (err) {
|
|
169
|
-
// Only a genuinely missing file is "absent". A permissions/IO error leaves
|
|
170
|
-
// the sidecar's contents unknown, which must not license overwriting it.
|
|
171
|
-
readFailed = (err as { code?: string })?.code !== "ENOENT";
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
let navFile: unknown;
|
|
175
|
-
let parseFailed = false;
|
|
176
|
-
if (navRaw !== undefined) {
|
|
177
|
-
try {
|
|
178
|
-
navFile = JSON.parse(navRaw);
|
|
179
|
-
} catch {
|
|
180
|
-
parseFailed = true;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const content = mergeSiteContent(index, sectionFiles, navFile);
|
|
185
|
-
return readFailed || parseFailed ? { ...content, navDegraded: true } : content;
|
|
125
|
+
return mergeSiteContent(index, sectionFiles, sidecars);
|
|
186
126
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { MediaItem, MediaManifest } from "../schemas/media";
|
|
2
|
+
import type { DocumentManifest, DocumentManifestEntry } from "../schemas/documents";
|
|
3
|
+
|
|
4
|
+
// Media intents (CONTEXT.md: Index op / Media intent): a change to the media
|
|
5
|
+
// library stated as what to do, applied by the write path to its own fresh read
|
|
6
|
+
// of the manifests. A writer that sent a whole manifest instead could only
|
|
7
|
+
// send back what it had read — dropping another writer's images, or `folders`,
|
|
8
|
+
// the moment its copy was stale. Intents leave everything they do not name as
|
|
9
|
+
// the branch has it. Pure: the write path does the reads and the commit.
|
|
10
|
+
|
|
11
|
+
export type MediaBlob = { path: string; base64: string };
|
|
12
|
+
|
|
13
|
+
export type MediaOp =
|
|
14
|
+
/**
|
|
15
|
+
* A new image and its variant files, keyed by its id (the content hash).
|
|
16
|
+
* `alt` is the caller's alt text, if it sent one — the only alt applied when
|
|
17
|
+
* the image turns out to be in the library already (`entry.alt` is just the
|
|
18
|
+
* new entry's default).
|
|
19
|
+
*/
|
|
20
|
+
| { op: "addImage"; entry: MediaItem; blobs: MediaBlob[]; alt?: string }
|
|
21
|
+
| { op: "setImageAlt"; imageId: string; alt: string }
|
|
22
|
+
| { op: "deleteImage"; imageId: string }
|
|
23
|
+
/**
|
|
24
|
+
* A document's manifest entry, with its bytes when they ride in the commit
|
|
25
|
+
* (git tier; bucket-tier bytes are uploaded beforehand). For an id already in
|
|
26
|
+
* the library — git-tier ids are the content hash, so the same bytes — only
|
|
27
|
+
* the filename is applied: its stored bytes and path stay. That is how a
|
|
28
|
+
* rename lands.
|
|
29
|
+
*/
|
|
30
|
+
| { op: "putDocument"; documentId: string; entry: DocumentManifestEntry; blob?: MediaBlob };
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Per op, in order. `existed` means `addImage` found the image already in the
|
|
34
|
+
* library: its bytes are not committed again, and only a differing alt text is
|
|
35
|
+
* applied.
|
|
36
|
+
*/
|
|
37
|
+
export type MediaOpOutcome = "added" | "existed" | "updated" | "deleted";
|
|
38
|
+
|
|
39
|
+
export type AppliedMediaOps = {
|
|
40
|
+
ok: true;
|
|
41
|
+
images: MediaManifest;
|
|
42
|
+
/** Null when no op touched documents, so the write leaves that file alone. */
|
|
43
|
+
documents: DocumentManifest | null;
|
|
44
|
+
uploads: { item: { id: string; folder: string }; blobs: MediaBlob[] }[];
|
|
45
|
+
/** Images whose variant folders the write deletes. */
|
|
46
|
+
deletions: { id: string; folder: string }[];
|
|
47
|
+
outcomes: MediaOpOutcome[];
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export function applyMediaOps(
|
|
51
|
+
manifests: { images: MediaManifest; documents: DocumentManifest },
|
|
52
|
+
ops: MediaOp[],
|
|
53
|
+
): AppliedMediaOps | { ok: false; code: "not_found"; error: string } {
|
|
54
|
+
const images: MediaManifest = { ...manifests.images, images: { ...manifests.images.images } };
|
|
55
|
+
let documents: DocumentManifest | null = null;
|
|
56
|
+
const uploads: AppliedMediaOps["uploads"] = [];
|
|
57
|
+
const deletions: AppliedMediaOps["deletions"] = [];
|
|
58
|
+
const outcomes: MediaOpOutcome[] = [];
|
|
59
|
+
|
|
60
|
+
// Keys are content hashes and normally equal the entry's id; find by id so a
|
|
61
|
+
// caller naming the id it was given always reaches the right entry.
|
|
62
|
+
const keyOf = (imageId: string) =>
|
|
63
|
+
imageId in images.images ? imageId : Object.keys(images.images).find((key) => images.images[key].id === imageId);
|
|
64
|
+
const notFound = (imageId: string) =>
|
|
65
|
+
({ ok: false, code: "not_found", error: `No media with imageId "${imageId}" in the site's media library.` }) as const;
|
|
66
|
+
|
|
67
|
+
for (const op of ops) {
|
|
68
|
+
switch (op.op) {
|
|
69
|
+
case "addImage": {
|
|
70
|
+
const key = keyOf(op.entry.id);
|
|
71
|
+
if (key === undefined) {
|
|
72
|
+
images.images[op.entry.id] = op.entry;
|
|
73
|
+
uploads.push({ item: { id: op.entry.id, folder: op.entry.folder }, blobs: op.blobs });
|
|
74
|
+
outcomes.push("added");
|
|
75
|
+
} else {
|
|
76
|
+
if (op.alt !== undefined) images.images[key] = { ...images.images[key], alt: op.alt };
|
|
77
|
+
outcomes.push("existed");
|
|
78
|
+
}
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
case "setImageAlt": {
|
|
82
|
+
const key = keyOf(op.imageId);
|
|
83
|
+
if (key === undefined) return notFound(op.imageId);
|
|
84
|
+
images.images[key] = { ...images.images[key], alt: op.alt };
|
|
85
|
+
outcomes.push("updated");
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
case "deleteImage": {
|
|
89
|
+
const key = keyOf(op.imageId);
|
|
90
|
+
if (key === undefined) return notFound(op.imageId);
|
|
91
|
+
deletions.push({ id: key, folder: images.images[key].folder });
|
|
92
|
+
delete images.images[key];
|
|
93
|
+
outcomes.push("deleted");
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
case "putDocument": {
|
|
97
|
+
documents ??= { ...manifests.documents };
|
|
98
|
+
const existing = documents[op.documentId];
|
|
99
|
+
if (existing) {
|
|
100
|
+
documents[op.documentId] = { ...existing, filename: op.entry.filename };
|
|
101
|
+
outcomes.push(existing.filename === op.entry.filename ? "existed" : "updated");
|
|
102
|
+
} else {
|
|
103
|
+
documents[op.documentId] = op.entry;
|
|
104
|
+
if (op.blob) uploads.push({ item: { id: op.documentId, folder: op.blob.path.split("/")[2] ?? "" }, blobs: [op.blob] });
|
|
105
|
+
outcomes.push("added");
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return { ok: true, images, documents, uploads, deletions, outcomes };
|
|
112
|
+
}
|
package/src/lib/nav-tree.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { NavEntry, NavGroupEntry } from "../schemas/nav";
|
|
2
2
|
import type { Page, SiteIndex } from "../schemas/site-config";
|
|
3
|
+
import { diagnosticsCollector, type SidecarDiagnostic } from "./sidecar-diagnostics";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Repair an authored nav against the current page set.
|
|
@@ -19,6 +20,15 @@ import type { Page, SiteIndex } from "../schemas/site-config";
|
|
|
19
20
|
* prior state and defeat identity-based re-render checks.
|
|
20
21
|
*/
|
|
21
22
|
export function reconcileNav(entries: NavEntry[], pages: Page[]): NavEntry[] {
|
|
23
|
+
return reconcileNavReport(entries, pages).entries;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** reconcileNav plus what the repair changed — what a validator reports. */
|
|
27
|
+
export function reconcileNavReport(
|
|
28
|
+
entries: NavEntry[],
|
|
29
|
+
pages: Page[],
|
|
30
|
+
): { entries: NavEntry[]; diagnostics: SidecarDiagnostic[] } {
|
|
31
|
+
const report = diagnosticsCollector();
|
|
22
32
|
const entryList = Array.isArray(entries) ? entries : [];
|
|
23
33
|
const pageList = Array.isArray(pages) ? pages : [];
|
|
24
34
|
|
|
@@ -33,7 +43,14 @@ export function reconcileNav(entries: NavEntry[], pages: Page[]): NavEntry[] {
|
|
|
33
43
|
|
|
34
44
|
for (const entry of entryList) {
|
|
35
45
|
if (entry?.kind === "page") {
|
|
36
|
-
if (!validIds.has(entry.pageId)
|
|
46
|
+
if (!validIds.has(entry.pageId)) {
|
|
47
|
+
report.add("dangling", entry.pageId);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (placed.has(entry.pageId)) {
|
|
51
|
+
report.add("duplicate-member", entry.pageId);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
37
54
|
placed.add(entry.pageId);
|
|
38
55
|
result.push({ ...entry });
|
|
39
56
|
continue;
|
|
@@ -46,12 +63,23 @@ export function reconcileNav(entries: NavEntry[], pages: Page[]): NavEntry[] {
|
|
|
46
63
|
// and "total" would be a lie. Dropping it spills its members to the tail
|
|
47
64
|
// append below: a group lost, never a page.
|
|
48
65
|
if (typeof entry.id !== "string" || entry.id === "") continue;
|
|
49
|
-
if (seenGroupIds.has(entry.id))
|
|
66
|
+
if (seenGroupIds.has(entry.id)) {
|
|
67
|
+
report.add("duplicate-id", entry.id);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
50
70
|
seenGroupIds.add(entry.id);
|
|
51
71
|
|
|
52
72
|
const claimed = Array.isArray(entry.pageIds) ? entry.pageIds : [];
|
|
53
73
|
const pageIds = claimed.filter((id) => {
|
|
54
|
-
if (typeof id !== "string"
|
|
74
|
+
if (typeof id !== "string") return false;
|
|
75
|
+
if (!validIds.has(id)) {
|
|
76
|
+
report.add("dangling", id);
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
if (placed.has(id)) {
|
|
80
|
+
report.add("duplicate-member", id);
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
55
83
|
placed.add(id);
|
|
56
84
|
return true;
|
|
57
85
|
});
|
|
@@ -70,10 +98,11 @@ export function reconcileNav(entries: NavEntry[], pages: Page[]): NavEntry[] {
|
|
|
70
98
|
for (const p of pageList) {
|
|
71
99
|
if (!p?.id || placed.has(p.id)) continue;
|
|
72
100
|
placed.add(p.id);
|
|
101
|
+
report.add("unlisted", p.id);
|
|
73
102
|
result.push({ kind: "page", pageId: p.id });
|
|
74
103
|
}
|
|
75
104
|
|
|
76
|
-
return result;
|
|
105
|
+
return { entries: result, diagnostics: report.list() };
|
|
77
106
|
}
|
|
78
107
|
|
|
79
108
|
/**
|
|
@@ -204,3 +233,74 @@ export function moveNavEntry(index: SiteIndex, from: NavLocation, to: NavLocatio
|
|
|
204
233
|
|
|
205
234
|
return withNav(index, entries);
|
|
206
235
|
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* "Moved <label> to position N of M" for the aria-live reorder announcement,
|
|
239
|
+
* covering both `moveNavEntry` callers: drag (PagesModal/NavGroupRow) and the
|
|
240
|
+
* Move up/down buttons. `prevIndex` resolves WHO moved and its label (read
|
|
241
|
+
* before the move, since `from` is a position, not an id); `nextIndex` (the
|
|
242
|
+
* result of `moveNavEntry(prevIndex, from, to)`) is searched by id for where
|
|
243
|
+
* it actually landed — robust to `moveNavEntry`'s own clamping, so the caller
|
|
244
|
+
* never has to replicate that math. Returns null if `from` didn't resolve to
|
|
245
|
+
* a real row (defensive; ordinary callers always pass a live location).
|
|
246
|
+
*/
|
|
247
|
+
/** A top-level entry counts toward "N of M" iff it's a group (always visible)
|
|
248
|
+
* or a page that isn't archived — mirrors the PagesModal Move up/down rows,
|
|
249
|
+
* which skip archived pages entirely rather than render an inert slot. */
|
|
250
|
+
function isLiveTopEntry(index: SiteIndex, entry: NavEntry): boolean {
|
|
251
|
+
if (entry.kind === "group") return true;
|
|
252
|
+
const page = index.pages.find((p) => p.id === entry.pageId);
|
|
253
|
+
return page?.status === "live";
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export function describeNavMove(prevIndex: SiteIndex, nextIndex: SiteIndex, from: NavLocation): string | null {
|
|
257
|
+
const prevEntries = navEntries(prevIndex);
|
|
258
|
+
let label: string;
|
|
259
|
+
let pageId: string | null = null;
|
|
260
|
+
let groupId: string | null = null;
|
|
261
|
+
|
|
262
|
+
if (from.groupId === null) {
|
|
263
|
+
const entry = prevEntries[from.index];
|
|
264
|
+
if (!entry) return null;
|
|
265
|
+
if (entry.kind === "group") {
|
|
266
|
+
label = groupDisplayLabel(entry.label);
|
|
267
|
+
groupId = entry.id;
|
|
268
|
+
} else {
|
|
269
|
+
const page = prevIndex.pages.find((p) => p.id === entry.pageId);
|
|
270
|
+
if (!page) return null;
|
|
271
|
+
label = page.title || "Untitled";
|
|
272
|
+
pageId = page.id;
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
const group = prevEntries.find((e) => e.kind === "group" && e.id === from.groupId);
|
|
276
|
+
if (!group || group.kind !== "group") return null;
|
|
277
|
+
const id = group.pageIds[from.index];
|
|
278
|
+
if (!id) return null;
|
|
279
|
+
const page = prevIndex.pages.find((p) => p.id === id);
|
|
280
|
+
if (!page) return null;
|
|
281
|
+
label = page.title || "Untitled";
|
|
282
|
+
pageId = page.id;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const nextEntries = navEntries(nextIndex);
|
|
286
|
+
const liveTopEntries = nextEntries.filter((e) => isLiveTopEntry(nextIndex, e));
|
|
287
|
+
|
|
288
|
+
if (groupId !== null) {
|
|
289
|
+
const i = liveTopEntries.findIndex((e) => e.kind === "group" && e.id === groupId);
|
|
290
|
+
if (i === -1) return null;
|
|
291
|
+
return `Moved ${label} to position ${i + 1} of ${liveTopEntries.length}`;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (pageId === null) return null;
|
|
295
|
+
|
|
296
|
+
const topIndex = liveTopEntries.findIndex((e) => e.kind === "page" && e.pageId === pageId);
|
|
297
|
+
if (topIndex !== -1) return `Moved ${label} to position ${topIndex + 1} of ${liveTopEntries.length}`;
|
|
298
|
+
for (const e of nextEntries) {
|
|
299
|
+
if (e.kind === "group") {
|
|
300
|
+
const liveMemberIds = e.pageIds.filter((id) => nextIndex.pages.find((p) => p.id === id)?.status === "live");
|
|
301
|
+
const gi = liveMemberIds.indexOf(pageId);
|
|
302
|
+
if (gi !== -1) return `Moved ${label} to position ${gi + 1} of ${liveMemberIds.length}`;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return null;
|
|
306
|
+
}
|