@agent-native/core 0.92.10 → 0.92.12
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 +1 -1
- package/corpus/core/CHANGELOG.md +29 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +214 -17
- package/corpus/core/src/agent/run-manager.ts +72 -14
- package/corpus/core/src/agent/run-store.ts +152 -27
- package/corpus/core/src/cli/design-connect.ts +433 -151
- package/corpus/core/src/cli/skills.ts +14 -0
- package/corpus/core/src/client/AssistantChat.tsx +25 -0
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +40 -6
- package/corpus/core/src/client/agent-chat-adapter.ts +56 -12
- package/corpus/core/src/client/agent-chat.ts +165 -1
- package/corpus/core/src/client/chat/index.ts +9 -1
- package/corpus/core/src/client/extensions/EmbeddedExtension.tsx +38 -2
- package/corpus/core/src/client/index.ts +5 -0
- package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +18 -7
- package/corpus/core/src/collab/awareness-store.ts +23 -12
- package/corpus/core/src/collab/client.ts +16 -5
- package/corpus/core/src/collab/index.ts +4 -0
- package/corpus/core/src/collab/recent-edits.ts +65 -2
- package/corpus/core/src/index.browser.ts +1 -0
- package/corpus/core/src/server/agent-chat-plugin.ts +98 -11
- package/corpus/core/src/server/builder-design-systems.ts +30 -4
- package/corpus/templates/clips/.agents/skills/ai-video-tools/SKILL.md +1 -1
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +12 -6
- package/corpus/templates/clips/AGENTS.md +4 -0
- package/corpus/templates/clips/actions/create-recording.ts +2 -0
- package/corpus/templates/clips/actions/lib/create-recording-schema.ts +5 -3
- package/corpus/templates/clips/actions/request-transcript.ts +102 -33
- package/corpus/templates/clips/app/components/library/library-grid.tsx +1 -0
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +59 -19
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +75 -9
- package/corpus/templates/clips/app/components/player/video-player.tsx +17 -12
- package/corpus/templates/clips/app/hooks/use-player-shortcuts.ts +1 -0
- package/corpus/templates/clips/app/i18n/ar-SA.ts +1 -0
- package/corpus/templates/clips/app/i18n/de-DE.ts +1 -0
- package/corpus/templates/clips/app/i18n/en-US.ts +1 -0
- package/corpus/templates/clips/app/i18n/es-ES.ts +1 -0
- package/corpus/templates/clips/app/i18n/fr-FR.ts +1 -0
- package/corpus/templates/clips/app/i18n/hi-IN.ts +1 -0
- package/corpus/templates/clips/app/i18n/ja-JP.ts +1 -0
- package/corpus/templates/clips/app/i18n/ko-KR.ts +1 -0
- package/corpus/templates/clips/app/i18n/pt-BR.ts +1 -0
- package/corpus/templates/clips/app/i18n/zh-CN.ts +1 -0
- package/corpus/templates/clips/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +70 -37
- package/corpus/templates/clips/app/routes/record.tsx +17 -4
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +2 -0
- package/corpus/templates/clips/changelog/2026-07-09-desktop-popover-sits-closer-to-the-menu-bar.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-desktop-recording-optimization-progress-stays-visible-until-the-clip-opens.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-fixed-large-video-file-uploads-failing-before-their-resumabl.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-fixed-new-video-uploads-defaulting-to-private.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-long-recordings-now-get-enough-time-to-download-their-media-.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-meeting-notes-no-longer-lowers-your-microphone-volume-for-ot.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-on-mobile-tapping-a-playing-clip-reveals-playback-controls-w.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-regenerate-any-clip-transcript-from-its-saved-recording-or-r.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-09-slack-previews-now-show-the-clip-length-alongside-its-descri.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-10-fixed-copying-agent-responses-and-transcript-text-from-recor.md +6 -0
- package/corpus/templates/clips/desktop/src/app.tsx +12 -2
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +8 -1
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +8 -5
- package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +5 -5
- package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +3 -0
- package/corpus/templates/clips/desktop/src/styles.css +6 -3
- package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +29 -11
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +1 -1
- package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +103 -21
- package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +117 -39
- package/corpus/templates/clips/server/lib/slack-unfurls.ts +20 -1
- package/corpus/templates/clips/server/lib/streaming-upload-mode.ts +10 -4
- package/corpus/templates/clips/shared/recording-core.ts +12 -0
- package/corpus/templates/content/AGENTS.md +7 -6
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +82 -7
- package/corpus/templates/content/actions/_database-source-utils.ts +149 -30
- package/corpus/templates/content/actions/_document-flush.ts +132 -17
- package/corpus/templates/content/actions/_notion-action-utils.ts +15 -0
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +4 -7
- package/corpus/templates/content/actions/attach-content-database-source.ts +41 -17
- package/corpus/templates/content/actions/change-content-database-source-role.ts +46 -8
- package/corpus/templates/content/actions/create-and-link-notion-page.ts +2 -0
- package/corpus/templates/content/actions/link-notion-page.ts +2 -0
- package/corpus/templates/content/actions/pull-document.ts +5 -7
- package/corpus/templates/content/actions/pull-notion-page.ts +2 -0
- package/corpus/templates/content/actions/push-notion-page.ts +10 -0
- package/corpus/templates/content/actions/resolve-notion-sync-conflict.ts +2 -0
- package/corpus/templates/content/actions/suggest-source-join-key.ts +8 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +88 -23
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +32 -2
- package/corpus/templates/content/app/hooks/use-notion.ts +6 -6
- package/corpus/templates/content/app/i18n/zh-TW.ts +1 -0
- package/corpus/templates/content/app/i18n-data.ts +18 -0
- package/corpus/templates/content/changelog/2026-07-09-builder-source-refreshes-now-keep-mapped-fields-such-as-topi.md +6 -0
- package/corpus/templates/content/changelog/2026-07-09-notion-conflict-choices-and-version-restores-preserve-docume.md +6 -0
- package/corpus/templates/content/server/lib/notion-sync.ts +80 -64
- package/corpus/templates/content/shared/api.ts +1 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +29 -2
- package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +86 -0
- package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +57 -0
- package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +11 -0
- package/corpus/templates/design/AGENTS.md +45 -10
- package/corpus/templates/design/actions/add-localhost-screens.ts +66 -13
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +45 -36
- package/corpus/templates/design/actions/apply-motion-edit.ts +25 -31
- package/corpus/templates/design/actions/apply-shader-fill.ts +29 -42
- package/corpus/templates/design/actions/detach-component-instance.ts +337 -0
- package/corpus/templates/design/actions/export-design-as-figma-svg.ts +219 -0
- package/corpus/templates/design/actions/generate-design.ts +79 -12
- package/corpus/templates/design/actions/generate-screens.ts +57 -12
- package/corpus/templates/design/actions/get-figma-styles.ts +115 -0
- package/corpus/templates/design/actions/go-to-main-component.ts +254 -0
- package/corpus/templates/design/actions/grant-localhost-write-consent.ts +4 -3
- package/corpus/templates/design/actions/import-design-source.ts +4 -31
- package/corpus/templates/design/actions/import-figma-clipboard.ts +134 -0
- package/corpus/templates/design/actions/import-figma-frame.ts +95 -0
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +16 -1
- package/corpus/templates/design/actions/list-design-components.ts +104 -0
- package/corpus/templates/design/actions/list-figma-library-assets.ts +1 -24
- package/corpus/templates/design/actions/open-component-source.ts +2 -4
- package/corpus/templates/design/actions/present-design-variants.ts +412 -16
- package/corpus/templates/design/actions/preview-source-edit.ts +14 -1
- package/corpus/templates/design/actions/run-design-audit.ts +25 -3
- package/corpus/templates/design/actions/show-design-questions.ts +10 -0
- package/corpus/templates/design/actions/swap-component-instance.ts +544 -0
- package/corpus/templates/design/actions/take-design-screenshot.ts +45 -60
- package/corpus/templates/design/actions/write-local-file.ts +25 -1
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +152 -0
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +1077 -58
- package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +5 -5
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +73 -21
- package/corpus/templates/design/app/components/design/EditPanel.tsx +16 -11
- package/corpus/templates/design/app/components/design/KeyboardShortcutsPanel.tsx +364 -0
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +180 -53
- package/corpus/templates/design/app/components/design/LocalhostWriteConsentDialog.tsx +0 -2
- package/corpus/templates/design/app/components/design/MotionDock.tsx +144 -21
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1152 -167
- package/corpus/templates/design/app/components/design/QuestionFlow.tsx +27 -5
- package/corpus/templates/design/app/components/design/ReviewPanel.tsx +23 -2
- package/corpus/templates/design/app/components/design/TokensPanel.tsx +63 -49
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +1293 -54
- package/corpus/templates/design/app/components/design/bridge/embedded-wheel.bridge.ts +7 -0
- package/corpus/templates/design/app/components/design/bridge/hit-test.bridge.ts +6 -1
- package/corpus/templates/design/app/components/design/bridge/motion-preview.bridge.ts +23 -6
- package/corpus/templates/design/app/components/design/bridge/sample.bridge.ts +7 -0
- package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +5 -0
- package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +14 -2
- package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +37 -2
- package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open-guard.ts +25 -0
- package/corpus/templates/design/app/components/design/code-workbench/format/format-on-open.ts +19 -1
- package/corpus/templates/design/app/components/design/code-workbench/model-registry.ts +43 -5
- package/corpus/templates/design/app/components/design/code-workbench/search/SearchView.tsx +27 -2
- package/corpus/templates/design/app/components/design/code-workbench/search/search-engine.ts +10 -1
- package/corpus/templates/design/app/components/design/code-workbench/store.tsx +19 -2
- package/corpus/templates/design/app/components/design/design-canvas/annotation-snapshot.ts +265 -0
- package/corpus/templates/design/app/components/design/design-canvas/annotation-submit.ts +16 -5
- package/corpus/templates/design/app/components/design/design-canvas/coordinate-transforms.ts +16 -2
- package/corpus/templates/design/app/components/design/design-canvas/embedded-frame.ts +7 -2
- package/corpus/templates/design/app/components/design/design-canvas/iframe-events.ts +3 -1
- package/corpus/templates/design/app/components/design/edit-panel/code-inspect-helpers.tsx +78 -8
- package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +451 -73
- package/corpus/templates/design/app/components/design/edit-panel/document-colors.ts +12 -4
- package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +398 -272
- package/corpus/templates/design/app/components/design/edit-panel/element-classification.ts +41 -7
- package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +16 -3
- package/corpus/templates/design/app/components/design/edit-panel/field-primitives.tsx +24 -4
- package/corpus/templates/design/app/components/design/edit-panel/fill-gradient-helpers.ts +222 -4
- package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +171 -78
- package/corpus/templates/design/app/components/design/edit-panel/inspector-controls.tsx +45 -5
- package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +299 -28
- package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +120 -150
- package/corpus/templates/design/app/components/design/edit-panel/position-helpers.ts +53 -1
- package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +284 -117
- package/corpus/templates/design/app/components/design/edit-panel/selection-helpers.ts +81 -0
- package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +19 -14
- package/corpus/templates/design/app/components/design/edit-panel/style-options.ts +7 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-helpers.ts +155 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-properties.tsx +268 -46
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +350 -31
- package/corpus/templates/design/app/components/design/inspector/ConstraintsWidget.tsx +13 -4
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +233 -23
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +72 -2
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +51 -11
- package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +84 -11
- package/corpus/templates/design/app/components/design/inspector/index.ts +3 -0
- package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +552 -0
- package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +157 -0
- package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +53 -0
- package/corpus/templates/design/app/components/design/multi-screen/overview-layout.ts +184 -0
- package/corpus/templates/design/app/components/design/multi-screen/primitive-drop-target.ts +403 -26
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +20 -1
- package/corpus/templates/design/app/components/design/types.ts +33 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +59 -7
- package/corpus/templates/design/app/components/visual-editor/CanvasCommentPins.tsx +119 -17
- package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +275 -63
- package/corpus/templates/design/app/hooks/use-question-flow.ts +14 -3
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +67 -10
- package/corpus/templates/design/app/i18n/zh-TW.ts +91 -1
- package/corpus/templates/design/app/i18n-data.ts +1217 -10
- package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +577 -0
- package/corpus/templates/design/app/lib/agent-chat.ts +23 -0
- package/corpus/templates/design/app/lib/design-import.ts +24 -0
- package/corpus/templates/design/app/lib/figma-clipboard.ts +157 -0
- package/corpus/templates/design/app/lib/figma-svg-copy.ts +221 -0
- package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +143 -30
- package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +15 -0
- package/corpus/templates/design/app/pages/design-editor/editor-session.ts +33 -0
- package/corpus/templates/design/app/pages/design-editor/editor-state.ts +38 -0
- package/corpus/templates/design/app/pages/design-editor/overview-annotation-context.ts +157 -0
- package/corpus/templates/design/app/pages/design-editor/overview-camera.ts +62 -6
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +245 -0
- package/corpus/templates/design/app/pages/design-editor/react-semantic-handoff.ts +586 -0
- package/corpus/templates/design/app/pages/design-editor/screen-auto-layout.ts +169 -0
- package/corpus/templates/design/app/pages/design-editor/selection-state.ts +201 -1
- package/corpus/templates/design/changelog/2026-07-09-added-underline-strikethrough-and-text-case-uppercase-lowerc.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-annotate-now-draws-across-the-all-screens-canvas-without-swi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-auto-layout-children-can-now-be-dragged-into-freeform-screen.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-board-shapes-now-stay-visible-and-nest-correctly-across-the-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-component-source-navigation-now-opens-reliably-from-the-insp.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-cross-screen-local-react-layer-moves-now-hand-off-exact-sour.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-cross-screen-moves-undo-and-redo-now-keep-both-screens-stabl.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-detach-a-component-instance-into-plain-editable-eleme.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-dragging-layers-into-auto-layout-now-respects-ignore-auto-la.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-drawing-annotations-sent-to-the-agent-now-include-a-rendered.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-editor-sidebars-now-use-figma-matched-default-widths-for-a-r.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-empty-frames-and-rectangles-now-expose-full-auto-layout-cont.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-export-any-design-screen-as-a-real-vector-svg-for-figma-with.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-grid-auto-layout-now-uses-true-responsive-rows-and-columns-w.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-hidden-and-locked-screens-now-behave-consistently-between-la.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-image-fills-now-preserve-valid-urls-and-layered-fit-settings.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-import-figma-frames-as-pixel-accurate-design-screens-via-a-s.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-inspect-code-now-hides-internal-styling-metadata-and-wraps-l.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-inspector-blur-and-shadow-effects-now-preserve-other-effects.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-jump-to-a-components-other-instances-from-the-inspecto.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-keyboard-shortcuts-are-now-discoverable-in-a-figma-style-bot.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-layer-selection-now-keeps-cmd-or-ctrl-toggles-and-shift-rang.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-layers-dropped-into-auto-layout-now-participate-correctly-in.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-live-edit-screens-now-enter-and-leave-full-view-withou.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-preview-urls-now-live-in-the-inspector-instead-of-taki.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-layers-can-now-be-hidden-and-locked-from-layers-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-layers-now-keep-exact-source-provenance-and-supp.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-local-react-visual-editing-now-loads-reliably-and-shows-live.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-paste-from-figma-cmd-v-now-imports-exact-editable-nodes-when.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-pressing-escape-after-selecting-a-screen-now-reveals-page-pr.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-right-click-overlapping-or-nested-objects-to-choose-the-exac.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-scale-edge-stretch-and-center-constraints-now-preserve-layer.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-screen-rows-can-now-be-reordered-in-layers-with-matching-can.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-screen-selection-stays-responsive-in-designs-with-hundreds-o.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-shift-a-now-enables-auto-layout-on-a-selected-screen-with-fl.md +6 -0
- package/corpus/templates/design/changelog/2026-07-09-swap-a-component-instance-for-another-from-the-libra.md +6 -0
- package/corpus/templates/design/changelog/2026-07-10-drawing-annotations-now-stay-available-to-retry-when-the.md +6 -0
- package/corpus/templates/design/e2e/global-setup.ts +3 -6
- package/corpus/templates/design/e2e/helpers.ts +27 -6
- package/corpus/templates/design/server/lib/design-to-figma-svg.ts +1412 -0
- package/corpus/templates/design/server/lib/figma-clipboard-match.ts +196 -0
- package/corpus/templates/design/server/lib/figma-node-import.ts +311 -0
- package/corpus/templates/design/server/lib/figma-node-to-html.ts +1334 -0
- package/corpus/templates/design/server/lib/figma-paste-fallback.ts +64 -0
- package/corpus/templates/design/server/lib/playwright-runtime.ts +78 -0
- package/corpus/templates/design/server/plugins/db.ts +41 -0
- package/corpus/templates/design/server/source-workspace.ts +64 -0
- package/corpus/templates/design/shared/board-file.ts +13 -2
- package/corpus/templates/design/shared/canvas-math.ts +231 -33
- package/corpus/templates/design/shared/code-layer.ts +122 -8
- package/corpus/templates/design/shared/component-library.ts +161 -0
- package/corpus/templates/design/shared/db-conflict.ts +27 -0
- package/corpus/templates/design/shared/design-source-capabilities.ts +2 -1
- package/corpus/templates/design/shared/figma-url.ts +149 -0
- package/corpus/templates/design/shared/pen-path.ts +16 -7
- package/corpus/templates/design/shared/source-mode.ts +1 -0
- package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +7 -19
- package/corpus/templates/plan/changelog/2026-07-09-canvas-panning-now-keeps-zoom-fixed-even-at-the-edges.md +6 -0
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +16 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +311 -70
- package/corpus/templates/slides/changelog/2026-07-09-fixed-the-slide-rail-going-permanently-stale-during-a-long-a.md +6 -0
- package/dist/agent/production-agent.d.ts +82 -7
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +180 -17
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +63 -14
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/run-store.d.ts +46 -0
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +129 -22
- package/dist/agent/run-store.js.map +1 -1
- package/dist/cli/design-connect.d.ts +6 -0
- package/dist/cli/design-connect.d.ts.map +1 -1
- package/dist/cli/design-connect.js +336 -139
- package/dist/cli/design-connect.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +14 -0
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AssistantChat.d.ts +2 -0
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +19 -3
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +38 -18
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/agent-chat-adapter.d.ts.map +1 -1
- package/dist/client/agent-chat-adapter.js +48 -12
- package/dist/client/agent-chat-adapter.js.map +1 -1
- package/dist/client/agent-chat.d.ts +60 -0
- package/dist/client/agent-chat.d.ts.map +1 -1
- package/dist/client/agent-chat.js +122 -1
- package/dist/client/agent-chat.js.map +1 -1
- package/dist/client/chat/index.d.ts +1 -1
- package/dist/client/chat/index.d.ts.map +1 -1
- package/dist/client/chat/index.js +1 -1
- package/dist/client/chat/index.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts +12 -0
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +36 -2
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +18 -6
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
- package/dist/collab/awareness-store.d.ts +5 -0
- package/dist/collab/awareness-store.d.ts.map +1 -1
- package/dist/collab/awareness-store.js +19 -12
- package/dist/collab/awareness-store.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/client.d.ts.map +1 -1
- package/dist/collab/client.js +13 -5
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/index.d.ts +1 -0
- package/dist/collab/index.d.ts.map +1 -1
- package/dist/collab/index.js +1 -0
- package/dist/collab/index.js.map +1 -1
- package/dist/collab/recent-edits.d.ts +3 -1
- package/dist/collab/recent-edits.d.ts.map +1 -1
- package/dist/collab/recent-edits.js +57 -2
- package/dist/collab/recent-edits.js.map +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/index.browser.d.ts +1 -1
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +87 -10
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/builder-design-systems.d.ts +15 -0
- package/dist/server/builder-design-systems.d.ts.map +1 -1
- package/dist/server/builder-design-systems.js +9 -4
- package/dist/server/builder-design-systems.js.map +1 -1
- package/package.json +1 -1
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
type GlslShaderPanelContext,
|
|
38
38
|
} from "../inspector/GlslShaderPanel";
|
|
39
39
|
import type { ElementInfo } from "../types";
|
|
40
|
-
import {
|
|
40
|
+
import { elementStableKey } from "./element-identity";
|
|
41
41
|
import { FieldTrailer } from "./field-primitives";
|
|
42
42
|
import { splitCssLayers } from "./fill-gradient-helpers";
|
|
43
43
|
import {
|
|
@@ -50,8 +50,10 @@ import {
|
|
|
50
50
|
colorHasVisibleAlpha,
|
|
51
51
|
compactCssValue,
|
|
52
52
|
cssColorOrFallback,
|
|
53
|
+
roundToOneDecimal,
|
|
53
54
|
swatchStyle,
|
|
54
55
|
} from "./position-helpers";
|
|
56
|
+
import { isMixedValue } from "./selection-helpers";
|
|
55
57
|
import type {
|
|
56
58
|
MotionKeyframeFieldContext,
|
|
57
59
|
StyleChangeHandler,
|
|
@@ -59,7 +61,7 @@ import type {
|
|
|
59
61
|
StylesChangeHandler,
|
|
60
62
|
} from "./style-change-types";
|
|
61
63
|
|
|
62
|
-
interface ShadowLayer {
|
|
64
|
+
export interface ShadowLayer {
|
|
63
65
|
id: string;
|
|
64
66
|
x: number;
|
|
65
67
|
y: number;
|
|
@@ -81,7 +83,7 @@ function defaultDropShadowLayer(index: number): ShadowLayer {
|
|
|
81
83
|
};
|
|
82
84
|
}
|
|
83
85
|
|
|
84
|
-
function parseShadowLayers(value: string | undefined): ShadowLayer[] {
|
|
86
|
+
export function parseShadowLayers(value: string | undefined): ShadowLayer[] {
|
|
85
87
|
return splitCssLayers(value || "")
|
|
86
88
|
.filter((layer) => layer && layer !== "none")
|
|
87
89
|
.map((layer, index) => parseShadowLayer(layer, index));
|
|
@@ -133,18 +135,18 @@ function splitCssTokens(value: string): string[] {
|
|
|
133
135
|
return tokens;
|
|
134
136
|
}
|
|
135
137
|
|
|
136
|
-
function serializeShadowLayers(layers: ShadowLayer[]) {
|
|
138
|
+
export function serializeShadowLayers(layers: ShadowLayer[]) {
|
|
137
139
|
if (!layers.length) return "none";
|
|
138
140
|
return layers
|
|
139
141
|
.map((layer) =>
|
|
140
142
|
[
|
|
141
143
|
layer.inset ? "inset" : "",
|
|
142
|
-
`${
|
|
143
|
-
`${
|
|
144
|
-
`${Math.max(0,
|
|
144
|
+
`${roundToOneDecimal(layer.x)}px`,
|
|
145
|
+
`${roundToOneDecimal(layer.y)}px`,
|
|
146
|
+
`${Math.max(0, roundToOneDecimal(layer.blur))}px`,
|
|
145
147
|
// Spread radius may legitimately be negative for either inset or
|
|
146
148
|
// drop shadows — only blur-radius is clamped to >= 0 in CSS.
|
|
147
|
-
`${
|
|
149
|
+
`${roundToOneDecimal(layer.spread)}px`,
|
|
148
150
|
layer.color,
|
|
149
151
|
]
|
|
150
152
|
.filter(Boolean)
|
|
@@ -153,8 +155,8 @@ function serializeShadowLayers(layers: ShadowLayer[]) {
|
|
|
153
155
|
.join(", ");
|
|
154
156
|
}
|
|
155
157
|
|
|
156
|
-
function readBlurFilter(value: string | undefined): number {
|
|
157
|
-
const match = value?.match(/blur\((
|
|
158
|
+
export function readBlurFilter(value: string | undefined): number {
|
|
159
|
+
const match = value?.match(/blur\((-?(?:\d+(?:\.\d+)?|\.\d+))px\)/);
|
|
158
160
|
return match ? Math.max(0, Number(match[1])) : 0;
|
|
159
161
|
}
|
|
160
162
|
|
|
@@ -162,12 +164,62 @@ function hasBlurFilter(value: string | undefined): boolean {
|
|
|
162
164
|
return /blur\(/.test(value || "");
|
|
163
165
|
}
|
|
164
166
|
|
|
165
|
-
function setBlurFilterValue(
|
|
166
|
-
|
|
167
|
+
export function setBlurFilterValue(
|
|
168
|
+
value: string | undefined,
|
|
169
|
+
blur: number,
|
|
170
|
+
): string {
|
|
171
|
+
const blurFn = `blur(${Math.max(0, roundToOneDecimal(blur))}px)`;
|
|
167
172
|
const existing = compactCssValue(value, "");
|
|
168
173
|
return existing.includes("blur(")
|
|
169
174
|
? existing.replace(/blur\([^)]*\)/, blurFn)
|
|
170
|
-
:
|
|
175
|
+
: existing && existing !== "none"
|
|
176
|
+
? `${existing} ${blurFn}`
|
|
177
|
+
: blurFn;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** Remove only the layer/background blur function, preserving every sibling
|
|
181
|
+
* CSS filter (brightness, contrast, drop-shadow, etc.). Figma models layer
|
|
182
|
+
* blur as one effect row; deleting that row must not delete the other effects
|
|
183
|
+
* that happen to share CSS's `filter`/`backdrop-filter` declaration. */
|
|
184
|
+
export function removeBlurFilterValue(value: string | undefined): string {
|
|
185
|
+
const existing = compactCssValue(value, "");
|
|
186
|
+
if (!existing || existing === "none") return "none";
|
|
187
|
+
const remaining = existing
|
|
188
|
+
.replace(/blur\([^)]*\)/g, " ")
|
|
189
|
+
.replace(/\s+/g, " ")
|
|
190
|
+
.trim();
|
|
191
|
+
return remaining || "none";
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Keep the transient original-opacity stash attached to the same shadow when
|
|
195
|
+
* positional CSS layers are reordered or removed. Parsed shadow ids are
|
|
196
|
+
* necessarily index-based (`shadow-0`, `shadow-1`, …); after a reorder the
|
|
197
|
+
* next computed-style read regenerates those ids in the new order. Without
|
|
198
|
+
* remapping, a hidden shadow's saved alpha stays at its old index and the eye
|
|
199
|
+
* button restores the wrong layer (or falls back to 25%). */
|
|
200
|
+
export function remapIndexedShadowStash(
|
|
201
|
+
stash: Record<string, string>,
|
|
202
|
+
elementKey: string,
|
|
203
|
+
nextLayers: readonly Pick<ShadowLayer, "id">[],
|
|
204
|
+
): Record<string, string> {
|
|
205
|
+
const prefix = `${elementKey}:shadow:`;
|
|
206
|
+
const moved = nextLayers.flatMap((layer, index) => {
|
|
207
|
+
const value = stash[`${prefix}${layer.id}`];
|
|
208
|
+
return value === undefined ? [] : [[`${prefix}shadow-${index}`, value]];
|
|
209
|
+
});
|
|
210
|
+
if (!Object.keys(stash).some((key) => key.startsWith(prefix))) return stash;
|
|
211
|
+
const next = Object.fromEntries(
|
|
212
|
+
Object.entries(stash).filter(([key]) => !key.startsWith(prefix)),
|
|
213
|
+
);
|
|
214
|
+
for (const [key, value] of moved) next[key] = value;
|
|
215
|
+
const stashEntries = Object.entries(stash);
|
|
216
|
+
if (
|
|
217
|
+
stashEntries.length === Object.keys(next).length &&
|
|
218
|
+
stashEntries.every(([key, value]) => next[key] === value)
|
|
219
|
+
) {
|
|
220
|
+
return stash;
|
|
221
|
+
}
|
|
222
|
+
return next;
|
|
171
223
|
}
|
|
172
224
|
|
|
173
225
|
function shadowColorWithOpacity(color: string, opacity: number): string {
|
|
@@ -179,6 +231,33 @@ function shadowColorWithOpacity(color: string, opacity: number): string {
|
|
|
179
231
|
: color;
|
|
180
232
|
}
|
|
181
233
|
|
|
234
|
+
/**
|
|
235
|
+
* True when the current multi-selection has differing box-shadow, filter,
|
|
236
|
+
* or backdrop-filter values (the synthetic mixed-selection ElementInfo
|
|
237
|
+
* reports the `MIXED_VALUE`/"Mixed" sentinel for any style property that
|
|
238
|
+
* disagrees across the selection — see selection-helpers.ts). Effects had no
|
|
239
|
+
* mixed-selection handling at all: `parseShadowLayers("Mixed")` would parse
|
|
240
|
+
* the literal sentinel string as a bogus single shadow layer (color:
|
|
241
|
+
* "Mixed", the rest defaulted), and editing any of its fields would commit
|
|
242
|
+
* an invalid `box-shadow: ... Mixed` to every selected element. Fill and
|
|
243
|
+
* Stroke both already gate their sections on an equivalent mixed check and
|
|
244
|
+
* show a "Click + to replace" hint instead of rendering broken per-field
|
|
245
|
+
* controls; Effects needs the same gate.
|
|
246
|
+
*/
|
|
247
|
+
export function effectsSelectionIsMixed(styles: {
|
|
248
|
+
boxShadow?: string;
|
|
249
|
+
filter?: string;
|
|
250
|
+
backdropFilter?: string;
|
|
251
|
+
webkitBackdropFilter?: string;
|
|
252
|
+
}): boolean {
|
|
253
|
+
return [
|
|
254
|
+
styles.boxShadow,
|
|
255
|
+
styles.filter,
|
|
256
|
+
styles.backdropFilter,
|
|
257
|
+
styles.webkitBackdropFilter,
|
|
258
|
+
].some(isMixedValue);
|
|
259
|
+
}
|
|
260
|
+
|
|
182
261
|
function ShadowEffectRow({
|
|
183
262
|
layer,
|
|
184
263
|
index,
|
|
@@ -376,22 +455,37 @@ export function EffectsProperties({
|
|
|
376
455
|
const t = useT();
|
|
377
456
|
const [shaderPickerOpen, setShaderPickerOpen] = useState(false);
|
|
378
457
|
const styles = element.computedStyles;
|
|
379
|
-
const blurValue = readBlurFilter(styles.filter);
|
|
380
|
-
const filterHasBlur = hasBlurFilter(styles.filter);
|
|
381
458
|
// M5 · Background (backdrop) blur is a distinct design effect type, backed by
|
|
382
459
|
// CSS `backdrop-filter: blur()` (vs layer blur's `filter: blur()`).
|
|
383
460
|
const backdropFilterValue =
|
|
384
461
|
styles.backdropFilter || styles.webkitBackdropFilter;
|
|
385
|
-
|
|
462
|
+
// Differing box-shadow/filter/backdrop-filter across a multi-selection —
|
|
463
|
+
// gates the whole section to a "Click + to replace" hint below, same as
|
|
464
|
+
// Fill/Stroke, instead of parsing the "Mixed" sentinel as real CSS.
|
|
465
|
+
const effectsAreMixed = effectsSelectionIsMixed({
|
|
466
|
+
boxShadow: styles.boxShadow,
|
|
467
|
+
filter: styles.filter,
|
|
468
|
+
backdropFilter: styles.backdropFilter,
|
|
469
|
+
webkitBackdropFilter: styles.webkitBackdropFilter,
|
|
470
|
+
});
|
|
471
|
+
const blurValue = readBlurFilter(styles.filter);
|
|
472
|
+
const filterHasBlur = !effectsAreMixed && hasBlurFilter(styles.filter);
|
|
473
|
+
const backdropFilterHasBlur =
|
|
474
|
+
!effectsAreMixed && hasBlurFilter(backdropFilterValue);
|
|
386
475
|
const backdropBlurValue = readBlurFilter(backdropFilterValue);
|
|
387
476
|
const [hiddenEffectStash, setHiddenEffectStash] = useState<
|
|
388
477
|
Record<string, string>
|
|
389
478
|
>({});
|
|
390
|
-
const effectStashKey =
|
|
479
|
+
const effectStashKey = elementStableKey(element);
|
|
391
480
|
const layerBlurStashKey = `${effectStashKey}:filter:blur`;
|
|
392
481
|
const backdropBlurStashKey = `${effectStashKey}:backdrop-filter:blur`;
|
|
393
|
-
const shadowLayers =
|
|
482
|
+
const shadowLayers = effectsAreMixed
|
|
483
|
+
? []
|
|
484
|
+
: parseShadowLayers(styles.boxShadow);
|
|
394
485
|
const setShadowLayers = (layers: ShadowLayer[], meta?: StyleChangeMeta) => {
|
|
486
|
+
setHiddenEffectStash((stash) =>
|
|
487
|
+
remapIndexedShadowStash(stash, effectStashKey, layers),
|
|
488
|
+
);
|
|
395
489
|
const boxShadow = serializeShadowLayers(layers);
|
|
396
490
|
if (onStylesChange) onStylesChange({ boxShadow }, meta);
|
|
397
491
|
else onStyleChange("boxShadow", boxShadow, meta);
|
|
@@ -401,8 +495,10 @@ export function EffectsProperties({
|
|
|
401
495
|
...shadowLayers,
|
|
402
496
|
defaultDropShadowLayer(shadowLayers.length),
|
|
403
497
|
]);
|
|
404
|
-
const addLayerBlur = () =>
|
|
405
|
-
|
|
498
|
+
const addLayerBlur = () =>
|
|
499
|
+
onStyleChange("filter", setBlurFilterValue(styles.filter, 4));
|
|
500
|
+
const addBackgroundBlur = () =>
|
|
501
|
+
onStyleChange("backdropFilter", setBlurFilterValue(backdropFilterValue, 8));
|
|
406
502
|
const reorderShadowLayers = (from: number, to: number) => {
|
|
407
503
|
const next = [...shadowLayers];
|
|
408
504
|
const [moved] = next.splice(from, 1);
|
|
@@ -443,6 +539,7 @@ export function EffectsProperties({
|
|
|
443
539
|
// `!effectMount && !pickerOpen` early-return so opening the picker doesn't
|
|
444
540
|
// get swallowed by this outer gate before it can render itself.
|
|
445
541
|
const hasEffectsContent =
|
|
542
|
+
effectsAreMixed ||
|
|
446
543
|
shadowLayers.length > 0 ||
|
|
447
544
|
filterHasBlur ||
|
|
448
545
|
backdropFilterHasBlur ||
|
|
@@ -506,262 +603,291 @@ export function EffectsProperties({
|
|
|
506
603
|
>
|
|
507
604
|
{hasEffectsContent ? (
|
|
508
605
|
<>
|
|
509
|
-
{
|
|
510
|
-
<
|
|
511
|
-
{
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
606
|
+
{effectsAreMixed ? (
|
|
607
|
+
<p className="px-1.5 py-2 !text-[11px] text-muted-foreground">
|
|
608
|
+
{
|
|
609
|
+
"Click + to replace mixed content" /* i18n-ignore figma mixed effects hint */
|
|
610
|
+
}
|
|
611
|
+
</p>
|
|
612
|
+
) : (
|
|
613
|
+
<>
|
|
614
|
+
{shadowLayers.length ? (
|
|
615
|
+
<div className="space-y-1.5">
|
|
616
|
+
{shadowLayers.map((layer, index) => (
|
|
617
|
+
<ShadowEffectRow
|
|
618
|
+
key={layer.id}
|
|
619
|
+
layer={layer}
|
|
620
|
+
index={index}
|
|
621
|
+
dragHandleLabel={t("editPanel.labels.reorderLayer")}
|
|
622
|
+
dropIndicator={
|
|
623
|
+
shadowDrag.dragIndex != null &&
|
|
624
|
+
shadowDrag.overIndex === index
|
|
625
|
+
? shadowDrag.overIndex > shadowDrag.dragIndex
|
|
626
|
+
? "after"
|
|
627
|
+
: "before"
|
|
628
|
+
: null
|
|
629
|
+
}
|
|
630
|
+
rowProps={shadowDrag.getRowProps(index)}
|
|
631
|
+
handleProps={shadowDrag.getHandleProps(index)}
|
|
632
|
+
onChange={(patch, meta) => {
|
|
633
|
+
const next = shadowLayers.map((candidate) =>
|
|
634
|
+
candidate.id === layer.id
|
|
635
|
+
? { ...candidate, ...patch }
|
|
636
|
+
: candidate,
|
|
637
|
+
);
|
|
638
|
+
setShadowLayers(next, meta);
|
|
639
|
+
}}
|
|
640
|
+
onToggleVisibility={() => {
|
|
641
|
+
const visible = colorHasVisibleAlpha(layer.color);
|
|
642
|
+
const shadowStashKey = `${effectStashKey}:shadow:${layer.id}`;
|
|
643
|
+
if (visible) {
|
|
644
|
+
setHiddenEffectStash((prev) => ({
|
|
645
|
+
...prev,
|
|
646
|
+
[shadowStashKey]: layer.color,
|
|
647
|
+
}));
|
|
648
|
+
const next = shadowLayers.map((candidate) =>
|
|
649
|
+
candidate.id === layer.id
|
|
650
|
+
? {
|
|
651
|
+
...candidate,
|
|
652
|
+
color: shadowColorWithOpacity(
|
|
653
|
+
candidate.color,
|
|
654
|
+
0,
|
|
655
|
+
),
|
|
656
|
+
}
|
|
657
|
+
: candidate,
|
|
658
|
+
);
|
|
659
|
+
setShadowLayers(next);
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
554
662
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
663
|
+
const restored =
|
|
664
|
+
hiddenEffectStash[shadowStashKey] ??
|
|
665
|
+
shadowColorWithOpacity(layer.color, 25);
|
|
666
|
+
setHiddenEffectStash((prev) => {
|
|
667
|
+
const next = { ...prev };
|
|
668
|
+
delete next[shadowStashKey];
|
|
669
|
+
return next;
|
|
670
|
+
});
|
|
671
|
+
const next = shadowLayers.map((candidate) =>
|
|
672
|
+
candidate.id === layer.id
|
|
673
|
+
? { ...candidate, color: restored }
|
|
674
|
+
: candidate,
|
|
675
|
+
);
|
|
676
|
+
setShadowLayers(next);
|
|
677
|
+
}}
|
|
678
|
+
onRemove={() =>
|
|
679
|
+
setShadowLayers(
|
|
680
|
+
shadowLayers.filter(
|
|
681
|
+
(candidate) => candidate.id !== layer.id,
|
|
682
|
+
),
|
|
683
|
+
)
|
|
684
|
+
}
|
|
685
|
+
element={element}
|
|
686
|
+
motionKeyframeContext={motionKeyframeContext}
|
|
687
|
+
/>
|
|
688
|
+
))}
|
|
689
|
+
</div>
|
|
690
|
+
) : null}
|
|
691
|
+
{filterHasBlur ? (
|
|
692
|
+
/* design effect row for layer blur: flat row matching shadow rows */
|
|
693
|
+
<Popover>
|
|
694
|
+
<div className="group flex items-center gap-1.5">
|
|
695
|
+
<PopoverTrigger asChild>
|
|
696
|
+
<button
|
|
697
|
+
type="button"
|
|
698
|
+
className="flex h-6 min-w-0 flex-1 items-center gap-1.5 rounded-md border border-[var(--design-editor-control-border)] bg-[var(--design-editor-control-bg)] px-1.5 text-left !text-[11px] hover:bg-[var(--design-editor-panel-raised-bg)]"
|
|
699
|
+
>
|
|
700
|
+
<span className="min-w-0 flex-1 truncate font-medium text-foreground">
|
|
701
|
+
{t("editPanel.labels.layerBlur")}
|
|
702
|
+
</span>
|
|
703
|
+
<span className="shrink-0 tabular-nums text-muted-foreground">
|
|
704
|
+
{roundToOneDecimal(blurValue)}px
|
|
705
|
+
</span>
|
|
706
|
+
</button>
|
|
707
|
+
</PopoverTrigger>
|
|
708
|
+
<SectionIconButton
|
|
709
|
+
label={
|
|
710
|
+
blurValue > 0
|
|
711
|
+
? t("editPanel.labels.hideLayer")
|
|
712
|
+
: t("editPanel.labels.showLayer")
|
|
713
|
+
}
|
|
714
|
+
onClick={() => {
|
|
715
|
+
if (blurValue > 0) {
|
|
716
|
+
setHiddenEffectStash((prev) => ({
|
|
717
|
+
...prev,
|
|
718
|
+
[layerBlurStashKey]: String(blurValue),
|
|
719
|
+
}));
|
|
720
|
+
onStyleChange(
|
|
721
|
+
"filter",
|
|
722
|
+
setBlurFilterValue(styles.filter, 0),
|
|
723
|
+
);
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
618
726
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
setBlurFilterValue(styles.filter, value),
|
|
662
|
-
meta,
|
|
663
|
-
)
|
|
664
|
-
}
|
|
665
|
-
unit="px"
|
|
666
|
-
min={0}
|
|
667
|
-
precision={1}
|
|
668
|
-
labelClassName="w-16"
|
|
669
|
-
inputClassName="h-6"
|
|
670
|
-
/>
|
|
671
|
-
</PopoverContent>
|
|
672
|
-
</Popover>
|
|
673
|
-
) : null}
|
|
674
|
-
{backdropFilterHasBlur ? (
|
|
675
|
-
/* M5 · Background (backdrop) blur effect row — mirrors the layer-blur row */
|
|
676
|
-
<Popover>
|
|
677
|
-
<div className="group flex items-center gap-1.5">
|
|
678
|
-
<PopoverTrigger asChild>
|
|
679
|
-
<button
|
|
680
|
-
type="button"
|
|
681
|
-
className="flex h-6 min-w-0 flex-1 items-center gap-1.5 rounded-md border border-[var(--design-editor-control-border)] bg-[var(--design-editor-control-bg)] px-1.5 text-left !text-[11px] hover:bg-[var(--design-editor-panel-raised-bg)]"
|
|
727
|
+
const restored = Number(
|
|
728
|
+
hiddenEffectStash[layerBlurStashKey],
|
|
729
|
+
);
|
|
730
|
+
const nextBlur =
|
|
731
|
+
Number.isFinite(restored) && restored > 0
|
|
732
|
+
? restored
|
|
733
|
+
: 4;
|
|
734
|
+
setHiddenEffectStash((prev) => {
|
|
735
|
+
const next = { ...prev };
|
|
736
|
+
delete next[layerBlurStashKey];
|
|
737
|
+
return next;
|
|
738
|
+
});
|
|
739
|
+
onStyleChange(
|
|
740
|
+
"filter",
|
|
741
|
+
setBlurFilterValue(styles.filter, nextBlur),
|
|
742
|
+
);
|
|
743
|
+
}}
|
|
744
|
+
>
|
|
745
|
+
{blurValue > 0 ? (
|
|
746
|
+
<IconEye className="size-3.5" />
|
|
747
|
+
) : (
|
|
748
|
+
<IconEyeOff className="size-3.5" />
|
|
749
|
+
)}
|
|
750
|
+
</SectionIconButton>
|
|
751
|
+
<SectionIconButton
|
|
752
|
+
label={t("editPanel.labels.removeLayer")}
|
|
753
|
+
onClick={() =>
|
|
754
|
+
onStyleChange(
|
|
755
|
+
"filter",
|
|
756
|
+
removeBlurFilterValue(styles.filter),
|
|
757
|
+
)
|
|
758
|
+
}
|
|
759
|
+
disabled={!filterHasBlur}
|
|
760
|
+
>
|
|
761
|
+
<IconMinus className="size-3.5" />
|
|
762
|
+
</SectionIconButton>
|
|
763
|
+
</div>
|
|
764
|
+
<PopoverContent
|
|
765
|
+
side="left"
|
|
766
|
+
align="start"
|
|
767
|
+
sideOffset={8}
|
|
768
|
+
className="w-56 p-3"
|
|
682
769
|
>
|
|
683
|
-
<
|
|
684
|
-
{"
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
770
|
+
<ScrubInput
|
|
771
|
+
label={t("editPanel.labels.blur")}
|
|
772
|
+
value={blurValue}
|
|
773
|
+
onChange={(value, meta) =>
|
|
774
|
+
onStyleChange(
|
|
775
|
+
"filter",
|
|
776
|
+
setBlurFilterValue(styles.filter, value),
|
|
777
|
+
meta,
|
|
778
|
+
)
|
|
779
|
+
}
|
|
780
|
+
unit="px"
|
|
781
|
+
min={0}
|
|
782
|
+
precision={1}
|
|
783
|
+
labelClassName="w-16"
|
|
784
|
+
inputClassName="h-6"
|
|
785
|
+
/>
|
|
786
|
+
</PopoverContent>
|
|
787
|
+
</Popover>
|
|
788
|
+
) : null}
|
|
789
|
+
{backdropFilterHasBlur ? (
|
|
790
|
+
/* M5 · Background (backdrop) blur effect row — mirrors the layer-blur row */
|
|
791
|
+
<Popover>
|
|
792
|
+
<div className="group flex items-center gap-1.5">
|
|
793
|
+
<PopoverTrigger asChild>
|
|
794
|
+
<button
|
|
795
|
+
type="button"
|
|
796
|
+
className="flex h-6 min-w-0 flex-1 items-center gap-1.5 rounded-md border border-[var(--design-editor-control-border)] bg-[var(--design-editor-control-bg)] px-1.5 text-left !text-[11px] hover:bg-[var(--design-editor-panel-raised-bg)]"
|
|
797
|
+
>
|
|
798
|
+
<span className="min-w-0 flex-1 truncate font-medium text-foreground">
|
|
799
|
+
{
|
|
800
|
+
"Background blur" /* i18n-ignore design effect type */
|
|
801
|
+
}
|
|
802
|
+
</span>
|
|
803
|
+
<span className="shrink-0 tabular-nums text-muted-foreground">
|
|
804
|
+
{roundToOneDecimal(backdropBlurValue)}px
|
|
805
|
+
</span>
|
|
806
|
+
</button>
|
|
807
|
+
</PopoverTrigger>
|
|
808
|
+
<SectionIconButton
|
|
809
|
+
label={
|
|
810
|
+
backdropBlurValue > 0
|
|
811
|
+
? t("editPanel.labels.hideLayer")
|
|
812
|
+
: t("editPanel.labels.showLayer")
|
|
813
|
+
}
|
|
814
|
+
onClick={() => {
|
|
815
|
+
if (backdropBlurValue > 0) {
|
|
816
|
+
setHiddenEffectStash((prev) => ({
|
|
817
|
+
...prev,
|
|
818
|
+
[backdropBlurStashKey]: String(backdropBlurValue),
|
|
819
|
+
}));
|
|
820
|
+
onStyleChange(
|
|
821
|
+
"backdropFilter",
|
|
822
|
+
setBlurFilterValue(backdropFilterValue, 0),
|
|
823
|
+
);
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
709
826
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
827
|
+
const restored = Number(
|
|
828
|
+
hiddenEffectStash[backdropBlurStashKey],
|
|
829
|
+
);
|
|
830
|
+
const nextBlur =
|
|
831
|
+
Number.isFinite(restored) && restored > 0
|
|
832
|
+
? restored
|
|
833
|
+
: 8;
|
|
834
|
+
setHiddenEffectStash((prev) => {
|
|
835
|
+
const next = { ...prev };
|
|
836
|
+
delete next[backdropBlurStashKey];
|
|
837
|
+
return next;
|
|
838
|
+
});
|
|
839
|
+
onStyleChange(
|
|
840
|
+
"backdropFilter",
|
|
841
|
+
setBlurFilterValue(backdropFilterValue, nextBlur),
|
|
842
|
+
);
|
|
843
|
+
}}
|
|
844
|
+
>
|
|
845
|
+
{backdropBlurValue > 0 ? (
|
|
846
|
+
<IconEye className="size-3.5" />
|
|
847
|
+
) : (
|
|
848
|
+
<IconEyeOff className="size-3.5" />
|
|
849
|
+
)}
|
|
850
|
+
</SectionIconButton>
|
|
851
|
+
<SectionIconButton
|
|
852
|
+
label={t("editPanel.labels.removeLayer")}
|
|
853
|
+
onClick={() =>
|
|
854
|
+
onStyleChange(
|
|
855
|
+
"backdropFilter",
|
|
856
|
+
removeBlurFilterValue(backdropFilterValue),
|
|
857
|
+
)
|
|
858
|
+
}
|
|
859
|
+
disabled={!backdropFilterHasBlur}
|
|
860
|
+
>
|
|
861
|
+
<IconMinus className="size-3.5" />
|
|
862
|
+
</SectionIconButton>
|
|
863
|
+
</div>
|
|
864
|
+
<PopoverContent
|
|
865
|
+
side="left"
|
|
866
|
+
align="start"
|
|
867
|
+
sideOffset={8}
|
|
868
|
+
className="w-56 p-3"
|
|
869
|
+
>
|
|
870
|
+
<ScrubInput
|
|
871
|
+
label={t("editPanel.labels.blur")}
|
|
872
|
+
value={backdropBlurValue}
|
|
873
|
+
onChange={(value, meta) =>
|
|
874
|
+
onStyleChange(
|
|
875
|
+
"backdropFilter",
|
|
876
|
+
setBlurFilterValue(backdropFilterValue, value),
|
|
877
|
+
meta,
|
|
878
|
+
)
|
|
879
|
+
}
|
|
880
|
+
unit="px"
|
|
881
|
+
min={0}
|
|
882
|
+
precision={1}
|
|
883
|
+
labelClassName="w-16"
|
|
884
|
+
inputClassName="h-6"
|
|
885
|
+
/>
|
|
886
|
+
</PopoverContent>
|
|
887
|
+
</Popover>
|
|
888
|
+
) : null}
|
|
889
|
+
</>
|
|
890
|
+
)}
|
|
765
891
|
{glslShaderContext?.nodeId ? (
|
|
766
892
|
/* Code-backed GLSL shader effect — overlay canvas above the
|
|
767
893
|
element's content, persisted as editable GLSL in the screen HTML
|