@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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
2
|
import { EditorModal } from "../shell/EditorModal";
|
|
3
3
|
import { Button } from "./Button";
|
|
4
|
+
import { ConfirmDialog } from "./ConfirmDialog";
|
|
4
5
|
|
|
5
6
|
export interface ChangedSection {
|
|
6
7
|
id: string;
|
|
@@ -165,33 +166,48 @@ export function HistoryChangesModal({
|
|
|
165
166
|
<EditorModal
|
|
166
167
|
isOpen={isOpen}
|
|
167
168
|
onClose={onClose}
|
|
168
|
-
title={
|
|
169
|
+
title={title}
|
|
169
170
|
size="standard"
|
|
170
171
|
tabbed
|
|
171
172
|
noPadding
|
|
172
173
|
>
|
|
173
174
|
<div className="flex min-h-0 flex-1 flex-col">
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
175
|
+
{confirmingRestore ? (
|
|
176
|
+
<div className="flex-1 overflow-y-auto px-6 py-4">
|
|
177
|
+
<ConfirmDialog
|
|
178
|
+
isOpen
|
|
179
|
+
embedded
|
|
180
|
+
title="Restore this version?"
|
|
181
|
+
body={
|
|
182
|
+
<>
|
|
183
|
+
<p className="text-sm text-base-contrast-light">
|
|
184
|
+
This will publish the content from this version as a new update.
|
|
185
|
+
Your currently published content stays available in the history.
|
|
186
|
+
</p>
|
|
187
|
+
{restoreError && (
|
|
188
|
+
<p role="alert" className="mt-3 text-sm font-medium text-danger">
|
|
189
|
+
{restoreError} Nothing was published — you can try again.
|
|
190
|
+
</p>
|
|
191
|
+
)}
|
|
192
|
+
{hasUnsavedChanges && (
|
|
193
|
+
<p className="mt-3 text-sm font-medium text-danger">
|
|
194
|
+
You have unsaved changes. Restoring discards them, and unlike
|
|
195
|
+
published content they cannot be recovered from history.
|
|
196
|
+
</p>
|
|
197
|
+
)}
|
|
198
|
+
</>
|
|
199
|
+
}
|
|
200
|
+
confirmLabel="Restore"
|
|
201
|
+
tone="destructive"
|
|
202
|
+
busy={isRestoring}
|
|
203
|
+
busyLabel="Restoring…"
|
|
204
|
+
onConfirm={onRestore}
|
|
205
|
+
onCancel={() => setConfirmingRestore(false)}
|
|
206
|
+
/>
|
|
207
|
+
</div>
|
|
208
|
+
) : (
|
|
209
|
+
<>
|
|
210
|
+
<div className="flex-1 overflow-y-auto px-6 py-4">
|
|
195
211
|
{error && (
|
|
196
212
|
<p className="py-6 text-center text-sm text-base-contrast-light">
|
|
197
213
|
Couldn’t load the change summary.
|
|
@@ -237,30 +253,16 @@ export function HistoryChangesModal({
|
|
|
237
253
|
)}
|
|
238
254
|
</>
|
|
239
255
|
)}
|
|
240
|
-
|
|
241
|
-
)}
|
|
242
|
-
</div>
|
|
256
|
+
</div>
|
|
243
257
|
|
|
244
|
-
|
|
245
|
-
{confirmingRestore ? (
|
|
246
|
-
<>
|
|
247
|
-
<Button variant="secondary" size="sm" disabled={isRestoring}
|
|
248
|
-
onClick={() => setConfirmingRestore(false)}>
|
|
249
|
-
Cancel
|
|
250
|
-
</Button>
|
|
251
|
-
<Button variant="destructive" size="sm" disabled={isRestoring} onClick={onRestore}>
|
|
252
|
-
{isRestoring ? "Restoring…" : "Restore"}
|
|
253
|
-
</Button>
|
|
254
|
-
</>
|
|
255
|
-
) : (
|
|
256
|
-
<>
|
|
258
|
+
<div className="flex shrink-0 justify-end gap-2 border-t border-base-200 px-6 py-3">
|
|
257
259
|
<Button variant="destructive" size="sm" onClick={() => setConfirmingRestore(true)}>
|
|
258
260
|
Restore…
|
|
259
261
|
</Button>
|
|
260
262
|
<Button size="sm" onClick={onBrowse}>Browse this version</Button>
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
263
|
+
</div>
|
|
264
|
+
</>
|
|
265
|
+
)}
|
|
264
266
|
</div>
|
|
265
267
|
</EditorModal>
|
|
266
268
|
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect, useMemo, lazy, Suspense } from "react";
|
|
2
|
+
import { ChevronRight, ChevronLeft, MousePointer2 } from "lucide-react";
|
|
2
3
|
import { cn } from "../../lib/cn";
|
|
3
4
|
import { historyRestoreEvent, historyRestoreFailedEvent } from "../../lib/events";
|
|
4
5
|
import {
|
|
@@ -26,26 +27,12 @@ interface Frame {
|
|
|
26
27
|
node: HistoryNode | null;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
const Chevron = () =>
|
|
30
|
-
<svg width="9" height="9" viewBox="0 0 10 10" fill="none" stroke="currentColor"
|
|
31
|
-
strokeWidth="1.7" aria-hidden="true">
|
|
32
|
-
<path d="M3.5 1.5L7 5l-3.5 3.5" />
|
|
33
|
-
</svg>
|
|
34
|
-
);
|
|
30
|
+
const Chevron = () => <ChevronRight size={9} strokeWidth={1.7} aria-hidden="true" />;
|
|
35
31
|
|
|
36
|
-
const BackArrow = () =>
|
|
37
|
-
<svg width="11" height="11" viewBox="0 0 10 10" fill="none" stroke="currentColor"
|
|
38
|
-
strokeWidth="1.7" aria-hidden="true">
|
|
39
|
-
<path d="M6.5 1.5L3 5l3.5 3.5" />
|
|
40
|
-
</svg>
|
|
41
|
-
);
|
|
32
|
+
const BackArrow = () => <ChevronLeft size={11} strokeWidth={1.7} aria-hidden="true" />;
|
|
42
33
|
|
|
43
34
|
/** Browse-to-this-version: a pointer cursor — "go look at the site as it was". */
|
|
44
|
-
const BrowseCursor = () =>
|
|
45
|
-
<svg width="13" height="13" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
|
|
46
|
-
<path d="M3.6 1.9a.4.4 0 0 1 .66-.3l8 6.7a.4.4 0 0 1-.23.71l-3.4.2 1.94 3.5a.4.4 0 0 1-.17.54l-1.4.75a.4.4 0 0 1-.54-.18l-1.9-3.55-2.3 2.2a.4.4 0 0 1-.68-.29z" />
|
|
47
|
-
</svg>
|
|
48
|
-
);
|
|
35
|
+
const BrowseCursor = () => <MousePointer2 size={13} aria-hidden="true" />;
|
|
49
36
|
|
|
50
37
|
function Volume({ count, max }: { count: number; max: number }) {
|
|
51
38
|
// sqrt so a 200-commit year doesn't flatten every other bar to nothing.
|
|
@@ -89,7 +76,7 @@ export function HistoryPopover({ onSelectCommit, hasUnsavedChanges = false }: Hi
|
|
|
89
76
|
const res = await fetch(`/api/history?page=${page}&per_page=${PER_PAGE}`, {
|
|
90
77
|
signal: controller.signal,
|
|
91
78
|
});
|
|
92
|
-
if (!res.ok) throw new Error(`
|
|
79
|
+
if (!res.ok) throw new Error(`Couldn't load history: ${res.status}`);
|
|
93
80
|
const data = (await res.json()) as { items: HistoryCommit[] };
|
|
94
81
|
all.push(...data.items);
|
|
95
82
|
// Render each page as it lands. These requests are sequential, so waiting
|
|
@@ -105,7 +92,7 @@ export function HistoryPopover({ onSelectCommit, hasUnsavedChanges = false }: Hi
|
|
|
105
92
|
if (!live || controller.signal.aborted) return;
|
|
106
93
|
// A later page failing is not worth throwing away the pages that landed:
|
|
107
94
|
// the error view replaces the tree entirely. Keep what we have instead.
|
|
108
|
-
if (all.length === 0) setError(err instanceof Error ? err.message : "
|
|
95
|
+
if (all.length === 0) setError(err instanceof Error ? err.message : "Couldn't load history");
|
|
109
96
|
} finally {
|
|
110
97
|
if (live) setLoading(false);
|
|
111
98
|
}
|
|
@@ -139,7 +126,7 @@ export function HistoryPopover({ onSelectCommit, hasUnsavedChanges = false }: Hi
|
|
|
139
126
|
return <div className="p-4 text-center text-xs text-base-contrast-light">Loading history…</div>;
|
|
140
127
|
}
|
|
141
128
|
if (error) {
|
|
142
|
-
return <div className="p-4 text-center text-xs text-
|
|
129
|
+
return <div className="p-4 text-center text-xs text-danger">{error}</div>;
|
|
143
130
|
}
|
|
144
131
|
if (commits.length === 0) {
|
|
145
132
|
return <div className="p-4 text-center text-xs text-base-contrast-light">No history found</div>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { ImageBackground, ImageBackgroundSurface } from "../../schemas/shared";
|
|
2
|
+
import { cn } from "../../lib/cn";
|
|
3
|
+
import { FormLabel } from "./FormLabel";
|
|
4
|
+
import { SegmentedControl } from "./SegmentedControl";
|
|
5
|
+
import { Select } from "./Select";
|
|
6
|
+
import { ColorPicker } from "./ColorPicker";
|
|
7
|
+
import { useBrandSwatches } from "./BrandSwatchesContext";
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
label: string;
|
|
11
|
+
value: ImageBackground | undefined;
|
|
12
|
+
onChange: (value: ImageBackground | undefined) => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const MODES = [
|
|
16
|
+
{ value: "none", label: "None" },
|
|
17
|
+
{ value: "theme", label: "Light / Dark" },
|
|
18
|
+
{ value: "custom", label: "Custom" },
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const SURFACES: { value: ImageBackgroundSurface; label: string }[] = [
|
|
22
|
+
{ value: "none", label: "None" },
|
|
23
|
+
{ value: "light", label: "Light" },
|
|
24
|
+
{ value: "dark", label: "Dark" },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export function ImageBackgroundField({ label, value, onChange }: Props) {
|
|
28
|
+
const swatches = useBrandSwatches();
|
|
29
|
+
const mode = value?.mode ?? "none";
|
|
30
|
+
|
|
31
|
+
function setMode(next: string) {
|
|
32
|
+
if (next === "theme") onChange({ mode: "theme", light: "none", dark: "none" });
|
|
33
|
+
else if (next === "custom") onChange({ mode: "custom", color: "#ffffff" });
|
|
34
|
+
else onChange(undefined);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div className="flex flex-col gap-3">
|
|
39
|
+
<FormLabel>{label}</FormLabel>
|
|
40
|
+
<SegmentedControl options={MODES} value={mode} onChange={setMode} className="self-start" />
|
|
41
|
+
|
|
42
|
+
{value?.mode === "theme" && (
|
|
43
|
+
<div className="grid grid-cols-2 gap-3">
|
|
44
|
+
<Select
|
|
45
|
+
label="Light mode"
|
|
46
|
+
value={value.light}
|
|
47
|
+
options={SURFACES}
|
|
48
|
+
onChange={(light) => onChange({ ...value, light: light as ImageBackgroundSurface })}
|
|
49
|
+
/>
|
|
50
|
+
<Select
|
|
51
|
+
label="Dark mode"
|
|
52
|
+
value={value.dark}
|
|
53
|
+
options={SURFACES}
|
|
54
|
+
onChange={(dark) => onChange({ ...value, dark: dark as ImageBackgroundSurface })}
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
|
|
59
|
+
{value?.mode === "custom" && (
|
|
60
|
+
<div className="flex flex-col gap-2">
|
|
61
|
+
<div className="flex items-center gap-2">
|
|
62
|
+
<ColorPicker
|
|
63
|
+
label="Background color"
|
|
64
|
+
value={value.color}
|
|
65
|
+
onChange={(color) => onChange({ mode: "custom", color })}
|
|
66
|
+
/>
|
|
67
|
+
<span className="font-mono text-xs text-base-contrast-light">{value.color}</span>
|
|
68
|
+
</div>
|
|
69
|
+
{swatches.length > 0 && (
|
|
70
|
+
<div role="group" aria-label="Brand colors" className="flex flex-wrap gap-2">
|
|
71
|
+
{swatches.map((s) => (
|
|
72
|
+
<button
|
|
73
|
+
key={s.hex}
|
|
74
|
+
type="button"
|
|
75
|
+
aria-label={s.name ? `${s.name} (${s.hex})` : s.hex}
|
|
76
|
+
aria-pressed={s.hex === value.color.toLowerCase()}
|
|
77
|
+
title={s.name ?? s.hex}
|
|
78
|
+
onClick={() => onChange({ mode: "custom", color: s.hex })}
|
|
79
|
+
className={cn(
|
|
80
|
+
"h-7 w-7 cursor-pointer rounded-full border border-base-200",
|
|
81
|
+
"aria-pressed:outline aria-pressed:outline-2 aria-pressed:outline-offset-2 aria-pressed:outline-base-contrast",
|
|
82
|
+
)}
|
|
83
|
+
style={{ backgroundColor: s.hex }}
|
|
84
|
+
/>
|
|
85
|
+
))}
|
|
86
|
+
</div>
|
|
87
|
+
)}
|
|
88
|
+
</div>
|
|
89
|
+
)}
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { cn } from "../../lib/cn";
|
|
1
2
|
import { Button } from "./Button";
|
|
2
3
|
import { formatFileSize } from "../../media/utils";
|
|
3
4
|
|
|
@@ -30,18 +31,33 @@ export function formatRejections(files: UploadRejection[], maxFileSize?: number)
|
|
|
30
31
|
return `${files.length} files rejected (${parts.join(", ")}).`;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
export
|
|
34
|
+
export type InlineAlertTone = "success" | "info" | "warning" | "error";
|
|
35
|
+
|
|
36
|
+
const toneClasses: Record<InlineAlertTone, string> = {
|
|
37
|
+
success: "border-success bg-success-bg text-success",
|
|
38
|
+
info: "border-base-200 bg-base-accent text-base-contrast",
|
|
39
|
+
warning: "border-warning bg-warning-bg text-warning",
|
|
40
|
+
error: "border-danger bg-danger-bg text-danger",
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export function InlineAlert({
|
|
34
44
|
message,
|
|
35
45
|
onDismiss,
|
|
46
|
+
tone = "warning",
|
|
36
47
|
}: {
|
|
37
48
|
message: string;
|
|
38
49
|
onDismiss: () => void;
|
|
50
|
+
tone?: InlineAlertTone;
|
|
39
51
|
}) {
|
|
40
52
|
return (
|
|
41
|
-
<div
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
53
|
+
<div
|
|
54
|
+
role="alert"
|
|
55
|
+
className={cn(
|
|
56
|
+
"flex flex-col items-center rounded-lg border px-4 py-3 lg:flex-row lg:justify-between",
|
|
57
|
+
toneClasses[tone],
|
|
58
|
+
)}
|
|
59
|
+
>
|
|
60
|
+
<p className="mb-2 text-center text-sm lg:mb-0 lg:text-left">{message}</p>
|
|
45
61
|
<div className="flex shrink-0 items-center">
|
|
46
62
|
<Button variant="secondary" size="sm" type="button" onClick={onDismiss}>
|
|
47
63
|
Dismiss
|
|
@@ -6,17 +6,28 @@ interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "onChan
|
|
|
6
6
|
label: string;
|
|
7
7
|
onChange: (value: string) => void;
|
|
8
8
|
error?: string;
|
|
9
|
+
/** Helper text below the field, styled like `error` but neutral — for
|
|
10
|
+
* guidance that isn't a validation failure. Not shown while `error` is set. */
|
|
11
|
+
hint?: string;
|
|
12
|
+
/** Keeps the field's accessible name (still a real associated `<label>`,
|
|
13
|
+
* not just `aria-label`) without a visible caption — for compact/inline
|
|
14
|
+
* fields (e.g. an editable row's title) where a caption would add layout
|
|
15
|
+
* a raw `<input>` with just `aria-label` never had. */
|
|
16
|
+
hideLabel?: boolean;
|
|
17
|
+
/** Escape hatch for one-off input sizing, matching `Select`'s `selectClassName`. */
|
|
18
|
+
inputClassName?: string;
|
|
9
19
|
}
|
|
10
20
|
|
|
11
21
|
export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
|
12
|
-
{ label, value, onChange, type = "text", className, disabled, error, ...rest },
|
|
22
|
+
{ label, value, onChange, type = "text", className, disabled, error, hint, hideLabel, inputClassName, ...rest },
|
|
13
23
|
ref,
|
|
14
24
|
) {
|
|
15
25
|
const id = useId();
|
|
16
26
|
const errorId = `${id}-error`;
|
|
27
|
+
const hintId = `${id}-hint`;
|
|
17
28
|
return (
|
|
18
29
|
<div className={className}>
|
|
19
|
-
<FormLabel htmlFor={id}>{label}</FormLabel>
|
|
30
|
+
<FormLabel htmlFor={id} className={hideLabel ? "sr-only" : undefined}>{label}</FormLabel>
|
|
20
31
|
<input
|
|
21
32
|
ref={ref}
|
|
22
33
|
id={id}
|
|
@@ -25,21 +36,26 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(function Input(
|
|
|
25
36
|
onChange={(e) => onChange(e.target.value)}
|
|
26
37
|
disabled={disabled}
|
|
27
38
|
aria-invalid={error ? true : undefined}
|
|
28
|
-
aria-describedby={error ? errorId : undefined}
|
|
39
|
+
aria-describedby={error ? errorId : hint ? hintId : undefined}
|
|
29
40
|
className={cn(
|
|
30
41
|
"w-full rounded border bg-base px-3 py-2 text-sm text-base-contrast focus:outline-none focus:ring-1",
|
|
31
42
|
error
|
|
32
|
-
? "border-
|
|
43
|
+
? "border-danger focus:border-danger focus:ring-danger"
|
|
33
44
|
: "border-base-200 focus:border-base-contrast focus:ring-base-contrast",
|
|
34
45
|
disabled && "cursor-not-allowed opacity-50",
|
|
46
|
+
inputClassName,
|
|
35
47
|
)}
|
|
36
48
|
{...rest}
|
|
37
49
|
/>
|
|
38
|
-
{error
|
|
39
|
-
<p id={errorId} className="mt-1 text-xs text-
|
|
50
|
+
{error ? (
|
|
51
|
+
<p id={errorId} className="mt-1 text-xs text-danger">
|
|
40
52
|
{error}
|
|
41
53
|
</p>
|
|
42
|
-
)
|
|
54
|
+
) : hint ? (
|
|
55
|
+
<p id={hintId} className="mt-1 text-xs text-base-contrast-light">
|
|
56
|
+
{hint}
|
|
57
|
+
</p>
|
|
58
|
+
) : null}
|
|
43
59
|
</div>
|
|
44
60
|
);
|
|
45
61
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect, useRef, type ReactNode } from "react";
|
|
2
|
-
import { ChevronRight, Users } from "lucide-react";
|
|
2
|
+
import { ChevronRight, ChevronUp, Menu, X, Users } from "lucide-react";
|
|
3
3
|
import { cn } from "../../lib/cn";
|
|
4
4
|
import { Toggle } from "./Toggle";
|
|
5
5
|
import type { SiteNav, NavItem, GroupNavItem, PageNavItem, DocGroupNavItem, DocNavItem } from "../../lib/nav";
|
|
@@ -93,6 +93,8 @@ export default function Navigation({ siteNav: initialNav, siteName, darkMode, la
|
|
|
93
93
|
|
|
94
94
|
// /api/auth/sign-out clears BOTH the editor session and the audience cookie,
|
|
95
95
|
// so one call serves either kind of session; only the destination differs.
|
|
96
|
+
// While an editor is impersonating it ends only that, and names the page to
|
|
97
|
+
// return to (#61).
|
|
96
98
|
const handleLogout = useCallback(async () => {
|
|
97
99
|
setLogoutError(null);
|
|
98
100
|
setLoggingOut(true);
|
|
@@ -103,7 +105,9 @@ export default function Navigation({ siteNav: initialNav, siteName, darkMode, la
|
|
|
103
105
|
setLoggingOut(false);
|
|
104
106
|
return;
|
|
105
107
|
}
|
|
106
|
-
|
|
108
|
+
const body = (await res.json().catch(() => null)) as { redirectTo?: unknown } | null;
|
|
109
|
+
const redirectTo = typeof body?.redirectTo === "string" ? body.redirectTo : null;
|
|
110
|
+
window.location.assign(redirectTo ?? (identity?.kind === "editor" ? "/edit/login" : "/login"));
|
|
107
111
|
} catch {
|
|
108
112
|
setLogoutError("Network error");
|
|
109
113
|
setLoggingOut(false);
|
|
@@ -371,25 +375,25 @@ export default function Navigation({ siteNav: initialNav, siteName, darkMode, la
|
|
|
371
375
|
|
|
372
376
|
return (
|
|
373
377
|
<>
|
|
374
|
-
<header className={cn("fixed top-0 left-0 right-0 z-50 bg-base", bp.hidden)}>
|
|
378
|
+
<header className={cn("bp-nav-header fixed top-0 left-0 right-0 z-50 bg-base", bp.hidden)}>
|
|
375
379
|
<div className="mx-auto max-w-screen-xl flex h-16 items-center justify-between px-4">
|
|
376
380
|
<div className="flex flex-col items-start gap-1">
|
|
377
381
|
{renderLogo("h-8 w-auto")}
|
|
378
382
|
{showTitle && <span className="text-lg font-bold text-primary">{currentSiteName}</span>}
|
|
379
383
|
</div>
|
|
380
|
-
<button onClick={() => setIsOpen(!isOpen)} className="cursor-pointer p-2 text-base-contrast" aria-label="Toggle navigation">
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
384
|
+
<button onClick={() => setIsOpen(!isOpen)} className="cursor-pointer p-2 text-base-contrast" aria-label="Toggle navigation" aria-expanded={isOpen} aria-controls="bp-mobile-nav">
|
|
385
|
+
{isOpen ? (
|
|
386
|
+
<X className="h-6 w-6" aria-hidden="true" />
|
|
387
|
+
) : (
|
|
388
|
+
<Menu className="h-6 w-6" aria-hidden="true" />
|
|
389
|
+
)}
|
|
386
390
|
</button>
|
|
387
391
|
</div>
|
|
388
392
|
</header>
|
|
389
393
|
|
|
390
394
|
{isOpen && <div className={cn("fixed inset-0 z-40 bg-black/50", bp.hidden)} onClick={() => setIsOpen(false)} />}
|
|
391
395
|
|
|
392
|
-
<nav className={cn("fixed top-0 left-0 z-40 h-full w-64 flex flex-col overflow-y-auto border-r border-base-200 bg-base pt-16 transition-transform nav-sidebar",
|
|
396
|
+
<nav id="bp-mobile-nav" className={cn("fixed top-0 left-0 z-40 h-full w-64 flex flex-col overflow-y-auto border-r border-base-200 bg-base pt-16 transition-transform nav-sidebar",
|
|
393
397
|
bp.leftAuto, bp.translate,
|
|
394
398
|
isOpen ? "translate-x-0" : "-translate-x-full")}>
|
|
395
399
|
{/* No horizontal padding on the wrapper: the logo's 80% is of the nav
|
|
@@ -467,11 +471,12 @@ export default function Navigation({ siteNav: initialNav, siteName, darkMode, la
|
|
|
467
471
|
{/* The panel opens upward, so the caret points up when closed
|
|
468
472
|
and flips when open — the affordance that this is a toggle
|
|
469
473
|
rather than a label. */}
|
|
470
|
-
<
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
474
|
+
<ChevronUp
|
|
475
|
+
size={9}
|
|
476
|
+
strokeWidth={1.7}
|
|
477
|
+
aria-hidden="true"
|
|
478
|
+
className={cn("transition-transform", showHistory && "rotate-180")}
|
|
479
|
+
/>
|
|
475
480
|
</button>
|
|
476
481
|
{/* Portalled: the sidebar sets overflow-y-auto, which computes
|
|
477
482
|
overflow-x to auto, so a panel wider than the 16rem sidebar
|
|
@@ -506,10 +511,10 @@ export default function Navigation({ siteNav: initialNav, siteName, darkMode, la
|
|
|
506
511
|
disabled={loggingOut}
|
|
507
512
|
className="cursor-pointer underline-offset-2 transition-colors hover:text-primary hover:underline disabled:cursor-wait"
|
|
508
513
|
>
|
|
509
|
-
{loggingOut ? "Logging out
|
|
514
|
+
{loggingOut ? "Logging out…" : "Log out"}
|
|
510
515
|
</button>
|
|
511
516
|
</p>
|
|
512
|
-
{logoutError && <p className="mt-1 text-xs text-
|
|
517
|
+
{logoutError && <p className="mt-1 text-xs text-danger">{logoutError}</p>}
|
|
513
518
|
</div>
|
|
514
519
|
)}
|
|
515
520
|
</div>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { X } from "lucide-react";
|
|
3
|
+
import { cn } from "../../lib/cn";
|
|
4
|
+
import { IconButton } from "./IconButton";
|
|
5
|
+
|
|
6
|
+
export type NoticeTone = "success" | "info" | "warning" | "error";
|
|
7
|
+
|
|
8
|
+
const toneClasses: Record<NoticeTone, string> = {
|
|
9
|
+
success: "border-success bg-success-bg text-success",
|
|
10
|
+
info: "border-base-200 bg-base-accent text-base-contrast",
|
|
11
|
+
warning: "border-warning bg-warning-bg text-warning",
|
|
12
|
+
error: "border-danger bg-danger-bg text-danger",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// role="alert" interrupts assistive tech immediately (warning/error); role="status"
|
|
16
|
+
// only announces at the next polite opportunity (success/info) — matches how
|
|
17
|
+
// urgently each tone needs to reach a screen reader user.
|
|
18
|
+
const toneRole: Record<NoticeTone, "alert" | "status"> = {
|
|
19
|
+
success: "status",
|
|
20
|
+
info: "status",
|
|
21
|
+
warning: "alert",
|
|
22
|
+
error: "alert",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export interface NoticeProps {
|
|
26
|
+
tone: NoticeTone;
|
|
27
|
+
children: ReactNode;
|
|
28
|
+
onDismiss?: () => void;
|
|
29
|
+
placement: "inline" | "toast";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function Notice({ tone, children, onDismiss, placement }: NoticeProps) {
|
|
33
|
+
return (
|
|
34
|
+
<div
|
|
35
|
+
role={toneRole[tone]}
|
|
36
|
+
className={cn(
|
|
37
|
+
"flex items-center gap-3 rounded-md border px-4 py-2 text-xs font-medium shadow-lg",
|
|
38
|
+
toneClasses[tone],
|
|
39
|
+
placement === "toast"
|
|
40
|
+
// top-16 clears the h-16 ToolbarFrame bar exactly; the extra 1rem
|
|
41
|
+
// (top-20) is the gap below it, so the toast never sits flush
|
|
42
|
+
// against — or, at top-14, partly under — the bar.
|
|
43
|
+
? "fixed left-1/2 top-20 z-60 -translate-x-1/2"
|
|
44
|
+
: "w-full",
|
|
45
|
+
)}
|
|
46
|
+
>
|
|
47
|
+
<span className="flex-1">{children}</span>
|
|
48
|
+
{onDismiss && (
|
|
49
|
+
<IconButton
|
|
50
|
+
icon={<X size={14} />}
|
|
51
|
+
label="Dismiss"
|
|
52
|
+
size="sm"
|
|
53
|
+
onClick={onDismiss}
|
|
54
|
+
className="shrink-0 opacity-70 hover:opacity-100 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary"
|
|
55
|
+
/>
|
|
56
|
+
)}
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect, useLayoutEffect, useRef, useState, type ReactNode, type RefObject } from "react";
|
|
2
2
|
import { createPortal } from "react-dom";
|
|
3
3
|
import { useInitialFocus } from "../../hooks/useFocusTrap";
|
|
4
|
+
import { useStackedEscape } from "../../hooks/useStackedEscape";
|
|
4
5
|
import { cn } from "../../lib/cn";
|
|
5
6
|
|
|
6
7
|
interface PopoverProps {
|
|
@@ -106,17 +107,14 @@ export function Popover({
|
|
|
106
107
|
panel.style.right = "";
|
|
107
108
|
}, [isOpen, align]);
|
|
108
109
|
|
|
110
|
+
// A modal opened from inside this popover also closes on Escape. Without
|
|
111
|
+
// this the one keypress dismisses both, losing the navigator's zoom stack
|
|
112
|
+
// — inconsistent with the X button, and with the mousedown exemption below
|
|
113
|
+
// that exists for exactly this stacking.
|
|
114
|
+
useStackedEscape(onClose, { enabled: isOpen });
|
|
115
|
+
|
|
109
116
|
useEffect(() => {
|
|
110
117
|
if (!isOpen) return;
|
|
111
|
-
function onKeyDown(e: KeyboardEvent) {
|
|
112
|
-
if (e.key !== "Escape") return;
|
|
113
|
-
// A modal opened from inside this popover also closes on Escape. Without
|
|
114
|
-
// this the one keypress dismisses both, losing the navigator's zoom stack
|
|
115
|
-
// — inconsistent with the X button, and with the mousedown exemption
|
|
116
|
-
// below that exists for exactly this stacking.
|
|
117
|
-
if (document.querySelector("[data-modal-layer]")) return;
|
|
118
|
-
onClose();
|
|
119
|
-
}
|
|
120
118
|
function onMouseDown(e: MouseEvent) {
|
|
121
119
|
const target = e.target as Node;
|
|
122
120
|
if (panelRef.current?.contains(target)) return;
|
|
@@ -127,10 +125,8 @@ export function Popover({
|
|
|
127
125
|
if (target instanceof Element && target.closest("[data-modal-layer]")) return;
|
|
128
126
|
onClose();
|
|
129
127
|
}
|
|
130
|
-
document.addEventListener("keydown", onKeyDown);
|
|
131
128
|
document.addEventListener("mousedown", onMouseDown);
|
|
132
129
|
return () => {
|
|
133
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
134
130
|
document.removeEventListener("mousedown", onMouseDown);
|
|
135
131
|
};
|
|
136
132
|
}, [isOpen, onClose, anchorRef]);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { createContext } from "react";
|
|
2
|
+
import type { Audience } from "../../schemas/auth";
|
|
3
|
+
import type { SiteIndex } from "../../schemas/site-config";
|
|
4
|
+
import type { LoadedSection } from "../../lib/loader";
|
|
5
|
+
import type { Section } from "../../schemas/sections";
|
|
6
|
+
import type { MediaManifest } from "../../media/types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The whole site's working copy, for the Reference section's editor list and
|
|
10
|
+
* settings picker — a Reference points across pages, so the page-scoped props
|
|
11
|
+
* a section gets aren't enough. EditorShell provides it above the modal root
|
|
12
|
+
* so the settings form sees it too. Absent (null) outside the editor.
|
|
13
|
+
*/
|
|
14
|
+
export interface ReferenceSources {
|
|
15
|
+
index: SiteIndex;
|
|
16
|
+
sections: LoadedSection[];
|
|
17
|
+
/** Every audience on the site. */
|
|
18
|
+
audiences: Audience[];
|
|
19
|
+
mediaManifest: MediaManifest;
|
|
20
|
+
/** The page being edited's copies, per Reference id then source id, with
|
|
21
|
+
* the page-wide anchors the editor nav links to (pageReferenceCopies). */
|
|
22
|
+
copies: Record<string, Record<string, Section>>;
|
|
23
|
+
/** Open the section's page and scroll it into view. */
|
|
24
|
+
jumpToSection: (sectionId: string) => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const ReferenceSourcesContext = createContext<ReferenceSources | null>(null);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useId } from "react";
|
|
1
|
+
import { useId, type SelectHTMLAttributes } from "react";
|
|
2
2
|
import { ChevronDown } from "lucide-react";
|
|
3
3
|
import { cn } from "../../lib/cn";
|
|
4
4
|
import { FormLabel } from "./FormLabel";
|
|
@@ -8,7 +8,8 @@ interface SelectOption {
|
|
|
8
8
|
label: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
interface SelectProps
|
|
11
|
+
interface SelectProps
|
|
12
|
+
extends Omit<SelectHTMLAttributes<HTMLSelectElement>, "value" | "onChange" | "disabled" | "className" | "id"> {
|
|
12
13
|
label?: string;
|
|
13
14
|
value: string;
|
|
14
15
|
onChange: (value: string) => void;
|
|
@@ -26,6 +27,7 @@ export function Select({
|
|
|
26
27
|
disabled,
|
|
27
28
|
className,
|
|
28
29
|
selectClassName,
|
|
30
|
+
...rest
|
|
29
31
|
}: SelectProps) {
|
|
30
32
|
const id = useId();
|
|
31
33
|
return (
|
|
@@ -37,6 +39,7 @@ export function Select({
|
|
|
37
39
|
value={value}
|
|
38
40
|
onChange={(e) => onChange(e.target.value)}
|
|
39
41
|
disabled={disabled}
|
|
42
|
+
{...rest}
|
|
40
43
|
className={cn(
|
|
41
44
|
"w-full appearance-none rounded border border-base-200 bg-base py-2 pr-8 pl-3 text-sm text-base-contrast",
|
|
42
45
|
"focus:border-base-contrast focus:outline-none focus:ring-1 focus:ring-base-contrast",
|