@drawnagency/primitives 0.1.112 → 0.1.114
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/auth/cookies.d.ts +39 -0
- package/dist/auth/cookies.d.ts.map +1 -1
- package/dist/auth/index.js +3 -3
- package/dist/auth/types.d.ts +1 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/{chunk-GPPVYLEI.js → chunk-45FA7Z55.js} +1 -1
- package/dist/{chunk-REDDTTGJ.js → chunk-4Y2JQQZL.js} +19 -1
- package/dist/chunk-5GFACGSN.js +6 -0
- package/dist/chunk-5KSAS4VY.js +275 -0
- package/dist/{chunk-5KNXTMUC.js → chunk-7SAAJVDE.js} +408 -28
- package/dist/{chunk-S2L3BPLS.js → chunk-7SX42OP4.js} +1 -1
- package/dist/{chunk-GGXZZ77Z.js → chunk-AASEGXNT.js} +18 -1
- package/dist/{chunk-WKZ7OENC.js → chunk-BQ5TZZUE.js} +5 -1
- package/dist/chunk-DIMDRBFK.js +11 -0
- package/dist/{chunk-WUJ3XNFI.js → chunk-GGYY3JQJ.js} +19 -24
- package/dist/{chunk-VLPELTPI.js → chunk-IP2SEBAJ.js} +5 -1
- package/dist/{chunk-IINIZBQB.js → chunk-JCDZAFX2.js} +30 -10
- package/dist/chunk-JR24U7FJ.js +120 -0
- package/dist/{chunk-SW6PCQQD.js → chunk-KQA772WQ.js} +2 -1
- package/dist/{chunk-Z2LO4PSQ.js → chunk-N3G7DOU3.js} +609 -61
- package/dist/chunk-OAGJBCSH.js +67 -0
- package/dist/{chunk-VT3PYGVW.js → chunk-PLANHXS7.js} +191 -61
- package/dist/{chunk-OGGZ5AXT.js → chunk-PNSCDBU7.js} +38 -56
- package/dist/{chunk-HSXMOS5Q.js → chunk-PTY2RG2K.js} +5 -2
- package/dist/{chunk-EPWBPIV6.js → chunk-PZPGJZRG.js} +9 -8
- package/dist/{chunk-P3ZNCHW7.js → chunk-QHMKIODQ.js} +19 -5
- package/dist/{chunk-HBULBDGP.js → chunk-S37DZPHW.js} +1 -1
- package/dist/{chunk-4I5OO5UB.js → chunk-TEOAKGZA.js} +0 -1
- package/dist/chunk-VUYCRBJK.js +174 -0
- package/dist/{chunk-4RNF2DRG.js → chunk-XDEPXTBY.js} +0 -2
- package/dist/{chunk-3SZNUCXI.js → chunk-Y5QECJX7.js} +223 -16
- package/dist/collab/rebase.d.ts +2 -1
- package/dist/collab/rebase.d.ts.map +1 -1
- package/dist/collab/rebase.js +20 -5
- package/dist/components/brandguide/ColorsEditable.d.ts.map +1 -1
- package/dist/components/chat/ChatPanel.d.ts.map +1 -1
- package/dist/components/chat/ChatWidget.d.ts.map +1 -1
- package/dist/components/docfile/DocFilePane.d.ts.map +1 -1
- package/dist/components/editor/ChildBlockWrapper.d.ts.map +1 -1
- package/dist/components/editor/ConflictDialog.d.ts.map +1 -1
- package/dist/components/editor/DragHandle.d.ts +12 -2
- package/dist/components/editor/DragHandle.d.ts.map +1 -1
- package/dist/components/editor/DropEdgeIndicator.d.ts +15 -6
- package/dist/components/editor/DropEdgeIndicator.d.ts.map +1 -1
- package/dist/components/editor/NavGroupRow.d.ts +4 -1
- package/dist/components/editor/NavGroupRow.d.ts.map +1 -1
- package/dist/components/editor/PagesModal.d.ts.map +1 -1
- package/dist/components/editor/SectionWrapper.d.ts +1 -1
- package/dist/components/editor/SectionWrapper.d.ts.map +1 -1
- package/dist/components/editor/SettingsForm.d.ts.map +1 -1
- package/dist/components/editor/TagIndicator.d.ts +15 -0
- package/dist/components/editor/TagIndicator.d.ts.map +1 -0
- package/dist/components/editor/index.js +148 -77
- package/dist/components/primitives/DocumentDropZone.d.ts +1 -1
- package/dist/components/primitives/EditableGrid.d.ts.map +1 -1
- package/dist/components/primitives/EditableList.d.ts.map +1 -1
- package/dist/components/primitives/HeadingSection.d.ts +4 -1
- package/dist/components/primitives/HeadingSection.d.ts.map +1 -1
- package/dist/components/primitives/ResolvedMedia.d.ts +5 -1
- package/dist/components/primitives/ResolvedMedia.d.ts.map +1 -1
- package/dist/components/primitives/{defineHeadingSection.d.ts → define-heading-section.d.ts} +1 -1
- package/dist/components/primitives/define-heading-section.d.ts.map +1 -0
- package/dist/components/primitives/{gridDrop.d.ts → grid-drop.d.ts} +1 -1
- package/dist/components/primitives/grid-drop.d.ts.map +1 -0
- package/dist/components/primitives/index.d.ts +1 -1
- package/dist/components/primitives/index.d.ts.map +1 -1
- package/dist/components/primitives/index.js +17 -154
- package/dist/components/sections/Button/CTAButton.d.ts.map +1 -1
- package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts +2 -6
- package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts.map +1 -1
- package/dist/components/sections/DoDontMedia/index.d.ts +8 -0
- package/dist/components/sections/DoDontMedia/index.d.ts.map +1 -1
- package/dist/components/sections/IconList/IconList.d.ts +2 -1
- package/dist/components/sections/IconList/IconList.d.ts.map +1 -1
- package/dist/components/sections/IconList/IconListSettings.d.ts +2 -1
- package/dist/components/sections/IconList/IconListSettings.d.ts.map +1 -1
- package/dist/components/sections/IconList/index.d.ts +1 -0
- package/dist/components/sections/IconList/index.d.ts.map +1 -1
- package/dist/components/sections/Media/MediaBlock.d.ts +2 -1
- package/dist/components/sections/Media/MediaBlock.d.ts.map +1 -1
- package/dist/components/sections/Media/index.d.ts +8 -0
- package/dist/components/sections/Media/index.d.ts.map +1 -1
- package/dist/components/sections/Reference/ReferenceList.d.ts +35 -0
- package/dist/components/sections/Reference/ReferenceList.d.ts.map +1 -0
- package/dist/components/sections/Reference/ReferenceSettings.d.ts +12 -0
- package/dist/components/sections/Reference/ReferenceSettings.d.ts.map +1 -0
- package/dist/components/sections/Reference/index.d.ts +9 -0
- package/dist/components/sections/Reference/index.d.ts.map +1 -0
- package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts +38 -0
- package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts.map +1 -0
- package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts +20 -0
- package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts.map +1 -0
- package/dist/components/sections/SectionSummary/index.d.ts +33 -0
- package/dist/components/sections/SectionSummary/index.d.ts.map +1 -0
- package/dist/components/sections/all-sections.d.ts +53 -0
- package/dist/components/sections/all-sections.d.ts.map +1 -1
- package/dist/components/sections/brand-guide.d.ts +41 -2
- package/dist/components/sections/brand-guide.d.ts.map +1 -1
- package/dist/components/sections/brand-guide.js +12 -10
- package/dist/components/sections/core-sections.d.ts +14 -0
- package/dist/components/sections/core-sections.d.ts.map +1 -1
- package/dist/components/sections/register-schemas.js +19 -17
- package/dist/components/sections/register.js +19 -17
- package/dist/components/shared/BrandSwatchesContext.d.ts +9 -0
- package/dist/components/shared/BrandSwatchesContext.d.ts.map +1 -0
- package/dist/components/shared/Button.d.ts +11 -3
- package/dist/components/shared/Button.d.ts.map +1 -1
- package/dist/components/shared/Checkbox.d.ts +6 -0
- package/dist/components/shared/Checkbox.d.ts.map +1 -1
- package/dist/components/shared/ConfirmDialog.d.ts +25 -0
- package/dist/components/shared/ConfirmDialog.d.ts.map +1 -0
- package/dist/components/shared/ConfirmInline.d.ts +25 -0
- package/dist/components/shared/ConfirmInline.d.ts.map +1 -0
- package/dist/components/shared/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/shared/Fab.d.ts +11 -2
- package/dist/components/shared/Fab.d.ts.map +1 -1
- package/dist/components/shared/FabStack.d.ts +22 -0
- package/dist/components/shared/FabStack.d.ts.map +1 -0
- package/dist/components/shared/HistoryChangesModal.d.ts.map +1 -1
- package/dist/components/shared/HistoryPopover.d.ts.map +1 -1
- package/dist/components/shared/ImageBackgroundField.d.ts +9 -0
- package/dist/components/shared/ImageBackgroundField.d.ts.map +1 -0
- package/dist/components/shared/{UploadRejectionAlert.d.ts → InlineAlert.d.ts} +4 -2
- package/dist/components/shared/InlineAlert.d.ts.map +1 -0
- package/dist/components/shared/Input.d.ts +10 -0
- package/dist/components/shared/Input.d.ts.map +1 -1
- package/dist/components/shared/Navigation.d.ts +1 -0
- package/dist/components/shared/Navigation.d.ts.map +1 -1
- package/dist/components/shared/Notice.d.ts +10 -0
- package/dist/components/shared/Notice.d.ts.map +1 -0
- package/dist/components/shared/Popover.d.ts.map +1 -1
- package/dist/components/shared/ReferenceSourcesContext.d.ts +25 -0
- package/dist/components/shared/ReferenceSourcesContext.d.ts.map +1 -0
- package/dist/components/shared/Select.d.ts +3 -2
- package/dist/components/shared/Select.d.ts.map +1 -1
- package/dist/components/shared/SplitButton.d.ts.map +1 -1
- package/dist/components/shared/SummaryAnchorsContext.d.ts +10 -0
- package/dist/components/shared/SummaryAnchorsContext.d.ts.map +1 -0
- package/dist/components/shared/Textarea.d.ts +7 -0
- package/dist/components/shared/Textarea.d.ts.map +1 -1
- package/dist/components/shared/ToolbarFrame.d.ts +17 -0
- package/dist/components/shared/ToolbarFrame.d.ts.map +1 -0
- package/dist/components/shared/copy.d.ts +13 -0
- package/dist/components/shared/copy.d.ts.map +1 -0
- package/dist/components/shared/icons.d.ts +0 -12
- package/dist/components/shared/icons.d.ts.map +1 -1
- package/dist/components/shell/AudienceDetailsPanel.d.ts +7 -1
- package/dist/components/shell/AudienceDetailsPanel.d.ts.map +1 -1
- package/dist/components/shell/AudienceRow.d.ts.map +1 -1
- package/dist/components/shell/BugReportFAB.d.ts +7 -1
- package/dist/components/shell/BugReportFAB.d.ts.map +1 -1
- package/dist/components/shell/CredentialList.d.ts.map +1 -1
- package/dist/components/shell/DocInspector.d.ts.map +1 -1
- package/dist/components/shell/DocumentEditorOverlay.d.ts.map +1 -1
- package/dist/components/shell/EditorContext.d.ts +4 -0
- package/dist/components/shell/EditorContext.d.ts.map +1 -1
- package/dist/components/shell/EditorLoginForm.d.ts.map +1 -1
- package/dist/components/shell/EditorModal.d.ts.map +1 -1
- package/dist/components/shell/EditorShell.d.ts.map +1 -1
- package/dist/components/shell/HistoryToolbar.d.ts.map +1 -1
- package/dist/components/shell/MediaFolderTile.d.ts +4 -1
- package/dist/components/shell/MediaFolderTile.d.ts.map +1 -1
- package/dist/components/shell/MediaLibraryModal.d.ts.map +1 -1
- package/dist/components/shell/RestoreModal.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsChatbot.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsDisplay.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsModal.d.ts +3 -1
- package/dist/components/shell/SiteSettingsModal.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsTags.d.ts +13 -0
- package/dist/components/shell/SiteSettingsTags.d.ts.map +1 -0
- package/dist/components/shell/SiteSettingsUsers.d.ts.map +1 -1
- package/dist/components/shell/ViewerLoginForm.d.ts.map +1 -1
- package/dist/components/shell/{blockMoveDispatch.d.ts → block-move-dispatch.d.ts} +1 -1
- package/dist/components/shell/block-move-dispatch.d.ts.map +1 -0
- package/dist/components/shell/reference-sources.d.ts +22 -0
- package/dist/components/shell/reference-sources.d.ts.map +1 -0
- package/dist/deck/index.d.ts +2 -2
- package/dist/deck/index.d.ts.map +1 -1
- package/dist/deck/index.js +1 -3
- package/dist/deck-builder/index.js +11 -18
- package/dist/document/index.d.ts +2 -2
- package/dist/document/index.d.ts.map +1 -1
- package/dist/hooks/useBlockDnd.d.ts +11 -0
- package/dist/hooks/useBlockDnd.d.ts.map +1 -1
- package/dist/hooks/useBuildStatus.d.ts +1 -1
- package/dist/hooks/useBuildStatus.d.ts.map +1 -1
- package/dist/hooks/useDocumentUploads.d.ts +1 -1
- package/dist/hooks/useDocumentUploads.d.ts.map +1 -1
- package/dist/hooks/useEditorPersistence.d.ts +5 -1
- package/dist/hooks/useEditorPersistence.d.ts.map +1 -1
- package/dist/hooks/useEditorPublish.d.ts +2 -2
- package/dist/hooks/useEditorPublish.d.ts.map +1 -1
- package/dist/hooks/useNotice.d.ts +19 -0
- package/dist/hooks/useNotice.d.ts.map +1 -0
- package/dist/hooks/useSortableNavRow.d.ts +11 -0
- package/dist/hooks/useSortableNavRow.d.ts.map +1 -1
- package/dist/hooks/useSortableRow.d.ts +11 -0
- package/dist/hooks/useSortableRow.d.ts.map +1 -1
- package/dist/hooks/useStackedEscape.d.ts +32 -0
- package/dist/hooks/useStackedEscape.d.ts.map +1 -0
- package/dist/index.js +67 -49
- package/dist/lib/audience-secret.js +2 -2
- package/dist/lib/block-dnd.d.ts +5 -0
- package/dist/lib/block-dnd.d.ts.map +1 -1
- package/dist/lib/block-move.d.ts.map +1 -1
- package/dist/lib/brand-swatches.d.ts +12 -0
- package/dist/lib/brand-swatches.d.ts.map +1 -0
- package/dist/lib/container-ops.d.ts +3 -2
- package/dist/lib/container-ops.d.ts.map +1 -1
- package/dist/lib/dexie.d.ts.map +1 -1
- package/dist/lib/dexie.js +9 -1
- package/dist/lib/env.d.ts +4 -0
- package/dist/lib/env.d.ts.map +1 -1
- package/dist/lib/env.js +5 -3
- package/dist/lib/events.d.ts +1 -2
- package/dist/lib/events.d.ts.map +1 -1
- package/dist/lib/image-background.d.ts +8 -0
- package/dist/lib/image-background.d.ts.map +1 -0
- package/dist/lib/index-ops.js +3 -3
- package/dist/lib/index.d.ts +6 -4
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +29 -21
- package/dist/lib/loader.d.ts +21 -7
- package/dist/lib/loader.d.ts.map +1 -1
- package/dist/lib/nav-tree.d.ts +1 -0
- package/dist/lib/nav-tree.d.ts.map +1 -1
- package/dist/lib/nav.d.ts +38 -0
- package/dist/lib/nav.d.ts.map +1 -1
- package/dist/lib/platform-broker.d.ts +4 -2
- package/dist/lib/platform-broker.d.ts.map +1 -1
- package/dist/lib/platform-broker.js +21 -13
- package/dist/lib/reference-type.d.ts +2 -0
- package/dist/lib/reference-type.d.ts.map +1 -0
- package/dist/lib/reference-validation.d.ts +31 -0
- package/dist/lib/reference-validation.d.ts.map +1 -0
- package/dist/lib/reference-validation.js +39 -0
- package/dist/lib/references.d.ts +74 -0
- package/dist/lib/references.d.ts.map +1 -0
- package/dist/lib/registry.d.ts +35 -0
- package/dist/lib/registry.d.ts.map +1 -1
- package/dist/lib/{safeRedirect.d.ts → safe-redirect.d.ts} +1 -1
- package/dist/lib/safe-redirect.d.ts.map +1 -0
- package/dist/lib/tags.d.ts +58 -0
- package/dist/lib/tags.d.ts.map +1 -0
- package/dist/lib/theme-vars.d.ts +9 -0
- package/dist/lib/theme-vars.d.ts.map +1 -1
- package/dist/media/index.d.ts +1 -1
- package/dist/media/index.d.ts.map +1 -1
- package/dist/media/index.js +8 -4
- package/dist/media/resolve.d.ts +2 -0
- package/dist/media/resolve.d.ts.map +1 -1
- package/dist/media/utils.d.ts +2 -0
- package/dist/media/utils.d.ts.map +1 -1
- package/dist/media/{videoPoster.d.ts → video-poster.d.ts} +1 -1
- package/dist/media/video-poster.d.ts.map +1 -0
- package/dist/schemas/audience.js +2 -2
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +14 -8
- package/dist/schemas/shared.d.ts +26 -0
- package/dist/schemas/shared.d.ts.map +1 -1
- package/dist/schemas/site-config.d.ts +7 -0
- package/dist/schemas/site-config.d.ts.map +1 -1
- package/dist/schemas/tags.d.ts +27 -0
- package/dist/schemas/tags.d.ts.map +1 -0
- package/dist/storage/index.js +1 -1
- package/dist/types/database.d.ts +8 -0
- package/dist/types/database.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/auth/cookies.ts +111 -0
- package/src/auth/types.ts +1 -0
- package/src/collab/rebase.ts +26 -2
- package/src/components/brandguide/ColorSwatchSettings.tsx +1 -1
- package/src/components/brandguide/ColorsEditable.tsx +1 -0
- package/src/components/chat/ChatPanel.tsx +2 -3
- package/src/components/chat/ChatWidget.tsx +7 -7
- package/src/components/docfile/DocFilePane.tsx +4 -12
- package/src/components/editor/ChildBlockWrapper.tsx +13 -19
- package/src/components/editor/ConflictDialog.tsx +27 -35
- package/src/components/editor/DeleteButton.tsx +2 -2
- package/src/components/editor/DragHandle.tsx +16 -3
- package/src/components/editor/DropEdgeIndicator.tsx +36 -10
- package/src/components/editor/InsertButton.tsx +2 -2
- package/src/components/editor/NavGroupRow.tsx +43 -14
- package/src/components/editor/PagesModal.tsx +99 -26
- package/src/components/editor/SectionWrapper.tsx +64 -23
- package/src/components/editor/SettingsButton.tsx +2 -2
- package/src/components/editor/SettingsForm.tsx +19 -2
- package/src/components/editor/StatusIndicator.tsx +4 -4
- package/src/components/editor/TagIndicator.tsx +80 -0
- package/src/components/primitives/DocumentDropZone.tsx +1 -1
- package/src/components/primitives/EditableGrid.tsx +15 -14
- package/src/components/primitives/EditableList.tsx +27 -74
- package/src/components/primitives/HeadingSection.tsx +5 -2
- package/src/components/primitives/ResolvedMedia.tsx +13 -0
- package/src/components/primitives/{defineHeadingSection.tsx → define-heading-section.tsx} +1 -0
- package/src/components/primitives/index.ts +1 -1
- package/src/components/primitives/useEditablePlainText.ts +5 -5
- package/src/components/sections/Button/CTAButton.tsx +3 -1
- package/src/components/sections/DoDontMedia/DoDontMediaBlock.tsx +4 -4
- package/src/components/sections/DoDontMedia/index.tsx +12 -3
- package/src/components/sections/IconList/DoDontToggle.tsx +2 -2
- package/src/components/sections/IconList/IconList.tsx +70 -37
- package/src/components/sections/IconList/IconListSettings.tsx +55 -17
- package/src/components/sections/IconList/index.tsx +10 -3
- package/src/components/sections/LinkHeading/index.tsx +1 -1
- package/src/components/sections/Media/MediaBlock.tsx +13 -2
- package/src/components/sections/Media/index.tsx +12 -4
- package/src/components/sections/Reference/ReferenceList.tsx +214 -0
- package/src/components/sections/Reference/ReferenceSettings.tsx +159 -0
- package/src/components/sections/Reference/index.tsx +47 -0
- package/src/components/sections/SectionSummary/SectionSummaryBlock.tsx +476 -0
- package/src/components/sections/SectionSummary/SectionSummarySettings.tsx +126 -0
- package/src/components/sections/SectionSummary/index.tsx +149 -0
- package/src/components/sections/SubHeading/index.tsx +1 -1
- package/src/components/sections/SubSubHeading/index.tsx +1 -1
- package/src/components/sections/brand-guide.ts +4 -3
- package/src/components/sections/core-sections.ts +2 -0
- package/src/components/shared/BrandSwatchesContext.ts +13 -0
- package/src/components/shared/Button.tsx +47 -34
- package/src/components/shared/Checkbox.tsx +21 -12
- package/src/components/shared/ConfirmDialog.tsx +87 -0
- package/src/components/shared/ConfirmInline.tsx +90 -0
- package/src/components/shared/ErrorBoundary.tsx +6 -18
- package/src/components/shared/Fab.tsx +15 -5
- package/src/components/shared/FabStack.tsx +28 -0
- package/src/components/shared/HistoryChangesModal.tsx +43 -41
- package/src/components/shared/HistoryPopover.tsx +7 -20
- package/src/components/shared/ImageBackgroundField.tsx +92 -0
- package/src/components/shared/{UploadRejectionAlert.tsx → InlineAlert.tsx} +21 -5
- package/src/components/shared/Input.tsx +23 -7
- package/src/components/shared/Navigation.tsx +48 -35
- package/src/components/shared/Notice.tsx +59 -0
- package/src/components/shared/Popover.tsx +7 -11
- package/src/components/shared/ReferenceSourcesContext.ts +27 -0
- package/src/components/shared/Select.tsx +5 -2
- package/src/components/shared/SplitButton.tsx +11 -17
- package/src/components/shared/SummaryAnchorsContext.ts +11 -0
- package/src/components/shared/Textarea.tsx +17 -2
- package/src/components/shared/ToolbarFrame.tsx +28 -0
- package/src/components/shared/VideoSourceField.tsx +1 -1
- package/src/components/shared/copy.ts +18 -0
- package/src/components/shared/icons.tsx +1 -17
- package/src/components/shell/AudienceAddForm.tsx +2 -2
- package/src/components/shell/AudienceDetailsPanel.tsx +23 -5
- package/src/components/shell/AudienceRow.tsx +22 -15
- package/src/components/shell/BugReportFAB.tsx +50 -40
- package/src/components/shell/CredentialList.tsx +33 -13
- package/src/components/shell/DocInspector.tsx +3 -12
- package/src/components/shell/DocumentEditorOverlay.tsx +33 -23
- package/src/components/shell/EditorContext.tsx +7 -0
- package/src/components/shell/EditorLoginForm.tsx +26 -36
- package/src/components/shell/EditorModal.tsx +8 -10
- package/src/components/shell/EditorShell.tsx +499 -339
- package/src/components/shell/HistoryToolbar.tsx +24 -26
- package/src/components/shell/MediaFolderTile.tsx +8 -3
- package/src/components/shell/MediaLibraryModal.tsx +59 -60
- package/src/components/shell/ProcessingIndicator.tsx +2 -2
- package/src/components/shell/RestoreModal.tsx +17 -16
- package/src/components/shell/SetPasswordForm.tsx +3 -3
- package/src/components/shell/SiteSettingsChatbot.tsx +61 -42
- package/src/components/shell/SiteSettingsDisplay.tsx +20 -21
- package/src/components/shell/SiteSettingsModal.tsx +24 -2
- package/src/components/shell/SiteSettingsTags.tsx +143 -0
- package/src/components/shell/SiteSettingsUsers.tsx +85 -28
- package/src/components/shell/SiteSettingsViewerAccess.tsx +2 -2
- package/src/components/shell/ViewerLoginForm.tsx +5 -4
- package/src/components/shell/reference-sources.ts +36 -0
- package/src/deck/index.ts +2 -2
- package/src/document/index.ts +2 -2
- package/src/hooks/useBlockDnd.ts +11 -0
- package/src/hooks/useBuildStatus.ts +53 -6
- package/src/hooks/useDocumentUploads.ts +1 -1
- package/src/hooks/useEditorPersistence.ts +141 -35
- package/src/hooks/useEditorPublish.ts +18 -27
- package/src/hooks/useMediaPipeline.ts +1 -1
- package/src/hooks/useNotice.ts +45 -0
- package/src/hooks/useSortableNavRow.ts +11 -0
- package/src/hooks/useSortableRow.ts +22 -2
- package/src/hooks/useStackedEscape.ts +62 -0
- package/src/lib/block-dnd.ts +6 -1
- package/src/lib/block-move.ts +3 -0
- package/src/lib/brand-swatches.ts +32 -0
- package/src/lib/container-ops.ts +5 -3
- package/src/lib/dexie.ts +15 -1
- package/src/lib/env.ts +9 -0
- package/src/lib/events.ts +1 -2
- package/src/lib/image-background.ts +31 -0
- package/src/lib/index.ts +5 -4
- package/src/lib/loader.ts +54 -55
- package/src/lib/nav-tree.ts +71 -0
- package/src/lib/nav.ts +196 -36
- package/src/lib/platform-broker.ts +32 -14
- package/src/lib/reference-type.ts +3 -0
- package/src/lib/reference-validation.ts +69 -0
- package/src/lib/references.ts +130 -0
- package/src/lib/registry.ts +37 -0
- package/src/lib/tags.ts +148 -0
- package/src/lib/theme-vars.ts +23 -0
- package/src/media/index.ts +1 -1
- package/src/media/resolve.ts +3 -1
- package/src/media/utils.ts +18 -0
- package/src/media/{videoPoster.ts → video-poster.ts} +2 -2
- package/src/schemas/index.ts +1 -0
- package/src/schemas/shared.ts +24 -1
- package/src/schemas/site-config.ts +9 -1
- package/src/schemas/tags.ts +33 -0
- package/src/storage/types.ts +1 -1
- package/src/types/database.ts +6 -0
- package/dist/chunk-BR4MIPTM.js +0 -138
- package/dist/chunk-DNY72JZN.js +0 -86
- package/dist/chunk-F2LYQPXV.js +0 -77
- package/dist/chunk-TALRVOGO.js +0 -128
- package/dist/components/primitives/defineHeadingSection.d.ts.map +0 -1
- package/dist/components/primitives/gridDrop.d.ts.map +0 -1
- package/dist/components/shared/UploadRejectionAlert.d.ts.map +0 -1
- package/dist/components/shell/BuildStatusIndicator.d.ts +0 -7
- package/dist/components/shell/BuildStatusIndicator.d.ts.map +0 -1
- package/dist/components/shell/blockMoveDispatch.d.ts.map +0 -1
- package/dist/hooks/index.d.ts +0 -9
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/lib/grid.d.ts +0 -2
- package/dist/lib/grid.d.ts.map +0 -1
- package/dist/lib/safeRedirect.d.ts.map +0 -1
- package/dist/media/videoPoster.d.ts.map +0 -1
- package/src/components/brandguide/ColorSwatchSettings.d.ts.map +0 -1
- package/src/components/brandguide/Colors.d.ts.map +0 -1
- package/src/components/primitives/CustomParagraph.d.ts.map +0 -1
- package/src/components/primitives/EditableGrid.d.ts.map +0 -1
- package/src/components/primitives/EditablePlainText.d.ts.map +0 -1
- package/src/components/primitives/EditableRichText.d.ts.map +0 -1
- package/src/components/primitives/HeadingSection.d.ts.map +0 -1
- package/src/components/primitives/IconPicker.d.ts.map +0 -1
- package/src/components/primitives/LinkPopover.d.ts.map +0 -1
- package/src/components/primitives/MediaSettingsForms.d.ts.map +0 -1
- package/src/components/primitives/ResolvedMedia.d.ts.map +0 -1
- package/src/components/primitives/RichTextToolbar.d.ts.map +0 -1
- package/src/components/primitives/tiptap-presets.d.ts.map +0 -1
- package/src/components/primitives/useEditableCollection.d.ts.map +0 -1
- package/src/components/primitives/useEditablePlainText.d.ts.map +0 -1
- package/src/components/primitives/useEditableRichText.d.ts.map +0 -1
- package/src/components/sections/Button/CTAButton.d.ts.map +0 -1
- package/src/components/sections/Button/index.d.ts.map +0 -1
- package/src/components/sections/Colors/index.d.ts.map +0 -1
- package/src/components/sections/IconList/IconList.d.ts.map +0 -1
- package/src/components/sections/IconList/IconListSettings.d.ts.map +0 -1
- package/src/components/sections/IconList/index.d.ts.map +0 -1
- package/src/components/sections/LinkHeading/index.d.ts.map +0 -1
- package/src/components/sections/Prose/Prose.d.ts.map +0 -1
- package/src/components/sections/Prose/index.d.ts.map +0 -1
- package/src/components/sections/SubHeading/index.d.ts.map +0 -1
- package/src/components/sections/SubSubHeading/index.d.ts.map +0 -1
- package/src/components/sections/register-schemas.d.ts.map +0 -1
- package/src/components/shared/Button.d.ts.map +0 -1
- package/src/components/shared/Checkbox.d.ts.map +0 -1
- package/src/components/shared/FormLabel.d.ts.map +0 -1
- package/src/components/shared/IconButton.d.ts.map +0 -1
- package/src/components/shared/Input.d.ts.map +0 -1
- package/src/components/shared/Select.d.ts.map +0 -1
- package/src/components/shared/icons.d.ts.map +0 -1
- package/src/components/shell/BuildStatusIndicator.tsx +0 -59
- package/src/components/shell/MediaLibraryContext.d.ts.map +0 -1
- package/src/hooks/index.ts +0 -8
- package/src/hooks/useResolvedMedia.d.ts.map +0 -1
- package/src/lib/cn.d.ts.map +0 -1
- package/src/lib/grid.d.ts.map +0 -1
- package/src/lib/grid.ts +0 -7
- package/src/lib/icons.d.ts.map +0 -1
- package/src/lib/loader.d.ts.map +0 -1
- package/src/lib/nav.d.ts.map +0 -1
- package/src/lib/registry.d.ts.map +0 -1
- package/src/lib/sanitize.d.ts.map +0 -1
- package/src/media/github.d.ts.map +0 -1
- package/src/media/index.d.ts.map +0 -1
- package/src/media/queue.d.ts.map +0 -1
- package/src/media/resolve.d.ts.map +0 -1
- package/src/media/types.d.ts.map +0 -1
- package/src/media/utils.d.ts.map +0 -1
- package/src/media/videoPoster.d.ts.map +0 -1
- package/src/schemas/auth.d.ts.map +0 -1
- package/src/schemas/media-grid-options.d.ts.map +0 -1
- package/src/schemas/media.d.ts.map +0 -1
- package/src/schemas/sections.d.ts.map +0 -1
- package/src/schemas/shared.d.ts.map +0 -1
- package/src/schemas/site-config.d.ts.map +0 -1
- /package/dist/{chunk-B7VBSE5X.js → chunk-3JDTXOIG.js} +0 -0
- /package/dist/{chunk-CXZ5YJG4.js → chunk-L45X7DKX.js} +0 -0
- /package/src/components/primitives/{gridDrop.ts → grid-drop.ts} +0 -0
- /package/src/components/shell/{blockMoveDispatch.ts → block-move-dispatch.ts} +0 -0
- /package/src/lib/{safeRedirect.ts → safe-redirect.ts} +0 -0
|
@@ -5,6 +5,7 @@ import { ColorPicker } from "../shared/ColorPicker";
|
|
|
5
5
|
import { FontPicker } from "../shared/FontPicker";
|
|
6
6
|
import { Input } from "../shared/Input";
|
|
7
7
|
import { Select } from "../shared/Select";
|
|
8
|
+
import { Textarea } from "../shared/Textarea";
|
|
8
9
|
import { SubTabs } from "../shared/SubTabs";
|
|
9
10
|
import { FormLabel } from "../shared/FormLabel";
|
|
10
11
|
import { useMediaLibrary } from "./MediaLibraryContext";
|
|
@@ -12,22 +13,13 @@ import { contrastRatio, wcagLevel, suggestAccessibleOn } from "../../lib/contras
|
|
|
12
13
|
import { cn } from "../../lib/cn";
|
|
13
14
|
import { buildGoogleFontsUrl } from "../../lib/google-fonts";
|
|
14
15
|
import type { SiteConfig } from "../../schemas/site-config";
|
|
15
|
-
import
|
|
16
|
+
import { imageThumbnailUrl } from "../../media/utils";
|
|
16
17
|
|
|
17
18
|
interface Props {
|
|
18
19
|
siteConfig: SiteConfig;
|
|
19
20
|
onChange: (config: SiteConfig) => void;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
// Smallest generated variant for the editor-preview thumbnail (mirrors
|
|
23
|
-
// DocInspector's thumbSrc) — avoids needing a MediaProvider in this context.
|
|
24
|
-
function thumbSrc(imageId: string, item: MediaItem | undefined): string | null {
|
|
25
|
-
if (!item || item.kind !== "image") return null;
|
|
26
|
-
if (item.mimeType === "image/svg+xml") return `/api/media/${imageId}/original.svg`;
|
|
27
|
-
const widths = item.variants.map((v) => v.width).sort((a, b) => a - b);
|
|
28
|
-
if (widths.length === 0) return null;
|
|
29
|
-
return `/api/media/${imageId}/${widths[0]}.webp`;
|
|
30
|
-
}
|
|
31
23
|
|
|
32
24
|
const darkModeOptions = [
|
|
33
25
|
{ label: "Light", value: "light" },
|
|
@@ -63,7 +55,7 @@ function ContrastRow({ label, entries }: { label: string; entries: ContrastEntry
|
|
|
63
55
|
<span className="text-base-contrast-light">{label}</span>
|
|
64
56
|
{entries.map((e) => {
|
|
65
57
|
const level = wcagLevel(e.ratio);
|
|
66
|
-
const tone = level.aa ? "text-
|
|
58
|
+
const tone = level.aa ? "text-success" : level.aaLarge ? "text-warning" : "text-danger";
|
|
67
59
|
const mark = level.aa ? "AA" : level.aaLarge ? "large only" : "fail";
|
|
68
60
|
return (
|
|
69
61
|
<span key={e.mode} className="inline-flex items-center gap-1">
|
|
@@ -88,7 +80,7 @@ export function SiteSettingsDisplay({ siteConfig, onChange }: Props) {
|
|
|
88
80
|
|
|
89
81
|
function pickLogo(which: "light" | "dark") {
|
|
90
82
|
mediaLibrary?.openSelectModal((imageId) => {
|
|
91
|
-
const base = siteConfig.logo ?? { light: { imageId: "" }, dark: null, invertInDark: false, showInNav: true };
|
|
83
|
+
const base = siteConfig.logo ?? { light: { imageId: "" }, dark: null, invertInDark: false, showInNav: true, hideTitle: true };
|
|
92
84
|
update({ logo: { ...base, [which]: { imageId } } });
|
|
93
85
|
});
|
|
94
86
|
}
|
|
@@ -154,16 +146,14 @@ export function SiteSettingsDisplay({ siteConfig, onChange }: Props) {
|
|
|
154
146
|
/>
|
|
155
147
|
|
|
156
148
|
<div>
|
|
157
|
-
<
|
|
158
|
-
|
|
159
|
-
id="site-description"
|
|
149
|
+
<Textarea
|
|
150
|
+
label="Description"
|
|
160
151
|
aria-label="Site description"
|
|
161
152
|
rows={2}
|
|
162
153
|
maxLength={300}
|
|
163
154
|
value={siteConfig.description ?? ""}
|
|
164
|
-
onChange={(
|
|
155
|
+
onChange={(value) => update({ description: value || null })}
|
|
165
156
|
placeholder="Short summary for search results and social shares."
|
|
166
|
-
className="w-full rounded border border-base-200 bg-base px-3 py-2 text-sm text-base-contrast"
|
|
167
157
|
/>
|
|
168
158
|
<div className="mt-1 flex items-start justify-between gap-2">
|
|
169
159
|
<p className="text-xs text-base-contrast/70">
|
|
@@ -214,13 +204,13 @@ export function SiteSettingsDisplay({ siteConfig, onChange }: Props) {
|
|
|
214
204
|
)}
|
|
215
205
|
</div>
|
|
216
206
|
<p className="mt-1 text-xs text-base-contrast/70">SVG or PNG, up to 100KB. Shown in browser tabs.</p>
|
|
217
|
-
{faviconError && <p className="mt-1 text-xs text-
|
|
207
|
+
{faviconError && <p className="mt-1 text-xs text-danger">{faviconError}</p>}
|
|
218
208
|
</div>
|
|
219
209
|
|
|
220
210
|
{(() => {
|
|
221
211
|
const logo = siteConfig.logo;
|
|
222
|
-
const lightSrc = logo ?
|
|
223
|
-
const darkSrc = logo?.dark ?
|
|
212
|
+
const lightSrc = logo ? imageThumbnailUrl(mediaLibrary?.manifest.images[logo.light.imageId]) : null;
|
|
213
|
+
const darkSrc = logo?.dark ? imageThumbnailUrl(mediaLibrary?.manifest.images[logo.dark.imageId]) : null;
|
|
224
214
|
const needsDarkHint = logo != null && siteConfig.darkMode !== "light" && !logo.dark && !logo.invertInDark;
|
|
225
215
|
|
|
226
216
|
return (
|
|
@@ -292,8 +282,17 @@ export function SiteSettingsDisplay({ siteConfig, onChange }: Props) {
|
|
|
292
282
|
label="Show in navigation"
|
|
293
283
|
/>
|
|
294
284
|
|
|
285
|
+
{/* Not gated on showInNav: the login page shows the logo either
|
|
286
|
+
way, so this has to stay reachable when the nav one is off. */}
|
|
287
|
+
<Checkbox
|
|
288
|
+
checked={logo.hideTitle}
|
|
289
|
+
onChange={(v) => update({ logo: { ...logo, hideTitle: v } })}
|
|
290
|
+
label="Hide site title"
|
|
291
|
+
description="The logo stands in for the site name in the navigation and on the login page. Turn this off to show both."
|
|
292
|
+
/>
|
|
293
|
+
|
|
295
294
|
{needsDarkHint && (
|
|
296
|
-
<p className="text-xs text-
|
|
295
|
+
<p className="text-xs text-warning">
|
|
297
296
|
Add a dark variant or enable invert so the logo stays legible in dark mode.
|
|
298
297
|
</p>
|
|
299
298
|
)}
|
|
@@ -7,6 +7,8 @@ import { SiteSettingsDisplay } from "./SiteSettingsDisplay";
|
|
|
7
7
|
import { SiteSettingsUsers } from "./SiteSettingsUsers";
|
|
8
8
|
import { SiteSettingsChatbot } from "./SiteSettingsChatbot";
|
|
9
9
|
import { SiteSettingsDecks } from "./SiteSettingsDecks";
|
|
10
|
+
import { SiteSettingsTags } from "./SiteSettingsTags";
|
|
11
|
+
import type { SiteTagging } from "../../lib/registry";
|
|
10
12
|
import type { SiteConfig } from "../../schemas/site-config";
|
|
11
13
|
import type { Audience } from "../../auth/types";
|
|
12
14
|
|
|
@@ -27,9 +29,13 @@ interface Props {
|
|
|
27
29
|
passwordToggle: boolean;
|
|
28
30
|
};
|
|
29
31
|
currentUser: { email: string; role: "owner" | "editor" } | null;
|
|
32
|
+
tagging: SiteTagging;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
|
-
export function SiteSettingsModal({
|
|
35
|
+
export function SiteSettingsModal({
|
|
36
|
+
isOpen, onClose, siteConfig, onSiteConfigChange, onAudiencesChange, audiences, chatbotPlatformEnabled, capabilities, currentUser,
|
|
37
|
+
tagging,
|
|
38
|
+
}: Props) {
|
|
33
39
|
const [signOutError, setSignOutError] = useState<string | null>(null);
|
|
34
40
|
|
|
35
41
|
async function handleSignOut() {
|
|
@@ -92,6 +98,22 @@ export function SiteSettingsModal({ isOpen, onClose, siteConfig, onSiteConfigCha
|
|
|
92
98
|
</div>
|
|
93
99
|
),
|
|
94
100
|
},
|
|
101
|
+
{
|
|
102
|
+
id: "tags",
|
|
103
|
+
label: "Tags",
|
|
104
|
+
show: true,
|
|
105
|
+
content: (
|
|
106
|
+
<div data-testid="site-settings-tab-panel" className="flex flex-1 flex-col overflow-y-auto px-6 py-4">
|
|
107
|
+
<SiteSettingsTags
|
|
108
|
+
tags={tagging.tags}
|
|
109
|
+
editable={tagging.editable}
|
|
110
|
+
onCreate={(label) => tagging.onCreate(label)}
|
|
111
|
+
onRename={tagging.onRename}
|
|
112
|
+
onDelete={tagging.onDelete}
|
|
113
|
+
/>
|
|
114
|
+
</div>
|
|
115
|
+
),
|
|
116
|
+
},
|
|
95
117
|
{
|
|
96
118
|
id: "display",
|
|
97
119
|
label: "Display",
|
|
@@ -130,7 +152,7 @@ export function SiteSettingsModal({ isOpen, onClose, siteConfig, onSiteConfigCha
|
|
|
130
152
|
<span className="ml-1 capitalize">({currentUser.role})</span>
|
|
131
153
|
)}
|
|
132
154
|
{signOutError && (
|
|
133
|
-
<span className="ml-2 text-
|
|
155
|
+
<span className="ml-2 text-danger">— {signOutError}</span>
|
|
134
156
|
)}
|
|
135
157
|
</div>
|
|
136
158
|
<Button
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { useRef, useState, type FormEvent } from "react";
|
|
2
|
+
import { pluralize } from "../../lib/text";
|
|
3
|
+
import { findTagByLabel, tagDisplayLabel } from "../../lib/tags";
|
|
4
|
+
import type { TagEntry } from "../../schemas/tags";
|
|
5
|
+
import { Button } from "../shared/Button";
|
|
6
|
+
import { ConfirmInline } from "../shared/ConfirmInline";
|
|
7
|
+
import { Input } from "../shared/Input";
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
/** The site's tag registry, already reconciled (siteTags). */
|
|
11
|
+
tags: TagEntry[];
|
|
12
|
+
/** False when the registry was never loaded, or loaded degraded; the tab then edits nothing. */
|
|
13
|
+
editable: boolean;
|
|
14
|
+
onCreate: (label: string) => void;
|
|
15
|
+
onRename: (tagId: string, label: string) => void;
|
|
16
|
+
onDelete: (tagId: string) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function SiteSettingsTags({ tags, editable, onCreate, onRename, onDelete }: Props) {
|
|
20
|
+
const [draft, setDraft] = useState("");
|
|
21
|
+
const [error, setError] = useState<string | null>(null);
|
|
22
|
+
|
|
23
|
+
function submit(e: FormEvent) {
|
|
24
|
+
e.preventDefault();
|
|
25
|
+
const label = draft.trim();
|
|
26
|
+
if (!label) return;
|
|
27
|
+
if (findTagByLabel(tags, label)) {
|
|
28
|
+
setError(`A tag named "${label}" already exists.`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
onCreate(label);
|
|
32
|
+
setDraft("");
|
|
33
|
+
setError(null);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const header = (
|
|
37
|
+
<div>
|
|
38
|
+
<h3 className="mb-1 text-sm font-medium text-base-contrast">Section tags</h3>
|
|
39
|
+
<p className="text-xs text-base-contrast-light">
|
|
40
|
+
Tags group related sections across pages. Put them on a section from the Tags pill above it. Viewers never see
|
|
41
|
+
tag names.
|
|
42
|
+
</p>
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
if (!editable) {
|
|
47
|
+
return (
|
|
48
|
+
<div className="space-y-4">
|
|
49
|
+
{header}
|
|
50
|
+
<p className="text-xs text-danger">Tags could not be loaded in full for this session, so they are read-only. Reload the editor to manage them.</p>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<div className="space-y-4">
|
|
57
|
+
{header}
|
|
58
|
+
|
|
59
|
+
<form onSubmit={submit} className="flex items-start gap-2">
|
|
60
|
+
<Input
|
|
61
|
+
label="New tag"
|
|
62
|
+
hideLabel
|
|
63
|
+
className="flex-1"
|
|
64
|
+
value={draft}
|
|
65
|
+
placeholder="New tag name"
|
|
66
|
+
error={error ?? undefined}
|
|
67
|
+
onChange={(v) => { setDraft(v); setError(null); }}
|
|
68
|
+
/>
|
|
69
|
+
<Button type="submit" variant="secondary">Add tag</Button>
|
|
70
|
+
</form>
|
|
71
|
+
|
|
72
|
+
{tags.length === 0 ? (
|
|
73
|
+
<p className="text-xs text-base-contrast-light">No tags yet.</p>
|
|
74
|
+
) : (
|
|
75
|
+
<ul className="space-y-2">
|
|
76
|
+
{tags.map((t) => (
|
|
77
|
+
<TagRow
|
|
78
|
+
key={t.id}
|
|
79
|
+
tag={t}
|
|
80
|
+
duplicate={t.label.trim() !== "" && findTagByLabel(tags, t.label)?.id !== t.id}
|
|
81
|
+
onRename={(label) => onRename(t.id, label)}
|
|
82
|
+
onDelete={() => onDelete(t.id)}
|
|
83
|
+
/>
|
|
84
|
+
))}
|
|
85
|
+
</ul>
|
|
86
|
+
)}
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function TagRow({ tag, duplicate, onRename, onDelete }: {
|
|
92
|
+
tag: TagEntry;
|
|
93
|
+
/** An earlier tag already has this name — inline creates would pick that one. */
|
|
94
|
+
duplicate: boolean;
|
|
95
|
+
onRename: (label: string) => void;
|
|
96
|
+
onDelete: () => void;
|
|
97
|
+
}) {
|
|
98
|
+
const [confirming, setConfirming] = useState(false);
|
|
99
|
+
const deleteRef = useRef<HTMLButtonElement>(null);
|
|
100
|
+
const count = tag.sectionIds.length;
|
|
101
|
+
const name = tagDisplayLabel(tag.label);
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<li className="rounded-md border border-base-200 px-3 py-2">
|
|
105
|
+
<div className="flex items-center gap-3">
|
|
106
|
+
<Input
|
|
107
|
+
label="Tag name"
|
|
108
|
+
hideLabel
|
|
109
|
+
className="min-w-0 flex-1"
|
|
110
|
+
value={tag.label}
|
|
111
|
+
placeholder="Untitled tag"
|
|
112
|
+
error={duplicate ? "Another tag already has this name." : undefined}
|
|
113
|
+
onChange={onRename}
|
|
114
|
+
/>
|
|
115
|
+
<span className="shrink-0 text-xs text-base-contrast/60">{pluralize(count, "section")}</span>
|
|
116
|
+
{!confirming && (
|
|
117
|
+
<Button
|
|
118
|
+
ref={deleteRef}
|
|
119
|
+
variant="destructive"
|
|
120
|
+
size="sm"
|
|
121
|
+
aria-label={`Delete tag ${name}`}
|
|
122
|
+
onClick={() => (count === 0 ? onDelete() : setConfirming(true))}
|
|
123
|
+
>
|
|
124
|
+
Delete
|
|
125
|
+
</Button>
|
|
126
|
+
)}
|
|
127
|
+
</div>
|
|
128
|
+
{confirming && (
|
|
129
|
+
<div className="mt-2">
|
|
130
|
+
<ConfirmInline
|
|
131
|
+
message={`Delete "${name}"? It is removed from ${pluralize(count, "section")}. The sections themselves stay.`}
|
|
132
|
+
confirmLabel="Delete"
|
|
133
|
+
confirmAriaLabel="Confirm delete"
|
|
134
|
+
tone="destructive"
|
|
135
|
+
onConfirm={onDelete}
|
|
136
|
+
onCancel={() => setConfirming(false)}
|
|
137
|
+
returnFocusTo={deleteRef}
|
|
138
|
+
/>
|
|
139
|
+
</div>
|
|
140
|
+
)}
|
|
141
|
+
</li>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { Fragment, useState, useEffect, type FormEvent } from "react";
|
|
1
|
+
import { Fragment, useRef, useState, useEffect, type FormEvent, type RefObject } from "react";
|
|
2
2
|
import { ChevronDown } from "lucide-react";
|
|
3
3
|
import type { Role } from "../../auth/types";
|
|
4
4
|
import { Button } from "../shared/Button";
|
|
5
|
+
import { ConfirmInline } from "../shared/ConfirmInline";
|
|
6
|
+
import { Input } from "../shared/Input";
|
|
5
7
|
|
|
6
8
|
interface User {
|
|
7
9
|
id: string;
|
|
@@ -21,12 +23,25 @@ export function SiteSettingsUsers({ currentUser }: Props) {
|
|
|
21
23
|
const [inviteRole, setInviteRole] = useState<Role>("editor");
|
|
22
24
|
const [error, setError] = useState<string | null>(null);
|
|
23
25
|
const [confirmingRevoke, setConfirmingRevoke] = useState<string | null>(null);
|
|
26
|
+
// One stable ref object per user, so a row's Remove button and its
|
|
27
|
+
// ConfirmInline share the same object across the swap — the button
|
|
28
|
+
// reattaches to it (layout phase) before ConfirmInline's cleanup effect
|
|
29
|
+
// (passive phase) reads it back to return focus.
|
|
30
|
+
const removeButtonRefs = useRef(new Map<string, RefObject<HTMLButtonElement | null>>());
|
|
31
|
+
function getRemoveButtonRef(userId: string): RefObject<HTMLButtonElement | null> {
|
|
32
|
+
let ref = removeButtonRefs.current.get(userId);
|
|
33
|
+
if (!ref) {
|
|
34
|
+
ref = { current: null };
|
|
35
|
+
removeButtonRefs.current.set(userId, ref);
|
|
36
|
+
}
|
|
37
|
+
return ref;
|
|
38
|
+
}
|
|
24
39
|
|
|
25
40
|
async function loadUsers() {
|
|
26
41
|
try {
|
|
27
42
|
const res = await fetch("/api/auth/users");
|
|
28
43
|
if (!res.ok) {
|
|
29
|
-
setError("
|
|
44
|
+
setError("Couldn't load users");
|
|
30
45
|
setUsers([]);
|
|
31
46
|
return;
|
|
32
47
|
}
|
|
@@ -83,6 +98,29 @@ export function SiteSettingsUsers({ currentUser }: Props) {
|
|
|
83
98
|
setConfirmingRevoke(userId);
|
|
84
99
|
}
|
|
85
100
|
|
|
101
|
+
async function handleRoleChange(userId: string, role: Role) {
|
|
102
|
+
setError(null);
|
|
103
|
+
try {
|
|
104
|
+
const res = await fetch("/api/auth/users", {
|
|
105
|
+
method: "PATCH",
|
|
106
|
+
headers: { "Content-Type": "application/json" },
|
|
107
|
+
body: JSON.stringify({ userId, role }),
|
|
108
|
+
});
|
|
109
|
+
if (!res.ok) {
|
|
110
|
+
const data = await res.json().catch(() => ({}));
|
|
111
|
+
// Resync first: a rejected change would otherwise leave the select
|
|
112
|
+
// showing a role the user does not have. loadUsers() clears `error` on
|
|
113
|
+
// success, so the message has to be set after it, not before.
|
|
114
|
+
await loadUsers();
|
|
115
|
+
setError(data.error || "Role change failed");
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
await loadUsers();
|
|
119
|
+
} catch {
|
|
120
|
+
setError("Network error while changing role");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
86
124
|
async function confirmRevoke(userId: string) {
|
|
87
125
|
setConfirmingRevoke(null);
|
|
88
126
|
try {
|
|
@@ -114,33 +152,36 @@ export function SiteSettingsUsers({ currentUser }: Props) {
|
|
|
114
152
|
{users.map((user) => (
|
|
115
153
|
<Fragment key={user.id}>
|
|
116
154
|
<div className="flex items-center border-b border-base-200 py-2 pr-2 text-base-contrast">{user.email}</div>
|
|
117
|
-
<div className="flex items-center border-b border-base-200 py-2 pr-2
|
|
118
|
-
{user.
|
|
155
|
+
<div className="flex items-center border-b border-base-200 py-2 pr-2 text-base-contrast-light">
|
|
156
|
+
{currentUser?.email === user.email ? (
|
|
157
|
+
// Owners can't change their own role — the same rule that makes
|
|
158
|
+
// this row's Remove control a dash.
|
|
159
|
+
<span className="capitalize">{user.role}</span>
|
|
160
|
+
) : (
|
|
161
|
+
<div className="relative w-full">
|
|
162
|
+
<select
|
|
163
|
+
value={user.role}
|
|
164
|
+
onChange={(e) => handleRoleChange(user.id, e.target.value as Role)}
|
|
165
|
+
aria-label={`Role for ${user.email}`}
|
|
166
|
+
className="w-full appearance-none rounded border border-base-200 bg-base py-1 pr-7 pl-2 text-sm text-base-contrast focus:border-base-contrast focus:outline-none focus:ring-1 focus:ring-base-contrast"
|
|
167
|
+
>
|
|
168
|
+
<option value="editor">Editor</option>
|
|
169
|
+
<option value="owner">Owner</option>
|
|
170
|
+
</select>
|
|
171
|
+
<ChevronDown
|
|
172
|
+
size={14}
|
|
173
|
+
className="pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-base-contrast-light"
|
|
174
|
+
/>
|
|
175
|
+
</div>
|
|
176
|
+
)}
|
|
119
177
|
</div>
|
|
120
178
|
<div className="flex items-center justify-end border-b border-base-200 py-2">
|
|
121
179
|
{currentUser?.email === user.email ? (
|
|
122
180
|
<span className="text-xs text-base-contrast-light">—</span>
|
|
123
|
-
) : confirmingRevoke === user.id ? (
|
|
124
|
-
<span className="flex items-center gap-1">
|
|
125
|
-
<Button
|
|
126
|
-
type="button"
|
|
127
|
-
variant="ghost"
|
|
128
|
-
tone="destructive"
|
|
129
|
-
onClick={() => confirmRevoke(user.id)}
|
|
130
|
-
>
|
|
131
|
-
Confirm
|
|
132
|
-
</Button>
|
|
133
|
-
<Button
|
|
134
|
-
type="button"
|
|
135
|
-
variant="ghost"
|
|
136
|
-
onClick={() => setConfirmingRevoke(null)}
|
|
137
|
-
>
|
|
138
|
-
Cancel
|
|
139
|
-
</Button>
|
|
140
|
-
</span>
|
|
141
|
-
) : (
|
|
181
|
+
) : confirmingRevoke === user.id ? null : (
|
|
142
182
|
<Button
|
|
143
183
|
type="button"
|
|
184
|
+
ref={getRemoveButtonRef(user.id)}
|
|
144
185
|
variant="ghost"
|
|
145
186
|
tone="destructive"
|
|
146
187
|
onClick={() => handleRevoke(user.id)}
|
|
@@ -149,20 +190,32 @@ export function SiteSettingsUsers({ currentUser }: Props) {
|
|
|
149
190
|
</Button>
|
|
150
191
|
)}
|
|
151
192
|
</div>
|
|
193
|
+
{confirmingRevoke === user.id && (
|
|
194
|
+
<div className="col-span-3 pb-2">
|
|
195
|
+
<ConfirmInline
|
|
196
|
+
message={`Remove ${user.email}?`}
|
|
197
|
+
confirmLabel="Remove"
|
|
198
|
+
tone="destructive"
|
|
199
|
+
onConfirm={() => confirmRevoke(user.id)}
|
|
200
|
+
onCancel={() => setConfirmingRevoke(null)}
|
|
201
|
+
returnFocusTo={getRemoveButtonRef(user.id)}
|
|
202
|
+
/>
|
|
203
|
+
</div>
|
|
204
|
+
)}
|
|
152
205
|
</Fragment>
|
|
153
206
|
))}
|
|
154
207
|
</div>
|
|
155
208
|
|
|
156
209
|
<form onSubmit={handleInvite} className="grid grid-cols-[1fr_7rem_5rem] text-sm">
|
|
157
210
|
<div className="pr-2">
|
|
158
|
-
<
|
|
211
|
+
<Input
|
|
212
|
+
label="Email address"
|
|
213
|
+
hideLabel
|
|
159
214
|
type="email"
|
|
160
215
|
placeholder="Email address"
|
|
161
216
|
value={inviteEmail}
|
|
162
|
-
onChange={
|
|
217
|
+
onChange={setInviteEmail}
|
|
163
218
|
required
|
|
164
|
-
aria-label="Email address"
|
|
165
|
-
className="w-full rounded border border-base-200 bg-base px-3 py-2 text-sm text-base-contrast focus:border-base-contrast focus:outline-none focus:ring-1 focus:ring-base-contrast"
|
|
166
219
|
/>
|
|
167
220
|
</div>
|
|
168
221
|
<div className="pr-2">
|
|
@@ -187,7 +240,11 @@ export function SiteSettingsUsers({ currentUser }: Props) {
|
|
|
187
240
|
</Button>
|
|
188
241
|
</form>
|
|
189
242
|
|
|
190
|
-
|
|
243
|
+
<p className="text-xs text-base-contrast-light">
|
|
244
|
+
Role changes take effect the next time the user signs in, or within 24 hours.
|
|
245
|
+
</p>
|
|
246
|
+
|
|
247
|
+
{error && <p className="text-sm text-danger">{error}</p>}
|
|
191
248
|
</div>
|
|
192
249
|
);
|
|
193
250
|
}
|
|
@@ -153,7 +153,7 @@ export function SiteSettingsViewerAccess({ audienceManagement, passwordToggle, o
|
|
|
153
153
|
// Deliberately a hard stop rather than an empty list: rendering the normal UI
|
|
154
154
|
// here would show "no audiences" for a site that has them.
|
|
155
155
|
if (loadError) {
|
|
156
|
-
return <p className="text-sm text-
|
|
156
|
+
return <p className="text-sm text-danger">{loadError}</p>;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
return (
|
|
@@ -182,7 +182,7 @@ export function SiteSettingsViewerAccess({ audienceManagement, passwordToggle, o
|
|
|
182
182
|
? "Viewers must sign in with a username and password to see any content."
|
|
183
183
|
: "Viewers must select an audience and enter a password to see any content."}
|
|
184
184
|
</p>
|
|
185
|
-
{toggleError && <p className="text-xs text-
|
|
185
|
+
{toggleError && <p className="text-xs text-danger">{toggleError}</p>}
|
|
186
186
|
</div>
|
|
187
187
|
)}
|
|
188
188
|
|
|
@@ -3,7 +3,8 @@ import { Input } from "../shared/Input";
|
|
|
3
3
|
import { PasswordInput } from "../shared/PasswordInput";
|
|
4
4
|
import { Button } from "../shared/Button";
|
|
5
5
|
import { Select } from "../shared/Select";
|
|
6
|
-
import { safeRedirect } from "../../lib/
|
|
6
|
+
import { safeRedirect } from "../../lib/safe-redirect";
|
|
7
|
+
import { COPY } from "../shared/copy";
|
|
7
8
|
|
|
8
9
|
interface Props {
|
|
9
10
|
/** Audience mode only. Empty (and unused) in credential mode — the page must
|
|
@@ -55,7 +56,7 @@ export function ViewerLoginForm({ audiences, mode = "audience", next }: Props) {
|
|
|
55
56
|
|
|
56
57
|
if (!response.ok) {
|
|
57
58
|
const data = await response.json().catch(() => ({}));
|
|
58
|
-
setError(data.error ||
|
|
59
|
+
setError(data.error || COPY.auth.signInFallback);
|
|
59
60
|
return;
|
|
60
61
|
}
|
|
61
62
|
|
|
@@ -99,7 +100,7 @@ export function ViewerLoginForm({ audiences, mode = "audience", next }: Props) {
|
|
|
99
100
|
)}
|
|
100
101
|
|
|
101
102
|
{error && (
|
|
102
|
-
<p className="text-sm text-
|
|
103
|
+
<p className="text-sm text-danger">{error}</p>
|
|
103
104
|
)}
|
|
104
105
|
|
|
105
106
|
<Button
|
|
@@ -108,7 +109,7 @@ export function ViewerLoginForm({ audiences, mode = "audience", next }: Props) {
|
|
|
108
109
|
size="md"
|
|
109
110
|
disabled={loading || (credentialMode ? username.trim().length === 0 : !audience)}
|
|
110
111
|
isLoading={loading}
|
|
111
|
-
loadingLabel="Verifying
|
|
112
|
+
loadingLabel="Verifying…"
|
|
112
113
|
className="w-full"
|
|
113
114
|
>
|
|
114
115
|
Enter
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Audience } from "../../schemas/auth";
|
|
2
|
+
import type { SiteIndex } from "../../schemas/site-config";
|
|
3
|
+
import type { LoadedSection } from "../../lib/loader";
|
|
4
|
+
import type { MediaManifest } from "../../media/types";
|
|
5
|
+
import { pageById } from "../../lib/pages";
|
|
6
|
+
import { pageReferenceCopies } from "../../lib/nav";
|
|
7
|
+
import type { ReferenceSources } from "../shared/ReferenceSourcesContext";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* What References resolve against in the Published preview: main's content
|
|
11
|
+
* (`viewIndex` once the history/view fetch lands, else the `mainIndex` the
|
|
12
|
+
* load reported), live sections only — the same content and page the viewer
|
|
13
|
+
* would expand. Null when there is no published view to resolve against, and
|
|
14
|
+
* the canvas falls back to the working copy.
|
|
15
|
+
*/
|
|
16
|
+
export function publishedReferenceSources(opts: {
|
|
17
|
+
viewSections: LoadedSection[] | null;
|
|
18
|
+
viewIndex: SiteIndex | null;
|
|
19
|
+
mainIndex: SiteIndex | null;
|
|
20
|
+
activePageId: string | null;
|
|
21
|
+
audiences: Audience[];
|
|
22
|
+
mediaManifest: MediaManifest;
|
|
23
|
+
jumpToSection: (sectionId: string) => void;
|
|
24
|
+
}): ReferenceSources | null {
|
|
25
|
+
const { viewSections, activePageId, audiences, mediaManifest, jumpToSection } = opts;
|
|
26
|
+
const index = opts.viewIndex ?? opts.mainIndex;
|
|
27
|
+
if (!viewSections || !index || !activePageId) return null;
|
|
28
|
+
const byId = new Map(viewSections.map((s) => [s.section.id, s]));
|
|
29
|
+
const pageSections = (pageById(index, activePageId)?.order ?? [])
|
|
30
|
+
.flatMap((id) => byId.get(id) ?? [])
|
|
31
|
+
.filter((s) => s.meta.status === "live");
|
|
32
|
+
return {
|
|
33
|
+
index, sections: viewSections, audiences, mediaManifest, jumpToSection,
|
|
34
|
+
copies: pageReferenceCopies(pageSections, { index, allSections: viewSections }),
|
|
35
|
+
};
|
|
36
|
+
}
|
package/src/deck/index.ts
CHANGED
|
@@ -25,6 +25,6 @@ export {
|
|
|
25
25
|
type DeckMediaAsset,
|
|
26
26
|
type DeckMediaResolver,
|
|
27
27
|
} from "./media";
|
|
28
|
-
export { DeckTextEditProvider, EditableText,
|
|
28
|
+
export { DeckTextEditProvider, EditableText, type DeckTextEditor } from "./editing";
|
|
29
29
|
export { useStageScale } from "./useStageScale";
|
|
30
|
-
export { deckAlign, surfaceInk, DECK_ELEVATION, SURFACE_BACKGROUND, type
|
|
30
|
+
export { deckAlign, surfaceInk, DECK_ELEVATION, SURFACE_BACKGROUND, type DeckSurface } from "./tokens";
|
package/src/document/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ export * from "./engine/settings";
|
|
|
6
6
|
export { splitProseBlocks } from "./engine/blocks";
|
|
7
7
|
export { harvest } from "./engine/harvest";
|
|
8
8
|
export * from "./engine/paginate";
|
|
9
|
-
export { layoutMasonryPage, type MasonryOpts, type
|
|
9
|
+
export { layoutMasonryPage, type MasonryOpts, type Sized } from "./engine/masonry";
|
|
10
10
|
|
|
11
11
|
export { DocPage, type DocMeta } from "./components/DocPage";
|
|
12
12
|
export { DocSectionPage, type DocHost } from "./components/DocSectionPage";
|
|
@@ -14,5 +14,5 @@ export { DocCoverPage } from "./components/DocCoverPage";
|
|
|
14
14
|
export { useDocPages } from "./components/useDocPages";
|
|
15
15
|
|
|
16
16
|
// Task 3 — shared document shell (presentation + editing).
|
|
17
|
-
export { DocViewer
|
|
17
|
+
export { DocViewer } from "./components/DocViewer";
|
|
18
18
|
export { DocRail, entryId, type RailEntry } from "./components/DocRail";
|
package/src/hooks/useBlockDnd.ts
CHANGED
|
@@ -15,6 +15,17 @@ export interface UseBlockDndArgs {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
+
* One of three sibling drag-and-drop position hooks, split by location type
|
|
19
|
+
* rather than unified behind a generic `useSortable({ axis })`: this one
|
|
20
|
+
* (block/container id + index — the section canvas, root and nested),
|
|
21
|
+
* `useSortableRow` (flat index — section-ordering lists), and
|
|
22
|
+
* `useSortableNavRow` (NavLocation — the Pages modal's group-aware nav tree).
|
|
23
|
+
* A fourth location type earns its own hook on the same shape (rowRef/
|
|
24
|
+
* handleRef, lazy atlaskit import, closest-edge state, a ref for the latest
|
|
25
|
+
* callback) rather than a parameter bag bolted onto an existing one — see
|
|
26
|
+
* docs/superpowers/specs/2026-09-04-editor-ui-primitives-consolidation.md
|
|
27
|
+
* § D6 for why a shared `useSortable` was deferred.
|
|
28
|
+
*
|
|
18
29
|
* Wires a block as a unified drag source + drop target. Manages only this block's
|
|
19
30
|
* local hover edge + dragging flag — the actual move dispatch is centralized in the
|
|
20
31
|
* EditorContent monitor (a later task), so nested targets never double-fire. The edge
|