nudge-ui 0.2.1 → 0.2.3

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 (258) hide show
  1. package/README.md +164 -46
  2. package/dist/client.mjs +252 -54
  3. package/dist/css/value-semantics/colorSemantics.d.ts +4 -0
  4. package/dist/css/value-semantics/colorSemantics.js +17 -0
  5. package/dist/hosts/astro/astroRuntimeConfig.js +1 -0
  6. package/dist/hosts/astro/clientTransport.js +41 -32
  7. package/dist/hosts/astro/integration.d.ts +2 -2
  8. package/dist/hosts/astro/integration.js +9 -4
  9. package/dist/hosts/astro/markdownIdentity.d.ts +28 -0
  10. package/dist/hosts/astro/markdownIdentity.js +81 -0
  11. package/dist/hosts/environment.d.ts +15 -0
  12. package/dist/hosts/environment.js +16 -0
  13. package/dist/hosts/next/manifest.js +1 -1
  14. package/dist/hosts/next/sidecar.js +12 -2
  15. package/dist/hosts/next/wrapper.d.ts +2 -0
  16. package/dist/hosts/next/wrapper.js +2 -1
  17. package/dist/hosts/projectBridge.d.ts +1 -0
  18. package/dist/hosts/projectBridge.js +1 -0
  19. package/dist/hosts/static/manifest.js +3 -1
  20. package/dist/hosts/static/server.js +4 -0
  21. package/dist/hosts/vite/vite.d.ts +4 -0
  22. package/dist/hosts/vite/vite.js +28 -5
  23. package/dist/inspector/agent/McpConnectionDialog.d.ts +3 -2
  24. package/dist/inspector/agent/McpConnectionDialog.js +23 -22
  25. package/dist/inspector/agent/activity.d.ts +18 -0
  26. package/dist/inspector/agent/activity.js +70 -0
  27. package/dist/inspector/agent/client.d.ts +8 -0
  28. package/dist/inspector/agent/client.js +65 -5
  29. package/dist/inspector/agent/connectionStatus.d.ts +3 -3
  30. package/dist/inspector/agent/connectionStatus.js +9 -2
  31. package/dist/inspector/agent/httpTransport.d.ts +6 -0
  32. package/dist/inspector/agent/httpTransport.js +50 -3
  33. package/dist/inspector/agent/protocol.d.ts +9 -3
  34. package/dist/inspector/agent/protocol.js +1 -1
  35. package/dist/inspector/agent/verification.d.ts +11 -1
  36. package/dist/inspector/agent/verification.js +53 -25
  37. package/dist/inspector/canvas/AgentActivityOverlay.d.ts +13 -0
  38. package/dist/inspector/canvas/AgentActivityOverlay.js +111 -0
  39. package/dist/inspector/canvas/CanvasCard.d.ts +9 -2
  40. package/dist/inspector/canvas/CanvasCard.js +133 -38
  41. package/dist/inspector/canvas/CanvasElementOverlay.js +200 -22
  42. package/dist/inspector/canvas/CanvasToolIcons.d.ts +10 -0
  43. package/dist/inspector/canvas/CanvasToolIcons.js +20 -0
  44. package/dist/inspector/canvas/CanvasToolbar.js +8 -4
  45. package/dist/inspector/canvas/CanvasWorkspace.js +243 -56
  46. package/dist/inspector/canvas/StaleChangeIndicator.js +3 -13
  47. package/dist/inspector/canvas/agentPresentation.d.ts +8 -8
  48. package/dist/inspector/canvas/agentPresentation.js +64 -52
  49. package/dist/inspector/canvas/canvasGestures.d.ts +1 -1
  50. package/dist/inspector/canvas/canvasGestures.js +1 -1
  51. package/dist/inspector/canvas/canvasStore.d.ts +46 -82
  52. package/dist/inspector/canvas/canvasStore.js +251 -284
  53. package/dist/inspector/canvas/frameContent.d.ts +21 -0
  54. package/dist/inspector/canvas/frameContent.js +44 -0
  55. package/dist/inspector/canvas/frameProtocol.d.ts +34 -4
  56. package/dist/inspector/canvas/frameProtocol.js +9 -2
  57. package/dist/inspector/canvas/keyboardShortcuts.d.ts +4 -1
  58. package/dist/inspector/canvas/keyboardShortcuts.js +5 -3
  59. package/dist/inspector/canvas/layout.d.ts +52 -0
  60. package/dist/inspector/canvas/layout.js +106 -0
  61. package/dist/inspector/canvas/linkEligibility.d.ts +0 -5
  62. package/dist/inspector/canvas/linkEligibility.js +0 -29
  63. package/dist/inspector/canvas/projection.d.ts +15 -5
  64. package/dist/inspector/canvas/projection.js +69 -13
  65. package/dist/inspector/canvas/rendererBootstrap.js +45 -4
  66. package/dist/inspector/canvas/rendererElementSelector.d.ts +1 -1
  67. package/dist/inspector/canvas/rendererElementSelector.js +102 -45
  68. package/dist/inspector/canvas/rendererStylesheet.js +2 -2
  69. package/dist/inspector/canvas/resizeHandleScale.js +1 -1
  70. package/dist/inspector/canvas/sessionStore.d.ts +11 -26
  71. package/dist/inspector/canvas/sessionStore.js +43 -183
  72. package/dist/inspector/canvas/staleChangeDetector.js +9 -3
  73. package/dist/inspector/canvas/useCanvasLayoutAnimation.d.ts +5 -0
  74. package/dist/inspector/canvas/useCanvasLayoutAnimation.js +107 -0
  75. package/dist/inspector/canvas/viewStore.d.ts +38 -0
  76. package/dist/inspector/canvas/viewStore.js +104 -0
  77. package/dist/inspector/canvas/wheelPan.d.ts +8 -0
  78. package/dist/inspector/canvas/wheelPan.js +8 -0
  79. package/dist/inspector/changes/changesLog.d.ts +6 -5
  80. package/dist/inspector/changes/changesLog.js +40 -32
  81. package/dist/inspector/changes/draftChanges.d.ts +56 -0
  82. package/dist/inspector/changes/draftChanges.js +300 -0
  83. package/dist/inspector/changes/previewDiagnostics.d.ts +4 -2
  84. package/dist/inspector/changes/previewDiagnostics.js +11 -25
  85. package/dist/inspector/clientManifest.d.ts +3 -1
  86. package/dist/inspector/clientManifest.js +1 -0
  87. package/dist/inspector/comments/CommentsOverlay.d.ts +2 -0
  88. package/dist/inspector/comments/CommentsOverlay.js +250 -0
  89. package/dist/inspector/comments/element.d.ts +6 -0
  90. package/dist/inspector/comments/element.js +47 -0
  91. package/dist/inspector/comments/store.d.ts +29 -0
  92. package/dist/inspector/comments/store.js +121 -0
  93. package/dist/inspector/comments/verification.d.ts +5 -0
  94. package/dist/inspector/comments/verification.js +52 -0
  95. package/dist/inspector/drafts/model.d.ts +35 -0
  96. package/dist/inspector/drafts/model.js +45 -0
  97. package/dist/inspector/drafts/store.d.ts +28 -0
  98. package/dist/inspector/drafts/store.js +231 -0
  99. package/dist/inspector/index.js +26 -35
  100. package/dist/inspector/inline-text/inlineTextEditor.js +7 -0
  101. package/dist/inspector/inspection/useBrowserCssInspection.js +15 -1
  102. package/dist/inspector/iterations/capture.d.ts +2 -0
  103. package/dist/inspector/iterations/capture.js +173 -0
  104. package/dist/inspector/iterations/client.d.ts +7 -0
  105. package/dist/inspector/iterations/client.js +52 -0
  106. package/dist/inspector/iterations/coordinator.d.ts +15 -0
  107. package/dist/inspector/iterations/coordinator.js +130 -0
  108. package/dist/inspector/iterations/prompt.d.ts +3 -0
  109. package/dist/inspector/iterations/prompt.js +26 -0
  110. package/dist/inspector/overlay/DomNavigator.d.ts +10 -0
  111. package/dist/inspector/overlay/DomNavigator.js +46 -0
  112. package/dist/inspector/overlay/InspectorOverlay.js +6 -2
  113. package/dist/inspector/overlay/clickPolicy.d.ts +18 -2
  114. package/dist/inspector/overlay/clickPolicy.js +34 -3
  115. package/dist/inspector/overlay/elementSelector.d.ts +1 -1
  116. package/dist/inspector/overlay/elementSelector.js +18 -7
  117. package/dist/inspector/overlay/interactionStyles.js +3 -1
  118. package/dist/inspector/overlay/spacingGestures.d.ts +15 -3
  119. package/dist/inspector/overlay/spacingGestures.js +88 -13
  120. package/dist/inspector/projection/{workspaceProjection.d.ts → draftProjection.d.ts} +6 -6
  121. package/dist/inspector/projection/{workspaceProjection.js → draftProjection.js} +4 -4
  122. package/dist/inspector/projection/renderedInstance.d.ts +2 -1
  123. package/dist/inspector/projection/renderedInstance.js +9 -5
  124. package/dist/inspector/projection/structuralProjection.d.ts +2 -1
  125. package/dist/inspector/projection/structuralProjection.js +19 -15
  126. package/dist/inspector/projection/textProjection.d.ts +2 -1
  127. package/dist/inspector/projection/textProjection.js +8 -4
  128. package/dist/inspector/prompt/PromptSettingsDialog.js +1 -5
  129. package/dist/inspector/prompt/clipboardHandoff.d.ts +10 -18
  130. package/dist/inspector/prompt/clipboardHandoff.js +92 -143
  131. package/dist/inspector/prompt/generatePrompt.d.ts +4 -1
  132. package/dist/inspector/prompt/generatePrompt.js +17 -16
  133. package/dist/inspector/runtime/runtimeConfig.d.ts +10 -1
  134. package/dist/inspector/runtime/runtimeConfig.js +24 -0
  135. package/dist/inspector/selection/hierarchy.d.ts +6 -0
  136. package/dist/inspector/selection/hierarchy.js +8 -0
  137. package/dist/inspector/settings/SettingsDialog.d.ts +1 -1
  138. package/dist/inspector/settings/SettingsDialog.js +22 -9
  139. package/dist/inspector/shell/AgentStatusButton.d.ts +11 -0
  140. package/dist/inspector/shell/AgentStatusButton.js +36 -0
  141. package/dist/inspector/shell/AppShell.js +4 -2
  142. package/dist/inspector/shell/ChangesLog.js +47 -27
  143. package/dist/inspector/shell/CopyPromptButton.js +146 -90
  144. package/dist/inspector/shell/EmptyState.js +9 -8
  145. package/dist/inspector/shell/InspectorShell.js +14 -25
  146. package/dist/inspector/shell/PeekOriginalButton.js +24 -23
  147. package/dist/inspector/shell/originalPreview.js +5 -5
  148. package/dist/inspector/shell/shortcuts.d.ts +3 -0
  149. package/dist/inspector/shell/shortcuts.js +11 -0
  150. package/dist/inspector/sketch/SketchEditor.js +14 -14
  151. package/dist/inspector/sketch/SketchEntryButton.js +1 -1
  152. package/dist/inspector/sketch/SketchFrameOverlay.d.ts +3 -1
  153. package/dist/inspector/sketch/SketchFrameOverlay.js +11 -8
  154. package/dist/inspector/sketch/SketchLayersPanel.js +13 -5
  155. package/dist/inspector/sketch/SketchOverlay.js +7 -7
  156. package/dist/inspector/sketch/SketchWorkspace.js +18 -12
  157. package/dist/inspector/sketch/interaction.d.ts +1 -0
  158. package/dist/inspector/sketch/interaction.js +8 -4
  159. package/dist/inspector/sketch/model.d.ts +5 -0
  160. package/dist/inspector/sketch/model.js +6 -2
  161. package/dist/inspector/sketch/raster.d.ts +1 -2
  162. package/dist/inspector/sketch/raster.js +68 -4
  163. package/dist/inspector/sketch/store.js +48 -23
  164. package/dist/inspector/styleEditors/BackgroundEditor.d.ts +4 -0
  165. package/dist/inspector/styleEditors/BackgroundEditor.js +195 -0
  166. package/dist/inspector/styleEditors/BorderEditor.js +49 -78
  167. package/dist/inspector/styleEditors/BorderRadiusEditor.js +6 -1
  168. package/dist/inspector/styleEditors/BoxShadowEditor.d.ts +1 -2
  169. package/dist/inspector/styleEditors/BoxShadowEditor.js +132 -4
  170. package/dist/inspector/styleEditors/ColorPicker.d.ts +5 -1
  171. package/dist/inspector/styleEditors/ColorPicker.js +10 -4
  172. package/dist/inspector/styleEditors/GapField.js +3 -5
  173. package/dist/inspector/styleEditors/GridChildSection.d.ts +1 -1
  174. package/dist/inspector/styleEditors/GridChildSection.js +18 -9
  175. package/dist/inspector/styleEditors/GridPicker.d.ts +1 -1
  176. package/dist/inspector/styleEditors/GridPicker.js +8 -2
  177. package/dist/inspector/styleEditors/GridSection.js +1 -1
  178. package/dist/inspector/styleEditors/GridValueField.js +19 -14
  179. package/dist/inspector/styleEditors/ImageBackgroundEditor.d.ts +18 -0
  180. package/dist/inspector/styleEditors/ImageBackgroundEditor.js +118 -0
  181. package/dist/inspector/styleEditors/LayoutBlockedIndicator.d.ts +2 -2
  182. package/dist/inspector/styleEditors/LayoutBlockedIndicator.js +3 -3
  183. package/dist/inspector/styleEditors/LayoutComboField.js +6 -4
  184. package/dist/inspector/styleEditors/LayoutDropdown.js +6 -3
  185. package/dist/inspector/styleEditors/LayoutSection.js +32 -11
  186. package/dist/inspector/styleEditors/SpacingBox.js +16 -9
  187. package/dist/inspector/styleEditors/Typography.js +11 -3
  188. package/dist/inspector/styleEditors/backgroundLayers.d.ts +24 -0
  189. package/dist/inspector/styleEditors/backgroundLayers.js +51 -0
  190. package/dist/inspector/styleEditors/gradientValue.d.ts +17 -0
  191. package/dist/inspector/styleEditors/gradientValue.js +114 -0
  192. package/dist/inspector/styleEditors/inlineAuthored.d.ts +10 -0
  193. package/dist/inspector/styleEditors/inlineAuthored.js +114 -0
  194. package/dist/inspector/styleEditors/layoutValue.d.ts +0 -8
  195. package/dist/inspector/styleEditors/layoutValue.js +0 -42
  196. package/dist/inspector/styleEditors/nudgeValue.d.ts +4 -4
  197. package/dist/inspector/styleEditors/nudgeValue.js +41 -11
  198. package/dist/inspector/tokens/TokenField.d.ts +7 -0
  199. package/dist/inspector/tokens/TokenField.js +49 -22
  200. package/dist/inspector/tokens/TokenLabel.js +5 -14
  201. package/dist/inspector/tokens/TokensPanel.js +2 -1
  202. package/dist/inspector/tokens/dragPointerLock.d.ts +8 -0
  203. package/dist/inspector/tokens/dragPointerLock.js +70 -0
  204. package/dist/inspector/tokens/editActions.d.ts +1 -1
  205. package/dist/inspector/tokens/editActions.js +1 -1
  206. package/dist/inspector/ui/AtRuleContext.js +4 -6
  207. package/dist/inspector/ui/Button.d.ts +6 -2
  208. package/dist/inspector/ui/Button.js +4 -3
  209. package/dist/inspector/ui/ControlSurface.d.ts +2 -2
  210. package/dist/inspector/ui/ControlSurface.js +4 -3
  211. package/dist/inspector/ui/Disclosure.d.ts +22 -0
  212. package/dist/inspector/ui/Disclosure.js +13 -0
  213. package/dist/inspector/ui/InlineStyleWarning.d.ts +11 -0
  214. package/dist/inspector/ui/InlineStyleWarning.js +13 -0
  215. package/dist/inspector/ui/InspectorPopover.d.ts +2 -1
  216. package/dist/inspector/ui/InspectorPopover.js +4 -5
  217. package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
  218. package/dist/inspector/ui/PopoverListbox.js +8 -7
  219. package/dist/inspector/ui/SegmentedControl.d.ts +2 -1
  220. package/dist/inspector/ui/SegmentedControl.js +2 -2
  221. package/dist/inspector/ui/Select.d.ts +6 -1
  222. package/dist/inspector/ui/Select.js +7 -11
  223. package/dist/inspector/ui/SideValuesField.js +1 -1
  224. package/dist/inspector/ui/Tooltip.d.ts +26 -0
  225. package/dist/inspector/ui/Tooltip.js +32 -0
  226. package/dist/inspector/ui/classNames.d.ts +2 -0
  227. package/dist/inspector/ui/classNames.js +4 -0
  228. package/dist/inspector/ui/customCursors.d.ts +23 -0
  229. package/dist/inspector/ui/customCursors.js +122 -0
  230. package/dist/inspector/ui/dragCursor.d.ts +6 -0
  231. package/dist/inspector/ui/dragCursor.js +13 -0
  232. package/dist/inspector/ui/portalContainer.d.ts +2 -0
  233. package/dist/inspector/ui/portalContainer.js +6 -0
  234. package/dist/inspector/ui/styles.js +34 -24
  235. package/dist/inspector/workspace/commands.d.ts +9 -0
  236. package/dist/inspector/workspace/commands.js +82 -0
  237. package/dist/inspector/workspace/controller.d.ts +4 -0
  238. package/dist/inspector/workspace/controller.js +66 -0
  239. package/dist/inspector/workspace/handoff.d.ts +42 -0
  240. package/dist/inspector/workspace/handoff.js +115 -0
  241. package/dist/inspector/workspace/timeline.d.ts +30 -0
  242. package/dist/inspector/workspace/timeline.js +108 -0
  243. package/dist/internal/agent-protocol.d.ts +19 -2
  244. package/dist/internal/agent-protocol.js +13 -0
  245. package/dist/nudge-ui.mjs +560 -299
  246. package/dist/project/artifacts.d.ts +13 -0
  247. package/dist/project/artifacts.js +253 -0
  248. package/dist/transport/artifacts.d.ts +8 -0
  249. package/dist/transport/artifacts.js +9 -0
  250. package/dist/transport/editor.d.ts +20 -1
  251. package/dist/transport/editor.js +44 -11
  252. package/dist/transport/routes.d.ts +6 -1
  253. package/dist/transport/routes.js +6 -1
  254. package/package.json +6 -2
  255. package/dist/inspector/changes/workspaceChanges.d.ts +0 -43
  256. package/dist/inspector/changes/workspaceChanges.js +0 -239
  257. package/dist/inspector/shell/DomNavigation.d.ts +0 -8
  258. package/dist/inspector/shell/DomNavigation.js +0 -30
@@ -1,10 +1,12 @@
1
1
  import { PROTOCOL_VERSION, clearRendererIdentity, getRendererIdentity, isRendererMessageFor, sendToParent, setRendererIdentity, } from "./frameProtocol.js";
2
+ import { wheelPanDelta } from "./wheelPan.js";
2
3
  import { handleReplaceStyles, startRendererProjectionDiagnostics } from "./rendererStylesheet.js";
3
4
  import { findClosestAnchor, isEligibleNavigation, hasDifferentRoute } from "./linkEligibility.js";
4
5
  import { installRendererElementSelector } from "./rendererElementSelector.js";
5
6
  import { createFrameThrottle } from "../overlay/frameThrottle.js";
6
7
  import { isNudgeUiDev } from "../runtime/devFlag.js";
7
8
  import { getNudgeUiRuntimeConfig, subscribeNudgeUiRuntime } from "../runtime/runtimeConfig.js";
9
+ import { APP_INTERACTION_KEY } from "./keyboardShortcuts.js";
8
10
  let activeRendererBootstrap = null;
9
11
  function ownsRendererBootstrap(owner) {
10
12
  return owner.active && activeRendererBootstrap?.owner === owner;
@@ -155,6 +157,7 @@ export function bootstrapRenderer() {
155
157
  if (disposeSelector)
156
158
  owner.resourceDisposers.push(disposeSelector);
157
159
  installRendererPanProxy(owner);
160
+ let openLinksInCards = false;
158
161
  const onClick = (event) => {
159
162
  if (!ownsRendererBootstrap(owner))
160
163
  return;
@@ -168,10 +171,16 @@ export function bootstrapRenderer() {
168
171
  const identity = getRendererIdentity();
169
172
  if (!identity)
170
173
  return;
174
+ if (openLinksInCards) {
175
+ // Capture on document runs before framework routers, so the card keeps its route.
176
+ event.preventDefault();
177
+ event.stopImmediatePropagation();
178
+ }
171
179
  const msg = {
172
180
  type: "navigation-intent",
173
181
  protocolVersion: PROTOCOL_VERSION,
174
182
  url: anchor.href,
183
+ ...(openLinksInCards ? { openInCard: true } : {}),
175
184
  ...identity,
176
185
  };
177
186
  sendToParent(msg);
@@ -198,6 +207,12 @@ export function bootstrapRenderer() {
198
207
  sendFrameReady(owner);
199
208
  return;
200
209
  }
210
+ const frameIdentity = getRendererIdentity();
211
+ if (frameIdentity && isRendererMessageFor(msg, frameIdentity) && msg.type === "link-target-state") {
212
+ // SAFETY: the identity check proves a protocol message; the discriminator selects this shape.
213
+ openLinksInCards = msg.openInCard === true;
214
+ return;
215
+ }
201
216
  if (msg &&
202
217
  typeof msg === "object" &&
203
218
  msg.type === "replace-styles" &&
@@ -239,6 +254,8 @@ function installRendererPanProxy(owner) {
239
254
  let spaceHeld = false;
240
255
  let panning = false;
241
256
  let boardGesturesEnabled = false;
257
+ let boardScrollPans = false;
258
+ let nativeAppInteraction = false;
242
259
  const panMoveUpdate = createFrameThrottle((point) => {
243
260
  if (!ownsRendererBootstrap(owner))
244
261
  return;
@@ -285,7 +302,9 @@ function installRendererPanProxy(owner) {
285
302
  }
286
303
  if (event.data.type === "board-gesture-state") {
287
304
  boardGesturesEnabled = event.data.enabled;
288
- if (!boardGesturesEnabled) {
305
+ boardScrollPans = event.data.panScroll === true;
306
+ nativeAppInteraction = event.data.panScroll === false;
307
+ if (!boardGesturesEnabled || nativeAppInteraction) {
289
308
  spaceHeld = false;
290
309
  endPan();
291
310
  }
@@ -293,10 +312,18 @@ function installRendererPanProxy(owner) {
293
312
  };
294
313
  window.addEventListener("message", onMessage);
295
314
  owner.listenerRemovers.push(() => window.removeEventListener("message", onMessage));
315
+ function sendAppInteractionModifier(held) {
316
+ const identity = getRendererIdentity();
317
+ if (!identity)
318
+ return;
319
+ sendToParent({ type: "app-interaction-modifier", protocolVersion: PROTOCOL_VERSION, held, ...identity });
320
+ }
296
321
  const onKeyDown = (event) => {
297
322
  if (!ownsRendererBootstrap(owner))
298
323
  return;
299
- if (boardGesturesEnabled && event.code === "Space" && !event.repeat && !isEditableTarget(event.target)) {
324
+ if (event.code === APP_INTERACTION_KEY && !event.repeat && !isEditableTarget(event.target))
325
+ sendAppInteractionModifier(true);
326
+ if (boardGesturesEnabled && !nativeAppInteraction && event.code === "Space" && !event.repeat && !isEditableTarget(event.target)) {
300
327
  spaceHeld = true;
301
328
  if (getRendererIdentity())
302
329
  event.preventDefault();
@@ -308,6 +335,8 @@ function installRendererPanProxy(owner) {
308
335
  const onKeyUp = (event) => {
309
336
  if (!ownsRendererBootstrap(owner))
310
337
  return;
338
+ if (event.code === APP_INTERACTION_KEY)
339
+ sendAppInteractionModifier(false);
311
340
  if (event.code === "Space") {
312
341
  spaceHeld = false;
313
342
  sendSpaceState();
@@ -342,7 +371,7 @@ function installRendererPanProxy(owner) {
342
371
  const onPointerDown = (event) => {
343
372
  if (!ownsRendererBootstrap(owner))
344
373
  return;
345
- if (!boardGesturesEnabled || !spaceHeld || event.button !== 0 || isEditableTarget(event.target))
374
+ if (!boardGesturesEnabled || nativeAppInteraction || !spaceHeld || event.button !== 0 || isEditableTarget(event.target))
346
375
  return;
347
376
  const identity = getRendererIdentity();
348
377
  if (!identity)
@@ -379,6 +408,8 @@ function installRendererPanProxy(owner) {
379
408
  const onBlur = () => {
380
409
  if (!ownsRendererBootstrap(owner))
381
410
  return;
411
+ if (!window.parent.document.hasFocus())
412
+ sendAppInteractionModifier(false);
382
413
  spaceHeld = false;
383
414
  sendSpaceState();
384
415
  endPan();
@@ -388,13 +419,23 @@ function installRendererPanProxy(owner) {
388
419
  const onWheel = (event) => {
389
420
  if (!ownsRendererBootstrap(owner))
390
421
  return;
391
- if (!boardGesturesEnabled || (!event.ctrlKey && !event.metaKey))
422
+ const zoom = event.ctrlKey || event.metaKey;
423
+ if (!boardGesturesEnabled || (!zoom && !boardScrollPans))
392
424
  return;
393
425
  const identity = getRendererIdentity();
394
426
  if (!identity)
395
427
  return;
396
428
  event.preventDefault();
397
429
  event.stopPropagation();
430
+ if (!zoom) {
431
+ const delta = wheelPanDelta(event, { width: window.innerWidth, height: window.innerHeight });
432
+ const message = {
433
+ type: "wheel-pan", protocolVersion: PROTOCOL_VERSION,
434
+ deltaX: delta.x, deltaY: delta.y, ...identity,
435
+ };
436
+ sendToParent(message);
437
+ return;
438
+ }
398
439
  const message = {
399
440
  type: "zoom",
400
441
  protocolVersion: PROTOCOL_VERSION,
@@ -1,2 +1,2 @@
1
1
  export declare function buildSelector(el: HTMLElement): string;
2
- export declare function installRendererElementSelector(): () => void;
2
+ export declare function installRendererElementSelector(acceptsClick?: (event: Event) => boolean): () => void;
@@ -1,5 +1,4 @@
1
1
  import { PROTOCOL_VERSION, getRendererIdentity, sendToParent, isKeyboardShortcutCode, } from "./frameProtocol.js";
2
- import { findClosestAnchor, isEligibleNavigation, hasDifferentRoute, shouldPreserveNativeLinkActivation, } from "./linkEligibility.js";
3
2
  import { readBorderWidths, readMargins } from "../overlay/overlayGeometry.js";
4
3
  import { installInteractionStyles } from "../overlay/interactionStyles.js";
5
4
  import { createFrameThrottle } from "../overlay/frameThrottle.js";
@@ -8,9 +7,10 @@ import { isNudgeUiDev } from "../runtime/devFlag.js";
8
7
  import { isEditableEvent, isInspectorToggleShortcut, isSendPromptShortcut } from "../shell/shortcuts.js";
9
8
  import { resolveSelectionTarget, selectionTargetMode } from "../selection/selectionTarget.js";
10
9
  import { escapeCssString } from "../projection/cssEscapes.js";
11
- import { blockApplicationClick, isApplicationActivationClick } from "../overlay/clickPolicy.js";
10
+ import { APPLICATION_GESTURE_EVENTS, blockApplicationClick, blockApplicationGesture, isInlineEditorTarget, isUserClick, } from "../overlay/clickPolicy.js";
12
11
  import { EMPTY_TEXT_PROJECTION_ATTR } from "../projection/textProjection.js";
13
- import { getSpacingAffordanceAtPoint, toSpacingDescriptor, } from "../overlay/spacingGestures.js";
12
+ import { getSpacingAffordanceAtPoint, getSpacingHoverAtPoint, toSpacingDescriptor, } from "../overlay/spacingGestures.js";
13
+ import { COMMENT_CURSOR, INTERACTION_CURSOR_PROPERTY, rendererCursorValue } from "../ui/customCursors.js";
14
14
  const REACT_FIBER_KEY = /^__reactFiber\$/;
15
15
  const REACT_INTERNAL_KEY = /^__reactInternalInstance\$/;
16
16
  const HOVER_SCROLL_SETTLE_DELAY = 150;
@@ -78,19 +78,20 @@ export function buildSelector(el) {
78
78
  }
79
79
  let installed = false;
80
80
  const noopDisposal = () => undefined;
81
- export function installRendererElementSelector() {
81
+ export function installRendererElementSelector(acceptsClick = isUserClick) {
82
82
  if (!isNudgeUiDev())
83
83
  return noopDisposal;
84
84
  if (installed)
85
85
  return noopDisposal;
86
86
  installed = true;
87
- const removeInteractionStyles = installInteractionStyles();
87
+ let removeInteractionStyles = installInteractionStyles();
88
88
  const listenerCleanup = [];
89
89
  let disposed = false;
90
90
  let interactionsSuspended = false;
91
91
  let scrolling = false;
92
92
  let scrollSettleTimer = null;
93
93
  let activeHoverElement = null;
94
+ let suppressHoverDuringSpacingDrag = false;
94
95
  let lastHoverPoint = null;
95
96
  function trackListener(target, type, listener, options) {
96
97
  const eventListener = (event) => listener(event);
@@ -100,8 +101,29 @@ export function installRendererElementSelector() {
100
101
  const cidIndex = createCidIndex(document);
101
102
  const initialCursor = document.documentElement.style.getPropertyValue("cursor");
102
103
  const initialCursorPriority = document.documentElement.style.getPropertyPriority("cursor");
104
+ const initialInteractionCursor = document.documentElement.style.getPropertyValue(INTERACTION_CURSOR_PROPERTY);
105
+ const initialInteractionCursorPriority = document.documentElement.style.getPropertyPriority(INTERACTION_CURSOR_PROPERTY);
106
+ let commentMode = false;
107
+ let interactionCursor = "design";
108
+ let commentCursor = COMMENT_CURSOR;
109
+ let appliedInteractionCursor = rendererCursorValue("design");
103
110
  let appliedRootCursor = null;
104
111
  let spacingCursor = null;
112
+ function setInteractionCursor(cursor) {
113
+ appliedInteractionCursor = rendererCursorValue(cursor, commentCursor);
114
+ document.documentElement.style.setProperty(INTERACTION_CURSOR_PROPERTY, appliedInteractionCursor);
115
+ }
116
+ function restoreInteractionCursor() {
117
+ if (document.documentElement.style.getPropertyValue(INTERACTION_CURSOR_PROPERTY) !== appliedInteractionCursor)
118
+ return;
119
+ if (initialInteractionCursor) {
120
+ document.documentElement.style.setProperty(INTERACTION_CURSOR_PROPERTY, initialInteractionCursor, initialInteractionCursorPriority);
121
+ }
122
+ else {
123
+ document.documentElement.style.removeProperty(INTERACTION_CURSOR_PROPERTY);
124
+ }
125
+ }
126
+ setInteractionCursor("design");
105
127
  function clearSpacingCursor() {
106
128
  const active = spacingCursor;
107
129
  spacingCursor = null;
@@ -140,7 +162,7 @@ export function installRendererElementSelector() {
140
162
  spacingCursor.appliedValue = cursor;
141
163
  }
142
164
  element.style.setProperty("cursor", cursor, "important");
143
- document.documentElement.style.setProperty("cursor", cursor);
165
+ document.documentElement.style.setProperty("cursor", cursor, "important");
144
166
  appliedRootCursor = cursor;
145
167
  }
146
168
  function reportHover(pending) {
@@ -152,10 +174,16 @@ export function installRendererElementSelector() {
152
174
  const selector = buildSelector(element);
153
175
  const src = element.getAttribute("data-src") ?? "";
154
176
  const rect = clear ? null : element.getBoundingClientRect();
155
- const rawSpacing = !clear && pending.point
177
+ // The handle hit is the only target that starts a drag, so it is the only
178
+ // one that changes the cursor. The area-wide match is purely visual.
179
+ const rawSpacing = !commentMode && !clear && pending.point
156
180
  ? getSpacingAffordanceAtPoint(document, pending.point.x, pending.point.y)
157
181
  : null;
158
182
  const spacing = rawSpacing && rawSpacing.element === element ? rawSpacing : null;
183
+ const rawHoverSpacing = !commentMode && !clear && pending.point
184
+ ? getSpacingHoverAtPoint(document, pending.point.x, pending.point.y)
185
+ : null;
186
+ const hoverSpacing = rawHoverSpacing && rawHoverSpacing.element === element ? rawHoverSpacing : null;
159
187
  if (spacing) {
160
188
  setSpacingCursor(spacing.element, spacing.cursor);
161
189
  }
@@ -182,12 +210,13 @@ export function installRendererElementSelector() {
182
210
  borders: rect ? readBorderWidths(element) : null,
183
211
  point: pending.point,
184
212
  spacing: spacing ? toSpacingDescriptor(spacing) : null,
213
+ hoverSpacing: hoverSpacing ? toSpacingDescriptor(hoverSpacing) : null,
185
214
  ...identity,
186
215
  };
187
216
  sendToParent(msg);
188
217
  }
189
218
  const hoverUpdate = createFrameThrottle((pending) => {
190
- if (disposed || scrolling)
219
+ if (disposed || scrolling || suppressHoverDuringSpacingDrag)
191
220
  return;
192
221
  reportHover(pending);
193
222
  });
@@ -202,7 +231,7 @@ export function installRendererElementSelector() {
202
231
  function resumeHoverAfterScroll() {
203
232
  scrollSettleTimer = null;
204
233
  scrolling = false;
205
- if (disposed || interactionsSuspended || !lastHoverPoint)
234
+ if (disposed || interactionsSuspended || suppressHoverDuringSpacingDrag || !lastHoverPoint)
206
235
  return;
207
236
  const target = document.elementFromPoint?.(lastHoverPoint.x, lastHoverPoint.y);
208
237
  const element = resolveSelectionTarget(target, lastHoverPoint.mode);
@@ -248,6 +277,8 @@ export function installRendererElementSelector() {
248
277
  if (interactionsSuspended)
249
278
  return;
250
279
  updateMeasureState(event.altKey, true);
280
+ if (suppressHoverDuringSpacingDrag)
281
+ return;
251
282
  const target = event.target;
252
283
  if (!(target instanceof Element))
253
284
  return;
@@ -290,8 +321,19 @@ export function installRendererElementSelector() {
290
321
  updateMeasureState(message.altKey, measurePointerOverPage);
291
322
  return;
292
323
  }
324
+ if (message.type === "pan-modifier" && typeof message.spaceHeld === "boolean") {
325
+ setInteractionCursor(message.spaceHeld ? "drag" : interactionCursor);
326
+ return;
327
+ }
293
328
  if (message.type !== "inspector-interaction-state" || typeof message.open !== "boolean")
294
329
  return;
330
+ if (typeof message.commentCursor === "string")
331
+ commentCursor = message.commentCursor;
332
+ interactionCursor = message.cursor === "comment" ? "comment" : message.cursor === "drag" ? "drag" : "design";
333
+ commentMode = interactionCursor === "comment";
334
+ cancelActiveDrag();
335
+ clearSpacingCursor();
336
+ setInteractionCursor(interactionCursor);
295
337
  const interactionsEnabled = message.interactionsEnabled === undefined
296
338
  ? message.open
297
339
  : message.interactionsEnabled === true;
@@ -304,26 +346,35 @@ export function installRendererElementSelector() {
304
346
  }
305
347
  if (interactionsSuspended) {
306
348
  cancelActiveDrag();
307
- hoverUpdate.cancel();
308
- clearSpacingCursor();
349
+ clearActiveHover();
309
350
  if (scrollSettleTimer !== null)
310
351
  window.clearTimeout(scrollSettleTimer);
311
352
  scrollSettleTimer = null;
312
353
  scrolling = false;
313
- activeHoverElement = null;
314
354
  updateMeasureState(false, false);
355
+ removeInteractionStyles?.();
356
+ removeInteractionStyles = null;
357
+ }
358
+ else {
359
+ removeInteractionStyles ??= installInteractionStyles();
315
360
  }
316
361
  });
317
- const dragMoveUpdate = createFrameThrottle((point) => {
362
+ const dragMoveUpdate = createFrameThrottle((drag) => {
318
363
  if (disposed)
319
364
  return;
320
365
  const identity = getRendererIdentity();
321
- if (!point || !identity)
366
+ if (!drag || !identity)
322
367
  return;
323
- const msg = { type: "element-drag-move", protocolVersion: PROTOCOL_VERSION, point, ...identity };
368
+ const msg = {
369
+ type: "element-drag-move",
370
+ protocolVersion: PROTOCOL_VERSION,
371
+ point: drag.point,
372
+ shiftKey: drag.shiftKey,
373
+ ...identity,
374
+ };
324
375
  sendToParent(msg);
325
376
  });
326
- function sendDragEnd(point, cancelled) {
377
+ function sendDragEnd(point, cancelled, shiftKey = false) {
327
378
  if (!dragging || !point)
328
379
  return;
329
380
  const identity = getRendererIdentity();
@@ -333,6 +384,7 @@ export function installRendererElementSelector() {
333
384
  type: "element-drag-end",
334
385
  protocolVersion: PROTOCOL_VERSION,
335
386
  point,
387
+ shiftKey,
336
388
  ...(cancelled ? { cancelled: true } : {}),
337
389
  ...identity,
338
390
  };
@@ -343,11 +395,12 @@ export function installRendererElementSelector() {
343
395
  sendDragEnd(lastDragPoint, true);
344
396
  pendingDrag = null;
345
397
  dragging = false;
398
+ suppressHoverDuringSpacingDrag = false;
346
399
  }
347
400
  trackListener(document, "mousedown", (event) => {
348
401
  if (interactionsSuspended)
349
402
  return;
350
- if (event.button !== 0)
403
+ if (event.button !== 0 || commentMode)
351
404
  return;
352
405
  const element = resolveSelectionTarget(event.target, selectionTargetMode(event));
353
406
  if (!element)
@@ -356,6 +409,11 @@ export function installRendererElementSelector() {
356
409
  const spacing = spacingAffordance?.element === element
357
410
  ? toSpacingDescriptor(spacingAffordance)
358
411
  : null;
412
+ if (spacing) {
413
+ suppressHoverDuringSpacingDrag = true;
414
+ hoverUpdate.cancel();
415
+ lastHoverPoint = null;
416
+ }
359
417
  const identity = getRendererIdentity();
360
418
  // A spacing drag owns the pointer gesture. Do not start an inline-text
361
419
  // attempt for the same down event; padding and gaps are intentionally not
@@ -386,6 +444,13 @@ export function installRendererElementSelector() {
386
444
  };
387
445
  lastDragPoint = { x: event.clientX, y: event.clientY };
388
446
  }, true);
447
+ for (const type of APPLICATION_GESTURE_EVENTS) {
448
+ trackListener(document, type, (event) => {
449
+ if (interactionsSuspended || !acceptsClick(event) || isInlineEditorTarget(event.target))
450
+ return;
451
+ blockApplicationGesture(event);
452
+ }, true);
453
+ }
389
454
  trackListener(document, "mousemove", (event) => {
390
455
  if (!pendingDrag) {
391
456
  if (interactionsSuspended)
@@ -419,12 +484,13 @@ export function installRendererElementSelector() {
419
484
  elementId: cidIndex.elementId(pendingDrag.element), point,
420
485
  startPoint: pendingDrag.point,
421
486
  spacing: pendingDrag.spacing,
487
+ shiftKey: event.shiftKey,
422
488
  ...identity,
423
489
  };
424
490
  sendToParent(msg);
425
491
  }
426
492
  else {
427
- dragMoveUpdate.schedule(point);
493
+ dragMoveUpdate.schedule({ point, shiftKey: event.shiftKey });
428
494
  }
429
495
  }, true);
430
496
  function finishDrag(event) {
@@ -433,10 +499,11 @@ export function installRendererElementSelector() {
433
499
  event.preventDefault();
434
500
  const point = { x: event.clientX, y: event.clientY };
435
501
  lastDragPoint = point;
436
- sendDragEnd(point, false);
502
+ sendDragEnd(point, false, event.shiftKey);
437
503
  }
438
504
  pendingDrag = null;
439
505
  dragging = false;
506
+ suppressHoverDuringSpacingDrag = false;
440
507
  }
441
508
  trackListener(document, "mouseup", finishDrag, true);
442
509
  function forwardKeyboardShortcut(event, phase) {
@@ -470,7 +537,10 @@ export function installRendererElementSelector() {
470
537
  sendToParent(message);
471
538
  return phase === "keydown";
472
539
  }
473
- trackListener(document, "keydown", (event) => {
540
+ // Global tool shortcuts need to run before application capture handlers on
541
+ // the iframe document. A page-level window handler can otherwise stop the
542
+ // event before it reaches the document listener.
543
+ trackListener(window, "keydown", (event) => {
474
544
  if (isEditableEvent(event))
475
545
  return;
476
546
  if (forwardKeyboardShortcut(event, "keydown"))
@@ -529,7 +599,7 @@ export function installRendererElementSelector() {
529
599
  sendToParent(msg);
530
600
  return;
531
601
  }
532
- if (!lastSelected)
602
+ if (!lastSelected || commentMode)
533
603
  return;
534
604
  const identity = getRendererIdentity();
535
605
  if (!identity)
@@ -554,7 +624,7 @@ export function installRendererElementSelector() {
554
624
  };
555
625
  sendToParent(msg);
556
626
  }, true);
557
- trackListener(document, "keyup", (event) => {
627
+ trackListener(window, "keyup", (event) => {
558
628
  forwardKeyboardShortcut(event, "keyup");
559
629
  if (event.key === "Alt")
560
630
  updateMeasureState(false, measurePointerOverPage);
@@ -589,7 +659,7 @@ export function installRendererElementSelector() {
589
659
  hoverUpdate.schedule({ element: el, clear: true, point: null });
590
660
  }, true);
591
661
  trackListener(document, "dblclick", (event) => {
592
- if (interactionsSuspended)
662
+ if (interactionsSuspended || commentMode)
593
663
  return;
594
664
  const element = resolveSelectionTarget(event.target, selectionTargetMode(event));
595
665
  const identity = getRendererIdentity();
@@ -612,36 +682,20 @@ export function installRendererElementSelector() {
612
682
  sendToParent(message);
613
683
  }, true);
614
684
  trackListener(document, "click", (event) => {
615
- if (interactionsSuspended)
685
+ if (interactionsSuspended || !acceptsClick(event))
616
686
  return;
617
687
  const target = event.target;
618
688
  if (!(target instanceof Element))
619
689
  return;
620
- // Defer to navigation-intent when the user clicked a navigable same-origin
621
- // anchor that points to a different route. The later listener reports the
622
- // intent to the controller while leaving native or framework navigation in
623
- // charge of the live application document.
624
- const anchor = findClosestAnchor(target);
625
- if (anchor && isEligibleNavigation(anchor, event) && hasDifferentRoute(anchor)) {
626
- return;
627
- }
628
- // Command/Ctrl+Shift-click is the deliberate escape hatch for running
629
- // the application action. All other selected canvas clicks are editing
630
- // gestures and must not reach the rendered application.
631
- if (isApplicationActivationClick(event))
632
- return;
633
- const preserveNativeLink = anchor
634
- ? shouldPreserveNativeLinkActivation(anchor, event)
635
- : false;
690
+ // Design-tool clicks are editing gestures and must not reach the
691
+ // rendered application; the Select tool is how the app receives them.
636
692
  const el = resolveSelectionTarget(target, selectionTargetMode(event));
637
693
  if (!el) {
638
- if (!preserveNativeLink)
639
- blockApplicationClick(event);
694
+ blockApplicationClick(event);
640
695
  return;
641
696
  }
642
697
  lastSelected = el;
643
- if (!preserveNativeLink)
644
- blockApplicationClick(event);
698
+ blockApplicationClick(event);
645
699
  const cid = el.getAttribute("data-cid");
646
700
  const selector = buildSelector(el);
647
701
  const { file, line, component, src } = getFiberInfo(el);
@@ -676,14 +730,17 @@ export function installRendererElementSelector() {
676
730
  for (const cleanup of listenerCleanup)
677
731
  cleanup();
678
732
  listenerCleanup.length = 0;
679
- removeInteractionStyles();
733
+ removeInteractionStyles?.();
734
+ removeInteractionStyles = null;
680
735
  lastSelected = null;
681
736
  activeHoverElement = null;
682
737
  lastHoverPoint = null;
683
738
  scrolling = false;
739
+ suppressHoverDuringSpacingDrag = false;
684
740
  measurePointerOverPage = false;
685
741
  measureAltKey = false;
686
742
  document.documentElement.removeAttribute("data-nudge-ui-panel");
687
743
  clearSpacingCursor();
744
+ restoreInteractionCursor();
688
745
  };
689
746
  }
@@ -8,7 +8,7 @@ import { applyRenderedInstanceProjection, getRenderedInstanceProjectionReports,
8
8
  import { applyStructuralProjection, getStructuralProjectionReports, isStructuralChange, subscribeStructuralDiagnostics, } from "../projection/structuralProjection.js";
9
9
  import { applyTextContentProjection, getTextProjectionReports, subscribeTextProjectionDiagnostics, } from "../projection/textProjection.js";
10
10
  import { isTextContentChangeListValue } from "../changes/types.js";
11
- import { applyWorkspaceProjection, } from "../projection/workspaceProjection.js";
11
+ import { applyDraftProjection, } from "../projection/draftProjection.js";
12
12
  const SHEET_ID = "nudge-ui-styles";
13
13
  function replaceRendererCss(css) {
14
14
  let sheet = document.getElementById(SHEET_ID);
@@ -208,7 +208,7 @@ export function handleReplaceStyles(msg, projectId, workspaceId, cardId) {
208
208
  return false;
209
209
  if (msg.revision <= lastAppliedRevision)
210
210
  return false;
211
- applyWorkspaceProjection(rendererDocumentProjectionAdapter, projectionFromReplaceStylesMessage(msg));
211
+ applyDraftProjection(rendererDocumentProjectionAdapter, projectionFromReplaceStylesMessage(msg));
212
212
  lastStructuralReportRevision = msg.revision;
213
213
  lastRenderedInstanceReportRevision = msg.revision;
214
214
  lastTextProjectionReportRevision = msg.revision;
@@ -1,4 +1,4 @@
1
- import { MAX_CAMERA_ZOOM } from "./canvasStore.js";
1
+ import { MAX_CAMERA_ZOOM } from "./viewStore.js";
2
2
  import { CANVAS_TOOLBAR_MAX_SCALE } from "./toolbarScale.js";
3
3
  /**
4
4
  * Keep the resize handle usable while the board is zoomed without allowing
@@ -1,46 +1,33 @@
1
- import { type SerializableChange } from "../changes/codecs.js";
2
- import { type CanvasMode } from "./canvasStore.js";
3
- import { type StructuralChange } from "../projection/structuralProjection.js";
1
+ import { type FrameContent } from "./frameContent.js";
2
+ import { type FrameGroup } from "./canvasStore.js";
3
+ import { type CanvasPresentation, type CanvasMode } from "./viewStore.js";
4
4
  import { type ClipboardHandoffSnapshot } from "../prompt/clipboardHandoff.js";
5
- declare const SCHEMA_VERSION = 12;
5
+ declare const SCHEMA_VERSION = 17;
6
6
  declare function storageKey(projectId: string): string;
7
7
  export interface SerializableCard {
8
8
  id: string;
9
- url: string;
9
+ content: FrameContent;
10
10
  title: string | null;
11
+ groupId?: string;
11
12
  x: number;
12
13
  y: number;
13
14
  width: number;
14
15
  height: number;
15
- comparisonGroupId?: string;
16
- }
17
- export interface SerializableComparisonGroup {
18
- id: string;
19
- label: string;
20
- owner: "agent";
21
- agentId: string;
22
- cardIds: string[];
23
- routes: Array<{
24
- url: string;
25
- title?: string | null;
26
- label?: string;
27
- }>;
28
16
  }
29
17
  export interface DurableSession {
30
18
  schemaVersion: typeof SCHEMA_VERSION;
31
19
  projectId: string;
32
20
  mode: CanvasMode;
21
+ presentation: CanvasPresentation;
22
+ groups: readonly FrameGroup[];
33
23
  inspectUrl: string;
34
24
  cards: SerializableCard[];
35
- comparisonGroups: SerializableComparisonGroup[];
36
25
  camera: {
37
26
  x: number;
38
27
  y: number;
39
28
  zoom: number;
40
29
  };
41
30
  focusedCardId?: string | null;
42
- changes: SerializableChange[];
43
- structuralChanges: StructuralChange[];
44
31
  clipboardHandoff: ClipboardHandoffSnapshot | null;
45
32
  }
46
33
  export type { SerializableChange, SerializableComponentChange, SerializableElementChange, SerializableTextContentChange, SerializableTokenChange, SerializableTokenRef, } from "../changes/codecs.js";
@@ -51,6 +38,8 @@ export interface HydrationResult {
51
38
  export declare function serializeSession(): DurableSession;
52
39
  export declare function persistSession(): boolean;
53
40
  export declare function hydrateSession(): HydrationResult;
41
+ /** Clears the active frame's edit draft while preserving canvas geometry and other drafts. */
42
+ export declare function clearSelectedFrameChanges(): void;
54
43
  export declare function clearSession(): void;
55
44
  export declare function enableAutoSave(): void;
56
45
  /**
@@ -59,12 +48,8 @@ export declare function enableAutoSave(): void;
59
48
  * refresh or close inside the debounce window still flushes on `beforeunload`.
60
49
  */
61
50
  export declare function scheduleAutoSave(): void;
62
- /**
63
- * Canvas mode/card/camera changes persist immediately (synchronous) so a
64
- * refresh always restores the workspace, even inside the edit-autosave
65
- * debounce window. Edit autosave stays coalesced behind the trailing timer.
66
- */
67
51
  export declare function scheduleCanvasSave(): void;
52
+ export declare function flushAutoSave(): void;
68
53
  export declare function getRestoreCount(): number;
69
54
  export declare function setRestoreCount(count: number): void;
70
55
  export declare function clearRestoreCount(): void;