nudge-ui 0.2.3 → 0.2.5
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/dist/cli/agentCommand.js +4 -28
- package/dist/client.mjs +870 -212
- package/dist/hosts/next/wrapper.js +1 -7
- package/dist/hosts/projectBridge.js +3 -17
- package/dist/inspector/agent/McpConnectionDialog.js +7 -3
- package/dist/inspector/agent/activity.d.ts +1 -1
- package/dist/inspector/agent/activity.js +3 -2
- package/dist/inspector/agent/client.d.ts +2 -2
- package/dist/inspector/agent/client.js +28 -29
- package/dist/inspector/agent/connectionStatus.d.ts +3 -1
- package/dist/inspector/agent/connectionStatus.js +25 -0
- package/dist/inspector/agent/httpTransport.js +31 -147
- package/dist/inspector/agent/protocol.d.ts +1 -1
- package/dist/inspector/agent/protocol.js +1 -1
- package/dist/inspector/agent/verification.d.ts +5 -7
- package/dist/inspector/agent/verification.js +67 -20
- package/dist/inspector/boot.d.ts +3 -0
- package/dist/inspector/boot.js +297 -0
- package/dist/inspector/canvas/AgentActivityOverlay.d.ts +2 -1
- package/dist/inspector/canvas/AgentActivityOverlay.js +6 -3
- package/dist/inspector/canvas/CanvasCard.js +23 -12
- package/dist/inspector/canvas/CanvasElementOverlay.js +97 -128
- package/dist/inspector/canvas/CanvasToolbar.js +2 -1
- package/dist/inspector/canvas/CanvasWorkspace.js +119 -162
- package/dist/inspector/canvas/LockedWorkspaceNotice.d.ts +3 -2
- package/dist/inspector/canvas/LockedWorkspaceNotice.js +10 -6
- package/dist/inspector/canvas/PageCard.d.ts +10 -0
- package/dist/inspector/canvas/PageCard.js +51 -0
- package/dist/inspector/canvas/SketchToolOptions.d.ts +5 -0
- package/dist/inspector/canvas/SketchToolOptions.js +86 -0
- package/dist/inspector/canvas/StaleChangeIndicator.d.ts +1 -1
- package/dist/inspector/canvas/StaleChangeIndicator.js +1 -1
- package/dist/inspector/canvas/ToolOptionsDrawer.d.ts +21 -0
- package/dist/inspector/canvas/ToolOptionsDrawer.js +77 -0
- package/dist/inspector/canvas/activeCanvasDocument.d.ts +3 -2
- package/dist/inspector/canvas/assets/eraser.svg +28 -0
- package/dist/inspector/canvas/assets/pen.svg +25 -0
- package/dist/inspector/canvas/canvasFrame.d.ts +16 -0
- package/dist/inspector/canvas/canvasFrame.js +10 -0
- package/dist/inspector/canvas/canvasGestures.d.ts +0 -1
- package/dist/inspector/canvas/canvasGestures.js +0 -6
- package/dist/inspector/canvas/canvasStore.d.ts +6 -0
- package/dist/inspector/canvas/canvasStore.js +36 -1
- package/dist/inspector/canvas/frameConnection.d.ts +48 -0
- package/dist/inspector/canvas/frameConnection.js +73 -0
- package/dist/inspector/canvas/frameProtocol.d.ts +18 -1
- package/dist/inspector/canvas/frameProtocol.js +36 -0
- package/dist/inspector/canvas/frameScrollbarStyles.d.ts +3 -0
- package/dist/inspector/canvas/frameScrollbarStyles.js +21 -0
- package/dist/inspector/canvas/pageSurface.d.ts +11 -0
- package/dist/inspector/canvas/pageSurface.js +34 -0
- package/dist/inspector/canvas/projection.d.ts +19 -9
- package/dist/inspector/canvas/projection.js +58 -31
- package/dist/inspector/canvas/rendererBootstrap.js +4 -1
- package/dist/inspector/canvas/rendererElementSelector.js +9 -1
- package/dist/inspector/canvas/rendererMessageRouter.d.ts +4 -5
- package/dist/inspector/canvas/rendererMessageRouter.js +12 -16
- package/dist/inspector/canvas/rendererSelectionProxy.d.ts +7 -1
- package/dist/inspector/canvas/rendererSelectionProxy.js +8 -36
- package/dist/inspector/canvas/rendererStylesheet.js +15 -0
- package/dist/inspector/canvas/sessionStore.d.ts +2 -2
- package/dist/inspector/canvas/sessionStore.js +12 -9
- package/dist/inspector/canvas/staleChangeDetector.d.ts +1 -1
- package/dist/inspector/canvas/staleChangeDetector.js +10 -22
- package/dist/inspector/changes/codecs.d.ts +2 -0
- package/dist/inspector/changes/codecs.js +27 -3
- package/dist/inspector/changes/draftPreview.d.ts +12 -0
- package/dist/inspector/changes/draftPreview.js +133 -0
- package/dist/inspector/changes/editModel.d.ts +18 -0
- package/dist/inspector/changes/editModel.js +16 -3
- package/dist/inspector/changes/managedStyleProjection.js +2 -1
- package/dist/inspector/changes/previewDiagnostics.js +1 -1
- package/dist/inspector/changes/types.d.ts +18 -1
- package/dist/inspector/comments/CommentsOverlay.js +18 -16
- package/dist/inspector/comments/element.js +10 -3
- package/dist/inspector/comments/store.js +3 -2
- package/dist/inspector/comments/verification.js +1 -1
- package/dist/inspector/componentSemantics/ComponentPropsSection.js +2 -1
- package/dist/inspector/componentSemantics/adapterRegistry.d.ts +6 -1
- package/dist/inspector/componentSemantics/adapterRegistry.js +23 -1
- package/dist/inspector/componentSemantics/changeAction.js +1 -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/textBinding.d.ts +1 -2
- package/dist/inspector/componentSemantics/textBinding.js +4 -45
- package/dist/inspector/componentSemantics/types.d.ts +11 -0
- package/dist/inspector/drafts/draftStore.d.ts +109 -0
- package/dist/inspector/drafts/draftStore.js +451 -0
- package/dist/inspector/drafts/model.d.ts +9 -1
- package/dist/inspector/drafts/model.js +5 -1
- package/dist/inspector/drafts/store.d.ts +53 -15
- package/dist/inspector/drafts/store.js +143 -169
- package/dist/inspector/index.d.ts +2 -4
- package/dist/inspector/index.js +2 -264
- package/dist/inspector/inline-text/inlineTextEditor.d.ts +1 -1
- package/dist/inspector/inline-text/inlineTextEditor.js +1 -2
- package/dist/inspector/inline-text/textEditChange.d.ts +1 -1
- package/dist/inspector/inspection/bridge.d.ts +1 -1
- package/dist/inspector/inspection/bridge.js +2 -1
- package/dist/inspector/inspection/browserCssInspection.d.ts +8 -0
- package/dist/inspector/inspection/browserCssInspection.js +28 -6
- package/dist/inspector/inspection/inspectionSnapshot.d.ts +6 -0
- package/dist/inspector/inspection/inspectionSnapshot.js +10 -0
- package/dist/inspector/inspection/performanceDiagnostics.d.ts +18 -0
- package/dist/inspector/inspection/performanceDiagnostics.js +31 -0
- package/dist/inspector/inspection/useBrowserCssInspection.js +17 -38
- package/dist/inspector/iterations/capture.d.ts +2 -1
- package/dist/inspector/iterations/capture.js +2 -1
- package/dist/inspector/iterations/client.d.ts +2 -1
- package/dist/inspector/iterations/coordinator.d.ts +4 -3
- package/dist/inspector/iterations/coordinator.js +5 -3
- package/dist/inspector/iterations/prompt.js +9 -8
- package/dist/inspector/overlay/interactionStyles.js +17 -0
- package/dist/inspector/pageInspector.d.ts +42 -0
- package/dist/inspector/pageInspector.js +342 -0
- package/dist/inspector/projection/draftProjection.d.ts +10 -2
- package/dist/inspector/projection/draftProjection.js +9 -1
- package/dist/inspector/projection/managedStylesheet.js +24 -4
- package/dist/inspector/projection/renderedInstance.d.ts +15 -2
- package/dist/inspector/projection/renderedInstance.js +60 -7
- package/dist/inspector/projection/structuralProjection.d.ts +0 -9
- package/dist/inspector/projection/structuralProjection.js +16 -46
- package/dist/inspector/projection/textProjection.d.ts +8 -2
- package/dist/inspector/projection/textProjection.js +77 -24
- package/dist/inspector/prompt/clipboardHandoff.d.ts +14 -0
- package/dist/inspector/prompt/clipboardHandoff.js +47 -16
- package/dist/inspector/prompt/generatePrompt.d.ts +1 -1
- package/dist/inspector/prompt/generatePrompt.js +248 -148
- package/dist/inspector/prompt/promptDocument.d.ts +3 -0
- package/dist/inspector/prompt/promptDocument.js +8 -0
- package/dist/inspector/prompt/promptSettings.js +7 -5
- package/dist/inspector/runtime/inspectorStorage.d.ts +17 -0
- package/dist/inspector/runtime/inspectorStorage.js +42 -0
- package/dist/inspector/runtime/ownedStylesheets.d.ts +20 -0
- package/dist/inspector/runtime/ownedStylesheets.js +72 -0
- package/dist/inspector/runtime/runtimeConfig.d.ts +4 -0
- package/dist/inspector/runtime/runtimeConfig.js +10 -1
- package/dist/inspector/runtime/runtimeIdentityClaims.d.ts +29 -0
- package/dist/inspector/runtime/runtimeIdentityClaims.js +188 -0
- package/dist/inspector/runtime/staticHtmlRuntimeIdentity.d.ts +15 -0
- package/dist/inspector/runtime/staticHtmlRuntimeIdentity.js +113 -29
- package/dist/inspector/selection/editScope.d.ts +1 -0
- package/dist/inspector/selection/editScope.js +13 -2
- package/dist/inspector/selection/sourceSite.d.ts +12 -0
- package/dist/inspector/selection/sourceSite.js +28 -0
- package/dist/inspector/shell/AgentStatusButton.js +2 -2
- package/dist/inspector/shell/AppShell.js +6 -2
- package/dist/inspector/shell/ChangesLog.js +27 -9
- package/dist/inspector/shell/CopyPromptButton.js +74 -26
- package/dist/inspector/shell/EmptyState.js +3 -3
- package/dist/inspector/shell/InspectorShell.d.ts +0 -3
- package/dist/inspector/shell/InspectorShell.js +21 -13
- package/dist/inspector/shell/PeekOriginalButton.js +3 -3
- package/dist/inspector/shell/interactionStatePreview.d.ts +9 -0
- package/dist/inspector/shell/interactionStatePreview.js +112 -0
- package/dist/inspector/shell/originalPreview.d.ts +3 -2
- package/dist/inspector/shell/originalPreview.js +10 -37
- package/dist/inspector/shell/stateValue.js +2 -3
- package/dist/inspector/sketch/SketchEditor.js +5 -4
- package/dist/inspector/sketch/SketchFrameOverlay.d.ts +2 -1
- package/dist/inspector/sketch/SketchFrameOverlay.js +5 -4
- package/dist/inspector/sketch/SketchOverlay.d.ts +3 -5
- package/dist/inspector/sketch/SketchOverlay.js +139 -263
- package/dist/inspector/sketch/SketchPromptPanel.d.ts +1 -1
- package/dist/inspector/sketch/SketchPromptPanel.js +8 -1
- package/dist/inspector/sketch/SketchThumbnail.d.ts +5 -0
- package/dist/inspector/sketch/SketchThumbnail.js +18 -0
- package/dist/inspector/sketch/SketchWorkspace.d.ts +1 -2
- package/dist/inspector/sketch/SketchWorkspace.js +69 -34
- package/dist/inspector/sketch/capture.js +19 -3
- package/dist/inspector/sketch/copySketch.d.ts +10 -0
- package/dist/inspector/sketch/copySketch.js +52 -0
- package/dist/inspector/sketch/drawingTools.d.ts +17 -0
- package/dist/inspector/sketch/drawingTools.js +47 -0
- package/dist/inspector/sketch/frameHeading.d.ts +9 -0
- package/dist/inspector/sketch/frameHeading.js +30 -0
- package/dist/inspector/sketch/freehand.js +3 -3
- package/dist/inspector/sketch/geometry.d.ts +6 -0
- package/dist/inspector/sketch/geometry.js +19 -0
- package/dist/inspector/sketch/history.d.ts +30 -0
- package/dist/inspector/sketch/history.js +58 -0
- package/dist/inspector/sketch/interaction.d.ts +1 -3
- package/dist/inspector/sketch/interaction.js +6 -9
- package/dist/inspector/sketch/model.d.ts +35 -1
- package/dist/inspector/sketch/model.js +116 -61
- package/dist/inspector/sketch/persistence.d.ts +14 -0
- package/dist/inspector/sketch/persistence.js +63 -7
- package/dist/inspector/sketch/raster.d.ts +6 -2
- package/dist/inspector/sketch/raster.js +43 -17
- package/dist/inspector/sketch/store.d.ts +1 -1
- package/dist/inspector/sketch/store.js +1 -1
- package/dist/inspector/sketch/videoFrames.d.ts +6 -0
- package/dist/inspector/sketch/videoFrames.js +81 -0
- package/dist/inspector/styleEditors/BackgroundEditor.js +3 -2
- package/dist/inspector/styleEditors/BorderEditor.js +30 -130
- package/dist/inspector/styleEditors/BorderRadiusEditor.js +8 -3
- package/dist/inspector/styleEditors/ImageBackgroundEditor.js +1 -1
- package/dist/inspector/styleEditors/LayoutSection.js +2 -2
- package/dist/inspector/styleEditors/borderModel.d.ts +42 -0
- package/dist/inspector/styleEditors/borderModel.js +114 -0
- package/dist/inspector/styleEditors/layoutValue.js +2 -3
- package/dist/inspector/tokens/TokenField.js +40 -7
- package/dist/inspector/tokens/TokensPanel.js +2 -1
- package/dist/inspector/tokens/editActions.d.ts +3 -3
- package/dist/inspector/tokens/editActions.js +15 -3
- package/dist/inspector/tokens/resolution/containerQueryEvaluator.d.ts +15 -0
- package/dist/inspector/tokens/resolution/containerQueryEvaluator.js +86 -0
- package/dist/inspector/tokens/resolution/cssomCollector.js +44 -9
- package/dist/inspector/tokens/resolution/nestedSelectors.d.ts +6 -0
- package/dist/inspector/tokens/resolution/nestedSelectors.js +67 -0
- package/dist/inspector/tokens/resolution/ruleMatching.js +23 -4
- package/dist/inspector/tokens/resolution.d.ts +6 -3
- package/dist/inspector/tokens/resolution.js +91 -112
- package/dist/inspector/tokens/tokenEdits.d.ts +1 -1
- package/dist/inspector/tokens/tokenEdits.js +1 -1
- package/dist/inspector/ui/InlineStyleWarning.js +2 -2
- package/dist/inspector/ui/InspectorStyle.d.ts +8 -0
- package/dist/inspector/ui/InspectorStyle.js +26 -0
- package/dist/inspector/ui/PopoverListbox.d.ts +2 -1
- package/dist/inspector/ui/PopoverListbox.js +3 -3
- package/dist/inspector/ui/Toast.d.ts +14 -0
- package/dist/inspector/ui/Toast.js +30 -0
- package/dist/inspector/ui/assets/canvasIllustration.d.ts +2 -0
- package/dist/inspector/ui/assets/canvasIllustration.js +21 -0
- package/dist/inspector/ui/assets/gridIllustration.d.ts +2 -0
- package/dist/inspector/ui/assets/{grid.svg → gridIllustration.js} +3 -2
- package/dist/inspector/ui/customCursors.d.ts +5 -0
- package/dist/inspector/ui/customCursors.js +32 -6
- package/dist/inspector/ui/styles.js +12 -10
- package/dist/inspector/workspace/commands.js +1 -2
- package/dist/inspector/workspace/controller.js +1 -2
- package/dist/inspector/workspace/handoff.js +3 -2
- package/dist/inspector/workspace/sentItems.d.ts +16 -0
- package/dist/inspector/workspace/sentItems.js +33 -0
- package/dist/inspector/workspace/timeline.d.ts +24 -10
- package/dist/inspector/workspace/timeline.js +118 -96
- package/dist/internal/agent-protocol.d.ts +50 -13
- package/dist/internal/agent-protocol.js +145 -19
- package/dist/nudge-ui.mjs +81 -65
- package/dist/project/mcpPackage.d.ts +8 -0
- package/dist/project/mcpPackage.js +60 -0
- package/package.json +13 -3
- package/dist/inspector/canvas/measurementProjection.d.ts +0 -8
- package/dist/inspector/canvas/measurementProjection.js +0 -16
- package/dist/inspector/changes/changesLog.d.ts +0 -47
- package/dist/inspector/changes/changesLog.js +0 -247
- package/dist/inspector/changes/draftChanges.d.ts +0 -56
- package/dist/inspector/changes/draftChanges.js +0 -300
- package/dist/inspector/conformance/projection.d.ts +0 -2
- package/dist/inspector/conformance/projection.js +0 -3
- package/dist/inspector/inline-text/textChangeBoundary.d.ts +0 -6
- package/dist/inspector/inline-text/textChangeBoundary.js +0 -1
- package/dist/inspector/overlay/InspectorOverlay.d.ts +0 -5
- package/dist/inspector/overlay/InspectorOverlay.js +0 -332
- package/dist/inspector/overlay/elementSelector.d.ts +0 -1
- package/dist/inspector/overlay/elementSelector.js +0 -111
- package/dist/inspector/sketch/SketchChanges.d.ts +0 -2
- package/dist/inspector/sketch/SketchChanges.js +0 -72
- package/dist/inspector/sketch/SketchEntryButton.d.ts +0 -4
- package/dist/inspector/sketch/SketchEntryButton.js +0 -11
- package/dist/inspector/sketch/SketchLayersPanel.d.ts +0 -2
- package/dist/inspector/sketch/SketchLayersPanel.js +0 -71
|
@@ -17,8 +17,42 @@ export declare const SKETCH_LIMITS: {
|
|
|
17
17
|
readonly title: 512;
|
|
18
18
|
};
|
|
19
19
|
export declare const SKETCH_STROKE_WIDTH = 6;
|
|
20
|
+
/** Drawn rectangles use a lighter outline than the freehand pen. */
|
|
21
|
+
export declare const SKETCH_RECTANGLE_STROKE_WIDTH = 4;
|
|
22
|
+
/** Opacity of the tint inside a drawn rectangle, in the rectangle's own color. */
|
|
23
|
+
export declare const SKETCH_RECTANGLE_FILL_OPACITY = 0.1;
|
|
24
|
+
/** Default pen color, and the fallback for strokes saved without one. */
|
|
20
25
|
export declare const SKETCH_STROKE_COLOR = "#0096ff";
|
|
26
|
+
/** Annotation markers and the notes panel; independent of the chosen pen color. */
|
|
27
|
+
export declare const SKETCH_ACCENT_COLOR = "#0096ff";
|
|
21
28
|
export declare const SKETCH_STROKE_OUTLINE = "";
|
|
29
|
+
/** Pen palette offered by the canvas toolbar, in clockwise order around its swatch picker. */
|
|
30
|
+
export declare const SKETCH_PEN_COLORS: readonly [{
|
|
31
|
+
readonly id: "red";
|
|
32
|
+
readonly name: "Red";
|
|
33
|
+
readonly value: "#f03e1e";
|
|
34
|
+
}, {
|
|
35
|
+
readonly id: "orange";
|
|
36
|
+
readonly name: "Orange";
|
|
37
|
+
readonly value: "#ff8a00";
|
|
38
|
+
}, {
|
|
39
|
+
readonly id: "blue";
|
|
40
|
+
readonly name: "Blue";
|
|
41
|
+
readonly value: "#0096ff";
|
|
42
|
+
}, {
|
|
43
|
+
readonly id: "black";
|
|
44
|
+
readonly name: "Black";
|
|
45
|
+
readonly value: "#242424";
|
|
46
|
+
}, {
|
|
47
|
+
readonly id: "yellow";
|
|
48
|
+
readonly name: "Yellow";
|
|
49
|
+
readonly value: "#ffc800";
|
|
50
|
+
}, {
|
|
51
|
+
readonly id: "green";
|
|
52
|
+
readonly name: "Green";
|
|
53
|
+
readonly value: "#1fc85a";
|
|
54
|
+
}];
|
|
55
|
+
export type SketchPenColor = (typeof SKETCH_PEN_COLORS)[number];
|
|
22
56
|
export declare const SKETCH_ANNOTATION_RADIUS = 16;
|
|
23
57
|
declare const LEGACY_SKETCH_STROKE_COLOR = "#ef4444";
|
|
24
58
|
declare const LEGACY_SKETCH_STROKE_OUTLINE = "#111827";
|
|
@@ -29,7 +63,7 @@ export interface SketchPoint {
|
|
|
29
63
|
readonly x: number;
|
|
30
64
|
readonly y: number;
|
|
31
65
|
}
|
|
32
|
-
type SketchStrokeColor =
|
|
66
|
+
export type SketchStrokeColor = SketchPenColor["value"] | typeof LEGACY_SKETCH_STROKE_COLOR;
|
|
33
67
|
type SketchStrokeOutline = typeof SKETCH_STROKE_OUTLINE | typeof LEGACY_SKETCH_STROKE_OUTLINE;
|
|
34
68
|
export type SketchStrokeKind = "freehand" | "rectangle";
|
|
35
69
|
export interface SketchStroke {
|
|
@@ -16,8 +16,24 @@ export const SKETCH_LIMITS = {
|
|
|
16
16
|
title: 512,
|
|
17
17
|
};
|
|
18
18
|
export const SKETCH_STROKE_WIDTH = 6;
|
|
19
|
+
/** Drawn rectangles use a lighter outline than the freehand pen. */
|
|
20
|
+
export const SKETCH_RECTANGLE_STROKE_WIDTH = 4;
|
|
21
|
+
/** Opacity of the tint inside a drawn rectangle, in the rectangle's own color. */
|
|
22
|
+
export const SKETCH_RECTANGLE_FILL_OPACITY = 0.1;
|
|
23
|
+
/** Default pen color, and the fallback for strokes saved without one. */
|
|
19
24
|
export const SKETCH_STROKE_COLOR = "#0096ff";
|
|
25
|
+
/** Annotation markers and the notes panel; independent of the chosen pen color. */
|
|
26
|
+
export const SKETCH_ACCENT_COLOR = "#0096ff";
|
|
20
27
|
export const SKETCH_STROKE_OUTLINE = "";
|
|
28
|
+
/** Pen palette offered by the canvas toolbar, in clockwise order around its swatch picker. */
|
|
29
|
+
export const SKETCH_PEN_COLORS = [
|
|
30
|
+
{ id: "red", name: "Red", value: "#f03e1e" },
|
|
31
|
+
{ id: "orange", name: "Orange", value: "#ff8a00" },
|
|
32
|
+
{ id: "blue", name: "Blue", value: SKETCH_STROKE_COLOR },
|
|
33
|
+
{ id: "black", name: "Black", value: "#242424" },
|
|
34
|
+
{ id: "yellow", name: "Yellow", value: "#ffc800" },
|
|
35
|
+
{ id: "green", name: "Green", value: "#1fc85a" },
|
|
36
|
+
];
|
|
21
37
|
export const SKETCH_ANNOTATION_RADIUS = 16;
|
|
22
38
|
// Keep accepting sketches saved before the annotation color update. Existing
|
|
23
39
|
// PNGs remain unchanged until a user edits and saves them again.
|
|
@@ -26,18 +42,36 @@ const LEGACY_SKETCH_STROKE_OUTLINE = "#111827";
|
|
|
26
42
|
export function createSketchFilename(id, revision) {
|
|
27
43
|
return `sketch-${id}-r${revision}.png`;
|
|
28
44
|
}
|
|
29
|
-
export function isFiniteNumber(
|
|
45
|
+
export function isFiniteNumber(
|
|
46
|
+
// Stored sketch fields are untrusted until this check narrows them.
|
|
47
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
48
|
+
value) {
|
|
30
49
|
return typeof value === "number" && Number.isFinite(value);
|
|
31
50
|
}
|
|
32
|
-
function
|
|
51
|
+
function safeIntegerInRange(
|
|
52
|
+
// Stored sketch fields are untrusted until this check narrows them.
|
|
53
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
54
|
+
value, minimum, maximum = Number.MAX_SAFE_INTEGER) {
|
|
55
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= minimum && value <= maximum;
|
|
56
|
+
}
|
|
57
|
+
function boundedString(
|
|
58
|
+
// Stored sketch fields are untrusted until this check narrows them.
|
|
59
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
60
|
+
value, maximum, allowEmpty = false) {
|
|
33
61
|
return typeof value === "string" && value.length <= maximum && (allowEmpty || value.length > 0);
|
|
34
62
|
}
|
|
35
|
-
function isBlob(
|
|
63
|
+
function isBlob(
|
|
64
|
+
// Stored sketch images are untrusted until this check narrows them.
|
|
65
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
66
|
+
value, mimeType) {
|
|
36
67
|
return typeof Blob !== "undefined"
|
|
37
68
|
&& value instanceof Blob
|
|
38
69
|
&& (mimeType === undefined || value.type === mimeType);
|
|
39
70
|
}
|
|
40
|
-
function validHttpUrl(
|
|
71
|
+
function validHttpUrl(
|
|
72
|
+
// Stored sketch fields are untrusted until this check narrows them.
|
|
73
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
74
|
+
value, maximum) {
|
|
41
75
|
if (!boundedString(value, maximum))
|
|
42
76
|
return false;
|
|
43
77
|
try {
|
|
@@ -48,9 +82,19 @@ function validHttpUrl(value, maximum) {
|
|
|
48
82
|
return false;
|
|
49
83
|
}
|
|
50
84
|
}
|
|
51
|
-
|
|
52
|
-
|
|
85
|
+
function isPlainObject(
|
|
86
|
+
// Stored sketch records are untrusted until this check narrows them.
|
|
87
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
88
|
+
value) {
|
|
89
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
90
|
+
}
|
|
91
|
+
export function isSketchCaptureMetadata(
|
|
92
|
+
// Capture metadata is read back from storage and parsed here.
|
|
93
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
94
|
+
value) {
|
|
95
|
+
if (!isPlainObject(value))
|
|
53
96
|
return false;
|
|
97
|
+
// SAFETY: the object check above makes reading optional candidate fields safe.
|
|
54
98
|
const capture = value;
|
|
55
99
|
const keys = [
|
|
56
100
|
"url",
|
|
@@ -70,14 +114,9 @@ export function isSketchCaptureMetadata(value) {
|
|
|
70
114
|
return false;
|
|
71
115
|
return validHttpUrl(capture.url, SKETCH_LIMITS.url)
|
|
72
116
|
&& boundedString(capture.title, SKETCH_LIMITS.title, true)
|
|
73
|
-
&&
|
|
74
|
-
&& capture.
|
|
75
|
-
&&
|
|
76
|
-
&& capture.viewportWidth > 0
|
|
77
|
-
&& capture.viewportWidth <= 100_000
|
|
78
|
-
&& Number.isSafeInteger(capture.viewportHeight)
|
|
79
|
-
&& capture.viewportHeight > 0
|
|
80
|
-
&& capture.viewportHeight <= 100_000
|
|
117
|
+
&& safeIntegerInRange(capture.timestamp, 1)
|
|
118
|
+
&& safeIntegerInRange(capture.viewportWidth, 1, 100_000)
|
|
119
|
+
&& safeIntegerInRange(capture.viewportHeight, 1, 100_000)
|
|
81
120
|
&& isFiniteNumber(capture.scrollX)
|
|
82
121
|
&& capture.scrollX >= 0
|
|
83
122
|
&& isFiniteNumber(capture.scrollY)
|
|
@@ -87,16 +126,16 @@ export function isSketchCaptureMetadata(value) {
|
|
|
87
126
|
&& capture.devicePixelRatio <= 100
|
|
88
127
|
&& boundedString(capture.host, 128)
|
|
89
128
|
&& boundedString(capture.framework, 128)
|
|
90
|
-
&&
|
|
91
|
-
&& capture.
|
|
92
|
-
&& capture.imageWidth <= SKETCH_LIMITS.imageEdge
|
|
93
|
-
&& Number.isSafeInteger(capture.imageHeight)
|
|
94
|
-
&& capture.imageHeight > 0
|
|
95
|
-
&& capture.imageHeight <= SKETCH_LIMITS.imageEdge;
|
|
129
|
+
&& safeIntegerInRange(capture.imageWidth, 1, SKETCH_LIMITS.imageEdge)
|
|
130
|
+
&& safeIntegerInRange(capture.imageHeight, 1, SKETCH_LIMITS.imageEdge);
|
|
96
131
|
}
|
|
97
|
-
export function isSketchPoint(
|
|
98
|
-
|
|
132
|
+
export function isSketchPoint(
|
|
133
|
+
// Stored points are untrusted until this check narrows them.
|
|
134
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
135
|
+
value) {
|
|
136
|
+
if (!isPlainObject(value))
|
|
99
137
|
return false;
|
|
138
|
+
// SAFETY: the object check above makes reading optional candidate fields safe.
|
|
100
139
|
const point = value;
|
|
101
140
|
return Object.keys(point).every((key) => key === "x" || key === "y")
|
|
102
141
|
&& isFiniteNumber(point.x)
|
|
@@ -106,21 +145,27 @@ export function isSketchPoint(value) {
|
|
|
106
145
|
&& point.y >= 0
|
|
107
146
|
&& point.y <= SKETCH_LIMITS.imageEdge;
|
|
108
147
|
}
|
|
109
|
-
export function isSketchAnnotation(
|
|
110
|
-
|
|
148
|
+
export function isSketchAnnotation(
|
|
149
|
+
// Stored annotations are untrusted until this check narrows them.
|
|
150
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
151
|
+
value) {
|
|
152
|
+
if (!isPlainObject(value))
|
|
111
153
|
return false;
|
|
154
|
+
// SAFETY: the object check above makes reading optional candidate fields safe.
|
|
112
155
|
const annotation = value;
|
|
113
156
|
return Object.keys(annotation).every((key) => ["id", "number", "point", "description"].includes(key))
|
|
114
157
|
&& boundedString(annotation.id, 256)
|
|
115
|
-
&&
|
|
116
|
-
&& annotation.number >= 1
|
|
117
|
-
&& annotation.number <= SKETCH_LIMITS.annotations
|
|
158
|
+
&& safeIntegerInRange(annotation.number, 1, SKETCH_LIMITS.annotations)
|
|
118
159
|
&& isSketchPoint(annotation.point)
|
|
119
160
|
&& boundedString(annotation.description, SKETCH_LIMITS.description);
|
|
120
161
|
}
|
|
121
|
-
export function isSketchStroke(
|
|
122
|
-
|
|
162
|
+
export function isSketchStroke(
|
|
163
|
+
// Stored strokes are untrusted until this check narrows them.
|
|
164
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
165
|
+
value) {
|
|
166
|
+
if (!isPlainObject(value))
|
|
123
167
|
return false;
|
|
168
|
+
// SAFETY: the object check above makes reading optional candidate fields safe.
|
|
124
169
|
const stroke = value;
|
|
125
170
|
return Object.keys(stroke).every((key) => ["id", "kind", "width", "color", "outlineColor", "points"].includes(key))
|
|
126
171
|
&& boundedString(stroke.id, 256)
|
|
@@ -128,16 +173,37 @@ export function isSketchStroke(value) {
|
|
|
128
173
|
&& isFiniteNumber(stroke.width)
|
|
129
174
|
&& stroke.width > 0
|
|
130
175
|
&& stroke.width <= 128
|
|
131
|
-
&& (
|
|
176
|
+
&& (SKETCH_PEN_COLORS.some((color) => color.value === stroke.color)
|
|
177
|
+
|| stroke.color === LEGACY_SKETCH_STROKE_COLOR)
|
|
132
178
|
&& (stroke.outlineColor === SKETCH_STROKE_OUTLINE || stroke.outlineColor === LEGACY_SKETCH_STROKE_OUTLINE)
|
|
133
179
|
&& Array.isArray(stroke.points)
|
|
134
180
|
&& stroke.points.length > 0
|
|
135
181
|
&& stroke.points.length <= SKETCH_LIMITS.points
|
|
136
182
|
&& stroke.points.every(isSketchPoint);
|
|
137
183
|
}
|
|
138
|
-
|
|
139
|
-
|
|
184
|
+
function isSketchStrokeList(
|
|
185
|
+
// Stored stroke lists are untrusted until this check narrows them.
|
|
186
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
187
|
+
value) {
|
|
188
|
+
return Array.isArray(value)
|
|
189
|
+
&& value.length <= SKETCH_LIMITS.strokes
|
|
190
|
+
&& value.every(isSketchStroke);
|
|
191
|
+
}
|
|
192
|
+
function isSketchAnnotationList(
|
|
193
|
+
// Stored annotation lists are untrusted until this check narrows them.
|
|
194
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
195
|
+
value) {
|
|
196
|
+
return Array.isArray(value)
|
|
197
|
+
&& value.length <= SKETCH_LIMITS.annotations
|
|
198
|
+
&& value.every(isSketchAnnotation);
|
|
199
|
+
}
|
|
200
|
+
export function isSketchDocument(
|
|
201
|
+
// Sketch documents are read back from storage and parsed here.
|
|
202
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
203
|
+
value) {
|
|
204
|
+
if (!isPlainObject(value))
|
|
140
205
|
return false;
|
|
206
|
+
// SAFETY: the object check above makes reading optional candidate fields safe.
|
|
141
207
|
const document = value;
|
|
142
208
|
return Object.keys(document).every((key) => [
|
|
143
209
|
"schemaVersion",
|
|
@@ -161,42 +227,33 @@ export function isSketchDocument(value) {
|
|
|
161
227
|
&& document.schemaVersion === SKETCH_SCHEMA_VERSION
|
|
162
228
|
&& boundedString(document.projectId, 256)
|
|
163
229
|
&& boundedString(document.id, 256)
|
|
164
|
-
&&
|
|
165
|
-
&& document.
|
|
166
|
-
&&
|
|
167
|
-
&& Number.isSafeInteger(document.updatedAt)
|
|
230
|
+
&& safeIntegerInRange(document.revision, 1)
|
|
231
|
+
&& safeIntegerInRange(document.createdAt, Number.MIN_SAFE_INTEGER)
|
|
232
|
+
&& safeIntegerInRange(document.updatedAt, Number.MIN_SAFE_INTEGER)
|
|
168
233
|
&& isSketchCaptureMetadata(document.capture)
|
|
169
234
|
&& boundedString(document.description, SKETCH_LIMITS.description, true)
|
|
170
|
-
&&
|
|
171
|
-
&& document.strokes.length <= SKETCH_LIMITS.strokes
|
|
172
|
-
&& document.strokes.every(isSketchStroke)
|
|
235
|
+
&& isSketchStrokeList(document.strokes)
|
|
173
236
|
&& document.strokes.reduce((total, stroke) => total + stroke.points.length, 0) <= SKETCH_LIMITS.points
|
|
174
237
|
&& (document.annotations === undefined
|
|
175
|
-
|| (
|
|
176
|
-
&& document.annotations.length <= SKETCH_LIMITS.annotations
|
|
177
|
-
&& document.annotations.every(isSketchAnnotation)
|
|
238
|
+
|| (isSketchAnnotationList(document.annotations)
|
|
178
239
|
&& new Set(document.annotations.map((annotation) => annotation.number)).size === document.annotations.length))
|
|
179
|
-
&&
|
|
180
|
-
&& document.
|
|
181
|
-
&& document.
|
|
182
|
-
&&
|
|
183
|
-
&& document.imageHeight > 0
|
|
184
|
-
&& document.imageHeight <= SKETCH_LIMITS.imageEdge
|
|
185
|
-
&& Number.isSafeInteger(document.originalByteSize)
|
|
186
|
-
&& document.originalByteSize > 0
|
|
187
|
-
&& document.originalByteSize <= SKETCH_LIMITS.imageBytes
|
|
188
|
-
&& Number.isSafeInteger(document.annotatedByteSize)
|
|
189
|
-
&& document.annotatedByteSize > 0
|
|
190
|
-
&& document.annotatedByteSize <= SKETCH_LIMITS.imageBytes
|
|
240
|
+
&& safeIntegerInRange(document.imageWidth, 1, SKETCH_LIMITS.imageEdge)
|
|
241
|
+
&& safeIntegerInRange(document.imageHeight, 1, SKETCH_LIMITS.imageEdge)
|
|
242
|
+
&& safeIntegerInRange(document.originalByteSize, 1, SKETCH_LIMITS.imageBytes)
|
|
243
|
+
&& safeIntegerInRange(document.annotatedByteSize, 1, SKETCH_LIMITS.imageBytes)
|
|
191
244
|
&& boundedString(document.filename, 256)
|
|
192
245
|
&& isBlob(document.originalImage, "image/png")
|
|
193
246
|
&& isBlob(document.annotatedImage, "image/png")
|
|
194
247
|
&& document.originalImage.size === document.originalByteSize
|
|
195
248
|
&& document.annotatedImage.size === document.annotatedByteSize;
|
|
196
249
|
}
|
|
197
|
-
export function isSketchHandoffRecord(
|
|
198
|
-
|
|
250
|
+
export function isSketchHandoffRecord(
|
|
251
|
+
// Handoff records are read back from storage and parsed here.
|
|
252
|
+
// oxlint-disable-next-line anti-slop/no-unknown-parameters
|
|
253
|
+
value) {
|
|
254
|
+
if (!isPlainObject(value))
|
|
199
255
|
return false;
|
|
256
|
+
// SAFETY: the object check above makes reading optional candidate fields safe.
|
|
200
257
|
const handoff = value;
|
|
201
258
|
return Object.keys(handoff).every((key) => [
|
|
202
259
|
"id",
|
|
@@ -213,14 +270,12 @@ export function isSketchHandoffRecord(value) {
|
|
|
213
270
|
&& boundedString(handoff.id, 256)
|
|
214
271
|
&& boundedString(handoff.projectId, 256)
|
|
215
272
|
&& boundedString(handoff.sketchId, 256)
|
|
216
|
-
&&
|
|
217
|
-
&& handoff.sketchRevision > 0
|
|
273
|
+
&& safeIntegerInRange(handoff.sketchRevision, 1)
|
|
218
274
|
&& boundedString(handoff.localBatchId, 256)
|
|
219
|
-
&& (handoff.batchRevision === undefined
|
|
220
|
-
|| (Number.isSafeInteger(handoff.batchRevision) && handoff.batchRevision >= 0))
|
|
275
|
+
&& (handoff.batchRevision === undefined || safeIntegerInRange(handoff.batchRevision, 0))
|
|
221
276
|
&& (handoff.transport === "local" || handoff.transport === "clipboard" || handoff.transport === "direct")
|
|
222
277
|
&& (handoff.agentRequestId === undefined || boundedString(handoff.agentRequestId, 256))
|
|
223
|
-
&&
|
|
278
|
+
&& safeIntegerInRange(handoff.timestamp, Number.MIN_SAFE_INTEGER)
|
|
224
279
|
&& (handoff.state === "pending"
|
|
225
280
|
|| handoff.state === "dispatching"
|
|
226
281
|
|| handoff.state === "handing-off"
|
|
@@ -5,10 +5,24 @@ export declare class SketchStorageError extends Error {
|
|
|
5
5
|
cause?: unknown;
|
|
6
6
|
});
|
|
7
7
|
}
|
|
8
|
+
export declare const SKETCH_STORAGE_FULL_MESSAGE = "Browser storage is full. Remove saved sketches you no longer need, then try again.";
|
|
8
9
|
export interface SketchPersistenceSnapshot {
|
|
9
10
|
readonly documents: SketchDocument[];
|
|
10
11
|
readonly handoffs: SketchHandoffRecord[];
|
|
11
12
|
}
|
|
13
|
+
/** One atomic set of puts and deletes against a project's sketch records. */
|
|
14
|
+
export interface SketchStorageChange {
|
|
15
|
+
readonly documents?: readonly SketchDocument[];
|
|
16
|
+
readonly handoffs?: readonly SketchHandoffRecord[];
|
|
17
|
+
readonly deleteDocumentIds?: readonly string[];
|
|
18
|
+
readonly deleteHandoffIds?: readonly string[];
|
|
19
|
+
}
|
|
20
|
+
/** Replaces the page origin's IndexedDB for sketches, for example with extension storage. */
|
|
21
|
+
export interface SketchStorage {
|
|
22
|
+
read(projectId: string): Promise<SketchPersistenceSnapshot>;
|
|
23
|
+
update(projectId: string, change: SketchStorageChange): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export declare function configureSketchStorage(storage: SketchStorage | null): void;
|
|
12
26
|
export declare function readSketchPersistence(projectId: string): Promise<SketchPersistenceSnapshot>;
|
|
13
27
|
/** Writes a document and its initial/current handoff atomically. */
|
|
14
28
|
export declare function writeSketchPersistence(projectId: string, document: SketchDocument, handoff: SketchHandoffRecord): Promise<void>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isDemoRuntime } from "../runtime/runtimeConfig.js";
|
|
1
2
|
import { SKETCH_DATABASE_NAME, SKETCH_DATABASE_VERSION, SKETCH_DOCUMENTS_STORE, SKETCH_HANDOFFS_STORE, } from "./model.js";
|
|
2
3
|
export class SketchStorageError extends Error {
|
|
3
4
|
code = "sketch_storage_error";
|
|
@@ -6,8 +7,30 @@ export class SketchStorageError extends Error {
|
|
|
6
7
|
this.name = "SketchStorageError";
|
|
7
8
|
}
|
|
8
9
|
}
|
|
10
|
+
export const SKETCH_STORAGE_FULL_MESSAGE = "Browser storage is full. Remove saved sketches you no longer need, then try again.";
|
|
11
|
+
// IndexedDB rejects with a QuotaExceededError; `chrome.storage` with a "quota exceeded" message.
|
|
12
|
+
function isQuotaError(error) {
|
|
13
|
+
if (error instanceof DOMException && error.name === "QuotaExceededError")
|
|
14
|
+
return true;
|
|
15
|
+
return error instanceof Error && /quota/i.test(error.message);
|
|
16
|
+
}
|
|
17
|
+
function storageError(message, error) {
|
|
18
|
+
return new SketchStorageError(isQuotaError(error) ? SKETCH_STORAGE_FULL_MESSAGE : message, { cause: error });
|
|
19
|
+
}
|
|
9
20
|
const memoryProjects = new Map();
|
|
10
21
|
let databasePromise = null;
|
|
22
|
+
let configuredStorage = null;
|
|
23
|
+
export function configureSketchStorage(storage) {
|
|
24
|
+
configuredStorage = storage;
|
|
25
|
+
}
|
|
26
|
+
async function updateConfigured(storage, projectId, change, message) {
|
|
27
|
+
try {
|
|
28
|
+
await storage.update(projectId, change);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
throw storageError(message, error);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
11
34
|
function memoryState(projectId) {
|
|
12
35
|
let state = memoryProjects.get(projectId);
|
|
13
36
|
if (!state) {
|
|
@@ -38,6 +61,10 @@ async function openDatabase() {
|
|
|
38
61
|
const factory = indexedDbFactory();
|
|
39
62
|
if (!factory)
|
|
40
63
|
return null;
|
|
64
|
+
// Demo runtimes (the landing page) are session-only: sketches live in the
|
|
65
|
+
// in-memory fallback and never touch IndexedDB, so every visit starts clean.
|
|
66
|
+
if (isDemoRuntime())
|
|
67
|
+
return null;
|
|
41
68
|
if (!databasePromise) {
|
|
42
69
|
databasePromise = new Promise((resolve, reject) => {
|
|
43
70
|
let request;
|
|
@@ -69,12 +96,20 @@ async function openDatabase() {
|
|
|
69
96
|
request.onblocked = () => reject(new Error("IndexedDB upgrade is blocked by another tab."));
|
|
70
97
|
}).catch((error) => {
|
|
71
98
|
databasePromise = null;
|
|
72
|
-
throw
|
|
99
|
+
throw storageError("Sketch storage is unavailable in this browser.", error);
|
|
73
100
|
});
|
|
74
101
|
}
|
|
75
102
|
return databasePromise;
|
|
76
103
|
}
|
|
77
104
|
export async function readSketchPersistence(projectId) {
|
|
105
|
+
if (configuredStorage) {
|
|
106
|
+
try {
|
|
107
|
+
return await configuredStorage.read(projectId);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
throw storageError("Sketch storage could not be read.", error);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
78
113
|
const database = await openDatabase();
|
|
79
114
|
if (!database) {
|
|
80
115
|
const state = memoryState(projectId);
|
|
@@ -92,11 +127,15 @@ export async function readSketchPersistence(projectId) {
|
|
|
92
127
|
return { documents, handoffs };
|
|
93
128
|
}
|
|
94
129
|
catch (error) {
|
|
95
|
-
throw
|
|
130
|
+
throw storageError("Sketch storage could not be read.", error);
|
|
96
131
|
}
|
|
97
132
|
}
|
|
98
133
|
/** Writes a document and its initial/current handoff atomically. */
|
|
99
134
|
export async function writeSketchPersistence(projectId, document, handoff) {
|
|
135
|
+
if (configuredStorage) {
|
|
136
|
+
const change = { documents: [document], handoffs: [handoff] };
|
|
137
|
+
return updateConfigured(configuredStorage, projectId, change, "Sketch could not be saved to browser storage.");
|
|
138
|
+
}
|
|
100
139
|
const database = await openDatabase();
|
|
101
140
|
if (!database) {
|
|
102
141
|
const state = memoryState(projectId);
|
|
@@ -111,10 +150,13 @@ export async function writeSketchPersistence(projectId, document, handoff) {
|
|
|
111
150
|
await transactionDone(transaction);
|
|
112
151
|
}
|
|
113
152
|
catch (error) {
|
|
114
|
-
throw
|
|
153
|
+
throw storageError("Sketch could not be saved to browser storage.", error);
|
|
115
154
|
}
|
|
116
155
|
}
|
|
117
156
|
export async function writeSketchHandoff(projectId, handoff) {
|
|
157
|
+
if (configuredStorage) {
|
|
158
|
+
return updateConfigured(configuredStorage, projectId, { handoffs: [handoff] }, "Sketch handoff state could not be saved.");
|
|
159
|
+
}
|
|
118
160
|
const database = await openDatabase();
|
|
119
161
|
if (!database) {
|
|
120
162
|
memoryState(projectId).handoffs.set(handoff.id, handoff);
|
|
@@ -126,12 +168,15 @@ export async function writeSketchHandoff(projectId, handoff) {
|
|
|
126
168
|
await transactionDone(transaction);
|
|
127
169
|
}
|
|
128
170
|
catch (error) {
|
|
129
|
-
throw
|
|
171
|
+
throw storageError("Sketch handoff state could not be saved.", error);
|
|
130
172
|
}
|
|
131
173
|
}
|
|
132
174
|
export async function writeSketchHandoffs(projectId, handoffs) {
|
|
133
175
|
if (handoffs.length === 0)
|
|
134
176
|
return;
|
|
177
|
+
if (configuredStorage) {
|
|
178
|
+
return updateConfigured(configuredStorage, projectId, { handoffs }, "Sketch handoff state could not be saved.");
|
|
179
|
+
}
|
|
135
180
|
const database = await openDatabase();
|
|
136
181
|
if (!database) {
|
|
137
182
|
const state = memoryState(projectId);
|
|
@@ -145,7 +190,7 @@ export async function writeSketchHandoffs(projectId, handoffs) {
|
|
|
145
190
|
await transactionDone(transaction);
|
|
146
191
|
}
|
|
147
192
|
catch (error) {
|
|
148
|
-
throw
|
|
193
|
+
throw storageError("Sketch handoff state could not be saved.", error);
|
|
149
194
|
}
|
|
150
195
|
}
|
|
151
196
|
export async function deleteSketchPersistence(projectId, sketchId) {
|
|
@@ -153,6 +198,10 @@ export async function deleteSketchPersistence(projectId, sketchId) {
|
|
|
153
198
|
const handoffIds = existing.handoffs
|
|
154
199
|
.filter((handoff) => handoff.sketchId === sketchId)
|
|
155
200
|
.map((handoff) => handoff.id);
|
|
201
|
+
if (configuredStorage) {
|
|
202
|
+
const change = { deleteDocumentIds: [sketchId], deleteHandoffIds: handoffIds };
|
|
203
|
+
return updateConfigured(configuredStorage, projectId, change, "Sketch could not be removed from browser storage.");
|
|
204
|
+
}
|
|
156
205
|
const database = await openDatabase();
|
|
157
206
|
if (!database) {
|
|
158
207
|
const state = memoryState(projectId);
|
|
@@ -168,11 +217,18 @@ export async function deleteSketchPersistence(projectId, sketchId) {
|
|
|
168
217
|
await transactionDone(transaction);
|
|
169
218
|
}
|
|
170
219
|
catch (error) {
|
|
171
|
-
throw
|
|
220
|
+
throw storageError("Sketch could not be removed from browser storage.", error);
|
|
172
221
|
}
|
|
173
222
|
}
|
|
174
223
|
export async function clearSketchPersistence(projectId) {
|
|
175
224
|
const existing = await readSketchPersistence(projectId);
|
|
225
|
+
if (configuredStorage) {
|
|
226
|
+
const change = {
|
|
227
|
+
deleteDocumentIds: existing.documents.map((document) => document.id),
|
|
228
|
+
deleteHandoffIds: existing.handoffs.map((handoff) => handoff.id),
|
|
229
|
+
};
|
|
230
|
+
return updateConfigured(configuredStorage, projectId, change, "Sketch storage could not be cleared.");
|
|
231
|
+
}
|
|
176
232
|
const database = await openDatabase();
|
|
177
233
|
if (!database) {
|
|
178
234
|
const state = memoryState(projectId);
|
|
@@ -189,7 +245,7 @@ export async function clearSketchPersistence(projectId) {
|
|
|
189
245
|
await transactionDone(transaction);
|
|
190
246
|
}
|
|
191
247
|
catch (error) {
|
|
192
|
-
throw
|
|
248
|
+
throw storageError("Sketch storage could not be cleared.", error);
|
|
193
249
|
}
|
|
194
250
|
}
|
|
195
251
|
export async function closeSketchDatabase() {
|
|
@@ -10,12 +10,16 @@ export declare function drawSketchStroke(ctx: CanvasRenderingContext2D, stroke:
|
|
|
10
10
|
export declare function drawSketchStrokes(ctx: CanvasRenderingContext2D, strokes: readonly SketchStroke[], scaleX?: number, scaleY?: number): void;
|
|
11
11
|
export declare function drawSketchAnnotation(ctx: CanvasRenderingContext2D, annotation: Pick<SketchAnnotation, "number" | "point">, scaleX?: number, scaleY?: number): void;
|
|
12
12
|
export declare function drawSketchAnnotations(ctx: CanvasRenderingContext2D, annotations: readonly SketchAnnotation[], scaleX?: number, scaleY?: number): void;
|
|
13
|
-
export declare function renderAnnotatedPng(originalImage: Blob, imageWidth: number, imageHeight: number, strokes: readonly SketchStroke[], annotations?: readonly SketchAnnotation[], description?: string): Promise<{
|
|
13
|
+
export declare function renderAnnotatedPng(originalImage: Blob, imageWidth: number, imageHeight: number, strokes: readonly SketchStroke[], annotations?: readonly SketchAnnotation[], description?: string, heading?: string): Promise<{
|
|
14
14
|
readonly blob: Blob;
|
|
15
15
|
readonly width: number;
|
|
16
16
|
readonly height: number;
|
|
17
17
|
}>;
|
|
18
18
|
export declare function blobToBase64(blob: Blob): Promise<string>;
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Accepts a pending blob so callers can start the write inside the user gesture
|
|
21
|
+
* (required by Safari) and resolve the image once rendering finishes.
|
|
22
|
+
*/
|
|
23
|
+
export declare function copyImageToClipboard(blob: Blob | Promise<Blob>): Promise<void>;
|
|
20
24
|
export declare function copyImageAndTextToClipboard(blob: Blob, text: string): Promise<void>;
|
|
21
25
|
export declare function downloadImage(blob: Blob, filename: string): void;
|