canopycms 0.0.67-int.90 → 0.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -3
- package/dist/ai/generate.js +1 -27
- package/dist/ai/handler.d.ts +0 -4
- package/dist/ai/handler.js +0 -11
- package/dist/ai/index.d.ts +1 -8
- package/dist/ai/index.js +1 -8
- package/dist/ai/json-to-markdown.js +15 -58
- package/dist/ai/resolve-branch.d.ts +2 -7
- package/dist/ai/resolve-branch.js +2 -8
- package/dist/ai/strip-mdx.d.ts +5 -13
- package/dist/ai/strip-mdx.js +5 -17
- package/dist/ai/to-plain-text.d.ts +10 -28
- package/dist/ai/to-plain-text.js +10 -28
- package/dist/ai/transform-components.d.ts +2 -4
- package/dist/ai/transform-components.js +8 -19
- package/dist/ai/types.d.ts +5 -10
- package/dist/api/admin-branch-health.d.ts +4 -12
- package/dist/api/admin-branch-health.js +26 -66
- package/dist/api/admin.d.ts +4 -12
- package/dist/api/admin.js +10 -26
- package/dist/api/assets.d.ts +0 -25
- package/dist/api/assets.js +50 -91
- package/dist/api/branch-merge.d.ts +1 -1
- package/dist/api/branch-merge.js +0 -2
- package/dist/api/branch-review.d.ts +0 -8
- package/dist/api/branch-review.js +0 -13
- package/dist/api/branch-status.d.ts +0 -3
- package/dist/api/branch-status.js +8 -33
- package/dist/api/branch-withdraw.d.ts +0 -1
- package/dist/api/branch-withdraw.js +6 -9
- package/dist/api/branch.d.ts +7 -12
- package/dist/api/branch.js +7 -44
- package/dist/api/client.d.ts +71 -224
- package/dist/api/client.js +82 -233
- package/dist/api/comments.d.ts +2 -4
- package/dist/api/comments.js +0 -17
- package/dist/api/content.d.ts +0 -6
- package/dist/api/content.js +66 -142
- package/dist/api/entries-constants.d.ts +5 -9
- package/dist/api/entries-constants.js +5 -9
- package/dist/api/entries.d.ts +8 -13
- package/dist/api/entries.js +20 -51
- package/dist/api/github-sync.d.ts +2 -4
- package/dist/api/github-sync.js +4 -8
- package/dist/api/groups.d.ts +3 -0
- package/dist/api/groups.js +8 -21
- package/dist/api/guards.d.ts +4 -16
- package/dist/api/guards.js +3 -22
- package/dist/api/index.d.ts +4 -4
- package/dist/api/permissions.d.ts +2 -0
- package/dist/api/permissions.js +18 -40
- package/dist/api/reference-options.d.ts +0 -1
- package/dist/api/reference-options.js +3 -11
- package/dist/api/request-body-hash.d.ts +12 -23
- package/dist/api/request-body-hash.js +12 -23
- package/dist/api/resolve-references.d.ts +0 -1
- package/dist/api/resolve-references.js +13 -28
- package/dist/api/route-builder.d.ts +3 -7
- package/dist/api/route-builder.js +1 -1
- package/dist/api/routes.d.ts +12 -0
- package/dist/api/routes.js +47 -0
- package/dist/api/schema.d.ts +23 -33
- package/dist/api/schema.js +20 -74
- package/dist/api/settings-helpers.js +4 -5
- package/dist/api/types.d.ts +0 -5
- package/dist/api/user.js +0 -5
- package/dist/api/validators.d.ts +14 -52
- package/dist/api/validators.js +14 -52
- package/dist/assets/asset-prefixes.d.ts +4 -8
- package/dist/assets/asset-prefixes.js +4 -8
- package/dist/assets/asset-src.d.ts +5 -22
- package/dist/assets/asset-src.js +5 -21
- package/dist/assets/factory.d.ts +1 -2
- package/dist/assets/factory.js +1 -2
- package/dist/assets/finalize.d.ts +3 -1
- package/dist/assets/finalize.js +3 -1
- package/dist/assets/index.d.ts +3 -3
- package/dist/assets/index.js +1 -1
- package/dist/assets/keys.d.ts +5 -3
- package/dist/assets/keys.js +6 -3
- package/dist/assets/pipeline.d.ts +3 -2
- package/dist/assets/pipeline.js +22 -56
- package/dist/assets/sharp-loader.d.ts +2 -10
- package/dist/assets/sharp-loader.js +2 -10
- package/dist/assets/store-local.d.ts +1 -2
- package/dist/assets/store-local.js +1 -2
- package/dist/assets/store-s3.d.ts +3 -4
- package/dist/assets/svg-sanitizer.d.ts +6 -14
- package/dist/assets/svg-sanitizer.js +6 -14
- package/dist/assets/transform-directives.d.ts +3 -4
- package/dist/assets/transform-directives.js +1 -1
- package/dist/assets/transform.d.ts +19 -30
- package/dist/assets/transform.js +18 -31
- package/dist/auth/cache.d.ts +2 -3
- package/dist/auth/cache.js +2 -3
- package/dist/auth/caching-auth-plugin.d.ts +11 -22
- package/dist/auth/caching-auth-plugin.js +12 -14
- package/dist/auth/context-helpers.d.ts +6 -20
- package/dist/auth/context-helpers.js +5 -17
- package/dist/auth/file-based-auth-cache.d.ts +10 -21
- package/dist/auth/file-based-auth-cache.js +23 -51
- package/dist/auth/plugin.d.ts +29 -61
- package/dist/auth/plugin.js +9 -13
- package/dist/auth/types.d.ts +11 -20
- package/dist/authorization/branch.d.ts +30 -49
- package/dist/authorization/branch.js +16 -42
- package/dist/authorization/content.d.ts +11 -40
- package/dist/authorization/content.js +13 -45
- package/dist/authorization/groups/index.d.ts +0 -3
- package/dist/authorization/groups/index.js +0 -3
- package/dist/authorization/groups/loader.d.ts +14 -28
- package/dist/authorization/groups/loader.js +14 -38
- package/dist/authorization/groups/schema.d.ts +0 -6
- package/dist/authorization/groups/schema.js +4 -7
- package/dist/authorization/helpers.d.ts +9 -28
- package/dist/authorization/helpers.js +9 -28
- package/dist/authorization/index.d.ts +3 -25
- package/dist/authorization/index.js +3 -35
- package/dist/authorization/path.d.ts +6 -13
- package/dist/authorization/path.js +8 -25
- package/dist/authorization/permissions/index.d.ts +0 -3
- package/dist/authorization/permissions/index.js +0 -3
- package/dist/authorization/permissions/loader.d.ts +14 -27
- package/dist/authorization/permissions/loader.js +14 -32
- package/dist/authorization/permissions/schema.d.ts +1 -6
- package/dist/authorization/permissions/schema.js +6 -13
- package/dist/authorization/protected-branch.d.ts +36 -65
- package/dist/authorization/protected-branch.js +29 -41
- package/dist/authorization/settings-file-store.d.ts +38 -81
- package/dist/authorization/settings-file-store.js +38 -79
- package/dist/authorization/types.d.ts +4 -26
- package/dist/authorization/types.js +0 -6
- package/dist/authorization/validation.d.ts +1 -23
- package/dist/authorization/validation.js +1 -24
- package/dist/branch-health.d.ts +39 -67
- package/dist/branch-health.js +27 -43
- package/dist/branch-metadata-file.d.ts +16 -32
- package/dist/branch-metadata-file.js +13 -26
- package/dist/branch-metadata.d.ts +49 -80
- package/dist/branch-metadata.js +57 -87
- package/dist/branch-registry.d.ts +26 -64
- package/dist/branch-registry.js +44 -93
- package/dist/branch-schema-cache.d.ts +34 -124
- package/dist/branch-schema-cache.js +49 -155
- package/dist/branch-workspace.d.ts +4 -4
- package/dist/branch-workspace.js +15 -19
- package/dist/build/generate-ai-content.d.ts +1 -0
- package/dist/build/generate-ai-content.js +12 -25
- package/dist/build-canopy.d.ts +17 -27
- package/dist/build-canopy.js +16 -23
- package/dist/build-mode.d.ts +25 -27
- package/dist/build-mode.js +25 -29
- package/dist/cli/cli.d.ts +15 -26
- package/dist/cli/cli.js +601 -978
- package/dist/cli/generate-ai-content.js +351 -628
- package/dist/cli/github-app-manifest.d.ts +84 -0
- package/dist/cli/github-app-manifest.js +161 -0
- package/dist/cli/init-github-app.d.ts +110 -444
- package/dist/cli/init-github-app.js +236 -773
- package/dist/cli/init.js +39 -80
- package/dist/cli/migrate.d.ts +13 -10
- package/dist/cli/migrate.js +22 -30
- package/dist/cli/project-detect.d.ts +17 -31
- package/dist/cli/project-detect.js +31 -42
- package/dist/cli/project-root.d.ts +4 -11
- package/dist/cli/project-root.js +4 -11
- package/dist/cli/prompt.d.ts +10 -0
- package/dist/cli/prompt.js +67 -0
- package/dist/cli/sync.d.ts +0 -8
- package/dist/cli/sync.js +8 -28
- package/dist/cli/template-files/middleware.ts.template +15 -29
- package/dist/cli/templates.d.ts +2 -12
- package/dist/cli/templates.js +4 -4
- package/dist/client.d.ts +1 -1
- package/dist/comment-store.d.ts +32 -53
- package/dist/comment-store.js +32 -52
- package/dist/config/flatten.d.ts +0 -3
- package/dist/config/flatten.js +2 -12
- package/dist/config/helpers.js +2 -2
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +1 -4
- package/dist/config/schemas/collection.d.ts +0 -8
- package/dist/config/schemas/collection.js +0 -10
- package/dist/config/schemas/config.d.ts +6 -78
- package/dist/config/schemas/config.js +38 -54
- package/dist/config/schemas/field.d.ts +2 -242
- package/dist/config/schemas/field.js +9 -20
- package/dist/config/schemas/media.js +1 -1
- package/dist/config/schemas/permissions.js +0 -2
- package/dist/config/schemas/url.d.ts +5 -6
- package/dist/config/schemas/url.js +5 -6
- package/dist/config/types.d.ts +45 -33
- package/dist/config/types.js +0 -1
- package/dist/config.d.ts +1 -8
- package/dist/config.js +1 -9
- package/dist/content-id-index.d.ts +76 -188
- package/dist/content-id-index.js +79 -230
- package/dist/content-index-generation.d.ts +27 -48
- package/dist/content-index-generation.js +35 -84
- package/dist/content-index-registry.d.ts +15 -24
- package/dist/content-index-registry.js +5 -9
- package/dist/content-listing.d.ts +64 -107
- package/dist/content-listing.js +68 -118
- package/dist/content-reader.d.ts +20 -29
- package/dist/content-reader.js +10 -18
- package/dist/content-store.d.ts +210 -336
- package/dist/content-store.js +413 -657
- package/dist/content-tree.d.ts +44 -86
- package/dist/content-tree.js +26 -54
- package/dist/context.d.ts +67 -94
- package/dist/context.js +53 -72
- package/dist/dev-content-watcher.d.ts +18 -18
- package/dist/dev-content-watcher.js +41 -44
- package/dist/editor/BranchManager.d.ts +3 -6
- package/dist/editor/BranchManager.js +24 -44
- package/dist/editor/CanopyEditor.js +5 -2
- package/dist/editor/CommentsPanel.js +0 -2
- package/dist/editor/Editor.js +19 -76
- package/dist/editor/EditorAuthGate.d.ts +27 -0
- package/dist/editor/EditorAuthGate.js +140 -0
- package/dist/editor/EntryNavigator.js +0 -20
- package/dist/editor/FormRenderer.d.ts +1 -2
- package/dist/editor/FormRenderer.js +8 -23
- package/dist/editor/admin/SystemHealthPanel.js +20 -37
- package/dist/editor/admin/useSystemHealth.d.ts +2 -3
- package/dist/editor/admin/useSystemHealth.js +10 -12
- package/dist/editor/client-reference-resolver.d.ts +2 -5
- package/dist/editor/client-reference-resolver.js +2 -19
- package/dist/editor/comments/BranchComments.js +0 -4
- package/dist/editor/comments/EntryComments.js +0 -4
- package/dist/editor/comments/FieldWrapper.js +0 -4
- package/dist/editor/comments/InlineCommentThread.js +0 -2
- package/dist/editor/comments/ThreadCarousel.d.ts +0 -58
- package/dist/editor/comments/ThreadCarousel.js +0 -12
- package/dist/editor/components/EditorFooter.d.ts +0 -8
- package/dist/editor/components/EditorFooter.js +0 -5
- package/dist/editor/components/EditorHeader.d.ts +0 -31
- package/dist/editor/components/EditorHeader.js +21 -71
- package/dist/editor/components/EditorSidebar.d.ts +0 -19
- package/dist/editor/components/EditorSidebar.js +0 -16
- package/dist/editor/components/EntryCreateModal.d.ts +4 -4
- package/dist/editor/components/EntryCreateModal.js +7 -22
- package/dist/editor/components/RenameEntryModal.js +0 -4
- package/dist/editor/components/UserBadge.js +0 -10
- package/dist/editor/components/index.js +0 -2
- package/dist/editor/context/ApiClientContext.d.ts +8 -7
- package/dist/editor/context/ApiClientContext.js +39 -11
- package/dist/editor/context/AssetContext.d.ts +7 -17
- package/dist/editor/context/AssetContext.js +7 -17
- package/dist/editor/context/EditorIdentityContext.d.ts +13 -0
- package/dist/editor/context/EditorIdentityContext.js +7 -0
- package/dist/editor/context/EditorStateContext.d.ts +10 -41
- package/dist/editor/context/EditorStateContext.js +7 -23
- package/dist/editor/context/SWRProvider.d.ts +3 -6
- package/dist/editor/context/index.d.ts +1 -20
- package/dist/editor/context/index.js +1 -20
- package/dist/editor/editor-utils.d.ts +8 -47
- package/dist/editor/editor-utils.js +19 -72
- package/dist/editor/fields/BlockField.d.ts +2 -2
- package/dist/editor/fields/BlockField.js +1 -2
- package/dist/editor/fields/CodeField.d.ts +0 -1
- package/dist/editor/fields/CodeField.js +0 -1
- package/dist/editor/fields/DateTimeField.d.ts +15 -22
- package/dist/editor/fields/DateTimeField.js +17 -26
- package/dist/editor/fields/ImageField.d.ts +2 -2
- package/dist/editor/fields/ImageField.js +8 -14
- package/dist/editor/fields/InlineGroupField.d.ts +0 -1
- package/dist/editor/fields/InlineGroupField.js +0 -1
- package/dist/editor/fields/MarkdownField.d.ts +0 -1
- package/dist/editor/fields/MarkdownField.js +6 -11
- package/dist/editor/fields/MdxImageDialog.d.ts +1 -1
- package/dist/editor/fields/MdxImageDialog.js +0 -1
- package/dist/editor/fields/NumberField.d.ts +9 -19
- package/dist/editor/fields/NumberField.js +11 -22
- package/dist/editor/fields/NumberListField.d.ts +7 -10
- package/dist/editor/fields/NumberListField.js +7 -10
- package/dist/editor/fields/ObjectField.d.ts +5 -8
- package/dist/editor/fields/ObjectField.js +0 -1
- package/dist/editor/fields/ReferenceField.d.ts +1 -1
- package/dist/editor/fields/ReferenceField.js +11 -16
- package/dist/editor/fields/SelectField.d.ts +2 -2
- package/dist/editor/fields/SelectField.js +0 -1
- package/dist/editor/fields/StringListField.d.ts +0 -4
- package/dist/editor/fields/StringListField.js +4 -9
- package/dist/editor/fields/TextField.d.ts +0 -1
- package/dist/editor/fields/TextField.js +0 -1
- package/dist/editor/fields/ToggleField.d.ts +0 -1
- package/dist/editor/fields/ToggleField.js +0 -1
- package/dist/editor/fields/entry-link/EntryLinkContext.js +2 -4
- package/dist/editor/fields/entry-link/InsertEntryLink.d.ts +0 -3
- package/dist/editor/fields/entry-link/InsertEntryLink.js +0 -4
- package/dist/editor/group-manager/ExternalGroupsTab.d.ts +0 -3
- package/dist/editor/group-manager/ExternalGroupsTab.js +0 -1
- package/dist/editor/group-manager/GroupCard.d.ts +0 -3
- package/dist/editor/group-manager/GroupForm.d.ts +0 -3
- package/dist/editor/group-manager/InternalGroupsTab.d.ts +0 -3
- package/dist/editor/group-manager/InternalGroupsTab.js +0 -2
- package/dist/editor/group-manager/MemberList.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useExternalGroupSearch.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useExternalGroupSearch.js +0 -3
- package/dist/editor/group-manager/hooks/useGroupState.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useGroupState.js +0 -5
- package/dist/editor/group-manager/hooks/useUserSearch.d.ts +0 -3
- package/dist/editor/group-manager/hooks/useUserSearch.js +0 -3
- package/dist/editor/group-manager/index.d.ts +0 -6
- package/dist/editor/group-manager/index.js +0 -10
- package/dist/editor/group-manager/types.d.ts +2 -5
- package/dist/editor/group-manager/types.js +0 -3
- package/dist/editor/hooks/index.d.ts +6 -11
- package/dist/editor/hooks/index.js +6 -12
- package/dist/editor/hooks/useBranchActions.d.ts +0 -14
- package/dist/editor/hooks/useBranchActions.js +0 -22
- package/dist/editor/hooks/useBranchManager.d.ts +2 -48
- package/dist/editor/hooks/useBranchManager.js +4 -64
- package/dist/editor/hooks/useBranchesData.d.ts +7 -6
- package/dist/editor/hooks/useBranchesData.js +7 -6
- package/dist/editor/hooks/useCommentSystem.d.ts +0 -49
- package/dist/editor/hooks/useCommentSystem.js +1 -36
- package/dist/editor/hooks/useDraftManager.d.ts +2 -35
- package/dist/editor/hooks/useDraftManager.js +23 -64
- package/dist/editor/hooks/useEditorLayout.d.ts +0 -20
- package/dist/editor/hooks/useEditorLayout.js +0 -23
- package/dist/editor/hooks/useEntriesData.d.ts +1 -0
- package/dist/editor/hooks/useEntriesData.js +2 -3
- package/dist/editor/hooks/useEntryLinkResolution.d.ts +2 -2
- package/dist/editor/hooks/useEntryLinkResolution.js +2 -2
- package/dist/editor/hooks/useEntryManager.d.ts +2 -27
- package/dist/editor/hooks/useEntryManager.js +29 -78
- package/dist/editor/hooks/useGroupManager.d.ts +0 -21
- package/dist/editor/hooks/useGroupManager.js +0 -21
- package/dist/editor/hooks/usePermissionManager.d.ts +0 -20
- package/dist/editor/hooks/usePermissionManager.js +0 -20
- package/dist/editor/hooks/useReferenceResolution.d.ts +2 -33
- package/dist/editor/hooks/useReferenceResolution.js +1 -48
- package/dist/editor/hooks/useSchemaManager.d.ts +8 -27
- package/dist/editor/hooks/useSchemaManager.js +0 -19
- package/dist/editor/hooks/useUserContext.d.ts +2 -9
- package/dist/editor/hooks/useUserContext.js +10 -10
- package/dist/editor/hooks/useUserMetadata.d.ts +0 -2
- package/dist/editor/hooks/useUserMetadata.js +0 -3
- package/dist/editor/media/AssetCard.d.ts +0 -1
- package/dist/editor/media/AssetCard.js +1 -2
- package/dist/editor/media/CropStep.d.ts +0 -1
- package/dist/editor/media/CropStep.js +0 -1
- package/dist/editor/media/MediaLibrary.d.ts +1 -2
- package/dist/editor/media/MediaLibrary.js +1 -2
- package/dist/editor/media/MediaLibraryBody.d.ts +0 -1
- package/dist/editor/media/MediaLibraryBody.js +0 -1
- package/dist/editor/media/crop-math.d.ts +1 -1
- package/dist/editor/media/crop-math.js +1 -1
- package/dist/editor/permission-manager/GroupSelector.d.ts +0 -3
- package/dist/editor/permission-manager/PermissionEditor.d.ts +0 -4
- package/dist/editor/permission-manager/PermissionEditor.js +0 -1
- package/dist/editor/permission-manager/PermissionLevelBadge.d.ts +0 -7
- package/dist/editor/permission-manager/PermissionLevelBadge.js +0 -4
- package/dist/editor/permission-manager/PermissionTree.d.ts +0 -4
- package/dist/editor/permission-manager/UserSelector.d.ts +0 -3
- package/dist/editor/permission-manager/constants.d.ts +0 -3
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.d.ts +0 -3
- package/dist/editor/permission-manager/hooks/useGroupsAndUsers.js +0 -10
- package/dist/editor/permission-manager/hooks/usePermissionTree.d.ts +0 -14
- package/dist/editor/permission-manager/hooks/usePermissionTree.js +0 -11
- package/dist/editor/permission-manager/index.d.ts +0 -7
- package/dist/editor/permission-manager/index.js +0 -16
- package/dist/editor/permission-manager/types.d.ts +2 -12
- package/dist/editor/permission-manager/types.js +0 -3
- package/dist/editor/permission-manager/utils.d.ts +0 -28
- package/dist/editor/permission-manager/utils.js +9 -23
- package/dist/editor/preview-bridge.d.ts +5 -1
- package/dist/editor/preview-bridge.js +4 -4
- package/dist/editor/schema-editor/CollectionEditor.d.ts +0 -5
- package/dist/editor/schema-editor/CollectionEditor.js +9 -31
- package/dist/editor/schema-editor/EntryTypeEditor.d.ts +0 -6
- package/dist/editor/schema-editor/EntryTypeEditor.js +3 -24
- package/dist/editor/schema-editor/index.d.ts +0 -7
- package/dist/editor/schema-editor/index.js +0 -7
- package/dist/editor/utils/env.d.ts +3 -18
- package/dist/editor/utils/env.js +6 -25
- package/dist/entry-link-resolver.d.ts +13 -35
- package/dist/entry-link-resolver.js +20 -53
- package/dist/entry-schema-registry.d.ts +20 -60
- package/dist/entry-schema-registry.js +20 -69
- package/dist/entry-schema.d.ts +118 -223
- package/dist/entry-schema.js +46 -91
- package/dist/git-manager.d.ts +101 -200
- package/dist/git-manager.js +211 -384
- package/dist/github-service.d.ts +34 -75
- package/dist/github-service.js +37 -91
- package/dist/http/handler.d.ts +6 -37
- package/dist/http/handler.js +65 -120
- package/dist/http/router.d.ts +15 -32
- package/dist/http/router.js +34 -99
- package/dist/http/types.d.ts +15 -40
- package/dist/http/types.js +3 -7
- package/dist/id.d.ts +4 -10
- package/dist/id.js +4 -10
- package/dist/index.js +6 -9
- package/dist/operating-mode/client-safe-strategy.d.ts +7 -14
- package/dist/operating-mode/client-safe-strategy.js +8 -28
- package/dist/operating-mode/client-unsafe-strategy.d.ts +6 -16
- package/dist/operating-mode/client-unsafe-strategy.js +9 -34
- package/dist/operating-mode/client.d.ts +3 -10
- package/dist/operating-mode/client.js +3 -8
- package/dist/operating-mode/deployment-name-fixtures.d.ts +14 -18
- package/dist/operating-mode/deployment-name-fixtures.js +14 -18
- package/dist/operating-mode/deployment-name.d.ts +19 -29
- package/dist/operating-mode/deployment-name.js +29 -47
- package/dist/operating-mode/index.d.ts +4 -25
- package/dist/operating-mode/index.js +9 -31
- package/dist/operating-mode/mode-env.d.ts +32 -54
- package/dist/operating-mode/mode-env.js +36 -58
- package/dist/operating-mode/types.d.ts +24 -72
- package/dist/operating-mode/types.js +1 -7
- package/dist/paths/branch-name.d.ts +30 -40
- package/dist/paths/branch-name.js +30 -40
- package/dist/paths/branch.d.ts +4 -18
- package/dist/paths/branch.js +6 -22
- package/dist/paths/index.d.ts +2 -13
- package/dist/paths/index.js +3 -23
- package/dist/paths/normalize-server.d.ts +3 -15
- package/dist/paths/normalize-server.js +3 -15
- package/dist/paths/normalize.d.ts +13 -33
- package/dist/paths/normalize.js +13 -33
- package/dist/paths/resolve.d.ts +4 -17
- package/dist/paths/resolve.js +4 -22
- package/dist/paths/types.d.ts +12 -34
- package/dist/paths/types.js +5 -7
- package/dist/paths/validation.d.ts +22 -119
- package/dist/paths/validation.js +30 -148
- package/dist/reference-resolver.d.ts +0 -13
- package/dist/reference-resolver.js +0 -18
- package/dist/resolve-canopy-user.d.ts +16 -18
- package/dist/resolve-canopy-user.js +17 -26
- package/dist/resource-generation.d.ts +16 -25
- package/dist/resource-generation.js +34 -97
- package/dist/schema/meta-loader.d.ts +2 -14
- package/dist/schema/meta-loader.js +15 -64
- package/dist/schema/resolver.d.ts +1 -4
- package/dist/schema/resolver.js +1 -6
- package/dist/schema/schema-store-types.d.ts +0 -12
- package/dist/schema/schema-store.d.ts +61 -138
- package/dist/schema/schema-store.js +85 -282
- package/dist/schema/types.d.ts +0 -4
- package/dist/server.d.ts +62 -93
- package/dist/server.js +63 -94
- package/dist/services.d.ts +23 -47
- package/dist/services.js +55 -98
- package/dist/settings-workspace.d.ts +17 -30
- package/dist/settings-workspace.js +51 -81
- package/dist/static/index.d.ts +26 -52
- package/dist/static/index.js +33 -67
- package/dist/{worker/task-queue.d.ts → task-queue/cms-task-queue.d.ts} +7 -9
- package/dist/task-queue/cms-task-queue.js +13 -0
- package/dist/task-queue/task-queue-config.d.ts +3 -0
- package/dist/{worker → task-queue}/task-queue-config.js +1 -6
- package/dist/task-queue/task-queue.d.ts +16 -22
- package/dist/task-queue/task-queue.js +20 -44
- package/dist/task-queue/types.d.ts +0 -1
- package/dist/task-queue/worker-status.d.ts +35 -0
- package/dist/task-queue/worker-status.js +40 -0
- package/dist/types.d.ts +40 -51
- package/dist/url-collision.d.ts +26 -40
- package/dist/url-collision.js +47 -63
- package/dist/url-exclusivity-fixtures.d.ts +15 -20
- package/dist/url-exclusivity-fixtures.js +14 -19
- package/dist/url-path-resolver.d.ts +8 -16
- package/dist/url-path-resolver.js +19 -29
- package/dist/user.d.ts +8 -21
- package/dist/user.js +10 -19
- package/dist/utils/async-mutex.js +4 -6
- package/dist/utils/atomic-write.d.ts +2 -11
- package/dist/utils/atomic-write.js +2 -11
- package/dist/utils/body-field.d.ts +8 -15
- package/dist/utils/body-field.js +8 -15
- package/dist/utils/content-serialize.d.ts +18 -24
- package/dist/utils/content-serialize.js +109 -160
- package/dist/utils/content-write-lock.d.ts +51 -106
- package/dist/utils/content-write-lock.js +66 -111
- package/dist/utils/debug.d.ts +7 -23
- package/dist/utils/debug.js +7 -23
- package/dist/utils/entry-url.d.ts +11 -23
- package/dist/utils/entry-url.js +11 -26
- package/dist/utils/error.d.ts +25 -90
- package/dist/utils/error.js +60 -147
- package/dist/utils/flatten-group-fields.d.ts +5 -7
- package/dist/utils/flatten-group-fields.js +5 -7
- package/dist/utils/format.d.ts +1 -5
- package/dist/utils/format.js +1 -5
- package/dist/utils/fs.d.ts +3 -4
- package/dist/utils/fs.js +3 -4
- package/dist/utils/git.d.ts +52 -83
- package/dist/utils/git.js +79 -125
- package/dist/utils/logger.d.ts +35 -50
- package/dist/utils/logger.js +35 -52
- package/dist/utils/provisioning-lock.d.ts +23 -35
- package/dist/utils/provisioning-lock.js +49 -69
- package/dist/utils/sanitize-href.d.ts +5 -10
- package/dist/utils/sanitize-href.js +8 -18
- package/dist/utils/title-field.d.ts +17 -20
- package/dist/utils/title-field.js +18 -27
- package/dist/utils/typed-filename.d.ts +20 -48
- package/dist/utils/typed-filename.js +25 -61
- package/dist/utils/url-prefix.d.ts +3 -3
- package/dist/utils/url-prefix.js +3 -3
- package/dist/validation/block-structural-keys.d.ts +16 -31
- package/dist/validation/block-structural-keys.js +19 -29
- package/dist/validation/deletion-checker.d.ts +0 -34
- package/dist/validation/deletion-checker.js +1 -43
- package/dist/validation/entry-link-validator.d.ts +6 -13
- package/dist/validation/entry-link-validator.js +4 -13
- package/dist/validation/entry-type-reference-validator.d.ts +13 -18
- package/dist/validation/entry-type-reference-validator.js +13 -18
- package/dist/validation/entry-validator.d.ts +13 -25
- package/dist/validation/entry-validator.js +15 -32
- package/dist/validation/field-traversal.d.ts +3 -30
- package/dist/validation/field-traversal.js +1 -32
- package/dist/validation/reference-validator.d.ts +5 -24
- package/dist/validation/reference-validator.js +5 -30
- package/dist/worker/cms-worker.d.ts +172 -232
- package/dist/worker/cms-worker.js +241 -333
- package/dist/worker/git-sync.d.ts +32 -133
- package/dist/worker/git-sync.js +129 -191
- package/dist/worker/github-auth.d.ts +13 -19
- package/dist/worker/github-auth.js +13 -19
- package/dist/worker/history-rewrite.d.ts +53 -66
- package/dist/worker/history-rewrite.js +54 -60
- package/dist/worker/log.d.ts +24 -41
- package/dist/worker/log.js +25 -42
- package/dist/worker/rebase.d.ts +20 -110
- package/dist/worker/rebase.js +279 -354
- package/dist/worker/task-runner.d.ts +32 -66
- package/dist/worker/task-runner.js +126 -162
- package/dist/worker/worker-context.d.ts +41 -81
- package/package.json +4 -4
- package/dist/cli/template-files/middleware-clerk.ts.template +0 -37
- package/dist/worker/task-queue-config.d.ts +0 -8
- package/dist/worker/task-queue.js +0 -19
- package/dist/worker/worker-status.d.ts +0 -47
- package/dist/worker/worker-status.js +0 -52
|
@@ -27,7 +27,6 @@ const normalizeOptions = (options) => {
|
|
|
27
27
|
};
|
|
28
28
|
const fieldKey = (path) => formatCanopyPath(path);
|
|
29
29
|
export const FormRenderer = ({ fields, value, onChange, customRenderers, branch = 'main', comments = [], currentEntryPath, currentUserId, canResolve = false, focusedFieldPath, highlightThreadId, onAddComment, onResolveThread, onResolvedValueChange, onLoadingStateChange, conflictNotice = false, fieldErrors, }) => {
|
|
30
|
-
// Use the extracted reference resolution hook for live preview
|
|
31
30
|
useReferenceResolution({
|
|
32
31
|
value,
|
|
33
32
|
fields,
|
|
@@ -47,7 +46,6 @@ export const FormRenderer = ({ fields, value, onChange, customRenderers, branch
|
|
|
47
46
|
const renderFieldControl = (field, currentValue, update, path) => {
|
|
48
47
|
const fieldId = `field-${fieldKey(path).replace(/[^a-zA-Z0-9_-]/g, '-')}`;
|
|
49
48
|
const canopyPath = normalizeCanopyPath(path);
|
|
50
|
-
// Filter comments for this specific field
|
|
51
49
|
const fieldThreads = currentEntryPath && onAddComment
|
|
52
50
|
? comments.filter((thread) => thread.type === 'field' &&
|
|
53
51
|
thread.entryPath === currentEntryPath &&
|
|
@@ -62,14 +60,12 @@ export const FormRenderer = ({ fields, value, onChange, customRenderers, branch
|
|
|
62
60
|
path,
|
|
63
61
|
id: fieldId,
|
|
64
62
|
}) }, fieldKey(path)));
|
|
65
|
-
// Wrap custom fields with FieldWrapper if comments enabled
|
|
66
63
|
if (currentEntryPath && currentUserId && onAddComment && onResolveThread) {
|
|
67
64
|
return (_jsx(FieldWrapper, { canopyPath: canopyPath, entryPath: currentEntryPath, threads: fieldThreads, autoFocus: focusedFieldPath === canopyPath, currentUserId: currentUserId, canResolve: canResolve, onAddComment: onAddComment, onResolveThread: onResolveThread, highlightThreadId: highlightThreadId, children: renderedField }, fieldKey(path)));
|
|
68
65
|
}
|
|
69
66
|
return renderedField;
|
|
70
67
|
}
|
|
71
68
|
const label = field.label ?? field.name;
|
|
72
|
-
// Helper to wrap field with FieldWrapper if comments enabled
|
|
73
69
|
const wrapWithComments = (renderedField) => {
|
|
74
70
|
if (currentEntryPath && currentUserId && onAddComment && onResolveThread) {
|
|
75
71
|
return (_jsx(FieldWrapper, { canopyPath: canopyPath, entryPath: currentEntryPath, threads: fieldThreads, autoFocus: focusedFieldPath === canopyPath, currentUserId: currentUserId, canResolve: canResolve, onAddComment: onAddComment, onResolveThread: onResolveThread, highlightThreadId: highlightThreadId, children: renderedField }));
|
|
@@ -145,24 +141,14 @@ export const FormRenderer = ({ fields, value, onChange, customRenderers, branch
|
|
|
145
141
|
update(nextItems);
|
|
146
142
|
}, renderField: renderField, path: [...path, idx], dataCanopyField: normalizeCanopyPath([...path, idx]) })] }) }, fieldKey([...path, idx])))), items.length === 0 && (_jsx(Text, { size: "xs", c: "dimmed", children: "No items yet. Add one to get started." }))] })] }) }, fieldKey(path)));
|
|
147
143
|
}
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
//
|
|
152
|
-
//
|
|
153
|
-
//
|
|
154
|
-
//
|
|
155
|
-
//
|
|
156
|
-
// invalid. The Clear button (wired through ObjectField's onRemove)
|
|
157
|
-
// fixes that by resetting to `undefined`, never `{}` (which would
|
|
158
|
-
// still carry a required-but-empty child into validation).
|
|
159
|
-
//
|
|
160
|
-
// Shown only when the field is optional (a required object should
|
|
161
|
-
// not be clearable back to a missing state) and only once it
|
|
162
|
-
// actually has a value (nothing to clear otherwise). Labeled
|
|
163
|
-
// "Clear" rather than "Remove" so it doesn't read as deleting the
|
|
164
|
-
// field from the schema, the way "Remove" correctly does for a list
|
|
165
|
-
// item above.
|
|
144
|
+
// Unlike the list branch above (each item has its own Remove button), a
|
|
145
|
+
// non-list object has no other way back to `undefined`: a required child
|
|
146
|
+
// filled and cleared to `''` reads as empty via `isEmptyForRequired`
|
|
147
|
+
// (entry-validator.ts), but the object itself only reads "absent" when
|
|
148
|
+
// `undefined`/`null`. The Clear button (ObjectField's `onRemove`) resets to
|
|
149
|
+
// `undefined`, never `{}` -- shown only when the field is optional and
|
|
150
|
+
// already has a value, and labeled "Clear" rather than "Remove" so it
|
|
151
|
+
// doesn't read as deleting the field from the schema.
|
|
166
152
|
const hasValue = currentValue !== undefined && currentValue !== null;
|
|
167
153
|
const canClear = objectField.required !== true && hasValue;
|
|
168
154
|
return wrapWithComments(_jsx(ObjectField, { label: label, fields: objectField.fields, value: currentValue, onChange: (next) => update(next), onRemove: canClear ? () => update(undefined) : undefined, renderField: renderField, path: path, dataCanopyField: normalizeCanopyPath(path) }, fieldKey(path)));
|
|
@@ -184,4 +170,3 @@ export const FormRenderer = ({ fields, value, onChange, customRenderers, branch
|
|
|
184
170
|
return (_jsx("div", { children: renderField(field, val, (next) => onChange({ ...value, [field.name]: next }), path) }, fieldKey(path)));
|
|
185
171
|
})] }));
|
|
186
172
|
};
|
|
187
|
-
export default FormRenderer;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
|
-
* SystemHealthPanel - Admin-only modal surfacing
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* SystemHealthPanel - Admin-only modal surfacing observability endpoints:
|
|
5
|
+
* task-queue/worker liveness (Overview), task recovery (Tasks), and
|
|
6
|
+
* branch-directory recovery (Branches).
|
|
7
7
|
*
|
|
8
|
-
* Visibility is
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* PermissionManager rely on their callers for that gate.
|
|
8
|
+
* Visibility is the caller's responsibility: Editor.tsx renders/opens this
|
|
9
|
+
* only for admins (see isAdmin(userContext?.groups)); this component does not
|
|
10
|
+
* re-check that itself, same as GroupManager and PermissionManager.
|
|
12
11
|
*/
|
|
13
12
|
import { Alert, Badge, Button, Code, Group, Loader, Modal, Paper, SegmentedControl, SimpleGrid, Spoiler, Stack, Table, Tabs, Text, ThemeIcon, Tooltip, } from '@mantine/core';
|
|
14
13
|
import { IconAlertCircle, IconAlertTriangle } from '@tabler/icons-react';
|
|
@@ -37,20 +36,16 @@ function formatAgeMs(ms) {
|
|
|
37
36
|
return `${totalDays}d ${totalHours % 24}h`;
|
|
38
37
|
}
|
|
39
38
|
/**
|
|
40
|
-
* Whether the Purge button should be disabled for
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* - Fresh provisioning lock: provisioning may genuinely be in progress
|
|
47
|
-
* (mirrors the server's [H1] freshness rail) -- applies to BOTH kinds,
|
|
48
|
-
* not just orphans.
|
|
39
|
+
* Whether the Purge button should be disabled for this row, and why (tooltip).
|
|
40
|
+
* - Base branch: never purgeable — the server already 400s this (UX
|
|
41
|
+
* consistency, not a new rail); see purgeBranchDirHandler in
|
|
42
|
+
* api/admin-branch-health.ts.
|
|
43
|
+
* - Fresh provisioning lock ([H1] freshness rail): provisioning may
|
|
44
|
+
* genuinely be in progress, for either row kind.
|
|
49
45
|
* - Orphan-only youth rail: a directory younger than
|
|
50
|
-
* ORPHAN_YOUTH_THRESHOLD_MS may still be
|
|
51
|
-
* written
|
|
52
|
-
*
|
|
53
|
-
* signature), so they're exempt here too.
|
|
46
|
+
* ORPHAN_YOUTH_THRESHOLD_MS may still be mid-clone, before branch.json is
|
|
47
|
+
* written. Corrupt-metadata dirs are exempt server-side too (a
|
|
48
|
+
* parseable-then-corrupted file isn't a mid-clone signature).
|
|
54
49
|
*/
|
|
55
50
|
function purgeGateFor(entry) {
|
|
56
51
|
if (entry.isBaseBranch) {
|
|
@@ -99,10 +94,8 @@ const TASK_STATUS_VALUES = TASK_STATUS_OPTIONS.map((o) => o.value);
|
|
|
99
94
|
function isAdminTaskStatus(value) {
|
|
100
95
|
return TASK_STATUS_VALUES.includes(value);
|
|
101
96
|
}
|
|
102
|
-
// ============================================================================
|
|
103
97
|
// Confirm-modal copy (races/limitations these actions accept -- see
|
|
104
98
|
// api/admin.ts and api/admin-branch-health.ts's handler docstrings)
|
|
105
|
-
// ============================================================================
|
|
106
99
|
const RETRY_CONFIRM_TEXT = 'Retrying may duplicate work if the task also runs another way; task actions are safe to run twice.';
|
|
107
100
|
function deleteConfirmText(status) {
|
|
108
101
|
if (status === 'pending') {
|
|
@@ -117,9 +110,6 @@ export function SystemHealthPanel({ opened, onClose }) {
|
|
|
117
110
|
const health = useSystemHealth({ isOpen: opened });
|
|
118
111
|
return (_jsx(Modal, { opened: opened, onClose: onClose, title: "System health", size: "xl", children: _jsxs(Tabs, { defaultValue: "overview", children: [_jsxs(Tabs.List, { children: [_jsx(Tabs.Tab, { value: "overview", children: "Overview" }), _jsx(Tabs.Tab, { value: "tasks", children: "Tasks" }), _jsx(Tabs.Tab, { value: "branches", children: "Branches" })] }), _jsx(Tabs.Panel, { value: "overview", pt: "md", children: _jsx(OverviewTab, { health: health }) }), _jsx(Tabs.Panel, { value: "tasks", pt: "md", children: _jsx(TasksTab, { health: health }) }), _jsx(Tabs.Panel, { value: "branches", pt: "md", children: _jsx(BranchesTab, { health: health }) })] }) }));
|
|
119
112
|
}
|
|
120
|
-
// ============================================================================
|
|
121
|
-
// Overview tab
|
|
122
|
-
// ============================================================================
|
|
123
113
|
function OverviewTab({ health }) {
|
|
124
114
|
const { status, statusLoading, isRecentFatalError, error, refresh } = health;
|
|
125
115
|
if (!status && statusLoading) {
|
|
@@ -135,9 +125,6 @@ function OverviewTab({ health }) {
|
|
|
135
125
|
? ` · ${lastGitSync.skippedLocked.length} skipped (content write in progress)`
|
|
136
126
|
: ''] }), lastGitSync.failed.length > 0 && (_jsx(Spoiler, { maxHeight: 0, showLabel: `${lastGitSync.failed.length} failed — show details`, hideLabel: "Hide", children: _jsx(Stack, { gap: 4, mt: 4, children: lastGitSync.failed.map((f) => (_jsxs(Text, { size: "xs", c: "red", children: [f.branch, ": ", f.error] }, f.branch))) }) }))] })), _jsx(SimpleGrid, { cols: 5, spacing: "xs", children: ['pending', 'processing', 'completed', 'failed', 'corrupt'].map((key) => (_jsxs(Paper, { withBorder: true, p: "xs", radius: "md", ta: "center", children: [_jsx(Text, { size: "xs", c: "dimmed", tt: "capitalize", children: key }), _jsx(Text, { size: "lg", fw: 700, c: (key === 'failed' || key === 'corrupt') && status.queue[key] > 0 ? 'red' : undefined, children: status.queue[key] })] }, key))) }), status.queue.oldestPendingAgeMs !== undefined && (_jsxs(Text, { size: "xs", c: "dimmed", children: ["Oldest pending task: ", formatAgeMs(status.queue.oldestPendingAgeMs), " old"] })), _jsxs(Group, { justify: "space-between", align: "center", children: [_jsxs(Text, { size: "xs", c: "dimmed", children: ["Generated at ", status.generatedAt] }), _jsx(Button, { size: "xs", variant: "light", onClick: () => refresh(), loading: statusLoading, children: "Refresh" })] }), _jsx(Text, { size: "xs", c: "dimmed", children: "Data may lag up to ~60s (shared-filesystem caching)" })] }));
|
|
137
127
|
}
|
|
138
|
-
// ============================================================================
|
|
139
|
-
// Tasks tab
|
|
140
|
-
// ============================================================================
|
|
141
128
|
function TasksTab({ health }) {
|
|
142
129
|
const { taskStatus, setTaskStatus, tasks, tasksLoading } = health;
|
|
143
130
|
const isCorrupt = taskStatus === 'corrupt';
|
|
@@ -170,9 +157,6 @@ function TasksTab({ health }) {
|
|
|
170
157
|
? corruptRows.map((file) => (_jsxs(Table.Tr, { children: [_jsx(Table.Td, { children: _jsx("span", { title: file.fileName, children: truncate(file.fileName, 30) }) }), _jsxs(Table.Td, { children: [file.size, " bytes"] }), _jsx(Table.Td, { children: file.mtime }), _jsx(Table.Td, { children: _jsx(Code, { block: true, style: { maxWidth: 320, whiteSpace: 'pre-wrap' }, children: file.rawSnippet }) }), _jsx(Table.Td, { children: _jsx(Button, { size: "xs", variant: "light", color: "red", "data-testid": `delete-task-${file.fileName}`, onClick: () => handleDeleteClick('corrupt', file.fileName), children: "Delete" }) })] }, file.fileName)))
|
|
171
158
|
: taskRows.map((task) => (_jsxs(Table.Tr, { children: [_jsx(Table.Td, { children: _jsx("span", { title: task.id, children: truncate(task.id, 12) }) }), _jsx(Table.Td, { children: task.action }), _jsx(Table.Td, { children: task.createdAt }), _jsx(Table.Td, { children: task.retryCount ?? 0 }), _jsx(Table.Td, { children: task.error ? (_jsx(Tooltip, { label: task.error, multiline: true, maw: 400, children: _jsx(Text, { size: "xs", style: { cursor: 'help' }, children: truncate(task.error, 50) }) })) : (_jsx(Text, { size: "xs", c: "dimmed", children: "\u2014" })) }), _jsx(Table.Td, { children: _jsxs(Group, { gap: "xs", children: [taskStatus === 'failed' && (_jsx(Button, { size: "xs", variant: "light", "data-testid": `retry-task-${task.id}`, onClick: () => handleRetryClick(task), children: "Retry" })), canDelete && (_jsx(Button, { size: "xs", variant: "light", color: "red", "data-testid": `delete-task-${task.id}`, onClick: () => handleDeleteClick(taskStatus, `${task.id}.json`), children: "Delete" }))] }) })] }, task.id))) })] }) }))] }));
|
|
172
159
|
}
|
|
173
|
-
// ============================================================================
|
|
174
|
-
// Branches tab
|
|
175
|
-
// ============================================================================
|
|
176
160
|
function BranchesTab({ health }) {
|
|
177
161
|
const { branchHealth, branchHealthLoading } = health;
|
|
178
162
|
const entries = branchHealth?.entries ?? [];
|
|
@@ -214,12 +198,11 @@ function BranchesTab({ health }) {
|
|
|
214
198
|
function BranchHealthRow({ entry, onMarkMerged, onRepair, onPurge, }) {
|
|
215
199
|
if (entry.kind === 'healthy' && entry.branch) {
|
|
216
200
|
const b = entry.branch;
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
// this replaced.
|
|
201
|
+
// Mirrors the rebase loop's skip logic (worker/rebase.ts): the worker
|
|
202
|
+
// rebases every branch except 'submitted'/'approved' (under an active PR)
|
|
203
|
+
// and 'archived' (already merged). An exclusion list, not `status ===
|
|
204
|
+
// 'editing'`, so a status added later still shows its rebase failures by
|
|
205
|
+
// default instead of silently hiding them.
|
|
223
206
|
const showRebaseFailure = !['submitted', 'approved', 'archived'].includes(b.status) && !!b.rebaseFailure;
|
|
224
207
|
const canMarkMerged = (b.status === 'submitted' || b.status === 'approved') && !!b.pullRequestNumber;
|
|
225
208
|
return (_jsxs(Table.Tr, { children: [_jsx(Table.Td, { children: _jsxs(Group, { gap: 4, wrap: "nowrap", children: [_jsx(Text, { size: "sm", children: entry.dirName }), entry.isBaseBranch && (_jsx(Badge, { size: "xs", color: "gray", variant: "outline", children: "base" }))] }) }), _jsx(Table.Td, { children: _jsx(Badge, { color: branchStatusColorMap[b.status] ?? 'neutral', variant: "light", children: b.status }) }), _jsx(Table.Td, { children: b.pullRequestNumber ? (_jsxs(Text, { size: "xs", c: "blue", component: "a", href: b.pullRequestUrl, target: "_blank", rel: "noopener noreferrer", style: { textDecoration: 'underline' }, children: ["PR #", b.pullRequestNumber, b.pullRequestState ? ` (${b.pullRequestState})` : ''] })) : (_jsx(Text, { size: "xs", c: "dimmed", children: "\u2014" })) }), _jsx(Table.Td, { children: b.syncStatus === 'sync-failed' ? (_jsx(Tooltip, { label: b.syncFailureReason
|
|
@@ -14,9 +14,8 @@ export interface UseSystemHealthReturn {
|
|
|
14
14
|
statusLoading: boolean;
|
|
15
15
|
/**
|
|
16
16
|
* True when workerStatus.lastFatalError exists and is < 30 min old, as of
|
|
17
|
-
* the last fetch. Computed at fetch time
|
|
18
|
-
*
|
|
19
|
-
* react-hooks/purity rule this sidesteps.
|
|
17
|
+
* the last fetch. Computed at fetch time, not in the component's render, so
|
|
18
|
+
* the panel never calls Date.now() during render (react-hooks/purity).
|
|
20
19
|
*/
|
|
21
20
|
isRecentFatalError: boolean;
|
|
22
21
|
tasks: AdminTasksData | null;
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
/**
|
|
3
|
-
* useSystemHealth - Data + actions for the admin System Health panel
|
|
3
|
+
* useSystemHealth - Data + actions for the admin System Health panel.
|
|
4
4
|
*
|
|
5
|
-
* Mirrors useGroupManager's shape
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* other way to catch a worker coming back up or a task finishing.
|
|
5
|
+
* Mirrors useGroupManager's shape (load on open, typed actions that notify
|
|
6
|
+
* then refresh()), but also polls every 30s while open (cleared on
|
|
7
|
+
* close/unmount) since queue depth and worker liveness go stale quickly and
|
|
8
|
+
* the panel has no other way to catch a worker recovering or a task finishing.
|
|
10
9
|
*/
|
|
11
10
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
12
11
|
import { notifications } from '@mantine/notifications';
|
|
@@ -14,9 +13,9 @@ import { useApiClient } from '../context/index.js';
|
|
|
14
13
|
const POLL_INTERVAL_MS = 30_000;
|
|
15
14
|
/**
|
|
16
15
|
* Crash-loop rider window: a worker that fatally exits and restarts
|
|
17
|
-
* repeatedly can flap between 'absent' and 'alive'
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* repeatedly can flap between 'absent' and 'alive' and never sit still long
|
|
17
|
+
* enough to read 'stale' — surfacing a recent lastFatalError regardless of
|
|
18
|
+
* liveness state is the only way the panel catches that.
|
|
20
19
|
*/
|
|
21
20
|
const CRASH_LOOP_WINDOW_MS = 30 * 60_000;
|
|
22
21
|
export function useSystemHealth(options) {
|
|
@@ -31,9 +30,8 @@ export function useSystemHealth(options) {
|
|
|
31
30
|
const [branchHealthLoading, setBranchHealthLoading] = useState(false);
|
|
32
31
|
const [error, setError] = useState(null);
|
|
33
32
|
// refresh() has no status argument, so it needs the CURRENT taskStatus
|
|
34
|
-
// without
|
|
35
|
-
//
|
|
36
|
-
// changes). A ref sidesteps the stale-closure problem cleanly.
|
|
33
|
+
// without depending on it (that would tear down/rebuild the poll interval
|
|
34
|
+
// below on every Tasks-tab status change) — a ref sidesteps the stale closure.
|
|
37
35
|
const taskStatusRef = useRef(taskStatus);
|
|
38
36
|
taskStatusRef.current = taskStatus;
|
|
39
37
|
const fetchStatus = useCallback(async () => {
|
|
@@ -11,17 +11,14 @@ import type { ApiClient } from './context/index.js';
|
|
|
11
11
|
* can't be sourced here via `useApiClient()`/`useOptionalApiClient()` directly; instead every
|
|
12
12
|
* entry point takes an optional `apiClient`, which the caller (a hook, which CAN call
|
|
13
13
|
* `useOptionalApiClient()` during render) resolves and passes down. Falls back to a
|
|
14
|
-
* default-configured `createApiClient()` when no client is supplied
|
|
15
|
-
* that predate this DI path keep working unchanged.
|
|
14
|
+
* default-configured `createApiClient()` when no client is supplied.
|
|
16
15
|
*/
|
|
17
16
|
/**
|
|
18
|
-
* Find which fields changed between two form values.
|
|
19
17
|
* Only returns top-level field configs for fields that changed.
|
|
18
|
+
* @internal Exported for tests.
|
|
20
19
|
*/
|
|
21
20
|
export declare function findChangedFields(prevValue: FormValue, currentValue: FormValue, schema: EntrySchema): FieldConfig[];
|
|
22
21
|
/**
|
|
23
|
-
* Resolve changed references incrementally.
|
|
24
|
-
* Only resolves reference fields that have changed.
|
|
25
22
|
* Uses cache to avoid duplicate API calls.
|
|
26
23
|
*/
|
|
27
24
|
export declare function resolveChangedReferences(prevValue: FormValue, currentValue: FormValue, schema: EntrySchema, branch: string, cache: Map<string, unknown>, apiClient?: ApiClient): Promise<Partial<FormValue>>;
|
|
@@ -10,19 +10,17 @@ import { flattenGroupFields } from '../utils/flatten-group-fields.js';
|
|
|
10
10
|
* can't be sourced here via `useApiClient()`/`useOptionalApiClient()` directly; instead every
|
|
11
11
|
* entry point takes an optional `apiClient`, which the caller (a hook, which CAN call
|
|
12
12
|
* `useOptionalApiClient()` during render) resolves and passes down. Falls back to a
|
|
13
|
-
* default-configured `createApiClient()` when no client is supplied
|
|
14
|
-
* that predate this DI path keep working unchanged.
|
|
13
|
+
* default-configured `createApiClient()` when no client is supplied.
|
|
15
14
|
*/
|
|
16
15
|
/**
|
|
17
|
-
* Find which fields changed between two form values.
|
|
18
16
|
* Only returns top-level field configs for fields that changed.
|
|
17
|
+
* @internal Exported for tests.
|
|
19
18
|
*/
|
|
20
19
|
export function findChangedFields(prevValue, currentValue, schema) {
|
|
21
20
|
const changed = [];
|
|
22
21
|
for (const field of flattenGroupFields(schema)) {
|
|
23
22
|
const prevFieldValue = prevValue[field.name];
|
|
24
23
|
const currentFieldValue = currentValue[field.name];
|
|
25
|
-
// Deep equality check for objects and arrays
|
|
26
24
|
if (JSON.stringify(prevFieldValue) !== JSON.stringify(currentFieldValue)) {
|
|
27
25
|
changed.push(field);
|
|
28
26
|
}
|
|
@@ -30,8 +28,6 @@ export function findChangedFields(prevValue, currentValue, schema) {
|
|
|
30
28
|
return changed;
|
|
31
29
|
}
|
|
32
30
|
/**
|
|
33
|
-
* Resolve changed references incrementally.
|
|
34
|
-
* Only resolves reference fields that have changed.
|
|
35
31
|
* Uses cache to avoid duplicate API calls.
|
|
36
32
|
*/
|
|
37
33
|
export async function resolveChangedReferences(prevValue, currentValue, schema, branch, cache, apiClient) {
|
|
@@ -41,14 +37,11 @@ export async function resolveChangedReferences(prevValue, currentValue, schema,
|
|
|
41
37
|
if (field.type === 'reference') {
|
|
42
38
|
const refField = field;
|
|
43
39
|
const fieldValue = currentValue[field.name];
|
|
44
|
-
// Resolve this field's value
|
|
45
40
|
if (refField.list && Array.isArray(fieldValue)) {
|
|
46
|
-
// List of references
|
|
47
41
|
const resolved = await Promise.all(fieldValue.map((id) => resolveReferenceId(id, branch, cache, apiClient)));
|
|
48
42
|
updates[field.name] = resolved;
|
|
49
43
|
}
|
|
50
44
|
else if (fieldValue) {
|
|
51
|
-
// Single reference
|
|
52
45
|
const resolved = await resolveReferenceId(fieldValue, branch, cache, apiClient);
|
|
53
46
|
updates[field.name] = resolved;
|
|
54
47
|
}
|
|
@@ -56,13 +49,7 @@ export async function resolveChangedReferences(prevValue, currentValue, schema,
|
|
|
56
49
|
}
|
|
57
50
|
return updates;
|
|
58
51
|
}
|
|
59
|
-
/**
|
|
60
|
-
* Resolve a single reference ID to full object.
|
|
61
|
-
* Checks cache first, then makes API call if needed.
|
|
62
|
-
* Returns original ID if resolution fails.
|
|
63
|
-
*/
|
|
64
52
|
async function resolveReferenceId(id, branch, cache, apiClient) {
|
|
65
|
-
// Only resolve string IDs
|
|
66
53
|
if (typeof id !== 'string') {
|
|
67
54
|
return id;
|
|
68
55
|
}
|
|
@@ -71,7 +58,6 @@ async function resolveReferenceId(id, branch, cache, apiClient) {
|
|
|
71
58
|
return id;
|
|
72
59
|
}
|
|
73
60
|
const cacheKey = `${branch}:${id}`;
|
|
74
|
-
// Check cache first
|
|
75
61
|
if (cache.has(cacheKey)) {
|
|
76
62
|
return cache.get(cacheKey);
|
|
77
63
|
}
|
|
@@ -82,17 +68,14 @@ async function resolveReferenceId(id, branch, cache, apiClient) {
|
|
|
82
68
|
const client = apiClient ?? createApiClient();
|
|
83
69
|
const result = await client.content.resolveReferences({ branch }, { ids: [id] });
|
|
84
70
|
if (result.ok && result.data && result.data.resolved[id]) {
|
|
85
|
-
// Cache and return resolved object
|
|
86
71
|
const resolved = result.data.resolved[id];
|
|
87
72
|
cache.set(cacheKey, resolved);
|
|
88
73
|
return resolved;
|
|
89
74
|
}
|
|
90
|
-
// Resolution failed - return original ID string
|
|
91
75
|
return id;
|
|
92
76
|
}
|
|
93
77
|
catch (error) {
|
|
94
78
|
console.error(`Failed to resolve reference ID ${id}:`, error);
|
|
95
|
-
// Return original ID on error
|
|
96
79
|
return id;
|
|
97
80
|
}
|
|
98
81
|
}
|
|
@@ -9,15 +9,11 @@ import { ThreadCarousel } from './ThreadCarousel.js';
|
|
|
9
9
|
*/
|
|
10
10
|
export const BranchComments = ({ comments, currentUserId, canResolve, onAddComment, onResolveThread, autoFocus, highlightThreadId, onGetUserMetadata, }) => {
|
|
11
11
|
const [showCarousel, setShowCarousel] = useState(false);
|
|
12
|
-
// Filter for branch-level threads
|
|
13
12
|
const branchThreads = useMemo(() => comments.filter((t) => t.type === 'branch'), [comments]);
|
|
14
|
-
// Show carousel if threads exist or if auto-focused
|
|
15
13
|
const shouldShowCarousel = branchThreads.length > 0 || showCarousel || autoFocus;
|
|
16
|
-
// Wrapper to add branch context to comment handler
|
|
17
14
|
const handleAddComment = async (text, threadId) => {
|
|
18
15
|
await onAddComment(text, 'branch', undefined, undefined, threadId);
|
|
19
16
|
};
|
|
20
|
-
// Show "New branch comment" button when no threads
|
|
21
17
|
if (!shouldShowCarousel) {
|
|
22
18
|
return (_jsx(Box, { children: _jsx(Button, { size: "xs", variant: "subtle", color: "gray", onClick: () => setShowCarousel(true), style: { fontSize: '0.75rem', height: '1.5rem' }, children: "New branch comment" }) }));
|
|
23
19
|
}
|
|
@@ -9,15 +9,11 @@ import { ThreadCarousel } from './ThreadCarousel.js';
|
|
|
9
9
|
*/
|
|
10
10
|
export const EntryComments = ({ comments, entryPath, currentUserId, canResolve, onAddComment, onResolveThread, autoFocus, highlightThreadId, }) => {
|
|
11
11
|
const [showCarousel, setShowCarousel] = useState(false);
|
|
12
|
-
// Filter for entry-level threads
|
|
13
12
|
const entryThreads = useMemo(() => comments.filter((t) => t.type === 'entry' && t.entryPath === entryPath), [comments, entryPath]);
|
|
14
|
-
// Show carousel if threads exist or if auto-focused
|
|
15
13
|
const shouldShowCarousel = entryThreads.length > 0 || showCarousel || autoFocus;
|
|
16
|
-
// Wrapper to add entry context to comment handler
|
|
17
14
|
const handleAddComment = async (text, threadId) => {
|
|
18
15
|
await onAddComment(text, 'entry', entryPath, undefined, threadId);
|
|
19
16
|
};
|
|
20
|
-
// Show "New file comment" button when no threads
|
|
21
17
|
if (!shouldShowCarousel) {
|
|
22
18
|
return (_jsx(Box, { children: _jsx(Button, { size: "xs", variant: "subtle", color: "gray", onClick: () => setShowCarousel(true), style: { fontSize: '0.75rem', height: '1.5rem' }, children: "New file comment" }) }));
|
|
23
19
|
}
|
|
@@ -10,9 +10,7 @@ import { ThreadCarousel } from './ThreadCarousel.js';
|
|
|
10
10
|
export const FieldWrapper = ({ children, canopyPath, entryPath, threads, autoFocus, currentUserId, canResolve, onAddComment, onResolveThread, highlightThreadId, }) => {
|
|
11
11
|
const wrapperRef = useRef(null);
|
|
12
12
|
const [showCarousel, setShowCarousel] = useState(false);
|
|
13
|
-
// Show carousel if threads exist or user explicitly requested it
|
|
14
13
|
const shouldShowCarousel = threads.length > 0 || showCarousel;
|
|
15
|
-
// Scroll to field when focused from preview
|
|
16
14
|
useEffect(() => {
|
|
17
15
|
if (autoFocus) {
|
|
18
16
|
wrapperRef.current?.scrollIntoView({
|
|
@@ -21,12 +19,10 @@ export const FieldWrapper = ({ children, canopyPath, entryPath, threads, autoFoc
|
|
|
21
19
|
});
|
|
22
20
|
}
|
|
23
21
|
}, [autoFocus]);
|
|
24
|
-
// Wrapper to add field context to comment handler
|
|
25
22
|
const handleAddComment = async (text, threadId) => {
|
|
26
23
|
await onAddComment(text, 'field', entryPath, canopyPath, threadId);
|
|
27
24
|
};
|
|
28
25
|
return (_jsxs(Box, { ref: wrapperRef, "data-canopy-field": canopyPath, pos: "relative", style: { width: '100%' }, children: [_jsx(Box, { style: {
|
|
29
|
-
// Add subtle highlight when auto-focused
|
|
30
26
|
outline: autoFocus ? '2px solid var(--mantine-color-blue-5)' : undefined,
|
|
31
27
|
outlineOffset: autoFocus ? 2 : undefined,
|
|
32
28
|
borderRadius: 4,
|
|
@@ -45,10 +45,8 @@ export const InlineCommentThread = ({ thread, onAddReply, onResolve, currentUser
|
|
|
45
45
|
const canUserResolve = () => {
|
|
46
46
|
if (!canResolve)
|
|
47
47
|
return false;
|
|
48
|
-
// Thread author or user with resolver permission
|
|
49
48
|
return thread.authorId === currentUserId || canResolve;
|
|
50
49
|
};
|
|
51
|
-
// Always show full thread view with per-thread scrolling
|
|
52
50
|
return (_jsx(Paper, { withBorder: true, p: "md", bg: "white", "data-testid": "inline-comment-thread", style: {
|
|
53
51
|
width: '100%',
|
|
54
52
|
overflowY: 'auto',
|
|
@@ -2,64 +2,11 @@ import React from 'react';
|
|
|
2
2
|
import type { CommentThread } from '../../comment-store.js';
|
|
3
3
|
import type { UserSearchResult } from '../../auth/types.js';
|
|
4
4
|
/**
|
|
5
|
-
* ThreadCarousel - Horizontal comment thread navigation component
|
|
6
|
-
*
|
|
7
5
|
* ## Purpose
|
|
8
6
|
* Provides a horizontal carousel UI for navigating between multiple comment threads
|
|
9
7
|
* on fields, entries, or branches. Supports both keyboard navigation (arrow buttons)
|
|
10
8
|
* and displays a visual "peekaboo" preview of adjacent threads.
|
|
11
9
|
*
|
|
12
|
-
* ## Key Behaviors
|
|
13
|
-
*
|
|
14
|
-
* ### Layout & Sizing
|
|
15
|
-
* - **Active thread width**: `calc(100% - 72px)` - fills container minus peekaboo space
|
|
16
|
-
* - **Single thread width**: `calc(100% - 72px)` - same as active (for consistency)
|
|
17
|
-
* - **Inactive thread width**: `400px` - fixed width when not in view
|
|
18
|
-
* - **Peekaboo size**: `60px` - sliver of next thread shown on right edge
|
|
19
|
-
* - **Gap between threads**: `12px`
|
|
20
|
-
*
|
|
21
|
-
* ### Peekaboo Preview
|
|
22
|
-
* - Shows 60px of the next thread on the right edge (when not viewing last thread)
|
|
23
|
-
* - Gradient fade overlay applied to peekaboo area for visual polish
|
|
24
|
-
* - **Last thread behavior**: Invisible 60px spacer ensures last thread stays left-aligned
|
|
25
|
-
* without showing previous threads on the left
|
|
26
|
-
* - Peekaboo helps users discover there are more threads to navigate
|
|
27
|
-
*
|
|
28
|
-
* ### Thread Sorting
|
|
29
|
-
* - **Unresolved threads first** (primary sort)
|
|
30
|
-
* - **Newest first within same resolved state** (secondary sort by createdAt)
|
|
31
|
-
* - This ensures urgent unresolved feedback appears first
|
|
32
|
-
*
|
|
33
|
-
* ### Navigation
|
|
34
|
-
* - **Arrow buttons**: `← 2/5 →` counter with disabled states at boundaries
|
|
35
|
-
* - **Smooth scrolling**: CSS `scroll-behavior: smooth` with programmatic scroll
|
|
36
|
-
* - **Auto-scroll**: When `autoFocus` is true, automatically scrolls to first unresolved thread
|
|
37
|
-
* - **Mouse scrolling disabled**: `overflowX: 'hidden'` - only button navigation allowed
|
|
38
|
-
* - **Scroll calculation**: Accounts for active thread width + gaps when navigating
|
|
39
|
-
*
|
|
40
|
-
* ### Always-Visible Design
|
|
41
|
-
* - Component renders even with 0 threads (shows "No comments yet" message)
|
|
42
|
-
* - "New" button always accessible in header
|
|
43
|
-
* - Header shows thread count when threads exist: "Comments (3)"
|
|
44
|
-
* - Navigation arrows only appear when multiple threads exist
|
|
45
|
-
*
|
|
46
|
-
* ### Vertical Resizing
|
|
47
|
-
* - **Default height**: 400px
|
|
48
|
-
* - **Resize range**: 200px (min) to 600px (max)
|
|
49
|
-
* - **Resize handle**: Bottom edge with visual feedback on hover/drag
|
|
50
|
-
* - User can drag to adjust carousel height for their workflow
|
|
51
|
-
*
|
|
52
|
-
* ### New Thread Creation
|
|
53
|
-
* - "New" button in header toggles inline thread creation box
|
|
54
|
-
* - `autoOpenNewThread` prop auto-opens box (used when clicking "New comment" button)
|
|
55
|
-
* - New thread box appears above carousel, with textarea and Create/Cancel buttons
|
|
56
|
-
*
|
|
57
|
-
* ## Usage Context
|
|
58
|
-
* Used by:
|
|
59
|
-
* - **FieldWrapper**: Inline comments beneath form fields
|
|
60
|
-
* - **EntryComments**: Comments at top of entry form
|
|
61
|
-
* - **BranchComments**: Comments at top of BranchManager
|
|
62
|
-
*
|
|
63
10
|
* ## Design Decisions
|
|
64
11
|
*
|
|
65
12
|
* ### Why calc(100% - 72px)?
|
|
@@ -67,11 +14,6 @@ import type { UserSearchResult } from '../../auth/types.js';
|
|
|
67
14
|
* - Active thread fills remaining space for maximum readability
|
|
68
15
|
* - Consistent sizing between single thread and active thread in multi-thread scenarios
|
|
69
16
|
*
|
|
70
|
-
* ### Why invisible spacer at end?
|
|
71
|
-
* - Without spacer: last thread would align to right edge, showing previous threads on left
|
|
72
|
-
* - With spacer: last thread stays left-aligned with blank space on right (matching peekaboo size)
|
|
73
|
-
* - Creates consistent left-alignment across all thread positions
|
|
74
|
-
*
|
|
75
17
|
* ### Why disable mouse scrolling?
|
|
76
18
|
* - Prevents accidental scroll-wheel navigation that could be jarring
|
|
77
19
|
* - Forces deliberate button-based navigation for better UX
|
|
@@ -16,28 +16,23 @@ export const ThreadCarousel = ({ threads, label = 'Comments', contextType: _, cu
|
|
|
16
16
|
const scrollContainerRef = useRef(null);
|
|
17
17
|
const resizeStartY = useRef(0);
|
|
18
18
|
const resizeStartHeight = useRef(0);
|
|
19
|
-
// Sort: unresolved first, then resolved
|
|
20
19
|
const sortedThreads = useMemo(() => [...threads].sort((a, b) => {
|
|
21
20
|
if (a.resolved === b.resolved) {
|
|
22
|
-
// Same resolved state: sort by createdAt (newest first)
|
|
23
21
|
return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
|
|
24
22
|
}
|
|
25
23
|
return a.resolved ? 1 : -1;
|
|
26
24
|
}), [threads]);
|
|
27
|
-
// Auto-scroll to first unresolved thread when autoFocus is true
|
|
28
25
|
useEffect(() => {
|
|
29
26
|
if (autoFocus && sortedThreads.length > 0) {
|
|
30
27
|
const firstUnresolved = sortedThreads.find((t) => !t.resolved);
|
|
31
28
|
if (firstUnresolved) {
|
|
32
29
|
const index = sortedThreads.findIndex((t) => t.id === firstUnresolved.id);
|
|
33
30
|
setCurrentIndex(index);
|
|
34
|
-
// Scroll to thread
|
|
35
31
|
scrollToIndex(index);
|
|
36
32
|
}
|
|
37
33
|
}
|
|
38
34
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- scrollToIndex is stable
|
|
39
35
|
}, [autoFocus, sortedThreads]);
|
|
40
|
-
// Scroll to and highlight specific thread when highlightThreadId changes
|
|
41
36
|
useEffect(() => {
|
|
42
37
|
if (highlightThreadId && sortedThreads.length > 0) {
|
|
43
38
|
const threadIndex = sortedThreads.findIndex((t) => t.id === highlightThreadId);
|
|
@@ -45,7 +40,6 @@ export const ThreadCarousel = ({ threads, label = 'Comments', contextType: _, cu
|
|
|
45
40
|
setCurrentIndex(threadIndex);
|
|
46
41
|
scrollToIndex(threadIndex);
|
|
47
42
|
setHighlightedThreadId(highlightThreadId);
|
|
48
|
-
// Clear highlight after 2 seconds
|
|
49
43
|
const timer = window.setTimeout(() => {
|
|
50
44
|
setHighlightedThreadId(undefined);
|
|
51
45
|
}, 2000);
|
|
@@ -54,13 +48,11 @@ export const ThreadCarousel = ({ threads, label = 'Comments', contextType: _, cu
|
|
|
54
48
|
}
|
|
55
49
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- scrollToIndex is stable
|
|
56
50
|
}, [highlightThreadId, sortedThreads]);
|
|
57
|
-
// Auto-open new thread box when autoOpenNewThread is true
|
|
58
51
|
useEffect(() => {
|
|
59
52
|
if (autoOpenNewThread) {
|
|
60
53
|
setShowNewThreadBox(true);
|
|
61
54
|
}
|
|
62
55
|
}, [autoOpenNewThread]);
|
|
63
|
-
// Handle resize dragging
|
|
64
56
|
useEffect(() => {
|
|
65
57
|
const handleMouseMove = (e) => {
|
|
66
58
|
if (!isResizing)
|
|
@@ -90,8 +82,6 @@ export const ThreadCarousel = ({ threads, label = 'Comments', contextType: _, cu
|
|
|
90
82
|
const scrollToIndex = (index) => {
|
|
91
83
|
if (scrollContainerRef.current) {
|
|
92
84
|
const container = scrollContainerRef.current;
|
|
93
|
-
// Calculate scroll position based on container width
|
|
94
|
-
// Active thread takes most space, others are 400px + gap
|
|
95
85
|
let scrollLeft = 0;
|
|
96
86
|
for (let i = 0; i < index; i++) {
|
|
97
87
|
if (sortedThreads.length > 1) {
|
|
@@ -175,12 +165,10 @@ export const ThreadCarousel = ({ threads, label = 'Comments', contextType: _, cu
|
|
|
175
165
|
return (_jsx("div", { style: {
|
|
176
166
|
scrollSnapAlign: 'start',
|
|
177
167
|
flexShrink: 0,
|
|
178
|
-
// Active thread or single thread stretches to fill space minus peekaboo
|
|
179
168
|
width: isActive || sortedThreads.length === 1
|
|
180
169
|
? 'calc(100% - 72px)' // Active or single: leave room for peekaboo/spacing
|
|
181
170
|
: 400, // Non-active: fixed width
|
|
182
171
|
maxWidth: isActive || sortedThreads.length === 1 ? 'calc(100% - 72px)' : 400,
|
|
183
|
-
// Add highlight animation
|
|
184
172
|
outline: isHighlighted ? '3px solid var(--mantine-color-blue-5)' : undefined,
|
|
185
173
|
outlineOffset: isHighlighted ? 2 : undefined,
|
|
186
174
|
borderRadius: isHighlighted ? 8 : undefined,
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Props for the EditorFooter component.
|
|
3
|
-
*/
|
|
4
1
|
export interface EditorFooterProps {
|
|
5
2
|
/**
|
|
6
3
|
* Optional custom footer content.
|
|
@@ -10,10 +7,5 @@ export interface EditorFooterProps {
|
|
|
10
7
|
/**
|
|
11
8
|
* Footer component for the Editor.
|
|
12
9
|
* Displays static links (Terms, Privacy) and copyright notice.
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```tsx
|
|
16
|
-
* <EditorFooter />
|
|
17
|
-
* ```
|
|
18
10
|
*/
|
|
19
11
|
export declare function EditorFooter({ children }: EditorFooterProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,11 +3,6 @@ import { Group, Paper, Text } from '@mantine/core';
|
|
|
3
3
|
/**
|
|
4
4
|
* Footer component for the Editor.
|
|
5
5
|
* Displays static links (Terms, Privacy) and copyright notice.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```tsx
|
|
9
|
-
* <EditorFooter />
|
|
10
|
-
* ```
|
|
11
6
|
*/
|
|
12
7
|
export function EditorFooter({ children }) {
|
|
13
8
|
return (_jsx(Paper, { withBorder: true, radius: 0, shadow: "sm", px: "md", py: "xs", style: { position: 'fixed', left: 0, right: 0, bottom: 0, zIndex: 40 }, children: children ?? (_jsxs(Group, { gap: "md", justify: "center", children: [_jsx(Text, { size: "xs", c: "dimmed", children: "Terms" }), _jsx(Text, { size: "xs", c: "dimmed", children: "Privacy" }), _jsx(Text, { size: "xs", c: "dimmed", children: "\u00A9 CanopyCMS" })] })) }));
|