nudge-ui 0.2.2 → 0.2.4
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/README.md +164 -46
- package/dist/client.mjs +260 -61
- package/dist/css/value-semantics/colorSemantics.d.ts +4 -0
- package/dist/css/value-semantics/colorSemantics.js +17 -0
- package/dist/hosts/astro/astroRuntimeConfig.js +1 -0
- package/dist/hosts/astro/clientTransport.js +38 -32
- package/dist/hosts/astro/integration.js +5 -1
- package/dist/hosts/astro/markdownIdentity.d.ts +28 -0
- package/dist/hosts/astro/markdownIdentity.js +81 -0
- package/dist/hosts/next/manifest.js +1 -1
- package/dist/hosts/next/sidecar.js +5 -1
- package/dist/hosts/static/manifest.js +1 -1
- package/dist/hosts/static/server.js +3 -0
- package/dist/hosts/vite/vite.d.ts +3 -0
- package/dist/hosts/vite/vite.js +24 -4
- package/dist/inspector/agent/McpConnectionDialog.js +13 -19
- package/dist/inspector/agent/activity.d.ts +18 -0
- package/dist/inspector/agent/activity.js +70 -0
- package/dist/inspector/agent/client.d.ts +2 -0
- package/dist/inspector/agent/client.js +29 -1
- package/dist/inspector/agent/connectionStatus.js +1 -1
- package/dist/inspector/agent/httpTransport.js +9 -2
- package/dist/inspector/agent/protocol.d.ts +6 -3
- package/dist/inspector/agent/protocol.js +1 -1
- package/dist/inspector/agent/verification.d.ts +15 -7
- package/dist/inspector/agent/verification.js +113 -41
- package/dist/inspector/canvas/AgentActivityOverlay.d.ts +13 -0
- package/dist/inspector/canvas/AgentActivityOverlay.js +111 -0
- package/dist/inspector/canvas/CanvasCard.d.ts +9 -2
- package/dist/inspector/canvas/CanvasCard.js +135 -38
- package/dist/inspector/canvas/CanvasElementOverlay.js +166 -16
- package/dist/inspector/canvas/CanvasToolIcons.d.ts +10 -0
- package/dist/inspector/canvas/CanvasToolIcons.js +20 -0
- package/dist/inspector/canvas/CanvasToolbar.js +8 -4
- package/dist/inspector/canvas/CanvasWorkspace.js +270 -122
- package/dist/inspector/canvas/StaleChangeIndicator.js +3 -13
- package/dist/inspector/canvas/agentPresentation.d.ts +8 -8
- package/dist/inspector/canvas/agentPresentation.js +64 -52
- package/dist/inspector/canvas/canvasGestures.d.ts +1 -1
- package/dist/inspector/canvas/canvasGestures.js +1 -1
- package/dist/inspector/canvas/canvasStore.d.ts +46 -82
- package/dist/inspector/canvas/canvasStore.js +251 -284
- package/dist/inspector/canvas/frameContent.d.ts +21 -0
- package/dist/inspector/canvas/frameContent.js +44 -0
- package/dist/inspector/canvas/frameProtocol.d.ts +21 -4
- package/dist/inspector/canvas/frameProtocol.js +3 -3
- package/dist/inspector/canvas/frameScrollbarStyles.d.ts +3 -0
- package/dist/inspector/canvas/frameScrollbarStyles.js +21 -0
- package/dist/inspector/canvas/keyboardShortcuts.d.ts +3 -1
- package/dist/inspector/canvas/keyboardShortcuts.js +4 -4
- package/dist/inspector/canvas/layout.d.ts +52 -0
- package/dist/inspector/canvas/layout.js +106 -0
- package/dist/inspector/canvas/projection.d.ts +15 -5
- package/dist/inspector/canvas/projection.js +69 -13
- package/dist/inspector/canvas/rendererBootstrap.js +32 -4
- package/dist/inspector/canvas/rendererElementSelector.js +47 -6
- package/dist/inspector/canvas/rendererStylesheet.js +2 -2
- package/dist/inspector/canvas/resizeHandleScale.js +1 -1
- package/dist/inspector/canvas/sessionStore.d.ts +11 -26
- package/dist/inspector/canvas/sessionStore.js +43 -183
- package/dist/inspector/canvas/staleChangeDetector.js +9 -3
- package/dist/inspector/canvas/useCanvasLayoutAnimation.d.ts +5 -0
- package/dist/inspector/canvas/useCanvasLayoutAnimation.js +107 -0
- package/dist/inspector/canvas/viewStore.d.ts +38 -0
- package/dist/inspector/canvas/viewStore.js +104 -0
- package/dist/inspector/canvas/wheelPan.d.ts +8 -0
- package/dist/inspector/canvas/wheelPan.js +8 -0
- package/dist/inspector/changes/changesLog.d.ts +9 -6
- package/dist/inspector/changes/changesLog.js +48 -32
- package/dist/inspector/changes/codecs.d.ts +1 -0
- package/dist/inspector/changes/codecs.js +10 -1
- package/dist/inspector/changes/draftChanges.d.ts +58 -0
- package/dist/inspector/changes/draftChanges.js +304 -0
- package/dist/inspector/changes/editModel.d.ts +10 -0
- package/dist/inspector/changes/editModel.js +9 -2
- package/dist/inspector/changes/previewDiagnostics.d.ts +4 -2
- package/dist/inspector/changes/previewDiagnostics.js +11 -25
- package/dist/inspector/changes/types.d.ts +7 -0
- package/dist/inspector/clientManifest.d.ts +1 -1
- package/dist/inspector/comments/CommentsOverlay.d.ts +2 -0
- package/dist/inspector/comments/CommentsOverlay.js +250 -0
- package/dist/inspector/comments/element.d.ts +6 -0
- package/dist/inspector/comments/element.js +54 -0
- package/dist/inspector/comments/store.d.ts +29 -0
- package/dist/inspector/comments/store.js +121 -0
- package/dist/inspector/comments/verification.d.ts +5 -0
- package/dist/inspector/comments/verification.js +52 -0
- package/dist/inspector/componentSemantics/adapterRegistry.d.ts +6 -1
- package/dist/inspector/componentSemantics/adapterRegistry.js +23 -1
- package/dist/inspector/componentSemantics/reactRuntime.d.ts +2 -1
- package/dist/inspector/componentSemantics/reactRuntime.js +38 -0
- package/dist/inspector/componentSemantics/runtimeBridge.d.ts +4 -2
- package/dist/inspector/componentSemantics/runtimeBridge.js +17 -0
- package/dist/inspector/componentSemantics/types.d.ts +11 -0
- package/dist/inspector/drafts/model.d.ts +35 -0
- package/dist/inspector/drafts/model.js +45 -0
- package/dist/inspector/drafts/store.d.ts +28 -0
- package/dist/inspector/drafts/store.js +231 -0
- package/dist/inspector/index.js +20 -27
- package/dist/inspector/inline-text/inlineTextEditor.js +7 -0
- package/dist/inspector/inspection/useBrowserCssInspection.js +15 -1
- package/dist/inspector/iterations/capture.d.ts +2 -0
- package/dist/inspector/iterations/capture.js +174 -0
- package/dist/inspector/iterations/client.d.ts +7 -0
- package/dist/inspector/iterations/client.js +52 -0
- package/dist/inspector/iterations/coordinator.d.ts +15 -0
- package/dist/inspector/iterations/coordinator.js +130 -0
- package/dist/inspector/iterations/prompt.d.ts +3 -0
- package/dist/inspector/iterations/prompt.js +26 -0
- package/dist/inspector/overlay/DomNavigator.js +21 -15
- package/dist/inspector/overlay/interactionStyles.js +3 -1
- package/dist/inspector/overlay/spacingGestures.d.ts +13 -1
- package/dist/inspector/overlay/spacingGestures.js +82 -5
- package/dist/inspector/projection/{workspaceProjection.d.ts → draftProjection.d.ts} +6 -6
- package/dist/inspector/projection/{workspaceProjection.js → draftProjection.js} +4 -4
- package/dist/inspector/projection/renderedInstance.d.ts +17 -3
- package/dist/inspector/projection/renderedInstance.js +62 -11
- package/dist/inspector/projection/structuralProjection.d.ts +2 -1
- package/dist/inspector/projection/structuralProjection.js +21 -17
- package/dist/inspector/projection/textProjection.d.ts +2 -1
- package/dist/inspector/projection/textProjection.js +64 -15
- package/dist/inspector/prompt/PromptSettingsDialog.js +1 -5
- package/dist/inspector/prompt/clipboardHandoff.d.ts +15 -18
- package/dist/inspector/prompt/clipboardHandoff.js +97 -143
- package/dist/inspector/prompt/generatePrompt.d.ts +4 -1
- package/dist/inspector/prompt/generatePrompt.js +22 -17
- package/dist/inspector/runtime/runtimeConfig.d.ts +9 -0
- package/dist/inspector/runtime/runtimeConfig.js +24 -0
- package/dist/inspector/selection/sourceSite.d.ts +12 -0
- package/dist/inspector/selection/sourceSite.js +28 -0
- package/dist/inspector/settings/SettingsDialog.js +21 -8
- package/dist/inspector/shell/AgentStatusButton.d.ts +11 -0
- package/dist/inspector/shell/AgentStatusButton.js +36 -0
- package/dist/inspector/shell/AppShell.js +4 -2
- package/dist/inspector/shell/ChangesLog.js +46 -26
- package/dist/inspector/shell/CopyPromptButton.js +184 -93
- package/dist/inspector/shell/EmptyState.js +9 -8
- package/dist/inspector/shell/InspectorShell.js +13 -21
- package/dist/inspector/shell/PeekOriginalButton.js +24 -23
- package/dist/inspector/shell/originalPreview.js +5 -5
- package/dist/inspector/shell/shortcuts.d.ts +3 -0
- package/dist/inspector/shell/shortcuts.js +11 -0
- package/dist/inspector/sketch/SketchEditor.js +14 -14
- package/dist/inspector/sketch/SketchEntryButton.js +1 -1
- package/dist/inspector/sketch/SketchFrameOverlay.d.ts +3 -1
- package/dist/inspector/sketch/SketchFrameOverlay.js +11 -8
- package/dist/inspector/sketch/SketchLayersPanel.js +13 -5
- package/dist/inspector/sketch/SketchOverlay.js +7 -7
- package/dist/inspector/sketch/SketchWorkspace.js +18 -12
- package/dist/inspector/sketch/interaction.d.ts +1 -0
- package/dist/inspector/sketch/interaction.js +8 -4
- package/dist/inspector/sketch/model.d.ts +5 -0
- package/dist/inspector/sketch/model.js +6 -2
- package/dist/inspector/sketch/raster.d.ts +1 -2
- package/dist/inspector/sketch/raster.js +68 -4
- package/dist/inspector/styleEditors/BackgroundEditor.d.ts +4 -0
- package/dist/inspector/styleEditors/BackgroundEditor.js +195 -0
- package/dist/inspector/styleEditors/BorderEditor.js +49 -78
- package/dist/inspector/styleEditors/BorderRadiusEditor.js +6 -1
- package/dist/inspector/styleEditors/BoxShadowEditor.d.ts +1 -2
- package/dist/inspector/styleEditors/BoxShadowEditor.js +132 -4
- package/dist/inspector/styleEditors/ColorPicker.d.ts +5 -1
- package/dist/inspector/styleEditors/ColorPicker.js +10 -4
- package/dist/inspector/styleEditors/GapField.js +3 -5
- package/dist/inspector/styleEditors/GridChildSection.d.ts +1 -1
- package/dist/inspector/styleEditors/GridChildSection.js +18 -9
- package/dist/inspector/styleEditors/GridPicker.d.ts +1 -1
- package/dist/inspector/styleEditors/GridPicker.js +8 -2
- package/dist/inspector/styleEditors/GridSection.js +1 -1
- package/dist/inspector/styleEditors/GridValueField.js +19 -14
- package/dist/inspector/styleEditors/ImageBackgroundEditor.d.ts +18 -0
- package/dist/inspector/styleEditors/ImageBackgroundEditor.js +118 -0
- package/dist/inspector/styleEditors/LayoutBlockedIndicator.d.ts +2 -2
- package/dist/inspector/styleEditors/LayoutBlockedIndicator.js +3 -3
- package/dist/inspector/styleEditors/LayoutComboField.js +6 -4
- package/dist/inspector/styleEditors/LayoutDropdown.js +6 -3
- package/dist/inspector/styleEditors/LayoutSection.js +32 -11
- package/dist/inspector/styleEditors/SpacingBox.js +7 -5
- package/dist/inspector/styleEditors/Typography.js +11 -3
- package/dist/inspector/styleEditors/backgroundLayers.d.ts +24 -0
- package/dist/inspector/styleEditors/backgroundLayers.js +51 -0
- package/dist/inspector/styleEditors/gradientValue.d.ts +17 -0
- package/dist/inspector/styleEditors/gradientValue.js +114 -0
- package/dist/inspector/styleEditors/inlineAuthored.d.ts +10 -0
- package/dist/inspector/styleEditors/inlineAuthored.js +114 -0
- package/dist/inspector/styleEditors/layoutValue.d.ts +0 -8
- package/dist/inspector/styleEditors/layoutValue.js +0 -42
- package/dist/inspector/styleEditors/nudgeValue.d.ts +2 -2
- package/dist/inspector/styleEditors/nudgeValue.js +36 -8
- package/dist/inspector/tokens/TokenField.d.ts +7 -0
- package/dist/inspector/tokens/TokenField.js +35 -25
- package/dist/inspector/tokens/TokenLabel.js +5 -14
- package/dist/inspector/tokens/editActions.d.ts +1 -1
- package/dist/inspector/tokens/editActions.js +7 -1
- package/dist/inspector/ui/AtRuleContext.js +4 -6
- package/dist/inspector/ui/Button.d.ts +6 -2
- package/dist/inspector/ui/Button.js +4 -3
- package/dist/inspector/ui/ControlSurface.d.ts +2 -2
- package/dist/inspector/ui/ControlSurface.js +4 -3
- package/dist/inspector/ui/InlineStyleWarning.d.ts +11 -0
- package/dist/inspector/ui/InlineStyleWarning.js +13 -0
- package/dist/inspector/ui/InspectorPopover.d.ts +2 -1
- package/dist/inspector/ui/InspectorPopover.js +4 -5
- package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
- package/dist/inspector/ui/PopoverListbox.js +8 -7
- package/dist/inspector/ui/SegmentedControl.d.ts +2 -1
- package/dist/inspector/ui/SegmentedControl.js +2 -2
- package/dist/inspector/ui/Select.d.ts +6 -1
- package/dist/inspector/ui/Select.js +7 -11
- package/dist/inspector/ui/SideValuesField.js +1 -1
- package/dist/inspector/ui/Tooltip.d.ts +26 -0
- package/dist/inspector/ui/Tooltip.js +32 -0
- package/dist/inspector/ui/classNames.d.ts +2 -0
- package/dist/inspector/ui/classNames.js +4 -0
- package/dist/inspector/ui/customCursors.d.ts +23 -0
- package/dist/inspector/ui/customCursors.js +122 -0
- package/dist/inspector/ui/dragCursor.d.ts +0 -2
- package/dist/inspector/ui/dragCursor.js +2 -10
- package/dist/inspector/ui/portalContainer.d.ts +2 -0
- package/dist/inspector/ui/portalContainer.js +6 -0
- package/dist/inspector/ui/styles.js +29 -21
- package/dist/inspector/workspace/commands.d.ts +9 -0
- package/dist/inspector/workspace/commands.js +82 -0
- package/dist/inspector/workspace/controller.d.ts +4 -0
- package/dist/inspector/workspace/controller.js +66 -0
- package/dist/inspector/workspace/handoff.d.ts +42 -0
- package/dist/inspector/workspace/handoff.js +115 -0
- package/dist/inspector/workspace/sentItems.d.ts +19 -0
- package/dist/inspector/workspace/sentItems.js +51 -0
- package/dist/inspector/workspace/timeline.d.ts +30 -0
- package/dist/inspector/workspace/timeline.js +108 -0
- package/dist/internal/agent-protocol.d.ts +19 -2
- package/dist/internal/agent-protocol.js +13 -0
- package/dist/nudge-ui.mjs +558 -311
- package/dist/project/artifacts.d.ts +13 -0
- package/dist/project/artifacts.js +253 -0
- package/dist/transport/artifacts.d.ts +8 -0
- package/dist/transport/artifacts.js +9 -0
- package/dist/transport/editor.js +3 -1
- package/dist/transport/routes.d.ts +2 -0
- package/dist/transport/routes.js +2 -0
- package/package.json +7 -3
- package/dist/inspector/changes/workspaceChanges.d.ts +0 -47
- package/dist/inspector/changes/workspaceChanges.js +0 -265
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type DraftTarget } from "../drafts/model.js";
|
|
2
|
+
/** Content identity is independent of frame geometry and its editable draft. */
|
|
3
|
+
export type FrameContent = {
|
|
4
|
+
kind: "route";
|
|
5
|
+
url: string;
|
|
6
|
+
navigationUrl?: string;
|
|
7
|
+
} | {
|
|
8
|
+
kind: "iteration";
|
|
9
|
+
artifactId: string;
|
|
10
|
+
sourceUrl: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function contentSourceUrl(content: FrameContent | undefined): string;
|
|
13
|
+
export declare function iterationId(content: FrameContent | undefined): string | undefined;
|
|
14
|
+
export declare function contentNavigationUrl(content: FrameContent): string | undefined;
|
|
15
|
+
export declare function contentDocumentUrl(content: FrameContent): string;
|
|
16
|
+
export declare function contentEditTarget(content: FrameContent): DraftTarget;
|
|
17
|
+
export declare function getLinkedFrameIds(frames: readonly {
|
|
18
|
+
id: string;
|
|
19
|
+
content: FrameContent;
|
|
20
|
+
}[], activeId: string | null): readonly string[];
|
|
21
|
+
export declare function isFrameContent(value: unknown, origin: string): value is FrameContent;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { applicationTarget, htmlTarget } from "../drafts/model.js";
|
|
2
|
+
import { artifactDocumentUrl } from "../iterations/client.js";
|
|
3
|
+
export function contentSourceUrl(content) {
|
|
4
|
+
return content ? content.kind === "route" ? content.url : content.sourceUrl : "";
|
|
5
|
+
}
|
|
6
|
+
export function iterationId(content) {
|
|
7
|
+
return content?.kind === "iteration" ? content.artifactId : undefined;
|
|
8
|
+
}
|
|
9
|
+
export function contentNavigationUrl(content) {
|
|
10
|
+
return content.kind === "route" ? content.navigationUrl : undefined;
|
|
11
|
+
}
|
|
12
|
+
export function contentDocumentUrl(content) {
|
|
13
|
+
return content.kind === "route" ? content.navigationUrl ?? content.url : artifactDocumentUrl(content.artifactId);
|
|
14
|
+
}
|
|
15
|
+
export function contentEditTarget(content) {
|
|
16
|
+
return content.kind === "route" ? applicationTarget(content.url) : htmlTarget(content.artifactId);
|
|
17
|
+
}
|
|
18
|
+
export function getLinkedFrameIds(frames, activeId) {
|
|
19
|
+
const active = frames.find((frame) => frame.id === activeId);
|
|
20
|
+
if (active?.content.kind !== "route")
|
|
21
|
+
return [];
|
|
22
|
+
const route = applicationTarget(active.content.url).route;
|
|
23
|
+
const matching = frames.filter((frame) => frame.content.kind === "route"
|
|
24
|
+
&& applicationTarget(frame.content.url).route === route);
|
|
25
|
+
return matching.length > 1 ? matching.map((frame) => frame.id) : [];
|
|
26
|
+
}
|
|
27
|
+
export function isFrameContent(value, origin) {
|
|
28
|
+
if (!value || typeof value !== "object")
|
|
29
|
+
return false;
|
|
30
|
+
const content = value;
|
|
31
|
+
const url = content.kind === "route" ? content.url : content.sourceUrl;
|
|
32
|
+
if (typeof url !== "string")
|
|
33
|
+
return false;
|
|
34
|
+
try {
|
|
35
|
+
if (new URL(url).origin !== origin)
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
if (content.kind === "iteration")
|
|
42
|
+
return typeof content.artifactId === "string" && /^[a-f0-9-]{36}$/i.test(content.artifactId);
|
|
43
|
+
return content.kind === "route" && content.navigationUrl === undefined;
|
|
44
|
+
}
|
|
@@ -2,7 +2,7 @@ import type { ComponentOverride } from "../componentSemantics/types.js";
|
|
|
2
2
|
import type { RenderedInstanceOverride } from "../changes/editModel.js";
|
|
3
3
|
import type { NudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
|
|
4
4
|
import type { SpacingDescriptor } from "../overlay/spacingGestures.js";
|
|
5
|
-
export declare const PROTOCOL_VERSION =
|
|
5
|
+
export declare const PROTOCOL_VERSION = 21;
|
|
6
6
|
export interface FrameMessage {
|
|
7
7
|
type: string;
|
|
8
8
|
protocolVersion: number;
|
|
@@ -130,8 +130,12 @@ export interface ElementHoverMessage extends RendererMessage {
|
|
|
130
130
|
x: number;
|
|
131
131
|
y: number;
|
|
132
132
|
} | null;
|
|
133
|
-
/** The
|
|
133
|
+
/** The spacing handle under the pointer. Drives the resize cursor and drag
|
|
134
|
+
* start; only present when the pointer is inside the handle hit area. */
|
|
134
135
|
spacing?: SpacingDescriptor | null;
|
|
136
|
+
/** The padding bar or layout gap area under the pointer, regardless of the
|
|
137
|
+
* handle. Drives the hover fill overlay across the whole area. */
|
|
138
|
+
hoverSpacing?: SpacingDescriptor | null;
|
|
135
139
|
}
|
|
136
140
|
/** Modifier state stays inside one renderer frame; the parent never infers it
|
|
137
141
|
* from its own keyboard events because focus lives in the iframe. */
|
|
@@ -235,7 +239,7 @@ export interface InspectorToggleRequestMessage extends RendererMessage {
|
|
|
235
239
|
export interface InspectorOpenRequestMessage extends RendererMessage {
|
|
236
240
|
type: "inspector-open-request";
|
|
237
241
|
}
|
|
238
|
-
export type KeyboardShortcutCode = "Backslash" | "KeyI" | "KeyV" | "
|
|
242
|
+
export type KeyboardShortcutCode = "Backslash" | "KeyI" | "KeyV" | "KeyC" | "KeyP" | "KeyS";
|
|
239
243
|
export type KeyboardShortcutPhase = "keydown" | "keyup";
|
|
240
244
|
/** Forwards controller-owned keyboard shortcuts from an iframe document. */
|
|
241
245
|
export interface KeyboardShortcutMessage extends RendererMessage {
|
|
@@ -274,6 +278,8 @@ export interface MeasureModifierMessage extends RendererMessage {
|
|
|
274
278
|
export interface BoardGestureStateMessage extends RendererMessage {
|
|
275
279
|
type: "board-gesture-state";
|
|
276
280
|
enabled: boolean;
|
|
281
|
+
/** Ordinary wheel gestures pan the board instead of scrolling the app. */
|
|
282
|
+
panScroll?: boolean;
|
|
277
283
|
}
|
|
278
284
|
/** Proxies modified wheel gestures that originate inside an iframe card. */
|
|
279
285
|
export interface ZoomMessage extends RendererMessage {
|
|
@@ -284,7 +290,18 @@ export interface ZoomMessage extends RendererMessage {
|
|
|
284
290
|
y: number;
|
|
285
291
|
};
|
|
286
292
|
}
|
|
287
|
-
|
|
293
|
+
/** Proxies ordinary wheel gestures as normalized pixel distances. */
|
|
294
|
+
export interface WheelPanMessage extends RendererMessage {
|
|
295
|
+
type: "wheel-pan";
|
|
296
|
+
deltaX: number;
|
|
297
|
+
deltaY: number;
|
|
298
|
+
}
|
|
299
|
+
/** Keeps the A key state synchronized when keyboard focus moves into an iframe. */
|
|
300
|
+
export interface AppInteractionModifierMessage extends RendererMessage {
|
|
301
|
+
type: "app-interaction-modifier";
|
|
302
|
+
held: boolean;
|
|
303
|
+
}
|
|
304
|
+
export type FrameProtocolMessage = ParentReadyMessage | RendererHelloMessage | FrameReadyMessage | FrameRuntimeMessage | FrameMetadataMessage | FrameLoadError | ReplaceStylesMessage | ProjectionAppliedMessage | StructuralProjectionReportMessage | RenderedInstanceProjectionReportMessage | TextProjectionReportMessage | NavigationIntentMessage | LinkTargetStateMessage | ElementHoverMessage | ElementMeasureStateMessage | ElementClickMessage | InlineTextIntentMessage | ElementDeselectMessage | ElementDragStartMessage | ElementDragMoveMessage | ElementDragEndMessage | ElementDeleteMessage | ElementNudgeMessage | HistoryRequestMessage | InspectorToggleRequestMessage | InspectorOpenRequestMessage | KeyboardShortcutMessage | PanStartMessage | PanMoveMessage | PanEndMessage | PanModifierMessage | MeasureModifierMessage | BoardGestureStateMessage | ZoomMessage | WheelPanMessage | AppInteractionModifierMessage;
|
|
288
305
|
export declare function setRendererIdentity(identity: FrameIdentity): void;
|
|
289
306
|
export declare function clearRendererIdentity(expected?: FrameIdentity): void;
|
|
290
307
|
export declare function getRendererIdentity(): FrameIdentity | null;
|
|
@@ -1,6 +1,7 @@
|
|
|
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
|
+
// v21 adds the Comment tool cursor and C shortcut.
|
|
4
5
|
// v20 adds Shift state to element drag messages so spacing handles can snap
|
|
5
6
|
// changes to 8px increments.
|
|
6
7
|
// v19 adds spacing drag gestures (hover point, spacing descriptor, start
|
|
@@ -17,7 +18,7 @@ import { isStructuralProjectionReport } from "../projection/structuralProjection
|
|
|
17
18
|
// rereading a Canvas iframe until the renderer has applied its revision. v11
|
|
18
19
|
// added the renderer-hello handshake solicitation for runtimes whose boot
|
|
19
20
|
// completes after the controller's load-time parent-ready.
|
|
20
|
-
export const PROTOCOL_VERSION =
|
|
21
|
+
export const PROTOCOL_VERSION = 21;
|
|
21
22
|
let rendererIdentity = null;
|
|
22
23
|
export function setRendererIdentity(identity) {
|
|
23
24
|
rendererIdentity = identity;
|
|
@@ -40,9 +41,8 @@ export function isRendererMessageFor(value, identity) {
|
|
|
40
41
|
}
|
|
41
42
|
export function isKeyboardShortcutCode(value) {
|
|
42
43
|
return value === "Backslash"
|
|
43
|
-
|| value === "KeyI"
|
|
44
44
|
|| value === "KeyV"
|
|
45
|
-
|| value === "
|
|
45
|
+
|| value === "KeyC"
|
|
46
46
|
|| value === "KeyP"
|
|
47
47
|
|| value === "KeyS";
|
|
48
48
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const FRAME_SCROLLBAR_STYLE_ID = "nudge-ui-frame-scrollbar-styles";
|
|
2
|
+
// `:where()` keeps specificity at zero so any application scrollbar rule wins.
|
|
3
|
+
const FRAME_SCROLLBAR_CSS = `
|
|
4
|
+
:where(html) {
|
|
5
|
+
scrollbar-color: rgba(128, 128, 128, 0.5) transparent;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
:where(*) {
|
|
9
|
+
scrollbar-width: thin;
|
|
10
|
+
}
|
|
11
|
+
`;
|
|
12
|
+
/** Gives frame documents thin scrollbars over a transparent track by default. */
|
|
13
|
+
export function installFrameScrollbarStyles(doc) {
|
|
14
|
+
if (!doc.head || doc.getElementById(FRAME_SCROLLBAR_STYLE_ID))
|
|
15
|
+
return () => undefined;
|
|
16
|
+
const style = doc.createElement("style");
|
|
17
|
+
style.id = FRAME_SCROLLBAR_STYLE_ID;
|
|
18
|
+
style.textContent = FRAME_SCROLLBAR_CSS;
|
|
19
|
+
doc.head.append(style);
|
|
20
|
+
return () => style.remove();
|
|
21
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/** `select` leaves the application interactive; `design` turns clicks into inspector selection. */
|
|
2
|
-
export type CanvasInteractionTool = "select" | "design" | "
|
|
2
|
+
export type CanvasInteractionTool = "select" | "design" | "comment" | "sketch";
|
|
3
|
+
/** Physical key used to temporarily interact with the app in the canvas. */
|
|
4
|
+
export declare const APP_INTERACTION_KEY = "KeyA";
|
|
3
5
|
export declare function canvasToolForCode(code: string): CanvasInteractionTool | null;
|
|
4
6
|
export declare function canvasToolForEvent(event: KeyboardEvent): CanvasInteractionTool | null;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
/** Physical key used to temporarily interact with the app in the canvas. */
|
|
2
|
+
export const APP_INTERACTION_KEY = "KeyA";
|
|
1
3
|
export function canvasToolForCode(code) {
|
|
2
|
-
if (code === "KeyI")
|
|
3
|
-
return "select";
|
|
4
4
|
if (code === "KeyV")
|
|
5
5
|
return "design";
|
|
6
|
-
if (code === "
|
|
7
|
-
return "
|
|
6
|
+
if (code === "KeyC")
|
|
7
|
+
return "comment";
|
|
8
8
|
if (code === "KeyP")
|
|
9
9
|
return "sketch";
|
|
10
10
|
return null;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface LayoutCard {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly x: number;
|
|
4
|
+
readonly y: number;
|
|
5
|
+
readonly width: number;
|
|
6
|
+
readonly height: number;
|
|
7
|
+
}
|
|
8
|
+
export interface Bounds {
|
|
9
|
+
readonly minX: number;
|
|
10
|
+
readonly minY: number;
|
|
11
|
+
readonly maxX: number;
|
|
12
|
+
readonly maxY: number;
|
|
13
|
+
}
|
|
14
|
+
/** The layout fields a creation may change on existing frames. */
|
|
15
|
+
export interface LayoutShift {
|
|
16
|
+
readonly id: string;
|
|
17
|
+
readonly from: Pick<LayoutCard, "x" | "y">;
|
|
18
|
+
readonly to: Pick<LayoutCard, "x" | "y">;
|
|
19
|
+
}
|
|
20
|
+
export declare function boundsOf(cards: readonly LayoutCard[]): Bounds;
|
|
21
|
+
/** Places a new frame to the right of every frame, on the first frame's row. */
|
|
22
|
+
export declare function nextCardPosition(cards: readonly LayoutCard[], gap: number): {
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
};
|
|
26
|
+
export declare function pushOverlappingCards<T extends LayoutCard>(cards: readonly T[], protectedIds: ReadonlySet<string>, gap: number): T[];
|
|
27
|
+
export declare function iterationPosition(cards: readonly LayoutCard[], source: LayoutCard, gap: number): {
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
};
|
|
31
|
+
/** Zooms and centers content inside the padded viewport; null for empty content. */
|
|
32
|
+
export declare function fitCamera(bounds: Bounds, viewport: {
|
|
33
|
+
width: number;
|
|
34
|
+
height: number;
|
|
35
|
+
}, padding: number): {
|
|
36
|
+
x: number;
|
|
37
|
+
y: number;
|
|
38
|
+
zoom: number;
|
|
39
|
+
} | null;
|
|
40
|
+
export declare function centerCamera(bounds: Bounds, zoom: number, viewport: {
|
|
41
|
+
width: number;
|
|
42
|
+
height: number;
|
|
43
|
+
}): {
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
zoom: number;
|
|
47
|
+
};
|
|
48
|
+
export declare function layoutShifts(before: readonly LayoutCard[], after: readonly LayoutCard[]): LayoutShift[];
|
|
49
|
+
/** Replays recorded shifts as deltas, so frames moved since the creation keep their later moves. */
|
|
50
|
+
export declare function applyLayoutShifts<T extends LayoutCard>(cards: readonly T[], shifts: readonly LayoutShift[], forward: boolean): T[];
|
|
51
|
+
/** Reinserts recorded frames after their nearest recorded predecessor that still exists. */
|
|
52
|
+
export declare function reinsertInRecordedOrder<T extends LayoutCard>(cards: readonly T[], recorded: readonly T[], ids: ReadonlySet<string>): T[];
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { MAX_CAMERA_ZOOM, MIN_CAMERA_ZOOM } from "./viewStore.js";
|
|
2
|
+
export function boundsOf(cards) {
|
|
3
|
+
let minX = Infinity;
|
|
4
|
+
let minY = Infinity;
|
|
5
|
+
let maxX = -Infinity;
|
|
6
|
+
let maxY = -Infinity;
|
|
7
|
+
for (const card of cards) {
|
|
8
|
+
minX = Math.min(minX, card.x);
|
|
9
|
+
minY = Math.min(minY, card.y);
|
|
10
|
+
maxX = Math.max(maxX, card.x + card.width);
|
|
11
|
+
maxY = Math.max(maxY, card.y + card.height);
|
|
12
|
+
}
|
|
13
|
+
return { minX, minY, maxX, maxY };
|
|
14
|
+
}
|
|
15
|
+
/** Places a new frame to the right of every frame, on the first frame's row. */
|
|
16
|
+
export function nextCardPosition(cards, gap) {
|
|
17
|
+
if (cards.length === 0)
|
|
18
|
+
return { x: 0, y: 0 };
|
|
19
|
+
return { x: Math.max(...cards.map((card) => card.x + card.width + gap)), y: cards[0].y };
|
|
20
|
+
}
|
|
21
|
+
export function pushOverlappingCards(cards, protectedIds, gap) {
|
|
22
|
+
const fixed = cards.filter((card) => protectedIds.has(card.id)).map((card) => boundsOf([card]));
|
|
23
|
+
const moving = cards.filter((card) => !protectedIds.has(card.id)).sort((a, b) => a.x - b.x);
|
|
24
|
+
const shifts = new Map();
|
|
25
|
+
for (const card of moving) {
|
|
26
|
+
let bounds = boundsOf([card]);
|
|
27
|
+
let dx = 0;
|
|
28
|
+
let collision = true;
|
|
29
|
+
while (collision) {
|
|
30
|
+
collision = false;
|
|
31
|
+
for (const other of fixed) {
|
|
32
|
+
if (bounds.minY >= other.maxY || bounds.maxY <= other.minY
|
|
33
|
+
|| bounds.minX >= other.maxX + gap || bounds.maxX + gap <= other.minX)
|
|
34
|
+
continue;
|
|
35
|
+
const shift = other.maxX + gap - bounds.minX;
|
|
36
|
+
dx += shift;
|
|
37
|
+
bounds = { ...bounds, minX: bounds.minX + shift, maxX: bounds.maxX + shift };
|
|
38
|
+
collision = true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (dx)
|
|
42
|
+
shifts.set(card.id, dx);
|
|
43
|
+
fixed.push(bounds);
|
|
44
|
+
}
|
|
45
|
+
return shifts.size ? cards.map((card) => shifts.has(card.id) ? { ...card, x: card.x + shifts.get(card.id) } : card) : [...cards];
|
|
46
|
+
}
|
|
47
|
+
export function iterationPosition(cards, source, gap) {
|
|
48
|
+
const x = source.x;
|
|
49
|
+
let y = source.y + source.height + gap * 2;
|
|
50
|
+
for (const neighbor of [...cards].sort((a, b) => a.y - b.y)) {
|
|
51
|
+
if (x >= neighbor.x + neighbor.width + gap || x + source.width + gap <= neighbor.x)
|
|
52
|
+
continue;
|
|
53
|
+
if (y < neighbor.y + neighbor.height + gap * 2 && y + source.height + gap * 2 > neighbor.y)
|
|
54
|
+
y = neighbor.y + neighbor.height + gap * 2;
|
|
55
|
+
}
|
|
56
|
+
return { x, y };
|
|
57
|
+
}
|
|
58
|
+
/** Zooms and centers content inside the padded viewport; null for empty content. */
|
|
59
|
+
export function fitCamera(bounds, viewport, padding) {
|
|
60
|
+
const width = bounds.maxX - bounds.minX;
|
|
61
|
+
const height = bounds.maxY - bounds.minY;
|
|
62
|
+
if (width <= 0 || height <= 0)
|
|
63
|
+
return null;
|
|
64
|
+
const zoom = Math.max(MIN_CAMERA_ZOOM, Math.min(Math.max(1, viewport.width - padding * 2) / width, Math.max(1, viewport.height - padding * 2) / height, MAX_CAMERA_ZOOM));
|
|
65
|
+
return centerCamera(bounds, zoom, viewport);
|
|
66
|
+
}
|
|
67
|
+
export function centerCamera(bounds, zoom, viewport) {
|
|
68
|
+
return {
|
|
69
|
+
x: -((bounds.minX + bounds.maxX) / 2) * zoom + viewport.width / 2,
|
|
70
|
+
y: -((bounds.minY + bounds.maxY) / 2) * zoom + viewport.height / 2,
|
|
71
|
+
zoom,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export function layoutShifts(before, after) {
|
|
75
|
+
const previous = new Map(before.map((card) => [card.id, card]));
|
|
76
|
+
return after.flatMap((card) => {
|
|
77
|
+
const old = previous.get(card.id);
|
|
78
|
+
if (!old || (old.x === card.x && old.y === card.y))
|
|
79
|
+
return [];
|
|
80
|
+
return [{ id: card.id, from: { x: old.x, y: old.y }, to: { x: card.x, y: card.y } }];
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/** Replays recorded shifts as deltas, so frames moved since the creation keep their later moves. */
|
|
84
|
+
export function applyLayoutShifts(cards, shifts, forward) {
|
|
85
|
+
const byId = new Map(shifts.map((shift) => [shift.id, shift]));
|
|
86
|
+
return cards.map((card) => {
|
|
87
|
+
const shift = byId.get(card.id);
|
|
88
|
+
if (!shift)
|
|
89
|
+
return card;
|
|
90
|
+
const from = forward ? shift.from : shift.to;
|
|
91
|
+
const to = forward ? shift.to : shift.from;
|
|
92
|
+
return { ...card, x: card.x + to.x - from.x, y: card.y + to.y - from.y };
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/** Reinserts recorded frames after their nearest recorded predecessor that still exists. */
|
|
96
|
+
export function reinsertInRecordedOrder(cards, recorded, ids) {
|
|
97
|
+
let next = [...cards];
|
|
98
|
+
for (const [index, added] of recorded.entries()) {
|
|
99
|
+
if (!ids.has(added.id))
|
|
100
|
+
continue;
|
|
101
|
+
const preceding = recorded.slice(0, index).reverse().find((card) => next.some((item) => item.id === card.id));
|
|
102
|
+
const insertion = preceding ? next.findIndex((card) => card.id === preceding.id) + 1 : 0;
|
|
103
|
+
next = [...next.slice(0, insertion), { ...added }, ...next.slice(insertion)];
|
|
104
|
+
}
|
|
105
|
+
return next;
|
|
106
|
+
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type DraftContents } from "../changes/draftChanges.js";
|
|
2
2
|
import type { CanvasCard } from "./canvasStore.js";
|
|
3
3
|
import { type PreviewDocument } from "../changes/previewDiagnostics.js";
|
|
4
|
-
import { type CompiledManagedStyles } from "../projection/
|
|
4
|
+
import { type CompiledManagedStyles, type DraftProjectionPlan } from "../projection/draftProjection.js";
|
|
5
5
|
export declare const PROJECT_ID: string;
|
|
6
|
-
export declare const WORKSPACE_ID:
|
|
6
|
+
export declare const WORKSPACE_ID: string;
|
|
7
|
+
export interface FrameProjection extends DraftProjectionPlan<CompiledManagedStyles> {
|
|
8
|
+
readonly draftId: string;
|
|
9
|
+
readonly draftRevision: number;
|
|
10
|
+
readonly revision: number;
|
|
11
|
+
readonly css: string;
|
|
12
|
+
}
|
|
7
13
|
export interface CanvasProjectionStatus {
|
|
8
14
|
sentRevision: number;
|
|
9
15
|
appliedRevision: number;
|
|
@@ -22,10 +28,14 @@ export declare function computeProjection(): {
|
|
|
22
28
|
textContentChanges: readonly import("../changes/editModel.js").TextContentChangeRecord[];
|
|
23
29
|
componentOverrides: readonly import("../componentSemantics/types.js").ComponentOverride[];
|
|
24
30
|
};
|
|
31
|
+
export declare function computeProjectionForCard(cardId: string): FrameProjection;
|
|
32
|
+
export declare function getCanonicalFrameProjection(cardId: string, expectedRevision: number): FrameProjection | null;
|
|
33
|
+
export declare function restoreCanonicalFrameProjection(doc: Document): void;
|
|
34
|
+
export declare function getCanvasCardIdForDocument(doc: Document): string | null;
|
|
25
35
|
export declare function resetProjectionRevision(): void;
|
|
26
|
-
export declare function sendProjectionToCard(card: CanvasCard, iframe: HTMLIFrameElement): void;
|
|
36
|
+
export declare function sendProjectionToCard(card: Pick<CanvasCard, "id">, iframe: HTMLIFrameElement): void;
|
|
27
37
|
/** Temporarily projects a snapshot through the renderer that owns the document. */
|
|
28
|
-
export declare function
|
|
38
|
+
export declare function projectDraftToDocument(doc: Document, snapshot: DraftContents): Promise<number | null>;
|
|
29
39
|
/** Returns whether an acknowledged temporary projection is still authoritative. */
|
|
30
40
|
export declare function isCanvasProjectionRevisionCurrent(doc: Document, expectedRevision: number): boolean;
|
|
31
41
|
/** Returns whether the live frame acknowledged its latest canonical workspace projection. */
|
|
@@ -1,18 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { draftIdForCard } from "../drafts/store.js";
|
|
2
|
+
import { getDraftChanges, getActiveDraftChanges } from "../changes/draftChanges.js";
|
|
3
|
+
import { getCanvasCards } from "./canvasStore.js";
|
|
4
|
+
import { getCanvasMode } from "./viewStore.js";
|
|
3
5
|
import { PROTOCOL_VERSION } from "./frameProtocol.js";
|
|
4
6
|
import { clearCanvasRenderedInstanceProjectionReports, setCanonicalRenderedInstanceOverrides, } from "../projection/renderedInstance.js";
|
|
5
7
|
import { clearCanvasTextProjectionReports, setCanonicalTextContentChanges, } from "../projection/textProjection.js";
|
|
6
8
|
import { clearCanvasStructuralProjectionReports } from "../projection/structuralProjection.js";
|
|
7
9
|
import { invalidatePreviewDocumentSession, startPreviewDocumentSession, } from "../changes/previewDiagnostics.js";
|
|
8
|
-
import {
|
|
10
|
+
import { compileDraftProjection, } from "../projection/draftProjection.js";
|
|
9
11
|
import { isOriginalPreviewActive } from "../shell/originalPreview.js";
|
|
10
12
|
import { disposeBrowserCssInspection } from "../inspection/browserCssInspectionRegistry.js";
|
|
11
|
-
export const PROJECT_ID = window.location
|
|
12
|
-
|
|
13
|
+
export const PROJECT_ID = typeof window !== "undefined" && window.location?.origin
|
|
14
|
+
? window.location.origin
|
|
15
|
+
: "";
|
|
16
|
+
export const WORKSPACE_ID = typeof crypto !== "undefined" && typeof crypto.randomUUID === "function"
|
|
17
|
+
? crypto.randomUUID()
|
|
18
|
+
: `ws-${Date.now()}`;
|
|
13
19
|
let revision = 0;
|
|
14
20
|
let lastRulesKey = null;
|
|
15
21
|
let lastPeekActive = false;
|
|
22
|
+
const draftPlans = new Map();
|
|
16
23
|
const frameProjectionStates = new Map();
|
|
17
24
|
const previewDocuments = new Map();
|
|
18
25
|
const projectionAcknowledgementListeners = new Set();
|
|
@@ -22,6 +29,7 @@ function createPreviewDocumentIdentity(cardId) {
|
|
|
22
29
|
const previewDocument = {
|
|
23
30
|
logicalDocument: `canvas:${cardId}`,
|
|
24
31
|
sessionId: `canvas-session-${nextPreviewSessionId++}`,
|
|
32
|
+
draftId: draftIdForCard(cardId) ?? getActiveDraftChanges().draftId,
|
|
25
33
|
};
|
|
26
34
|
previewDocuments.set(cardId, previewDocument);
|
|
27
35
|
return previewDocument;
|
|
@@ -50,7 +58,7 @@ function projectionKey(plan) {
|
|
|
50
58
|
return `${plan.managedStyles.css}\u0000${JSON.stringify(plan.instanceOverrides)}\u0000${JSON.stringify(plan.structuralChanges)}\u0000${JSON.stringify(plan.textContentChanges)}\u0000${JSON.stringify(plan.componentOverrides)}`;
|
|
51
59
|
}
|
|
52
60
|
export function computeProjection() {
|
|
53
|
-
const plan =
|
|
61
|
+
const plan = compileDraftProjection(getActiveDraftChanges());
|
|
54
62
|
if (isOriginalPreviewActive()) {
|
|
55
63
|
// Hold-to-view-original: frames show the page without inspector changes
|
|
56
64
|
// while canonical intent (and its projection key) stays untouched.
|
|
@@ -84,14 +92,53 @@ export function computeProjection() {
|
|
|
84
92
|
}
|
|
85
93
|
return { ...plan, css: plan.managedStyles.css, revision };
|
|
86
94
|
}
|
|
95
|
+
export function computeProjectionForCard(cardId) {
|
|
96
|
+
const draftId = draftIdForCard(cardId);
|
|
97
|
+
const workspace = draftId ? getDraftChanges(draftId) : getActiveDraftChanges();
|
|
98
|
+
const peek = isOriginalPreviewActive();
|
|
99
|
+
const cached = draftPlans.get(workspace.draftId);
|
|
100
|
+
if (cached && cached.plan.draftRevision === workspace.revision && cached.peek === peek)
|
|
101
|
+
return cached.plan;
|
|
102
|
+
const source = peek ? { ...workspace, changes: [], structuralChanges: [] } : workspace;
|
|
103
|
+
const compiled = compileDraftProjection(source);
|
|
104
|
+
const plan = { ...compiled, draftId: workspace.draftId, draftRevision: workspace.revision, css: compiled.managedStyles.css, revision: ++revision };
|
|
105
|
+
draftPlans.set(workspace.draftId, { peek, plan });
|
|
106
|
+
return plan;
|
|
107
|
+
}
|
|
108
|
+
export function getCanonicalFrameProjection(cardId, expectedRevision) {
|
|
109
|
+
const state = frameProjectionStates.get(cardId);
|
|
110
|
+
const plan = state?.canonicalProjection;
|
|
111
|
+
const draftId = draftIdForCard(cardId);
|
|
112
|
+
const draft = draftId ? getDraftChanges(draftId) : null;
|
|
113
|
+
if (!state || !previewDocuments.has(cardId) || state.iframe.contentDocument !== state.document
|
|
114
|
+
|| !plan || plan.revision !== expectedRevision || state.sentRevision !== expectedRevision
|
|
115
|
+
|| (draft && (draft.draftId !== plan.draftId || draft.revision !== plan.draftRevision)))
|
|
116
|
+
return null;
|
|
117
|
+
return plan;
|
|
118
|
+
}
|
|
119
|
+
export function restoreCanonicalFrameProjection(doc) {
|
|
120
|
+
const id = getCanvasCardIdForDocument(doc);
|
|
121
|
+
const card = getCanvasCards().find((card) => card.id === id);
|
|
122
|
+
const frame = id ? frameRegistry.get(id) : undefined;
|
|
123
|
+
if (card && frame)
|
|
124
|
+
sendProjectionToCard(card, frame);
|
|
125
|
+
}
|
|
126
|
+
export function getCanvasCardIdForDocument(doc) {
|
|
127
|
+
for (const [id, state] of frameProjectionStates)
|
|
128
|
+
if (state.document === doc && state.iframe.contentDocument === doc)
|
|
129
|
+
return id;
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
87
132
|
export function resetProjectionRevision() {
|
|
88
133
|
revision = 0;
|
|
89
134
|
lastRulesKey = null;
|
|
90
135
|
lastPeekActive = false;
|
|
136
|
+
draftPlans.clear();
|
|
91
137
|
for (const state of frameProjectionStates.values()) {
|
|
92
138
|
state.sentRevision = -1;
|
|
93
139
|
state.appliedRevision = -1;
|
|
94
140
|
state.canonicalSentRevision = -1;
|
|
141
|
+
state.canonicalProjection = null;
|
|
95
142
|
}
|
|
96
143
|
projectionAcknowledgementVersion += 1;
|
|
97
144
|
notifyProjectionAcknowledgementListeners();
|
|
@@ -100,7 +147,15 @@ export function sendProjectionToCard(card, iframe) {
|
|
|
100
147
|
const win = iframe.contentWindow;
|
|
101
148
|
if (!win)
|
|
102
149
|
return;
|
|
103
|
-
|
|
150
|
+
let plan = computeProjectionForCard(card.id);
|
|
151
|
+
const state = frameProjectionStates.get(card.id);
|
|
152
|
+
if (state && plan.revision < state.sentRevision) {
|
|
153
|
+
plan = { ...plan, revision: ++revision };
|
|
154
|
+
draftPlans.set(plan.draftId, { peek: isOriginalPreviewActive(), plan });
|
|
155
|
+
}
|
|
156
|
+
if (state)
|
|
157
|
+
state.canonicalProjection = plan;
|
|
158
|
+
const { css, revision: rev, instanceOverrides, structuralChanges, textContentChanges, componentOverrides } = plan;
|
|
104
159
|
sendProjectionMessage(card.id, iframe, rev, css, instanceOverrides, structuralChanges, textContentChanges, componentOverrides, true);
|
|
105
160
|
}
|
|
106
161
|
function sendProjectionMessage(cardId, iframe, rev, css, instanceOverrides, structuralChanges, textContentChanges, componentOverrides, canonical = false) {
|
|
@@ -124,12 +179,12 @@ function sendProjectionMessage(cardId, iframe, rev, css, instanceOverrides, stru
|
|
|
124
179
|
win.postMessage(msg, window.location.origin);
|
|
125
180
|
}
|
|
126
181
|
/** Temporarily projects a snapshot through the renderer that owns the document. */
|
|
127
|
-
export async function
|
|
182
|
+
export async function projectDraftToDocument(doc, snapshot) {
|
|
128
183
|
const entry = [...frameProjectionStates.entries()].find(([, state]) => state.document === doc);
|
|
129
184
|
if (!entry)
|
|
130
185
|
return null;
|
|
131
186
|
const [cardId, state] = entry;
|
|
132
|
-
const plan =
|
|
187
|
+
const plan = compileDraftProjection({ ...snapshot, revision: 0 });
|
|
133
188
|
revision += 1;
|
|
134
189
|
sendProjectionMessage(cardId, state.iframe, revision, plan.managedStyles.css, plan.instanceOverrides, plan.structuralChanges, plan.textContentChanges, plan.componentOverrides);
|
|
135
190
|
if (state.appliedRevision === revision && state.sentRevision === revision)
|
|
@@ -203,6 +258,8 @@ export function registerCardFrame(cardId, iframe) {
|
|
|
203
258
|
const existing = frameProjectionStates.get(cardId);
|
|
204
259
|
if (!existing || existing.iframe !== iframe || existing.document !== frameDocument) {
|
|
205
260
|
if (existing) {
|
|
261
|
+
if (existing.canonicalProjection)
|
|
262
|
+
draftPlans.delete(existing.canonicalProjection.draftId);
|
|
206
263
|
invalidatePreviewDocumentSession(existing.previewDocument.logicalDocument, existing.previewDocument.sessionId);
|
|
207
264
|
previewDocuments.delete(cardId);
|
|
208
265
|
}
|
|
@@ -215,6 +272,7 @@ export function registerCardFrame(cardId, iframe) {
|
|
|
215
272
|
sentRevision: -1,
|
|
216
273
|
appliedRevision: -1,
|
|
217
274
|
canonicalSentRevision: -1,
|
|
275
|
+
canonicalProjection: null,
|
|
218
276
|
});
|
|
219
277
|
}
|
|
220
278
|
else {
|
|
@@ -318,8 +376,6 @@ function notifyFrameRegistryListeners() {
|
|
|
318
376
|
export function projectToAllReadyCards() {
|
|
319
377
|
if (getCanvasMode() !== "canvas")
|
|
320
378
|
return;
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
sendProjectionMessage(cardId, iframe, rev, css, instanceOverrides, structuralChanges, textContentChanges, componentOverrides, true);
|
|
324
|
-
}
|
|
379
|
+
for (const [id, iframe] of frameRegistry)
|
|
380
|
+
sendProjectionToCard({ id }, iframe);
|
|
325
381
|
}
|