nudge-ui 0.2.3 → 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 (264) hide show
  1. package/dist/cli/agentCommand.js +4 -28
  2. package/dist/client.mjs +870 -212
  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 +5 -7
  16. package/dist/inspector/agent/verification.js +67 -20
  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 +23 -12
  22. package/dist/inspector/canvas/CanvasElementOverlay.js +97 -128
  23. package/dist/inspector/canvas/CanvasToolbar.js +2 -1
  24. package/dist/inspector/canvas/CanvasWorkspace.js +119 -162
  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/frameScrollbarStyles.d.ts +3 -0
  49. package/dist/inspector/canvas/frameScrollbarStyles.js +21 -0
  50. package/dist/inspector/canvas/pageSurface.d.ts +11 -0
  51. package/dist/inspector/canvas/pageSurface.js +34 -0
  52. package/dist/inspector/canvas/projection.d.ts +19 -9
  53. package/dist/inspector/canvas/projection.js +58 -31
  54. package/dist/inspector/canvas/rendererBootstrap.js +4 -1
  55. package/dist/inspector/canvas/rendererElementSelector.js +9 -1
  56. package/dist/inspector/canvas/rendererMessageRouter.d.ts +4 -5
  57. package/dist/inspector/canvas/rendererMessageRouter.js +12 -16
  58. package/dist/inspector/canvas/rendererSelectionProxy.d.ts +7 -1
  59. package/dist/inspector/canvas/rendererSelectionProxy.js +8 -36
  60. package/dist/inspector/canvas/rendererStylesheet.js +15 -0
  61. package/dist/inspector/canvas/sessionStore.d.ts +2 -2
  62. package/dist/inspector/canvas/sessionStore.js +12 -9
  63. package/dist/inspector/canvas/staleChangeDetector.d.ts +1 -1
  64. package/dist/inspector/canvas/staleChangeDetector.js +10 -22
  65. package/dist/inspector/changes/codecs.d.ts +2 -0
  66. package/dist/inspector/changes/codecs.js +27 -3
  67. package/dist/inspector/changes/draftPreview.d.ts +12 -0
  68. package/dist/inspector/changes/draftPreview.js +133 -0
  69. package/dist/inspector/changes/editModel.d.ts +18 -0
  70. package/dist/inspector/changes/editModel.js +16 -3
  71. package/dist/inspector/changes/managedStyleProjection.js +2 -1
  72. package/dist/inspector/changes/previewDiagnostics.js +1 -1
  73. package/dist/inspector/changes/types.d.ts +18 -1
  74. package/dist/inspector/comments/CommentsOverlay.js +18 -16
  75. package/dist/inspector/comments/element.js +10 -3
  76. package/dist/inspector/comments/store.js +3 -2
  77. package/dist/inspector/comments/verification.js +1 -1
  78. package/dist/inspector/componentSemantics/ComponentPropsSection.js +2 -1
  79. package/dist/inspector/componentSemantics/adapterRegistry.d.ts +6 -1
  80. package/dist/inspector/componentSemantics/adapterRegistry.js +23 -1
  81. package/dist/inspector/componentSemantics/changeAction.js +1 -1
  82. package/dist/inspector/componentSemantics/reactRuntime.d.ts +2 -1
  83. package/dist/inspector/componentSemantics/reactRuntime.js +38 -0
  84. package/dist/inspector/componentSemantics/runtimeBridge.d.ts +4 -2
  85. package/dist/inspector/componentSemantics/runtimeBridge.js +17 -0
  86. package/dist/inspector/componentSemantics/textBinding.d.ts +1 -2
  87. package/dist/inspector/componentSemantics/textBinding.js +4 -45
  88. package/dist/inspector/componentSemantics/types.d.ts +11 -0
  89. package/dist/inspector/drafts/draftStore.d.ts +109 -0
  90. package/dist/inspector/drafts/draftStore.js +451 -0
  91. package/dist/inspector/drafts/model.d.ts +9 -1
  92. package/dist/inspector/drafts/model.js +5 -1
  93. package/dist/inspector/drafts/store.d.ts +53 -15
  94. package/dist/inspector/drafts/store.js +143 -169
  95. package/dist/inspector/index.d.ts +2 -4
  96. package/dist/inspector/index.js +2 -264
  97. package/dist/inspector/inline-text/inlineTextEditor.d.ts +1 -1
  98. package/dist/inspector/inline-text/inlineTextEditor.js +1 -2
  99. package/dist/inspector/inline-text/textEditChange.d.ts +1 -1
  100. package/dist/inspector/inspection/bridge.d.ts +1 -1
  101. package/dist/inspector/inspection/bridge.js +2 -1
  102. package/dist/inspector/inspection/browserCssInspection.d.ts +8 -0
  103. package/dist/inspector/inspection/browserCssInspection.js +28 -6
  104. package/dist/inspector/inspection/inspectionSnapshot.d.ts +6 -0
  105. package/dist/inspector/inspection/inspectionSnapshot.js +10 -0
  106. package/dist/inspector/inspection/performanceDiagnostics.d.ts +18 -0
  107. package/dist/inspector/inspection/performanceDiagnostics.js +31 -0
  108. package/dist/inspector/inspection/useBrowserCssInspection.js +17 -38
  109. package/dist/inspector/iterations/capture.d.ts +2 -1
  110. package/dist/inspector/iterations/capture.js +2 -1
  111. package/dist/inspector/iterations/client.d.ts +2 -1
  112. package/dist/inspector/iterations/coordinator.d.ts +4 -3
  113. package/dist/inspector/iterations/coordinator.js +5 -3
  114. package/dist/inspector/iterations/prompt.js +9 -8
  115. package/dist/inspector/overlay/interactionStyles.js +17 -0
  116. package/dist/inspector/pageInspector.d.ts +42 -0
  117. package/dist/inspector/pageInspector.js +342 -0
  118. package/dist/inspector/projection/draftProjection.d.ts +10 -2
  119. package/dist/inspector/projection/draftProjection.js +9 -1
  120. package/dist/inspector/projection/managedStylesheet.js +24 -4
  121. package/dist/inspector/projection/renderedInstance.d.ts +15 -2
  122. package/dist/inspector/projection/renderedInstance.js +60 -7
  123. package/dist/inspector/projection/structuralProjection.d.ts +0 -9
  124. package/dist/inspector/projection/structuralProjection.js +16 -46
  125. package/dist/inspector/projection/textProjection.d.ts +8 -2
  126. package/dist/inspector/projection/textProjection.js +77 -24
  127. package/dist/inspector/prompt/clipboardHandoff.d.ts +14 -0
  128. package/dist/inspector/prompt/clipboardHandoff.js +47 -16
  129. package/dist/inspector/prompt/generatePrompt.d.ts +1 -1
  130. package/dist/inspector/prompt/generatePrompt.js +248 -148
  131. package/dist/inspector/prompt/promptDocument.d.ts +3 -0
  132. package/dist/inspector/prompt/promptDocument.js +8 -0
  133. package/dist/inspector/prompt/promptSettings.js +7 -5
  134. package/dist/inspector/runtime/inspectorStorage.d.ts +17 -0
  135. package/dist/inspector/runtime/inspectorStorage.js +42 -0
  136. package/dist/inspector/runtime/ownedStylesheets.d.ts +20 -0
  137. package/dist/inspector/runtime/ownedStylesheets.js +72 -0
  138. package/dist/inspector/runtime/runtimeConfig.d.ts +4 -0
  139. package/dist/inspector/runtime/runtimeConfig.js +10 -1
  140. package/dist/inspector/runtime/runtimeIdentityClaims.d.ts +29 -0
  141. package/dist/inspector/runtime/runtimeIdentityClaims.js +188 -0
  142. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.d.ts +15 -0
  143. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.js +113 -29
  144. package/dist/inspector/selection/editScope.d.ts +1 -0
  145. package/dist/inspector/selection/editScope.js +13 -2
  146. package/dist/inspector/selection/sourceSite.d.ts +12 -0
  147. package/dist/inspector/selection/sourceSite.js +28 -0
  148. package/dist/inspector/shell/AgentStatusButton.js +2 -2
  149. package/dist/inspector/shell/AppShell.js +6 -2
  150. package/dist/inspector/shell/ChangesLog.js +27 -9
  151. package/dist/inspector/shell/CopyPromptButton.js +74 -26
  152. package/dist/inspector/shell/EmptyState.js +3 -3
  153. package/dist/inspector/shell/InspectorShell.d.ts +0 -3
  154. package/dist/inspector/shell/InspectorShell.js +21 -13
  155. package/dist/inspector/shell/PeekOriginalButton.js +3 -3
  156. package/dist/inspector/shell/interactionStatePreview.d.ts +9 -0
  157. package/dist/inspector/shell/interactionStatePreview.js +112 -0
  158. package/dist/inspector/shell/originalPreview.d.ts +3 -2
  159. package/dist/inspector/shell/originalPreview.js +10 -37
  160. package/dist/inspector/shell/stateValue.js +2 -3
  161. package/dist/inspector/sketch/SketchEditor.js +5 -4
  162. package/dist/inspector/sketch/SketchFrameOverlay.d.ts +2 -1
  163. package/dist/inspector/sketch/SketchFrameOverlay.js +5 -4
  164. package/dist/inspector/sketch/SketchOverlay.d.ts +3 -5
  165. package/dist/inspector/sketch/SketchOverlay.js +139 -263
  166. package/dist/inspector/sketch/SketchPromptPanel.d.ts +1 -1
  167. package/dist/inspector/sketch/SketchPromptPanel.js +8 -1
  168. package/dist/inspector/sketch/SketchThumbnail.d.ts +5 -0
  169. package/dist/inspector/sketch/SketchThumbnail.js +18 -0
  170. package/dist/inspector/sketch/SketchWorkspace.d.ts +1 -2
  171. package/dist/inspector/sketch/SketchWorkspace.js +69 -34
  172. package/dist/inspector/sketch/capture.js +19 -3
  173. package/dist/inspector/sketch/copySketch.d.ts +10 -0
  174. package/dist/inspector/sketch/copySketch.js +52 -0
  175. package/dist/inspector/sketch/drawingTools.d.ts +17 -0
  176. package/dist/inspector/sketch/drawingTools.js +47 -0
  177. package/dist/inspector/sketch/frameHeading.d.ts +9 -0
  178. package/dist/inspector/sketch/frameHeading.js +30 -0
  179. package/dist/inspector/sketch/freehand.js +3 -3
  180. package/dist/inspector/sketch/geometry.d.ts +6 -0
  181. package/dist/inspector/sketch/geometry.js +19 -0
  182. package/dist/inspector/sketch/history.d.ts +30 -0
  183. package/dist/inspector/sketch/history.js +58 -0
  184. package/dist/inspector/sketch/interaction.d.ts +1 -3
  185. package/dist/inspector/sketch/interaction.js +6 -9
  186. package/dist/inspector/sketch/model.d.ts +35 -1
  187. package/dist/inspector/sketch/model.js +116 -61
  188. package/dist/inspector/sketch/persistence.d.ts +14 -0
  189. package/dist/inspector/sketch/persistence.js +63 -7
  190. package/dist/inspector/sketch/raster.d.ts +6 -2
  191. package/dist/inspector/sketch/raster.js +43 -17
  192. package/dist/inspector/sketch/store.d.ts +1 -1
  193. package/dist/inspector/sketch/store.js +1 -1
  194. package/dist/inspector/sketch/videoFrames.d.ts +6 -0
  195. package/dist/inspector/sketch/videoFrames.js +81 -0
  196. package/dist/inspector/styleEditors/BackgroundEditor.js +3 -2
  197. package/dist/inspector/styleEditors/BorderEditor.js +30 -130
  198. package/dist/inspector/styleEditors/BorderRadiusEditor.js +8 -3
  199. package/dist/inspector/styleEditors/ImageBackgroundEditor.js +1 -1
  200. package/dist/inspector/styleEditors/LayoutSection.js +2 -2
  201. package/dist/inspector/styleEditors/borderModel.d.ts +42 -0
  202. package/dist/inspector/styleEditors/borderModel.js +114 -0
  203. package/dist/inspector/styleEditors/layoutValue.js +2 -3
  204. package/dist/inspector/tokens/TokenField.js +40 -7
  205. package/dist/inspector/tokens/TokensPanel.js +2 -1
  206. package/dist/inspector/tokens/editActions.d.ts +3 -3
  207. package/dist/inspector/tokens/editActions.js +15 -3
  208. package/dist/inspector/tokens/resolution/containerQueryEvaluator.d.ts +15 -0
  209. package/dist/inspector/tokens/resolution/containerQueryEvaluator.js +86 -0
  210. package/dist/inspector/tokens/resolution/cssomCollector.js +44 -9
  211. package/dist/inspector/tokens/resolution/nestedSelectors.d.ts +6 -0
  212. package/dist/inspector/tokens/resolution/nestedSelectors.js +67 -0
  213. package/dist/inspector/tokens/resolution/ruleMatching.js +23 -4
  214. package/dist/inspector/tokens/resolution.d.ts +6 -3
  215. package/dist/inspector/tokens/resolution.js +91 -112
  216. package/dist/inspector/tokens/tokenEdits.d.ts +1 -1
  217. package/dist/inspector/tokens/tokenEdits.js +1 -1
  218. package/dist/inspector/ui/InlineStyleWarning.js +2 -2
  219. package/dist/inspector/ui/InspectorStyle.d.ts +8 -0
  220. package/dist/inspector/ui/InspectorStyle.js +26 -0
  221. package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
  222. package/dist/inspector/ui/PopoverListbox.js +3 -3
  223. package/dist/inspector/ui/Toast.d.ts +14 -0
  224. package/dist/inspector/ui/Toast.js +30 -0
  225. package/dist/inspector/ui/assets/canvasIllustration.d.ts +2 -0
  226. package/dist/inspector/ui/assets/canvasIllustration.js +21 -0
  227. package/dist/inspector/ui/assets/gridIllustration.d.ts +2 -0
  228. package/dist/inspector/ui/assets/{grid.svg → gridIllustration.js} +3 -2
  229. package/dist/inspector/ui/customCursors.d.ts +5 -0
  230. package/dist/inspector/ui/customCursors.js +32 -6
  231. package/dist/inspector/ui/styles.js +12 -10
  232. package/dist/inspector/workspace/commands.js +1 -2
  233. package/dist/inspector/workspace/controller.js +1 -2
  234. package/dist/inspector/workspace/handoff.js +3 -2
  235. package/dist/inspector/workspace/sentItems.d.ts +16 -0
  236. package/dist/inspector/workspace/sentItems.js +33 -0
  237. package/dist/inspector/workspace/timeline.d.ts +24 -10
  238. package/dist/inspector/workspace/timeline.js +118 -96
  239. package/dist/internal/agent-protocol.d.ts +50 -13
  240. package/dist/internal/agent-protocol.js +145 -19
  241. package/dist/nudge-ui.mjs +81 -65
  242. package/dist/project/mcpPackage.d.ts +8 -0
  243. package/dist/project/mcpPackage.js +60 -0
  244. package/package.json +13 -3
  245. package/dist/inspector/canvas/measurementProjection.d.ts +0 -8
  246. package/dist/inspector/canvas/measurementProjection.js +0 -16
  247. package/dist/inspector/changes/changesLog.d.ts +0 -47
  248. package/dist/inspector/changes/changesLog.js +0 -247
  249. package/dist/inspector/changes/draftChanges.d.ts +0 -56
  250. package/dist/inspector/changes/draftChanges.js +0 -300
  251. package/dist/inspector/conformance/projection.d.ts +0 -2
  252. package/dist/inspector/conformance/projection.js +0 -3
  253. package/dist/inspector/inline-text/textChangeBoundary.d.ts +0 -6
  254. package/dist/inspector/inline-text/textChangeBoundary.js +0 -1
  255. package/dist/inspector/overlay/InspectorOverlay.d.ts +0 -5
  256. package/dist/inspector/overlay/InspectorOverlay.js +0 -332
  257. package/dist/inspector/overlay/elementSelector.d.ts +0 -1
  258. package/dist/inspector/overlay/elementSelector.js +0 -111
  259. package/dist/inspector/sketch/SketchChanges.d.ts +0 -2
  260. package/dist/inspector/sketch/SketchChanges.js +0 -72
  261. package/dist/inspector/sketch/SketchEntryButton.d.ts +0 -4
  262. package/dist/inspector/sketch/SketchEntryButton.js +0 -11
  263. package/dist/inspector/sketch/SketchLayersPanel.d.ts +0 -2
  264. package/dist/inspector/sketch/SketchLayersPanel.js +0 -71
@@ -0,0 +1,297 @@
1
+ import { startWorkspaceController } from "./workspace/controller.js";
2
+ import { createElement } from "react";
3
+ import { createRoot } from "react-dom/client";
4
+ import { toggleInspector, setInspectorOpen } from "./shell/openStore.js";
5
+ import { setSelectedElement } from "./selection/selectionStore.js";
6
+ import { removeManagedSheet } from "./projection/managedStylesheet.js";
7
+ import { isInspectorToggleShortcut, isOriginalPreviewShortcut, SEND_PROMPT_HOTKEY_EVENT, } from "./shell/shortcuts.js";
8
+ import { isCanvasRenderer } from "./canvas/roleDetection.js";
9
+ import { isPageSurface } from "./canvas/pageSurface.js";
10
+ import { isKeyboardShortcutMessage } from "./canvas/frameProtocol.js";
11
+ import { subscribeCanvasRendererMessages } from "./canvas/rendererMessageRouter.js";
12
+ import { bootstrapRenderer } from "./canvas/rendererBootstrap.js";
13
+ import { setRestoreCount, } from "./canvas/sessionStore.js";
14
+ import { getChangesList } from "./drafts/store.js";
15
+ import { acquireLease, enableWriteGuard, hasWriteLease, releaseLease, subscribeOwnership, } from "./canvas/workspaceLease.js";
16
+ import { cancelStaleDetection, startStaleDetection } from "./canvas/staleChangeDetector.js";
17
+ import { LockedWorkspaceNotice } from "./canvas/LockedWorkspaceNotice.js";
18
+ import { AppShell } from "./shell/AppShell.js";
19
+ import { installInspectionBridge } from "./inspection/bridge.js";
20
+ import { releaseDocumentProjection, getStructuralChanges } from "./projection/structuralProjection.js";
21
+ import { cancelInlineTextEdit } from "./inline-text/inlineTextEditor.js";
22
+ import { configureNudgeUiRuntime, getNudgeUiRuntimeConfig, isDemoRuntime } from "./runtime/runtimeConfig.js";
23
+ import { setCanvasMode } from "./canvas/viewStore.js";
24
+ import { isNudgeUiDev, setNudgeUiHostDevFlag } from "./runtime/devFlag.js";
25
+ import { clearClipboardHandoff, } from "./prompt/clipboardHandoff.js";
26
+ import { createWorkspace, InspectorSessionProvider, } from "./session/index.js";
27
+ import { clearSketchClipboardHandoff } from "./sketch/handoff.js";
28
+ import { cancelSketchInteraction, isSketchInteractionActive } from "./sketch/interaction.js";
29
+ import { setOriginalPreviewActive } from "./shell/originalPreview.js";
30
+ import { initializeSketchStore } from "./sketch/store.js";
31
+ import { inspectorStorage } from "./runtime/inspectorStorage.js";
32
+ import { disposeRuntimeIdentityClaims } from "./runtime/runtimeIdentityClaims.js";
33
+ let hostElement = null;
34
+ let reactRoot = null;
35
+ let lockedRoot = null;
36
+ const workspace = createWorkspace();
37
+ let inspectorSession = null;
38
+ let rendererBootstrapHandle = null;
39
+ let workspaceController = null;
40
+ let unsubscribeOwnership = null;
41
+ let removeInspectionBridge = null;
42
+ let controllerStartId = 0;
43
+ let keyboardPeekHeld = false;
44
+ function onKeydown(e) {
45
+ if (isSketchInteractionActive())
46
+ return;
47
+ if (isInspectorToggleShortcut(e)) {
48
+ toggleInspector();
49
+ e.preventDefault();
50
+ return;
51
+ }
52
+ if (isOriginalPreviewShortcut(e)) {
53
+ keyboardPeekHeld = true;
54
+ setOriginalPreviewActive(true);
55
+ e.preventDefault();
56
+ }
57
+ }
58
+ function onKeyup(e) {
59
+ // Release only a keyboard-started peek so a button-held preview survives
60
+ // unrelated Backslash keyups (e.g. the panel-toggle shortcuts pressed
61
+ // mid-hold). A guarded keydown never sets the flag, so this stays a no-op
62
+ // for keyups without a matching hold.
63
+ if (e.code === "Backslash" && keyboardPeekHeld) {
64
+ keyboardPeekHeld = false;
65
+ setOriginalPreviewActive(false);
66
+ }
67
+ }
68
+ function onRendererKeyboardShortcut(message, identity) {
69
+ if (!isKeyboardShortcutMessage(message, identity))
70
+ return;
71
+ if (message.code === "KeyS" && message.phase === "keydown") {
72
+ window.dispatchEvent(new Event(SEND_PROMPT_HOTKEY_EVENT));
73
+ return;
74
+ }
75
+ if (message.code !== "Backslash")
76
+ return;
77
+ if (message.phase === "keydown") {
78
+ keyboardPeekHeld = true;
79
+ setOriginalPreviewActive(true);
80
+ }
81
+ else if (keyboardPeekHeld) {
82
+ keyboardPeekHeld = false;
83
+ setOriginalPreviewActive(false);
84
+ }
85
+ }
86
+ function disposeInspectorSession() {
87
+ const session = inspectorSession;
88
+ inspectorSession = null;
89
+ session?.dispose();
90
+ }
91
+ export function bootstrapNudgeUi(inspectorHost) {
92
+ controllerStartId += 1;
93
+ const runtimeConfig = getNudgeUiRuntimeConfig();
94
+ const explicitDemo = isDemoRuntime();
95
+ if (!isNudgeUiDev() && !explicitDemo)
96
+ return;
97
+ if (explicitDemo) {
98
+ rendererBootstrapHandle?.teardown();
99
+ rendererBootstrapHandle = null;
100
+ // ADR-0014: only the configured demo runtime opens the shared dev gate
101
+ // for its own document. The bundle mode name alone must never flip it,
102
+ // so every build without both opt-ins stays governed by ADR-0002.
103
+ setNudgeUiHostDevFlag(true);
104
+ if (runtimeConfig.capabilities.canvas && isCanvasRenderer()) {
105
+ rendererBootstrapHandle = bootstrapRenderer() ?? null;
106
+ return;
107
+ }
108
+ // The public demo shares the iframe editor while keeping the write lease,
109
+ // persistence, and agent bridge disabled.
110
+ setCanvasMode("canvas");
111
+ workspaceController?.dispose();
112
+ workspaceController = startWorkspaceController();
113
+ mountInspector(inspectorHost);
114
+ setInspectorOpen(false);
115
+ return;
116
+ }
117
+ if (!runtimeConfig.capabilities.canvas) {
118
+ // A project can be reopened with a runtime that does not expose Canvas.
119
+ // Clear any stale in-memory mode before mounting the static inspector.
120
+ setCanvasMode("inspect");
121
+ }
122
+ rendererBootstrapHandle?.teardown();
123
+ rendererBootstrapHandle = null;
124
+ removeInspectionBridge?.();
125
+ removeInspectionBridge = installInspectionBridge();
126
+ if (getNudgeUiRuntimeConfig().capabilities.canvas && isCanvasRenderer()) {
127
+ rendererBootstrapHandle = bootstrapRenderer() ?? null;
128
+ return;
129
+ }
130
+ enableWriteGuard();
131
+ const leaseGranted = acquireLease();
132
+ if (!leaseGranted) {
133
+ mountLockedNotice(inspectorHost);
134
+ return;
135
+ }
136
+ void startController(inspectorHost);
137
+ }
138
+ async function startController(inspectorHost) {
139
+ const startId = ++controllerStartId;
140
+ if (!hasWriteLease()) {
141
+ mountLockedNotice(inspectorHost);
142
+ return;
143
+ }
144
+ // Ownership prevents the previous tab from saving after this snapshot.
145
+ // Refresh on remount as well as explicit takeover, before hydration writes.
146
+ try {
147
+ const storage = inspectorStorage();
148
+ if (storage?.refresh)
149
+ await storage.refresh();
150
+ }
151
+ catch {
152
+ if (startId !== controllerStartId)
153
+ return;
154
+ releaseLease();
155
+ mountLockedNotice(inspectorHost, true);
156
+ return;
157
+ }
158
+ if (startId !== controllerStartId)
159
+ return;
160
+ if (!hasWriteLease()) {
161
+ mountLockedNotice(inspectorHost);
162
+ return;
163
+ }
164
+ if (lockedRoot) {
165
+ lockedRoot.unmount();
166
+ lockedRoot = null;
167
+ }
168
+ void initializeSketchStore(getNudgeUiRuntimeConfig().projectId).catch(() => undefined);
169
+ unsubscribeOwnership?.();
170
+ unsubscribeOwnership = subscribeOwnership((hasLease) => {
171
+ if (!hasLease) {
172
+ workspaceController?.dispose();
173
+ workspaceController = null;
174
+ mountLockedNotice(inspectorHost);
175
+ }
176
+ });
177
+ workspaceController?.dispose();
178
+ const result = startWorkspaceController();
179
+ workspaceController = result;
180
+ if (result.restored) {
181
+ setRestoreCount(getChangesList().length + getStructuralChanges().length);
182
+ const restored = getChangesList();
183
+ if (restored.length > 0) {
184
+ startStaleDetection(restored);
185
+ }
186
+ }
187
+ if (getNudgeUiRuntimeConfig().capabilities.canvas) {
188
+ // Normal controllers always host the iframe workspace. Hydration runs
189
+ // first so this mode change cannot discard cards, camera, or edits.
190
+ setCanvasMode("canvas");
191
+ }
192
+ mountInspector(inspectorHost);
193
+ if (getNudgeUiRuntimeConfig().capabilities.canvas && isPageSurface()) {
194
+ rendererBootstrapHandle = bootstrapRenderer() ?? null;
195
+ }
196
+ }
197
+ function mountLockedNotice(host, storageError = false) {
198
+ controllerStartId += 1;
199
+ if (reactRoot) {
200
+ reactRoot.unmount();
201
+ reactRoot = null;
202
+ }
203
+ try {
204
+ disposeInspectorSession();
205
+ }
206
+ finally {
207
+ cancelStaleDetection();
208
+ setInspectorOpen(false);
209
+ cancelInlineTextEdit();
210
+ cancelSketchInteraction();
211
+ clearSketchClipboardHandoff();
212
+ setSelectedElement(null);
213
+ removeManagedSheet();
214
+ disposeRuntimeIdentityClaims(document);
215
+ releaseDocumentProjection(document);
216
+ hostElement = null;
217
+ unsubscribeOwnership?.();
218
+ unsubscribeOwnership = null;
219
+ }
220
+ const shadow = host.shadowRoot ?? host.attachShadow({ mode: "open" });
221
+ if (!lockedRoot) {
222
+ lockedRoot = createRoot(shadow);
223
+ }
224
+ lockedRoot.render(createElement(LockedWorkspaceNotice, {
225
+ onTakeover: () => startController(host),
226
+ storageError,
227
+ }));
228
+ }
229
+ export function mountInspector(host) {
230
+ const demo = isDemoRuntime();
231
+ if (!demo && !hasWriteLease())
232
+ return;
233
+ const runtimeConfig = getNudgeUiRuntimeConfig();
234
+ if (runtimeConfig.capabilities.domNavigation !== true) {
235
+ configureNudgeUiRuntime({
236
+ ...runtimeConfig,
237
+ capabilities: { ...runtimeConfig.capabilities, domNavigation: true },
238
+ });
239
+ }
240
+ if (lockedRoot) {
241
+ lockedRoot.unmount();
242
+ lockedRoot = null;
243
+ }
244
+ if (!hostElement)
245
+ hostElement = host;
246
+ const shadow = host.shadowRoot ?? host.attachShadow({ mode: "open" });
247
+ if (!reactRoot) {
248
+ reactRoot = createRoot(shadow);
249
+ inspectorSession = workspace.createInspectorSession(host);
250
+ inspectorSession.registerCleanup(() => window.removeEventListener("keydown", onKeydown));
251
+ inspectorSession.registerCleanup(() => window.removeEventListener("keyup", onKeyup));
252
+ inspectorSession.registerCleanup(subscribeCanvasRendererMessages(({ frame, message }) => {
253
+ onRendererKeyboardShortcut(message, frame.identity);
254
+ }));
255
+ reactRoot.render(createElement(InspectorSessionProvider, { inspector: inspectorSession, documentSession: null }, createElement(AppShell)));
256
+ window.addEventListener("keydown", onKeydown);
257
+ window.addEventListener("keyup", onKeyup);
258
+ }
259
+ setInspectorOpen(true);
260
+ }
261
+ export function unmountInspector() {
262
+ controllerStartId += 1;
263
+ rendererBootstrapHandle?.teardown();
264
+ rendererBootstrapHandle = null;
265
+ workspaceController?.dispose();
266
+ workspaceController = null;
267
+ unsubscribeOwnership?.();
268
+ unsubscribeOwnership = null;
269
+ if (lockedRoot) {
270
+ lockedRoot.unmount();
271
+ lockedRoot = null;
272
+ }
273
+ cancelStaleDetection();
274
+ cancelInlineTextEdit();
275
+ cancelSketchInteraction();
276
+ setSelectedElement(null);
277
+ if (reactRoot) {
278
+ reactRoot.unmount();
279
+ reactRoot = null;
280
+ }
281
+ try {
282
+ disposeInspectorSession();
283
+ }
284
+ finally {
285
+ // Document-session cleanup already releases host projection when a
286
+ // session exists; release directly as well so projection applied outside
287
+ // a session (gestures, workspace projection) cannot leak across unmount.
288
+ disposeRuntimeIdentityClaims(document);
289
+ releaseDocumentProjection(document);
290
+ clearClipboardHandoff();
291
+ clearSketchClipboardHandoff();
292
+ removeManagedSheet();
293
+ removeInspectionBridge?.();
294
+ removeInspectionBridge = null;
295
+ hostElement = null;
296
+ }
297
+ }
@@ -1,3 +1,4 @@
1
+ import { type CanvasFrame } from "./canvasFrame.js";
1
2
  import { type ActivityFile } from "../agent/activity.js";
2
3
  import { type FrameContent } from "./frameContent.js";
3
4
  export interface ActivityAttribution {
@@ -9,5 +10,5 @@ export declare function attributeActivity(content: FrameContent, document: Docum
9
10
  export declare function AgentActivityOverlay({ cardId, content, iframe }: {
10
11
  cardId: string;
11
12
  content: FrameContent;
12
- iframe: HTMLIFrameElement | null;
13
+ iframe: CanvasFrame | null;
13
14
  }): import("react").JSX.Element | null;
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { canvasFrameElement } from "./canvasFrame.js";
2
3
  const activityStyles = ".canvas-agent-activity {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 12;\n overflow: hidden;\n border-radius: 4px;\n}\n\n.canvas-agent-activity__label {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n position: absolute;\n top: 12px;\n right: 12px;\n max-width: 80%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n padding: 4px 10px 4px 4px;\n border-radius: 20px;\n background: #242424e8;\n color: #fff;\n font: 12px system-ui;\n box-shadow: 0 2px 12px #0003;\n}\n\n.canvas-agent-activity__label canvas {\n flex: 0 0 auto;\n}\n\n.canvas-agent-activity__label > span {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.canvas-agent-activity__shimmer {\n position: absolute;\n border-radius: 5px;\n background: linear-gradient(110deg, transparent 20%, rgb(212 212 212 / 0.18) 35%, rgb(212 212 212 / 0.35) 50%, rgb(212 212 212 / 0.18) 65%, transparent 80%);\n background-size: 250% 100%;\n animation: nudge-component-shimmer 2.4s ease-in-out infinite;\n}\n\n@keyframes nudge-component-shimmer {\n from { background-position: 150% 0; }\n to { background-position: -150% 0; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .canvas-agent-activity__shimmer {\n animation: none;\n }\n}\n";
3
4
  import { useEffect, useState } from "react";
4
5
  import { ThinkingOrb } from "thinking-orbs";
@@ -7,6 +8,7 @@ import { getNudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
7
8
  import { parseDataSrc } from "../selection/resolveSelection.js";
8
9
  import { targetKey } from "../drafts/model.js";
9
10
  import { contentEditTarget } from "./frameContent.js";
11
+ import { InspectorStyle } from "../ui/InspectorStyle.js";
10
12
  /** Reuses rendered source identities. Iteration provenance cannot target application source. */
11
13
  export function attributeActivity(content, document, files) {
12
14
  const target = contentEditTarget(content);
@@ -99,13 +101,14 @@ export function AgentActivityOverlay({ cardId, content, iframe }) {
99
101
  };
100
102
  };
101
103
  attachDocument();
102
- iframe.addEventListener("load", attachDocument);
103
- return () => { iframe.removeEventListener("load", attachDocument); detachDocument(); };
104
+ const element = canvasFrameElement(iframe);
105
+ element?.addEventListener("load", attachDocument);
106
+ return () => { element?.removeEventListener("load", attachDocument); detachDocument(); };
104
107
  }, [activity, content, iframe]);
105
108
  const submitted = activity.requestId !== null && activity.targets.includes(cardId)
106
109
  && (!activity.target || targetKey(activity.target) === targetKey(contentEditTarget(content)));
107
110
  const working = activity.requestId !== null && (submitted || visual.files.length > 0);
108
111
  if (!working)
109
112
  return null;
110
- return _jsxs("div", { className: "canvas-agent-activity", "data-test": `canvas-agent-activity-${cardId}`, children: [visual.highlights.map((rect, index) => _jsx("div", { className: "canvas-agent-activity__shimmer", "data-test": "canvas-agent-component-shimmer", style: { left: rect.x, top: rect.y, width: rect.width, height: rect.height } }, index)), _jsxs("span", { className: "canvas-agent-activity__label", role: "status", children: [_jsx(ThinkingOrb, { state: "solving", size: 20, theme: "dark", "aria-hidden": "true" }), _jsx("span", { children: "Agent working\u2026" })] }), _jsx("style", { children: activityStyles })] });
113
+ return _jsxs("div", { className: "canvas-agent-activity", "data-test": `canvas-agent-activity-${cardId}`, children: [visual.highlights.map((rect, index) => _jsx("div", { className: "canvas-agent-activity__shimmer", "data-test": "canvas-agent-component-shimmer", style: { left: rect.x, top: rect.y, width: rect.width, height: rect.height } }, index)), _jsxs("span", { className: "canvas-agent-activity__label", role: "status", children: [_jsx(ThinkingOrb, { state: "solving", size: 20, theme: "dark", "aria-hidden": "true" }), _jsx("span", { children: "Agent working\u2026" })] }), _jsx(InspectorStyle, { css: activityStyles })] });
111
114
  }
@@ -4,11 +4,11 @@ import { contentDocumentUrl, contentNavigationUrl, contentSourceUrl, iterationId
4
4
  import { refreshHtmlIteration } from "../iterations/coordinator.js";
5
5
  import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
6
6
  import { CANVAS_RENDERER_ATTR } from "./roleDetection.js";
7
- import { useCanvasCards, getCanvasCardLabel, updateCardUrl, resizeCard, setCardPosition, selectCard, getSelectedCardId, useSelectedCardId, useFocusedCardId, } from "./canvasStore.js";
7
+ import { useCanvasCards, getCanvasCardLabel, updateCardUrl, resizeCard, setCardPosition, beginCardGeometryChange, selectCard, getSelectedCardId, useSelectedCardId, useFocusedCardId, } from "./canvasStore.js";
8
8
  import { useBoardCamera } from "./viewStore.js";
9
9
  import { IconArrowsDiagonal, IconCopy, IconCornerLeftDown, IconBoltFilled, IconArtboard, IconTrash } from "@tabler/icons-react";
10
- import { PROTOCOL_VERSION, } from "./frameProtocol.js";
11
- import { registerCardFrame, registerCardFrameSource, unregisterCardFrame, sendProjectionToCard, invalidateCanvasPreviewDocument, PROJECT_ID, WORKSPACE_ID } from "./projection.js";
10
+ import { connectFrame } from "./frameConnection.js";
11
+ import { registerCardFrame, registerCardFrameSource, unregisterCardFrame, sendProjectionToCard, invalidateCanvasPreviewDocument } from "./projection.js";
12
12
  import { Button } from "../ui/Button.js";
13
13
  import { IconButton } from "../ui/IconButton.js";
14
14
  import { Tooltip } from "../ui/Tooltip.js";
@@ -20,6 +20,7 @@ import { getCanvasToolbarScale } from "./toolbarScale.js";
20
20
  import { getCanvasResizeHandleScale } from "./resizeHandleScale.js";
21
21
  import { disposeBrowserCssInspection } from "../inspection/browserCssInspectionRegistry.js";
22
22
  import { releaseDocumentProjection } from "../projection/structuralProjection.js";
23
+ import { disposeRuntimeIdentityClaims } from "../runtime/runtimeIdentityClaims.js";
23
24
  import { startClipboardHandoffController } from "../prompt/clipboardHandoff.js";
24
25
  import { disposeInlineTextEdit, isInlineTextEditingActive } from "../inline-text/inlineTextEditor.js";
25
26
  import { configureNudgeUiRuntime, getNudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
@@ -27,6 +28,7 @@ import { useNudgeUiRuntimeConfig } from "../runtime/useRuntimeConfig.js";
27
28
  import { reconcileRuntimeWithDocumentStylesheets } from "../runtime/documentStylesheetOrder.js";
28
29
  import { subscribeCanvasRendererMessages } from "./rendererMessageRouter.js";
29
30
  import { SketchFrameOverlay } from "../sketch/SketchFrameOverlay.js";
31
+ import { installFrameScrollbarStyles } from "./frameScrollbarStyles.js";
30
32
  import { getCanvasResizeEdges, resizeCanvasRect, } from "./canvasResize.js";
31
33
  import { getDraftContentsForCard } from "../drafts/store.js";
32
34
  import { removeFrame } from "../workspace/commands.js";
@@ -92,14 +94,20 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
92
94
  const frameDocument = iframeRef.current?.contentDocument;
93
95
  if (!documentOwner || !frameDocument)
94
96
  return;
97
+ // The initial blank document is discarded by navigation. A blocked frame
98
+ // can make its Window inaccessible before cleanup runs.
99
+ if (frameDocument.URL === "about:blank")
100
+ return;
95
101
  if (documentSessionRef.current?.document === frameDocument)
96
102
  return;
97
103
  disposeDocumentSession();
98
104
  const session = documentOwner.createDocumentSession(frameDocument);
99
105
  session.registerCleanup(() => disposeBrowserCssInspection(frameDocument));
100
106
  session.registerCleanup(() => releaseDocumentProjection(frameDocument));
107
+ session.registerCleanup(() => disposeRuntimeIdentityClaims(frameDocument));
101
108
  session.registerCleanup(() => disposeInlineTextEdit("frame-disposed", frameDocument));
102
109
  session.registerCleanup(startClipboardHandoffController(frameDocument));
110
+ session.registerCleanup(installFrameScrollbarStyles(frameDocument));
103
111
  documentSessionRef.current = { document: frameDocument, session };
104
112
  }, [disposeDocumentSession, documentOwner]);
105
113
  useEffect(() => {
@@ -168,13 +176,8 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
168
176
  }
169
177
  /** The controller half of the handshake: announce workspace identity. */
170
178
  function sendParentReady() {
171
- iframeRef.current?.contentWindow?.postMessage({
172
- type: "parent-ready",
173
- protocolVersion: PROTOCOL_VERSION,
174
- projectId: PROJECT_ID,
175
- workspaceId: WORKSPACE_ID,
176
- cardId: card.id,
177
- }, window.location.origin);
179
+ if (iframeRef.current)
180
+ connectFrame(card.id, iframeRef.current).post({ type: "parent-ready" });
178
181
  }
179
182
  function adoptFrameRuntime(runtime) {
180
183
  frameRuntimeRef.current = runtime;
@@ -200,8 +203,8 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
200
203
  adoptFrameRuntime(frameRuntimeRef.current);
201
204
  }, [isSelected]);
202
205
  useEffect(() => {
203
- return subscribeCanvasRendererMessages(({ cardId, message: data }) => {
204
- if (cardId !== card.id)
206
+ return subscribeCanvasRendererMessages(({ frame, message: data }) => {
207
+ if (frame.cardId !== card.id)
205
208
  return;
206
209
  // A renderer whose runtime finished booting after the iframe load event
207
210
  // asks for the identity announcement it may have missed.
@@ -292,6 +295,8 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
292
295
  e.stopPropagation();
293
296
  e.preventDefault();
294
297
  const iterationDrag = e.altKey && !!onCreateIteration && loadState === "ready" && !creatingIteration;
298
+ // Iteration creation history already records where the new frame was dropped.
299
+ const commitMove = iterationDrag ? null : beginCardGeometryChange(card.id);
295
300
  let moved = false;
296
301
  let iterationId;
297
302
  let creationStarted = false;
@@ -342,6 +347,7 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
342
347
  cleanup();
343
348
  setIsDragging(false);
344
349
  cancelled = true;
350
+ commitMove?.();
345
351
  if (iterationId) {
346
352
  removeFrame(iterationId, { undoable: false });
347
353
  selectCard(card.id);
@@ -350,6 +356,7 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
350
356
  function onUp() {
351
357
  cleanup();
352
358
  setIsDragging(false);
359
+ commitMove?.();
353
360
  if (iterationId)
354
361
  setCardPosition(iterationId, position.x, position.y);
355
362
  }
@@ -378,6 +385,7 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
378
385
  width: card.width,
379
386
  height: card.height,
380
387
  };
388
+ const commitResize = beginCardGeometryChange(card.id);
381
389
  function onMove(ev) {
382
390
  if (ev.pointerId !== pointerId)
383
391
  return;
@@ -397,6 +405,7 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
397
405
  target.releasePointerCapture(pointerId);
398
406
  if (resizeCleanupRef.current === cleanup)
399
407
  resizeCleanupRef.current = null;
408
+ commitResize();
400
409
  }
401
410
  function onUp(ev) {
402
411
  if (ev.pointerId !== pointerId)
@@ -439,7 +448,9 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
439
448
  if ((delta.x !== 0 && edges.horizontal === null) || (delta.y !== 0 && edges.vertical === null))
440
449
  return;
441
450
  const next = resizeCanvasRect(card, direction, delta);
451
+ const commitResize = beginCardGeometryChange(card.id);
442
452
  resizeCard(card.id, next.width, next.height, { x: next.x, y: next.y });
453
+ commitResize();
443
454
  }
444
455
  return (_jsxs("div", { className: `canvas-card${linkedToActive ? " is-linked" : ""}${isDragging ? " is-dragging" : ""}${isSelected ? " is-selected" : ""}${isFocused ? " is-focused" : ""}${isFocusPresentationCard ? " is-focus-presentation" : ""}${presentationCard ? " is-presentation-card" : ""}`, "data-card-id": card.id, tabIndex: presentation === "canvas" ? 0 : undefined, role: "group", "aria-label": `Frame: ${frameLabel}`, style: {
445
456
  "--canvas-toolbar-scale": toolbarScale,