canopycms 0.0.68-int.98 → 0.1.0
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/CHANGELOG.md +2131 -0
- package/README.md +47 -63
- package/dist/ai/generate.d.ts +5 -0
- package/dist/ai/generate.js +244 -115
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/json-to-markdown.d.ts +21 -1
- package/dist/ai/json-to-markdown.js +120 -57
- package/dist/ai/references.d.ts +72 -0
- package/dist/ai/references.js +223 -0
- package/dist/ai/resolve-branch.js +9 -2
- package/dist/ai/to-plain-text.d.ts +17 -8
- package/dist/ai/to-plain-text.js +18 -15
- package/dist/ai/types.d.ts +84 -3
- package/dist/api/admin-branch-health.d.ts +24 -1
- package/dist/api/admin-branch-health.js +52 -20
- package/dist/api/admin.d.ts +23 -5
- package/dist/api/admin.js +36 -1
- package/dist/api/assets.js +88 -78
- package/dist/api/branch-create-window.d.ts +12 -0
- package/dist/api/branch-create-window.js +13 -0
- package/dist/api/branch-merge.d.ts +1 -1
- package/dist/api/branch-merge.js +1 -1
- package/dist/api/branch-review.d.ts +3 -3
- package/dist/api/branch-review.js +16 -7
- package/dist/api/branch-status.d.ts +16 -6
- package/dist/api/branch-status.js +57 -12
- package/dist/api/branch-withdraw.d.ts +2 -2
- package/dist/api/branch-withdraw.js +8 -3
- package/dist/api/branch.d.ts +25 -12
- package/dist/api/branch.js +164 -103
- package/dist/api/client.d.ts +78 -58
- package/dist/api/client.js +150 -117
- package/dist/api/comments.d.ts +12 -3
- package/dist/api/comments.js +118 -9
- package/dist/api/content.d.ts +9 -9
- package/dist/api/content.js +131 -22
- package/dist/api/entries-constants.d.ts +14 -3
- package/dist/api/entries-constants.js +14 -3
- package/dist/api/entries.d.ts +40 -2
- package/dist/api/entries.js +102 -6
- package/dist/api/github-sync.d.ts +19 -0
- package/dist/api/github-sync.js +50 -3
- package/dist/api/groups.d.ts +4 -4
- package/dist/api/groups.js +2 -1
- package/dist/api/guards.js +23 -3
- package/dist/api/index.d.ts +3 -1
- package/dist/api/index.js +1 -0
- package/dist/api/permissions.d.ts +21 -2
- package/dist/api/permissions.js +50 -3
- package/dist/api/request-deadline.d.ts +59 -0
- package/dist/api/request-deadline.js +73 -0
- package/dist/api/resolve-references.js +8 -7
- package/dist/api/route-builder.d.ts +14 -0
- package/dist/api/route-builder.js +14 -1
- package/dist/api/schema.d.ts +11 -9
- package/dist/api/schema.js +2 -0
- package/dist/api/settings-helpers.d.ts +5 -1
- package/dist/api/settings-helpers.js +10 -2
- package/dist/api/types.d.ts +18 -0
- package/dist/api/users-constants.d.ts +6 -0
- package/dist/api/users-constants.js +6 -0
- package/dist/assets/asset-url.d.ts +28 -16
- package/dist/assets/asset-url.js +51 -25
- package/dist/assets/finalize.js +3 -0
- package/dist/assets/index.d.ts +1 -1
- package/dist/assets/materialize.d.ts +153 -0
- package/dist/assets/materialize.js +402 -0
- package/dist/assets/store-local.d.ts +19 -5
- package/dist/assets/store-local.js +69 -10
- package/dist/assets/store-s3.d.ts +38 -7
- package/dist/assets/store-s3.js +128 -22
- package/dist/assets/transform-directives.d.ts +52 -13
- package/dist/assets/transform-directives.js +87 -27
- package/dist/assets/transform.d.ts +3 -3
- package/dist/assets/transform.js +13 -8
- package/dist/assets/types.d.ts +31 -4
- package/dist/auth/cache.d.ts +1 -1
- package/dist/auth/cache.js +1 -1
- package/dist/auth/caching-auth-plugin.d.ts +2 -0
- package/dist/auth/caching-auth-plugin.js +12 -2
- package/dist/auth/file-based-auth-cache.d.ts +8 -0
- package/dist/auth/file-based-auth-cache.js +18 -8
- package/dist/auth/person-name.d.ts +5 -0
- package/dist/auth/person-name.js +8 -0
- package/dist/auth/plugin.d.ts +10 -1
- package/dist/auth/types.d.ts +2 -0
- package/dist/auth/user-metadata-lookup.d.ts +21 -0
- package/dist/auth/user-metadata-lookup.js +116 -0
- package/dist/authorization/branch.d.ts +1 -1
- package/dist/authorization/branch.js +12 -13
- package/dist/authorization/groups/schema.d.ts +4 -4
- package/dist/authorization/helpers.d.ts +8 -0
- package/dist/authorization/helpers.js +8 -0
- package/dist/authorization/index.d.ts +1 -1
- package/dist/authorization/index.js +1 -1
- package/dist/authorization/protected-branch.d.ts +5 -4
- package/dist/authorization/protected-branch.js +7 -5
- package/dist/branch-health.d.ts +35 -8
- package/dist/branch-health.js +54 -18
- package/dist/branch-metadata-error.d.ts +27 -0
- package/dist/branch-metadata-error.js +23 -0
- package/dist/branch-metadata-file.d.ts +205 -24
- package/dist/branch-metadata-file.js +126 -25
- package/dist/branch-metadata.d.ts +45 -6
- package/dist/branch-metadata.js +142 -50
- package/dist/branch-provisioning.d.ts +167 -0
- package/dist/branch-provisioning.js +501 -0
- package/dist/branch-registry.d.ts +8 -0
- package/dist/branch-registry.js +61 -9
- package/dist/branch-schema-cache.d.ts +29 -12
- package/dist/branch-schema-cache.js +64 -21
- package/dist/branch-sparse.d.ts +23 -0
- package/dist/branch-sparse.js +118 -0
- package/dist/branch-workspace.d.ts +42 -3
- package/dist/branch-workspace.js +239 -100
- package/dist/build/asset-refs.d.ts +94 -0
- package/dist/build/asset-refs.js +267 -0
- package/dist/build/generate-ai-content.js +5 -0
- package/dist/build/inline-flight.d.ts +37 -0
- package/dist/build/inline-flight.js +142 -0
- package/dist/cli/asset-refs.d.ts +52 -0
- package/dist/cli/asset-refs.js +194 -0
- package/dist/cli/cli.d.ts +15 -1
- package/dist/cli/cli.js +8543 -3193
- package/dist/cli/configured-asset-store.d.ts +12 -0
- package/dist/cli/configured-asset-store.js +46 -0
- package/dist/cli/generate-ai-content.js +4244 -1072
- package/dist/cli/init.js +217 -126
- package/dist/cli/project-detect.d.ts +2 -0
- package/dist/cli/project-detect.js +2 -0
- package/dist/cli/template-files/Dockerfile.cms.template +13 -5
- package/dist/cli/template-files/cms-stack.ts.template +16 -13
- package/dist/client.d.ts +1 -2
- package/dist/client.js +1 -2
- package/dist/comment-store.d.ts +25 -0
- package/dist/comment-store.js +43 -8
- package/dist/config/flatten.js +2 -0
- package/dist/config/helpers.js +2 -2
- package/dist/config/index.d.ts +1 -1
- package/dist/config/schemas/config.d.ts +12 -29
- package/dist/config/schemas/config.js +9 -12
- package/dist/config/schemas/field.d.ts +3 -0
- package/dist/config/schemas/field.js +58 -4
- package/dist/config/schemas/media.d.ts +4 -13
- package/dist/config/schemas/media.js +5 -8
- package/dist/config/schemas/url.d.ts +2 -20
- package/dist/config/schemas/url.js +2 -25
- package/dist/config/types.d.ts +116 -22
- package/dist/config/types.js +3 -9
- package/dist/config/validation.d.ts +25 -4
- package/dist/config/validation.js +116 -3
- package/dist/content-id-index.js +2 -2
- package/dist/content-index-generation.d.ts +1 -1
- package/dist/content-index-generation.js +1 -1
- package/dist/content-listing.d.ts +10 -1
- package/dist/content-listing.js +22 -5
- package/dist/content-reader.d.ts +9 -0
- package/dist/content-reader.js +16 -11
- package/dist/content-store.d.ts +75 -12
- package/dist/content-store.js +249 -86
- package/dist/content-tree.js +2 -2
- package/dist/context.js +5 -2
- package/dist/dangling-reference-log.d.ts +17 -0
- package/dist/dangling-reference-log.js +29 -0
- package/dist/dev-content-watcher.d.ts +1 -1
- package/dist/dev-content-watcher.js +1 -1
- package/dist/editor/BranchManager.d.ts +23 -7
- package/dist/editor/BranchManager.js +119 -54
- package/dist/editor/CanopyEditor.d.ts +1 -1
- package/dist/editor/CanopyEditor.js +1 -2
- package/dist/editor/CommentsPanel.d.ts +14 -0
- package/dist/editor/CommentsPanel.js +68 -43
- package/dist/editor/Editor.d.ts +11 -5
- package/dist/editor/Editor.js +891 -218
- package/dist/editor/EditorAuthGate.d.ts +7 -1
- package/dist/editor/EditorAuthGate.js +41 -9
- package/dist/editor/EntryNavigator.d.ts +22 -0
- package/dist/editor/EntryNavigator.js +353 -105
- package/dist/editor/FormHeader.d.ts +25 -0
- package/dist/editor/FormHeader.js +82 -0
- package/dist/editor/FormRenderer.d.ts +27 -3
- package/dist/editor/FormRenderer.js +171 -76
- package/dist/editor/PreviewFrame.d.ts +40 -0
- package/dist/editor/PreviewFrame.js +215 -0
- package/dist/editor/PreviewPane.d.ts +47 -0
- package/dist/editor/PreviewPane.js +147 -0
- package/dist/editor/PreviewToolbarTools.d.ts +22 -0
- package/dist/editor/PreviewToolbarTools.js +73 -0
- package/dist/editor/admin/SystemHealthPanel.d.ts +2 -1
- package/dist/editor/admin/SystemHealthPanel.js +163 -33
- package/dist/editor/admin/useSystemHealth.d.ts +18 -0
- package/dist/editor/admin/useSystemHealth.js +70 -1
- package/dist/editor/branch-status.d.ts +17 -0
- package/dist/editor/branch-status.js +29 -0
- package/dist/editor/canopy-path.d.ts +9 -6
- package/dist/editor/canopy-path.js +8 -11
- package/dist/editor/client-reference-resolver.d.ts +43 -16
- package/dist/editor/client-reference-resolver.js +155 -64
- package/dist/editor/comments/BranchComments.d.ts +1 -1
- package/dist/editor/comments/BranchComments.js +2 -2
- package/dist/editor/comments/CloseRefusedNotice.d.ts +4 -0
- package/dist/editor/comments/CloseRefusedNotice.js +7 -0
- package/dist/editor/comments/CommentThreadsPopover.d.ts +47 -0
- package/dist/editor/comments/CommentThreadsPopover.js +274 -0
- package/dist/editor/comments/CommentWriteAlert.d.ts +11 -0
- package/dist/editor/comments/CommentWriteAlert.js +13 -0
- package/dist/editor/comments/EntryComments.d.ts +10 -4
- package/dist/editor/comments/EntryComments.js +14 -17
- package/dist/editor/comments/FieldWrapper.d.ts +18 -4
- package/dist/editor/comments/FieldWrapper.js +62 -28
- package/dist/editor/comments/InlineCommentThread.d.ts +9 -2
- package/dist/editor/comments/InlineCommentThread.js +11 -47
- package/dist/editor/comments/ThreadCarousel.d.ts +1 -1
- package/dist/editor/comments/ThreadCarousel.js +18 -21
- package/dist/editor/comments/ThreadReplyControls.d.ts +28 -0
- package/dist/editor/comments/ThreadReplyControls.js +92 -0
- package/dist/editor/comments/field-comment-context.d.ts +14 -0
- package/dist/editor/comments/field-comment-context.js +14 -0
- package/dist/editor/comments/form-comments.d.ts +48 -0
- package/dist/editor/comments/form-comments.js +178 -0
- package/dist/editor/comments/item-anchor-copy.d.ts +6 -0
- package/dist/editor/comments/item-anchor-copy.js +6 -0
- package/dist/editor/comments/move-focus-if-unmoved.d.ts +6 -0
- package/dist/editor/comments/move-focus-if-unmoved.js +11 -0
- package/dist/editor/comments/popover-placement.d.ts +18 -0
- package/dist/editor/comments/popover-placement.js +58 -0
- package/dist/editor/comments/use-tracked-writes.d.ts +16 -0
- package/dist/editor/comments/use-tracked-writes.js +53 -0
- package/dist/editor/components/BranchAccessList.d.ts +15 -0
- package/dist/editor/components/BranchAccessList.js +52 -0
- package/dist/editor/components/BranchLockBanner.d.ts +22 -0
- package/dist/editor/components/BranchLockBanner.js +39 -0
- package/dist/editor/components/BranchPill.d.ts +32 -0
- package/dist/editor/components/BranchPill.js +33 -0
- package/dist/editor/components/BranchesDrawer.d.ts +11 -0
- package/dist/editor/components/BranchesDrawer.js +5 -0
- package/dist/editor/components/ConfirmDeleteModal.d.ts +6 -1
- package/dist/editor/components/ConfirmDeleteModal.js +3 -2
- package/dist/editor/components/DestructiveMenuItem.d.ts +7 -0
- package/dist/editor/components/DestructiveMenuItem.js +8 -0
- package/dist/editor/components/EditorCrashScreen.d.ts +17 -0
- package/dist/editor/components/EditorCrashScreen.js +22 -0
- package/dist/editor/components/EditorErrorBoundary.d.ts +38 -0
- package/dist/editor/components/EditorErrorBoundary.js +40 -0
- package/dist/editor/components/EditorHeader.d.ts +56 -106
- package/dist/editor/components/EditorHeader.js +130 -131
- package/dist/editor/components/EditorRail.d.ts +49 -0
- package/dist/editor/components/EditorRail.js +65 -0
- package/dist/editor/components/EntryBreadcrumb.d.ts +33 -0
- package/dist/editor/components/EntryBreadcrumb.js +56 -0
- package/dist/editor/components/EntryCreateModal.d.ts +12 -7
- package/dist/editor/components/EntryCreateModal.js +51 -57
- package/dist/editor/components/NoEditPermissionNotice.d.ts +6 -5
- package/dist/editor/components/NoEditPermissionNotice.js +5 -4
- package/dist/editor/components/QuickOpenPalette.d.ts +22 -0
- package/dist/editor/components/QuickOpenPalette.js +66 -0
- package/dist/editor/components/ReadOnlyDraftNotice.d.ts +11 -0
- package/dist/editor/components/ReadOnlyDraftNotice.js +12 -0
- package/dist/editor/components/ReasonedMenuItem.d.ts +15 -0
- package/dist/editor/components/ReasonedMenuItem.js +15 -0
- package/dist/editor/components/ReferencedByList.d.ts +11 -0
- package/dist/editor/components/ReferencedByList.js +28 -0
- package/dist/editor/components/RelativeTime.d.ts +10 -0
- package/dist/editor/components/RelativeTime.js +10 -0
- package/dist/editor/components/RenameEntryModal.d.ts +9 -1
- package/dist/editor/components/RenameEntryModal.js +19 -31
- package/dist/editor/components/RetryToastMessage.d.ts +9 -0
- package/dist/editor/components/RetryToastMessage.js +6 -0
- package/dist/editor/components/SaveAllResult.d.ts +25 -0
- package/dist/editor/components/SaveAllResult.js +86 -0
- package/dist/editor/components/SaveSplitButton.d.ts +30 -0
- package/dist/editor/components/SaveSplitButton.js +108 -0
- package/dist/editor/components/StagedChangesDrawer.d.ts +39 -0
- package/dist/editor/components/StagedChangesDrawer.js +92 -0
- package/dist/editor/components/UnavailableEntryNotice.d.ts +6 -0
- package/dist/editor/components/UnavailableEntryNotice.js +9 -0
- package/dist/editor/components/UnavailableTypeMessage.d.ts +6 -0
- package/dist/editor/components/UnavailableTypeMessage.js +9 -0
- package/dist/editor/components/UndoToastMessage.d.ts +18 -0
- package/dist/editor/components/UndoToastMessage.js +10 -0
- package/dist/editor/components/UserBadge.d.ts +2 -5
- package/dist/editor/components/UserBadge.js +62 -33
- package/dist/editor/components/ValidationSummary.d.ts +14 -0
- package/dist/editor/components/ValidationSummary.js +24 -0
- package/dist/editor/components/index.d.ts +2 -2
- package/dist/editor/components/index.js +2 -2
- package/dist/editor/context/ApiClientContext.d.ts +8 -2
- package/dist/editor/context/ApiClientContext.js +19 -8
- package/dist/editor/context/AssetContext.d.ts +13 -35
- package/dist/editor/context/AssetContext.js +12 -31
- package/dist/editor/context/EditorStateContext.d.ts +4 -4
- package/dist/editor/context/EditorStateContext.js +4 -4
- package/dist/editor/context/SWRProvider.d.ts +3 -3
- package/dist/editor/context/SiteMdxAllowContext.d.ts +4 -0
- package/dist/editor/context/SiteMdxAllowContext.js +7 -0
- package/dist/editor/context/index.d.ts +2 -1
- package/dist/editor/context/index.js +2 -1
- package/dist/editor/contrast.d.ts +19 -0
- package/dist/editor/contrast.js +41 -0
- package/dist/editor/copy.d.ts +18 -0
- package/dist/editor/copy.js +18 -0
- package/dist/editor/editor-config.js +16 -0
- package/dist/editor/editor-utils.d.ts +34 -8
- package/dist/editor/editor-utils.js +42 -20
- package/dist/editor/entry-search.d.ts +20 -0
- package/dist/editor/entry-search.js +34 -0
- package/dist/editor/field-breadcrumb.d.ts +12 -0
- package/dist/editor/field-breadcrumb.js +85 -0
- package/dist/editor/field-props.d.ts +86 -0
- package/dist/editor/field-props.js +27 -0
- package/dist/editor/field-target.d.ts +30 -0
- package/dist/editor/field-target.js +77 -0
- package/dist/editor/fields/BlockField.d.ts +12 -0
- package/dist/editor/fields/BlockField.js +89 -73
- package/dist/editor/fields/CodeField.d.ts +2 -0
- package/dist/editor/fields/CodeField.js +6 -2
- package/dist/editor/fields/DateTimeField.d.ts +4 -29
- package/dist/editor/fields/DateTimeField.js +79 -41
- package/dist/editor/fields/ExpandAllButton.d.ts +6 -0
- package/dist/editor/fields/ExpandAllButton.js +4 -0
- package/dist/editor/fields/FieldCrashFallback.d.ts +17 -0
- package/dist/editor/fields/FieldCrashFallback.js +30 -0
- package/dist/editor/fields/FieldLabel.d.ts +37 -0
- package/dist/editor/fields/FieldLabel.js +19 -0
- package/dist/editor/fields/ImageField.d.ts +4 -0
- package/dist/editor/fields/ImageField.js +29 -14
- package/dist/editor/fields/InlineGroupField.js +4 -3
- package/dist/editor/fields/ItemList.d.ts +42 -0
- package/dist/editor/fields/ItemList.js +130 -0
- package/dist/editor/fields/MarkdownField.d.ts +32 -0
- package/dist/editor/fields/MarkdownField.js +223 -46
- package/dist/editor/fields/MdxImageDialog.js +1 -1
- package/dist/editor/fields/NumberField.d.ts +2 -0
- package/dist/editor/fields/NumberField.js +8 -5
- package/dist/editor/fields/NumberListField.d.ts +2 -0
- package/dist/editor/fields/NumberListField.js +19 -16
- package/dist/editor/fields/ObjectField.d.ts +2 -7
- package/dist/editor/fields/ObjectField.js +15 -5
- package/dist/editor/fields/ObjectListField.d.ts +29 -0
- package/dist/editor/fields/ObjectListField.js +57 -0
- package/dist/editor/fields/ReferenceField.d.ts +2 -0
- package/dist/editor/fields/ReferenceField.js +34 -9
- package/dist/editor/fields/SelectField.d.ts +2 -0
- package/dist/editor/fields/SelectField.js +11 -2
- package/dist/editor/fields/StringListField.d.ts +4 -1
- package/dist/editor/fields/StringListField.js +22 -8
- package/dist/editor/fields/TextField.d.ts +2 -0
- package/dist/editor/fields/TextField.js +6 -2
- package/dist/editor/fields/ToggleField.d.ts +2 -0
- package/dist/editor/fields/ToggleField.js +8 -3
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +1 -1
- package/dist/editor/fields/entry-link/InsertEntryLink.js +1 -1
- package/dist/editor/fields/form-expansion.d.ts +9 -0
- package/dist/editor/fields/form-expansion.js +2 -0
- package/dist/editor/fields/item-expansion.d.ts +15 -0
- package/dist/editor/fields/item-expansion.js +60 -0
- package/dist/editor/fields/list-item-keys.d.ts +8 -0
- package/dist/editor/fields/list-item-keys.js +50 -0
- package/dist/editor/fields/list-item-title.d.ts +20 -0
- package/dist/editor/fields/list-item-title.js +85 -0
- package/dist/editor/fields/markdown-export-options.d.ts +2 -0
- package/dist/editor/fields/markdown-export-options.js +8 -0
- package/dist/editor/fields/markdown-fidelity-visitors.d.ts +11 -0
- package/dist/editor/fields/markdown-fidelity-visitors.js +160 -0
- package/dist/editor/fields/mdx-jsx-support.d.ts +5 -1
- package/dist/editor/fields/mdx-jsx-support.js +157 -69
- package/dist/editor/fields/rich-text-failures.d.ts +5 -0
- package/dist/editor/fields/rich-text-failures.js +26 -0
- package/dist/editor/fields/toolbar-wrap.d.ts +7 -0
- package/dist/editor/fields/toolbar-wrap.js +35 -0
- package/dist/editor/form-outline.d.ts +13 -0
- package/dist/editor/form-outline.js +70 -0
- package/dist/editor/group-manager/GroupCard.d.ts +4 -1
- package/dist/editor/group-manager/GroupCard.js +12 -3
- package/dist/editor/group-manager/GroupForm.js +1 -1
- package/dist/editor/group-manager/InternalGroupsTab.d.ts +2 -1
- package/dist/editor/group-manager/InternalGroupsTab.js +4 -4
- package/dist/editor/group-manager/MemberList.d.ts +2 -1
- package/dist/editor/group-manager/MemberList.js +15 -4
- package/dist/editor/group-manager/hooks/useGroupState.d.ts +5 -0
- package/dist/editor/group-manager/hooks/useGroupState.js +30 -7
- package/dist/editor/group-manager/index.js +34 -5
- package/dist/editor/group-manager/types.d.ts +5 -2
- package/dist/editor/hooks/create-branch-request.d.ts +20 -0
- package/dist/editor/hooks/create-branch-request.js +54 -0
- package/dist/editor/hooks/save-all.d.ts +68 -0
- package/dist/editor/hooks/save-all.js +61 -0
- package/dist/editor/hooks/useBranchActions.d.ts +11 -1
- package/dist/editor/hooks/useBranchActions.js +42 -19
- package/dist/editor/hooks/useBranchManager.d.ts +21 -0
- package/dist/editor/hooks/useBranchManager.js +321 -125
- package/dist/editor/hooks/useBranchesData.d.ts +8 -4
- package/dist/editor/hooks/useBranchesData.js +9 -5
- package/dist/editor/hooks/useCommentSystem.d.ts +14 -2
- package/dist/editor/hooks/useCommentSystem.js +79 -55
- package/dist/editor/hooks/useCommentsData.d.ts +11 -7
- package/dist/editor/hooks/useCommentsData.js +20 -19
- package/dist/editor/hooks/useDraftManager.d.ts +77 -3
- package/dist/editor/hooks/useDraftManager.js +887 -94
- package/dist/editor/hooks/useEditorLayout.d.ts +53 -7
- package/dist/editor/hooks/useEditorLayout.js +98 -20
- package/dist/editor/hooks/useEntriesData.d.ts +2 -1
- package/dist/editor/hooks/useEntriesData.js +18 -4
- package/dist/editor/hooks/useEntryManager.d.ts +41 -2
- package/dist/editor/hooks/useEntryManager.js +227 -41
- package/dist/editor/hooks/useGroupManager.js +13 -16
- package/dist/editor/hooks/usePermissionManager.js +14 -6
- package/dist/editor/hooks/usePreviewMarks.d.ts +21 -0
- package/dist/editor/hooks/usePreviewMarks.js +33 -0
- package/dist/editor/hooks/useReferenceResolution.d.ts +10 -3
- package/dist/editor/hooks/useReferenceResolution.js +34 -177
- package/dist/editor/hooks/useSchemaManager.d.ts +25 -6
- package/dist/editor/hooks/useSchemaManager.js +97 -39
- package/dist/editor/hooks/useUserMetadata.d.ts +14 -4
- package/dist/editor/hooks/useUserMetadata.js +76 -47
- package/dist/editor/hooks/user-metadata-batcher.d.ts +8 -0
- package/dist/editor/hooks/user-metadata-batcher.js +33 -0
- package/dist/editor/media/AssetCard.d.ts +6 -7
- package/dist/editor/media/AssetCard.js +24 -31
- package/dist/editor/media/AssetListRow.d.ts +16 -0
- package/dist/editor/media/AssetListRow.js +41 -0
- package/dist/editor/media/CropStep.js +6 -1
- package/dist/editor/media/MediaLibrary.d.ts +4 -3
- package/dist/editor/media/MediaLibrary.js +11 -4
- package/dist/editor/media/MediaLibraryBody.d.ts +3 -3
- package/dist/editor/media/MediaLibraryBody.js +195 -80
- package/dist/editor/media/MediaLibrarySkeleton.d.ts +6 -0
- package/dist/editor/media/MediaLibrarySkeleton.js +14 -0
- package/dist/editor/media/crop-math.d.ts +3 -4
- package/dist/editor/media/crop-math.js +11 -22
- package/dist/editor/media/editor-image-src.d.ts +8 -0
- package/dist/editor/media/editor-image-src.js +10 -0
- package/dist/editor/media/format-bytes.d.ts +2 -0
- package/dist/editor/media/format-bytes.js +23 -0
- package/dist/editor/media/media-library-prefs.d.ts +23 -0
- package/dist/editor/media/media-library-prefs.js +49 -0
- package/dist/editor/media/media-library-view.d.ts +34 -0
- package/dist/editor/media/media-library-view.js +40 -0
- package/dist/editor/media/useAssetLibrary.d.ts +30 -0
- package/dist/editor/media/useAssetLibrary.js +126 -0
- package/dist/editor/media/useStableAssetOrder.d.ts +11 -0
- package/dist/editor/media/useStableAssetOrder.js +37 -0
- package/dist/editor/media/useThumbnailFailure.d.ts +6 -0
- package/dist/editor/media/useThumbnailFailure.js +16 -0
- package/dist/editor/permission-manager/GroupSelector.js +2 -2
- package/dist/editor/permission-manager/PermissionEditor.d.ts +1 -1
- package/dist/editor/permission-manager/PermissionEditor.js +15 -4
- package/dist/editor/permission-manager/PermissionLevelBadge.js +1 -1
- package/dist/editor/permission-manager/PermissionTree.d.ts +1 -1
- package/dist/editor/permission-manager/UserSelector.d.ts +1 -1
- package/dist/editor/permission-manager/UserSelector.js +3 -3
- package/dist/editor/permission-manager/index.js +12 -3
- package/dist/editor/permission-manager/types.d.ts +5 -2
- package/dist/editor/platform.d.ts +3 -0
- package/dist/editor/platform.js +9 -0
- package/dist/editor/preview-asset-base.d.ts +9 -0
- package/dist/editor/preview-asset-base.js +17 -0
- package/dist/editor/preview-bridge.d.ts +51 -27
- package/dist/editor/preview-bridge.js +103 -144
- package/dist/editor/preview-marks.d.ts +15 -0
- package/dist/editor/preview-marks.js +74 -0
- package/dist/editor/preview-path.d.ts +12 -0
- package/dist/editor/preview-path.js +45 -1
- package/dist/editor/preview-scale.d.ts +27 -0
- package/dist/editor/preview-scale.js +34 -0
- package/dist/editor/raw-asset-base.d.ts +5 -0
- package/dist/editor/raw-asset-base.js +14 -0
- package/dist/editor/relative-time.d.ts +4 -4
- package/dist/editor/relative-time.js +16 -8
- package/dist/editor/schema-editor/CollectionEditor.d.ts +20 -3
- package/dist/editor/schema-editor/CollectionEditor.js +361 -62
- package/dist/editor/schema-editor/EntryTypeEditor.d.ts +5 -1
- package/dist/editor/schema-editor/EntryTypeEditor.js +11 -6
- package/dist/editor/schema-editor/collection-draft.d.ts +22 -0
- package/dist/editor/schema-editor/collection-draft.js +40 -0
- package/dist/editor/schema-editor/index.d.ts +1 -1
- package/dist/editor/schema-label.d.ts +10 -0
- package/dist/editor/schema-label.js +17 -0
- package/dist/editor/settings-conflict.d.ts +5 -0
- package/dist/editor/settings-conflict.js +8 -0
- package/dist/editor/shell/ActivityRail.d.ts +37 -0
- package/dist/editor/shell/ActivityRail.js +91 -0
- package/dist/editor/shell/EditorShell.d.ts +17 -0
- package/dist/editor/shell/EditorShell.js +31 -0
- package/dist/editor/shell/PaneLayout.d.ts +28 -0
- package/dist/editor/shell/PaneLayout.js +116 -0
- package/dist/editor/shell/SidePanelHost.d.ts +35 -0
- package/dist/editor/shell/SidePanelHost.js +184 -0
- package/dist/editor/shell/TopBar.d.ts +12 -0
- package/dist/editor/shell/TopBar.js +14 -0
- package/dist/editor/shell/host-chrome.d.ts +16 -0
- package/dist/editor/shell/host-chrome.js +69 -0
- package/dist/editor/slug.d.ts +16 -0
- package/dist/editor/slug.js +43 -0
- package/dist/editor/theme.d.ts +2 -1
- package/dist/editor/theme.js +314 -13
- package/dist/editor/unanswered.d.ts +17 -0
- package/dist/editor/unanswered.js +26 -0
- package/dist/editor/unavailable-entry-type.d.ts +20 -0
- package/dist/editor/unavailable-entry-type.js +28 -0
- package/dist/editor/undo-removal.d.ts +57 -0
- package/dist/editor/undo-removal.js +163 -0
- package/dist/editor/user-display.d.ts +4 -0
- package/dist/editor/user-display.js +5 -0
- package/dist/editor/utils/confirm-modal.d.ts +8 -0
- package/dist/editor/utils/confirm-modal.js +12 -0
- package/dist/editor/utils/editor-errors.d.ts +19 -0
- package/dist/editor/utils/editor-errors.js +32 -0
- package/dist/editor/utils/focus-return.d.ts +56 -0
- package/dist/editor/utils/focus-return.js +106 -0
- package/dist/entry-link-resolver.d.ts +11 -1
- package/dist/entry-link-resolver.js +65 -5
- package/dist/entry-schema-registry.d.ts +3 -3
- package/dist/entry-schema-registry.js +7 -4
- package/dist/entry-schema.d.ts +49 -3
- package/dist/entry-schema.js +18 -0
- package/dist/git-manager.d.ts +172 -10
- package/dist/git-manager.js +449 -107
- package/dist/github-service.d.ts +39 -2
- package/dist/github-service.js +101 -7
- package/dist/http/handler.js +74 -9
- package/dist/http/types.d.ts +2 -0
- package/dist/http/worker-not-ready.d.ts +9 -4
- package/dist/http/worker-not-ready.js +59 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/item-keys.d.ts +46 -0
- package/dist/item-keys.js +235 -0
- package/dist/operating-mode/editor-mode-check.d.ts +15 -0
- package/dist/operating-mode/editor-mode-check.js +24 -0
- package/dist/operating-mode/mode-env.d.ts +13 -14
- package/dist/operating-mode/mode-env.js +13 -14
- package/dist/operating-mode/types.d.ts +2 -2
- package/dist/paths/branch.d.ts +0 -1
- package/dist/paths/branch.js +1 -8
- package/dist/paths/index.d.ts +1 -1
- package/dist/paths/index.js +1 -1
- package/dist/paths/validation.js +0 -2
- package/dist/preview.d.ts +8 -0
- package/dist/preview.js +7 -0
- package/dist/reference-resolver.js +1 -0
- package/dist/resolve-canopy-user.d.ts +1 -1
- package/dist/resolve-canopy-user.js +1 -1
- package/dist/schema/meta-loader.d.ts +18 -8
- package/dist/schema/meta-loader.js +42 -9
- package/dist/schema/registry-fingerprint.d.ts +14 -0
- package/dist/schema/registry-fingerprint.js +63 -0
- package/dist/schema/resolver.d.ts +7 -4
- package/dist/schema/resolver.js +7 -6
- package/dist/schema/schema-store.d.ts +7 -10
- package/dist/schema/schema-store.js +13 -11
- package/dist/schema/schema-unavailable-error.d.ts +11 -0
- package/dist/schema/schema-unavailable-error.js +15 -0
- package/dist/schema/types.d.ts +22 -0
- package/dist/schema-registry-record.d.ts +35 -0
- package/dist/schema-registry-record.js +134 -0
- package/dist/server.d.ts +79 -9
- package/dist/server.js +62 -8
- package/dist/services.d.ts +33 -5
- package/dist/services.js +155 -37
- package/dist/settings-workspace.d.ts +23 -3
- package/dist/settings-workspace.js +159 -45
- package/dist/stamp-on-publish.d.ts +36 -0
- package/dist/stamp-on-publish.js +71 -0
- package/dist/static/index.d.ts +58 -5
- package/dist/static/index.js +133 -3
- package/dist/static/seo.d.ts +5 -5
- package/dist/static/seo.js +5 -5
- package/dist/submission-attribution.d.ts +8 -0
- package/dist/submission-attribution.js +22 -0
- package/dist/system-users.d.ts +12 -0
- package/dist/system-users.js +12 -0
- package/dist/task-queue/cms-task-queue.d.ts +1 -1
- package/dist/task-queue/cms-task-queue.js +1 -1
- package/dist/task-queue/index.d.ts +1 -1
- package/dist/task-queue/index.js +1 -1
- package/dist/task-queue/task-queue.d.ts +6 -0
- package/dist/task-queue/task-queue.js +29 -0
- package/dist/task-queue/worker-status.d.ts +35 -9
- package/dist/task-queue/worker-status.js +84 -17
- package/dist/types.d.ts +90 -9
- package/dist/url-collision.js +3 -3
- package/dist/url-exclusivity-fixtures.d.ts +8 -1
- package/dist/url-exclusivity-fixtures.js +11 -1
- package/dist/user.js +2 -1
- package/dist/utils/atomic-write.js +2 -1
- package/dist/utils/base-branch.d.ts +13 -0
- package/dist/utils/base-branch.js +23 -0
- package/dist/utils/content-serialize.d.ts +15 -7
- package/dist/utils/content-serialize.js +353 -51
- package/dist/utils/content-write-lock.d.ts +6 -1
- package/dist/utils/content-write-lock.js +21 -6
- package/dist/utils/debug.d.ts +1 -1
- package/dist/utils/debug.js +5 -3
- package/dist/utils/error.js +13 -2
- package/dist/utils/escape-text.d.ts +7 -0
- package/dist/utils/escape-text.js +27 -0
- package/dist/utils/fs.d.ts +12 -4
- package/dist/utils/fs.js +18 -5
- package/dist/utils/git.d.ts +21 -1
- package/dist/utils/git.js +63 -8
- package/dist/utils/json-source-splice.d.ts +14 -0
- package/dist/utils/json-source-splice.js +120 -0
- package/dist/utils/markdown-body-splice.d.ts +39 -0
- package/dist/utils/markdown-body-splice.js +421 -0
- package/dist/utils/occ-json-write.js +18 -12
- package/dist/utils/provision-log.d.ts +25 -0
- package/dist/utils/provision-log.js +49 -0
- package/dist/utils/provisioning-lock.d.ts +32 -1
- package/dist/utils/provisioning-lock.js +78 -32
- package/dist/utils/sanitize-href.d.ts +9 -23
- package/dist/utils/sanitize-href.js +14 -28
- package/dist/utils/title-field.d.ts +10 -0
- package/dist/utils/title-field.js +47 -0
- package/dist/utils/yaml-source-splice.d.ts +58 -0
- package/dist/utils/yaml-source-splice.js +515 -0
- package/dist/validation/block-structural-keys.d.ts +1 -1
- package/dist/validation/block-structural-keys.js +1 -1
- package/dist/validation/deletion-checker.d.ts +21 -29
- package/dist/validation/deletion-checker.js +41 -117
- package/dist/validation/entry-validator.d.ts +6 -10
- package/dist/validation/entry-validator.js +19 -26
- package/dist/validation/field-traversal.d.ts +22 -0
- package/dist/validation/field-traversal.js +39 -8
- package/dist/validation/markdown-safety.d.ts +68 -0
- package/dist/validation/markdown-safety.js +596 -0
- package/dist/validation/mdx-allowlist.d.ts +55 -0
- package/dist/validation/mdx-allowlist.js +183 -0
- package/dist/validation/reference-validator.d.ts +2 -0
- package/dist/validation/reference-validator.js +3 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/branch-policy.d.ts +124 -0
- package/dist/worker/branch-policy.js +243 -0
- package/dist/worker/bundle-header.d.ts +117 -0
- package/dist/worker/bundle-header.js +253 -0
- package/dist/worker/cms-worker.d.ts +236 -142
- package/dist/worker/cms-worker.js +772 -285
- package/dist/worker/gateway-egress.d.ts +43 -0
- package/dist/worker/gateway-egress.js +209 -0
- package/dist/worker/gateway-instance.d.ts +42 -0
- package/dist/worker/gateway-instance.js +129 -0
- package/dist/worker/git-process.d.ts +81 -0
- package/dist/worker/git-process.js +234 -0
- package/dist/worker/git-sync.d.ts +34 -17
- package/dist/worker/git-sync.js +394 -131
- package/dist/worker/github-auth.d.ts +9 -9
- package/dist/worker/github-auth.js +13 -15
- package/dist/worker/github-gateway-http.d.ts +62 -0
- package/dist/worker/github-gateway-http.js +977 -0
- package/dist/worker/github-gateway-wire.d.ts +590 -0
- package/dist/worker/github-gateway-wire.js +488 -0
- package/dist/worker/github-gateway.d.ts +238 -0
- package/dist/worker/github-gateway.js +726 -0
- package/dist/worker/github-mirror-upkeep.d.ts +75 -0
- package/dist/worker/github-mirror-upkeep.js +266 -0
- package/dist/worker/github-mirror.d.ts +364 -0
- package/dist/worker/github-mirror.js +1030 -0
- package/dist/worker/github-transfer.d.ts +56 -0
- package/dist/worker/github-transfer.js +444 -0
- package/dist/worker/history-rewrite.d.ts +4 -5
- package/dist/worker/history-rewrite.js +12 -17
- package/dist/worker/provisioned-workspace.d.ts +5 -5
- package/dist/worker/provisioned-workspace.js +5 -5
- package/dist/worker/rebase.d.ts +1 -1
- package/dist/worker/rebase.js +58 -54
- package/dist/worker/remote-git-maintenance.d.ts +3 -0
- package/dist/worker/remote-git-maintenance.js +12 -0
- package/dist/worker/schema-gate.d.ts +49 -0
- package/dist/worker/schema-gate.js +226 -0
- package/dist/worker/self-checks.d.ts +107 -0
- package/dist/worker/self-checks.js +358 -0
- package/dist/worker/shared-repo-git.d.ts +96 -0
- package/dist/worker/shared-repo-git.js +459 -0
- package/dist/worker/sparse-cone.d.ts +20 -0
- package/dist/worker/sparse-cone.js +136 -0
- package/dist/worker/stale-mirror.d.ts +82 -0
- package/dist/worker/stale-mirror.js +130 -0
- package/dist/worker/task-runner.d.ts +5 -3
- package/dist/worker/task-runner.js +287 -186
- package/dist/worker/worker-context.d.ts +36 -37
- package/package.json +35 -7
- package/dist/editor/EditorPanes.d.ts +0 -10
- package/dist/editor/EditorPanes.js +0 -98
- package/dist/editor/components/EditorFooter.d.ts +0 -11
- package/dist/editor/components/EditorFooter.js +0 -9
- package/dist/editor/components/EditorSidebar.d.ts +0 -67
- package/dist/editor/components/EditorSidebar.js +0 -22
|
@@ -12,15 +12,17 @@
|
|
|
12
12
|
* })` -- see the comment on `fetchBranches` for why it doesn't just call
|
|
13
13
|
* `mutate()` to revalidate.
|
|
14
14
|
*/
|
|
15
|
-
import useSWR from 'swr';
|
|
15
|
+
import useSWR, { useSWRConfig } from 'swr';
|
|
16
16
|
import { isNonApiResponse } from '../../api/client.js';
|
|
17
|
+
import { seedUserProfiles } from './useUserMetadata.js';
|
|
17
18
|
/** Cache key for the branches list. */
|
|
18
19
|
export const BRANCHES_KEY = 'canopy:branches';
|
|
19
20
|
/**
|
|
20
|
-
* Fetch the branches list
|
|
21
|
-
*
|
|
21
|
+
* Fetch the branches list, writing the owners it names into the user-metadata cache before the
|
|
22
|
+
* listing lands, so owner badges render named. Exported for direct testing and for the imperative
|
|
23
|
+
* reload path.
|
|
22
24
|
*/
|
|
23
|
-
export async function fetchBranches(apiClient) {
|
|
25
|
+
export async function fetchBranches(apiClient, swr) {
|
|
24
26
|
const result = await apiClient.branches.list();
|
|
25
27
|
if (result.status === 404 && !isNonApiResponse(result)) {
|
|
26
28
|
// No branch endpoint available; stay branchless rather than erroring --
|
|
@@ -31,6 +33,7 @@ export async function fetchBranches(apiClient) {
|
|
|
31
33
|
if (!result.ok) {
|
|
32
34
|
throw new Error(result.error ?? `Failed to load branches: ${result.status}`);
|
|
33
35
|
}
|
|
36
|
+
await seedUserProfiles(swr, result.data?.users ?? []);
|
|
34
37
|
return {
|
|
35
38
|
branches: result.data?.branches ?? [],
|
|
36
39
|
defaultBranch: result.data?.defaultBranch,
|
|
@@ -69,7 +72,8 @@ export function hasInFlightBranch(data) {
|
|
|
69
72
|
* `refreshInterval`, and narrower than the pre-SWR behavior it replaces.
|
|
70
73
|
*/
|
|
71
74
|
export function useBranchesData(apiClient) {
|
|
72
|
-
|
|
75
|
+
const { cache, mutate } = useSWRConfig();
|
|
76
|
+
return useSWR(BRANCHES_KEY, () => fetchBranches(apiClient, { cache, mutate }), {
|
|
73
77
|
refreshInterval: (data) => hasInFlightBranch(data) ? IN_FLIGHT_POLL_MS : 0,
|
|
74
78
|
});
|
|
75
79
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CommentThread } from '../../comment-store.js';
|
|
2
|
+
import type { UserSearchResult } from '../../auth/types.js';
|
|
2
3
|
import type { EditorEntry } from '../Editor.js';
|
|
3
4
|
export interface UseCommentSystemOptions {
|
|
4
5
|
branchName: string;
|
|
@@ -8,10 +9,14 @@ export interface UseCommentSystemOptions {
|
|
|
8
9
|
canResolveComments: boolean;
|
|
9
10
|
setSelectedPath: (id: string) => void;
|
|
10
11
|
setBranchManagerOpen: (open: boolean) => void;
|
|
12
|
+
/** Uncovers the form before anything here focuses one of its fields. */
|
|
13
|
+
onRevealForm?: () => void;
|
|
11
14
|
onCommentsChange?: (comments: CommentThread[]) => void;
|
|
12
15
|
}
|
|
13
16
|
export interface UseCommentSystemReturn {
|
|
14
17
|
comments: CommentThread[];
|
|
18
|
+
/** Resolves a user from the seeded cache, without email or a request (`useSeededUserResolver`). */
|
|
19
|
+
getCommentUser: (userId: string) => Promise<UserSearchResult | null>;
|
|
15
20
|
focusedFieldPath: string | undefined;
|
|
16
21
|
setFocusedFieldPath: (path: string | undefined) => void;
|
|
17
22
|
highlightThreadId: string | undefined;
|
|
@@ -30,13 +35,20 @@ export interface UseCommentSystemReturn {
|
|
|
30
35
|
} | null) => void;
|
|
31
36
|
activeThreads: CommentThread[];
|
|
32
37
|
activeContextLabel: string;
|
|
33
|
-
|
|
38
|
+
/** `itemKeys`: for a new field thread, the keys of the list items on `canopyPath`. */
|
|
39
|
+
handleAddComment: (text: string, type: 'field' | 'entry' | 'branch', entryPath?: string, canopyPath?: string, threadId?: string, itemKeys?: string[]) => Promise<void>;
|
|
34
40
|
handleResolveThread: (threadId: string) => Promise<void>;
|
|
35
|
-
loadComments: (branch: string) => Promise<
|
|
41
|
+
loadComments: (branch: string) => Promise<CommentThread[] | undefined>;
|
|
36
42
|
handleJumpToField: (entryPath: string, canopyPath: string, threadId: string) => void;
|
|
37
43
|
handleJumpToEntry: (entryPath: string, threadId: string) => void;
|
|
38
44
|
handleJumpToBranch: (threadId: string) => void;
|
|
39
45
|
}
|
|
46
|
+
/** @internal Exported for tests. */
|
|
47
|
+
export declare const COMMENT_NOT_ADDED = "Couldn't add the comment. Try again.";
|
|
48
|
+
/** @internal Exported for tests. */
|
|
49
|
+
export declare const COMMENT_MAY_BE_ADDED = "The server didn't answer, and the comments don't show yours yet, but it may still be posted. Wait a moment and check before sending it again.";
|
|
50
|
+
/** @internal Exported for tests. */
|
|
51
|
+
export declare const THREAD_NOT_RESOLVED = "Couldn't resolve the thread. Try again.";
|
|
40
52
|
/**
|
|
41
53
|
* Custom hook for managing the comment system.
|
|
42
54
|
*/
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import { useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import { useSWRConfig } from 'swr';
|
|
3
|
-
import {
|
|
4
|
-
import { normalizeCanopyPath } from '../canopy-path.js';
|
|
3
|
+
import { findFieldTarget, whenRevealed } from '../field-target.js';
|
|
5
4
|
import { useApiClient } from '../context/index.js';
|
|
5
|
+
import { isGatewayFailure, isUnanswered, MayHaveLandedError } from '../unanswered.js';
|
|
6
6
|
import { resolveMessageOrigin } from '../preview-bridge.js';
|
|
7
7
|
import { isSamePreviewPath } from '../preview-path.js';
|
|
8
|
-
import { commentsKey,
|
|
8
|
+
import { commentsKey, fetchCommentsSeedingUsers, useCommentsData } from './useCommentsData.js';
|
|
9
|
+
import { useSeededUserResolver } from './useUserMetadata.js';
|
|
10
|
+
/** @internal Exported for tests. */
|
|
11
|
+
export const COMMENT_NOT_ADDED = "Couldn't add the comment. Try again.";
|
|
12
|
+
/** @internal Exported for tests. */
|
|
13
|
+
export const COMMENT_MAY_BE_ADDED = "The server didn't answer, and the comments don't show yours yet, but it may still be posted. Wait a moment and check before sending it again.";
|
|
14
|
+
/** @internal Exported for tests. */
|
|
15
|
+
export const THREAD_NOT_RESOLVED = "Couldn't resolve the thread. Try again.";
|
|
9
16
|
/**
|
|
10
17
|
* Custom hook for managing the comment system.
|
|
11
18
|
*/
|
|
12
19
|
export function useCommentSystem(options) {
|
|
13
20
|
const apiClient = useApiClient();
|
|
14
|
-
const { mutate: globalMutate } = useSWRConfig();
|
|
21
|
+
const { cache, mutate: globalMutate } = useSWRConfig();
|
|
15
22
|
const [focusedFieldPath, setFocusedFieldPath] = useState(undefined);
|
|
16
23
|
const [highlightThreadId, setHighlightThreadId] = useState(undefined);
|
|
17
24
|
const [commentsPanelOpen, setCommentsPanelOpen] = useState(false);
|
|
@@ -21,64 +28,81 @@ export function useCommentSystem(options) {
|
|
|
21
28
|
// Mode's double effect invoke collapses to a single request). Switching
|
|
22
29
|
// branches re-keys automatically, so no manual branch-change effect is
|
|
23
30
|
// needed.
|
|
24
|
-
const { data: commentsData } = useCommentsData(apiClient, options.branchName);
|
|
31
|
+
const { data: commentsData, error: commentsError } = useCommentsData(apiClient, options.branchName);
|
|
25
32
|
const comments = commentsData?.threads ?? [];
|
|
33
|
+
const getCommentUser = useSeededUserResolver();
|
|
26
34
|
// Deliberately omits `options.onCommentsChange` from the deps: it's a
|
|
27
35
|
// stable setState passthrough, and this file is plain .ts (not .tsx), so
|
|
28
36
|
// the react-hooks/exhaustive-deps rule isn't active here anyway --
|
|
29
37
|
// including it would refire this on every Editor.tsx render regardless.
|
|
38
|
+
// A branch whose comments never loaded reports none, not the previous branch's.
|
|
30
39
|
useEffect(() => {
|
|
31
40
|
if (commentsData)
|
|
32
41
|
options.onCommentsChange?.(commentsData.threads);
|
|
33
|
-
|
|
42
|
+
else if (commentsError)
|
|
43
|
+
options.onCommentsChange?.([]);
|
|
44
|
+
}, [commentsData, commentsError]);
|
|
34
45
|
// Explicit reload: always issues a fresh, independent fetch (raw call, not
|
|
35
46
|
// SWR's `mutate()` revalidate path) so a caller requesting a reload right
|
|
36
47
|
// after mount isn't coalesced against the still-in-flight automatic load
|
|
37
48
|
// -- then writes the result into the shared cache so useCommentsData's
|
|
38
49
|
// bound hook (and the effect above) pick it up.
|
|
50
|
+
// A failed reload logs and keeps the threads already shown. Resolves to the reloaded threads.
|
|
39
51
|
const loadComments = async (branch) => {
|
|
40
52
|
if (!branch)
|
|
41
|
-
return;
|
|
42
|
-
|
|
53
|
+
return undefined;
|
|
54
|
+
let fresh;
|
|
55
|
+
try {
|
|
56
|
+
fresh = await fetchCommentsSeedingUsers(apiClient, { cache, mutate: globalMutate }, branch);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
console.error('Failed to load comments:', err);
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
43
62
|
await globalMutate(commentsKey(branch), fresh, { revalidate: false });
|
|
63
|
+
return fresh.threads;
|
|
44
64
|
};
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
// Both reject on failure, so the caller keeps the person's text and shows the error where they
|
|
66
|
+
// wrote it. Success shows itself in the thread, so it has no toast.
|
|
67
|
+
const handleAddComment = async (text, type, entryPath, canopyPath, threadId, itemKeys) => {
|
|
68
|
+
const branch = options.branchName;
|
|
69
|
+
if (!branch)
|
|
47
70
|
return;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
// What was on screen at send, so only a comment that is new since can count as this one.
|
|
72
|
+
const loaded = commentsData !== undefined;
|
|
73
|
+
const shownComments = new Set(comments.flatMap((t) => t.comments.map((c) => c.id)));
|
|
74
|
+
const isThis = (c) => !shownComments.has(c.id) && c.userId === options.currentUser && c.text === text;
|
|
75
|
+
const result = await apiClient.comments
|
|
76
|
+
.add({ branch }, { text, threadId, type, entryPath, canopyPath, itemKeys })
|
|
77
|
+
.catch((err) => (isUnanswered(err) ? 'unanswered' : null));
|
|
78
|
+
if (result === 'unanswered' || (result && isGatewayFailure(result))) {
|
|
79
|
+
// Landed, it is a new comment of theirs: in the thread replied to, or opening one here.
|
|
80
|
+
const reloaded = await loadComments(branch);
|
|
81
|
+
const posted = loaded &&
|
|
82
|
+
reloaded?.some((t) => threadId
|
|
83
|
+
? t.id === threadId && t.comments.some(isThis)
|
|
84
|
+
: t.type === type &&
|
|
85
|
+
t.entryPath === entryPath &&
|
|
86
|
+
t.canopyPath === canopyPath &&
|
|
87
|
+
t.comments[0] !== undefined &&
|
|
88
|
+
isThis(t.comments[0]));
|
|
89
|
+
if (posted)
|
|
90
|
+
return;
|
|
91
|
+
throw new MayHaveLandedError(COMMENT_MAY_BE_ADDED);
|
|
64
92
|
}
|
|
93
|
+
if (!result?.ok)
|
|
94
|
+
throw new Error(COMMENT_NOT_ADDED);
|
|
95
|
+
await loadComments(branch);
|
|
65
96
|
};
|
|
66
97
|
const handleResolveThread = async (threadId) => {
|
|
67
98
|
if (!options.branchName)
|
|
68
99
|
return;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
throw new Error('Failed to resolve thread');
|
|
76
|
-
await loadComments(options.branchName);
|
|
77
|
-
notifications.show({ message: 'Thread resolved', color: 'green' });
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
notifications.show({ message: 'Failed to resolve thread', color: 'red' });
|
|
81
|
-
}
|
|
100
|
+
const result = await apiClient.comments
|
|
101
|
+
.resolve({ branch: options.branchName, threadId })
|
|
102
|
+
.catch(() => null);
|
|
103
|
+
if (!result?.ok)
|
|
104
|
+
throw new Error(THREAD_NOT_RESOLVED);
|
|
105
|
+
await loadComments(options.branchName);
|
|
82
106
|
};
|
|
83
107
|
// Compute active comment threads for the thread panel
|
|
84
108
|
const activeThreads = useMemo(() => {
|
|
@@ -87,7 +111,8 @@ export function useCommentSystem(options) {
|
|
|
87
111
|
if (activeCommentContext.type === 'field' && activeCommentContext.canopyPath) {
|
|
88
112
|
return comments.filter((t) => t.type === 'field' &&
|
|
89
113
|
t.entryPath === options.selectedPath &&
|
|
90
|
-
t.canopyPath === activeCommentContext.canopyPath
|
|
114
|
+
t.canopyPath === activeCommentContext.canopyPath &&
|
|
115
|
+
!t.onRemovedItem);
|
|
91
116
|
}
|
|
92
117
|
else if (activeCommentContext.type === 'entry') {
|
|
93
118
|
return comments.filter((t) => t.type === 'entry' && t.entryPath === options.selectedPath);
|
|
@@ -138,23 +163,19 @@ export function useCommentSystem(options) {
|
|
|
138
163
|
currentPath === undefined ||
|
|
139
164
|
!isSamePreviewPath(msg.entryPath, currentPath)))
|
|
140
165
|
return;
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
:
|
|
145
|
-
if (target) {
|
|
146
|
-
target.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
166
|
+
const found = typeof msg.fieldPath === 'string' ? findFieldTarget(msg.fieldPath) : undefined;
|
|
167
|
+
if (found) {
|
|
168
|
+
const target = found.element;
|
|
169
|
+
whenRevealed(target, () => target.scrollIntoView({ behavior: 'smooth', block: 'center' }));
|
|
147
170
|
const previous = target.style.boxShadow;
|
|
148
171
|
target.style.boxShadow = '0 0 0 3px rgba(79, 70, 229, 0.35)';
|
|
149
172
|
later(() => {
|
|
150
173
|
target.style.boxShadow = previous;
|
|
151
174
|
}, 1200);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
later(() => setFocusedFieldPath(undefined), 100);
|
|
157
|
-
}
|
|
175
|
+
options.onRevealForm?.();
|
|
176
|
+
// Cleared shortly after, once FieldWrapper has seen it and scrolled to the field.
|
|
177
|
+
setFocusedFieldPath(found.path);
|
|
178
|
+
later(() => setFocusedFieldPath(undefined), 100);
|
|
158
179
|
}
|
|
159
180
|
};
|
|
160
181
|
window.addEventListener('message', handleFocus);
|
|
@@ -172,10 +193,11 @@ export function useCommentSystem(options) {
|
|
|
172
193
|
options.setSelectedPath(entryPath);
|
|
173
194
|
}
|
|
174
195
|
window.setTimeout(() => {
|
|
175
|
-
const
|
|
176
|
-
if (
|
|
177
|
-
|
|
196
|
+
const target = findFieldTarget(canopyPath)?.element;
|
|
197
|
+
if (target) {
|
|
198
|
+
whenRevealed(target, () => target.scrollIntoView({ behavior: 'smooth', block: 'center' }));
|
|
178
199
|
}
|
|
200
|
+
options.onRevealForm?.();
|
|
179
201
|
setFocusedFieldPath(canopyPath);
|
|
180
202
|
setHighlightThreadId(threadId);
|
|
181
203
|
window.setTimeout(() => {
|
|
@@ -194,6 +216,7 @@ export function useCommentSystem(options) {
|
|
|
194
216
|
if (formElement) {
|
|
195
217
|
formElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
196
218
|
}
|
|
219
|
+
options.onRevealForm?.();
|
|
197
220
|
setHighlightThreadId(threadId);
|
|
198
221
|
window.setTimeout(() => {
|
|
199
222
|
setHighlightThreadId(undefined);
|
|
@@ -209,6 +232,7 @@ export function useCommentSystem(options) {
|
|
|
209
232
|
};
|
|
210
233
|
return {
|
|
211
234
|
comments,
|
|
235
|
+
getCommentUser,
|
|
212
236
|
focusedFieldPath,
|
|
213
237
|
setFocusedFieldPath,
|
|
214
238
|
highlightThreadId,
|
|
@@ -6,23 +6,27 @@
|
|
|
6
6
|
* its own branch-keyed effect. See useBranchesData.ts for the same pattern
|
|
7
7
|
* applied to the branches list.
|
|
8
8
|
*/
|
|
9
|
-
import { type SWRResponse } from 'swr';
|
|
9
|
+
import { type Cache, type ScopedMutator, type SWRResponse } from 'swr';
|
|
10
10
|
import type { ApiClient } from '../context/index.js';
|
|
11
11
|
import type { CommentThread } from '../../comment-store.js';
|
|
12
|
+
import type { UserProfile } from '../../auth/types.js';
|
|
12
13
|
/** Cache key for a branch's comment threads. */
|
|
13
14
|
export declare const commentsKey: (branch: string) => string;
|
|
14
15
|
export interface CommentsData {
|
|
15
16
|
threads: CommentThread[];
|
|
17
|
+
/** Who wrote or resolved `threads`: name and avatar, never email. */
|
|
18
|
+
users: UserProfile[];
|
|
16
19
|
}
|
|
17
20
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* failure rather than surfacing an error state (comments have no error UI).
|
|
21
|
-
* Exported for direct testing and for the imperative reload path.
|
|
21
|
+
* {@link fetchComments}, with the users it names written into the user-metadata cache before the
|
|
22
|
+
* threads that show them land, so their badges render named.
|
|
22
23
|
*/
|
|
23
|
-
export declare function
|
|
24
|
+
export declare function fetchCommentsSeedingUsers(apiClient: Pick<ApiClient, 'comments'>, swr: {
|
|
25
|
+
cache: Cache;
|
|
26
|
+
mutate: ScopedMutator;
|
|
27
|
+
}, branch: string): Promise<CommentsData>;
|
|
24
28
|
/**
|
|
25
29
|
* SWR-backed read of a branch's comment threads. `branch` may be empty
|
|
26
30
|
* (branchless start), in which case fetching is disabled entirely (null key).
|
|
27
31
|
*/
|
|
28
|
-
export declare function useCommentsData(apiClient: Pick<ApiClient, 'comments'>, branch: string): SWRResponse<CommentsData,
|
|
32
|
+
export declare function useCommentsData(apiClient: Pick<ApiClient, 'comments'>, branch: string): SWRResponse<CommentsData, unknown>;
|
|
@@ -7,33 +7,34 @@
|
|
|
7
7
|
* its own branch-keyed effect. See useBranchesData.ts for the same pattern
|
|
8
8
|
* applied to the branches list.
|
|
9
9
|
*/
|
|
10
|
-
import useSWR from 'swr';
|
|
10
|
+
import useSWR, { useSWRConfig } from 'swr';
|
|
11
|
+
import { seedUserProfiles } from './useUserMetadata.js';
|
|
11
12
|
/** Cache key for a branch's comment threads. */
|
|
12
13
|
export const commentsKey = (branch) => `canopy:comments:${branch}`;
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* failure rather than surfacing an error state (comments have no error UI).
|
|
17
|
-
* Exported for direct testing and for the imperative reload path.
|
|
15
|
+
* A branch's comment threads. Rejects when they can't be read, so a failed reload leaves the
|
|
16
|
+
* threads already shown in place rather than emptying them.
|
|
18
17
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
18
|
+
async function fetchComments(apiClient, branch) {
|
|
19
|
+
const result = await apiClient.comments.list({ branch });
|
|
20
|
+
if (!result.ok)
|
|
21
|
+
throw new Error(`Failed to load comments (HTTP ${result.status})`);
|
|
22
|
+
return { threads: result.data?.threads ?? [], users: result.data?.users ?? [] };
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* {@link fetchComments}, with the users it names written into the user-metadata cache before the
|
|
26
|
+
* threads that show them land, so their badges render named.
|
|
27
|
+
*/
|
|
28
|
+
export async function fetchCommentsSeedingUsers(apiClient, swr, branch) {
|
|
29
|
+
const data = await fetchComments(apiClient, branch);
|
|
30
|
+
await seedUserProfiles(swr, data.users);
|
|
31
|
+
return data;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* SWR-backed read of a branch's comment threads. `branch` may be empty
|
|
35
35
|
* (branchless start), in which case fetching is disabled entirely (null key).
|
|
36
36
|
*/
|
|
37
37
|
export function useCommentsData(apiClient, branch) {
|
|
38
|
-
|
|
38
|
+
const { cache, mutate } = useSWRConfig();
|
|
39
|
+
return useSWR(branch ? commentsKey(branch) : null, () => fetchCommentsSeedingUsers(apiClient, { cache, mutate }, branch), { onError: (err) => console.error('Failed to load comments:', err) });
|
|
39
40
|
}
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
import type { EditorEntry } from '../Editor.js';
|
|
2
2
|
import type { LogicalPath } from '../../paths/types.js';
|
|
3
3
|
import type { FormValue } from '../FormRenderer.js';
|
|
4
|
+
import type { StampedEntry } from '../../stamp-on-publish.js';
|
|
5
|
+
import { type SaveAllProgress, type SaveAllResult } from './save-all.js';
|
|
6
|
+
/** @internal Exported for tests. */
|
|
7
|
+
export declare const SAVE_TIMED_OUT_MESSAGE = "Save didn't finish, and may not have gone through. Your changes are still here, so save again.";
|
|
8
|
+
/** @internal Exported for tests. Shown when a save may already have landed, until a reload. */
|
|
9
|
+
export declare const SAVE_MAY_HAVE_LANDED_MESSAGE = "Your last save may already have gone through. Before saving again, choose \"Refresh from server\" in the entry's menu, on its name; your unsaved edits will be lost.";
|
|
10
|
+
/** @internal Exported for tests. A save refused because the entry was deleted. */
|
|
11
|
+
export declare const ENTRY_DELETED_MESSAGE = "This entry was deleted since you opened it, so it was not saved. Your changes are still in the form until the content list next refreshes and closes it: choose \"Save as new entry\" to keep them.";
|
|
12
|
+
/** @internal Exported for tests. A save refused because the entry was renamed; the editor has opened it. */
|
|
13
|
+
export declare const ENTRY_RENAMED_MESSAGE = "This entry was renamed since you opened it, so it was not saved. Your changes moved with it and are still in the form: save again to keep them.";
|
|
14
|
+
/** @internal Exported for tests. "Save as new entry" refused because an entry, possibly the user's own earlier attempt, now holds the path. */
|
|
15
|
+
export declare const RECREATE_TAKEN_MESSAGE = "An entry with this entry's name already exists, perhaps from your own earlier attempt, so it was not saved as a new entry. Your changes are still in the form: copy what you want to keep into that entry.";
|
|
16
|
+
/** @internal Exported for tests. The save was refused as gone, and the check for a rename failed. */
|
|
17
|
+
export declare const ENTRY_GONE_UNCHECKED_MESSAGE = "This entry was deleted or renamed since you opened it, so it was not saved, and the editor could not check which. Your changes are still in the form until the content list next refreshes and closes it: copy what you want to keep.";
|
|
18
|
+
/** @internal Exported for tests. "Save as new entry" landed, but the content list does not show it yet. */
|
|
19
|
+
export declare const RECREATED_NOT_LISTED_MESSAGE = "Saved as a new entry, but the content list doesn't show it yet. Reload the page in a moment to open it.";
|
|
20
|
+
/** @internal Exported for tests. "Save as new entry" got no answer. */
|
|
21
|
+
export declare const RECREATE_TIMED_OUT_MESSAGE = "Saving as a new entry may have gone through even though the server didn't answer. Choose \"Save as new entry\" to try again: if it went through, you'll be told an entry with this name already exists.";
|
|
4
22
|
export interface UseDraftManagerOptions {
|
|
5
23
|
branchName: string;
|
|
6
24
|
selectedPath: string;
|
|
@@ -8,6 +26,12 @@ export interface UseDraftManagerOptions {
|
|
|
8
26
|
entries: EditorEntry[];
|
|
9
27
|
initialValues?: Record<string, FormValue>;
|
|
10
28
|
loadEntry: (entry: EditorEntry) => Promise<FormValue>;
|
|
29
|
+
/**
|
|
30
|
+
* Server read that records no OCC token (useEntryManager's `readEntryValue`),
|
|
31
|
+
* for checking restored drafts of unopened entries. Without it they stay
|
|
32
|
+
* unverified and count as dirty.
|
|
33
|
+
*/
|
|
34
|
+
readEntryValue?: (entry: EditorEntry) => Promise<FormValue>;
|
|
11
35
|
saveEntry: (entry: EditorEntry, value: FormValue) => Promise<FormValue>;
|
|
12
36
|
/**
|
|
13
37
|
* The OCC version token currently held for an entry on the branch being
|
|
@@ -17,6 +41,8 @@ export interface UseDraftManagerOptions {
|
|
|
17
41
|
* conflict detection falls back entirely to saveEntry's token check.
|
|
18
42
|
*/
|
|
19
43
|
getEntryVersion?: (contentId: string) => number | undefined;
|
|
44
|
+
/** Holds a version the server moved an entry to itself (useEntryManager's `adoptEntryVersion`). */
|
|
45
|
+
adoptEntryVersion?: (contentId: string, version: number) => void;
|
|
20
46
|
setBusy: (busy: boolean) => void;
|
|
21
47
|
/**
|
|
22
48
|
* Fired (fire-and-forget) after a successful save. Lets callers refresh
|
|
@@ -25,6 +51,23 @@ export interface UseDraftManagerOptions {
|
|
|
25
51
|
* instead of the stale label from the last entries fetch.
|
|
26
52
|
*/
|
|
27
53
|
onSaved?: () => void;
|
|
54
|
+
/** A save was refused for field errors, which the form now shows. */
|
|
55
|
+
onSaveBlocked?: () => void;
|
|
56
|
+
/**
|
|
57
|
+
* Fired when drafts are thrown away for the server's copy: Discard (one entry, or every entry
|
|
58
|
+
* when `contentId` is undefined) and Reload. Anything built on the discarded draft, such as an
|
|
59
|
+
* Undo, no longer applies.
|
|
60
|
+
*/
|
|
61
|
+
onDraftsReset?: (contentId?: string) => void;
|
|
62
|
+
/** Finds an entry a save reported gone under its new name (useEntryManager's `followMovedEntry`). */
|
|
63
|
+
followMovedEntry?: (entry: EditorEntry) => Promise<EditorEntry | undefined>;
|
|
64
|
+
/** Creates a deleted entry again from its draft (useEntryManager's `recreateEntry`). */
|
|
65
|
+
recreateEntry?: (entry: EditorEntry, value: FormValue) => Promise<EditorEntry | undefined>;
|
|
66
|
+
}
|
|
67
|
+
/** The unsaved work a branch-level action would leave behind. `labels` names the entries (it may be shorter than `count`). */
|
|
68
|
+
export interface UnsavedSummary {
|
|
69
|
+
count: number;
|
|
70
|
+
labels: string[];
|
|
28
71
|
}
|
|
29
72
|
export interface UseDraftManagerReturn {
|
|
30
73
|
drafts: Record<string, FormValue>;
|
|
@@ -40,12 +83,39 @@ export interface UseDraftManagerReturn {
|
|
|
40
83
|
label: string;
|
|
41
84
|
}>;
|
|
42
85
|
handleSave: () => Promise<void>;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
86
|
+
/** The entry a single Save is writing, while it is in flight. */
|
|
87
|
+
singleSaving: {
|
|
88
|
+
branch: string;
|
|
89
|
+
contentId: string;
|
|
90
|
+
} | null;
|
|
91
|
+
/** The last Save that landed; its `seq` rises with each, and the Save button says "Saved". */
|
|
92
|
+
lastSaved: {
|
|
93
|
+
branch: string;
|
|
94
|
+
contentId: string;
|
|
95
|
+
seq: number;
|
|
96
|
+
} | null;
|
|
97
|
+
/**
|
|
98
|
+
* Saves every entry with unsaved changes on the branch, one at a time. Undefined when a run or
|
|
99
|
+
* a single Save is already in flight, or the branch changed or the editor unmounted meanwhile.
|
|
100
|
+
*/
|
|
101
|
+
handleSaveAll: () => Promise<SaveAllResult | undefined>;
|
|
102
|
+
/** Set while Save all runs. */
|
|
103
|
+
saveAllProgress: SaveAllProgress | null;
|
|
104
|
+
/** Whether Save all is running now, read at the moment of a click rather than a render. */
|
|
105
|
+
isSaveAllRunning: () => boolean;
|
|
106
|
+
handleDiscardDrafts: (returnFocusTo?: () => HTMLElement | null) => void;
|
|
107
|
+
/** `announce` toasts the discard, for a draft the form isn't showing (a read-only branch's). */
|
|
108
|
+
handleDiscardFileDraft: (returnFocusTo?: () => HTMLElement | null, options?: {
|
|
109
|
+
announce?: boolean;
|
|
110
|
+
}) => void;
|
|
111
|
+
handleReload: (returnFocusTo?: () => HTMLElement | null) => Promise<void>;
|
|
46
112
|
isDirtyForEntry: (entryPath: string) => boolean;
|
|
47
113
|
isSelectedDirty: () => boolean;
|
|
48
114
|
isAnyDirty: () => boolean;
|
|
115
|
+
/** Resolves once restored drafts have been checked against the server (or a read failed), capped so a hung read cannot block. */
|
|
116
|
+
whenDraftsVerified: () => Promise<void>;
|
|
117
|
+
/** `whenDraftsVerified`, then the entries still counted dirty. */
|
|
118
|
+
resolveUnsaved: () => Promise<UnsavedSummary>;
|
|
49
119
|
/**
|
|
50
120
|
* Per-field validation errors for the selected entry, keyed by canonical
|
|
51
121
|
* canopy path (e.g. `blocks[0].title`). Populated when a save is blocked by
|
|
@@ -54,6 +124,10 @@ export interface UseDraftManagerReturn {
|
|
|
54
124
|
* errors disappear as fields are fixed.
|
|
55
125
|
*/
|
|
56
126
|
fieldErrors: Record<string, string>;
|
|
127
|
+
/** True while the last write of drafts to localStorage failed. */
|
|
128
|
+
draftStorageFailed: boolean;
|
|
129
|
+
/** Moves loaded values, tokens and drafts onto the versions a submit's stamps left. */
|
|
130
|
+
applySubmitStamps: (stamped: readonly StampedEntry[]) => void;
|
|
57
131
|
}
|
|
58
132
|
/**
|
|
59
133
|
* Custom hook for managing draft state (localStorage persistence, save/discard).
|