@agent-native/core 0.181.0 → 0.181.1-nightly-20260916144018
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/templates/clips/app/components/player/create-account-dialog.tsx +2 -1
- package/corpus/templates/clips/changelog/2026-09-15-google-sign-up-now-opens-reliably-in-embedded-browsers.md +6 -0
- package/corpus/templates/content/actions/resolve-preview-document-draft.ts +320 -60
- package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +3 -1
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +349 -104
- package/corpus/templates/content/app/components/editor/DocumentReconcileRecovery.tsx +109 -0
- package/corpus/templates/content/app/components/editor/PageDraftRecovery.tsx +31 -153
- package/corpus/templates/content/app/components/editor/RecoveryComparison.tsx +230 -0
- package/corpus/templates/content/app/components/editor/VisualEditor.tsx +46 -19
- package/corpus/templates/content/app/components/editor/editor-draft-save.ts +13 -0
- package/corpus/templates/content/app/components/editor/useDocumentReconcileRecovery.ts +248 -0
- package/corpus/templates/content/app/components/sidebar/NotionButton.tsx +2 -1
- package/corpus/templates/content/app/i18n-data.ts +13 -0
- package/corpus/templates/content/changelog/2026-09-15-oauth-connections-now-open-reliably-in-embedded-browsers.md +6 -0
- package/corpus/templates/content/docs/solutions/2026-09-02-content-suggested-edits-parity-shape.md +84 -2
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +27 -7
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +45 -15
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +35 -8
- package/corpus/templates/design/app/components/design/design-canvas/element-payload.ts +14 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +18 -5
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-live-structure-edit.ts +9 -4
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-structure-change.ts +3 -0
- package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +7 -2
- package/corpus/templates/design/app/pages/design-editor/commands/visual-structure-change.ts +2 -0
- package/corpus/templates/design/app/pages/design-editor/pending-edits.ts +4 -0
- package/corpus/templates/design/app/pages/design-editor/pending-structure-verification.ts +197 -147
- package/corpus/templates/design/changelog/2026-09-16-design-editor-agent-chat-uses-shared-conversation-tabs-and-s.md +6 -0
- package/corpus/templates/design/changelog/2026-09-16-visual-edits-stay-applied-after-replacements.md +5 -0
- package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +2 -1
- package/corpus/templates/mail/changelog/2026-09-15-google-connections-now-open-reliably-in-embedded-browsers.md +6 -0
- package/dist/client/AgentPanel.d.ts +1 -1
- package/dist/client/AgentPanel.js +4 -4
- package/dist/client/auth/AuthPage.js +6 -1
- package/dist/client/oauth-popup.d.ts +7 -0
- package/dist/client/oauth-popup.js +14 -0
- package/dist/client/ocean/OceanBackground.d.ts +3 -1
- package/dist/client/ocean/OceanBackground.js +4 -3
- package/dist/client/resources/mcp-integration-catalog.js +7 -3
- package/dist/client/settings/useBuilderStatus.js +4 -3
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/app-roles.d.ts +8 -0
- package/dist/org/app-roles.js +7 -0
- package/dist/org/index.d.ts +1 -1
- package/dist/org/index.js +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/auth.js +3 -0
- package/dist/server/core-routes-plugin.d.ts +3 -0
- package/dist/server/core-routes-plugin.js +17 -0
- package/dist/server/realtime-token.d.ts +1 -1
- package/package.json +5 -4
|
@@ -103,6 +103,7 @@ import {
|
|
|
103
103
|
import {
|
|
104
104
|
isComputedStyleMap,
|
|
105
105
|
isElementInfoPayload,
|
|
106
|
+
parseRuntimeSnapshotHtml,
|
|
106
107
|
} from "./design-canvas/element-payload";
|
|
107
108
|
import {
|
|
108
109
|
embeddedContentOffsetCss,
|
|
@@ -698,6 +699,7 @@ interface DesignCanvasProps {
|
|
|
698
699
|
replacementSelector?: string;
|
|
699
700
|
replacementSourceId?: string;
|
|
700
701
|
replacementElementInfo?: ElementInfo;
|
|
702
|
+
replacementSnapshotHtml?: string;
|
|
701
703
|
},
|
|
702
704
|
) => boolean | "pending" | void;
|
|
703
705
|
onVisualDuplicateChange?: (
|
|
@@ -3298,24 +3300,34 @@ export function DesignCanvas({
|
|
|
3298
3300
|
allowedOrigins: canvasBridgeAllowedOrigins,
|
|
3299
3301
|
});
|
|
3300
3302
|
if (trustedRuntimeVerificationFrame) {
|
|
3303
|
+
if (e.data?.type === "agent-native:runtime-layer-snapshot-error") {
|
|
3304
|
+
onRuntimeStructureInsertRejected?.(
|
|
3305
|
+
e.data.payload?.reason === "snapshot-too-large"
|
|
3306
|
+
? "verification-snapshot-too-large"
|
|
3307
|
+
: "verification-snapshot-unavailable",
|
|
3308
|
+
);
|
|
3309
|
+
return;
|
|
3310
|
+
}
|
|
3301
3311
|
if (e.data?.type !== "agent-native:runtime-layer-snapshot") return;
|
|
3302
3312
|
const payload = e.data.payload;
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
html: payload.html,
|
|
3312
|
-
nodeCount: Math.max(0, Math.floor(payload.nodeCount)),
|
|
3313
|
-
documentId:
|
|
3314
|
-
typeof payload.documentId === "string"
|
|
3315
|
-
? payload.documentId
|
|
3316
|
-
: undefined,
|
|
3317
|
-
});
|
|
3313
|
+
const snapshot = parseRuntimeSnapshotHtml(payload?.html);
|
|
3314
|
+
if (!snapshot.ok || !Number.isFinite(payload?.nodeCount)) {
|
|
3315
|
+
onRuntimeStructureInsertRejected?.(
|
|
3316
|
+
snapshot.ok
|
|
3317
|
+
? "verification-snapshot-unavailable"
|
|
3318
|
+
: `verification-${snapshot.reason}`,
|
|
3319
|
+
);
|
|
3320
|
+
return;
|
|
3318
3321
|
}
|
|
3322
|
+
onRuntimeVerificationSnapshot?.({
|
|
3323
|
+
requestId: runtimeVerificationRequest.requestId,
|
|
3324
|
+
html: snapshot.html,
|
|
3325
|
+
nodeCount: Math.max(0, Math.floor(payload.nodeCount)),
|
|
3326
|
+
documentId:
|
|
3327
|
+
typeof payload.documentId === "string"
|
|
3328
|
+
? payload.documentId
|
|
3329
|
+
: undefined,
|
|
3330
|
+
});
|
|
3319
3331
|
return;
|
|
3320
3332
|
}
|
|
3321
3333
|
const lateReadyRecovery =
|
|
@@ -3593,6 +3605,21 @@ export function DesignCanvas({
|
|
|
3593
3605
|
});
|
|
3594
3606
|
const requestId =
|
|
3595
3607
|
typeof e.data.requestId === "string" ? e.data.requestId : undefined;
|
|
3608
|
+
const replacementSnapshot = replaced
|
|
3609
|
+
? parseRuntimeSnapshotHtml(e.data.replacementSnapshotHtml)
|
|
3610
|
+
: undefined;
|
|
3611
|
+
if (replacementSnapshot?.ok === false) {
|
|
3612
|
+
if (requestId) {
|
|
3613
|
+
iframeRef.current?.contentWindow?.postMessage(
|
|
3614
|
+
{ type: "visual-structure-ack", requestId, applied: false },
|
|
3615
|
+
"*",
|
|
3616
|
+
);
|
|
3617
|
+
}
|
|
3618
|
+
onRuntimeStructureInsertRejected?.(
|
|
3619
|
+
`replacement-${replacementSnapshot.reason}`,
|
|
3620
|
+
);
|
|
3621
|
+
return;
|
|
3622
|
+
}
|
|
3596
3623
|
const sourceId =
|
|
3597
3624
|
typeof e.data.sourceId === "string" ? e.data.sourceId : undefined;
|
|
3598
3625
|
const anchorSourceId =
|
|
@@ -3667,6 +3694,9 @@ export function DesignCanvas({
|
|
|
3667
3694
|
replaced: true as const,
|
|
3668
3695
|
replacementSelector: selector,
|
|
3669
3696
|
replacementSourceId: sourceId,
|
|
3697
|
+
replacementSnapshotHtml: replacementSnapshot?.ok
|
|
3698
|
+
? replacementSnapshot.html
|
|
3699
|
+
: undefined,
|
|
3670
3700
|
replacementElementInfo: isElementInfoPayload(e.data.payload)
|
|
3671
3701
|
? e.data.payload
|
|
3672
3702
|
: undefined,
|
|
@@ -1557,11 +1557,12 @@ declare var __INITIAL_SOURCE_HEAD__: string;
|
|
|
1557
1557
|
);
|
|
1558
1558
|
}
|
|
1559
1559
|
|
|
1560
|
-
function serializeRuntimeLayerSnapshot(
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1560
|
+
function serializeRuntimeLayerSnapshot(
|
|
1561
|
+
excludedRoot?: Element,
|
|
1562
|
+
):
|
|
1563
|
+
| { ok: true; html: string; nodeCount: number; documentId: string }
|
|
1564
|
+
| { ok: false; reason: "snapshot-unavailable" | "snapshot-too-large" } {
|
|
1565
|
+
if (!document.body) return { ok: false, reason: "snapshot-unavailable" };
|
|
1565
1566
|
// Keep this list export-focused and bounded. The runtime snapshot is also
|
|
1566
1567
|
// the hosted/cross-origin Design→Figma fallback: inlining the resolved
|
|
1567
1568
|
// paint/layout values lets the parent reconstruct the already-rendered
|
|
@@ -1666,7 +1667,10 @@ declare var __INITIAL_SOURCE_HEAD__: string;
|
|
|
1666
1667
|
) {
|
|
1667
1668
|
var sourceNode = sourceNodes[index];
|
|
1668
1669
|
var cloneNode = cloneNodes[index];
|
|
1669
|
-
if (
|
|
1670
|
+
if (
|
|
1671
|
+
excludedRoot?.contains(sourceNode) ||
|
|
1672
|
+
!isRuntimeLayerVisualNode(sourceNode)
|
|
1673
|
+
) {
|
|
1670
1674
|
cloneNode.setAttribute("data-an-runtime-layer-remove", "true");
|
|
1671
1675
|
continue;
|
|
1672
1676
|
}
|
|
@@ -1787,8 +1791,10 @@ declare var __INITIAL_SOURCE_HEAD__: string;
|
|
|
1787
1791
|
inlineSnapshotComputedStyle(document.body, cloneBody);
|
|
1788
1792
|
cloneBody.setAttribute("data-an-runtime-layer-snapshot", "true");
|
|
1789
1793
|
var html = "<!doctype html><html>" + cloneBody.outerHTML + "</html>"; // i18n-ignore serialized runtime-layer HTML payload, not visible UI copy
|
|
1790
|
-
if (html.length > 2_000_000)
|
|
1794
|
+
if (html.length > 2_000_000)
|
|
1795
|
+
return { ok: false, reason: "snapshot-too-large" };
|
|
1791
1796
|
return {
|
|
1797
|
+
ok: true,
|
|
1792
1798
|
html: html,
|
|
1793
1799
|
nodeCount: nodeCount,
|
|
1794
1800
|
documentId: runtimeDocumentId,
|
|
@@ -1805,7 +1811,17 @@ declare var __INITIAL_SOURCE_HEAD__: string;
|
|
|
1805
1811
|
runtimeLayerSnapshotTimer = null;
|
|
1806
1812
|
runtimeLayerSnapshotMaxTimer = null;
|
|
1807
1813
|
var snapshot = serializeRuntimeLayerSnapshot();
|
|
1808
|
-
if (!snapshot
|
|
1814
|
+
if (!snapshot.ok) {
|
|
1815
|
+
(window.parent as Window).postMessage(
|
|
1816
|
+
{
|
|
1817
|
+
type: "agent-native:runtime-layer-snapshot-error",
|
|
1818
|
+
payload: snapshot,
|
|
1819
|
+
},
|
|
1820
|
+
"*",
|
|
1821
|
+
);
|
|
1822
|
+
return;
|
|
1823
|
+
}
|
|
1824
|
+
if (snapshot.html === lastRuntimeLayerSnapshotHtml) return;
|
|
1809
1825
|
lastRuntimeLayerSnapshotHtml = snapshot.html;
|
|
1810
1826
|
(window.parent as Window).postMessage(
|
|
1811
1827
|
{
|
|
@@ -13603,6 +13619,7 @@ declare var __INITIAL_SOURCE_HEAD__: string;
|
|
|
13603
13619
|
origin,
|
|
13604
13620
|
insertedHtml?,
|
|
13605
13621
|
replaced?,
|
|
13622
|
+
replacementSnapshotHtml?: string,
|
|
13606
13623
|
) {
|
|
13607
13624
|
if (!el || !target || !target.anchor) return;
|
|
13608
13625
|
dndLog("post:structure-change", {
|
|
@@ -13636,6 +13653,7 @@ declare var __INITIAL_SOURCE_HEAD__: string;
|
|
|
13636
13653
|
insertedHtml:
|
|
13637
13654
|
typeof insertedHtml === "string" ? insertedHtml : undefined,
|
|
13638
13655
|
replaced: replaced === true ? true : undefined,
|
|
13656
|
+
replacementSnapshotHtml: replacementSnapshotHtml,
|
|
13639
13657
|
sourceRect: rectInfoForElement(el),
|
|
13640
13658
|
anchorRect: rectInfoForElement(target.anchor),
|
|
13641
13659
|
payload: getElementInfo(el),
|
|
@@ -20146,6 +20164,14 @@ declare var __INITIAL_SOURCE_HEAD__: string;
|
|
|
20146
20164
|
}
|
|
20147
20165
|
var replaceNextSibling = insertAnchor.nextSibling;
|
|
20148
20166
|
replaceParent.insertBefore(parsedInsertEl, insertAnchor);
|
|
20167
|
+
// Capture while the original still supplies its selector/provenance,
|
|
20168
|
+
// and reject before publishing a pending operation if proof is unavailable.
|
|
20169
|
+
var replacementSnapshot = serializeRuntimeLayerSnapshot(insertAnchor);
|
|
20170
|
+
if (!replacementSnapshot.ok) {
|
|
20171
|
+
parsedInsertEl.remove();
|
|
20172
|
+
rejectInsert("replacement-" + replacementSnapshot.reason);
|
|
20173
|
+
return;
|
|
20174
|
+
}
|
|
20149
20175
|
selectedEl = parsedInsertEl;
|
|
20150
20176
|
positionOverlay(selectionOverlay, selectedEl);
|
|
20151
20177
|
refreshOverlays();
|
|
@@ -20160,6 +20186,7 @@ declare var __INITIAL_SOURCE_HEAD__: string;
|
|
|
20160
20186
|
},
|
|
20161
20187
|
parsedInsertEl.outerHTML,
|
|
20162
20188
|
true,
|
|
20189
|
+
replacementSnapshot.html,
|
|
20163
20190
|
);
|
|
20164
20191
|
replaceParent.removeChild(insertAnchor);
|
|
20165
20192
|
refreshOverlays();
|
|
@@ -36,3 +36,17 @@ export function isElementInfoPayload(value: unknown): value is ElementInfo {
|
|
|
36
36
|
typeof value.isFlexContainer === "boolean"
|
|
37
37
|
);
|
|
38
38
|
}
|
|
39
|
+
|
|
40
|
+
export function parseRuntimeSnapshotHtml(
|
|
41
|
+
value: unknown,
|
|
42
|
+
):
|
|
43
|
+
| { ok: true; html: string }
|
|
44
|
+
| { ok: false; reason: "snapshot-unavailable" | "snapshot-too-large" } {
|
|
45
|
+
if (typeof value !== "string" || !value) {
|
|
46
|
+
return { ok: false, reason: "snapshot-unavailable" };
|
|
47
|
+
}
|
|
48
|
+
if (value.length > 2_000_000) {
|
|
49
|
+
return { ok: false, reason: "snapshot-too-large" };
|
|
50
|
+
}
|
|
51
|
+
return { ok: true, html: value };
|
|
52
|
+
}
|
|
@@ -1721,7 +1721,7 @@ function DesignEditor() {
|
|
|
1721
1721
|
const initialUrlSelectionHydratedForIdRef = useRef<string | null>(null);
|
|
1722
1722
|
// Figma's 56px workspace rail (plus its 1px divider) and 280px Layers/Pages
|
|
1723
1723
|
// pane place the content divider at x=337. Keep that total while honoring
|
|
1724
|
-
// resizable 220–420px content range.
|
|
1724
|
+
// the resizable 220–420px content range, with 320px reserved for Agent chat.
|
|
1725
1725
|
const [leftSidebarWidth, setLeftSidebarWidth] = useState(280);
|
|
1726
1726
|
const [rightSidebarWidth, setRightSidebarWidth] = useState(240);
|
|
1727
1727
|
// Cmd/Ctrl+\ hides the sidebars while leaving the bottom tools available.
|
|
@@ -7828,6 +7828,7 @@ function DesignEditor() {
|
|
|
7828
7828
|
replacementSelector?: string;
|
|
7829
7829
|
replacementSourceId?: string;
|
|
7830
7830
|
replacementElementInfo?: ElementInfo;
|
|
7831
|
+
replacementSnapshotHtml?: string;
|
|
7831
7832
|
/** This change DELETED the subject; it has no anchor. */
|
|
7832
7833
|
removed?: true;
|
|
7833
7834
|
},
|
|
@@ -12092,6 +12093,7 @@ function DesignEditor() {
|
|
|
12092
12093
|
replacementSelector?: string;
|
|
12093
12094
|
replacementSourceId?: string;
|
|
12094
12095
|
replacementElementInfo?: ElementInfo;
|
|
12096
|
+
replacementSnapshotHtml?: string;
|
|
12095
12097
|
},
|
|
12096
12098
|
) =>
|
|
12097
12099
|
runVisualStructureChange(
|
|
@@ -12334,6 +12336,7 @@ function DesignEditor() {
|
|
|
12334
12336
|
replacementSelector?: string;
|
|
12335
12337
|
replacementSourceId?: string;
|
|
12336
12338
|
replacementElementInfo?: ElementInfo;
|
|
12339
|
+
replacementSnapshotHtml?: string;
|
|
12337
12340
|
},
|
|
12338
12341
|
) =>
|
|
12339
12342
|
runScreenVisualStructureChange(
|
|
@@ -14461,6 +14464,11 @@ function DesignEditor() {
|
|
|
14461
14464
|
|
|
14462
14465
|
const handleRuntimeStructureInsertRejected = useCallback(
|
|
14463
14466
|
(reason: string) => {
|
|
14467
|
+
if (reason.startsWith("verification-")) {
|
|
14468
|
+
cancelPendingStructureVerification("conflict");
|
|
14469
|
+
toast.error(t("designEditor.pendingVisualStyles.conflictToast"));
|
|
14470
|
+
return;
|
|
14471
|
+
}
|
|
14464
14472
|
// Never swallow this: a rejected insert leaves nothing on screen and
|
|
14465
14473
|
// nothing in the pending list, so a silent return is indistinguishable
|
|
14466
14474
|
// from the drop never having happened.
|
|
@@ -14469,7 +14477,7 @@ function DesignEditor() {
|
|
|
14469
14477
|
}
|
|
14470
14478
|
toast.error(t("designEditor.toasts.layerMoveFailed"), { duration: 4000 });
|
|
14471
14479
|
},
|
|
14472
|
-
[t],
|
|
14480
|
+
[cancelPendingStructureVerification, t],
|
|
14473
14481
|
);
|
|
14474
14482
|
|
|
14475
14483
|
const handleCutSelection = useCallback(async () => {
|
|
@@ -23398,7 +23406,10 @@ function DesignEditor() {
|
|
|
23398
23406
|
const leftContentWidth =
|
|
23399
23407
|
activeLeftPanel === "code"
|
|
23400
23408
|
? Math.max(leftSidebarWidth, 640)
|
|
23401
|
-
: Math.max(
|
|
23409
|
+
: Math.max(
|
|
23410
|
+
Math.min(leftSidebarWidth, 420),
|
|
23411
|
+
activeLeftPanel === "agent" ? 320 : 220,
|
|
23412
|
+
);
|
|
23402
23413
|
const leftSidebarVisible = !hostOwnsChrome && !uiHidden && !minimalUi;
|
|
23403
23414
|
// These focused surfaces need a clear viewport beside the absolute rail.
|
|
23404
23415
|
const leftChromeOverlayInset = leftSidebarVisible
|
|
@@ -23712,7 +23723,7 @@ function DesignEditor() {
|
|
|
23712
23723
|
<div
|
|
23713
23724
|
data-design-agent-panel
|
|
23714
23725
|
className={cn(
|
|
23715
|
-
"min-h-0 flex-1 flex-col overflow-hidden",
|
|
23726
|
+
"min-h-0 min-w-0 flex-1 flex-col overflow-hidden",
|
|
23716
23727
|
activeLeftPanel === "agent" ? "flex" : "hidden",
|
|
23717
23728
|
)}
|
|
23718
23729
|
>
|
|
@@ -23721,7 +23732,9 @@ function DesignEditor() {
|
|
|
23721
23732
|
) : canEditDesign ? (
|
|
23722
23733
|
<AgentChatSurface
|
|
23723
23734
|
mode="panel"
|
|
23724
|
-
className="min-h-0 flex-1 border-0 bg-transparent shadow-none"
|
|
23735
|
+
className="min-h-0 min-w-0 flex-1 border-0 bg-transparent shadow-none"
|
|
23736
|
+
chatOnly={true}
|
|
23737
|
+
onCollapse={() => setActiveLeftPanel(null)}
|
|
23725
23738
|
storageKey={DESIGN_CHAT_STORAGE_KEY}
|
|
23726
23739
|
emptyStateText={t("chat.emptyState")}
|
|
23727
23740
|
suggestions={designAgentSuggestions}
|
|
@@ -23,7 +23,10 @@ import {
|
|
|
23
23
|
reactSourceAnchorForPendingEdit,
|
|
24
24
|
runtimeStructureNodeSignature,
|
|
25
25
|
} from "@/pages/design-editor/pending-edits";
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
isPendingStructureDropNoOp,
|
|
28
|
+
runtimeStructureSnapshotSignature,
|
|
29
|
+
} from "@/pages/design-editor/pending-structure-verification";
|
|
27
30
|
import type { DesignFile } from "@/pages/design-editor/types";
|
|
28
31
|
|
|
29
32
|
export interface RecordPendingLiveStructureEditArgs {
|
|
@@ -86,6 +89,7 @@ export function runRecordPendingLiveStructureEdit(
|
|
|
86
89
|
replacementSelector?: string;
|
|
87
90
|
replacementSourceId?: string;
|
|
88
91
|
replacementElementInfo?: ElementInfo;
|
|
92
|
+
replacementSnapshotHtml?: string;
|
|
89
93
|
/** This change DELETED the subject; it has no anchor. */
|
|
90
94
|
removed?: true;
|
|
91
95
|
},
|
|
@@ -108,9 +112,7 @@ export function runRecordPendingLiveStructureEdit(
|
|
|
108
112
|
const subjectInfo = details?.replaced
|
|
109
113
|
? details.anchorElementInfo
|
|
110
114
|
: elementInfo;
|
|
111
|
-
const subjectSourceId = details?.
|
|
112
|
-
? details.anchorSourceId
|
|
113
|
-
: (details?.sourceId ?? elementInfo?.sourceId);
|
|
115
|
+
const subjectSourceId = details?.sourceId ?? subjectInfo?.sourceId;
|
|
114
116
|
const nextEdit: PendingLiveStructureEdit = {
|
|
115
117
|
kind: "structure",
|
|
116
118
|
screenId,
|
|
@@ -164,6 +166,9 @@ export function runRecordPendingLiveStructureEdit(
|
|
|
164
166
|
replaced: true as const,
|
|
165
167
|
replacementSelector: details.replacementSelector,
|
|
166
168
|
replacementSourceId: details.replacementSourceId,
|
|
169
|
+
replacementSnapshotSignature: details.replacementSnapshotHtml
|
|
170
|
+
? runtimeStructureSnapshotSignature(details.replacementSnapshotHtml)
|
|
171
|
+
: undefined,
|
|
167
172
|
}
|
|
168
173
|
: {}),
|
|
169
174
|
...(details?.removed ? { removed: true as const } : {}),
|
package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-structure-change.ts
CHANGED
|
@@ -48,6 +48,7 @@ export interface ScreenVisualStructureChangeArgs {
|
|
|
48
48
|
replacementSelector?: string;
|
|
49
49
|
replacementSourceId?: string;
|
|
50
50
|
replacementElementInfo?: ElementInfo;
|
|
51
|
+
replacementSnapshotHtml?: string;
|
|
51
52
|
},
|
|
52
53
|
) => boolean | "pending";
|
|
53
54
|
overviewScreens: OverviewScreen[];
|
|
@@ -71,6 +72,7 @@ export interface ScreenVisualStructureChangeArgs {
|
|
|
71
72
|
replacementSelector?: string;
|
|
72
73
|
replacementSourceId?: string;
|
|
73
74
|
replacementElementInfo?: ElementInfo;
|
|
75
|
+
replacementSnapshotHtml?: string;
|
|
74
76
|
removed?: true;
|
|
75
77
|
},
|
|
76
78
|
) => void;
|
|
@@ -117,6 +119,7 @@ export function runScreenVisualStructureChange(
|
|
|
117
119
|
replacementSelector?: string;
|
|
118
120
|
replacementSourceId?: string;
|
|
119
121
|
replacementElementInfo?: ElementInfo;
|
|
122
|
+
replacementSnapshotHtml?: string;
|
|
120
123
|
},
|
|
121
124
|
) {
|
|
122
125
|
if (screenId === activeFile?.id) {
|
|
@@ -35,14 +35,19 @@ export function runStartSidebarResize(
|
|
|
35
35
|
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
36
36
|
const startX = event.clientX;
|
|
37
37
|
const codePanelOpen = side === "left" && activeLeftPanel === "code";
|
|
38
|
+
const leftPanelMinWidth = codePanelOpen
|
|
39
|
+
? 520
|
|
40
|
+
: activeLeftPanel === "agent"
|
|
41
|
+
? 320
|
|
42
|
+
: 220;
|
|
38
43
|
const startWidth =
|
|
39
44
|
side === "left"
|
|
40
45
|
? codePanelOpen
|
|
41
46
|
? Math.max(leftSidebarWidth, 640)
|
|
42
|
-
: Math.min(leftSidebarWidth, 420)
|
|
47
|
+
: Math.max(Math.min(leftSidebarWidth, 420), leftPanelMinWidth)
|
|
43
48
|
: rightSidebarWidth;
|
|
44
49
|
const setWidth = side === "left" ? setLeftSidebarWidth : setRightSidebarWidth;
|
|
45
|
-
const minWidth = side === "left" ?
|
|
50
|
+
const minWidth = side === "left" ? leftPanelMinWidth : 240;
|
|
46
51
|
const maxWidth = side === "left" ? (codePanelOpen ? 1100 : 420) : 390;
|
|
47
52
|
const target =
|
|
48
53
|
side === "left"
|
|
@@ -73,6 +73,7 @@ export interface VisualStructureChangeArgs {
|
|
|
73
73
|
replacementSelector?: string;
|
|
74
74
|
replacementSourceId?: string;
|
|
75
75
|
replacementElementInfo?: ElementInfo;
|
|
76
|
+
replacementSnapshotHtml?: string;
|
|
76
77
|
removed?: true;
|
|
77
78
|
},
|
|
78
79
|
) => void;
|
|
@@ -114,6 +115,7 @@ export function runVisualStructureChange(
|
|
|
114
115
|
replacementSelector?: string;
|
|
115
116
|
replacementSourceId?: string;
|
|
116
117
|
replacementElementInfo?: ElementInfo;
|
|
118
|
+
replacementSnapshotHtml?: string;
|
|
117
119
|
},
|
|
118
120
|
) {
|
|
119
121
|
dndHostLog("persist:begin", {
|
|
@@ -326,6 +326,10 @@ export interface PendingLiveStructureEdit {
|
|
|
326
326
|
replacementSelector?: string;
|
|
327
327
|
replacementSourceId?: string | null;
|
|
328
328
|
replacementSignature?: RuntimeStructureNodeSignature;
|
|
329
|
+
/** Expected visual tree captured by the bridge while it still owns the
|
|
330
|
+
* original DOM element. Runtime ids and computed styles are excluded.
|
|
331
|
+
* Missing evidence or later context changes cannot prove replacement. */
|
|
332
|
+
replacementSnapshotSignature?: string;
|
|
329
333
|
/**
|
|
330
334
|
* This edit DELETED the subject from the running app. A removal has no
|
|
331
335
|
* anchor — `anchorSelector`/`placement` carry no meaning for it — so every
|