@drawnagency/primitives 0.1.113 → 0.1.115
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/auth/cookies.d.ts +39 -0
- package/dist/auth/cookies.d.ts.map +1 -1
- package/dist/auth/index.js +3 -3
- package/dist/chunk-4WQ36ZP7.js +83 -0
- package/dist/{chunk-REDDTTGJ.js → chunk-4Y2JQQZL.js} +19 -1
- package/dist/chunk-5GFACGSN.js +6 -0
- package/dist/{chunk-AHALSCQH.js → chunk-67P34WNW.js} +76 -131
- package/dist/{chunk-S2L3BPLS.js → chunk-7SX42OP4.js} +1 -1
- package/dist/{chunk-GGXZZ77Z.js → chunk-AASEGXNT.js} +18 -1
- package/dist/chunk-APIJPTFG.js +64 -0
- package/dist/{chunk-WKZ7OENC.js → chunk-BQ5TZZUE.js} +5 -1
- package/dist/chunk-CDBURDPX.js +90 -0
- package/dist/chunk-DFKTF3CH.js +0 -0
- package/dist/chunk-DIMDRBFK.js +11 -0
- package/dist/chunk-DJABADOO.js +131 -0
- package/dist/{chunk-NHN2LSIU.js → chunk-DJOGPSRU.js} +31 -68
- package/dist/{chunk-KR2MHTNJ.js → chunk-FHTKSELX.js} +610 -62
- package/dist/{chunk-WUJ3XNFI.js → chunk-GGYY3JQJ.js} +19 -24
- package/dist/chunk-GNF6KFQ7.js +18 -0
- package/dist/{chunk-FRE2CCLV.js → chunk-HHNPSKPT.js} +5 -79
- package/dist/{chunk-IINIZBQB.js → chunk-JCDZAFX2.js} +30 -10
- package/dist/chunk-JR24U7FJ.js +120 -0
- package/dist/{chunk-BDFTMGCL.js → chunk-JXATNKLV.js} +11 -10
- package/dist/{chunk-SW6PCQQD.js → chunk-KQA772WQ.js} +2 -1
- package/dist/{chunk-6BZ2KNTP.js → chunk-NX7TFHA4.js} +195 -65
- package/dist/{chunk-VWWY5TL5.js → chunk-O37AV27P.js} +14 -75
- package/dist/chunk-RIITGTV3.js +275 -0
- package/dist/{chunk-HBULBDGP.js → chunk-S37DZPHW.js} +1 -1
- package/dist/chunk-S7QRHUWO.js +8 -0
- package/dist/{chunk-Z7W3DQTR.js → chunk-T26HAKW3.js} +424 -42
- package/dist/{chunk-4I5OO5UB.js → chunk-TEOAKGZA.js} +0 -1
- package/dist/{chunk-GPPVYLEI.js → chunk-UUUSJDIG.js} +1 -1
- package/dist/chunk-VY3IFGE3.js +70 -0
- package/dist/chunk-WYOFQHKI.js +176 -0
- package/dist/{chunk-4RNF2DRG.js → chunk-XDEPXTBY.js} +0 -2
- package/dist/{chunk-DS4GCYV2.js → chunk-YV3YSZEB.js} +223 -16
- package/dist/collab/rebase.d.ts +2 -1
- package/dist/collab/rebase.d.ts.map +1 -1
- package/dist/collab/rebase.js +24 -9
- package/dist/components/brandguide/ColorsEditable.d.ts.map +1 -1
- package/dist/components/chat/ChatPanel.d.ts.map +1 -1
- package/dist/components/chat/ChatWidget.d.ts.map +1 -1
- package/dist/components/docfile/DocFilePane.d.ts.map +1 -1
- package/dist/components/editor/ChildBlockWrapper.d.ts.map +1 -1
- package/dist/components/editor/ConflictDialog.d.ts.map +1 -1
- package/dist/components/editor/DragHandle.d.ts +12 -2
- package/dist/components/editor/DragHandle.d.ts.map +1 -1
- package/dist/components/editor/DropEdgeIndicator.d.ts +15 -6
- package/dist/components/editor/DropEdgeIndicator.d.ts.map +1 -1
- package/dist/components/editor/NavGroupRow.d.ts +4 -1
- package/dist/components/editor/NavGroupRow.d.ts.map +1 -1
- package/dist/components/editor/PagesModal.d.ts.map +1 -1
- package/dist/components/editor/SectionWrapper.d.ts +1 -1
- package/dist/components/editor/SectionWrapper.d.ts.map +1 -1
- package/dist/components/editor/SettingsForm.d.ts.map +1 -1
- package/dist/components/editor/TagIndicator.d.ts +15 -0
- package/dist/components/editor/TagIndicator.d.ts.map +1 -0
- package/dist/components/editor/index.js +150 -79
- package/dist/components/primitives/DocumentDropZone.d.ts +1 -1
- package/dist/components/primitives/EditableGrid.d.ts.map +1 -1
- package/dist/components/primitives/EditableList.d.ts.map +1 -1
- package/dist/components/primitives/HeadingSection.d.ts +4 -1
- package/dist/components/primitives/HeadingSection.d.ts.map +1 -1
- package/dist/components/primitives/ResolvedMedia.d.ts +5 -1
- package/dist/components/primitives/ResolvedMedia.d.ts.map +1 -1
- package/dist/components/primitives/{defineHeadingSection.d.ts → define-heading-section.d.ts} +1 -1
- package/dist/components/primitives/define-heading-section.d.ts.map +1 -0
- package/dist/components/primitives/{gridDrop.d.ts → grid-drop.d.ts} +1 -1
- package/dist/components/primitives/grid-drop.d.ts.map +1 -0
- package/dist/components/primitives/index.d.ts +1 -1
- package/dist/components/primitives/index.d.ts.map +1 -1
- package/dist/components/primitives/index.js +22 -154
- package/dist/components/sections/Button/CTAButton.d.ts.map +1 -1
- package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts +2 -6
- package/dist/components/sections/DoDontMedia/DoDontMediaBlock.d.ts.map +1 -1
- package/dist/components/sections/DoDontMedia/index.d.ts +8 -0
- package/dist/components/sections/DoDontMedia/index.d.ts.map +1 -1
- package/dist/components/sections/IconList/IconList.d.ts +2 -1
- package/dist/components/sections/IconList/IconList.d.ts.map +1 -1
- package/dist/components/sections/IconList/IconListSettings.d.ts +2 -1
- package/dist/components/sections/IconList/IconListSettings.d.ts.map +1 -1
- package/dist/components/sections/IconList/index.d.ts +1 -0
- package/dist/components/sections/IconList/index.d.ts.map +1 -1
- package/dist/components/sections/Media/MediaBlock.d.ts +2 -1
- package/dist/components/sections/Media/MediaBlock.d.ts.map +1 -1
- package/dist/components/sections/Media/index.d.ts +8 -0
- package/dist/components/sections/Media/index.d.ts.map +1 -1
- package/dist/components/sections/Reference/ReferenceList.d.ts +35 -0
- package/dist/components/sections/Reference/ReferenceList.d.ts.map +1 -0
- package/dist/components/sections/Reference/ReferenceSettings.d.ts +12 -0
- package/dist/components/sections/Reference/ReferenceSettings.d.ts.map +1 -0
- package/dist/components/sections/Reference/index.d.ts +9 -0
- package/dist/components/sections/Reference/index.d.ts.map +1 -0
- package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts +38 -0
- package/dist/components/sections/SectionSummary/SectionSummaryBlock.d.ts.map +1 -0
- package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts +20 -0
- package/dist/components/sections/SectionSummary/SectionSummarySettings.d.ts.map +1 -0
- package/dist/components/sections/SectionSummary/index.d.ts +33 -0
- package/dist/components/sections/SectionSummary/index.d.ts.map +1 -0
- package/dist/components/sections/all-sections.d.ts +53 -0
- package/dist/components/sections/all-sections.d.ts.map +1 -1
- package/dist/components/sections/brand-guide.d.ts +41 -2
- package/dist/components/sections/brand-guide.d.ts.map +1 -1
- package/dist/components/sections/brand-guide.js +17 -10
- package/dist/components/sections/core-sections.d.ts +14 -0
- package/dist/components/sections/core-sections.d.ts.map +1 -1
- package/dist/components/sections/register-schemas.js +25 -18
- package/dist/components/sections/register.js +25 -18
- package/dist/components/shared/BrandSwatchesContext.d.ts +9 -0
- package/dist/components/shared/BrandSwatchesContext.d.ts.map +1 -0
- package/dist/components/shared/Button.d.ts +11 -3
- package/dist/components/shared/Button.d.ts.map +1 -1
- package/dist/components/shared/Checkbox.d.ts +6 -0
- package/dist/components/shared/Checkbox.d.ts.map +1 -1
- package/dist/components/shared/ConfirmDialog.d.ts +25 -0
- package/dist/components/shared/ConfirmDialog.d.ts.map +1 -0
- package/dist/components/shared/ConfirmInline.d.ts +25 -0
- package/dist/components/shared/ConfirmInline.d.ts.map +1 -0
- package/dist/components/shared/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/shared/Fab.d.ts +11 -2
- package/dist/components/shared/Fab.d.ts.map +1 -1
- package/dist/components/shared/FabStack.d.ts +22 -0
- package/dist/components/shared/FabStack.d.ts.map +1 -0
- package/dist/components/shared/HistoryChangesModal.d.ts.map +1 -1
- package/dist/components/shared/HistoryPopover.d.ts.map +1 -1
- package/dist/components/shared/ImageBackgroundField.d.ts +9 -0
- package/dist/components/shared/ImageBackgroundField.d.ts.map +1 -0
- package/dist/components/shared/{UploadRejectionAlert.d.ts → InlineAlert.d.ts} +4 -2
- package/dist/components/shared/InlineAlert.d.ts.map +1 -0
- package/dist/components/shared/Input.d.ts +10 -0
- package/dist/components/shared/Input.d.ts.map +1 -1
- package/dist/components/shared/Navigation.d.ts.map +1 -1
- package/dist/components/shared/Notice.d.ts +10 -0
- package/dist/components/shared/Notice.d.ts.map +1 -0
- package/dist/components/shared/Popover.d.ts.map +1 -1
- package/dist/components/shared/ReferenceSourcesContext.d.ts +25 -0
- package/dist/components/shared/ReferenceSourcesContext.d.ts.map +1 -0
- package/dist/components/shared/Select.d.ts +3 -2
- package/dist/components/shared/Select.d.ts.map +1 -1
- package/dist/components/shared/SplitButton.d.ts.map +1 -1
- package/dist/components/shared/SummaryAnchorsContext.d.ts +10 -0
- package/dist/components/shared/SummaryAnchorsContext.d.ts.map +1 -0
- package/dist/components/shared/Textarea.d.ts +7 -0
- package/dist/components/shared/Textarea.d.ts.map +1 -1
- package/dist/components/shared/ToolbarFrame.d.ts +17 -0
- package/dist/components/shared/ToolbarFrame.d.ts.map +1 -0
- package/dist/components/shared/copy.d.ts +13 -0
- package/dist/components/shared/copy.d.ts.map +1 -0
- package/dist/components/shared/icons.d.ts +0 -12
- package/dist/components/shared/icons.d.ts.map +1 -1
- package/dist/components/shell/AudienceDetailsPanel.d.ts +7 -1
- package/dist/components/shell/AudienceDetailsPanel.d.ts.map +1 -1
- package/dist/components/shell/AudienceRow.d.ts.map +1 -1
- package/dist/components/shell/BugReportFAB.d.ts +7 -1
- package/dist/components/shell/BugReportFAB.d.ts.map +1 -1
- package/dist/components/shell/CredentialList.d.ts.map +1 -1
- package/dist/components/shell/DocInspector.d.ts.map +1 -1
- package/dist/components/shell/DocumentEditorOverlay.d.ts.map +1 -1
- package/dist/components/shell/EditorContext.d.ts +4 -0
- package/dist/components/shell/EditorContext.d.ts.map +1 -1
- package/dist/components/shell/EditorLoginForm.d.ts.map +1 -1
- package/dist/components/shell/EditorModal.d.ts.map +1 -1
- package/dist/components/shell/EditorShell.d.ts.map +1 -1
- package/dist/components/shell/HistoryToolbar.d.ts.map +1 -1
- package/dist/components/shell/MediaFolderTile.d.ts +4 -1
- package/dist/components/shell/MediaFolderTile.d.ts.map +1 -1
- package/dist/components/shell/MediaLibraryModal.d.ts.map +1 -1
- package/dist/components/shell/RestoreModal.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsChatbot.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsDisplay.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsModal.d.ts +3 -1
- package/dist/components/shell/SiteSettingsModal.d.ts.map +1 -1
- package/dist/components/shell/SiteSettingsTags.d.ts +13 -0
- package/dist/components/shell/SiteSettingsTags.d.ts.map +1 -0
- package/dist/components/shell/SiteSettingsUsers.d.ts.map +1 -1
- package/dist/components/shell/ViewerLoginForm.d.ts.map +1 -1
- package/dist/components/shell/{blockMoveDispatch.d.ts → block-move-dispatch.d.ts} +1 -1
- package/dist/components/shell/block-move-dispatch.d.ts.map +1 -0
- package/dist/components/shell/reference-sources.d.ts +22 -0
- package/dist/components/shell/reference-sources.d.ts.map +1 -0
- package/dist/deck/index.d.ts +2 -2
- package/dist/deck/index.d.ts.map +1 -1
- package/dist/deck/index.js +1 -3
- package/dist/deck-builder/index.js +10 -17
- package/dist/document/index.d.ts +2 -2
- package/dist/document/index.d.ts.map +1 -1
- package/dist/hooks/useBlockDnd.d.ts +11 -0
- package/dist/hooks/useBlockDnd.d.ts.map +1 -1
- package/dist/hooks/useBuildStatus.d.ts +1 -1
- package/dist/hooks/useBuildStatus.d.ts.map +1 -1
- package/dist/hooks/useDocumentUploads.d.ts +1 -1
- package/dist/hooks/useDocumentUploads.d.ts.map +1 -1
- package/dist/hooks/useEditorPersistence.d.ts +5 -1
- package/dist/hooks/useEditorPersistence.d.ts.map +1 -1
- package/dist/hooks/useEditorPublish.d.ts +6 -3
- package/dist/hooks/useEditorPublish.d.ts.map +1 -1
- package/dist/hooks/useMediaPipeline.d.ts.map +1 -1
- package/dist/hooks/useNotice.d.ts +19 -0
- package/dist/hooks/useNotice.d.ts.map +1 -0
- package/dist/hooks/useSortableNavRow.d.ts +11 -0
- package/dist/hooks/useSortableNavRow.d.ts.map +1 -1
- package/dist/hooks/useSortableRow.d.ts +11 -0
- package/dist/hooks/useSortableRow.d.ts.map +1 -1
- package/dist/hooks/useStackedEscape.d.ts +32 -0
- package/dist/hooks/useStackedEscape.d.ts.map +1 -0
- package/dist/index.js +95 -48
- package/dist/lib/audience-secret.js +2 -2
- package/dist/lib/block-dnd.d.ts +5 -0
- package/dist/lib/block-dnd.d.ts.map +1 -1
- package/dist/lib/block-move.d.ts.map +1 -1
- package/dist/lib/brand-swatches.d.ts +12 -0
- package/dist/lib/brand-swatches.d.ts.map +1 -0
- package/dist/lib/container-ops.d.ts +3 -2
- package/dist/lib/container-ops.d.ts.map +1 -1
- package/dist/lib/dexie.d.ts +7 -1
- package/dist/lib/dexie.d.ts.map +1 -1
- package/dist/lib/dexie.js +12 -3
- package/dist/lib/env.d.ts +4 -0
- package/dist/lib/env.d.ts.map +1 -1
- package/dist/lib/env.js +5 -3
- package/dist/lib/events.d.ts +1 -2
- package/dist/lib/events.d.ts.map +1 -1
- package/dist/lib/image-background.d.ts +8 -0
- package/dist/lib/image-background.d.ts.map +1 -0
- package/dist/lib/image-variant-plan.d.ts +42 -0
- package/dist/lib/image-variant-plan.d.ts.map +1 -0
- package/dist/lib/image-variant-plan.js +53 -0
- package/dist/lib/index-ops.d.ts.map +1 -1
- package/dist/lib/index-ops.js +21 -17
- package/dist/lib/index.d.ts +7 -4
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +55 -26
- package/dist/lib/loader.d.ts +25 -12
- package/dist/lib/loader.d.ts.map +1 -1
- package/dist/lib/media-ops.d.ts +73 -0
- package/dist/lib/media-ops.d.ts.map +1 -0
- package/dist/lib/media-ops.js +60 -0
- package/dist/lib/nav-tree.d.ts +7 -0
- package/dist/lib/nav-tree.d.ts.map +1 -1
- package/dist/lib/nav.d.ts +38 -0
- package/dist/lib/nav.d.ts.map +1 -1
- package/dist/lib/pages.d.ts +2 -1
- package/dist/lib/pages.d.ts.map +1 -1
- package/dist/lib/platform-broker.d.ts +4 -2
- package/dist/lib/platform-broker.d.ts.map +1 -1
- package/dist/lib/platform-broker.js +21 -13
- package/dist/lib/reference-type.d.ts +2 -0
- package/dist/lib/reference-type.d.ts.map +1 -0
- package/dist/lib/reference-validation.d.ts +31 -0
- package/dist/lib/reference-validation.d.ts.map +1 -0
- package/dist/lib/reference-validation.js +39 -0
- package/dist/lib/references.d.ts +74 -0
- package/dist/lib/references.d.ts.map +1 -0
- package/dist/lib/registry.d.ts +35 -0
- package/dist/lib/registry.d.ts.map +1 -1
- package/dist/lib/{safeRedirect.d.ts → safe-redirect.d.ts} +1 -1
- package/dist/lib/safe-redirect.d.ts.map +1 -0
- package/dist/lib/sidecar-diagnostics.d.ts +20 -0
- package/dist/lib/sidecar-diagnostics.d.ts.map +1 -0
- package/dist/lib/sidecars.d.ts +118 -0
- package/dist/lib/sidecars.d.ts.map +1 -0
- package/dist/lib/sidecars.js +23 -0
- package/dist/lib/slug.d.ts +2 -0
- package/dist/lib/slug.d.ts.map +1 -0
- package/dist/lib/storage-tier.d.ts +17 -0
- package/dist/lib/storage-tier.d.ts.map +1 -0
- package/dist/lib/storage-tier.js +29 -0
- package/dist/lib/tags.d.ts +64 -0
- package/dist/lib/tags.d.ts.map +1 -0
- package/dist/lib/theme-vars.d.ts +9 -0
- package/dist/lib/theme-vars.d.ts.map +1 -1
- package/dist/media/index.d.ts +1 -1
- package/dist/media/index.d.ts.map +1 -1
- package/dist/media/index.js +18 -14
- package/dist/media/queue.d.ts +2 -0
- package/dist/media/queue.d.ts.map +1 -1
- package/dist/media/utils.d.ts +2 -0
- package/dist/media/utils.d.ts.map +1 -1
- package/dist/media/{videoPoster.d.ts → video-poster.d.ts} +1 -1
- package/dist/media/video-poster.d.ts.map +1 -0
- package/dist/media/worker.d.ts +1 -35
- package/dist/media/worker.d.ts.map +1 -1
- package/dist/schemas/audience.js +2 -2
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +25 -13
- package/dist/schemas/media.d.ts +4 -0
- package/dist/schemas/media.d.ts.map +1 -1
- package/dist/schemas/shared.d.ts +26 -0
- package/dist/schemas/shared.d.ts.map +1 -1
- package/dist/schemas/site-config.d.ts +6 -0
- package/dist/schemas/site-config.d.ts.map +1 -1
- package/dist/schemas/tags.d.ts +27 -0
- package/dist/schemas/tags.d.ts.map +1 -0
- package/dist/storage/index.js +2 -1
- package/dist/storage/memory.d.ts +21 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +129 -0
- package/dist/storage/types.d.ts +9 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/types/database.d.ts.map +1 -1
- package/package.json +26 -1
- package/src/auth/cookies.ts +111 -0
- package/src/collab/rebase.ts +29 -9
- package/src/components/brandguide/ColorSwatchSettings.tsx +1 -1
- package/src/components/brandguide/ColorsEditable.tsx +1 -0
- package/src/components/chat/ChatPanel.tsx +2 -3
- package/src/components/chat/ChatWidget.tsx +2 -3
- package/src/components/docfile/DocFilePane.tsx +4 -12
- package/src/components/editor/ChildBlockWrapper.tsx +13 -19
- package/src/components/editor/ConflictDialog.tsx +27 -35
- package/src/components/editor/DeleteButton.tsx +2 -2
- package/src/components/editor/DragHandle.tsx +16 -3
- package/src/components/editor/DropEdgeIndicator.tsx +36 -10
- package/src/components/editor/InsertButton.tsx +2 -2
- package/src/components/editor/NavGroupRow.tsx +43 -14
- package/src/components/editor/PagesModal.tsx +99 -26
- package/src/components/editor/SectionWrapper.tsx +64 -23
- package/src/components/editor/SettingsButton.tsx +2 -2
- package/src/components/editor/SettingsForm.tsx +19 -2
- package/src/components/editor/StatusIndicator.tsx +4 -4
- package/src/components/editor/TagIndicator.tsx +80 -0
- package/src/components/primitives/DocumentDropZone.tsx +1 -1
- package/src/components/primitives/EditableGrid.tsx +15 -14
- package/src/components/primitives/EditableList.tsx +27 -74
- package/src/components/primitives/HeadingSection.tsx +5 -2
- package/src/components/primitives/ResolvedMedia.tsx +13 -0
- package/src/components/primitives/{defineHeadingSection.tsx → define-heading-section.tsx} +1 -0
- package/src/components/primitives/index.ts +1 -1
- package/src/components/primitives/useEditablePlainText.ts +5 -5
- package/src/components/sections/Button/CTAButton.tsx +3 -1
- package/src/components/sections/DoDontMedia/DoDontMediaBlock.tsx +4 -4
- package/src/components/sections/DoDontMedia/index.tsx +12 -3
- package/src/components/sections/IconList/DoDontToggle.tsx +2 -2
- package/src/components/sections/IconList/IconList.tsx +70 -37
- package/src/components/sections/IconList/IconListSettings.tsx +55 -17
- package/src/components/sections/IconList/index.tsx +10 -3
- package/src/components/sections/LinkHeading/index.tsx +1 -1
- package/src/components/sections/Media/MediaBlock.tsx +13 -2
- package/src/components/sections/Media/index.tsx +12 -4
- package/src/components/sections/Reference/ReferenceList.tsx +214 -0
- package/src/components/sections/Reference/ReferenceSettings.tsx +159 -0
- package/src/components/sections/Reference/index.tsx +47 -0
- package/src/components/sections/SectionSummary/SectionSummaryBlock.tsx +476 -0
- package/src/components/sections/SectionSummary/SectionSummarySettings.tsx +126 -0
- package/src/components/sections/SectionSummary/index.tsx +149 -0
- package/src/components/sections/SubHeading/index.tsx +1 -1
- package/src/components/sections/SubSubHeading/index.tsx +1 -1
- package/src/components/sections/brand-guide.ts +4 -3
- package/src/components/sections/core-sections.ts +2 -0
- package/src/components/shared/BrandSwatchesContext.ts +13 -0
- package/src/components/shared/Button.tsx +47 -34
- package/src/components/shared/Checkbox.tsx +21 -12
- package/src/components/shared/ConfirmDialog.tsx +87 -0
- package/src/components/shared/ConfirmInline.tsx +90 -0
- package/src/components/shared/ErrorBoundary.tsx +6 -18
- package/src/components/shared/Fab.tsx +15 -5
- package/src/components/shared/FabStack.tsx +28 -0
- package/src/components/shared/HistoryChangesModal.tsx +43 -41
- package/src/components/shared/HistoryPopover.tsx +7 -20
- package/src/components/shared/ImageBackgroundField.tsx +92 -0
- package/src/components/shared/{UploadRejectionAlert.tsx → InlineAlert.tsx} +21 -5
- package/src/components/shared/Input.tsx +23 -7
- package/src/components/shared/Navigation.tsx +22 -17
- package/src/components/shared/Notice.tsx +59 -0
- package/src/components/shared/Popover.tsx +7 -11
- package/src/components/shared/ReferenceSourcesContext.ts +27 -0
- package/src/components/shared/Select.tsx +5 -2
- package/src/components/shared/SplitButton.tsx +11 -17
- package/src/components/shared/SummaryAnchorsContext.ts +11 -0
- package/src/components/shared/Textarea.tsx +17 -2
- package/src/components/shared/ToolbarFrame.tsx +28 -0
- package/src/components/shared/VideoSourceField.tsx +1 -1
- package/src/components/shared/copy.ts +18 -0
- package/src/components/shared/icons.tsx +1 -17
- package/src/components/shell/AudienceAddForm.tsx +2 -2
- package/src/components/shell/AudienceDetailsPanel.tsx +23 -5
- package/src/components/shell/AudienceRow.tsx +22 -15
- package/src/components/shell/BugReportFAB.tsx +50 -40
- package/src/components/shell/CredentialList.tsx +33 -13
- package/src/components/shell/DocInspector.tsx +3 -12
- package/src/components/shell/DocumentEditorOverlay.tsx +33 -23
- package/src/components/shell/EditorContext.tsx +7 -0
- package/src/components/shell/EditorLoginForm.tsx +26 -36
- package/src/components/shell/EditorModal.tsx +8 -10
- package/src/components/shell/EditorShell.tsx +501 -338
- package/src/components/shell/HistoryToolbar.tsx +24 -26
- package/src/components/shell/MediaFolderTile.tsx +8 -3
- package/src/components/shell/MediaLibraryModal.tsx +59 -60
- package/src/components/shell/ProcessingIndicator.tsx +2 -2
- package/src/components/shell/RestoreModal.tsx +17 -16
- package/src/components/shell/SetPasswordForm.tsx +3 -3
- package/src/components/shell/SiteSettingsChatbot.tsx +61 -42
- package/src/components/shell/SiteSettingsDisplay.tsx +10 -20
- package/src/components/shell/SiteSettingsModal.tsx +24 -2
- package/src/components/shell/SiteSettingsTags.tsx +143 -0
- package/src/components/shell/SiteSettingsUsers.tsx +36 -26
- package/src/components/shell/SiteSettingsViewerAccess.tsx +2 -2
- package/src/components/shell/ViewerLoginForm.tsx +5 -4
- package/src/components/shell/reference-sources.ts +36 -0
- package/src/deck/index.ts +2 -2
- package/src/document/index.ts +2 -2
- package/src/hooks/useBlockDnd.ts +11 -0
- package/src/hooks/useBuildStatus.ts +53 -6
- package/src/hooks/useDocumentUploads.ts +1 -1
- package/src/hooks/useEditorPersistence.ts +141 -35
- package/src/hooks/useEditorPublish.ts +27 -31
- package/src/hooks/useMediaPipeline.ts +30 -24
- package/src/hooks/useNotice.ts +45 -0
- package/src/hooks/useSortableNavRow.ts +11 -0
- package/src/hooks/useSortableRow.ts +22 -2
- package/src/hooks/useStackedEscape.ts +62 -0
- package/src/lib/block-dnd.ts +6 -1
- package/src/lib/block-move.ts +3 -0
- package/src/lib/brand-swatches.ts +32 -0
- package/src/lib/container-ops.ts +5 -3
- package/src/lib/dexie.ts +24 -2
- package/src/lib/env.ts +9 -0
- package/src/lib/events.ts +1 -2
- package/src/lib/image-background.ts +31 -0
- package/src/lib/image-variant-plan.ts +92 -0
- package/src/lib/index-ops.ts +9 -18
- package/src/lib/index.ts +20 -4
- package/src/lib/loader.ts +28 -88
- package/src/lib/media-ops.ts +112 -0
- package/src/lib/nav-tree.ts +104 -4
- package/src/lib/nav.ts +196 -36
- package/src/lib/pages.ts +2 -3
- package/src/lib/platform-broker.ts +32 -14
- package/src/lib/reference-type.ts +3 -0
- package/src/lib/reference-validation.ts +69 -0
- package/src/lib/references.ts +130 -0
- package/src/lib/registry.ts +37 -0
- package/src/lib/sidecar-diagnostics.ts +29 -0
- package/src/lib/sidecars.ts +221 -0
- package/src/lib/slug.ts +6 -0
- package/src/lib/storage-tier.ts +38 -0
- package/src/lib/tags.ts +165 -0
- package/src/lib/theme-vars.ts +23 -0
- package/src/media/index.ts +1 -1
- package/src/media/queue.ts +3 -0
- package/src/media/utils.ts +19 -1
- package/src/media/{videoPoster.ts → video-poster.ts} +2 -2
- package/src/media/worker.ts +17 -8
- package/src/schemas/index.ts +1 -0
- package/src/schemas/media.ts +7 -2
- package/src/schemas/shared.ts +24 -1
- package/src/schemas/site-config.ts +6 -1
- package/src/schemas/tags.ts +33 -0
- package/src/storage/memory.ts +178 -0
- package/src/storage/types.ts +16 -3
- package/src/types/database.ts +2 -0
- package/dist/chunk-DNY72JZN.js +0 -86
- package/dist/chunk-F2LYQPXV.js +0 -77
- package/dist/chunk-JH762VUH.js +0 -128
- package/dist/chunk-K7DYZXVU.js +0 -138
- package/dist/components/primitives/defineHeadingSection.d.ts.map +0 -1
- package/dist/components/primitives/gridDrop.d.ts.map +0 -1
- package/dist/components/shared/UploadRejectionAlert.d.ts.map +0 -1
- package/dist/components/shell/BuildStatusIndicator.d.ts +0 -7
- package/dist/components/shell/BuildStatusIndicator.d.ts.map +0 -1
- package/dist/components/shell/blockMoveDispatch.d.ts.map +0 -1
- package/dist/hooks/index.d.ts +0 -9
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/lib/grid.d.ts +0 -2
- package/dist/lib/grid.d.ts.map +0 -1
- package/dist/lib/safeRedirect.d.ts.map +0 -1
- package/dist/media/videoPoster.d.ts.map +0 -1
- package/src/components/brandguide/ColorSwatchSettings.d.ts.map +0 -1
- package/src/components/brandguide/Colors.d.ts.map +0 -1
- package/src/components/primitives/CustomParagraph.d.ts.map +0 -1
- package/src/components/primitives/EditableGrid.d.ts.map +0 -1
- package/src/components/primitives/EditablePlainText.d.ts.map +0 -1
- package/src/components/primitives/EditableRichText.d.ts.map +0 -1
- package/src/components/primitives/HeadingSection.d.ts.map +0 -1
- package/src/components/primitives/IconPicker.d.ts.map +0 -1
- package/src/components/primitives/LinkPopover.d.ts.map +0 -1
- package/src/components/primitives/MediaSettingsForms.d.ts.map +0 -1
- package/src/components/primitives/ResolvedMedia.d.ts.map +0 -1
- package/src/components/primitives/RichTextToolbar.d.ts.map +0 -1
- package/src/components/primitives/tiptap-presets.d.ts.map +0 -1
- package/src/components/primitives/useEditableCollection.d.ts.map +0 -1
- package/src/components/primitives/useEditablePlainText.d.ts.map +0 -1
- package/src/components/primitives/useEditableRichText.d.ts.map +0 -1
- package/src/components/sections/Button/CTAButton.d.ts.map +0 -1
- package/src/components/sections/Button/index.d.ts.map +0 -1
- package/src/components/sections/Colors/index.d.ts.map +0 -1
- package/src/components/sections/IconList/IconList.d.ts.map +0 -1
- package/src/components/sections/IconList/IconListSettings.d.ts.map +0 -1
- package/src/components/sections/IconList/index.d.ts.map +0 -1
- package/src/components/sections/LinkHeading/index.d.ts.map +0 -1
- package/src/components/sections/Prose/Prose.d.ts.map +0 -1
- package/src/components/sections/Prose/index.d.ts.map +0 -1
- package/src/components/sections/SubHeading/index.d.ts.map +0 -1
- package/src/components/sections/SubSubHeading/index.d.ts.map +0 -1
- package/src/components/sections/register-schemas.d.ts.map +0 -1
- package/src/components/shared/Button.d.ts.map +0 -1
- package/src/components/shared/Checkbox.d.ts.map +0 -1
- package/src/components/shared/FormLabel.d.ts.map +0 -1
- package/src/components/shared/IconButton.d.ts.map +0 -1
- package/src/components/shared/Input.d.ts.map +0 -1
- package/src/components/shared/Select.d.ts.map +0 -1
- package/src/components/shared/icons.d.ts.map +0 -1
- package/src/components/shell/BuildStatusIndicator.tsx +0 -59
- package/src/components/shell/MediaLibraryContext.d.ts.map +0 -1
- package/src/hooks/index.ts +0 -8
- package/src/hooks/useResolvedMedia.d.ts.map +0 -1
- package/src/lib/cn.d.ts.map +0 -1
- package/src/lib/grid.d.ts.map +0 -1
- package/src/lib/grid.ts +0 -7
- package/src/lib/icons.d.ts.map +0 -1
- package/src/lib/loader.d.ts.map +0 -1
- package/src/lib/nav.d.ts.map +0 -1
- package/src/lib/registry.d.ts.map +0 -1
- package/src/lib/sanitize.d.ts.map +0 -1
- package/src/media/github.d.ts.map +0 -1
- package/src/media/index.d.ts.map +0 -1
- package/src/media/queue.d.ts.map +0 -1
- package/src/media/resolve.d.ts.map +0 -1
- package/src/media/types.d.ts.map +0 -1
- package/src/media/utils.d.ts.map +0 -1
- package/src/media/videoPoster.d.ts.map +0 -1
- package/src/schemas/auth.d.ts.map +0 -1
- package/src/schemas/media-grid-options.d.ts.map +0 -1
- package/src/schemas/media.d.ts.map +0 -1
- package/src/schemas/sections.d.ts.map +0 -1
- package/src/schemas/shared.d.ts.map +0 -1
- package/src/schemas/site-config.d.ts.map +0 -1
- /package/dist/{chunk-B7VBSE5X.js → chunk-3JDTXOIG.js} +0 -0
- /package/dist/{chunk-CXZ5YJG4.js → chunk-L45X7DKX.js} +0 -0
- /package/src/components/primitives/{gridDrop.ts → grid-drop.ts} +0 -0
- /package/src/components/shell/{blockMoveDispatch.ts → block-move-dispatch.ts} +0 -0
- /package/src/lib/{safeRedirect.ts → safe-redirect.ts} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useCallback, useState, useEffect } from "react";
|
|
2
|
-
import { Check, ChevronDown, Home } from "lucide-react";
|
|
1
|
+
import { useCallback, useState, useEffect, useId } from "react";
|
|
2
|
+
import { Check, ChevronDown, ChevronUp, Home } from "lucide-react";
|
|
3
3
|
import type { SiteIndex, Page } from "../../schemas/site-config";
|
|
4
4
|
import type { Audience } from "../../auth/types";
|
|
5
5
|
// Sanctioned outside->inside import: document/ is a sealed subtree, but the
|
|
@@ -7,6 +7,8 @@ import type { Audience } from "../../auth/types";
|
|
|
7
7
|
// sanctioned import in schemas/site-config.ts and lib/pages.ts).
|
|
8
8
|
import type { DocumentOptions } from "../../document/engine/settings";
|
|
9
9
|
import { Button } from "../shared/Button";
|
|
10
|
+
import { ConfirmDialog } from "../shared/ConfirmDialog";
|
|
11
|
+
import { IconButton } from "../shared/IconButton";
|
|
10
12
|
import { Input } from "../shared/Input";
|
|
11
13
|
import { Toggle } from "../shared/Toggle";
|
|
12
14
|
import { AudienceIndicator } from "./AudienceIndicator";
|
|
@@ -80,7 +82,17 @@ export function PagesModal(props: PagesModalProps) {
|
|
|
80
82
|
|
|
81
83
|
// `location` is optional: the archived flat block renders inert rows with no
|
|
82
84
|
// nav position, exactly as it did when draggability keyed off `dragIndex`.
|
|
83
|
-
|
|
85
|
+
// `liveSiblingRawIndexes` is the ordered list of RAW positions (within the
|
|
86
|
+
// group's `pageIds`, or within the top-level `entries`) that Move up/down
|
|
87
|
+
// may cross into — i.e. every LIVE sibling's raw slot, archived ones
|
|
88
|
+
// excluded. `location.index` is itself a raw position (drag needs it to
|
|
89
|
+
// splice correctly — see the ORIGINAL pageIds index comment below), so
|
|
90
|
+
// comparing it against a raw-space list (not a live COUNT) is what keeps an
|
|
91
|
+
// archived page sitting between two live ones from producing a wrongly
|
|
92
|
+
// disabled button or a click that silently swaps past the archived page
|
|
93
|
+
// with no visible reorder (drag can cross a group boundary; the keyboard
|
|
94
|
+
// pair deliberately cannot).
|
|
95
|
+
const renderPage = (page: Page, location?: NavLocation, entryIndex?: number, liveSiblingRawIndexes?: number[]) => (
|
|
84
96
|
<PageRow
|
|
85
97
|
key={page.id}
|
|
86
98
|
page={page}
|
|
@@ -90,6 +102,7 @@ export function PagesModal(props: PagesModalProps) {
|
|
|
90
102
|
otherSlugs={index.pages.filter((p) => p.id !== page.id).map((p) => p.slug)}
|
|
91
103
|
location={location}
|
|
92
104
|
entryIndex={entryIndex}
|
|
105
|
+
liveSiblingRawIndexes={liveSiblingRawIndexes}
|
|
93
106
|
onMove={props.onMoveNavEntry}
|
|
94
107
|
onToggleExpand={() => toggleExpand(page.id)}
|
|
95
108
|
onSetHome={() => props.onSetHome(page.id)}
|
|
@@ -108,14 +121,28 @@ export function PagesModal(props: PagesModalProps) {
|
|
|
108
121
|
/>
|
|
109
122
|
);
|
|
110
123
|
|
|
124
|
+
const entries = navEntries(index);
|
|
125
|
+
const entryCount = entries.length;
|
|
126
|
+
// Raw top-level positions that are "live" for Move up/down purposes: every
|
|
127
|
+
// group (always visible) plus every non-archived page — mirrors
|
|
128
|
+
// isLiveTopEntry in lib/nav-tree.ts, which describeNavMove's "N of M" uses.
|
|
129
|
+
const liveTopIndexes = entries
|
|
130
|
+
.map((entry, i) => ({ entry, i }))
|
|
131
|
+
.filter(({ entry }) => {
|
|
132
|
+
if (entry.kind === "group") return true;
|
|
133
|
+
const page = index.pages.find((p) => p.id === entry.pageId);
|
|
134
|
+
return page?.status === "live";
|
|
135
|
+
})
|
|
136
|
+
.map(({ i }) => i);
|
|
137
|
+
|
|
111
138
|
return (
|
|
112
139
|
<div className="flex flex-col gap-2 overflow-y-auto">
|
|
113
140
|
<div className="flex flex-col gap-2">
|
|
114
|
-
{
|
|
141
|
+
{entries.map((entry, entryIndex) => {
|
|
115
142
|
if (entry.kind === "page") {
|
|
116
143
|
const page = index.pages.find((p) => p.id === entry.pageId);
|
|
117
144
|
if (!page || page.status !== "live") return null;
|
|
118
|
-
return renderPage(page, { groupId: null, index: entryIndex }, entryIndex);
|
|
145
|
+
return renderPage(page, { groupId: null, index: entryIndex }, entryIndex, liveTopIndexes);
|
|
119
146
|
}
|
|
120
147
|
|
|
121
148
|
// CRITICAL: carry the ORIGINAL pageIds index (`pi`) through the filter.
|
|
@@ -134,6 +161,7 @@ export function PagesModal(props: PagesModalProps) {
|
|
|
134
161
|
<NavGroupRow
|
|
135
162
|
group={entry}
|
|
136
163
|
entryIndex={entryIndex}
|
|
164
|
+
entryCount={entryCount}
|
|
137
165
|
memberCount={members.length}
|
|
138
166
|
autoOpenSettings={newGroupId === entry.id}
|
|
139
167
|
onRename={(label) => props.onRenameGroup(entry.id, label)}
|
|
@@ -146,7 +174,7 @@ export function PagesModal(props: PagesModalProps) {
|
|
|
146
174
|
<div data-testid={`nav-group-members-${entry.id}`} className="ml-6 flex flex-col gap-2">
|
|
147
175
|
{members.length === 0
|
|
148
176
|
? <EmptyGroupDropzone groupId={entry.id} onMove={props.onMoveNavEntry} />
|
|
149
|
-
: members.map(({ page, pi }) => renderPage(page, { groupId: entry.id, index: pi }, entryIndex))}
|
|
177
|
+
: members.map(({ page, pi }) => renderPage(page, { groupId: entry.id, index: pi }, entryIndex, members.map((m) => m.pi)))}
|
|
150
178
|
</div>
|
|
151
179
|
)}
|
|
152
180
|
</div>
|
|
@@ -156,7 +184,7 @@ export function PagesModal(props: PagesModalProps) {
|
|
|
156
184
|
|
|
157
185
|
{/* The only target for "after the last entry" when that entry is a group:
|
|
158
186
|
every edge of a trailing group resolves to a position inside it. */}
|
|
159
|
-
<TailDropzone entryCount={
|
|
187
|
+
<TailDropzone entryCount={entryCount} onMove={props.onMoveNavEntry} />
|
|
160
188
|
|
|
161
189
|
<div className="mt-2 flex gap-2">
|
|
162
190
|
<Button
|
|
@@ -194,11 +222,16 @@ export function PagesModal(props: PagesModalProps) {
|
|
|
194
222
|
}
|
|
195
223
|
|
|
196
224
|
function PageRow({
|
|
197
|
-
page, audiences, expanded, isNew, otherSlugs, location, entryIndex, onMove, onToggleExpand, onSetHome, onSetArchived, onSetFields, onSetAudience, onSetDocument, onRequestDelete,
|
|
225
|
+
page, audiences, expanded, isNew, otherSlugs, location, entryIndex, liveSiblingRawIndexes, onMove, onToggleExpand, onSetHome, onSetArchived, onSetFields, onSetAudience, onSetDocument, onRequestDelete,
|
|
198
226
|
}: {
|
|
199
227
|
page: Page; audiences: Audience[]; expanded: boolean;
|
|
200
228
|
isNew: boolean; otherSlugs: string[];
|
|
201
229
|
location?: NavLocation; entryIndex?: number;
|
|
230
|
+
/** Ordered RAW positions of every LIVE sibling (the enclosing group's
|
|
231
|
+
* `pageIds`, or the top-level `entries`, whichever `location.groupId`
|
|
232
|
+
* selects) — see the comment on `renderPage` in PagesModal. Drag can cross
|
|
233
|
+
* a group boundary; the keyboard pair deliberately cannot. */
|
|
234
|
+
liveSiblingRawIndexes?: number[];
|
|
202
235
|
onMove: (from: NavLocation, to: NavLocation) => void;
|
|
203
236
|
onToggleExpand: () => void; onSetHome: () => void; onSetArchived: (v: boolean) => void;
|
|
204
237
|
onSetFields: (patch: Partial<Pick<Page, "title" | "slug" | "showInNav">>) => void;
|
|
@@ -211,6 +244,19 @@ function PageRow({
|
|
|
211
244
|
row: { kind: "page", pageId: page.id, groupId: location?.groupId ?? null, index: location?.index ?? 0 },
|
|
212
245
|
entryIndex: entryIndex ?? 0, kind: "page", onMove, enabled: draggable,
|
|
213
246
|
});
|
|
247
|
+
const dragHintId = useId();
|
|
248
|
+
// Neighbours are resolved among LIVE siblings only, then translated back to
|
|
249
|
+
// the neighbour's own raw index — never `location.index + delta`, which
|
|
250
|
+
// would step into an archived page's raw slot instead of the next visible
|
|
251
|
+
// row (see the `liveSiblingRawIndexes` comment on PagesModal's renderPage).
|
|
252
|
+
const liveIndex = liveSiblingRawIndexes?.indexOf(location?.index ?? -1) ?? -1;
|
|
253
|
+
const canMoveUp = draggable && liveIndex > 0;
|
|
254
|
+
const canMoveDown = draggable && liveSiblingRawIndexes !== undefined && liveIndex !== -1 && liveIndex < liveSiblingRawIndexes.length - 1;
|
|
255
|
+
const moveTo = (delta: 1 | -1) => {
|
|
256
|
+
const neighbourRawIndex = liveSiblingRawIndexes?.[liveIndex + delta];
|
|
257
|
+
if (neighbourRawIndex === undefined) return;
|
|
258
|
+
onMove(location!, { groupId: location!.groupId, index: neighbourRawIndex });
|
|
259
|
+
};
|
|
214
260
|
|
|
215
261
|
// The slug input edits a local draft; only valid values commit to the index,
|
|
216
262
|
// which must always hold a non-empty, unique, non-reserved slug.
|
|
@@ -297,8 +343,27 @@ function PageRow({
|
|
|
297
343
|
>
|
|
298
344
|
<DropEdgeIndicator edge={closestEdge} inset={location?.groupId != null} />
|
|
299
345
|
{draggable && (
|
|
300
|
-
<div className="flex shrink-0 items-center py-2 [&_[role=tooltip]]:hidden">
|
|
301
|
-
<DragHandle ref={handleRef} />
|
|
346
|
+
<div className="flex shrink-0 items-center gap-1 py-2 [&_[role=tooltip]]:hidden">
|
|
347
|
+
<DragHandle ref={handleRef} tabIndex={0} aria-describedby={dragHintId} />
|
|
348
|
+
<div className="flex flex-col">
|
|
349
|
+
<IconButton
|
|
350
|
+
icon={<ChevronUp size={12} />}
|
|
351
|
+
label="Move up"
|
|
352
|
+
size="sm"
|
|
353
|
+
disabled={!canMoveUp}
|
|
354
|
+
onClick={() => moveTo(-1)}
|
|
355
|
+
/>
|
|
356
|
+
<IconButton
|
|
357
|
+
icon={<ChevronDown size={12} />}
|
|
358
|
+
label="Move down"
|
|
359
|
+
size="sm"
|
|
360
|
+
disabled={!canMoveDown}
|
|
361
|
+
onClick={() => moveTo(1)}
|
|
362
|
+
/>
|
|
363
|
+
</div>
|
|
364
|
+
<span id={dragHintId} className="sr-only">
|
|
365
|
+
Use Move up / Move down to reorder with the keyboard.
|
|
366
|
+
</span>
|
|
302
367
|
</div>
|
|
303
368
|
)}
|
|
304
369
|
<div className={cn("min-w-0 flex-1 rounded-md border border-base-200 bg-base", isDragging && "outline outline-2 outline-primary/50")}>
|
|
@@ -455,21 +520,29 @@ function DeleteConfirm({ page, onCancel, onConfirm }: { page: Page; onCancel: ()
|
|
|
455
520
|
// type-the-name guard pre-satisfied ("" === "").
|
|
456
521
|
const confirmName = pageDisplayTitle(page.title);
|
|
457
522
|
return (
|
|
458
|
-
<
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
523
|
+
<ConfirmDialog
|
|
524
|
+
isOpen
|
|
525
|
+
embedded
|
|
526
|
+
title="Delete this page?"
|
|
527
|
+
body={
|
|
528
|
+
<div className="flex flex-col gap-3">
|
|
529
|
+
<p className="text-sm text-base-contrast">
|
|
530
|
+
Deleting <strong>{confirmName}</strong> permanently removes the page and its{" "}
|
|
531
|
+
<strong>{pluralize(n, "section")}</strong>. This is recoverable only via GitHub version history.
|
|
532
|
+
</p>
|
|
533
|
+
<Input
|
|
534
|
+
label={`Type the page name "${confirmName}" to confirm`}
|
|
535
|
+
value={typed}
|
|
536
|
+
onChange={setTyped}
|
|
537
|
+
placeholder={confirmName}
|
|
538
|
+
/>
|
|
539
|
+
</div>
|
|
540
|
+
}
|
|
541
|
+
confirmLabel="Delete"
|
|
542
|
+
tone="destructive"
|
|
543
|
+
confirmDisabled={typed !== confirmName}
|
|
544
|
+
onConfirm={onConfirm}
|
|
545
|
+
onCancel={onCancel}
|
|
546
|
+
/>
|
|
474
547
|
);
|
|
475
548
|
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { useState, useRef, useEffect } from "react";
|
|
2
|
-
import { ArrowRightLeft, Plus } from "lucide-react";
|
|
1
|
+
import { useState, useRef, useEffect, useId } from "react";
|
|
2
|
+
import { ArrowRightLeft, Plus, ChevronUp, ChevronDown } from "lucide-react";
|
|
3
3
|
import type { Edge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
|
|
4
4
|
import { DragHandle } from "./DragHandle";
|
|
5
|
+
import { DropEdgeIndicator } from "./DropEdgeIndicator";
|
|
5
6
|
import { InsertButton } from "./InsertButton";
|
|
6
7
|
import { DeleteButton } from "./DeleteButton";
|
|
7
8
|
import { SettingsButton } from "./SettingsButton";
|
|
8
9
|
import { IconButton } from "../shared/IconButton";
|
|
9
|
-
import { Tooltip
|
|
10
|
+
import { Tooltip } from "../shared/Tooltip";
|
|
10
11
|
import { StatusIndicator } from "./StatusIndicator";
|
|
11
12
|
import { AudienceIndicator } from "./AudienceIndicator";
|
|
13
|
+
import { TagIndicator } from "./TagIndicator";
|
|
12
14
|
import { LockBadge } from "./LockBadge";
|
|
13
15
|
import { SettingsForm } from "./SettingsForm";
|
|
14
16
|
import { useEditorContext } from "../shell/EditorContext";
|
|
@@ -16,6 +18,7 @@ import { useEditorModal } from "../shell/EditorModalContext";
|
|
|
16
18
|
import type { WrapperProps } from "../../lib/registry";
|
|
17
19
|
import { buildBlockDragData, buildBlockDropData, isBlockDragData, canDropBlock } from "../../lib/block-dnd";
|
|
18
20
|
import { cn } from "../../lib/cn";
|
|
21
|
+
import { REFERENCE_TYPE } from "../../lib/reference-type";
|
|
19
22
|
|
|
20
23
|
export function SectionWrapper({
|
|
21
24
|
sectionId,
|
|
@@ -24,6 +27,7 @@ export function SectionWrapper({
|
|
|
24
27
|
dirty,
|
|
25
28
|
index,
|
|
26
29
|
isLast,
|
|
30
|
+
sectionCount,
|
|
27
31
|
containerId,
|
|
28
32
|
isContainerBlock,
|
|
29
33
|
definition,
|
|
@@ -31,6 +35,7 @@ export function SectionWrapper({
|
|
|
31
35
|
audiences,
|
|
32
36
|
access,
|
|
33
37
|
onAccessChange,
|
|
38
|
+
tagging,
|
|
34
39
|
onStatusChange,
|
|
35
40
|
onSectionChange,
|
|
36
41
|
onReorder,
|
|
@@ -64,6 +69,7 @@ export function SectionWrapper({
|
|
|
64
69
|
const handleRef = useRef<HTMLButtonElement>(null);
|
|
65
70
|
const [isDragging, setIsDragging] = useState(false);
|
|
66
71
|
const [closestEdge, setClosestEdge] = useState<Edge | null>(null);
|
|
72
|
+
const dragHintId = useId();
|
|
67
73
|
|
|
68
74
|
const hasSettings = !!(
|
|
69
75
|
(definition.settings || definition.settingsForm) &&
|
|
@@ -120,6 +126,7 @@ export function SectionWrapper({
|
|
|
120
126
|
containerId,
|
|
121
127
|
index,
|
|
122
128
|
isContainer: isContainerBlock,
|
|
129
|
+
isReference: sectionType === REFERENCE_TYPE,
|
|
123
130
|
}),
|
|
124
131
|
onGenerateDragPreview: () => {
|
|
125
132
|
dropElement.style.opacity = "0.4";
|
|
@@ -182,7 +189,7 @@ export function SectionWrapper({
|
|
|
182
189
|
// be torn down on lock-acquire (cleanup above) and re-run against the fresh
|
|
183
190
|
// handle node on lock-release — without it, a locked-then-released section's
|
|
184
191
|
// registration stays bound to the old unmounted handle and reorder breaks.
|
|
185
|
-
}, [sectionId, index, containerId, isContainerBlock, isEditMode, isLocked]);
|
|
192
|
+
}, [sectionId, sectionType, index, containerId, isContainerBlock, isEditMode, isLocked]);
|
|
186
193
|
|
|
187
194
|
function handleSettingsClick() {
|
|
188
195
|
if (!onSectionChange) return;
|
|
@@ -278,11 +285,14 @@ export function SectionWrapper({
|
|
|
278
285
|
<div
|
|
279
286
|
className={cn(
|
|
280
287
|
"absolute left-0 bottom-full z-30 hover:z-[60] mb-1 flex items-center gap-1.5 transition-opacity",
|
|
281
|
-
|
|
288
|
+
// group-focus-within: this cluster's own tab stops (DragHandle,
|
|
289
|
+
// Move up/down) would otherwise be focusable but invisible —
|
|
290
|
+
// hover alone doesn't cover keyboard navigation.
|
|
291
|
+
alwaysShow ? "opacity-100" : "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100",
|
|
282
292
|
)}
|
|
283
293
|
>
|
|
284
294
|
<div className="relative -ml-[34px] flex flex-col items-center">
|
|
285
|
-
<DragHandle ref={handleRef} />
|
|
295
|
+
<DragHandle ref={handleRef} tabIndex={0} aria-describedby={dragHintId} />
|
|
286
296
|
{onRequestInsert && !isDragging && chromeReady && (
|
|
287
297
|
// Below xl the gutter can't fit the plus beside the handle, so it
|
|
288
298
|
// hangs below it (absolute → no row-height contribution: the handle
|
|
@@ -295,6 +305,27 @@ export function SectionWrapper({
|
|
|
295
305
|
<span className="pointer-events-none select-none whitespace-nowrap text-sm capitalize text-base-contrast-light/80">
|
|
296
306
|
{definition.label}
|
|
297
307
|
</span>
|
|
308
|
+
{onReorder && (
|
|
309
|
+
<div className="pointer-events-auto flex items-center">
|
|
310
|
+
<IconButton
|
|
311
|
+
icon={<ChevronUp size={14} />}
|
|
312
|
+
label={sectionCount ? `Move up (position ${index + 1} of ${sectionCount})` : "Move up"}
|
|
313
|
+
size="sm"
|
|
314
|
+
disabled={index === 0}
|
|
315
|
+
onClick={() => onReorder(index, index - 1)}
|
|
316
|
+
/>
|
|
317
|
+
<IconButton
|
|
318
|
+
icon={<ChevronDown size={14} />}
|
|
319
|
+
label={sectionCount ? `Move down (position ${index + 1} of ${sectionCount})` : "Move down"}
|
|
320
|
+
size="sm"
|
|
321
|
+
disabled={isLast}
|
|
322
|
+
onClick={() => onReorder(index, index + 1)}
|
|
323
|
+
/>
|
|
324
|
+
</div>
|
|
325
|
+
)}
|
|
326
|
+
<span id={dragHintId} className="sr-only">
|
|
327
|
+
Use Move up / Move down to reorder with the keyboard.
|
|
328
|
+
</span>
|
|
298
329
|
</div>
|
|
299
330
|
)}
|
|
300
331
|
|
|
@@ -331,9 +362,18 @@ export function SectionWrapper({
|
|
|
331
362
|
onChange={(newAccess) => onAccessChange?.(newAccess)}
|
|
332
363
|
/>
|
|
333
364
|
</div>
|
|
365
|
+
<div className="pointer-events-auto">
|
|
366
|
+
<TagIndicator
|
|
367
|
+
tags={tagging.tags}
|
|
368
|
+
assignedIds={tagging.assignedIds}
|
|
369
|
+
disabled={isLocked || !tagging.onToggle || !tagging.onCreate}
|
|
370
|
+
onToggle={(tagId, tagged) => tagging.onToggle?.(tagId, tagged)}
|
|
371
|
+
onCreate={(label) => tagging.onCreate?.(label)}
|
|
372
|
+
/>
|
|
373
|
+
</div>
|
|
334
374
|
|
|
335
375
|
{!isLocked && onAddChild && (
|
|
336
|
-
<Tooltip className="pointer-events-auto" content=
|
|
376
|
+
<Tooltip className="pointer-events-auto" content="Add a block">
|
|
337
377
|
<IconButton
|
|
338
378
|
icon={<Plus size={16} />}
|
|
339
379
|
label="Add block"
|
|
@@ -344,7 +384,7 @@ export function SectionWrapper({
|
|
|
344
384
|
)}
|
|
345
385
|
|
|
346
386
|
{!isLocked && onMoveSection && (
|
|
347
|
-
<Tooltip className="pointer-events-auto" content=
|
|
387
|
+
<Tooltip className="pointer-events-auto" content="Move to page">
|
|
348
388
|
<IconButton
|
|
349
389
|
icon={<ArrowRightLeft size={16} />}
|
|
350
390
|
label="Move to page"
|
|
@@ -355,31 +395,32 @@ export function SectionWrapper({
|
|
|
355
395
|
)}
|
|
356
396
|
|
|
357
397
|
{!isLocked && hasSettings && (
|
|
358
|
-
<Tooltip className="pointer-events-auto" content=
|
|
398
|
+
<Tooltip className="pointer-events-auto" content="Edit settings">
|
|
359
399
|
<SettingsButton onClick={handleSettingsClick} />
|
|
360
400
|
</Tooltip>
|
|
361
401
|
)}
|
|
362
402
|
|
|
363
403
|
{!isLocked && onDelete && (
|
|
364
|
-
<Tooltip className="pointer-events-auto" content=
|
|
404
|
+
<Tooltip className="pointer-events-auto" content="Delete section">
|
|
365
405
|
<DeleteButton onDelete={onDelete} />
|
|
366
406
|
</Tooltip>
|
|
367
407
|
)}
|
|
368
408
|
</div>
|
|
369
409
|
|
|
370
|
-
{/* Drop indicator — centered in the section's own padding-top
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
410
|
+
{/* Drop indicator — centered in the section's own padding-top. Bottom
|
|
411
|
+
only ever shows on the last section: every other slot's "insert
|
|
412
|
+
after me" is the next section's own "top" line, so showing both
|
|
413
|
+
would double the line. */}
|
|
414
|
+
<DropEdgeIndicator
|
|
415
|
+
edge={closestEdge === "bottom" && !isLast ? null : closestEdge}
|
|
416
|
+
style={
|
|
417
|
+
closestEdge === "top"
|
|
418
|
+
? { top: "calc(var(--section-gap) / 2 * -1)" }
|
|
419
|
+
: closestEdge === "bottom"
|
|
420
|
+
? { transform: "none" }
|
|
421
|
+
: undefined
|
|
422
|
+
}
|
|
423
|
+
/>
|
|
383
424
|
|
|
384
425
|
{isLocked ? (
|
|
385
426
|
// React 19 supports the boolean `inert` prop — blocks focus, pointer,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Settings } from "lucide-react";
|
|
2
2
|
import { IconButton } from "../shared/IconButton";
|
|
3
3
|
|
|
4
4
|
interface SettingsButtonProps {
|
|
@@ -8,7 +8,7 @@ interface SettingsButtonProps {
|
|
|
8
8
|
export function SettingsButton({ onClick }: SettingsButtonProps) {
|
|
9
9
|
return (
|
|
10
10
|
<IconButton
|
|
11
|
-
icon={<
|
|
11
|
+
icon={<Settings size={16} />}
|
|
12
12
|
label="Section settings"
|
|
13
13
|
onClick={onClick}
|
|
14
14
|
className="pointer-events-auto"
|
|
@@ -7,8 +7,10 @@ import { FormLabel } from "../shared/FormLabel";
|
|
|
7
7
|
import { LinkField } from "../shared/LinkField";
|
|
8
8
|
import { VideoSourceField } from "../shared/VideoSourceField";
|
|
9
9
|
import { DocumentSourceField, type DocumentRef } from "../shared/DocumentSourceField";
|
|
10
|
+
import { ImageBackgroundField } from "../shared/ImageBackgroundField";
|
|
10
11
|
import { Tabs } from "../shared/Tabs";
|
|
11
12
|
import type { LinkValue } from "../../schemas/link";
|
|
13
|
+
import type { ImageBackground } from "../../schemas/shared";
|
|
12
14
|
import type { VideoSource } from "../sections/Video/VideoBlock";
|
|
13
15
|
import { cn } from "../../lib/cn";
|
|
14
16
|
|
|
@@ -101,6 +103,7 @@ function renderField(
|
|
|
101
103
|
field: SettingsFieldDef,
|
|
102
104
|
value: unknown,
|
|
103
105
|
handleFieldChange: (key: string, newValue: unknown) => void,
|
|
106
|
+
values: Record<string, unknown>,
|
|
104
107
|
) {
|
|
105
108
|
switch (field.type) {
|
|
106
109
|
case "text":
|
|
@@ -184,6 +187,17 @@ function renderField(
|
|
|
184
187
|
/>
|
|
185
188
|
);
|
|
186
189
|
|
|
190
|
+
case "image-background":
|
|
191
|
+
if (field.hidden?.(values)) return null;
|
|
192
|
+
return (
|
|
193
|
+
<ImageBackgroundField
|
|
194
|
+
key={key}
|
|
195
|
+
label={field.label}
|
|
196
|
+
value={value as ImageBackground | undefined}
|
|
197
|
+
onChange={(v) => handleFieldChange(key, v)}
|
|
198
|
+
/>
|
|
199
|
+
);
|
|
200
|
+
|
|
187
201
|
default:
|
|
188
202
|
return null;
|
|
189
203
|
}
|
|
@@ -192,6 +206,9 @@ function renderField(
|
|
|
192
206
|
export function SettingsForm({ schema, values, onChange, tabs }: SettingsFormProps) {
|
|
193
207
|
const [local, setLocal] = useState(() => resolveValues(schema, values));
|
|
194
208
|
|
|
209
|
+
// `local` holds only schema keys; `hidden` predicates may read others (e.g. `ref`).
|
|
210
|
+
const allValues = { ...values, ...local };
|
|
211
|
+
|
|
195
212
|
function handleFieldChange(key: string, newValue: unknown) {
|
|
196
213
|
const next = { ...local, [key]: newValue };
|
|
197
214
|
setLocal(next);
|
|
@@ -200,7 +217,7 @@ export function SettingsForm({ schema, values, onChange, tabs }: SettingsFormPro
|
|
|
200
217
|
|
|
201
218
|
if (tabs) {
|
|
202
219
|
const fields = (keys: string[]) =>
|
|
203
|
-
keys.filter((key) => key in schema).map((key) => renderField(key, schema[key], local[key], handleFieldChange));
|
|
220
|
+
keys.filter((key) => key in schema).map((key) => renderField(key, schema[key], local[key], handleFieldChange, allValues));
|
|
204
221
|
|
|
205
222
|
const listed = new Set(tabs.flatMap((t) => t.fields));
|
|
206
223
|
const otherKeys = Object.keys(schema).filter((key) => !listed.has(key));
|
|
@@ -216,7 +233,7 @@ export function SettingsForm({ schema, values, onChange, tabs }: SettingsFormPro
|
|
|
216
233
|
|
|
217
234
|
return (
|
|
218
235
|
<div className="flex flex-col gap-4">
|
|
219
|
-
{Object.entries(schema).map(([key, field]) => renderField(key, field, local[key], handleFieldChange))}
|
|
236
|
+
{Object.entries(schema).map(([key, field]) => renderField(key, field, local[key], handleFieldChange, allValues))}
|
|
220
237
|
</div>
|
|
221
238
|
);
|
|
222
239
|
}
|
|
@@ -74,10 +74,10 @@ export function deriveStatusDisplay({ mainStatus, savedStatus, contentDiffers, i
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
const dotColorClasses: Record<StatusColor, string> = {
|
|
77
|
-
live: "bg-
|
|
78
|
-
draft: "bg-
|
|
79
|
-
archived: "bg-white border-
|
|
80
|
-
modified: "bg-
|
|
77
|
+
live: "bg-status-live-text",
|
|
78
|
+
draft: "bg-status-draft-text",
|
|
79
|
+
archived: "bg-white border-status-draft-text",
|
|
80
|
+
modified: "bg-status-modified-text",
|
|
81
81
|
};
|
|
82
82
|
|
|
83
83
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { useState, type FormEvent } from "react";
|
|
2
|
+
import { Plus } from "lucide-react";
|
|
3
|
+
import { cn } from "../../lib/cn";
|
|
4
|
+
import { tagDisplayLabel } from "../../lib/tags";
|
|
5
|
+
import type { TagEntry } from "../../schemas/tags";
|
|
6
|
+
import { IndicatorPill } from "./IndicatorPill";
|
|
7
|
+
import { PopoverItem } from "../shared/PopoverItem";
|
|
8
|
+
import { IconButton } from "../shared/IconButton";
|
|
9
|
+
import { CheckboxBox } from "../shared/Checkbox";
|
|
10
|
+
|
|
11
|
+
interface TagIndicatorProps {
|
|
12
|
+
/** The site's tag registry, already reconciled (siteTags). */
|
|
13
|
+
tags: TagEntry[];
|
|
14
|
+
/** The ids of the tags on this section. */
|
|
15
|
+
assignedIds: string[];
|
|
16
|
+
onToggle: (tagId: string, tagged: boolean) => void;
|
|
17
|
+
/** Create a tag from a typed name and put it on this section. */
|
|
18
|
+
onCreate: (label: string) => void;
|
|
19
|
+
/** Display-only mode — the pill still summarizes, but the picker never opens. */
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function TagIndicator({ tags, assignedIds, onToggle, onCreate, disabled }: TagIndicatorProps) {
|
|
24
|
+
const [draft, setDraft] = useState("");
|
|
25
|
+
const assigned = tags.filter((t) => assignedIds.includes(t.id));
|
|
26
|
+
|
|
27
|
+
const labelText = assigned.length === 0
|
|
28
|
+
? "No tags"
|
|
29
|
+
: assigned.length === 1 ? tagDisplayLabel(assigned[0].label) : `${assigned.length} tags`;
|
|
30
|
+
const ariaSummary = assigned.length === 0 ? "none" : assigned.map((t) => tagDisplayLabel(t.label)).join(", ");
|
|
31
|
+
|
|
32
|
+
function submit(e: FormEvent) {
|
|
33
|
+
e.preventDefault();
|
|
34
|
+
const label = draft.trim();
|
|
35
|
+
if (!label) return;
|
|
36
|
+
onCreate(label);
|
|
37
|
+
setDraft("");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<IndicatorPill
|
|
42
|
+
dots={[]}
|
|
43
|
+
label={labelText}
|
|
44
|
+
ariaLabel={`Tags: ${ariaSummary}`}
|
|
45
|
+
buttonClassName={assigned.length === 0 ? "text-base-contrast-light" : undefined}
|
|
46
|
+
disabled={disabled}
|
|
47
|
+
clickContent={
|
|
48
|
+
<div className="w-56 py-1">
|
|
49
|
+
{tags.length > 0 && (
|
|
50
|
+
<ul role="list" className="max-h-64 overflow-y-auto">
|
|
51
|
+
{tags.map((t) => {
|
|
52
|
+
const checked = assignedIds.includes(t.id);
|
|
53
|
+
return (
|
|
54
|
+
<li key={t.id}>
|
|
55
|
+
<PopoverItem role="checkbox" aria-checked={checked} onClick={() => onToggle(t.id, !checked)}>
|
|
56
|
+
<CheckboxBox checked={checked} />
|
|
57
|
+
<span className={cn("truncate font-medium text-base-contrast", !t.label && "italic text-base-contrast/60")}>
|
|
58
|
+
{tagDisplayLabel(t.label)}
|
|
59
|
+
</span>
|
|
60
|
+
</PopoverItem>
|
|
61
|
+
</li>
|
|
62
|
+
);
|
|
63
|
+
})}
|
|
64
|
+
</ul>
|
|
65
|
+
)}
|
|
66
|
+
<form onSubmit={submit} className={cn("flex items-center gap-1 px-3 py-1.5", tags.length > 0 && "border-t border-base-200")}>
|
|
67
|
+
<input
|
|
68
|
+
aria-label="New tag"
|
|
69
|
+
value={draft}
|
|
70
|
+
placeholder={tags.length > 0 ? "New tag" : "Create the first tag"}
|
|
71
|
+
onChange={(e) => setDraft(e.target.value)}
|
|
72
|
+
className="min-w-0 flex-1 rounded border border-base-200 bg-base px-2 py-1 text-xs text-base-contrast focus:border-base-contrast focus:outline-none"
|
|
73
|
+
/>
|
|
74
|
+
<IconButton icon={<Plus size={14} />} label="Create tag" size="sm" type="submit" />
|
|
75
|
+
</form>
|
|
76
|
+
</div>
|
|
77
|
+
}
|
|
78
|
+
/>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
@@ -19,7 +19,7 @@ const isDocumentFile = (file: File) => file.type in DOCUMENT_MIME_TO_EXT;
|
|
|
19
19
|
*
|
|
20
20
|
* Deliberately thin on validation: every rejection (wrong type, too large, no
|
|
21
21
|
* documents store) belongs to `uploadDocument`, which already routes typed copy
|
|
22
|
-
* through the pipeline's `onUploadError` → `
|
|
22
|
+
* through the pipeline's `onUploadError` → `InlineAlert` channel. The
|
|
23
23
|
* one judgement made here is WHICH file of a multi-file drop to hand over.
|
|
24
24
|
*/
|
|
25
25
|
export function DocumentDropZone({ onDocumentSelected, className }: DocumentDropZoneProps) {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { useRef, useEffect, useState, useId, type ReactNode } from "react";
|
|
2
|
-
import { ImageIcon } from "lucide-react";
|
|
3
|
-
import {
|
|
2
|
+
import { ImageIcon, Plus, Trash2, Settings } from "lucide-react";
|
|
3
|
+
import { DragHandle } from "../shared/icons";
|
|
4
4
|
import { IconButton } from "../shared/IconButton";
|
|
5
|
+
import { DropEdgeIndicator } from "../editor/DropEdgeIndicator";
|
|
5
6
|
import { cn } from "../../lib/cn";
|
|
6
7
|
import { containerGridClass } from "../../lib/container-grid";
|
|
7
8
|
import { useEditableCollection } from "./useEditableCollection";
|
|
8
|
-
import { resolveDropIndex } from "./
|
|
9
|
+
import { resolveDropIndex } from "./grid-drop";
|
|
9
10
|
|
|
10
11
|
interface EditableGridProps<T> {
|
|
11
12
|
items: T[];
|
|
@@ -166,7 +167,7 @@ export function EditableGrid<T>({
|
|
|
166
167
|
|
|
167
168
|
{/* Add button — absolute, centered below the grid */}
|
|
168
169
|
<IconButton
|
|
169
|
-
icon={<
|
|
170
|
+
icon={<Plus size={16} />}
|
|
170
171
|
label="Add item"
|
|
171
172
|
size="lg"
|
|
172
173
|
intent="primary"
|
|
@@ -287,18 +288,18 @@ function GridCell<T>({
|
|
|
287
288
|
isCellDragging && "opacity-50",
|
|
288
289
|
)}
|
|
289
290
|
>
|
|
290
|
-
{/* Drop indicator — centered in the gap between cells
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
291
|
+
{/* Drop indicator — centered in the gap between cells. The gap is wider
|
|
292
|
+
here than DropEdgeIndicator's default gutter, so the offset goes
|
|
293
|
+
through `style`. */}
|
|
294
|
+
<DropEdgeIndicator
|
|
295
|
+
edge={showLeftEdge ? "left" : showRightEdge ? "right" : null}
|
|
296
|
+
style={{ transform: showLeftEdge ? "translateX(-0.5rem)" : "translateX(0.5rem)" }}
|
|
297
|
+
/>
|
|
297
298
|
|
|
298
299
|
{/* Insert button — centered in the gap between cells */}
|
|
299
300
|
{!isDragging && !isLast && (
|
|
300
301
|
<IconButton
|
|
301
|
-
icon={<
|
|
302
|
+
icon={<Plus size={12} />}
|
|
302
303
|
label="Insert item"
|
|
303
304
|
size="sm"
|
|
304
305
|
intent="primary"
|
|
@@ -328,14 +329,14 @@ function GridCell<T>({
|
|
|
328
329
|
)}
|
|
329
330
|
{onSettings && (
|
|
330
331
|
<IconButton
|
|
331
|
-
icon={<
|
|
332
|
+
icon={<Settings size={16} />}
|
|
332
333
|
label="Item settings"
|
|
333
334
|
onClick={onSettings}
|
|
334
335
|
className="bg-base/80 shadow-sm"
|
|
335
336
|
/>
|
|
336
337
|
)}
|
|
337
338
|
<IconButton
|
|
338
|
-
icon={<
|
|
339
|
+
icon={<Trash2 size={16} />}
|
|
339
340
|
label="Delete item"
|
|
340
341
|
intent="destructive"
|
|
341
342
|
onClick={() => onRemove(id)}
|