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
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import { Button, Group, Paper, Stack, Text } from '@mantine/core';
|
|
4
|
+
import { IconPlus } from '@tabler/icons-react';
|
|
5
|
+
import { isPlainRecord } from '../../validation/field-traversal.js';
|
|
6
|
+
import { ITEM_KEY, mintItemKey, withFreshItemKeys } from '../../item-keys.js';
|
|
7
|
+
import { formatCanopyPath } from '../canopy-path.js';
|
|
8
|
+
import { useFieldCommentControl } from '../comments/field-comment-context.js';
|
|
9
|
+
import { groupDescriptionProps } from './FieldDescription.js';
|
|
10
|
+
import { FieldLabel } from './FieldLabel.js';
|
|
11
|
+
import { ExpandAllButton } from './ExpandAllButton.js';
|
|
12
|
+
import { ItemList } from './ItemList.js';
|
|
13
|
+
import { useItemExpansion } from './item-expansion.js';
|
|
14
|
+
import { listItemSummary } from './list-item-title.js';
|
|
15
|
+
/**
|
|
16
|
+
* A `list: true` object field: one collapsible row per item, titled from the item's content,
|
|
17
|
+
* holding the item's fields directly rather than in a second card.
|
|
18
|
+
*/
|
|
19
|
+
export const ObjectListField = ({ id, label, field, items, itemKeys, onChange, renderField, path, canopyPath, readOnly, resetKey, hasErrors, onRemoved, }) => {
|
|
20
|
+
const commentControl = useFieldCommentControl(canopyPath);
|
|
21
|
+
const expansion = useItemExpansion(itemKeys, resetKey);
|
|
22
|
+
const focusAfterRenderRef = useRef(null);
|
|
23
|
+
const insertAt = (index, item) => {
|
|
24
|
+
focusAfterRenderRef.current = index;
|
|
25
|
+
onChange([...items.slice(0, index), item, ...items.slice(index)]);
|
|
26
|
+
};
|
|
27
|
+
return (_jsx(Paper, { withBorder: true, p: "md", shadow: "xs", ...groupDescriptionProps(id, field.description), role: "group", "aria-label": label, "data-removal-focus": true, tabIndex: -1, children: _jsxs(Stack, { gap: "sm", children: [_jsx(FieldLabel, { label: label, required: field.required, description: field.description, descriptionBaseId: id, commentControl: commentControl, actions: items.length > 1 && _jsx(ExpandAllButton, { expansion: expansion }) }), _jsx(ItemList, { items: items, itemKeys: itemKeys, path: path, readOnly: readOnly, expansion: expansion, summarize: (item, idx) => listItemSummary(item, field, idx), hasErrors: hasErrors, focusAfterRenderRef: focusAfterRenderRef, onMove: (from, to) => {
|
|
28
|
+
if (from === to || to < 0 || to >= items.length)
|
|
29
|
+
return;
|
|
30
|
+
const next = [...items];
|
|
31
|
+
const [moved] = next.splice(from, 1);
|
|
32
|
+
next.splice(to, 0, moved);
|
|
33
|
+
onChange(next);
|
|
34
|
+
}, onDuplicate: (idx) =>
|
|
35
|
+
// Focus stays on the row's menu, which stands in for the item that acted. The copy
|
|
36
|
+
// gets new keys, so no comment thread follows it.
|
|
37
|
+
onChange([
|
|
38
|
+
...items.slice(0, idx + 1),
|
|
39
|
+
withFreshItemKeys(field, structuredClone(items[idx])),
|
|
40
|
+
...items.slice(idx + 1),
|
|
41
|
+
]), onRemove: (idx) => {
|
|
42
|
+
const item = items[idx];
|
|
43
|
+
onChange(items.filter((_, i) => i !== idx));
|
|
44
|
+
onRemoved?.(idx, item);
|
|
45
|
+
}, renderItem: (item, idx) => {
|
|
46
|
+
const itemPath = [...path, idx];
|
|
47
|
+
const current = isPlainRecord(item) ? item : {};
|
|
48
|
+
return field.fields.map((child) => {
|
|
49
|
+
const childPath = [...itemPath, child.name];
|
|
50
|
+
return (_jsx("div", { children: renderField(child, current[child.name], (next) => {
|
|
51
|
+
const nextItems = [...items];
|
|
52
|
+
nextItems[idx] = { ...current, [child.name]: next };
|
|
53
|
+
onChange(nextItems);
|
|
54
|
+
}, childPath) }, formatCanopyPath(childPath)));
|
|
55
|
+
});
|
|
56
|
+
} }), items.length === 0 && (_jsx(Text, { size: "sm", c: "dimmed", children: readOnly ? 'Nothing added.' : 'Nothing added yet.' })), !readOnly && (_jsx(Group, { children: _jsxs(Button, { variant: "light", size: "xs", leftSection: _jsx(IconPlus, { size: 14, "aria-hidden": true }), onClick: () => insertAt(items.length, { [ITEM_KEY]: mintItemKey() }), "data-testid": "object-list-add", children: ["Add ", field.itemLabel ?? 'item'] }) }))] }) }));
|
|
57
|
+
};
|
|
@@ -17,5 +17,7 @@ export interface ReferenceFieldProps {
|
|
|
17
17
|
onChange: (value: string | string[]) => void;
|
|
18
18
|
multiple?: boolean;
|
|
19
19
|
dataCanopyField?: string;
|
|
20
|
+
/** Shows the value without accepting edits. */
|
|
21
|
+
readOnly?: boolean;
|
|
20
22
|
}
|
|
21
23
|
export declare const ReferenceField: React.FC<ReferenceFieldProps>;
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useId, useState } from 'react';
|
|
4
4
|
import { Alert, Button, MultiSelect, Select, Stack, Text, Loader } from '@mantine/core';
|
|
5
5
|
import { IconAlertCircle } from '@tabler/icons-react';
|
|
6
6
|
import { createApiClient } from '../../api/client.js';
|
|
7
7
|
import { useOptionalApiClient } from '../context/index.js';
|
|
8
8
|
import { getErrorMessage } from '../../utils/error.js';
|
|
9
|
+
import { useFieldCommentControl } from '../comments/field-comment-context.js';
|
|
9
10
|
import { FieldDescription, groupDescriptionProps } from './FieldDescription.js';
|
|
10
|
-
|
|
11
|
+
import { FieldLabel } from './FieldLabel.js';
|
|
12
|
+
/** Label for a set value the options omit (a restricted, missing or unlisted target). */
|
|
13
|
+
function unlistedReferenceLabel(value, id) {
|
|
14
|
+
if (value && typeof value === 'object' && 'unavailable' in value && value.unavailable === true) {
|
|
15
|
+
if ('reason' in value && value.reason === 'restricted' && 'title' in value) {
|
|
16
|
+
return `Restricted entry: ${String(value.title)}`;
|
|
17
|
+
}
|
|
18
|
+
return `Missing entry (${id})`;
|
|
19
|
+
}
|
|
20
|
+
return `Unavailable entry (${id})`;
|
|
21
|
+
}
|
|
22
|
+
export const ReferenceField = ({ id, label, description, options: staticOptions, collections, entryTypes, displayField = 'title', branch = 'main', value, onChange, multiple, dataCanopyField, readOnly = false, }) => {
|
|
11
23
|
// Configured with the deployment's basePath when rendered inside an
|
|
12
24
|
// ApiClientProvider (always true in the real Editor tree); `null` outside one
|
|
13
25
|
// (e.g. FormRenderer.stories.tsx), so the fetch effect falls back to a
|
|
@@ -32,8 +44,19 @@ export const ReferenceField = ({ id, label, description, options: staticOptions,
|
|
|
32
44
|
? value.map(extractId)
|
|
33
45
|
: []
|
|
34
46
|
: extractId(value);
|
|
47
|
+
// Otherwise Select shows a set value as empty, inviting an editor to repoint it.
|
|
48
|
+
const listed = new Set(options.map((option) => option.value));
|
|
49
|
+
const unlisted = new Map();
|
|
50
|
+
for (const raw of multiple ? (Array.isArray(value) ? value : []) : [value]) {
|
|
51
|
+
const valueId = extractId(raw);
|
|
52
|
+
if (valueId && !listed.has(valueId) && !unlisted.has(valueId)) {
|
|
53
|
+
unlisted.set(valueId, { value: valueId, label: unlistedReferenceLabel(raw, valueId) });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const data = unlisted.size > 0 ? [...options, ...unlisted.values()] : options;
|
|
35
57
|
const generatedId = useId();
|
|
36
58
|
const inputId = id ?? generatedId;
|
|
59
|
+
const commentControl = useFieldCommentControl(dataCanopyField);
|
|
37
60
|
// Track deps to detect changes and reset loading during render
|
|
38
61
|
const [prevFetchKey, setPrevFetchKey] = useState('');
|
|
39
62
|
const fetchKey = needsFetch
|
|
@@ -101,11 +124,13 @@ export const ReferenceField = ({ id, label, description, options: staticOptions,
|
|
|
101
124
|
setError(null);
|
|
102
125
|
setRetryCount((count) => count + 1);
|
|
103
126
|
};
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
127
|
+
const settled = !loading && !error;
|
|
128
|
+
// One label row for every state, so the comment popover in it survives loading and Retry.
|
|
129
|
+
return (_jsxs(Stack, { gap: 4, "data-canopy-field": dataCanopyField, "data-testid": `reference-field-${dataCanopyField}`, ...(settled ? {} : groupDescriptionProps(inputId, description)), children: [_jsx(FieldLabel, { label: label, htmlFor: settled ? inputId : undefined, commentControl: commentControl }), loading ? (_jsxs(_Fragment, { children: [_jsx(FieldDescription, { baseId: inputId, description: description }), _jsx(Loader, { size: "sm", "data-testid": `reference-loading-${dataCanopyField}` })] })) : error ? (_jsxs(_Fragment, { children: [_jsx(FieldDescription, { baseId: inputId, description: description }), _jsx(Alert, { icon: _jsx(IconAlertCircle, { size: 16 }), color: "red", title: "Error", "data-testid": `reference-error-${dataCanopyField}`, children: _jsxs(Stack, { gap: 4, children: [_jsx(Text, { size: "sm", children: error }), _jsx(Button, { variant: "light", onClick: handleRetry, "data-testid": `reference-retry-${dataCanopyField}`, children: "Retry" })] }) })] })) : multiple ? (_jsx(MultiSelect, { id: inputId, "aria-label": label, description: description, data: data, value: normalizedValue, readOnly: readOnly, rightSection: readOnly ? _jsx("span", {}) : undefined, onChange: (next) => {
|
|
130
|
+
if (!readOnly)
|
|
131
|
+
onChange(next);
|
|
132
|
+
}, searchable: true, placeholder: readOnly ? undefined : 'Select reference…', size: "sm" })) : (_jsx(Select, { id: inputId, "aria-label": label, description: description, data: data, value: normalizedValue, readOnly: readOnly, rightSection: readOnly ? _jsx("span", {}) : undefined, onChange: (next) => {
|
|
133
|
+
if (!readOnly)
|
|
134
|
+
onChange(next ?? '');
|
|
135
|
+
}, searchable: true, clearable: true, placeholder: readOnly ? undefined : 'Select reference…', size: "sm" }))] }));
|
|
111
136
|
};
|
|
@@ -13,6 +13,8 @@ export interface SelectFieldProps {
|
|
|
13
13
|
multiple?: boolean;
|
|
14
14
|
placeholder?: string;
|
|
15
15
|
dataCanopyField?: string;
|
|
16
|
+
/** Shows the value without accepting edits. */
|
|
17
|
+
readOnly?: boolean;
|
|
16
18
|
}
|
|
17
19
|
export declare const SelectField: React.FC<SelectFieldProps>;
|
|
18
20
|
export {};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useId } from 'react';
|
|
3
3
|
import { MultiSelect, Select, Stack, Text } from '@mantine/core';
|
|
4
|
-
|
|
4
|
+
import { useFieldCommentControl } from '../comments/field-comment-context.js';
|
|
5
|
+
import { FieldLabel } from './FieldLabel.js';
|
|
6
|
+
export const SelectField = ({ id, label, description, options, value, onChange, multiple, placeholder = 'Select…', dataCanopyField, readOnly = false, }) => {
|
|
5
7
|
const normalizedValue = multiple
|
|
6
8
|
? Array.isArray(value)
|
|
7
9
|
? value
|
|
@@ -11,5 +13,12 @@ export const SelectField = ({ id, label, description, options, value, onChange,
|
|
|
11
13
|
: '';
|
|
12
14
|
const generatedId = useId();
|
|
13
15
|
const inputId = id ?? generatedId;
|
|
14
|
-
|
|
16
|
+
const commentControl = useFieldCommentControl(dataCanopyField);
|
|
17
|
+
return (_jsxs(Stack, { gap: 4, "data-canopy-field": dataCanopyField, children: [_jsx(FieldLabel, { label: label, htmlFor: inputId, commentControl: commentControl }), multiple ? (_jsx(MultiSelect, { id: inputId, "aria-label": label, description: description, data: options, value: normalizedValue, readOnly: readOnly, rightSection: readOnly ? _jsx("span", {}) : undefined, onChange: (next) => {
|
|
18
|
+
if (!readOnly)
|
|
19
|
+
onChange(next);
|
|
20
|
+
}, searchable: true, placeholder: readOnly ? undefined : placeholder, size: "sm" })) : (_jsx(Select, { id: inputId, "aria-label": label, description: description, data: options, value: normalizedValue, readOnly: readOnly, rightSection: readOnly ? _jsx("span", {}) : undefined, onChange: (next) => {
|
|
21
|
+
if (!readOnly)
|
|
22
|
+
onChange(next ?? '');
|
|
23
|
+
}, searchable: true, clearable: true, placeholder: readOnly ? undefined : placeholder, size: "sm" })), multiple && !readOnly && (_jsx(Text, { size: "xs", c: "dimmed", children: "Searchable multi-select; start typing to filter." }))] }));
|
|
15
24
|
};
|
|
@@ -6,11 +6,14 @@ export interface StringListFieldProps {
|
|
|
6
6
|
value: string[];
|
|
7
7
|
onChange: (value: string[]) => void;
|
|
8
8
|
dataCanopyField?: string;
|
|
9
|
+
/** Shows the value without accepting edits. */
|
|
10
|
+
readOnly?: boolean;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
11
13
|
* Editor for `type: 'string', list: true` fields.
|
|
12
14
|
*
|
|
13
15
|
* Uses Mantine's TagsInput: type + Enter adds an item, each item renders as a
|
|
14
|
-
* removable pill, and Backspace on an empty input removes the last item.
|
|
16
|
+
* removable pill, and Backspace on an empty input removes the last item. An editable list says
|
|
17
|
+
* that Enter adds, after the field's own description.
|
|
15
18
|
*/
|
|
16
19
|
export declare const StringListField: React.FC<StringListFieldProps>;
|
|
@@ -1,19 +1,33 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useId } from 'react';
|
|
3
3
|
import { TagsInput } from '@mantine/core';
|
|
4
|
+
import { LabelledInput } from './FieldLabel.js';
|
|
5
|
+
/** The field's description, ended as a sentence, then the hint that Enter adds. */
|
|
6
|
+
const withEnterHint = (description) => {
|
|
7
|
+
const own = description?.trim();
|
|
8
|
+
if (!own)
|
|
9
|
+
return 'Press Enter to add.';
|
|
10
|
+
return `${/[.!?]$/.test(own) ? own : `${own}.`} Press Enter to add.`;
|
|
11
|
+
};
|
|
4
12
|
/**
|
|
5
13
|
* Editor for `type: 'string', list: true` fields.
|
|
6
14
|
*
|
|
7
15
|
* Uses Mantine's TagsInput: type + Enter adds an item, each item renders as a
|
|
8
|
-
* removable pill, and Backspace on an empty input removes the last item.
|
|
16
|
+
* removable pill, and Backspace on an empty input removes the last item. An editable list says
|
|
17
|
+
* that Enter adds, after the field's own description.
|
|
9
18
|
*/
|
|
10
|
-
export const StringListField = ({ id, label, description, value, onChange, dataCanopyField, }) => {
|
|
19
|
+
export const StringListField = ({ id, label, description, value, onChange, dataCanopyField, readOnly = false, }) => {
|
|
11
20
|
const generatedId = useId();
|
|
12
21
|
const inputId = id ?? generatedId;
|
|
13
|
-
return (_jsx(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
return (_jsx(LabelledInput, { label: label, inputId: inputId, canopyPath: dataCanopyField, children: _jsx(TagsInput, { id: inputId,
|
|
23
|
+
// TagsInput gives no sign that Enter adds a typed item.
|
|
24
|
+
description: readOnly ? description : withEnterHint(description), value: value, size: "sm", readOnly: readOnly, onChange: (next) => {
|
|
25
|
+
if (!readOnly)
|
|
26
|
+
onChange(next);
|
|
27
|
+
},
|
|
28
|
+
// Faithful generic-list semantics, not tag ergonomics: no comma-splitting
|
|
29
|
+
// ("New York, NY" stays one item) and duplicates are legitimate list
|
|
30
|
+
// data — TagsInput's defaults would break both, so existing file data
|
|
31
|
+
// couldn't round-trip.
|
|
32
|
+
splitChars: [], allowDuplicates: true, "data-canopy-field": dataCanopyField }) }));
|
|
19
33
|
};
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useId } from 'react';
|
|
3
3
|
import { TextInput } from '@mantine/core';
|
|
4
|
-
|
|
4
|
+
import { LabelledInput } from './FieldLabel.js';
|
|
5
|
+
export const TextField = ({ id, label, description, value, onChange, dataCanopyField, readOnly = false, }) => {
|
|
5
6
|
const generatedId = useId();
|
|
6
7
|
const inputId = id ?? generatedId;
|
|
7
|
-
return (_jsx(
|
|
8
|
+
return (_jsx(LabelledInput, { label: label, inputId: inputId, canopyPath: dataCanopyField, children: _jsx(TextInput, { id: inputId, description: description, value: value, size: "sm", readOnly: readOnly, onChange: (e) => {
|
|
9
|
+
if (!readOnly)
|
|
10
|
+
onChange(e.currentTarget.value);
|
|
11
|
+
}, "data-canopy-field": dataCanopyField }) }));
|
|
8
12
|
};
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useId } from 'react';
|
|
3
|
-
import { Stack, Switch } from '@mantine/core';
|
|
3
|
+
import { Group, Stack, Switch, Text } from '@mantine/core';
|
|
4
|
+
import { useFieldCommentControl } from '../comments/field-comment-context.js';
|
|
4
5
|
import { FieldDescription, fieldDescriptionId } from './FieldDescription.js';
|
|
5
|
-
export const ToggleField = ({ id, label, description, value, onChange, dataCanopyField, testId, }) => {
|
|
6
|
+
export const ToggleField = ({ id, label, description, value, onChange, dataCanopyField, testId, readOnly = false, }) => {
|
|
6
7
|
const generatedId = useId();
|
|
7
8
|
const inputId = id ?? generatedId;
|
|
9
|
+
const commentControl = useFieldCommentControl(dataCanopyField);
|
|
8
10
|
// A Switch's `description` sits inside its <label> and so joins the accessible name;
|
|
9
11
|
// rendering it as a sibling keeps the name to the label alone.
|
|
10
|
-
return (_jsxs(Stack, { gap: 4, children: [_jsx(Switch, { id: inputId, label: label, "aria-describedby": description ? fieldDescriptionId(inputId) : undefined, checked: value,
|
|
12
|
+
return (_jsxs(Stack, { gap: 4, children: [_jsxs(Group, { gap: "sm", wrap: "nowrap", children: [_jsx(Switch, { id: inputId, label: label, "aria-describedby": description ? fieldDescriptionId(inputId) : undefined, checked: value, "aria-readonly": readOnly || undefined, styles: readOnly ? { track: { cursor: 'default' }, input: { cursor: 'default' } } : undefined, onChange: (e) => {
|
|
13
|
+
if (!readOnly)
|
|
14
|
+
onChange(e.currentTarget.checked);
|
|
15
|
+
}, size: "sm", "data-canopy-field": dataCanopyField, wrapperProps: testId ? { 'data-testid': testId } : undefined }), commentControl, readOnly && (_jsx(Text, { size: "sm", c: "dimmed", "data-testid": testId ? `${testId}-value` : undefined, children: value ? 'On' : 'Off' }))] }), _jsx(FieldDescription, { baseId: inputId, description: description })] }));
|
|
11
16
|
};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import React from 'react';
|
|
7
7
|
interface InsertEntryLinkProps {
|
|
8
|
-
/**
|
|
8
|
+
/** Inserts the link's markdown into the editor (MarkdownField's `handleInsert`). */
|
|
9
9
|
onInsert: (markdown: string) => void;
|
|
10
10
|
}
|
|
11
11
|
export declare const InsertEntryLink: React.FC<InsertEntryLinkProps>;
|
|
@@ -44,7 +44,7 @@ export const InsertEntryLink = ({ onInsert }) => {
|
|
|
44
44
|
setOpened(false);
|
|
45
45
|
setSearch('');
|
|
46
46
|
};
|
|
47
|
-
return (_jsxs(_Fragment, { children: [_jsx(ActionIcon, { variant: "subtle",
|
|
47
|
+
return (_jsxs(_Fragment, { children: [_jsx(ActionIcon, { variant: "subtle", color: "gray", title: "Insert entry link", "data-testid": "insert-entry-link-button", onClick: () => setOpened(true), children: _jsx(IconFileSymlink, { size: 16 }) }), _jsx(Modal, { opened: opened, onClose: () => {
|
|
48
48
|
setOpened(false);
|
|
49
49
|
setSearch('');
|
|
50
50
|
}, title: "Link to Entry", size: "md", children: _jsx(Stack, { gap: "sm", children: _jsxs(Combobox, { store: combobox, onOptionSubmit: (val) => {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A form-wide "Expand all" or "Collapse all". `seq` grows with each press, so pressing the same
|
|
3
|
+
* one twice still counts; a list applies only presses made while it is mounted.
|
|
4
|
+
*/
|
|
5
|
+
export interface FormExpansionCommand {
|
|
6
|
+
seq: number;
|
|
7
|
+
expanded: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare const FormExpansionContext: import("react").Context<FormExpansionCommand | undefined>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ItemExpansion {
|
|
2
|
+
isExpanded: (key: string) => boolean;
|
|
3
|
+
setExpanded: (key: string, expanded: boolean) => void;
|
|
4
|
+
setAll: (expanded: boolean) => void;
|
|
5
|
+
/** True when every row is expanded; false for an empty list. */
|
|
6
|
+
allExpanded: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Which rows of a collapsible list are open, by list-item key (`useListItemKeys`), so a row keeps
|
|
10
|
+
* its state through moves, and through a Remove and its Undo. A list inside a row that moves
|
|
11
|
+
* remounts and starts over. A list's first rows start open as `EXPAND_ALL_UP_TO` says; a row added
|
|
12
|
+
* later (Add, Duplicate) starts open. `resetKey` names the entry being edited: a new one starts
|
|
13
|
+
* over. The form's own Expand all and Collapse all (`FormExpansionContext`) reach every list.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useItemExpansion(itemKeys: readonly string[], resetKey: string): ItemExpansion;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { FormExpansionContext } from './form-expansion.js';
|
|
3
|
+
/** Up to this many rows all start expanded; a longer list starts with only its first open. */
|
|
4
|
+
const EXPAND_ALL_UP_TO = 3;
|
|
5
|
+
/**
|
|
6
|
+
* Which rows of a collapsible list are open, by list-item key (`useListItemKeys`), so a row keeps
|
|
7
|
+
* its state through moves, and through a Remove and its Undo. A list inside a row that moves
|
|
8
|
+
* remounts and starts over. A list's first rows start open as `EXPAND_ALL_UP_TO` says; a row added
|
|
9
|
+
* later (Add, Duplicate) starts open. `resetKey` names the entry being edited: a new one starts
|
|
10
|
+
* over. The form's own Expand all and Collapse all (`FormExpansionContext`) reach every list.
|
|
11
|
+
*/
|
|
12
|
+
export function useItemExpansion(itemKeys, resetKey) {
|
|
13
|
+
const [toggled, setToggled] = useState(() => ({
|
|
14
|
+
resetKey,
|
|
15
|
+
open: new Map(),
|
|
16
|
+
}));
|
|
17
|
+
// Decided once per key, the first time it renders, and kept until `resetKey` changes.
|
|
18
|
+
const defaults = useRef({
|
|
19
|
+
resetKey,
|
|
20
|
+
open: new Map(),
|
|
21
|
+
started: false,
|
|
22
|
+
});
|
|
23
|
+
if (defaults.current.resetKey !== resetKey) {
|
|
24
|
+
defaults.current = { resetKey, open: new Map(), started: false };
|
|
25
|
+
}
|
|
26
|
+
const firstPopulation = !defaults.current.started && itemKeys.length > 0;
|
|
27
|
+
itemKeys.forEach((key, idx) => {
|
|
28
|
+
if (defaults.current.open.has(key))
|
|
29
|
+
return;
|
|
30
|
+
defaults.current.open.set(key, firstPopulation ? idx === 0 || itemKeys.length <= EXPAND_ALL_UP_TO : true);
|
|
31
|
+
});
|
|
32
|
+
if (itemKeys.length > 0)
|
|
33
|
+
defaults.current.started = true;
|
|
34
|
+
const explicit = toggled.resetKey === resetKey ? toggled.open : undefined;
|
|
35
|
+
const isExpanded = (key) => explicit?.get(key) ?? defaults.current.open.get(key) ?? true;
|
|
36
|
+
const setExpanded = useCallback((key, expanded) => setToggled((prev) => {
|
|
37
|
+
const open = new Map(prev.resetKey === resetKey ? prev.open : undefined);
|
|
38
|
+
open.set(key, expanded);
|
|
39
|
+
return { resetKey, open };
|
|
40
|
+
}), [resetKey]);
|
|
41
|
+
const setAll = (expanded) => setToggled(() => ({ resetKey, open: new Map(itemKeys.map((key) => [key, expanded])) }));
|
|
42
|
+
const command = useContext(FormExpansionContext);
|
|
43
|
+
const appliedSeq = useRef(command?.seq);
|
|
44
|
+
const keysRef = useRef(itemKeys);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
keysRef.current = itemKeys;
|
|
47
|
+
});
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!command || command.seq === appliedSeq.current)
|
|
50
|
+
return;
|
|
51
|
+
appliedSeq.current = command.seq;
|
|
52
|
+
setToggled({ resetKey, open: new Map(keysRef.current.map((key) => [key, command.expanded])) });
|
|
53
|
+
}, [command, resetKey]);
|
|
54
|
+
return {
|
|
55
|
+
isExpanded,
|
|
56
|
+
setExpanded,
|
|
57
|
+
setAll,
|
|
58
|
+
allExpanded: itemKeys.length > 0 && itemKeys.every(isExpanded),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keys for the items of object lists and block lists. An object listed once keeps the key it
|
|
3
|
+
* was first shown with, so an append remounts no item, a removal never hands a crashed item's
|
|
4
|
+
* boundary to the next one, and an item put back by Undo (the same object) gets its key back. A
|
|
5
|
+
* list whose length is unchanged (an edited item, the saved copy of the same items) keeps keys by
|
|
6
|
+
* position. One instance serves every list a component renders, told apart by `listPath`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useListItemKeys(): (items: readonly unknown[], listPath: string) => string[];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Keys for the items of object lists and block lists. An object listed once keeps the key it
|
|
4
|
+
* was first shown with, so an append remounts no item, a removal never hands a crashed item's
|
|
5
|
+
* boundary to the next one, and an item put back by Undo (the same object) gets its key back. A
|
|
6
|
+
* list whose length is unchanged (an edited item, the saved copy of the same items) keeps keys by
|
|
7
|
+
* position. One instance serves every list a component renders, told apart by `listPath`.
|
|
8
|
+
*/
|
|
9
|
+
export function useListItemKeys() {
|
|
10
|
+
const listItemKeys = useRef(new WeakMap());
|
|
11
|
+
const lastListKeys = useRef(new Map());
|
|
12
|
+
const nextListItemKey = useRef(0);
|
|
13
|
+
return (items, listPath) => {
|
|
14
|
+
const previous = lastListKeys.current.get(listPath);
|
|
15
|
+
const occurrences = new Map();
|
|
16
|
+
for (const item of items) {
|
|
17
|
+
if (typeof item === 'object' && item !== null) {
|
|
18
|
+
occurrences.set(item, (occurrences.get(item) ?? 0) + 1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Only an object listed once has an identity; a repeated one is keyed by position.
|
|
22
|
+
const single = (item) => typeof item === 'object' && item !== null && occurrences.get(item) === 1;
|
|
23
|
+
const claimed = new Set();
|
|
24
|
+
const keys = items.map((item) => {
|
|
25
|
+
const own = single(item) ? listItemKeys.current.get(item) : undefined;
|
|
26
|
+
// Two objects can hold one key, an edited copy having inherited its original's.
|
|
27
|
+
if (own === undefined || claimed.has(own))
|
|
28
|
+
return undefined;
|
|
29
|
+
claimed.add(own);
|
|
30
|
+
return own;
|
|
31
|
+
});
|
|
32
|
+
// The rest inherit their position's key, never one an object present here holds.
|
|
33
|
+
const resolved = keys.map((key, idx) => {
|
|
34
|
+
if (key !== undefined)
|
|
35
|
+
return key;
|
|
36
|
+
let next = previous?.length === items.length ? previous[idx] : undefined;
|
|
37
|
+
if (next === undefined || claimed.has(next)) {
|
|
38
|
+
nextListItemKey.current += 1;
|
|
39
|
+
next = `item-${nextListItemKey.current}`;
|
|
40
|
+
}
|
|
41
|
+
claimed.add(next);
|
|
42
|
+
const item = items[idx];
|
|
43
|
+
if (single(item))
|
|
44
|
+
listItemKeys.current.set(item, next);
|
|
45
|
+
return next;
|
|
46
|
+
});
|
|
47
|
+
lastListKeys.current.set(listPath, resolved);
|
|
48
|
+
return resolved;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FieldConfig, ObjectFieldConfig } from '../../config/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* What an object-list item is called: its `itemTitleField` value when that is a non-blank
|
|
4
|
+
* string or a number, else its first non-blank single-line text field, else undefined.
|
|
5
|
+
*/
|
|
6
|
+
export declare const listItemTitle: (item: unknown, objectField: Pick<ObjectFieldConfig, "fields" | "itemTitleField">) => string | undefined;
|
|
7
|
+
type ItemNaming = Pick<ObjectFieldConfig, 'fields' | 'itemTitleField' | 'itemLabel'>;
|
|
8
|
+
/** An object-list item's card heading: its title, else its positional title (1-based). */
|
|
9
|
+
export declare const listItemHeading: (item: unknown, objectField: ItemNaming, index: number) => string;
|
|
10
|
+
/**
|
|
11
|
+
* The second value a collapsed row shows beside its title: the first non-blank single-line text
|
|
12
|
+
* field other than the one `exclude` names, so a row never repeats its title.
|
|
13
|
+
*/
|
|
14
|
+
export declare const listItemSecondary: (item: unknown, fields: readonly FieldConfig[], exclude?: string) => string | undefined;
|
|
15
|
+
/** A collapsed object-list row's title and secondary value. */
|
|
16
|
+
export declare const listItemSummary: (item: unknown, objectField: ItemNaming, index: number) => {
|
|
17
|
+
title: string;
|
|
18
|
+
secondary?: string;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const MAX_TITLE_LENGTH = 60;
|
|
2
|
+
const shorten = (text) => text.length > MAX_TITLE_LENGTH ? `${text.slice(0, MAX_TITLE_LENGTH - 1)}…` : text;
|
|
3
|
+
/** The item's own fields, with inline groups opened up, since groups are transparent to values. */
|
|
4
|
+
const flattenFields = (fields) => fields.flatMap((f) => (f.type === 'group' && 'fields' in f ? flattenFields(f.fields) : [f]));
|
|
5
|
+
const asRecord = (item) => item && typeof item === 'object' && !Array.isArray(item)
|
|
6
|
+
? item
|
|
7
|
+
: undefined;
|
|
8
|
+
/** A value worth showing on one line: a non-blank string's first line, or a finite number. */
|
|
9
|
+
const shownText = (raw) => {
|
|
10
|
+
if (typeof raw === 'number' && Number.isFinite(raw))
|
|
11
|
+
return String(raw);
|
|
12
|
+
if (typeof raw === 'string' && raw.trim() !== '')
|
|
13
|
+
return shorten(raw.trim().split('\n')[0]);
|
|
14
|
+
return undefined;
|
|
15
|
+
};
|
|
16
|
+
/** A select's value as its option's label, which is what an editor picked it by. */
|
|
17
|
+
const optionLabel = (field, value) => {
|
|
18
|
+
const option = (field.options ?? []).find((o) => (typeof o === 'string' ? o : o.value) === value);
|
|
19
|
+
return option === undefined || typeof option === 'string' ? value : option.label;
|
|
20
|
+
};
|
|
21
|
+
/** The item's single-line text fields, in schema order: strings, numbers and single selects. */
|
|
22
|
+
const textFields = (fields) => flattenFields(fields).filter((f) => (f.type === 'string' || f.type === 'number' || f.type === 'select') && !f.list);
|
|
23
|
+
/**
|
|
24
|
+
* Which field titles an object-list item, and its text: its `itemTitleField` value when that is
|
|
25
|
+
* a non-blank string or a number, else its first non-blank single-line string field.
|
|
26
|
+
*/
|
|
27
|
+
const titleSource = (record, objectField) => {
|
|
28
|
+
const named = objectField.itemTitleField;
|
|
29
|
+
const raw = named ? record[named] : undefined;
|
|
30
|
+
if (named && typeof raw === 'number' && Number.isFinite(raw))
|
|
31
|
+
return { name: named, text: String(raw) };
|
|
32
|
+
if (named && typeof raw === 'string' && raw.trim() !== '') {
|
|
33
|
+
return { name: named, text: shorten(raw.trim()) };
|
|
34
|
+
}
|
|
35
|
+
for (const f of flattenFields(objectField.fields)) {
|
|
36
|
+
if (f.type !== 'string' || f.list)
|
|
37
|
+
continue;
|
|
38
|
+
const value = record[f.name];
|
|
39
|
+
if (typeof value === 'string' && value.trim() !== '') {
|
|
40
|
+
return { name: f.name, text: shorten(value.trim()) };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* What an object-list item is called: its `itemTitleField` value when that is a non-blank
|
|
47
|
+
* string or a number, else its first non-blank single-line text field, else undefined.
|
|
48
|
+
*/
|
|
49
|
+
export const listItemTitle = (item, objectField) => {
|
|
50
|
+
const record = asRecord(item);
|
|
51
|
+
return record ? titleSource(record, objectField)?.text : undefined;
|
|
52
|
+
};
|
|
53
|
+
/** What an untitled item is called by position: "Item 3", or "Team member 3" from `itemLabel`. */
|
|
54
|
+
const positionalTitle = (objectField, index) => {
|
|
55
|
+
const noun = objectField.itemLabel ?? 'item';
|
|
56
|
+
return `${noun.charAt(0).toUpperCase()}${noun.slice(1)} ${index + 1}`;
|
|
57
|
+
};
|
|
58
|
+
/** An object-list item's card heading: its title, else its positional title (1-based). */
|
|
59
|
+
export const listItemHeading = (item, objectField, index) => listItemTitle(item, objectField) ?? positionalTitle(objectField, index);
|
|
60
|
+
/**
|
|
61
|
+
* The second value a collapsed row shows beside its title: the first non-blank single-line text
|
|
62
|
+
* field other than the one `exclude` names, so a row never repeats its title.
|
|
63
|
+
*/
|
|
64
|
+
export const listItemSecondary = (item, fields, exclude) => {
|
|
65
|
+
const record = asRecord(item);
|
|
66
|
+
if (!record)
|
|
67
|
+
return undefined;
|
|
68
|
+
for (const f of textFields(fields)) {
|
|
69
|
+
if (f.name === exclude)
|
|
70
|
+
continue;
|
|
71
|
+
const text = shownText(f.type === 'select' ? optionLabel(f, record[f.name]) : record[f.name]);
|
|
72
|
+
if (text !== undefined)
|
|
73
|
+
return text;
|
|
74
|
+
}
|
|
75
|
+
return undefined;
|
|
76
|
+
};
|
|
77
|
+
/** A collapsed object-list row's title and secondary value. */
|
|
78
|
+
export const listItemSummary = (item, objectField, index) => {
|
|
79
|
+
const record = asRecord(item);
|
|
80
|
+
const source = record ? titleSource(record, objectField) : undefined;
|
|
81
|
+
return {
|
|
82
|
+
title: source?.text ?? positionalTitle(objectField, index),
|
|
83
|
+
secondary: listItemSecondary(item, objectField.fields, source?.name),
|
|
84
|
+
};
|
|
85
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MarkdownField's MDXEditor visitors for markdown its own import and export would change the
|
|
3
|
+
* meaning of: an ordered list's `start`, a link inside a formatted span, an auto-link inside code,
|
|
4
|
+
* and the code spans either side of one. MDXEditor is passed in, as `mdx-jsx-support.tsx`
|
|
5
|
+
* explains.
|
|
6
|
+
*/
|
|
7
|
+
import type * as MdxEditor from '@mdxeditor/editor';
|
|
8
|
+
type MdxEditorModule = typeof MdxEditor;
|
|
9
|
+
/** Creates the plugin from MDXEditor's exports; call once per load of MDXEditor. */
|
|
10
|
+
export declare function createMarkdownFidelityPlugin(mdx: MdxEditorModule): () => MdxEditor.RealmPlugin;
|
|
11
|
+
export {};
|