@neta-art/cohub 8.23.0 → 9.0.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/board/animation.d.ts +57 -181
- package/dist/board/animation.js +374 -220
- package/dist/board/core/arrow-geometry.d.ts +33 -18
- package/dist/board/core/arrow-geometry.js +283 -52
- package/dist/board/core/draw-geometry.d.ts +22 -36
- package/dist/board/core/draw-geometry.js +148 -85
- package/dist/board/core/export-assets.d.ts +3 -6
- package/dist/board/core/export-assets.js +0 -2
- package/dist/board/core/export-plan.d.ts +12 -63
- package/dist/board/core/export-plan.js +55 -94
- package/dist/board/core/palette.d.ts +4 -21
- package/dist/board/core/palette.js +8 -13
- package/dist/board/core/scene.d.ts +33 -0
- package/dist/board/core/scene.js +302 -0
- package/dist/board/core/shape-definition.d.ts +12 -24
- package/dist/board/core/shape-definition.js +0 -19
- package/dist/board/core/shape-types.d.ts +6 -120
- package/dist/board/core/shape-types.js +5 -5
- package/dist/board/core/text-metrics.d.ts +8 -11
- package/dist/board/core/text-metrics.js +5 -34
- package/dist/board/core/tool-styles.d.ts +6 -16
- package/dist/board/core/tool-styles.js +17 -25
- package/dist/board/export/index.d.ts +10 -17
- package/dist/board/export/index.js +22 -21
- package/dist/board/export/scene.d.ts +10 -16
- package/dist/board/export/scene.js +17 -30
- package/dist/board/geometry.d.ts +27 -56
- package/dist/board/geometry.js +7 -67
- package/dist/board/headless/index.d.ts +7 -27
- package/dist/board/headless/index.js +20 -19
- package/dist/board/headless/sketch.d.ts +19 -0
- package/dist/board/headless/sketch.js +146 -0
- package/dist/board/image-key.d.ts +2 -12
- package/dist/board/image-key.js +3 -13
- package/dist/board/index.d.ts +18 -20
- package/dist/board/index.js +17 -17
- package/dist/board/media-playback.d.ts +3 -6
- package/dist/board/media-playback.js +6 -6
- package/dist/board/presets.d.ts +150 -0
- package/dist/board/presets.js +226 -0
- package/dist/board/render/board-background.d.ts +5 -3
- package/dist/board/render/board-background.js +8 -7
- package/dist/board/render/clip.d.ts +14 -0
- package/dist/board/render/clip.js +47 -0
- package/dist/board/render/index.d.ts +8 -5
- package/dist/board/render/index.js +7 -4
- package/dist/board/render/media-interaction.d.ts +4 -5
- package/dist/board/render/media-interaction.js +1 -2
- package/dist/board/render/palette.d.ts +6 -2
- package/dist/board/render/palette.js +7 -1
- package/dist/board/render/renderers/arrow-card-renderer.js +69 -71
- package/dist/board/render/renderers/audio-card-renderer.js +3 -3
- package/dist/board/render/renderers/base-card-renderer.d.ts +6 -17
- package/dist/board/render/renderers/base-card-renderer.js +1 -24
- package/dist/board/render/renderers/board-renderer-registry.d.ts +20 -50
- package/dist/board/render/renderers/board-renderer-registry.js +6 -7
- package/dist/board/render/renderers/draw-card-renderer.js +89 -56
- package/dist/board/render/renderers/effect-card-renderer.d.ts +6 -0
- package/dist/board/render/renderers/effect-card-renderer.js +197 -0
- package/dist/board/render/renderers/far-plate.d.ts +4 -21
- package/dist/board/render/renderers/far-plate.js +15 -34
- package/dist/board/render/renderers/file-card-renderer.d.ts +4 -25
- package/dist/board/render/renderers/file-card-renderer.js +8 -58
- package/dist/board/render/renderers/frame-card-renderer.js +28 -28
- package/dist/board/render/renderers/image-card-renderer.d.ts +4 -3
- package/dist/board/render/renderers/image-card-renderer.js +0 -9
- package/dist/board/render/renderers/shape-card-renderer.d.ts +9 -0
- package/dist/board/render/renderers/shape-card-renderer.js +240 -0
- package/dist/board/render/renderers/sketch-card-renderer.d.ts +5 -0
- package/dist/board/render/renderers/sketch-card-renderer.js +98 -0
- package/dist/board/render/renderers/task-card-renderer.d.ts +0 -1
- package/dist/board/render/renderers/task-card-renderer.js +14 -16
- package/dist/board/render/renderers/text-card-renderer.d.ts +1 -3
- package/dist/board/render/renderers/text-card-renderer.js +56 -46
- package/dist/board/render/renderers/unknown-card-renderer.js +4 -10
- package/dist/board/render/renderers/video-card-renderer.d.ts +4 -2
- package/dist/board/render/renderers/video-card-renderer.js +2 -1
- package/dist/board/render/sketch-host.d.ts +14 -0
- package/dist/board/render/sketch-host.js +216 -0
- package/dist/board/render/stroke.d.ts +12 -0
- package/dist/board/render/stroke.js +90 -0
- package/dist/board/render/text-measurement.d.ts +6 -26
- package/dist/board/render/text-measurement.js +11 -30
- package/dist/board/replay.d.ts +6 -31
- package/dist/board/replay.js +45 -203
- package/dist/board/runtime/board-player.d.ts +24 -0
- package/dist/board/runtime/board-player.js +161 -0
- package/dist/board/task.d.ts +2 -10
- package/dist/board/task.js +1 -10
- package/dist/chunks/environment.d.ts +2296 -3864
- package/dist/chunks/host-bridge.d.ts +253 -0
- package/dist/chunks/http.d.ts +238 -58
- package/dist/chunks/http.js +1061 -1034
- package/dist/chunks/transport.js +113 -59
- package/dist/chunks/websocket.d.ts +1 -1
- package/dist/chunks/websocket.js +1 -1
- package/dist/host-bridge.d.ts +54 -0
- package/dist/host-bridge.js +322 -0
- package/dist/http.d.ts +3 -3
- package/dist/index.d.ts +76 -193
- package/dist/index.js +2037 -1191
- package/dist/protocol/dist/board-constants.d.ts +1 -29
- package/dist/protocol/dist/board-constants.js +2 -115
- package/dist/protocol/dist/board-layout.d.ts +59 -0
- package/dist/protocol/dist/board-layout.js +482 -0
- package/dist/protocol/dist/board-model.d.ts +2052 -0
- package/dist/protocol/dist/board-model.js +592 -0
- package/dist/protocol/dist/board-patch.d.ts +86 -0
- package/dist/protocol/dist/board-patch.js +734 -0
- package/dist/protocol/dist/board-schema.d.ts +33 -0
- package/dist/protocol/dist/board-schema.js +59 -0
- package/dist/protocol/dist/board-upgrade.d.ts +1 -0
- package/dist/protocol/dist/board-url.d.ts +1 -3
- package/dist/protocol/dist/board-url.js +2 -2
- package/dist/protocol/dist/board.d.ts +37 -232
- package/dist/protocol/dist/board.js +62 -160
- package/dist/protocol/dist/display/actions.d.ts +1 -0
- package/dist/protocol/dist/display/index.d.ts +2 -0
- package/dist/protocol/dist/index.d.ts +11 -12
- package/dist/protocol/dist/model/metrics.d.ts +2 -0
- package/dist/protocol/dist/model/session.d.ts +2 -1
- package/dist/protocol/dist/realtime/types.d.ts +2 -2
- package/dist/protocol/dist/runtime/index.d.ts +1 -0
- package/dist/space-picker.d.ts +1 -0
- package/dist/space-picker.js +1 -0
- package/dist/types.d.ts +2 -5
- package/package.json +9 -1
- package/dist/board/core/connections.d.ts +0 -108
- package/dist/board/core/connections.js +0 -455
- package/dist/board/mutation.d.ts +0 -6
- package/dist/board/mutation.js +0 -14
- package/dist/board/render/connection-layer.d.ts +0 -53
- package/dist/board/render/connection-layer.js +0 -375
- package/dist/board/render/renderers/geo-card-renderer.d.ts +0 -5
- package/dist/board/render/renderers/geo-card-renderer.js +0 -127
- package/dist/board/semantic-document.d.ts +0 -37
- package/dist/board/semantic-document.js +0 -288
- package/dist/board/semantic-mutation.d.ts +0 -10
- package/dist/board/semantic-mutation.js +0 -209
- package/dist/protocol/dist/board-animation.js +0 -34
- package/dist/protocol/dist/board-authoring.d.ts +0 -1326
- package/dist/protocol/dist/board-authoring.js +0 -302
- package/dist/protocol/dist/board-capability-registry.d.ts +0 -2
- package/dist/protocol/dist/board-capability-registry.js +0 -123
- package/dist/protocol/dist/board-codec.d.ts +0 -3
- package/dist/protocol/dist/board-codec.js +0 -383
- package/dist/protocol/dist/board-composition.d.ts +0 -383
- package/dist/protocol/dist/board-composition.js +0 -310
- package/dist/protocol/dist/board-connection.d.ts +0 -317
- package/dist/protocol/dist/board-connection.js +0 -219
- package/dist/protocol/dist/board-document.d.ts +0 -1566
- package/dist/protocol/dist/board-document.js +0 -456
- package/dist/protocol/dist/board-effect.d.ts +0 -96
- package/dist/protocol/dist/board-effect.js +0 -54
- package/dist/protocol/dist/board-geometry.d.ts +0 -15
- package/dist/protocol/dist/board-geometry.js +0 -137
- package/dist/protocol/dist/board-node.d.ts +0 -8
- package/dist/protocol/dist/board-node.js +0 -252
- /package/dist/protocol/dist/{board-animation.d.ts → host-bridge.d.ts} +0 -0
|
@@ -1,23 +1,38 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BoardArrowAnchor, BoardArrowItem } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import { BoardFrame, BoardLayout, BoardMatrix } from "../../protocol/dist/board-layout.js";
|
|
3
|
+
import "../../protocol/dist/index.js";
|
|
2
4
|
import { Rect, WorldPoint } from "../geometry.js";
|
|
3
5
|
//#region src/board/core/arrow-geometry.d.ts
|
|
6
|
+
declare const ARROW_BINDING_GAP = 4;
|
|
7
|
+
type ResolvedArrowEnd = {
|
|
8
|
+
point: WorldPoint;
|
|
9
|
+
normal: WorldPoint;
|
|
10
|
+
item?: string;
|
|
11
|
+
};
|
|
4
12
|
type ResolvedArrow = {
|
|
5
|
-
start:
|
|
6
|
-
end:
|
|
7
|
-
|
|
8
|
-
|
|
13
|
+
start: ResolvedArrowEnd;
|
|
14
|
+
end: ResolvedArrowEnd;
|
|
15
|
+
path: WorldPoint[];
|
|
16
|
+
mid: WorldPoint;
|
|
17
|
+
};
|
|
18
|
+
type ArrowFrameLookup = (id: string) => BoardFrame | undefined;
|
|
19
|
+
declare function resolveAnchor(anchor: BoardArrowAnchor, frame: BoardFrame, toward: WorldPoint, gap?: number): {
|
|
20
|
+
point: WorldPoint;
|
|
21
|
+
normal: WorldPoint;
|
|
9
22
|
};
|
|
10
|
-
|
|
11
|
-
declare function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
declare function
|
|
20
|
-
|
|
21
|
-
declare function
|
|
23
|
+
declare function resolveArrow(item: BoardArrowItem, matrix: BoardMatrix, getFrame: ArrowFrameLookup): ResolvedArrow;
|
|
24
|
+
declare function resolveSceneArrow(item: BoardArrowItem & {
|
|
25
|
+
id: string;
|
|
26
|
+
}, scene: {
|
|
27
|
+
layout: BoardLayout;
|
|
28
|
+
get(id: string): {
|
|
29
|
+
frame: BoardFrame;
|
|
30
|
+
} | undefined;
|
|
31
|
+
}): ResolvedArrow;
|
|
32
|
+
declare function pathMidpoint(path: readonly WorldPoint[]): WorldPoint;
|
|
33
|
+
declare function pathPointAt(path: readonly WorldPoint[], fraction: number): WorldPoint;
|
|
34
|
+
declare function arrowPathBounds(resolved: ResolvedArrow, strokeWidth?: number): Rect;
|
|
35
|
+
declare function distanceToArrow(resolved: ResolvedArrow, point: WorldPoint): number;
|
|
36
|
+
declare function arrowHitRadius(strokeWidth?: number): number;
|
|
22
37
|
//#endregion
|
|
23
|
-
export { ResolvedArrow,
|
|
38
|
+
export { ARROW_BINDING_GAP, ArrowFrameLookup, ResolvedArrow, ResolvedArrowEnd, arrowHitRadius, arrowPathBounds, distanceToArrow, pathMidpoint, pathPointAt, resolveAnchor, resolveArrow, resolveSceneArrow };
|
|
@@ -1,48 +1,283 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BOARD_ARROW_STROKE_SIZE } from "../../protocol/dist/board-constants.js";
|
|
2
|
+
import { applyMatrix, autoAnchorSide, bendControl, framePoint, isArrowBinding, sideAnchor } from "../../protocol/dist/board-layout.js";
|
|
2
3
|
import { worldPoint } from "../geometry.js";
|
|
3
4
|
//#region src/board/core/arrow-geometry.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
5
|
+
const ARROW_BINDING_GAP = 4;
|
|
6
|
+
const CURVE_SEGMENTS = 20;
|
|
7
|
+
const ORTHOGONAL_SNAP = .5;
|
|
8
|
+
const SIDE_NORMALS = {
|
|
9
|
+
top: worldPoint(0, -1),
|
|
10
|
+
right: worldPoint(1, 0),
|
|
11
|
+
bottom: worldPoint(0, 1),
|
|
12
|
+
left: worldPoint(-1, 0)
|
|
13
|
+
};
|
|
14
|
+
function rotate(vector, degrees) {
|
|
15
|
+
if (!degrees) return vector;
|
|
16
|
+
const radians = degrees * Math.PI / 180;
|
|
17
|
+
const cos = Math.cos(radians);
|
|
18
|
+
const sin = Math.sin(radians);
|
|
19
|
+
return worldPoint(vector.x * cos - vector.y * sin, vector.x * sin + vector.y * cos);
|
|
20
|
+
}
|
|
21
|
+
function nearestSide(x, y) {
|
|
22
|
+
const distances = [
|
|
23
|
+
["left", x],
|
|
24
|
+
["right", 1 - x],
|
|
25
|
+
["top", y],
|
|
26
|
+
["bottom", 1 - y]
|
|
27
|
+
];
|
|
28
|
+
distances.sort((a, b) => a[1] - b[1]);
|
|
29
|
+
return distances[0]?.[0] ?? "right";
|
|
30
|
+
}
|
|
31
|
+
function center(frame) {
|
|
32
|
+
return worldPoint(frame.x + frame.width / 2, frame.y + frame.height / 2);
|
|
33
|
+
}
|
|
34
|
+
function resolveAnchor(anchor, frame, toward, gap = 4) {
|
|
35
|
+
let side;
|
|
36
|
+
let normalized;
|
|
37
|
+
if (anchor === "auto") {
|
|
38
|
+
side = autoAnchorSide(frame, toward);
|
|
39
|
+
normalized = sideAnchor(side, .5);
|
|
40
|
+
} else if ("side" in anchor) {
|
|
41
|
+
side = anchor.side;
|
|
42
|
+
normalized = sideAnchor(side, anchor.offset);
|
|
43
|
+
} else {
|
|
44
|
+
normalized = anchor;
|
|
45
|
+
side = nearestSide(anchor.x, anchor.y);
|
|
46
|
+
}
|
|
47
|
+
const base = framePoint(frame, normalized.x, normalized.y);
|
|
48
|
+
const normal = rotate(SIDE_NORMALS[side], frame.rotation);
|
|
16
49
|
return {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
control: worldPoint(resolved.control.x, resolved.control.y)
|
|
50
|
+
point: worldPoint(base.x + normal.x * gap, base.y + normal.y * gap),
|
|
51
|
+
normal
|
|
20
52
|
};
|
|
21
53
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return
|
|
54
|
+
function toWorld(matrix, point) {
|
|
55
|
+
const mapped = applyMatrix(matrix, point);
|
|
56
|
+
return worldPoint(mapped.x, mapped.y);
|
|
25
57
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
58
|
+
function resolveEnd(end, other, matrix, getFrame) {
|
|
59
|
+
const origin = toWorld(matrix, {
|
|
60
|
+
x: 0,
|
|
61
|
+
y: 0
|
|
62
|
+
});
|
|
63
|
+
const otherPoint = (() => {
|
|
64
|
+
if (!isArrowBinding(other)) return toWorld(matrix, other);
|
|
65
|
+
const frame = getFrame(other.item);
|
|
66
|
+
return frame ? center(frame) : origin;
|
|
67
|
+
})();
|
|
68
|
+
if (isArrowBinding(end)) {
|
|
69
|
+
const frame = getFrame(end.item);
|
|
70
|
+
if (frame) return {
|
|
71
|
+
...resolveAnchor(end.anchor, frame, otherPoint),
|
|
72
|
+
item: end.item
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const point = isArrowBinding(end) ? origin : toWorld(matrix, end);
|
|
76
|
+
const dx = point.x - otherPoint.x;
|
|
77
|
+
const dy = point.y - otherPoint.y;
|
|
78
|
+
const length = Math.hypot(dx, dy) || 1;
|
|
79
|
+
return {
|
|
80
|
+
point,
|
|
81
|
+
normal: worldPoint(dx / length, dy / length)
|
|
82
|
+
};
|
|
29
83
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
84
|
+
function quadratic(start, control, end) {
|
|
85
|
+
const out = [];
|
|
86
|
+
for (let index = 0; index <= CURVE_SEGMENTS; index += 1) {
|
|
87
|
+
const t = index / CURVE_SEGMENTS;
|
|
88
|
+
const mt = 1 - t;
|
|
89
|
+
out.push(worldPoint(mt * mt * start.x + 2 * mt * t * control.x + t * t * end.x, mt * mt * start.y + 2 * mt * t * control.y + t * t * end.y));
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
33
92
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
93
|
+
function orthogonal(start, end) {
|
|
94
|
+
const horizontalStart = Math.abs(start.normal.x) > Math.abs(start.normal.y);
|
|
95
|
+
const horizontalEnd = Math.abs(end.normal.x) > Math.abs(end.normal.y);
|
|
96
|
+
const a = start.point;
|
|
97
|
+
const b = end.point;
|
|
98
|
+
if (horizontalStart && horizontalEnd) {
|
|
99
|
+
const midX = a.x + (b.x - a.x) * ORTHOGONAL_SNAP;
|
|
100
|
+
return [
|
|
101
|
+
a,
|
|
102
|
+
worldPoint(midX, a.y),
|
|
103
|
+
worldPoint(midX, b.y),
|
|
104
|
+
b
|
|
105
|
+
];
|
|
44
106
|
}
|
|
45
|
-
|
|
107
|
+
if (!horizontalStart && !horizontalEnd) {
|
|
108
|
+
const midY = a.y + (b.y - a.y) * ORTHOGONAL_SNAP;
|
|
109
|
+
return [
|
|
110
|
+
a,
|
|
111
|
+
worldPoint(a.x, midY),
|
|
112
|
+
worldPoint(b.x, midY),
|
|
113
|
+
b
|
|
114
|
+
];
|
|
115
|
+
}
|
|
116
|
+
return horizontalStart ? [
|
|
117
|
+
a,
|
|
118
|
+
worldPoint(b.x, a.y),
|
|
119
|
+
b
|
|
120
|
+
] : [
|
|
121
|
+
a,
|
|
122
|
+
worldPoint(a.x, b.y),
|
|
123
|
+
b
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
function curveControl(start, end, bend) {
|
|
127
|
+
if (bend) return bendControl(start.point, end.point, bend);
|
|
128
|
+
const mid = worldPoint((start.point.x + end.point.x) / 2, (start.point.y + end.point.y) / 2);
|
|
129
|
+
const normals = [start, end].filter((entry) => entry.item).map((entry) => entry.normal);
|
|
130
|
+
if (!normals.length) return mid;
|
|
131
|
+
const nx = normals.reduce((sum, normal) => sum + normal.x, 0) / normals.length;
|
|
132
|
+
const ny = normals.reduce((sum, normal) => sum + normal.y, 0) / normals.length;
|
|
133
|
+
const magnitude = Math.hypot(nx, ny);
|
|
134
|
+
if (magnitude < 1e-4) return mid;
|
|
135
|
+
const length = Math.hypot(end.point.x - start.point.x, end.point.y - start.point.y);
|
|
136
|
+
const strength = Math.min(length * .18, 96);
|
|
137
|
+
return worldPoint(mid.x + nx / magnitude * strength, mid.y + ny / magnitude * strength);
|
|
138
|
+
}
|
|
139
|
+
function selfLoop(frame) {
|
|
140
|
+
const size = Math.max(Math.min(frame.width, frame.height) * .45, 24);
|
|
141
|
+
const right = frame.x + frame.width + 4;
|
|
142
|
+
const top = frame.y - 4;
|
|
143
|
+
const midY = frame.y + frame.height * .3;
|
|
144
|
+
const midX = frame.x + frame.width * .7;
|
|
145
|
+
return [
|
|
146
|
+
worldPoint(midX, top),
|
|
147
|
+
worldPoint(midX, top - size),
|
|
148
|
+
worldPoint(right + size, top - size),
|
|
149
|
+
worldPoint(right + size, midY),
|
|
150
|
+
worldPoint(right, midY)
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
function resolveArrow(item, matrix, getFrame) {
|
|
154
|
+
const { props } = item;
|
|
155
|
+
if (isArrowBinding(props.start) && isArrowBinding(props.end) && props.start.item === props.end.item) {
|
|
156
|
+
const frame = getFrame(props.start.item);
|
|
157
|
+
if (frame) {
|
|
158
|
+
const path = selfLoop(frame);
|
|
159
|
+
const first = path[0];
|
|
160
|
+
const last = path[path.length - 1];
|
|
161
|
+
return {
|
|
162
|
+
start: {
|
|
163
|
+
point: first,
|
|
164
|
+
normal: worldPoint(0, -1),
|
|
165
|
+
item: props.start.item
|
|
166
|
+
},
|
|
167
|
+
end: {
|
|
168
|
+
point: last,
|
|
169
|
+
normal: worldPoint(1, 0),
|
|
170
|
+
item: props.end.item
|
|
171
|
+
},
|
|
172
|
+
path,
|
|
173
|
+
mid: path[2]
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const start = resolveEnd(props.start, props.end, matrix, getFrame);
|
|
178
|
+
const end = resolveEnd(props.end, props.start, matrix, getFrame);
|
|
179
|
+
let path;
|
|
180
|
+
if (props.waypoints.length) path = [
|
|
181
|
+
start.point,
|
|
182
|
+
...props.waypoints.map((point) => toWorld(matrix, point)),
|
|
183
|
+
end.point
|
|
184
|
+
];
|
|
185
|
+
else if (props.route === "orthogonal") path = orthogonal(start, end);
|
|
186
|
+
else if (props.route === "straight" && !props.bend) path = [start.point, end.point];
|
|
187
|
+
else path = quadratic(start.point, curveControl(start, end, props.bend), end.point);
|
|
188
|
+
return {
|
|
189
|
+
start,
|
|
190
|
+
end,
|
|
191
|
+
path,
|
|
192
|
+
mid: pathMidpoint(path)
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function resolveSceneArrow(item, scene) {
|
|
196
|
+
const getFrame = (id) => scene.get(id)?.frame;
|
|
197
|
+
const matrix = scene.layout.matrix(item.id);
|
|
198
|
+
const key = arrowKey(item, matrix, getFrame);
|
|
199
|
+
const cached = resolvedCache.get(item);
|
|
200
|
+
if (cached && cached.key === key) return cached.resolved;
|
|
201
|
+
const resolved = resolveArrow(item, matrix, getFrame);
|
|
202
|
+
resolvedCache.set(item, {
|
|
203
|
+
key,
|
|
204
|
+
resolved
|
|
205
|
+
});
|
|
206
|
+
return resolved;
|
|
207
|
+
}
|
|
208
|
+
const resolvedCache = /* @__PURE__ */ new WeakMap();
|
|
209
|
+
function frameKey(frame) {
|
|
210
|
+
return frame ? `${frame.x},${frame.y},${frame.width},${frame.height},${frame.rotation}` : "-";
|
|
211
|
+
}
|
|
212
|
+
function arrowKey(item, matrix, getFrame) {
|
|
213
|
+
const { start, end } = item.props;
|
|
214
|
+
return `${matrix.join(",")}|${isArrowBinding(start) ? frameKey(getFrame(start.item)) : ""}|${isArrowBinding(end) ? frameKey(getFrame(end.item)) : ""}`;
|
|
215
|
+
}
|
|
216
|
+
function pathMidpoint(path) {
|
|
217
|
+
if (path.length === 0) return worldPoint(0, 0);
|
|
218
|
+
if (path.length === 1) return path[0];
|
|
219
|
+
let total = 0;
|
|
220
|
+
for (let index = 0; index < path.length - 1; index += 1) {
|
|
221
|
+
const from = path[index];
|
|
222
|
+
const to = path[index + 1];
|
|
223
|
+
total += Math.hypot(to.x - from.x, to.y - from.y);
|
|
224
|
+
}
|
|
225
|
+
let travelled = 0;
|
|
226
|
+
const half = total / 2;
|
|
227
|
+
for (let index = 0; index < path.length - 1; index += 1) {
|
|
228
|
+
const from = path[index];
|
|
229
|
+
const to = path[index + 1];
|
|
230
|
+
const segment = Math.hypot(to.x - from.x, to.y - from.y);
|
|
231
|
+
if (travelled + segment >= half) {
|
|
232
|
+
const t = segment > 0 ? (half - travelled) / segment : 0;
|
|
233
|
+
return worldPoint(from.x + (to.x - from.x) * t, from.y + (to.y - from.y) * t);
|
|
234
|
+
}
|
|
235
|
+
travelled += segment;
|
|
236
|
+
}
|
|
237
|
+
return path[path.length - 1];
|
|
238
|
+
}
|
|
239
|
+
function pathPointAt(path, fraction) {
|
|
240
|
+
if (path.length < 2) return path[0] ?? worldPoint(0, 0);
|
|
241
|
+
const lengths = [];
|
|
242
|
+
let total = 0;
|
|
243
|
+
for (let index = 0; index < path.length - 1; index += 1) {
|
|
244
|
+
const from = path[index];
|
|
245
|
+
const to = path[index + 1];
|
|
246
|
+
const length = Math.hypot(to.x - from.x, to.y - from.y);
|
|
247
|
+
lengths.push(length);
|
|
248
|
+
total += length;
|
|
249
|
+
}
|
|
250
|
+
let remaining = Math.min(1, Math.max(0, fraction)) * total;
|
|
251
|
+
for (let index = 0; index < lengths.length; index += 1) {
|
|
252
|
+
const length = lengths[index];
|
|
253
|
+
if (remaining <= length) {
|
|
254
|
+
const from = path[index];
|
|
255
|
+
const to = path[index + 1];
|
|
256
|
+
const t = length > 0 ? remaining / length : 0;
|
|
257
|
+
return worldPoint(from.x + (to.x - from.x) * t, from.y + (to.y - from.y) * t);
|
|
258
|
+
}
|
|
259
|
+
remaining -= length;
|
|
260
|
+
}
|
|
261
|
+
return path[path.length - 1];
|
|
262
|
+
}
|
|
263
|
+
function arrowPathBounds(resolved, strokeWidth = BOARD_ARROW_STROKE_SIZE) {
|
|
264
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
265
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
266
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
267
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
268
|
+
for (const point of resolved.path) {
|
|
269
|
+
minX = Math.min(minX, point.x);
|
|
270
|
+
minY = Math.min(minY, point.y);
|
|
271
|
+
maxX = Math.max(maxX, point.x);
|
|
272
|
+
maxY = Math.max(maxY, point.y);
|
|
273
|
+
}
|
|
274
|
+
const pad = Math.max(8, strokeWidth * 2);
|
|
275
|
+
return {
|
|
276
|
+
x: minX - pad,
|
|
277
|
+
y: minY - pad,
|
|
278
|
+
width: Math.max(1, maxX - minX + pad * 2),
|
|
279
|
+
height: Math.max(1, maxY - minY + pad * 2)
|
|
280
|
+
};
|
|
46
281
|
}
|
|
47
282
|
function segmentDistance(p, a, b) {
|
|
48
283
|
const dx = b.x - a.x;
|
|
@@ -52,21 +287,17 @@ function segmentDistance(p, a, b) {
|
|
|
52
287
|
const t = Math.min(1, Math.max(0, ((p.x - a.x) * dx + (p.y - a.y) * dy) / lengthSq));
|
|
53
288
|
return Math.hypot(p.x - (a.x + t * dx), p.y - (a.y + t * dy));
|
|
54
289
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
...next,
|
|
68
|
-
frame: arrowFrame(next)
|
|
69
|
-
};
|
|
290
|
+
function distanceToArrow(resolved, point) {
|
|
291
|
+
let min = Number.POSITIVE_INFINITY;
|
|
292
|
+
for (let index = 0; index < resolved.path.length - 1; index += 1) {
|
|
293
|
+
const from = resolved.path[index];
|
|
294
|
+
const to = resolved.path[index + 1];
|
|
295
|
+
if (from && to) min = Math.min(min, segmentDistance(point, from, to));
|
|
296
|
+
}
|
|
297
|
+
return min;
|
|
298
|
+
}
|
|
299
|
+
function arrowHitRadius(strokeWidth = BOARD_ARROW_STROKE_SIZE) {
|
|
300
|
+
return Math.max(8, strokeWidth * 2.5);
|
|
70
301
|
}
|
|
71
302
|
//#endregion
|
|
72
|
-
export {
|
|
303
|
+
export { ARROW_BINDING_GAP, arrowHitRadius, arrowPathBounds, distanceToArrow, pathMidpoint, pathPointAt, resolveAnchor, resolveArrow, resolveSceneArrow };
|
|
@@ -1,49 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { BoardDrawPoint } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import { drawPointsBounds, drawSampleRadius } from "../../protocol/dist/board-layout.js";
|
|
3
3
|
import "../../protocol/dist/index.js";
|
|
4
4
|
import { WorldPoint } from "../geometry.js";
|
|
5
5
|
//#region src/board/core/draw-geometry.d.ts
|
|
6
|
-
|
|
7
|
-
declare const
|
|
8
|
-
|
|
9
|
-
declare
|
|
10
|
-
|
|
11
|
-
* Ramer–Douglas–Peucker simplification. Reduces point count for low-zoom
|
|
12
|
-
* rendering without touching the persisted raw samples. Returns indices into
|
|
13
|
-
* the input so callers can keep pressure alongside the simplified path.
|
|
14
|
-
*/
|
|
15
|
-
declare function simplifyDrawIndices(points: DrawPoint[], tolerance: number): number[];
|
|
16
|
-
/**
|
|
17
|
-
* Build a closed outline for callers that need a path representation.
|
|
18
|
-
* Interactive rendering uses `buildStrokeRibbonGeometry` below because a single
|
|
19
|
-
* outline is unsafe when a freehand path folds back over itself.
|
|
20
|
-
*/
|
|
21
|
-
declare function buildStrokeOutline(points: DrawPoint[], size: number): Array<{
|
|
6
|
+
declare const sampleRadius: typeof drawSampleRadius;
|
|
7
|
+
declare const computeDrawBounds: typeof drawPointsBounds;
|
|
8
|
+
declare function simplifyDrawIndices(points: BoardDrawPoint[], tolerance: number): number[];
|
|
9
|
+
declare function trimDrawPoints(points: readonly BoardDrawPoint[], trim: number | undefined): readonly BoardDrawPoint[];
|
|
10
|
+
declare function buildStrokeOutline(points: BoardDrawPoint[], size: number): Array<{
|
|
22
11
|
x: number;
|
|
23
12
|
y: number;
|
|
24
13
|
}>;
|
|
25
|
-
|
|
26
|
-
declare function isStrokeCorner(points: readonly DrawPoint[], index: number): boolean;
|
|
14
|
+
declare function isStrokeCorner(points: readonly BoardDrawPoint[], index: number): boolean;
|
|
27
15
|
type StrokeRibbonGeometry = {
|
|
28
16
|
positions: Float32Array;
|
|
29
17
|
indices: Uint32Array;
|
|
30
18
|
uvs: Float32Array;
|
|
31
|
-
/** Normalized distance along the centerline for reveal animations. */
|
|
32
19
|
progress: Float32Array;
|
|
33
20
|
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
declare function distanceToStroke(points: DrawPoint[], local: WorldPoint): number;
|
|
21
|
+
type StrokeRibbonMesh = {
|
|
22
|
+
positions: Float32Array;
|
|
23
|
+
indices: Uint32Array;
|
|
24
|
+
distances: Float32Array;
|
|
25
|
+
length: number;
|
|
26
|
+
};
|
|
27
|
+
type StrokeRibbonBuilder = {
|
|
28
|
+
build(points: readonly BoardDrawPoint[]): StrokeRibbonMesh;
|
|
29
|
+
};
|
|
30
|
+
/** A growing stroke re-emits only its last two samples. */
|
|
31
|
+
declare function createStrokeRibbonBuilder(size: number): StrokeRibbonBuilder;
|
|
32
|
+
declare function buildStrokeRibbonGeometry(points: readonly BoardDrawPoint[], size: number): StrokeRibbonGeometry;
|
|
33
|
+
declare function distanceToStroke(points: BoardDrawPoint[], local: WorldPoint): number;
|
|
48
34
|
//#endregion
|
|
49
|
-
export { StrokeRibbonGeometry, buildStrokeOutline, buildStrokeRibbonGeometry, computeDrawBounds, distanceToStroke, isStrokeCorner, sampleRadius, simplifyDrawIndices };
|
|
35
|
+
export { StrokeRibbonBuilder, StrokeRibbonGeometry, StrokeRibbonMesh, buildStrokeOutline, buildStrokeRibbonGeometry, computeDrawBounds, createStrokeRibbonBuilder, distanceToStroke, isStrokeCorner, sampleRadius, simplifyDrawIndices, trimDrawPoints };
|