@agent-native/core 0.90.1 → 0.90.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 +1 -1
- package/corpus/core/CHANGELOG.md +14 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/AgentPanel.tsx +1 -1
- package/corpus/core/src/client/rich-markdown-editor/useCollabReconcile.ts +11 -6
- package/corpus/core/src/client/use-action.ts +39 -2
- package/corpus/core/src/client/use-db-sync.ts +44 -18
- package/corpus/core/src/db/create-get-db.ts +32 -2
- package/corpus/core/src/server/framework-request-handler.ts +52 -4
- package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +5 -0
- package/corpus/templates/assets/.agents/skills/logo-composite/SKILL.md +34 -6
- package/corpus/templates/assets/AGENTS.md +23 -4
- package/corpus/templates/assets/actions/_generation-preset-settings.ts +48 -0
- package/corpus/templates/assets/actions/_helpers.ts +8 -1
- package/corpus/templates/assets/actions/_preset-skeleton-validation.ts +64 -0
- package/corpus/templates/assets/actions/create-generation-preset.ts +11 -3
- package/corpus/templates/assets/actions/generate-image-batch.ts +7 -2
- package/corpus/templates/assets/actions/generate-image.ts +342 -25
- package/corpus/templates/assets/actions/get-library.ts +4 -3
- package/corpus/templates/assets/actions/navigate.ts +2 -1
- package/corpus/templates/assets/actions/refresh-generation-run.ts +5 -1
- package/corpus/templates/assets/actions/update-asset.ts +1 -0
- package/corpus/templates/assets/actions/update-generation-preset.ts +8 -1
- package/corpus/templates/assets/actions/view-screen.ts +8 -1
- package/corpus/templates/assets/app/components/generation/GenerationResults.tsx +9 -1
- package/corpus/templates/assets/app/hooks/use-image-model-menu.ts +1 -0
- package/corpus/templates/assets/app/hooks/use-navigation-state.ts +11 -0
- package/corpus/templates/assets/app/i18n/zh-TW.ts +64 -0
- package/corpus/templates/assets/app/i18n-data.ts +650 -0
- package/corpus/templates/assets/app/routes/asset.$id.tsx +2 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +44 -33
- package/corpus/templates/assets/app/routes/brand-kits.$id_.presets.$presetId.tsx +1474 -0
- package/corpus/templates/assets/app/routes/library.tsx +43 -1
- package/corpus/templates/assets/server/lib/generation.ts +366 -44
- package/corpus/templates/assets/server/lib/image-processing.ts +252 -0
- package/corpus/templates/assets/server/lib/preset-skeleton.ts +137 -0
- package/corpus/templates/assets/shared/api.ts +47 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +7 -2
- package/corpus/templates/clips/app/components/library/sort-menu.tsx +1 -1
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +114 -33
- package/corpus/templates/clips/app/routes/_app.library._index.tsx +27 -1
- package/corpus/templates/clips/app/routes/record.tsx +157 -68
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +5 -5
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +20 -3
- package/corpus/templates/clips/shared/finalize-recovery.ts +23 -3
- package/corpus/templates/content/AGENTS.md +52 -52
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +188 -8
- package/corpus/templates/content/actions/_builder-docs-client.ts +41 -3
- package/corpus/templates/content/actions/_database-source-utils.ts +998 -160
- package/corpus/templates/content/actions/_database-utils.ts +44 -4
- package/corpus/templates/content/actions/_notion-action-utils.ts +6 -2
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +23 -1
- package/corpus/templates/content/actions/attach-content-database-source.ts +85 -12
- package/corpus/templates/content/actions/change-content-database-source-role.ts +9 -1
- package/corpus/templates/content/actions/delete-content-database.ts +1 -0
- package/corpus/templates/content/actions/get-document.ts +11 -2
- package/corpus/templates/content/actions/list-content-databases.ts +57 -9
- package/corpus/templates/content/actions/prepare-builder-source-review.ts +23 -6
- package/corpus/templates/content/actions/refresh-content-database-source.ts +26 -3
- package/corpus/templates/content/actions/restore-content-database.ts +1 -0
- package/corpus/templates/content/actions/update-document.ts +43 -0
- package/corpus/templates/content/app/components/editor/BuilderBodySyncingNotice.tsx +21 -0
- package/corpus/templates/content/app/components/editor/DocumentDatabase.tsx +0 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +70 -28
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +69 -17
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +4 -4
- package/corpus/templates/content/app/components/editor/body-hydration.ts +112 -0
- package/corpus/templates/content/app/components/editor/builder-body-hydration-pump.ts +52 -0
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +9076 -2876
- package/corpus/templates/content/app/components/editor/database-sources/BuilderSourceReviewDialog.tsx +41 -1
- package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +36 -11
- package/corpus/templates/content/app/components/editor/previewDocumentSaveController.ts +21 -1
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +11 -1
- package/corpus/templates/content/app/components/sidebar/DocumentTreeItem.tsx +11 -8
- package/corpus/templates/content/app/global.css +41 -0
- package/corpus/templates/content/app/hooks/use-content-database.ts +346 -42
- package/corpus/templates/content/app/hooks/use-db-sync.ts +9 -0
- package/corpus/templates/content/app/hooks/use-documents.ts +47 -0
- package/corpus/templates/content/app/hooks/use-notion.ts +12 -10
- package/corpus/templates/content/app/i18n/zh-TW.ts +35 -0
- package/corpus/templates/content/app/i18n-data.ts +355 -0
- package/corpus/templates/content/app/root.tsx +22 -0
- package/corpus/templates/content/changelog/2026-07-01-builder-database-sources-keep-loading-rows-in-the-background.md +6 -0
- package/corpus/templates/content/changelog/2026-07-01-builder-source-attach-starts-with-usable-rows.md +6 -0
- package/corpus/templates/content/changelog/2026-07-01-builder-source-attachment-now-stays-connected-after-large.md +6 -0
- package/corpus/templates/content/changelog/2026-07-01-builder-source-refreshes-now-show-progress-for-large-docs-blog.md +6 -0
- package/corpus/templates/content/changelog/2026-07-01-database-pages-now-delete-to-trash-without-route-errors.md +6 -0
- package/corpus/templates/content/changelog/2026-07-02-builder-source-refreshes-recover-from-stalled-background-row.md +6 -0
- package/corpus/templates/content/changelog/2026-07-02-builder-sourced-rows-open-with-sync-protection.md +6 -0
- package/corpus/templates/content/changelog/2026-07-02-database-rows-and-pages-open-faster-from-recently-loaded-dat.md +6 -0
- package/corpus/templates/content/changelog/2026-07-02-preview-panels-close-reliably-narrow-sidebar-row-actions-sta.md +6 -0
- package/corpus/templates/content/changelog/2026-07-06-builder-sync-progress-no-longer-shows-continue.md +6 -0
- package/corpus/templates/content/shared/api.ts +13 -0
- package/corpus/templates/content/shared/builder-mdx.ts +16 -3
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +23 -13
- package/corpus/templates/design/.agents/skills/responsive-breakpoints/SKILL.md +98 -0
- package/corpus/templates/design/.agents/skills/shader-fills/SKILL.md +162 -0
- package/corpus/templates/design/AGENTS.md +9 -2
- package/corpus/templates/design/actions/add-breakpoint.ts +6 -3
- package/corpus/templates/design/actions/apply-a11y-fix.ts +57 -37
- package/corpus/templates/design/actions/apply-component-prop-edit.ts +41 -20
- package/corpus/templates/design/actions/apply-motion-edit.ts +251 -38
- package/corpus/templates/design/actions/apply-shader-fill.ts +90 -66
- package/corpus/templates/design/actions/apply-visual-edit.ts +282 -55
- package/corpus/templates/design/actions/create-component.ts +29 -60
- package/corpus/templates/design/actions/create-file.ts +9 -2
- package/corpus/templates/design/actions/duplicate-design.ts +31 -2
- package/corpus/templates/design/actions/edit-design.ts +36 -38
- package/corpus/templates/design/actions/generate-design-title.ts +87 -0
- package/corpus/templates/design/actions/generate-design.ts +53 -18
- package/corpus/templates/design/actions/generate-screens.ts +108 -4
- package/corpus/templates/design/actions/get-motion-timeline.ts +35 -7
- package/corpus/templates/design/actions/insert-asset.ts +34 -29
- package/corpus/templates/design/actions/insert-design-native-asset.ts +129 -32
- package/corpus/templates/design/actions/insert-figma-library-asset.ts +35 -30
- package/corpus/templates/design/actions/present-design-variants.ts +7 -2
- package/corpus/templates/design/actions/remove-motion-timeline.ts +31 -36
- package/corpus/templates/design/actions/update-file.ts +190 -75
- package/corpus/templates/design/app/components/design/BreakpointBar.tsx +403 -0
- package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +469 -222
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +708 -53
- package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +83 -3
- package/corpus/templates/design/app/components/design/EditPanel.tsx +1091 -6948
- package/corpus/templates/design/app/components/design/LayersPanel.tsx +419 -85
- package/corpus/templates/design/app/components/design/MotionDock.tsx +1124 -103
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +2610 -1398
- package/corpus/templates/design/app/components/design/ReadOnlyDesignBanner.tsx +22 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2182 -235
- package/corpus/templates/design/app/components/design/bridge/motion-preview.bridge.ts +187 -11
- package/corpus/templates/design/app/components/design/bridge/shader-fill-preview.bridge.ts +376 -1
- package/corpus/templates/design/app/components/design/bridge/shader-runtime.bridge.ts +746 -0
- package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +17 -0
- package/corpus/templates/design/app/components/design/code-workbench/SideBar.tsx +1 -1
- package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +1 -3
- package/corpus/templates/design/app/components/design/code-workbench/quickinput/QuickInput.tsx +1 -1
- package/corpus/templates/design/app/components/design/edit-panel/appearance-properties.tsx +518 -0
- package/corpus/templates/design/app/components/design/edit-panel/code-inspect-helpers.tsx +562 -0
- package/corpus/templates/design/app/components/design/edit-panel/component-section.tsx +763 -0
- package/corpus/templates/design/app/components/design/edit-panel/document-colors.ts +94 -0
- package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +780 -0
- package/corpus/templates/design/app/components/design/edit-panel/element-classification.ts +446 -0
- package/corpus/templates/design/app/components/design/edit-panel/element-identity.ts +79 -0
- package/corpus/templates/design/app/components/design/edit-panel/field-primitives.tsx +315 -0
- package/corpus/templates/design/app/components/design/edit-panel/fill-gradient-helpers.ts +344 -0
- package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +594 -0
- package/corpus/templates/design/app/components/design/edit-panel/frame-presets-panel.tsx +119 -0
- package/corpus/templates/design/app/components/design/edit-panel/inspector-controls.tsx +248 -0
- package/corpus/templates/design/app/components/design/edit-panel/interaction-state-helpers.ts +45 -0
- package/corpus/templates/design/app/components/design/edit-panel/layout-properties.tsx +693 -0
- package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +724 -0
- package/corpus/templates/design/app/components/design/edit-panel/position-helpers.ts +207 -0
- package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +628 -0
- package/corpus/templates/design/app/components/design/edit-panel/selection-helpers.ts +91 -0
- package/corpus/templates/design/app/components/design/edit-panel/stroke-properties.tsx +649 -0
- package/corpus/templates/design/app/components/design/edit-panel/style-change-types.ts +118 -0
- package/corpus/templates/design/app/components/design/edit-panel/style-options.ts +88 -0
- package/corpus/templates/design/app/components/design/edit-panel/transform-helpers.ts +100 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-helpers.ts +117 -0
- package/corpus/templates/design/app/components/design/edit-panel/typography-properties.tsx +501 -0
- package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +91 -40
- package/corpus/templates/design/app/components/design/inspector/BreakpointOverrideIndicator.tsx +82 -0
- package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +189 -87
- package/corpus/templates/design/app/components/design/inspector/GlslShaderPanel.tsx +1097 -0
- package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +44 -0
- package/corpus/templates/design/app/components/design/inspector/InteractionStatePanel.tsx +258 -0
- package/corpus/templates/design/app/components/design/inspector/MotionKeyframeDiamond.tsx +144 -0
- package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +99 -9
- package/corpus/templates/design/app/components/design/inspector/frame-size-presets.ts +116 -0
- package/corpus/templates/design/app/components/design/inspector/index.ts +26 -0
- package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +29 -0
- package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +171 -0
- package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +220 -0
- package/corpus/templates/design/app/components/design/multi-screen/chrome-transitions.ts +35 -0
- package/corpus/templates/design/app/components/design/multi-screen/cross-screen-drop.ts +134 -0
- package/corpus/templates/design/app/components/design/multi-screen/culling.ts +185 -0
- package/corpus/templates/design/app/components/design/multi-screen/gradient-overlay-geometry.ts +120 -0
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +892 -0
- package/corpus/templates/design/app/components/design/multi-screen/vector-edit-geometry.ts +21 -0
- package/corpus/templates/design/app/components/design/types.ts +15 -0
- package/corpus/templates/design/app/components/editor/PromptDialog.tsx +109 -5
- package/corpus/templates/design/app/global.css +8 -8
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +259 -2
- package/corpus/templates/design/app/i18n/zh-TW.ts +163 -9
- package/corpus/templates/design/app/i18n-breakpoints.ts +205 -0
- package/corpus/templates/design/app/i18n-data.ts +1664 -152
- package/corpus/templates/design/app/i18n-motion.ts +563 -0
- package/corpus/templates/design/app/lib/design-import.ts +73 -0
- package/corpus/templates/design/app/pages/Index.tsx +41 -22
- package/corpus/templates/design/changelog/2026-06-29-design-inspector-controls-now-match-figmas-softer-dark-chrome.md +1 -1
- package/corpus/templates/design/changelog/2026-06-30-design-now-has-a-figma-style-left-rail-for-file-agent-assets.md +1 -1
- package/corpus/templates/design/changelog/2026-06-30-design-tools-now-use-a-quieter-figma-style-list-layout.md +1 -1
- package/corpus/templates/design/changelog/2026-06-30-multi-select-outlines-now-stay-consistent-across-all-screens.md +1 -1
- package/corpus/templates/design/changelog/2026-07-03-canvas-interactions-now-match-figma-rotation-aware-resizing-.md +1 -1
- package/corpus/templates/design/changelog/2026-07-03-layers-panel-matches-figma-top-layer-on-top-drag-with-auto-s.md +1 -1
- package/corpus/templates/design/changelog/2026-07-05-designs-get-ai-generated-names-from-your-prompt.md +6 -0
- package/corpus/templates/design/changelog/2026-07-05-local-code-screens-keep-their-connection-when-duplicated-and.md +6 -0
- package/corpus/templates/design/changelog/2026-07-05-press-a-to-draw-screens-on-the-canvas-inside-a-screen-it-dr.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-3d-rotation-and-perspective-controls-on-every-element.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-ai-generated-and-duplicated-screens-now-get-their-editor-sel.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-applying-shaders-and-fills-in-quick-succession-can-no-longer.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-breakpoint-frames-in-the-overview-now-support-click-to-selec.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-breakpoint-segments-in-the-inspector-now-show-a-device-icon-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-breakpoint-targeting-now-lives-in-one-compact-control-in-the.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-canvas-edits-can-no-longer-be-overwritten-by-stale-collabora.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-canvas-edits-inside-screens-save-reliably-again.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-cleaner-inspector-removed-the-ask-ai-box-from-the-design-tab.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-clicking-empty-canvas-space-now-deselects-an-element-inside-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-dragging-an-element-onto-a-rectangle-now-nests-it-inside-wit.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-dragging-screens-and-objects-on-the-canvas-is-now-much-smoot.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-drawing-a-shape-or-text-on-the-canvas-no-longer-flashes-away.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-dropping-an-element-between-two-others-inside-a-screen-now-s.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-duplicating-a-screen-now-places-the-copy-exactly-where-you-d.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-edit-gradients-directly-on-elements-inside-screens-scale-str.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-edits-from-collaborators-and-the-agent-now-update-the-canvas.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-a-bug-where-most-style-position-and-text-edits-briefly.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-a-confusing-raw-error-message-when-a-file-upload-fails.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-a-rare-case-where-an-edit-could-be-silently-overwritte.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-inserted-assets-sometimes-disappearing-reappearing-or-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-inspector-value-scrubbing-producing-erratic-numbers-an.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-padding-gap-and-min-max-size-scrubbing-not-updating-th.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-text-stroke-color-turning-black-and-glyphs-disappearin.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-the-collapsed-effects-and-stroke-inspector-sections-sh.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-the-new-design-dialog-closing-unexpectedly-when-using-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-fixed-the-typography-section-missing-when-selecting-text-nes.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-full-view-no-longer-flashes-back-to-the-overview-on-entry-no.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-keyframe-animation-timeline-per-property-keyframes-easing-cu.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-moving-restyling-and-scrubbing-values-on-elements-in-ai-gene.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-padding-and-corner-radius-value-scrubbing-now-snaps-to-whole.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-padding-handles-now-only-resize-on-the-handle-line-itself-sh.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-preview-and-edit-hover-focus-and-pressed-states-with-real-cs.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-promoting-an-element-to-a-component-now-works-correctly-for-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-reduced-url-history-churn-and-selection-overlay-flicker-whil.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-removed-the-decorative-dot-before-screen-names-in-the-overvi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-responsive-breakpoints-edit-at-any-width-with-cascading-over.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-screen-labels-no-longer-turn-blue-when-you-hover-inside-the-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-scrolling-a-screen-with-an-element-selected-stays-smooth-on-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-selecting-multiple-elements-and-dragging-now-moves-the-whole.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-selection-borders-handles-and-value-readouts-now-stay-the-sa.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-selection-handles-and-editing-chrome-now-stay-a-constant-siz.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-shader-fills-and-effects-ai-authored-or-preset-glsl-shaders-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-text-drawn-on-the-canvas-now-defaults-to-white-and-inter-in-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-text-dropped-into-a-shape-now-stays-readable-instead-of-disa.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-the-add-tweak-controls-prompt-no-longer-jumps-to-the-corner-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-the-padding-value-readout-now-stays-visible-while-you-hover-.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-the-selected-element-attachment-now-clears-from-the-chat-com.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-the-zoom-menu-is-more-compact-with-tight-rows-and-right-alig.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-undo-and-redo-no-longer-flash-the-screen-changes-now-apply-i.md +6 -0
- package/corpus/templates/design/changelog/2026-07-06-zoom-presets-like-zoom-to-50-now-stay-on-the-focused-screen-.md +6 -0
- package/corpus/templates/design/server/lib/import-design-files.ts +11 -2
- package/corpus/templates/design/server/source-workspace.ts +139 -59
- package/corpus/templates/design/shared/board-file.ts +11 -2
- package/corpus/templates/design/shared/breakpoint-media.ts +543 -0
- package/corpus/templates/design/shared/canvas-math.ts +354 -35
- package/corpus/templates/design/shared/code-layer.ts +277 -8
- package/corpus/templates/design/shared/design-state.ts +11 -4
- package/corpus/templates/design/shared/interaction-states.ts +548 -0
- package/corpus/templates/design/shared/motion-compiler.ts +186 -23
- package/corpus/templates/design/shared/motion-easing.ts +294 -0
- package/corpus/templates/design/shared/motion-timeline.ts +400 -34
- package/corpus/templates/design/shared/prompt-title.ts +95 -0
- package/corpus/templates/design/shared/responsive-classes.ts +448 -10
- package/corpus/templates/design/shared/screen-annotation.ts +46 -0
- package/corpus/templates/design/shared/shader-fills.ts +1009 -0
- package/corpus/templates/design/shared/shader-presets.ts +852 -4
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +15 -2
- package/corpus/templates/slides/app/components/editor/ImportButton.tsx +10 -1
- package/corpus/templates/slides/app/lib/upload-response.ts +71 -0
- package/dist/client/AgentPanel.js +1 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.d.ts.map +1 -1
- package/dist/client/rich-markdown-editor/useCollabReconcile.js +11 -6
- package/dist/client/rich-markdown-editor/useCollabReconcile.js.map +1 -1
- package/dist/client/use-action.d.ts +3 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +34 -3
- package/dist/client/use-action.js.map +1 -1
- package/dist/client/use-db-sync.d.ts +4 -0
- package/dist/client/use-db-sync.d.ts.map +1 -1
- package/dist/client/use-db-sync.js +37 -18
- package/dist/client/use-db-sync.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db/create-get-db.d.ts +25 -0
- package/dist/db/create-get-db.d.ts.map +1 -1
- package/dist/db/create-get-db.js +25 -2
- package/dist/db/create-get-db.js.map +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/framework-request-handler.d.ts.map +1 -1
- package/dist/server/framework-request-handler.js +37 -1
- package/dist/server/framework-request-handler.js.map +1 -1
- package/package.json +1 -1
- package/corpus/templates/design/app/components/design/inspector/InspectorAiActions.tsx +0 -153
- package/corpus/templates/design/app/hooks/useAgentEditRequest.ts +0 -133
- package/corpus/templates/design/app/pages/DesignEditor.tsx +0 -22924
|
@@ -0,0 +1,594 @@
|
|
|
1
|
+
import { useT } from "@agent-native/core/client";
|
|
2
|
+
import {
|
|
3
|
+
parseCssColor,
|
|
4
|
+
rgbaToCss,
|
|
5
|
+
rgbaToHex,
|
|
6
|
+
withColorOpacity,
|
|
7
|
+
} from "@shared/color-utils";
|
|
8
|
+
import {
|
|
9
|
+
IconEye,
|
|
10
|
+
IconEyeOff,
|
|
11
|
+
IconLayoutGrid,
|
|
12
|
+
IconMinus,
|
|
13
|
+
IconPlus,
|
|
14
|
+
} from "@tabler/icons-react";
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
Popover,
|
|
18
|
+
PopoverContent,
|
|
19
|
+
PopoverTrigger,
|
|
20
|
+
} from "@/components/ui/popover";
|
|
21
|
+
|
|
22
|
+
import { DesignColorPicker, imageFillToBackgroundStyles } from "../inspector";
|
|
23
|
+
import type { GlslShaderPanelContext } from "../inspector/GlslShaderPanel";
|
|
24
|
+
import type { ElementInfo } from "../types";
|
|
25
|
+
import { selectionColorValues } from "./document-colors";
|
|
26
|
+
import { isTextElement } from "./element-classification";
|
|
27
|
+
import { commitStylePatch, FieldTrailer } from "./field-primitives";
|
|
28
|
+
import {
|
|
29
|
+
averageGradientOpacity,
|
|
30
|
+
buildGradientLayer,
|
|
31
|
+
defaultGradientLayer,
|
|
32
|
+
gradientLabel,
|
|
33
|
+
isLayerHiddenBySize,
|
|
34
|
+
joinCssLayers,
|
|
35
|
+
parseGradientLayer,
|
|
36
|
+
removeFillLayerAtIndex,
|
|
37
|
+
splitCssLayers,
|
|
38
|
+
withLayerSizeMarker,
|
|
39
|
+
} from "./fill-gradient-helpers";
|
|
40
|
+
import {
|
|
41
|
+
RowDragHandle,
|
|
42
|
+
SectionIconButton,
|
|
43
|
+
useRowDragReorder,
|
|
44
|
+
} from "./inspector-controls";
|
|
45
|
+
import { ColorInput, PanelSection } from "./panel-primitives";
|
|
46
|
+
import {
|
|
47
|
+
colorHasVisibleAlpha,
|
|
48
|
+
compactCssValue,
|
|
49
|
+
cssColorOrFallback,
|
|
50
|
+
swatchStyle,
|
|
51
|
+
} from "./position-helpers";
|
|
52
|
+
import { isMixedValue } from "./selection-helpers";
|
|
53
|
+
import type {
|
|
54
|
+
BreakpointOverrideFieldContext,
|
|
55
|
+
MotionKeyframeFieldContext,
|
|
56
|
+
StyleChangeHandler,
|
|
57
|
+
StylesChangeHandler,
|
|
58
|
+
} from "./style-change-types";
|
|
59
|
+
|
|
60
|
+
export function FillProperties({
|
|
61
|
+
element,
|
|
62
|
+
onStyleChange,
|
|
63
|
+
onStylesChange,
|
|
64
|
+
documentColorPalette = [],
|
|
65
|
+
glslShaderContext,
|
|
66
|
+
motionKeyframeContext,
|
|
67
|
+
breakpointOverrideContext,
|
|
68
|
+
}: {
|
|
69
|
+
element: ElementInfo;
|
|
70
|
+
onStyleChange: StyleChangeHandler;
|
|
71
|
+
onStylesChange?: StylesChangeHandler;
|
|
72
|
+
/** Document-wide palette (see `extractDocumentColorPalette`), already
|
|
73
|
+
* capped/ordered by frequency. Merged with the current selection's own
|
|
74
|
+
* colors below so a real, always-populated "Document colors" row is
|
|
75
|
+
* available even before any file content has been scanned. */
|
|
76
|
+
documentColorPalette?: string[];
|
|
77
|
+
/**
|
|
78
|
+
* Persistence context for the code-backed Shader paint type (GLSL source
|
|
79
|
+
* saved into the screen HTML). Threaded into the fill picker so its
|
|
80
|
+
* Shader tab opens the GlslShaderPanel.
|
|
81
|
+
*/
|
|
82
|
+
glslShaderContext?: GlslShaderPanelContext;
|
|
83
|
+
motionKeyframeContext?: MotionKeyframeFieldContext;
|
|
84
|
+
breakpointOverrideContext?: BreakpointOverrideFieldContext;
|
|
85
|
+
}) {
|
|
86
|
+
const t = useT();
|
|
87
|
+
const styles = element.computedStyles;
|
|
88
|
+
const isTextFillElement = isTextElement(element);
|
|
89
|
+
const fillProperty = isTextFillElement ? "color" : "backgroundColor";
|
|
90
|
+
const fillValue = isTextFillElement
|
|
91
|
+
? styles.color || ""
|
|
92
|
+
: styles.backgroundColor || "";
|
|
93
|
+
const backgroundLayers = isTextFillElement
|
|
94
|
+
? []
|
|
95
|
+
: splitCssLayers(styles.backgroundImage || "");
|
|
96
|
+
const backgroundSizeLayers = isTextFillElement
|
|
97
|
+
? []
|
|
98
|
+
: splitCssLayers(styles.backgroundSize || "");
|
|
99
|
+
const backgroundRepeatLayers = isTextFillElement
|
|
100
|
+
? []
|
|
101
|
+
: splitCssLayers(styles.backgroundRepeat || "");
|
|
102
|
+
const backgroundPositionLayers = isTextFillElement
|
|
103
|
+
? []
|
|
104
|
+
: splitCssLayers(styles.backgroundPosition || "");
|
|
105
|
+
const fillIsMixed =
|
|
106
|
+
isMixedValue(fillValue) ||
|
|
107
|
+
isMixedValue(styles.backgroundImage) ||
|
|
108
|
+
isMixedValue(styles.backgroundSize) ||
|
|
109
|
+
isMixedValue(styles.backgroundRepeat) ||
|
|
110
|
+
isMixedValue(styles.backgroundPosition);
|
|
111
|
+
const hasBackgroundLayer = !isTextFillElement && backgroundLayers.length > 0;
|
|
112
|
+
const hasVisibleFill =
|
|
113
|
+
isTextFillElement || colorHasVisibleAlpha(fillValue) || hasBackgroundLayer;
|
|
114
|
+
|
|
115
|
+
// Non-destructive fill hide: instead of stashing the pre-hide color in
|
|
116
|
+
// React state (lost on unmount — e.g. deselect then reselect the same
|
|
117
|
+
// element, since FillProperties only mounts while something is selected),
|
|
118
|
+
// zero the alpha channel while preserving the RGB channels in the
|
|
119
|
+
// persisted CSS itself: rgba(r,g,b,0) renders identically to fully
|
|
120
|
+
// transparent, but getComputedStyle round-trips the r/g/b losslessly (CSS
|
|
121
|
+
// color-list channels are real data, unlike comments — verified
|
|
122
|
+
// separately: computed style strips comments but keeps rgba() channels).
|
|
123
|
+
// Showing again just restores alpha to 1 using those same channels, so no
|
|
124
|
+
// stash is required and the hide survives reselect/reload.
|
|
125
|
+
const isHidden = !colorHasVisibleAlpha(fillValue);
|
|
126
|
+
const handleFillVisibilityToggle = () => {
|
|
127
|
+
const parsed = parseCssColor(fillValue);
|
|
128
|
+
if (isHidden) {
|
|
129
|
+
const restored = parsed
|
|
130
|
+
? rgbaToCss(withColorOpacity(parsed, 100))
|
|
131
|
+
: isTextFillElement
|
|
132
|
+
? "#000000"
|
|
133
|
+
: "#ffffff";
|
|
134
|
+
onStyleChange(fillProperty, restored);
|
|
135
|
+
} else if (parsed) {
|
|
136
|
+
onStyleChange(fillProperty, rgbaToCss(withColorOpacity(parsed, 0)));
|
|
137
|
+
} else {
|
|
138
|
+
// Value wasn't a parseable color (e.g. already the literal
|
|
139
|
+
// "transparent") — nothing to preserve, transparent is the best we
|
|
140
|
+
// can do.
|
|
141
|
+
onStyleChange(fillProperty, "transparent");
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// Reorder fill layers by dragging: permute all four index-aligned parallel
|
|
146
|
+
// arrays (image/size/repeat/position) together and commit them as one patch
|
|
147
|
+
// so stacking order changes in a single history step. Prefer onStylesChange
|
|
148
|
+
// (single call) when available; otherwise fall back to four sequential
|
|
149
|
+
// onStyleChange calls, matching the commit-path convention used elsewhere
|
|
150
|
+
// in this component (see commitStylePatch).
|
|
151
|
+
const reorderFillLayers = (from: number, to: number) => {
|
|
152
|
+
const reorder = (layers: string[]) => {
|
|
153
|
+
const next = [...layers];
|
|
154
|
+
const [moved] = next.splice(from, 1);
|
|
155
|
+
if (moved === undefined) return layers;
|
|
156
|
+
next.splice(to, 0, moved);
|
|
157
|
+
return next;
|
|
158
|
+
};
|
|
159
|
+
const patch = {
|
|
160
|
+
backgroundImage: joinCssLayers(reorder(backgroundLayers)),
|
|
161
|
+
backgroundSize: joinCssLayers(reorder(backgroundSizeLayers)),
|
|
162
|
+
backgroundRepeat: joinCssLayers(reorder(backgroundRepeatLayers)),
|
|
163
|
+
backgroundPosition: joinCssLayers(reorder(backgroundPositionLayers)),
|
|
164
|
+
};
|
|
165
|
+
if (onStylesChange) {
|
|
166
|
+
onStylesChange(patch);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
Object.entries(patch).forEach(([property, value]) =>
|
|
170
|
+
onStyleChange(property, value),
|
|
171
|
+
);
|
|
172
|
+
};
|
|
173
|
+
const fillDrag = useRowDragReorder(
|
|
174
|
+
backgroundLayers.length,
|
|
175
|
+
reorderFillLayers,
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
// Document colors: the selected element's own colors lead the row (so the
|
|
179
|
+
// colors most relevant to what's currently selected are immediately
|
|
180
|
+
// visible), followed by the real document-wide palette collected across
|
|
181
|
+
// every file in the design (see `extractDocumentColorPalette` /
|
|
182
|
+
// `documentColorPalette`, computed once in EditPanel and passed down —
|
|
183
|
+
// this is the actual "every distinct color used in the file" behavior;
|
|
184
|
+
// previously this row only ever showed the 4 lines below, mislabeled as
|
|
185
|
+
// document colors).
|
|
186
|
+
const selectionHexes = selectionColorValues(element)
|
|
187
|
+
.map((c) => {
|
|
188
|
+
const parsed = parseCssColor(c.value);
|
|
189
|
+
return parsed ? rgbaToHex(parsed) : null;
|
|
190
|
+
})
|
|
191
|
+
.filter((h): h is string => Boolean(h));
|
|
192
|
+
// Deduplicate (selectionColorValues already dedupes by raw CSS value, but
|
|
193
|
+
// hex normalisation may collapse additional entries e.g. rgb vs #hex; the
|
|
194
|
+
// document-wide palette is also normalized/deduped on its own, but may
|
|
195
|
+
// still repeat one of the selection's own colors).
|
|
196
|
+
const seenHex = new Set<string>();
|
|
197
|
+
const documentColors = [...selectionHexes, ...documentColorPalette].filter(
|
|
198
|
+
(h) => {
|
|
199
|
+
const key = h.toUpperCase();
|
|
200
|
+
if (seenHex.has(key)) return false;
|
|
201
|
+
seenHex.add(key);
|
|
202
|
+
return true;
|
|
203
|
+
},
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
return (
|
|
207
|
+
<PanelSection
|
|
208
|
+
title={t("editPanel.sections.fill")}
|
|
209
|
+
actions={
|
|
210
|
+
<>
|
|
211
|
+
{/* design color-styles affordance (grid icon) to the left of "+".
|
|
212
|
+
Not yet implemented — disabled with a "Coming soon" tooltip
|
|
213
|
+
rather than a dead, silently-no-op click. */}
|
|
214
|
+
<SectionIconButton
|
|
215
|
+
label={t("editPanel.labels.stylesComingSoon")}
|
|
216
|
+
disabled
|
|
217
|
+
>
|
|
218
|
+
<IconLayoutGrid className="size-3.5" />
|
|
219
|
+
</SectionIconButton>
|
|
220
|
+
<SectionIconButton
|
|
221
|
+
label={t("editPanel.labels.addLayer")}
|
|
222
|
+
onClick={() => {
|
|
223
|
+
if (fillIsMixed) {
|
|
224
|
+
commitStylePatch(
|
|
225
|
+
{
|
|
226
|
+
color: "#000000",
|
|
227
|
+
backgroundColor: "#ffffff",
|
|
228
|
+
backgroundImage: "none",
|
|
229
|
+
},
|
|
230
|
+
onStyleChange,
|
|
231
|
+
onStylesChange,
|
|
232
|
+
);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (isTextFillElement) {
|
|
236
|
+
onStyleChange(
|
|
237
|
+
"color",
|
|
238
|
+
cssColorOrFallback(styles.color, "#000000"),
|
|
239
|
+
);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (!colorHasVisibleAlpha(styles.backgroundColor)) {
|
|
243
|
+
onStyleChange(
|
|
244
|
+
"backgroundColor",
|
|
245
|
+
cssColorOrFallback(styles.backgroundColor, "#ffffff"),
|
|
246
|
+
);
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const current = compactCssValue(styles.backgroundImage, "");
|
|
250
|
+
const nextLayer = defaultGradientLayer(
|
|
251
|
+
"linear",
|
|
252
|
+
styles.backgroundColor || "#ffffff",
|
|
253
|
+
);
|
|
254
|
+
if (!current) {
|
|
255
|
+
onStyleChange("backgroundImage", nextLayer);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
// Prepending a layer without also prepending matching entries
|
|
259
|
+
// to the other three index-aligned parallel arrays
|
|
260
|
+
// (size/repeat/position) would shift every existing layer's
|
|
261
|
+
// index by one, silently re-pairing each of them with the
|
|
262
|
+
// *previous* layer's size/repeat/position (same class of bug
|
|
263
|
+
// as the removeLayer fix above). Commit a default entry for
|
|
264
|
+
// the new layer in all four arrays together, in one patch.
|
|
265
|
+
const patch = {
|
|
266
|
+
backgroundImage: `${nextLayer}, ${current}`,
|
|
267
|
+
backgroundSize: joinCssLayers([
|
|
268
|
+
"auto",
|
|
269
|
+
...backgroundSizeLayers,
|
|
270
|
+
]),
|
|
271
|
+
backgroundRepeat: joinCssLayers([
|
|
272
|
+
"no-repeat",
|
|
273
|
+
...backgroundRepeatLayers,
|
|
274
|
+
]),
|
|
275
|
+
backgroundPosition: joinCssLayers([
|
|
276
|
+
"0% 0%",
|
|
277
|
+
...backgroundPositionLayers,
|
|
278
|
+
]),
|
|
279
|
+
};
|
|
280
|
+
if (onStylesChange) {
|
|
281
|
+
onStylesChange(patch);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
Object.entries(patch).forEach(([property, value]) =>
|
|
285
|
+
onStyleChange(property, value),
|
|
286
|
+
);
|
|
287
|
+
}}
|
|
288
|
+
>
|
|
289
|
+
<IconPlus className="size-3.5" />
|
|
290
|
+
</SectionIconButton>
|
|
291
|
+
</>
|
|
292
|
+
}
|
|
293
|
+
>
|
|
294
|
+
{fillIsMixed ? (
|
|
295
|
+
<p className="px-1.5 py-2 !text-[11px] text-muted-foreground">
|
|
296
|
+
{
|
|
297
|
+
"Click + to replace mixed content" /* i18n-ignore figma mixed fill hint */
|
|
298
|
+
}
|
|
299
|
+
</p>
|
|
300
|
+
) : hasVisibleFill ? (
|
|
301
|
+
<div className="space-y-1.5">
|
|
302
|
+
{isTextFillElement || colorHasVisibleAlpha(fillValue) ? (
|
|
303
|
+
/* design row: [swatch+hex trigger (flex-1)] [eye] [remove] */
|
|
304
|
+
<div className="group flex items-center gap-1.5">
|
|
305
|
+
<div className="min-w-0 flex-1">
|
|
306
|
+
<ColorInput
|
|
307
|
+
label=""
|
|
308
|
+
value={fillValue}
|
|
309
|
+
onChange={(v, meta) => onStyleChange(fillProperty, v, meta)}
|
|
310
|
+
// Pass the real layer stack (not "") so that switching this
|
|
311
|
+
// swatch's paint type to gradient/image composes a new
|
|
312
|
+
// layer on top of any existing backgroundImage layers
|
|
313
|
+
// (rendered as their own rows below) instead of clobbering
|
|
314
|
+
// them — ColorInput derives its add/replace-layer logic
|
|
315
|
+
// from this prop.
|
|
316
|
+
backgroundImage={
|
|
317
|
+
isTextFillElement ? "" : styles.backgroundImage
|
|
318
|
+
}
|
|
319
|
+
blendMode={
|
|
320
|
+
isTextFillElement
|
|
321
|
+
? undefined
|
|
322
|
+
: styles.backgroundBlendMode || "normal"
|
|
323
|
+
}
|
|
324
|
+
onBlendModeChange={
|
|
325
|
+
isTextFillElement
|
|
326
|
+
? undefined
|
|
327
|
+
: (v) => onStyleChange("backgroundBlendMode", v)
|
|
328
|
+
}
|
|
329
|
+
// Text fill ("color") can't hold a gradient/image paint —
|
|
330
|
+
// there is no background-clip:text support here — so never
|
|
331
|
+
// offer layered fills for it; the picker's Gradient/Image
|
|
332
|
+
// tabs remain reachable as raw UI (it manages that tab
|
|
333
|
+
// selection as local state independent of these props) but
|
|
334
|
+
// ColorInput's setNext guard rejects non-color writes back
|
|
335
|
+
// into `color` when supportsLayeredFills is false. For any
|
|
336
|
+
// other element the base fill is a real backgroundImage
|
|
337
|
+
// layer stack, so wire the same layered-fill handlers the
|
|
338
|
+
// page background row uses (see PageProperties above).
|
|
339
|
+
supportsLayeredFills={!isTextFillElement}
|
|
340
|
+
onBackgroundImageChange={
|
|
341
|
+
isTextFillElement
|
|
342
|
+
? undefined
|
|
343
|
+
: (v) => onStyleChange("backgroundImage", v)
|
|
344
|
+
}
|
|
345
|
+
onImageFillChange={
|
|
346
|
+
isTextFillElement
|
|
347
|
+
? undefined
|
|
348
|
+
: (value) =>
|
|
349
|
+
commitStylePatch(
|
|
350
|
+
imageFillToBackgroundStyles(value),
|
|
351
|
+
onStyleChange,
|
|
352
|
+
onStylesChange,
|
|
353
|
+
)
|
|
354
|
+
}
|
|
355
|
+
documentColors={documentColors}
|
|
356
|
+
pickerKey={[
|
|
357
|
+
element.sourceId ??
|
|
358
|
+
element.id ??
|
|
359
|
+
element.selector ??
|
|
360
|
+
element.tagName,
|
|
361
|
+
fillProperty,
|
|
362
|
+
].join(":")}
|
|
363
|
+
// Code-backed GLSL Shader paint type — text fills can't
|
|
364
|
+
// host a shader canvas, so only container fills get it.
|
|
365
|
+
glslShaderContext={
|
|
366
|
+
isTextFillElement ? undefined : glslShaderContext
|
|
367
|
+
}
|
|
368
|
+
/>
|
|
369
|
+
</div>
|
|
370
|
+
<SectionIconButton
|
|
371
|
+
label={
|
|
372
|
+
isHidden
|
|
373
|
+
? t("editPanel.labels.showLayer")
|
|
374
|
+
: t("editPanel.labels.hideLayer")
|
|
375
|
+
}
|
|
376
|
+
onClick={handleFillVisibilityToggle}
|
|
377
|
+
activateOnPointerDown
|
|
378
|
+
>
|
|
379
|
+
{isHidden ? (
|
|
380
|
+
<IconEyeOff className="size-3.5" />
|
|
381
|
+
) : (
|
|
382
|
+
<IconEye className="size-3.5" />
|
|
383
|
+
)}
|
|
384
|
+
</SectionIconButton>
|
|
385
|
+
<SectionIconButton
|
|
386
|
+
label={t("editPanel.labels.removeLayer")}
|
|
387
|
+
onClick={() => {
|
|
388
|
+
if (isTextFillElement) {
|
|
389
|
+
onStyleChange(fillProperty, "transparent");
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
if (onStylesChange) {
|
|
393
|
+
onStylesChange({
|
|
394
|
+
backgroundColor: "transparent",
|
|
395
|
+
backgroundImage: "none",
|
|
396
|
+
});
|
|
397
|
+
} else {
|
|
398
|
+
onStyleChange(fillProperty, "transparent");
|
|
399
|
+
}
|
|
400
|
+
}}
|
|
401
|
+
>
|
|
402
|
+
<IconMinus className="size-3.5" />
|
|
403
|
+
</SectionIconButton>
|
|
404
|
+
{!isTextFillElement ? (
|
|
405
|
+
<FieldTrailer
|
|
406
|
+
element={element}
|
|
407
|
+
motionCssProperty="background-color"
|
|
408
|
+
motionKeyframeContext={motionKeyframeContext}
|
|
409
|
+
breakpointOverrideContext={breakpointOverrideContext}
|
|
410
|
+
hoverRevealClassName="opacity-0 group-hover:opacity-100"
|
|
411
|
+
/>
|
|
412
|
+
) : null}
|
|
413
|
+
</div>
|
|
414
|
+
) : null}
|
|
415
|
+
{!isTextFillElement
|
|
416
|
+
? backgroundLayers.map((layer, index) => {
|
|
417
|
+
const gradient = parseGradientLayer(layer);
|
|
418
|
+
// Hidden state lives in the real, persisted backgroundSize
|
|
419
|
+
// marker (see withLayerSizeMarker) rather than React state,
|
|
420
|
+
// so it survives deselect/reselect. Opacity still reflects
|
|
421
|
+
// the gradient's own stop opacities for display, but no
|
|
422
|
+
// longer drives hide/show — a layer can be a fully-opaque
|
|
423
|
+
// gradient and still be hidden via zero-size.
|
|
424
|
+
const hidden = isLayerHiddenBySize(backgroundSizeLayers[index]);
|
|
425
|
+
const opacity = gradient
|
|
426
|
+
? averageGradientOpacity(gradient.stops)
|
|
427
|
+
: 100;
|
|
428
|
+
const label = gradient
|
|
429
|
+
? `${gradientLabel(gradient.type)} ${index + 1}`
|
|
430
|
+
: `${"Image" /* i18n-ignore design inspector paint row */} ${
|
|
431
|
+
index + 1
|
|
432
|
+
}`;
|
|
433
|
+
const replaceLayer = (nextLayer: string) => {
|
|
434
|
+
const nextLayers = [...backgroundLayers];
|
|
435
|
+
nextLayers[index] = nextLayer;
|
|
436
|
+
onStyleChange("backgroundImage", joinCssLayers(nextLayers));
|
|
437
|
+
};
|
|
438
|
+
// Remove one fill layer by index. Mirrors reorderFillLayers:
|
|
439
|
+
// all four index-aligned parallel arrays (image/size/repeat/
|
|
440
|
+
// position) must be spliced together and committed as one
|
|
441
|
+
// patch (see removeFillLayerAtIndex), or the arrays fall out
|
|
442
|
+
// of alignment for every layer after the removed index (each
|
|
443
|
+
// remaining layer's size ends up paired with the next
|
|
444
|
+
// layer's repeat/position). The previous version only
|
|
445
|
+
// filtered backgroundImage and backgroundSize, silently
|
|
446
|
+
// leaving backgroundRepeat and backgroundPosition
|
|
447
|
+
// unfiltered/misaligned.
|
|
448
|
+
const removeLayer = () => {
|
|
449
|
+
const patch = removeFillLayerAtIndex(
|
|
450
|
+
{
|
|
451
|
+
backgroundImage: backgroundLayers,
|
|
452
|
+
backgroundSize: backgroundSizeLayers,
|
|
453
|
+
backgroundRepeat: backgroundRepeatLayers,
|
|
454
|
+
backgroundPosition: backgroundPositionLayers,
|
|
455
|
+
},
|
|
456
|
+
index,
|
|
457
|
+
);
|
|
458
|
+
if (onStylesChange) {
|
|
459
|
+
onStylesChange(patch);
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
Object.entries(patch).forEach(([property, value]) =>
|
|
463
|
+
onStyleChange(property, value),
|
|
464
|
+
);
|
|
465
|
+
};
|
|
466
|
+
const setLayerHidden = (nextHidden: boolean) => {
|
|
467
|
+
onStyleChange(
|
|
468
|
+
"backgroundSize",
|
|
469
|
+
withLayerSizeMarker(
|
|
470
|
+
backgroundSizeLayers,
|
|
471
|
+
backgroundLayers.length,
|
|
472
|
+
index,
|
|
473
|
+
nextHidden,
|
|
474
|
+
),
|
|
475
|
+
);
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
return (
|
|
479
|
+
/* design row: [grip] [swatch+label+opacity% trigger (flex-1)] [eye] [remove] */
|
|
480
|
+
<div
|
|
481
|
+
key={`${layer}-${index}`}
|
|
482
|
+
className="group relative flex items-center gap-1.5"
|
|
483
|
+
{...fillDrag.getRowProps(index)}
|
|
484
|
+
>
|
|
485
|
+
<RowDragHandle
|
|
486
|
+
label={t("editPanel.labels.reorderLayer")}
|
|
487
|
+
dropIndicator={
|
|
488
|
+
fillDrag.dragIndex != null &&
|
|
489
|
+
fillDrag.overIndex === index
|
|
490
|
+
? fillDrag.overIndex > fillDrag.dragIndex
|
|
491
|
+
? "after"
|
|
492
|
+
: "before"
|
|
493
|
+
: null
|
|
494
|
+
}
|
|
495
|
+
{...fillDrag.getHandleProps(index)}
|
|
496
|
+
/>
|
|
497
|
+
<Popover>
|
|
498
|
+
<PopoverTrigger asChild>
|
|
499
|
+
<button
|
|
500
|
+
type="button"
|
|
501
|
+
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)]"
|
|
502
|
+
>
|
|
503
|
+
<span
|
|
504
|
+
className="size-4 shrink-0 rounded-sm border border-[var(--design-editor-control-border)]"
|
|
505
|
+
style={swatchStyle(layer)}
|
|
506
|
+
/>
|
|
507
|
+
<span className="min-w-0 flex-1 truncate font-medium text-foreground">
|
|
508
|
+
{label}
|
|
509
|
+
</span>
|
|
510
|
+
<span className="shrink-0 tabular-nums text-muted-foreground">
|
|
511
|
+
{hidden ? 0 : opacity}%
|
|
512
|
+
</span>
|
|
513
|
+
</button>
|
|
514
|
+
</PopoverTrigger>
|
|
515
|
+
<PopoverContent
|
|
516
|
+
side="left"
|
|
517
|
+
align="start"
|
|
518
|
+
sideOffset={8}
|
|
519
|
+
className="w-80 p-0"
|
|
520
|
+
>
|
|
521
|
+
<DesignColorPicker
|
|
522
|
+
value={layer}
|
|
523
|
+
onPaintValueChange={replaceLayer}
|
|
524
|
+
onChange={(nextColor) => {
|
|
525
|
+
if (!gradient) return;
|
|
526
|
+
const firstStop = gradient.stops[0];
|
|
527
|
+
if (!firstStop) return;
|
|
528
|
+
replaceLayer(
|
|
529
|
+
buildGradientLayer(
|
|
530
|
+
gradient.type,
|
|
531
|
+
[
|
|
532
|
+
{ ...firstStop, color: nextColor },
|
|
533
|
+
...gradient.stops.slice(1),
|
|
534
|
+
],
|
|
535
|
+
gradient.prefix,
|
|
536
|
+
),
|
|
537
|
+
);
|
|
538
|
+
}}
|
|
539
|
+
paintType={gradient?.type ?? "image"}
|
|
540
|
+
backgroundImage={layer}
|
|
541
|
+
backgroundSize={backgroundSizeLayers[index]}
|
|
542
|
+
backgroundRepeat={backgroundRepeatLayers[index]}
|
|
543
|
+
backgroundPosition={backgroundPositionLayers[index]}
|
|
544
|
+
gradientType={gradient?.type}
|
|
545
|
+
onGradientTypeChange={(type) => {
|
|
546
|
+
if (!gradient) return;
|
|
547
|
+
replaceLayer(
|
|
548
|
+
buildGradientLayer(type, gradient.stops),
|
|
549
|
+
);
|
|
550
|
+
}}
|
|
551
|
+
fillRows={[
|
|
552
|
+
{
|
|
553
|
+
id: `layer-${index}`,
|
|
554
|
+
label,
|
|
555
|
+
value: layer,
|
|
556
|
+
type: gradient ? "gradient" : "image",
|
|
557
|
+
selected: true,
|
|
558
|
+
swatch: layer,
|
|
559
|
+
},
|
|
560
|
+
]}
|
|
561
|
+
selectedFillId={`layer-${index}`}
|
|
562
|
+
/>
|
|
563
|
+
</PopoverContent>
|
|
564
|
+
</Popover>
|
|
565
|
+
<SectionIconButton
|
|
566
|
+
label={
|
|
567
|
+
hidden
|
|
568
|
+
? t("editPanel.labels.showLayer")
|
|
569
|
+
: t("editPanel.labels.hideLayer")
|
|
570
|
+
}
|
|
571
|
+
onClick={() => setLayerHidden(!hidden)}
|
|
572
|
+
activateOnPointerDown
|
|
573
|
+
>
|
|
574
|
+
{hidden ? (
|
|
575
|
+
<IconEyeOff className="size-3.5" />
|
|
576
|
+
) : (
|
|
577
|
+
<IconEye className="size-3.5" />
|
|
578
|
+
)}
|
|
579
|
+
</SectionIconButton>
|
|
580
|
+
<SectionIconButton
|
|
581
|
+
label={t("editPanel.labels.removeLayer")}
|
|
582
|
+
onClick={removeLayer}
|
|
583
|
+
>
|
|
584
|
+
<IconMinus className="size-3.5" />
|
|
585
|
+
</SectionIconButton>
|
|
586
|
+
</div>
|
|
587
|
+
);
|
|
588
|
+
})
|
|
589
|
+
: null}
|
|
590
|
+
</div>
|
|
591
|
+
) : null}
|
|
592
|
+
</PanelSection>
|
|
593
|
+
);
|
|
594
|
+
}
|