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
|
@@ -4,18 +4,22 @@ import { useEffect, useId, useRef, useState } from 'react';
|
|
|
4
4
|
import { Alert, Button, Group, Stack, Text, TextInput } from '@mantine/core';
|
|
5
5
|
import { Dropzone } from '@mantine/dropzone';
|
|
6
6
|
import { IconAlertCircle, IconPhoto, IconPhotoOff, IconUpload } from '@tabler/icons-react';
|
|
7
|
-
import {
|
|
7
|
+
import { isAssetStoreSrc } from '../../assets/asset-url.js';
|
|
8
8
|
import { useAssetContext } from '../context/index.js';
|
|
9
9
|
import { CropStep } from '../media/CropStep.js';
|
|
10
|
+
import { editorImageSrc } from '../media/editor-image-src.js';
|
|
10
11
|
import { parseAspectRatio } from '../media/crop-math.js';
|
|
11
12
|
import { MediaLibrary } from '../media/MediaLibrary.js';
|
|
12
13
|
import { useAssetUpload } from '../media/useAssetUpload.js';
|
|
13
14
|
import { ACCEPTED_IMAGE_MIME_TYPES, MAX_UPLOAD_BYTES } from '../media/upload-constants.js';
|
|
15
|
+
import { useFieldCommentControl } from '../comments/field-comment-context.js';
|
|
14
16
|
import { FieldDescription, groupDescriptionProps } from './FieldDescription.js';
|
|
17
|
+
import { FieldLabel } from './FieldLabel.js';
|
|
15
18
|
const PREVIEW_WIDTH = 320;
|
|
16
|
-
export const ImageField = ({ id, label, description, value, onChange, aspect, altOptional, dataCanopyField, errors, }) => {
|
|
19
|
+
export const ImageField = ({ id, label, description, value, onChange, aspect, altOptional, dataCanopyField, errors, readOnly = false, onRemoved, }) => {
|
|
17
20
|
const generatedId = useId();
|
|
18
21
|
const inputId = id ?? generatedId;
|
|
22
|
+
const commentControl = useFieldCommentControl(dataCanopyField);
|
|
19
23
|
const { baseUrl } = useAssetContext();
|
|
20
24
|
const upload = useAssetUpload();
|
|
21
25
|
const [pickerOpen, setPickerOpen] = useState(false);
|
|
@@ -28,8 +32,10 @@ export const ImageField = ({ id, label, description, value, onChange, aspect, al
|
|
|
28
32
|
const aspectRatio = parseAspectRatio(aspect);
|
|
29
33
|
const hasValue = !!value?.src;
|
|
30
34
|
const previewSrc = value
|
|
31
|
-
?
|
|
35
|
+
? editorImageSrc(value.src, baseUrl, { width: PREVIEW_WIDTH, crop: value.crop })
|
|
32
36
|
: undefined;
|
|
37
|
+
// `assetUrl` never applies a crop to a src outside the asset store, so one stored there never renders.
|
|
38
|
+
const canCrop = aspectRatio !== undefined && !!value && isAssetStoreSrc(value.src);
|
|
33
39
|
// Broken-preview fallback, mirroring AssetCard.tsx's thumbnail fallback (same
|
|
34
40
|
// icon/copy, same reset-during-render pattern). Covers both an asset broken
|
|
35
41
|
// at upload time and a transform failing at render time.
|
|
@@ -47,9 +53,13 @@ export const ImageField = ({ id, label, description, value, onChange, aspect, al
|
|
|
47
53
|
altInputRef.current?.focus();
|
|
48
54
|
}
|
|
49
55
|
}, [value?.src]);
|
|
56
|
+
const edit = (next) => {
|
|
57
|
+
if (!readOnly)
|
|
58
|
+
onChange(next);
|
|
59
|
+
};
|
|
50
60
|
const commitAsset = (asset, crop) => {
|
|
51
61
|
justCommittedRef.current = true;
|
|
52
|
-
|
|
62
|
+
edit({
|
|
53
63
|
src: asset.src,
|
|
54
64
|
// Preserves the current alt text on replace (it often still fits); an
|
|
55
65
|
// empty field has no prior alt, so it stays ''.
|
|
@@ -82,27 +92,32 @@ export const ImageField = ({ id, label, description, value, onChange, aspect, al
|
|
|
82
92
|
const handleAltChange = (nextAlt) => {
|
|
83
93
|
if (!value)
|
|
84
94
|
return;
|
|
85
|
-
|
|
95
|
+
edit({ ...value, alt: nextAlt });
|
|
86
96
|
};
|
|
87
|
-
const handleRemove = () => {
|
|
88
|
-
|
|
97
|
+
const handleRemove = (event) => {
|
|
98
|
+
if (readOnly || !value)
|
|
99
|
+
return;
|
|
100
|
+
const field = event.currentTarget.closest('[data-removal-focus]');
|
|
101
|
+
edit(undefined);
|
|
102
|
+
onRemoved?.(value);
|
|
103
|
+
field?.focus();
|
|
89
104
|
};
|
|
90
105
|
const handleCropConfirm = (rect) => {
|
|
91
106
|
if (cropRequest?.kind === 'new') {
|
|
92
107
|
commitAsset(cropRequest.asset, rect);
|
|
93
108
|
}
|
|
94
109
|
else if (cropRequest?.kind === 'existing' && value) {
|
|
95
|
-
|
|
110
|
+
edit({ ...value, crop: rect });
|
|
96
111
|
}
|
|
97
112
|
setCropRequest(null);
|
|
98
113
|
};
|
|
99
114
|
const cropImageSrc = cropRequest?.kind === 'new'
|
|
100
|
-
?
|
|
115
|
+
? editorImageSrc(cropRequest.asset.src, baseUrl)
|
|
101
116
|
: cropRequest?.kind === 'existing' && value
|
|
102
|
-
?
|
|
117
|
+
? editorImageSrc(value.src, baseUrl)
|
|
103
118
|
: '';
|
|
104
119
|
const cropInitial = cropRequest?.kind === 'existing' ? value?.crop : undefined;
|
|
105
|
-
return (_jsxs(Stack, { gap: 4, "data-canopy-field": dataCanopyField, "data-testid": `image-field-${dataCanopyField}`, ...groupDescriptionProps(inputId, description),
|
|
120
|
+
return (_jsxs(Stack, { gap: 4, "data-canopy-field": dataCanopyField, "data-testid": `image-field-${dataCanopyField}`, ...groupDescriptionProps(inputId, description), role: "group", "aria-label": label, "data-removal-focus": true, tabIndex: -1, children: [_jsx(FieldLabel, { label: label, commentControl: commentControl }), _jsx(FieldDescription, { baseId: inputId, description: description }), !hasValue && readOnly ? (_jsx(Text, { size: "sm", c: "dimmed", "data-testid": `image-field-empty-${dataCanopyField}`, children: "No image" })) : !hasValue ? (_jsxs(Stack, { gap: "xs", children: [_jsx(Dropzone, { onDrop: (files) => void handleDrop(files), onReject: handleReject, maxSize: MAX_UPLOAD_BYTES, accept: ACCEPTED_IMAGE_MIME_TYPES, loading: upload.uploading, multiple: false, "data-testid": `image-field-dropzone-${dataCanopyField}`, children: _jsxs(Group, { justify: "center", gap: "xs", py: "xs", style: { pointerEvents: 'none' }, children: [_jsx(IconUpload, { size: 18 }), _jsx(Text, { size: "xs", children: "Drop an image here, or click to browse" })] }) }), _jsx(Group, { justify: "center", children: _jsx(Button, { variant: "light", leftSection: _jsx(IconPhoto, { size: 14 }), onClick: () => setPickerOpen(true), "data-testid": `image-field-browse-library-${dataCanopyField}`, children: "Browse library" }) }), (upload.error || dropError) && (_jsx(Alert, { icon: _jsx(IconAlertCircle, { size: 16 }), color: "red", children: upload.error || dropError })), errors?.src && (_jsx(Text, { size: "xs", c: "var(--canopy-danger-text)", children: errors.src }))] })) : (_jsxs(Stack, { gap: "xs", children: [previewFailed ? (_jsxs("div", { "data-testid": `image-field-preview-fallback-${dataCanopyField}`, style: {
|
|
106
121
|
width: PREVIEW_WIDTH,
|
|
107
122
|
height: 160,
|
|
108
123
|
display: 'flex',
|
|
@@ -111,11 +126,11 @@ export const ImageField = ({ id, label, description, value, onChange, aspect, al
|
|
|
111
126
|
justifyContent: 'center',
|
|
112
127
|
gap: 4,
|
|
113
128
|
borderRadius: 'var(--mantine-radius-sm)',
|
|
114
|
-
background: 'var(--
|
|
115
|
-
}, children: [_jsx(IconPhotoOff, { size: 28, stroke: 1.5, color: "var(--mantine-color-
|
|
129
|
+
background: 'var(--canopy-surface-muted)',
|
|
130
|
+
}, children: [_jsx(IconPhotoOff, { size: 28, stroke: 1.5, color: "var(--mantine-color-dimmed)" }), _jsx(Text, { size: "xs", c: "dimmed", children: "Preview unavailable" })] })) : (_jsx("img", { src: previewSrc, alt: value.alt, style: {
|
|
116
131
|
maxWidth: PREVIEW_WIDTH,
|
|
117
132
|
maxHeight: PREVIEW_WIDTH,
|
|
118
133
|
borderRadius: 'var(--mantine-radius-sm)',
|
|
119
134
|
display: 'block',
|
|
120
|
-
}, onError: () => setPreviewFailed(true) })), errors?.src && (_jsx(Text, { size: "xs", c: "
|
|
135
|
+
}, onError: () => setPreviewFailed(true) })), errors?.src && (_jsx(Text, { size: "xs", c: "var(--canopy-danger-text)", children: errors.src })), _jsx(TextInput, { id: inputId, ref: altInputRef, label: "Alt text", required: !altOptional, readOnly: readOnly, value: value.alt, onChange: (event) => handleAltChange(event.currentTarget.value), error: errors?.alt, size: "sm", "data-testid": `image-field-alt-${dataCanopyField}` }), !readOnly && (_jsxs(Group, { gap: "xs", children: [_jsx(Button, { variant: "light", onClick: () => setPickerOpen(true), "data-testid": `image-field-replace-${dataCanopyField}`, children: "Replace" }), canCrop && (_jsx(Button, { variant: "light", onClick: () => setCropRequest({ kind: 'existing' }), "data-testid": `image-field-crop-${dataCanopyField}`, children: "Crop" })), _jsx(Button, { variant: "subtle", color: "red", onClick: handleRemove, "data-testid": `image-field-remove-${dataCanopyField}`, children: "Remove" })] })), errors?.crop && (_jsx(Text, { size: "xs", c: "var(--canopy-danger-text)", children: errors.crop }))] })), !readOnly && (_jsx(MediaLibrary, { opened: pickerOpen, onClose: () => setPickerOpen(false), mode: "picker", onSelect: handleAssetReady })), aspectRatio !== undefined && !readOnly && (_jsx(CropStep, { opened: cropRequest !== null, onClose: () => setCropRequest(null), imageSrc: cropImageSrc, aspect: aspectRatio, initialCrop: cropInitial, onConfirm: handleCropConfirm }))] }));
|
|
121
136
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useId } from 'react';
|
|
3
|
-
import { Paper, Stack
|
|
3
|
+
import { Paper, Stack } from '@mantine/core';
|
|
4
4
|
import { formatCanopyPath } from '../canopy-path.js';
|
|
5
|
-
import {
|
|
5
|
+
import { groupDescriptionProps } from './FieldDescription.js';
|
|
6
|
+
import { FieldLabel } from './FieldLabel.js';
|
|
6
7
|
export const InlineGroupField = ({ label, description, fields, value, onChange, renderField, path, }) => {
|
|
7
8
|
const descriptionBaseId = useId();
|
|
8
|
-
return (_jsx(Paper, { withBorder: true,
|
|
9
|
+
return (_jsx(Paper, { withBorder: true, p: "md", bg: "var(--canopy-surface-subtle)", shadow: "xs", ...groupDescriptionProps(descriptionBaseId, description), children: _jsxs(Stack, { gap: "sm", children: [_jsx(FieldLabel, { label: label, description: description, descriptionBaseId: descriptionBaseId }), _jsx(Stack, { gap: "sm", children: fields.map((field) => {
|
|
9
10
|
// Nested inline groups are also transparent — pass the same parent value/onChange
|
|
10
11
|
if (field.type === 'group') {
|
|
11
12
|
const childGroup = field;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ItemExpansion } from './item-expansion.js';
|
|
3
|
+
/** What a collapsed row shows: its title, and a second value from its content. */
|
|
4
|
+
interface ItemSummary {
|
|
5
|
+
title: string;
|
|
6
|
+
secondary?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ItemListProps<T> {
|
|
9
|
+
items: readonly T[];
|
|
10
|
+
/** One stable key per item, from `useListItemKeys`. */
|
|
11
|
+
itemKeys: readonly string[];
|
|
12
|
+
/** The list field's own path; row `i` is `[...path, i]`. */
|
|
13
|
+
path: Array<string | number>;
|
|
14
|
+
readOnly: boolean;
|
|
15
|
+
expansion: ItemExpansion;
|
|
16
|
+
summarize: (item: T, index: number) => ItemSummary;
|
|
17
|
+
renderItem: (item: T, index: number) => React.ReactNode;
|
|
18
|
+
/** Guidance shown at the top of an open row, which the row's group is described by. */
|
|
19
|
+
describe?: (item: T) => string | undefined;
|
|
20
|
+
/** True when a field inside row `index` has a validation error. */
|
|
21
|
+
hasErrors?: (index: number) => boolean;
|
|
22
|
+
onMove: (from: number, to: number) => void;
|
|
23
|
+
onDuplicate: (index: number) => void;
|
|
24
|
+
/** Takes row `index` out; focus has already moved to the enclosing `[data-removal-focus]` list. */
|
|
25
|
+
onRemove: (index: number) => void;
|
|
26
|
+
/** Rendered before row `index`, such as a block list's insert-here control. */
|
|
27
|
+
renderBetween?: (index: number) => React.ReactNode;
|
|
28
|
+
/**
|
|
29
|
+
* A row index to focus after the next render, set by the caller just before it adds a row.
|
|
30
|
+
* Cleared once used.
|
|
31
|
+
*/
|
|
32
|
+
focusAfterRenderRef?: React.MutableRefObject<number | null>;
|
|
33
|
+
'data-testid'?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The rows of an object list or block list: each collapses to a one-line summary and carries a
|
|
37
|
+
* drag handle (pointer and keyboard, via dnd-kit) and a "…" menu with Move up, Move down,
|
|
38
|
+
* Duplicate and Remove. A read-only list keeps only collapsing. A collapsed row stays mounted
|
|
39
|
+
* and opens when something asks to reveal a field inside it (`REVEAL_FIELD_EVENT`).
|
|
40
|
+
*/
|
|
41
|
+
export declare function ItemList<T>({ items, itemKeys, path, readOnly, expansion, summarize, renderItem, describe, hasErrors, onMove, onDuplicate, onRemove, renderBetween, focusAfterRenderRef, 'data-testid': testId, }: ItemListProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React, { useEffect, useId, useRef, useState } from 'react';
|
|
4
|
+
import { ActionIcon, Box, Group, Menu, Paper, Stack, Text, Tooltip, UnstyledButton, VisuallyHidden, } from '@mantine/core';
|
|
5
|
+
import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, } from '@dnd-kit/core';
|
|
6
|
+
import { SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
|
|
7
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
8
|
+
import { useIsomorphicEffect } from '@mantine/hooks';
|
|
9
|
+
import { IconAlertCircle, IconChevronRight, IconDots, IconGripVertical } from '@tabler/icons-react';
|
|
10
|
+
import { formatCanopyPath } from '../canopy-path.js';
|
|
11
|
+
import { EDITOR_ACTIONS } from '../copy.js';
|
|
12
|
+
import { DestructiveMenuItem } from '../components/DestructiveMenuItem.js';
|
|
13
|
+
import { ReasonedMenuItem } from '../components/ReasonedMenuItem.js';
|
|
14
|
+
import { REVEAL_FIELD_EVENT, focusFieldTarget } from '../field-target.js';
|
|
15
|
+
import { FieldDescription, fieldDescriptionId } from './FieldDescription.js';
|
|
16
|
+
const ROW_GAP = 8;
|
|
17
|
+
/**
|
|
18
|
+
* The rows of an object list or block list: each collapses to a one-line summary and carries a
|
|
19
|
+
* drag handle (pointer and keyboard, via dnd-kit) and a "…" menu with Move up, Move down,
|
|
20
|
+
* Duplicate and Remove. A read-only list keeps only collapsing. A collapsed row stays mounted
|
|
21
|
+
* and opens when something asks to reveal a field inside it (`REVEAL_FIELD_EVENT`).
|
|
22
|
+
*/
|
|
23
|
+
export function ItemList({ items, itemKeys, path, readOnly, expansion, summarize, renderItem, describe, hasErrors, onMove, onDuplicate, onRemove, renderBetween, focusAfterRenderRef, 'data-testid': testId, }) {
|
|
24
|
+
const listRef = useRef(null);
|
|
25
|
+
const [announcement, setAnnouncement] = useState('');
|
|
26
|
+
// Constant: DndContext's hooks depend on the sensor count; read-only disables each row instead.
|
|
27
|
+
const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 6 } }), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const index = focusAfterRenderRef?.current;
|
|
30
|
+
if (index === null || index === undefined || !focusAfterRenderRef)
|
|
31
|
+
return;
|
|
32
|
+
focusAfterRenderRef.current = null;
|
|
33
|
+
// Keys are unique only within one list, so a nested list's rows never count.
|
|
34
|
+
const row = [...(listRef.current?.querySelectorAll('[data-item-row]') ?? [])].find((el) => el.dataset.itemRow === itemKeys[index] &&
|
|
35
|
+
el.closest('[data-item-list]') === listRef.current);
|
|
36
|
+
if (row)
|
|
37
|
+
focusFieldTarget(row);
|
|
38
|
+
});
|
|
39
|
+
const titleAt = (index) => summarize(items[index], index).title;
|
|
40
|
+
const indexOf = (id) => itemKeys.indexOf(String(id));
|
|
41
|
+
const position = (index) => `position ${index + 1} of ${items.length}`;
|
|
42
|
+
// dnd-kit's defaults read out the internal row keys; these use the rows' titles.
|
|
43
|
+
const announcements = {
|
|
44
|
+
onDragStart: ({ active }) => `Picked up ${titleAt(indexOf(active.id))}, ${position(indexOf(active.id))}.`,
|
|
45
|
+
onDragOver: ({ active, over }) => over
|
|
46
|
+
? `${titleAt(indexOf(active.id))} is over ${position(indexOf(over.id))}.`
|
|
47
|
+
: `${titleAt(indexOf(active.id))} is not over a position.`,
|
|
48
|
+
onDragEnd: ({ active, over }) => over
|
|
49
|
+
? `${titleAt(indexOf(active.id))} moved to ${position(indexOf(over.id))}.`
|
|
50
|
+
: `${titleAt(indexOf(active.id))} dropped.`,
|
|
51
|
+
onDragCancel: ({ active }) => `Reordering cancelled. ${titleAt(indexOf(active.id))} is back at ${position(indexOf(active.id))}.`,
|
|
52
|
+
};
|
|
53
|
+
const handleDragEnd = ({ active, over }) => {
|
|
54
|
+
if (!over || active.id === over.id)
|
|
55
|
+
return;
|
|
56
|
+
const from = indexOf(active.id);
|
|
57
|
+
const to = indexOf(over.id);
|
|
58
|
+
if (from !== -1 && to !== -1)
|
|
59
|
+
onMove(from, to);
|
|
60
|
+
};
|
|
61
|
+
const move = (from, to) => {
|
|
62
|
+
onMove(from, to);
|
|
63
|
+
setAnnouncement(`${titleAt(from)} moved to ${position(to)}.`);
|
|
64
|
+
};
|
|
65
|
+
const duplicate = (index) => {
|
|
66
|
+
onDuplicate(index);
|
|
67
|
+
setAnnouncement(`${titleAt(index)} duplicated, position ${index + 2} of ${items.length + 1}.`);
|
|
68
|
+
};
|
|
69
|
+
const remove = (index) => {
|
|
70
|
+
// The row goes, so focus moves to its list, not the page.
|
|
71
|
+
listRef.current?.closest('[data-removal-focus]')?.focus();
|
|
72
|
+
onRemove(index);
|
|
73
|
+
};
|
|
74
|
+
return (_jsxs("div", { ref: listRef, "data-item-list": true, "data-testid": testId, children: [_jsx(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragEnd: handleDragEnd, accessibility: { announcements }, children: _jsx(SortableContext, { items: [...itemKeys], strategy: verticalListSortingStrategy, children: items.map((item, idx) => {
|
|
75
|
+
const key = itemKeys[idx];
|
|
76
|
+
const summary = summarize(item, idx);
|
|
77
|
+
return (_jsxs(React.Fragment, { children: [renderBetween ? renderBetween(idx) : idx > 0 && _jsx(Box, { h: ROW_GAP, "aria-hidden": true }), _jsx(ItemRow, { rowKey: key, canopyPath: formatCanopyPath([...path, idx]), summary: summary, description: describe?.(item), hasErrors: hasErrors?.(idx) ?? false, expanded: expansion.isExpanded(key), onExpandedChange: (open) => expansion.setExpanded(key, open), readOnly: readOnly, isFirst: idx === 0, isLast: idx === items.length - 1, onMoveUp: () => move(idx, idx - 1), onMoveDown: () => move(idx, idx + 1), onDuplicate: () => duplicate(idx), onRemove: () => remove(idx), children: renderItem(item, idx) })] }, key));
|
|
78
|
+
}) }) }), _jsx(VisuallyHidden, { "aria-live": "polite", children: announcement })] }));
|
|
79
|
+
}
|
|
80
|
+
const ItemRow = ({ rowKey, canopyPath, summary, description, hasErrors, expanded, onExpandedChange, readOnly, isFirst, isLast, onMoveUp, onMoveDown, onDuplicate, onRemove, children, }) => {
|
|
81
|
+
const baseId = useId();
|
|
82
|
+
const bodyId = `${baseId}-body`;
|
|
83
|
+
const rowRef = useRef(null);
|
|
84
|
+
const menuTargetRef = useRef(null);
|
|
85
|
+
const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging, } = useSortable({ id: rowKey, disabled: readOnly });
|
|
86
|
+
const expandedRef = useRef(expanded);
|
|
87
|
+
const onExpandedChangeRef = useRef(onExpandedChange);
|
|
88
|
+
// Both from the layout phase, before any field inside runs a passive effect that asks to reveal
|
|
89
|
+
// it; `whenRevealed` asks again for one that asks earlier.
|
|
90
|
+
useIsomorphicEffect(() => {
|
|
91
|
+
expandedRef.current = expanded;
|
|
92
|
+
onExpandedChangeRef.current = onExpandedChange;
|
|
93
|
+
});
|
|
94
|
+
useIsomorphicEffect(() => {
|
|
95
|
+
const row = rowRef.current;
|
|
96
|
+
if (!row)
|
|
97
|
+
return;
|
|
98
|
+
const reveal = (event) => {
|
|
99
|
+
if (expandedRef.current)
|
|
100
|
+
return;
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
onExpandedChangeRef.current(true);
|
|
103
|
+
};
|
|
104
|
+
row.addEventListener(REVEAL_FIELD_EVENT, reveal);
|
|
105
|
+
return () => row.removeEventListener(REVEAL_FIELD_EVENT, reveal);
|
|
106
|
+
}, []);
|
|
107
|
+
// A menu item is gone once it acts, so focus returns to the menu's trigger, which moves with
|
|
108
|
+
// the row.
|
|
109
|
+
const thenFocusMenu = (act) => () => {
|
|
110
|
+
act();
|
|
111
|
+
requestAnimationFrame(() => menuTargetRef.current?.focus());
|
|
112
|
+
};
|
|
113
|
+
// Rows can share a title (two sections of one template), so names carry the second value too.
|
|
114
|
+
const name = summary.secondary ? `${summary.title}, ${summary.secondary}` : summary.title;
|
|
115
|
+
const actionsLabel = `Actions for ${name}`;
|
|
116
|
+
return (_jsxs(Paper, { ref: (node) => {
|
|
117
|
+
rowRef.current = node;
|
|
118
|
+
setNodeRef(node);
|
|
119
|
+
}, withBorder: true, shadow: "xs", role: "group", "aria-label": name, "aria-describedby": expanded && description ? fieldDescriptionId(baseId) : undefined, "data-canopy-field": canopyPath, "data-item-row": rowKey, "data-testid": "item-row", "data-expanded": expanded || undefined, style: {
|
|
120
|
+
transform: CSS.Translate.toString(transform),
|
|
121
|
+
transition,
|
|
122
|
+
position: 'relative',
|
|
123
|
+
zIndex: isDragging ? 1 : undefined,
|
|
124
|
+
boxShadow: isDragging ? 'var(--mantine-shadow-md)' : undefined,
|
|
125
|
+
}, children: [_jsxs(Group, { gap: 4, wrap: "nowrap", px: 6, py: 4, align: "center", children: [!readOnly && (_jsx(Tooltip, { label: "Drag to reorder", openDelay: 500, children: _jsx(ActionIcon, { ref: setActivatorNodeRef, variant: "subtle", color: "gray", "aria-label": "Drag to reorder", ...attributes, ...listeners, style: { cursor: isDragging ? 'grabbing' : 'grab', touchAction: 'none' }, children: _jsx(IconGripVertical, { size: 16, "aria-hidden": true }) }) })), _jsx(UnstyledButton, { "aria-expanded": expanded, "aria-controls": bodyId, onClick: () => onExpandedChange(!expanded), "data-testid": "item-row-toggle", style: { flex: 1, minWidth: 0, borderRadius: 'var(--mantine-radius-sm)' }, px: 4, py: 4, children: _jsxs(Group, { gap: 6, wrap: "nowrap", children: [_jsx(IconChevronRight, { size: 16, "aria-hidden": true, style: {
|
|
126
|
+
flexShrink: 0,
|
|
127
|
+
transform: expanded ? 'rotate(90deg)' : undefined,
|
|
128
|
+
transition: 'transform 120ms ease',
|
|
129
|
+
} }), _jsx(Text, { size: "sm", fw: 500, truncate: "end", style: summary.secondary ? { flexShrink: 0, maxWidth: '60%' } : { minWidth: 0 }, children: summary.title }), summary.secondary && (_jsx(Text, { size: "sm", c: "dimmed", truncate: "end", style: { minWidth: 0 }, children: summary.secondary })), hasErrors && !expanded && (_jsxs(Group, { gap: 2, wrap: "nowrap", ml: "auto", style: { flexShrink: 0 }, children: [_jsx(IconAlertCircle, { size: 14, color: "var(--canopy-danger-text)", "aria-hidden": true }), _jsx(Text, { size: "xs", c: "var(--canopy-danger-text)", children: "Has errors" })] }))] }) }), !readOnly && (_jsxs(Menu, { position: "bottom-end", withinPortal: true, shadow: "sm", width: 220, children: [_jsx(Tooltip, { label: actionsLabel, openDelay: 500, children: _jsx(Menu.Target, { children: _jsx(ActionIcon, { ref: menuTargetRef, variant: "subtle", color: "gray", "aria-label": actionsLabel, "data-testid": "item-row-menu", children: _jsx(IconDots, { size: 16, "aria-hidden": true }) }) }) }), _jsxs(Menu.Dropdown, { children: [_jsx(ReasonedMenuItem, { blockedReason: isFirst ? 'Already first' : undefined, onClick: thenFocusMenu(onMoveUp), "data-testid": "item-row-move-up", children: "Move up" }), _jsx(ReasonedMenuItem, { blockedReason: isLast ? 'Already last' : undefined, onClick: thenFocusMenu(onMoveDown), "data-testid": "item-row-move-down", children: "Move down" }), _jsx(Menu.Item, { onClick: thenFocusMenu(onDuplicate), "data-testid": "item-row-duplicate", children: "Duplicate" }), _jsx(Menu.Divider, {}), _jsx(DestructiveMenuItem, { onClick: onRemove, "data-testid": "item-row-remove", children: EDITOR_ACTIONS.remove })] })] }))] }), _jsx(Box, { id: bodyId, hidden: !expanded, children: _jsxs(Stack, { gap: "sm", px: "sm", pb: "sm", pt: 4, children: [description && _jsx(FieldDescription, { baseId: baseId, description: description }), children] }) })] }));
|
|
130
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { MDXEditorMethods } from '@mdxeditor/editor';
|
|
2
3
|
export interface MarkdownFieldProps {
|
|
3
4
|
id?: string;
|
|
4
5
|
label?: string;
|
|
@@ -6,5 +7,36 @@ export interface MarkdownFieldProps {
|
|
|
6
7
|
value: string;
|
|
7
8
|
onChange: (value: string) => void;
|
|
8
9
|
dataCanopyField?: string;
|
|
10
|
+
/** The HTML tags the field accepts; the toolbar offers no action writing another. Omitted: any. */
|
|
11
|
+
htmlTags?: ReadonlySet<string>;
|
|
12
|
+
/** Shows the content without accepting edits, in the rich-text editor or as source. */
|
|
13
|
+
readOnly?: boolean;
|
|
9
14
|
}
|
|
15
|
+
/** @internal Exported for the round-trip corpus test, which drives exactly this editor. */
|
|
16
|
+
export declare const MDXEditorLazy: React.LazyExoticComponent<React.FC<{
|
|
17
|
+
markdown: string;
|
|
18
|
+
onChange: (value: string, initialMarkdownNormalize: boolean) => void;
|
|
19
|
+
onError: (payload: {
|
|
20
|
+
error: string;
|
|
21
|
+
source: string;
|
|
22
|
+
}) => void;
|
|
23
|
+
onInsert: (insert: () => void, markdown: string) => void;
|
|
24
|
+
editorRef?: React.Ref<MDXEditorMethods>;
|
|
25
|
+
imageUploadHandler: (file: File) => Promise<string>;
|
|
26
|
+
imagePreviewHandler: (src: string) => Promise<string>;
|
|
27
|
+
htmlTags?: ReadonlySet<string>;
|
|
28
|
+
readOnly?: boolean;
|
|
29
|
+
/** Names the content area for assistive tech; MDXEditor's default is "editable markdown". */
|
|
30
|
+
contentLabel?: string;
|
|
31
|
+
/** Draws the editor and its popups in MDXEditor's dark theme. */
|
|
32
|
+
dark?: boolean;
|
|
33
|
+
}>>;
|
|
34
|
+
/** The textarea over a markdown value; `failure` is why the rich-text editor could not open it. */
|
|
35
|
+
export declare const MarkdownSourceEditor: React.FC<{
|
|
36
|
+
label?: string;
|
|
37
|
+
value: string;
|
|
38
|
+
onChange: (value: string) => void;
|
|
39
|
+
failure?: string;
|
|
40
|
+
readOnly?: boolean;
|
|
41
|
+
}>;
|
|
10
42
|
export declare const MarkdownField: React.FC<MarkdownFieldProps>;
|