feat(canvas): frame-based layer separation UI

Render and manage the separated layers produced by the edit-elements
action as a manual-frame container with attached image and text
children.

- canvasNodeOps: frame container/child helpers, render ordering,
  auto-attach nodes to containing frames, and layer reordering
- CanvasWorkspace wires frame-aware selection, drag, resize, hide/lock,
  and layer reorder through the new ops
- CanvasPanels: expandable layer tree with rename/reorder
- designGateway.submitGeneratorTask + GeneratorTaskSubmitResponse and
  bbox/generator_name artifact metadata in the domain
- ArtboardPreview shows a working state for generating frame layers
- i18n: expandLayer / renameLayer / layerTitlePlaceholder; styles

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-09 12:27:00 +08:00
parent 039d166972
commit a1503a1687
9 changed files with 613 additions and 94 deletions
+47 -6
View File
@@ -2616,9 +2616,10 @@ button:disabled {
}
.layer-row {
position: relative;
height: 46px;
display: grid;
grid-template-columns: 32px minmax(0, 1fr) 26px 26px;
grid-template-columns: 18px 30px minmax(0, 1fr) 24px 24px;
align-items: center;
gap: 7px;
padding: 4px 6px;
@@ -2627,6 +2628,18 @@ button:disabled {
cursor: default;
}
.layer-row.is-dragging {
opacity: 0.42;
}
.layer-row.drop-before {
box-shadow: inset 0 2px 0 #2f80ff;
}
.layer-row.drop-after {
box-shadow: inset 0 -2px 0 #2f80ff;
}
.layer-row:hover,
.layer-row.selected {
background: #edf0f4;
@@ -2638,12 +2651,8 @@ button:disabled {
font-weight: 760;
}
.layer-row.boolean-layer-group-row {
grid-template-columns: 14px 32px minmax(0, 1fr) 26px 26px;
}
.layer-row.nested {
grid-template-columns: 20px 28px minmax(0, 1fr) 24px 24px;
grid-template-columns: 20px 18px 28px minmax(0, 1fr) 24px 24px;
padding-left: 12px;
}
@@ -2654,6 +2663,38 @@ button:disabled {
content: "";
}
.layer-disclosure,
.layer-drag-handle {
width: 18px;
height: 26px;
display: grid;
place-items: center;
border: 0;
color: #8a92a0;
background: transparent;
}
.layer-disclosure {
border-radius: 6px;
}
.layer-disclosure:not(:disabled):hover {
color: #20242b;
background: #e4e8ee;
}
.layer-disclosure:disabled {
opacity: 0.32;
}
.layer-drag-handle {
opacity: 0.42;
}
.layer-row:hover .layer-drag-handle {
opacity: 0.8;
}
.layer-row.is-hidden {
opacity: 0.58;
}