nudge-ui 0.2.4 → 0.2.5

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.
Files changed (250) hide show
  1. package/dist/cli/agentCommand.js +4 -28
  2. package/dist/client.mjs +863 -213
  3. package/dist/hosts/next/wrapper.js +1 -7
  4. package/dist/hosts/projectBridge.js +3 -17
  5. package/dist/inspector/agent/McpConnectionDialog.js +7 -3
  6. package/dist/inspector/agent/activity.d.ts +1 -1
  7. package/dist/inspector/agent/activity.js +3 -2
  8. package/dist/inspector/agent/client.d.ts +2 -2
  9. package/dist/inspector/agent/client.js +28 -29
  10. package/dist/inspector/agent/connectionStatus.d.ts +3 -1
  11. package/dist/inspector/agent/connectionStatus.js +25 -0
  12. package/dist/inspector/agent/httpTransport.js +31 -147
  13. package/dist/inspector/agent/protocol.d.ts +1 -1
  14. package/dist/inspector/agent/protocol.js +1 -1
  15. package/dist/inspector/agent/verification.d.ts +1 -1
  16. package/dist/inspector/agent/verification.js +7 -4
  17. package/dist/inspector/boot.d.ts +3 -0
  18. package/dist/inspector/boot.js +297 -0
  19. package/dist/inspector/canvas/AgentActivityOverlay.d.ts +2 -1
  20. package/dist/inspector/canvas/AgentActivityOverlay.js +6 -3
  21. package/dist/inspector/canvas/CanvasCard.js +21 -12
  22. package/dist/inspector/canvas/CanvasElementOverlay.js +82 -127
  23. package/dist/inspector/canvas/CanvasToolbar.js +2 -1
  24. package/dist/inspector/canvas/CanvasWorkspace.js +74 -97
  25. package/dist/inspector/canvas/LockedWorkspaceNotice.d.ts +3 -2
  26. package/dist/inspector/canvas/LockedWorkspaceNotice.js +10 -6
  27. package/dist/inspector/canvas/PageCard.d.ts +10 -0
  28. package/dist/inspector/canvas/PageCard.js +51 -0
  29. package/dist/inspector/canvas/SketchToolOptions.d.ts +5 -0
  30. package/dist/inspector/canvas/SketchToolOptions.js +86 -0
  31. package/dist/inspector/canvas/StaleChangeIndicator.d.ts +1 -1
  32. package/dist/inspector/canvas/StaleChangeIndicator.js +1 -1
  33. package/dist/inspector/canvas/ToolOptionsDrawer.d.ts +21 -0
  34. package/dist/inspector/canvas/ToolOptionsDrawer.js +77 -0
  35. package/dist/inspector/canvas/activeCanvasDocument.d.ts +3 -2
  36. package/dist/inspector/canvas/assets/eraser.svg +28 -0
  37. package/dist/inspector/canvas/assets/pen.svg +25 -0
  38. package/dist/inspector/canvas/canvasFrame.d.ts +16 -0
  39. package/dist/inspector/canvas/canvasFrame.js +10 -0
  40. package/dist/inspector/canvas/canvasGestures.d.ts +0 -1
  41. package/dist/inspector/canvas/canvasGestures.js +0 -6
  42. package/dist/inspector/canvas/canvasStore.d.ts +6 -0
  43. package/dist/inspector/canvas/canvasStore.js +36 -1
  44. package/dist/inspector/canvas/frameConnection.d.ts +48 -0
  45. package/dist/inspector/canvas/frameConnection.js +73 -0
  46. package/dist/inspector/canvas/frameProtocol.d.ts +18 -1
  47. package/dist/inspector/canvas/frameProtocol.js +36 -0
  48. package/dist/inspector/canvas/pageSurface.d.ts +11 -0
  49. package/dist/inspector/canvas/pageSurface.js +34 -0
  50. package/dist/inspector/canvas/projection.d.ts +19 -9
  51. package/dist/inspector/canvas/projection.js +58 -31
  52. package/dist/inspector/canvas/rendererBootstrap.js +4 -1
  53. package/dist/inspector/canvas/rendererElementSelector.js +9 -1
  54. package/dist/inspector/canvas/rendererMessageRouter.d.ts +4 -5
  55. package/dist/inspector/canvas/rendererMessageRouter.js +12 -16
  56. package/dist/inspector/canvas/rendererSelectionProxy.d.ts +7 -1
  57. package/dist/inspector/canvas/rendererSelectionProxy.js +8 -36
  58. package/dist/inspector/canvas/rendererStylesheet.js +15 -0
  59. package/dist/inspector/canvas/sessionStore.d.ts +2 -2
  60. package/dist/inspector/canvas/sessionStore.js +12 -9
  61. package/dist/inspector/canvas/staleChangeDetector.d.ts +1 -1
  62. package/dist/inspector/canvas/staleChangeDetector.js +10 -22
  63. package/dist/inspector/changes/codecs.d.ts +1 -0
  64. package/dist/inspector/changes/codecs.js +20 -5
  65. package/dist/inspector/changes/draftPreview.d.ts +12 -0
  66. package/dist/inspector/changes/draftPreview.js +133 -0
  67. package/dist/inspector/changes/editModel.d.ts +8 -0
  68. package/dist/inspector/changes/editModel.js +8 -2
  69. package/dist/inspector/changes/managedStyleProjection.js +2 -1
  70. package/dist/inspector/changes/previewDiagnostics.js +1 -1
  71. package/dist/inspector/changes/types.d.ts +11 -1
  72. package/dist/inspector/comments/CommentsOverlay.js +18 -16
  73. package/dist/inspector/comments/store.js +3 -2
  74. package/dist/inspector/comments/verification.js +1 -1
  75. package/dist/inspector/componentSemantics/ComponentPropsSection.js +2 -1
  76. package/dist/inspector/componentSemantics/changeAction.js +1 -1
  77. package/dist/inspector/componentSemantics/textBinding.d.ts +1 -2
  78. package/dist/inspector/componentSemantics/textBinding.js +4 -45
  79. package/dist/inspector/drafts/draftStore.d.ts +109 -0
  80. package/dist/inspector/drafts/draftStore.js +451 -0
  81. package/dist/inspector/drafts/model.d.ts +9 -1
  82. package/dist/inspector/drafts/model.js +5 -1
  83. package/dist/inspector/drafts/store.d.ts +53 -15
  84. package/dist/inspector/drafts/store.js +143 -169
  85. package/dist/inspector/index.d.ts +2 -4
  86. package/dist/inspector/index.js +2 -264
  87. package/dist/inspector/inline-text/inlineTextEditor.d.ts +1 -1
  88. package/dist/inspector/inline-text/inlineTextEditor.js +1 -2
  89. package/dist/inspector/inline-text/textEditChange.d.ts +1 -1
  90. package/dist/inspector/inspection/bridge.d.ts +1 -1
  91. package/dist/inspector/inspection/bridge.js +2 -1
  92. package/dist/inspector/inspection/browserCssInspection.d.ts +8 -0
  93. package/dist/inspector/inspection/browserCssInspection.js +28 -6
  94. package/dist/inspector/inspection/inspectionSnapshot.d.ts +6 -0
  95. package/dist/inspector/inspection/inspectionSnapshot.js +10 -0
  96. package/dist/inspector/inspection/performanceDiagnostics.d.ts +18 -0
  97. package/dist/inspector/inspection/performanceDiagnostics.js +31 -0
  98. package/dist/inspector/inspection/useBrowserCssInspection.js +17 -38
  99. package/dist/inspector/iterations/capture.d.ts +2 -1
  100. package/dist/inspector/iterations/client.d.ts +2 -1
  101. package/dist/inspector/iterations/coordinator.d.ts +4 -3
  102. package/dist/inspector/iterations/coordinator.js +5 -3
  103. package/dist/inspector/iterations/prompt.js +9 -8
  104. package/dist/inspector/overlay/interactionStyles.js +17 -0
  105. package/dist/inspector/pageInspector.d.ts +42 -0
  106. package/dist/inspector/pageInspector.js +342 -0
  107. package/dist/inspector/projection/draftProjection.d.ts +10 -2
  108. package/dist/inspector/projection/draftProjection.js +9 -1
  109. package/dist/inspector/projection/managedStylesheet.js +24 -4
  110. package/dist/inspector/projection/renderedInstance.js +7 -1
  111. package/dist/inspector/projection/structuralProjection.d.ts +0 -9
  112. package/dist/inspector/projection/structuralProjection.js +14 -44
  113. package/dist/inspector/projection/textProjection.d.ts +8 -2
  114. package/dist/inspector/projection/textProjection.js +21 -13
  115. package/dist/inspector/prompt/clipboardHandoff.d.ts +9 -0
  116. package/dist/inspector/prompt/clipboardHandoff.js +42 -16
  117. package/dist/inspector/prompt/generatePrompt.d.ts +1 -1
  118. package/dist/inspector/prompt/generatePrompt.js +243 -147
  119. package/dist/inspector/prompt/promptDocument.d.ts +3 -0
  120. package/dist/inspector/prompt/promptDocument.js +8 -0
  121. package/dist/inspector/prompt/promptSettings.js +7 -5
  122. package/dist/inspector/runtime/inspectorStorage.d.ts +17 -0
  123. package/dist/inspector/runtime/inspectorStorage.js +42 -0
  124. package/dist/inspector/runtime/ownedStylesheets.d.ts +20 -0
  125. package/dist/inspector/runtime/ownedStylesheets.js +72 -0
  126. package/dist/inspector/runtime/runtimeConfig.d.ts +4 -0
  127. package/dist/inspector/runtime/runtimeConfig.js +10 -1
  128. package/dist/inspector/runtime/runtimeIdentityClaims.d.ts +29 -0
  129. package/dist/inspector/runtime/runtimeIdentityClaims.js +188 -0
  130. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.d.ts +15 -0
  131. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.js +113 -29
  132. package/dist/inspector/selection/editScope.d.ts +1 -0
  133. package/dist/inspector/selection/editScope.js +13 -2
  134. package/dist/inspector/shell/AgentStatusButton.js +2 -2
  135. package/dist/inspector/shell/AppShell.js +6 -2
  136. package/dist/inspector/shell/ChangesLog.js +27 -9
  137. package/dist/inspector/shell/CopyPromptButton.js +60 -54
  138. package/dist/inspector/shell/EmptyState.js +3 -3
  139. package/dist/inspector/shell/InspectorShell.d.ts +0 -3
  140. package/dist/inspector/shell/InspectorShell.js +21 -13
  141. package/dist/inspector/shell/PeekOriginalButton.js +3 -3
  142. package/dist/inspector/shell/interactionStatePreview.d.ts +9 -0
  143. package/dist/inspector/shell/interactionStatePreview.js +112 -0
  144. package/dist/inspector/shell/originalPreview.d.ts +3 -2
  145. package/dist/inspector/shell/originalPreview.js +10 -37
  146. package/dist/inspector/shell/stateValue.js +2 -3
  147. package/dist/inspector/sketch/SketchEditor.js +5 -4
  148. package/dist/inspector/sketch/SketchFrameOverlay.d.ts +2 -1
  149. package/dist/inspector/sketch/SketchFrameOverlay.js +5 -4
  150. package/dist/inspector/sketch/SketchOverlay.d.ts +3 -5
  151. package/dist/inspector/sketch/SketchOverlay.js +139 -263
  152. package/dist/inspector/sketch/SketchPromptPanel.d.ts +1 -1
  153. package/dist/inspector/sketch/SketchPromptPanel.js +8 -1
  154. package/dist/inspector/sketch/SketchThumbnail.d.ts +5 -0
  155. package/dist/inspector/sketch/SketchThumbnail.js +18 -0
  156. package/dist/inspector/sketch/SketchWorkspace.d.ts +1 -2
  157. package/dist/inspector/sketch/SketchWorkspace.js +69 -34
  158. package/dist/inspector/sketch/capture.js +19 -3
  159. package/dist/inspector/sketch/copySketch.d.ts +10 -0
  160. package/dist/inspector/sketch/copySketch.js +52 -0
  161. package/dist/inspector/sketch/drawingTools.d.ts +17 -0
  162. package/dist/inspector/sketch/drawingTools.js +47 -0
  163. package/dist/inspector/sketch/frameHeading.d.ts +9 -0
  164. package/dist/inspector/sketch/frameHeading.js +30 -0
  165. package/dist/inspector/sketch/freehand.js +3 -3
  166. package/dist/inspector/sketch/geometry.d.ts +6 -0
  167. package/dist/inspector/sketch/geometry.js +19 -0
  168. package/dist/inspector/sketch/history.d.ts +30 -0
  169. package/dist/inspector/sketch/history.js +58 -0
  170. package/dist/inspector/sketch/interaction.d.ts +1 -3
  171. package/dist/inspector/sketch/interaction.js +6 -9
  172. package/dist/inspector/sketch/model.d.ts +35 -1
  173. package/dist/inspector/sketch/model.js +116 -61
  174. package/dist/inspector/sketch/persistence.d.ts +14 -0
  175. package/dist/inspector/sketch/persistence.js +63 -7
  176. package/dist/inspector/sketch/raster.d.ts +6 -2
  177. package/dist/inspector/sketch/raster.js +43 -17
  178. package/dist/inspector/sketch/store.d.ts +1 -1
  179. package/dist/inspector/sketch/store.js +1 -1
  180. package/dist/inspector/sketch/videoFrames.d.ts +6 -0
  181. package/dist/inspector/sketch/videoFrames.js +81 -0
  182. package/dist/inspector/styleEditors/BackgroundEditor.js +2 -1
  183. package/dist/inspector/styleEditors/BorderEditor.js +30 -130
  184. package/dist/inspector/styleEditors/BorderRadiusEditor.js +8 -3
  185. package/dist/inspector/styleEditors/ImageBackgroundEditor.js +1 -1
  186. package/dist/inspector/styleEditors/LayoutSection.js +2 -2
  187. package/dist/inspector/styleEditors/borderModel.d.ts +42 -0
  188. package/dist/inspector/styleEditors/borderModel.js +114 -0
  189. package/dist/inspector/styleEditors/layoutValue.js +2 -3
  190. package/dist/inspector/tokens/TokenField.js +34 -3
  191. package/dist/inspector/tokens/TokensPanel.js +2 -1
  192. package/dist/inspector/tokens/editActions.d.ts +3 -3
  193. package/dist/inspector/tokens/editActions.js +9 -3
  194. package/dist/inspector/tokens/resolution/containerQueryEvaluator.d.ts +15 -0
  195. package/dist/inspector/tokens/resolution/containerQueryEvaluator.js +86 -0
  196. package/dist/inspector/tokens/resolution/cssomCollector.js +44 -9
  197. package/dist/inspector/tokens/resolution/nestedSelectors.d.ts +6 -0
  198. package/dist/inspector/tokens/resolution/nestedSelectors.js +67 -0
  199. package/dist/inspector/tokens/resolution/ruleMatching.js +23 -4
  200. package/dist/inspector/tokens/resolution.d.ts +6 -3
  201. package/dist/inspector/tokens/resolution.js +91 -112
  202. package/dist/inspector/tokens/tokenEdits.d.ts +1 -1
  203. package/dist/inspector/tokens/tokenEdits.js +1 -1
  204. package/dist/inspector/ui/InlineStyleWarning.js +2 -2
  205. package/dist/inspector/ui/InspectorStyle.d.ts +8 -0
  206. package/dist/inspector/ui/InspectorStyle.js +26 -0
  207. package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
  208. package/dist/inspector/ui/PopoverListbox.js +3 -3
  209. package/dist/inspector/ui/Toast.d.ts +14 -0
  210. package/dist/inspector/ui/Toast.js +30 -0
  211. package/dist/inspector/ui/assets/canvasIllustration.d.ts +2 -0
  212. package/dist/inspector/ui/assets/canvasIllustration.js +21 -0
  213. package/dist/inspector/ui/assets/gridIllustration.d.ts +2 -0
  214. package/dist/inspector/ui/assets/{grid.svg → gridIllustration.js} +3 -2
  215. package/dist/inspector/ui/customCursors.d.ts +5 -0
  216. package/dist/inspector/ui/customCursors.js +32 -6
  217. package/dist/inspector/ui/styles.js +12 -10
  218. package/dist/inspector/workspace/commands.js +1 -2
  219. package/dist/inspector/workspace/controller.js +1 -2
  220. package/dist/inspector/workspace/handoff.js +3 -2
  221. package/dist/inspector/workspace/sentItems.d.ts +3 -6
  222. package/dist/inspector/workspace/sentItems.js +6 -24
  223. package/dist/inspector/workspace/timeline.d.ts +24 -10
  224. package/dist/inspector/workspace/timeline.js +118 -96
  225. package/dist/internal/agent-protocol.d.ts +50 -13
  226. package/dist/internal/agent-protocol.js +145 -19
  227. package/dist/nudge-ui.mjs +81 -65
  228. package/dist/project/mcpPackage.d.ts +8 -0
  229. package/dist/project/mcpPackage.js +60 -0
  230. package/package.json +12 -2
  231. package/dist/inspector/canvas/measurementProjection.d.ts +0 -8
  232. package/dist/inspector/canvas/measurementProjection.js +0 -16
  233. package/dist/inspector/changes/changesLog.d.ts +0 -49
  234. package/dist/inspector/changes/changesLog.js +0 -255
  235. package/dist/inspector/changes/draftChanges.d.ts +0 -58
  236. package/dist/inspector/changes/draftChanges.js +0 -304
  237. package/dist/inspector/conformance/projection.d.ts +0 -2
  238. package/dist/inspector/conformance/projection.js +0 -3
  239. package/dist/inspector/inline-text/textChangeBoundary.d.ts +0 -6
  240. package/dist/inspector/inline-text/textChangeBoundary.js +0 -1
  241. package/dist/inspector/overlay/InspectorOverlay.d.ts +0 -5
  242. package/dist/inspector/overlay/InspectorOverlay.js +0 -332
  243. package/dist/inspector/overlay/elementSelector.d.ts +0 -1
  244. package/dist/inspector/overlay/elementSelector.js +0 -111
  245. package/dist/inspector/sketch/SketchChanges.d.ts +0 -2
  246. package/dist/inspector/sketch/SketchChanges.js +0 -72
  247. package/dist/inspector/sketch/SketchEntryButton.d.ts +0 -4
  248. package/dist/inspector/sketch/SketchEntryButton.js +0 -11
  249. package/dist/inspector/sketch/SketchLayersPanel.d.ts +0 -2
  250. package/dist/inspector/sketch/SketchLayersPanel.js +0 -71
@@ -0,0 +1,34 @@
1
+ import { NUDGE_UI_MOUNT_ID } from "../../transport/routes.js";
2
+ let pageSurface = false;
3
+ /**
4
+ * Runs the renderer and controller in the inspected window. The single Canvas
5
+ * card is the page itself, so no iframe or framing permission is needed.
6
+ */
7
+ export function enablePageSurface() {
8
+ pageSurface = true;
9
+ }
10
+ export function isPageSurface() {
11
+ return pageSurface;
12
+ }
13
+ const pageFrames = new WeakMap();
14
+ /** The page-surface card's frame: the inspected window, filling the viewport. */
15
+ export function getPageFrame(win = window) {
16
+ const existing = pageFrames.get(win);
17
+ if (existing)
18
+ return existing;
19
+ const root = win.document.documentElement;
20
+ const frame = {
21
+ contentWindow: win,
22
+ contentDocument: win.document,
23
+ isConnected: true,
24
+ get clientWidth() { return root.clientWidth; },
25
+ get clientHeight() { return root.clientHeight; },
26
+ getBoundingClientRect: () => new DOMRect(0, 0, root.clientWidth, root.clientHeight),
27
+ };
28
+ pageFrames.set(win, frame);
29
+ return frame;
30
+ }
31
+ /** True for events that start inside the inspector's own shadow root. */
32
+ export function isInspectorUiEvent(event) {
33
+ return pageSurface && event.composedPath().some((node) => node instanceof Element && node.id === NUDGE_UI_MOUNT_ID);
34
+ }
@@ -1,9 +1,8 @@
1
- import { type DraftContents } from "../changes/draftChanges.js";
1
+ import type { CanvasFrame } from "./canvasFrame.js";
2
+ import type { DraftContents } from "../drafts/model.js";
2
3
  import type { CanvasCard } from "./canvasStore.js";
3
4
  import { type PreviewDocument } from "../changes/previewDiagnostics.js";
4
5
  import { type CompiledManagedStyles, type DraftProjectionPlan } from "../projection/draftProjection.js";
5
- export declare const PROJECT_ID: string;
6
- export declare const WORKSPACE_ID: string;
7
6
  export interface FrameProjection extends DraftProjectionPlan<CompiledManagedStyles> {
8
7
  readonly draftId: string;
9
8
  readonly draftRevision: number;
@@ -27,27 +26,36 @@ export declare function computeProjection(): {
27
26
  structuralChanges: readonly import("../changes/structuralTypes.js").StructuralChange[];
28
27
  textContentChanges: readonly import("../changes/editModel.js").TextContentChangeRecord[];
29
28
  componentOverrides: readonly import("../componentSemantics/types.js").ComponentOverride[];
29
+ runtimeIdentities?: readonly import("../runtime/runtimeIdentityClaims.js").RuntimeIdentityClaim[];
30
30
  };
31
31
  export declare function computeProjectionForCard(cardId: string): FrameProjection;
32
32
  export declare function getCanonicalFrameProjection(cardId: string, expectedRevision: number): FrameProjection | null;
33
- export declare function restoreCanonicalFrameProjection(doc: Document): void;
33
+ /**
34
+ * Re-sends the canonical projection after a temporary verification projection
35
+ * and settles once the renderer acknowledges it, so callers can treat the
36
+ * acknowledgement's stylesheet invalidation as part of their own work.
37
+ */
38
+ export declare function restoreCanonicalFrameProjection(doc: Document): Promise<void>;
34
39
  export declare function getCanvasCardIdForDocument(doc: Document): string | null;
35
40
  export declare function resetProjectionRevision(): void;
36
- export declare function sendProjectionToCard(card: Pick<CanvasCard, "id">, iframe: HTMLIFrameElement): void;
41
+ /** Sends the canonical projection and returns its revision, or null when the frame has no window. */
42
+ export declare function sendProjectionToCard(card: Pick<CanvasCard, "id">, iframe: CanvasFrame): number | null;
37
43
  /** Temporarily projects a snapshot through the renderer that owns the document. */
38
44
  export declare function projectDraftToDocument(doc: Document, snapshot: DraftContents): Promise<number | null>;
39
45
  /** Returns whether an acknowledged temporary projection is still authoritative. */
40
46
  export declare function isCanvasProjectionRevisionCurrent(doc: Document, expectedRevision: number): boolean;
41
47
  /** Returns whether the live frame acknowledged its latest canonical workspace projection. */
42
48
  export declare function isCanvasCanonicalProjectionRevisionCurrent(doc: Document, expectedRevision: number): boolean;
43
- export declare function registerCardFrameSource(cardId: string, iframe: HTMLIFrameElement): void;
44
- export declare function registerCardFrame(cardId: string, iframe: HTMLIFrameElement): void;
49
+ export declare function registerCardFrameSource(cardId: string, iframe: CanvasFrame): void;
50
+ export declare function registerCardFrame(cardId: string, iframe: CanvasFrame): void;
45
51
  export declare function unregisterCardFrame(cardId: string): void;
46
- export declare function getRegisteredFrames(): ReadonlyMap<string, HTMLIFrameElement>;
52
+ export declare function getRegisteredFrames(): ReadonlyMap<string, CanvasFrame>;
47
53
  export declare function findCanvasFrameBySource(source: MessageEventSource | null): {
48
54
  cardId: string;
49
- iframe: HTMLIFrameElement;
55
+ iframe: CanvasFrame;
50
56
  } | null;
57
+ /** The registered frame rendering `doc`, which may be the controller document on the page surface. */
58
+ export declare function findCanvasFrameByDocument(doc: Document | null | undefined): CanvasFrame | null;
51
59
  export declare function subscribeFrameRegistry(listener: () => void): () => void;
52
60
  /** Records the highest complete projection revision accepted by one frame. */
53
61
  export declare function recordCanvasProjectionApplied(cardId: string, appliedRevision: number): void;
@@ -55,4 +63,6 @@ export declare function recordCanvasProjectionApplied(cardId: string, appliedRev
55
63
  export declare function getCanvasProjectionStatus(doc: Document): CanvasProjectionStatus | null;
56
64
  export declare function subscribeCanvasProjectionAcknowledgements(listener: () => void): () => void;
57
65
  export declare function getCanvasProjectionAcknowledgementVersion(): number;
66
+ /** Changes whenever a frame registers or unregisters, for `useSyncExternalStore`. */
67
+ export declare function getFrameRegistryVersion(): number;
58
68
  export declare function projectToAllReadyCards(): void;
@@ -1,21 +1,14 @@
1
- import { draftIdForCard } from "../drafts/store.js";
2
- import { getDraftChanges, getActiveDraftChanges } from "../changes/draftChanges.js";
1
+ import { draftIdForCard, getDraftChanges, getActiveDraftChanges } from "../drafts/store.js";
3
2
  import { getCanvasCards } from "./canvasStore.js";
4
3
  import { getCanvasMode } from "./viewStore.js";
5
- import { PROTOCOL_VERSION } from "./frameProtocol.js";
4
+ import { connectFrame } from "./frameConnection.js";
6
5
  import { clearCanvasRenderedInstanceProjectionReports, setCanonicalRenderedInstanceOverrides, } from "../projection/renderedInstance.js";
7
6
  import { clearCanvasTextProjectionReports, setCanonicalTextContentChanges, } from "../projection/textProjection.js";
8
7
  import { clearCanvasStructuralProjectionReports } from "../projection/structuralProjection.js";
9
8
  import { invalidatePreviewDocumentSession, startPreviewDocumentSession, } from "../changes/previewDiagnostics.js";
10
9
  import { compileDraftProjection, } from "../projection/draftProjection.js";
11
10
  import { isOriginalPreviewActive } from "../shell/originalPreview.js";
12
- import { disposeBrowserCssInspection } from "../inspection/browserCssInspectionRegistry.js";
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()}`;
11
+ import { disposeBrowserCssInspection, notifyBrowserStylesheetChange } from "../inspection/browserCssInspectionRegistry.js";
19
12
  let revision = 0;
20
13
  let lastRulesKey = null;
21
14
  let lastPeekActive = false;
@@ -116,12 +109,20 @@ export function getCanonicalFrameProjection(cardId, expectedRevision) {
116
109
  return null;
117
110
  return plan;
118
111
  }
119
- export function restoreCanonicalFrameProjection(doc) {
112
+ /**
113
+ * Re-sends the canonical projection after a temporary verification projection
114
+ * and settles once the renderer acknowledges it, so callers can treat the
115
+ * acknowledgement's stylesheet invalidation as part of their own work.
116
+ */
117
+ export async function restoreCanonicalFrameProjection(doc) {
120
118
  const id = getCanvasCardIdForDocument(doc);
121
119
  const card = getCanvasCards().find((card) => card.id === id);
122
120
  const frame = id ? frameRegistry.get(id) : undefined;
123
- if (card && frame)
124
- sendProjectionToCard(card, frame);
121
+ if (!card || !frame)
122
+ return;
123
+ const sent = sendProjectionToCard(card, frame);
124
+ if (sent !== null)
125
+ await waitForProjectionApplied(card.id, doc, sent);
125
126
  }
126
127
  export function getCanvasCardIdForDocument(doc) {
127
128
  for (const [id, state] of frameProjectionStates)
@@ -143,10 +144,11 @@ export function resetProjectionRevision() {
143
144
  projectionAcknowledgementVersion += 1;
144
145
  notifyProjectionAcknowledgementListeners();
145
146
  }
147
+ /** Sends the canonical projection and returns its revision, or null when the frame has no window. */
146
148
  export function sendProjectionToCard(card, iframe) {
147
149
  const win = iframe.contentWindow;
148
150
  if (!win)
149
- return;
151
+ return null;
150
152
  let plan = computeProjectionForCard(card.id);
151
153
  const state = frameProjectionStates.get(card.id);
152
154
  if (state && plan.revision < state.sentRevision) {
@@ -155,28 +157,24 @@ export function sendProjectionToCard(card, iframe) {
155
157
  }
156
158
  if (state)
157
159
  state.canonicalProjection = plan;
158
- const { css, revision: rev, instanceOverrides, structuralChanges, textContentChanges, componentOverrides } = plan;
159
- sendProjectionMessage(card.id, iframe, rev, css, instanceOverrides, structuralChanges, textContentChanges, componentOverrides, true);
160
+ const { css, revision: rev, instanceOverrides, structuralChanges, textContentChanges, componentOverrides, runtimeIdentities } = plan;
161
+ sendProjectionMessage(card.id, iframe, rev, css, instanceOverrides, structuralChanges, textContentChanges, componentOverrides, runtimeIdentities, true);
162
+ return rev;
160
163
  }
161
- function sendProjectionMessage(cardId, iframe, rev, css, instanceOverrides, structuralChanges, textContentChanges, componentOverrides, canonical = false) {
162
- const win = iframe.contentWindow;
163
- if (!win)
164
+ function sendProjectionMessage(cardId, iframe, rev, css, instanceOverrides, structuralChanges, textContentChanges, componentOverrides, runtimeIdentities, canonical = false) {
165
+ if (!iframe.contentWindow)
164
166
  return;
165
- const msg = {
167
+ markProjectionSent(cardId, iframe, rev, canonical);
168
+ connectFrame(cardId, iframe).post({
166
169
  type: "replace-styles",
167
- protocolVersion: PROTOCOL_VERSION,
168
- projectId: PROJECT_ID,
169
- workspaceId: WORKSPACE_ID,
170
- cardId,
171
170
  css,
172
171
  revision: rev,
173
172
  instanceOverrides: [...instanceOverrides],
174
173
  structuralChanges: [...structuralChanges],
175
174
  textContentChanges: [...textContentChanges],
176
175
  componentOverrides: [...componentOverrides],
177
- };
178
- markProjectionSent(cardId, iframe, rev, canonical);
179
- win.postMessage(msg, window.location.origin);
176
+ ...(runtimeIdentities ? { runtimeIdentities: [...runtimeIdentities] } : {}),
177
+ });
180
178
  }
181
179
  /** Temporarily projects a snapshot through the renderer that owns the document. */
182
180
  export async function projectDraftToDocument(doc, snapshot) {
@@ -186,10 +184,18 @@ export async function projectDraftToDocument(doc, snapshot) {
186
184
  const [cardId, state] = entry;
187
185
  const plan = compileDraftProjection({ ...snapshot, revision: 0 });
188
186
  revision += 1;
189
- sendProjectionMessage(cardId, state.iframe, revision, plan.managedStyles.css, plan.instanceOverrides, plan.structuralChanges, plan.textContentChanges, plan.componentOverrides);
190
- if (state.appliedRevision === revision && state.sentRevision === revision)
191
- return revision;
192
- const requestedRevision = revision;
187
+ sendProjectionMessage(cardId, state.iframe, revision, plan.managedStyles.css, plan.instanceOverrides, plan.structuralChanges, plan.textContentChanges, plan.componentOverrides, plan.runtimeIdentities);
188
+ return waitForProjectionApplied(cardId, doc, revision);
189
+ }
190
+ /**
191
+ * Resolves with `requestedRevision` once the frame acknowledges it, or null
192
+ * when a newer projection supersedes it, the frame is replaced, or 2s pass.
193
+ */
194
+ function waitForProjectionApplied(cardId, doc, requestedRevision) {
195
+ const initial = frameProjectionStates.get(cardId);
196
+ if (initial?.appliedRevision === requestedRevision && initial.sentRevision === requestedRevision) {
197
+ return Promise.resolve(requestedRevision);
198
+ }
193
199
  return new Promise((resolve) => {
194
200
  let settled = false;
195
201
  let timer;
@@ -304,6 +310,16 @@ export function findCanvasFrameBySource(source) {
304
310
  }
305
311
  return null;
306
312
  }
313
+ /** The registered frame rendering `doc`, which may be the controller document on the page surface. */
314
+ export function findCanvasFrameByDocument(doc) {
315
+ if (!doc)
316
+ return null;
317
+ for (const iframe of frameRegistry.values()) {
318
+ if (getFrameDocument(iframe) === doc)
319
+ return iframe;
320
+ }
321
+ return null;
322
+ }
307
323
  const frameRegistryListeners = new Set();
308
324
  export function subscribeFrameRegistry(listener) {
309
325
  frameRegistryListeners.add(listener);
@@ -333,6 +349,11 @@ export function recordCanvasProjectionApplied(cardId, appliedRevision) {
333
349
  if (!state || appliedRevision > state.sentRevision || appliedRevision <= state.appliedRevision)
334
350
  return;
335
351
  state.appliedRevision = appliedRevision;
352
+ // Adopted stylesheet writes in the renderer do not emit DOM mutations or
353
+ // invalidate the controller's separate CSSOM cache.
354
+ if (state.document && state.iframe.contentDocument === state.document) {
355
+ notifyBrowserStylesheetChange(state.document);
356
+ }
336
357
  projectionAcknowledgementVersion += 1;
337
358
  notifyProjectionAcknowledgementListeners();
338
359
  }
@@ -365,7 +386,13 @@ function notifyProjectionAcknowledgementListeners() {
365
386
  catch { /* ignore */ }
366
387
  }
367
388
  }
389
+ let frameRegistryVersion = 0;
390
+ /** Changes whenever a frame registers or unregisters, for `useSyncExternalStore`. */
391
+ export function getFrameRegistryVersion() {
392
+ return frameRegistryVersion;
393
+ }
368
394
  function notifyFrameRegistryListeners() {
395
+ frameRegistryVersion += 1;
369
396
  for (const listener of frameRegistryListeners) {
370
397
  try {
371
398
  listener();
@@ -7,6 +7,8 @@ import { createFrameThrottle } from "../overlay/frameThrottle.js";
7
7
  import { isNudgeUiDev } from "../runtime/devFlag.js";
8
8
  import { getNudgeUiRuntimeConfig, subscribeNudgeUiRuntime } from "../runtime/runtimeConfig.js";
9
9
  import { APP_INTERACTION_KEY } from "./keyboardShortcuts.js";
10
+ import { isInspectorUiEvent } from "./pageSurface.js";
11
+ import { disposeRuntimeIdentityClaims } from "../runtime/runtimeIdentityClaims.js";
10
12
  let activeRendererBootstrap = null;
11
13
  function ownsRendererBootstrap(owner) {
12
14
  return owner.active && activeRendererBootstrap?.owner === owner;
@@ -149,6 +151,7 @@ export function bootstrapRenderer() {
149
151
  activeRendererBootstrap = { owner, handle };
150
152
  try {
151
153
  observeFrameMetadata(owner);
154
+ owner.resourceDisposers.push(() => disposeRuntimeIdentityClaims(document));
152
155
  owner.resourceDisposers.push(subscribeNudgeUiRuntime(() => sendFrameRuntime(owner)));
153
156
  const disposeDiagnostics = startRendererProjectionDiagnostics();
154
157
  if (disposeDiagnostics)
@@ -319,7 +322,7 @@ function installRendererPanProxy(owner) {
319
322
  sendToParent({ type: "app-interaction-modifier", protocolVersion: PROTOCOL_VERSION, held, ...identity });
320
323
  }
321
324
  const onKeyDown = (event) => {
322
- if (!ownsRendererBootstrap(owner))
325
+ if (!ownsRendererBootstrap(owner) || isInspectorUiEvent(event))
323
326
  return;
324
327
  if (event.code === APP_INTERACTION_KEY && !event.repeat && !isEditableTarget(event.target))
325
328
  sendAppInteractionModifier(true);
@@ -11,6 +11,7 @@ import { APPLICATION_GESTURE_EVENTS, blockApplicationClick, blockApplicationGest
11
11
  import { EMPTY_TEXT_PROJECTION_ATTR } from "../projection/textProjection.js";
12
12
  import { getSpacingAffordanceAtPoint, getSpacingHoverAtPoint, toSpacingDescriptor, } from "../overlay/spacingGestures.js";
13
13
  import { COMMENT_CURSOR, INTERACTION_CURSOR_PROPERTY, rendererCursorValue } from "../ui/customCursors.js";
14
+ import { isInspectorUiEvent, isPageSurface } from "./pageSurface.js";
14
15
  const REACT_FIBER_KEY = /^__reactFiber\$/;
15
16
  const REACT_INTERNAL_KEY = /^__reactInternalInstance\$/;
16
17
  const HOVER_SCROLL_SETTLE_DELAY = 150;
@@ -94,7 +95,11 @@ export function installRendererElementSelector(acceptsClick = isUserClick) {
94
95
  let suppressHoverDuringSpacingDrag = false;
95
96
  let lastHoverPoint = null;
96
97
  function trackListener(target, type, listener, options) {
97
- const eventListener = (event) => listener(event);
98
+ const eventListener = (event) => {
99
+ if (isInspectorUiEvent(event))
100
+ return;
101
+ listener(event);
102
+ };
98
103
  target.addEventListener(type, eventListener, options);
99
104
  listenerCleanup.push(() => target.removeEventListener(type, eventListener, options));
100
105
  }
@@ -507,6 +512,9 @@ export function installRendererElementSelector(acceptsClick = isUserClick) {
507
512
  }
508
513
  trackListener(document, "mouseup", finishDrag, true);
509
514
  function forwardKeyboardShortcut(event, phase) {
515
+ // The controller's own window listeners already see page-surface keys.
516
+ if (isPageSurface())
517
+ return false;
510
518
  const code = isKeyboardShortcutCode(event.code) ? event.code : null;
511
519
  if (!code)
512
520
  return false;
@@ -1,9 +1,8 @@
1
- import { type FrameIdentity, type FrameProtocolMessage } from "./frameProtocol.js";
1
+ import { type RendererToControllerMessage } from "./frameProtocol.js";
2
+ import { type FrameConnection } from "./frameConnection.js";
2
3
  export interface CanvasRendererMessage {
3
- cardId: string;
4
- iframe: HTMLIFrameElement;
5
- identity: FrameIdentity;
6
- message: FrameProtocolMessage;
4
+ frame: FrameConnection;
5
+ message: RendererToControllerMessage;
7
6
  }
8
7
  type CanvasRendererMessageListener = (event: CanvasRendererMessage) => void;
9
8
  /** Subscribes to same-origin messages from registered Canvas renderer frames. */
@@ -1,32 +1,28 @@
1
- import { isRendererMessageFor, PROTOCOL_VERSION, } from "./frameProtocol.js";
2
- import { findCanvasFrameBySource, PROJECT_ID, WORKSPACE_ID } from "./projection.js";
1
+ import { isRendererMessageFor, isRendererMessageType, PROTOCOL_VERSION, } from "./frameProtocol.js";
2
+ import { connectFrame } from "./frameConnection.js";
3
+ import { findCanvasFrameBySource } from "./projection.js";
3
4
  const listeners = new Set();
4
5
  function routeRendererMessage(event) {
5
6
  if (event.origin !== window.location.origin || !event.data || typeof event.data !== "object")
6
7
  return;
7
- const frame = findCanvasFrameBySource(event.source);
8
- if (!frame)
8
+ const source = findCanvasFrameBySource(event.source);
9
+ if (!source)
9
10
  return;
10
- const identity = {
11
- projectId: PROJECT_ID,
12
- workspaceId: WORKSPACE_ID,
13
- cardId: frame.cardId,
14
- };
11
+ const frame = connectFrame(source.cardId, source.iframe);
15
12
  // SAFETY: The object guard above makes the optional discriminator fields safe to inspect.
16
13
  const candidate = event.data;
14
+ if (!isRendererMessageType(candidate.type))
15
+ return;
17
16
  if (candidate.type === "renderer-hello") {
18
17
  if (candidate.protocolVersion !== PROTOCOL_VERSION)
19
18
  return;
20
19
  }
21
- else if (!isRendererMessageFor(event.data, identity)) {
20
+ else if (!isRendererMessageFor(event.data, frame.identity)) {
22
21
  return;
23
22
  }
24
- const routed = {
25
- ...frame,
26
- identity,
27
- // SAFETY: Subscribers narrow the discriminated protocol union before reading message-specific fields.
28
- message: event.data,
29
- };
23
+ // SAFETY: The type is a known renderer message; subscribers narrow it and
24
+ // apply the strict per-message schema before trusting message-specific fields.
25
+ const routed = { frame, message: event.data };
30
26
  for (const listener of listeners)
31
27
  listener(routed);
32
28
  }
@@ -1,2 +1,8 @@
1
1
  import type { ElementClickMessage } from "./frameProtocol.js";
2
- export declare function handleElementClick(msg: ElementClickMessage, iframe: HTMLIFrameElement, cardId: string): void;
2
+ import type { FrameConnection } from "./frameConnection.js";
3
+ /**
4
+ * Selects the exact DOM node the user clicked inside a card's frame, so the
5
+ * controller mutates that physical node. If it no longer exists, the card is
6
+ * selected instead of binding the click to an unrelated node.
7
+ */
8
+ export declare function handleElementClick(msg: ElementClickMessage, frame: FrameConnection): void;
@@ -1,44 +1,16 @@
1
1
  import { getSelectedElements, setSelectedElement, toggleSelectedElement } from "../selection/selectionStore.js";
2
2
  import { selectCard } from "./canvasStore.js";
3
- import { RENDERER_ELEMENT_ID_ATTR } from "./rendererCidIndex.js";
4
3
  import { inspectComponentTargets } from "../componentSemantics/index.js";
5
- function isHtmlElementInDocument(node, doc) {
6
- const frameWindow = doc.defaultView;
7
- return frameWindow !== null && node instanceof frameWindow.HTMLElement;
8
- }
9
4
  /**
10
- * Resolve the exact DOM element inside a card's iframe that matches an
11
- * element-click message. The renderer (running inside the iframe) tells us
12
- * the clicked element's renderer-owned `elementId`; we re-find the element by
13
- * that stable data attribute so that the parent app can mutate the same
14
- * physical DOM node the user clicked.
15
- *
16
- * The resolution uses a scoped ID query and never depends on document order.
17
- *
18
- * If the exact renderer-owned node no longer exists, fail closed instead of
19
- * binding the copied component metadata to an unrelated DOM node.
5
+ * Selects the exact DOM node the user clicked inside a card's frame, so the
6
+ * controller mutates that physical node. If it no longer exists, the card is
7
+ * selected instead of binding the click to an unrelated node.
20
8
  */
21
- function findClickedElement(doc, elementId, cid, src) {
22
- if (!doc)
23
- return null;
24
- if (!/^r\d+$/.test(elementId))
25
- return null;
26
- const candidates = doc.querySelectorAll(`[${RENDERER_ELEMENT_ID_ATTR}="${elementId}"]`);
27
- if (candidates.length !== 1)
28
- return null;
29
- const candidate = candidates[0] ?? null;
30
- if (!candidate
31
- || candidate.getAttribute("data-cid") !== cid
32
- || (candidate.getAttribute("data-src") ?? "") !== src)
33
- return null;
34
- return isHtmlElementInDocument(candidate, doc) ? candidate : null;
35
- }
36
- export function handleElementClick(msg, iframe, cardId) {
37
- const doc = iframe.contentDocument;
38
- const el = findClickedElement(doc, msg.elementId, msg.cid, msg.src);
9
+ export function handleElementClick(msg, frame) {
10
+ const el = frame.element(msg);
39
11
  if (!el) {
40
12
  setSelectedElement(null);
41
- selectCard(cardId);
13
+ selectCard(frame.cardId);
42
14
  return;
43
15
  }
44
16
  const componentTargets = inspectComponentTargets(el);
@@ -55,11 +27,11 @@ export function handleElementClick(msg, iframe, cardId) {
55
27
  // setSelectedElement must run before any side effect that could reload the
56
28
  // host page, otherwise the selection would be discarded by the unload.
57
29
  const current = getSelectedElements();
58
- if (msg.additive && current.length > 0 && current.every((candidate) => candidate.domElement.ownerDocument === doc)) {
30
+ if (msg.additive && current.length > 0 && current.every((candidate) => candidate.domElement.ownerDocument === el.ownerDocument)) {
59
31
  toggleSelectedElement(selected);
60
32
  }
61
33
  else {
62
34
  setSelectedElement(selected);
63
35
  }
64
- selectCard(cardId);
36
+ selectCard(frame.cardId);
65
37
  }
@@ -9,8 +9,15 @@ import { applyStructuralProjection, getStructuralProjectionReports, isStructural
9
9
  import { applyTextContentProjection, getTextProjectionReports, subscribeTextProjectionDiagnostics, } from "../projection/textProjection.js";
10
10
  import { isTextContentChangeListValue } from "../changes/types.js";
11
11
  import { applyDraftProjection, } from "../projection/draftProjection.js";
12
+ import { adoptStylesheet, allowsStyleElements } from "../runtime/ownedStylesheets.js";
13
+ import { applyRuntimeIdentityClaims, isRuntimeIdentityClaim } from "../runtime/runtimeIdentityClaims.js";
12
14
  const SHEET_ID = "nudge-ui-styles";
13
15
  function replaceRendererCss(css) {
16
+ if (!allowsStyleElements(document)) {
17
+ adoptStylesheet(document, SHEET_ID, css);
18
+ notifyBrowserStylesheetChange(document);
19
+ return;
20
+ }
14
21
  let sheet = document.getElementById(SHEET_ID);
15
22
  if (!sheet) {
16
23
  sheet = document.createElement("style");
@@ -22,6 +29,9 @@ function replaceRendererCss(css) {
22
29
  notifyBrowserStylesheetChange(document);
23
30
  }
24
31
  const rendererDocumentProjectionAdapter = {
32
+ applyRuntimeIdentities: (claims) => {
33
+ applyRuntimeIdentityClaims(document, claims);
34
+ },
25
35
  applyStructural: (changes) => {
26
36
  applyStructuralProjection(document, changes);
27
37
  },
@@ -44,6 +54,7 @@ function projectionFromReplaceStylesMessage(msg) {
44
54
  structuralChanges: msg.structuralChanges,
45
55
  textContentChanges: msg.textContentChanges,
46
56
  componentOverrides: msg.componentOverrides,
57
+ runtimeIdentities: msg.runtimeIdentities,
47
58
  };
48
59
  }
49
60
  let lastAppliedRevision = -1;
@@ -195,6 +206,10 @@ export function validateReplaceStyles(msg, projectId, workspaceId, cardId) {
195
206
  if (!isTextContentChangeListValue(m.textContentChanges)) {
196
207
  return { valid: false, reason: "text content changes are invalid" };
197
208
  }
209
+ if (m.runtimeIdentities !== undefined
210
+ && (!Array.isArray(m.runtimeIdentities) || !m.runtimeIdentities.every(isRuntimeIdentityClaim))) {
211
+ return { valid: false, reason: "runtime identities are invalid" };
212
+ }
198
213
  if (!isComponentOverrideList(m.componentOverrides)) {
199
214
  return { valid: false, reason: "component overrides are invalid" };
200
215
  }
@@ -38,8 +38,8 @@ export interface HydrationResult {
38
38
  export declare function serializeSession(): DurableSession;
39
39
  export declare function persistSession(): boolean;
40
40
  export declare function hydrateSession(): HydrationResult;
41
- /** Clears the active frame's edit draft while preserving canvas geometry and other drafts. */
42
- export declare function clearSelectedFrameChanges(): void;
41
+ /** Clears the active draft, its comments, and project sketches while preserving canvas geometry and other drafts. */
42
+ export declare function clearSelectedFrameChanges(): Promise<void>;
43
43
  export declare function clearSession(): void;
44
44
  export declare function enableAutoSave(): void;
45
45
  /**
@@ -1,11 +1,12 @@
1
+ import { inspectorStorage } from "../runtime/inspectorStorage.js";
1
2
  import { isFrameContent } from "./frameContent.js";
2
3
  import { clearComments } from "../comments/store.js";
4
+ import { clearSketchesForProject } from "../sketch/store.js";
5
+ import { clearSketchClipboardHandoff } from "../sketch/handoff.js";
3
6
  import { documentTarget, targetFromKey } from "../drafts/model.js";
4
- import { canEditDraft, getActiveDraftChanges, isDraftLocked } from "../changes/draftChanges.js";
5
7
  import { getFrameGroups, isFrameGroup, getCanvasCards, getFocusedCardId, getSelectedCardId, hydrateCanvasStore, removeCanvasCard, } from "./canvasStore.js";
6
8
  import { getCanvasMode, getCanvasPresentation, getBoardCamera, setBoardCamera, } from "./viewStore.js";
7
9
  import { applyRules } from "../projection/managedStylesheet.js";
8
- import { clearActiveDraft } from "../changes/changesLog.js";
9
10
  import { removeManagedSheet } from "../projection/managedStylesheet.js";
10
11
  import { setSelectedElement } from "../selection/selectionStore.js";
11
12
  import { canWriteWorkspace } from "./workspaceLease.js";
@@ -13,7 +14,7 @@ import { resetStructuralDeleteProjection, } from "../projection/structuralProjec
13
14
  import { projectToAllReadyCards } from "./projection.js";
14
15
  import { getNudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
15
16
  import { clearClipboardHandoff, getClipboardHandoffSnapshot, hydrateClipboardHandoff, isClipboardHandoffSnapshot, } from "../prompt/clipboardHandoff.js";
16
- import { activateDraftForCard, clearDrafts, persistDrafts } from "../drafts/store.js";
17
+ import { activateDraftForCard, canEditDraft, clearActiveDraft, clearDrafts, getActiveDraftChanges, isDraftLocked, persistDrafts, } from "../drafts/store.js";
17
18
  const SCHEMA_VERSION = 17;
18
19
  const STORAGE_PREFIX = "nudge-ui";
19
20
  function projectId() {
@@ -79,7 +80,7 @@ function persistSessionUnchecked() {
79
80
  try {
80
81
  persistDrafts();
81
82
  const session = buildSession();
82
- localStorage.setItem(storageKey(projectId()), JSON.stringify(session));
83
+ inspectorStorage()?.setItem(storageKey(projectId()), JSON.stringify(session));
83
84
  return true;
84
85
  }
85
86
  catch {
@@ -92,7 +93,7 @@ export function hydrateSession() {
92
93
  return { restored: false, changeCount: 0 };
93
94
  let raw = null;
94
95
  try {
95
- raw = localStorage.getItem(storageKey(projectId()));
96
+ raw = inspectorStorage()?.getItem(storageKey(projectId())) ?? null;
96
97
  }
97
98
  catch {
98
99
  return { restored: false, changeCount: 0 };
@@ -211,24 +212,26 @@ export function hydrateSession() {
211
212
  }
212
213
  function safeDiscard() {
213
214
  try {
214
- localStorage.removeItem(storageKey(projectId()));
215
+ inspectorStorage()?.removeItem(storageKey(projectId()));
215
216
  }
216
217
  catch {
217
218
  // ignore
218
219
  }
219
220
  }
220
- /** Clears the active frame's edit draft while preserving canvas geometry and other drafts. */
221
+ /** Clears the active draft, its comments, and project sketches while preserving canvas geometry and other drafts. */
221
222
  export function clearSelectedFrameChanges() {
222
223
  if (!canEditDraft())
223
- return;
224
+ return Promise.resolve();
224
225
  const cardId = getSelectedCardId() ?? getFocusedCardId();
225
226
  if (cardId)
226
227
  activateDraftForCard(cardId);
227
228
  clearComments(targetFromKey(getActiveDraftChanges().draftId) ?? documentTarget(window.location.href));
228
229
  clearActiveDraft();
230
+ clearSketchClipboardHandoff();
229
231
  setSelectedElement(null);
230
232
  projectToAllReadyCards();
231
233
  scheduleAutoSave();
234
+ return clearSketchesForProject();
232
235
  }
233
236
  export function clearSession() {
234
237
  if (isDraftLocked())
@@ -236,7 +239,7 @@ export function clearSession() {
236
239
  if (!canWriteWorkspace())
237
240
  return;
238
241
  try {
239
- localStorage.removeItem(storageKey(projectId()));
242
+ inspectorStorage()?.removeItem(storageKey(projectId()));
240
243
  }
241
244
  catch {
242
245
  // ignore
@@ -1,4 +1,4 @@
1
- import type { ChangeRecord } from "../changes/changesLog.js";
1
+ import { type ChangeRecord } from "../changes/types.js";
2
2
  export type StaleChangeStatus = "unverified" | "verified" | "stale" | "token-drift";
3
3
  export interface StaleChangeInfo {
4
4
  index: number;