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
@@ -1,7 +1,6 @@
1
- import { getActiveDraftChanges, getDraftChanges } from "../changes/draftChanges.js";
2
- import { captureRenderedInstance, matchesRenderedInstanceEvidence, resolveRenderedInstance, } from "./renderedInstance.js";
1
+ import { commitStructuralChange, getActiveDraftChanges, getDraftChanges, revertStructuralChange as revertDraftStructuralChange, subscribeActiveDraftChanges, } from "../drafts/store.js";
2
+ import { captureRenderedInstance, captureStructuralTarget, matchesRenderedInstanceEvidence, resolveRenderedInstance, } from "./renderedInstance.js";
3
3
  import { isStructuralProjectionReport } from "./structuralProjectionBoundary.js";
4
- import { resetDraftChanges, draftChangeStore, } from "../changes/draftChanges.js";
5
4
  export { isStructuralChange, isStructuralDelete, isStructuralMove, isStructuralProjectionReport, } from "./structuralProjectionBoundary.js";
6
5
  const VOID_PARENT_TAGS = new Set([
7
6
  "area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr",
@@ -177,12 +176,15 @@ function cloneSnapshot(snapshot) {
177
176
  // array is enough: no operation mutates a change or its nested references.
178
177
  return [...snapshot];
179
178
  }
180
- function projectStructuralChanges(snapshot) {
181
- reprojectKnownDocuments(snapshot.structuralChanges);
179
+ /** The Draft store already re-projected the host; this covers every other known document. */
180
+ function projectStructuralChanges() {
181
+ const changes = getStructuralChanges();
182
+ for (const doc of documentStates.keys())
183
+ applyStructuralProjection(doc, changes);
182
184
  }
183
185
  /** Captures a delete intent once, in the controller, at the user gesture. */
184
186
  export function createStructuralDelete(element, id = structuralId()) {
185
- const target = captureRenderedInstance(element);
187
+ const target = captureStructuralTarget(element);
186
188
  if (!target)
187
189
  return null;
188
190
  const route = documentRoute(element.ownerDocument);
@@ -194,9 +196,9 @@ export function createStructuralDelete(element, id = structuralId()) {
194
196
  ...(route ? { route } : {}),
195
197
  ...(state ? { state } : {}),
196
198
  };
197
- if (!draftChangeStore.commitStructuralChange(change))
199
+ if (!commitStructuralChange(change))
198
200
  return null;
199
- projectStructuralChanges(draftChangeStore.getSnapshot());
201
+ projectStructuralChanges();
200
202
  return change;
201
203
  }
202
204
  /**
@@ -237,51 +239,27 @@ export function createStructuralMove(element, destination, id = structuralId())
237
239
  : destinationChildren.length - (sameParent ? 1 : 0),
238
240
  },
239
241
  };
240
- if (!draftChangeStore.commitStructuralChange(change))
242
+ if (!commitStructuralChange(change))
241
243
  return null;
242
- projectStructuralChanges(draftChangeStore.getSnapshot());
244
+ projectStructuralChanges();
243
245
  return change;
244
246
  }
245
247
  export function getStructuralChanges() {
246
- return draftChangeStore.getSnapshot().structuralChanges;
248
+ return getActiveDraftChanges().structuralChanges;
247
249
  }
248
250
  export function getStructuralDeletes() {
249
251
  return getStructuralChanges().filter((change) => change.kind === "delete");
250
252
  }
251
253
  /** Revert removes one canonical intent and leaves every other intent intact. */
252
254
  export function revertStructuralChange(changeId) {
253
- const changed = draftChangeStore.revertStructuralChangeRecord(changeId);
255
+ const changed = revertDraftStructuralChange(changeId);
254
256
  if (changed)
255
- projectStructuralChanges(draftChangeStore.getSnapshot());
257
+ projectStructuralChanges();
256
258
  return changed;
257
259
  }
258
- /**
259
- * Removes source-verified structural intents without leaving an undo path that
260
- * can recreate their browser-only previews.
261
- *
262
- * Agent completion can verify a subset of one dispatched snapshot. The
263
- * remaining records and their useful history stay intact while every verified
264
- * ID is pruned from canonical state, undo/redo snapshots, and Canvas reports.
265
- */
266
- export function reconcileVerifiedStructuralChanges(verifiedIds) {
267
- if (verifiedIds.size === 0)
268
- return 0;
269
- const removed = draftChangeStore.reconcileActiveDraftChanges(new Set(), verifiedIds);
270
- if (removed === 0)
271
- return 0;
272
- projectStructuralChanges(draftChangeStore.getSnapshot());
273
- for (const [cardId, canvasReports] of reportsByCanvasCard) {
274
- reportsByCanvasCard.set(cardId, {
275
- ...canvasReports,
276
- reports: canvasReports.reports.filter((report) => !verifiedIds.has(report.changeId)),
277
- });
278
- }
279
- notifyDiagnostics();
280
- return removed;
281
- }
282
260
  /** State changes drive controller-to-renderer projection. Diagnostics do not. */
283
261
  export function subscribeStructuralChanges(listener) {
284
- return draftChangeStore.subscribe(listener);
262
+ return subscribeActiveDraftChanges(listener);
285
263
  }
286
264
  /** Compatibility name retained while the controller moved to a full union. */
287
265
  export const subscribeStructuralDeletes = subscribeStructuralChanges;
@@ -503,13 +481,6 @@ function validationStatus(local) {
503
481
  ? "applied"
504
482
  : "overridden";
505
483
  }
506
- /** Rebuild already-mounted document adapters from canonical data only. */
507
- function reprojectKnownDocuments(changes = getStructuralChanges()) {
508
- for (const [doc, state] of documentStates) {
509
- rebuildForSnapshot(doc, state, changes);
510
- storeReports(doc, reportsForSnapshot(state, state.snapshot));
511
- }
512
- }
513
484
  function validateAppliedPreview(doc, state) {
514
485
  let changed = false;
515
486
  for (const local of state.applied.values()) {
@@ -619,7 +590,6 @@ export function resetStructuralDeleteProjection() {
619
590
  reportsByCanvasCard.clear();
620
591
  nextStructuralId = 1;
621
592
  diagnosticRevision = 0;
622
- resetDraftChanges();
623
593
  notifyDiagnostics();
624
594
  }
625
595
  /**
@@ -1,8 +1,8 @@
1
1
  import type { FrameProjection } from "../canvas/projection.js";
2
- import { isTextProjectionTargetValue, type TextContentChangeRecord, type TextProjectionTarget, type TextProjectionScope, type TextBindingEvidence } from "../inline-text/textChangeBoundary.js";
2
+ import { isTextProjectionTargetValue, type TextContentChangeRecord, type TextProjectionTarget, type TextProjectionScope, type TextBindingEvidence } from "../changes/editModel.js";
3
3
  /** Strict JSON boundary guard for a text projection target. */
4
4
  export declare const isTextProjectionTarget: typeof isTextProjectionTargetValue;
5
- export type { TextProjectionTarget } from "../inline-text/textChangeBoundary.js";
5
+ export type { TextProjectionTarget } from "../changes/editModel.js";
6
6
  export type TextProjectionStatus = "applied" | "missing" | "ambiguous" | "overridden";
7
7
  export interface TextProjectionReport {
8
8
  changeId: string;
@@ -30,6 +30,12 @@ export type TextProjectionResolution = {
30
30
  /** Find the exact text node represented by a target, tolerating a changed
31
31
  * child path only when one bounded before/after text node remains unique. */
32
32
  export declare function resolveTextProjectionTextNode(element: HTMLElement, target: Pick<TextProjectionTarget, "textNodePath"> & Partial<Pick<TextProjectionTarget, "beforeText">>, expectedText?: string | undefined): Text | null;
33
+ /** Whether an element's text is code, form state, or other non-prose content. */
34
+ export declare function isUnsafeTextHost(element: Element): boolean;
35
+ /** Whether an application-owned editing region contains the element. */
36
+ export declare function isInApplicationEditingHost(element: Element): boolean;
37
+ /** Whether replacing one text node inside the element keeps its authored markup. */
38
+ export declare function hasSafeMixedDescendants(element: HTMLElement): boolean;
33
39
  /** Capture stable source/evidence identity without retaining a DOM reference. */
34
40
  export declare function captureTextProjectionTarget(element: HTMLElement, beforeText?: string, selectedTextNode?: Text): TextProjectionTarget | null;
35
41
  /**
@@ -1,7 +1,8 @@
1
- import { getActiveDraftChanges, getDraftChanges } from "../changes/draftChanges.js";
1
+ import { boundRuntimeEvidence, normalizeRuntimeTag, runtimeDomPath } from "../runtime/staticHtmlRuntimeIdentity.js";
2
+ import { getActiveDraftChanges, getDraftChanges } from "../drafts/store.js";
2
3
  import { sourceSiteSelector } from "../selection/sourceSite.js";
3
4
  import { isNudgeUiDev } from "../runtime/devFlag.js";
4
- import { isTextContentChangeValue, isTextProjectionTargetValue, } from "../inline-text/textChangeBoundary.js";
5
+ import { isTextContentChangeValue, isTextProjectionTargetValue, } from "../changes/editModel.js";
5
6
  import { isInteractionStylesInstalled } from "../overlay/interactionStyles.js";
6
7
  /** Strict JSON boundary guard for a text projection target. */
7
8
  export const isTextProjectionTarget = isTextProjectionTargetValue;
@@ -49,6 +50,39 @@ function isEmptyTextAffordance(node) {
49
50
  function hasInlineTextEditor(element) {
50
51
  return element.querySelector('[data-inline-editor="true"]') !== null;
51
52
  }
53
+ /**
54
+ * What the application last rendered into each projected Text node. A source
55
+ * update can render the projected value itself, so restoring `before` would
56
+ * overwrite real application output that the framework will not repaint.
57
+ */
58
+ let applicationText = new WeakMap();
59
+ function isInlineEditorNode(node) {
60
+ return node.nodeType === 1 && (node.matches('[data-inline-editor="true"]')
61
+ || hasInlineTextEditor(node));
62
+ }
63
+ function recordApplicationWrites(records) {
64
+ // The inline editor swaps its wrapper back for the original node, writing
65
+ // the draft, in one task. That write belongs to the editor.
66
+ if (records.some((record) => record.type === "childList"
67
+ && [...record.addedNodes, ...record.removedNodes].some(isInlineEditorNode)))
68
+ return;
69
+ for (const record of records) {
70
+ if (record.type !== "characterData" || !isTextNode(record.target))
71
+ continue;
72
+ if (applicationText.has(record.target))
73
+ applicationText.set(record.target, record.target.nodeValue ?? "");
74
+ }
75
+ }
76
+ /** Writes projection-owned text without mistaking it for an application render. */
77
+ function writeProjectedText(state, node, value) {
78
+ const pending = state.observer?.takeRecords() ?? [];
79
+ if (pending.length > 0) {
80
+ recordApplicationWrites(pending);
81
+ scheduleValidation(state.doc, state);
82
+ }
83
+ node.nodeValue = value;
84
+ state.observer?.takeRecords();
85
+ }
52
86
  function readProjectionMarkers(element) {
53
87
  const raw = element.getAttribute(TEXT_PROJECTION_ATTR);
54
88
  if (!raw)
@@ -157,28 +191,32 @@ export function resolveTextProjectionTextNode(element, target, expectedText = ta
157
191
  }
158
192
  return matches.length === 1 ? matches[0] : null;
159
193
  }
160
- function hasSafeMixedDescendants(element) {
194
+ /** Whether an element's text is code, form state, or other non-prose content. */
195
+ export function isUnsafeTextHost(element) {
196
+ return UNSAFE_TEXT_TAGS.has(element.tagName);
197
+ }
198
+ /** Whether an application-owned editing region contains the element. */
199
+ export function isInApplicationEditingHost(element) {
200
+ const editingHost = element.closest("[contenteditable]");
201
+ return Boolean(editingHost
202
+ && editingHost.getAttribute("data-inline-editor") !== "true"
203
+ && editingHost.getAttribute("contenteditable") !== "false");
204
+ }
205
+ /** Whether replacing one text node inside the element keeps its authored markup. */
206
+ export function hasSafeMixedDescendants(element) {
161
207
  // <br> only controls line layout. The projection targets one exact text
162
208
  // node, so keeping the break while changing that node is safe; formatting
163
209
  // descendants below still reject a flattening text projection.
164
210
  for (const descendant of Array.from(element.querySelectorAll("*"))) {
165
211
  if (UNSAFE_MIXED_DESCENDANT_TAGS.has(descendant.tagName))
166
212
  return false;
167
- const editingHost = descendant.closest("[contenteditable]");
168
- if (editingHost
169
- && editingHost.getAttribute("data-inline-editor") !== "true"
170
- && editingHost.getAttribute("contenteditable") !== "false")
213
+ if (isInApplicationEditingHost(descendant))
171
214
  return false;
172
215
  }
173
216
  return true;
174
217
  }
175
218
  function textHostIsSafe(element, allowEmpty = false, target) {
176
- if (UNSAFE_TEXT_TAGS.has(element.tagName))
177
- return false;
178
- const editingHost = element.closest("[contenteditable]");
179
- if (editingHost
180
- && editingHost.getAttribute("data-inline-editor") !== "true"
181
- && editingHost.getAttribute("contenteditable") !== "false")
219
+ if (isUnsafeTextHost(element) || isInApplicationEditingHost(element))
182
220
  return false;
183
221
  if (allowEmpty && element.childNodes.length === 0)
184
222
  return true;
@@ -262,6 +300,9 @@ export function captureTextProjectionTarget(element, beforeText = element.textCo
262
300
  props: element.getAttribute("data-cprops"),
263
301
  ariaLabel: element.getAttribute("aria-label"),
264
302
  beforeText,
303
+ tagName: normalizeRuntimeTag(element.tagName),
304
+ elementId: boundRuntimeEvidence(element.id || null),
305
+ domPath: runtimeDomPath(element),
265
306
  ...pathTarget,
266
307
  };
267
308
  }
@@ -411,7 +452,7 @@ function textProjectionIdentityMatches(element, change) {
411
452
  && element.getAttribute("data-cprops") === change.target.props
412
453
  && element.getAttribute("aria-label") === change.target.ariaLabel;
413
454
  }
414
- function restoreAppliedProjection(applied) {
455
+ function restoreAppliedProjection(state, applied) {
415
456
  const element = applied.element;
416
457
  if (!element || !element.isConnected)
417
458
  return;
@@ -426,7 +467,9 @@ function restoreAppliedProjection(applied) {
426
467
  if (!textHostIsSafe(element, applied.change.after.length === 0, applied.change.target))
427
468
  return;
428
469
  if (textNode) {
429
- textNode.nodeValue = applied.change.before;
470
+ const rendered = applicationText.get(textNode);
471
+ applicationText.delete(textNode);
472
+ writeProjectedText(state, textNode, rendered ?? applied.change.before);
430
473
  }
431
474
  else if (applied.change.target.textNodePath === undefined
432
475
  && applied.change.after.length === 0
@@ -467,7 +510,7 @@ function validationStatus(applied) {
467
510
  * mutates; an overridden projection remains authoritative and is never
468
511
  * re-applied.
469
512
  */
470
- function resolvePendingProjection(doc, applied) {
513
+ function resolvePendingProjection(doc, state, applied) {
471
514
  if (applied.status !== "missing" && applied.status !== "ambiguous") {
472
515
  return validationStatus(applied);
473
516
  }
@@ -484,7 +527,9 @@ function resolvePendingProjection(doc, applied) {
484
527
  element.textContent = applied.change.after;
485
528
  }
486
529
  else {
487
- textNode.nodeValue = applied.change.after;
530
+ if (!applicationText.has(textNode))
531
+ applicationText.set(textNode, textNode.nodeValue ?? "");
532
+ writeProjectedText(state, textNode, applied.change.after);
488
533
  }
489
534
  applied.element = element;
490
535
  return "applied";
@@ -492,7 +537,7 @@ function resolvePendingProjection(doc, applied) {
492
537
  function validateAppliedProjection(doc, state) {
493
538
  let changed = false;
494
539
  for (const applied of state.applied.values()) {
495
- const status = resolvePendingProjection(doc, applied);
540
+ const status = resolvePendingProjection(doc, state, applied);
496
541
  if (status !== applied.status) {
497
542
  applied.status = status;
498
543
  changed = true;
@@ -516,6 +561,7 @@ function getDocumentState(doc) {
516
561
  if (existing)
517
562
  return existing;
518
563
  const state = {
564
+ doc,
519
565
  applied: new Map(),
520
566
  emptyAffordances: new Map(),
521
567
  snapshotKey: null,
@@ -524,7 +570,10 @@ function getDocumentState(doc) {
524
570
  };
525
571
  const Observer = doc.defaultView?.MutationObserver;
526
572
  if (Observer && doc.documentElement) {
527
- state.observer = new Observer(() => scheduleValidation(doc, state));
573
+ state.observer = new Observer((records) => {
574
+ recordApplicationWrites(records);
575
+ scheduleValidation(doc, state);
576
+ });
528
577
  state.observer.observe(doc.documentElement, {
529
578
  childList: true,
530
579
  subtree: true,
@@ -571,7 +620,7 @@ export function applyTextContentProjection(doc, changes) {
571
620
  if (incomingIds.has(id))
572
621
  continue;
573
622
  removeEmptyTextAffordance(state, id);
574
- restoreAppliedProjection(applied);
623
+ restoreAppliedProjection(state, applied);
575
624
  if (applied.element)
576
625
  removeProjectionMarker(applied.element, applied.change.target, id);
577
626
  }
@@ -579,13 +628,13 @@ export function applyTextContentProjection(doc, changes) {
579
628
  for (const change of changes) {
580
629
  const existing = previous.get(change.id);
581
630
  if (existing && JSON.stringify(existing.change) === JSON.stringify(change)) {
582
- existing.status = resolvePendingProjection(doc, existing);
631
+ existing.status = resolvePendingProjection(doc, state, existing);
583
632
  next.set(change.id, existing);
584
633
  continue;
585
634
  }
586
635
  if (existing) {
587
636
  removeEmptyTextAffordance(state, change.id);
588
- restoreAppliedProjection(existing);
637
+ restoreAppliedProjection(state, existing);
589
638
  if (existing.element)
590
639
  removeProjectionMarker(existing.element, existing.change.target, change.id);
591
640
  }
@@ -603,8 +652,11 @@ export function applyTextContentProjection(doc, changes) {
603
652
  next.set(change.id, { change, element: null, status: "missing" });
604
653
  continue;
605
654
  }
606
- if (textNode)
607
- textNode.nodeValue = change.after;
655
+ if (textNode) {
656
+ if (!applicationText.has(textNode))
657
+ applicationText.set(textNode, textNode.nodeValue ?? "");
658
+ writeProjectedText(state, textNode, change.after);
659
+ }
608
660
  else
609
661
  element.textContent = change.after;
610
662
  next.set(change.id, { change, element, status: "applied" });
@@ -708,6 +760,7 @@ export function resetTextProjectionState() {
708
760
  }
709
761
  }
710
762
  documentStates = new Map();
763
+ applicationText = new WeakMap();
711
764
  canonicalChanges = new Map();
712
765
  reportsByDocument = new WeakMap();
713
766
  reportsByCanvasCard.clear();
@@ -21,6 +21,20 @@ export declare function clearClipboardHandoff(): void;
21
21
  export declare function subscribeClipboardHandoff(listener: () => void): () => void;
22
22
  export declare function getClipboardHandoffRevision(): number;
23
23
  export declare function getLastClipboardReconciledCount(): number;
24
+ /** Records in one draft that still equal its copied, unverified snapshot. */
25
+ export declare function getClipboardHandoffRecords(draftId: string): {
26
+ changes: ChangeRecord[];
27
+ structuralChanges: StructuralChange[];
28
+ };
24
29
  export declare function reconcileClipboardHandoff(doc?: Document): Promise<number>;
30
+ /**
31
+ * Verifies copied edits after the document changes. Each check briefly removes
32
+ * the copied preview, so a check that reconciles nothing doubles the minimum
33
+ * interval before the next one: a page that mutates continuously (clocks,
34
+ * carousels) would otherwise flash the preview every few hundred milliseconds.
35
+ * Later changes never postpone a pending check, so a busy page is still
36
+ * checked once per interval. Returning to the page or copying a new prompt
37
+ * resets the interval.
38
+ */
25
39
  export declare function startClipboardHandoffController(doc?: Document): () => void;
26
40
  export {};
@@ -1,5 +1,5 @@
1
1
  import { changeKey } from "../changes/model.js";
2
- import { getDraftChanges, getActiveDraftChanges, subscribeActiveDraftChanges } from "../changes/draftChanges.js";
2
+ import { getDraftChanges, getActiveDraftChanges, subscribeActiveDraftChanges } from "../drafts/store.js";
3
3
  import { documentRevisions, subscribeDocumentRevision } from "../tokens/resolution/cssomCollector.js";
4
4
  import { captureHandoffOwner, handoffChangeFingerprint, handoffStructuralFingerprint, verifyAndReconcileHandoff, } from "../agent/verification.js";
5
5
  import { isDraftTarget } from "../drafts/model.js";
@@ -87,6 +87,11 @@ function matchingRecords(snapshot) {
87
87
  structuralChanges: workspace.structuralChanges.filter((change) => structures.get(change.id) === handoffStructuralFingerprint(change)),
88
88
  };
89
89
  }
90
+ /** Records in one draft that still equal its copied, unverified snapshot. */
91
+ export function getClipboardHandoffRecords(draftId) {
92
+ const snapshot = checkpoints.get(draftId);
93
+ return snapshot ? matchingRecords(snapshot) : { changes: [], structuralChanges: [] };
94
+ }
90
95
  function pruneCheckpoints() {
91
96
  let changed = false;
92
97
  for (const [id, snapshot] of checkpoints) {
@@ -119,33 +124,58 @@ export async function reconcileClipboardHandoff(doc = document) {
119
124
  }
120
125
  return removed;
121
126
  }
127
+ const CHECK_DELAY_MS = 450;
128
+ const MAX_CHECK_DELAY_MS = 8_000;
129
+ /**
130
+ * Verifies copied edits after the document changes. Each check briefly removes
131
+ * the copied preview, so a check that reconciles nothing doubles the minimum
132
+ * interval before the next one: a page that mutates continuously (clocks,
133
+ * carousels) would otherwise flash the preview every few hundred milliseconds.
134
+ * Later changes never postpone a pending check, so a busy page is still
135
+ * checked once per interval. Returning to the page or copying a new prompt
136
+ * resets the interval.
137
+ */
122
138
  export function startClipboardHandoffController(doc = document) {
123
139
  const view = doc.defaultView;
124
140
  let timer = null;
125
141
  let checking = false;
126
142
  let stopped = false;
127
- const schedule = () => {
143
+ let interval = CHECK_DELAY_MS;
144
+ let lastCheckEndedAt = -Infinity;
145
+ const run = () => {
146
+ timer = null;
128
147
  if (stopped || checking || !checkpoints.size)
129
148
  return;
149
+ checking = true;
150
+ void reconcileClipboardHandoff(doc).then((removed) => {
151
+ interval = removed > 0 ? CHECK_DELAY_MS : Math.min(interval * 2, MAX_CHECK_DELAY_MS);
152
+ }, () => undefined).finally(() => {
153
+ lastCheckEndedAt = Date.now();
154
+ setTimeout(() => { checking = false; }, 0);
155
+ });
156
+ };
157
+ const schedule = () => {
158
+ if (stopped || checking || !checkpoints.size || timer !== null)
159
+ return;
160
+ // Let the change that triggered this settle, and keep the backoff interval.
161
+ timer = setTimeout(run, Math.max(CHECK_DELAY_MS, lastCheckEndedAt + interval - Date.now()));
162
+ };
163
+ const returned = () => {
164
+ interval = CHECK_DELAY_MS;
165
+ lastCheckEndedAt = -Infinity;
130
166
  if (timer !== null)
131
167
  clearTimeout(timer);
132
- timer = setTimeout(() => {
133
- timer = null;
134
- if (stopped || checking || !checkpoints.size)
135
- return;
136
- checking = true;
137
- void reconcileClipboardHandoff(doc).catch(() => undefined).finally(() => {
138
- setTimeout(() => { checking = false; }, 0);
139
- });
140
- }, 450);
168
+ timer = null;
169
+ schedule();
141
170
  };
142
171
  const visible = () => { if (doc.visibilityState === "visible")
143
- schedule(); };
172
+ returned(); };
144
173
  documentRevisions(doc);
145
174
  const stopRevision = subscribeDocumentRevision(doc, schedule);
146
175
  const stopChanges = subscribeActiveDraftChanges(pruneCheckpoints);
147
- view?.addEventListener("focus", schedule);
148
- view?.addEventListener("pageshow", schedule);
176
+ const stopHandoff = subscribeClipboardHandoff(() => { interval = CHECK_DELAY_MS; });
177
+ view?.addEventListener("focus", returned);
178
+ view?.addEventListener("pageshow", returned);
149
179
  doc.addEventListener("visibilitychange", visible);
150
180
  schedule();
151
181
  return () => {
@@ -154,8 +184,9 @@ export function startClipboardHandoffController(doc = document) {
154
184
  clearTimeout(timer);
155
185
  stopRevision();
156
186
  stopChanges();
157
- view?.removeEventListener("focus", schedule);
158
- view?.removeEventListener("pageshow", schedule);
187
+ stopHandoff();
188
+ view?.removeEventListener("focus", returned);
189
+ view?.removeEventListener("pageshow", returned);
159
190
  doc.removeEventListener("visibilitychange", visible);
160
191
  };
161
192
  }
@@ -1,4 +1,4 @@
1
- import type { ChangeRecord } from "../changes/changesLog.js";
1
+ import type { ChangeRecord } from "../changes/types.js";
2
2
  import type { StructuralChange } from "../projection/structuralProjection.js";
3
3
  import type { AgentSketchMetadata } from "../agent/protocol.js";
4
4
  import { type ElementComment } from "../comments/store.js";