nudge-ui 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/dist/cli/agentCommand.js +4 -28
  2. package/dist/client.mjs +863 -213
  3. package/dist/hosts/next/wrapper.js +1 -7
  4. package/dist/hosts/projectBridge.js +3 -17
  5. package/dist/inspector/agent/McpConnectionDialog.js +7 -3
  6. package/dist/inspector/agent/activity.d.ts +1 -1
  7. package/dist/inspector/agent/activity.js +3 -2
  8. package/dist/inspector/agent/client.d.ts +2 -2
  9. package/dist/inspector/agent/client.js +28 -29
  10. package/dist/inspector/agent/connectionStatus.d.ts +3 -1
  11. package/dist/inspector/agent/connectionStatus.js +25 -0
  12. package/dist/inspector/agent/httpTransport.js +31 -147
  13. package/dist/inspector/agent/protocol.d.ts +1 -1
  14. package/dist/inspector/agent/protocol.js +1 -1
  15. package/dist/inspector/agent/verification.d.ts +1 -1
  16. package/dist/inspector/agent/verification.js +7 -4
  17. package/dist/inspector/boot.d.ts +3 -0
  18. package/dist/inspector/boot.js +297 -0
  19. package/dist/inspector/canvas/AgentActivityOverlay.d.ts +2 -1
  20. package/dist/inspector/canvas/AgentActivityOverlay.js +6 -3
  21. package/dist/inspector/canvas/CanvasCard.js +21 -12
  22. package/dist/inspector/canvas/CanvasElementOverlay.js +82 -127
  23. package/dist/inspector/canvas/CanvasToolbar.js +2 -1
  24. package/dist/inspector/canvas/CanvasWorkspace.js +74 -97
  25. package/dist/inspector/canvas/LockedWorkspaceNotice.d.ts +3 -2
  26. package/dist/inspector/canvas/LockedWorkspaceNotice.js +10 -6
  27. package/dist/inspector/canvas/PageCard.d.ts +10 -0
  28. package/dist/inspector/canvas/PageCard.js +51 -0
  29. package/dist/inspector/canvas/SketchToolOptions.d.ts +5 -0
  30. package/dist/inspector/canvas/SketchToolOptions.js +86 -0
  31. package/dist/inspector/canvas/StaleChangeIndicator.d.ts +1 -1
  32. package/dist/inspector/canvas/StaleChangeIndicator.js +1 -1
  33. package/dist/inspector/canvas/ToolOptionsDrawer.d.ts +21 -0
  34. package/dist/inspector/canvas/ToolOptionsDrawer.js +77 -0
  35. package/dist/inspector/canvas/activeCanvasDocument.d.ts +3 -2
  36. package/dist/inspector/canvas/assets/eraser.svg +28 -0
  37. package/dist/inspector/canvas/assets/pen.svg +25 -0
  38. package/dist/inspector/canvas/canvasFrame.d.ts +16 -0
  39. package/dist/inspector/canvas/canvasFrame.js +10 -0
  40. package/dist/inspector/canvas/canvasGestures.d.ts +0 -1
  41. package/dist/inspector/canvas/canvasGestures.js +0 -6
  42. package/dist/inspector/canvas/canvasStore.d.ts +6 -0
  43. package/dist/inspector/canvas/canvasStore.js +36 -1
  44. package/dist/inspector/canvas/frameConnection.d.ts +48 -0
  45. package/dist/inspector/canvas/frameConnection.js +73 -0
  46. package/dist/inspector/canvas/frameProtocol.d.ts +18 -1
  47. package/dist/inspector/canvas/frameProtocol.js +36 -0
  48. package/dist/inspector/canvas/pageSurface.d.ts +11 -0
  49. package/dist/inspector/canvas/pageSurface.js +34 -0
  50. package/dist/inspector/canvas/projection.d.ts +19 -9
  51. package/dist/inspector/canvas/projection.js +58 -31
  52. package/dist/inspector/canvas/rendererBootstrap.js +4 -1
  53. package/dist/inspector/canvas/rendererElementSelector.js +9 -1
  54. package/dist/inspector/canvas/rendererMessageRouter.d.ts +4 -5
  55. package/dist/inspector/canvas/rendererMessageRouter.js +12 -16
  56. package/dist/inspector/canvas/rendererSelectionProxy.d.ts +7 -1
  57. package/dist/inspector/canvas/rendererSelectionProxy.js +8 -36
  58. package/dist/inspector/canvas/rendererStylesheet.js +15 -0
  59. package/dist/inspector/canvas/sessionStore.d.ts +2 -2
  60. package/dist/inspector/canvas/sessionStore.js +12 -9
  61. package/dist/inspector/canvas/staleChangeDetector.d.ts +1 -1
  62. package/dist/inspector/canvas/staleChangeDetector.js +10 -22
  63. package/dist/inspector/changes/codecs.d.ts +1 -0
  64. package/dist/inspector/changes/codecs.js +20 -5
  65. package/dist/inspector/changes/draftPreview.d.ts +12 -0
  66. package/dist/inspector/changes/draftPreview.js +133 -0
  67. package/dist/inspector/changes/editModel.d.ts +8 -0
  68. package/dist/inspector/changes/editModel.js +8 -2
  69. package/dist/inspector/changes/managedStyleProjection.js +2 -1
  70. package/dist/inspector/changes/previewDiagnostics.js +1 -1
  71. package/dist/inspector/changes/types.d.ts +11 -1
  72. package/dist/inspector/comments/CommentsOverlay.js +18 -16
  73. package/dist/inspector/comments/store.js +3 -2
  74. package/dist/inspector/comments/verification.js +1 -1
  75. package/dist/inspector/componentSemantics/ComponentPropsSection.js +2 -1
  76. package/dist/inspector/componentSemantics/changeAction.js +1 -1
  77. package/dist/inspector/componentSemantics/textBinding.d.ts +1 -2
  78. package/dist/inspector/componentSemantics/textBinding.js +4 -45
  79. package/dist/inspector/drafts/draftStore.d.ts +109 -0
  80. package/dist/inspector/drafts/draftStore.js +451 -0
  81. package/dist/inspector/drafts/model.d.ts +9 -1
  82. package/dist/inspector/drafts/model.js +5 -1
  83. package/dist/inspector/drafts/store.d.ts +53 -15
  84. package/dist/inspector/drafts/store.js +143 -169
  85. package/dist/inspector/index.d.ts +2 -4
  86. package/dist/inspector/index.js +2 -264
  87. package/dist/inspector/inline-text/inlineTextEditor.d.ts +1 -1
  88. package/dist/inspector/inline-text/inlineTextEditor.js +1 -2
  89. package/dist/inspector/inline-text/textEditChange.d.ts +1 -1
  90. package/dist/inspector/inspection/bridge.d.ts +1 -1
  91. package/dist/inspector/inspection/bridge.js +2 -1
  92. package/dist/inspector/inspection/browserCssInspection.d.ts +8 -0
  93. package/dist/inspector/inspection/browserCssInspection.js +28 -6
  94. package/dist/inspector/inspection/inspectionSnapshot.d.ts +6 -0
  95. package/dist/inspector/inspection/inspectionSnapshot.js +10 -0
  96. package/dist/inspector/inspection/performanceDiagnostics.d.ts +18 -0
  97. package/dist/inspector/inspection/performanceDiagnostics.js +31 -0
  98. package/dist/inspector/inspection/useBrowserCssInspection.js +17 -38
  99. package/dist/inspector/iterations/capture.d.ts +2 -1
  100. package/dist/inspector/iterations/client.d.ts +2 -1
  101. package/dist/inspector/iterations/coordinator.d.ts +4 -3
  102. package/dist/inspector/iterations/coordinator.js +5 -3
  103. package/dist/inspector/iterations/prompt.js +9 -8
  104. package/dist/inspector/overlay/interactionStyles.js +17 -0
  105. package/dist/inspector/pageInspector.d.ts +42 -0
  106. package/dist/inspector/pageInspector.js +342 -0
  107. package/dist/inspector/projection/draftProjection.d.ts +10 -2
  108. package/dist/inspector/projection/draftProjection.js +9 -1
  109. package/dist/inspector/projection/managedStylesheet.js +24 -4
  110. package/dist/inspector/projection/renderedInstance.js +7 -1
  111. package/dist/inspector/projection/structuralProjection.d.ts +0 -9
  112. package/dist/inspector/projection/structuralProjection.js +14 -44
  113. package/dist/inspector/projection/textProjection.d.ts +8 -2
  114. package/dist/inspector/projection/textProjection.js +21 -13
  115. package/dist/inspector/prompt/clipboardHandoff.d.ts +9 -0
  116. package/dist/inspector/prompt/clipboardHandoff.js +42 -16
  117. package/dist/inspector/prompt/generatePrompt.d.ts +1 -1
  118. package/dist/inspector/prompt/generatePrompt.js +243 -147
  119. package/dist/inspector/prompt/promptDocument.d.ts +3 -0
  120. package/dist/inspector/prompt/promptDocument.js +8 -0
  121. package/dist/inspector/prompt/promptSettings.js +7 -5
  122. package/dist/inspector/runtime/inspectorStorage.d.ts +17 -0
  123. package/dist/inspector/runtime/inspectorStorage.js +42 -0
  124. package/dist/inspector/runtime/ownedStylesheets.d.ts +20 -0
  125. package/dist/inspector/runtime/ownedStylesheets.js +72 -0
  126. package/dist/inspector/runtime/runtimeConfig.d.ts +4 -0
  127. package/dist/inspector/runtime/runtimeConfig.js +10 -1
  128. package/dist/inspector/runtime/runtimeIdentityClaims.d.ts +29 -0
  129. package/dist/inspector/runtime/runtimeIdentityClaims.js +188 -0
  130. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.d.ts +15 -0
  131. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.js +113 -29
  132. package/dist/inspector/selection/editScope.d.ts +1 -0
  133. package/dist/inspector/selection/editScope.js +13 -2
  134. package/dist/inspector/shell/AgentStatusButton.js +2 -2
  135. package/dist/inspector/shell/AppShell.js +6 -2
  136. package/dist/inspector/shell/ChangesLog.js +27 -9
  137. package/dist/inspector/shell/CopyPromptButton.js +60 -54
  138. package/dist/inspector/shell/EmptyState.js +3 -3
  139. package/dist/inspector/shell/InspectorShell.d.ts +0 -3
  140. package/dist/inspector/shell/InspectorShell.js +21 -13
  141. package/dist/inspector/shell/PeekOriginalButton.js +3 -3
  142. package/dist/inspector/shell/interactionStatePreview.d.ts +9 -0
  143. package/dist/inspector/shell/interactionStatePreview.js +112 -0
  144. package/dist/inspector/shell/originalPreview.d.ts +3 -2
  145. package/dist/inspector/shell/originalPreview.js +10 -37
  146. package/dist/inspector/shell/stateValue.js +2 -3
  147. package/dist/inspector/sketch/SketchEditor.js +5 -4
  148. package/dist/inspector/sketch/SketchFrameOverlay.d.ts +2 -1
  149. package/dist/inspector/sketch/SketchFrameOverlay.js +5 -4
  150. package/dist/inspector/sketch/SketchOverlay.d.ts +3 -5
  151. package/dist/inspector/sketch/SketchOverlay.js +139 -263
  152. package/dist/inspector/sketch/SketchPromptPanel.d.ts +1 -1
  153. package/dist/inspector/sketch/SketchPromptPanel.js +8 -1
  154. package/dist/inspector/sketch/SketchThumbnail.d.ts +5 -0
  155. package/dist/inspector/sketch/SketchThumbnail.js +18 -0
  156. package/dist/inspector/sketch/SketchWorkspace.d.ts +1 -2
  157. package/dist/inspector/sketch/SketchWorkspace.js +69 -34
  158. package/dist/inspector/sketch/capture.js +19 -3
  159. package/dist/inspector/sketch/copySketch.d.ts +10 -0
  160. package/dist/inspector/sketch/copySketch.js +52 -0
  161. package/dist/inspector/sketch/drawingTools.d.ts +17 -0
  162. package/dist/inspector/sketch/drawingTools.js +47 -0
  163. package/dist/inspector/sketch/frameHeading.d.ts +9 -0
  164. package/dist/inspector/sketch/frameHeading.js +30 -0
  165. package/dist/inspector/sketch/freehand.js +3 -3
  166. package/dist/inspector/sketch/geometry.d.ts +6 -0
  167. package/dist/inspector/sketch/geometry.js +19 -0
  168. package/dist/inspector/sketch/history.d.ts +30 -0
  169. package/dist/inspector/sketch/history.js +58 -0
  170. package/dist/inspector/sketch/interaction.d.ts +1 -3
  171. package/dist/inspector/sketch/interaction.js +6 -9
  172. package/dist/inspector/sketch/model.d.ts +35 -1
  173. package/dist/inspector/sketch/model.js +116 -61
  174. package/dist/inspector/sketch/persistence.d.ts +14 -0
  175. package/dist/inspector/sketch/persistence.js +63 -7
  176. package/dist/inspector/sketch/raster.d.ts +6 -2
  177. package/dist/inspector/sketch/raster.js +43 -17
  178. package/dist/inspector/sketch/store.d.ts +1 -1
  179. package/dist/inspector/sketch/store.js +1 -1
  180. package/dist/inspector/sketch/videoFrames.d.ts +6 -0
  181. package/dist/inspector/sketch/videoFrames.js +81 -0
  182. package/dist/inspector/styleEditors/BackgroundEditor.js +2 -1
  183. package/dist/inspector/styleEditors/BorderEditor.js +30 -130
  184. package/dist/inspector/styleEditors/BorderRadiusEditor.js +8 -3
  185. package/dist/inspector/styleEditors/ImageBackgroundEditor.js +1 -1
  186. package/dist/inspector/styleEditors/LayoutSection.js +2 -2
  187. package/dist/inspector/styleEditors/borderModel.d.ts +42 -0
  188. package/dist/inspector/styleEditors/borderModel.js +114 -0
  189. package/dist/inspector/styleEditors/layoutValue.js +2 -3
  190. package/dist/inspector/tokens/TokenField.js +34 -3
  191. package/dist/inspector/tokens/TokensPanel.js +2 -1
  192. package/dist/inspector/tokens/editActions.d.ts +3 -3
  193. package/dist/inspector/tokens/editActions.js +9 -3
  194. package/dist/inspector/tokens/resolution/containerQueryEvaluator.d.ts +15 -0
  195. package/dist/inspector/tokens/resolution/containerQueryEvaluator.js +86 -0
  196. package/dist/inspector/tokens/resolution/cssomCollector.js +44 -9
  197. package/dist/inspector/tokens/resolution/nestedSelectors.d.ts +6 -0
  198. package/dist/inspector/tokens/resolution/nestedSelectors.js +67 -0
  199. package/dist/inspector/tokens/resolution/ruleMatching.js +23 -4
  200. package/dist/inspector/tokens/resolution.d.ts +6 -3
  201. package/dist/inspector/tokens/resolution.js +91 -112
  202. package/dist/inspector/tokens/tokenEdits.d.ts +1 -1
  203. package/dist/inspector/tokens/tokenEdits.js +1 -1
  204. package/dist/inspector/ui/InlineStyleWarning.js +2 -2
  205. package/dist/inspector/ui/InspectorStyle.d.ts +8 -0
  206. package/dist/inspector/ui/InspectorStyle.js +26 -0
  207. package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
  208. package/dist/inspector/ui/PopoverListbox.js +3 -3
  209. package/dist/inspector/ui/Toast.d.ts +14 -0
  210. package/dist/inspector/ui/Toast.js +30 -0
  211. package/dist/inspector/ui/assets/canvasIllustration.d.ts +2 -0
  212. package/dist/inspector/ui/assets/canvasIllustration.js +21 -0
  213. package/dist/inspector/ui/assets/gridIllustration.d.ts +2 -0
  214. package/dist/inspector/ui/assets/{grid.svg → gridIllustration.js} +3 -2
  215. package/dist/inspector/ui/customCursors.d.ts +5 -0
  216. package/dist/inspector/ui/customCursors.js +32 -6
  217. package/dist/inspector/ui/styles.js +12 -10
  218. package/dist/inspector/workspace/commands.js +1 -2
  219. package/dist/inspector/workspace/controller.js +1 -2
  220. package/dist/inspector/workspace/handoff.js +3 -2
  221. package/dist/inspector/workspace/sentItems.d.ts +3 -6
  222. package/dist/inspector/workspace/sentItems.js +6 -24
  223. package/dist/inspector/workspace/timeline.d.ts +24 -10
  224. package/dist/inspector/workspace/timeline.js +118 -96
  225. package/dist/internal/agent-protocol.d.ts +50 -13
  226. package/dist/internal/agent-protocol.js +145 -19
  227. package/dist/nudge-ui.mjs +81 -65
  228. package/dist/project/mcpPackage.d.ts +8 -0
  229. package/dist/project/mcpPackage.js +60 -0
  230. package/package.json +12 -2
  231. package/dist/inspector/canvas/measurementProjection.d.ts +0 -8
  232. package/dist/inspector/canvas/measurementProjection.js +0 -16
  233. package/dist/inspector/changes/changesLog.d.ts +0 -49
  234. package/dist/inspector/changes/changesLog.js +0 -255
  235. package/dist/inspector/changes/draftChanges.d.ts +0 -58
  236. package/dist/inspector/changes/draftChanges.js +0 -304
  237. package/dist/inspector/conformance/projection.d.ts +0 -2
  238. package/dist/inspector/conformance/projection.js +0 -3
  239. package/dist/inspector/inline-text/textChangeBoundary.d.ts +0 -6
  240. package/dist/inspector/inline-text/textChangeBoundary.js +0 -1
  241. package/dist/inspector/overlay/InspectorOverlay.d.ts +0 -5
  242. package/dist/inspector/overlay/InspectorOverlay.js +0 -332
  243. package/dist/inspector/overlay/elementSelector.d.ts +0 -1
  244. package/dist/inspector/overlay/elementSelector.js +0 -111
  245. package/dist/inspector/sketch/SketchChanges.d.ts +0 -2
  246. package/dist/inspector/sketch/SketchChanges.js +0 -72
  247. package/dist/inspector/sketch/SketchEntryButton.d.ts +0 -4
  248. package/dist/inspector/sketch/SketchEntryButton.js +0 -11
  249. package/dist/inspector/sketch/SketchLayersPanel.d.ts +0 -2
  250. package/dist/inspector/sketch/SketchLayersPanel.js +0 -71
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useMemo, useSyncExternalStore } from "react";
2
+ import { useMemo, useState, useSyncExternalStore } from "react";
3
3
  import { IconArrowBackUp } from "@tabler/icons-react";
4
- import { isComponentChange, isElementChange, isTextContentChange, isTokenChange, useChanges, revertChange, } from "../changes/changesLog.js";
4
+ import { isComponentChange, isElementChange, isTextContentChange, isTokenChange, } from "../changes/types.js";
5
+ import { useChanges, revertChange } from "../drafts/store.js";
5
6
  import { StaleChangeIndicator } from "../canvas/StaleChangeIndicator.js";
6
7
  import { Button } from "../ui/Button.js";
7
8
  import { Disclosure } from "../ui/Disclosure.js";
@@ -11,8 +12,8 @@ import { presentChange } from "../changes/presentation.js";
11
12
  import { getStructuralChanges, getStructuralChangeDiagnostics, getStructuralDiagnosticRevision, revertStructuralChange, subscribeStructuralChanges, subscribeStructuralDiagnostics, } from "../projection/structuralProjection.js";
12
13
  import { getRenderedInstanceChangeDiagnostics, getRenderedInstanceDiagnosticRevision, subscribeRenderedInstanceDiagnostics, } from "../projection/renderedInstance.js";
13
14
  import { getTextContentChangeDiagnostics, getTextProjectionDiagnosticRevision, subscribeTextProjectionDiagnostics, } from "../projection/textProjection.js";
14
- import { SketchChanges } from "../sketch/SketchChanges.js";
15
- import { useSketchStore } from "../sketch/store.js";
15
+ import { removeSketch, useSketchStore } from "../sketch/store.js";
16
+ import { StatusCallout } from "../ui/StatusCallout.js";
16
17
  import { useFrameComments } from "../comments/store.js";
17
18
  import { countPromptChanges } from "../prompt/generatePrompt.js";
18
19
  function groupChanges(changes) {
@@ -75,8 +76,25 @@ function changeActionLabel(change, presentation) {
75
76
  return "Changed text";
76
77
  return `Changed ${presentation.propertyLabel}`;
77
78
  }
78
- function RevertButton({ dataTest, dataProperty, onClick, }) {
79
- return (_jsx(Tooltip, { content: "Revert", stableTrigger: true, children: _jsx(IconButton, { variant: "quiet", size: "compact", className: "changes__revert", "data-test": dataTest, "data-property": dataProperty, label: "Revert change", onClick: onClick, children: _jsx(IconArrowBackUp, { size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }) }) }));
79
+ function RevertButton({ dataTest, dataProperty, onClick, disabled, label = "Revert change", tooltip = "Revert", }) {
80
+ return (_jsx(Tooltip, { content: tooltip, stableTrigger: true, children: _jsx(IconButton, { variant: "quiet", size: "compact", className: "changes__revert", "data-test": dataTest, "data-property": dataProperty, label: label, disabled: disabled, onClick: onClick, children: _jsx(IconArrowBackUp, { size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }) }) }));
81
+ }
82
+ function SketchChangeRow({ item }) {
83
+ const [error, setError] = useState(null);
84
+ const note = item.document.description.trim()
85
+ || item.document.annotations?.map((annotation) => annotation.description).join("; ");
86
+ const busy = item.status === "dispatching" || item.status === "handing-off";
87
+ async function remove() {
88
+ setError(null);
89
+ try {
90
+ if (!await removeSketch(item.document.id))
91
+ setError("The sketch could not be removed yet.");
92
+ }
93
+ catch (cause) {
94
+ setError(cause instanceof Error ? cause.message : "The sketch could not be removed.");
95
+ }
96
+ }
97
+ return (_jsxs("div", { className: "changes__group", children: [_jsxs("div", { className: "changes__row changes__row--sketch", "data-test": "sketch-row", "data-sketch-id": item.document.id, children: [_jsxs("div", { className: "changes__summary", children: [_jsx("span", { className: "changes__target", children: "Sketch" }), note ? _jsx("span", { className: "changes__action", title: note, children: note }) : null] }), _jsx(RevertButton, { dataTest: "sketch-revert", label: "Remove sketch", tooltip: "Remove sketch", disabled: busy, onClick: () => void remove() })] }), error ? _jsx(StatusCallout, { tone: "warning", role: "status", children: error }) : null] }));
80
98
  }
81
99
  export function ChangesLog({ onClearSession }) {
82
100
  const changes = useChanges();
@@ -103,8 +121,8 @@ export function ChangesLog({ onClearSession }) {
103
121
  const textDiagnostics = change.kind === "text-content"
104
122
  ? getTextContentChangeDiagnostics(change.id)
105
123
  : [];
106
- return (_jsxs("div", { className: "changes__row", "data-test": "change-row", "data-property": presentation.property, children: [_jsx("span", { className: "changes__target", "data-test": "change-target", children: changeTargetLabel(change, presentation) }), _jsx("span", { className: "changes__action", "data-test": "change-action", children: changeActionLabel(change, presentation) }), _jsxs("span", { className: "changes__metadata", "aria-hidden": "true", children: [_jsx("span", { className: "changes__prop", children: presentation.propertyLabel }), _jsxs("span", { className: "changes__value", children: [_jsx("span", { className: "changes__before", children: presentation.before }), _jsx("span", { className: "changes__arrow", children: "\u2192" }), _jsx("span", { className: "changes__after", children: presentation.after })] }), presentation.scope ? (_jsx("span", { className: "changes__scope", "data-test": "change-scope", children: presentation.scope === "source-site" ? "All outputs at source site" : "This rendered item only" })) : null, presentation.evidence ? (_jsx("span", { className: "changes__evidence", "data-test": "change-evidence", children: presentation.evidence })) : null, _jsx(StaleChangeIndicator, { change: change }), instanceDiagnostics.map((diagnostic) => (_jsxs("span", { className: "changes__diagnostic", "data-test": "instance-diagnostic", "data-document": diagnostic.document, "data-status": diagnostic.status, children: [diagnostic.document, ": ", diagnostic.status] }, `${diagnostic.document}:${diagnostic.status}`))), textDiagnostics.map((diagnostic) => (_jsxs("span", { className: "changes__diagnostic", "data-test": "text-projection-diagnostic", "data-document": diagnostic.document, "data-status": diagnostic.status, children: [diagnostic.document, ": ", diagnostic.status] }, `${diagnostic.document}:${diagnostic.status}`)))] }), _jsx(RevertButton, { dataTest: "change-revert", dataProperty: presentation.property, onClick: () => revertChange(change) })] }, `${group.key}\u0000${presentation.property}\u0000${i}`));
107
- }) }, group.key))), structuralChanges.map((change) => (_jsx("div", { className: "changes__group", "data-test": "dom-change", "data-cid": change.target.sourceSite.cid, children: _jsxs("div", { className: "changes__row", "data-test": "dom-change-row", "data-action": change.kind, children: [_jsx("span", { className: "changes__target", "data-test": "structural-target", children: change.target.sourceSite.cid }), _jsx("span", { className: "changes__action", "data-test": "structural-action", children: change.kind === "move" ? "Moved" : "Deleted" }), _jsxs("span", { className: "changes__metadata", "aria-hidden": "true", children: [_jsxs("span", { className: "changes__source-site", "data-test": "structural-source-site", children: ["Source site: ", change.target.sourceSite.cid] }), _jsx("span", { className: "changes__prop", children: change.kind === "move" ? "Move in DOM" : "Delete from DOM" }), _jsxs("span", { className: "changes__value", children: [_jsx("span", { className: "changes__before", children: change.kind === "move"
124
+ return (_jsxs("div", { className: "changes__row", "data-test": "change-row", "data-property": presentation.property, children: [_jsxs("div", { className: "changes__summary", children: [_jsx("span", { className: "changes__target", "data-test": "change-target", children: changeTargetLabel(change, presentation) }), _jsx("span", { className: "changes__action", "data-test": "change-action", children: changeActionLabel(change, presentation) })] }), _jsxs("span", { className: "changes__metadata", "aria-hidden": "true", children: [_jsx("span", { className: "changes__prop", children: presentation.propertyLabel }), _jsxs("span", { className: "changes__value", children: [_jsx("span", { className: "changes__before", children: presentation.before }), _jsx("span", { className: "changes__arrow", children: "\u2192" }), _jsx("span", { className: "changes__after", children: presentation.after })] }), presentation.scope ? (_jsx("span", { className: "changes__scope", "data-test": "change-scope", children: presentation.scope === "source-site" ? "All outputs at source site" : "This rendered item only" })) : null, presentation.evidence ? (_jsx("span", { className: "changes__evidence", "data-test": "change-evidence", children: presentation.evidence })) : null, _jsx(StaleChangeIndicator, { change: change }), instanceDiagnostics.map((diagnostic) => (_jsxs("span", { className: "changes__diagnostic", "data-test": "instance-diagnostic", "data-document": diagnostic.document, "data-status": diagnostic.status, children: [diagnostic.document, ": ", diagnostic.status] }, `${diagnostic.document}:${diagnostic.status}`))), textDiagnostics.map((diagnostic) => (_jsxs("span", { className: "changes__diagnostic", "data-test": "text-projection-diagnostic", "data-document": diagnostic.document, "data-status": diagnostic.status, children: [diagnostic.document, ": ", diagnostic.status] }, `${diagnostic.document}:${diagnostic.status}`)))] }), _jsx(RevertButton, { dataTest: "change-revert", dataProperty: presentation.property, onClick: () => revertChange(change) })] }, `${group.key}\u0000${presentation.property}\u0000${i}`));
125
+ }) }, group.key))), structuralChanges.map((change) => (_jsx("div", { className: "changes__group", "data-test": "dom-change", "data-cid": change.target.sourceSite.cid, children: _jsxs("div", { className: "changes__row", "data-test": "dom-change-row", "data-action": change.kind, children: [_jsxs("div", { className: "changes__summary", children: [_jsx("span", { className: "changes__target", "data-test": "structural-target", children: change.target.sourceSite.cid }), _jsx("span", { className: "changes__action", "data-test": "structural-action", children: change.kind === "move" ? "Moved" : "Deleted" })] }), _jsxs("span", { className: "changes__metadata", "aria-hidden": "true", children: [_jsxs("span", { className: "changes__source-site", "data-test": "structural-source-site", children: ["Source site: ", change.target.sourceSite.cid] }), _jsx("span", { className: "changes__prop", children: change.kind === "move" ? "Move in DOM" : "Delete from DOM" }), _jsxs("span", { className: "changes__value", children: [_jsx("span", { className: "changes__before", children: change.kind === "move"
108
126
  ? structuralParentIdentityKey(change.source.parent) === structuralParentIdentityKey(change.destination.parent)
109
127
  ? `${change.presentation.sourceParentTag} position ${change.presentation.fromIndex + 1}`
110
128
  : `${structuralParentLabel(change, "source")} position ${change.presentation.fromIndex + 1}`
@@ -112,5 +130,5 @@ export function ChangesLog({ onClearSession }) {
112
130
  ? structuralParentIdentityKey(change.source.parent) === structuralParentIdentityKey(change.destination.parent)
113
131
  ? `${change.presentation.destinationParentTag} position ${change.presentation.toIndex + 1}`
114
132
  : `${structuralParentLabel(change, "destination")} position ${change.presentation.toIndex + 1}`
115
- : "Removed" })] }), _jsx("span", { className: "changes__scope", "data-test": "structural-scope", children: "This rendered item only" }), getStructuralChangeDiagnostics(change.id).map((diagnostic) => (_jsx("span", { className: "changes__diagnostic", "data-test": "structural-diagnostic", "data-document": diagnostic.document, "data-status": diagnostic.status, "data-reason": diagnostic.reason, children: structuralDiagnosticText(diagnostic) }, `${diagnostic.document}:${diagnostic.status}:${diagnostic.reason ?? ""}`)))] }), _jsx(RevertButton, { dataTest: "dom-change-revert", onClick: () => revertStructuralChange(change.id) })] }) }, change.id))), _jsx(SketchChanges, {})] })) }) : null, onClearSession ? (_jsx("div", { className: "changes__session-action", "data-test": "session-actions", children: _jsx(Button, { variant: "secondary", type: "button", "data-test": "clear-session", onClick: onClearSession, children: "Clear Changes" }) })) : null] }));
133
+ : "Removed" })] }), _jsx("span", { className: "changes__scope", "data-test": "structural-scope", children: "This rendered item only" }), getStructuralChangeDiagnostics(change.id).map((diagnostic) => (_jsx("span", { className: "changes__diagnostic", "data-test": "structural-diagnostic", "data-document": diagnostic.document, "data-status": diagnostic.status, "data-reason": diagnostic.reason, children: structuralDiagnosticText(diagnostic) }, `${diagnostic.document}:${diagnostic.status}:${diagnostic.reason ?? ""}`)))] }), _jsx(RevertButton, { dataTest: "dom-change-revert", onClick: () => revertStructuralChange(change.id) })] }) }, change.id))), sketches.map((item) => _jsx(SketchChangeRow, { item: item }, `${item.document.id}:${item.document.revision}`)), sketchStore.error ? _jsx(StatusCallout, { tone: "warning", "data-test": "sketch-storage-error", children: sketchStore.error }) : null] })) }) : null, onClearSession ? (_jsx("div", { className: "changes__session-action", "data-test": "session-actions", children: _jsx(Button, { variant: "secondary", type: "button", "data-test": "clear-session", onClick: onClearSession, children: "Clear Changes" }) })) : null] }));
116
134
  }
@@ -2,11 +2,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { Menu } from "@base-ui/react/menu";
3
3
  import { iterationId } from "../canvas/frameContent.js";
4
4
  import { useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
5
- import { IconArtboard, IconBoltFilled, IconCheck, IconChevronDown, IconCopy, IconPlugConnected, IconSend, } from "@tabler/icons-react";
6
- import { useChanges } from "../changes/changesLog.js";
5
+ import { IconArtboard, IconBoltFilled, IconCheck, IconChevronDown, IconCopy, IconPencil, IconPlugConnected, IconSend, IconX, } from "@tabler/icons-react";
6
+ import { useChanges } from "../drafts/store.js";
7
7
  import { countPromptChanges } from "../prompt/generatePrompt.js";
8
8
  import { loadCustomInstructions, saveCustomInstructions } from "../prompt/promptSettings.js";
9
- import { getAgentConnectionStatus } from "../agent/connectionStatus.js";
9
+ import { useAgentConnectionStatus } from "../agent/connectionStatus.js";
10
10
  import { SettingsDialog } from "../settings/SettingsDialog.js";
11
11
  import { Button } from "../ui/Button.js";
12
12
  import { portalContainer } from "../ui/portalContainer.js";
@@ -18,8 +18,12 @@ import { createAgentPresentationAdapter } from "../canvas/agentPresentation.js";
18
18
  import { captureHandoffOwner, getAgentDispatch, verifyAndReconcileAgentDispatch, } from "../agent/verification.js";
19
19
  import { clearSentItems, getSentItems, sentItemCount } from "../workspace/sentItems.js";
20
20
  import { getClipboardHandoffRevision, getLastClipboardReconciledCount, subscribeClipboardHandoff, } from "../prompt/clipboardHandoff.js";
21
- import { useSketches, settleSketchDispatch } from "../sketch/store.js";
22
- import { SketchLayersPanel } from "../sketch/SketchLayersPanel.js";
21
+ import { removeSketch, useSketches, settleSketchDispatch } from "../sketch/store.js";
22
+ import { SketchThumbnail } from "../sketch/SketchThumbnail.js";
23
+ import { copySketchImageOnRequest } from "../sketch/copySketch.js";
24
+ import { closeSketchNote } from "../sketch/sketchNote.js";
25
+ import { IconButton } from "../ui/IconButton.js";
26
+ import { showToast } from "../ui/Toast.js";
23
27
  import { isSendPromptShortcut, SEND_PROMPT_HOTKEY_EVENT } from "./shortcuts.js";
24
28
  import { getFocusedCardId, getSelectedCardId, useCanvasCards, useFocusedCardId, useSelectedCardId } from "../canvas/canvasStore.js";
25
29
  import { getEditableCardId, sketchBelongsToCard, useDrafts } from "../drafts/store.js";
@@ -49,8 +53,6 @@ export function CopyPromptButton({ settingsOpen: controlledSettingsOpen, setting
49
53
  const handoffBusy = useRef(false);
50
54
  const [saveMessage, setSaveMessage] = useState(null);
51
55
  const [agentOutcome, setAgentOutcome] = useState(null);
52
- const [clipboardPhase, setClipboardPhase] = useState("idle");
53
- const [undoClear, setUndoClear] = useState(null);
54
56
  const [sketchFallback, setSketchFallback] = useState(null);
55
57
  const [localSettingsOpen, setLocalSettingsOpen] = useState(false);
56
58
  const [localSettingsSection, setLocalSettingsSection] = useState("instructions");
@@ -124,16 +126,20 @@ export function CopyPromptButton({ settingsOpen: controlledSettingsOpen, setting
124
126
  void settleSketchDispatch(request.changeRevision, request.status, request.requestId, request.clientDispatchId).catch(() => undefined);
125
127
  }, [agent.request?.changeRevision, agent.request?.requestId, agent.request?.clientDispatchId, agent.request?.sketches, agent.request?.status]);
126
128
  const connecting = agent.state === "pairing";
129
+ const delivered = agent.state === "delivered" || agent.request?.status === "delivered";
127
130
  const working = agent.state === "working" || agent.request?.status === "working";
128
131
  const canConnect = agent.companionReachable
129
132
  && agent.listenerActive
130
133
  && !agent.paired
131
134
  && !connecting
132
- && !working;
133
- const canSend = agent.paired && agent.listenerActive && !working;
135
+ && !working
136
+ && !delivered;
137
+ const canSend = agent.paired && agent.listenerActive && !working && !delivered;
134
138
  const changeCount = countPromptChanges(changes, structuralChanges, canSend ? pendingSketches.length : 0) + comments.length;
135
- const disabled = preparing || connecting || working || (!canConnect && !hasChanges);
136
- const agentStatus = getAgentConnectionStatus(agent);
139
+ // The badge counts every pending sketch, including ones copied separately from the menu.
140
+ const badgeCount = countPromptChanges(changes, structuralChanges, pendingSketches.length) + comments.length;
141
+ const disabled = preparing || connecting || working || delivered || (!canConnect && !hasChanges);
142
+ const agentStatus = useAgentConnectionStatus(agent);
137
143
  const statusAction = agentStatus.action;
138
144
  const label = preparing
139
145
  ? "Saving iteration…"
@@ -141,18 +147,20 @@ export function CopyPromptButton({ settingsOpen: controlledSettingsOpen, setting
141
147
  ? "Copied!"
142
148
  : connecting
143
149
  ? "Connecting…"
144
- : working
145
- ? "Agent working…"
146
- : canConnect && !activeArtifactId
147
- ? "Connect agent"
148
- : canSend && !activeArtifactId
149
- ? "Send prompt"
150
- : "Copy prompt";
150
+ : delivered
151
+ ? "Awaiting agent…"
152
+ : working
153
+ ? "Agent working…"
154
+ : canConnect && !activeArtifactId
155
+ ? "Connect agent"
156
+ : canSend && !activeArtifactId
157
+ ? "Send prompt"
158
+ : "Copy prompt";
151
159
  const icon = copied
152
160
  ? _jsx(IconCheck, { size: "var(--icon-size-small)", stroke: 1.8, "aria-hidden": "true" })
153
161
  : !activeArtifactId && (canConnect || connecting)
154
162
  ? _jsx(IconPlugConnected, { size: "var(--icon-size-small)", stroke: 1.8, "aria-hidden": "true" })
155
- : !activeArtifactId && (canSend || working)
163
+ : !activeArtifactId && (canSend || working || delivered)
156
164
  ? _jsx(IconSend, { size: "var(--icon-size-small)", stroke: 1.8, "aria-hidden": "true" })
157
165
  : _jsx(IconCopy, { size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" });
158
166
  async function onClick() {
@@ -232,8 +240,6 @@ export function CopyPromptButton({ settingsOpen: controlledSettingsOpen, setting
232
240
  return;
233
241
  }
234
242
  setAgentOutcome(null);
235
- setUndoClear(null);
236
- setClipboardPhase("idle");
237
243
  setSketchFallback(null);
238
244
  const outcome = await deliverHandoff(prepared, runtimeConfig.projectId, canSend ? agentClient : null);
239
245
  if (outcome.kind === "sketch-failed") {
@@ -243,39 +249,14 @@ export function CopyPromptButton({ settingsOpen: controlledSettingsOpen, setting
243
249
  if (outcome.kind === "sent")
244
250
  return;
245
251
  setCopied(true);
246
- setClipboardPhase("copied");
247
252
  }
248
- useEffect(() => {
249
- if (clipboardPhase !== "copied" && clipboardPhase !== "away")
250
- return;
251
- // Focus moving into a canvas frame is not a return from the agent.
252
- const onBlur = () => {
253
- if (!(document.activeElement instanceof HTMLIFrameElement))
254
- setClipboardPhase("away");
255
- };
256
- const onFocus = () => setClipboardPhase((phase) => phase === "away" ? "returned" : phase);
257
- window.addEventListener("blur", onBlur);
258
- window.addEventListener("focus", onFocus);
259
- return () => {
260
- window.removeEventListener("blur", onBlur);
261
- window.removeEventListener("focus", onFocus);
262
- };
263
- }, [clipboardPhase]);
264
- useEffect(() => {
265
- if (!undoClear)
266
- return;
267
- const timer = window.setTimeout(() => setUndoClear(null), 10_000);
268
- return () => window.clearTimeout(timer);
269
- }, [undoClear]);
270
253
  const handoffOwner = captureHandoffOwner(activeDraftCardId);
271
254
  const sentItems = getSentItems(handoffOwner.draftId, handoffOwner.target, agentOutcome?.dispatch ?? null);
272
255
  const remainingCount = sentItemCount(sentItems);
273
256
  const showImplemented = (agentOutcome?.removed ?? 0) > 0 || reconciledCount > 0
274
- || (remainingCount > 0 && (agentOutcome !== null || clipboardPhase === "returned"));
257
+ || (remainingCount > 0 && agentOutcome !== null);
275
258
  function clearRemaining() {
276
- const restore = clearSentItems(sentItems);
277
- if (restore)
278
- setUndoClear(() => restore);
259
+ clearSentItems(sentItems);
279
260
  }
280
261
  useEffect(() => {
281
262
  function onKeydown(event) {
@@ -323,11 +304,36 @@ export function CopyPromptButton({ settingsOpen: controlledSettingsOpen, setting
323
304
  }
324
305
  openMcpConnection();
325
306
  }
326
- const promptButton = (_jsxs(Button, { variant: "primary", className: "copy-prompt__main", "data-test": "copy-prompt", type: "button", disabled: disabled, "data-copied": copied ? "true" : "false", "data-agent-state": agent.state, "aria-busy": preparing || working || connecting ? "true" : undefined, onClick: activeArtifactId ? undefined : onClick, children: [icon, label, changeCount > 0 ? (_jsx("span", { className: "copy-prompt__change-count", "data-test": "copy-prompt-change-count", children: changeCount })) : null, activeArtifactId ? _jsx(IconChevronDown, { size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }) : null] }));
327
- return (_jsxs("div", { className: "copy-prompt__stack", "data-test": "copy-prompt-control", children: [activeArtifactId ? (_jsxs(Menu.Root, { modal: false, children: [_jsx(Menu.Trigger, { render: promptButton }), _jsx(Menu.Portal, { container: portalContainer(), children: _jsx(Menu.Positioner, { className: "inspector-popover__positioner", side: "bottom", align: "start", sideOffset: 6, children: _jsxs(Menu.Popup, { className: "inspector-popover__popup copy-prompt__menu", "data-test": "copy-prompt-menu", children: [_jsxs(Menu.Item, { className: "copy-prompt__menu-item", "data-test": "copy-iteration-prompt", label: "Copy iteration prompt", onClick: () => void copyIterationPrompt("iteration"), children: [_jsx(IconArtboard, { className: "copy-prompt__menu-icon", size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), _jsxs("span", { className: "copy-prompt__menu-content", children: [_jsx("span", { className: "copy-prompt__menu-title", children: "Copy iteration prompt" }), _jsx("span", { className: "copy-prompt__menu-description", children: "Continue editing this HTML iteration." })] })] }), _jsxs(Menu.Item, { className: "copy-prompt__menu-item", "data-test": "copy-iteration-implementation", label: "Copy prompt for live app", onClick: () => void copyIterationPrompt("application"), children: [_jsx(IconBoltFilled, { className: "copy-prompt__menu-icon copy-prompt__menu-icon--live", size: "var(--icon-size-small)", "aria-hidden": "true" }), _jsxs("span", { className: "copy-prompt__menu-content", children: [_jsx("span", { className: "copy-prompt__menu-title", children: "Copy prompt for live app" }), _jsx("span", { className: "copy-prompt__menu-description", children: "Implement design in real app" })] })] })] }) }) })] }, activeDraftCardId)) : promptButton, _jsx(SketchLayersPanel, {}), statusAction || agentStatus.kind === "connected-not-listening" ? (_jsx(StatusCallout, { className: "copy-prompt__agent-status", tone: agentStatus.tone, "data-test": "agent-connection-status", children: _jsxs("div", { className: "copy-prompt__agent-status-content", children: [_jsx("span", { role: "status", children: agentStatus.label }), statusAction ? (_jsx(Button, { size: "compact", variant: "quiet", "data-test": "agent-status-action", "data-action": statusAction.kind, type: "button", onClick: () => void handleAgentStatusAction(), children: statusAction.label })) : null] }) })) : null, undoClear ? (_jsxs("p", { className: "copy-prompt__hint copy-prompt__hint--centered copy-prompt__hint--implemented", "data-test": "handoff-cleared-hint", role: "status", children: ["Cleared stale edits.", " ", _jsx("button", { type: "button", className: "copy-prompt__hint-action", "data-test": "handoff-undo-clear", onClick: () => {
328
- undoClear();
329
- setUndoClear(null);
330
- }, children: "Undo" })] })) : showImplemented ? (_jsxs("p", { className: "copy-prompt__hint copy-prompt__hint--centered copy-prompt__hint--implemented", "data-test": "handoff-implemented-hint", role: "status", children: ["Changes implemented.", remainingCount > 0 ? (_jsxs(_Fragment, { children: [" ", _jsx("button", { type: "button", className: "copy-prompt__hint-action", "data-test": "handoff-clear-remaining", onClick: clearRemaining, children: "Clear stale edits" })] })) : null] })) : null, saveMessage ? (_jsx("p", { className: "copy-prompt__hint copy-prompt__hint--centered", "data-test": "iteration-save-hint", role: "status", children: saveMessage })) : null, sketchFallback ? (_jsxs(StatusCallout, { className: "copy-prompt__sketch-fallback", tone: "warning", "data-test": "sketch-dispatch-error", children: [_jsx("span", { children: sketchFallback.error }), _jsx(Button, { size: "compact", variant: "secondary", type: "button", "data-test": "sketch-copy-fallback", onClick: () => {
331
- void copyHandoff(sketchFallback.handoff).then(() => setSketchFallback(null)).catch(() => undefined);
307
+ async function deleteSketch(sketchId) {
308
+ try {
309
+ if (!await removeSketch(sketchId)) {
310
+ showToast({ tone: "error", title: "Sketch not deleted", description: "This sketch is being sent and cannot be deleted yet." });
311
+ return;
312
+ }
313
+ closeSketchNote();
314
+ }
315
+ catch (error) {
316
+ showToast({ tone: "error", title: "Sketch not deleted", description: error instanceof Error ? error.message : "The sketch could not be deleted." });
317
+ }
318
+ }
319
+ const hasMenu = Boolean(activeArtifactId) || visibleSketches.length > 0;
320
+ const styleEditLabel = canConnect ? "Connect agent" : canSend ? "Send style edit prompt" : "Copy style edit prompt";
321
+ const styleEditDescription = canConnect
322
+ ? "Pair an agent first"
323
+ : canSend
324
+ ? "Send to the connected agent"
325
+ : "Edits made in the inspector";
326
+ const promptButton = (_jsxs(Button, { variant: "primary", className: "copy-prompt__main", "data-test": "copy-prompt", type: "button", disabled: disabled, "data-copied": copied ? "true" : "false", "data-agent-state": agent.state, "aria-busy": preparing || working || connecting ? "true" : undefined, onClick: hasMenu ? undefined : onClick, children: [icon, label, badgeCount > 0 ? (_jsx("span", { className: "copy-prompt__change-count", "data-test": "copy-prompt-change-count", children: badgeCount })) : null, hasMenu ? _jsx(IconChevronDown, { size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }) : null] }));
327
+ return (_jsxs("div", { className: "copy-prompt__stack", "data-test": "copy-prompt-control", children: [hasMenu ? (_jsxs(Menu.Root, { modal: false, children: [_jsx(Menu.Trigger, { render: promptButton }), _jsx(Menu.Portal, { container: portalContainer(), children: _jsx(Menu.Positioner, { className: "inspector-popover__positioner", side: "bottom", align: "start", sideOffset: 6, children: _jsxs(Menu.Popup, { className: "inspector-popover__popup copy-prompt__menu", "data-test": "copy-prompt-menu", children: [activeArtifactId ? (_jsxs(_Fragment, { children: [_jsxs(Menu.Item, { className: "copy-prompt__menu-item", "data-test": "copy-iteration-prompt", label: "Copy iteration prompt", onClick: () => void copyIterationPrompt("iteration"), children: [_jsx(IconArtboard, { className: "copy-prompt__menu-icon", size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), _jsxs("span", { className: "copy-prompt__menu-content", children: [_jsx("span", { className: "copy-prompt__menu-title", children: "Copy iteration prompt" }), _jsx("span", { className: "copy-prompt__menu-description", children: "Continue editing this HTML iteration." })] })] }), _jsxs(Menu.Item, { className: "copy-prompt__menu-item", "data-test": "copy-iteration-implementation", label: "Copy prompt for live app", onClick: () => void copyIterationPrompt("application"), children: [_jsx(IconBoltFilled, { className: "copy-prompt__menu-icon copy-prompt__menu-icon--live", size: "var(--icon-size-small)", "aria-hidden": "true" }), _jsxs("span", { className: "copy-prompt__menu-content", children: [_jsx("span", { className: "copy-prompt__menu-title", children: "Copy prompt for live app" }), _jsx("span", { className: "copy-prompt__menu-description", children: "Implement design in real app" })] })] })] })) : (_jsxs(Menu.Item, { className: "copy-prompt__menu-item", "data-test": "copy-style-edit-prompt", label: styleEditLabel, disabled: !canConnect && changeCount === 0, onClick: () => void onClick(), children: [canConnect
328
+ ? _jsx(IconPlugConnected, { className: "copy-prompt__menu-icon", size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" })
329
+ : canSend
330
+ ? _jsx(IconSend, { className: "copy-prompt__menu-icon", size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" })
331
+ : _jsx(IconPencil, { className: "copy-prompt__menu-icon", size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), _jsxs("span", { className: "copy-prompt__menu-content", children: [_jsx("span", { className: "copy-prompt__menu-title", children: styleEditLabel }), _jsx("span", { className: "copy-prompt__menu-description", children: styleEditDescription })] })] })), visibleSketches.length > 0 ? _jsx(Menu.Separator, { className: "copy-prompt__menu-separator" }) : null, visibleSketches.map((item, index) => {
332
+ const busy = item.status === "dispatching" || item.status === "handing-off";
333
+ return (_jsxs("div", { className: "copy-prompt__menu-row", children: [_jsxs(Menu.Item, { className: "copy-prompt__menu-item copy-prompt__menu-item--sketch", "data-test": "copy-sketch", "data-sketch-id": item.document.id, label: `Copy Sketch ${index + 1}`, disabled: busy, onClick: () => void copySketchImageOnRequest(item.document.annotatedImage), children: [_jsx(SketchThumbnail, { item: item }), _jsxs("span", { className: "copy-prompt__menu-content", children: [_jsxs("span", { className: "copy-prompt__menu-title", children: ["Copy Sketch ", index + 1] }), item.document.description ? (_jsx("span", { className: "copy-prompt__menu-description copy-prompt__menu-description--truncate", children: item.document.description })) : null] })] }), _jsx(IconButton, { className: "copy-prompt__menu-delete", variant: "quiet", size: "compact", label: `Delete Sketch ${index + 1}`, "data-test": "copy-sketch-delete", disabled: busy, onClick: () => void deleteSketch(item.document.id), children: _jsx(IconX, { size: "var(--icon-size-small)", "aria-hidden": "true" }) })] }, item.document.id));
334
+ })] }) }) })] }, activeDraftCardId)) : promptButton, statusAction || agentStatus.kind === "connected-not-listening" ? (_jsx(StatusCallout, { className: "copy-prompt__agent-status", tone: agentStatus.tone, "data-test": "agent-connection-status", children: _jsxs("div", { className: "copy-prompt__agent-status-content", children: [_jsx("span", { role: "status", children: agentStatus.label }), statusAction ? (_jsx(Button, { size: "compact", variant: "quiet", "data-test": "agent-status-action", "data-action": statusAction.kind, type: "button", onClick: () => void handleAgentStatusAction(), children: statusAction.label })) : null] }) })) : null, showImplemented ? (_jsxs("p", { className: "copy-prompt__hint copy-prompt__hint--centered copy-prompt__hint--implemented", "data-test": "handoff-implemented-hint", role: "status", children: ["Changes implemented.", remainingCount > 0 ? (_jsxs(_Fragment, { children: [" ", _jsx("button", { type: "button", className: "copy-prompt__hint-action", "data-test": "handoff-clear-remaining", onClick: clearRemaining, children: "Clear stale edits" })] })) : null] })) : null, saveMessage ? (_jsx("p", { className: "copy-prompt__hint copy-prompt__hint--centered", "data-test": "iteration-save-hint", role: "status", children: saveMessage })) : null, sketchFallback ? (_jsxs(StatusCallout, { className: "copy-prompt__sketch-fallback", tone: "warning", "data-test": "sketch-dispatch-error", children: [_jsx("span", { children: sketchFallback.error }), _jsx(Button, { size: "compact", variant: "secondary", type: "button", "data-test": "sketch-copy-fallback", onClick: () => {
335
+ void copyHandoff(sketchFallback.handoff).then(() => {
336
+ setSketchFallback(null);
337
+ }).catch(() => undefined);
332
338
  }, children: "Copy prompt" })] })) : null, _jsx(SettingsDialog, { open: settingsOpen, initialSection: settingsSection, value: customInstructions, onValueChange: handleCustomInstructionsChange, onOpenChange: setSettingsOpen, projectId: runtimeConfig.projectId, origin: window.location.origin, snapshot: agent, onConnect: () => agentClient.connect(), onTakeOver: () => agentClient.takeOver(), onDisconnect: () => agentClient.disconnect(), onCheckAgain: () => agentClient.checkConnection() })] }));
333
339
  }
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { IconArtboard, IconBoltFilled, IconSparkles } from "@tabler/icons-react";
3
2
  import { useCanvasPresentation } from "../canvas/viewStore.js";
4
3
  import { Disclosure } from "../ui/Disclosure.js";
5
- import gridIllustration from "../ui/assets/grid.svg";
4
+ import { CANVAS_ILLUSTRATION_SVG } from "../ui/assets/canvasIllustration.js";
5
+ import { GRID_ILLUSTRATION_SVG } from "../ui/assets/gridIllustration.js";
6
6
  import { getPlatformModifierKey, isMacPlatform } from "./shortcuts.js";
7
7
  export function EmptyState() {
8
8
  const presentation = useCanvasPresentation();
@@ -12,5 +12,5 @@ export function EmptyState() {
12
12
  const modifierName = macPlatform ? "Command" : "Control";
13
13
  const optionKey = macPlatform ? "⌥" : "Alt";
14
14
  const optionName = macPlatform ? "Option" : "Alt";
15
- return (_jsxs("div", { className: `empty-state${canvas ? " empty-state--canvas" : ""}`, "data-test": "empty-state", children: [canvas ? (_jsxs("div", { className: "empty-state__canvas", "data-test": "canvas-intro", children: [_jsx("h2", { className: "empty-state__title", children: "Using the canvas" }), _jsxs("p", { children: [_jsx("span", { className: "empty-state__live-badge", children: _jsx(IconBoltFilled, { "aria-hidden": "true" }) }), _jsxs("span", { children: [_jsx("strong", { children: "Live app" }), "A view of your real running app"] })] }), _jsxs("p", { children: [_jsx(IconArtboard, { "aria-hidden": "true" }), _jsxs("span", { children: [_jsx("strong", { children: "HTML iterations" }), "Unlinked from live app for isolated changes. Ask your agent to implement in live app once ready."] })] }), _jsxs("p", { children: [_jsx(IconSparkles, { "aria-hidden": "true" }), _jsxs("span", { children: [_jsx("strong", { children: "Agent with MCP" }), "Ask your agent to: lay out flows, show page states and create iterations."] })] })] })) : (_jsxs(_Fragment, { children: [_jsx("img", { className: "empty-state__icon", src: gridIllustration, alt: "", "aria-hidden": "true" }), _jsx("h2", { className: "empty-state__title", children: "Select an element to edit" })] })), _jsx(Disclosure, { className: "empty-state__shortcuts", title: "Keyboard shortcuts", triggerDataTest: "empty-state-shortcuts-toggle", defaultOpen: !canvas, children: _jsxs("ul", { className: "empty-state__shortcut-list", children: [_jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Nudge" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": "Arrow keys", children: [_jsx("kbd", { children: "\u2191" }), _jsx("kbd", { children: "\u2193" }), _jsx("kbd", { children: "\u2190" }), _jsx("kbd", { children: "\u2192" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Big Nudge (8px)" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": "Shift plus arrow keys", children: [_jsx("kbd", { children: "Shift" }), _jsx("span", { "aria-hidden": "true", children: "+" }), _jsx("kbd", { children: "Arrow" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Select deeper" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": `${modifierName} plus click`, children: [_jsx("kbd", { children: modifierKey }), _jsx("span", { "aria-hidden": "true", children: "+" }), _jsx("kbd", { children: "Click" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Measure" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": `${optionName} plus hover`, children: [_jsx("kbd", { children: optionKey }), _jsx("span", { "aria-hidden": "true", children: "+" }), _jsx("kbd", { children: "Hover" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Hide UI" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": `${modifierName} plus backslash`, children: [_jsx("kbd", { children: modifierKey }), _jsx("span", { "aria-hidden": "true", children: "+" }), _jsx("kbd", { children: "\\" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Hold to view original" }), _jsx("span", { className: "empty-state__shortcut-keys", "aria-label": "Backslash", children: _jsx("kbd", { children: "\\" }) })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Undo" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": `${modifierName} plus Z`, children: [_jsx("kbd", { children: modifierKey }), _jsx("span", { "aria-hidden": "true", children: "+" }), _jsx("kbd", { children: "Z" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Deselect" }), _jsx("span", { className: "empty-state__shortcut-keys", children: _jsx("kbd", { children: "Esc" }) })] })] }) }, presentation)] }));
15
+ return (_jsxs("div", { className: "empty-state", "data-test": "empty-state", children: [canvas ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "empty-state__icon", "aria-hidden": "true", dangerouslySetInnerHTML: { __html: CANVAS_ILLUSTRATION_SVG } }), _jsxs("p", { className: "empty-state__hint", "data-test": "canvas-intro", children: ["Hold ", _jsx("kbd", { children: "A" }), " to click links and open them as new pages on the canvas."] })] })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "empty-state__icon", "aria-hidden": "true", dangerouslySetInnerHTML: { __html: GRID_ILLUSTRATION_SVG } }), _jsx("h2", { className: "empty-state__title", children: "Select an element to edit" })] })), _jsx(Disclosure, { className: "empty-state__shortcuts", title: "Keyboard shortcuts", triggerDataTest: "empty-state-shortcuts-toggle", defaultOpen: true, children: _jsxs("ul", { className: "empty-state__shortcut-list", children: [_jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Nudge" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": "Arrow keys", children: [_jsx("kbd", { children: "\u2191" }), _jsx("kbd", { children: "\u2193" }), _jsx("kbd", { children: "\u2190" }), _jsx("kbd", { children: "\u2192" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Big Nudge (8px)" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": "Shift plus arrow keys", children: [_jsx("kbd", { children: "Shift" }), _jsx("span", { "aria-hidden": "true", children: "+" }), _jsx("kbd", { children: "Arrow" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Select deeper" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": `${modifierName} plus click`, children: [_jsx("kbd", { children: modifierKey }), _jsx("span", { "aria-hidden": "true", children: "+" }), _jsx("kbd", { children: "Click" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Measure" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": `${optionName} plus hover`, children: [_jsx("kbd", { children: optionKey }), _jsx("span", { "aria-hidden": "true", children: "+" }), _jsx("kbd", { children: "Hover" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Hide UI" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": `${modifierName} plus backslash`, children: [_jsx("kbd", { children: modifierKey }), _jsx("span", { "aria-hidden": "true", children: "+" }), _jsx("kbd", { children: "\\" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Hold to view original" }), _jsx("span", { className: "empty-state__shortcut-keys", "aria-label": "Backslash", children: _jsx("kbd", { children: "\\" }) })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Undo" }), _jsxs("span", { className: "empty-state__shortcut-keys", "aria-label": `${modifierName} plus Z`, children: [_jsx("kbd", { children: modifierKey }), _jsx("span", { "aria-hidden": "true", children: "+" }), _jsx("kbd", { children: "Z" })] })] }), _jsxs("li", { className: "empty-state__shortcut", "data-test": "empty-state-shortcut", children: [_jsx("span", { children: "Deselect" }), _jsx("span", { className: "empty-state__shortcut-keys", children: _jsx("kbd", { children: "Esc" }) })] })] }) }, presentation)] }));
16
16
  }
@@ -1,10 +1,7 @@
1
1
  import type { ReactElement } from "react";
2
- import { toggleInspector, setInspectorOpen } from "./openStore.js";
3
2
  declare global {
4
3
  interface Window {
5
4
  MutationObserver: typeof MutationObserver;
6
5
  }
7
6
  }
8
- export { toggleInspector, setInspectorOpen };
9
- export type { SelectedElement } from "../selection/selectionStore.js";
10
7
  export declare function InspectorShell(): ReactElement;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useEffect, useMemo, useState } from "react";
2
+ import { useEffect, useMemo, useState, useSyncExternalStore } from "react";
3
3
  import { IconLayoutSidebarRight } from "@tabler/icons-react";
4
- import { useInspectorOpen, toggleInspector, setInspectorOpen } from "./openStore.js";
4
+ import { useInspectorOpen, setInspectorOpen } from "./openStore.js";
5
5
  import { useSelectedElement, useSelectedElements, setSelectedElement, removeSelectedElement, } from "../selection/selectionStore.js";
6
6
  import { findTokenRow } from "../styleEditors/rowLookup.js";
7
7
  import { useBrowserCssInspection } from "../inspection/useBrowserCssInspection.js";
@@ -17,7 +17,7 @@ import { AppearanceSection } from "../styleEditors/AppearanceSection.js";
17
17
  import { BoxShadowEditor } from "../styleEditors/BoxShadowEditor.js";
18
18
  import { LayoutSection } from "../styleEditors/LayoutSection.js";
19
19
  import { ChangesLog } from "./ChangesLog.js";
20
- import { discardChangesForInstanceOverride, undo, redo } from "../changes/changesLog.js";
20
+ import { discardChangesForInstanceOverride, undo, redo } from "../drafts/store.js";
21
21
  import { countSourceSiteMatches, getEditScope, relinkElement, sourceSiteSelector, unlinkElement } from "../selection/editScope.js";
22
22
  import { canEditStyles } from "../tokens/editActions.js";
23
23
  import { Button } from "../ui/Button.js";
@@ -27,6 +27,7 @@ import { StatusCallout } from "../ui/StatusCallout.js";
27
27
  import { IconButton } from "../ui/IconButton.js";
28
28
  import { UI_STYLES } from "../ui/styles.js";
29
29
  import { getActiveStyleState, setActiveStyleState } from "./styleState.js";
30
+ import { useInteractionStatePreview } from "./interactionStatePreview.js";
30
31
  import { getInspectorToggleShortcutLabel, isEditableEvent } from "./shortcuts.js";
31
32
  import { formatInspectorLabel } from "../ui/labels.js";
32
33
  import { FieldRow } from "../ui/FieldRow.js";
@@ -34,6 +35,8 @@ import { Select } from "../ui/Select.js";
34
35
  import { clearSelectedFrameChanges } from "../canvas/sessionStore.js";
35
36
  import { useFocusedCardId, useSelectedCardId, } from "../canvas/canvasStore.js";
36
37
  import { getActiveCanvasFrame } from "../canvas/activeCanvasDocument.js";
38
+ import { canvasFrameHost } from "../canvas/canvasFrame.js";
39
+ import { getFrameRegistryVersion, subscribeFrameRegistry } from "../canvas/projection.js";
37
40
  import { getElementWindow } from "../runtime/domRealm.js";
38
41
  import { deleteElement, nudgeElement } from "../overlay/structuralGestures.js";
39
42
  import { AtRuleContextProvider } from "../ui/AtRuleContext.js";
@@ -45,10 +48,11 @@ import { EmptyState } from "./EmptyState.js";
45
48
  import { createStyleSelection } from "../selection/styleSelection.js";
46
49
  import { intersectTokenEntries } from "../inspection/selectionProperty.js";
47
50
  import { isNudgeUiDev } from "../runtime/devFlag.js";
48
- import { isDemoRuntime } from "../runtime/runtimeConfig.js";
51
+ import { isDemoRuntime, isNudgeUiFeatureEnabled } from "../runtime/runtimeConfig.js";
49
52
  import { SketchWorkspace } from "../sketch/SketchWorkspace.js";
50
53
  import { useSketchInteractionActive } from "../sketch/interaction.js";
51
54
  import { Tooltip } from "../ui/Tooltip.js";
55
+ import { InspectorStyle } from "../ui/InspectorStyle.js";
52
56
  function findFirstTokenRow(rows, properties) {
53
57
  for (const property of properties) {
54
58
  const row = findTokenRow(rows, property);
@@ -62,7 +66,6 @@ function findFirstTokenRow(rows, properties) {
62
66
  }
63
67
  return null;
64
68
  }
65
- export { toggleInspector, setInspectorOpen };
66
69
  function nodeMatchesSelector(node, selector) {
67
70
  if (!selector || node.nodeType !== node.ELEMENT_NODE)
68
71
  return false;
@@ -88,11 +91,14 @@ function scopeMutationAffectsSelection(records, selected) {
88
91
  export function InspectorShell() {
89
92
  const isOpen = useInspectorOpen();
90
93
  const runtimeConfig = useNudgeUiRuntimeConfig();
91
- const sketchEnabled = isNudgeUiDev() && !isDemoRuntime();
94
+ const sketchEnabled = isNudgeUiDev()
95
+ && !runtimeConfig.inspectionUnavailableReason
96
+ && (!isDemoRuntime() || isNudgeUiFeatureEnabled(runtimeConfig.features, "sketch"));
92
97
  const sketchActive = useSketchInteractionActive();
93
98
  const selectedCardId = useSelectedCardId();
94
99
  const focusedCardId = useFocusedCardId();
95
- const sketchHost = selectedCardId || focusedCardId ? getActiveCanvasFrame() : null;
100
+ useSyncExternalStore(subscribeFrameRegistry, getFrameRegistryVersion);
101
+ const sketchHost = selectedCardId || focusedCardId ? canvasFrameHost(getActiveCanvasFrame()) : null;
96
102
  const selected = useSelectedElement();
97
103
  const selectedElements = useSelectedElements();
98
104
  const inlineTextFeedback = getInlineTextFeedback(useInlineTextDiagnostic());
@@ -100,6 +106,7 @@ export function InspectorShell() {
100
106
  const [settingsSection, setSettingsSection] = useState("instructions");
101
107
  const [scopeRevision, refreshScope] = useState(0);
102
108
  const [styleState, setStyleState] = useState(getActiveStyleState());
109
+ useInteractionStatePreview(selectedElements.length === 1 ? selectedElements[0].domElement : null, styleState);
103
110
  const cssInspection = useBrowserCssInspection(selectedElements, styleState);
104
111
  const isMultiSelection = selectedElements.length > 1;
105
112
  useEffect(() => {
@@ -144,7 +151,7 @@ export function InspectorShell() {
144
151
  return () => observers.forEach((observer) => observer.disconnect());
145
152
  }, [selectedElements, scopeRevision]);
146
153
  useEffect(() => {
147
- if (sketchActive)
154
+ if (sketchActive || runtimeConfig.inspectionUnavailableReason)
148
155
  return;
149
156
  function onKeydown(event) {
150
157
  if (isInlineTextEditingActive())
@@ -197,7 +204,7 @@ export function InspectorShell() {
197
204
  }
198
205
  window.addEventListener("keydown", onKeydown);
199
206
  return () => window.removeEventListener("keydown", onKeydown);
200
- }, [isMultiSelection, selected, sketchActive]);
207
+ }, [isMultiSelection, selected, sketchActive, runtimeConfig.inspectionUnavailableReason]);
201
208
  const inspectionSnapshot = cssInspection.element;
202
209
  const styleSelection = useMemo(() => createStyleSelection(selectedElements, cssInspection.elements, selected), [cssInspection.elements, selected, selectedElements]);
203
210
  const selectionEditable = useMemo(() => styleSelection ? canEditStyles(styleSelection.target) : false, [scopeRevision, styleSelection]);
@@ -205,7 +212,7 @@ export function InspectorShell() {
205
212
  const tokenRows = useMemo(() => styleSelection ? [...styleSelection.primaryRows] : [], [styleSelection]);
206
213
  const availableInteractionStates = inspectionSnapshot?.availableStates ?? [];
207
214
  const showText = selectedElements.length > 0 && selectedElements.every((element, index) => isTextRelevant(element.domElement, cssInspection.elements[index]?.properties ?? []));
208
- const showInteractionState = !isMultiSelection && availableInteractionStates.length > 2;
215
+ const showInteractionState = !isMultiSelection && availableInteractionStates.length > 1;
209
216
  const paintedBackgroundRow = findFirstTokenRow(tokenRows, ["background-color", "background"]);
210
217
  const backgroundTokenRow = useMemo(() => {
211
218
  if (!selected)
@@ -230,12 +237,13 @@ export function InspectorShell() {
230
237
  setSettingsOpen(true);
231
238
  }
232
239
  function clearInspectorSession() {
233
- clearSelectedFrameChanges();
240
+ // Sketch persistence failures are reported by the sketch store in the panel.
241
+ void clearSelectedFrameChanges().catch(() => undefined);
234
242
  }
235
- return (_jsxs(_Fragment, { children: [_jsx("style", { "data-test": "inspector-styles", children: UI_STYLES }), _jsxs("div", { className: "panel", "data-open": isOpen ? "true" : "false", children: [_jsxs("div", { className: "panel__tabs", "aria-label": "Inspector controls", children: [_jsxs("div", { className: "panel__header-row", "data-test": "inspect-tab", children: [_jsx(Tooltip, { content: "Hide inspector", shortcut: getInspectorToggleShortcutLabel(), stableTrigger: true, children: _jsx(IconButton, { variant: "quiet", label: "Collapse inspector", "data-test": "collapse-inspector", disabled: sketchActive, style: { marginLeft: "calc(var(--space-8) * -1)" }, onClick: () => {
243
+ return (_jsxs(_Fragment, { children: [_jsx(InspectorStyle, { testId: "inspector-styles", css: UI_STYLES }), _jsxs("div", { className: "panel", "data-open": isOpen ? "true" : "false", children: [_jsxs("div", { className: "panel__tabs", "aria-label": "Inspector controls", children: [_jsxs("div", { className: "panel__header-row", "data-test": "inspect-tab", children: [_jsx(Tooltip, { content: "Hide inspector", shortcut: getInspectorToggleShortcutLabel(), stableTrigger: true, children: _jsx(IconButton, { variant: "quiet", label: "Collapse inspector", "data-test": "collapse-inspector", disabled: sketchActive, style: { marginLeft: "calc(var(--space-8) * -1)" }, onClick: () => {
236
244
  cancelInlineTextEdit();
237
245
  setInspectorOpen(false);
238
- }, children: _jsx(IconLayoutSidebarRight, { size: "var(--icon-size-small)", stroke: 1.8, "aria-hidden": "true" }) }) }), _jsxs("div", { className: "panel__header-actions", children: [_jsx(PeekOriginalButton, {}), _jsx(AgentStatusButton, { onOpenSettings: openSettings })] })] }), _jsx("div", { className: "panel__copy-row", children: _jsx(CopyPromptButton, { settingsOpen: settingsOpen, settingsSection: settingsSection, onOpenSettings: openSettings, onSettingsOpenChange: setSettingsOpen }) })] }), _jsxs("div", { className: "panel__body", children: [inlineTextFeedback ? (_jsx(StatusCallout, { tone: "danger", className: "inline-text-diagnostic", "data-test": "inline-text-diagnostic", role: "status", "aria-live": "polite", "aria-atomic": "true", children: _jsx("span", { children: inlineTextFeedback.message }) })) : null, selected ? (_jsxs(_Fragment, { children: [isMultiSelection || showInteractionState || hasEditScopeCallout ? (_jsxs("div", { className: `selection${hasEditScopeCallout ? "" : " selection--without-scope-callout"}`, "data-test": "selection", "data-selected-cid": selected.cid, "data-selected-src": selected.src, "data-selected-count": selectedElements.length, children: [isMultiSelection ? (_jsx("div", { className: "selection__summary", "data-test": "multi-selection-summary", children: _jsxs("span", { className: "selection__count", children: [selectedElements.length, " elements selected"] }) })) : null, hasEditScopeCallout ? (_jsx(StatusCallout, { tone: editScope === "rendered-instance" ? "neutral" : "accent", "data-test": "edit-scope", "data-lost": "false", children: editScope === "rendered-instance" ? (_jsxs("div", { className: "scope__unlinked", children: [_jsx("span", { children: "Element unlinked" }), _jsx(Button, { size: "compact", className: "scope__action", "data-test": "relink-element", onClick: () => {
246
+ }, children: _jsx(IconLayoutSidebarRight, { size: "var(--icon-size-small)", stroke: 1.8, "aria-hidden": "true" }) }) }), _jsxs("div", { className: "panel__header-actions", children: [_jsx(PeekOriginalButton, {}), _jsx(AgentStatusButton, { onOpenSettings: openSettings })] })] }), _jsx("div", { className: "panel__copy-row", children: _jsx(CopyPromptButton, { settingsOpen: settingsOpen, settingsSection: settingsSection, onOpenSettings: openSettings, onSettingsOpenChange: setSettingsOpen }) })] }), _jsxs("div", { className: "panel__body", children: [inlineTextFeedback ? (_jsx(StatusCallout, { tone: "danger", className: "inline-text-diagnostic", "data-test": "inline-text-diagnostic", role: "status", "aria-live": "polite", "aria-atomic": "true", children: _jsx("span", { children: inlineTextFeedback.message }) })) : null, runtimeConfig.inspectionUnavailableReason ? (_jsxs(StatusCallout, { tone: "danger", "data-test": "page-inspection-error", role: "status", children: ["Can\u2019t load Nudge on this page due to ", runtimeConfig.inspectionUnavailableReason, "."] })) : selected ? (_jsxs(_Fragment, { children: [showInteractionState || hasEditScopeCallout ? (_jsxs("div", { className: `selection${hasEditScopeCallout ? "" : " selection--without-scope-callout"}`, "data-test": "selection", "data-selected-cid": selected.cid, "data-selected-src": selected.src, "data-selected-count": selectedElements.length, children: [hasEditScopeCallout ? (_jsx(StatusCallout, { tone: editScope === "rendered-instance" ? "neutral" : "accent", "data-test": "edit-scope", "data-lost": "false", children: editScope === "rendered-instance" ? (_jsxs("div", { className: "scope__unlinked", children: [_jsx("span", { children: "Element unlinked" }), _jsx(Button, { size: "compact", className: "scope__action", "data-test": "relink-element", onClick: () => {
239
247
  const overrideId = relinkElement(selected.domElement);
240
248
  if (overrideId)
241
249
  discardChangesForInstanceOverride(overrideId);
@@ -3,11 +3,11 @@ import { useEffect, useSyncExternalStore } from "react";
3
3
  import { IconButton } from "../ui/IconButton.js";
4
4
  import { Tooltip } from "../ui/Tooltip.js";
5
5
  import { PeekOriginalIcon } from "./PeekOriginalIcon.js";
6
- import { draftChangeStore } from "../changes/draftChanges.js";
6
+ import { getActiveDraftChanges, subscribeActiveDraftChanges } from "../drafts/store.js";
7
7
  import { setOriginalPreviewActive, useOriginalPreviewActive, } from "./originalPreview.js";
8
8
  function useDraftChangeCount() {
9
- return useSyncExternalStore(draftChangeStore.subscribe, () => {
10
- const snapshot = draftChangeStore.getSnapshot();
9
+ return useSyncExternalStore(subscribeActiveDraftChanges, () => {
10
+ const snapshot = getActiveDraftChanges();
11
11
  return snapshot.changes.length + snapshot.structuralChanges.length;
12
12
  }, () => 0);
13
13
  }
@@ -0,0 +1,9 @@
1
+ import { type InteractionState } from "./styleState.js";
2
+ /** Matches native interaction states and the Inspector's temporary CSS state. */
3
+ export declare function selectorForInteractionStatePreview(selector: string): string;
4
+ /**
5
+ * Projects CSS interaction states into the selected element's document.
6
+ * This previews styles without dispatching events or changing application state.
7
+ */
8
+ export declare function startInteractionStatePreview(element: HTMLElement, state: InteractionState): () => void;
9
+ export declare function useInteractionStatePreview(element: HTMLElement | null, state: InteractionState): void;