@agent-native/core 0.117.1 → 0.117.2
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 +10 -0
- package/corpus/core/package.json +2 -1
- package/corpus/core/src/cli/context-xray-local.ts +1 -1
- package/corpus/core/src/client/extensions/ExtensionViewer.tsx +4 -4
- package/corpus/core/src/client/extensions/ExtensionsSidebarSection.tsx +11 -11
- package/corpus/core/src/client/extensions/agent-native-extension-runtime.ts +1 -1
- package/corpus/core/src/client/extensions/delete-extension.ts +2 -2
- package/corpus/core/src/client/org/OrgSwitcher.tsx +25 -1
- package/corpus/core/src/client/settings/SettingsPanel.tsx +102 -10
- package/corpus/core/src/client/sharing/ShareButton.tsx +7 -6
- package/corpus/core/src/db/client.ts +13 -10
- package/corpus/core/src/extensions/actions.ts +13 -5
- package/corpus/core/src/extensions/local.ts +1 -0
- package/corpus/core/src/extensions/routes.ts +10 -5
- package/corpus/core/src/extensions/schema.ts +5 -0
- package/corpus/core/src/extensions/slots/store.ts +14 -4
- package/corpus/core/src/extensions/store.ts +55 -19
- package/corpus/core/src/extensions/theme.ts +1 -1
- package/corpus/core/src/file-upload/registry.ts +9 -0
- package/corpus/core/src/index.browser.ts +5 -0
- package/corpus/core/src/index.ts +1 -0
- package/corpus/core/src/localization/default-messages.ts +23 -6
- package/corpus/core/src/server/action-discovery.ts +8 -0
- package/corpus/core/src/server/better-auth-instance.ts +7 -2
- package/corpus/core/src/server/email-template.ts +18 -0
- package/corpus/core/src/server/email-templates.ts +3 -0
- package/corpus/core/src/server/email.ts +40 -4
- package/corpus/core/src/sharing/actions/share-resource.ts +1 -0
- package/corpus/core/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/core/src/templates/default/app/global.css +1 -1
- package/corpus/core/src/templates/default/app/i18n/ar-SA.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/de-DE.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/en-US.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/es-ES.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/fr-FR.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/hi-IN.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/ja-JP.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/ko-KR.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/pt-BR.ts +6 -6
- package/corpus/core/src/templates/default/app/i18n/zh-CN.ts +7 -7
- package/corpus/core/src/templates/default/app/i18n/zh-TW.ts +7 -7
- package/corpus/core/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/core/src/user-profile/actions/get-user-profile.ts +16 -0
- package/corpus/core/src/user-profile/actions/update-user-profile.ts +24 -0
- package/corpus/core/src/user-profile/index.ts +5 -0
- package/corpus/core/src/user-profile/shared.ts +14 -0
- package/corpus/core/src/user-profile/store.ts +50 -0
- package/corpus/templates/analytics/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/assets/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/assets/app/global.css +1 -1
- package/corpus/templates/assets/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/brain/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/brain/app/global.css +2 -2
- package/corpus/templates/brain/app/lib/brain.ts +2 -2
- package/corpus/templates/brain/app/root.tsx +2 -2
- package/corpus/templates/brain/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/calendar/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +6 -2
- package/corpus/templates/calendar/app/global.css +1 -1
- package/corpus/templates/calendar/app/root.tsx +2 -2
- package/corpus/templates/calendar/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/chat/app/global.css +1 -1
- package/corpus/templates/chat/app/root.tsx +2 -2
- package/corpus/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/clips/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/clips/actions/export-to-brain.ts +1 -1
- package/corpus/templates/clips/actions/invite-member.ts +1 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +2 -2
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +20 -11
- package/corpus/templates/clips/app/global.css +1 -1
- package/corpus/templates/clips/app/root.tsx +7 -2
- package/corpus/templates/clips/app/routes/record.tsx +2 -88
- package/corpus/templates/clips/changelog/2026-07-22-builder-connected-recordings-start-resumable-upload-sessions.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-clip-thumbnails-now-come-from-the-recording-instead-of-the-p.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-clips-emails-now-render-the-agent-native-logo-in-gmail-and-o.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-dismissed-zoom-and-teams-meeting-note-prompts-now-stay-dismi.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-22-quieter-permissions-and-rewind-controls.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +86 -52
- package/corpus/templates/clips/desktop/src/lib/meeting-notification-dismissal.ts +31 -0
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +4 -167
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +10 -1
- package/corpus/templates/clips/desktop/src/styles.css +98 -36
- package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +67 -4
- package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +51 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +5 -1
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +0 -189
- package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +62 -0
- package/corpus/templates/clips/server/plugins/db.ts +6 -2
- package/corpus/templates/content/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +3 -3
- package/corpus/templates/content/app/global.css +1 -1
- package/corpus/templates/content/app/root.tsx +2 -2
- package/corpus/templates/content/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/crm/app/global.css +1 -1
- package/corpus/templates/design/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +19 -1
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +12 -1
- package/corpus/templates/design/app/components/design/EditPanel.tsx +177 -52
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +179 -59
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +74 -27
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +2 -0
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/design/app/global.css +1 -1
- package/corpus/templates/design/app/hooks/use-navigation-state.ts +6 -5
- package/corpus/templates/design/app/root.tsx +2 -2
- package/corpus/templates/design/changelog/2026-07-22-design-owners-can-keep-editing-their-designs-after-switching.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-inspector-tabs-keep-their-text-labels-at-narrow-widths.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-narrow-breakpoint-previews-keep-their-device-labels-readable.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-removed-the-draft-status-chip-from-the-design-editor.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-responsive-breakpoint-controls-stay-within-narrow-sidebars.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-responsive-peers-now-use-a-softer-selection-highlight-withou.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-rotate-from-context-menu.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-the-selection-outline-now-stays-attached-while-moving-screen.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-view-only-designs-now-support-figma-style-layer-inspection-w.md +6 -0
- package/corpus/templates/design/server/db/index.ts +4 -0
- package/corpus/templates/dispatch/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/dispatch/app/dispatch-extensions.tsx +2 -2
- package/corpus/templates/dispatch/app/global.css +1 -1
- package/corpus/templates/dispatch/app/root.tsx +2 -2
- package/corpus/templates/dispatch/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/forms/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/forms/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +3 -3
- package/corpus/templates/forms/app/global.css +1 -1
- package/corpus/templates/forms/app/hooks/use-forms.ts +55 -2
- package/corpus/templates/forms/app/i18n/en-US.ts +2 -0
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +3 -3
- package/corpus/templates/forms/app/pages/FormsListPage.tsx +23 -6
- package/corpus/templates/forms/app/root.tsx +2 -2
- package/corpus/templates/forms/changelog/2026-07-22-forms-now-archive-with-optimistic-feedback.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/macros/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +2 -2
- package/corpus/templates/macros/app/root.tsx +2 -2
- package/corpus/templates/macros/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/mail/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +3 -3
- package/corpus/templates/mail/app/components/layout/CommandPalette.tsx +2 -2
- package/corpus/templates/mail/app/global.css +1 -1
- package/corpus/templates/mail/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/plan/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/plan/app/global.css +1 -1
- package/corpus/templates/plan/app/root.tsx +2 -2
- package/corpus/templates/plan/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/slides/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +2 -2
- package/corpus/templates/slides/app/root.tsx +2 -2
- package/corpus/templates/slides/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-22-slides-no-longer-fail-intermittently-on-fresh-server-instances.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-22-uploaded-screenshots-can-now-be-analyzed-and-recreated-as-ed.md +6 -0
- package/corpus/templates/slides/server/lib/chat-attachments.ts +7 -3
- package/corpus/templates/slides/server/plugins/db.ts +44 -17
- package/corpus/templates/tasks/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/corpus/templates/tasks/app/global.css +1 -1
- package/dist/cli/context-xray-local.js +1 -1
- package/dist/cli/context-xray-local.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +2 -2
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +11 -11
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/extensions/agent-native-extension-runtime.js +1 -1
- package/dist/client/extensions/agent-native-extension-runtime.js.map +1 -1
- package/dist/client/extensions/delete-extension.d.ts +1 -1
- package/dist/client/extensions/delete-extension.d.ts.map +1 -1
- package/dist/client/extensions/delete-extension.js +1 -1
- package/dist/client/extensions/delete-extension.js.map +1 -1
- package/dist/client/org/OrgSwitcher.d.ts +3 -1
- package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
- package/dist/client/org/OrgSwitcher.js +12 -4
- package/dist/client/org/OrgSwitcher.js.map +1 -1
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +37 -4
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +3 -4
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +3 -2
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/db/client.d.ts +7 -7
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +13 -10
- package/dist/db/client.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +8 -5
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/local.d.ts.map +1 -1
- package/dist/extensions/local.js +1 -0
- package/dist/extensions/local.js.map +1 -1
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +9 -4
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/schema.d.ts +23 -2
- package/dist/extensions/schema.d.ts.map +1 -1
- package/dist/extensions/schema.js +5 -0
- package/dist/extensions/schema.js.map +1 -1
- package/dist/extensions/slots/store.d.ts +1 -1
- package/dist/extensions/slots/store.d.ts.map +1 -1
- package/dist/extensions/slots/store.js +4 -4
- package/dist/extensions/slots/store.js.map +1 -1
- package/dist/extensions/store.d.ts +1 -0
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +38 -21
- package/dist/extensions/store.js.map +1 -1
- package/dist/extensions/theme.js +1 -1
- package/dist/extensions/theme.js.map +1 -1
- package/dist/file-upload/registry.d.ts.map +1 -1
- package/dist/file-upload/registry.js +9 -0
- package/dist/file-upload/registry.js.map +1 -1
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -0
- package/dist/index.browser.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/localization/default-messages.d.ts +16 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +22 -6
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/action-discovery.d.ts.map +1 -1
- package/dist/server/action-discovery.js +8 -0
- package/dist/server/action-discovery.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/better-auth-instance.d.ts +7 -2
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/email-template.d.ts +3 -0
- package/dist/server/email-template.d.ts.map +1 -1
- package/dist/server/email-template.js +13 -0
- package/dist/server/email-template.js.map +1 -1
- package/dist/server/email-templates.d.ts.map +1 -1
- package/dist/server/email-templates.js +3 -0
- package/dist/server/email-templates.js.map +1 -1
- package/dist/server/email.d.ts.map +1 -1
- package/dist/server/email.js +27 -4
- package/dist/server/email.js.map +1 -1
- package/dist/sharing/actions/share-resource.js +1 -0
- package/dist/sharing/actions/share-resource.js.map +1 -1
- package/dist/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +2 -2
- package/dist/templates/chat/app/global.css +1 -1
- package/dist/templates/chat/app/root.tsx +2 -2
- package/dist/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/dist/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/dist/templates/default/app/global.css +1 -1
- package/dist/templates/default/app/i18n/ar-SA.ts +6 -6
- package/dist/templates/default/app/i18n/de-DE.ts +6 -6
- package/dist/templates/default/app/i18n/en-US.ts +6 -6
- package/dist/templates/default/app/i18n/es-ES.ts +6 -6
- package/dist/templates/default/app/i18n/fr-FR.ts +6 -6
- package/dist/templates/default/app/i18n/hi-IN.ts +6 -6
- package/dist/templates/default/app/i18n/ja-JP.ts +6 -6
- package/dist/templates/default/app/i18n/ko-KR.ts +6 -6
- package/dist/templates/default/app/i18n/pt-BR.ts +6 -6
- package/dist/templates/default/app/i18n/zh-CN.ts +7 -7
- package/dist/templates/default/app/i18n/zh-TW.ts +7 -7
- package/dist/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/dist/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/dist/user-profile/actions/get-user-profile.d.ts +4 -0
- package/dist/user-profile/actions/get-user-profile.d.ts.map +1 -0
- package/dist/user-profile/actions/get-user-profile.js +14 -0
- package/dist/user-profile/actions/get-user-profile.js.map +1 -0
- package/dist/user-profile/actions/update-user-profile.d.ts +6 -0
- package/dist/user-profile/actions/update-user-profile.d.ts.map +1 -0
- package/dist/user-profile/actions/update-user-profile.js +20 -0
- package/dist/user-profile/actions/update-user-profile.js.map +1 -0
- package/dist/user-profile/index.d.ts +2 -0
- package/dist/user-profile/index.d.ts.map +1 -0
- package/dist/user-profile/index.js +2 -0
- package/dist/user-profile/index.js.map +1 -0
- package/dist/user-profile/shared.d.ts +7 -0
- package/dist/user-profile/shared.d.ts.map +1 -0
- package/dist/user-profile/shared.js +6 -0
- package/dist/user-profile/shared.js.map +1 -0
- package/dist/user-profile/store.d.ts +4 -0
- package/dist/user-profile/store.d.ts.map +1 -0
- package/dist/user-profile/store.js +38 -0
- package/dist/user-profile/store.js.map +1 -0
- package/package.json +2 -1
- package/src/cli/context-xray-local.ts +1 -1
- package/src/client/extensions/ExtensionViewer.tsx +4 -4
- package/src/client/extensions/ExtensionsSidebarSection.tsx +11 -11
- package/src/client/extensions/agent-native-extension-runtime.ts +1 -1
- package/src/client/extensions/delete-extension.ts +2 -2
- package/src/client/org/OrgSwitcher.tsx +25 -1
- package/src/client/settings/SettingsPanel.tsx +102 -10
- package/src/client/sharing/ShareButton.tsx +7 -6
- package/src/db/client.ts +13 -10
- package/src/extensions/actions.ts +13 -5
- package/src/extensions/local.ts +1 -0
- package/src/extensions/routes.ts +10 -5
- package/src/extensions/schema.ts +5 -0
- package/src/extensions/slots/store.ts +14 -4
- package/src/extensions/store.ts +55 -19
- package/src/extensions/theme.ts +1 -1
- package/src/file-upload/registry.ts +9 -0
- package/src/index.browser.ts +5 -0
- package/src/index.ts +1 -0
- package/src/localization/default-messages.ts +23 -6
- package/src/server/action-discovery.ts +8 -0
- package/src/server/better-auth-instance.ts +7 -2
- package/src/server/email-template.ts +18 -0
- package/src/server/email-templates.ts +3 -0
- package/src/server/email.ts +40 -4
- package/src/sharing/actions/share-resource.ts +1 -0
- package/src/templates/chat/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/src/templates/chat/app/components/layout/Sidebar.tsx +2 -2
- package/src/templates/chat/app/global.css +1 -1
- package/src/templates/chat/app/root.tsx +2 -2
- package/src/templates/chat/changelog/2026-07-22-manage-agent-navigation-now-uses-the-connected-nodes-icon.md +6 -0
- package/src/templates/default/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/src/templates/default/app/global.css +1 -1
- package/src/templates/default/app/i18n/ar-SA.ts +6 -6
- package/src/templates/default/app/i18n/de-DE.ts +6 -6
- package/src/templates/default/app/i18n/en-US.ts +6 -6
- package/src/templates/default/app/i18n/es-ES.ts +6 -6
- package/src/templates/default/app/i18n/fr-FR.ts +6 -6
- package/src/templates/default/app/i18n/hi-IN.ts +6 -6
- package/src/templates/default/app/i18n/ja-JP.ts +6 -6
- package/src/templates/default/app/i18n/ko-KR.ts +6 -6
- package/src/templates/default/app/i18n/pt-BR.ts +6 -6
- package/src/templates/default/app/i18n/zh-CN.ts +7 -7
- package/src/templates/default/app/i18n/zh-TW.ts +7 -7
- package/src/templates/headless/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/src/templates/workspace-core/.agents/skills/agent-native-toolkit/SKILL.md +6 -0
- package/src/user-profile/actions/get-user-profile.ts +16 -0
- package/src/user-profile/actions/update-user-profile.ts +24 -0
- package/src/user-profile/index.ts +5 -0
- package/src/user-profile/shared.ts +14 -0
- package/src/user-profile/store.ts +50 -0
|
@@ -406,6 +406,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
406
406
|
pendingReviewScreenIds = EMPTY_SCREEN_IDS,
|
|
407
407
|
onReviewPendingScreen,
|
|
408
408
|
interactMode = false,
|
|
409
|
+
readOnly = false,
|
|
409
410
|
activeScreenHasHoveredChild = false,
|
|
410
411
|
hoveredChildScreenId,
|
|
411
412
|
directlyHoveredScreenId,
|
|
@@ -487,6 +488,13 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
487
488
|
const [surfaceSize, setSurfaceSize] = useState({ width: 0, height: 0 });
|
|
488
489
|
const [frameGeometry, setFrameGeometry] = useState<FrameGeometryById>({});
|
|
489
490
|
const frameGeometryRef = useRef(frameGeometry);
|
|
491
|
+
const liveFrameDragPositionsRef = useRef(
|
|
492
|
+
new Map<string, { left: number; top: number }>(),
|
|
493
|
+
);
|
|
494
|
+
const liveFrameDragSelectionPositionRef = useRef<{
|
|
495
|
+
left: number;
|
|
496
|
+
top: number;
|
|
497
|
+
} | null>(null);
|
|
490
498
|
const onGeometryChangeRef = useRef(onGeometryChange);
|
|
491
499
|
const onGeometryCommitRef = useRef(onGeometryCommit);
|
|
492
500
|
const screensRef = useRef(screens);
|
|
@@ -1162,6 +1170,29 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
1162
1170
|
frameGeometryRef.current = frameGeometry;
|
|
1163
1171
|
}, [frameGeometry]);
|
|
1164
1172
|
|
|
1173
|
+
// Frame drags update the shell and selection box imperatively between React
|
|
1174
|
+
// commits. Reapply the live box position after any feedback-driven commit
|
|
1175
|
+
// so alignment guides or transform badges cannot paint stale geometry over
|
|
1176
|
+
// the moving outline.
|
|
1177
|
+
useLayoutEffect(() => {
|
|
1178
|
+
for (const [id, position] of liveFrameDragPositionsRef.current) {
|
|
1179
|
+
const frame = surfaceRef.current?.querySelector<HTMLElement>(
|
|
1180
|
+
`[data-frame-id="${CSS.escape(id)}"]`,
|
|
1181
|
+
);
|
|
1182
|
+
if (!frame) continue;
|
|
1183
|
+
frame.style.left = `${position.left}px`;
|
|
1184
|
+
frame.style.top = `${position.top}px`;
|
|
1185
|
+
}
|
|
1186
|
+
const position = liveFrameDragSelectionPositionRef.current;
|
|
1187
|
+
if (!position) return;
|
|
1188
|
+
const selectionBox = surfaceRef.current?.querySelector<HTMLElement>(
|
|
1189
|
+
"[data-frame-selection-box]",
|
|
1190
|
+
);
|
|
1191
|
+
if (!selectionBox) return;
|
|
1192
|
+
selectionBox.style.left = `${position.left}px`;
|
|
1193
|
+
selectionBox.style.top = `${position.top}px`;
|
|
1194
|
+
});
|
|
1195
|
+
|
|
1165
1196
|
const onSelectionChangeRef = useRef(onSelectionChange);
|
|
1166
1197
|
useEffect(() => {
|
|
1167
1198
|
onSelectionChangeRef.current = onSelectionChange;
|
|
@@ -2524,6 +2555,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
2524
2555
|
]);
|
|
2525
2556
|
|
|
2526
2557
|
const deleteSelectedItems = useCallback(() => {
|
|
2558
|
+
if (readOnly) return false;
|
|
2527
2559
|
const frameIds = selectedIdsRef.current.filter(
|
|
2528
2560
|
(id) => frameGeometryRef.current[id],
|
|
2529
2561
|
);
|
|
@@ -2563,6 +2595,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
2563
2595
|
return true;
|
|
2564
2596
|
}, [
|
|
2565
2597
|
onDeleteSelection,
|
|
2598
|
+
readOnly,
|
|
2566
2599
|
updateDraftPrimitives,
|
|
2567
2600
|
updateFrameGeometry,
|
|
2568
2601
|
updateSelectedDraftIds,
|
|
@@ -2939,6 +2972,8 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
2939
2972
|
feedbackTimerRef.current = null;
|
|
2940
2973
|
}
|
|
2941
2974
|
dragState.current = null;
|
|
2975
|
+
liveFrameDragPositionsRef.current.clear();
|
|
2976
|
+
liveFrameDragSelectionPositionRef.current = null;
|
|
2942
2977
|
setIsDragging(false);
|
|
2943
2978
|
setIsPanning(false);
|
|
2944
2979
|
setMarquee(null);
|
|
@@ -4303,6 +4338,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
4303
4338
|
|
|
4304
4339
|
const beginDraftDrag = useCallback(
|
|
4305
4340
|
(id: string, e: React.MouseEvent) => {
|
|
4341
|
+
if (readOnly) return;
|
|
4306
4342
|
if (e.button !== 0 || e.shiftKey) return;
|
|
4307
4343
|
e.preventDefault();
|
|
4308
4344
|
e.stopPropagation();
|
|
@@ -4622,6 +4658,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
4622
4658
|
|
|
4623
4659
|
const beginDraftResize = useCallback(
|
|
4624
4660
|
(id: string, handle: ResizeHandle, e: React.MouseEvent) => {
|
|
4661
|
+
if (readOnly) return;
|
|
4625
4662
|
if (e.button !== 0) return;
|
|
4626
4663
|
e.preventDefault();
|
|
4627
4664
|
e.stopPropagation();
|
|
@@ -4863,6 +4900,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
4863
4900
|
|
|
4864
4901
|
const beginFrameDrag = useCallback(
|
|
4865
4902
|
(id: string, e: React.MouseEvent) => {
|
|
4903
|
+
if (readOnly) return;
|
|
4866
4904
|
if (e.button !== 0 || e.shiftKey || lockedScreenIdSet.has(id)) return;
|
|
4867
4905
|
e.preventDefault();
|
|
4868
4906
|
e.stopPropagation();
|
|
@@ -4931,15 +4969,23 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
4931
4969
|
const frameLabelHeight =
|
|
4932
4970
|
FRAME_LABEL_HEIGHT * chromeScaleFromZoom(zoomRef.current);
|
|
4933
4971
|
const draggedFrameEls = new Map<string, HTMLElement>();
|
|
4972
|
+
const draggedFrameOriginPositions = new Map<
|
|
4973
|
+
string,
|
|
4974
|
+
{ left: number; top: number }
|
|
4975
|
+
>();
|
|
4934
4976
|
targetIds.forEach((targetId) => {
|
|
4935
4977
|
const el = surfaceRef.current?.querySelector<HTMLElement>(
|
|
4936
4978
|
`[data-frame-id="${CSS.escape(targetId)}"]`,
|
|
4937
4979
|
);
|
|
4938
|
-
if (el)
|
|
4980
|
+
if (!el) return;
|
|
4981
|
+
draggedFrameEls.set(targetId, el);
|
|
4939
4982
|
});
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4983
|
+
// Selecting an unselected screen mounts the SelectionBox after this
|
|
4984
|
+
// callback returns. Resolve it on the first live move instead of
|
|
4985
|
+
// caching null at drag start, then keep the lookup out of later ticks.
|
|
4986
|
+
let selectionBoxEl: HTMLElement | null = null;
|
|
4987
|
+
let selectionBoxOriginPosition: { left: number; top: number } | null =
|
|
4988
|
+
null;
|
|
4943
4989
|
|
|
4944
4990
|
const handleMouseMove = (ev: MouseEvent) => {
|
|
4945
4991
|
const state = dragState.current;
|
|
@@ -5023,42 +5069,60 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
5023
5069
|
const geometry = settledGeometryById[targetId];
|
|
5024
5070
|
const el = draggedFrameEls.get(targetId);
|
|
5025
5071
|
if (!geometry || !el) return;
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5072
|
+
let originPosition = draggedFrameOriginPositions.get(targetId);
|
|
5073
|
+
if (!originPosition) {
|
|
5074
|
+
const fallback = frameStyleLeftTop(
|
|
5075
|
+
state.originFrames[targetId],
|
|
5076
|
+
frameLabelHeight,
|
|
5077
|
+
);
|
|
5078
|
+
const renderedLeft = Number.parseFloat(el.style.left);
|
|
5079
|
+
const renderedTop = Number.parseFloat(el.style.top);
|
|
5080
|
+
originPosition = {
|
|
5081
|
+
left: Number.isFinite(renderedLeft)
|
|
5082
|
+
? renderedLeft
|
|
5083
|
+
: fallback.left,
|
|
5084
|
+
top: Number.isFinite(renderedTop) ? renderedTop : fallback.top,
|
|
5085
|
+
};
|
|
5086
|
+
draggedFrameOriginPositions.set(targetId, originPosition);
|
|
5087
|
+
}
|
|
5088
|
+
if (!originPosition) return;
|
|
5089
|
+
const moveX = dx + snap.dx;
|
|
5090
|
+
const moveY = dy + snap.dy;
|
|
5091
|
+
const nextPosition = {
|
|
5092
|
+
left: originPosition.left + moveX,
|
|
5093
|
+
top: originPosition.top + moveY,
|
|
5094
|
+
};
|
|
5095
|
+
liveFrameDragPositionsRef.current.set(targetId, nextPosition);
|
|
5096
|
+
el.style.left = `${nextPosition.left}px`;
|
|
5097
|
+
el.style.top = `${nextPosition.top}px`;
|
|
5029
5098
|
});
|
|
5030
5099
|
// Keep the selection outline + resize/rotate handles glued to the
|
|
5031
5100
|
// dragged frame — SelectionBox's own `geometry` prop only updates
|
|
5032
5101
|
// on the next real React render, which this tick intentionally
|
|
5033
5102
|
// skips (see above), so without this it would visually detach and
|
|
5034
5103
|
// trail behind during the drag.
|
|
5104
|
+
if (!selectionBoxEl) {
|
|
5105
|
+
selectionBoxEl =
|
|
5106
|
+
surfaceRef.current?.querySelector<HTMLElement>(
|
|
5107
|
+
"[data-frame-selection-box]",
|
|
5108
|
+
) ?? null;
|
|
5109
|
+
}
|
|
5035
5110
|
if (selectionBoxEl) {
|
|
5036
|
-
|
|
5037
|
-
(
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
x: groupBounds.left,
|
|
5052
|
-
y: groupBounds.top,
|
|
5053
|
-
width: groupBounds.width,
|
|
5054
|
-
height: groupBounds.height,
|
|
5055
|
-
}
|
|
5056
|
-
: null;
|
|
5057
|
-
})();
|
|
5058
|
-
if (bounds) {
|
|
5059
|
-
const { left, top } = frameStyleLeftTop(bounds);
|
|
5060
|
-
selectionBoxEl.style.left = `${left}px`;
|
|
5061
|
-
selectionBoxEl.style.top = `${top}px`;
|
|
5111
|
+
if (!selectionBoxOriginPosition) {
|
|
5112
|
+
const left = Number.parseFloat(selectionBoxEl.style.left);
|
|
5113
|
+
const top = Number.parseFloat(selectionBoxEl.style.top);
|
|
5114
|
+
if (Number.isFinite(left) && Number.isFinite(top)) {
|
|
5115
|
+
selectionBoxOriginPosition = { left, top };
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
5118
|
+
if (selectionBoxOriginPosition) {
|
|
5119
|
+
const nextPosition = {
|
|
5120
|
+
left: selectionBoxOriginPosition.left + dx + snap.dx,
|
|
5121
|
+
top: selectionBoxOriginPosition.top + dy + snap.dy,
|
|
5122
|
+
};
|
|
5123
|
+
liveFrameDragSelectionPositionRef.current = nextPosition;
|
|
5124
|
+
selectionBoxEl.style.left = `${nextPosition.left}px`;
|
|
5125
|
+
selectionBoxEl.style.top = `${nextPosition.top}px`;
|
|
5062
5126
|
}
|
|
5063
5127
|
}
|
|
5064
5128
|
}
|
|
@@ -5196,6 +5260,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
5196
5260
|
installDragListeners,
|
|
5197
5261
|
lockedScreenIdSet,
|
|
5198
5262
|
onPick,
|
|
5263
|
+
readOnly,
|
|
5199
5264
|
resolvePrimitiveScreenId,
|
|
5200
5265
|
showTransformFeedback,
|
|
5201
5266
|
updateFrameGeometry,
|
|
@@ -5208,6 +5273,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
5208
5273
|
|
|
5209
5274
|
const beginResize = useCallback(
|
|
5210
5275
|
(id: string, handle: ResizeHandle, e: React.MouseEvent) => {
|
|
5276
|
+
if (readOnly) return;
|
|
5211
5277
|
if (e.button !== 0 || lockedScreenIdSet.has(id)) return;
|
|
5212
5278
|
e.preventDefault();
|
|
5213
5279
|
e.stopPropagation();
|
|
@@ -5597,6 +5663,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
5597
5663
|
|
|
5598
5664
|
const beginRotate = useCallback(
|
|
5599
5665
|
(id: string, e: React.MouseEvent) => {
|
|
5666
|
+
if (readOnly) return;
|
|
5600
5667
|
if (e.button !== 0 || lockedScreenIdSet.has(id)) return;
|
|
5601
5668
|
e.preventDefault();
|
|
5602
5669
|
e.stopPropagation();
|
|
@@ -5739,6 +5806,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
5739
5806
|
// beginRotate above — single-frame rotate is unaffected.
|
|
5740
5807
|
const beginGroupRotate = useCallback(
|
|
5741
5808
|
(e: React.MouseEvent) => {
|
|
5809
|
+
if (readOnly) return;
|
|
5742
5810
|
if (e.button !== 0) return;
|
|
5743
5811
|
e.preventDefault();
|
|
5744
5812
|
e.stopPropagation();
|
|
@@ -5981,6 +6049,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
5981
6049
|
|
|
5982
6050
|
const beginDuplicateGesture = useCallback(
|
|
5983
6051
|
(screen: ScreenFile, display: string, e: React.MouseEvent<HTMLElement>) => {
|
|
6052
|
+
if (readOnly) return;
|
|
5984
6053
|
if (e.button !== 0 || !e.altKey || lockedScreenIdSet.has(screen.id)) {
|
|
5985
6054
|
return;
|
|
5986
6055
|
}
|
|
@@ -6808,6 +6877,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
6808
6877
|
useEffect(() => {
|
|
6809
6878
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
6810
6879
|
if (activePenPathRef.current) return;
|
|
6880
|
+
if (readOnly) return;
|
|
6811
6881
|
if (!isArrowNudgeKey(event.key) || isEditableHotkeyTarget(event.target)) {
|
|
6812
6882
|
return;
|
|
6813
6883
|
}
|
|
@@ -6901,6 +6971,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
6901
6971
|
};
|
|
6902
6972
|
}, [
|
|
6903
6973
|
getCurrentCanvasEntries,
|
|
6974
|
+
readOnly,
|
|
6904
6975
|
scheduleFeedbackClear,
|
|
6905
6976
|
updateDraftPrimitives,
|
|
6906
6977
|
updateFrameGeometry,
|
|
@@ -6909,6 +6980,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
6909
6980
|
useEffect(() => {
|
|
6910
6981
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
6911
6982
|
if (activePenPathRef.current) return;
|
|
6983
|
+
if (readOnly) return;
|
|
6912
6984
|
if (
|
|
6913
6985
|
(event.key !== "Delete" && event.key !== "Backspace") ||
|
|
6914
6986
|
event.metaKey ||
|
|
@@ -6927,7 +6999,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
6927
6999
|
return () => {
|
|
6928
7000
|
window.removeEventListener("keydown", handleKeyDown, true);
|
|
6929
7001
|
};
|
|
6930
|
-
}, [deleteSelectedItems]);
|
|
7002
|
+
}, [deleteSelectedItems, readOnly]);
|
|
6931
7003
|
|
|
6932
7004
|
useEffect(() => {
|
|
6933
7005
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
@@ -7018,6 +7090,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7018
7090
|
useEffect(() => {
|
|
7019
7091
|
if (!onDuplicate) return;
|
|
7020
7092
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
7093
|
+
if (readOnly) return;
|
|
7021
7094
|
if (activePenPathRef.current) return;
|
|
7022
7095
|
if (
|
|
7023
7096
|
!(event.metaKey || event.ctrlKey) ||
|
|
@@ -7077,7 +7150,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7077
7150
|
return () => {
|
|
7078
7151
|
window.removeEventListener("keydown", handleKeyDown, true);
|
|
7079
7152
|
};
|
|
7080
|
-
}, [onDuplicate, screens]);
|
|
7153
|
+
}, [onDuplicate, readOnly, screens]);
|
|
7081
7154
|
|
|
7082
7155
|
// Releasing Alt should clear the alt-hover measurement immediately even if
|
|
7083
7156
|
// the mouse never moves again (e.g. the user just lifts the Alt key while
|
|
@@ -7101,8 +7174,9 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7101
7174
|
useEffect(() => {
|
|
7102
7175
|
effectiveToolRef.current = effectiveTool;
|
|
7103
7176
|
}, [effectiveTool]);
|
|
7104
|
-
const penActive = effectiveTool === "pen";
|
|
7105
|
-
const creationToolActive =
|
|
7177
|
+
const penActive = !readOnly && effectiveTool === "pen";
|
|
7178
|
+
const creationToolActive =
|
|
7179
|
+
!readOnly && Boolean(getDraftCreationTool(effectiveTool));
|
|
7106
7180
|
// PERF9-WHEEL: an in-flight wheel pan/zoom also mutes iframe pointer
|
|
7107
7181
|
// events, but imperatively (see markWheelGestureActive) rather than via
|
|
7108
7182
|
// this flag — flipping React state here at gesture start re-rendered every
|
|
@@ -7559,7 +7633,10 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7559
7633
|
editorChromeScaleY={canvasZoom / 100}
|
|
7560
7634
|
editMode={boardEditMode && !interactMode}
|
|
7561
7635
|
interactMode={interactMode}
|
|
7562
|
-
scaleMode={
|
|
7636
|
+
scaleMode={
|
|
7637
|
+
!readOnly && boardIsActive && effectiveTool === "scale"
|
|
7638
|
+
}
|
|
7639
|
+
readOnly={readOnly}
|
|
7563
7640
|
clearSelectionRequest={boardClearSelectionRequest}
|
|
7564
7641
|
selectedSelector={
|
|
7565
7642
|
boardIsActive ? (boardSelectedSelector ?? null) : null
|
|
@@ -7641,7 +7718,8 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7641
7718
|
screen.id === hoveredChildScreenId
|
|
7642
7719
|
}
|
|
7643
7720
|
groupSelected={hasGroupSelection}
|
|
7644
|
-
handlesEnabled={!hasGroupSelection}
|
|
7721
|
+
handlesEnabled={!hasGroupSelection && !readOnly}
|
|
7722
|
+
readOnly={readOnly}
|
|
7645
7723
|
penActive={penActive}
|
|
7646
7724
|
creationToolActive={creationToolActive}
|
|
7647
7725
|
canvasGestureActive={canvasGestureActive}
|
|
@@ -7674,6 +7752,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7674
7752
|
isSelected={selectedDraftIdSet.has(draft.id)}
|
|
7675
7753
|
groupSelected={Boolean(selectedDraftGroupBounds)}
|
|
7676
7754
|
penActive={penActive}
|
|
7755
|
+
readOnly={readOnly}
|
|
7677
7756
|
chromeScale={chromeScale}
|
|
7678
7757
|
chromeSettling={chromeSettling}
|
|
7679
7758
|
onClick={handleDraftClick}
|
|
@@ -7689,6 +7768,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7689
7768
|
preview
|
|
7690
7769
|
groupSelected={false}
|
|
7691
7770
|
penActive={penActive}
|
|
7771
|
+
readOnly={readOnly}
|
|
7692
7772
|
chromeScale={chromeScale}
|
|
7693
7773
|
chromeSettling={chromeSettling}
|
|
7694
7774
|
onClick={() => {}}
|
|
@@ -7704,6 +7784,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7704
7784
|
geometry={entry.geometry}
|
|
7705
7785
|
chromeScale={chromeScale}
|
|
7706
7786
|
chromeSettling={chromeSettling}
|
|
7787
|
+
showHandles={!readOnly}
|
|
7707
7788
|
/>
|
|
7708
7789
|
))
|
|
7709
7790
|
: null}
|
|
@@ -7715,6 +7796,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7715
7796
|
geometry={entry.geometry}
|
|
7716
7797
|
chromeScale={chromeScale}
|
|
7717
7798
|
chromeSettling={chromeSettling}
|
|
7799
|
+
showHandles={!readOnly}
|
|
7718
7800
|
/>
|
|
7719
7801
|
))
|
|
7720
7802
|
: null}
|
|
@@ -7747,6 +7829,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7747
7829
|
geometry={singleSelectedFrame.geometry}
|
|
7748
7830
|
chromeScale={chromeScale}
|
|
7749
7831
|
chromeSettling={chromeSettling}
|
|
7832
|
+
handlesEnabled={!readOnly}
|
|
7750
7833
|
showRotate
|
|
7751
7834
|
onStartResize={(handle, event) =>
|
|
7752
7835
|
beginResize(singleSelectedFrame.id, handle, event)
|
|
@@ -7762,6 +7845,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7762
7845
|
geometry={singleSelectedDraft.geometry}
|
|
7763
7846
|
chromeScale={chromeScale}
|
|
7764
7847
|
chromeSettling={chromeSettling}
|
|
7848
|
+
handlesEnabled={!readOnly}
|
|
7765
7849
|
showRotate={false}
|
|
7766
7850
|
onStartResize={(handle, event) =>
|
|
7767
7851
|
beginDraftResize(singleSelectedDraft.id, handle, event)
|
|
@@ -7775,6 +7859,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7775
7859
|
bounds={selectedGroupBounds}
|
|
7776
7860
|
chromeScale={chromeScale}
|
|
7777
7861
|
chromeSettling={chromeSettling}
|
|
7862
|
+
handlesEnabled={!readOnly}
|
|
7778
7863
|
onStartResize={beginGroupResize}
|
|
7779
7864
|
onStartRotate={beginGroupRotate}
|
|
7780
7865
|
/>
|
|
@@ -7785,6 +7870,7 @@ export const MultiScreenCanvas = memo(function MultiScreenCanvas({
|
|
|
7785
7870
|
bounds={selectedDraftGroupBounds}
|
|
7786
7871
|
chromeScale={chromeScale}
|
|
7787
7872
|
chromeSettling={chromeSettling}
|
|
7873
|
+
handlesEnabled={!readOnly}
|
|
7788
7874
|
onStartResize={beginDraftGroupResize}
|
|
7789
7875
|
/>
|
|
7790
7876
|
) : null}
|
|
@@ -8126,6 +8212,7 @@ function DraftPrimitiveLayer({
|
|
|
8126
8212
|
isSelected,
|
|
8127
8213
|
groupSelected,
|
|
8128
8214
|
penActive,
|
|
8215
|
+
readOnly,
|
|
8129
8216
|
chromeScale,
|
|
8130
8217
|
chromeSettling,
|
|
8131
8218
|
preview = false,
|
|
@@ -8137,6 +8224,7 @@ function DraftPrimitiveLayer({
|
|
|
8137
8224
|
isSelected: boolean;
|
|
8138
8225
|
groupSelected: boolean;
|
|
8139
8226
|
penActive: boolean;
|
|
8227
|
+
readOnly: boolean;
|
|
8140
8228
|
chromeScale: number;
|
|
8141
8229
|
chromeSettling: boolean;
|
|
8142
8230
|
preview?: boolean;
|
|
@@ -8180,6 +8268,10 @@ function DraftPrimitiveLayer({
|
|
|
8180
8268
|
}}
|
|
8181
8269
|
onMouseDown={(event) => {
|
|
8182
8270
|
if (penActive) return;
|
|
8271
|
+
if (readOnly) {
|
|
8272
|
+
event.stopPropagation();
|
|
8273
|
+
return;
|
|
8274
|
+
}
|
|
8183
8275
|
if (!preview) onStartDrag(draft.id, event);
|
|
8184
8276
|
}}
|
|
8185
8277
|
>
|
|
@@ -8206,7 +8298,7 @@ function DraftPrimitiveLayer({
|
|
|
8206
8298
|
/>
|
|
8207
8299
|
<ResizeHandles
|
|
8208
8300
|
active={preview}
|
|
8209
|
-
enabled={!penActive && preview}
|
|
8301
|
+
enabled={!readOnly && !penActive && preview}
|
|
8210
8302
|
showRotate={false}
|
|
8211
8303
|
chromeScale={chromeScale}
|
|
8212
8304
|
chromeSettling={chromeSettling}
|
|
@@ -8922,6 +9014,7 @@ interface ScreenProps {
|
|
|
8922
9014
|
pendingReview: boolean;
|
|
8923
9015
|
onReviewPendingScreen?: (screenId: string) => void;
|
|
8924
9016
|
interactMode: boolean;
|
|
9017
|
+
readOnly: boolean;
|
|
8925
9018
|
isDirectlyHovered: boolean;
|
|
8926
9019
|
/** True while a native OS file drag is hovering this frame (Figma parity §1). */
|
|
8927
9020
|
isFileDragOver: boolean;
|
|
@@ -8992,6 +9085,7 @@ const Screen = memo(function Screen({
|
|
|
8992
9085
|
pendingReview,
|
|
8993
9086
|
onReviewPendingScreen,
|
|
8994
9087
|
interactMode,
|
|
9088
|
+
readOnly,
|
|
8995
9089
|
isDirectlyHovered,
|
|
8996
9090
|
isFileDragOver,
|
|
8997
9091
|
hasHoveredChild,
|
|
@@ -9150,6 +9244,10 @@ const Screen = memo(function Screen({
|
|
|
9150
9244
|
onMouseDown={(e) => {
|
|
9151
9245
|
if (e.button !== 0) return;
|
|
9152
9246
|
if (penActive || creationToolActive) return;
|
|
9247
|
+
if (readOnly) {
|
|
9248
|
+
e.stopPropagation();
|
|
9249
|
+
return;
|
|
9250
|
+
}
|
|
9153
9251
|
if (e.altKey) {
|
|
9154
9252
|
// Matches the data-screen-card mousedown handler below: without
|
|
9155
9253
|
// this, a trailing click after the alt-drag/duplicate gesture
|
|
@@ -9307,6 +9405,10 @@ const Screen = memo(function Screen({
|
|
|
9307
9405
|
return;
|
|
9308
9406
|
}
|
|
9309
9407
|
if (penActive) return;
|
|
9408
|
+
if (readOnly) {
|
|
9409
|
+
e.stopPropagation();
|
|
9410
|
+
return;
|
|
9411
|
+
}
|
|
9310
9412
|
if (e.altKey && e.button === 0) {
|
|
9311
9413
|
suppressNextClick.current = true;
|
|
9312
9414
|
onStartDuplicateGesture(screen, display, e);
|
|
@@ -9555,6 +9657,7 @@ function areScreenPropsEqual(prev: ScreenProps, next: ScreenProps) {
|
|
|
9555
9657
|
prev.isFileDragOver === next.isFileDragOver &&
|
|
9556
9658
|
prev.hasHoveredChild === next.hasHoveredChild &&
|
|
9557
9659
|
prev.groupSelected === next.groupSelected &&
|
|
9660
|
+
prev.readOnly === next.readOnly &&
|
|
9558
9661
|
prev.handlesEnabled === next.handlesEnabled &&
|
|
9559
9662
|
prev.penActive === next.penActive &&
|
|
9560
9663
|
prev.creationToolActive === next.creationToolActive &&
|
|
@@ -9583,6 +9686,7 @@ function areScreenPropsEqual(prev: ScreenProps, next: ScreenProps) {
|
|
|
9583
9686
|
|
|
9584
9687
|
/** Gap between adjacent breakpoint frames in canvas pixels. */
|
|
9585
9688
|
const BREAKPOINT_FRAME_GAP = 24;
|
|
9689
|
+
const BREAKPOINT_LABEL_WITH_WIDTH_MIN_FRAME_WIDTH = 128;
|
|
9586
9690
|
|
|
9587
9691
|
/**
|
|
9588
9692
|
* Pure geometry helper for one breakpoint sub-frame (BP-DEEP item 3a): the
|
|
@@ -9733,6 +9837,8 @@ function BreakpointPreviewRow({
|
|
|
9733
9837
|
});
|
|
9734
9838
|
const currentOffsetX = offsetX;
|
|
9735
9839
|
offsetX += frameWidth + BREAKPOINT_FRAME_GAP;
|
|
9840
|
+
const showBreakpointWidth =
|
|
9841
|
+
frameWidth >= BREAKPOINT_LABEL_WITH_WIDTH_MIN_FRAME_WIDTH;
|
|
9736
9842
|
// BP-DEEP item 5 — clicking a frame in the group always SELECTS it
|
|
9737
9843
|
// (never toggles it off): the Framer click-to-target model returns to
|
|
9738
9844
|
// Base by clicking the base frame / empty canvas / Escape, not by
|
|
@@ -9839,9 +9945,14 @@ function BreakpointPreviewRow({
|
|
|
9839
9945
|
>
|
|
9840
9946
|
{breakpointLabel(widthPx)}
|
|
9841
9947
|
</span>
|
|
9842
|
-
|
|
9843
|
-
|
|
9844
|
-
|
|
9948
|
+
{showBreakpointWidth ? (
|
|
9949
|
+
<span
|
|
9950
|
+
data-breakpoint-width
|
|
9951
|
+
className="shrink-0 text-[10px] tabular-nums text-muted-foreground/50"
|
|
9952
|
+
>
|
|
9953
|
+
{widthPx}px
|
|
9954
|
+
</span>
|
|
9955
|
+
) : null}
|
|
9845
9956
|
</div>
|
|
9846
9957
|
{/* Item 8b — "…" menu (Change width / Remove), reusing the
|
|
9847
9958
|
exact affordance BreakpointDeviceControl already offers per
|
|
@@ -10152,6 +10263,7 @@ function GroupSelectionBox({
|
|
|
10152
10263
|
chromeSettling,
|
|
10153
10264
|
onStartResize,
|
|
10154
10265
|
onStartRotate,
|
|
10266
|
+
handlesEnabled = true,
|
|
10155
10267
|
}: {
|
|
10156
10268
|
bounds: NonNullable<ReturnType<typeof getFrameGroupBounds>>;
|
|
10157
10269
|
chromeScale: number;
|
|
@@ -10161,6 +10273,7 @@ function GroupSelectionBox({
|
|
|
10161
10273
|
* rotate handle shown) — used by callers whose selection kind doesn't
|
|
10162
10274
|
* support group rotate yet (e.g. draft primitives). */
|
|
10163
10275
|
onStartRotate?: (e: React.MouseEvent) => void;
|
|
10276
|
+
handlesEnabled?: boolean;
|
|
10164
10277
|
}) {
|
|
10165
10278
|
return (
|
|
10166
10279
|
<SelectionBox
|
|
@@ -10173,6 +10286,7 @@ function GroupSelectionBox({
|
|
|
10173
10286
|
chromeScale={chromeScale}
|
|
10174
10287
|
chromeSettling={chromeSettling}
|
|
10175
10288
|
showRotate={!!onStartRotate}
|
|
10289
|
+
handlesEnabled={handlesEnabled}
|
|
10176
10290
|
filled
|
|
10177
10291
|
onStartResize={onStartResize}
|
|
10178
10292
|
onStartRotate={onStartRotate ?? (() => {})}
|
|
@@ -10184,10 +10298,12 @@ function PassiveSelectionBox({
|
|
|
10184
10298
|
geometry,
|
|
10185
10299
|
chromeScale,
|
|
10186
10300
|
chromeSettling,
|
|
10301
|
+
showHandles = true,
|
|
10187
10302
|
}: {
|
|
10188
10303
|
geometry: FrameGeometry;
|
|
10189
10304
|
chromeScale: number;
|
|
10190
10305
|
chromeSettling: boolean;
|
|
10306
|
+
showHandles?: boolean;
|
|
10191
10307
|
}) {
|
|
10192
10308
|
return (
|
|
10193
10309
|
<div
|
|
@@ -10208,21 +10324,23 @@ function PassiveSelectionBox({
|
|
|
10208
10324
|
zIndex: 999_999,
|
|
10209
10325
|
}}
|
|
10210
10326
|
>
|
|
10211
|
-
{
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10225
|
-
|
|
10327
|
+
{showHandles
|
|
10328
|
+
? CORNER_RESIZE_HANDLE_CONFIGS.map((config) => (
|
|
10329
|
+
<span
|
|
10330
|
+
key={config.handle}
|
|
10331
|
+
data-passive-resize-handle={config.handle}
|
|
10332
|
+
className="pointer-events-none absolute z-20 rounded-[2px] border border-[var(--design-editor-accent-color)] bg-[var(--design-editor-accent-contrast-color)] shadow"
|
|
10333
|
+
style={cornerHandleStyle(
|
|
10334
|
+
config.handle,
|
|
10335
|
+
config.cursor,
|
|
10336
|
+
chromeScale,
|
|
10337
|
+
chromeSettling,
|
|
10338
|
+
geometry.width,
|
|
10339
|
+
geometry.height,
|
|
10340
|
+
)}
|
|
10341
|
+
/>
|
|
10342
|
+
))
|
|
10343
|
+
: null}
|
|
10226
10344
|
</div>
|
|
10227
10345
|
);
|
|
10228
10346
|
}
|
|
@@ -10233,6 +10351,7 @@ function SelectionBox({
|
|
|
10233
10351
|
chromeSettling,
|
|
10234
10352
|
filled = false,
|
|
10235
10353
|
showRotate = true,
|
|
10354
|
+
handlesEnabled = true,
|
|
10236
10355
|
onStartResize,
|
|
10237
10356
|
onStartRotate,
|
|
10238
10357
|
}: {
|
|
@@ -10241,6 +10360,7 @@ function SelectionBox({
|
|
|
10241
10360
|
chromeSettling: boolean;
|
|
10242
10361
|
filled?: boolean;
|
|
10243
10362
|
showRotate?: boolean;
|
|
10363
|
+
handlesEnabled?: boolean;
|
|
10244
10364
|
onStartResize: (handle: ResizeHandle, e: React.MouseEvent) => void;
|
|
10245
10365
|
onStartRotate: (e: React.MouseEvent) => void;
|
|
10246
10366
|
}) {
|
|
@@ -10269,7 +10389,7 @@ function SelectionBox({
|
|
|
10269
10389
|
>
|
|
10270
10390
|
<ResizeHandles
|
|
10271
10391
|
active
|
|
10272
|
-
enabled
|
|
10392
|
+
enabled={handlesEnabled}
|
|
10273
10393
|
showRotate={showRotate}
|
|
10274
10394
|
chromeScale={chromeScale}
|
|
10275
10395
|
chromeSettling={chromeSettling}
|