@pixerate/editor 0.227.0 → 0.228.0
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/agent/index.cjs +3 -3
- package/dist/agent/index.js +2 -2
- package/dist/animation-editor/index.cjs +9 -9
- package/dist/animation-editor/index.js +1 -1
- package/dist/canvas/drawController.d.cts +6 -0
- package/dist/canvas/drawController.d.ts +6 -0
- package/dist/canvas/effects.d.cts +18 -0
- package/dist/canvas/effects.d.ts +18 -0
- package/dist/canvas/gestures.d.cts +87 -0
- package/dist/canvas/gestures.d.ts +87 -0
- package/dist/canvas/index.cjs +56 -9
- package/dist/canvas/index.d.cts +1 -0
- package/dist/canvas/index.d.ts +1 -0
- package/dist/canvas/index.js +50 -3
- package/dist/{chunk-ABQ2VGUB.cjs → chunk-5MQOBTNP.cjs} +13 -2
- package/dist/{chunk-53GOGBTM.cjs → chunk-CHAWTXBE.cjs} +243 -39
- package/dist/{chunk-C6CMQXMI.cjs → chunk-IGPEBXUD.cjs} +7 -7
- package/dist/{chunk-4PA6YS6W.cjs → chunk-K5GXW5TR.cjs} +14 -14
- package/dist/{chunk-7KZ2HKKC.js → chunk-LPFQHVCO.js} +244 -1
- package/dist/{chunk-56RFHF7O.js → chunk-LPTFDCJO.js} +1 -1
- package/dist/{chunk-4MDWEX44.js → chunk-PB6JV62G.js} +1 -1
- package/dist/{chunk-4EFNS2HV.cjs → chunk-T7QSEKDY.cjs} +248 -5
- package/dist/{chunk-7DZ55AIE.js → chunk-UGYUGZE2.js} +13 -2
- package/dist/{chunk-ZPJEH456.js → chunk-XVIK73LS.js} +206 -2
- package/dist/commands/agentTools.d.cts +14 -0
- package/dist/commands/agentTools.d.ts +14 -0
- package/dist/commands/builtins.d.cts +11 -1
- package/dist/commands/builtins.d.ts +11 -1
- package/dist/commands/index.cjs +23 -9
- package/dist/commands/index.js +17 -3
- package/dist/effects/index.cjs +44 -44
- package/dist/effects/index.js +2 -2
- package/dist/image-editor/index.cjs +13 -13
- package/dist/image-editor/index.js +1 -1
- package/dist/paint-editor/index.cjs +7 -7
- package/dist/paint-editor/index.js +2 -2
- package/dist/vector/index.cjs +6 -6
- package/dist/vector/index.js +1 -1
- package/dist/video-editor/index.cjs +309 -309
- package/dist/video-editor/index.js +3 -3
- package/package.json +1 -1
- package/skills/pixerate-agent-tools/SKILL.md +5 -0
- package/skills/pixerate-canvas/SKILL.md +41 -2
package/dist/agent/index.cjs
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
var _chunkSOSBOS5Tcjs = require('../chunk-SOSBOS5T.cjs');
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _chunkCHAWTXBEcjs = require('../chunk-CHAWTXBE.cjs');
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ var _chunk53GOGBTMcjs = require('../chunk-53GOGBTM.cjs');
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
var _chunkEL4PSKFTcjs = require('../chunk-EL4PSKFT.cjs');
|
|
17
|
-
require('../chunk-
|
|
17
|
+
require('../chunk-T7QSEKDY.cjs');
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
@@ -2112,7 +2112,7 @@ function createCanvasComponentToolProvider(controller, options = { id: "canvas-c
|
|
|
2112
2112
|
({ id }) => check(controller.restoreMainComponent(id))
|
|
2113
2113
|
)
|
|
2114
2114
|
];
|
|
2115
|
-
if (
|
|
2115
|
+
if (_chunkCHAWTXBEcjs.hasVariantCommands.call(void 0, controller)) {
|
|
2116
2116
|
const SET = { type: "string", description: "Component set, or one of its variants (default: the selection\u2019s set)." };
|
|
2117
2117
|
const VARIANT = { type: "string", description: "Variant id (default: the first selected variant)." };
|
|
2118
2118
|
const VALUES = { type: "object", additionalProperties: { type: "string" }, description: 'Variant property \u2192 value, e.g. { "Size": "Medium" }.' };
|
package/dist/agent/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "../chunk-GOBOCZZI.js";
|
|
6
6
|
import {
|
|
7
7
|
hasVariantCommands
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-XVIK73LS.js";
|
|
9
9
|
import {
|
|
10
10
|
createNodeLookup,
|
|
11
11
|
ensureLayout,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
placeBeside,
|
|
15
15
|
placeInView
|
|
16
16
|
} from "../chunk-U4VE4UI2.js";
|
|
17
|
-
import "../chunk-
|
|
17
|
+
import "../chunk-LPFQHVCO.js";
|
|
18
18
|
import {
|
|
19
19
|
callEvalTool,
|
|
20
20
|
createStyleResolver,
|
|
@@ -48,7 +48,7 @@ require('../chunk-NM3G4VQT.cjs');
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
var
|
|
51
|
+
var _chunk5MQOBTNPcjs = require('../chunk-5MQOBTNP.cjs');
|
|
52
52
|
require('../chunk-WOFXZ3XU.cjs');
|
|
53
53
|
require('../chunk-PQ3H2AAN.cjs');
|
|
54
54
|
require('../chunk-YQGCPL5X.cjs');
|
|
@@ -3828,7 +3828,7 @@ var AnimationEditorController = (_class = class {
|
|
|
3828
3828
|
|
|
3829
3829
|
|
|
3830
3830
|
/** The effects provider slot (see `setEffectsProvider`). */
|
|
3831
|
-
__init() {this.effects = new (0,
|
|
3831
|
+
__init() {this.effects = new (0, _chunk5MQOBTNPcjs.EffectsSlot)()}
|
|
3832
3832
|
|
|
3833
3833
|
|
|
3834
3834
|
__init2() {this.selection = null}
|
|
@@ -4013,7 +4013,7 @@ var AnimationEditorController = (_class = class {
|
|
|
4013
4013
|
try {
|
|
4014
4014
|
plan = await work();
|
|
4015
4015
|
} catch (error) {
|
|
4016
|
-
if (
|
|
4016
|
+
if (_chunk5MQOBTNPcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
|
|
4017
4017
|
throw error;
|
|
4018
4018
|
}
|
|
4019
4019
|
const r = this.apply({ op: "replace_scene", scene: plan.scene }, plan.label, { merge });
|
|
@@ -4024,11 +4024,11 @@ var AnimationEditorController = (_class = class {
|
|
|
4024
4024
|
}
|
|
4025
4025
|
async describeFor(effect, kinds) {
|
|
4026
4026
|
const provider = this.effects.require();
|
|
4027
|
-
if (!provider.applyVectorEffect) throw new (0,
|
|
4027
|
+
if (!provider.applyVectorEffect) throw new (0, _chunk5MQOBTNPcjs.EffectUnsupportedError)(`${provider.name} has no vector or motion effects.`);
|
|
4028
4028
|
const d = await provider.describe(effect);
|
|
4029
4029
|
if (!kinds.includes(d.kind)) {
|
|
4030
4030
|
const hint = d.kind === "motion" ? "apply it to nodes with apply_effect" : d.kind === "vector" ? "add it with add_vector_effect" : "it draws pixels, which scenes cannot hold";
|
|
4031
|
-
throw new (0,
|
|
4031
|
+
throw new (0, _chunk5MQOBTNPcjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is a ${d.kind} effect: ${hint}.`, d.id);
|
|
4032
4032
|
}
|
|
4033
4033
|
return d;
|
|
4034
4034
|
}
|
|
@@ -4049,7 +4049,7 @@ var AnimationEditorController = (_class = class {
|
|
|
4049
4049
|
return this.effectEdit(async () => {
|
|
4050
4050
|
this.knownNodes(targets);
|
|
4051
4051
|
const d = await this.describeFor(effect, ["motion"]);
|
|
4052
|
-
const values =
|
|
4052
|
+
const values = _chunk5MQOBTNPcjs.resolveEffectValues.call(void 0, d, options.values);
|
|
4053
4053
|
const instance = _nullishCoalesce(options.instance, () => ( nextMotionEffectInstance(this.scene)));
|
|
4054
4054
|
const motion = await this.effects.require().applyVectorEffect(d.id, { svg: motionArtworkSvg(this.scene.artwork), nodeIds: [...targets] }, values);
|
|
4055
4055
|
const source = { instance, effect: d.id, provider: this.effects.require().id, name: d.name, values };
|
|
@@ -4071,7 +4071,7 @@ var AnimationEditorController = (_class = class {
|
|
|
4071
4071
|
addVectorEffect(effect, options = {}) {
|
|
4072
4072
|
return this.effectEdit(async () => {
|
|
4073
4073
|
const d = await this.describeFor(effect, ["vector"]);
|
|
4074
|
-
const values =
|
|
4074
|
+
const values = _chunk5MQOBTNPcjs.resolveEffectValues.call(void 0, d, options.values);
|
|
4075
4075
|
const instance = _nullishCoalesce(options.instance, () => ( nextMotionEffectInstance(this.scene)));
|
|
4076
4076
|
const motion = await this.effects.require().applyVectorEffect(d.id, motionArtworkSvg(this.scene.artwork), values);
|
|
4077
4077
|
const source = { instance, effect: d.id, provider: this.effects.require().id, name: d.name, values };
|
|
@@ -4095,7 +4095,7 @@ var AnimationEditorController = (_class = class {
|
|
|
4095
4095
|
else if (k in d.controls.properties) base[k] = d.defaults[k];
|
|
4096
4096
|
else throw new Error(`"${k}" is not a control of "${d.id}"; its controls are ${Object.keys(d.controls.properties).join(", ")}.`);
|
|
4097
4097
|
}
|
|
4098
|
-
const merged = { ...base, ...
|
|
4098
|
+
const merged = { ...base, ..._chunk5MQOBTNPcjs.resolveEffectValues.call(void 0, { ...d, defaults: base }, given) };
|
|
4099
4099
|
const { scene: bare, place } = withoutMotionEffect(this.scene, instance);
|
|
4100
4100
|
const provider = this.effects.require();
|
|
4101
4101
|
const source = { instance, effect: d.id, provider: provider.id, name: d.name, values: merged };
|
|
@@ -5868,7 +5868,7 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
|
|
|
5868
5868
|
if (!r.ok) throw new Error(r.error);
|
|
5869
5869
|
return { target, effect: info(r.effect), effects: controller.appliedEffects().filter((e) => e.targets.includes(target)).map(info), ...r.notes.length ? { notes: r.notes } : {} };
|
|
5870
5870
|
};
|
|
5871
|
-
return withAnimationPlayback(
|
|
5871
|
+
return withAnimationPlayback(_chunk5MQOBTNPcjs.createEffectToolProvider.call(void 0, {
|
|
5872
5872
|
id: _nullishCoalesce(options.id, () => ( "animation-effects")),
|
|
5873
5873
|
namespace: options.namespace,
|
|
5874
5874
|
title: "Animation effects",
|
|
@@ -62,6 +62,12 @@ export declare function createCanvasDrawController<TNode extends CanvasNode = Ca
|
|
|
62
62
|
cancelStroke: () => void;
|
|
63
63
|
eraseAt: (point: Point, radius?: number) => TNode[];
|
|
64
64
|
drawStroke: (input: DrawStrokeInput) => Promise<DrawStrokeResult<TNode>>;
|
|
65
|
+
nodeBounds: (id: string) => {
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
width: number;
|
|
69
|
+
height: number;
|
|
70
|
+
} | undefined;
|
|
65
71
|
/** The dry paint presets a stroke can be brushed with (loads the paint engine). */
|
|
66
72
|
listBrushes: typeof listCanvasBrushes;
|
|
67
73
|
};
|
|
@@ -62,6 +62,12 @@ export declare function createCanvasDrawController<TNode extends CanvasNode = Ca
|
|
|
62
62
|
cancelStroke: () => void;
|
|
63
63
|
eraseAt: (point: Point, radius?: number) => TNode[];
|
|
64
64
|
drawStroke: (input: DrawStrokeInput) => Promise<DrawStrokeResult<TNode>>;
|
|
65
|
+
nodeBounds: (id: string) => {
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
width: number;
|
|
69
|
+
height: number;
|
|
70
|
+
} | undefined;
|
|
65
71
|
/** The dry paint presets a stroke can be brushed with (loads the paint engine). */
|
|
66
72
|
listBrushes: typeof listCanvasBrushes;
|
|
67
73
|
};
|
|
@@ -24,6 +24,22 @@ export declare const CANVAS_EFFECT_PLACES: {
|
|
|
24
24
|
export type CanvasEffectPlace = keyof typeof CANVAS_EFFECT_PLACES;
|
|
25
25
|
/** The shape effect of a node, if it has one. */
|
|
26
26
|
export declare function canvasNodeEffect(node: CanvasNode): CanvasShapeEffect | undefined;
|
|
27
|
+
/** Whether a saved effect can be drawn with `provider`, and if not, why. */
|
|
28
|
+
export type CanvasEffectStatus = {
|
|
29
|
+
ok: true;
|
|
30
|
+
} | {
|
|
31
|
+
ok: false;
|
|
32
|
+
reason: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Whether `provider` can draw `effect`: an effect keeps the id of the provider it came from, and
|
|
36
|
+
* another provider (e.g. after switching libraries) does not know its effect ids.
|
|
37
|
+
*/
|
|
38
|
+
export declare function canvasEffectStatus(effect: Pick<CanvasShapeEffect, 'effect' | 'provider' | 'name'>, provider: EffectProvider | null | undefined): CanvasEffectStatus;
|
|
39
|
+
/** Why a render of `effect` failed, for the placeholder drawn instead. */
|
|
40
|
+
export declare function canvasEffectErrorReason(effect: Pick<CanvasShapeEffect, 'effect' | 'name'>, error: unknown): string;
|
|
41
|
+
/** The CSS background of the placeholder drawn for an effect that cannot be drawn: a faint hatch. */
|
|
42
|
+
export declare const CANVAS_EFFECT_MISSING_PATTERN = "repeating-linear-gradient(45deg, rgba(128,128,128,0.28) 0 2px, transparent 2px 8px)";
|
|
27
43
|
export interface CanvasEffectsControllerOptions<TNode extends CanvasNode = CanvasNode> {
|
|
28
44
|
getNodes: () => TNode[];
|
|
29
45
|
setNodes: (nodes: TNode[]) => void;
|
|
@@ -45,6 +61,8 @@ export declare function createCanvasEffectsController<TNode extends CanvasNode =
|
|
|
45
61
|
setEffectsProvider(provider: EffectProvider | null): void;
|
|
46
62
|
/** Registers `provider` and returns a function that removes it again. */
|
|
47
63
|
useEffects(provider: EffectProvider): () => void;
|
|
64
|
+
/** Whether the registered provider can draw `effect` (see `canvasEffectStatus`). */
|
|
65
|
+
status(effect: CanvasShapeEffect): CanvasEffectStatus;
|
|
48
66
|
/** The shape nodes that carry effects (or one node's). */
|
|
49
67
|
list(nodeId?: string): {
|
|
50
68
|
nodeId: string;
|
package/dist/canvas/effects.d.ts
CHANGED
|
@@ -24,6 +24,22 @@ export declare const CANVAS_EFFECT_PLACES: {
|
|
|
24
24
|
export type CanvasEffectPlace = keyof typeof CANVAS_EFFECT_PLACES;
|
|
25
25
|
/** The shape effect of a node, if it has one. */
|
|
26
26
|
export declare function canvasNodeEffect(node: CanvasNode): CanvasShapeEffect | undefined;
|
|
27
|
+
/** Whether a saved effect can be drawn with `provider`, and if not, why. */
|
|
28
|
+
export type CanvasEffectStatus = {
|
|
29
|
+
ok: true;
|
|
30
|
+
} | {
|
|
31
|
+
ok: false;
|
|
32
|
+
reason: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Whether `provider` can draw `effect`: an effect keeps the id of the provider it came from, and
|
|
36
|
+
* another provider (e.g. after switching libraries) does not know its effect ids.
|
|
37
|
+
*/
|
|
38
|
+
export declare function canvasEffectStatus(effect: Pick<CanvasShapeEffect, 'effect' | 'provider' | 'name'>, provider: EffectProvider | null | undefined): CanvasEffectStatus;
|
|
39
|
+
/** Why a render of `effect` failed, for the placeholder drawn instead. */
|
|
40
|
+
export declare function canvasEffectErrorReason(effect: Pick<CanvasShapeEffect, 'effect' | 'name'>, error: unknown): string;
|
|
41
|
+
/** The CSS background of the placeholder drawn for an effect that cannot be drawn: a faint hatch. */
|
|
42
|
+
export declare const CANVAS_EFFECT_MISSING_PATTERN = "repeating-linear-gradient(45deg, rgba(128,128,128,0.28) 0 2px, transparent 2px 8px)";
|
|
27
43
|
export interface CanvasEffectsControllerOptions<TNode extends CanvasNode = CanvasNode> {
|
|
28
44
|
getNodes: () => TNode[];
|
|
29
45
|
setNodes: (nodes: TNode[]) => void;
|
|
@@ -45,6 +61,8 @@ export declare function createCanvasEffectsController<TNode extends CanvasNode =
|
|
|
45
61
|
setEffectsProvider(provider: EffectProvider | null): void;
|
|
46
62
|
/** Registers `provider` and returns a function that removes it again. */
|
|
47
63
|
useEffects(provider: EffectProvider): () => void;
|
|
64
|
+
/** Whether the registered provider can draw `effect` (see `canvasEffectStatus`). */
|
|
65
|
+
status(effect: CanvasShapeEffect): CanvasEffectStatus;
|
|
48
66
|
/** The shape nodes that carry effects (or one node's). */
|
|
49
67
|
list(nodeId?: string): {
|
|
50
68
|
nodeId: string;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-drawn annotation gestures (`canvas.circle`, `canvas.underline`, `canvas.arrow`,
|
|
3
|
+
* `canvas.bracket`, `canvas.strike`, `canvas.cross`, `canvas.check`): stroke points in canvas
|
|
4
|
+
* coordinates, generated with a seeded human wobble (overshoot, slightly open loops, uneven
|
|
5
|
+
* pressure). Pure geometry with no imports, so the command layer can use it.
|
|
6
|
+
*/
|
|
7
|
+
export type GesturePoint = [number, number];
|
|
8
|
+
export interface GestureRect {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
}
|
|
14
|
+
/** A generated gesture: one stroke, as `drawStroke` takes it. */
|
|
15
|
+
export interface GestureStroke {
|
|
16
|
+
points: GesturePoint[];
|
|
17
|
+
/** Uneven pen pressure along the stroke (only applied to brushed strokes). */
|
|
18
|
+
pressure: number[];
|
|
19
|
+
}
|
|
20
|
+
/** Seeded random numbers in [0, 1) (mulberry32). */
|
|
21
|
+
export declare function gestureRandom(seed: number): () => number;
|
|
22
|
+
/** A stable 32-bit seed for any JSON value (FNV-1a over its JSON), so equal requests draw equal marks. */
|
|
23
|
+
export declare function gestureSeed(value: unknown): number;
|
|
24
|
+
/** The box around several rects. */
|
|
25
|
+
export declare function gestureUnion(rects: readonly GestureRect[]): GestureRect;
|
|
26
|
+
export interface CircleGestureOptions {
|
|
27
|
+
/** Space between the rect and the loop, about this many canvas units at the ends of its axes (default 8). */
|
|
28
|
+
padding?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A loose, slightly open ellipse around `rect`: it starts near the top left, goes round once
|
|
32
|
+
* and overshoots past its start on a slightly wider path, so the ends never quite meet. It
|
|
33
|
+
* never cuts into the rect.
|
|
34
|
+
*/
|
|
35
|
+
export declare function circleGesture(rect: GestureRect, seed: number, options?: CircleGestureOptions): GestureStroke;
|
|
36
|
+
export interface UnderlineGestureOptions {
|
|
37
|
+
/** Gap below the rect's bottom edge, canvas units (default 4). */
|
|
38
|
+
offset?: number;
|
|
39
|
+
/** A wavy underline instead of a straight one (default false). */
|
|
40
|
+
wave?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** A stroke under the rect's bottom edge, a little longer or shorter than it, never touching it. */
|
|
43
|
+
export declare function underlineGesture(rect: GestureRect, seed: number, options?: UnderlineGestureOptions): GestureStroke;
|
|
44
|
+
/** Where the line from the rect's centre towards `toward` leaves the rect, pushed out by `gap`. */
|
|
45
|
+
export declare function gestureEdgePoint(rect: GestureRect, toward: GesturePoint, gap?: number): GesturePoint;
|
|
46
|
+
export type GestureEnd = GesturePoint | GestureRect;
|
|
47
|
+
export interface ArrowGestureOptions {
|
|
48
|
+
/** Bend of the shaft, −1..1: how far its middle bulges, as a fraction of half its length (+ bends left of travel). Default: a gentle seeded bend. */
|
|
49
|
+
curve?: number;
|
|
50
|
+
/** Space left between a rect end and the arrow, canvas units (default 6). */
|
|
51
|
+
gap?: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A curved arrow from `from` to `to` with a hand-drawn head. A rect end is reached at its
|
|
55
|
+
* nearest edge (on the line between the two ends' centres), `gap` units clear of it; a point
|
|
56
|
+
* end is used as it is. The head is drawn in the same stroke: tip, one barb, back to the tip,
|
|
57
|
+
* the other barb.
|
|
58
|
+
*/
|
|
59
|
+
export declare function arrowGesture(from: GestureEnd, to: GestureEnd, seed: number, options?: ArrowGestureOptions): GestureStroke;
|
|
60
|
+
export type GestureSide = 'left' | 'right' | 'top' | 'bottom';
|
|
61
|
+
export interface BracketGestureOptions {
|
|
62
|
+
/** `curly` (default) or `square`. */
|
|
63
|
+
shape?: 'curly' | 'square';
|
|
64
|
+
/** Gap between the rect and the bracket, canvas units (default 8). */
|
|
65
|
+
padding?: number;
|
|
66
|
+
/** How far the bracket reaches out from its ends, canvas units (default: from its span, 6..20). */
|
|
67
|
+
depth?: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A curly or square bracket on one `side` of `rect`, spanning it end to end. Its ends point at
|
|
71
|
+
* the rect; a curly bracket's middle point faces away from it. It never enters the rect.
|
|
72
|
+
*/
|
|
73
|
+
export declare function bracketGesture(rect: GestureRect, side: GestureSide, seed: number, options?: BracketGestureOptions): GestureStroke;
|
|
74
|
+
/** A line struck through the middle of `rect`, slightly past both ends. */
|
|
75
|
+
export declare function strikeGesture(rect: GestureRect, seed: number): GestureStroke;
|
|
76
|
+
/**
|
|
77
|
+
* A cross over `rect`, corner to corner and a little past. It is one stroke, so after the first
|
|
78
|
+
* diagonal the pen runs back along it to the middle and up the second one before drawing it
|
|
79
|
+
* (the retraced part overlaps itself).
|
|
80
|
+
*/
|
|
81
|
+
export declare function crossGesture(rect: GestureRect, seed: number): GestureStroke;
|
|
82
|
+
export interface CheckGestureOptions {
|
|
83
|
+
/** Height of the tick, canvas units (default: 60% of the rect's smaller side, 12..48; 20 at a point). */
|
|
84
|
+
size?: number;
|
|
85
|
+
}
|
|
86
|
+
/** A tick mark centred on a point, or in the middle of a rect. */
|
|
87
|
+
export declare function checkGesture(at: GestureEnd, seed: number, options?: CheckGestureOptions): GestureStroke;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-drawn annotation gestures (`canvas.circle`, `canvas.underline`, `canvas.arrow`,
|
|
3
|
+
* `canvas.bracket`, `canvas.strike`, `canvas.cross`, `canvas.check`): stroke points in canvas
|
|
4
|
+
* coordinates, generated with a seeded human wobble (overshoot, slightly open loops, uneven
|
|
5
|
+
* pressure). Pure geometry with no imports, so the command layer can use it.
|
|
6
|
+
*/
|
|
7
|
+
export type GesturePoint = [number, number];
|
|
8
|
+
export interface GestureRect {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
}
|
|
14
|
+
/** A generated gesture: one stroke, as `drawStroke` takes it. */
|
|
15
|
+
export interface GestureStroke {
|
|
16
|
+
points: GesturePoint[];
|
|
17
|
+
/** Uneven pen pressure along the stroke (only applied to brushed strokes). */
|
|
18
|
+
pressure: number[];
|
|
19
|
+
}
|
|
20
|
+
/** Seeded random numbers in [0, 1) (mulberry32). */
|
|
21
|
+
export declare function gestureRandom(seed: number): () => number;
|
|
22
|
+
/** A stable 32-bit seed for any JSON value (FNV-1a over its JSON), so equal requests draw equal marks. */
|
|
23
|
+
export declare function gestureSeed(value: unknown): number;
|
|
24
|
+
/** The box around several rects. */
|
|
25
|
+
export declare function gestureUnion(rects: readonly GestureRect[]): GestureRect;
|
|
26
|
+
export interface CircleGestureOptions {
|
|
27
|
+
/** Space between the rect and the loop, about this many canvas units at the ends of its axes (default 8). */
|
|
28
|
+
padding?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A loose, slightly open ellipse around `rect`: it starts near the top left, goes round once
|
|
32
|
+
* and overshoots past its start on a slightly wider path, so the ends never quite meet. It
|
|
33
|
+
* never cuts into the rect.
|
|
34
|
+
*/
|
|
35
|
+
export declare function circleGesture(rect: GestureRect, seed: number, options?: CircleGestureOptions): GestureStroke;
|
|
36
|
+
export interface UnderlineGestureOptions {
|
|
37
|
+
/** Gap below the rect's bottom edge, canvas units (default 4). */
|
|
38
|
+
offset?: number;
|
|
39
|
+
/** A wavy underline instead of a straight one (default false). */
|
|
40
|
+
wave?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** A stroke under the rect's bottom edge, a little longer or shorter than it, never touching it. */
|
|
43
|
+
export declare function underlineGesture(rect: GestureRect, seed: number, options?: UnderlineGestureOptions): GestureStroke;
|
|
44
|
+
/** Where the line from the rect's centre towards `toward` leaves the rect, pushed out by `gap`. */
|
|
45
|
+
export declare function gestureEdgePoint(rect: GestureRect, toward: GesturePoint, gap?: number): GesturePoint;
|
|
46
|
+
export type GestureEnd = GesturePoint | GestureRect;
|
|
47
|
+
export interface ArrowGestureOptions {
|
|
48
|
+
/** Bend of the shaft, −1..1: how far its middle bulges, as a fraction of half its length (+ bends left of travel). Default: a gentle seeded bend. */
|
|
49
|
+
curve?: number;
|
|
50
|
+
/** Space left between a rect end and the arrow, canvas units (default 6). */
|
|
51
|
+
gap?: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A curved arrow from `from` to `to` with a hand-drawn head. A rect end is reached at its
|
|
55
|
+
* nearest edge (on the line between the two ends' centres), `gap` units clear of it; a point
|
|
56
|
+
* end is used as it is. The head is drawn in the same stroke: tip, one barb, back to the tip,
|
|
57
|
+
* the other barb.
|
|
58
|
+
*/
|
|
59
|
+
export declare function arrowGesture(from: GestureEnd, to: GestureEnd, seed: number, options?: ArrowGestureOptions): GestureStroke;
|
|
60
|
+
export type GestureSide = 'left' | 'right' | 'top' | 'bottom';
|
|
61
|
+
export interface BracketGestureOptions {
|
|
62
|
+
/** `curly` (default) or `square`. */
|
|
63
|
+
shape?: 'curly' | 'square';
|
|
64
|
+
/** Gap between the rect and the bracket, canvas units (default 8). */
|
|
65
|
+
padding?: number;
|
|
66
|
+
/** How far the bracket reaches out from its ends, canvas units (default: from its span, 6..20). */
|
|
67
|
+
depth?: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A curly or square bracket on one `side` of `rect`, spanning it end to end. Its ends point at
|
|
71
|
+
* the rect; a curly bracket's middle point faces away from it. It never enters the rect.
|
|
72
|
+
*/
|
|
73
|
+
export declare function bracketGesture(rect: GestureRect, side: GestureSide, seed: number, options?: BracketGestureOptions): GestureStroke;
|
|
74
|
+
/** A line struck through the middle of `rect`, slightly past both ends. */
|
|
75
|
+
export declare function strikeGesture(rect: GestureRect, seed: number): GestureStroke;
|
|
76
|
+
/**
|
|
77
|
+
* A cross over `rect`, corner to corner and a little past. It is one stroke, so after the first
|
|
78
|
+
* diagonal the pen runs back along it to the middle and up the second one before drawing it
|
|
79
|
+
* (the retraced part overlaps itself).
|
|
80
|
+
*/
|
|
81
|
+
export declare function crossGesture(rect: GestureRect, seed: number): GestureStroke;
|
|
82
|
+
export interface CheckGestureOptions {
|
|
83
|
+
/** Height of the tick, canvas units (default: 60% of the rect's smaller side, 12..48; 20 at a point). */
|
|
84
|
+
size?: number;
|
|
85
|
+
}
|
|
86
|
+
/** A tick mark centred on a point, or in the middle of a rect. */
|
|
87
|
+
export declare function checkGesture(at: GestureEnd, seed: number, options?: CheckGestureOptions): GestureStroke;
|