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,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,17 @@ 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";
|
|
30
|
+
import { installFrameScrollbarStyles } from "./frameScrollbarStyles.js";
|
|
23
31
|
import { getCanvasResizeEdges, resizeCanvasRect, } from "./canvasResize.js";
|
|
32
|
+
import { getDraftContentsForCard } from "../drafts/store.js";
|
|
33
|
+
import { removeFrame } from "../workspace/commands.js";
|
|
34
|
+
import { artifactDocumentUrl } from "../iterations/client.js";
|
|
24
35
|
const RESIZE_HANDLES = [
|
|
25
36
|
{ direction: "top-left", cursor: "nwse-resize", transformOrigin: "left top", label: "Resize card from the top-left corner" },
|
|
26
37
|
{ direction: "top", cursor: "ns-resize", transformOrigin: "center top", label: "Resize card from the top edge" },
|
|
@@ -38,15 +49,23 @@ function resizeHandleTransform(direction, scale) {
|
|
|
38
49
|
return `scale(${scale}, 1)`;
|
|
39
50
|
return `scale(${scale})`;
|
|
40
51
|
}
|
|
41
|
-
export function CanvasCard({ card, presentation = "canvas", presentationCard = true, onShowFocus, documentOwner }) {
|
|
52
|
+
export function CanvasCard({ card, presentation = "canvas", presentationCard = true, linkedToActive = false, onShowFocus, onDuplicate, onCreateIteration, documentOwner }) {
|
|
42
53
|
const iframeRef = useRef(null);
|
|
43
|
-
const initialUrlRef = useRef(card.
|
|
44
|
-
const navigationUrlRef = useRef(card.
|
|
54
|
+
const initialUrlRef = useRef(contentNavigationUrl(card.content) ?? contentSourceUrl(card.content));
|
|
55
|
+
const navigationUrlRef = useRef(contentNavigationUrl(card.content));
|
|
45
56
|
const documentSessionRef = useRef(null);
|
|
46
57
|
const frameRuntimeRef = useRef(null);
|
|
47
58
|
const [loadState, setLoadState] = useState("loading");
|
|
48
59
|
const [errorMessage, setErrorMessage] = useState(null);
|
|
60
|
+
const [creatingIteration, setCreatingIteration] = useState(false);
|
|
61
|
+
const [iterationError, setIterationError] = useState(null);
|
|
49
62
|
const camera = useBoardCamera();
|
|
63
|
+
const runtimeConfig = useNudgeUiRuntimeConfig();
|
|
64
|
+
const canvasCards = useCanvasCards();
|
|
65
|
+
const canRemove = canvasCards.length > 1;
|
|
66
|
+
const frameLabel = runtimeConfig.demo === true && runtimeConfig.demoCardLabels?.length && card.title
|
|
67
|
+
? card.title
|
|
68
|
+
: getCanvasCardLabel(card, canvasCards);
|
|
50
69
|
const selectedCardId = useSelectedCardId();
|
|
51
70
|
const focusedCardId = useFocusedCardId();
|
|
52
71
|
const isSelected = selectedCardId === card.id;
|
|
@@ -82,6 +101,7 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
82
101
|
session.registerCleanup(() => releaseDocumentProjection(frameDocument));
|
|
83
102
|
session.registerCleanup(() => disposeInlineTextEdit("frame-disposed", frameDocument));
|
|
84
103
|
session.registerCleanup(startClipboardHandoffController(frameDocument));
|
|
104
|
+
session.registerCleanup(installFrameScrollbarStyles(frameDocument));
|
|
85
105
|
documentSessionRef.current = { document: frameDocument, session };
|
|
86
106
|
}, [disposeDocumentSession, documentOwner]);
|
|
87
107
|
useEffect(() => {
|
|
@@ -94,22 +114,59 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
94
114
|
disposeDocumentSession();
|
|
95
115
|
unregisterCardFrame(card.id);
|
|
96
116
|
};
|
|
97
|
-
}, [bindDocumentSession, card.id, disposeDocumentSession]);
|
|
117
|
+
}, [bindDocumentSession, card.id, iterationId(card.content), disposeDocumentSession]);
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
if (card.content.kind !== "iteration" || loadState !== "ready")
|
|
120
|
+
return;
|
|
121
|
+
const artifactId = card.content.artifactId;
|
|
122
|
+
let active = true;
|
|
123
|
+
let checking = false;
|
|
124
|
+
let reloadPending = false;
|
|
125
|
+
const timer = window.setInterval(() => {
|
|
126
|
+
const workspace = getDraftContentsForCard(card.id);
|
|
127
|
+
// Pending inspector edits still project over preview.html. Do not replace
|
|
128
|
+
// that base until they have been saved and handed off.
|
|
129
|
+
if (checking || isInlineTextEditingActive() || workspace?.changes.length || workspace?.structuralChanges.length)
|
|
130
|
+
return;
|
|
131
|
+
checking = true;
|
|
132
|
+
const frame = iframeRef.current;
|
|
133
|
+
if (!frame) {
|
|
134
|
+
checking = false;
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
void refreshHtmlIteration(card.id, artifactId, frame).then((changed) => {
|
|
138
|
+
reloadPending ||= changed;
|
|
139
|
+
const latest = getDraftContentsForCard(card.id);
|
|
140
|
+
if (active && reloadPending && !isInlineTextEditingActive() && !latest?.changes.length && !latest?.structuralChanges.length) {
|
|
141
|
+
reloadPending = false;
|
|
142
|
+
loadFrame(`${artifactDocumentUrl(artifactId)}?revision=${Date.now()}`);
|
|
143
|
+
}
|
|
144
|
+
}).catch(() => undefined).finally(() => { checking = false; });
|
|
145
|
+
}, 1500);
|
|
146
|
+
return () => { active = false; window.clearInterval(timer); };
|
|
147
|
+
}, [iterationId(card.content), card.id, loadFrame, loadState]);
|
|
98
148
|
function handleReload() {
|
|
99
149
|
loadFrame();
|
|
100
150
|
}
|
|
101
151
|
function handleRemove() {
|
|
102
152
|
if (getSelectedCardId() === card.id)
|
|
103
153
|
setSelectedElement(null);
|
|
104
|
-
|
|
154
|
+
removeFrame(card.id);
|
|
105
155
|
}
|
|
106
|
-
function
|
|
107
|
-
if (!
|
|
108
|
-
return;
|
|
109
|
-
const runtime = getNudgeUiRuntimeConfig();
|
|
110
|
-
if (runtime.demo === true && (runtime.demoCardLabels?.length ?? 0) > 0)
|
|
156
|
+
async function handleIteration(position) {
|
|
157
|
+
if (creatingIteration || !onCreateIteration || loadState !== "ready")
|
|
111
158
|
return;
|
|
112
|
-
|
|
159
|
+
setCreatingIteration(true);
|
|
160
|
+
setIterationError(null);
|
|
161
|
+
try {
|
|
162
|
+
return await onCreateIteration(card.id, position);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
setIterationError(error instanceof Error ? error.message : "The iteration could not be created.");
|
|
166
|
+
}
|
|
167
|
+
finally {
|
|
168
|
+
setCreatingIteration(false);
|
|
169
|
+
}
|
|
113
170
|
}
|
|
114
171
|
/** The controller half of the handshake: announce workspace identity. */
|
|
115
172
|
function sendParentReady() {
|
|
@@ -158,8 +215,7 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
158
215
|
adoptFrameRuntime(data.runtime);
|
|
159
216
|
setLoadState("ready");
|
|
160
217
|
setErrorMessage(null);
|
|
161
|
-
|
|
162
|
-
if (data.url)
|
|
218
|
+
if (data.url && !iterationId(card.content))
|
|
163
219
|
updateCardUrl(card.id, data.url);
|
|
164
220
|
if (iframeRef.current) {
|
|
165
221
|
registerCardFrame(card.id, iframeRef.current);
|
|
@@ -172,8 +228,7 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
172
228
|
return;
|
|
173
229
|
}
|
|
174
230
|
if (data.type === "frame-metadata") {
|
|
175
|
-
|
|
176
|
-
if (data.url)
|
|
231
|
+
if (data.url && !iterationId(card.content))
|
|
177
232
|
updateCardUrl(card.id, data.url);
|
|
178
233
|
return;
|
|
179
234
|
}
|
|
@@ -182,13 +237,13 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
182
237
|
setErrorMessage(data.message || "Frame failed to load");
|
|
183
238
|
}
|
|
184
239
|
});
|
|
185
|
-
}, [card.id]);
|
|
240
|
+
}, [card.id, iterationId(card.content)]);
|
|
186
241
|
useLayoutEffect(() => {
|
|
187
|
-
if (!card.
|
|
242
|
+
if (!contentNavigationUrl(card.content) || navigationUrlRef.current === contentNavigationUrl(card.content))
|
|
188
243
|
return;
|
|
189
|
-
navigationUrlRef.current = card.
|
|
190
|
-
loadFrame(card.
|
|
191
|
-
}, [card.
|
|
244
|
+
navigationUrlRef.current = contentNavigationUrl(card.content);
|
|
245
|
+
loadFrame(contentNavigationUrl(card.content));
|
|
246
|
+
}, [contentNavigationUrl(card.content), loadFrame]);
|
|
192
247
|
useEffect(() => {
|
|
193
248
|
if (loadState !== "loading")
|
|
194
249
|
return;
|
|
@@ -220,12 +275,13 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
220
275
|
}
|
|
221
276
|
iframe.addEventListener("load", onLoad);
|
|
222
277
|
return () => iframe.removeEventListener("load", onLoad);
|
|
223
|
-
}, [bindDocumentSession, card.id, disposeDocumentSession]);
|
|
278
|
+
}, [bindDocumentSession, card.id, iterationId(card.content), disposeDocumentSession]);
|
|
224
279
|
const [isDragging, setIsDragging] = useState(false);
|
|
225
280
|
const dragRef = useRef({ startX: 0, startY: 0, cardX: 0, cardY: 0 });
|
|
281
|
+
const dragCleanupRef = useRef(null);
|
|
226
282
|
const resizeCleanupRef = useRef(null);
|
|
227
283
|
useEffect(() => {
|
|
228
|
-
return () => resizeCleanupRef.current?.();
|
|
284
|
+
return () => { resizeCleanupRef.current?.(); dragCleanupRef.current?.(); };
|
|
229
285
|
}, []);
|
|
230
286
|
const handleToolbarPointerDown = useCallback((e) => {
|
|
231
287
|
// SAFETY: pointer events on the card target are HTMLElements in this DOM context.
|
|
@@ -237,6 +293,12 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
237
293
|
selectCard(card.id);
|
|
238
294
|
e.stopPropagation();
|
|
239
295
|
e.preventDefault();
|
|
296
|
+
const iterationDrag = e.altKey && !!onCreateIteration && loadState === "ready" && !creatingIteration;
|
|
297
|
+
let moved = false;
|
|
298
|
+
let iterationId;
|
|
299
|
+
let creationStarted = false;
|
|
300
|
+
let cancelled = false;
|
|
301
|
+
let position = { x: card.x, y: card.y };
|
|
240
302
|
dragRef.current = {
|
|
241
303
|
startX: e.clientX,
|
|
242
304
|
startY: e.clientY,
|
|
@@ -249,16 +311,56 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
249
311
|
function onMove(ev) {
|
|
250
312
|
const dx = (ev.clientX - dragRef.current.startX) / camera.zoom;
|
|
251
313
|
const dy = (ev.clientY - dragRef.current.startY) / camera.zoom;
|
|
252
|
-
|
|
314
|
+
moved ||= Math.hypot(ev.clientX - dragRef.current.startX, ev.clientY - dragRef.current.startY) >= 6;
|
|
315
|
+
position = { x: dragRef.current.cardX + dx, y: dragRef.current.cardY + dy };
|
|
316
|
+
if (iterationDrag) {
|
|
317
|
+
if (iterationId)
|
|
318
|
+
setCardPosition(iterationId, position.x, position.y);
|
|
319
|
+
else if (moved && !creationStarted) {
|
|
320
|
+
creationStarted = true;
|
|
321
|
+
void handleIteration(position).then((id) => {
|
|
322
|
+
if (!id)
|
|
323
|
+
return;
|
|
324
|
+
iterationId = id;
|
|
325
|
+
if (cancelled) {
|
|
326
|
+
removeFrame(id, { undoable: false });
|
|
327
|
+
selectCard(card.id);
|
|
328
|
+
}
|
|
329
|
+
else
|
|
330
|
+
setCardPosition(id, position.x, position.y);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
else
|
|
335
|
+
setCardPosition(card.id, position.x, position.y);
|
|
253
336
|
}
|
|
254
|
-
function
|
|
255
|
-
setIsDragging(false);
|
|
337
|
+
function cleanup() {
|
|
256
338
|
window.removeEventListener("pointermove", onMove);
|
|
257
339
|
window.removeEventListener("pointerup", onUp);
|
|
340
|
+
window.removeEventListener("pointercancel", onCancel);
|
|
341
|
+
dragCleanupRef.current = null;
|
|
258
342
|
}
|
|
343
|
+
function onCancel() {
|
|
344
|
+
cleanup();
|
|
345
|
+
setIsDragging(false);
|
|
346
|
+
cancelled = true;
|
|
347
|
+
if (iterationId) {
|
|
348
|
+
removeFrame(iterationId, { undoable: false });
|
|
349
|
+
selectCard(card.id);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function onUp() {
|
|
353
|
+
cleanup();
|
|
354
|
+
setIsDragging(false);
|
|
355
|
+
if (iterationId)
|
|
356
|
+
setCardPosition(iterationId, position.x, position.y);
|
|
357
|
+
}
|
|
358
|
+
dragCleanupRef.current?.();
|
|
359
|
+
dragCleanupRef.current = onCancel;
|
|
259
360
|
window.addEventListener("pointermove", onMove);
|
|
260
361
|
window.addEventListener("pointerup", onUp);
|
|
261
|
-
|
|
362
|
+
window.addEventListener("pointercancel", onCancel);
|
|
363
|
+
}, [card.id, card.x, card.y, camera.zoom, onCreateIteration, loadState, creatingIteration]);
|
|
262
364
|
const handleCardPointerDown = useCallback(() => {
|
|
263
365
|
if (getSelectedCardId() !== card.id)
|
|
264
366
|
setSelectedElement(null);
|
|
@@ -341,7 +443,8 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
341
443
|
const next = resizeCanvasRect(card, direction, delta);
|
|
342
444
|
resizeCard(card.id, next.width, next.height, { x: next.x, y: next.y });
|
|
343
445
|
}
|
|
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: {
|
|
446
|
+
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: {
|
|
447
|
+
"--canvas-toolbar-scale": toolbarScale,
|
|
345
448
|
position: "absolute",
|
|
346
449
|
visibility: presentation === "focus" && !presentationCard ? "hidden" : undefined,
|
|
347
450
|
pointerEvents: presentation === "focus" && !presentationCard ? "none" : undefined,
|
|
@@ -349,13 +452,7 @@ export function CanvasCard({ card, presentation = "canvas", presentationCard = t
|
|
|
349
452
|
top: isFocusPresentationCard ? 0 : card.y,
|
|
350
453
|
width: isFocusPresentationCard ? "100%" : card.width,
|
|
351
454
|
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: {
|
|
455
|
+
}, 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
456
|
// Keep the edge's long axis aligned with the zoomed card. Only
|
|
360
457
|
// the thickness needs inverse scaling to remain screen-sized.
|
|
361
458
|
transform: resizeHandleTransform(handle.direction, resizeHandleScale),
|