nudge-ui 0.2.2 → 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 -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 +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 +152 -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 +225 -57
- 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/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 +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 +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 +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 +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 +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.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 +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 +9 -0
- package/dist/inspector/runtime/runtimeConfig.js +24 -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 +138 -89
- 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 +29 -21
- package/dist/inspector/tokens/TokenLabel.js +5 -14
- 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/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/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 +6 -2
- package/dist/inspector/changes/workspaceChanges.d.ts +0 -47
- package/dist/inspector/changes/workspaceChanges.js +0 -265
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { AgentActivityOverlay } from "./AgentActivityOverlay.js";
|
|
3
|
+
import { contentDocumentUrl, contentNavigationUrl, contentSourceUrl, iterationId } from "./frameContent.js";
|
|
4
|
+
import { refreshHtmlIteration } from "../iterations/coordinator.js";
|
|
2
5
|
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
3
6
|
import { CANVAS_RENDERER_ATTR } from "./roleDetection.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
7
|
+
import { useCanvasCards, getCanvasCardLabel, updateCardUrl, resizeCard, setCardPosition, selectCard, getSelectedCardId, useSelectedCardId, useFocusedCardId, } from "./canvasStore.js";
|
|
8
|
+
import { useBoardCamera } from "./viewStore.js";
|
|
9
|
+
import { IconArrowsDiagonal, IconCopy, IconCornerLeftDown, IconBoltFilled, IconArtboard, IconTrash } from "@tabler/icons-react";
|
|
6
10
|
import { PROTOCOL_VERSION, } from "./frameProtocol.js";
|
|
7
11
|
import { registerCardFrame, registerCardFrameSource, unregisterCardFrame, sendProjectionToCard, invalidateCanvasPreviewDocument, PROJECT_ID, WORKSPACE_ID } from "./projection.js";
|
|
8
12
|
import { Button } from "../ui/Button.js";
|
|
13
|
+
import { IconButton } from "../ui/IconButton.js";
|
|
14
|
+
import { Tooltip } from "../ui/Tooltip.js";
|
|
9
15
|
import { setSelectedElement } from "../selection/selectionStore.js";
|
|
10
16
|
import { clearCanvasStructuralProjectionReports } from "../projection/structuralProjection.js";
|
|
11
17
|
import { clearCanvasRenderedInstanceProjectionReports } from "../projection/renderedInstance.js";
|
|
@@ -15,12 +21,16 @@ import { getCanvasResizeHandleScale } from "./resizeHandleScale.js";
|
|
|
15
21
|
import { disposeBrowserCssInspection } from "../inspection/browserCssInspectionRegistry.js";
|
|
16
22
|
import { releaseDocumentProjection } from "../projection/structuralProjection.js";
|
|
17
23
|
import { startClipboardHandoffController } from "../prompt/clipboardHandoff.js";
|
|
18
|
-
import { disposeInlineTextEdit } from "../inline-text/inlineTextEditor.js";
|
|
24
|
+
import { disposeInlineTextEdit, isInlineTextEditingActive } from "../inline-text/inlineTextEditor.js";
|
|
19
25
|
import { configureNudgeUiRuntime, getNudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
|
|
26
|
+
import { useNudgeUiRuntimeConfig } from "../runtime/useRuntimeConfig.js";
|
|
20
27
|
import { reconcileRuntimeWithDocumentStylesheets } from "../runtime/documentStylesheetOrder.js";
|
|
21
28
|
import { subscribeCanvasRendererMessages } from "./rendererMessageRouter.js";
|
|
22
29
|
import { SketchFrameOverlay } from "../sketch/SketchFrameOverlay.js";
|
|
23
30
|
import { getCanvasResizeEdges, resizeCanvasRect, } from "./canvasResize.js";
|
|
31
|
+
import { getDraftContentsForCard } from "../drafts/store.js";
|
|
32
|
+
import { removeFrame } from "../workspace/commands.js";
|
|
33
|
+
import { artifactDocumentUrl } from "../iterations/client.js";
|
|
24
34
|
const RESIZE_HANDLES = [
|
|
25
35
|
{ direction: "top-left", cursor: "nwse-resize", transformOrigin: "left top", label: "Resize card from the top-left corner" },
|
|
26
36
|
{ direction: "top", cursor: "ns-resize", transformOrigin: "center top", label: "Resize card from the top edge" },
|
|
@@ -38,15 +48,23 @@ function resizeHandleTransform(direction, scale) {
|
|
|
38
48
|
return `scale(${scale}, 1)`;
|
|
39
49
|
return `scale(${scale})`;
|
|
40
50
|
}
|
|
41
|
-
export function CanvasCard({ card, presentation = "canvas", presentationCard = true, onShowFocus, documentOwner }) {
|
|
51
|
+
export function CanvasCard({ card, presentation = "canvas", presentationCard = true, linkedToActive = false, onShowFocus, onDuplicate, onCreateIteration, documentOwner }) {
|
|
42
52
|
const iframeRef = useRef(null);
|
|
43
|
-
const initialUrlRef = useRef(card.
|
|
44
|
-
const navigationUrlRef = useRef(card.
|
|
53
|
+
const initialUrlRef = useRef(contentNavigationUrl(card.content) ?? contentSourceUrl(card.content));
|
|
54
|
+
const navigationUrlRef = useRef(contentNavigationUrl(card.content));
|
|
45
55
|
const documentSessionRef = useRef(null);
|
|
46
56
|
const frameRuntimeRef = useRef(null);
|
|
47
57
|
const [loadState, setLoadState] = useState("loading");
|
|
48
58
|
const [errorMessage, setErrorMessage] = useState(null);
|
|
59
|
+
const [creatingIteration, setCreatingIteration] = useState(false);
|
|
60
|
+
const [iterationError, setIterationError] = useState(null);
|
|
49
61
|
const camera = useBoardCamera();
|
|
62
|
+
const runtimeConfig = useNudgeUiRuntimeConfig();
|
|
63
|
+
const canvasCards = useCanvasCards();
|
|
64
|
+
const canRemove = canvasCards.length > 1;
|
|
65
|
+
const frameLabel = runtimeConfig.demo === true && runtimeConfig.demoCardLabels?.length && card.title
|
|
66
|
+
? card.title
|
|
67
|
+
: getCanvasCardLabel(card, canvasCards);
|
|
50
68
|
const selectedCardId = useSelectedCardId();
|
|
51
69
|
const focusedCardId = useFocusedCardId();
|
|
52
70
|
const isSelected = selectedCardId === card.id;
|
|
@@ -94,22 +112,59 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
94
112
|
disposeDocumentSession();
|
|
95
113
|
unregisterCardFrame(card.id);
|
|
96
114
|
};
|
|
97
|
-
}, [bindDocumentSession, card.id, disposeDocumentSession]);
|
|
115
|
+
}, [bindDocumentSession, card.id, iterationId(card.content), disposeDocumentSession]);
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
if (card.content.kind !== "iteration" || loadState !== "ready")
|
|
118
|
+
return;
|
|
119
|
+
const artifactId = card.content.artifactId;
|
|
120
|
+
let active = true;
|
|
121
|
+
let checking = false;
|
|
122
|
+
let reloadPending = false;
|
|
123
|
+
const timer = window.setInterval(() => {
|
|
124
|
+
const workspace = getDraftContentsForCard(card.id);
|
|
125
|
+
// Pending inspector edits still project over preview.html. Do not replace
|
|
126
|
+
// that base until they have been saved and handed off.
|
|
127
|
+
if (checking || isInlineTextEditingActive() || workspace?.changes.length || workspace?.structuralChanges.length)
|
|
128
|
+
return;
|
|
129
|
+
checking = true;
|
|
130
|
+
const frame = iframeRef.current;
|
|
131
|
+
if (!frame) {
|
|
132
|
+
checking = false;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
void refreshHtmlIteration(card.id, artifactId, frame).then((changed) => {
|
|
136
|
+
reloadPending ||= changed;
|
|
137
|
+
const latest = getDraftContentsForCard(card.id);
|
|
138
|
+
if (active && reloadPending && !isInlineTextEditingActive() && !latest?.changes.length && !latest?.structuralChanges.length) {
|
|
139
|
+
reloadPending = false;
|
|
140
|
+
loadFrame(`${artifactDocumentUrl(artifactId)}?revision=${Date.now()}`);
|
|
141
|
+
}
|
|
142
|
+
}).catch(() => undefined).finally(() => { checking = false; });
|
|
143
|
+
}, 1500);
|
|
144
|
+
return () => { active = false; window.clearInterval(timer); };
|
|
145
|
+
}, [iterationId(card.content), card.id, loadFrame, loadState]);
|
|
98
146
|
function handleReload() {
|
|
99
147
|
loadFrame();
|
|
100
148
|
}
|
|
101
149
|
function handleRemove() {
|
|
102
150
|
if (getSelectedCardId() === card.id)
|
|
103
151
|
setSelectedElement(null);
|
|
104
|
-
|
|
152
|
+
removeFrame(card.id);
|
|
105
153
|
}
|
|
106
|
-
function
|
|
107
|
-
if (!
|
|
108
|
-
return;
|
|
109
|
-
const runtime = getNudgeUiRuntimeConfig();
|
|
110
|
-
if (runtime.demo === true && (runtime.demoCardLabels?.length ?? 0) > 0)
|
|
154
|
+
async function handleIteration(position) {
|
|
155
|
+
if (creatingIteration || !onCreateIteration || loadState !== "ready")
|
|
111
156
|
return;
|
|
112
|
-
|
|
157
|
+
setCreatingIteration(true);
|
|
158
|
+
setIterationError(null);
|
|
159
|
+
try {
|
|
160
|
+
return await onCreateIteration(card.id, position);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
setIterationError(error instanceof Error ? error.message : "The iteration could not be created.");
|
|
164
|
+
}
|
|
165
|
+
finally {
|
|
166
|
+
setCreatingIteration(false);
|
|
167
|
+
}
|
|
113
168
|
}
|
|
114
169
|
/** The controller half of the handshake: announce workspace identity. */
|
|
115
170
|
function sendParentReady() {
|
|
@@ -158,8 +213,7 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
158
213
|
adoptFrameRuntime(data.runtime);
|
|
159
214
|
setLoadState("ready");
|
|
160
215
|
setErrorMessage(null);
|
|
161
|
-
|
|
162
|
-
if (data.url)
|
|
216
|
+
if (data.url && !iterationId(card.content))
|
|
163
217
|
updateCardUrl(card.id, data.url);
|
|
164
218
|
if (iframeRef.current) {
|
|
165
219
|
registerCardFrame(card.id, iframeRef.current);
|
|
@@ -172,8 +226,7 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
172
226
|
return;
|
|
173
227
|
}
|
|
174
228
|
if (data.type === "frame-metadata") {
|
|
175
|
-
|
|
176
|
-
if (data.url)
|
|
229
|
+
if (data.url && !iterationId(card.content))
|
|
177
230
|
updateCardUrl(card.id, data.url);
|
|
178
231
|
return;
|
|
179
232
|
}
|
|
@@ -182,13 +235,13 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
182
235
|
setErrorMessage(data.message || "Frame failed to load");
|
|
183
236
|
}
|
|
184
237
|
});
|
|
185
|
-
}, [card.id]);
|
|
238
|
+
}, [card.id, iterationId(card.content)]);
|
|
186
239
|
useLayoutEffect(() => {
|
|
187
|
-
if (!card.
|
|
240
|
+
if (!contentNavigationUrl(card.content) || navigationUrlRef.current === contentNavigationUrl(card.content))
|
|
188
241
|
return;
|
|
189
|
-
navigationUrlRef.current = card.
|
|
190
|
-
loadFrame(card.
|
|
191
|
-
}, [card.
|
|
242
|
+
navigationUrlRef.current = contentNavigationUrl(card.content);
|
|
243
|
+
loadFrame(contentNavigationUrl(card.content));
|
|
244
|
+
}, [contentNavigationUrl(card.content), loadFrame]);
|
|
192
245
|
useEffect(() => {
|
|
193
246
|
if (loadState !== "loading")
|
|
194
247
|
return;
|
|
@@ -220,12 +273,13 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
220
273
|
}
|
|
221
274
|
iframe.addEventListener("load", onLoad);
|
|
222
275
|
return () => iframe.removeEventListener("load", onLoad);
|
|
223
|
-
}, [bindDocumentSession, card.id, disposeDocumentSession]);
|
|
276
|
+
}, [bindDocumentSession, card.id, iterationId(card.content), disposeDocumentSession]);
|
|
224
277
|
const [isDragging, setIsDragging] = useState(false);
|
|
225
278
|
const dragRef = useRef({ startX: 0, startY: 0, cardX: 0, cardY: 0 });
|
|
279
|
+
const dragCleanupRef = useRef(null);
|
|
226
280
|
const resizeCleanupRef = useRef(null);
|
|
227
281
|
useEffect(() => {
|
|
228
|
-
return () => resizeCleanupRef.current?.();
|
|
282
|
+
return () => { resizeCleanupRef.current?.(); dragCleanupRef.current?.(); };
|
|
229
283
|
}, []);
|
|
230
284
|
const handleToolbarPointerDown = useCallback((e) => {
|
|
231
285
|
// SAFETY: pointer events on the card target are HTMLElements in this DOM context.
|
|
@@ -237,6 +291,12 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
237
291
|
selectCard(card.id);
|
|
238
292
|
e.stopPropagation();
|
|
239
293
|
e.preventDefault();
|
|
294
|
+
const iterationDrag = e.altKey && !!onCreateIteration && loadState === "ready" && !creatingIteration;
|
|
295
|
+
let moved = false;
|
|
296
|
+
let iterationId;
|
|
297
|
+
let creationStarted = false;
|
|
298
|
+
let cancelled = false;
|
|
299
|
+
let position = { x: card.x, y: card.y };
|
|
240
300
|
dragRef.current = {
|
|
241
301
|
startX: e.clientX,
|
|
242
302
|
startY: e.clientY,
|
|
@@ -249,16 +309,56 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
249
309
|
function onMove(ev) {
|
|
250
310
|
const dx = (ev.clientX - dragRef.current.startX) / camera.zoom;
|
|
251
311
|
const dy = (ev.clientY - dragRef.current.startY) / camera.zoom;
|
|
252
|
-
|
|
312
|
+
moved ||= Math.hypot(ev.clientX - dragRef.current.startX, ev.clientY - dragRef.current.startY) >= 6;
|
|
313
|
+
position = { x: dragRef.current.cardX + dx, y: dragRef.current.cardY + dy };
|
|
314
|
+
if (iterationDrag) {
|
|
315
|
+
if (iterationId)
|
|
316
|
+
setCardPosition(iterationId, position.x, position.y);
|
|
317
|
+
else if (moved && !creationStarted) {
|
|
318
|
+
creationStarted = true;
|
|
319
|
+
void handleIteration(position).then((id) => {
|
|
320
|
+
if (!id)
|
|
321
|
+
return;
|
|
322
|
+
iterationId = id;
|
|
323
|
+
if (cancelled) {
|
|
324
|
+
removeFrame(id, { undoable: false });
|
|
325
|
+
selectCard(card.id);
|
|
326
|
+
}
|
|
327
|
+
else
|
|
328
|
+
setCardPosition(id, position.x, position.y);
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
else
|
|
333
|
+
setCardPosition(card.id, position.x, position.y);
|
|
253
334
|
}
|
|
254
|
-
function
|
|
255
|
-
setIsDragging(false);
|
|
335
|
+
function cleanup() {
|
|
256
336
|
window.removeEventListener("pointermove", onMove);
|
|
257
337
|
window.removeEventListener("pointerup", onUp);
|
|
338
|
+
window.removeEventListener("pointercancel", onCancel);
|
|
339
|
+
dragCleanupRef.current = null;
|
|
258
340
|
}
|
|
341
|
+
function onCancel() {
|
|
342
|
+
cleanup();
|
|
343
|
+
setIsDragging(false);
|
|
344
|
+
cancelled = true;
|
|
345
|
+
if (iterationId) {
|
|
346
|
+
removeFrame(iterationId, { undoable: false });
|
|
347
|
+
selectCard(card.id);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
function onUp() {
|
|
351
|
+
cleanup();
|
|
352
|
+
setIsDragging(false);
|
|
353
|
+
if (iterationId)
|
|
354
|
+
setCardPosition(iterationId, position.x, position.y);
|
|
355
|
+
}
|
|
356
|
+
dragCleanupRef.current?.();
|
|
357
|
+
dragCleanupRef.current = onCancel;
|
|
259
358
|
window.addEventListener("pointermove", onMove);
|
|
260
359
|
window.addEventListener("pointerup", onUp);
|
|
261
|
-
|
|
360
|
+
window.addEventListener("pointercancel", onCancel);
|
|
361
|
+
}, [card.id, card.x, card.y, camera.zoom, onCreateIteration, loadState, creatingIteration]);
|
|
262
362
|
const handleCardPointerDown = useCallback(() => {
|
|
263
363
|
if (getSelectedCardId() !== card.id)
|
|
264
364
|
setSelectedElement(null);
|
|
@@ -341,7 +441,8 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
341
441
|
const next = resizeCanvasRect(card, direction, delta);
|
|
342
442
|
resizeCard(card.id, next.width, next.height, { x: next.x, y: next.y });
|
|
343
443
|
}
|
|
344
|
-
return (_jsxs("div", { className: `canvas-card${isDragging ? " is-dragging" : ""}${isSelected ? " is-selected" : ""}${isFocused ? " is-focused" : ""}${isFocusPresentationCard ? " is-focus-presentation" : ""}${presentationCard ? " is-presentation-card" : ""}`, "data-card-id": card.id, style: {
|
|
444
|
+
return (_jsxs("div", { className: `canvas-card${linkedToActive ? " is-linked" : ""}${isDragging ? " is-dragging" : ""}${isSelected ? " is-selected" : ""}${isFocused ? " is-focused" : ""}${isFocusPresentationCard ? " is-focus-presentation" : ""}${presentationCard ? " is-presentation-card" : ""}`, "data-card-id": card.id, tabIndex: presentation === "canvas" ? 0 : undefined, role: "group", "aria-label": `Frame: ${frameLabel}`, style: {
|
|
445
|
+
"--canvas-toolbar-scale": toolbarScale,
|
|
345
446
|
position: "absolute",
|
|
346
447
|
visibility: presentation === "focus" && !presentationCard ? "hidden" : undefined,
|
|
347
448
|
pointerEvents: presentation === "focus" && !presentationCard ? "none" : undefined,
|
|
@@ -349,13 +450,7 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
349
450
|
top: isFocusPresentationCard ? 0 : card.y,
|
|
350
451
|
width: isFocusPresentationCard ? "100%" : card.width,
|
|
351
452
|
height: isFocusPresentationCard ? "100%" : card.height,
|
|
352
|
-
}, onPointerDown: presentation === "canvas" ? handleCardPointerDown : undefined, children: [presentation === "canvas" ? _jsx("div", { className: "canvas-
|
|
353
|
-
transform: `scale(${toolbarScale})`,
|
|
354
|
-
transformOrigin: "left bottom",
|
|
355
|
-
}, onClick: () => onShowFocus(card.id), children: [_jsx(IconCornerLeftDown, { size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), "Focus"] })) : null, _jsx("span", { className: "canvas-card__dimensions", "data-test": `canvas-card-dimensions-${card.id}`, style: {
|
|
356
|
-
transform: `translateX(-50%) scale(${toolbarScale})`,
|
|
357
|
-
transformOrigin: "center bottom",
|
|
358
|
-
}, children: card.title || `${Math.round(card.width)} × ${Math.round(card.height)} px` })] }) }) : null, _jsxs("div", { className: "canvas-card__frame", children: [loadState === "loading" ? (_jsx("div", { className: "canvas-card__loading", "data-test": `canvas-card-loading-${card.id}`, children: "Loading preview..." })) : loadState === "error" ? (_jsxs("div", { className: "canvas-card__error", "data-test": `canvas-card-error-${card.id}`, children: [_jsx("p", { children: errorMessage || "Frame could not be loaded" }), _jsxs("div", { className: "canvas-card__error-actions", children: [_jsx(Button, { size: "compact", variant: "secondary", onClick: handleReload, children: "Retry" }), _jsx(Button, { size: "compact", variant: "danger", onClick: handleRemove, children: "Remove" })] })] })) : null, _jsx("iframe", { ref: iframeRef, className: "canvas-card__iframe", src: initialUrlRef.current, title: card.title || card.url, [CANVAS_RENDERER_ATTR]: "", sandbox: "allow-scripts allow-same-origin allow-forms allow-popups", "data-test": `canvas-card-iframe-${card.id}` }), _jsx(SketchFrameOverlay, { iframe: iframeRef.current, cardUrl: card.url, ready: loadState === "ready" })] }), presentation === "canvas" ? RESIZE_HANDLES.map((handle) => (_jsx("div", { className: `canvas-card__resize-handle canvas-card__resize-handle--${handle.direction}`, "data-test": `canvas-card-resize-${card.id}${handle.direction === "bottom-right" ? "" : `-${handle.direction}`}`, "data-resize-direction": handle.direction, style: {
|
|
453
|
+
}, onPointerDown: presentation === "canvas" ? handleCardPointerDown : undefined, children: [presentation === "canvas" ? _jsx(_Fragment, { children: _jsxs("div", { className: "canvas-card__header", style: { bottom: "100%", minHeight: `calc(var(--control-height-large) * ${toolbarScale})` }, children: [_jsxs("div", { className: "canvas-card__drag-surface", style: { minHeight: `calc(var(--control-height-large) * ${toolbarScale})` }, "data-test": `canvas-card-drag-${card.id}`, onPointerDown: handleToolbarPointerDown, children: [_jsx("div", { className: "canvas-card__identity", style: { zoom: toolbarScale }, children: _jsxs("span", { className: "canvas-card__dimensions", "data-test": `canvas-card-dimensions-${card.id}`, children: [!iterationId(card.content) ? (_jsx(Tooltip, { content: "Live view", children: _jsx("span", { className: "canvas-card__live-badge", "aria-label": "Live view", "data-test": `canvas-card-live-${card.id}`, children: _jsx(IconBoltFilled, { size: 12, "aria-hidden": "true" }) }) })) : (_jsx(Tooltip, { content: "HTML only", children: _jsx("span", { className: "canvas-card__iteration-badge", "aria-label": "HTML only", "data-test": `canvas-card-iteration-badge-${card.id}`, children: _jsx(IconArtboard, { size: 14, "aria-hidden": "true" }) }) })), _jsx("span", { className: "canvas-card__title", children: frameLabel })] }) }), iterationError ? _jsx("span", { className: "canvas-card__iteration-error", role: "status", children: iterationError }) : null] }), _jsx("div", { className: "canvas-card__floating-toolbar", "data-busy": creatingIteration ? "true" : undefined, onPointerDown: (event) => event.stopPropagation(), children: _jsxs("div", { className: "canvas-toolbar canvas-card__actions", style: { zoom: toolbarScale }, role: "toolbar", "aria-label": "Frame actions", "aria-busy": creatingIteration, "data-test": `canvas-card-actions-${card.id}`, children: [onShowFocus ? (_jsx(Tooltip, { content: "Open this frame in focus view", children: _jsxs(Button, { variant: "quiet", size: "default", "data-test": `canvas-card-focus-${card.id}`, onClick: () => onShowFocus(card.id), children: [_jsx(IconCornerLeftDown, { size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), "Focus"] }) })) : null, onDuplicate && !iterationId(card.content) ? (_jsx(Tooltip, { content: "Create a linked copy of this frame", children: _jsxs(Button, { variant: "quiet", size: "default", "data-test": `canvas-card-duplicate-${card.id}`, onClick: () => onDuplicate(card.id), children: [_jsx(IconCopy, { size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), "Duplicate"] }) })) : null, onCreateIteration ? (_jsx(Tooltip, { content: "Unlinked HTML version", stableTrigger: true, children: _jsxs(Button, { variant: "quiet", size: "default", "data-test": `canvas-card-create-iteration-${card.id}`, disabled: creatingIteration || loadState !== "ready", onClick: () => void handleIteration(), children: [_jsx(IconArtboard, { size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }), creatingIteration ? "Creating…" : "Iteration"] }) })) : null, _jsx("div", { className: "canvas-toolbar__divider", "aria-hidden": "true" }), _jsx(Tooltip, { content: canRemove ? "Delete frame" : "Keep at least one frame on the canvas", children: _jsx(IconButton, { variant: "quiet", size: "default", label: "Delete frame", "data-test": `canvas-card-delete-${card.id}`, disabled: !canRemove, onClick: handleRemove, children: _jsx(IconTrash, { size: "var(--icon-size-small)", stroke: "var(--icon-stroke-width)", "aria-hidden": "true" }) }) })] }) })] }) }) : null, _jsxs("div", { className: "canvas-card__frame", children: [loadState === "loading" ? (_jsx("div", { className: "canvas-card__loading", "data-test": `canvas-card-loading-${card.id}`, children: "Loading preview..." })) : loadState === "error" ? (_jsxs("div", { className: "canvas-card__error", "data-test": `canvas-card-error-${card.id}`, children: [_jsx("p", { children: errorMessage || "Frame could not be loaded" }), _jsxs("div", { className: "canvas-card__error-actions", children: [_jsx(Button, { size: "compact", variant: "secondary", onClick: handleReload, children: "Retry" }), _jsx(Button, { size: "compact", variant: "danger", onClick: handleRemove, children: "Remove" })] })] })) : null, _jsx("iframe", { ref: iframeRef, className: "canvas-card__iframe", src: card.content.kind === "iteration" ? contentDocumentUrl(card.content) : initialUrlRef.current, title: frameLabel, [CANVAS_RENDERER_ATTR]: "", sandbox: "allow-scripts allow-same-origin allow-forms allow-popups", "data-test": `canvas-card-iframe-${card.id}` }, iterationId(card.content) ?? "live"), _jsx(AgentActivityOverlay, { cardId: card.id, content: card.content, iframe: loadState === "ready" ? iframeRef.current : null }), _jsx(SketchFrameOverlay, { cardId: card.id, iframe: iframeRef.current, cardUrl: contentSourceUrl(card.content), artifactId: iterationId(card.content), ready: loadState === "ready" })] }), presentation === "canvas" ? RESIZE_HANDLES.map((handle) => (_jsx("div", { className: `canvas-card__resize-handle canvas-card__resize-handle--${handle.direction}`, "data-test": `canvas-card-resize-${card.id}${handle.direction === "bottom-right" ? "" : `-${handle.direction}`}`, "data-resize-direction": handle.direction, style: {
|
|
359
454
|
// Keep the edge's long axis aligned with the zoomed card. Only
|
|
360
455
|
// the thickness needs inverse scaling to remain screen-sized.
|
|
361
456
|
transform: resizeHandleTransform(handle.direction, resizeHandleScale),
|
|
@@ -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 = {
|
|
@@ -281,6 +392,12 @@ export function CanvasElementOverlay() {
|
|
|
281
392
|
}
|
|
282
393
|
if (data.type === "renderer-hello")
|
|
283
394
|
return;
|
|
395
|
+
if (data.type === "projection-applied") {
|
|
396
|
+
releasePendingSpacingCommits(pendingSpacingCommitsRef.current, sourceIframe);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (getCanvasLayoutTransitioning())
|
|
400
|
+
return;
|
|
284
401
|
if (data.type === "element-hover") {
|
|
285
402
|
const msg = data;
|
|
286
403
|
if (!msg.cid)
|
|
@@ -289,7 +406,7 @@ export function CanvasElementOverlay() {
|
|
|
289
406
|
setHover((current) => current?.cardId === sourceCardId ? null : current);
|
|
290
407
|
return;
|
|
291
408
|
}
|
|
292
|
-
const spacingDescriptor = msg.spacing ?? null;
|
|
409
|
+
const spacingDescriptor = msg.hoverSpacing ?? msg.spacing ?? null;
|
|
293
410
|
const hoverPoint = msg.point ?? null;
|
|
294
411
|
const hoverElement = spacingDescriptor
|
|
295
412
|
? findFrameElement(sourceIframe, msg.elementId, msg.cid, msg.src)
|
|
@@ -297,7 +414,7 @@ export function CanvasElementOverlay() {
|
|
|
297
414
|
const hoverAffordance = spacingDescriptor && hoverElement
|
|
298
415
|
? getSpacingAffordanceForDescriptor(hoverElement, spacingDescriptor)
|
|
299
416
|
: spacingDescriptor && hoverPoint && sourceIframe.contentDocument
|
|
300
|
-
?
|
|
417
|
+
? getSpacingHoverAtPoint(sourceIframe.contentDocument, hoverPoint.x, hoverPoint.y)
|
|
301
418
|
: null;
|
|
302
419
|
const matchingAffordance = spacingDescriptorMatches(hoverAffordance, spacingDescriptor)
|
|
303
420
|
? hoverAffordance
|
|
@@ -354,6 +471,7 @@ export function CanvasElementOverlay() {
|
|
|
354
471
|
}
|
|
355
472
|
else if (data.type === "element-deselect") {
|
|
356
473
|
clearSpacingDrag(spacingDragRef);
|
|
474
|
+
setSpacingDragBadge(null);
|
|
357
475
|
dragRef.current = null;
|
|
358
476
|
clearDropGuide("canvas");
|
|
359
477
|
setSelectedElement(null);
|
|
@@ -391,6 +509,7 @@ export function CanvasElementOverlay() {
|
|
|
391
509
|
if (selectedElement)
|
|
392
510
|
setSelectedElement(selectedElement);
|
|
393
511
|
applySpacingPreview(spacingDragRef.current, msg.point, msg.shiftKey === true);
|
|
512
|
+
setSpacingDragBadge(spacingBadgeForDrag(spacingDragRef.current, msg.point));
|
|
394
513
|
refreshSpacingPreviewOverlay(spacingDragRef.current);
|
|
395
514
|
return;
|
|
396
515
|
}
|
|
@@ -404,6 +523,7 @@ export function CanvasElementOverlay() {
|
|
|
404
523
|
const spacing = spacingDragRef.current;
|
|
405
524
|
if (spacing && spacing.iframe === sourceIframe) {
|
|
406
525
|
applySpacingPreview(spacing, data.point, data.shiftKey === true);
|
|
526
|
+
setSpacingDragBadge(spacingBadgeForDrag(spacing, data.point));
|
|
407
527
|
refreshSpacingPreviewOverlay(spacing);
|
|
408
528
|
return;
|
|
409
529
|
}
|
|
@@ -414,13 +534,25 @@ export function CanvasElementOverlay() {
|
|
|
414
534
|
const spacing = spacingDragRef.current;
|
|
415
535
|
if (spacing && spacing.iframe === sourceIframe) {
|
|
416
536
|
spacingDragRef.current = null;
|
|
537
|
+
setSpacingDragBadge(null);
|
|
417
538
|
if (msg.cancelled) {
|
|
418
539
|
restoreSpacingPreview(spacing);
|
|
419
540
|
refreshSpacingPreviewOverlay(spacing);
|
|
420
541
|
}
|
|
421
542
|
else {
|
|
422
543
|
applySpacingPreview(spacing, msg.point, msg.shiftKey === true);
|
|
423
|
-
commitSpacingDrag(spacing);
|
|
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
|
+
}
|
|
424
556
|
refreshSpacingPreviewOverlay(spacing);
|
|
425
557
|
}
|
|
426
558
|
clearDropGuide("canvas");
|
|
@@ -495,6 +627,7 @@ export function CanvasElementOverlay() {
|
|
|
495
627
|
unsubscribe();
|
|
496
628
|
clearSpacingDrag(spacingDragRef);
|
|
497
629
|
dragRef.current = null;
|
|
630
|
+
pendingSpacingCommitsRef.current = [];
|
|
498
631
|
clearDropGuide("canvas");
|
|
499
632
|
};
|
|
500
633
|
}, []);
|
|
@@ -505,6 +638,9 @@ export function CanvasElementOverlay() {
|
|
|
505
638
|
const projectedHoverRect = hover ? projectRect(hover.iframe, hover.rect, projectionZoom) : null;
|
|
506
639
|
const projectedSpacingGuides = hover?.spacingGuides.map((guide) => projectRect(hover.iframe, guide, projectionZoom)) ?? [];
|
|
507
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;
|
|
508
644
|
const hoverSpacing = hover?.spacing ?? null;
|
|
509
645
|
const measureStateForSelectedFrame = measureState?.iframe === selectedFrame ? measureState : null;
|
|
510
646
|
const hoverInSelectedFrame = hover?.iframe === selectedFrame ? hover : null;
|
|
@@ -529,9 +665,9 @@ export function CanvasElementOverlay() {
|
|
|
529
665
|
hoveredBorders: hoverInSelectedFrame.borders,
|
|
530
666
|
}).segments, projectionZoom)
|
|
531
667
|
: [];
|
|
532
|
-
if (presentationTransitioning)
|
|
668
|
+
if (presentationTransitioning || layoutTransitioning || temporaryAppInteraction)
|
|
533
669
|
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
|
|
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
|
|
535
671
|
? projectRect(selectedFrame, toRect(element.getBoundingClientRect()), projectionZoom)
|
|
536
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" })] }));
|
|
537
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 {};
|