@agent-native/core 0.80.4 → 0.80.6
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +28 -2
- package/corpus/core/docs/content/locales/ar-SA/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/de-DE/real-time-collaboration.mdx +3 -3
- package/corpus/core/docs/content/locales/de-DE/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/es-ES/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/es-ES/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/fr-FR/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/ja-JP/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/ko-KR/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/pt-BR/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-CN/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +1 -1
- package/corpus/core/docs/content/locales/zh-TW/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +1 -1
- package/corpus/core/docs/content/real-time-collaboration.mdx +2 -2
- package/corpus/core/docs/content/template-design.mdx +1 -1
- package/corpus/core/package.json +3 -7
- package/corpus/core/src/action.ts +21 -0
- package/corpus/core/src/agent/durable-background.ts +32 -11
- package/corpus/core/src/agent/production-agent.ts +11 -1
- package/corpus/core/src/agent/run-loop-with-resume.ts +3 -1
- package/corpus/core/src/brand-kit/fig/index.ts +17 -37
- package/corpus/core/src/cli/create.ts +1 -0
- package/corpus/core/src/cli/index.ts +1 -1
- package/corpus/core/src/cli/mcp-config-writers.ts +187 -51
- package/corpus/core/src/cli/skills.ts +18 -3
- package/corpus/core/src/client/AssistantChat.tsx +11 -1
- package/corpus/core/src/client/agent-chat.ts +12 -1
- package/corpus/core/src/client/composer/PromptComposer.tsx +100 -41
- package/corpus/core/src/client/org/OrgSwitcher.tsx +1 -1
- package/corpus/core/src/client/sharing/ShareButton.tsx +3 -27
- package/corpus/core/src/collab/presence.ts +1 -1
- package/corpus/core/src/mcp/connect-route.ts +34 -5
- package/corpus/core/src/server/action-discovery.ts +4 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +20 -0
- package/corpus/core/src/sharing/registry.ts +17 -0
- package/corpus/core/src/templates/default/pnpm-workspace.yaml +1 -0
- package/corpus/core/src/templates/workspace-root/pnpm-workspace.yaml +1 -0
- package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +2 -0
- package/corpus/templates/analytics/actions/update-dashboard.ts +8 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +117 -33
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +4 -0
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +7 -0
- package/corpus/templates/analytics/changelog/2026-06-27-dashboards-can-now-nest-under-a-parent-in-the-sidebar-via-a-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-29-analytics-pages-now-sit-closer-under-the-header-with-tighter.md +6 -0
- package/corpus/templates/assets/actions/generate-image-batch.ts +3 -0
- package/corpus/templates/assets/actions/generate-image.ts +3 -0
- package/corpus/templates/assets/changelog/2026-06-29-longer-agent-generation-window.md +6 -0
- package/corpus/templates/assets/netlify.toml +3 -3
- package/corpus/templates/assets/server/plugins/agent-chat.ts +4 -1
- package/corpus/templates/clips/app/components/capture-install-options.tsx +7 -8
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +1 -1
- package/corpus/templates/content/AGENTS.md +57 -44
- package/corpus/templates/content/README.md +16 -0
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +125 -0
- package/corpus/templates/content/actions/_builder-cms-source-adapter.ts +28 -6
- package/corpus/templates/content/actions/_builder-cms-write-adapter.ts +238 -69
- package/corpus/templates/content/actions/_builder-cms-write-settings.ts +125 -43
- package/corpus/templates/content/actions/_database-source-utils.ts +746 -97
- package/corpus/templates/content/actions/_database-utils.ts +17 -14
- package/corpus/templates/content/actions/_federation-join.ts +14 -2
- package/corpus/templates/content/actions/_join-suggestion.ts +89 -14
- package/corpus/templates/content/actions/_local-file-documents.ts +2 -1
- package/corpus/templates/content/actions/attach-content-database-source.ts +124 -5
- package/corpus/templates/content/actions/bind-content-database-source-field.ts +256 -0
- package/corpus/templates/content/actions/change-content-database-source-role.ts +420 -0
- package/corpus/templates/content/actions/create-document.ts +8 -0
- package/corpus/templates/content/actions/execute-builder-source-batch.ts +282 -0
- package/corpus/templates/content/actions/execute-builder-source-execution.ts +220 -8
- package/corpus/templates/content/actions/get-content-database.ts +10 -2
- package/corpus/templates/content/actions/prepare-builder-source-execution.ts +19 -2
- package/corpus/templates/content/actions/prepare-builder-source-review.ts +47 -15
- package/corpus/templates/content/actions/refresh-content-database-source.ts +11 -4
- package/corpus/templates/content/actions/review-content-database-source-change-set.ts +6 -2
- package/corpus/templates/content/actions/set-content-database-source-write-mode.ts +32 -12
- package/corpus/templates/content/actions/stage-builder-revision.ts +14 -10
- package/corpus/templates/content/actions/validate-builder-source-execution.ts +25 -3
- package/corpus/templates/content/app/blocks/BuilderDocsBlocks.tsx +10 -0
- package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +1 -0
- package/corpus/templates/content/app/components/editor/ContentReferencePreview.tsx +185 -0
- package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +1520 -553
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +3 -0
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +150 -1
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +19 -0
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +647 -66
- package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +543 -204
- package/corpus/templates/content/app/components/editor/extensions/ContentReferenceNode.tsx +82 -0
- package/corpus/templates/content/app/global.css +9 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +62 -0
- package/corpus/templates/content/app/i18n/zh-TW.ts +76 -0
- package/corpus/templates/content/app/i18n-data.ts +924 -0
- package/corpus/templates/content/changelog/2026-06-29-builder-review-checks-now-preserve-publish-and-unpublish-cho.md +6 -0
- package/corpus/templates/content/changelog/2026-06-29-database-sources-can-now-be-added-as-more-rows-or-matched.md +6 -0
- package/corpus/templates/content/changelog/2026-06-29-fixed-loading-the-final-rows-in-larger-databases-without-bre.md +6 -0
- package/corpus/templates/content/changelog/2026-06-29-reusable-mdx-references-now-preview-linked-local-documents-i.md +6 -0
- package/corpus/templates/content/shared/api.ts +91 -1
- package/corpus/templates/content/shared/builder-docs-blocks.ts +8 -0
- package/corpus/templates/content/shared/builder-mdx.ts +141 -4
- package/corpus/templates/content/shared/nfm.ts +62 -0
- package/corpus/templates/content/vite.config.ts +14 -7
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +10 -11
- package/corpus/templates/design/AGENTS.md +5 -0
- package/corpus/templates/design/_gitignore +7 -0
- package/corpus/templates/design/actions/apply-visual-edit.ts +22 -12
- package/corpus/templates/design/actions/create-design-system.ts +15 -4
- package/corpus/templates/design/actions/create-file.ts +20 -1
- package/corpus/templates/design/actions/delete-design-system.ts +2 -2
- package/corpus/templates/design/actions/duplicate-design.ts +35 -9
- package/corpus/templates/design/actions/generate-design.ts +146 -69
- package/corpus/templates/design/actions/generate-screens.ts +51 -19
- package/corpus/templates/design/actions/get-design-snapshot.ts +5 -1
- package/corpus/templates/design/actions/get-design.ts +2 -0
- package/corpus/templates/design/actions/import-design-project.ts +28 -9
- package/corpus/templates/design/actions/import-document.ts +22 -8
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +6 -153
- package/corpus/templates/design/actions/navigate.ts +105 -54
- package/corpus/templates/design/actions/set-default-design-system.ts +17 -3
- package/corpus/templates/design/actions/show-design-questions.ts +2 -0
- package/corpus/templates/design/actions/update-design.ts +2 -1
- package/corpus/templates/design/actions/view-screen.ts +12 -6
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +4 -4
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +159 -41
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +8 -4
- package/corpus/templates/design/app/components/design/DrawOverlay.tsx +37 -42
- package/corpus/templates/design/app/components/design/EditPanel.tsx +336 -183
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +153 -34
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +135 -33
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +6 -0
- package/corpus/templates/design/app/components/design/TweaksPanel.tsx +2 -1
- package/corpus/templates/design/app/components/design/inspector/AlignmentMatrix.tsx +4 -10
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +84 -43
- package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +4 -4
- package/corpus/templates/design/app/components/design/inspector/{FigmaColorPicker.tsx → DesignColorPicker.tsx} +89 -62
- package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +14 -26
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +40 -12
- package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +13 -4
- package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +13 -13
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +13 -9
- package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +13 -4
- package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +6 -6
- package/corpus/templates/design/app/components/design/inspector/{figma-icons.tsx → design-icons.tsx} +2 -2
- package/corpus/templates/design/app/components/design/inspector/index.ts +12 -12
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +5 -2
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +3 -3
- package/corpus/templates/design/app/components/layout/Layout.tsx +5 -2
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +1 -1
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +167 -91
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +16 -3
- package/corpus/templates/design/app/components/visual-editor/SaveStatusIndicator.tsx +15 -0
- package/corpus/templates/design/app/global.css +4 -0
- package/corpus/templates/design/app/hooks/use-design-system.ts +4 -1
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +38 -3
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +9 -2
- package/corpus/templates/design/app/i18n/zh-TW.ts +22 -0
- package/corpus/templates/design/app/i18n-data.ts +527 -0
- package/corpus/templates/design/app/lib/design-systems.ts +6 -4
- package/corpus/templates/design/app/lib/design-templates.ts +15 -3
- package/corpus/templates/design/app/pages/DesignEditor.tsx +641 -158
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +42 -34
- package/corpus/templates/design/app/pages/VisualEdit.tsx +100 -0
- package/corpus/templates/design/app/root.tsx +42 -9
- package/corpus/templates/design/app/routes/visual-edit.tsx +7 -0
- package/corpus/templates/design/changelog/2026-06-28-live-cursors-now-keep-names-beside-a-cleaner-pointer-marker.md +1 -1
- package/corpus/templates/design/changelog/2026-06-28-mode-switching-now-lives-in-a-compact-bottom-right-icon-dock.md +1 -1
- package/corpus/templates/design/changelog/2026-06-28-visual-code-design-mode.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-generation-prompts-now-show-connect-ai-before-sending.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-design-mode-top-chrome-now-groups-collaborators-preview-shar.md +1 -1
- package/corpus/templates/design/changelog/2026-06-29-fixed-design-editor-exports-and-gradient-edits-so-multi-scre.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-png-export-handles-modern-css-color-functions-more-reliably.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-png-export-now-ignores-duplicate-clicks-while-a-download-is-.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-public-visual-edit-and-shared-design-links-now-invite-visito.md +6 -0
- package/corpus/templates/design/changelog/2026-06-29-visual-edit-actions-now-reject-missing-design-targets-before.md +6 -0
- package/corpus/templates/design/e2e/README.md +71 -0
- package/corpus/templates/design/e2e/global-setup.ts +157 -0
- package/corpus/templates/design/e2e/helpers.ts +148 -0
- package/corpus/templates/design/netlify.toml +3 -4
- package/corpus/templates/design/package.json +5 -1
- package/corpus/templates/design/playwright.config.ts +51 -0
- package/corpus/templates/design/server/handlers/index-design-system-with-builder.ts +121 -0
- package/corpus/templates/design/server/handlers/uploads.ts +89 -38
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +181 -0
- package/corpus/templates/design/server/lib/coding-handoff.ts +33 -4
- package/corpus/templates/design/server/lib/design-export.ts +35 -8
- package/corpus/templates/design/server/plugins/agent-chat.ts +4 -0
- package/corpus/templates/design/server/plugins/auth.ts +10 -1
- package/corpus/templates/design/server/routes/api/index-design-system-with-builder.post.ts +1 -0
- package/corpus/templates/design/shared/api.ts +2 -0
- package/corpus/templates/design/shared/apply-edits.ts +12 -8
- package/corpus/templates/design/shared/canvas-math.ts +19 -1
- package/corpus/templates/design/shared/code-layer.ts +87 -28
- package/corpus/templates/design/shared/generation-session.ts +1 -0
- package/corpus/templates/design/shared/resolve-tweaks.ts +4 -3
- package/corpus/templates/design/shared/shader-presets.ts +10 -0
- package/corpus/templates/design/shared/source-mode.ts +9 -0
- package/corpus/templates/design/vitest.config.ts +2 -1
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +1 -1
- package/corpus/templates/plan/.agents/skills/visual-plan/references/canvas.md +1 -1
- package/corpus/templates/plan/AGENTS.md +1 -1
- package/corpus/templates/plan/actions/create-plan-design.ts +1 -1
- package/corpus/templates/plan/actions/validate-local-plan-source.ts +2 -10
- package/corpus/templates/plan/app/pages/PlansPage.tsx +1 -0
- package/corpus/templates/plan/docs/commenting-ux-plan.md +2 -2
- package/corpus/templates/plan/server/plan-content.ts +1 -1
- package/corpus/templates/plan/server/ui-plan-html.ts +2 -2
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +6 -153
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +53 -38
- package/corpus/templates/slides/app/components/design-system/{fig-import-response.ts → builder-index-response.ts} +9 -6
- package/corpus/templates/slides/app/components/visual-editor/MultiSelectChip.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-06-29-design-system-setup-now-indexes-uploaded-design-files-throug.md +6 -0
- package/corpus/templates/slides/changelog/2026-06-29-longer-hosted-agent-turns.md +6 -0
- package/corpus/templates/slides/netlify.toml +3 -6
- package/corpus/templates/slides/server/handlers/index-design-system-with-builder.ts +116 -0
- package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +179 -0
- package/corpus/templates/slides/server/plugins/agent-chat.ts +4 -1
- package/corpus/templates/slides/server/routes/api/index-design-system-with-builder.post.ts +1 -0
- package/dist/action.d.ts +15 -0
- package/dist/action.d.ts.map +1 -1
- package/dist/action.js +6 -0
- package/dist/action.js.map +1 -1
- package/dist/agent/durable-background.d.ts +9 -7
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +27 -11
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/production-agent.d.ts +7 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +4 -1
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-loop-with-resume.d.ts +2 -1
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +2 -2
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/brand-kit/fig/index.d.ts +4 -4
- package/dist/brand-kit/fig/index.d.ts.map +1 -1
- package/dist/brand-kit/fig/index.js +14 -27
- package/dist/brand-kit/fig/index.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +1 -0
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-config-writers.d.ts +15 -7
- package/dist/cli/mcp-config-writers.d.ts.map +1 -1
- package/dist/cli/mcp-config-writers.js +198 -45
- package/dist/cli/mcp-config-writers.js.map +1 -1
- package/dist/cli/skills.d.ts +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +18 -3
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +11 -1
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +15 -2
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/composer/PromptComposer.d.ts.map +1 -1
- package/dist/client/composer/PromptComposer.js +35 -1
- package/dist/client/composer/PromptComposer.js.map +1 -1
- package/dist/client/org/OrgSwitcher.js +1 -1
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +1 -1
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +2 -15
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/collab/presence.d.ts +1 -1
- package/dist/collab/presence.js +1 -1
- package/dist/collab/presence.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/mcp/connect-route.d.ts.map +1 -1
- package/dist/mcp/connect-route.js +34 -5
- package/dist/mcp/connect-route.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +8 -8
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +5 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts +6 -0
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +12 -3
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/sharing/registry.d.ts.map +1 -1
- package/dist/sharing/registry.js +11 -0
- package/dist/sharing/registry.js.map +1 -1
- package/dist/templates/default/pnpm-workspace.yaml +1 -0
- package/dist/templates/workspace-root/pnpm-workspace.yaml +1 -0
- package/docs/content/locales/ar-SA/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/ar-SA/template-design.mdx +1 -1
- package/docs/content/locales/de-DE/real-time-collaboration.mdx +3 -3
- package/docs/content/locales/de-DE/template-design.mdx +1 -1
- package/docs/content/locales/es-ES/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/es-ES/template-design.mdx +1 -1
- package/docs/content/locales/fr-FR/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/fr-FR/template-design.mdx +1 -1
- package/docs/content/locales/hi-IN/template-design.mdx +1 -1
- package/docs/content/locales/ja-JP/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/ja-JP/template-design.mdx +1 -1
- package/docs/content/locales/ko-KR/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/ko-KR/template-design.mdx +1 -1
- package/docs/content/locales/pt-BR/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/pt-BR/template-design.mdx +1 -1
- package/docs/content/locales/zh-CN/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/zh-CN/template-design.mdx +1 -1
- package/docs/content/locales/zh-TW/real-time-collaboration.mdx +2 -2
- package/docs/content/locales/zh-TW/template-design.mdx +1 -1
- package/docs/content/real-time-collaboration.mdx +2 -2
- package/docs/content/template-design.mdx +1 -1
- package/package.json +3 -7
- package/src/templates/default/pnpm-workspace.yaml +1 -0
- package/src/templates/workspace-root/pnpm-workspace.yaml +1 -0
- package/corpus/core/src/brand-kit/fig/decode.ts +0 -410
- package/corpus/core/src/brand-kit/fig/extract-design-system.ts +0 -947
- package/corpus/core/src/brand-kit/fig/fig-to-html.ts +0 -1906
- package/corpus/templates/design/actions/import-figma.ts +0 -55
- package/corpus/templates/design/changelog/2026-06-28-figma-style-code-design-mode.md +0 -6
- package/corpus/templates/design/server/handlers/import-figma-system.ts +0 -86
- package/corpus/templates/design/server/routes/api/import-figma-system.post.ts +0 -1
- package/corpus/templates/slides/server/handlers/import-figma-system.ts +0 -101
- package/corpus/templates/slides/server/routes/api/import-figma-system.post.ts +0 -1
- package/dist/brand-kit/fig/decode.d.ts +0 -33
- package/dist/brand-kit/fig/decode.d.ts.map +0 -1
- package/dist/brand-kit/fig/decode.js +0 -358
- package/dist/brand-kit/fig/decode.js.map +0 -1
- package/dist/brand-kit/fig/extract-design-system.d.ts +0 -44
- package/dist/brand-kit/fig/extract-design-system.d.ts.map +0 -1
- package/dist/brand-kit/fig/extract-design-system.js +0 -752
- package/dist/brand-kit/fig/extract-design-system.js.map +0 -1
- package/dist/brand-kit/fig/fig-to-html.d.ts +0 -246
- package/dist/brand-kit/fig/fig-to-html.d.ts.map +0 -1
- package/dist/brand-kit/fig/fig-to-html.js +0 -1506
- package/dist/brand-kit/fig/fig-to-html.js.map +0 -1
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client";
|
|
2
|
+
import { BUILDER_CMS_SAFE_WRITE_MODEL } from "@shared/api";
|
|
2
3
|
import type {
|
|
4
|
+
BuilderCmsPublicationTransitionIntent,
|
|
5
|
+
BuilderCmsWriteEffect,
|
|
3
6
|
ContentDatabaseSource,
|
|
4
|
-
ContentDatabaseSourceChangeSet,
|
|
5
7
|
ContentDatabaseSourceReviewPayload,
|
|
6
8
|
DocumentPropertyValue,
|
|
9
|
+
ExecuteBuilderSourceBatchTransition,
|
|
10
|
+
ExecuteBuilderSourceBatchResponse,
|
|
7
11
|
} from "@shared/api";
|
|
8
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
IconAlertTriangle,
|
|
14
|
+
IconCheck,
|
|
15
|
+
IconCloudUpload,
|
|
16
|
+
IconX,
|
|
17
|
+
} from "@tabler/icons-react";
|
|
18
|
+
import { useEffect, useMemo, useState } from "react";
|
|
9
19
|
|
|
10
20
|
import { Button } from "@/components/ui/button";
|
|
11
21
|
import {
|
|
@@ -16,54 +26,190 @@ import {
|
|
|
16
26
|
} from "@/components/ui/dialog";
|
|
17
27
|
import { Spinner } from "@/components/ui/spinner";
|
|
18
28
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
29
|
+
export type BuilderReviewPublicationTransitionSelection = {
|
|
30
|
+
publicationTransition: BuilderCmsPublicationTransitionIntent;
|
|
31
|
+
confirmUnpublish?: boolean;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type BuilderReviewPublicationTransitionSelections = Record<
|
|
35
|
+
string,
|
|
36
|
+
BuilderReviewPublicationTransitionSelection
|
|
37
|
+
>;
|
|
38
|
+
|
|
39
|
+
export type BuilderReviewPublicationTransitions = Record<
|
|
40
|
+
string,
|
|
41
|
+
ExecuteBuilderSourceBatchTransition
|
|
42
|
+
>;
|
|
43
|
+
|
|
44
|
+
const EFFECT_LABELS: Record<
|
|
45
|
+
BuilderCmsWriteEffect,
|
|
46
|
+
{ tag: string; sentence: string }
|
|
47
|
+
> = {
|
|
48
|
+
create_draft: { tag: "New", sentence: "Creates a new draft entry" },
|
|
49
|
+
update_in_place: { tag: "Edit", sentence: "Updates the live entry" },
|
|
50
|
+
autosave: { tag: "Draft", sentence: "Saves a draft revision" },
|
|
51
|
+
publish: { tag: "Publish", sentence: "Publishes this entry" },
|
|
52
|
+
unpublish: { tag: "Unpublish", sentence: "Unpublishes the live entry" },
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export function builderReviewRowEffectLabel(effect: BuilderCmsWriteEffect) {
|
|
56
|
+
return EFFECT_LABELS[effect] ?? EFFECT_LABELS.update_in_place;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** The effect a row will actually run, accounting for a chosen transition. */
|
|
60
|
+
export function builderReviewEffectiveRowEffect(
|
|
61
|
+
baseEffect: BuilderCmsWriteEffect,
|
|
62
|
+
selection?: BuilderReviewPublicationTransitionSelection,
|
|
63
|
+
): BuilderCmsWriteEffect {
|
|
64
|
+
// A create has no Builder entry yet, so a publish/unpublish transition can't
|
|
65
|
+
// apply — the adapter always writes a draft (create_draft) when there's no
|
|
66
|
+
// entry id. Never let a transition relabel a create.
|
|
67
|
+
if (baseEffect === "create_draft") return "create_draft";
|
|
68
|
+
if (selection?.publicationTransition === "publish") return "publish";
|
|
69
|
+
if (selection?.publicationTransition === "unpublish") return "unpublish";
|
|
70
|
+
return baseEffect;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function builderReviewIntentSummary(
|
|
74
|
+
rows: { changeSetId: string; effect: BuilderCmsWriteEffect }[],
|
|
75
|
+
selections: BuilderReviewPublicationTransitionSelections,
|
|
76
|
+
) {
|
|
77
|
+
const counts: Record<BuilderCmsWriteEffect, number> = {
|
|
78
|
+
create_draft: 0,
|
|
79
|
+
update_in_place: 0,
|
|
80
|
+
autosave: 0,
|
|
81
|
+
publish: 0,
|
|
82
|
+
unpublish: 0,
|
|
83
|
+
};
|
|
84
|
+
for (const row of rows) {
|
|
85
|
+
counts[
|
|
86
|
+
builderReviewEffectiveRowEffect(row.effect, selections[row.changeSetId])
|
|
87
|
+
] += 1;
|
|
88
|
+
}
|
|
89
|
+
const parts: string[] = [];
|
|
90
|
+
if (counts.create_draft) {
|
|
91
|
+
parts.push(
|
|
92
|
+
`${counts.create_draft} draft${counts.create_draft === 1 ? "" : "s"} to create`,
|
|
93
|
+
);
|
|
22
94
|
}
|
|
23
|
-
if (
|
|
24
|
-
|
|
95
|
+
if (counts.update_in_place) {
|
|
96
|
+
parts.push(
|
|
97
|
+
`${counts.update_in_place} update${counts.update_in_place === 1 ? "" : "s"}`,
|
|
98
|
+
);
|
|
25
99
|
}
|
|
26
|
-
|
|
100
|
+
if (counts.autosave) {
|
|
101
|
+
parts.push(
|
|
102
|
+
`${counts.autosave} draft save${counts.autosave === 1 ? "" : "s"}`,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
if (counts.publish) parts.push(`${counts.publish} to publish`);
|
|
106
|
+
if (counts.unpublish) parts.push(`${counts.unpublish} to unpublish`);
|
|
107
|
+
return parts.join(" · ") || "No changes";
|
|
27
108
|
}
|
|
28
109
|
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
110
|
+
export function builderReviewDestinationLine(args: {
|
|
111
|
+
rows: { changeSetId: string; effect: BuilderCmsWriteEffect }[];
|
|
112
|
+
selections: BuilderReviewPublicationTransitionSelections;
|
|
113
|
+
liveWritesEnabled: boolean;
|
|
114
|
+
}) {
|
|
115
|
+
if (!args.liveWritesEnabled) {
|
|
116
|
+
return "Checks the update only — nothing is sent to Builder.";
|
|
117
|
+
}
|
|
118
|
+
const effects = new Set(
|
|
119
|
+
args.rows.map((row) =>
|
|
120
|
+
builderReviewEffectiveRowEffect(
|
|
121
|
+
row.effect,
|
|
122
|
+
args.selections[row.changeSetId],
|
|
123
|
+
),
|
|
124
|
+
),
|
|
125
|
+
);
|
|
126
|
+
if (effects.has("unpublish")) {
|
|
127
|
+
return "Unpublishes selected entries in Builder.";
|
|
128
|
+
}
|
|
129
|
+
if (effects.has("publish")) {
|
|
130
|
+
return "Publishes selected entries in Builder.";
|
|
131
|
+
}
|
|
132
|
+
if (effects.size === 1 && effects.has("create_draft")) {
|
|
133
|
+
return args.rows.length === 1
|
|
134
|
+
? "Writes a new draft to Builder — won't publish."
|
|
135
|
+
: "Writes new drafts to Builder — nothing is published.";
|
|
136
|
+
}
|
|
137
|
+
return "Updates content in Builder — publication state is preserved.";
|
|
34
138
|
}
|
|
35
139
|
|
|
36
|
-
function
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
140
|
+
export function builderReviewResultStatus(status?: string): {
|
|
141
|
+
// i18n key under the `database.` namespace; resolved by the caller via t().
|
|
142
|
+
labelKey: string;
|
|
143
|
+
tone: "ok" | "warn" | "danger" | "muted";
|
|
144
|
+
} {
|
|
145
|
+
switch (status) {
|
|
146
|
+
case "succeeded":
|
|
147
|
+
return { labelKey: "pushed", tone: "ok" };
|
|
148
|
+
case "validated":
|
|
149
|
+
return { labelKey: "ready", tone: "ok" };
|
|
150
|
+
case "partial":
|
|
151
|
+
case "blocked":
|
|
152
|
+
return { labelKey: "needsAttention", tone: "warn" };
|
|
153
|
+
case "failed":
|
|
154
|
+
return { labelKey: "failedYouCanRetry", tone: "danger" };
|
|
155
|
+
case "stale":
|
|
156
|
+
return { labelKey: "needsAFreshReview", tone: "warn" };
|
|
157
|
+
case "running":
|
|
158
|
+
return { labelKey: "working", tone: "muted" };
|
|
159
|
+
case "write_disabled":
|
|
160
|
+
return { labelKey: "checksOnly", tone: "muted" };
|
|
161
|
+
default:
|
|
162
|
+
return { labelKey: "ready", tone: "muted" };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function resultToneClass(tone: "ok" | "warn" | "danger" | "muted") {
|
|
167
|
+
if (tone === "ok") return "text-emerald-600 dark:text-emerald-400";
|
|
168
|
+
if (tone === "warn") return "text-amber-700 dark:text-amber-300";
|
|
169
|
+
if (tone === "danger") return "text-destructive";
|
|
170
|
+
return "text-muted-foreground";
|
|
48
171
|
}
|
|
49
172
|
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
t: ReturnType<typeof useT>,
|
|
173
|
+
export function builderReviewPublicationTransitionsMap(
|
|
174
|
+
selections: BuilderReviewPublicationTransitionSelections,
|
|
53
175
|
) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
176
|
+
const transitions: BuilderReviewPublicationTransitions = {};
|
|
177
|
+
|
|
178
|
+
for (const [changeSetId, selection] of Object.entries(selections)) {
|
|
179
|
+
if (selection.publicationTransition === "publish") {
|
|
180
|
+
transitions[changeSetId] = { publicationTransition: "publish" };
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (
|
|
185
|
+
selection.publicationTransition === "unpublish" &&
|
|
186
|
+
selection.confirmUnpublish === true
|
|
187
|
+
) {
|
|
188
|
+
transitions[changeSetId] = {
|
|
189
|
+
publicationTransition: "unpublish",
|
|
190
|
+
confirmUnpublish: true,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return transitions;
|
|
58
196
|
}
|
|
59
197
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
198
|
+
const ATTENTION_TAG_EFFECTS: ReadonlySet<BuilderCmsWriteEffect> = new Set([
|
|
199
|
+
"unpublish",
|
|
200
|
+
]);
|
|
201
|
+
|
|
202
|
+
function rowEffectTagClass(effect: BuilderCmsWriteEffect) {
|
|
203
|
+
return ATTENTION_TAG_EFFECTS.has(effect)
|
|
204
|
+
? "rounded border border-amber-300 bg-amber-50 px-1.5 py-0.5 text-amber-700 dark:border-amber-800 dark:bg-amber-950/30 dark:text-amber-300"
|
|
205
|
+
: "rounded border border-border bg-muted/40 px-1.5 py-0.5 text-muted-foreground";
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function sourceValueText(value: DocumentPropertyValue) {
|
|
209
|
+
if (value === null || value === undefined || value === "") return "empty";
|
|
210
|
+
if (Array.isArray(value)) return value.join(", ") || "empty";
|
|
211
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
212
|
+
return String(value);
|
|
67
213
|
}
|
|
68
214
|
|
|
69
215
|
export function BuilderSourceReviewDialog({
|
|
@@ -72,6 +218,7 @@ export function BuilderSourceReviewDialog({
|
|
|
72
218
|
source,
|
|
73
219
|
canEdit,
|
|
74
220
|
pending,
|
|
221
|
+
batchResult = null,
|
|
75
222
|
checkedAt,
|
|
76
223
|
onClose,
|
|
77
224
|
onValidate,
|
|
@@ -81,44 +228,179 @@ export function BuilderSourceReviewDialog({
|
|
|
81
228
|
source: ContentDatabaseSource | null;
|
|
82
229
|
canEdit: boolean;
|
|
83
230
|
pending: boolean;
|
|
231
|
+
// Optional so the inline-database caller (DatabaseView) that doesn't surface
|
|
232
|
+
// batch results can still mount the dialog.
|
|
233
|
+
batchResult?: ExecuteBuilderSourceBatchResponse | null;
|
|
84
234
|
checkedAt: string | null;
|
|
85
235
|
onClose: () => void;
|
|
86
|
-
onValidate: () => void;
|
|
236
|
+
onValidate: (transitions: BuilderReviewPublicationTransitions) => void;
|
|
87
237
|
}) {
|
|
88
238
|
const t = useT();
|
|
89
239
|
const checked = !!checkedAt;
|
|
240
|
+
const safeModel =
|
|
241
|
+
source?.sourceType === "builder-cms" &&
|
|
242
|
+
source.sourceTable === BUILDER_CMS_SAFE_WRITE_MODEL;
|
|
243
|
+
const writeMode = source?.metadata.writeMode;
|
|
244
|
+
const allowPublicationTransitionControls =
|
|
245
|
+
safeModel &&
|
|
246
|
+
writeMode === "publish_updates" &&
|
|
247
|
+
source?.metadata.allowPublicationTransitions === true;
|
|
248
|
+
const reviewRows = useMemo(() => review?.rows ?? [], [review]);
|
|
249
|
+
const reviewRowIds = useMemo(
|
|
250
|
+
() => reviewRows.map((row) => row.changeSetId),
|
|
251
|
+
[reviewRows],
|
|
252
|
+
);
|
|
253
|
+
const reviewRowIdsKey = reviewRowIds.join("\u0000");
|
|
254
|
+
const [transitionSelections, setTransitionSelections] =
|
|
255
|
+
useState<BuilderReviewPublicationTransitionSelections>({});
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
if (!open || !allowPublicationTransitionControls) {
|
|
258
|
+
setTransitionSelections({});
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const reviewRowIdSet = new Set(
|
|
263
|
+
reviewRowIdsKey ? reviewRowIdsKey.split("\u0000") : [],
|
|
264
|
+
);
|
|
265
|
+
setTransitionSelections((current) => {
|
|
266
|
+
const next: BuilderReviewPublicationTransitionSelections = {};
|
|
267
|
+
for (const [changeSetId, selection] of Object.entries(current)) {
|
|
268
|
+
if (reviewRowIdSet.has(changeSetId)) next[changeSetId] = selection;
|
|
269
|
+
}
|
|
270
|
+
return Object.keys(next).length === Object.keys(current).length
|
|
271
|
+
? current
|
|
272
|
+
: next;
|
|
273
|
+
});
|
|
274
|
+
}, [allowPublicationTransitionControls, open, reviewRowIdsKey]);
|
|
275
|
+
const transitionMap = useMemo(
|
|
276
|
+
() => builderReviewPublicationTransitionsMap(transitionSelections),
|
|
277
|
+
[transitionSelections],
|
|
278
|
+
);
|
|
279
|
+
const intentSummary = builderReviewIntentSummary(
|
|
280
|
+
reviewRows,
|
|
281
|
+
transitionSelections,
|
|
282
|
+
);
|
|
283
|
+
const destinationLine = builderReviewDestinationLine({
|
|
284
|
+
rows: reviewRows,
|
|
285
|
+
selections: transitionSelections,
|
|
286
|
+
liveWritesEnabled: review?.liveWritesEnabled === true,
|
|
287
|
+
});
|
|
288
|
+
const hasUnconfirmedUnpublish = Object.values(transitionSelections).some(
|
|
289
|
+
(selection) =>
|
|
290
|
+
selection.publicationTransition === "unpublish" &&
|
|
291
|
+
selection.confirmUnpublish !== true,
|
|
292
|
+
);
|
|
293
|
+
const batchHasIssues =
|
|
294
|
+
!!batchResult &&
|
|
295
|
+
(batchResult.summary.blocked > 0 || batchResult.summary.failed > 0);
|
|
90
296
|
const retryable =
|
|
91
297
|
review?.result.status === "failed" ||
|
|
92
298
|
review?.result.status === "blocked" ||
|
|
93
|
-
review?.result.status === "stale"
|
|
299
|
+
review?.result.status === "stale" ||
|
|
300
|
+
batchHasIssues;
|
|
301
|
+
const unsafeLiveTarget = review?.liveWritesEnabled === true && !safeModel;
|
|
94
302
|
const disabled =
|
|
95
303
|
!canEdit ||
|
|
96
304
|
pending ||
|
|
97
305
|
(!retryable && checked) ||
|
|
98
306
|
!review ||
|
|
99
|
-
review.rows.length === 0
|
|
100
|
-
|
|
307
|
+
review.rows.length === 0 ||
|
|
308
|
+
unsafeLiveTarget ||
|
|
309
|
+
hasUnconfirmedUnpublish;
|
|
310
|
+
const rowTitleById = new Map(
|
|
311
|
+
reviewRows.map((row) => [row.changeSetId, row.title]),
|
|
312
|
+
);
|
|
313
|
+
const batchIssueResults =
|
|
314
|
+
batchResult?.results.filter((result) => result.status !== "succeeded") ??
|
|
315
|
+
[];
|
|
316
|
+
const resultStatus = builderReviewResultStatus(
|
|
317
|
+
batchResult
|
|
318
|
+
? batchHasIssues
|
|
319
|
+
? "partial"
|
|
320
|
+
: "succeeded"
|
|
321
|
+
: review?.result.status,
|
|
322
|
+
);
|
|
323
|
+
const footerHint = pending
|
|
101
324
|
? review?.liveWritesEnabled
|
|
102
|
-
?
|
|
103
|
-
:
|
|
104
|
-
:
|
|
105
|
-
?
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
325
|
+
? "Sending to Builder…"
|
|
326
|
+
: "Checking…"
|
|
327
|
+
: hasUnconfirmedUnpublish
|
|
328
|
+
? "Confirm unpublish on the selected rows first."
|
|
329
|
+
: unsafeLiveTarget
|
|
330
|
+
? `Live pushes are limited to the ${BUILDER_CMS_SAFE_WRITE_MODEL} test model.`
|
|
331
|
+
: null;
|
|
332
|
+
const effectiveEffects = new Set(
|
|
333
|
+
reviewRows.map((row) =>
|
|
334
|
+
builderReviewEffectiveRowEffect(
|
|
335
|
+
row.effect,
|
|
336
|
+
transitionSelections[row.changeSetId],
|
|
337
|
+
),
|
|
338
|
+
),
|
|
339
|
+
);
|
|
340
|
+
const pushVerb = !review?.liveWritesEnabled
|
|
341
|
+
? "Check"
|
|
342
|
+
: effectiveEffects.has("unpublish")
|
|
343
|
+
? "Unpublish"
|
|
344
|
+
: effectiveEffects.has("publish")
|
|
345
|
+
? "Publish"
|
|
346
|
+
: effectiveEffects.size === 1 && effectiveEffects.has("create_draft")
|
|
347
|
+
? reviewRows.length > 1
|
|
348
|
+
? `Create ${reviewRows.length} drafts`
|
|
349
|
+
: "Create draft"
|
|
350
|
+
: reviewRows.length > 1
|
|
351
|
+
? `Push ${reviewRows.length} updates`
|
|
352
|
+
: "Push update";
|
|
113
353
|
const buttonLabel = pending
|
|
114
354
|
? review?.liveWritesEnabled
|
|
115
|
-
?
|
|
116
|
-
:
|
|
117
|
-
: checked &&
|
|
118
|
-
?
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
355
|
+
? "Working…"
|
|
356
|
+
: "Checking…"
|
|
357
|
+
: checked && batchResult
|
|
358
|
+
? batchHasIssues
|
|
359
|
+
? "Retry"
|
|
360
|
+
: "Pushed"
|
|
361
|
+
: checked && review?.result.status === "succeeded"
|
|
362
|
+
? "Pushed"
|
|
363
|
+
: checked && !retryable
|
|
364
|
+
? "Checked"
|
|
365
|
+
: pushVerb;
|
|
366
|
+
|
|
367
|
+
function setRowPublicationTransition(
|
|
368
|
+
changeSetId: string,
|
|
369
|
+
publicationTransition: BuilderCmsPublicationTransitionIntent,
|
|
370
|
+
) {
|
|
371
|
+
setTransitionSelections((current) => {
|
|
372
|
+
const currentSelection = current[changeSetId];
|
|
373
|
+
const next = { ...current };
|
|
374
|
+
|
|
375
|
+
if (currentSelection?.publicationTransition === publicationTransition) {
|
|
376
|
+
delete next[changeSetId];
|
|
377
|
+
return next;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
next[changeSetId] = {
|
|
381
|
+
publicationTransition,
|
|
382
|
+
confirmUnpublish:
|
|
383
|
+
publicationTransition === "unpublish" ? false : undefined,
|
|
384
|
+
};
|
|
385
|
+
return next;
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function setRowConfirmUnpublish(changeSetId: string, confirmed: boolean) {
|
|
390
|
+
setTransitionSelections((current) => {
|
|
391
|
+
const currentSelection = current[changeSetId];
|
|
392
|
+
if (currentSelection?.publicationTransition !== "unpublish") {
|
|
393
|
+
return current;
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
...current,
|
|
397
|
+
[changeSetId]: {
|
|
398
|
+
publicationTransition: "unpublish",
|
|
399
|
+
confirmUnpublish: confirmed,
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
});
|
|
403
|
+
}
|
|
122
404
|
|
|
123
405
|
return (
|
|
124
406
|
<Dialog
|
|
@@ -140,7 +422,7 @@ export function BuilderSourceReviewDialog({
|
|
|
140
422
|
{t("database.reviewBuilderUpdate")}
|
|
141
423
|
</DialogTitle>
|
|
142
424
|
<DialogDescription className="truncate text-xs text-muted-foreground">
|
|
143
|
-
{review?.summary ??
|
|
425
|
+
{review?.summary ?? "No pending Builder changes."}
|
|
144
426
|
</DialogDescription>
|
|
145
427
|
</div>
|
|
146
428
|
<button
|
|
@@ -161,178 +443,235 @@ export function BuilderSourceReviewDialog({
|
|
|
161
443
|
{t("database.whatChanged")}
|
|
162
444
|
</div>
|
|
163
445
|
<div className="grid gap-2">
|
|
164
|
-
{
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
446
|
+
{reviewRows.map((row) => {
|
|
447
|
+
const selection = transitionSelections[row.changeSetId];
|
|
448
|
+
const effect = builderReviewEffectiveRowEffect(
|
|
449
|
+
row.effect,
|
|
450
|
+
selection,
|
|
451
|
+
);
|
|
452
|
+
const { tag, sentence } =
|
|
453
|
+
builderReviewRowEffectLabel(effect);
|
|
454
|
+
const showConflict =
|
|
455
|
+
effect !== "create_draft" &&
|
|
456
|
+
row.conflictState === "source_changed";
|
|
457
|
+
return (
|
|
458
|
+
<div
|
|
459
|
+
key={row.changeSetId}
|
|
460
|
+
className="rounded-md border border-border p-3"
|
|
461
|
+
>
|
|
462
|
+
<div className="flex min-w-0 items-start justify-between gap-3">
|
|
463
|
+
<div className="min-w-0">
|
|
464
|
+
<div className="truncate text-sm font-medium">
|
|
465
|
+
{row.title}
|
|
466
|
+
</div>
|
|
467
|
+
<div className="mt-1 text-xs text-muted-foreground">
|
|
468
|
+
{sentence}
|
|
469
|
+
</div>
|
|
181
470
|
</div>
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
<div className="mt-3 grid gap-2">
|
|
188
|
-
{row.fieldChanges.map((field) => (
|
|
189
|
-
<div
|
|
190
|
-
key={`${row.changeSetId}-${field.localFieldKey}`}
|
|
191
|
-
className="grid gap-1 rounded border border-border/70 bg-muted/20 p-2 text-xs"
|
|
471
|
+
<span
|
|
472
|
+
className={
|
|
473
|
+
"shrink-0 text-[11px] " +
|
|
474
|
+
rowEffectTagClass(effect)
|
|
475
|
+
}
|
|
192
476
|
>
|
|
193
|
-
|
|
194
|
-
|
|
477
|
+
{tag}
|
|
478
|
+
</span>
|
|
479
|
+
</div>
|
|
480
|
+
<div className="mt-3 grid gap-2">
|
|
481
|
+
{allowPublicationTransitionControls &&
|
|
482
|
+
row.effect !== "create_draft" ? (
|
|
483
|
+
<div className="flex flex-wrap items-center gap-1.5 text-xs">
|
|
484
|
+
<Button
|
|
485
|
+
type="button"
|
|
486
|
+
size="sm"
|
|
487
|
+
variant={
|
|
488
|
+
transitionSelections[row.changeSetId]
|
|
489
|
+
?.publicationTransition === "publish"
|
|
490
|
+
? "secondary"
|
|
491
|
+
: "outline"
|
|
492
|
+
}
|
|
493
|
+
className="h-7 px-2 text-xs"
|
|
494
|
+
disabled={pending}
|
|
495
|
+
aria-pressed={
|
|
496
|
+
transitionSelections[row.changeSetId]
|
|
497
|
+
?.publicationTransition === "publish"
|
|
498
|
+
}
|
|
499
|
+
onClick={() =>
|
|
500
|
+
setRowPublicationTransition(
|
|
501
|
+
row.changeSetId,
|
|
502
|
+
"publish",
|
|
503
|
+
)
|
|
504
|
+
}
|
|
505
|
+
>
|
|
506
|
+
Publish
|
|
507
|
+
</Button>
|
|
508
|
+
<Button
|
|
509
|
+
type="button"
|
|
510
|
+
size="sm"
|
|
511
|
+
variant={
|
|
512
|
+
transitionSelections[row.changeSetId]
|
|
513
|
+
?.publicationTransition === "unpublish"
|
|
514
|
+
? "destructive"
|
|
515
|
+
: "outline"
|
|
516
|
+
}
|
|
517
|
+
className="h-7 px-2 text-xs"
|
|
518
|
+
disabled={pending}
|
|
519
|
+
aria-pressed={
|
|
520
|
+
transitionSelections[row.changeSetId]
|
|
521
|
+
?.publicationTransition === "unpublish"
|
|
522
|
+
}
|
|
523
|
+
onClick={() =>
|
|
524
|
+
setRowPublicationTransition(
|
|
525
|
+
row.changeSetId,
|
|
526
|
+
"unpublish",
|
|
527
|
+
)
|
|
528
|
+
}
|
|
529
|
+
>
|
|
530
|
+
Unpublish
|
|
531
|
+
</Button>
|
|
532
|
+
{transitionSelections[row.changeSetId]
|
|
533
|
+
?.publicationTransition === "unpublish" ? (
|
|
534
|
+
<label className="flex items-center gap-1 rounded border border-destructive/30 bg-destructive/10 px-1.5 py-1 text-[11px] text-destructive">
|
|
535
|
+
<input
|
|
536
|
+
type="checkbox"
|
|
537
|
+
className="size-3 accent-destructive"
|
|
538
|
+
checked={
|
|
539
|
+
transitionSelections[row.changeSetId]
|
|
540
|
+
?.confirmUnpublish === true
|
|
541
|
+
}
|
|
542
|
+
disabled={pending}
|
|
543
|
+
onChange={(event) =>
|
|
544
|
+
setRowConfirmUnpublish(
|
|
545
|
+
row.changeSetId,
|
|
546
|
+
event.currentTarget.checked,
|
|
547
|
+
)
|
|
548
|
+
}
|
|
549
|
+
/>
|
|
550
|
+
{t("database.confirmUnpublish")}
|
|
551
|
+
</label>
|
|
552
|
+
) : null}
|
|
195
553
|
</div>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
554
|
+
) : null}
|
|
555
|
+
{row.fieldChanges.map((field) => (
|
|
556
|
+
<div
|
|
557
|
+
key={`${row.changeSetId}-${field.localFieldKey}`}
|
|
558
|
+
className="grid gap-1 rounded border border-border/70 bg-muted/20 p-2 text-xs"
|
|
559
|
+
>
|
|
560
|
+
<div className="font-medium">
|
|
561
|
+
{field.propertyName ?? field.sourceFieldKey}
|
|
204
562
|
</div>
|
|
205
|
-
<div className="
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
)
|
|
211
|
-
|
|
563
|
+
<div className="grid gap-1 text-muted-foreground sm:grid-cols-2">
|
|
564
|
+
<div className="min-w-0 break-words">
|
|
565
|
+
From: {sourceValueText(field.currentValue)}
|
|
566
|
+
</div>
|
|
567
|
+
<div className="min-w-0 break-words">
|
|
568
|
+
To: {sourceValueText(field.proposedValue)}
|
|
569
|
+
</div>
|
|
212
570
|
</div>
|
|
213
571
|
</div>
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
572
|
+
))}
|
|
573
|
+
{row.bodyChange ? (
|
|
574
|
+
<div className="rounded border border-border/70 bg-muted/20 p-2 text-xs">
|
|
575
|
+
<div className="font-medium">
|
|
576
|
+
{row.bodyChange.summary}
|
|
577
|
+
</div>
|
|
578
|
+
<div className="mt-1 text-muted-foreground">
|
|
579
|
+
{t("database.builderBodyEditsNeedSaferPath")}
|
|
580
|
+
</div>
|
|
220
581
|
</div>
|
|
221
|
-
|
|
222
|
-
|
|
582
|
+
) : null}
|
|
583
|
+
{showConflict ? (
|
|
584
|
+
<div className="flex items-start gap-1.5 rounded border border-amber-300 bg-amber-50 p-2 text-xs text-amber-700 dark:border-amber-800 dark:bg-amber-950/30 dark:text-amber-300">
|
|
585
|
+
<IconAlertTriangle className="mt-0.5 size-3.5 shrink-0" />
|
|
586
|
+
<span>
|
|
587
|
+
{t("database.changedInBuilderSinceSync")}
|
|
588
|
+
</span>
|
|
223
589
|
</div>
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
590
|
+
) : null}
|
|
591
|
+
{effect === "unpublish" ? (
|
|
592
|
+
<div className="flex items-start gap-1.5 rounded border border-amber-300 bg-amber-50 p-2 text-xs text-amber-700 dark:border-amber-800 dark:bg-amber-950/30 dark:text-amber-300">
|
|
593
|
+
<IconAlertTriangle className="mt-0.5 size-3.5 shrink-0" />
|
|
594
|
+
<span>
|
|
595
|
+
{t("database.thisUnpublishesTheLiveEntry")}
|
|
596
|
+
</span>
|
|
597
|
+
</div>
|
|
598
|
+
) : null}
|
|
599
|
+
{row.execution?.lastError ? (
|
|
600
|
+
<div className="rounded border border-destructive/30 bg-destructive/10 p-2 text-xs text-destructive">
|
|
601
|
+
{row.execution.lastError}
|
|
602
|
+
</div>
|
|
603
|
+
) : null}
|
|
604
|
+
</div>
|
|
231
605
|
</div>
|
|
232
|
-
|
|
233
|
-
)
|
|
234
|
-
</div>
|
|
235
|
-
</section>
|
|
236
|
-
|
|
237
|
-
<section className="grid gap-2 rounded-md border border-border p-3">
|
|
238
|
-
<div className="text-sm font-medium">
|
|
239
|
-
{t("database.whereItWillGo")}
|
|
240
|
-
</div>
|
|
241
|
-
<div className="grid gap-2 text-xs">
|
|
242
|
-
<SourceMetadataRow
|
|
243
|
-
label={t("database.source")}
|
|
244
|
-
value={review.sourceName}
|
|
245
|
-
/>
|
|
246
|
-
<SourceMetadataRow
|
|
247
|
-
label={t("database.builderModel")}
|
|
248
|
-
value={review.sourceTable}
|
|
249
|
-
/>
|
|
250
|
-
<SourceMetadataRow
|
|
251
|
-
label={t("database.pushMode")}
|
|
252
|
-
value={sourcePushModeLabel(review.pushMode, t)}
|
|
253
|
-
/>
|
|
254
|
-
<SourceMetadataRow
|
|
255
|
-
label={t("database.liveWrites")}
|
|
256
|
-
value={
|
|
257
|
-
review.liveWritesEnabled
|
|
258
|
-
? t("database.enabled")
|
|
259
|
-
: t("database.disabled")
|
|
260
|
-
}
|
|
261
|
-
/>
|
|
262
|
-
<SourceMetadataRow
|
|
263
|
-
label={t("database.readMode")}
|
|
264
|
-
value={
|
|
265
|
-
source
|
|
266
|
-
? sourceBuilderReadModeSummary(source, t)
|
|
267
|
-
: t("database.unknown")
|
|
268
|
-
}
|
|
269
|
-
/>
|
|
606
|
+
);
|
|
607
|
+
})}
|
|
270
608
|
</div>
|
|
271
609
|
</section>
|
|
272
610
|
|
|
273
|
-
<
|
|
274
|
-
<
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
<div className="flex flex-wrap gap-1.5 text-xs">
|
|
278
|
-
<span className={sourceRiskClass(review.riskLevel)}>
|
|
279
|
-
{t("database.riskLabel", { level: review.riskLevel })}
|
|
280
|
-
</span>
|
|
281
|
-
{(review.riskReasons.length
|
|
282
|
-
? review.riskReasons
|
|
283
|
-
: [t("database.singleFieldDiff")]
|
|
284
|
-
).map((reason) => (
|
|
285
|
-
<span
|
|
286
|
-
key={reason}
|
|
287
|
-
className="rounded border border-border px-1.5 py-0.5 text-muted-foreground"
|
|
288
|
-
>
|
|
289
|
-
{reason}
|
|
290
|
-
</span>
|
|
291
|
-
))}
|
|
292
|
-
<span className="rounded border border-border px-1.5 py-0.5 text-muted-foreground">
|
|
293
|
-
{review.dryRunOnly
|
|
294
|
-
? t("database.checksOnly")
|
|
295
|
-
: t("database.canSendToBuilder")}
|
|
296
|
-
</span>
|
|
297
|
-
</div>
|
|
298
|
-
</section>
|
|
611
|
+
<div className="flex items-start gap-1.5 text-xs text-muted-foreground">
|
|
612
|
+
<IconCloudUpload className="mt-0.5 size-3.5 shrink-0" />
|
|
613
|
+
<span>{destinationLine}</span>
|
|
614
|
+
</div>
|
|
299
615
|
|
|
300
|
-
|
|
301
|
-
<
|
|
302
|
-
<div>
|
|
303
|
-
|
|
304
|
-
{t("database.result")}
|
|
305
|
-
</div>
|
|
306
|
-
<div className="mt-1 text-xs text-muted-foreground">
|
|
307
|
-
{review.result.message}
|
|
308
|
-
</div>
|
|
616
|
+
{batchResult && batchIssueResults.length > 0 ? (
|
|
617
|
+
<section className="grid gap-1.5 rounded-md border border-amber-300 bg-amber-50 p-3 text-xs text-amber-800 dark:border-amber-800 dark:bg-amber-950/30 dark:text-amber-200">
|
|
618
|
+
<div className="font-medium">
|
|
619
|
+
{t("database.needsAttentionBeforeFinish")}
|
|
309
620
|
</div>
|
|
310
|
-
|
|
311
|
-
{
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
621
|
+
{batchIssueResults.map((result) => (
|
|
622
|
+
<div key={result.changeSetId} className="break-words">
|
|
623
|
+
<span className="font-medium">
|
|
624
|
+
{rowTitleById.get(result.changeSetId) ??
|
|
625
|
+
result.changeSetId}
|
|
626
|
+
</span>
|
|
627
|
+
{" — "}
|
|
628
|
+
{result.message ?? "No details returned."}
|
|
629
|
+
</div>
|
|
630
|
+
))}
|
|
631
|
+
</section>
|
|
632
|
+
) : null}
|
|
315
633
|
</div>
|
|
316
634
|
) : (
|
|
317
635
|
<div className="rounded-md border border-border p-4 text-sm text-muted-foreground">
|
|
318
|
-
{t("database.
|
|
636
|
+
{t("database.noPendingLocalBuilderChanges")}
|
|
319
637
|
</div>
|
|
320
638
|
)}
|
|
321
639
|
</div>
|
|
322
640
|
|
|
323
641
|
<div className="flex shrink-0 items-center justify-between gap-3 border-t border-border p-3">
|
|
324
|
-
<div className="min-w-0 text-xs text-muted-foreground">
|
|
325
|
-
{
|
|
642
|
+
<div className="grid min-w-0 gap-1 text-xs text-muted-foreground">
|
|
643
|
+
{review ? (
|
|
644
|
+
<div
|
|
645
|
+
className={
|
|
646
|
+
"flex items-center gap-1.5 font-medium " +
|
|
647
|
+
resultToneClass(resultStatus.tone)
|
|
648
|
+
}
|
|
649
|
+
>
|
|
650
|
+
{checked ? (
|
|
651
|
+
resultStatus.tone === "ok" ? (
|
|
652
|
+
<IconCheck className="size-3.5 shrink-0" />
|
|
653
|
+
) : (
|
|
654
|
+
<IconAlertTriangle className="size-3.5 shrink-0" />
|
|
655
|
+
)
|
|
656
|
+
) : null}
|
|
657
|
+
<span>
|
|
658
|
+
{checked
|
|
659
|
+
? `${t(`database.${resultStatus.labelKey}`)} · ${intentSummary}`
|
|
660
|
+
: intentSummary}
|
|
661
|
+
</span>
|
|
662
|
+
</div>
|
|
663
|
+
) : null}
|
|
664
|
+
{footerHint ? <div>{footerHint}</div> : null}
|
|
326
665
|
</div>
|
|
327
666
|
<div className="flex shrink-0 items-center gap-2">
|
|
328
667
|
<Button type="button" variant="ghost" size="sm" onClick={onClose}>
|
|
329
|
-
|
|
668
|
+
Close
|
|
330
669
|
</Button>
|
|
331
670
|
<Button
|
|
332
671
|
type="button"
|
|
333
672
|
size="sm"
|
|
334
673
|
disabled={disabled}
|
|
335
|
-
onClick={onValidate}
|
|
674
|
+
onClick={() => onValidate(transitionMap)}
|
|
336
675
|
>
|
|
337
676
|
{pending ? (
|
|
338
677
|
<Spinner className="mr-1.5 size-3.5" />
|