nudge-ui 0.2.0 → 0.2.1
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/bin/nudge-ui.mjs +3 -1
- package/dist/cli/agentCommand.d.ts +8 -0
- package/dist/cli/agentCommand.js +59 -0
- package/dist/client.mjs +872 -12
- package/dist/hosts/astro/astroRuntimeConfig.js +1 -1
- package/dist/hosts/astro/clientTransport.js +60 -11
- package/dist/hosts/next/sidecar.d.ts +4 -0
- package/dist/hosts/next/sidecar.js +49 -6
- package/dist/hosts/next/wrapper.js +30 -2
- package/dist/hosts/projectBridge.d.ts +20 -0
- package/dist/hosts/projectBridge.js +97 -0
- package/dist/hosts/static/cli.d.ts +1 -1
- package/dist/hosts/static/cli.js +6 -1
- package/dist/hosts/static/manifest.d.ts +1 -1
- package/dist/hosts/static/manifest.js +1 -1
- package/dist/hosts/static/server.js +44 -3
- package/dist/hosts/vite/vite.d.ts +5 -1
- package/dist/hosts/vite/vite.js +78 -14
- package/dist/inspector/agent/McpConnectionDialog.d.ts +2 -2
- package/dist/inspector/agent/McpConnectionDialog.js +11 -35
- package/dist/inspector/agent/client.d.ts +10 -3
- package/dist/inspector/agent/client.js +80 -9
- package/dist/inspector/agent/connectionStatus.js +3 -3
- package/dist/inspector/agent/httpTransport.d.ts +2 -0
- package/dist/inspector/agent/httpTransport.js +37 -17
- package/dist/inspector/agent/protocol.d.ts +8 -3
- package/dist/inspector/agent/protocol.js +1 -1
- package/dist/inspector/agent/verification.d.ts +1 -1
- package/dist/inspector/agent/verification.js +69 -12
- package/dist/inspector/canvas/CanvasCard.d.ts +5 -3
- package/dist/inspector/canvas/CanvasCard.js +181 -91
- package/dist/inspector/canvas/CanvasElementOverlay.js +246 -52
- package/dist/inspector/canvas/CanvasToolbar.d.ts +12 -0
- package/dist/inspector/canvas/CanvasToolbar.js +24 -0
- package/dist/inspector/canvas/CanvasWorkspace.d.ts +4 -1
- package/dist/inspector/canvas/CanvasWorkspace.js +392 -73
- package/dist/inspector/canvas/activeCanvasDocument.d.ts +5 -0
- package/dist/inspector/canvas/activeCanvasDocument.js +23 -0
- package/dist/inspector/canvas/canvasResize.d.ts +30 -0
- package/dist/inspector/canvas/canvasResize.js +52 -0
- package/dist/inspector/canvas/canvasStore.d.ts +30 -6
- package/dist/inspector/canvas/canvasStore.js +128 -61
- package/dist/inspector/canvas/frameProtocol.d.ts +69 -5
- package/dist/inspector/canvas/frameProtocol.js +56 -2
- package/dist/inspector/canvas/keyboardShortcuts.d.ts +3 -0
- package/dist/inspector/canvas/keyboardShortcuts.js +14 -0
- package/dist/inspector/canvas/projection.d.ts +7 -0
- package/dist/inspector/canvas/projection.js +118 -25
- package/dist/inspector/canvas/rendererBootstrap.js +29 -29
- package/dist/inspector/canvas/rendererElementSelector.js +341 -30
- package/dist/inspector/canvas/rendererMessageRouter.d.ts +11 -0
- package/dist/inspector/canvas/rendererMessageRouter.js +43 -0
- package/dist/inspector/canvas/rendererSelectionProxy.js +6 -2
- package/dist/inspector/canvas/sessionStore.d.ts +1 -0
- package/dist/inspector/canvas/sessionStore.js +12 -4
- package/dist/inspector/canvas/staleChangeDetector.js +16 -14
- package/dist/inspector/changes/changesLog.js +31 -1
- package/dist/inspector/changes/managedStyleProjection.d.ts +1 -1
- package/dist/inspector/changes/managedStyleProjection.js +3 -3
- package/dist/inspector/changes/structuralTypes.d.ts +4 -0
- package/dist/inspector/clientManifest.d.ts +5 -0
- package/dist/inspector/clientManifest.js +11 -0
- package/dist/inspector/componentSemantics/adapterRegistry.js +4 -3
- package/dist/inspector/componentSemantics/runtimeBridge.d.ts +2 -2
- package/dist/inspector/componentSemantics/runtimeBridge.js +16 -3
- package/dist/inspector/index.d.ts +2 -0
- package/dist/inspector/index.js +74 -24
- package/dist/inspector/inline-text/inlineTextDiagnostics.d.ts +10 -0
- package/dist/inspector/inline-text/inlineTextDiagnostics.js +65 -0
- package/dist/inspector/inline-text/inlineTextEditor.d.ts +3 -5
- package/dist/inspector/inline-text/inlineTextEditor.js +74 -206
- package/dist/inspector/inline-text/inlineTextFeedback.d.ts +5 -0
- package/dist/inspector/inline-text/inlineTextFeedback.js +27 -0
- package/dist/inspector/inline-text/inlineTextLifecycle.js +2 -0
- package/dist/inspector/inline-text/textEditChange.d.ts +14 -0
- package/dist/inspector/inline-text/textEditChange.js +165 -0
- package/dist/inspector/inspection/selectionProperty.d.ts +1 -0
- package/dist/inspector/inspection/selectionProperty.js +1 -0
- package/dist/inspector/overlay/selectedGeometry.js +21 -2
- package/dist/inspector/overlay/spacingGestures.d.ts +45 -0
- package/dist/inspector/overlay/spacingGestures.js +353 -0
- package/dist/inspector/overlay/structuralGestures.d.ts +2 -2
- package/dist/inspector/overlay/structuralGestures.js +12 -10
- package/dist/inspector/projection/managedStylesheet.js +4 -1
- package/dist/inspector/projection/renderedInstance.d.ts +2 -0
- package/dist/inspector/projection/renderedInstance.js +5 -1
- package/dist/inspector/projection/structuralProjection.d.ts +2 -0
- package/dist/inspector/projection/structuralProjection.js +85 -1
- package/dist/inspector/projection/structuralProjectionBoundary.js +17 -1
- package/dist/inspector/projection/textProjection.d.ts +2 -0
- package/dist/inspector/projection/textProjection.js +10 -4
- package/dist/inspector/prompt/clipboardHandoff.d.ts +1 -1
- package/dist/inspector/prompt/clipboardHandoff.js +3 -3
- package/dist/inspector/prompt/generatePrompt.d.ts +2 -1
- package/dist/inspector/prompt/generatePrompt.js +19 -2
- package/dist/inspector/runtime/editorShell.d.ts +2 -0
- package/dist/inspector/runtime/editorShell.js +4 -0
- package/dist/inspector/runtime/runtimeConfig.d.ts +4 -0
- package/dist/inspector/runtime/runtimeConfig.js +4 -0
- package/dist/inspector/selection/selectionStore.js +2 -0
- package/dist/inspector/settings/SettingsDialog.js +10 -0
- package/dist/inspector/shell/AppShell.js +5 -1
- package/dist/inspector/shell/ChangesLog.js +8 -4
- package/dist/inspector/shell/CopyPromptButton.js +95 -19
- package/dist/inspector/shell/EmptyState.js +1 -1
- package/dist/inspector/shell/InspectorShell.d.ts +0 -1
- package/dist/inspector/shell/InspectorShell.js +37 -38
- package/dist/inspector/shell/PeekOriginalButton.d.ts +7 -0
- package/dist/inspector/shell/PeekOriginalButton.js +57 -0
- package/dist/inspector/shell/PeekOriginalIcon.d.ts +7 -0
- package/dist/inspector/shell/PeekOriginalIcon.js +9 -0
- package/dist/inspector/shell/originalPreview.d.ts +9 -0
- package/dist/inspector/shell/originalPreview.js +61 -0
- package/dist/inspector/shell/shortcuts.d.ts +3 -0
- package/dist/inspector/shell/shortcuts.js +15 -0
- package/dist/inspector/sketch/SketchChanges.d.ts +2 -0
- package/dist/inspector/sketch/SketchChanges.js +72 -0
- package/dist/inspector/sketch/SketchEditor.d.ts +21 -0
- package/dist/inspector/sketch/SketchEditor.js +402 -0
- package/dist/inspector/sketch/SketchEntryButton.d.ts +4 -0
- package/dist/inspector/sketch/SketchEntryButton.js +11 -0
- package/dist/inspector/sketch/SketchFrameOverlay.d.ts +11 -0
- package/dist/inspector/sketch/SketchFrameOverlay.js +119 -0
- package/dist/inspector/sketch/SketchLayersPanel.d.ts +2 -0
- package/dist/inspector/sketch/SketchLayersPanel.js +63 -0
- package/dist/inspector/sketch/SketchOverlay.d.ts +19 -0
- package/dist/inspector/sketch/SketchOverlay.js +420 -0
- package/dist/inspector/sketch/SketchPromptPanel.d.ts +15 -0
- package/dist/inspector/sketch/SketchPromptPanel.js +18 -0
- package/dist/inspector/sketch/SketchWorkspace.d.ts +13 -0
- package/dist/inspector/sketch/SketchWorkspace.js +152 -0
- package/dist/inspector/sketch/capture.d.ts +55 -0
- package/dist/inspector/sketch/capture.js +350 -0
- package/dist/inspector/sketch/freehand.d.ts +13 -0
- package/dist/inspector/sketch/freehand.js +64 -0
- package/dist/inspector/sketch/geometry.d.ts +17 -0
- package/dist/inspector/sketch/geometry.js +98 -0
- package/dist/inspector/sketch/handoff.d.ts +21 -0
- package/dist/inspector/sketch/handoff.js +72 -0
- package/dist/inspector/sketch/interaction.d.ts +21 -0
- package/dist/inspector/sketch/interaction.js +98 -0
- package/dist/inspector/sketch/model.d.ts +104 -0
- package/dist/inspector/sketch/model.js +282 -0
- package/dist/inspector/sketch/persistence.d.ts +21 -0
- package/dist/inspector/sketch/persistence.js +205 -0
- package/dist/inspector/sketch/raster.d.ts +22 -0
- package/dist/inspector/sketch/raster.js +203 -0
- package/dist/inspector/sketch/sketchNote.d.ts +10 -0
- package/dist/inspector/sketch/sketchNote.js +30 -0
- package/dist/inspector/sketch/store.d.ts +47 -0
- package/dist/inspector/sketch/store.js +409 -0
- package/dist/inspector/styleEditors/BorderEditor.js +15 -19
- package/dist/inspector/styleEditors/BorderRadiusEditor.js +6 -6
- package/dist/inspector/styleEditors/BoxShadowEditor.js +12 -1
- package/dist/inspector/styleEditors/ColorPicker.js +11 -36
- package/dist/inspector/styleEditors/GapField.d.ts +3 -2
- package/dist/inspector/styleEditors/GapField.js +2 -2
- package/dist/inspector/styleEditors/GridSection.js +1 -1
- package/dist/inspector/styleEditors/LayoutSection.js +11 -8
- package/dist/inspector/styleEditors/SpacingBox.js +23 -30
- package/dist/inspector/styleEditors/layoutPreviewState.d.ts +5 -0
- package/dist/inspector/styleEditors/layoutPreviewState.js +19 -0
- package/dist/inspector/styleEditors/layoutValue.js +3 -0
- package/dist/inspector/styleEditors/nudgeValue.d.ts +11 -0
- package/dist/inspector/styleEditors/nudgeValue.js +91 -5
- package/dist/inspector/styleEditors/stylePresence.d.ts +7 -0
- package/dist/inspector/styleEditors/stylePresence.js +22 -0
- package/dist/inspector/styleEditors/textRelevance.d.ts +3 -0
- package/dist/inspector/styleEditors/textRelevance.js +35 -0
- package/dist/inspector/styleEditors/useFieldVisibility.d.ts +6 -0
- package/dist/inspector/styleEditors/useFieldVisibility.js +26 -0
- package/dist/inspector/tokens/TokenField.js +111 -7
- package/dist/inspector/tokens/editActions.d.ts +2 -0
- package/dist/inspector/tokens/editActions.js +2 -2
- package/dist/inspector/tokens/resolution/cssomCollector.d.ts +1 -1
- package/dist/inspector/tokens/resolution/cssomCollector.js +9 -5
- package/dist/inspector/tokens/resolution/ruleMatching.d.ts +40 -0
- package/dist/inspector/tokens/resolution/ruleMatching.js +423 -0
- package/dist/inspector/tokens/resolution/selectorSemantics.d.ts +19 -3
- package/dist/inspector/tokens/resolution/selectorSemantics.js +378 -4
- package/dist/inspector/tokens/resolution.d.ts +3 -26
- package/dist/inspector/tokens/resolution.js +44 -735
- package/dist/inspector/tokens/tokenAvailability.d.ts +18 -0
- package/dist/inspector/tokens/tokenAvailability.js +204 -0
- package/dist/inspector/ui/Button.d.ts +1 -1
- package/dist/inspector/ui/SideValuesField.js +2 -2
- package/dist/inspector/ui/StatusCallout.d.ts +4 -1
- package/dist/inspector/ui/StatusCallout.js +2 -2
- package/dist/inspector/ui/styles.js +13 -11
- package/dist/internal/agent-protocol.d.ts +65 -1
- package/dist/internal/agent-protocol.js +183 -3
- package/dist/nudge-ui.mjs +261 -57
- package/dist/transport/editor.d.ts +28 -0
- package/dist/transport/editor.js +132 -0
- package/dist/transport/index.d.ts +1 -0
- package/dist/transport/index.js +1 -0
- package/dist/transport/routes.d.ts +7 -0
- package/dist/transport/routes.js +7 -0
- package/package.json +3 -1
- package/dist/inspector/shell/panelLayout.d.ts +0 -2
- package/dist/inspector/shell/panelLayout.js +0 -29
|
@@ -4,7 +4,7 @@ import { beginPreviewAttempt, clearPreviewDiagnostics, getHostPreviewDocument, n
|
|
|
4
4
|
import { getWorkspaceChanges } from "../changes/workspaceChanges.js";
|
|
5
5
|
import { getCanvasPreviewDocument, getRegisteredFrames } from "./projection.js";
|
|
6
6
|
import { findCanvasFrameBySource, PROJECT_ID, WORKSPACE_ID } from "./projection.js";
|
|
7
|
-
import { getCanvasCards } from "./canvasStore.js";
|
|
7
|
+
import { getCanvasCards, getCanvasMode } from "./canvasStore.js";
|
|
8
8
|
import { isRendererMessageFor } from "./frameProtocol.js";
|
|
9
9
|
import { getNudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
|
|
10
10
|
const VERIFICATION_TIMEOUT_MS = 5000;
|
|
@@ -79,7 +79,7 @@ function checkTokenDrift(change) {
|
|
|
79
79
|
return null;
|
|
80
80
|
}
|
|
81
81
|
function getPreviewDocuments() {
|
|
82
|
-
const documents = [getHostPreviewDocument()];
|
|
82
|
+
const documents = getCanvasMode() === "canvas" ? [] : [getHostPreviewDocument()];
|
|
83
83
|
const frames = getRegisteredFrames();
|
|
84
84
|
for (const card of getCanvasCards()) {
|
|
85
85
|
if (frames.has(card.id))
|
|
@@ -99,15 +99,17 @@ function beginPreviewAttempts() {
|
|
|
99
99
|
}
|
|
100
100
|
function gatherMatchEvidence(changes) {
|
|
101
101
|
const evidence = new Map();
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
102
|
+
if (getCanvasMode() !== "canvas") {
|
|
103
|
+
const hostDocument = getHostPreviewDocument();
|
|
104
|
+
for (let i = 0; i < changes.length; i++) {
|
|
105
|
+
const change = changes[i];
|
|
106
|
+
if (isTokenChange(change))
|
|
107
|
+
continue;
|
|
108
|
+
if (checkSelectorInDocument(document, change.selector)) {
|
|
109
|
+
const routes = evidence.get(i) ?? [];
|
|
110
|
+
routes.push(hostDocument);
|
|
111
|
+
evidence.set(i, routes);
|
|
112
|
+
}
|
|
111
113
|
}
|
|
112
114
|
}
|
|
113
115
|
const frames = getRegisteredFrames();
|
|
@@ -131,13 +133,13 @@ function gatherMatchEvidence(changes) {
|
|
|
131
133
|
}
|
|
132
134
|
function applyStaleResults(changes, attempts) {
|
|
133
135
|
const evidence = gatherMatchEvidence(changes);
|
|
134
|
-
const
|
|
136
|
+
const tokenAttempt = attempts.values().next().value;
|
|
135
137
|
for (let i = 0; i < changes.length; i++) {
|
|
136
138
|
const change = changes[i];
|
|
137
139
|
if (isTokenChange(change)) {
|
|
138
140
|
const drift = checkTokenDrift(change);
|
|
139
|
-
if (drift &&
|
|
140
|
-
publishPreviewDiagnostic(
|
|
141
|
+
if (drift && tokenAttempt)
|
|
142
|
+
publishPreviewDiagnostic(tokenAttempt, changeKey(change), drift);
|
|
141
143
|
continue;
|
|
142
144
|
}
|
|
143
145
|
const routes = evidence.get(i);
|
|
@@ -8,6 +8,8 @@ import { workspaceChangeStore, } from "./workspaceChanges.js";
|
|
|
8
8
|
import { beginPreviewAttempt, clearPreviewDiagnostics, getHostPreviewDocument, publishPreviewDiagnostic, } from "./previewDiagnostics.js";
|
|
9
9
|
import { clearStructuralProjectionReports, pruneStructuralProjectionReports } from "../projection/structuralProjection.js";
|
|
10
10
|
import { applyHostWorkspaceProjection, compileWorkspaceProjection, } from "../projection/workspaceProjection.js";
|
|
11
|
+
import { isEditorShellDocument } from "../runtime/editorShell.js";
|
|
12
|
+
import { isOriginalPreviewActive, subscribeOriginalPreview, } from "../shell/originalPreview.js";
|
|
11
13
|
export { isComponentChange, isElementChange, isTextContentChange, isTextContentChangeValue, isPreviewableChange, isTokenChange, } from "./types.js";
|
|
12
14
|
/**
|
|
13
15
|
* Deferred delta verification (0044). Only the keys touched by a mutation are
|
|
@@ -28,14 +30,28 @@ export function getPendingRules() {
|
|
|
28
30
|
return buildManagedStyleRules(getChangesSnapshot());
|
|
29
31
|
}
|
|
30
32
|
function reapply(workspace) {
|
|
31
|
-
|
|
33
|
+
// While hold-to-view-original is active the host document intentionally
|
|
34
|
+
// shows the page without inspector changes. Commits still land in the
|
|
35
|
+
// canonical store; the release path re-projects the latest snapshot.
|
|
36
|
+
if (isOriginalPreviewActive())
|
|
37
|
+
return;
|
|
38
|
+
if (!isEditorShellDocument())
|
|
39
|
+
applyHostWorkspaceProjection(compileWorkspaceProjection(workspace));
|
|
32
40
|
}
|
|
33
41
|
function flushVerification() {
|
|
34
42
|
verificationHandle = null;
|
|
43
|
+
// Probing the original preview would report the held-back changes as
|
|
44
|
+
// conflicts. Keep the pending targets; releasing re-verifies them.
|
|
45
|
+
if (isOriginalPreviewActive())
|
|
46
|
+
return;
|
|
35
47
|
const targets = pendingVerificationTargets;
|
|
36
48
|
pendingVerificationTargets = new Map();
|
|
37
49
|
if (targets.size === 0)
|
|
38
50
|
return;
|
|
51
|
+
// The editor shell has no application document. Renderer diagnostics are
|
|
52
|
+
// owned by renderer projection reports.
|
|
53
|
+
if (isEditorShellDocument())
|
|
54
|
+
return;
|
|
39
55
|
const current = getChangesSnapshot();
|
|
40
56
|
const attempt = beginPreviewAttempt(getHostPreviewDocument(), workspaceChangeStore.getSnapshot().revision);
|
|
41
57
|
if (!attempt)
|
|
@@ -93,6 +109,20 @@ function markForVerification(keys, verificationTargets) {
|
|
|
93
109
|
if (added)
|
|
94
110
|
scheduleVerification();
|
|
95
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Releasing hold-to-view-original restores the edited preview; re-verify the
|
|
114
|
+
* surviving set against the restored DOM instead of leaving peek-era state.
|
|
115
|
+
* The retry is forced: a flush that ran during the hold retains its targets
|
|
116
|
+
* without scheduling, so markForVerification alone would see every key
|
|
117
|
+
* already present and schedule nothing.
|
|
118
|
+
*/
|
|
119
|
+
subscribeOriginalPreview(() => {
|
|
120
|
+
if (isOriginalPreviewActive())
|
|
121
|
+
return;
|
|
122
|
+
markForVerification(getChangesSnapshot().map(changeKey));
|
|
123
|
+
if (pendingVerificationTargets.size > 0)
|
|
124
|
+
scheduleVerification();
|
|
125
|
+
});
|
|
96
126
|
/** Append records and report whether canonical workspace state changed. */
|
|
97
127
|
export function appendChanges(incoming, options = {}) {
|
|
98
128
|
const result = workspaceChangeStore.commitChangeRecords(incoming);
|
|
@@ -3,4 +3,4 @@ import { type ChangeRecord, type PreviewableChangeRecord } from "./types.js";
|
|
|
3
3
|
/** The source selector stays canonical; the projection marker is document-local. */
|
|
4
4
|
export declare function selectorForManagedChange(change: PreviewableChangeRecord): string | null;
|
|
5
5
|
export declare function buildManagedStyleRules(changes: ChangeRecord[]): StyleRule[];
|
|
6
|
-
export declare function verifyManagedStyleProjection(change: PreviewableChangeRecord, selectedElement?: HTMLElement | null): PreviewResult | null;
|
|
6
|
+
export declare function verifyManagedStyleProjection(change: PreviewableChangeRecord, selectedElement?: HTMLElement | null, ownerDocument?: Document): PreviewResult | null;
|
|
@@ -63,7 +63,7 @@ export function buildManagedStyleRules(changes) {
|
|
|
63
63
|
// emitted afterwards so their additional marker specificity wins.
|
|
64
64
|
return [...sourceRules.values(), ...instanceRules.values()];
|
|
65
65
|
}
|
|
66
|
-
export function verifyManagedStyleProjection(change, selectedElement) {
|
|
66
|
+
export function verifyManagedStyleProjection(change, selectedElement, ownerDocument = document) {
|
|
67
67
|
// Deferred verification must use the selection that existed when the
|
|
68
68
|
// projection was committed. Reading the live selection here can make a
|
|
69
69
|
// host-document change verify against a later canvas selection (or vice
|
|
@@ -75,13 +75,13 @@ export function verifyManagedStyleProjection(change, selectedElement) {
|
|
|
75
75
|
// A Canvas-only selection belongs to an iframe. The controller stylesheet
|
|
76
76
|
// cannot verify it synchronously; leave its result unknown until the frame
|
|
77
77
|
// has received the canonical projection rather than claiming it is stale.
|
|
78
|
-
if (selected && selected.ownerDocument !==
|
|
78
|
+
if (selected && selected.ownerDocument !== ownerDocument) {
|
|
79
79
|
return null;
|
|
80
80
|
}
|
|
81
81
|
let targets = [];
|
|
82
82
|
try {
|
|
83
83
|
const selector = selectorForManagedChange(change);
|
|
84
|
-
targets = selector ? Array.from(
|
|
84
|
+
targets = selector ? Array.from(ownerDocument.querySelectorAll(selector)) : [];
|
|
85
85
|
}
|
|
86
86
|
catch {
|
|
87
87
|
targets = [];
|
|
@@ -4,6 +4,10 @@ export interface StructuralDelete {
|
|
|
4
4
|
id: string;
|
|
5
5
|
kind: "delete";
|
|
6
6
|
target: RenderedInstanceRef;
|
|
7
|
+
/** Hash-independent route where the target was captured. */
|
|
8
|
+
route?: string;
|
|
9
|
+
/** Bounded view identity where the target was captured. */
|
|
10
|
+
state?: string;
|
|
7
11
|
}
|
|
8
12
|
/** Controller-owned intent to move one rendered instance. */
|
|
9
13
|
export interface StructuralMove {
|
|
@@ -8,6 +8,11 @@ export interface NudgeUiClientManifest {
|
|
|
8
8
|
readonly version: typeof NUDGE_UI_CLIENT_MANIFEST_VERSION;
|
|
9
9
|
readonly revision: number;
|
|
10
10
|
readonly runtime: NudgeUiRuntimeConfig;
|
|
11
|
+
/** Project-owned, loopback-only agent bridge started by the dev host. */
|
|
12
|
+
readonly agentBridge?: {
|
|
13
|
+
readonly baseUrl: string;
|
|
14
|
+
readonly autoConnect?: boolean;
|
|
15
|
+
};
|
|
11
16
|
/** Optional document preparation requested by the host Adapter. */
|
|
12
17
|
readonly document?: {
|
|
13
18
|
readonly runtimeIdentity?: "static-html";
|
|
@@ -20,6 +20,7 @@ value) {
|
|
|
20
20
|
version: NUDGE_UI_CLIENT_MANIFEST_VERSION,
|
|
21
21
|
revision: value.revision,
|
|
22
22
|
runtime: normalizeNudgeUiRuntimeConfig(value.runtime),
|
|
23
|
+
...(isAgentBridge(value.agentBridge) ? { agentBridge: value.agentBridge } : {}),
|
|
23
24
|
...(value.document === undefined ? {} : { document: value.document }),
|
|
24
25
|
...(value.reload === undefined ? {} : { reload: value.reload }),
|
|
25
26
|
};
|
|
@@ -28,6 +29,16 @@ value) {
|
|
|
28
29
|
return null;
|
|
29
30
|
}
|
|
30
31
|
}
|
|
32
|
+
function isAgentBridge(value) {
|
|
33
|
+
if (value === undefined)
|
|
34
|
+
return false;
|
|
35
|
+
if (!isRecord(value))
|
|
36
|
+
return false;
|
|
37
|
+
const candidate = value;
|
|
38
|
+
if (typeof candidate.baseUrl !== "string" || candidate.baseUrl.length === 0)
|
|
39
|
+
return false;
|
|
40
|
+
return candidate.autoConnect === undefined || typeof candidate.autoConnect === "boolean";
|
|
41
|
+
}
|
|
31
42
|
function isDocumentOptions(
|
|
32
43
|
// Optional manifest capability is parsed before use.
|
|
33
44
|
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { getNudgeUiRuntimeConfig } from "../runtime/runtimeConfig.js";
|
|
2
2
|
import { copyComponentOverrides, copyRuntimeTarget, getHostRuntimeAdapters, registerHostRuntimeAdapter, replaceHostRuntimeAdapterOverrides, } from "./runtimeBridge.js";
|
|
3
3
|
const diagnosedAdapters = new WeakSet();
|
|
4
|
-
function enabledRuntimeAdapters() {
|
|
4
|
+
function enabledRuntimeAdapters(ownerGlobal) {
|
|
5
5
|
if (!getNudgeUiRuntimeConfig().capabilities.componentSemantics)
|
|
6
6
|
return [];
|
|
7
|
-
return [...getHostRuntimeAdapters()];
|
|
7
|
+
return [...getHostRuntimeAdapters(ownerGlobal)];
|
|
8
8
|
}
|
|
9
9
|
/** Register a framework adapter without coupling semantic resolution to React. */
|
|
10
10
|
export function registerComponentRuntimeAdapter(adapter) {
|
|
@@ -12,7 +12,8 @@ export function registerComponentRuntimeAdapter(adapter) {
|
|
|
12
12
|
}
|
|
13
13
|
export function inspectComponentTargets(element) {
|
|
14
14
|
const targets = [];
|
|
15
|
-
|
|
15
|
+
const ownerGlobal = element.ownerDocument.defaultView ?? globalThis;
|
|
16
|
+
for (const adapter of enabledRuntimeAdapters(ownerGlobal)) {
|
|
16
17
|
let inspected;
|
|
17
18
|
try {
|
|
18
19
|
inspected = adapter.inspect(element);
|
|
@@ -11,8 +11,8 @@ export declare const NUDGE_UI_HOST_RUNTIME_VERSION = 1;
|
|
|
11
11
|
* not accumulate stale implementations.
|
|
12
12
|
*/
|
|
13
13
|
export declare function registerHostRuntimeAdapter(adapter: ComponentRuntimeAdapter): () => void;
|
|
14
|
-
/** Returns the active host runtime Adapters for
|
|
15
|
-
export declare function getHostRuntimeAdapters(): readonly ComponentRuntimeAdapter[];
|
|
14
|
+
/** Returns the active host runtime Adapters for the requested browser realm. */
|
|
15
|
+
export declare function getHostRuntimeAdapters(ownerGlobal?: typeof globalThis): readonly ComponentRuntimeAdapter[];
|
|
16
16
|
/** Stores the latest projection and sends it to every registered host Adapter. */
|
|
17
17
|
export declare function replaceHostRuntimeAdapterOverrides(overrides: readonly ComponentOverride[]): void;
|
|
18
18
|
/**
|
|
@@ -42,9 +42,22 @@ export function registerHostRuntimeAdapter(adapter) {
|
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
|
-
/** Returns the active host runtime Adapters for
|
|
46
|
-
export function getHostRuntimeAdapters() {
|
|
47
|
-
|
|
45
|
+
/** Returns the active host runtime Adapters for the requested browser realm. */
|
|
46
|
+
export function getHostRuntimeAdapters(ownerGlobal = globalThis) {
|
|
47
|
+
if (ownerGlobal === globalThis)
|
|
48
|
+
return [...registry().adapters.values()];
|
|
49
|
+
const current = ownerGlobal[HOST_RUNTIME_KEY];
|
|
50
|
+
if (current === undefined)
|
|
51
|
+
return [];
|
|
52
|
+
const mapConstructor = Reflect.get(ownerGlobal, "Map");
|
|
53
|
+
if (!mapConstructor
|
|
54
|
+
|| typeof current !== "object"
|
|
55
|
+
|| current === null
|
|
56
|
+
|| current.version !== NUDGE_UI_HOST_RUNTIME_VERSION
|
|
57
|
+
|| !(current.adapters instanceof mapConstructor)) {
|
|
58
|
+
throw new Error(`Nudge UI host runtime is incompatible with version ${NUDGE_UI_HOST_RUNTIME_VERSION}.`);
|
|
59
|
+
}
|
|
60
|
+
return [...(current.adapters.values())];
|
|
48
61
|
}
|
|
49
62
|
/** Stores the latest projection and sends it to every registered host Adapter. */
|
|
50
63
|
export function replaceHostRuntimeAdapterOverrides(overrides) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { resolveNudgeUiClientEntry } from "../transport/editor.js";
|
|
1
2
|
export declare function bootstrapNudgeUi(inspectorHost: HTMLElement): void;
|
|
2
3
|
export declare function mountInspector(host: HTMLElement): void;
|
|
3
4
|
export declare function unmountInspector(): void;
|
|
@@ -6,6 +7,7 @@ export { InspectorShell } from "./shell/InspectorShell.js";
|
|
|
6
7
|
export { detectFramework } from "./prompt/detectFramework.js";
|
|
7
8
|
export { installStaticHtmlRuntimeIdentity, isRuntimeGeneratedSource, RUNTIME_ELEMENT_CID_PREFIX, RUNTIME_UNKNOWN_SOURCE_PREFIX, } from "./runtime/staticHtmlRuntimeIdentity.js";
|
|
8
9
|
export { isCanvasRenderer } from "./canvas/roleDetection.js";
|
|
10
|
+
export { createNudgeUiEditorUrl, hasNudgeUiDirectTabIntent, isNudgeUiDirectUrl, readNudgeUiEditorTarget, rememberNudgeUiDirectTabIntent, } from "../transport/editor.js";
|
|
9
11
|
export { NUDGE_UI_INSPECTION_VERSION, inspectElement, installInspectionBridge } from "./inspection/bridge.js";
|
|
10
12
|
export type { NudgeUiInspectionBridge, ElementInspection, InspectElementOptions, InspectionCatalogEntry, InspectionControl } from "./inspection/bridge.js";
|
|
11
13
|
export { beginInlineTextEdit, cancelInlineTextEdit, disposeInlineTextEdit, getInlineTextDiagnostic, getInlineTextDiagnostics, getInlineTextSession, inlineTextEditor, isInlineTextEditingActive, subscribeInlineTextDiagnostics, resolveTextBinding, useInlineTextSession, } from "./inline-text/inlineTextEditor.js";
|
package/dist/inspector/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { createElement } from "react";
|
|
2
2
|
import { createRoot } from "react-dom/client";
|
|
3
|
-
import { InspectorShell, toggleInspector, setInspectorOpen
|
|
3
|
+
import { InspectorShell, toggleInspector, setInspectorOpen } from "./shell/InspectorShell.js";
|
|
4
4
|
import { setSelectedElement } from "./selection/selectionStore.js";
|
|
5
5
|
import { removeManagedSheet } from "./projection/managedStylesheet.js";
|
|
6
|
-
import { isInspectorToggleShortcut } from "./shell/shortcuts.js";
|
|
7
|
-
import { clearInspectorLayout } from "./shell/panelLayout.js";
|
|
6
|
+
import { isInspectorToggleShortcut, isOriginalPreviewShortcut, SEND_PROMPT_HOTKEY_EVENT, } from "./shell/shortcuts.js";
|
|
8
7
|
import { isCanvasRenderer } from "./canvas/roleDetection.js";
|
|
8
|
+
import { isKeyboardShortcutMessage } from "./canvas/frameProtocol.js";
|
|
9
|
+
import { subscribeCanvasRendererMessages } from "./canvas/rendererMessageRouter.js";
|
|
9
10
|
import { bootstrapRenderer } from "./canvas/rendererBootstrap.js";
|
|
10
11
|
import { hydrateSession, enableAutoSave, scheduleAutoSave, scheduleCanvasSave, setRestoreCount, } from "./canvas/sessionStore.js";
|
|
11
12
|
import { subscribeChanges, getChangesList } from "./changes/changesLog.js";
|
|
@@ -15,14 +16,18 @@ import { cancelStaleDetection, startStaleDetection } from "./canvas/staleChangeD
|
|
|
15
16
|
import { LockedWorkspaceNotice } from "./canvas/LockedWorkspaceNotice.js";
|
|
16
17
|
import { AppShell } from "./shell/AppShell.js";
|
|
17
18
|
import { installInspectionBridge } from "./inspection/bridge.js";
|
|
18
|
-
import {
|
|
19
|
-
import { releaseDocumentProjection } from "./projection/structuralProjection.js";
|
|
19
|
+
import { releaseDocumentProjection, subscribeStructuralChanges } from "./projection/structuralProjection.js";
|
|
20
20
|
import { cancelInlineTextEdit } from "./inline-text/inlineTextEditor.js";
|
|
21
21
|
import { configureNudgeUiRuntime, getNudgeUiRuntimeConfig, isDemoRuntime } from "./runtime/runtimeConfig.js";
|
|
22
22
|
import { setCanvasMode } from "./canvas/canvasStore.js";
|
|
23
23
|
import { isNudgeUiDev, setNudgeUiHostDevFlag } from "./runtime/devFlag.js";
|
|
24
|
-
import { clearClipboardHandoff,
|
|
24
|
+
import { clearClipboardHandoff, subscribeClipboardHandoff, } from "./prompt/clipboardHandoff.js";
|
|
25
25
|
import { createWorkspace, InspectorSessionProvider, } from "./session/index.js";
|
|
26
|
+
import { clearSketchClipboardHandoff } from "./sketch/handoff.js";
|
|
27
|
+
import { cancelSketchInteraction, isSketchInteractionActive } from "./sketch/interaction.js";
|
|
28
|
+
import { setOriginalPreviewActive } from "./shell/originalPreview.js";
|
|
29
|
+
import { initializeSketchStore } from "./sketch/store.js";
|
|
30
|
+
export { resolveNudgeUiClientEntry } from "../transport/editor.js";
|
|
26
31
|
let hostElement = null;
|
|
27
32
|
let reactRoot = null;
|
|
28
33
|
let lockedRoot = null;
|
|
@@ -33,11 +38,47 @@ let beforeUnloadAttached = false;
|
|
|
33
38
|
let persistenceSubscribed = false;
|
|
34
39
|
let unsubscribeOwnership = null;
|
|
35
40
|
let removeInspectionBridge = null;
|
|
36
|
-
let
|
|
41
|
+
let keyboardPeekHeld = false;
|
|
37
42
|
function onKeydown(e) {
|
|
43
|
+
if (isSketchInteractionActive())
|
|
44
|
+
return;
|
|
38
45
|
if (isInspectorToggleShortcut(e)) {
|
|
39
46
|
toggleInspector();
|
|
40
47
|
e.preventDefault();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (isOriginalPreviewShortcut(e)) {
|
|
51
|
+
keyboardPeekHeld = true;
|
|
52
|
+
setOriginalPreviewActive(true);
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function onKeyup(e) {
|
|
57
|
+
// Release only a keyboard-started peek so a button-held preview survives
|
|
58
|
+
// unrelated Backslash keyups (e.g. the panel-toggle shortcuts pressed
|
|
59
|
+
// mid-hold). A guarded keydown never sets the flag, so this stays a no-op
|
|
60
|
+
// for keyups without a matching hold.
|
|
61
|
+
if (e.code === "Backslash" && keyboardPeekHeld) {
|
|
62
|
+
keyboardPeekHeld = false;
|
|
63
|
+
setOriginalPreviewActive(false);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function onRendererKeyboardShortcut(message, identity) {
|
|
67
|
+
if (!isKeyboardShortcutMessage(message, identity))
|
|
68
|
+
return;
|
|
69
|
+
if (message.code === "KeyS" && message.phase === "keydown") {
|
|
70
|
+
window.dispatchEvent(new Event(SEND_PROMPT_HOTKEY_EVENT));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (message.code !== "Backslash")
|
|
74
|
+
return;
|
|
75
|
+
if (message.phase === "keydown") {
|
|
76
|
+
keyboardPeekHeld = true;
|
|
77
|
+
setOriginalPreviewActive(true);
|
|
78
|
+
}
|
|
79
|
+
else if (keyboardPeekHeld) {
|
|
80
|
+
keyboardPeekHeld = false;
|
|
81
|
+
setOriginalPreviewActive(false);
|
|
41
82
|
}
|
|
42
83
|
}
|
|
43
84
|
function disposeInspectorSession() {
|
|
@@ -57,11 +98,15 @@ export function bootstrapNudgeUi(inspectorHost) {
|
|
|
57
98
|
// for its own document. The bundle mode name alone must never flip it,
|
|
58
99
|
// so every build without both opt-ins stays governed by ADR-0002.
|
|
59
100
|
setNudgeUiHostDevFlag(true);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
101
|
+
if (runtimeConfig.capabilities.canvas && isCanvasRenderer()) {
|
|
102
|
+
rendererBootstrapHandle = bootstrapRenderer() ?? null;
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// The public demo shares the iframe editor while keeping the write lease,
|
|
106
|
+
// persistence, and agent bridge disabled.
|
|
107
|
+
setCanvasMode("canvas");
|
|
64
108
|
mountInspector(inspectorHost);
|
|
109
|
+
setInspectorOpen(false);
|
|
65
110
|
return;
|
|
66
111
|
}
|
|
67
112
|
if (!runtimeConfig.capabilities.canvas) {
|
|
@@ -94,6 +139,7 @@ function startController(inspectorHost) {
|
|
|
94
139
|
lockedRoot.unmount();
|
|
95
140
|
lockedRoot = null;
|
|
96
141
|
}
|
|
142
|
+
void initializeSketchStore(getNudgeUiRuntimeConfig().projectId).catch(() => undefined);
|
|
97
143
|
unsubscribeOwnership?.();
|
|
98
144
|
unsubscribeOwnership = subscribeOwnership((hasLease) => {
|
|
99
145
|
if (!hasLease)
|
|
@@ -107,9 +153,12 @@ function startController(inspectorHost) {
|
|
|
107
153
|
startStaleDetection(restored);
|
|
108
154
|
}
|
|
109
155
|
}
|
|
156
|
+
if (getNudgeUiRuntimeConfig().capabilities.canvas) {
|
|
157
|
+
// Normal controllers always host the iframe workspace. Hydration runs
|
|
158
|
+
// first so this mode change cannot discard cards, camera, or edits.
|
|
159
|
+
setCanvasMode("canvas");
|
|
160
|
+
}
|
|
110
161
|
mountInspector(inspectorHost);
|
|
111
|
-
stopClipboardHandoffController?.();
|
|
112
|
-
stopClipboardHandoffController = startClipboardHandoffController(document);
|
|
113
162
|
enableAutoSave();
|
|
114
163
|
if (!beforeUnloadAttached) {
|
|
115
164
|
// enableAutoSave registers its flush listener first. Release the lease only
|
|
@@ -120,14 +169,13 @@ function startController(inspectorHost) {
|
|
|
120
169
|
}
|
|
121
170
|
if (!persistenceSubscribed) {
|
|
122
171
|
subscribeChanges(() => scheduleAutoSave());
|
|
172
|
+
subscribeStructuralChanges(() => scheduleAutoSave());
|
|
123
173
|
subscribeClipboardHandoff(() => scheduleAutoSave());
|
|
124
174
|
subscribeCanvas(() => scheduleCanvasSave());
|
|
125
175
|
persistenceSubscribed = true;
|
|
126
176
|
}
|
|
127
177
|
}
|
|
128
178
|
function mountLockedNotice(host) {
|
|
129
|
-
stopClipboardHandoffController?.();
|
|
130
|
-
stopClipboardHandoffController = null;
|
|
131
179
|
if (reactRoot) {
|
|
132
180
|
reactRoot.unmount();
|
|
133
181
|
reactRoot = null;
|
|
@@ -139,8 +187,9 @@ function mountLockedNotice(host) {
|
|
|
139
187
|
cancelStaleDetection();
|
|
140
188
|
setInspectorOpen(false);
|
|
141
189
|
cancelInlineTextEdit();
|
|
190
|
+
cancelSketchInteraction();
|
|
191
|
+
clearSketchClipboardHandoff();
|
|
142
192
|
setSelectedElement(null);
|
|
143
|
-
clearInspectorLayout();
|
|
144
193
|
removeManagedSheet();
|
|
145
194
|
releaseDocumentProjection(document);
|
|
146
195
|
hostElement = null;
|
|
@@ -178,21 +227,20 @@ export function mountInspector(host) {
|
|
|
178
227
|
if (!reactRoot) {
|
|
179
228
|
reactRoot = createRoot(shadow);
|
|
180
229
|
inspectorSession = workspace.createInspectorSession(host);
|
|
181
|
-
const documentSession = inspectorSession.createDocumentSession(document);
|
|
182
|
-
documentSession.registerCleanup(() => disposeBrowserCssInspection(document));
|
|
183
|
-
documentSession.registerCleanup(() => releaseDocumentProjection(document));
|
|
184
230
|
inspectorSession.registerCleanup(() => window.removeEventListener("keydown", onKeydown));
|
|
185
|
-
|
|
186
|
-
|
|
231
|
+
inspectorSession.registerCleanup(() => window.removeEventListener("keyup", onKeyup));
|
|
232
|
+
inspectorSession.registerCleanup(subscribeCanvasRendererMessages(({ identity, message }) => {
|
|
233
|
+
onRendererKeyboardShortcut(message, identity);
|
|
234
|
+
}));
|
|
235
|
+
reactRoot.render(createElement(InspectorSessionProvider, { inspector: inspectorSession, documentSession: null }, createElement(AppShell)));
|
|
187
236
|
window.addEventListener("keydown", onKeydown);
|
|
237
|
+
window.addEventListener("keyup", onKeyup);
|
|
188
238
|
}
|
|
189
239
|
setInspectorOpen(true);
|
|
190
240
|
}
|
|
191
241
|
export function unmountInspector() {
|
|
192
242
|
rendererBootstrapHandle?.teardown();
|
|
193
243
|
rendererBootstrapHandle = null;
|
|
194
|
-
stopClipboardHandoffController?.();
|
|
195
|
-
stopClipboardHandoffController = null;
|
|
196
244
|
unsubscribeOwnership?.();
|
|
197
245
|
unsubscribeOwnership = null;
|
|
198
246
|
if (lockedRoot) {
|
|
@@ -201,6 +249,7 @@ export function unmountInspector() {
|
|
|
201
249
|
}
|
|
202
250
|
cancelStaleDetection();
|
|
203
251
|
cancelInlineTextEdit();
|
|
252
|
+
cancelSketchInteraction();
|
|
204
253
|
setSelectedElement(null);
|
|
205
254
|
if (reactRoot) {
|
|
206
255
|
reactRoot.unmount();
|
|
@@ -215,8 +264,8 @@ export function unmountInspector() {
|
|
|
215
264
|
// a session (gestures, workspace projection) cannot leak across unmount.
|
|
216
265
|
releaseDocumentProjection(document);
|
|
217
266
|
clearClipboardHandoff();
|
|
267
|
+
clearSketchClipboardHandoff();
|
|
218
268
|
removeManagedSheet();
|
|
219
|
-
clearInspectorLayout();
|
|
220
269
|
removeInspectionBridge?.();
|
|
221
270
|
removeInspectionBridge = null;
|
|
222
271
|
hostElement = null;
|
|
@@ -227,6 +276,7 @@ export { InspectorShell } from "./shell/InspectorShell.js";
|
|
|
227
276
|
export { detectFramework } from "./prompt/detectFramework.js";
|
|
228
277
|
export { installStaticHtmlRuntimeIdentity, isRuntimeGeneratedSource, RUNTIME_ELEMENT_CID_PREFIX, RUNTIME_UNKNOWN_SOURCE_PREFIX, } from "./runtime/staticHtmlRuntimeIdentity.js";
|
|
229
278
|
export { isCanvasRenderer } from "./canvas/roleDetection.js";
|
|
279
|
+
export { createNudgeUiEditorUrl, hasNudgeUiDirectTabIntent, isNudgeUiDirectUrl, readNudgeUiEditorTarget, rememberNudgeUiDirectTabIntent, } from "../transport/editor.js";
|
|
230
280
|
export { NUDGE_UI_INSPECTION_VERSION, inspectElement, installInspectionBridge } from "./inspection/bridge.js";
|
|
231
281
|
export { beginInlineTextEdit, cancelInlineTextEdit, disposeInlineTextEdit, getInlineTextDiagnostic, getInlineTextDiagnostics, getInlineTextSession, inlineTextEditor, isInlineTextEditingActive, subscribeInlineTextDiagnostics, resolveTextBinding, useInlineTextSession, } from "./inline-text/inlineTextEditor.js";
|
|
232
282
|
export { projectInspectorValues, projectionSides } from "./spacing/projection.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { InlineTextDiagnostic } from "./inlineTextEditor.js";
|
|
2
|
+
export declare function recordInlineTextDiagnostic(diagnostic: InlineTextDiagnostic, ownerDocument?: Document, target?: Element): void;
|
|
3
|
+
export declare function getInlineTextDiagnostics(): readonly InlineTextDiagnostic[];
|
|
4
|
+
export declare function getInlineTextDiagnostic(): InlineTextDiagnostic | null;
|
|
5
|
+
export declare function subscribeInlineTextDiagnostics(listener: () => void): () => void;
|
|
6
|
+
export declare function useInlineTextDiagnostic(): InlineTextDiagnostic | null;
|
|
7
|
+
/** Clear the current diagnostic, optionally only when it belongs to a frame. */
|
|
8
|
+
export declare function clearInlineTextDiagnostics(ownerDocument?: Document): void;
|
|
9
|
+
/** Keep feedback for the target that was just selected, but clear stale feedback. */
|
|
10
|
+
export declare function clearInlineTextDiagnosticsForSelection(selectedElements: readonly HTMLElement[]): void;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
|
+
const listeners = new Set();
|
|
3
|
+
let diagnostics = [];
|
|
4
|
+
let revision = 0;
|
|
5
|
+
function notify() {
|
|
6
|
+
revision += 1;
|
|
7
|
+
for (const listener of listeners)
|
|
8
|
+
listener();
|
|
9
|
+
}
|
|
10
|
+
function sameDiagnostic(left, right) {
|
|
11
|
+
return left.kind === right.kind
|
|
12
|
+
&& left.status === right.status
|
|
13
|
+
&& left.reason === right.reason
|
|
14
|
+
&& left.before === right.before
|
|
15
|
+
&& left.after === right.after;
|
|
16
|
+
}
|
|
17
|
+
export function recordInlineTextDiagnostic(diagnostic, ownerDocument, target) {
|
|
18
|
+
const resolvedDocument = ownerDocument ?? target?.ownerDocument;
|
|
19
|
+
const previous = diagnostics.at(-1);
|
|
20
|
+
if (previous
|
|
21
|
+
&& previous.ownerDocument === resolvedDocument
|
|
22
|
+
&& previous.target === target
|
|
23
|
+
&& sameDiagnostic(previous.diagnostic, diagnostic)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
diagnostics = [
|
|
27
|
+
...diagnostics.slice(-31),
|
|
28
|
+
{ diagnostic, ownerDocument: resolvedDocument, target },
|
|
29
|
+
];
|
|
30
|
+
notify();
|
|
31
|
+
}
|
|
32
|
+
export function getInlineTextDiagnostics() {
|
|
33
|
+
return diagnostics.map(({ diagnostic }) => diagnostic);
|
|
34
|
+
}
|
|
35
|
+
export function getInlineTextDiagnostic() {
|
|
36
|
+
return diagnostics.at(-1)?.diagnostic ?? null;
|
|
37
|
+
}
|
|
38
|
+
export function subscribeInlineTextDiagnostics(listener) {
|
|
39
|
+
listeners.add(listener);
|
|
40
|
+
return () => listeners.delete(listener);
|
|
41
|
+
}
|
|
42
|
+
export function useInlineTextDiagnostic() {
|
|
43
|
+
useSyncExternalStore(subscribeInlineTextDiagnostics, () => revision, () => revision);
|
|
44
|
+
return getInlineTextDiagnostic();
|
|
45
|
+
}
|
|
46
|
+
/** Clear the current diagnostic, optionally only when it belongs to a frame. */
|
|
47
|
+
export function clearInlineTextDiagnostics(ownerDocument) {
|
|
48
|
+
const current = diagnostics.at(-1);
|
|
49
|
+
if (!current)
|
|
50
|
+
return;
|
|
51
|
+
if (ownerDocument && current.ownerDocument !== ownerDocument)
|
|
52
|
+
return;
|
|
53
|
+
diagnostics = [];
|
|
54
|
+
notify();
|
|
55
|
+
}
|
|
56
|
+
/** Keep feedback for the target that was just selected, but clear stale feedback. */
|
|
57
|
+
export function clearInlineTextDiagnosticsForSelection(selectedElements) {
|
|
58
|
+
const current = diagnostics.at(-1);
|
|
59
|
+
if (!current)
|
|
60
|
+
return;
|
|
61
|
+
const target = current.target;
|
|
62
|
+
if (target && selectedElements.length === 1 && selectedElements[0] === target)
|
|
63
|
+
return;
|
|
64
|
+
clearInlineTextDiagnostics();
|
|
65
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type TextBindingChoice, type TextEditBinding, type TextEditRejection } from "../componentSemantics/textBinding.js";
|
|
1
|
+
import { type TextBindingChoice, type TextEditBinding, type TextEditRejection, type TextEditRejectionReason } from "../componentSemantics/textBinding.js";
|
|
2
2
|
import type { ChangeRecord } from "../changes/types.js";
|
|
3
3
|
import type { TextProjectionScope } from "./textChangeBoundary.js";
|
|
4
4
|
export type { TextEditBinding, TextEditRejection } from "../componentSemantics/textBinding.js";
|
|
@@ -28,13 +28,11 @@ export type InlineTextInputRejectionReason = "cross-host-range" | "rich-input" |
|
|
|
28
28
|
export interface InlineTextDiagnostic {
|
|
29
29
|
kind: "inline-text";
|
|
30
30
|
status: "started" | "committed" | "cancelled" | "rejected";
|
|
31
|
-
reason: InlineTextSessionEndReason | InlineTextInputRejectionReason;
|
|
31
|
+
reason: InlineTextSessionEndReason | InlineTextInputRejectionReason | TextEditRejectionReason;
|
|
32
32
|
before: string;
|
|
33
33
|
after?: string;
|
|
34
34
|
}
|
|
35
|
-
export
|
|
36
|
-
export declare function getInlineTextDiagnostic(): InlineTextDiagnostic | null;
|
|
37
|
-
export declare function subscribeInlineTextDiagnostics(listener: () => void): () => void;
|
|
35
|
+
export { clearInlineTextDiagnostics, getInlineTextDiagnostic, getInlineTextDiagnostics, subscribeInlineTextDiagnostics, useInlineTextDiagnostic, } from "./inlineTextDiagnostics.js";
|
|
38
36
|
export declare function getInlineTextSession(): InlineTextSession | null;
|
|
39
37
|
export declare function useInlineTextSession(): InlineTextSession | null;
|
|
40
38
|
export declare function isInlineTextEditingActive(): boolean;
|