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,7 +1,13 @@
|
|
|
1
1
|
import { isDocumentProjectionReport } from "../projection/renderedInstance.js";
|
|
2
2
|
import { isTextProjectionReport } from "../projection/textProjection.js";
|
|
3
3
|
import { isStructuralProjectionReport } from "../projection/structuralProjectionBoundary.js";
|
|
4
|
-
//
|
|
4
|
+
// v19 adds spacing drag gestures (hover point, spacing descriptor, start
|
|
5
|
+
// point, and cancelled drag-end) plus renderer-to-controller keyboard shortcut
|
|
6
|
+
// forwarding for Canvas frames.
|
|
7
|
+
// v18 adds parent-to-renderer Alt modifier forwarding for Canvas measurements.
|
|
8
|
+
// v17 adds an idempotent renderer request to open the parent inspector. v16
|
|
9
|
+
// adds controller-owned inline-text intents for Canvas frames. v15 adds
|
|
10
|
+
// renderer-to-controller element deselection for Canvas frames. v14
|
|
5
11
|
// adds border widths to hover geometry so containment measurements can exclude
|
|
6
12
|
// the container border. v13 adds source-parent-aware structural moves and
|
|
7
13
|
// bounded structural failure reasons to the full projection snapshot. v12
|
|
@@ -9,7 +15,7 @@ import { isStructuralProjectionReport } from "../projection/structuralProjection
|
|
|
9
15
|
// rereading a Canvas iframe until the renderer has applied its revision. v11
|
|
10
16
|
// added the renderer-hello handshake solicitation for runtimes whose boot
|
|
11
17
|
// completes after the controller's load-time parent-ready.
|
|
12
|
-
export const PROTOCOL_VERSION =
|
|
18
|
+
export const PROTOCOL_VERSION = 19;
|
|
13
19
|
let rendererIdentity = null;
|
|
14
20
|
export function setRendererIdentity(identity) {
|
|
15
21
|
rendererIdentity = identity;
|
|
@@ -30,6 +36,21 @@ export function isRendererMessageFor(value, identity) {
|
|
|
30
36
|
&& message.workspaceId === identity.workspaceId
|
|
31
37
|
&& message.cardId === identity.cardId;
|
|
32
38
|
}
|
|
39
|
+
export function isKeyboardShortcutCode(value) {
|
|
40
|
+
return value === "Backslash" || value === "KeyV" || value === "KeyH" || value === "KeyP" || value === "KeyS";
|
|
41
|
+
}
|
|
42
|
+
/** Strict JSON-only schema for renderer-originated global keyboard shortcuts. */
|
|
43
|
+
export function isKeyboardShortcutMessage(value, identity) {
|
|
44
|
+
if (!isRendererMessageFor(value, identity) || !isProtocolObject(value))
|
|
45
|
+
return false;
|
|
46
|
+
if (!hasOnlyKeys(value, [
|
|
47
|
+
"type", "protocolVersion", "projectId", "workspaceId", "cardId", "phase", "code",
|
|
48
|
+
]))
|
|
49
|
+
return false;
|
|
50
|
+
return ownValue(value, "type") === "keyboard-shortcut"
|
|
51
|
+
&& (ownValue(value, "phase") === "keydown" || ownValue(value, "phase") === "keyup")
|
|
52
|
+
&& isKeyboardShortcutCode(ownValue(value, "code"));
|
|
53
|
+
}
|
|
33
54
|
/** Strict JSON-only schema for selecting an element from a renderer frame. */
|
|
34
55
|
export function isElementClickMessage(value, identity) {
|
|
35
56
|
if (!isRendererMessageFor(value, identity) || !isProtocolObject(value))
|
|
@@ -51,6 +72,31 @@ export function isElementClickMessage(value, identity) {
|
|
|
51
72
|
&& typeof ownValue(value, "component") === "string"
|
|
52
73
|
&& (additive === undefined || typeof additive === "boolean");
|
|
53
74
|
}
|
|
75
|
+
/** Strict JSON-only schema for starting controller-owned inline text editing. */
|
|
76
|
+
export function isInlineTextIntentMessage(value, identity) {
|
|
77
|
+
if (!isRendererMessageFor(value, identity) || !isProtocolObject(value))
|
|
78
|
+
return false;
|
|
79
|
+
if (!hasOnlyKeys(value, [
|
|
80
|
+
"type", "protocolVersion", "projectId", "workspaceId", "cardId",
|
|
81
|
+
"intent", "cid", "src", "elementId", "point", "clickCount", "emptyProjectionId",
|
|
82
|
+
]))
|
|
83
|
+
return false;
|
|
84
|
+
const intent = ownValue(value, "intent");
|
|
85
|
+
const point = ownValue(value, "point");
|
|
86
|
+
const clickCount = ownValue(value, "clickCount");
|
|
87
|
+
const emptyProjectionId = ownValue(value, "emptyProjectionId");
|
|
88
|
+
return ownValue(value, "type") === "inline-text-intent"
|
|
89
|
+
&& (intent === "pointer-down" || intent === "double-click")
|
|
90
|
+
&& typeof ownValue(value, "cid") === "string"
|
|
91
|
+
&& typeof ownValue(value, "src") === "string"
|
|
92
|
+
&& typeof ownValue(value, "elementId") === "string"
|
|
93
|
+
&& isProtocolObject(point)
|
|
94
|
+
&& hasOnlyKeys(point, ["x", "y"])
|
|
95
|
+
&& typeof ownValue(point, "x") === "number" && Number.isFinite(ownValue(point, "x"))
|
|
96
|
+
&& typeof ownValue(point, "y") === "number" && Number.isFinite(ownValue(point, "y"))
|
|
97
|
+
&& (clickCount === undefined || (typeof clickCount === "number" && Number.isSafeInteger(clickCount) && clickCount >= 0))
|
|
98
|
+
&& (emptyProjectionId === undefined || typeof emptyProjectionId === "string");
|
|
99
|
+
}
|
|
54
100
|
/** Strict JSON-only schema for renderer diagnostics before the parent records them. */
|
|
55
101
|
export function isStructuralProjectionReportMessage(value, identity) {
|
|
56
102
|
if (!isRendererMessageFor(value, identity) || !value || typeof value !== "object")
|
|
@@ -137,6 +183,7 @@ function isProtocolObject(value) {
|
|
|
137
183
|
function ownValue(value, key) {
|
|
138
184
|
switch (key) {
|
|
139
185
|
case "additive": return value.additive;
|
|
186
|
+
case "emptyProjectionId": return value.emptyProjectionId;
|
|
140
187
|
case "cardId": return value.cardId;
|
|
141
188
|
case "cid": return value.cid;
|
|
142
189
|
case "callsiteId": return value.callsiteId;
|
|
@@ -144,6 +191,11 @@ function ownValue(value, key) {
|
|
|
144
191
|
case "elementId": return value.elementId;
|
|
145
192
|
case "file": return value.file;
|
|
146
193
|
case "line": return value.line;
|
|
194
|
+
case "intent": return value.intent;
|
|
195
|
+
case "point": return value.point;
|
|
196
|
+
case "clickCount": return value.clickCount;
|
|
197
|
+
case "x": return value.x;
|
|
198
|
+
case "y": return value.y;
|
|
147
199
|
case "prop": return value.prop;
|
|
148
200
|
case "projectId": return value.projectId;
|
|
149
201
|
case "protocolVersion": return value.protocolVersion;
|
|
@@ -153,6 +205,8 @@ function ownValue(value, key) {
|
|
|
153
205
|
case "selector": return value.selector;
|
|
154
206
|
case "src": return value.src;
|
|
155
207
|
case "component": return value.component;
|
|
208
|
+
case "code": return value.code;
|
|
209
|
+
case "phase": return value.phase;
|
|
156
210
|
case "value": return value.value;
|
|
157
211
|
case "workspaceId": return value.workspaceId;
|
|
158
212
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function canvasToolForCode(code) {
|
|
2
|
+
if (code === "KeyV")
|
|
3
|
+
return "move";
|
|
4
|
+
if (code === "KeyH")
|
|
5
|
+
return "pan";
|
|
6
|
+
if (code === "KeyP")
|
|
7
|
+
return "sketch";
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
export function canvasToolForEvent(event) {
|
|
11
|
+
if (event.repeat || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
|
|
12
|
+
return null;
|
|
13
|
+
return canvasToolForCode(event.code);
|
|
14
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type WorkspaceContents } from "../changes/workspaceChanges.js";
|
|
1
2
|
import type { CanvasCard } from "./canvasStore.js";
|
|
2
3
|
import { type PreviewDocument } from "../changes/previewDiagnostics.js";
|
|
3
4
|
import { type CompiledManagedStyles } from "../projection/workspaceProjection.js";
|
|
@@ -23,6 +24,12 @@ export declare function computeProjection(): {
|
|
|
23
24
|
};
|
|
24
25
|
export declare function resetProjectionRevision(): void;
|
|
25
26
|
export declare function sendProjectionToCard(card: CanvasCard, iframe: HTMLIFrameElement): void;
|
|
27
|
+
/** Temporarily projects a snapshot through the renderer that owns the document. */
|
|
28
|
+
export declare function projectWorkspaceSnapshotToDocument(doc: Document, snapshot: WorkspaceContents): Promise<number | null>;
|
|
29
|
+
/** Returns whether an acknowledged temporary projection is still authoritative. */
|
|
30
|
+
export declare function isCanvasProjectionRevisionCurrent(doc: Document, expectedRevision: number): boolean;
|
|
31
|
+
/** Returns whether the live frame acknowledged its latest canonical workspace projection. */
|
|
32
|
+
export declare function isCanvasCanonicalProjectionRevisionCurrent(doc: Document, expectedRevision: number): boolean;
|
|
26
33
|
export declare function registerCardFrameSource(cardId: string, iframe: HTMLIFrameElement): void;
|
|
27
34
|
export declare function registerCardFrame(cardId: string, iframe: HTMLIFrameElement): void;
|
|
28
35
|
export declare function unregisterCardFrame(cardId: string): void;
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { getWorkspaceChanges } from "../changes/workspaceChanges.js";
|
|
2
2
|
import { getCanvasMode } from "./canvasStore.js";
|
|
3
3
|
import { PROTOCOL_VERSION } from "./frameProtocol.js";
|
|
4
|
-
import { clearCanvasRenderedInstanceProjectionReports, } from "../projection/renderedInstance.js";
|
|
5
|
-
import { clearCanvasTextProjectionReports, } from "../projection/textProjection.js";
|
|
4
|
+
import { clearCanvasRenderedInstanceProjectionReports, setCanonicalRenderedInstanceOverrides, } from "../projection/renderedInstance.js";
|
|
5
|
+
import { clearCanvasTextProjectionReports, setCanonicalTextContentChanges, } from "../projection/textProjection.js";
|
|
6
6
|
import { clearCanvasStructuralProjectionReports } from "../projection/structuralProjection.js";
|
|
7
7
|
import { invalidatePreviewDocumentSession, startPreviewDocumentSession, } from "../changes/previewDiagnostics.js";
|
|
8
|
-
import {
|
|
8
|
+
import { compileWorkspaceProjection, } from "../projection/workspaceProjection.js";
|
|
9
|
+
import { isOriginalPreviewActive } from "../shell/originalPreview.js";
|
|
9
10
|
import { disposeBrowserCssInspection } from "../inspection/browserCssInspectionRegistry.js";
|
|
10
11
|
export const PROJECT_ID = window.location.origin;
|
|
11
12
|
export const WORKSPACE_ID = crypto.randomUUID?.() ?? `ws-${Date.now()}`;
|
|
12
13
|
let revision = 0;
|
|
13
14
|
let lastRulesKey = null;
|
|
15
|
+
let lastPeekActive = false;
|
|
14
16
|
const frameProjectionStates = new Map();
|
|
15
17
|
const previewDocuments = new Map();
|
|
16
18
|
const projectionAcknowledgementListeners = new Set();
|
|
@@ -49,7 +51,32 @@ function projectionKey(plan) {
|
|
|
49
51
|
}
|
|
50
52
|
export function computeProjection() {
|
|
51
53
|
const plan = compileWorkspaceProjection(getWorkspaceChanges());
|
|
52
|
-
|
|
54
|
+
if (isOriginalPreviewActive()) {
|
|
55
|
+
// Hold-to-view-original: frames show the page without inspector changes
|
|
56
|
+
// while canonical intent (and its projection key) stays untouched.
|
|
57
|
+
if (!lastPeekActive) {
|
|
58
|
+
lastPeekActive = true;
|
|
59
|
+
revision += 1;
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
...plan,
|
|
63
|
+
managedStyles: { rules: [], css: "" },
|
|
64
|
+
css: "",
|
|
65
|
+
instanceOverrides: [],
|
|
66
|
+
structuralChanges: [],
|
|
67
|
+
textContentChanges: [],
|
|
68
|
+
componentOverrides: [],
|
|
69
|
+
revision,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (lastPeekActive) {
|
|
73
|
+
// Force the canonical projection to resend after a peek even though its
|
|
74
|
+
// key is unchanged since the peek began.
|
|
75
|
+
lastPeekActive = false;
|
|
76
|
+
lastRulesKey = null;
|
|
77
|
+
}
|
|
78
|
+
setCanonicalRenderedInstanceOverrides(plan.instanceOverrides);
|
|
79
|
+
setCanonicalTextContentChanges(plan.textContentChanges);
|
|
53
80
|
const key = projectionKey(plan);
|
|
54
81
|
if (key !== lastRulesKey) {
|
|
55
82
|
lastRulesKey = key;
|
|
@@ -60,9 +87,11 @@ export function computeProjection() {
|
|
|
60
87
|
export function resetProjectionRevision() {
|
|
61
88
|
revision = 0;
|
|
62
89
|
lastRulesKey = null;
|
|
90
|
+
lastPeekActive = false;
|
|
63
91
|
for (const state of frameProjectionStates.values()) {
|
|
64
92
|
state.sentRevision = -1;
|
|
65
93
|
state.appliedRevision = -1;
|
|
94
|
+
state.canonicalSentRevision = -1;
|
|
66
95
|
}
|
|
67
96
|
projectionAcknowledgementVersion += 1;
|
|
68
97
|
notifyProjectionAcknowledgementListeners();
|
|
@@ -72,12 +101,18 @@ export function sendProjectionToCard(card, iframe) {
|
|
|
72
101
|
if (!win)
|
|
73
102
|
return;
|
|
74
103
|
const { css, revision: rev, instanceOverrides, structuralChanges, textContentChanges, componentOverrides } = computeProjection();
|
|
104
|
+
sendProjectionMessage(card.id, iframe, rev, css, instanceOverrides, structuralChanges, textContentChanges, componentOverrides, true);
|
|
105
|
+
}
|
|
106
|
+
function sendProjectionMessage(cardId, iframe, rev, css, instanceOverrides, structuralChanges, textContentChanges, componentOverrides, canonical = false) {
|
|
107
|
+
const win = iframe.contentWindow;
|
|
108
|
+
if (!win)
|
|
109
|
+
return;
|
|
75
110
|
const msg = {
|
|
76
111
|
type: "replace-styles",
|
|
77
112
|
protocolVersion: PROTOCOL_VERSION,
|
|
78
113
|
projectId: PROJECT_ID,
|
|
79
114
|
workspaceId: WORKSPACE_ID,
|
|
80
|
-
cardId
|
|
115
|
+
cardId,
|
|
81
116
|
css,
|
|
82
117
|
revision: rev,
|
|
83
118
|
instanceOverrides: [...instanceOverrides],
|
|
@@ -85,9 +120,79 @@ export function sendProjectionToCard(card, iframe) {
|
|
|
85
120
|
textContentChanges: [...textContentChanges],
|
|
86
121
|
componentOverrides: [...componentOverrides],
|
|
87
122
|
};
|
|
88
|
-
markProjectionSent(
|
|
123
|
+
markProjectionSent(cardId, iframe, rev, canonical);
|
|
89
124
|
win.postMessage(msg, window.location.origin);
|
|
90
125
|
}
|
|
126
|
+
/** Temporarily projects a snapshot through the renderer that owns the document. */
|
|
127
|
+
export async function projectWorkspaceSnapshotToDocument(doc, snapshot) {
|
|
128
|
+
const entry = [...frameProjectionStates.entries()].find(([, state]) => state.document === doc);
|
|
129
|
+
if (!entry)
|
|
130
|
+
return null;
|
|
131
|
+
const [cardId, state] = entry;
|
|
132
|
+
const plan = compileWorkspaceProjection({ ...snapshot, revision: 0 });
|
|
133
|
+
revision += 1;
|
|
134
|
+
sendProjectionMessage(cardId, state.iframe, revision, plan.managedStyles.css, plan.instanceOverrides, plan.structuralChanges, plan.textContentChanges, plan.componentOverrides);
|
|
135
|
+
if (state.appliedRevision === revision && state.sentRevision === revision)
|
|
136
|
+
return revision;
|
|
137
|
+
const requestedRevision = revision;
|
|
138
|
+
return new Promise((resolve) => {
|
|
139
|
+
let settled = false;
|
|
140
|
+
let timer;
|
|
141
|
+
const finish = (appliedRevision) => {
|
|
142
|
+
if (settled)
|
|
143
|
+
return;
|
|
144
|
+
settled = true;
|
|
145
|
+
unsubscribe();
|
|
146
|
+
if (timer !== undefined)
|
|
147
|
+
clearTimeout(timer);
|
|
148
|
+
resolve(appliedRevision);
|
|
149
|
+
};
|
|
150
|
+
const unsubscribe = subscribeCanvasProjectionAcknowledgements(() => {
|
|
151
|
+
const current = frameProjectionStates.get(cardId);
|
|
152
|
+
if (!current || current.document !== doc)
|
|
153
|
+
finish(null);
|
|
154
|
+
else if (current.sentRevision > requestedRevision || current.appliedRevision > requestedRevision)
|
|
155
|
+
finish(null);
|
|
156
|
+
else if (current.appliedRevision === requestedRevision)
|
|
157
|
+
finish(requestedRevision);
|
|
158
|
+
});
|
|
159
|
+
timer = setTimeout(() => finish(null), 2_000);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
/** Returns whether an acknowledged temporary projection is still authoritative. */
|
|
163
|
+
export function isCanvasProjectionRevisionCurrent(doc, expectedRevision) {
|
|
164
|
+
for (const state of frameProjectionStates.values()) {
|
|
165
|
+
if (state.document !== doc)
|
|
166
|
+
continue;
|
|
167
|
+
try {
|
|
168
|
+
if (state.iframe.contentDocument !== doc)
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
return state.sentRevision === expectedRevision && state.appliedRevision === expectedRevision;
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
/** Returns whether the live frame acknowledged its latest canonical workspace projection. */
|
|
179
|
+
export function isCanvasCanonicalProjectionRevisionCurrent(doc, expectedRevision) {
|
|
180
|
+
for (const state of frameProjectionStates.values()) {
|
|
181
|
+
if (state.document !== doc)
|
|
182
|
+
continue;
|
|
183
|
+
try {
|
|
184
|
+
if (state.iframe.contentDocument !== doc)
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
return state.canonicalSentRevision === expectedRevision
|
|
191
|
+
&& state.sentRevision === expectedRevision
|
|
192
|
+
&& state.appliedRevision === expectedRevision;
|
|
193
|
+
}
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
91
196
|
const frameRegistry = new Map();
|
|
92
197
|
const frameSourceRegistry = new Map();
|
|
93
198
|
export function registerCardFrameSource(cardId, iframe) {
|
|
@@ -109,6 +214,7 @@ export function registerCardFrame(cardId, iframe) {
|
|
|
109
214
|
previewDocument,
|
|
110
215
|
sentRevision: -1,
|
|
111
216
|
appliedRevision: -1,
|
|
217
|
+
canonicalSentRevision: -1,
|
|
112
218
|
});
|
|
113
219
|
}
|
|
114
220
|
else {
|
|
@@ -123,6 +229,8 @@ export function unregisterCardFrame(cardId) {
|
|
|
123
229
|
frameRegistry.delete(cardId);
|
|
124
230
|
invalidateCanvasPreviewDocument(cardId);
|
|
125
231
|
frameProjectionStates.delete(cardId);
|
|
232
|
+
projectionAcknowledgementVersion += 1;
|
|
233
|
+
notifyProjectionAcknowledgementListeners();
|
|
126
234
|
clearCanvasStructuralProjectionReports(cardId);
|
|
127
235
|
clearCanvasRenderedInstanceProjectionReports(cardId);
|
|
128
236
|
clearCanvasTextProjectionReports(cardId);
|
|
@@ -153,11 +261,13 @@ function getFrameDocument(iframe) {
|
|
|
153
261
|
return null;
|
|
154
262
|
}
|
|
155
263
|
}
|
|
156
|
-
function markProjectionSent(cardId, iframe, sentRevision) {
|
|
264
|
+
function markProjectionSent(cardId, iframe, sentRevision, canonical = false) {
|
|
157
265
|
const state = frameProjectionStates.get(cardId);
|
|
158
266
|
if (!state || state.iframe !== iframe)
|
|
159
267
|
return;
|
|
160
268
|
state.sentRevision = Math.max(state.sentRevision, sentRevision);
|
|
269
|
+
if (canonical)
|
|
270
|
+
state.canonicalSentRevision = sentRevision;
|
|
161
271
|
}
|
|
162
272
|
/** Records the highest complete projection revision accepted by one frame. */
|
|
163
273
|
export function recordCanvasProjectionApplied(cardId, appliedRevision) {
|
|
@@ -210,23 +320,6 @@ export function projectToAllReadyCards() {
|
|
|
210
320
|
return;
|
|
211
321
|
const { css, revision: rev, instanceOverrides, structuralChanges, textContentChanges, componentOverrides } = computeProjection();
|
|
212
322
|
for (const [cardId, iframe] of frameRegistry) {
|
|
213
|
-
|
|
214
|
-
if (!win)
|
|
215
|
-
continue;
|
|
216
|
-
const msg = {
|
|
217
|
-
type: "replace-styles",
|
|
218
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
219
|
-
projectId: PROJECT_ID,
|
|
220
|
-
workspaceId: WORKSPACE_ID,
|
|
221
|
-
cardId,
|
|
222
|
-
css,
|
|
223
|
-
revision: rev,
|
|
224
|
-
instanceOverrides: [...instanceOverrides],
|
|
225
|
-
structuralChanges: [...structuralChanges],
|
|
226
|
-
textContentChanges: [...textContentChanges],
|
|
227
|
-
componentOverrides: [...componentOverrides],
|
|
228
|
-
};
|
|
229
|
-
markProjectionSent(cardId, iframe, rev);
|
|
230
|
-
win.postMessage(msg, window.location.origin);
|
|
323
|
+
sendProjectionMessage(cardId, iframe, rev, css, instanceOverrides, structuralChanges, textContentChanges, componentOverrides, true);
|
|
231
324
|
}
|
|
232
325
|
}
|
|
@@ -4,7 +4,7 @@ import { findClosestAnchor, isEligibleNavigation, hasDifferentRoute } from "./li
|
|
|
4
4
|
import { installRendererElementSelector } from "./rendererElementSelector.js";
|
|
5
5
|
import { createFrameThrottle } from "../overlay/frameThrottle.js";
|
|
6
6
|
import { isNudgeUiDev } from "../runtime/devFlag.js";
|
|
7
|
-
import { getNudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
|
|
7
|
+
import { getNudgeUiRuntimeConfig, subscribeNudgeUiRuntime } from "../runtime/runtimeConfig.js";
|
|
8
8
|
let activeRendererBootstrap = null;
|
|
9
9
|
function ownsRendererBootstrap(owner) {
|
|
10
10
|
return owner.active && activeRendererBootstrap?.owner === owner;
|
|
@@ -20,10 +20,25 @@ function sendFrameReady(owner) {
|
|
|
20
20
|
protocolVersion: PROTOCOL_VERSION,
|
|
21
21
|
url: window.location.href,
|
|
22
22
|
title: document.title,
|
|
23
|
+
runtime: getNudgeUiRuntimeConfig(),
|
|
23
24
|
...identity,
|
|
24
25
|
};
|
|
25
26
|
sendToParent(msg);
|
|
26
27
|
}
|
|
28
|
+
function sendFrameRuntime(owner) {
|
|
29
|
+
if (!ownsRendererBootstrap(owner))
|
|
30
|
+
return;
|
|
31
|
+
const identity = getRendererIdentity();
|
|
32
|
+
if (!identity)
|
|
33
|
+
return;
|
|
34
|
+
const message = {
|
|
35
|
+
type: "frame-runtime",
|
|
36
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
37
|
+
runtime: getNudgeUiRuntimeConfig(),
|
|
38
|
+
...identity,
|
|
39
|
+
};
|
|
40
|
+
sendToParent(message);
|
|
41
|
+
}
|
|
27
42
|
function sendFrameMetadata(owner) {
|
|
28
43
|
if (!ownsRendererBootstrap(owner))
|
|
29
44
|
return;
|
|
@@ -132,6 +147,7 @@ export function bootstrapRenderer() {
|
|
|
132
147
|
activeRendererBootstrap = { owner, handle };
|
|
133
148
|
try {
|
|
134
149
|
observeFrameMetadata(owner);
|
|
150
|
+
owner.resourceDisposers.push(subscribeNudgeUiRuntime(() => sendFrameRuntime(owner)));
|
|
135
151
|
const disposeDiagnostics = startRendererProjectionDiagnostics();
|
|
136
152
|
if (disposeDiagnostics)
|
|
137
153
|
owner.resourceDisposers.push(disposeDiagnostics);
|
|
@@ -145,25 +161,10 @@ export function bootstrapRenderer() {
|
|
|
145
161
|
const anchor = findClosestAnchor(event.target);
|
|
146
162
|
if (!anchor)
|
|
147
163
|
return;
|
|
148
|
-
if (!isEligibleNavigation(anchor, event))
|
|
149
|
-
if (isPrimarySelfNavigation(anchor, event)) {
|
|
150
|
-
event.preventDefault();
|
|
151
|
-
const identity = getRendererIdentity();
|
|
152
|
-
if (!identity)
|
|
153
|
-
return;
|
|
154
|
-
const msg = {
|
|
155
|
-
type: "external-navigation",
|
|
156
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
157
|
-
url: anchor.href,
|
|
158
|
-
...identity,
|
|
159
|
-
};
|
|
160
|
-
sendToParent(msg);
|
|
161
|
-
}
|
|
164
|
+
if (!isEligibleNavigation(anchor, event))
|
|
162
165
|
return;
|
|
163
|
-
}
|
|
164
166
|
if (!hasDifferentRoute(anchor))
|
|
165
167
|
return;
|
|
166
|
-
event.preventDefault();
|
|
167
168
|
const identity = getRendererIdentity();
|
|
168
169
|
if (!identity)
|
|
169
170
|
return;
|
|
@@ -234,18 +235,10 @@ export function bootstrapRenderer() {
|
|
|
234
235
|
}
|
|
235
236
|
return handle;
|
|
236
237
|
}
|
|
237
|
-
function isPrimarySelfNavigation(anchor, event) {
|
|
238
|
-
if (event.ctrlKey || event.metaKey || event.shiftKey || event.button !== 0)
|
|
239
|
-
return false;
|
|
240
|
-
if (anchor.hasAttribute("download"))
|
|
241
|
-
return false;
|
|
242
|
-
if (anchor.target && anchor.target !== "" && anchor.target !== "_self")
|
|
243
|
-
return false;
|
|
244
|
-
return anchor.protocol === "http:" || anchor.protocol === "https:";
|
|
245
|
-
}
|
|
246
238
|
function installRendererPanProxy(owner) {
|
|
247
239
|
let spaceHeld = false;
|
|
248
240
|
let panning = false;
|
|
241
|
+
let boardGesturesEnabled = false;
|
|
249
242
|
const panMoveUpdate = createFrameThrottle((point) => {
|
|
250
243
|
if (!ownsRendererBootstrap(owner))
|
|
251
244
|
return;
|
|
@@ -290,13 +283,20 @@ function installRendererPanProxy(owner) {
|
|
|
290
283
|
if (event.data.type === "pan-modifier") {
|
|
291
284
|
spaceHeld = event.data.spaceHeld;
|
|
292
285
|
}
|
|
286
|
+
if (event.data.type === "board-gesture-state") {
|
|
287
|
+
boardGesturesEnabled = event.data.enabled;
|
|
288
|
+
if (!boardGesturesEnabled) {
|
|
289
|
+
spaceHeld = false;
|
|
290
|
+
endPan();
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
293
|
};
|
|
294
294
|
window.addEventListener("message", onMessage);
|
|
295
295
|
owner.listenerRemovers.push(() => window.removeEventListener("message", onMessage));
|
|
296
296
|
const onKeyDown = (event) => {
|
|
297
297
|
if (!ownsRendererBootstrap(owner))
|
|
298
298
|
return;
|
|
299
|
-
if (event.code === "Space" && !event.repeat && !isEditableTarget(event.target)) {
|
|
299
|
+
if (boardGesturesEnabled && event.code === "Space" && !event.repeat && !isEditableTarget(event.target)) {
|
|
300
300
|
spaceHeld = true;
|
|
301
301
|
if (getRendererIdentity())
|
|
302
302
|
event.preventDefault();
|
|
@@ -342,7 +342,7 @@ function installRendererPanProxy(owner) {
|
|
|
342
342
|
const onPointerDown = (event) => {
|
|
343
343
|
if (!ownsRendererBootstrap(owner))
|
|
344
344
|
return;
|
|
345
|
-
if (!spaceHeld || event.button !== 0 || isEditableTarget(event.target))
|
|
345
|
+
if (!boardGesturesEnabled || !spaceHeld || event.button !== 0 || isEditableTarget(event.target))
|
|
346
346
|
return;
|
|
347
347
|
const identity = getRendererIdentity();
|
|
348
348
|
if (!identity)
|
|
@@ -388,7 +388,7 @@ function installRendererPanProxy(owner) {
|
|
|
388
388
|
const onWheel = (event) => {
|
|
389
389
|
if (!ownsRendererBootstrap(owner))
|
|
390
390
|
return;
|
|
391
|
-
if (!event.ctrlKey && !event.metaKey)
|
|
391
|
+
if (!boardGesturesEnabled || (!event.ctrlKey && !event.metaKey))
|
|
392
392
|
return;
|
|
393
393
|
const identity = getRendererIdentity();
|
|
394
394
|
if (!identity)
|