nudge-ui 0.2.0 → 0.2.1
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/bin/nudge-ui.mjs +3 -1
- package/dist/cli/agentCommand.d.ts +8 -0
- package/dist/cli/agentCommand.js +59 -0
- package/dist/client.mjs +872 -12
- package/dist/hosts/astro/astroRuntimeConfig.js +1 -1
- package/dist/hosts/astro/clientTransport.js +60 -11
- package/dist/hosts/next/sidecar.d.ts +4 -0
- package/dist/hosts/next/sidecar.js +49 -6
- package/dist/hosts/next/wrapper.js +30 -2
- package/dist/hosts/projectBridge.d.ts +20 -0
- package/dist/hosts/projectBridge.js +97 -0
- package/dist/hosts/static/cli.d.ts +1 -1
- package/dist/hosts/static/cli.js +6 -1
- package/dist/hosts/static/manifest.d.ts +1 -1
- package/dist/hosts/static/manifest.js +1 -1
- package/dist/hosts/static/server.js +44 -3
- package/dist/hosts/vite/vite.d.ts +5 -1
- package/dist/hosts/vite/vite.js +78 -14
- package/dist/inspector/agent/McpConnectionDialog.d.ts +2 -2
- package/dist/inspector/agent/McpConnectionDialog.js +11 -35
- package/dist/inspector/agent/client.d.ts +10 -3
- package/dist/inspector/agent/client.js +80 -9
- package/dist/inspector/agent/connectionStatus.js +3 -3
- package/dist/inspector/agent/httpTransport.d.ts +2 -0
- package/dist/inspector/agent/httpTransport.js +37 -17
- package/dist/inspector/agent/protocol.d.ts +8 -3
- package/dist/inspector/agent/protocol.js +1 -1
- package/dist/inspector/agent/verification.d.ts +1 -1
- package/dist/inspector/agent/verification.js +69 -12
- package/dist/inspector/canvas/CanvasCard.d.ts +5 -3
- package/dist/inspector/canvas/CanvasCard.js +181 -91
- package/dist/inspector/canvas/CanvasElementOverlay.js +246 -52
- package/dist/inspector/canvas/CanvasToolbar.d.ts +12 -0
- package/dist/inspector/canvas/CanvasToolbar.js +24 -0
- package/dist/inspector/canvas/CanvasWorkspace.d.ts +4 -1
- package/dist/inspector/canvas/CanvasWorkspace.js +392 -73
- package/dist/inspector/canvas/activeCanvasDocument.d.ts +5 -0
- package/dist/inspector/canvas/activeCanvasDocument.js +23 -0
- package/dist/inspector/canvas/canvasResize.d.ts +30 -0
- package/dist/inspector/canvas/canvasResize.js +52 -0
- package/dist/inspector/canvas/canvasStore.d.ts +30 -6
- package/dist/inspector/canvas/canvasStore.js +128 -61
- package/dist/inspector/canvas/frameProtocol.d.ts +69 -5
- package/dist/inspector/canvas/frameProtocol.js +56 -2
- package/dist/inspector/canvas/keyboardShortcuts.d.ts +3 -0
- package/dist/inspector/canvas/keyboardShortcuts.js +14 -0
- package/dist/inspector/canvas/projection.d.ts +7 -0
- package/dist/inspector/canvas/projection.js +118 -25
- package/dist/inspector/canvas/rendererBootstrap.js +29 -29
- package/dist/inspector/canvas/rendererElementSelector.js +341 -30
- package/dist/inspector/canvas/rendererMessageRouter.d.ts +11 -0
- package/dist/inspector/canvas/rendererMessageRouter.js +43 -0
- package/dist/inspector/canvas/rendererSelectionProxy.js +6 -2
- package/dist/inspector/canvas/sessionStore.d.ts +1 -0
- package/dist/inspector/canvas/sessionStore.js +12 -4
- package/dist/inspector/canvas/staleChangeDetector.js +16 -14
- package/dist/inspector/changes/changesLog.js +31 -1
- package/dist/inspector/changes/managedStyleProjection.d.ts +1 -1
- package/dist/inspector/changes/managedStyleProjection.js +3 -3
- package/dist/inspector/changes/structuralTypes.d.ts +4 -0
- package/dist/inspector/clientManifest.d.ts +5 -0
- package/dist/inspector/clientManifest.js +11 -0
- package/dist/inspector/componentSemantics/adapterRegistry.js +4 -3
- package/dist/inspector/componentSemantics/runtimeBridge.d.ts +2 -2
- package/dist/inspector/componentSemantics/runtimeBridge.js +16 -3
- package/dist/inspector/index.d.ts +2 -0
- package/dist/inspector/index.js +74 -24
- package/dist/inspector/inline-text/inlineTextDiagnostics.d.ts +10 -0
- package/dist/inspector/inline-text/inlineTextDiagnostics.js +65 -0
- package/dist/inspector/inline-text/inlineTextEditor.d.ts +3 -5
- package/dist/inspector/inline-text/inlineTextEditor.js +74 -206
- package/dist/inspector/inline-text/inlineTextFeedback.d.ts +5 -0
- package/dist/inspector/inline-text/inlineTextFeedback.js +27 -0
- package/dist/inspector/inline-text/inlineTextLifecycle.js +2 -0
- package/dist/inspector/inline-text/textEditChange.d.ts +14 -0
- package/dist/inspector/inline-text/textEditChange.js +165 -0
- package/dist/inspector/inspection/selectionProperty.d.ts +1 -0
- package/dist/inspector/inspection/selectionProperty.js +1 -0
- package/dist/inspector/overlay/selectedGeometry.js +21 -2
- package/dist/inspector/overlay/spacingGestures.d.ts +45 -0
- package/dist/inspector/overlay/spacingGestures.js +353 -0
- package/dist/inspector/overlay/structuralGestures.d.ts +2 -2
- package/dist/inspector/overlay/structuralGestures.js +12 -10
- package/dist/inspector/projection/managedStylesheet.js +4 -1
- package/dist/inspector/projection/renderedInstance.d.ts +2 -0
- package/dist/inspector/projection/renderedInstance.js +5 -1
- package/dist/inspector/projection/structuralProjection.d.ts +2 -0
- package/dist/inspector/projection/structuralProjection.js +85 -1
- package/dist/inspector/projection/structuralProjectionBoundary.js +17 -1
- package/dist/inspector/projection/textProjection.d.ts +2 -0
- package/dist/inspector/projection/textProjection.js +10 -4
- package/dist/inspector/prompt/clipboardHandoff.d.ts +1 -1
- package/dist/inspector/prompt/clipboardHandoff.js +3 -3
- package/dist/inspector/prompt/generatePrompt.d.ts +2 -1
- package/dist/inspector/prompt/generatePrompt.js +19 -2
- package/dist/inspector/runtime/editorShell.d.ts +2 -0
- package/dist/inspector/runtime/editorShell.js +4 -0
- package/dist/inspector/runtime/runtimeConfig.d.ts +4 -0
- package/dist/inspector/runtime/runtimeConfig.js +4 -0
- package/dist/inspector/selection/selectionStore.js +2 -0
- package/dist/inspector/settings/SettingsDialog.js +10 -0
- package/dist/inspector/shell/AppShell.js +5 -1
- package/dist/inspector/shell/ChangesLog.js +8 -4
- package/dist/inspector/shell/CopyPromptButton.js +95 -19
- package/dist/inspector/shell/EmptyState.js +1 -1
- package/dist/inspector/shell/InspectorShell.d.ts +0 -1
- package/dist/inspector/shell/InspectorShell.js +37 -38
- package/dist/inspector/shell/PeekOriginalButton.d.ts +7 -0
- package/dist/inspector/shell/PeekOriginalButton.js +57 -0
- package/dist/inspector/shell/PeekOriginalIcon.d.ts +7 -0
- package/dist/inspector/shell/PeekOriginalIcon.js +9 -0
- package/dist/inspector/shell/originalPreview.d.ts +9 -0
- package/dist/inspector/shell/originalPreview.js +61 -0
- package/dist/inspector/shell/shortcuts.d.ts +3 -0
- package/dist/inspector/shell/shortcuts.js +15 -0
- package/dist/inspector/sketch/SketchChanges.d.ts +2 -0
- package/dist/inspector/sketch/SketchChanges.js +72 -0
- package/dist/inspector/sketch/SketchEditor.d.ts +21 -0
- package/dist/inspector/sketch/SketchEditor.js +402 -0
- package/dist/inspector/sketch/SketchEntryButton.d.ts +4 -0
- package/dist/inspector/sketch/SketchEntryButton.js +11 -0
- package/dist/inspector/sketch/SketchFrameOverlay.d.ts +11 -0
- package/dist/inspector/sketch/SketchFrameOverlay.js +119 -0
- package/dist/inspector/sketch/SketchLayersPanel.d.ts +2 -0
- package/dist/inspector/sketch/SketchLayersPanel.js +63 -0
- package/dist/inspector/sketch/SketchOverlay.d.ts +19 -0
- package/dist/inspector/sketch/SketchOverlay.js +420 -0
- package/dist/inspector/sketch/SketchPromptPanel.d.ts +15 -0
- package/dist/inspector/sketch/SketchPromptPanel.js +18 -0
- package/dist/inspector/sketch/SketchWorkspace.d.ts +13 -0
- package/dist/inspector/sketch/SketchWorkspace.js +152 -0
- package/dist/inspector/sketch/capture.d.ts +55 -0
- package/dist/inspector/sketch/capture.js +350 -0
- package/dist/inspector/sketch/freehand.d.ts +13 -0
- package/dist/inspector/sketch/freehand.js +64 -0
- package/dist/inspector/sketch/geometry.d.ts +17 -0
- package/dist/inspector/sketch/geometry.js +98 -0
- package/dist/inspector/sketch/handoff.d.ts +21 -0
- package/dist/inspector/sketch/handoff.js +72 -0
- package/dist/inspector/sketch/interaction.d.ts +21 -0
- package/dist/inspector/sketch/interaction.js +98 -0
- package/dist/inspector/sketch/model.d.ts +104 -0
- package/dist/inspector/sketch/model.js +282 -0
- package/dist/inspector/sketch/persistence.d.ts +21 -0
- package/dist/inspector/sketch/persistence.js +205 -0
- package/dist/inspector/sketch/raster.d.ts +22 -0
- package/dist/inspector/sketch/raster.js +203 -0
- package/dist/inspector/sketch/sketchNote.d.ts +10 -0
- package/dist/inspector/sketch/sketchNote.js +30 -0
- package/dist/inspector/sketch/store.d.ts +47 -0
- package/dist/inspector/sketch/store.js +409 -0
- package/dist/inspector/styleEditors/BorderEditor.js +15 -19
- package/dist/inspector/styleEditors/BorderRadiusEditor.js +6 -6
- package/dist/inspector/styleEditors/BoxShadowEditor.js +12 -1
- package/dist/inspector/styleEditors/ColorPicker.js +11 -36
- package/dist/inspector/styleEditors/GapField.d.ts +3 -2
- package/dist/inspector/styleEditors/GapField.js +2 -2
- package/dist/inspector/styleEditors/GridSection.js +1 -1
- package/dist/inspector/styleEditors/LayoutSection.js +11 -8
- package/dist/inspector/styleEditors/SpacingBox.js +23 -30
- package/dist/inspector/styleEditors/layoutPreviewState.d.ts +5 -0
- package/dist/inspector/styleEditors/layoutPreviewState.js +19 -0
- package/dist/inspector/styleEditors/layoutValue.js +3 -0
- package/dist/inspector/styleEditors/nudgeValue.d.ts +11 -0
- package/dist/inspector/styleEditors/nudgeValue.js +91 -5
- package/dist/inspector/styleEditors/stylePresence.d.ts +7 -0
- package/dist/inspector/styleEditors/stylePresence.js +22 -0
- package/dist/inspector/styleEditors/textRelevance.d.ts +3 -0
- package/dist/inspector/styleEditors/textRelevance.js +35 -0
- package/dist/inspector/styleEditors/useFieldVisibility.d.ts +6 -0
- package/dist/inspector/styleEditors/useFieldVisibility.js +26 -0
- package/dist/inspector/tokens/TokenField.js +111 -7
- package/dist/inspector/tokens/editActions.d.ts +2 -0
- package/dist/inspector/tokens/editActions.js +2 -2
- package/dist/inspector/tokens/resolution/cssomCollector.d.ts +1 -1
- package/dist/inspector/tokens/resolution/cssomCollector.js +9 -5
- package/dist/inspector/tokens/resolution/ruleMatching.d.ts +40 -0
- package/dist/inspector/tokens/resolution/ruleMatching.js +423 -0
- package/dist/inspector/tokens/resolution/selectorSemantics.d.ts +19 -3
- package/dist/inspector/tokens/resolution/selectorSemantics.js +378 -4
- package/dist/inspector/tokens/resolution.d.ts +3 -26
- package/dist/inspector/tokens/resolution.js +44 -735
- package/dist/inspector/tokens/tokenAvailability.d.ts +18 -0
- package/dist/inspector/tokens/tokenAvailability.js +204 -0
- package/dist/inspector/ui/Button.d.ts +1 -1
- package/dist/inspector/ui/SideValuesField.js +2 -2
- package/dist/inspector/ui/StatusCallout.d.ts +4 -1
- package/dist/inspector/ui/StatusCallout.js +2 -2
- package/dist/inspector/ui/styles.js +13 -11
- package/dist/internal/agent-protocol.d.ts +65 -1
- package/dist/internal/agent-protocol.js +183 -3
- package/dist/nudge-ui.mjs +261 -57
- package/dist/transport/editor.d.ts +28 -0
- package/dist/transport/editor.js +132 -0
- package/dist/transport/index.d.ts +1 -0
- package/dist/transport/index.js +1 -0
- package/dist/transport/routes.d.ts +7 -0
- package/dist/transport/routes.js +7 -0
- package/package.json +3 -1
- package/dist/inspector/shell/panelLayout.d.ts +0 -2
- package/dist/inspector/shell/panelLayout.js +0 -29
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { applyStructuralProjection, canContainElement as canContainStructuralElement, createStructuralDelete, createStructuralMove, getStructuralMoveLegality, getStructuralChanges, } from "../projection/structuralProjection.js";
|
|
2
|
+
import { isEditorShellDocument } from "../runtime/editorShell.js";
|
|
2
3
|
/** Conservative HTML guard shared with canonical capture and document replay. */
|
|
3
4
|
export function canContainElement(parent, child) {
|
|
4
5
|
return canContainStructuralElement(parent, child);
|
|
@@ -141,16 +142,18 @@ export function getDropLocationAtPoint(doc, dragged, x, y) {
|
|
|
141
142
|
const inContainerInterior = y - rect.top > edgeBand && y - rect.top < rect.height - edgeBand;
|
|
142
143
|
return getDropLocationForElement(dragged, target, y < rect.top + rect.height / 2, inContainerInterior);
|
|
143
144
|
}
|
|
144
|
-
|
|
145
|
+
function projectInlineHost(node) {
|
|
146
|
+
if (node.ownerDocument !== document || isEditorShellDocument(document))
|
|
147
|
+
return;
|
|
148
|
+
applyStructuralProjection(document, getStructuralChanges());
|
|
149
|
+
}
|
|
150
|
+
/** Capture the move as canonical intent, then preview it in an inline host. */
|
|
145
151
|
export function moveElement(node, destination) {
|
|
146
152
|
if (!getStructuralMoveLegality(node, destination).valid)
|
|
147
153
|
return null;
|
|
148
154
|
const change = createStructuralMove(node, destination);
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
// `document` belongs to the controller runtime. A Canvas source element is
|
|
152
|
-
// deliberately not projected here; its renderer receives this snapshot once.
|
|
153
|
-
applyStructuralProjection(document, getStructuralChanges());
|
|
155
|
+
if (change)
|
|
156
|
+
projectInlineHost(node);
|
|
154
157
|
return change;
|
|
155
158
|
}
|
|
156
159
|
/** Reorder only same-parent siblings; horizontal movement needs a flex row. */
|
|
@@ -167,14 +170,13 @@ export function nudgeElement(node, key) {
|
|
|
167
170
|
const before = moveEarlier ? sibling : sibling.nextElementSibling;
|
|
168
171
|
return moveElement(node, { parent, before, ...lineFor(parent, before) });
|
|
169
172
|
}
|
|
170
|
-
/** Capture delete intent
|
|
173
|
+
/** Capture delete intent, then preview it in an inline host. */
|
|
171
174
|
export function deleteElement(selected) {
|
|
172
175
|
const node = selected.domElement;
|
|
173
176
|
if (!node.parentElement || !node.isConnected)
|
|
174
177
|
return null;
|
|
175
178
|
const change = createStructuralDelete(node);
|
|
176
|
-
if (
|
|
177
|
-
|
|
178
|
-
applyStructuralProjection(document, getStructuralChanges());
|
|
179
|
+
if (change)
|
|
180
|
+
projectInlineHost(node);
|
|
179
181
|
return change;
|
|
180
182
|
}
|
|
@@ -171,6 +171,9 @@ function commaListIncludes(value, property) {
|
|
|
171
171
|
return value.split(",").map((part) => part.trim()).some((part) => part === "all" || part === property);
|
|
172
172
|
}
|
|
173
173
|
function hasImportantAuthorRule(el, property) {
|
|
174
|
+
const StyleRule = el.ownerDocument.defaultView?.CSSStyleRule;
|
|
175
|
+
if (!StyleRule)
|
|
176
|
+
return false;
|
|
174
177
|
for (const sheet of Array.from(el.ownerDocument.styleSheets)) {
|
|
175
178
|
let rules;
|
|
176
179
|
try {
|
|
@@ -180,7 +183,7 @@ function hasImportantAuthorRule(el, property) {
|
|
|
180
183
|
continue;
|
|
181
184
|
}
|
|
182
185
|
for (const rule of Array.from(rules)) {
|
|
183
|
-
if (!(rule instanceof
|
|
186
|
+
if (!(rule instanceof StyleRule))
|
|
184
187
|
continue;
|
|
185
188
|
try {
|
|
186
189
|
if (el.matches(rule.selectorText) && rule.style.getPropertyPriority(property) === "important")
|
|
@@ -44,6 +44,8 @@ export declare function collectRenderedInstanceOverrides(changes: ReadonlyArray<
|
|
|
44
44
|
* later reconciliation changes diagnostics but never starts a reapply loop.
|
|
45
45
|
*/
|
|
46
46
|
export declare function applyRenderedInstanceProjection(doc: Document, overrides: ReadonlyArray<RenderedInstanceOverride>): DocumentProjectionReport[];
|
|
47
|
+
/** Registers controller-owned overrides without projecting them into the editor shell. */
|
|
48
|
+
export declare function setCanonicalRenderedInstanceOverrides(overrides: ReadonlyArray<RenderedInstanceOverride>): void;
|
|
47
49
|
export declare function getRenderedInstanceProjectionReports(doc: Document): readonly DocumentProjectionReport[];
|
|
48
50
|
/** Diagnostics arrive independently when a renderer reports or React reconciles. */
|
|
49
51
|
export declare function subscribeRenderedInstanceDiagnostics(listener: () => void): () => void;
|
|
@@ -213,7 +213,7 @@ export function applyRenderedInstanceProjection(doc, overrides) {
|
|
|
213
213
|
if (!isNudgeUiDev())
|
|
214
214
|
return [];
|
|
215
215
|
const state = getDocumentState(doc);
|
|
216
|
-
|
|
216
|
+
setCanonicalRenderedInstanceOverrides(overrides);
|
|
217
217
|
const key = JSON.stringify(overrides);
|
|
218
218
|
if (state.snapshotKey === key) {
|
|
219
219
|
const reports = reportsForSnapshot(state, overrides);
|
|
@@ -239,6 +239,10 @@ export function applyRenderedInstanceProjection(doc, overrides) {
|
|
|
239
239
|
storeReports(doc, reports);
|
|
240
240
|
return reports;
|
|
241
241
|
}
|
|
242
|
+
/** Registers controller-owned overrides without projecting them into the editor shell. */
|
|
243
|
+
export function setCanonicalRenderedInstanceOverrides(overrides) {
|
|
244
|
+
canonicalOverrides = new Map(overrides.map((override) => [override.id, override]));
|
|
245
|
+
}
|
|
242
246
|
export function getRenderedInstanceProjectionReports(doc) {
|
|
243
247
|
return reportsByDocument.get(doc) ?? [];
|
|
244
248
|
}
|
|
@@ -29,6 +29,8 @@ export declare function getStructuralMoveLegality(element: HTMLElement, destinat
|
|
|
29
29
|
export interface StructuralChangeDiagnostic extends StructuralProjectionReport {
|
|
30
30
|
document: "Inspect" | `Canvas ${string}`;
|
|
31
31
|
}
|
|
32
|
+
/** Returns bounded view state used to verify a delete in the same rendered view. */
|
|
33
|
+
export declare function documentStateKey(doc: Document, excluded?: HTMLElement): string | undefined;
|
|
32
34
|
/** Captures a delete intent once, in the controller, at the user gesture. */
|
|
33
35
|
export declare function createStructuralDelete(element: HTMLElement, id?: string): StructuralDelete | null;
|
|
34
36
|
/**
|
|
@@ -95,6 +95,82 @@ function notifyDiagnostics() {
|
|
|
95
95
|
function structuralId() {
|
|
96
96
|
return `structural-${crypto.randomUUID?.() ?? nextStructuralId++}`;
|
|
97
97
|
}
|
|
98
|
+
function documentRoute(doc) {
|
|
99
|
+
if (!doc.location)
|
|
100
|
+
return undefined;
|
|
101
|
+
try {
|
|
102
|
+
const url = new URL(doc.location.href);
|
|
103
|
+
url.hash = "";
|
|
104
|
+
return url.href;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function stableStateValue(value, seen = new WeakSet()) {
|
|
111
|
+
if (!value || typeof value !== "object")
|
|
112
|
+
return value;
|
|
113
|
+
if (seen.has(value))
|
|
114
|
+
return "[Circular]";
|
|
115
|
+
seen.add(value);
|
|
116
|
+
if (Array.isArray(value))
|
|
117
|
+
return value.map((entry) => stableStateValue(entry, seen));
|
|
118
|
+
return Object.fromEntries(Object.entries(value)
|
|
119
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
120
|
+
.map(([key, entry]) => [key, stableStateValue(entry, seen)]));
|
|
121
|
+
}
|
|
122
|
+
function textWithoutExcluded(element, excluded) {
|
|
123
|
+
let text = "";
|
|
124
|
+
const visit = (node) => {
|
|
125
|
+
if (node === excluded)
|
|
126
|
+
return;
|
|
127
|
+
if (node.nodeType === node.TEXT_NODE) {
|
|
128
|
+
text += node.nodeValue ?? "";
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
node.childNodes.forEach(visit);
|
|
132
|
+
};
|
|
133
|
+
visit(element);
|
|
134
|
+
return text.replace(/\s+/g, " ").trim().slice(0, 120) || null;
|
|
135
|
+
}
|
|
136
|
+
function renderedInstanceState(doc, excluded) {
|
|
137
|
+
try {
|
|
138
|
+
return Array.from(doc.querySelectorAll("[data-cid][data-src]"))
|
|
139
|
+
.filter((element) => element !== excluded && !excluded?.contains(element))
|
|
140
|
+
.map((element) => ({
|
|
141
|
+
tag: element.tagName.toLowerCase(),
|
|
142
|
+
cid: element.getAttribute("data-cid"),
|
|
143
|
+
src: element.getAttribute("data-src"),
|
|
144
|
+
props: element.getAttribute("data-cprops"),
|
|
145
|
+
text: textWithoutExcluded(element, excluded),
|
|
146
|
+
ariaLabel: element.getAttribute("aria-label"),
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** Returns bounded view state used to verify a delete in the same rendered view. */
|
|
154
|
+
export function documentStateKey(doc, excluded) {
|
|
155
|
+
const view = doc.defaultView;
|
|
156
|
+
if (!view || !doc.location)
|
|
157
|
+
return undefined;
|
|
158
|
+
try {
|
|
159
|
+
const url = new URL(doc.location.href);
|
|
160
|
+
const rendered = renderedInstanceState(doc, excluded);
|
|
161
|
+
if (!rendered)
|
|
162
|
+
return undefined;
|
|
163
|
+
const state = JSON.stringify({
|
|
164
|
+
hash: url.hash,
|
|
165
|
+
history: stableStateValue(view.history.state),
|
|
166
|
+
rendered,
|
|
167
|
+
});
|
|
168
|
+
return state.length <= 4096 ? state : undefined;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
98
174
|
function cloneSnapshot(snapshot) {
|
|
99
175
|
// Structural changes are small JSON-safe records. Cloning their top-level
|
|
100
176
|
// array is enough: no operation mutates a change or its nested references.
|
|
@@ -108,7 +184,15 @@ export function createStructuralDelete(element, id = structuralId()) {
|
|
|
108
184
|
const target = captureRenderedInstance(element);
|
|
109
185
|
if (!target)
|
|
110
186
|
return null;
|
|
111
|
-
const
|
|
187
|
+
const route = documentRoute(element.ownerDocument);
|
|
188
|
+
const state = documentStateKey(element.ownerDocument, element);
|
|
189
|
+
const change = {
|
|
190
|
+
id,
|
|
191
|
+
kind: "delete",
|
|
192
|
+
target,
|
|
193
|
+
...(route ? { route } : {}),
|
|
194
|
+
...(state ? { state } : {}),
|
|
195
|
+
};
|
|
112
196
|
if (!workspaceChangeStore.commitStructuralChange(change))
|
|
113
197
|
return null;
|
|
114
198
|
projectStructuralChanges(workspaceChangeStore.getSnapshot());
|
|
@@ -18,12 +18,28 @@ export function isStructuralDelete(value) {
|
|
|
18
18
|
if (!value || typeof value !== "object")
|
|
19
19
|
return false;
|
|
20
20
|
const candidate = value;
|
|
21
|
-
if (!hasOnlyKeys(candidate, ["id", "kind", "target"]))
|
|
21
|
+
if (!hasOnlyKeys(candidate, ["id", "kind", "target", "route", "state"]))
|
|
22
22
|
return false;
|
|
23
23
|
return candidate.kind === "delete"
|
|
24
24
|
&& typeof candidate.id === "string"
|
|
25
|
+
&& (candidate.route === undefined || isRoute(candidate.route))
|
|
26
|
+
&& (candidate.state === undefined || isStateKey(candidate.state))
|
|
25
27
|
&& isRenderedInstanceRef(candidate.target);
|
|
26
28
|
}
|
|
29
|
+
function isStateKey(value) {
|
|
30
|
+
return typeof value === "string" && value.length > 0 && value.length <= 4096;
|
|
31
|
+
}
|
|
32
|
+
function isRoute(value) {
|
|
33
|
+
if (typeof value !== "string" || value.length > 2048)
|
|
34
|
+
return false;
|
|
35
|
+
try {
|
|
36
|
+
const url = new URL(value);
|
|
37
|
+
return (url.protocol === "http:" || url.protocol === "https:") && url.hash === "";
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
27
43
|
export function isStructuralMove(value) {
|
|
28
44
|
if (!value || typeof value !== "object")
|
|
29
45
|
return false;
|
|
@@ -43,6 +43,8 @@ export declare function collectTextContentChanges(changes: ReadonlyArray<unknown
|
|
|
43
43
|
export declare function getTextContentChangeById(changeId: string): TextContentChangeRecord | null;
|
|
44
44
|
/** Apply one controller-owned text snapshot to a document adapter. */
|
|
45
45
|
export declare function applyTextContentProjection(doc: Document, changes: ReadonlyArray<TextContentChangeRecord>): TextProjectionReport[];
|
|
46
|
+
/** Registers controller-owned text changes without projecting them into the editor shell. */
|
|
47
|
+
export declare function setCanonicalTextContentChanges(changes: ReadonlyArray<TextContentChangeRecord>): void;
|
|
46
48
|
export declare function getTextProjectionReports(doc: Document): readonly TextProjectionReport[];
|
|
47
49
|
export declare function subscribeTextProjectionDiagnostics(listener: () => void): () => void;
|
|
48
50
|
export declare function getTextProjectionDiagnosticRevision(): number;
|
|
@@ -42,7 +42,8 @@ function markerKey(target) {
|
|
|
42
42
|
return target.textNodePath ? `path:${target.textNodePath.join(",")}` : "root";
|
|
43
43
|
}
|
|
44
44
|
function isEmptyTextAffordance(node) {
|
|
45
|
-
return node
|
|
45
|
+
return node?.nodeType === 1
|
|
46
|
+
&& node.hasAttribute(EMPTY_TEXT_PROJECTION_ATTR);
|
|
46
47
|
}
|
|
47
48
|
function hasInlineTextEditor(element) {
|
|
48
49
|
return element.querySelector('[data-inline-editor="true"]') !== null;
|
|
@@ -308,8 +309,9 @@ function emptyTextAffordanceFor(doc, state, change, element) {
|
|
|
308
309
|
if (!textNode || textNode.nodeValue !== "")
|
|
309
310
|
return null;
|
|
310
311
|
const parent = textNode.parentNode;
|
|
311
|
-
if (
|
|
312
|
+
if (parent?.nodeType !== 1)
|
|
312
313
|
return null;
|
|
314
|
+
const parentElement = parent;
|
|
313
315
|
const path = markerKey(change.target);
|
|
314
316
|
// During re-entry the temporary editor wraps the empty Text node. The
|
|
315
317
|
// existing slot remains beside that wrapper; search the whole projected
|
|
@@ -332,7 +334,7 @@ function emptyTextAffordanceFor(doc, state, change, element) {
|
|
|
332
334
|
// It has no application text and is never a source identity. The
|
|
333
335
|
// interaction stylesheet supplies its visible, borderless hit geometry.
|
|
334
336
|
affordance.hidden = !isInteractionStylesInstalled(doc);
|
|
335
|
-
|
|
337
|
+
parentElement.insertBefore(affordance, textNode.nextSibling);
|
|
336
338
|
state.emptyAffordances.set(change.id, affordance);
|
|
337
339
|
return affordance;
|
|
338
340
|
}
|
|
@@ -546,7 +548,7 @@ export function applyTextContentProjection(doc, changes) {
|
|
|
546
548
|
if (!isNudgeUiDev())
|
|
547
549
|
return [];
|
|
548
550
|
const state = getDocumentState(doc);
|
|
549
|
-
|
|
551
|
+
setCanonicalTextContentChanges(changes);
|
|
550
552
|
const key = JSON.stringify(changes);
|
|
551
553
|
if (state.snapshotKey === key) {
|
|
552
554
|
// Reconciliation can happen between controller snapshots. Validate before
|
|
@@ -624,6 +626,10 @@ export function applyTextContentProjection(doc, changes) {
|
|
|
624
626
|
storeReports(doc, reports);
|
|
625
627
|
return reports;
|
|
626
628
|
}
|
|
629
|
+
/** Registers controller-owned text changes without projecting them into the editor shell. */
|
|
630
|
+
export function setCanonicalTextContentChanges(changes) {
|
|
631
|
+
canonicalChanges = new Map(changes.map((change) => [change.id, change]));
|
|
632
|
+
}
|
|
627
633
|
export function getTextProjectionReports(doc) {
|
|
628
634
|
return reportsByDocument.get(doc) ?? [];
|
|
629
635
|
}
|
|
@@ -25,7 +25,7 @@ export declare function getLastClipboardReconciledCount(): number;
|
|
|
25
25
|
* Checks a copied prompt against source-rendered output and reconciles only
|
|
26
26
|
* exact records that the browser can positively verify.
|
|
27
27
|
*/
|
|
28
|
-
export declare function reconcileClipboardHandoff(): Promise<number>;
|
|
28
|
+
export declare function reconcileClipboardHandoff(doc?: Document): Promise<number>;
|
|
29
29
|
/**
|
|
30
30
|
* Watches source-driven document refreshes and page-return signals. The
|
|
31
31
|
* trailing debounce lets an HMR commit settle before verification lifts the
|
|
@@ -137,7 +137,7 @@ function pruneCheckpoint() {
|
|
|
137
137
|
* Checks a copied prompt against source-rendered output and reconciles only
|
|
138
138
|
* exact records that the browser can positively verify.
|
|
139
139
|
*/
|
|
140
|
-
export async function reconcileClipboardHandoff() {
|
|
140
|
+
export async function reconcileClipboardHandoff(doc = document) {
|
|
141
141
|
const snapshot = checkpoint;
|
|
142
142
|
if (!snapshot)
|
|
143
143
|
return 0;
|
|
@@ -147,7 +147,7 @@ export async function reconcileClipboardHandoff() {
|
|
|
147
147
|
pruneCheckpoint();
|
|
148
148
|
return 0;
|
|
149
149
|
}
|
|
150
|
-
const removed = await verifyAndReconcileHandoff({ changes, structuralChanges });
|
|
150
|
+
const removed = await verifyAndReconcileHandoff({ changes, structuralChanges }, doc);
|
|
151
151
|
pruneCheckpoint();
|
|
152
152
|
if (removed > 0) {
|
|
153
153
|
lastReconciledCount = removed;
|
|
@@ -175,7 +175,7 @@ export function startClipboardHandoffController(doc = document) {
|
|
|
175
175
|
if (stopped || checking || !checkpoint)
|
|
176
176
|
return;
|
|
177
177
|
checking = true;
|
|
178
|
-
void reconcileClipboardHandoff()
|
|
178
|
+
void reconcileClipboardHandoff(doc)
|
|
179
179
|
.catch(() => undefined)
|
|
180
180
|
.finally(() => {
|
|
181
181
|
// Keep the guard through the MutationObserver microtask generated by
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { ChangeRecord } from "../changes/changesLog.js";
|
|
2
2
|
import type { StructuralChange } from "../projection/structuralProjection.js";
|
|
3
|
+
import type { AgentSketchMetadata } from "../agent/protocol.js";
|
|
3
4
|
export interface FrameworkHints {
|
|
4
5
|
framework?: string;
|
|
5
6
|
stylingSystem?: string;
|
|
6
7
|
}
|
|
7
|
-
export declare function generatePrompt(changes: ChangeRecord[], frameworkHints?: FrameworkHints, structuralChanges?: readonly StructuralChange[], customInstructions?: string): string;
|
|
8
|
+
export declare function generatePrompt(changes: ChangeRecord[], frameworkHints?: FrameworkHints, structuralChanges?: readonly StructuralChange[], customInstructions?: string, sketches?: readonly AgentSketchMetadata[]): string;
|
|
@@ -244,6 +244,17 @@ function structuralChangeLine(change) {
|
|
|
244
244
|
? `- Move ${target} before ${renderedInstanceDescription(before)} in ${destinationParent}.`
|
|
245
245
|
: `- Move ${target} to the end of ${destinationParent}.`;
|
|
246
246
|
}
|
|
247
|
+
function sketchLines(sketches) {
|
|
248
|
+
const titles = [...new Set(sketches.map((sketch) => sketch.capture.title || "(untitled)"))];
|
|
249
|
+
return [
|
|
250
|
+
...titles.map((title) => `- Page title: ${promptText(title)}`),
|
|
251
|
+
...sketches.flatMap((sketch) => [
|
|
252
|
+
...(sketch.description ? [`- Description: ${promptText(sketch.description)}`] : []),
|
|
253
|
+
...(sketch.annotations ?? []).map((annotation) => `- Annotation ${annotation.number}: ${promptText(annotation.description)}`),
|
|
254
|
+
]),
|
|
255
|
+
"- Interpret the attached frozen screenshot, blue strokes, and numbered annotations as visual feedback. Do not derive selectors, source coordinates, or semantics from the strokes. Use each annotation number to match the note to its numbered dot.",
|
|
256
|
+
];
|
|
257
|
+
}
|
|
247
258
|
function renderedInstanceKey(ref) {
|
|
248
259
|
const { sourceSite, locator } = ref;
|
|
249
260
|
return JSON.stringify([
|
|
@@ -304,10 +315,10 @@ function canonicalizeStructuralChanges(changes) {
|
|
|
304
315
|
}
|
|
305
316
|
return canonical;
|
|
306
317
|
}
|
|
307
|
-
export function generatePrompt(changes, frameworkHints, structuralChanges = [], customInstructions = DEFAULT_CUSTOM_INSTRUCTIONS) {
|
|
318
|
+
export function generatePrompt(changes, frameworkHints, structuralChanges = [], customInstructions = DEFAULT_CUSTOM_INSTRUCTIONS, sketches = []) {
|
|
308
319
|
const deduplicated = canonicalizeChanges(changes);
|
|
309
320
|
const structuralIntent = canonicalizeStructuralChanges(structuralChanges);
|
|
310
|
-
if (deduplicated.length === 0 && structuralIntent.length === 0)
|
|
321
|
+
if (deduplicated.length === 0 && structuralIntent.length === 0 && sketches.length === 0)
|
|
311
322
|
return EMPTY_SENTINEL;
|
|
312
323
|
const tokenChanges = deduplicated.filter(isTokenChange);
|
|
313
324
|
const componentChanges = deduplicated.filter(isComponentChange);
|
|
@@ -387,5 +398,11 @@ export function generatePrompt(changes, frameworkHints, structuralChanges = [],
|
|
|
387
398
|
lines: structuralIntent.map(structuralChangeLine),
|
|
388
399
|
});
|
|
389
400
|
}
|
|
401
|
+
if (sketches.length > 0) {
|
|
402
|
+
sections.push({
|
|
403
|
+
heading: "Sketch annotations",
|
|
404
|
+
lines: sketchLines(sketches),
|
|
405
|
+
});
|
|
406
|
+
}
|
|
390
407
|
return renderPrompt(sections, customInstructions);
|
|
391
408
|
}
|
|
@@ -60,6 +60,10 @@ export interface NudgeUiRuntimeConfig {
|
|
|
60
60
|
readonly componentContracts: readonly ComponentContract[];
|
|
61
61
|
/** Whether this runtime is the explicit public landing-page demo. */
|
|
62
62
|
readonly demo?: boolean;
|
|
63
|
+
/** Additional same-origin pages seeded into the public demo canvas. */
|
|
64
|
+
readonly demoPages?: readonly string[];
|
|
65
|
+
/** Labels for demo cards in display order, including the primary card. */
|
|
66
|
+
readonly demoCardLabels?: readonly string[];
|
|
63
67
|
}
|
|
64
68
|
/**
|
|
65
69
|
* Validates a host-supplied configuration and fills safe defaults.
|
|
@@ -170,6 +170,8 @@ export function normalizeNudgeUiRuntimeConfig(input) {
|
|
|
170
170
|
if (isNormalizedRuntimeConfig(input))
|
|
171
171
|
return input;
|
|
172
172
|
const demo = optionalDemoFlag(input);
|
|
173
|
+
const demoPages = optionalStringArray(input, "demoPages");
|
|
174
|
+
const demoCardLabels = optionalStringArray(input, "demoCardLabels");
|
|
173
175
|
const normalized = cloneAndFreeze({
|
|
174
176
|
projectId: requireString(input, "projectId"),
|
|
175
177
|
host: requireEnum(input, "host", RUNTIME_HOSTS),
|
|
@@ -182,6 +184,8 @@ export function normalizeNudgeUiRuntimeConfig(input) {
|
|
|
182
184
|
tokenGeneration: optionalString(input, "tokenGeneration"),
|
|
183
185
|
componentContracts: optionalArray(input, "componentContracts"),
|
|
184
186
|
...(demo === true ? { demo: true } : {}),
|
|
187
|
+
...(demoPages === undefined ? {} : { demoPages }),
|
|
188
|
+
...(demoCardLabels === undefined ? {} : { demoCardLabels }),
|
|
185
189
|
});
|
|
186
190
|
normalizedRuntimeConfigs.add(normalized);
|
|
187
191
|
return normalized;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useSyncExternalStore } from "react";
|
|
2
2
|
import { computeHierarchy } from "./hierarchy.js";
|
|
3
3
|
import { resolveSelectionFromElement } from "./resolveSelection.js";
|
|
4
|
+
import { clearInlineTextDiagnosticsForSelection } from "../inline-text/inlineTextDiagnostics.js";
|
|
4
5
|
let currentSelection = null;
|
|
5
6
|
const EMPTY_SELECTION = [];
|
|
6
7
|
let chain = [];
|
|
@@ -28,6 +29,7 @@ function getHierarchyIndex() {
|
|
|
28
29
|
return index;
|
|
29
30
|
}
|
|
30
31
|
function notify() {
|
|
32
|
+
clearInlineTextDiagnosticsForSelection(getSelectedElements().map((element) => element.domElement));
|
|
31
33
|
listeners.forEach((l) => l());
|
|
32
34
|
}
|
|
33
35
|
function sameComponentTargets(a, b) {
|
|
@@ -6,6 +6,10 @@ import { useBrowserCssInspection } from "../inspection/useBrowserCssInspection.j
|
|
|
6
6
|
import { McpConnectionContent, } from "../agent/McpConnectionDialog.js";
|
|
7
7
|
import { PromptSettingsFields, } from "../prompt/PromptSettingsDialog.js";
|
|
8
8
|
import { TokensPanel } from "../tokens/TokensPanel.js";
|
|
9
|
+
import { useSelectedElement } from "../selection/selectionStore.js";
|
|
10
|
+
import { useFocusedCardId, useSelectedCardId } from "../canvas/canvasStore.js";
|
|
11
|
+
import { getRegisteredFrames } from "../canvas/projection.js";
|
|
12
|
+
import { getBrowserCssInspection } from "../inspection/browserCssInspectionRegistry.js";
|
|
9
13
|
const SETTINGS_SECTIONS = [
|
|
10
14
|
{
|
|
11
15
|
id: "instructions",
|
|
@@ -33,8 +37,14 @@ export function SettingsDialog({ open, initialSection, value, onValueChange, onO
|
|
|
33
37
|
const [activeSection, setActiveSection] = useState(initialSection);
|
|
34
38
|
const closeRef = useRef(null);
|
|
35
39
|
const instructionsRef = useRef(null);
|
|
40
|
+
const selectedElement = useSelectedElement();
|
|
41
|
+
const selectedCardId = useSelectedCardId();
|
|
42
|
+
const focusedCardId = useFocusedCardId();
|
|
43
|
+
const activeFrame = getRegisteredFrames().get(selectedCardId ?? focusedCardId ?? "");
|
|
44
|
+
const activeDocument = selectedElement?.domElement.ownerDocument ?? activeFrame?.contentDocument ?? document;
|
|
36
45
|
const tokenInspection = useBrowserCssInspection(null, "base", {
|
|
37
46
|
includeDocumentTokens: activeSection === "tokens",
|
|
47
|
+
session: getBrowserCssInspection(activeDocument),
|
|
38
48
|
});
|
|
39
49
|
const tokenRows = tokenInspection.documentTokens?.tokens ?? [];
|
|
40
50
|
const activeDefinition = SETTINGS_SECTIONS.find((section) => section.id === activeSection) ?? SETTINGS_SECTIONS[0];
|
|
@@ -3,7 +3,11 @@ import { InspectorShell } from "./InspectorShell.js";
|
|
|
3
3
|
import { CanvasWorkspace } from "../canvas/CanvasWorkspace.js";
|
|
4
4
|
import { CanvasElementOverlay } from "../canvas/CanvasElementOverlay.js";
|
|
5
5
|
import { useNudgeUiRuntimeConfig } from "../runtime/useRuntimeConfig.js";
|
|
6
|
+
import { readNudgeUiEditorTarget } from "../../transport/editor.js";
|
|
6
7
|
export function AppShell() {
|
|
7
8
|
const canvasEnabled = useNudgeUiRuntimeConfig().capabilities.canvas;
|
|
8
|
-
|
|
9
|
+
const primaryUrl = typeof window === "undefined"
|
|
10
|
+
? null
|
|
11
|
+
: readNudgeUiEditorTarget(window.location.href);
|
|
12
|
+
return (_jsxs(_Fragment, { children: [canvasEnabled ? _jsx(CanvasWorkspace, { primaryUrl: primaryUrl }) : null, canvasEnabled ? _jsx(CanvasElementOverlay, {}) : null, _jsx(InspectorShell, {})] }));
|
|
9
13
|
}
|
|
@@ -8,6 +8,8 @@ import { presentChange } from "../changes/presentation.js";
|
|
|
8
8
|
import { getStructuralChanges, getStructuralChangeDiagnostics, getStructuralDiagnosticRevision, revertStructuralChange, subscribeStructuralChanges, subscribeStructuralDiagnostics, } from "../projection/structuralProjection.js";
|
|
9
9
|
import { getRenderedInstanceChangeDiagnostics, getRenderedInstanceDiagnosticRevision, subscribeRenderedInstanceDiagnostics, } from "../projection/renderedInstance.js";
|
|
10
10
|
import { getTextContentChangeDiagnostics, getTextProjectionDiagnosticRevision, subscribeTextProjectionDiagnostics, } from "../projection/textProjection.js";
|
|
11
|
+
import { SketchChanges } from "../sketch/SketchChanges.js";
|
|
12
|
+
import { useSketchStore } from "../sketch/store.js";
|
|
11
13
|
function groupChanges(changes) {
|
|
12
14
|
const map = new Map();
|
|
13
15
|
for (const change of changes) {
|
|
@@ -60,6 +62,8 @@ function structuralDiagnosticText(diagnostic) {
|
|
|
60
62
|
}
|
|
61
63
|
export function ChangesLog({ onClearSession }) {
|
|
62
64
|
const changes = useChanges();
|
|
65
|
+
const sketchStore = useSketchStore();
|
|
66
|
+
const sketches = sketchStore.items;
|
|
63
67
|
const structuralChanges = useSyncExternalStore(subscribeStructuralChanges, getStructuralChanges, getStructuralChanges);
|
|
64
68
|
// Diagnostics arrive independently from structural state when a renderer
|
|
65
69
|
// resolves a snapshot or its document observer detects a reconciliation.
|
|
@@ -67,10 +71,10 @@ export function ChangesLog({ onClearSession }) {
|
|
|
67
71
|
useSyncExternalStore(subscribeRenderedInstanceDiagnostics, getRenderedInstanceDiagnosticRevision, getRenderedInstanceDiagnosticRevision);
|
|
68
72
|
useSyncExternalStore(subscribeTextProjectionDiagnostics, getTextProjectionDiagnosticRevision, getTextProjectionDiagnosticRevision);
|
|
69
73
|
const groups = useMemo(() => groupChanges(changes), [changes]);
|
|
70
|
-
const total = changes.length + structuralChanges.length;
|
|
71
|
-
if (total === 0)
|
|
74
|
+
const total = changes.length + structuralChanges.length + sketches.length;
|
|
75
|
+
if (total === 0 && sketchStore.error === null)
|
|
72
76
|
return null;
|
|
73
|
-
return (_jsxs(_Fragment, { children: [_jsxs("details", { className: "changes", "data-test": "changes-log", children: [_jsxs("summary", { className: "changes__title", "data-test": "changes-toggle", children: [_jsx("span", { className: "changes__title-label", children: "Changes" }), total > 0 ? _jsx("span", { className: "changes__count", children: total }) : null, _jsx(IconChevronDown, { className: "changes__toggle-icon", size: 15, stroke: 2, "aria-hidden": "true" })] }), _jsx("div", { className: "changes__content", children: groups.length === 0 && structuralChanges.length === 0 ? (_jsx("div", { className: "changes__empty", "data-test": "changes-empty", children: "No changes yet" })) : (_jsxs(_Fragment, { children: [groups.map((group) => (_jsxs("div", { className: "changes__group", "data-test": "changes-group", "data-cid": group.label, children: [_jsxs("div", { className: "changes__group-title", children: [_jsx("span", { children: group.label }), _jsx("span", { className: "changes__group-file", children: group.file })] }), group.changes.map((change, i) => {
|
|
77
|
+
return (_jsxs(_Fragment, { children: [_jsxs("details", { className: "changes", "data-test": "changes-log", children: [_jsxs("summary", { className: "changes__title", "data-test": "changes-toggle", children: [_jsx("span", { className: "changes__title-label", children: "Changes" }), total > 0 ? _jsx("span", { className: "changes__count", children: total }) : null, _jsx(IconChevronDown, { className: "changes__toggle-icon", size: 15, stroke: 2, "aria-hidden": "true" })] }), _jsx("div", { className: "changes__content", children: groups.length === 0 && structuralChanges.length === 0 && sketches.length === 0 && sketchStore.error === null ? (_jsx("div", { className: "changes__empty", "data-test": "changes-empty", children: "No changes yet" })) : (_jsxs(_Fragment, { children: [groups.map((group) => (_jsxs("div", { className: "changes__group", "data-test": "changes-group", "data-cid": group.label, children: [_jsxs("div", { className: "changes__group-title", children: [_jsx("span", { children: group.label }), _jsx("span", { className: "changes__group-file", children: group.file })] }), group.changes.map((change, i) => {
|
|
74
78
|
const presentation = presentChange(change);
|
|
75
79
|
const instanceDiagnostics = isElementChange(change) && change.scope === "rendered-instance"
|
|
76
80
|
&& change.instanceOverride
|
|
@@ -88,5 +92,5 @@ export function ChangesLog({ onClearSession }) {
|
|
|
88
92
|
? structuralParentIdentityKey(change.source.parent) === structuralParentIdentityKey(change.destination.parent)
|
|
89
93
|
? `${change.presentation.destinationParentTag} position ${change.presentation.toIndex + 1}`
|
|
90
94
|
: `${structuralParentLabel(change, "destination")} position ${change.presentation.toIndex + 1}`
|
|
91
|
-
: "Removed" })] }), _jsx("span", { className: "changes__scope", "data-test": "structural-scope", children: "This rendered item only" }), getStructuralChangeDiagnostics(change.id).map((diagnostic) => (_jsx("span", { className: "changes__diagnostic", "data-test": "structural-diagnostic", "data-document": diagnostic.document, "data-status": diagnostic.status, "data-reason": diagnostic.reason, children: structuralDiagnosticText(diagnostic) }, `${diagnostic.document}:${diagnostic.status}:${diagnostic.reason ?? ""}`))), _jsx(Button, { size: "compact", className: "changes__revert", "data-test": "dom-change-revert", onClick: () => revertStructuralChange(change.id), children: "Revert" })] })] }, change.id)))] })) })] }), onClearSession ? (_jsx("div", { className: "changes__session-action", "data-test": "session-actions", children: _jsx(Button, { variant: "secondary", type: "button", "data-test": "clear-session", onClick: onClearSession, children: "Clear Changes" }) })) : null] }));
|
|
95
|
+
: "Removed" })] }), _jsx("span", { className: "changes__scope", "data-test": "structural-scope", children: "This rendered item only" }), getStructuralChangeDiagnostics(change.id).map((diagnostic) => (_jsx("span", { className: "changes__diagnostic", "data-test": "structural-diagnostic", "data-document": diagnostic.document, "data-status": diagnostic.status, "data-reason": diagnostic.reason, children: structuralDiagnosticText(diagnostic) }, `${diagnostic.document}:${diagnostic.status}:${diagnostic.reason ?? ""}`))), _jsx(Button, { size: "compact", className: "changes__revert", "data-test": "dom-change-revert", onClick: () => revertStructuralChange(change.id), children: "Revert" })] })] }, change.id))), _jsx(SketchChanges, {})] })) })] }), onClearSession ? (_jsx("div", { className: "changes__session-action", "data-test": "session-actions", children: _jsx(Button, { variant: "secondary", type: "button", "data-test": "clear-session", onClick: onClearSession, children: "Clear Changes" }) })) : null] }));
|
|
92
96
|
}
|