nudge-ui 0.2.2 → 0.2.4
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 +260 -61
- 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 +38 -32
- package/dist/hosts/astro/integration.js +5 -1
- package/dist/hosts/astro/markdownIdentity.d.ts +28 -0
- package/dist/hosts/astro/markdownIdentity.js +81 -0
- package/dist/hosts/next/manifest.js +1 -1
- package/dist/hosts/next/sidecar.js +5 -1
- package/dist/hosts/static/manifest.js +1 -1
- package/dist/hosts/static/server.js +3 -0
- package/dist/hosts/vite/vite.d.ts +3 -0
- package/dist/hosts/vite/vite.js +24 -4
- package/dist/inspector/agent/McpConnectionDialog.js +13 -19
- package/dist/inspector/agent/activity.d.ts +18 -0
- package/dist/inspector/agent/activity.js +70 -0
- package/dist/inspector/agent/client.d.ts +2 -0
- package/dist/inspector/agent/client.js +29 -1
- package/dist/inspector/agent/connectionStatus.js +1 -1
- package/dist/inspector/agent/httpTransport.js +9 -2
- package/dist/inspector/agent/protocol.d.ts +6 -3
- package/dist/inspector/agent/protocol.js +1 -1
- package/dist/inspector/agent/verification.d.ts +15 -7
- package/dist/inspector/agent/verification.js +113 -41
- 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 +135 -38
- package/dist/inspector/canvas/CanvasElementOverlay.js +166 -16
- 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 +270 -122
- 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 +21 -4
- package/dist/inspector/canvas/frameProtocol.js +3 -3
- package/dist/inspector/canvas/frameScrollbarStyles.d.ts +3 -0
- package/dist/inspector/canvas/frameScrollbarStyles.js +21 -0
- package/dist/inspector/canvas/keyboardShortcuts.d.ts +3 -1
- package/dist/inspector/canvas/keyboardShortcuts.js +4 -4
- package/dist/inspector/canvas/layout.d.ts +52 -0
- package/dist/inspector/canvas/layout.js +106 -0
- package/dist/inspector/canvas/projection.d.ts +15 -5
- package/dist/inspector/canvas/projection.js +69 -13
- package/dist/inspector/canvas/rendererBootstrap.js +32 -4
- package/dist/inspector/canvas/rendererElementSelector.js +47 -6
- 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 +9 -6
- package/dist/inspector/changes/changesLog.js +48 -32
- package/dist/inspector/changes/codecs.d.ts +1 -0
- package/dist/inspector/changes/codecs.js +10 -1
- package/dist/inspector/changes/draftChanges.d.ts +58 -0
- package/dist/inspector/changes/draftChanges.js +304 -0
- package/dist/inspector/changes/editModel.d.ts +10 -0
- package/dist/inspector/changes/editModel.js +9 -2
- package/dist/inspector/changes/previewDiagnostics.d.ts +4 -2
- package/dist/inspector/changes/previewDiagnostics.js +11 -25
- package/dist/inspector/changes/types.d.ts +7 -0
- package/dist/inspector/clientManifest.d.ts +1 -1
- 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 +54 -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/componentSemantics/adapterRegistry.d.ts +6 -1
- package/dist/inspector/componentSemantics/adapterRegistry.js +23 -1
- package/dist/inspector/componentSemantics/reactRuntime.d.ts +2 -1
- package/dist/inspector/componentSemantics/reactRuntime.js +38 -0
- package/dist/inspector/componentSemantics/runtimeBridge.d.ts +4 -2
- package/dist/inspector/componentSemantics/runtimeBridge.js +17 -0
- package/dist/inspector/componentSemantics/types.d.ts +11 -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 +20 -27
- 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 +174 -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.js +21 -15
- package/dist/inspector/overlay/interactionStyles.js +3 -1
- package/dist/inspector/overlay/spacingGestures.d.ts +13 -1
- package/dist/inspector/overlay/spacingGestures.js +82 -5
- 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 +17 -3
- package/dist/inspector/projection/renderedInstance.js +62 -11
- package/dist/inspector/projection/structuralProjection.d.ts +2 -1
- package/dist/inspector/projection/structuralProjection.js +21 -17
- package/dist/inspector/projection/textProjection.d.ts +2 -1
- package/dist/inspector/projection/textProjection.js +64 -15
- package/dist/inspector/prompt/PromptSettingsDialog.js +1 -5
- package/dist/inspector/prompt/clipboardHandoff.d.ts +15 -18
- package/dist/inspector/prompt/clipboardHandoff.js +97 -143
- package/dist/inspector/prompt/generatePrompt.d.ts +4 -1
- package/dist/inspector/prompt/generatePrompt.js +22 -17
- package/dist/inspector/runtime/runtimeConfig.d.ts +9 -0
- package/dist/inspector/runtime/runtimeConfig.js +24 -0
- package/dist/inspector/selection/sourceSite.d.ts +12 -0
- package/dist/inspector/selection/sourceSite.js +28 -0
- package/dist/inspector/settings/SettingsDialog.js +21 -8
- 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 +46 -26
- package/dist/inspector/shell/CopyPromptButton.js +184 -93
- package/dist/inspector/shell/EmptyState.js +9 -8
- package/dist/inspector/shell/InspectorShell.js +13 -21
- 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/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 +7 -5
- 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 +2 -2
- package/dist/inspector/styleEditors/nudgeValue.js +36 -8
- package/dist/inspector/tokens/TokenField.d.ts +7 -0
- package/dist/inspector/tokens/TokenField.js +35 -25
- package/dist/inspector/tokens/TokenLabel.js +5 -14
- package/dist/inspector/tokens/editActions.d.ts +1 -1
- package/dist/inspector/tokens/editActions.js +7 -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/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 +0 -2
- package/dist/inspector/ui/dragCursor.js +2 -10
- package/dist/inspector/ui/portalContainer.d.ts +2 -0
- package/dist/inspector/ui/portalContainer.js +6 -0
- package/dist/inspector/ui/styles.js +29 -21
- 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/sentItems.d.ts +19 -0
- package/dist/inspector/workspace/sentItems.js +51 -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 +558 -311
- 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.js +3 -1
- package/dist/transport/routes.d.ts +2 -0
- package/dist/transport/routes.js +2 -0
- package/package.json +7 -3
- package/dist/inspector/changes/workspaceChanges.d.ts +0 -47
- package/dist/inspector/changes/workspaceChanges.js +0 -265
|
@@ -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
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,7 +26,7 @@ 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";
|
|
28
31
|
import { useNudgeUiRuntimeConfig } from "../runtime/useRuntimeConfig.js";
|
|
29
32
|
import { DomNavigator } from "../overlay/DomNavigator.js";
|
|
@@ -36,6 +39,20 @@ function projectRect(iframe, rect, zoom) {
|
|
|
36
39
|
height: rect.height * zoom,
|
|
37
40
|
};
|
|
38
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
|
+
}
|
|
39
56
|
function overlayStyle(rect) {
|
|
40
57
|
return {
|
|
41
58
|
position: "fixed",
|
|
@@ -121,19 +138,95 @@ function restoreSpacingPreview(drag) {
|
|
|
121
138
|
}
|
|
122
139
|
endLayoutPreview(drag.element, drag.affordance.property);
|
|
123
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
|
+
*/
|
|
124
149
|
function commitSpacingDrag(drag) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return;
|
|
131
|
-
setStyles(drag.element, [{
|
|
150
|
+
if (drag.currentValue === drag.startValue) {
|
|
151
|
+
restoreSpacingPreview(drag);
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
return setStyles(drag.element, [{
|
|
132
155
|
property: drag.affordance.property,
|
|
133
156
|
value: spacingValueCss(drag.currentValue),
|
|
134
157
|
oldRawValue: spacingValueCss(drag.startValue),
|
|
135
158
|
}]);
|
|
136
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
|
+
}
|
|
137
230
|
function sendMeasureModifier(iframe, cardId, altKey) {
|
|
138
231
|
iframe.contentWindow?.postMessage({
|
|
139
232
|
type: "measure-modifier",
|
|
@@ -156,6 +249,14 @@ export function CanvasElementOverlay() {
|
|
|
156
249
|
const camera = useBoardCamera();
|
|
157
250
|
const presentation = useCanvasPresentation();
|
|
158
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]);
|
|
159
260
|
const projectionZoom = presentation === "focus" ? 1 : camera.zoom;
|
|
160
261
|
const cards = useCanvasCards(); // Projected geometry must follow card drag and resize updates.
|
|
161
262
|
const cardGeometryKey = cards.map((card) => `${card.id}:${card.x}:${card.y}:${card.width}:${card.height}`).join("|");
|
|
@@ -163,6 +264,8 @@ export function CanvasElementOverlay() {
|
|
|
163
264
|
const previousProjectionGeometryKey = useRef(projectionGeometryKey);
|
|
164
265
|
const dragRef = useRef(null);
|
|
165
266
|
const spacingDragRef = useRef(null);
|
|
267
|
+
const pendingSpacingCommitsRef = useRef([]);
|
|
268
|
+
const [spacingDragBadge, setSpacingDragBadge] = useState(null);
|
|
166
269
|
const measureAltKeyRef = useRef(false);
|
|
167
270
|
const dropGuide = useDropGuide("canvas");
|
|
168
271
|
const projectedDropGuide = projectGuideToCanvas(dropGuide, projectionZoom);
|
|
@@ -245,6 +348,14 @@ export function CanvasElementOverlay() {
|
|
|
245
348
|
const elementId = el.getAttribute(RENDERER_ELEMENT_ID_ATTR);
|
|
246
349
|
return elementId ? { elementId } : null;
|
|
247
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
|
+
}, []);
|
|
248
359
|
useEffect(() => {
|
|
249
360
|
const refreshSpacingPreviewOverlay = (drag) => {
|
|
250
361
|
const descriptor = {
|
|
@@ -272,6 +383,9 @@ export function CanvasElementOverlay() {
|
|
|
272
383
|
borders,
|
|
273
384
|
spacingGuides: affordance?.affectedGuides ?? [],
|
|
274
385
|
spacingAreas: affordance?.affectedAreas ?? [],
|
|
386
|
+
spacingHandleBadge: current.spacingHandleBadge && affordance
|
|
387
|
+
? { ...current.spacingHandleBadge, value: affordance.value }
|
|
388
|
+
: current.spacingHandleBadge,
|
|
275
389
|
};
|
|
276
390
|
});
|
|
277
391
|
};
|
|
@@ -281,6 +395,12 @@ export function CanvasElementOverlay() {
|
|
|
281
395
|
}
|
|
282
396
|
if (data.type === "renderer-hello")
|
|
283
397
|
return;
|
|
398
|
+
if (data.type === "projection-applied") {
|
|
399
|
+
releasePendingSpacingCommits(pendingSpacingCommitsRef.current, sourceIframe);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
if (getCanvasLayoutTransitioning())
|
|
403
|
+
return;
|
|
284
404
|
if (data.type === "element-hover") {
|
|
285
405
|
const msg = data;
|
|
286
406
|
if (!msg.cid)
|
|
@@ -289,7 +409,7 @@ export function CanvasElementOverlay() {
|
|
|
289
409
|
setHover((current) => current?.cardId === sourceCardId ? null : current);
|
|
290
410
|
return;
|
|
291
411
|
}
|
|
292
|
-
const spacingDescriptor = msg.spacing ?? null;
|
|
412
|
+
const spacingDescriptor = msg.hoverSpacing ?? msg.spacing ?? null;
|
|
293
413
|
const hoverPoint = msg.point ?? null;
|
|
294
414
|
const hoverElement = spacingDescriptor
|
|
295
415
|
? findFrameElement(sourceIframe, msg.elementId, msg.cid, msg.src)
|
|
@@ -297,13 +417,21 @@ export function CanvasElementOverlay() {
|
|
|
297
417
|
const hoverAffordance = spacingDescriptor && hoverElement
|
|
298
418
|
? getSpacingAffordanceForDescriptor(hoverElement, spacingDescriptor)
|
|
299
419
|
: spacingDescriptor && hoverPoint && sourceIframe.contentDocument
|
|
300
|
-
?
|
|
420
|
+
? getSpacingHoverAtPoint(sourceIframe.contentDocument, hoverPoint.x, hoverPoint.y)
|
|
301
421
|
: null;
|
|
302
422
|
const matchingAffordance = spacingDescriptorMatches(hoverAffordance, spacingDescriptor)
|
|
303
423
|
? hoverAffordance
|
|
304
424
|
: null;
|
|
305
425
|
const spacingGuides = matchingAffordance?.affectedGuides ?? [];
|
|
306
426
|
const spacingAreas = matchingAffordance?.affectedAreas ?? [];
|
|
427
|
+
const handleAffordance = msg.spacing && hoverElement
|
|
428
|
+
? getSpacingAffordanceForDescriptor(hoverElement, msg.spacing)
|
|
429
|
+
: null;
|
|
430
|
+
const spacingHandleBadge = hoverPoint
|
|
431
|
+
&& handleAffordance
|
|
432
|
+
&& spacingDescriptorMatches(handleAffordance, msg.spacing)
|
|
433
|
+
? { point: hoverPoint, value: handleAffordance.value }
|
|
434
|
+
: null;
|
|
307
435
|
setHover({
|
|
308
436
|
iframe: sourceIframe,
|
|
309
437
|
identity: { elementId: msg.elementId },
|
|
@@ -313,6 +441,7 @@ export function CanvasElementOverlay() {
|
|
|
313
441
|
spacing: spacingGuides.length > 0 ? spacingDescriptor : null,
|
|
314
442
|
spacingGuides,
|
|
315
443
|
spacingAreas,
|
|
444
|
+
spacingHandleBadge,
|
|
316
445
|
});
|
|
317
446
|
}
|
|
318
447
|
else if (data.type === "element-measure-state") {
|
|
@@ -354,6 +483,7 @@ export function CanvasElementOverlay() {
|
|
|
354
483
|
}
|
|
355
484
|
else if (data.type === "element-deselect") {
|
|
356
485
|
clearSpacingDrag(spacingDragRef);
|
|
486
|
+
setSpacingDragBadge(null);
|
|
357
487
|
dragRef.current = null;
|
|
358
488
|
clearDropGuide("canvas");
|
|
359
489
|
setSelectedElement(null);
|
|
@@ -391,6 +521,7 @@ export function CanvasElementOverlay() {
|
|
|
391
521
|
if (selectedElement)
|
|
392
522
|
setSelectedElement(selectedElement);
|
|
393
523
|
applySpacingPreview(spacingDragRef.current, msg.point, msg.shiftKey === true);
|
|
524
|
+
setSpacingDragBadge(spacingBadgeForDrag(spacingDragRef.current, msg.point));
|
|
394
525
|
refreshSpacingPreviewOverlay(spacingDragRef.current);
|
|
395
526
|
return;
|
|
396
527
|
}
|
|
@@ -404,6 +535,7 @@ export function CanvasElementOverlay() {
|
|
|
404
535
|
const spacing = spacingDragRef.current;
|
|
405
536
|
if (spacing && spacing.iframe === sourceIframe) {
|
|
406
537
|
applySpacingPreview(spacing, data.point, data.shiftKey === true);
|
|
538
|
+
setSpacingDragBadge(spacingBadgeForDrag(spacing, data.point));
|
|
407
539
|
refreshSpacingPreviewOverlay(spacing);
|
|
408
540
|
return;
|
|
409
541
|
}
|
|
@@ -414,13 +546,25 @@ export function CanvasElementOverlay() {
|
|
|
414
546
|
const spacing = spacingDragRef.current;
|
|
415
547
|
if (spacing && spacing.iframe === sourceIframe) {
|
|
416
548
|
spacingDragRef.current = null;
|
|
549
|
+
setSpacingDragBadge(null);
|
|
417
550
|
if (msg.cancelled) {
|
|
418
551
|
restoreSpacingPreview(spacing);
|
|
419
552
|
refreshSpacingPreviewOverlay(spacing);
|
|
420
553
|
}
|
|
421
554
|
else {
|
|
422
555
|
applySpacingPreview(spacing, msg.point, msg.shiftKey === true);
|
|
423
|
-
commitSpacingDrag(spacing);
|
|
556
|
+
const records = commitSpacingDrag(spacing);
|
|
557
|
+
if (records.length > 0) {
|
|
558
|
+
pushPendingSpacingCommit(pendingSpacingCommitsRef.current, {
|
|
559
|
+
iframe: sourceIframe,
|
|
560
|
+
element: spacing.element,
|
|
561
|
+
property: spacing.affordance.property,
|
|
562
|
+
committedValue: spacingValueCss(spacing.currentValue),
|
|
563
|
+
keys: records.map((record) => changeKey(record)),
|
|
564
|
+
originalInlineValue: spacing.originalInlineValue,
|
|
565
|
+
originalInlinePriority: spacing.originalInlinePriority,
|
|
566
|
+
});
|
|
567
|
+
}
|
|
424
568
|
refreshSpacingPreviewOverlay(spacing);
|
|
425
569
|
}
|
|
426
570
|
clearDropGuide("canvas");
|
|
@@ -495,6 +639,7 @@ export function CanvasElementOverlay() {
|
|
|
495
639
|
unsubscribe();
|
|
496
640
|
clearSpacingDrag(spacingDragRef);
|
|
497
641
|
dragRef.current = null;
|
|
642
|
+
pendingSpacingCommitsRef.current = [];
|
|
498
643
|
clearDropGuide("canvas");
|
|
499
644
|
};
|
|
500
645
|
}, []);
|
|
@@ -505,6 +650,11 @@ export function CanvasElementOverlay() {
|
|
|
505
650
|
const projectedHoverRect = hover ? projectRect(hover.iframe, hover.rect, projectionZoom) : null;
|
|
506
651
|
const projectedSpacingGuides = hover?.spacingGuides.map((guide) => projectRect(hover.iframe, guide, projectionZoom)) ?? [];
|
|
507
652
|
const projectedSpacingAreas = hover?.spacingAreas.map((area) => projectRect(hover.iframe, area, projectionZoom)) ?? [];
|
|
653
|
+
const spacingBadge = spacingDragBadge
|
|
654
|
+
?? (hover?.spacingHandleBadge ? { iframe: hover.iframe, ...hover.spacingHandleBadge } : null);
|
|
655
|
+
const projectedSpacingBadge = spacingBadge
|
|
656
|
+
? projectPoint(spacingBadge.iframe, spacingBadge.point.x, spacingBadge.point.y, projectionZoom)
|
|
657
|
+
: null;
|
|
508
658
|
const hoverSpacing = hover?.spacing ?? null;
|
|
509
659
|
const measureStateForSelectedFrame = measureState?.iframe === selectedFrame ? measureState : null;
|
|
510
660
|
const hoverInSelectedFrame = hover?.iframe === selectedFrame ? hover : null;
|
|
@@ -529,9 +679,9 @@ export function CanvasElementOverlay() {
|
|
|
529
679
|
hoveredBorders: hoverInSelectedFrame.borders,
|
|
530
680
|
}).segments, projectionZoom)
|
|
531
681
|
: [];
|
|
532
|
-
if (presentationTransitioning)
|
|
682
|
+
if (presentationTransitioning || layoutTransitioning || temporaryAppInteraction)
|
|
533
683
|
return _jsx("style", { "data-test": "canvas-element-overlay-styles", children: overlayStyles });
|
|
534
|
-
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}`))), 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
|
|
684
|
+
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 && 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 && selectedFrame instanceof HTMLIFrameElement ? (_jsx(DomNavigator, { selected: selected, hierarchy: hierarchy, anchor: selectedRect, project: (element) => element.ownerDocument === selected.domElement.ownerDocument
|
|
535
685
|
? projectRect(selectedFrame, toRect(element.getBoundingClientRect()), projectionZoom)
|
|
536
686
|
: 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" })] }));
|
|
537
687
|
}
|
|
@@ -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 (_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, {
|
|
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
|
}
|