nudge-ui 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (264) hide show
  1. package/dist/cli/agentCommand.js +4 -28
  2. package/dist/client.mjs +870 -212
  3. package/dist/hosts/next/wrapper.js +1 -7
  4. package/dist/hosts/projectBridge.js +3 -17
  5. package/dist/inspector/agent/McpConnectionDialog.js +7 -3
  6. package/dist/inspector/agent/activity.d.ts +1 -1
  7. package/dist/inspector/agent/activity.js +3 -2
  8. package/dist/inspector/agent/client.d.ts +2 -2
  9. package/dist/inspector/agent/client.js +28 -29
  10. package/dist/inspector/agent/connectionStatus.d.ts +3 -1
  11. package/dist/inspector/agent/connectionStatus.js +25 -0
  12. package/dist/inspector/agent/httpTransport.js +31 -147
  13. package/dist/inspector/agent/protocol.d.ts +1 -1
  14. package/dist/inspector/agent/protocol.js +1 -1
  15. package/dist/inspector/agent/verification.d.ts +5 -7
  16. package/dist/inspector/agent/verification.js +67 -20
  17. package/dist/inspector/boot.d.ts +3 -0
  18. package/dist/inspector/boot.js +297 -0
  19. package/dist/inspector/canvas/AgentActivityOverlay.d.ts +2 -1
  20. package/dist/inspector/canvas/AgentActivityOverlay.js +6 -3
  21. package/dist/inspector/canvas/CanvasCard.js +23 -12
  22. package/dist/inspector/canvas/CanvasElementOverlay.js +97 -128
  23. package/dist/inspector/canvas/CanvasToolbar.js +2 -1
  24. package/dist/inspector/canvas/CanvasWorkspace.js +119 -162
  25. package/dist/inspector/canvas/LockedWorkspaceNotice.d.ts +3 -2
  26. package/dist/inspector/canvas/LockedWorkspaceNotice.js +10 -6
  27. package/dist/inspector/canvas/PageCard.d.ts +10 -0
  28. package/dist/inspector/canvas/PageCard.js +51 -0
  29. package/dist/inspector/canvas/SketchToolOptions.d.ts +5 -0
  30. package/dist/inspector/canvas/SketchToolOptions.js +86 -0
  31. package/dist/inspector/canvas/StaleChangeIndicator.d.ts +1 -1
  32. package/dist/inspector/canvas/StaleChangeIndicator.js +1 -1
  33. package/dist/inspector/canvas/ToolOptionsDrawer.d.ts +21 -0
  34. package/dist/inspector/canvas/ToolOptionsDrawer.js +77 -0
  35. package/dist/inspector/canvas/activeCanvasDocument.d.ts +3 -2
  36. package/dist/inspector/canvas/assets/eraser.svg +28 -0
  37. package/dist/inspector/canvas/assets/pen.svg +25 -0
  38. package/dist/inspector/canvas/canvasFrame.d.ts +16 -0
  39. package/dist/inspector/canvas/canvasFrame.js +10 -0
  40. package/dist/inspector/canvas/canvasGestures.d.ts +0 -1
  41. package/dist/inspector/canvas/canvasGestures.js +0 -6
  42. package/dist/inspector/canvas/canvasStore.d.ts +6 -0
  43. package/dist/inspector/canvas/canvasStore.js +36 -1
  44. package/dist/inspector/canvas/frameConnection.d.ts +48 -0
  45. package/dist/inspector/canvas/frameConnection.js +73 -0
  46. package/dist/inspector/canvas/frameProtocol.d.ts +18 -1
  47. package/dist/inspector/canvas/frameProtocol.js +36 -0
  48. package/dist/inspector/canvas/frameScrollbarStyles.d.ts +3 -0
  49. package/dist/inspector/canvas/frameScrollbarStyles.js +21 -0
  50. package/dist/inspector/canvas/pageSurface.d.ts +11 -0
  51. package/dist/inspector/canvas/pageSurface.js +34 -0
  52. package/dist/inspector/canvas/projection.d.ts +19 -9
  53. package/dist/inspector/canvas/projection.js +58 -31
  54. package/dist/inspector/canvas/rendererBootstrap.js +4 -1
  55. package/dist/inspector/canvas/rendererElementSelector.js +9 -1
  56. package/dist/inspector/canvas/rendererMessageRouter.d.ts +4 -5
  57. package/dist/inspector/canvas/rendererMessageRouter.js +12 -16
  58. package/dist/inspector/canvas/rendererSelectionProxy.d.ts +7 -1
  59. package/dist/inspector/canvas/rendererSelectionProxy.js +8 -36
  60. package/dist/inspector/canvas/rendererStylesheet.js +15 -0
  61. package/dist/inspector/canvas/sessionStore.d.ts +2 -2
  62. package/dist/inspector/canvas/sessionStore.js +12 -9
  63. package/dist/inspector/canvas/staleChangeDetector.d.ts +1 -1
  64. package/dist/inspector/canvas/staleChangeDetector.js +10 -22
  65. package/dist/inspector/changes/codecs.d.ts +2 -0
  66. package/dist/inspector/changes/codecs.js +27 -3
  67. package/dist/inspector/changes/draftPreview.d.ts +12 -0
  68. package/dist/inspector/changes/draftPreview.js +133 -0
  69. package/dist/inspector/changes/editModel.d.ts +18 -0
  70. package/dist/inspector/changes/editModel.js +16 -3
  71. package/dist/inspector/changes/managedStyleProjection.js +2 -1
  72. package/dist/inspector/changes/previewDiagnostics.js +1 -1
  73. package/dist/inspector/changes/types.d.ts +18 -1
  74. package/dist/inspector/comments/CommentsOverlay.js +18 -16
  75. package/dist/inspector/comments/element.js +10 -3
  76. package/dist/inspector/comments/store.js +3 -2
  77. package/dist/inspector/comments/verification.js +1 -1
  78. package/dist/inspector/componentSemantics/ComponentPropsSection.js +2 -1
  79. package/dist/inspector/componentSemantics/adapterRegistry.d.ts +6 -1
  80. package/dist/inspector/componentSemantics/adapterRegistry.js +23 -1
  81. package/dist/inspector/componentSemantics/changeAction.js +1 -1
  82. package/dist/inspector/componentSemantics/reactRuntime.d.ts +2 -1
  83. package/dist/inspector/componentSemantics/reactRuntime.js +38 -0
  84. package/dist/inspector/componentSemantics/runtimeBridge.d.ts +4 -2
  85. package/dist/inspector/componentSemantics/runtimeBridge.js +17 -0
  86. package/dist/inspector/componentSemantics/textBinding.d.ts +1 -2
  87. package/dist/inspector/componentSemantics/textBinding.js +4 -45
  88. package/dist/inspector/componentSemantics/types.d.ts +11 -0
  89. package/dist/inspector/drafts/draftStore.d.ts +109 -0
  90. package/dist/inspector/drafts/draftStore.js +451 -0
  91. package/dist/inspector/drafts/model.d.ts +9 -1
  92. package/dist/inspector/drafts/model.js +5 -1
  93. package/dist/inspector/drafts/store.d.ts +53 -15
  94. package/dist/inspector/drafts/store.js +143 -169
  95. package/dist/inspector/index.d.ts +2 -4
  96. package/dist/inspector/index.js +2 -264
  97. package/dist/inspector/inline-text/inlineTextEditor.d.ts +1 -1
  98. package/dist/inspector/inline-text/inlineTextEditor.js +1 -2
  99. package/dist/inspector/inline-text/textEditChange.d.ts +1 -1
  100. package/dist/inspector/inspection/bridge.d.ts +1 -1
  101. package/dist/inspector/inspection/bridge.js +2 -1
  102. package/dist/inspector/inspection/browserCssInspection.d.ts +8 -0
  103. package/dist/inspector/inspection/browserCssInspection.js +28 -6
  104. package/dist/inspector/inspection/inspectionSnapshot.d.ts +6 -0
  105. package/dist/inspector/inspection/inspectionSnapshot.js +10 -0
  106. package/dist/inspector/inspection/performanceDiagnostics.d.ts +18 -0
  107. package/dist/inspector/inspection/performanceDiagnostics.js +31 -0
  108. package/dist/inspector/inspection/useBrowserCssInspection.js +17 -38
  109. package/dist/inspector/iterations/capture.d.ts +2 -1
  110. package/dist/inspector/iterations/capture.js +2 -1
  111. package/dist/inspector/iterations/client.d.ts +2 -1
  112. package/dist/inspector/iterations/coordinator.d.ts +4 -3
  113. package/dist/inspector/iterations/coordinator.js +5 -3
  114. package/dist/inspector/iterations/prompt.js +9 -8
  115. package/dist/inspector/overlay/interactionStyles.js +17 -0
  116. package/dist/inspector/pageInspector.d.ts +42 -0
  117. package/dist/inspector/pageInspector.js +342 -0
  118. package/dist/inspector/projection/draftProjection.d.ts +10 -2
  119. package/dist/inspector/projection/draftProjection.js +9 -1
  120. package/dist/inspector/projection/managedStylesheet.js +24 -4
  121. package/dist/inspector/projection/renderedInstance.d.ts +15 -2
  122. package/dist/inspector/projection/renderedInstance.js +60 -7
  123. package/dist/inspector/projection/structuralProjection.d.ts +0 -9
  124. package/dist/inspector/projection/structuralProjection.js +16 -46
  125. package/dist/inspector/projection/textProjection.d.ts +8 -2
  126. package/dist/inspector/projection/textProjection.js +77 -24
  127. package/dist/inspector/prompt/clipboardHandoff.d.ts +14 -0
  128. package/dist/inspector/prompt/clipboardHandoff.js +47 -16
  129. package/dist/inspector/prompt/generatePrompt.d.ts +1 -1
  130. package/dist/inspector/prompt/generatePrompt.js +248 -148
  131. package/dist/inspector/prompt/promptDocument.d.ts +3 -0
  132. package/dist/inspector/prompt/promptDocument.js +8 -0
  133. package/dist/inspector/prompt/promptSettings.js +7 -5
  134. package/dist/inspector/runtime/inspectorStorage.d.ts +17 -0
  135. package/dist/inspector/runtime/inspectorStorage.js +42 -0
  136. package/dist/inspector/runtime/ownedStylesheets.d.ts +20 -0
  137. package/dist/inspector/runtime/ownedStylesheets.js +72 -0
  138. package/dist/inspector/runtime/runtimeConfig.d.ts +4 -0
  139. package/dist/inspector/runtime/runtimeConfig.js +10 -1
  140. package/dist/inspector/runtime/runtimeIdentityClaims.d.ts +29 -0
  141. package/dist/inspector/runtime/runtimeIdentityClaims.js +188 -0
  142. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.d.ts +15 -0
  143. package/dist/inspector/runtime/staticHtmlRuntimeIdentity.js +113 -29
  144. package/dist/inspector/selection/editScope.d.ts +1 -0
  145. package/dist/inspector/selection/editScope.js +13 -2
  146. package/dist/inspector/selection/sourceSite.d.ts +12 -0
  147. package/dist/inspector/selection/sourceSite.js +28 -0
  148. package/dist/inspector/shell/AgentStatusButton.js +2 -2
  149. package/dist/inspector/shell/AppShell.js +6 -2
  150. package/dist/inspector/shell/ChangesLog.js +27 -9
  151. package/dist/inspector/shell/CopyPromptButton.js +74 -26
  152. package/dist/inspector/shell/EmptyState.js +3 -3
  153. package/dist/inspector/shell/InspectorShell.d.ts +0 -3
  154. package/dist/inspector/shell/InspectorShell.js +21 -13
  155. package/dist/inspector/shell/PeekOriginalButton.js +3 -3
  156. package/dist/inspector/shell/interactionStatePreview.d.ts +9 -0
  157. package/dist/inspector/shell/interactionStatePreview.js +112 -0
  158. package/dist/inspector/shell/originalPreview.d.ts +3 -2
  159. package/dist/inspector/shell/originalPreview.js +10 -37
  160. package/dist/inspector/shell/stateValue.js +2 -3
  161. package/dist/inspector/sketch/SketchEditor.js +5 -4
  162. package/dist/inspector/sketch/SketchFrameOverlay.d.ts +2 -1
  163. package/dist/inspector/sketch/SketchFrameOverlay.js +5 -4
  164. package/dist/inspector/sketch/SketchOverlay.d.ts +3 -5
  165. package/dist/inspector/sketch/SketchOverlay.js +139 -263
  166. package/dist/inspector/sketch/SketchPromptPanel.d.ts +1 -1
  167. package/dist/inspector/sketch/SketchPromptPanel.js +8 -1
  168. package/dist/inspector/sketch/SketchThumbnail.d.ts +5 -0
  169. package/dist/inspector/sketch/SketchThumbnail.js +18 -0
  170. package/dist/inspector/sketch/SketchWorkspace.d.ts +1 -2
  171. package/dist/inspector/sketch/SketchWorkspace.js +69 -34
  172. package/dist/inspector/sketch/capture.js +19 -3
  173. package/dist/inspector/sketch/copySketch.d.ts +10 -0
  174. package/dist/inspector/sketch/copySketch.js +52 -0
  175. package/dist/inspector/sketch/drawingTools.d.ts +17 -0
  176. package/dist/inspector/sketch/drawingTools.js +47 -0
  177. package/dist/inspector/sketch/frameHeading.d.ts +9 -0
  178. package/dist/inspector/sketch/frameHeading.js +30 -0
  179. package/dist/inspector/sketch/freehand.js +3 -3
  180. package/dist/inspector/sketch/geometry.d.ts +6 -0
  181. package/dist/inspector/sketch/geometry.js +19 -0
  182. package/dist/inspector/sketch/history.d.ts +30 -0
  183. package/dist/inspector/sketch/history.js +58 -0
  184. package/dist/inspector/sketch/interaction.d.ts +1 -3
  185. package/dist/inspector/sketch/interaction.js +6 -9
  186. package/dist/inspector/sketch/model.d.ts +35 -1
  187. package/dist/inspector/sketch/model.js +116 -61
  188. package/dist/inspector/sketch/persistence.d.ts +14 -0
  189. package/dist/inspector/sketch/persistence.js +63 -7
  190. package/dist/inspector/sketch/raster.d.ts +6 -2
  191. package/dist/inspector/sketch/raster.js +43 -17
  192. package/dist/inspector/sketch/store.d.ts +1 -1
  193. package/dist/inspector/sketch/store.js +1 -1
  194. package/dist/inspector/sketch/videoFrames.d.ts +6 -0
  195. package/dist/inspector/sketch/videoFrames.js +81 -0
  196. package/dist/inspector/styleEditors/BackgroundEditor.js +3 -2
  197. package/dist/inspector/styleEditors/BorderEditor.js +30 -130
  198. package/dist/inspector/styleEditors/BorderRadiusEditor.js +8 -3
  199. package/dist/inspector/styleEditors/ImageBackgroundEditor.js +1 -1
  200. package/dist/inspector/styleEditors/LayoutSection.js +2 -2
  201. package/dist/inspector/styleEditors/borderModel.d.ts +42 -0
  202. package/dist/inspector/styleEditors/borderModel.js +114 -0
  203. package/dist/inspector/styleEditors/layoutValue.js +2 -3
  204. package/dist/inspector/tokens/TokenField.js +40 -7
  205. package/dist/inspector/tokens/TokensPanel.js +2 -1
  206. package/dist/inspector/tokens/editActions.d.ts +3 -3
  207. package/dist/inspector/tokens/editActions.js +15 -3
  208. package/dist/inspector/tokens/resolution/containerQueryEvaluator.d.ts +15 -0
  209. package/dist/inspector/tokens/resolution/containerQueryEvaluator.js +86 -0
  210. package/dist/inspector/tokens/resolution/cssomCollector.js +44 -9
  211. package/dist/inspector/tokens/resolution/nestedSelectors.d.ts +6 -0
  212. package/dist/inspector/tokens/resolution/nestedSelectors.js +67 -0
  213. package/dist/inspector/tokens/resolution/ruleMatching.js +23 -4
  214. package/dist/inspector/tokens/resolution.d.ts +6 -3
  215. package/dist/inspector/tokens/resolution.js +91 -112
  216. package/dist/inspector/tokens/tokenEdits.d.ts +1 -1
  217. package/dist/inspector/tokens/tokenEdits.js +1 -1
  218. package/dist/inspector/ui/InlineStyleWarning.js +2 -2
  219. package/dist/inspector/ui/InspectorStyle.d.ts +8 -0
  220. package/dist/inspector/ui/InspectorStyle.js +26 -0
  221. package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
  222. package/dist/inspector/ui/PopoverListbox.js +3 -3
  223. package/dist/inspector/ui/Toast.d.ts +14 -0
  224. package/dist/inspector/ui/Toast.js +30 -0
  225. package/dist/inspector/ui/assets/canvasIllustration.d.ts +2 -0
  226. package/dist/inspector/ui/assets/canvasIllustration.js +21 -0
  227. package/dist/inspector/ui/assets/gridIllustration.d.ts +2 -0
  228. package/dist/inspector/ui/assets/{grid.svg → gridIllustration.js} +3 -2
  229. package/dist/inspector/ui/customCursors.d.ts +5 -0
  230. package/dist/inspector/ui/customCursors.js +32 -6
  231. package/dist/inspector/ui/styles.js +12 -10
  232. package/dist/inspector/workspace/commands.js +1 -2
  233. package/dist/inspector/workspace/controller.js +1 -2
  234. package/dist/inspector/workspace/handoff.js +3 -2
  235. package/dist/inspector/workspace/sentItems.d.ts +16 -0
  236. package/dist/inspector/workspace/sentItems.js +33 -0
  237. package/dist/inspector/workspace/timeline.d.ts +24 -10
  238. package/dist/inspector/workspace/timeline.js +118 -96
  239. package/dist/internal/agent-protocol.d.ts +50 -13
  240. package/dist/internal/agent-protocol.js +145 -19
  241. package/dist/nudge-ui.mjs +81 -65
  242. package/dist/project/mcpPackage.d.ts +8 -0
  243. package/dist/project/mcpPackage.js +60 -0
  244. package/package.json +13 -3
  245. package/dist/inspector/canvas/measurementProjection.d.ts +0 -8
  246. package/dist/inspector/canvas/measurementProjection.js +0 -16
  247. package/dist/inspector/changes/changesLog.d.ts +0 -47
  248. package/dist/inspector/changes/changesLog.js +0 -247
  249. package/dist/inspector/changes/draftChanges.d.ts +0 -56
  250. package/dist/inspector/changes/draftChanges.js +0 -300
  251. package/dist/inspector/conformance/projection.d.ts +0 -2
  252. package/dist/inspector/conformance/projection.js +0 -3
  253. package/dist/inspector/inline-text/textChangeBoundary.d.ts +0 -6
  254. package/dist/inspector/inline-text/textChangeBoundary.js +0 -1
  255. package/dist/inspector/overlay/InspectorOverlay.d.ts +0 -5
  256. package/dist/inspector/overlay/InspectorOverlay.js +0 -332
  257. package/dist/inspector/overlay/elementSelector.d.ts +0 -1
  258. package/dist/inspector/overlay/elementSelector.js +0 -111
  259. package/dist/inspector/sketch/SketchChanges.d.ts +0 -2
  260. package/dist/inspector/sketch/SketchChanges.js +0 -72
  261. package/dist/inspector/sketch/SketchEntryButton.d.ts +0 -4
  262. package/dist/inspector/sketch/SketchEntryButton.js +0 -11
  263. package/dist/inspector/sketch/SketchLayersPanel.d.ts +0 -2
  264. package/dist/inspector/sketch/SketchLayersPanel.js +0 -71
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
3
- import { PROTOCOL_VERSION, isElementClickMessage, isInlineTextIntentMessage, } from "./frameProtocol.js";
3
+ import { isElementClickMessage, isInlineTextIntentMessage } from "./frameProtocol.js";
4
4
  import { useCanvasCards } from "./canvasStore.js";
5
5
  import { useBoardCamera, useCanvasPresentation, useCanvasPresentationTransitioning, useCanvasLayoutTransitioning, getCanvasLayoutTransitioning, useTemporaryAppInteraction, } from "./viewStore.js";
6
6
  import { handleElementClick } from "./rendererSelectionProxy.js";
@@ -9,7 +9,7 @@ import { readBorderWidths, toRect, } from "../overlay/overlayGeometry.js";
9
9
  const overlayStyles = ".canvas-element-overlay {\n position: fixed;\n pointer-events: none;\n z-index: 1;\n background: transparent;\n outline: 1px solid var(--accent);\n outline-offset: -1px;\n}\n\n.canvas-spacing-guide {\n position: fixed;\n z-index: 1;\n border-radius: 999px;\n background: var(--accent);\n outline: none;\n box-shadow: none;\n pointer-events: none;\n}\n\n.canvas-spacing-fill {\n position: fixed;\n z-index: 1;\n pointer-events: none;\n background: rgb(59 130 246 / 14%);\n}\n\n.canvas-spacing-fill[data-kind=\"gap\"] {\n background: rgb(236 72 153 / 14%);\n}\n\n.canvas-spacing-guide[data-kind=\"gap\"] {\n background: #ec4899;\n}\n\n.canvas-spacing-value-badge {\n position: fixed;\n z-index: 2;\n transform: translate(-50%, calc(-100% - var(--space-8)));\n padding: var(--space-4) var(--space-8);\n border-radius: var(--radius-8);\n background: var(--surface-raised-2x);\n box-shadow: var(--shadow-popup);\n color: var(--text-primary);\n font-family: var(--font-family);\n font-size: var(--font-size-base);\n font-weight: 400;\n line-height: 1.4;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n pointer-events: none;\n}\n\n.canvas-selected-outline {\n position: fixed;\n pointer-events: none;\n z-index: 1;\n outline: 1px solid var(--accent);\n outline-offset: -1px;\n}\n\n.canvas-dom-drop-line {\n z-index: 2147483647;\n border-radius: 999px;\n background: #3b82f6;\n box-shadow: 0 0 0 1px rgb(255 255 255 / 95%), 0 1px 5px rgb(37 99 235 / 72%);\n}\n\n.canvas-dom-drop-line::before,\n.canvas-dom-drop-line::after {\n position: absolute;\n top: 50%;\n width: 8px;\n height: 8px;\n border: 2px solid #ffffff;\n border-radius: 50%;\n background: #2563eb;\n content: \"\";\n transform: translateY(-50%);\n}\n\n.canvas-dom-drop-line::before { left: -3px; }\n.canvas-dom-drop-line::after { right: -3px; }\n\n.canvas-dom-drop-line[data-orientation=\"vertical\"]::before,\n.canvas-dom-drop-line[data-orientation=\"vertical\"]::after {\n left: 50%;\n right: auto;\n transform: translateX(-50%);\n}\n\n.canvas-dom-drop-line[data-orientation=\"vertical\"]::before { top: -3px; }\n.canvas-dom-drop-line[data-orientation=\"vertical\"]::after { top: auto; bottom: -3px; }\n\n.canvas-dom-drop-target {\n z-index: 2147483646;\n box-sizing: border-box;\n border: 1px solid rgb(59 130 246 / 72%);\n border-radius: 4px;\n background: rgb(59 130 246 / 5%);\n}\n";
10
10
  import { deleteElement, getDropLocationAtPoint, moveElement, nudgeElement } from "../overlay/structuralGestures.js";
11
11
  import { changeKey } from "../changes/model.js";
12
- import { getChanges, redo, subscribeChanges, undo } from "../changes/changesLog.js";
12
+ import { getActiveDraftChanges, redo, subscribeActiveDraftChanges, undo } from "../drafts/store.js";
13
13
  import { resolveSelectionFromElement } from "../selection/resolveSelection.js";
14
14
  import { setSelectedElement } from "../selection/selectionStore.js";
15
15
  import { clearDropGuide, showDropGuide, useDropGuide } from "../overlay/dropGuide.js";
@@ -17,8 +17,8 @@ import { DropGuideOverlay } from "../overlay/DropGuideOverlay.js";
17
17
  import { getMeasurementGeometry } from "../overlay/measurementGeometry.js";
18
18
  import { getElementComputedStyle } from "../runtime/domRealm.js";
19
19
  import { MeasurementGuideOverlay } from "../overlay/MeasurementGuideOverlay.js";
20
- import { projectMeasurementSegments } from "./measurementProjection.js";
21
- import { getRegisteredFrames, PROJECT_ID, WORKSPACE_ID } from "./projection.js";
20
+ import { findCanvasFrameByDocument, getRegisteredFrames } from "./projection.js";
21
+ import { connectFrame, measureFrameViewport, toViewportPoint, toViewportRect } from "./frameConnection.js";
22
22
  import { RENDERER_ELEMENT_ID_ATTR } from "./rendererCidIndex.js";
23
23
  import { observeSelectedGeometry } from "../overlay/selectedGeometry.js";
24
24
  import { handleInlineTextEditIntent, useInlineTextSession } from "../inline-text/inlineTextEditor.js";
@@ -30,22 +30,7 @@ import { getSpacingAffordanceAtPoint, getSpacingAffordanceForDescriptor, getSpac
30
30
  import { beginLayoutPreview, endLayoutPreview } from "../styleEditors/layoutPreviewState.js";
31
31
  import { useNudgeUiRuntimeConfig } from "../runtime/useRuntimeConfig.js";
32
32
  import { DomNavigator } from "../overlay/DomNavigator.js";
33
- function projectRect(iframe, rect, zoom) {
34
- const frameRect = iframe.getBoundingClientRect();
35
- return {
36
- left: frameRect.left + rect.left * zoom,
37
- top: frameRect.top + rect.top * zoom,
38
- width: rect.width * zoom,
39
- height: rect.height * zoom,
40
- };
41
- }
42
- function projectPoint(iframe, x, y, zoom) {
43
- const frameRect = iframe.getBoundingClientRect();
44
- return {
45
- x: frameRect.left + x * zoom,
46
- y: frameRect.top + y * zoom,
47
- };
48
- }
33
+ import { InspectorStyle } from "../ui/InspectorStyle.js";
49
34
  function spacingBadgeForDrag(drag, point) {
50
35
  return {
51
36
  iframe: drag.iframe,
@@ -74,40 +59,18 @@ function spacingGuideStyle(rect) {
74
59
  height,
75
60
  });
76
61
  }
77
- function findFrameElement(iframe, elementId, cid, src) {
78
- const doc = iframe.contentDocument;
79
- if (!doc)
80
- return null;
81
- if (!/^r\d+$/.test(elementId))
82
- return null;
83
- const candidates = doc.querySelectorAll(`[${RENDERER_ELEMENT_ID_ATTR}="${elementId}"]`);
84
- if (candidates.length !== 1)
85
- return null;
86
- const candidate = candidates[0] ?? null;
87
- if (!candidate
88
- || candidate.getAttribute("data-cid") !== cid
89
- || (candidate.getAttribute("data-src") ?? "") !== src)
90
- return null;
91
- const frameWindow = doc.defaultView;
92
- return frameWindow && candidate instanceof frameWindow.HTMLElement ? candidate : null;
93
- }
94
- function projectGuideToCanvas(guide, zoom) {
95
- if (!guide)
96
- return null;
97
- const iframe = guide.document.defaultView?.frameElement;
98
- if (!(iframe instanceof HTMLIFrameElement))
62
+ function projectGuideToCanvas(guide) {
63
+ const iframe = findCanvasFrameByDocument(guide?.document);
64
+ if (!guide || !iframe)
99
65
  return null;
100
- const iframeRect = iframe.getBoundingClientRect();
101
- const project = (rect, scaleWidth, scaleHeight) => ({
102
- left: iframeRect.left + rect.left * zoom,
103
- top: iframeRect.top + rect.top * zoom,
104
- width: scaleWidth ? rect.width * zoom : rect.width,
105
- height: scaleHeight ? rect.height * zoom : rect.height,
106
- });
66
+ const viewport = measureFrameViewport(iframe);
107
67
  return {
108
68
  orientation: guide.orientation,
109
- line: project(guide.line, guide.orientation === "horizontal", guide.orientation === "vertical"),
110
- target: project(guide.target, true, true),
69
+ line: toViewportRect(viewport, guide.line, {
70
+ width: guide.orientation === "horizontal",
71
+ height: guide.orientation === "vertical",
72
+ }),
73
+ target: toViewportRect(viewport, guide.target),
111
74
  };
112
75
  }
113
76
  function spacingDescriptorMatches(affordance, descriptor) {
@@ -191,7 +154,7 @@ function releasePendingSpacingCommits(pending, iframe) {
191
154
  function reconcilePendingSpacingCommits(pending) {
192
155
  if (pending.length === 0)
193
156
  return;
194
- const survivingKeys = new Set(getChanges().map(changeKey));
157
+ const survivingKeys = new Set(getActiveDraftChanges().changes.map(changeKey));
195
158
  let write = 0;
196
159
  for (const commit of pending) {
197
160
  if (commit.keys.some((key) => survivingKeys.has(key))) {
@@ -227,16 +190,6 @@ function pushPendingSpacingCommit(pending, next) {
227
190
  originalInlinePriority: pending[existing].originalInlinePriority,
228
191
  };
229
192
  }
230
- function sendMeasureModifier(iframe, cardId, altKey) {
231
- iframe.contentWindow?.postMessage({
232
- type: "measure-modifier",
233
- protocolVersion: PROTOCOL_VERSION,
234
- projectId: PROJECT_ID,
235
- workspaceId: WORKSPACE_ID,
236
- cardId,
237
- altKey,
238
- }, window.location.origin);
239
- }
240
193
  export function CanvasElementOverlay() {
241
194
  const [hover, setHover] = useState(null);
242
195
  const [measureState, setMeasureState] = useState(null);
@@ -257,10 +210,9 @@ export function CanvasElementOverlay() {
257
210
  setHover(null);
258
211
  setMeasureState(null);
259
212
  }, [layoutTransitioning]);
260
- const projectionZoom = presentation === "focus" ? 1 : camera.zoom;
261
213
  const cards = useCanvasCards(); // Projected geometry must follow card drag and resize updates.
262
214
  const cardGeometryKey = cards.map((card) => `${card.id}:${card.x}:${card.y}:${card.width}:${card.height}`).join("|");
263
- const projectionGeometryKey = `${presentation}:${camera.x}:${camera.y}:${projectionZoom}:${cardGeometryKey}`;
215
+ const projectionGeometryKey = `${presentation}:${camera.x}:${camera.y}:${camera.zoom}:${cardGeometryKey}`;
264
216
  const previousProjectionGeometryKey = useRef(projectionGeometryKey);
265
217
  const dragRef = useRef(null);
266
218
  const spacingDragRef = useRef(null);
@@ -268,29 +220,26 @@ export function CanvasElementOverlay() {
268
220
  const [spacingDragBadge, setSpacingDragBadge] = useState(null);
269
221
  const measureAltKeyRef = useRef(false);
270
222
  const dropGuide = useDropGuide("canvas");
271
- const projectedDropGuide = projectGuideToCanvas(dropGuide, projectionZoom);
272
- const selectedFrame = selected?.domElement.ownerDocument.defaultView?.frameElement;
273
- const selectedInCanvas = selectedFrame instanceof HTMLIFrameElement
274
- && selectedFrame.hasAttribute("data-nudge-ui-canvas-renderer");
223
+ const projectedDropGuide = projectGuideToCanvas(dropGuide);
224
+ const selectedFrame = findCanvasFrameByDocument(selected?.domElement.ownerDocument);
225
+ const selectedInCanvas = selectedFrame !== null;
275
226
  const selectedRects = selectedInCanvas
276
227
  ? selectedElements.map((candidate) => {
277
- const frame = candidate.domElement.ownerDocument.defaultView?.frameElement;
228
+ const frame = findCanvasFrameByDocument(candidate.domElement.ownerDocument);
278
229
  return frame === selectedFrame ? toRect(candidate.domElement.getBoundingClientRect()) : null;
279
230
  })
280
231
  : [];
281
232
  const selectedPrimaryIndex = selectedElements.findIndex((candidate) => candidate.domElement === selected?.domElement);
282
233
  const selectedLocalRect = selectedRects[selectedPrimaryIndex >= 0 ? selectedPrimaryIndex : 0] ?? null;
283
- const selectedFrameRect = selectedInCanvas
284
- ? toRect(selectedFrame.getBoundingClientRect())
285
- : null;
286
- const selectedRect = selectedInCanvas && selectedLocalRect
287
- ? projectRect(selectedFrame, selectedLocalRect, projectionZoom)
234
+ const selectedFrameViewport = selectedInCanvas ? measureFrameViewport(selectedFrame) : null;
235
+ const selectedRect = selectedFrameViewport && selectedLocalRect
236
+ ? toViewportRect(selectedFrameViewport, selectedLocalRect)
288
237
  : null;
289
- const projectedSelectedGeometry = selectedInCanvas
238
+ const projectedSelectedGeometry = selectedFrameViewport
290
239
  ? selectedRects.flatMap((rect, index) => {
291
240
  const element = selectedElements[index];
292
241
  return rect && element
293
- ? [{ element, rect: projectRect(selectedFrame, rect, projectionZoom) }]
242
+ ? [{ element, rect: toViewportRect(selectedFrameViewport, rect) }]
294
243
  : [];
295
244
  })
296
245
  : [];
@@ -316,7 +265,7 @@ export function CanvasElementOverlay() {
316
265
  const broadcastMeasureModifier = (altKey) => {
317
266
  measureAltKeyRef.current = altKey;
318
267
  for (const [cardId, iframe] of getRegisteredFrames()) {
319
- sendMeasureModifier(iframe, cardId, altKey);
268
+ connectFrame(cardId, iframe).post({ type: "measure-modifier", altKey });
320
269
  }
321
270
  };
322
271
  const onKeyDown = (event) => {
@@ -352,7 +301,7 @@ export function CanvasElementOverlay() {
352
301
  // it: undo/redo/revert/clear remove the record synchronously, so restore the
353
302
  // authored declaration before the renderer's next replace-styles lands.
354
303
  useEffect(() => {
355
- return subscribeChanges(() => {
304
+ return subscribeActiveDraftChanges(() => {
356
305
  reconcilePendingSpacingCommits(pendingSpacingCommitsRef.current);
357
306
  });
358
307
  }, []);
@@ -383,17 +332,20 @@ export function CanvasElementOverlay() {
383
332
  borders,
384
333
  spacingGuides: affordance?.affectedGuides ?? [],
385
334
  spacingAreas: affordance?.affectedAreas ?? [],
335
+ spacingHandleBadge: current.spacingHandleBadge && affordance
336
+ ? { ...current.spacingHandleBadge, value: affordance.value }
337
+ : current.spacingHandleBadge,
386
338
  };
387
339
  });
388
340
  };
389
- const unsubscribe = subscribeCanvasRendererMessages(({ cardId: sourceCardId, iframe: sourceIframe, identity: frameIdentity, message: data, }) => {
341
+ const unsubscribe = subscribeCanvasRendererMessages(({ frame, message: data }) => {
390
342
  if (data.type === "renderer-hello" || data.type === "frame-ready") {
391
- sendMeasureModifier(sourceIframe, sourceCardId, measureAltKeyRef.current);
343
+ frame.post({ type: "measure-modifier", altKey: measureAltKeyRef.current });
392
344
  }
393
345
  if (data.type === "renderer-hello")
394
346
  return;
395
347
  if (data.type === "projection-applied") {
396
- releasePendingSpacingCommits(pendingSpacingCommitsRef.current, sourceIframe);
348
+ releasePendingSpacingCommits(pendingSpacingCommitsRef.current, frame.iframe);
397
349
  return;
398
350
  }
399
351
  if (getCanvasLayoutTransitioning())
@@ -403,61 +355,69 @@ export function CanvasElementOverlay() {
403
355
  if (!msg.cid)
404
356
  return;
405
357
  if (msg.rect === null) {
406
- setHover((current) => current?.cardId === sourceCardId ? null : current);
358
+ setHover((current) => current?.cardId === frame.cardId ? null : current);
407
359
  return;
408
360
  }
409
361
  const spacingDescriptor = msg.hoverSpacing ?? msg.spacing ?? null;
410
362
  const hoverPoint = msg.point ?? null;
411
- const hoverElement = spacingDescriptor
412
- ? findFrameElement(sourceIframe, msg.elementId, msg.cid, msg.src)
413
- : null;
363
+ const hoverElement = spacingDescriptor ? frame.element(msg) : null;
364
+ const frameDocument = frame.document();
414
365
  const hoverAffordance = spacingDescriptor && hoverElement
415
366
  ? getSpacingAffordanceForDescriptor(hoverElement, spacingDescriptor)
416
- : spacingDescriptor && hoverPoint && sourceIframe.contentDocument
417
- ? getSpacingHoverAtPoint(sourceIframe.contentDocument, hoverPoint.x, hoverPoint.y)
367
+ : spacingDescriptor && hoverPoint && frameDocument
368
+ ? getSpacingHoverAtPoint(frameDocument, hoverPoint.x, hoverPoint.y)
418
369
  : null;
419
370
  const matchingAffordance = spacingDescriptorMatches(hoverAffordance, spacingDescriptor)
420
371
  ? hoverAffordance
421
372
  : null;
422
373
  const spacingGuides = matchingAffordance?.affectedGuides ?? [];
423
374
  const spacingAreas = matchingAffordance?.affectedAreas ?? [];
375
+ const handleAffordance = msg.spacing && hoverElement
376
+ ? getSpacingAffordanceForDescriptor(hoverElement, msg.spacing)
377
+ : null;
378
+ const spacingHandleBadge = hoverPoint
379
+ && handleAffordance
380
+ && spacingDescriptorMatches(handleAffordance, msg.spacing)
381
+ ? { point: hoverPoint, value: handleAffordance.value }
382
+ : null;
424
383
  setHover({
425
- iframe: sourceIframe,
384
+ iframe: frame.iframe,
426
385
  identity: { elementId: msg.elementId },
427
386
  rect: msg.rect,
428
387
  borders: msg.borders ?? { top: 0, right: 0, bottom: 0, left: 0 },
429
- cardId: sourceCardId,
388
+ cardId: frame.cardId,
430
389
  spacing: spacingGuides.length > 0 ? spacingDescriptor : null,
431
390
  spacingGuides,
432
391
  spacingAreas,
392
+ spacingHandleBadge,
433
393
  });
434
394
  }
435
395
  else if (data.type === "element-measure-state") {
436
396
  const msg = data;
437
397
  setMeasureState({
438
- iframe: sourceIframe,
398
+ iframe: frame.iframe,
439
399
  altKey: msg.altKey,
440
400
  pointerOverPage: msg.pointerOverPage,
441
401
  });
442
402
  }
443
403
  else if (data.type === "element-click") {
444
- if (!isElementClickMessage(data, frameIdentity))
404
+ if (!isElementClickMessage(data, frame.identity))
445
405
  return;
446
406
  const msg = data;
447
407
  if (!msg.cid)
448
408
  return;
449
- handleElementClick(msg, sourceIframe, sourceCardId);
409
+ handleElementClick(msg, frame);
450
410
  }
451
411
  else if (data.type === "inline-text-intent") {
452
- if (!isInlineTextIntentMessage(data, frameIdentity))
412
+ if (!isInlineTextIntentMessage(data, frame.identity))
453
413
  return;
454
414
  if (getSelectedElements().length > 1)
455
415
  return;
456
416
  const emptyProjection = data.emptyProjectionId
457
- ? Array.from(sourceIframe.contentDocument?.querySelectorAll(`[${EMPTY_TEXT_PROJECTION_ATTR}]`) ?? [])
417
+ ? Array.from(frame.document()?.querySelectorAll(`[${EMPTY_TEXT_PROJECTION_ATTR}]`) ?? [])
458
418
  .find((candidate) => candidate.getAttribute(EMPTY_TEXT_PROJECTION_ATTR) === data.emptyProjectionId)
459
419
  : null;
460
- const element = emptyProjection ?? findFrameElement(sourceIframe, data.elementId, data.cid, data.src);
420
+ const element = emptyProjection ?? frame.element(data);
461
421
  if (!element)
462
422
  return;
463
423
  handleInlineTextEditIntent(data.intent === "double-click"
@@ -480,23 +440,24 @@ export function CanvasElementOverlay() {
480
440
  if (getSelectedElements().length > 1)
481
441
  return;
482
442
  const msg = data;
483
- const element = findFrameElement(sourceIframe, msg.elementId, msg.cid, msg.src);
443
+ const element = frame.element(msg);
484
444
  if (!element)
485
445
  return;
486
446
  clearSpacingDrag(spacingDragRef);
487
447
  dragRef.current = null;
488
448
  const startPoint = msg.startPoint ?? msg.point;
449
+ const frameDocument = frame.document();
489
450
  const spacing = msg.spacing
490
451
  ? getSpacingAffordanceForDescriptor(element, msg.spacing)
491
- : sourceIframe.contentDocument
492
- ? getSpacingAffordanceAtPoint(sourceIframe.contentDocument, startPoint.x, startPoint.y)
452
+ : frameDocument
453
+ ? getSpacingAffordanceAtPoint(frameDocument, startPoint.x, startPoint.y)
493
454
  : null;
494
455
  const isSpacingDrag = spacing
495
456
  && spacing.element === element
496
457
  && (!msg.spacing || spacingDescriptorMatches(spacing, msg.spacing));
497
458
  if (isSpacingDrag) {
498
459
  spacingDragRef.current = {
499
- iframe: sourceIframe,
460
+ iframe: frame.iframe,
500
461
  element,
501
462
  affordance: spacing,
502
463
  start: startPoint,
@@ -513,26 +474,26 @@ export function CanvasElementOverlay() {
513
474
  refreshSpacingPreviewOverlay(spacingDragRef.current);
514
475
  return;
515
476
  }
516
- dragRef.current = { iframe: sourceIframe, element };
477
+ dragRef.current = { iframe: frame.iframe, element };
517
478
  const selectedElement = resolveSelectionFromElement(element);
518
479
  if (selectedElement)
519
480
  setSelectedElement(selectedElement);
520
- updateDropGuide(msg.point, sourceIframe);
481
+ updateDropGuide(msg.point);
521
482
  }
522
483
  else if (data.type === "element-drag-move") {
523
484
  const spacing = spacingDragRef.current;
524
- if (spacing && spacing.iframe === sourceIframe) {
485
+ if (spacing && spacing.iframe === frame.iframe) {
525
486
  applySpacingPreview(spacing, data.point, data.shiftKey === true);
526
487
  setSpacingDragBadge(spacingBadgeForDrag(spacing, data.point));
527
488
  refreshSpacingPreviewOverlay(spacing);
528
489
  return;
529
490
  }
530
- updateDropGuide(data.point, sourceIframe);
491
+ updateDropGuide(data.point);
531
492
  }
532
493
  else if (data.type === "element-drag-end") {
533
494
  const msg = data;
534
495
  const spacing = spacingDragRef.current;
535
- if (spacing && spacing.iframe === sourceIframe) {
496
+ if (spacing && spacing.iframe === frame.iframe) {
536
497
  spacingDragRef.current = null;
537
498
  setSpacingDragBadge(null);
538
499
  if (msg.cancelled) {
@@ -544,7 +505,7 @@ export function CanvasElementOverlay() {
544
505
  const records = commitSpacingDrag(spacing);
545
506
  if (records.length > 0) {
546
507
  pushPendingSpacingCommit(pendingSpacingCommitsRef.current, {
547
- iframe: sourceIframe,
508
+ iframe: frame.iframe,
548
509
  element: spacing.element,
549
510
  property: spacing.affordance.property,
550
511
  committedValue: spacingValueCss(spacing.currentValue),
@@ -564,8 +525,9 @@ export function CanvasElementOverlay() {
564
525
  return;
565
526
  }
566
527
  const current = dragRef.current;
567
- if (!msg.cancelled && current && current.iframe === sourceIframe && sourceIframe.contentDocument) {
568
- const drop = getDropLocationAtPoint(sourceIframe.contentDocument, current.element, msg.point.x, msg.point.y);
528
+ const frameDocument = frame.document();
529
+ if (!msg.cancelled && current && current.iframe === frame.iframe && frameDocument) {
530
+ const drop = getDropLocationAtPoint(frameDocument, current.element, msg.point.x, msg.point.y);
569
531
  if (drop)
570
532
  moveElement(current.element, drop);
571
533
  const selectedElement = resolveSelectionFromElement(current.element);
@@ -578,8 +540,7 @@ export function CanvasElementOverlay() {
578
540
  else if (data.type === "element-delete") {
579
541
  if (getSelectedElements().length !== 1)
580
542
  return;
581
- const msg = data;
582
- const element = findFrameElement(sourceIframe, msg.elementId, msg.cid, msg.src);
543
+ const element = frame.element(data);
583
544
  const selectedElement = element ? resolveSelectionFromElement(element) : null;
584
545
  if (selectedElement && deleteElement(selectedElement))
585
546
  setSelectedElement(null);
@@ -587,9 +548,8 @@ export function CanvasElementOverlay() {
587
548
  else if (data.type === "element-nudge") {
588
549
  if (getSelectedElements().length !== 1)
589
550
  return;
590
- const msg = data;
591
- const element = findFrameElement(sourceIframe, msg.elementId, msg.cid, msg.src);
592
- const record = element ? nudgeElement(element, msg.key) : null;
551
+ const element = frame.element(data);
552
+ const record = element ? nudgeElement(element, data.key) : null;
593
553
  if (element && record) {
594
554
  const selectedElement = resolveSelectionFromElement(element);
595
555
  if (selectedElement)
@@ -611,16 +571,17 @@ export function CanvasElementOverlay() {
611
571
  else if (data.type === "inspector-open-request") {
612
572
  setInspectorOpen(true);
613
573
  }
614
- function updateDropGuide(point, iframe) {
574
+ function updateDropGuide(point) {
615
575
  const current = dragRef.current;
616
- if (!current || current.iframe !== iframe || !iframe.contentDocument)
576
+ const frameDocument = frame.document();
577
+ if (!current || current.iframe !== frame.iframe || !frameDocument)
617
578
  return;
618
- const drop = getDropLocationAtPoint(iframe.contentDocument, current.element, point.x, point.y);
579
+ const drop = getDropLocationAtPoint(frameDocument, current.element, point.x, point.y);
619
580
  if (!drop) {
620
581
  clearDropGuide("canvas");
621
582
  return;
622
583
  }
623
- showDropGuide("canvas", iframe.contentDocument, drop);
584
+ showDropGuide("canvas", frameDocument, drop);
624
585
  }
625
586
  });
626
587
  return () => {
@@ -635,18 +596,21 @@ export function CanvasElementOverlay() {
635
596
  return null;
636
597
  if (!hover && projectedSelectedGeometry.length === 0 && !projectedDropGuide)
637
598
  return null;
638
- const projectedHoverRect = hover ? projectRect(hover.iframe, hover.rect, projectionZoom) : null;
639
- const projectedSpacingGuides = hover?.spacingGuides.map((guide) => projectRect(hover.iframe, guide, projectionZoom)) ?? [];
640
- const projectedSpacingAreas = hover?.spacingAreas.map((area) => projectRect(hover.iframe, area, projectionZoom)) ?? [];
641
- const projectedSpacingBadge = spacingDragBadge
642
- ? projectPoint(spacingDragBadge.iframe, spacingDragBadge.point.x, spacingDragBadge.point.y, projectionZoom)
599
+ const hoverViewport = hover ? measureFrameViewport(hover.iframe) : null;
600
+ const projectedHoverRect = hover && hoverViewport ? toViewportRect(hoverViewport, hover.rect) : null;
601
+ const projectedSpacingGuides = hover && hoverViewport ? hover.spacingGuides.map((guide) => toViewportRect(hoverViewport, guide)) : [];
602
+ const projectedSpacingAreas = hover && hoverViewport ? hover.spacingAreas.map((area) => toViewportRect(hoverViewport, area)) : [];
603
+ const spacingBadge = spacingDragBadge
604
+ ?? (hover?.spacingHandleBadge ? { iframe: hover.iframe, ...hover.spacingHandleBadge } : null);
605
+ const projectedSpacingBadge = spacingBadge
606
+ ? toViewportPoint(measureFrameViewport(spacingBadge.iframe), spacingBadge.point)
643
607
  : null;
644
608
  const hoverSpacing = hover?.spacing ?? null;
645
609
  const measureStateForSelectedFrame = measureState?.iframe === selectedFrame ? measureState : null;
646
610
  const hoverInSelectedFrame = hover?.iframe === selectedFrame ? hover : null;
647
611
  const showGuideOverlay = Boolean(selectedElements.length === 1
648
612
  && selectedRect
649
- && selectedFrameRect
613
+ && selectedFrameViewport
650
614
  && measureStateForSelectedFrame?.altKey
651
615
  && measureStateForSelectedFrame.pointerOverPage);
652
616
  const isSelfHover = Boolean(hoverInSelectedFrame
@@ -659,15 +623,20 @@ export function CanvasElementOverlay() {
659
623
  && selectedLocalRect
660
624
  && hoverInSelectedFrame
661
625
  && !isSelfHover);
662
- const measurementSegments = showMeasurement && selectedFrameRect && selectedLocalRect && hoverInSelectedFrame
663
- ? projectMeasurementSegments(selectedFrameRect, getMeasurementGeometry(selectedLocalRect, hoverInSelectedFrame.rect, {
626
+ // Segment distances stay in frame CSS pixels so labels read the same at any board zoom.
627
+ const measurementSegments = showMeasurement && selectedFrameViewport && selectedLocalRect && hoverInSelectedFrame
628
+ ? getMeasurementGeometry(selectedLocalRect, hoverInSelectedFrame.rect, {
664
629
  selectedBorders: selectedBorders ?? undefined,
665
630
  hoveredBorders: hoverInSelectedFrame.borders,
666
- }).segments, projectionZoom)
631
+ }).segments.map((segment) => ({
632
+ ...segment,
633
+ from: toViewportPoint(selectedFrameViewport, segment.from),
634
+ to: toViewportPoint(selectedFrameViewport, segment.to),
635
+ }))
667
636
  : [];
668
637
  if (presentationTransitioning || layoutTransitioning || temporaryAppInteraction)
669
- return _jsx("style", { "data-test": "canvas-element-overlay-styles", children: overlayStyles });
670
- return (_jsxs(_Fragment, { children: [_jsx("style", { "data-test": "canvas-element-overlay-styles", children: overlayStyles }), showGuideOverlay && selectedRect && selectedFrameRect ? (_jsx(MeasurementGuideOverlay, { testId: "canvas-measurement-overlay", selectedRect: selectedRect, guideViewport: selectedFrameRect, segments: measurementSegments })) : null, projectedHoverRect ? (_jsxs(_Fragment, { children: [hoverSpacing ? projectedSpacingAreas.map((area, index) => (_jsx("div", { className: "canvas-spacing-fill", "data-test": "canvas-spacing-fill", "data-kind": hoverSpacing.kind, "data-property": hoverSpacing.property, "data-side": hoverSpacing.side ?? undefined, "data-area-index": index, style: overlayStyle(area), "aria-hidden": "true" }, `${hoverSpacing.property}-area-${index}`))) : null, showHoverOutline ? (_jsx("div", { className: "canvas-element-overlay", "data-test": "canvas-hover-outline", style: overlayStyle(projectedHoverRect), "aria-hidden": "true" })) : null, hoverSpacing ? projectedSpacingGuides.map((guide, index) => (_jsx("div", { className: "canvas-spacing-guide", "data-test": "canvas-spacing-guide", "data-kind": hoverSpacing.kind, "data-property": hoverSpacing.property, "data-side": hoverSpacing.side ?? undefined, "data-guide-index": index, style: spacingGuideStyle(guide), "aria-hidden": "true" }, `${hoverSpacing.property}-${index}`))) : null] })) : null, projectedSelectedGeometry.map(({ element, rect }, index) => (_jsx("div", { className: "canvas-selected-outline", "data-test": "canvas-selected-outline", "data-selected-cid": element.cid, "data-selected-index": index, "data-selected-src": element.src, style: overlayStyle(rect), "aria-hidden": "true" }, `${element.cid}-${index}`))), projectedSpacingBadge && spacingDragBadge ? (_jsx("div", { className: "canvas-spacing-value-badge", "data-test": "canvas-spacing-value-badge", style: { left: projectedSpacingBadge.x, top: projectedSpacingBadge.y }, "aria-hidden": "true", children: spacingValueCss(spacingDragBadge.value) })) : null, domNavigationEnabled && !inlineTextSession && selectedElements.length === 1 && selected && selectedRect && selectedFrame instanceof HTMLIFrameElement ? (_jsx(DomNavigator, { selected: selected, hierarchy: hierarchy, anchor: selectedRect, project: (element) => element.ownerDocument === selected.domElement.ownerDocument
671
- ? projectRect(selectedFrame, toRect(element.getBoundingClientRect()), projectionZoom)
638
+ return _jsx(InspectorStyle, { testId: "canvas-element-overlay-styles", css: overlayStyles });
639
+ return (_jsxs(_Fragment, { children: [_jsx(InspectorStyle, { testId: "canvas-element-overlay-styles", css: overlayStyles }), showGuideOverlay && selectedRect && selectedFrameViewport ? (_jsx(MeasurementGuideOverlay, { testId: "canvas-measurement-overlay", selectedRect: selectedRect, guideViewport: selectedFrameViewport, segments: measurementSegments })) : null, projectedHoverRect ? (_jsxs(_Fragment, { children: [hoverSpacing ? projectedSpacingAreas.map((area, index) => (_jsx("div", { className: "canvas-spacing-fill", "data-test": "canvas-spacing-fill", "data-kind": hoverSpacing.kind, "data-property": hoverSpacing.property, "data-side": hoverSpacing.side ?? undefined, "data-area-index": index, style: overlayStyle(area), "aria-hidden": "true" }, `${hoverSpacing.property}-area-${index}`))) : null, showHoverOutline ? (_jsx("div", { className: "canvas-element-overlay", "data-test": "canvas-hover-outline", style: overlayStyle(projectedHoverRect), "aria-hidden": "true" })) : null, hoverSpacing ? projectedSpacingGuides.map((guide, index) => (_jsx("div", { className: "canvas-spacing-guide", "data-test": "canvas-spacing-guide", "data-kind": hoverSpacing.kind, "data-property": hoverSpacing.property, "data-side": hoverSpacing.side ?? undefined, "data-guide-index": index, style: spacingGuideStyle(guide), "aria-hidden": "true" }, `${hoverSpacing.property}-${index}`))) : null] })) : null, projectedSelectedGeometry.map(({ element, rect }, index) => (_jsx("div", { className: "canvas-selected-outline", "data-test": "canvas-selected-outline", "data-selected-cid": element.cid, "data-selected-index": index, "data-selected-src": element.src, style: overlayStyle(rect), "aria-hidden": "true" }, `${element.cid}-${index}`))), projectedSpacingBadge && spacingBadge ? (_jsx("div", { className: "canvas-spacing-value-badge", "data-test": "canvas-spacing-value-badge", style: { left: projectedSpacingBadge.x, top: projectedSpacingBadge.y }, "aria-hidden": "true", children: spacingValueCss(spacingBadge.value) })) : null, domNavigationEnabled && !inlineTextSession && selectedElements.length === 1 && selected && selectedRect && selectedFrameViewport ? (_jsx(DomNavigator, { selected: selected, hierarchy: hierarchy, anchor: selectedRect, project: (element) => element.ownerDocument === selected.domElement.ownerDocument
640
+ ? toViewportRect(selectedFrameViewport, toRect(element.getBoundingClientRect()))
672
641
  : null })) : null, _jsx(DropGuideOverlay, { guide: projectedDropGuide, lineClassName: "canvas-dom-drop-line", lineTestId: "canvas-dom-drop-line", targetClassName: "canvas-dom-drop-target", targetTestId: "canvas-dom-drop-target" })] }));
673
642
  }
@@ -3,6 +3,7 @@ import { IconMessageCircle, IconMessageCircleFilled, IconPointer2, IconSketching
3
3
  import { IconButton } from "../ui/IconButton.js";
4
4
  import { Tooltip } from "../ui/Tooltip.js";
5
5
  import { DesignPointerFilledIcon, SelectPlayFilledIcon, SelectPlayOutlineIcon, SketchThickIcon, } from "./CanvasToolIcons.js";
6
+ import { SketchToolOptions } from "./SketchToolOptions.js";
6
7
  export const CANVAS_ZOOM_LEVELS = [0.25, 0.5, 0.9, 1];
7
8
  export function closestCanvasZoomLevel(zoom) {
8
9
  let closest = CANVAS_ZOOM_LEVELS[0];
@@ -24,5 +25,5 @@ function ToolButton({ tool, activeTool, disabled, label, shortcut, icon, activeI
24
25
  return (_jsx(Tooltip, { content: label, shortcut: shortcut, stableTrigger: true, children: _jsx(IconButton, { variant: "quiet", size: "large", className: "canvas-toolbar__tool", label: label, "aria-pressed": active, "data-test": `canvas-tool-${tool}`, "data-active": active ? "true" : "false", disabled: disabled, onClick: () => onToolChange(tool), children: active ? activeIcon : icon }) }));
25
26
  }
26
27
  export function CanvasToolbar({ tool, sketchEnabled, onToolChange, }) {
27
- return (_jsxs("div", { className: "canvas-toolbar", "data-test": "canvas-toolbar", role: "toolbar", "aria-label": "Canvas tools", children: [_jsxs("div", { className: "canvas-toolbar__tools", role: "group", "aria-label": "Interaction tools", children: [_jsx(ToolButton, { tool: "design", activeTool: tool, label: "Select", shortcut: "V", icon: _jsx(IconPointer2, { size: ICON_SIZE, stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), activeIcon: _jsx(DesignPointerFilledIcon, { size: ICON_SIZE, "aria-hidden": "true" }), onToolChange: onToolChange }), _jsx(ToolButton, { tool: "comment", activeTool: tool, label: "Comment", shortcut: "C", icon: _jsx(IconMessageCircle, { size: ICON_SIZE, stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), activeIcon: _jsx(IconMessageCircleFilled, { size: ICON_SIZE, "aria-hidden": "true" }), onToolChange: onToolChange }), _jsx(ToolButton, { tool: "sketch", activeTool: tool, label: "Pencil", shortcut: "P", disabled: !sketchEnabled, icon: _jsx(IconSketching, { size: ICON_SIZE, stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), activeIcon: _jsx(SketchThickIcon, { size: ICON_SIZE, "aria-hidden": "true" }), onToolChange: onToolChange })] }), _jsx("div", { className: "canvas-toolbar__divider", "aria-hidden": "true" }), _jsx("div", { className: "canvas-toolbar__tools", role: "group", "aria-label": "Preview tools", children: _jsx(ToolButton, { tool: "select", activeTool: tool, label: "Use app normally", shortcut: "Hold A", icon: _jsx(SelectPlayOutlineIcon, { size: ICON_SIZE, "aria-hidden": "true" }), activeIcon: _jsx(SelectPlayFilledIcon, { size: ICON_SIZE, "aria-hidden": "true" }), onToolChange: onToolChange }) })] }));
28
+ return (_jsxs("div", { className: "canvas-toolbar", "data-test": "canvas-toolbar", role: "toolbar", "aria-label": "Canvas tools", children: [_jsxs("div", { className: "canvas-toolbar__tools", role: "group", "aria-label": "Interaction tools", children: [_jsx(ToolButton, { tool: "design", activeTool: tool, label: "Select", shortcut: "V", icon: _jsx(IconPointer2, { size: ICON_SIZE, stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), activeIcon: _jsx(DesignPointerFilledIcon, { size: ICON_SIZE, "aria-hidden": "true" }), onToolChange: onToolChange }), _jsx(ToolButton, { tool: "comment", activeTool: tool, label: "Comment", shortcut: "C", icon: _jsx(IconMessageCircle, { size: ICON_SIZE, stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), activeIcon: _jsx(IconMessageCircleFilled, { size: ICON_SIZE, "aria-hidden": "true" }), onToolChange: onToolChange }), _jsx(ToolButton, { tool: "sketch", activeTool: tool, label: "Pencil", shortcut: "P", disabled: !sketchEnabled, icon: _jsx(IconSketching, { size: ICON_SIZE, stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), activeIcon: _jsx(SketchThickIcon, { size: ICON_SIZE, "aria-hidden": "true" }), onToolChange: onToolChange }), _jsx(SketchToolOptions, { open: tool === "sketch" && sketchEnabled })] }), _jsx("div", { className: "canvas-toolbar__divider", "aria-hidden": "true" }), _jsx("div", { className: "canvas-toolbar__tools", role: "group", "aria-label": "Preview tools", children: _jsx(ToolButton, { tool: "select", activeTool: tool, label: "Use app normally", shortcut: "Hold A", icon: _jsx(SelectPlayOutlineIcon, { size: ICON_SIZE, "aria-hidden": "true" }), activeIcon: _jsx(SelectPlayFilledIcon, { size: ICON_SIZE, "aria-hidden": "true" }), onToolChange: onToolChange }) })] }));
28
29
  }