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.
- package/README.md +164 -46
- package/dist/client.mjs +252 -54
- package/dist/css/value-semantics/colorSemantics.d.ts +4 -0
- package/dist/css/value-semantics/colorSemantics.js +17 -0
- package/dist/hosts/astro/astroRuntimeConfig.js +1 -0
- package/dist/hosts/astro/clientTransport.js +41 -32
- package/dist/hosts/astro/integration.d.ts +2 -2
- package/dist/hosts/astro/integration.js +9 -4
- package/dist/hosts/astro/markdownIdentity.d.ts +28 -0
- package/dist/hosts/astro/markdownIdentity.js +81 -0
- package/dist/hosts/environment.d.ts +15 -0
- package/dist/hosts/environment.js +16 -0
- package/dist/hosts/next/manifest.js +1 -1
- package/dist/hosts/next/sidecar.js +12 -2
- package/dist/hosts/next/wrapper.d.ts +2 -0
- package/dist/hosts/next/wrapper.js +2 -1
- package/dist/hosts/projectBridge.d.ts +1 -0
- package/dist/hosts/projectBridge.js +1 -0
- package/dist/hosts/static/manifest.js +3 -1
- package/dist/hosts/static/server.js +4 -0
- package/dist/hosts/vite/vite.d.ts +4 -0
- package/dist/hosts/vite/vite.js +28 -5
- package/dist/inspector/agent/McpConnectionDialog.d.ts +3 -2
- package/dist/inspector/agent/McpConnectionDialog.js +23 -22
- package/dist/inspector/agent/activity.d.ts +18 -0
- package/dist/inspector/agent/activity.js +70 -0
- package/dist/inspector/agent/client.d.ts +8 -0
- package/dist/inspector/agent/client.js +65 -5
- package/dist/inspector/agent/connectionStatus.d.ts +3 -3
- package/dist/inspector/agent/connectionStatus.js +9 -2
- package/dist/inspector/agent/httpTransport.d.ts +6 -0
- package/dist/inspector/agent/httpTransport.js +50 -3
- package/dist/inspector/agent/protocol.d.ts +9 -3
- package/dist/inspector/agent/protocol.js +1 -1
- package/dist/inspector/agent/verification.d.ts +11 -1
- package/dist/inspector/agent/verification.js +53 -25
- package/dist/inspector/canvas/AgentActivityOverlay.d.ts +13 -0
- package/dist/inspector/canvas/AgentActivityOverlay.js +111 -0
- package/dist/inspector/canvas/CanvasCard.d.ts +9 -2
- package/dist/inspector/canvas/CanvasCard.js +133 -38
- package/dist/inspector/canvas/CanvasElementOverlay.js +200 -22
- package/dist/inspector/canvas/CanvasToolIcons.d.ts +10 -0
- package/dist/inspector/canvas/CanvasToolIcons.js +20 -0
- package/dist/inspector/canvas/CanvasToolbar.js +8 -4
- package/dist/inspector/canvas/CanvasWorkspace.js +243 -56
- package/dist/inspector/canvas/StaleChangeIndicator.js +3 -13
- package/dist/inspector/canvas/agentPresentation.d.ts +8 -8
- package/dist/inspector/canvas/agentPresentation.js +64 -52
- package/dist/inspector/canvas/canvasGestures.d.ts +1 -1
- package/dist/inspector/canvas/canvasGestures.js +1 -1
- package/dist/inspector/canvas/canvasStore.d.ts +46 -82
- package/dist/inspector/canvas/canvasStore.js +251 -284
- package/dist/inspector/canvas/frameContent.d.ts +21 -0
- package/dist/inspector/canvas/frameContent.js +44 -0
- package/dist/inspector/canvas/frameProtocol.d.ts +34 -4
- package/dist/inspector/canvas/frameProtocol.js +9 -2
- package/dist/inspector/canvas/keyboardShortcuts.d.ts +4 -1
- package/dist/inspector/canvas/keyboardShortcuts.js +5 -3
- package/dist/inspector/canvas/layout.d.ts +52 -0
- package/dist/inspector/canvas/layout.js +106 -0
- package/dist/inspector/canvas/linkEligibility.d.ts +0 -5
- package/dist/inspector/canvas/linkEligibility.js +0 -29
- package/dist/inspector/canvas/projection.d.ts +15 -5
- package/dist/inspector/canvas/projection.js +69 -13
- package/dist/inspector/canvas/rendererBootstrap.js +45 -4
- package/dist/inspector/canvas/rendererElementSelector.d.ts +1 -1
- package/dist/inspector/canvas/rendererElementSelector.js +102 -45
- package/dist/inspector/canvas/rendererStylesheet.js +2 -2
- package/dist/inspector/canvas/resizeHandleScale.js +1 -1
- package/dist/inspector/canvas/sessionStore.d.ts +11 -26
- package/dist/inspector/canvas/sessionStore.js +43 -183
- package/dist/inspector/canvas/staleChangeDetector.js +9 -3
- package/dist/inspector/canvas/useCanvasLayoutAnimation.d.ts +5 -0
- package/dist/inspector/canvas/useCanvasLayoutAnimation.js +107 -0
- package/dist/inspector/canvas/viewStore.d.ts +38 -0
- package/dist/inspector/canvas/viewStore.js +104 -0
- package/dist/inspector/canvas/wheelPan.d.ts +8 -0
- package/dist/inspector/canvas/wheelPan.js +8 -0
- package/dist/inspector/changes/changesLog.d.ts +6 -5
- package/dist/inspector/changes/changesLog.js +40 -32
- package/dist/inspector/changes/draftChanges.d.ts +56 -0
- package/dist/inspector/changes/draftChanges.js +300 -0
- package/dist/inspector/changes/previewDiagnostics.d.ts +4 -2
- package/dist/inspector/changes/previewDiagnostics.js +11 -25
- package/dist/inspector/clientManifest.d.ts +3 -1
- package/dist/inspector/clientManifest.js +1 -0
- package/dist/inspector/comments/CommentsOverlay.d.ts +2 -0
- package/dist/inspector/comments/CommentsOverlay.js +250 -0
- package/dist/inspector/comments/element.d.ts +6 -0
- package/dist/inspector/comments/element.js +47 -0
- package/dist/inspector/comments/store.d.ts +29 -0
- package/dist/inspector/comments/store.js +121 -0
- package/dist/inspector/comments/verification.d.ts +5 -0
- package/dist/inspector/comments/verification.js +52 -0
- package/dist/inspector/drafts/model.d.ts +35 -0
- package/dist/inspector/drafts/model.js +45 -0
- package/dist/inspector/drafts/store.d.ts +28 -0
- package/dist/inspector/drafts/store.js +231 -0
- package/dist/inspector/index.js +26 -35
- package/dist/inspector/inline-text/inlineTextEditor.js +7 -0
- package/dist/inspector/inspection/useBrowserCssInspection.js +15 -1
- package/dist/inspector/iterations/capture.d.ts +2 -0
- package/dist/inspector/iterations/capture.js +173 -0
- package/dist/inspector/iterations/client.d.ts +7 -0
- package/dist/inspector/iterations/client.js +52 -0
- package/dist/inspector/iterations/coordinator.d.ts +15 -0
- package/dist/inspector/iterations/coordinator.js +130 -0
- package/dist/inspector/iterations/prompt.d.ts +3 -0
- package/dist/inspector/iterations/prompt.js +26 -0
- package/dist/inspector/overlay/DomNavigator.d.ts +10 -0
- package/dist/inspector/overlay/DomNavigator.js +46 -0
- package/dist/inspector/overlay/InspectorOverlay.js +6 -2
- package/dist/inspector/overlay/clickPolicy.d.ts +18 -2
- package/dist/inspector/overlay/clickPolicy.js +34 -3
- package/dist/inspector/overlay/elementSelector.d.ts +1 -1
- package/dist/inspector/overlay/elementSelector.js +18 -7
- package/dist/inspector/overlay/interactionStyles.js +3 -1
- package/dist/inspector/overlay/spacingGestures.d.ts +15 -3
- package/dist/inspector/overlay/spacingGestures.js +88 -13
- package/dist/inspector/projection/{workspaceProjection.d.ts → draftProjection.d.ts} +6 -6
- package/dist/inspector/projection/{workspaceProjection.js → draftProjection.js} +4 -4
- package/dist/inspector/projection/renderedInstance.d.ts +2 -1
- package/dist/inspector/projection/renderedInstance.js +9 -5
- package/dist/inspector/projection/structuralProjection.d.ts +2 -1
- package/dist/inspector/projection/structuralProjection.js +19 -15
- package/dist/inspector/projection/textProjection.d.ts +2 -1
- package/dist/inspector/projection/textProjection.js +8 -4
- package/dist/inspector/prompt/PromptSettingsDialog.js +1 -5
- package/dist/inspector/prompt/clipboardHandoff.d.ts +10 -18
- package/dist/inspector/prompt/clipboardHandoff.js +92 -143
- package/dist/inspector/prompt/generatePrompt.d.ts +4 -1
- package/dist/inspector/prompt/generatePrompt.js +17 -16
- package/dist/inspector/runtime/runtimeConfig.d.ts +10 -1
- package/dist/inspector/runtime/runtimeConfig.js +24 -0
- package/dist/inspector/selection/hierarchy.d.ts +6 -0
- package/dist/inspector/selection/hierarchy.js +8 -0
- package/dist/inspector/settings/SettingsDialog.d.ts +1 -1
- package/dist/inspector/settings/SettingsDialog.js +22 -9
- package/dist/inspector/shell/AgentStatusButton.d.ts +11 -0
- package/dist/inspector/shell/AgentStatusButton.js +36 -0
- package/dist/inspector/shell/AppShell.js +4 -2
- package/dist/inspector/shell/ChangesLog.js +47 -27
- package/dist/inspector/shell/CopyPromptButton.js +146 -90
- package/dist/inspector/shell/EmptyState.js +9 -8
- package/dist/inspector/shell/InspectorShell.js +14 -25
- package/dist/inspector/shell/PeekOriginalButton.js +24 -23
- package/dist/inspector/shell/originalPreview.js +5 -5
- package/dist/inspector/shell/shortcuts.d.ts +3 -0
- package/dist/inspector/shell/shortcuts.js +11 -0
- package/dist/inspector/sketch/SketchEditor.js +14 -14
- package/dist/inspector/sketch/SketchEntryButton.js +1 -1
- package/dist/inspector/sketch/SketchFrameOverlay.d.ts +3 -1
- package/dist/inspector/sketch/SketchFrameOverlay.js +11 -8
- package/dist/inspector/sketch/SketchLayersPanel.js +13 -5
- package/dist/inspector/sketch/SketchOverlay.js +7 -7
- package/dist/inspector/sketch/SketchWorkspace.js +18 -12
- package/dist/inspector/sketch/interaction.d.ts +1 -0
- package/dist/inspector/sketch/interaction.js +8 -4
- package/dist/inspector/sketch/model.d.ts +5 -0
- package/dist/inspector/sketch/model.js +6 -2
- package/dist/inspector/sketch/raster.d.ts +1 -2
- package/dist/inspector/sketch/raster.js +68 -4
- package/dist/inspector/sketch/store.js +48 -23
- package/dist/inspector/styleEditors/BackgroundEditor.d.ts +4 -0
- package/dist/inspector/styleEditors/BackgroundEditor.js +195 -0
- package/dist/inspector/styleEditors/BorderEditor.js +49 -78
- package/dist/inspector/styleEditors/BorderRadiusEditor.js +6 -1
- package/dist/inspector/styleEditors/BoxShadowEditor.d.ts +1 -2
- package/dist/inspector/styleEditors/BoxShadowEditor.js +132 -4
- package/dist/inspector/styleEditors/ColorPicker.d.ts +5 -1
- package/dist/inspector/styleEditors/ColorPicker.js +10 -4
- package/dist/inspector/styleEditors/GapField.js +3 -5
- package/dist/inspector/styleEditors/GridChildSection.d.ts +1 -1
- package/dist/inspector/styleEditors/GridChildSection.js +18 -9
- package/dist/inspector/styleEditors/GridPicker.d.ts +1 -1
- package/dist/inspector/styleEditors/GridPicker.js +8 -2
- package/dist/inspector/styleEditors/GridSection.js +1 -1
- package/dist/inspector/styleEditors/GridValueField.js +19 -14
- package/dist/inspector/styleEditors/ImageBackgroundEditor.d.ts +18 -0
- package/dist/inspector/styleEditors/ImageBackgroundEditor.js +118 -0
- package/dist/inspector/styleEditors/LayoutBlockedIndicator.d.ts +2 -2
- package/dist/inspector/styleEditors/LayoutBlockedIndicator.js +3 -3
- package/dist/inspector/styleEditors/LayoutComboField.js +6 -4
- package/dist/inspector/styleEditors/LayoutDropdown.js +6 -3
- package/dist/inspector/styleEditors/LayoutSection.js +32 -11
- package/dist/inspector/styleEditors/SpacingBox.js +16 -9
- package/dist/inspector/styleEditors/Typography.js +11 -3
- package/dist/inspector/styleEditors/backgroundLayers.d.ts +24 -0
- package/dist/inspector/styleEditors/backgroundLayers.js +51 -0
- package/dist/inspector/styleEditors/gradientValue.d.ts +17 -0
- package/dist/inspector/styleEditors/gradientValue.js +114 -0
- package/dist/inspector/styleEditors/inlineAuthored.d.ts +10 -0
- package/dist/inspector/styleEditors/inlineAuthored.js +114 -0
- package/dist/inspector/styleEditors/layoutValue.d.ts +0 -8
- package/dist/inspector/styleEditors/layoutValue.js +0 -42
- package/dist/inspector/styleEditors/nudgeValue.d.ts +4 -4
- package/dist/inspector/styleEditors/nudgeValue.js +41 -11
- package/dist/inspector/tokens/TokenField.d.ts +7 -0
- package/dist/inspector/tokens/TokenField.js +49 -22
- package/dist/inspector/tokens/TokenLabel.js +5 -14
- package/dist/inspector/tokens/TokensPanel.js +2 -1
- package/dist/inspector/tokens/dragPointerLock.d.ts +8 -0
- package/dist/inspector/tokens/dragPointerLock.js +70 -0
- package/dist/inspector/tokens/editActions.d.ts +1 -1
- package/dist/inspector/tokens/editActions.js +1 -1
- package/dist/inspector/ui/AtRuleContext.js +4 -6
- package/dist/inspector/ui/Button.d.ts +6 -2
- package/dist/inspector/ui/Button.js +4 -3
- package/dist/inspector/ui/ControlSurface.d.ts +2 -2
- package/dist/inspector/ui/ControlSurface.js +4 -3
- package/dist/inspector/ui/Disclosure.d.ts +22 -0
- package/dist/inspector/ui/Disclosure.js +13 -0
- package/dist/inspector/ui/InlineStyleWarning.d.ts +11 -0
- package/dist/inspector/ui/InlineStyleWarning.js +13 -0
- package/dist/inspector/ui/InspectorPopover.d.ts +2 -1
- package/dist/inspector/ui/InspectorPopover.js +4 -5
- package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
- package/dist/inspector/ui/PopoverListbox.js +8 -7
- package/dist/inspector/ui/SegmentedControl.d.ts +2 -1
- package/dist/inspector/ui/SegmentedControl.js +2 -2
- package/dist/inspector/ui/Select.d.ts +6 -1
- package/dist/inspector/ui/Select.js +7 -11
- package/dist/inspector/ui/SideValuesField.js +1 -1
- package/dist/inspector/ui/Tooltip.d.ts +26 -0
- package/dist/inspector/ui/Tooltip.js +32 -0
- package/dist/inspector/ui/classNames.d.ts +2 -0
- package/dist/inspector/ui/classNames.js +4 -0
- package/dist/inspector/ui/customCursors.d.ts +23 -0
- package/dist/inspector/ui/customCursors.js +122 -0
- package/dist/inspector/ui/dragCursor.d.ts +6 -0
- package/dist/inspector/ui/dragCursor.js +13 -0
- package/dist/inspector/ui/portalContainer.d.ts +2 -0
- package/dist/inspector/ui/portalContainer.js +6 -0
- package/dist/inspector/ui/styles.js +34 -24
- package/dist/inspector/workspace/commands.d.ts +9 -0
- package/dist/inspector/workspace/commands.js +82 -0
- package/dist/inspector/workspace/controller.d.ts +4 -0
- package/dist/inspector/workspace/controller.js +66 -0
- package/dist/inspector/workspace/handoff.d.ts +42 -0
- package/dist/inspector/workspace/handoff.js +115 -0
- package/dist/inspector/workspace/timeline.d.ts +30 -0
- package/dist/inspector/workspace/timeline.js +108 -0
- package/dist/internal/agent-protocol.d.ts +19 -2
- package/dist/internal/agent-protocol.js +13 -0
- package/dist/nudge-ui.mjs +560 -299
- package/dist/project/artifacts.d.ts +13 -0
- package/dist/project/artifacts.js +253 -0
- package/dist/transport/artifacts.d.ts +8 -0
- package/dist/transport/artifacts.js +9 -0
- package/dist/transport/editor.d.ts +20 -1
- package/dist/transport/editor.js +44 -11
- package/dist/transport/routes.d.ts +6 -1
- package/dist/transport/routes.js +6 -1
- package/package.json +6 -2
- package/dist/inspector/changes/workspaceChanges.d.ts +0 -43
- package/dist/inspector/changes/workspaceChanges.js +0 -239
- package/dist/inspector/shell/DomNavigation.d.ts +0 -8
- package/dist/inspector/shell/DomNavigation.js +0 -30
|
@@ -1,18 +1,21 @@
|
|
|
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
3
|
import { PROTOCOL_VERSION, isElementClickMessage, isInlineTextIntentMessage, } from "./frameProtocol.js";
|
|
4
|
-
import {
|
|
4
|
+
import { useCanvasCards } from "./canvasStore.js";
|
|
5
|
+
import { useBoardCamera, useCanvasPresentation, useCanvasPresentationTransitioning, useCanvasLayoutTransitioning, getCanvasLayoutTransitioning, useTemporaryAppInteraction, } from "./viewStore.js";
|
|
5
6
|
import { handleElementClick } from "./rendererSelectionProxy.js";
|
|
6
|
-
import { getSelectedElements, useSelectedElement, useSelectedElements } from "../selection/selectionStore.js";
|
|
7
|
+
import { getSelectedElements, useHierarchy, useSelectedElement, useSelectedElements } from "../selection/selectionStore.js";
|
|
7
8
|
import { readBorderWidths, toRect, } from "../overlay/overlayGeometry.js";
|
|
8
|
-
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-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";
|
|
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";
|
|
9
10
|
import { deleteElement, getDropLocationAtPoint, moveElement, nudgeElement } from "../overlay/structuralGestures.js";
|
|
10
|
-
import {
|
|
11
|
+
import { changeKey } from "../changes/model.js";
|
|
12
|
+
import { getChanges, redo, subscribeChanges, undo } from "../changes/changesLog.js";
|
|
11
13
|
import { resolveSelectionFromElement } from "../selection/resolveSelection.js";
|
|
12
14
|
import { setSelectedElement } from "../selection/selectionStore.js";
|
|
13
15
|
import { clearDropGuide, showDropGuide, useDropGuide } from "../overlay/dropGuide.js";
|
|
14
16
|
import { DropGuideOverlay } from "../overlay/DropGuideOverlay.js";
|
|
15
17
|
import { getMeasurementGeometry } from "../overlay/measurementGeometry.js";
|
|
18
|
+
import { getElementComputedStyle } from "../runtime/domRealm.js";
|
|
16
19
|
import { MeasurementGuideOverlay } from "../overlay/MeasurementGuideOverlay.js";
|
|
17
20
|
import { projectMeasurementSegments } from "./measurementProjection.js";
|
|
18
21
|
import { getRegisteredFrames, PROJECT_ID, WORKSPACE_ID } from "./projection.js";
|
|
@@ -23,8 +26,10 @@ import { setInspectorOpen, toggleInspector } from "../shell/openStore.js";
|
|
|
23
26
|
import { EMPTY_TEXT_PROJECTION_ATTR } from "../projection/textProjection.js";
|
|
24
27
|
import { subscribeCanvasRendererMessages } from "./rendererMessageRouter.js";
|
|
25
28
|
import { setStyles } from "../tokens/editActions.js";
|
|
26
|
-
import { getSpacingAffordanceAtPoint, getSpacingAffordanceForDescriptor, SPACING_GUIDE_HANDLE_LENGTH, spacingValueCss, spacingValueForDrag, } from "../overlay/spacingGestures.js";
|
|
29
|
+
import { getSpacingAffordanceAtPoint, getSpacingAffordanceForDescriptor, getSpacingHoverAtPoint, SPACING_GUIDE_HANDLE_LENGTH, spacingValueCss, spacingValueForDrag, } from "../overlay/spacingGestures.js";
|
|
27
30
|
import { beginLayoutPreview, endLayoutPreview } from "../styleEditors/layoutPreviewState.js";
|
|
31
|
+
import { useNudgeUiRuntimeConfig } from "../runtime/useRuntimeConfig.js";
|
|
32
|
+
import { DomNavigator } from "../overlay/DomNavigator.js";
|
|
28
33
|
function projectRect(iframe, rect, zoom) {
|
|
29
34
|
const frameRect = iframe.getBoundingClientRect();
|
|
30
35
|
return {
|
|
@@ -34,6 +39,20 @@ function projectRect(iframe, rect, zoom) {
|
|
|
34
39
|
height: rect.height * zoom,
|
|
35
40
|
};
|
|
36
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
|
+
}
|
|
49
|
+
function spacingBadgeForDrag(drag, point) {
|
|
50
|
+
return {
|
|
51
|
+
iframe: drag.iframe,
|
|
52
|
+
point: { x: point.x, y: point.y },
|
|
53
|
+
value: drag.currentValue,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
37
56
|
function overlayStyle(rect) {
|
|
38
57
|
return {
|
|
39
58
|
position: "fixed",
|
|
@@ -104,8 +123,8 @@ function clearSpacingDrag(ref) {
|
|
|
104
123
|
if (drag)
|
|
105
124
|
restoreSpacingPreview(drag);
|
|
106
125
|
}
|
|
107
|
-
function applySpacingPreview(drag, point) {
|
|
108
|
-
const value = spacingValueForDrag(drag.affordance, drag.start, point);
|
|
126
|
+
function applySpacingPreview(drag, point, shiftKey = false) {
|
|
127
|
+
const value = spacingValueForDrag(drag.affordance, drag.start, point, shiftKey);
|
|
109
128
|
drag.currentValue = value;
|
|
110
129
|
beginLayoutPreview(drag.element, drag.affordance.property);
|
|
111
130
|
drag.element.style.setProperty(drag.affordance.property, spacingValueCss(value));
|
|
@@ -119,19 +138,95 @@ function restoreSpacingPreview(drag) {
|
|
|
119
138
|
}
|
|
120
139
|
endLayoutPreview(drag.element, drag.affordance.property);
|
|
121
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Commits a managed rule for the drag's final value. Returns the created change
|
|
143
|
+
* records (empty for a no-op drag). The preview inline is intentionally left
|
|
144
|
+
* applied at the committed value once a record exists; the caller must register
|
|
145
|
+
* a PendingSpacingCommit and release it after the renderer acknowledges the
|
|
146
|
+
* projected sheet. Restoring the authored declaration first would flash the old
|
|
147
|
+
* value for the postMessage round trip the sheet takes.
|
|
148
|
+
*/
|
|
122
149
|
function commitSpacingDrag(drag) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return;
|
|
129
|
-
setStyles(drag.element, [{
|
|
150
|
+
if (drag.currentValue === drag.startValue) {
|
|
151
|
+
restoreSpacingPreview(drag);
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
return setStyles(drag.element, [{
|
|
130
155
|
property: drag.affordance.property,
|
|
131
156
|
value: spacingValueCss(drag.currentValue),
|
|
132
157
|
oldRawValue: spacingValueCss(drag.startValue),
|
|
133
158
|
}]);
|
|
134
159
|
}
|
|
160
|
+
/** Removes a deferred preview inline as soon as the projected sheet alone
|
|
161
|
+
* reproduces the committed value; keeps it otherwise and retries on the next
|
|
162
|
+
* projection acknowledgement from that frame. */
|
|
163
|
+
function tryReleasePendingSpacingCommit(commit) {
|
|
164
|
+
const { element, property, committedValue } = commit;
|
|
165
|
+
if (!element.isConnected)
|
|
166
|
+
return true;
|
|
167
|
+
element.style.removeProperty(property);
|
|
168
|
+
const computed = getElementComputedStyle(element).getPropertyValue(property).trim();
|
|
169
|
+
if (computed === committedValue) {
|
|
170
|
+
endLayoutPreview(element, property);
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
element.style.setProperty(property, committedValue);
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
function releasePendingSpacingCommits(pending, iframe) {
|
|
177
|
+
if (pending.length === 0)
|
|
178
|
+
return;
|
|
179
|
+
let write = 0;
|
|
180
|
+
for (const commit of pending) {
|
|
181
|
+
if (commit.iframe !== iframe || !tryReleasePendingSpacingCommit(commit)) {
|
|
182
|
+
pending[write] = commit;
|
|
183
|
+
write += 1;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
pending.length = write;
|
|
187
|
+
}
|
|
188
|
+
/** Restores any held preview inline whose committed rule was undone, reverted,
|
|
189
|
+
* or cleared before its sheet landed. Runs synchronously with the workspace
|
|
190
|
+
* change, so the inline never outlives the intent behind it. */
|
|
191
|
+
function reconcilePendingSpacingCommits(pending) {
|
|
192
|
+
if (pending.length === 0)
|
|
193
|
+
return;
|
|
194
|
+
const survivingKeys = new Set(getChanges().map(changeKey));
|
|
195
|
+
let write = 0;
|
|
196
|
+
for (const commit of pending) {
|
|
197
|
+
if (commit.keys.some((key) => survivingKeys.has(key))) {
|
|
198
|
+
pending[write] = commit;
|
|
199
|
+
write += 1;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
const { element, property, originalInlineValue, originalInlinePriority } = commit;
|
|
203
|
+
if (originalInlineValue) {
|
|
204
|
+
element.style.setProperty(property, originalInlineValue, originalInlinePriority);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
element.style.removeProperty(property);
|
|
208
|
+
}
|
|
209
|
+
endLayoutPreview(element, property);
|
|
210
|
+
}
|
|
211
|
+
pending.length = write;
|
|
212
|
+
}
|
|
213
|
+
/** Registers a held preview inline, folding an older unapplied commit for the
|
|
214
|
+
* same element and property into the newest one so the held value and the
|
|
215
|
+
* authored baseline both stay coherent across rapid successive drags. */
|
|
216
|
+
function pushPendingSpacingCommit(pending, next) {
|
|
217
|
+
const existing = pending.findIndex((commit) => commit.iframe === next.iframe
|
|
218
|
+
&& commit.element === next.element
|
|
219
|
+
&& commit.property === next.property);
|
|
220
|
+
if (existing === -1) {
|
|
221
|
+
pending.push(next);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
pending[existing] = {
|
|
225
|
+
...next,
|
|
226
|
+
originalInlineValue: pending[existing].originalInlineValue,
|
|
227
|
+
originalInlinePriority: pending[existing].originalInlinePriority,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
135
230
|
function sendMeasureModifier(iframe, cardId, altKey) {
|
|
136
231
|
iframe.contentWindow?.postMessage({
|
|
137
232
|
type: "measure-modifier",
|
|
@@ -148,10 +243,20 @@ export function CanvasElementOverlay() {
|
|
|
148
243
|
const [, refreshSelectedGeometry] = useReducer((revision) => revision + 1, 0);
|
|
149
244
|
const selected = useSelectedElement();
|
|
150
245
|
const selectedElements = useSelectedElements();
|
|
246
|
+
const hierarchy = useHierarchy();
|
|
247
|
+
const domNavigationEnabled = useNudgeUiRuntimeConfig().capabilities.domNavigation === true;
|
|
151
248
|
const inlineTextSession = useInlineTextSession();
|
|
152
249
|
const camera = useBoardCamera();
|
|
153
250
|
const presentation = useCanvasPresentation();
|
|
154
251
|
const presentationTransitioning = useCanvasPresentationTransitioning();
|
|
252
|
+
const layoutTransitioning = useCanvasLayoutTransitioning();
|
|
253
|
+
const temporaryAppInteraction = useTemporaryAppInteraction();
|
|
254
|
+
useEffect(() => {
|
|
255
|
+
if (!layoutTransitioning)
|
|
256
|
+
return;
|
|
257
|
+
setHover(null);
|
|
258
|
+
setMeasureState(null);
|
|
259
|
+
}, [layoutTransitioning]);
|
|
155
260
|
const projectionZoom = presentation === "focus" ? 1 : camera.zoom;
|
|
156
261
|
const cards = useCanvasCards(); // Projected geometry must follow card drag and resize updates.
|
|
157
262
|
const cardGeometryKey = cards.map((card) => `${card.id}:${card.x}:${card.y}:${card.width}:${card.height}`).join("|");
|
|
@@ -159,6 +264,8 @@ export function CanvasElementOverlay() {
|
|
|
159
264
|
const previousProjectionGeometryKey = useRef(projectionGeometryKey);
|
|
160
265
|
const dragRef = useRef(null);
|
|
161
266
|
const spacingDragRef = useRef(null);
|
|
267
|
+
const pendingSpacingCommitsRef = useRef([]);
|
|
268
|
+
const [spacingDragBadge, setSpacingDragBadge] = useState(null);
|
|
162
269
|
const measureAltKeyRef = useRef(false);
|
|
163
270
|
const dropGuide = useDropGuide("canvas");
|
|
164
271
|
const projectedDropGuide = projectGuideToCanvas(dropGuide, projectionZoom);
|
|
@@ -241,13 +348,56 @@ export function CanvasElementOverlay() {
|
|
|
241
348
|
const elementId = el.getAttribute(RENDERER_ELEMENT_ID_ATTR);
|
|
242
349
|
return elementId ? { elementId } : null;
|
|
243
350
|
}, [selected?.domElement]);
|
|
351
|
+
// A held spacing preview inline must not outlive the committed rule behind
|
|
352
|
+
// it: undo/redo/revert/clear remove the record synchronously, so restore the
|
|
353
|
+
// authored declaration before the renderer's next replace-styles lands.
|
|
354
|
+
useEffect(() => {
|
|
355
|
+
return subscribeChanges(() => {
|
|
356
|
+
reconcilePendingSpacingCommits(pendingSpacingCommitsRef.current);
|
|
357
|
+
});
|
|
358
|
+
}, []);
|
|
244
359
|
useEffect(() => {
|
|
360
|
+
const refreshSpacingPreviewOverlay = (drag) => {
|
|
361
|
+
const descriptor = {
|
|
362
|
+
kind: drag.affordance.kind,
|
|
363
|
+
property: drag.affordance.property,
|
|
364
|
+
side: drag.affordance.side,
|
|
365
|
+
};
|
|
366
|
+
const affordance = getSpacingAffordanceForDescriptor(drag.element, descriptor);
|
|
367
|
+
const rect = toRect(drag.element.getBoundingClientRect());
|
|
368
|
+
const borders = readBorderWidths(drag.element);
|
|
369
|
+
const elementId = drag.element.getAttribute(RENDERER_ELEMENT_ID_ATTR);
|
|
370
|
+
setHover((current) => {
|
|
371
|
+
if (!current
|
|
372
|
+
|| current.iframe !== drag.iframe
|
|
373
|
+
|| current.identity.elementId !== elementId
|
|
374
|
+
|| !current.spacing
|
|
375
|
+
|| current.spacing.kind !== descriptor.kind
|
|
376
|
+
|| current.spacing.property !== descriptor.property
|
|
377
|
+
|| current.spacing.side !== descriptor.side) {
|
|
378
|
+
return current;
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
...current,
|
|
382
|
+
rect,
|
|
383
|
+
borders,
|
|
384
|
+
spacingGuides: affordance?.affectedGuides ?? [],
|
|
385
|
+
spacingAreas: affordance?.affectedAreas ?? [],
|
|
386
|
+
};
|
|
387
|
+
});
|
|
388
|
+
};
|
|
245
389
|
const unsubscribe = subscribeCanvasRendererMessages(({ cardId: sourceCardId, iframe: sourceIframe, identity: frameIdentity, message: data, }) => {
|
|
246
390
|
if (data.type === "renderer-hello" || data.type === "frame-ready") {
|
|
247
391
|
sendMeasureModifier(sourceIframe, sourceCardId, measureAltKeyRef.current);
|
|
248
392
|
}
|
|
249
393
|
if (data.type === "renderer-hello")
|
|
250
394
|
return;
|
|
395
|
+
if (data.type === "projection-applied") {
|
|
396
|
+
releasePendingSpacingCommits(pendingSpacingCommitsRef.current, sourceIframe);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (getCanvasLayoutTransitioning())
|
|
400
|
+
return;
|
|
251
401
|
if (data.type === "element-hover") {
|
|
252
402
|
const msg = data;
|
|
253
403
|
if (!msg.cid)
|
|
@@ -256,7 +406,7 @@ export function CanvasElementOverlay() {
|
|
|
256
406
|
setHover((current) => current?.cardId === sourceCardId ? null : current);
|
|
257
407
|
return;
|
|
258
408
|
}
|
|
259
|
-
const spacingDescriptor = msg.spacing ?? null;
|
|
409
|
+
const spacingDescriptor = msg.hoverSpacing ?? msg.spacing ?? null;
|
|
260
410
|
const hoverPoint = msg.point ?? null;
|
|
261
411
|
const hoverElement = spacingDescriptor
|
|
262
412
|
? findFrameElement(sourceIframe, msg.elementId, msg.cid, msg.src)
|
|
@@ -264,7 +414,7 @@ export function CanvasElementOverlay() {
|
|
|
264
414
|
const hoverAffordance = spacingDescriptor && hoverElement
|
|
265
415
|
? getSpacingAffordanceForDescriptor(hoverElement, spacingDescriptor)
|
|
266
416
|
: spacingDescriptor && hoverPoint && sourceIframe.contentDocument
|
|
267
|
-
?
|
|
417
|
+
? getSpacingHoverAtPoint(sourceIframe.contentDocument, hoverPoint.x, hoverPoint.y)
|
|
268
418
|
: null;
|
|
269
419
|
const matchingAffordance = spacingDescriptorMatches(hoverAffordance, spacingDescriptor)
|
|
270
420
|
? hoverAffordance
|
|
@@ -321,6 +471,7 @@ export function CanvasElementOverlay() {
|
|
|
321
471
|
}
|
|
322
472
|
else if (data.type === "element-deselect") {
|
|
323
473
|
clearSpacingDrag(spacingDragRef);
|
|
474
|
+
setSpacingDragBadge(null);
|
|
324
475
|
dragRef.current = null;
|
|
325
476
|
clearDropGuide("canvas");
|
|
326
477
|
setSelectedElement(null);
|
|
@@ -357,7 +508,9 @@ export function CanvasElementOverlay() {
|
|
|
357
508
|
const selectedElement = resolveSelectionFromElement(element);
|
|
358
509
|
if (selectedElement)
|
|
359
510
|
setSelectedElement(selectedElement);
|
|
360
|
-
applySpacingPreview(spacingDragRef.current, msg.point);
|
|
511
|
+
applySpacingPreview(spacingDragRef.current, msg.point, msg.shiftKey === true);
|
|
512
|
+
setSpacingDragBadge(spacingBadgeForDrag(spacingDragRef.current, msg.point));
|
|
513
|
+
refreshSpacingPreviewOverlay(spacingDragRef.current);
|
|
361
514
|
return;
|
|
362
515
|
}
|
|
363
516
|
dragRef.current = { iframe: sourceIframe, element };
|
|
@@ -369,7 +522,9 @@ export function CanvasElementOverlay() {
|
|
|
369
522
|
else if (data.type === "element-drag-move") {
|
|
370
523
|
const spacing = spacingDragRef.current;
|
|
371
524
|
if (spacing && spacing.iframe === sourceIframe) {
|
|
372
|
-
applySpacingPreview(spacing, data.point);
|
|
525
|
+
applySpacingPreview(spacing, data.point, data.shiftKey === true);
|
|
526
|
+
setSpacingDragBadge(spacingBadgeForDrag(spacing, data.point));
|
|
527
|
+
refreshSpacingPreviewOverlay(spacing);
|
|
373
528
|
return;
|
|
374
529
|
}
|
|
375
530
|
updateDropGuide(data.point, sourceIframe);
|
|
@@ -379,12 +534,26 @@ export function CanvasElementOverlay() {
|
|
|
379
534
|
const spacing = spacingDragRef.current;
|
|
380
535
|
if (spacing && spacing.iframe === sourceIframe) {
|
|
381
536
|
spacingDragRef.current = null;
|
|
537
|
+
setSpacingDragBadge(null);
|
|
382
538
|
if (msg.cancelled) {
|
|
383
539
|
restoreSpacingPreview(spacing);
|
|
540
|
+
refreshSpacingPreviewOverlay(spacing);
|
|
384
541
|
}
|
|
385
542
|
else {
|
|
386
|
-
applySpacingPreview(spacing, msg.point);
|
|
387
|
-
commitSpacingDrag(spacing);
|
|
543
|
+
applySpacingPreview(spacing, msg.point, msg.shiftKey === true);
|
|
544
|
+
const records = commitSpacingDrag(spacing);
|
|
545
|
+
if (records.length > 0) {
|
|
546
|
+
pushPendingSpacingCommit(pendingSpacingCommitsRef.current, {
|
|
547
|
+
iframe: sourceIframe,
|
|
548
|
+
element: spacing.element,
|
|
549
|
+
property: spacing.affordance.property,
|
|
550
|
+
committedValue: spacingValueCss(spacing.currentValue),
|
|
551
|
+
keys: records.map((record) => changeKey(record)),
|
|
552
|
+
originalInlineValue: spacing.originalInlineValue,
|
|
553
|
+
originalInlinePriority: spacing.originalInlinePriority,
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
refreshSpacingPreviewOverlay(spacing);
|
|
388
557
|
}
|
|
389
558
|
clearDropGuide("canvas");
|
|
390
559
|
if (!msg.cancelled) {
|
|
@@ -458,6 +627,7 @@ export function CanvasElementOverlay() {
|
|
|
458
627
|
unsubscribe();
|
|
459
628
|
clearSpacingDrag(spacingDragRef);
|
|
460
629
|
dragRef.current = null;
|
|
630
|
+
pendingSpacingCommitsRef.current = [];
|
|
461
631
|
clearDropGuide("canvas");
|
|
462
632
|
};
|
|
463
633
|
}, []);
|
|
@@ -468,6 +638,9 @@ export function CanvasElementOverlay() {
|
|
|
468
638
|
const projectedHoverRect = hover ? projectRect(hover.iframe, hover.rect, projectionZoom) : null;
|
|
469
639
|
const projectedSpacingGuides = hover?.spacingGuides.map((guide) => projectRect(hover.iframe, guide, projectionZoom)) ?? [];
|
|
470
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)
|
|
643
|
+
: null;
|
|
471
644
|
const hoverSpacing = hover?.spacing ?? null;
|
|
472
645
|
const measureStateForSelectedFrame = measureState?.iframe === selectedFrame ? measureState : null;
|
|
473
646
|
const hoverInSelectedFrame = hover?.iframe === selectedFrame ? hover : null;
|
|
@@ -479,6 +652,9 @@ export function CanvasElementOverlay() {
|
|
|
479
652
|
const isSelfHover = Boolean(hoverInSelectedFrame
|
|
480
653
|
&& selectedIdentity
|
|
481
654
|
&& hoverInSelectedFrame.identity.elementId === selectedIdentity.elementId);
|
|
655
|
+
// Selected elements already have a live geometry outline. The hover outline
|
|
656
|
+
// is based on a cached renderer message and can lag during spacing previews.
|
|
657
|
+
const showHoverOutline = Boolean(projectedHoverRect && !isSelfHover);
|
|
482
658
|
const showMeasurement = Boolean(showGuideOverlay
|
|
483
659
|
&& selectedLocalRect
|
|
484
660
|
&& hoverInSelectedFrame
|
|
@@ -489,7 +665,9 @@ export function CanvasElementOverlay() {
|
|
|
489
665
|
hoveredBorders: hoverInSelectedFrame.borders,
|
|
490
666
|
}).segments, projectionZoom)
|
|
491
667
|
: [];
|
|
492
|
-
if (presentationTransitioning)
|
|
668
|
+
if (presentationTransitioning || layoutTransitioning || temporaryAppInteraction)
|
|
493
669
|
return _jsx("style", { "data-test": "canvas-element-overlay-styles", children: overlayStyles });
|
|
494
|
-
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, _jsx("div", { className: "canvas-element-overlay", "data-test": "canvas-hover-outline", style: overlayStyle(projectedHoverRect), "aria-hidden": "true" }), 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}`))), _jsx(
|
|
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)
|
|
672
|
+
: 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" })] }));
|
|
495
673
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReactElement, SVGProps } from "react";
|
|
2
|
+
type CanvasToolIconProps = Pick<SVGProps<SVGSVGElement>, "aria-hidden" | "className" | "style"> & {
|
|
3
|
+
readonly size?: string | number;
|
|
4
|
+
};
|
|
5
|
+
export declare function DesignPointerFilledIcon(props: CanvasToolIconProps): ReactElement;
|
|
6
|
+
export declare function SketchThickIcon(props: CanvasToolIconProps): ReactElement;
|
|
7
|
+
export declare function PanHandFilledIcon(props: CanvasToolIconProps): ReactElement;
|
|
8
|
+
export declare function SelectPlayOutlineIcon(props: CanvasToolIconProps): ReactElement;
|
|
9
|
+
export declare function SelectPlayFilledIcon(props: CanvasToolIconProps): ReactElement;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
function ToolIconSvg({ size = 24, children, ...props }) {
|
|
3
|
+
return (_jsx("svg", { viewBox: "0 0 24 24", width: size, height: size, fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: children }));
|
|
4
|
+
}
|
|
5
|
+
export function DesignPointerFilledIcon(props) {
|
|
6
|
+
return (_jsx(ToolIconSvg, { ...props, children: _jsx("path", { d: "M19.8289 10.9379L14.499 12.9999L14.1844 13.1399C13.9474 13.2324 13.7322 13.373 13.5524 13.5529C13.3725 13.7327 13.2319 13.9479 13.1395 14.1849L10.9376 19.8288C10.3047 21.4538 7.97489 21.3668 7.46494 19.6988L3.08331 5.38099C2.65134 3.97101 3.97123 2.65202 5.38111 3.08302L19.6989 7.46496C21.3668 7.97595 21.4537 10.3039 19.8289 10.9379Z", fill: "currentColor" }) }));
|
|
7
|
+
}
|
|
8
|
+
export function SketchThickIcon(props) {
|
|
9
|
+
return (_jsx(ToolIconSvg, { ...props, children: _jsx("path", { d: "M4 15C6 10.03 11.356 4 13 4C17.25 4 7.5 15.958 10 17C12.5 18.042 15.65 10.322 17.4 11.098C19.15 11.875 16.35 18.687 17.1 19.728C17.85 20.769 20.25 18.831 21 17", stroke: "currentColor", strokeWidth: 3, strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
10
|
+
}
|
|
11
|
+
export function PanHandFilledIcon(props) {
|
|
12
|
+
return (_jsx(ToolIconSvg, { ...props, children: _jsx("path", { d: "M12.5 2.5C12.6312 2.50003 12.7616 2.52599 12.8828 2.57617C13.004 2.6264 13.1143 2.70024 13.207 2.79297C13.2998 2.88575 13.3736 2.99599 13.4238 3.11719C13.4741 3.23849 13.5 3.36871 13.5 3.5V12C13.5 12.2761 13.724 12.4999 14 12.5C14.2761 12.4999 14.5 12.2761 14.5 12V5.5C14.5 5.23483 14.6055 4.98049 14.793 4.79297C14.9805 4.60555 15.2349 4.50006 15.5 4.5C15.7651 4.50006 16.0196 4.60555 16.207 4.79297C16.3945 4.98049 16.5 5.23484 16.5 5.5V12C16.5 12.2761 16.724 12.4999 17 12.5C17.2761 12.4999 17.5 12.2761 17.5 12V7.5C17.5 7.23483 17.6055 6.9805 17.793 6.79297C17.9805 6.60555 18.2349 6.50006 18.5 6.5C18.7651 6.50006 19.0196 6.60555 19.207 6.79297C19.3945 6.98049 19.5 7.23484 19.5 7.5V16C19.5 17.4585 18.9208 18.8573 17.8897 19.8887C16.8583 20.9201 15.4586 21.4999 14 21.5H12.208C11.2973 21.5001 10.4005 21.2737 9.59865 20.8418C8.79689 20.4098 8.11519 19.786 7.61427 19.0254C7.54921 18.9264 7.48351 18.8269 7.41896 18.7275C7.11837 18.266 6.03484 16.376 4.15041 13.0264C4.0228 12.7994 3.98801 12.5319 4.0547 12.2803C4.12142 12.0287 4.28463 11.8126 4.50783 11.6787C4.7689 11.5222 5.07483 11.4571 5.37697 11.4941C5.67933 11.5313 5.96123 11.6685 6.17677 11.8838L7.6465 13.3535C7.68032 13.3873 7.71897 13.4135 7.7588 13.4355C7.80294 13.4601 7.85033 13.48 7.90138 13.4902C7.96605 13.5031 8.03299 13.5031 8.09767 13.4902C8.15175 13.4795 8.20178 13.4583 8.24806 13.4316C8.28533 13.4102 8.32167 13.3854 8.35353 13.3535C8.38754 13.3195 8.41341 13.2803 8.43556 13.2402C8.46003 13.196 8.48011 13.1488 8.49025 13.0977C8.49663 13.0654 8.50002 13.0327 8.50002 13V5.5C8.50002 5.23483 8.60551 4.98049 8.79298 4.79297C8.98046 4.60555 9.23493 4.50006 9.50002 4.5C9.7651 4.50006 10.0196 4.60555 10.207 4.79297C10.3945 4.98049 10.5 5.23484 10.5 5.5V12C10.5 12.2761 10.724 12.4999 11 12.5C11.2761 12.4999 11.5 12.2761 11.5 12V3.5C11.5 3.3687 11.526 3.23849 11.5762 3.11719C11.6264 2.99599 11.7002 2.88575 11.793 2.79297C11.8857 2.70024 11.996 2.6264 12.1172 2.57617C12.2384 2.526 12.3688 2.50003 12.5 2.5Z", fill: "currentColor" }) }));
|
|
13
|
+
}
|
|
14
|
+
const SELECT_PLAY_PATH = "M8.5241 4.93791C7.85783 4.52789 7 5.00724 7 5.78956V18.2104C7 18.9928 7.85783 19.4721 8.5241 19.0621L18.6161 12.8517C19.2506 12.4612 19.2506 11.5388 18.6161 11.1483L8.5241 4.93791Z";
|
|
15
|
+
export function SelectPlayOutlineIcon(props) {
|
|
16
|
+
return (_jsx(ToolIconSvg, { ...props, children: _jsx("path", { d: SELECT_PLAY_PATH, stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
17
|
+
}
|
|
18
|
+
export function SelectPlayFilledIcon(props) {
|
|
19
|
+
return (_jsx(ToolIconSvg, { ...props, children: _jsx("path", { d: SELECT_PLAY_PATH, fill: "currentColor", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
20
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { IconMessageCircle, IconMessageCircleFilled, IconPointer2, IconSketching } from "@tabler/icons-react";
|
|
3
3
|
import { IconButton } from "../ui/IconButton.js";
|
|
4
|
+
import { Tooltip } from "../ui/Tooltip.js";
|
|
5
|
+
import { DesignPointerFilledIcon, SelectPlayFilledIcon, SelectPlayOutlineIcon, SketchThickIcon, } from "./CanvasToolIcons.js";
|
|
4
6
|
export const CANVAS_ZOOM_LEVELS = [0.25, 0.5, 0.9, 1];
|
|
5
7
|
export function closestCanvasZoomLevel(zoom) {
|
|
6
8
|
let closest = CANVAS_ZOOM_LEVELS[0];
|
|
@@ -16,9 +18,11 @@ export function adjacentCanvasZoomLevel(zoom, direction) {
|
|
|
16
18
|
const next = CANVAS_ZOOM_LEVELS[index + direction];
|
|
17
19
|
return next === undefined ? null : next;
|
|
18
20
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
const ICON_SIZE = "var(--icon-size-large)";
|
|
22
|
+
function ToolButton({ tool, activeTool, disabled, label, shortcut, icon, activeIcon, onToolChange, }) {
|
|
23
|
+
const active = tool === activeTool;
|
|
24
|
+
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 }) }));
|
|
21
25
|
}
|
|
22
26
|
export function CanvasToolbar({ tool, sketchEnabled, onToolChange, }) {
|
|
23
|
-
return (
|
|
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 }) })] }));
|
|
24
28
|
}
|