@drawnagency/primitives 0.1.113 → 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/{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-Z7W3DQTR.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-NHN2LSIU.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-KR2MHTNJ.js → chunk-N3G7DOU3.js} +609 -61
- package/dist/chunk-OAGJBCSH.js +67 -0
- package/dist/{chunk-6BZ2KNTP.js → chunk-PLANHXS7.js} +191 -61
- package/dist/{chunk-VWWY5TL5.js → chunk-PNSCDBU7.js} +38 -56
- package/dist/{chunk-AHALSCQH.js → chunk-PTY2RG2K.js} +1 -1
- package/dist/{chunk-BDFTMGCL.js → chunk-PZPGJZRG.js} +9 -8
- package/dist/{chunk-FRE2CCLV.js → chunk-QHMKIODQ.js} +17 -4
- 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-DS4GCYV2.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.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/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 +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 +1 -1
- package/dist/types/database.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/auth/cookies.ts +111 -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 +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 +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 +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 +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/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 +6 -1
- package/src/schemas/tags.ts +33 -0
- package/src/storage/types.ts +1 -1
- 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
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Section } from "../schemas/sections";
|
|
2
|
+
import type { ColorItem } from "../components/sections/Colors/schema";
|
|
3
|
+
|
|
4
|
+
export interface BrandSwatch {
|
|
5
|
+
hex: string;
|
|
6
|
+
name: string | undefined;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type Block = { type?: unknown; content?: unknown };
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Every hex value from every Colors section, walking container children, in
|
|
13
|
+
* page order and deduped case-insensitively. Swatches are offered as plain hex
|
|
14
|
+
* values: color items carry no stable id, so a picked swatch is copied, not linked.
|
|
15
|
+
*/
|
|
16
|
+
export function collectBrandSwatches(sections: Section[]): BrandSwatch[] {
|
|
17
|
+
const seen = new Map<string, BrandSwatch>();
|
|
18
|
+
const visit = (block: Block) => {
|
|
19
|
+
const content = (block.content ?? {}) as { colors?: unknown; children?: unknown };
|
|
20
|
+
if (block.type === "colors" && Array.isArray(content.colors)) {
|
|
21
|
+
for (const item of content.colors as ColorItem[]) {
|
|
22
|
+
for (const space of item.spaces) {
|
|
23
|
+
const hex = space.hex?.toLowerCase();
|
|
24
|
+
if (hex && !seen.has(hex)) seen.set(hex, { hex, name: item.name });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (Array.isArray(content.children)) (content.children as Block[]).forEach(visit);
|
|
29
|
+
};
|
|
30
|
+
sections.forEach(visit);
|
|
31
|
+
return [...seen.values()];
|
|
32
|
+
}
|
package/src/lib/container-ops.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { ReactNode } from "react";
|
|
|
2
2
|
import type { Section } from "../schemas/sections";
|
|
3
3
|
import { getAllSections } from "./registry";
|
|
4
4
|
import { sortInsertMenuOptions } from "./insert-menu";
|
|
5
|
+
import { REFERENCE_TYPE } from "./reference-type";
|
|
5
6
|
|
|
6
7
|
interface ContainerContent {
|
|
7
8
|
columns: number;
|
|
@@ -37,13 +38,14 @@ export function reorderChild(container: Section, from: number, to: number): Sect
|
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* Block types insertable as a container CHILD — excludes `container` itself
|
|
40
|
-
* (v1 enforces one level of container nesting)
|
|
41
|
-
*
|
|
41
|
+
* (v1 enforces one level of container nesting) and `reference`, which only
|
|
42
|
+
* expands at the top level of a page. Shared so the depth guard has a single,
|
|
43
|
+
* testable source of truth (the container toolbar's "+" picker uses it).
|
|
42
44
|
*/
|
|
43
45
|
export function childInsertableTypes(): { type: string; label: string; icon: ReactNode }[] {
|
|
44
46
|
return sortInsertMenuOptions(
|
|
45
47
|
getAllSections()
|
|
46
|
-
.filter((d) => d.type !== "container" && d.type !== "spacer")
|
|
48
|
+
.filter((d) => d.type !== "container" && d.type !== "spacer" && d.type !== REFERENCE_TYPE)
|
|
47
49
|
.map((d) => ({ type: d.type, label: d.label, icon: d.icon })),
|
|
48
50
|
);
|
|
49
51
|
}
|
package/src/lib/dexie.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
// The editor's offline draft store (IndexedDB via Dexie): unsaved section
|
|
2
|
+
// edits, the working index/nav, site config, pending media, and a sha-keyed
|
|
3
|
+
// cache of the last loaded content. Nothing here is authoritative — GitHub is.
|
|
4
|
+
// Schema versions only ever append; an EMPTY `version(N)` bump is intentional
|
|
5
|
+
// (see the per-version notes in the constructor), never a leftover to remove.
|
|
1
6
|
import Dexie from "dexie";
|
|
2
7
|
import type { SectionContent } from "../schemas/sections";
|
|
3
8
|
import type { SiteIndex, SectionMeta, SiteConfig, Page } from "../schemas/site-config";
|
|
4
9
|
import type { NavEntry } from "../schemas/nav";
|
|
10
|
+
import type { TagEntry } from "../schemas/tags";
|
|
5
11
|
import type { LoadedSection } from "./loader";
|
|
6
12
|
import type { MediaManifest, MediaItem } from "../media/types";
|
|
7
13
|
import type { DocumentManifest, DocumentManifestEntry } from "../schemas/documents";
|
|
@@ -19,6 +25,9 @@ interface SiteIndexRow {
|
|
|
19
25
|
sections: Record<string, SectionMeta>;
|
|
20
26
|
/** Optional: rows written before page groups shipped have no nav. */
|
|
21
27
|
nav?: NavEntry[];
|
|
28
|
+
/** Optional: rows written before section tags shipped have none. Restored
|
|
29
|
+
* as absent (not []), which writers read as "leave tags.json alone". */
|
|
30
|
+
tags?: TagEntry[];
|
|
22
31
|
deletedSections: string[];
|
|
23
32
|
updatedAt: string;
|
|
24
33
|
}
|
|
@@ -311,7 +320,10 @@ export async function restoreLocalChanges(): Promise<{
|
|
|
311
320
|
const siteId = metaRow?.siteId || getDb().siteId;
|
|
312
321
|
return {
|
|
313
322
|
sections,
|
|
314
|
-
siteIndex: {
|
|
323
|
+
siteIndex: {
|
|
324
|
+
siteId, pages: indexRow.pages, sections: indexRow.sections, nav: indexRow.nav,
|
|
325
|
+
...(indexRow.tags !== undefined ? { tags: indexRow.tags } : {}),
|
|
326
|
+
},
|
|
315
327
|
siteConfig: configRow?.config,
|
|
316
328
|
deletedSections: indexRow.deletedSections ?? [],
|
|
317
329
|
};
|
|
@@ -345,6 +357,7 @@ export async function persistSiteIndex(index: SiteIndex, deletedSections: string
|
|
|
345
357
|
pages: index.pages,
|
|
346
358
|
sections: index.sections,
|
|
347
359
|
nav: index.nav,
|
|
360
|
+
tags: index.tags,
|
|
348
361
|
deletedSections,
|
|
349
362
|
updatedAt: now,
|
|
350
363
|
});
|
|
@@ -465,6 +478,7 @@ export async function persistAll(
|
|
|
465
478
|
pages: siteIndex.pages,
|
|
466
479
|
sections: siteIndex.sections,
|
|
467
480
|
nav: siteIndex.nav,
|
|
481
|
+
tags: siteIndex.tags,
|
|
468
482
|
// Record the deletion INTENT, not just its effect on the order. The
|
|
469
483
|
// restore path reads this back; when it was hardcoded `[]` that path
|
|
470
484
|
// had to re-derive deletions by diffing this snapshot against a fresh
|
package/src/lib/env.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// env() is a byte-for-byte twin of packages/platform/src/env.ts: platform cannot
|
|
2
|
+
// import primitives without dragging it into apps/admin's bundle, so keep both.
|
|
1
3
|
declare global {
|
|
2
4
|
interface ImportMeta {
|
|
3
5
|
readonly env?: Record<string, string | undefined>;
|
|
@@ -11,3 +13,10 @@ export function env(key: string): string {
|
|
|
11
13
|
""
|
|
12
14
|
);
|
|
13
15
|
}
|
|
16
|
+
|
|
17
|
+
/** Vite replaces `import.meta.env.PROD` with a boolean literal at build time
|
|
18
|
+
* (packages are `noExternal`, so that covers this file too), which is why the
|
|
19
|
+
* declared string type above is bypassed here. False under Node and vitest. */
|
|
20
|
+
export function isProd(): boolean {
|
|
21
|
+
return (import.meta.env?.PROD as unknown) === true;
|
|
22
|
+
}
|
package/src/lib/events.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SiteNav } from "./nav";
|
|
2
2
|
|
|
3
3
|
export interface TypedEvent<T> {
|
|
4
4
|
dispatch(detail: T): void;
|
|
@@ -19,7 +19,6 @@ export function createEvent<T>(name: string): TypedEvent<T> {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export const editModeEvent = createEvent<{ isEditMode: boolean }>("editmodechange");
|
|
22
|
-
export const navChangeEvent = createEvent<NavItem[]>("sitenavchange");
|
|
23
22
|
export const darkModeEvent = createEvent<string>("sitedarkmode");
|
|
24
23
|
export const siteNameChangeEvent = createEvent<string>("sitenamechange");
|
|
25
24
|
export const historySelectEvent = createEvent<{ sha: string; date: string }>("history-select");
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
import type { ImageBackground, ImageBackgroundSurface } from "../schemas/shared";
|
|
3
|
+
|
|
4
|
+
// Class names are spelled out in full so Tailwind's source scan emits them.
|
|
5
|
+
// The surface-light/-dark tokens deliberately do NOT flip under `.dark`: a dark
|
|
6
|
+
// plate chosen for light mode must stay dark. The per-mode switch comes from the
|
|
7
|
+
// `dark:` variant instead, so it follows the theme toggle with no JS. An unset
|
|
8
|
+
// dark mode clears a light-mode plate rather than inheriting it.
|
|
9
|
+
const LIGHT_MODE: Record<ImageBackgroundSurface, string | undefined> = {
|
|
10
|
+
none: undefined,
|
|
11
|
+
light: "bg-surface-light",
|
|
12
|
+
dark: "bg-surface-dark",
|
|
13
|
+
};
|
|
14
|
+
const DARK_MODE: Record<ImageBackgroundSurface, string | undefined> = {
|
|
15
|
+
none: "dark:bg-transparent",
|
|
16
|
+
light: "dark:bg-surface-light",
|
|
17
|
+
dark: "dark:bg-surface-dark",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export interface ImageBackdrop {
|
|
21
|
+
className?: string;
|
|
22
|
+
style?: CSSProperties;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function imageBackdrop(bg: ImageBackground | undefined): ImageBackdrop | undefined {
|
|
26
|
+
if (!bg) return undefined;
|
|
27
|
+
if (bg.mode === "custom") return { style: { backgroundColor: bg.color } };
|
|
28
|
+
const light = LIGHT_MODE[bg.light];
|
|
29
|
+
if (!light && bg.dark === "none") return undefined;
|
|
30
|
+
return { className: [light, DARK_MODE[bg.dark]].filter(Boolean).join(" ") };
|
|
31
|
+
}
|
package/src/lib/index.ts
CHANGED
|
@@ -4,6 +4,9 @@ export { audiencePasses } from "./pages";
|
|
|
4
4
|
export { resolveChatbotName, resolveThinkingPhrases, DEFAULT_CHATBOT_NAME } from "./chatbot";
|
|
5
5
|
export { generateNavLinks, toSectionId, type NavItem } from "./nav";
|
|
6
6
|
export { navEntries, pagesInNavOrder, groupOfPage, groupDisplayLabel, reconcileNav } from "./nav-tree";
|
|
7
|
+
export { siteTags, tagDisplayLabel, reconcileTags } from "./tags";
|
|
8
|
+
export { resolveReference, type ReferenceContent } from "./references";
|
|
9
|
+
export { REFERENCE_TYPE } from "./reference-type";
|
|
7
10
|
export {
|
|
8
11
|
deriveContrast,
|
|
9
12
|
contrastColor,
|
|
@@ -15,12 +18,11 @@ export {
|
|
|
15
18
|
} from "./contrast";
|
|
16
19
|
export { primaryVarValue, accentVarValue, onPrimaryVarValue } from "./theme-vars";
|
|
17
20
|
export { sanitizeHtml, ensureSanitizer } from "./sanitize";
|
|
18
|
-
export { gridColsClass } from "./grid";
|
|
19
21
|
export { getIcon, curatedIcons, type IconEntry } from "./icons";
|
|
20
22
|
export { buildGoogleFontsUrl } from "./google-fonts";
|
|
21
23
|
export { formatTimestamp } from "./timestamp";
|
|
22
|
-
export { safeRedirect } from "./
|
|
23
|
-
export { createEvent, editModeEvent,
|
|
24
|
+
export { safeRedirect } from "./safe-redirect";
|
|
25
|
+
export { createEvent, editModeEvent, darkModeEvent, type TypedEvent } from "./events";
|
|
24
26
|
export {
|
|
25
27
|
createRegistry,
|
|
26
28
|
defineSection,
|
|
@@ -42,7 +44,6 @@ export {
|
|
|
42
44
|
export {
|
|
43
45
|
mergeSiteContent,
|
|
44
46
|
loadStaticSiteContent,
|
|
45
|
-
loadSiteContent,
|
|
46
47
|
type LoadedSection,
|
|
47
48
|
type SiteContent,
|
|
48
49
|
} from "./loader";
|
package/src/lib/loader.ts
CHANGED
|
@@ -4,10 +4,14 @@ import { getAllSchemas } from "./registry";
|
|
|
4
4
|
import { blockDepth, MAX_BLOCK_DEPTH } from "../schemas/block";
|
|
5
5
|
import { upgradeLegacySection } from "./migrate-sections-transform";
|
|
6
6
|
import { NavEntrySchema, type NavEntry } from "../schemas/nav";
|
|
7
|
+
import { TagEntrySchema, type TagEntry } from "../schemas/tags";
|
|
7
8
|
|
|
8
9
|
export interface LoadedSection {
|
|
9
10
|
section: Section;
|
|
10
11
|
meta: SectionMeta;
|
|
12
|
+
/** Set only on render-time copies a Reference pulled in (resolveReference):
|
|
13
|
+
* the id of that Reference. Never loaded or persisted. */
|
|
14
|
+
referencedBy?: string;
|
|
11
15
|
}
|
|
12
16
|
|
|
13
17
|
export interface SiteContent {
|
|
@@ -19,6 +23,9 @@ export interface SiteContent {
|
|
|
19
23
|
* nav.json from a degraded read permanently destroys the entries this
|
|
20
24
|
* version dropped. */
|
|
21
25
|
navDegraded: boolean;
|
|
26
|
+
/** Same contract as navDegraded, for tags.json: a degraded read is
|
|
27
|
+
* read-only for tags. */
|
|
28
|
+
tagsDegraded: boolean;
|
|
22
29
|
}
|
|
23
30
|
|
|
24
31
|
/**
|
|
@@ -34,7 +41,7 @@ function parseNavFile(navFile: unknown): { entries: NavEntry[]; degraded: boolea
|
|
|
34
41
|
if (!navFile) return { entries: [], degraded: false };
|
|
35
42
|
const rawEntries = (navFile as { entries?: unknown }).entries;
|
|
36
43
|
if (!Array.isArray(rawEntries)) {
|
|
37
|
-
console.warn("Invalid nav.json, falling back to a flat navigation");
|
|
44
|
+
console.warn("[loader] Invalid nav.json, falling back to a flat navigation");
|
|
38
45
|
return { entries: [], degraded: true };
|
|
39
46
|
}
|
|
40
47
|
const entries: NavEntry[] = [];
|
|
@@ -45,11 +52,46 @@ function parseNavFile(navFile: unknown): { entries: NavEntry[]; degraded: boolea
|
|
|
45
52
|
else dropped++;
|
|
46
53
|
}
|
|
47
54
|
if (dropped > 0) {
|
|
48
|
-
console.warn(`nav.json: dropped ${dropped} entr${dropped === 1 ? "y" : "ies"} this package version cannot represent; navigation is degraded`);
|
|
55
|
+
console.warn(`[loader] nav.json: dropped ${dropped} entr${dropped === 1 ? "y" : "ies"} this package version cannot represent; navigation is degraded`);
|
|
49
56
|
}
|
|
50
57
|
return { entries, degraded: dropped > 0 };
|
|
51
58
|
}
|
|
52
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Parse the tags.json sidecar with parseNavFile's per-entry tolerance and the
|
|
62
|
+
* same `degraded` contract. Assignments to deleted sections are NOT pruned
|
|
63
|
+
* here — that is reconcileTags' job on every read (siteTags), so the runtime
|
|
64
|
+
* field stays a faithful copy of the file.
|
|
65
|
+
*/
|
|
66
|
+
function parseTagsFile(tagsFile: unknown): { tags: TagEntry[]; degraded: boolean } {
|
|
67
|
+
if (!tagsFile) return { tags: [], degraded: false };
|
|
68
|
+
const rawTags = (tagsFile as { tags?: unknown }).tags;
|
|
69
|
+
if (!Array.isArray(rawTags)) {
|
|
70
|
+
console.warn("[loader] Invalid tags.json, falling back to no tags");
|
|
71
|
+
return { tags: [], degraded: true };
|
|
72
|
+
}
|
|
73
|
+
const tags: TagEntry[] = [];
|
|
74
|
+
let dropped = 0;
|
|
75
|
+
for (const raw of rawTags) {
|
|
76
|
+
const result = TagEntrySchema.safeParse(raw);
|
|
77
|
+
if (result.success) tags.push(result.data);
|
|
78
|
+
else dropped++;
|
|
79
|
+
}
|
|
80
|
+
if (dropped > 0) {
|
|
81
|
+
console.warn(`[loader] tags.json: dropped ${dropped} entr${dropped === 1 ? "y" : "ies"} this package version cannot represent; tags are degraded`);
|
|
82
|
+
}
|
|
83
|
+
return { tags, degraded: dropped > 0 };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Whether a load looked for tags.json. Not loaded ⇒ no `index.tags` is attached
|
|
88
|
+
* and writers leave the file alone; loaded ⇒ `file` is its parsed contents,
|
|
89
|
+
* with null/undefined meaning absent (an empty registry). Unlike nav, the
|
|
90
|
+
* difference is load-bearing — an attached `[]` that a writer saves back
|
|
91
|
+
* deletes every tag — hence an explicit flag rather than undefined-vs-null.
|
|
92
|
+
*/
|
|
93
|
+
export type TagsSidecar = { loaded: false } | { loaded: true; file: unknown };
|
|
94
|
+
|
|
53
95
|
/**
|
|
54
96
|
* Merge a validated index with raw section file contents.
|
|
55
97
|
* Validates each section file against its Zod schema.
|
|
@@ -59,6 +101,7 @@ export function mergeSiteContent(
|
|
|
59
101
|
index: SiteIndex,
|
|
60
102
|
sectionFiles: Record<string, unknown>,
|
|
61
103
|
navFile?: unknown,
|
|
104
|
+
tagsSidecar: TagsSidecar = { loaded: false },
|
|
62
105
|
): SiteContent {
|
|
63
106
|
const sections: LoadedSection[] = [];
|
|
64
107
|
|
|
@@ -112,7 +155,13 @@ export function mergeSiteContent(
|
|
|
112
155
|
}
|
|
113
156
|
|
|
114
157
|
const nav = parseNavFile(navFile);
|
|
115
|
-
|
|
158
|
+
const tags = tagsSidecar.loaded ? parseTagsFile(tagsSidecar.file) : null;
|
|
159
|
+
return {
|
|
160
|
+
sections,
|
|
161
|
+
index: { ...index, nav: nav.entries, ...(tags ? { tags: tags.tags } : {}) },
|
|
162
|
+
navDegraded: nav.degraded,
|
|
163
|
+
tagsDegraded: tags?.degraded ?? false,
|
|
164
|
+
};
|
|
116
165
|
}
|
|
117
166
|
|
|
118
167
|
/**
|
|
@@ -124,6 +173,7 @@ export function loadStaticSiteContent(
|
|
|
124
173
|
index: SiteIndex,
|
|
125
174
|
sectionGlob: Record<string, unknown>,
|
|
126
175
|
navFile?: unknown,
|
|
176
|
+
tagsSidecar: TagsSidecar = { loaded: false },
|
|
127
177
|
): SiteContent {
|
|
128
178
|
const sectionFiles: Record<string, unknown> = {};
|
|
129
179
|
for (const [path, data] of Object.entries(sectionGlob)) {
|
|
@@ -131,56 +181,5 @@ export function loadStaticSiteContent(
|
|
|
131
181
|
const id = filename.replace(".json", "");
|
|
132
182
|
sectionFiles[id] = data;
|
|
133
183
|
}
|
|
134
|
-
return mergeSiteContent(index, sectionFiles, navFile);
|
|
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;
|
|
184
|
+
return mergeSiteContent(index, sectionFiles, navFile, tagsSidecar);
|
|
186
185
|
}
|
package/src/lib/nav-tree.ts
CHANGED
|
@@ -204,3 +204,74 @@ export function moveNavEntry(index: SiteIndex, from: NavLocation, to: NavLocatio
|
|
|
204
204
|
|
|
205
205
|
return withNav(index, entries);
|
|
206
206
|
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* "Moved <label> to position N of M" for the aria-live reorder announcement,
|
|
210
|
+
* covering both `moveNavEntry` callers: drag (PagesModal/NavGroupRow) and the
|
|
211
|
+
* Move up/down buttons. `prevIndex` resolves WHO moved and its label (read
|
|
212
|
+
* before the move, since `from` is a position, not an id); `nextIndex` (the
|
|
213
|
+
* result of `moveNavEntry(prevIndex, from, to)`) is searched by id for where
|
|
214
|
+
* it actually landed — robust to `moveNavEntry`'s own clamping, so the caller
|
|
215
|
+
* never has to replicate that math. Returns null if `from` didn't resolve to
|
|
216
|
+
* a real row (defensive; ordinary callers always pass a live location).
|
|
217
|
+
*/
|
|
218
|
+
/** A top-level entry counts toward "N of M" iff it's a group (always visible)
|
|
219
|
+
* or a page that isn't archived — mirrors the PagesModal Move up/down rows,
|
|
220
|
+
* which skip archived pages entirely rather than render an inert slot. */
|
|
221
|
+
function isLiveTopEntry(index: SiteIndex, entry: NavEntry): boolean {
|
|
222
|
+
if (entry.kind === "group") return true;
|
|
223
|
+
const page = index.pages.find((p) => p.id === entry.pageId);
|
|
224
|
+
return page?.status === "live";
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function describeNavMove(prevIndex: SiteIndex, nextIndex: SiteIndex, from: NavLocation): string | null {
|
|
228
|
+
const prevEntries = navEntries(prevIndex);
|
|
229
|
+
let label: string;
|
|
230
|
+
let pageId: string | null = null;
|
|
231
|
+
let groupId: string | null = null;
|
|
232
|
+
|
|
233
|
+
if (from.groupId === null) {
|
|
234
|
+
const entry = prevEntries[from.index];
|
|
235
|
+
if (!entry) return null;
|
|
236
|
+
if (entry.kind === "group") {
|
|
237
|
+
label = groupDisplayLabel(entry.label);
|
|
238
|
+
groupId = entry.id;
|
|
239
|
+
} else {
|
|
240
|
+
const page = prevIndex.pages.find((p) => p.id === entry.pageId);
|
|
241
|
+
if (!page) return null;
|
|
242
|
+
label = page.title || "Untitled";
|
|
243
|
+
pageId = page.id;
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
const group = prevEntries.find((e) => e.kind === "group" && e.id === from.groupId);
|
|
247
|
+
if (!group || group.kind !== "group") return null;
|
|
248
|
+
const id = group.pageIds[from.index];
|
|
249
|
+
if (!id) return null;
|
|
250
|
+
const page = prevIndex.pages.find((p) => p.id === id);
|
|
251
|
+
if (!page) return null;
|
|
252
|
+
label = page.title || "Untitled";
|
|
253
|
+
pageId = page.id;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const nextEntries = navEntries(nextIndex);
|
|
257
|
+
const liveTopEntries = nextEntries.filter((e) => isLiveTopEntry(nextIndex, e));
|
|
258
|
+
|
|
259
|
+
if (groupId !== null) {
|
|
260
|
+
const i = liveTopEntries.findIndex((e) => e.kind === "group" && e.id === groupId);
|
|
261
|
+
if (i === -1) return null;
|
|
262
|
+
return `Moved ${label} to position ${i + 1} of ${liveTopEntries.length}`;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (pageId === null) return null;
|
|
266
|
+
|
|
267
|
+
const topIndex = liveTopEntries.findIndex((e) => e.kind === "page" && e.pageId === pageId);
|
|
268
|
+
if (topIndex !== -1) return `Moved ${label} to position ${topIndex + 1} of ${liveTopEntries.length}`;
|
|
269
|
+
for (const e of nextEntries) {
|
|
270
|
+
if (e.kind === "group") {
|
|
271
|
+
const liveMemberIds = e.pageIds.filter((id) => nextIndex.pages.find((p) => p.id === id)?.status === "live");
|
|
272
|
+
const gi = liveMemberIds.indexOf(pageId);
|
|
273
|
+
if (gi !== -1) return `Moved ${label} to position ${gi + 1} of ${liveMemberIds.length}`;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
}
|