nudge-ui 0.2.0 → 0.2.2

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 (231) hide show
  1. package/bin/nudge-ui.mjs +3 -1
  2. package/dist/cli/agentCommand.d.ts +8 -0
  3. package/dist/cli/agentCommand.js +59 -0
  4. package/dist/client.mjs +878 -11
  5. package/dist/hosts/astro/astroRuntimeConfig.js +1 -1
  6. package/dist/hosts/astro/clientTransport.js +63 -11
  7. package/dist/hosts/astro/integration.d.ts +2 -2
  8. package/dist/hosts/astro/integration.js +4 -3
  9. package/dist/hosts/environment.d.ts +15 -0
  10. package/dist/hosts/environment.js +16 -0
  11. package/dist/hosts/next/sidecar.d.ts +4 -0
  12. package/dist/hosts/next/sidecar.js +56 -7
  13. package/dist/hosts/next/wrapper.d.ts +2 -0
  14. package/dist/hosts/next/wrapper.js +32 -3
  15. package/dist/hosts/projectBridge.d.ts +21 -0
  16. package/dist/hosts/projectBridge.js +98 -0
  17. package/dist/hosts/static/cli.d.ts +1 -1
  18. package/dist/hosts/static/cli.js +6 -1
  19. package/dist/hosts/static/manifest.d.ts +1 -1
  20. package/dist/hosts/static/manifest.js +3 -1
  21. package/dist/hosts/static/server.js +45 -3
  22. package/dist/hosts/vite/vite.d.ts +6 -1
  23. package/dist/hosts/vite/vite.js +82 -15
  24. package/dist/inspector/agent/McpConnectionDialog.d.ts +5 -4
  25. package/dist/inspector/agent/McpConnectionDialog.js +20 -37
  26. package/dist/inspector/agent/client.d.ts +16 -3
  27. package/dist/inspector/agent/client.js +114 -11
  28. package/dist/inspector/agent/connectionStatus.d.ts +3 -3
  29. package/dist/inspector/agent/connectionStatus.js +11 -4
  30. package/dist/inspector/agent/httpTransport.d.ts +8 -0
  31. package/dist/inspector/agent/httpTransport.js +78 -18
  32. package/dist/inspector/agent/protocol.d.ts +11 -3
  33. package/dist/inspector/agent/protocol.js +1 -1
  34. package/dist/inspector/agent/verification.d.ts +1 -1
  35. package/dist/inspector/agent/verification.js +69 -12
  36. package/dist/inspector/canvas/CanvasCard.d.ts +5 -3
  37. package/dist/inspector/canvas/CanvasCard.js +181 -91
  38. package/dist/inspector/canvas/CanvasElementOverlay.js +288 -52
  39. package/dist/inspector/canvas/CanvasToolbar.d.ts +12 -0
  40. package/dist/inspector/canvas/CanvasToolbar.js +24 -0
  41. package/dist/inspector/canvas/CanvasWorkspace.d.ts +4 -1
  42. package/dist/inspector/canvas/CanvasWorkspace.js +410 -72
  43. package/dist/inspector/canvas/activeCanvasDocument.d.ts +5 -0
  44. package/dist/inspector/canvas/activeCanvasDocument.js +23 -0
  45. package/dist/inspector/canvas/canvasResize.d.ts +30 -0
  46. package/dist/inspector/canvas/canvasResize.js +52 -0
  47. package/dist/inspector/canvas/canvasStore.d.ts +30 -6
  48. package/dist/inspector/canvas/canvasStore.js +128 -61
  49. package/dist/inspector/canvas/frameProtocol.d.ts +82 -5
  50. package/dist/inspector/canvas/frameProtocol.js +63 -2
  51. package/dist/inspector/canvas/keyboardShortcuts.d.ts +4 -0
  52. package/dist/inspector/canvas/keyboardShortcuts.js +16 -0
  53. package/dist/inspector/canvas/linkEligibility.d.ts +0 -5
  54. package/dist/inspector/canvas/linkEligibility.js +0 -29
  55. package/dist/inspector/canvas/projection.d.ts +7 -0
  56. package/dist/inspector/canvas/projection.js +118 -25
  57. package/dist/inspector/canvas/rendererBootstrap.js +42 -29
  58. package/dist/inspector/canvas/rendererElementSelector.d.ts +1 -1
  59. package/dist/inspector/canvas/rendererElementSelector.js +385 -58
  60. package/dist/inspector/canvas/rendererMessageRouter.d.ts +11 -0
  61. package/dist/inspector/canvas/rendererMessageRouter.js +43 -0
  62. package/dist/inspector/canvas/rendererSelectionProxy.js +6 -2
  63. package/dist/inspector/canvas/sessionStore.d.ts +1 -0
  64. package/dist/inspector/canvas/sessionStore.js +12 -4
  65. package/dist/inspector/canvas/staleChangeDetector.js +16 -14
  66. package/dist/inspector/changes/changesLog.js +31 -1
  67. package/dist/inspector/changes/managedStyleProjection.d.ts +1 -1
  68. package/dist/inspector/changes/managedStyleProjection.js +3 -3
  69. package/dist/inspector/changes/structuralTypes.d.ts +4 -0
  70. package/dist/inspector/changes/workspaceChanges.d.ts +4 -0
  71. package/dist/inspector/changes/workspaceChanges.js +29 -3
  72. package/dist/inspector/clientManifest.d.ts +7 -0
  73. package/dist/inspector/clientManifest.js +12 -0
  74. package/dist/inspector/componentSemantics/adapterRegistry.js +4 -3
  75. package/dist/inspector/componentSemantics/runtimeBridge.d.ts +2 -2
  76. package/dist/inspector/componentSemantics/runtimeBridge.js +16 -3
  77. package/dist/inspector/index.d.ts +2 -0
  78. package/dist/inspector/index.js +80 -32
  79. package/dist/inspector/inline-text/inlineTextDiagnostics.d.ts +10 -0
  80. package/dist/inspector/inline-text/inlineTextDiagnostics.js +65 -0
  81. package/dist/inspector/inline-text/inlineTextEditor.d.ts +3 -5
  82. package/dist/inspector/inline-text/inlineTextEditor.js +74 -206
  83. package/dist/inspector/inline-text/inlineTextFeedback.d.ts +5 -0
  84. package/dist/inspector/inline-text/inlineTextFeedback.js +27 -0
  85. package/dist/inspector/inline-text/inlineTextLifecycle.js +2 -0
  86. package/dist/inspector/inline-text/textEditChange.d.ts +14 -0
  87. package/dist/inspector/inline-text/textEditChange.js +165 -0
  88. package/dist/inspector/inspection/selectionProperty.d.ts +1 -0
  89. package/dist/inspector/inspection/selectionProperty.js +1 -0
  90. package/dist/inspector/overlay/DomNavigator.d.ts +10 -0
  91. package/dist/inspector/overlay/DomNavigator.js +40 -0
  92. package/dist/inspector/overlay/InspectorOverlay.js +6 -2
  93. package/dist/inspector/overlay/clickPolicy.d.ts +18 -2
  94. package/dist/inspector/overlay/clickPolicy.js +34 -3
  95. package/dist/inspector/overlay/elementSelector.d.ts +1 -1
  96. package/dist/inspector/overlay/elementSelector.js +18 -7
  97. package/dist/inspector/overlay/selectedGeometry.js +21 -2
  98. package/dist/inspector/overlay/spacingGestures.d.ts +45 -0
  99. package/dist/inspector/overlay/spacingGestures.js +351 -0
  100. package/dist/inspector/overlay/structuralGestures.d.ts +2 -2
  101. package/dist/inspector/overlay/structuralGestures.js +12 -10
  102. package/dist/inspector/projection/managedStylesheet.js +4 -1
  103. package/dist/inspector/projection/renderedInstance.d.ts +2 -0
  104. package/dist/inspector/projection/renderedInstance.js +5 -1
  105. package/dist/inspector/projection/structuralProjection.d.ts +2 -0
  106. package/dist/inspector/projection/structuralProjection.js +85 -1
  107. package/dist/inspector/projection/structuralProjectionBoundary.js +17 -1
  108. package/dist/inspector/projection/textProjection.d.ts +2 -0
  109. package/dist/inspector/projection/textProjection.js +10 -4
  110. package/dist/inspector/prompt/clipboardHandoff.d.ts +1 -1
  111. package/dist/inspector/prompt/clipboardHandoff.js +3 -3
  112. package/dist/inspector/prompt/generatePrompt.d.ts +2 -1
  113. package/dist/inspector/prompt/generatePrompt.js +19 -2
  114. package/dist/inspector/runtime/editorShell.d.ts +2 -0
  115. package/dist/inspector/runtime/editorShell.js +4 -0
  116. package/dist/inspector/runtime/runtimeConfig.d.ts +5 -1
  117. package/dist/inspector/runtime/runtimeConfig.js +4 -0
  118. package/dist/inspector/selection/hierarchy.d.ts +6 -0
  119. package/dist/inspector/selection/hierarchy.js +8 -0
  120. package/dist/inspector/selection/selectionStore.js +2 -0
  121. package/dist/inspector/settings/SettingsDialog.d.ts +1 -1
  122. package/dist/inspector/settings/SettingsDialog.js +12 -2
  123. package/dist/inspector/shell/AppShell.js +5 -1
  124. package/dist/inspector/shell/ChangesLog.js +26 -22
  125. package/dist/inspector/shell/CopyPromptButton.js +102 -19
  126. package/dist/inspector/shell/EmptyState.js +1 -1
  127. package/dist/inspector/shell/InspectorShell.d.ts +0 -1
  128. package/dist/inspector/shell/InspectorShell.js +38 -42
  129. package/dist/inspector/shell/PeekOriginalButton.d.ts +7 -0
  130. package/dist/inspector/shell/PeekOriginalButton.js +57 -0
  131. package/dist/inspector/shell/PeekOriginalIcon.d.ts +7 -0
  132. package/dist/inspector/shell/PeekOriginalIcon.js +9 -0
  133. package/dist/inspector/shell/originalPreview.d.ts +9 -0
  134. package/dist/inspector/shell/originalPreview.js +61 -0
  135. package/dist/inspector/shell/shortcuts.d.ts +3 -0
  136. package/dist/inspector/shell/shortcuts.js +15 -0
  137. package/dist/inspector/sketch/SketchChanges.d.ts +2 -0
  138. package/dist/inspector/sketch/SketchChanges.js +72 -0
  139. package/dist/inspector/sketch/SketchEditor.d.ts +21 -0
  140. package/dist/inspector/sketch/SketchEditor.js +402 -0
  141. package/dist/inspector/sketch/SketchEntryButton.d.ts +4 -0
  142. package/dist/inspector/sketch/SketchEntryButton.js +11 -0
  143. package/dist/inspector/sketch/SketchFrameOverlay.d.ts +11 -0
  144. package/dist/inspector/sketch/SketchFrameOverlay.js +119 -0
  145. package/dist/inspector/sketch/SketchLayersPanel.d.ts +2 -0
  146. package/dist/inspector/sketch/SketchLayersPanel.js +63 -0
  147. package/dist/inspector/sketch/SketchOverlay.d.ts +19 -0
  148. package/dist/inspector/sketch/SketchOverlay.js +420 -0
  149. package/dist/inspector/sketch/SketchPromptPanel.d.ts +15 -0
  150. package/dist/inspector/sketch/SketchPromptPanel.js +18 -0
  151. package/dist/inspector/sketch/SketchWorkspace.d.ts +13 -0
  152. package/dist/inspector/sketch/SketchWorkspace.js +152 -0
  153. package/dist/inspector/sketch/capture.d.ts +55 -0
  154. package/dist/inspector/sketch/capture.js +350 -0
  155. package/dist/inspector/sketch/freehand.d.ts +13 -0
  156. package/dist/inspector/sketch/freehand.js +64 -0
  157. package/dist/inspector/sketch/geometry.d.ts +17 -0
  158. package/dist/inspector/sketch/geometry.js +98 -0
  159. package/dist/inspector/sketch/handoff.d.ts +21 -0
  160. package/dist/inspector/sketch/handoff.js +72 -0
  161. package/dist/inspector/sketch/interaction.d.ts +21 -0
  162. package/dist/inspector/sketch/interaction.js +98 -0
  163. package/dist/inspector/sketch/model.d.ts +104 -0
  164. package/dist/inspector/sketch/model.js +282 -0
  165. package/dist/inspector/sketch/persistence.d.ts +21 -0
  166. package/dist/inspector/sketch/persistence.js +205 -0
  167. package/dist/inspector/sketch/raster.d.ts +22 -0
  168. package/dist/inspector/sketch/raster.js +203 -0
  169. package/dist/inspector/sketch/sketchNote.d.ts +10 -0
  170. package/dist/inspector/sketch/sketchNote.js +30 -0
  171. package/dist/inspector/sketch/store.d.ts +47 -0
  172. package/dist/inspector/sketch/store.js +434 -0
  173. package/dist/inspector/styleEditors/BorderEditor.js +15 -19
  174. package/dist/inspector/styleEditors/BorderRadiusEditor.js +6 -6
  175. package/dist/inspector/styleEditors/BoxShadowEditor.js +12 -1
  176. package/dist/inspector/styleEditors/ColorPicker.js +11 -36
  177. package/dist/inspector/styleEditors/GapField.d.ts +3 -2
  178. package/dist/inspector/styleEditors/GapField.js +2 -2
  179. package/dist/inspector/styleEditors/GridSection.js +1 -1
  180. package/dist/inspector/styleEditors/LayoutSection.js +11 -8
  181. package/dist/inspector/styleEditors/SpacingBox.js +31 -33
  182. package/dist/inspector/styleEditors/layoutPreviewState.d.ts +5 -0
  183. package/dist/inspector/styleEditors/layoutPreviewState.js +19 -0
  184. package/dist/inspector/styleEditors/layoutValue.js +3 -0
  185. package/dist/inspector/styleEditors/nudgeValue.d.ts +11 -0
  186. package/dist/inspector/styleEditors/nudgeValue.js +93 -5
  187. package/dist/inspector/styleEditors/stylePresence.d.ts +7 -0
  188. package/dist/inspector/styleEditors/stylePresence.js +22 -0
  189. package/dist/inspector/styleEditors/textRelevance.d.ts +3 -0
  190. package/dist/inspector/styleEditors/textRelevance.js +35 -0
  191. package/dist/inspector/styleEditors/useFieldVisibility.d.ts +6 -0
  192. package/dist/inspector/styleEditors/useFieldVisibility.js +26 -0
  193. package/dist/inspector/tokens/TokenField.js +130 -7
  194. package/dist/inspector/tokens/TokensPanel.js +2 -1
  195. package/dist/inspector/tokens/dragPointerLock.d.ts +8 -0
  196. package/dist/inspector/tokens/dragPointerLock.js +70 -0
  197. package/dist/inspector/tokens/editActions.d.ts +2 -0
  198. package/dist/inspector/tokens/editActions.js +2 -2
  199. package/dist/inspector/tokens/resolution/cssomCollector.d.ts +1 -1
  200. package/dist/inspector/tokens/resolution/cssomCollector.js +9 -5
  201. package/dist/inspector/tokens/resolution/ruleMatching.d.ts +40 -0
  202. package/dist/inspector/tokens/resolution/ruleMatching.js +423 -0
  203. package/dist/inspector/tokens/resolution/selectorSemantics.d.ts +19 -3
  204. package/dist/inspector/tokens/resolution/selectorSemantics.js +378 -4
  205. package/dist/inspector/tokens/resolution.d.ts +3 -26
  206. package/dist/inspector/tokens/resolution.js +44 -735
  207. package/dist/inspector/tokens/tokenAvailability.d.ts +18 -0
  208. package/dist/inspector/tokens/tokenAvailability.js +204 -0
  209. package/dist/inspector/ui/Button.d.ts +1 -1
  210. package/dist/inspector/ui/Disclosure.d.ts +22 -0
  211. package/dist/inspector/ui/Disclosure.js +13 -0
  212. package/dist/inspector/ui/SideValuesField.js +2 -2
  213. package/dist/inspector/ui/StatusCallout.d.ts +4 -1
  214. package/dist/inspector/ui/StatusCallout.js +2 -2
  215. package/dist/inspector/ui/dragCursor.d.ts +8 -0
  216. package/dist/inspector/ui/dragCursor.js +21 -0
  217. package/dist/inspector/ui/styles.js +21 -17
  218. package/dist/internal/agent-protocol.d.ts +65 -1
  219. package/dist/internal/agent-protocol.js +183 -3
  220. package/dist/nudge-ui.mjs +276 -58
  221. package/dist/transport/editor.d.ts +47 -0
  222. package/dist/transport/editor.js +163 -0
  223. package/dist/transport/index.d.ts +1 -0
  224. package/dist/transport/index.js +1 -0
  225. package/dist/transport/routes.d.ts +10 -0
  226. package/dist/transport/routes.js +10 -0
  227. package/package.json +3 -1
  228. package/dist/inspector/shell/DomNavigation.d.ts +0 -8
  229. package/dist/inspector/shell/DomNavigation.js +0 -30
  230. package/dist/inspector/shell/panelLayout.d.ts +0 -2
  231. package/dist/inspector/shell/panelLayout.js +0 -29
@@ -1,6 +1,7 @@
1
1
  import { getSelectedElements, setSelectedElement, toggleSelectedElement } from "../selection/selectionStore.js";
2
2
  import { selectCard } from "./canvasStore.js";
3
3
  import { RENDERER_ELEMENT_ID_ATTR } from "./rendererCidIndex.js";
4
+ import { inspectComponentTargets } from "../componentSemantics/index.js";
4
5
  function isHtmlElementInDocument(node, doc) {
5
6
  const frameWindow = doc.defaultView;
6
7
  return frameWindow !== null && node instanceof frameWindow.HTMLElement;
@@ -26,7 +27,9 @@ function findClickedElement(doc, elementId, cid, src) {
26
27
  if (candidates.length !== 1)
27
28
  return null;
28
29
  const candidate = candidates[0] ?? null;
29
- if (!candidate || candidate.getAttribute("data-cid") !== cid || candidate.getAttribute("data-src") !== src)
30
+ if (!candidate
31
+ || candidate.getAttribute("data-cid") !== cid
32
+ || (candidate.getAttribute("data-src") ?? "") !== src)
30
33
  return null;
31
34
  return isHtmlElementInDocument(candidate, doc) ? candidate : null;
32
35
  }
@@ -38,6 +41,7 @@ export function handleElementClick(msg, iframe, cardId) {
38
41
  selectCard(cardId);
39
42
  return;
40
43
  }
44
+ const componentTargets = inspectComponentTargets(el);
41
45
  const selected = {
42
46
  cid: msg.cid,
43
47
  src: el.getAttribute("data-src") ?? msg.src,
@@ -46,7 +50,7 @@ export function handleElementClick(msg, iframe, cardId) {
46
50
  line: msg.line,
47
51
  column: 0,
48
52
  domElement: el,
49
- componentTargets: [],
53
+ componentTargets,
50
54
  };
51
55
  // setSelectedElement must run before any side effect that could reload the
52
56
  // host page, otherwise the selection would be discarded by the unload.
@@ -38,6 +38,7 @@ export interface DurableSession {
38
38
  y: number;
39
39
  zoom: number;
40
40
  };
41
+ focusedCardId?: string | null;
41
42
  changes: SerializableChange[];
42
43
  structuralChanges: StructuralChange[];
43
44
  clipboardHandoff: ClipboardHandoffSnapshot | null;
@@ -1,11 +1,10 @@
1
1
  import { getWorkspaceChanges } from "../changes/workspaceChanges.js";
2
2
  import { loadWorkspaceChanges } from "../changes/changesLog.js";
3
3
  import { deserializeChange, isSerializableChange, serializeChange, } from "../changes/codecs.js";
4
- import { getCanvasMode, getCanvasCards, getCanvasComparisonGroups, getBoardCamera, setBoardCamera, hydrateCanvasStore, removeCanvasCard, } from "./canvasStore.js";
4
+ import { getCanvasMode, getCanvasCards, getCanvasComparisonGroups, getFocusedCardId, getBoardCamera, setBoardCamera, hydrateCanvasStore, removeCanvasCard, } from "./canvasStore.js";
5
5
  import { applyRules } from "../projection/managedStylesheet.js";
6
6
  import { clearWorkspace as clearWorkspaceLog } from "../changes/changesLog.js";
7
7
  import { removeManagedSheet } from "../projection/managedStylesheet.js";
8
- import { clearInspectorLayout } from "../shell/panelLayout.js";
9
8
  import { setSelectedElement } from "../selection/selectionStore.js";
10
9
  import { canWriteWorkspace } from "./workspaceLease.js";
11
10
  import { isStructuralChange, resetStructuralDeleteProjection, } from "../projection/structuralProjection.js";
@@ -121,6 +120,7 @@ function buildSession() {
121
120
  })),
122
121
  })),
123
122
  camera: { x: camera.x, y: camera.y, zoom: camera.zoom },
123
+ focusedCardId: getFocusedCardId(),
124
124
  changes: serializableChanges,
125
125
  structuralChanges: workspace.structuralChanges.map((change) => ({ ...change })),
126
126
  clipboardHandoff: getClipboardHandoffSnapshot(),
@@ -330,7 +330,16 @@ export function hydrateSession() {
330
330
  y: cameraRaw.y,
331
331
  zoom: cameraRaw.zoom,
332
332
  };
333
- hydrateCanvasStore(s.mode, serializableCards, camera, serializableComparisonGroups);
333
+ const focusedCardId = s.focusedCardId === undefined || s.focusedCardId === null
334
+ ? null
335
+ : typeof s.focusedCardId === "string" && cardsById.has(s.focusedCardId)
336
+ ? s.focusedCardId
337
+ : undefined;
338
+ if (focusedCardId === undefined) {
339
+ safeDiscard();
340
+ return { restored: false, changeCount: 0 };
341
+ }
342
+ hydrateCanvasStore(s.mode, serializableCards, camera, serializableComparisonGroups, focusedCardId);
334
343
  // Structural intent and instance evidence become visible atomically. The
335
344
  // projection layer preserves structural-first document application order.
336
345
  loadWorkspaceChanges(deserializedChanges, structuralChanges);
@@ -366,7 +375,6 @@ export function clearSession() {
366
375
  resetStructuralDeleteProjection();
367
376
  removeManagedSheet();
368
377
  setSelectedElement(null);
369
- clearInspectorLayout();
370
378
  for (const card of getCanvasCards()) {
371
379
  removeCanvasCard(card.id);
372
380
  }
@@ -4,7 +4,7 @@ import { beginPreviewAttempt, clearPreviewDiagnostics, getHostPreviewDocument, n
4
4
  import { getWorkspaceChanges } from "../changes/workspaceChanges.js";
5
5
  import { getCanvasPreviewDocument, getRegisteredFrames } from "./projection.js";
6
6
  import { findCanvasFrameBySource, PROJECT_ID, WORKSPACE_ID } from "./projection.js";
7
- import { getCanvasCards } from "./canvasStore.js";
7
+ import { getCanvasCards, getCanvasMode } from "./canvasStore.js";
8
8
  import { isRendererMessageFor } from "./frameProtocol.js";
9
9
  import { getNudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
10
10
  const VERIFICATION_TIMEOUT_MS = 5000;
@@ -79,7 +79,7 @@ function checkTokenDrift(change) {
79
79
  return null;
80
80
  }
81
81
  function getPreviewDocuments() {
82
- const documents = [getHostPreviewDocument()];
82
+ const documents = getCanvasMode() === "canvas" ? [] : [getHostPreviewDocument()];
83
83
  const frames = getRegisteredFrames();
84
84
  for (const card of getCanvasCards()) {
85
85
  if (frames.has(card.id))
@@ -99,15 +99,17 @@ function beginPreviewAttempts() {
99
99
  }
100
100
  function gatherMatchEvidence(changes) {
101
101
  const evidence = new Map();
102
- const hostDocument = getHostPreviewDocument();
103
- for (let i = 0; i < changes.length; i++) {
104
- const change = changes[i];
105
- if (isTokenChange(change))
106
- continue;
107
- if (checkSelectorInDocument(document, change.selector)) {
108
- const routes = evidence.get(i) ?? [];
109
- routes.push(hostDocument);
110
- evidence.set(i, routes);
102
+ if (getCanvasMode() !== "canvas") {
103
+ const hostDocument = getHostPreviewDocument();
104
+ for (let i = 0; i < changes.length; i++) {
105
+ const change = changes[i];
106
+ if (isTokenChange(change))
107
+ continue;
108
+ if (checkSelectorInDocument(document, change.selector)) {
109
+ const routes = evidence.get(i) ?? [];
110
+ routes.push(hostDocument);
111
+ evidence.set(i, routes);
112
+ }
111
113
  }
112
114
  }
113
115
  const frames = getRegisteredFrames();
@@ -131,13 +133,13 @@ function gatherMatchEvidence(changes) {
131
133
  }
132
134
  function applyStaleResults(changes, attempts) {
133
135
  const evidence = gatherMatchEvidence(changes);
134
- const hostAttempt = attempts.get(getHostPreviewDocument().logicalDocument);
136
+ const tokenAttempt = attempts.values().next().value;
135
137
  for (let i = 0; i < changes.length; i++) {
136
138
  const change = changes[i];
137
139
  if (isTokenChange(change)) {
138
140
  const drift = checkTokenDrift(change);
139
- if (drift && hostAttempt)
140
- publishPreviewDiagnostic(hostAttempt, changeKey(change), drift);
141
+ if (drift && tokenAttempt)
142
+ publishPreviewDiagnostic(tokenAttempt, changeKey(change), drift);
141
143
  continue;
142
144
  }
143
145
  const routes = evidence.get(i);
@@ -8,6 +8,8 @@ import { workspaceChangeStore, } from "./workspaceChanges.js";
8
8
  import { beginPreviewAttempt, clearPreviewDiagnostics, getHostPreviewDocument, publishPreviewDiagnostic, } from "./previewDiagnostics.js";
9
9
  import { clearStructuralProjectionReports, pruneStructuralProjectionReports } from "../projection/structuralProjection.js";
10
10
  import { applyHostWorkspaceProjection, compileWorkspaceProjection, } from "../projection/workspaceProjection.js";
11
+ import { isEditorShellDocument } from "../runtime/editorShell.js";
12
+ import { isOriginalPreviewActive, subscribeOriginalPreview, } from "../shell/originalPreview.js";
11
13
  export { isComponentChange, isElementChange, isTextContentChange, isTextContentChangeValue, isPreviewableChange, isTokenChange, } from "./types.js";
12
14
  /**
13
15
  * Deferred delta verification (0044). Only the keys touched by a mutation are
@@ -28,14 +30,28 @@ export function getPendingRules() {
28
30
  return buildManagedStyleRules(getChangesSnapshot());
29
31
  }
30
32
  function reapply(workspace) {
31
- applyHostWorkspaceProjection(compileWorkspaceProjection(workspace));
33
+ // While hold-to-view-original is active the host document intentionally
34
+ // shows the page without inspector changes. Commits still land in the
35
+ // canonical store; the release path re-projects the latest snapshot.
36
+ if (isOriginalPreviewActive())
37
+ return;
38
+ if (!isEditorShellDocument())
39
+ applyHostWorkspaceProjection(compileWorkspaceProjection(workspace));
32
40
  }
33
41
  function flushVerification() {
34
42
  verificationHandle = null;
43
+ // Probing the original preview would report the held-back changes as
44
+ // conflicts. Keep the pending targets; releasing re-verifies them.
45
+ if (isOriginalPreviewActive())
46
+ return;
35
47
  const targets = pendingVerificationTargets;
36
48
  pendingVerificationTargets = new Map();
37
49
  if (targets.size === 0)
38
50
  return;
51
+ // The editor shell has no application document. Renderer diagnostics are
52
+ // owned by renderer projection reports.
53
+ if (isEditorShellDocument())
54
+ return;
39
55
  const current = getChangesSnapshot();
40
56
  const attempt = beginPreviewAttempt(getHostPreviewDocument(), workspaceChangeStore.getSnapshot().revision);
41
57
  if (!attempt)
@@ -93,6 +109,20 @@ function markForVerification(keys, verificationTargets) {
93
109
  if (added)
94
110
  scheduleVerification();
95
111
  }
112
+ /**
113
+ * Releasing hold-to-view-original restores the edited preview; re-verify the
114
+ * surviving set against the restored DOM instead of leaving peek-era state.
115
+ * The retry is forced: a flush that ran during the hold retains its targets
116
+ * without scheduling, so markForVerification alone would see every key
117
+ * already present and schedule nothing.
118
+ */
119
+ subscribeOriginalPreview(() => {
120
+ if (isOriginalPreviewActive())
121
+ return;
122
+ markForVerification(getChangesSnapshot().map(changeKey));
123
+ if (pendingVerificationTargets.size > 0)
124
+ scheduleVerification();
125
+ });
96
126
  /** Append records and report whether canonical workspace state changed. */
97
127
  export function appendChanges(incoming, options = {}) {
98
128
  const result = workspaceChangeStore.commitChangeRecords(incoming);
@@ -3,4 +3,4 @@ import { type ChangeRecord, type PreviewableChangeRecord } from "./types.js";
3
3
  /** The source selector stays canonical; the projection marker is document-local. */
4
4
  export declare function selectorForManagedChange(change: PreviewableChangeRecord): string | null;
5
5
  export declare function buildManagedStyleRules(changes: ChangeRecord[]): StyleRule[];
6
- export declare function verifyManagedStyleProjection(change: PreviewableChangeRecord, selectedElement?: HTMLElement | null): PreviewResult | null;
6
+ export declare function verifyManagedStyleProjection(change: PreviewableChangeRecord, selectedElement?: HTMLElement | null, ownerDocument?: Document): PreviewResult | null;
@@ -63,7 +63,7 @@ export function buildManagedStyleRules(changes) {
63
63
  // emitted afterwards so their additional marker specificity wins.
64
64
  return [...sourceRules.values(), ...instanceRules.values()];
65
65
  }
66
- export function verifyManagedStyleProjection(change, selectedElement) {
66
+ export function verifyManagedStyleProjection(change, selectedElement, ownerDocument = document) {
67
67
  // Deferred verification must use the selection that existed when the
68
68
  // projection was committed. Reading the live selection here can make a
69
69
  // host-document change verify against a later canvas selection (or vice
@@ -75,13 +75,13 @@ export function verifyManagedStyleProjection(change, selectedElement) {
75
75
  // A Canvas-only selection belongs to an iframe. The controller stylesheet
76
76
  // cannot verify it synchronously; leave its result unknown until the frame
77
77
  // has received the canonical projection rather than claiming it is stale.
78
- if (selected && selected.ownerDocument !== document) {
78
+ if (selected && selected.ownerDocument !== ownerDocument) {
79
79
  return null;
80
80
  }
81
81
  let targets = [];
82
82
  try {
83
83
  const selector = selectorForManagedChange(change);
84
- targets = selector ? Array.from(document.querySelectorAll(selector)) : [];
84
+ targets = selector ? Array.from(ownerDocument.querySelectorAll(selector)) : [];
85
85
  }
86
86
  catch {
87
87
  targets = [];
@@ -4,6 +4,10 @@ export interface StructuralDelete {
4
4
  id: string;
5
5
  kind: "delete";
6
6
  target: RenderedInstanceRef;
7
+ /** Hash-independent route where the target was captured. */
8
+ route?: string;
9
+ /** Bounded view identity where the target was captured. */
10
+ state?: string;
7
11
  }
8
12
  /** Controller-owned intent to move one rendered instance. */
9
13
  export interface StructuralMove {
@@ -31,6 +31,10 @@ export interface WorkspaceChangeStore {
31
31
  restoreWorkspaceChanges(next: WorkspaceContents): void;
32
32
  clearWorkspaceChanges(): void;
33
33
  }
34
+ /** Groups consecutive synchronous updates from one gesture into one undo step.
35
+ * Updates outside the callback keep their own history entries.
36
+ */
37
+ export declare function createChangeHistoryGroup(): (update: () => void) => void;
34
38
  export declare const workspaceChangeStore: WorkspaceChangeStore;
35
39
  /** Compatibility accessors retained for callers that have not adopted the store seam. */
36
40
  export declare function getWorkspaceChanges(): WorkspaceChangesSnapshot;
@@ -5,6 +5,7 @@ let contents = { changes: [], structuralChanges: [] };
5
5
  let revision = 0;
6
6
  let undoStack = [];
7
7
  let redoStack = [];
8
+ let activeHistoryGroup;
8
9
  let snapshot = createSnapshot();
9
10
  const listeners = new Set();
10
11
  function cloneContents(value) {
@@ -60,11 +61,36 @@ function commit(next) {
60
61
  return false;
61
62
  const before = cloneContents(contents);
62
63
  contents = cloneContents(next);
63
- undoStack.push({ before, after: cloneContents(contents) });
64
+ const previous = undoStack.at(-1);
65
+ const entry = {
66
+ before: activeHistoryGroup && previous?.group === activeHistoryGroup ? previous.before : before,
67
+ after: cloneContents(contents),
68
+ group: activeHistoryGroup,
69
+ };
70
+ if (activeHistoryGroup && previous?.group === activeHistoryGroup)
71
+ undoStack.pop();
72
+ if (!sameWorkspaceContents(entry.before, entry.after))
73
+ undoStack.push(entry);
64
74
  redoStack = [];
65
75
  publish();
66
76
  return true;
67
77
  }
78
+ /** Groups consecutive synchronous updates from one gesture into one undo step.
79
+ * Updates outside the callback keep their own history entries.
80
+ */
81
+ export function createChangeHistoryGroup() {
82
+ const group = Symbol("change-history-group");
83
+ return (update) => {
84
+ const previous = activeHistoryGroup;
85
+ activeHistoryGroup = group;
86
+ try {
87
+ update();
88
+ }
89
+ finally {
90
+ activeHistoryGroup = previous;
91
+ }
92
+ };
93
+ }
68
94
  function getSnapshot() {
69
95
  return snapshot;
70
96
  }
@@ -123,7 +149,7 @@ function reconcileWorkspaceChangesImpl(verifiedKeys, verifiedStructuralIds) {
123
149
  return 0;
124
150
  contents = next;
125
151
  const prune = (entries) => entries
126
- .map((entry) => ({ before: retain(entry.before), after: retain(entry.after) }))
152
+ .map((entry) => ({ group: entry.group, before: retain(entry.before), after: retain(entry.after) }))
127
153
  .filter((entry) => !sameWorkspaceContents(entry.before, entry.after));
128
154
  undoStack = prune(undoStack);
129
155
  redoStack = prune(redoStack);
@@ -159,7 +185,7 @@ function redoWorkspaceChangeImpl() {
159
185
  return false;
160
186
  redoStack.pop();
161
187
  contents = cloneContents(entry.after);
162
- undoStack.push(entry);
188
+ undoStack.push({ before: entry.before, after: entry.after });
163
189
  publish();
164
190
  return true;
165
191
  }
@@ -8,6 +8,11 @@ export interface NudgeUiClientManifest {
8
8
  readonly version: typeof NUDGE_UI_CLIENT_MANIFEST_VERSION;
9
9
  readonly revision: number;
10
10
  readonly runtime: NudgeUiRuntimeConfig;
11
+ /** Project-owned, loopback-only agent bridge started by the dev host. */
12
+ readonly agentBridge?: {
13
+ readonly baseUrl: string;
14
+ readonly autoConnect?: boolean;
15
+ };
11
16
  /** Optional document preparation requested by the host Adapter. */
12
17
  readonly document?: {
13
18
  readonly runtimeIdentity?: "static-html";
@@ -19,6 +24,8 @@ export interface NudgeUiClientManifest {
19
24
  readonly strategy: "refresh-manifest" | "reload-document";
20
25
  readonly events?: readonly string[];
21
26
  };
27
+ /** Set by `NUDGE_UI=1`: automated browsers open the editor instead of the plain app. */
28
+ readonly inspectAutomatedBrowsers?: true;
22
29
  }
23
30
  /** Parses and normalizes an external manifest before it replaces inspector state. */
24
31
  export declare function parseNudgeUiClientManifest(value: unknown): NudgeUiClientManifest | null;
@@ -20,14 +20,26 @@ value) {
20
20
  version: NUDGE_UI_CLIENT_MANIFEST_VERSION,
21
21
  revision: value.revision,
22
22
  runtime: normalizeNudgeUiRuntimeConfig(value.runtime),
23
+ ...(isAgentBridge(value.agentBridge) ? { agentBridge: value.agentBridge } : {}),
23
24
  ...(value.document === undefined ? {} : { document: value.document }),
24
25
  ...(value.reload === undefined ? {} : { reload: value.reload }),
26
+ ...(value.inspectAutomatedBrowsers === true ? { inspectAutomatedBrowsers: true } : {}),
25
27
  };
26
28
  }
27
29
  catch {
28
30
  return null;
29
31
  }
30
32
  }
33
+ function isAgentBridge(value) {
34
+ if (value === undefined)
35
+ return false;
36
+ if (!isRecord(value))
37
+ return false;
38
+ const candidate = value;
39
+ if (typeof candidate.baseUrl !== "string" || candidate.baseUrl.length === 0)
40
+ return false;
41
+ return candidate.autoConnect === undefined || typeof candidate.autoConnect === "boolean";
42
+ }
31
43
  function isDocumentOptions(
32
44
  // Optional manifest capability is parsed before use.
33
45
  // oxlint-disable-next-line anti-slop/no-unknown-parameters
@@ -1,10 +1,10 @@
1
1
  import { getNudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
2
2
  import { copyComponentOverrides, copyRuntimeTarget, getHostRuntimeAdapters, registerHostRuntimeAdapter, replaceHostRuntimeAdapterOverrides, } from "./runtimeBridge.js";
3
3
  const diagnosedAdapters = new WeakSet();
4
- function enabledRuntimeAdapters() {
4
+ function enabledRuntimeAdapters(ownerGlobal) {
5
5
  if (!getNudgeUiRuntimeConfig().capabilities.componentSemantics)
6
6
  return [];
7
- return [...getHostRuntimeAdapters()];
7
+ return [...getHostRuntimeAdapters(ownerGlobal)];
8
8
  }
9
9
  /** Register a framework adapter without coupling semantic resolution to React. */
10
10
  export function registerComponentRuntimeAdapter(adapter) {
@@ -12,7 +12,8 @@ export function registerComponentRuntimeAdapter(adapter) {
12
12
  }
13
13
  export function inspectComponentTargets(element) {
14
14
  const targets = [];
15
- for (const adapter of enabledRuntimeAdapters()) {
15
+ const ownerGlobal = element.ownerDocument.defaultView ?? globalThis;
16
+ for (const adapter of enabledRuntimeAdapters(ownerGlobal)) {
16
17
  let inspected;
17
18
  try {
18
19
  inspected = adapter.inspect(element);
@@ -11,8 +11,8 @@ export declare const NUDGE_UI_HOST_RUNTIME_VERSION = 1;
11
11
  * not accumulate stale implementations.
12
12
  */
13
13
  export declare function registerHostRuntimeAdapter(adapter: ComponentRuntimeAdapter): () => void;
14
- /** Returns the active host runtime Adapters for this browser realm. */
15
- export declare function getHostRuntimeAdapters(): readonly ComponentRuntimeAdapter[];
14
+ /** Returns the active host runtime Adapters for the requested browser realm. */
15
+ export declare function getHostRuntimeAdapters(ownerGlobal?: typeof globalThis): readonly ComponentRuntimeAdapter[];
16
16
  /** Stores the latest projection and sends it to every registered host Adapter. */
17
17
  export declare function replaceHostRuntimeAdapterOverrides(overrides: readonly ComponentOverride[]): void;
18
18
  /**
@@ -42,9 +42,22 @@ export function registerHostRuntimeAdapter(adapter) {
42
42
  }
43
43
  };
44
44
  }
45
- /** Returns the active host runtime Adapters for this browser realm. */
46
- export function getHostRuntimeAdapters() {
47
- return [...registry().adapters.values()];
45
+ /** Returns the active host runtime Adapters for the requested browser realm. */
46
+ export function getHostRuntimeAdapters(ownerGlobal = globalThis) {
47
+ if (ownerGlobal === globalThis)
48
+ return [...registry().adapters.values()];
49
+ const current = ownerGlobal[HOST_RUNTIME_KEY];
50
+ if (current === undefined)
51
+ return [];
52
+ const mapConstructor = Reflect.get(ownerGlobal, "Map");
53
+ if (!mapConstructor
54
+ || typeof current !== "object"
55
+ || current === null
56
+ || current.version !== NUDGE_UI_HOST_RUNTIME_VERSION
57
+ || !(current.adapters instanceof mapConstructor)) {
58
+ throw new Error(`Nudge UI host runtime is incompatible with version ${NUDGE_UI_HOST_RUNTIME_VERSION}.`);
59
+ }
60
+ return [...(current.adapters.values())];
48
61
  }
49
62
  /** Stores the latest projection and sends it to every registered host Adapter. */
50
63
  export function replaceHostRuntimeAdapterOverrides(overrides) {
@@ -1,3 +1,4 @@
1
+ export { resolveNudgeUiClientEntry } from "../transport/editor.js";
1
2
  export declare function bootstrapNudgeUi(inspectorHost: HTMLElement): void;
2
3
  export declare function mountInspector(host: HTMLElement): void;
3
4
  export declare function unmountInspector(): void;
@@ -6,6 +7,7 @@ export { InspectorShell } from "./shell/InspectorShell.js";
6
7
  export { detectFramework } from "./prompt/detectFramework.js";
7
8
  export { installStaticHtmlRuntimeIdentity, isRuntimeGeneratedSource, RUNTIME_ELEMENT_CID_PREFIX, RUNTIME_UNKNOWN_SOURCE_PREFIX, } from "./runtime/staticHtmlRuntimeIdentity.js";
8
9
  export { isCanvasRenderer } from "./canvas/roleDetection.js";
10
+ export { createNudgeUiEditorUrl, hasNudgeUiDirectTabIntent, isNudgeUiDirectUrl, readNudgeUiEditorTarget, rememberNudgeUiDirectTabIntent, } from "../transport/editor.js";
9
11
  export { NUDGE_UI_INSPECTION_VERSION, inspectElement, installInspectionBridge } from "./inspection/bridge.js";
10
12
  export type { NudgeUiInspectionBridge, ElementInspection, InspectElementOptions, InspectionCatalogEntry, InspectionControl } from "./inspection/bridge.js";
11
13
  export { beginInlineTextEdit, cancelInlineTextEdit, disposeInlineTextEdit, getInlineTextDiagnostic, getInlineTextDiagnostics, getInlineTextSession, inlineTextEditor, isInlineTextEditingActive, subscribeInlineTextDiagnostics, resolveTextBinding, useInlineTextSession, } from "./inline-text/inlineTextEditor.js";