@neta-art/cohub 8.24.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 +6 -27
- package/dist/board/headless/index.js +4 -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 +2291 -3864
- package/dist/chunks/host-bridge.d.ts +253 -0
- package/dist/chunks/http.d.ts +233 -58
- package/dist/chunks/http.js +1046 -1028
- 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 +74 -191
- package/dist/index.js +2032 -1186
- 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,137 +0,0 @@
|
|
|
1
|
-
//#region ../protocol/dist/board-geometry.js
|
|
2
|
-
/**
|
|
3
|
-
* Renderer-independent Board geometry contracts.
|
|
4
|
-
*
|
|
5
|
-
* Renderers build their own primitives from these results, but validation and
|
|
6
|
-
* item factories use the same coordinate and bounds rules.
|
|
7
|
-
*/
|
|
8
|
-
/** Radius of a draw sample in world units given stroke size and pressure. */
|
|
9
|
-
function boardDrawSampleRadius(size, pressure) {
|
|
10
|
-
const clamped = Math.min(1, Math.max(0, pressure));
|
|
11
|
-
return Math.max(.5, size / 2 * (.5 + clamped));
|
|
12
|
-
}
|
|
13
|
-
/** Convert persisted frame-local draw points to world-space authoring points. */
|
|
14
|
-
function boardDrawPointsToWorld(points, x, y) {
|
|
15
|
-
return points.map((point) => ({
|
|
16
|
-
x: point.x + x,
|
|
17
|
-
y: point.y + y,
|
|
18
|
-
p: point.p
|
|
19
|
-
}));
|
|
20
|
-
}
|
|
21
|
-
/** Convert world-space authoring points to persisted frame-local points. */
|
|
22
|
-
function boardDrawPointsToLocal(points, x, y) {
|
|
23
|
-
return points.map((point) => ({
|
|
24
|
-
x: point.x - x,
|
|
25
|
-
y: point.y - y,
|
|
26
|
-
p: point.p
|
|
27
|
-
}));
|
|
28
|
-
}
|
|
29
|
-
/** Exact local bounds required by the draw node contract. */
|
|
30
|
-
function boardDrawBounds(points, size) {
|
|
31
|
-
if (points.length === 0) return {
|
|
32
|
-
x: 0,
|
|
33
|
-
y: 0,
|
|
34
|
-
width: 1,
|
|
35
|
-
height: 1
|
|
36
|
-
};
|
|
37
|
-
let minX = Number.POSITIVE_INFINITY;
|
|
38
|
-
let minY = Number.POSITIVE_INFINITY;
|
|
39
|
-
let maxX = Number.NEGATIVE_INFINITY;
|
|
40
|
-
let maxY = Number.NEGATIVE_INFINITY;
|
|
41
|
-
for (const point of points) {
|
|
42
|
-
const radius = boardDrawSampleRadius(size, point.p);
|
|
43
|
-
minX = Math.min(minX, point.x - radius);
|
|
44
|
-
minY = Math.min(minY, point.y - radius);
|
|
45
|
-
maxX = Math.max(maxX, point.x + radius);
|
|
46
|
-
maxY = Math.max(maxY, point.y + radius);
|
|
47
|
-
}
|
|
48
|
-
return {
|
|
49
|
-
x: minX,
|
|
50
|
-
y: minY,
|
|
51
|
-
width: Math.max(1, maxX - minX),
|
|
52
|
-
height: Math.max(1, maxY - minY)
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
/** Resolve the world-space quadratic curve represented by a free arrow. */
|
|
56
|
-
function boardResolveArrow(input) {
|
|
57
|
-
const start = input.start;
|
|
58
|
-
const end = input.end;
|
|
59
|
-
const mid = {
|
|
60
|
-
x: (start.x + end.x) / 2,
|
|
61
|
-
y: (start.y + end.y) / 2
|
|
62
|
-
};
|
|
63
|
-
if (!input.bend) return {
|
|
64
|
-
start,
|
|
65
|
-
end,
|
|
66
|
-
control: mid
|
|
67
|
-
};
|
|
68
|
-
const dx = end.x - start.x;
|
|
69
|
-
const dy = end.y - start.y;
|
|
70
|
-
const length = Math.hypot(dx, dy) || 1;
|
|
71
|
-
const offset = input.bend * length;
|
|
72
|
-
return {
|
|
73
|
-
start,
|
|
74
|
-
end,
|
|
75
|
-
control: {
|
|
76
|
-
x: mid.x + -dy / length * offset,
|
|
77
|
-
y: mid.y + dx / length * offset
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
/** Sample an already resolved arrow curve. */
|
|
82
|
-
function boardSampleResolvedArrow(resolved, segments) {
|
|
83
|
-
const { start, control, end } = resolved;
|
|
84
|
-
const count = Math.max(1, Math.floor(segments));
|
|
85
|
-
const points = [];
|
|
86
|
-
for (let index = 0; index <= count; index += 1) {
|
|
87
|
-
const t = index / count;
|
|
88
|
-
const mt = 1 - t;
|
|
89
|
-
points.push({
|
|
90
|
-
x: mt * mt * start.x + 2 * mt * t * control.x + t * t * end.x,
|
|
91
|
-
y: mt * mt * start.y + 2 * mt * t * control.y + t * t * end.y
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
return points;
|
|
95
|
-
}
|
|
96
|
-
/** World bounds of the curve, padded for the stroke. */
|
|
97
|
-
function boardArrowBounds(input) {
|
|
98
|
-
const { start, control, end } = boardResolveArrow(input);
|
|
99
|
-
const points = [start, end];
|
|
100
|
-
for (const axis of ["x", "y"]) {
|
|
101
|
-
const denominator = start[axis] - 2 * control[axis] + end[axis];
|
|
102
|
-
if (Math.abs(denominator) < 1e-12) continue;
|
|
103
|
-
const t = (start[axis] - control[axis]) / denominator;
|
|
104
|
-
if (t > 0 && t < 1) {
|
|
105
|
-
const mt = 1 - t;
|
|
106
|
-
points.push({
|
|
107
|
-
x: mt * mt * start.x + 2 * mt * t * control.x + t * t * end.x,
|
|
108
|
-
y: mt * mt * start.y + 2 * mt * t * control.y + t * t * end.y
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
let minX = Number.POSITIVE_INFINITY;
|
|
113
|
-
let minY = Number.POSITIVE_INFINITY;
|
|
114
|
-
let maxX = Number.NEGATIVE_INFINITY;
|
|
115
|
-
let maxY = Number.NEGATIVE_INFINITY;
|
|
116
|
-
for (const point of points) {
|
|
117
|
-
minX = Math.min(minX, point.x);
|
|
118
|
-
minY = Math.min(minY, point.y);
|
|
119
|
-
maxX = Math.max(maxX, point.x);
|
|
120
|
-
maxY = Math.max(maxY, point.y);
|
|
121
|
-
}
|
|
122
|
-
const pad = Math.max(8, input.size * 2);
|
|
123
|
-
return {
|
|
124
|
-
x: minX - pad,
|
|
125
|
-
y: minY - pad,
|
|
126
|
-
width: Math.max(1, maxX - minX + pad * 2),
|
|
127
|
-
height: Math.max(1, maxY - minY + pad * 2)
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
function boardArrowFrame(input) {
|
|
131
|
-
return {
|
|
132
|
-
...boardArrowBounds(input),
|
|
133
|
-
rotation: 0
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
//#endregion
|
|
137
|
-
export { boardArrowBounds, boardArrowFrame, boardDrawBounds, boardDrawPointsToLocal, boardDrawPointsToWorld, boardDrawSampleRadius, boardResolveArrow, boardSampleResolvedArrow };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
//#region ../protocol/dist/board-node.d.ts
|
|
3
|
-
declare const BOARD_COLOR_IDS: readonly ["brand", "neutral", "black", "white", "blue", "green", "amber", "violet", "rose"];
|
|
4
|
-
type BoardColorId = (typeof BOARD_COLOR_IDS)[number];
|
|
5
|
-
declare const BOARD_GEO_KINDS: readonly ["rectangle", "rounded", "ellipse", "diamond", "triangle"];
|
|
6
|
-
type BoardGeoKind = (typeof BOARD_GEO_KINDS)[number];
|
|
7
|
-
//#endregion
|
|
8
|
-
export { BOARD_COLOR_IDS, BOARD_GEO_KINDS, BoardColorId, BoardGeoKind };
|
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import { BOARD_ARROW_STROKE_SIZE } from "./board-constants.js";
|
|
2
|
-
import { BoardTaskSnapshotSchema } from "./board-document.js";
|
|
3
|
-
import { boardArrowFrame, boardDrawBounds } from "./board-geometry.js";
|
|
4
|
-
import { z } from "zod";
|
|
5
|
-
//#region ../protocol/dist/board-node.js
|
|
6
|
-
const BOARD_COLOR_IDS = [
|
|
7
|
-
"brand",
|
|
8
|
-
"neutral",
|
|
9
|
-
"black",
|
|
10
|
-
"white",
|
|
11
|
-
"blue",
|
|
12
|
-
"green",
|
|
13
|
-
"amber",
|
|
14
|
-
"violet",
|
|
15
|
-
"rose"
|
|
16
|
-
];
|
|
17
|
-
const BoardColorIdSchema = z.enum(BOARD_COLOR_IDS);
|
|
18
|
-
const BOARD_GEO_KINDS = [
|
|
19
|
-
"rectangle",
|
|
20
|
-
"rounded",
|
|
21
|
-
"ellipse",
|
|
22
|
-
"diamond",
|
|
23
|
-
"triangle"
|
|
24
|
-
];
|
|
25
|
-
const BoardGeoKindSchema = z.enum(BOARD_GEO_KINDS);
|
|
26
|
-
const BOARD_NATIVE_NODE_TYPES = [
|
|
27
|
-
"image",
|
|
28
|
-
"video",
|
|
29
|
-
"audio",
|
|
30
|
-
"file",
|
|
31
|
-
"task",
|
|
32
|
-
"text",
|
|
33
|
-
"geo",
|
|
34
|
-
"draw",
|
|
35
|
-
"arrow",
|
|
36
|
-
"frame"
|
|
37
|
-
];
|
|
38
|
-
const metadataSchema = z.record(z.string(), z.unknown());
|
|
39
|
-
const commonData = {
|
|
40
|
-
locked: z.boolean().optional(),
|
|
41
|
-
metadata: metadataSchema.optional()
|
|
42
|
-
};
|
|
43
|
-
const pointSchema = z.object({
|
|
44
|
-
x: z.number().finite(),
|
|
45
|
-
y: z.number().finite(),
|
|
46
|
-
p: z.number().finite().min(0).max(1).default(.5)
|
|
47
|
-
}).strict();
|
|
48
|
-
const worldPointSchema = z.object({
|
|
49
|
-
x: z.number().finite(),
|
|
50
|
-
y: z.number().finite()
|
|
51
|
-
}).strict();
|
|
52
|
-
const strokeSizeSchema = z.number().finite().min(1).max(64);
|
|
53
|
-
const mediaViewSchema = z.object({
|
|
54
|
-
title: z.string().optional(),
|
|
55
|
-
mimeType: z.string().optional(),
|
|
56
|
-
size: z.number().finite().nonnegative().optional(),
|
|
57
|
-
mtimeMs: z.number().finite().nonnegative().optional(),
|
|
58
|
-
naturalWidth: z.number().finite().positive().optional(),
|
|
59
|
-
naturalHeight: z.number().finite().positive().optional()
|
|
60
|
-
}).strict();
|
|
61
|
-
const audioViewSchema = mediaViewSchema.extend({ durationMs: z.number().finite().nonnegative().optional() });
|
|
62
|
-
const dataSchemas = {
|
|
63
|
-
text: z.object({
|
|
64
|
-
...commonData,
|
|
65
|
-
text: z.string().default(""),
|
|
66
|
-
color: BoardColorIdSchema.default("neutral"),
|
|
67
|
-
fontSize: z.number().finite().min(2).max(512).default(24)
|
|
68
|
-
}).strict(),
|
|
69
|
-
geo: z.object({
|
|
70
|
-
...commonData,
|
|
71
|
-
geo: BoardGeoKindSchema.default("rectangle"),
|
|
72
|
-
text: z.string().default(""),
|
|
73
|
-
color: BoardColorIdSchema.default("brand"),
|
|
74
|
-
fillOpacity: z.number().finite().min(0).max(1).default(0)
|
|
75
|
-
}).strict(),
|
|
76
|
-
draw: z.object({
|
|
77
|
-
...commonData,
|
|
78
|
-
points: z.array(pointSchema).min(1),
|
|
79
|
-
color: BoardColorIdSchema.default("brand"),
|
|
80
|
-
size: strokeSizeSchema.default(4)
|
|
81
|
-
}).strict(),
|
|
82
|
-
arrow: z.object({
|
|
83
|
-
...commonData,
|
|
84
|
-
start: worldPointSchema,
|
|
85
|
-
end: worldPointSchema,
|
|
86
|
-
bend: z.number().finite().min(-.85).max(.85).default(0),
|
|
87
|
-
color: BoardColorIdSchema.default("brand"),
|
|
88
|
-
size: strokeSizeSchema.default(BOARD_ARROW_STROKE_SIZE),
|
|
89
|
-
arrowStart: z.boolean().default(false),
|
|
90
|
-
arrowEnd: z.boolean().default(true),
|
|
91
|
-
label: z.string().default("")
|
|
92
|
-
}).strict(),
|
|
93
|
-
frame: z.object({
|
|
94
|
-
...commonData,
|
|
95
|
-
label: z.string().default("Frame"),
|
|
96
|
-
color: BoardColorIdSchema.default("neutral")
|
|
97
|
-
}).strict(),
|
|
98
|
-
image: z.object({
|
|
99
|
-
...commonData,
|
|
100
|
-
crop: z.object({
|
|
101
|
-
x: z.number().finite().min(0).max(1),
|
|
102
|
-
y: z.number().finite().min(0).max(1),
|
|
103
|
-
w: z.number().finite().min(0).max(1),
|
|
104
|
-
h: z.number().finite().min(0).max(1)
|
|
105
|
-
}).strict().optional()
|
|
106
|
-
}).strict(),
|
|
107
|
-
video: z.object(commonData).strict(),
|
|
108
|
-
audio: z.object(commonData).strict(),
|
|
109
|
-
file: z.object(commonData).strict(),
|
|
110
|
-
task: z.object({
|
|
111
|
-
...commonData,
|
|
112
|
-
taskRunId: z.string().min(1)
|
|
113
|
-
}).strict()
|
|
114
|
-
};
|
|
115
|
-
const fileViewSchema = z.object({
|
|
116
|
-
title: z.string().optional(),
|
|
117
|
-
mimeType: z.string().optional(),
|
|
118
|
-
size: z.number().finite().nonnegative().optional(),
|
|
119
|
-
mtimeMs: z.number().finite().nonnegative().optional(),
|
|
120
|
-
excerpt: z.string().optional(),
|
|
121
|
-
coverPath: z.string().optional(),
|
|
122
|
-
coverUrl: z.string().url().optional()
|
|
123
|
-
}).strict();
|
|
124
|
-
const taskViewSchema = BoardTaskSnapshotSchema;
|
|
125
|
-
const emptyViewSchema = z.object({}).strict();
|
|
126
|
-
const viewSchemas = {
|
|
127
|
-
image: mediaViewSchema,
|
|
128
|
-
video: mediaViewSchema,
|
|
129
|
-
audio: audioViewSchema,
|
|
130
|
-
file: fileViewSchema,
|
|
131
|
-
task: taskViewSchema,
|
|
132
|
-
text: emptyViewSchema,
|
|
133
|
-
geo: emptyViewSchema,
|
|
134
|
-
draw: emptyViewSchema,
|
|
135
|
-
arrow: emptyViewSchema,
|
|
136
|
-
frame: emptyViewSchema
|
|
137
|
-
};
|
|
138
|
-
const nodeEnvelopeSchema = z.object({
|
|
139
|
-
nodeId: z.string().min(1).max(160),
|
|
140
|
-
type: z.string().min(1).max(40),
|
|
141
|
-
parentId: z.string().min(1).max(160).nullable(),
|
|
142
|
-
orderKey: z.string().max(4096).nullable(),
|
|
143
|
-
x: z.number().finite(),
|
|
144
|
-
y: z.number().finite(),
|
|
145
|
-
width: z.number().finite().positive(),
|
|
146
|
-
height: z.number().finite().positive(),
|
|
147
|
-
rotation: z.number().finite(),
|
|
148
|
-
refKind: z.string().max(40).nullable(),
|
|
149
|
-
refPath: z.string().max(4096).nullable(),
|
|
150
|
-
refUrl: z.string().max(4096).nullable(),
|
|
151
|
-
view: z.record(z.string(), z.unknown()),
|
|
152
|
-
style: z.record(z.string(), z.unknown()),
|
|
153
|
-
data: z.record(z.string(), z.unknown())
|
|
154
|
-
}).strict();
|
|
155
|
-
function jsonSchema(schema) {
|
|
156
|
-
return z.toJSONSchema(schema);
|
|
157
|
-
}
|
|
158
|
-
jsonSchema(nodeEnvelopeSchema), Object.fromEntries(BOARD_NATIVE_NODE_TYPES.map((type) => [type, jsonSchema(dataSchemas[type])])), Object.fromEntries(BOARD_NATIVE_NODE_TYPES.map((type) => [type, jsonSchema(viewSchemas[type])]));
|
|
159
|
-
function issueDiagnostic(issue, path) {
|
|
160
|
-
const fullPath = [path, ...issue.path].join(".");
|
|
161
|
-
const values = "values" in issue && Array.isArray(issue.values) ? issue.values.filter((value) => typeof value === "string") : void 0;
|
|
162
|
-
return {
|
|
163
|
-
severity: "error",
|
|
164
|
-
code: "INVALID_BOARD_NODE",
|
|
165
|
-
message: `${fullPath}: ${issue.message}`,
|
|
166
|
-
path: fullPath,
|
|
167
|
-
...values?.length ? { allowedValues: values } : {}
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
function drawGeometryDiagnostic(node, data, path) {
|
|
171
|
-
const { x: minX, y: minY, width, height } = boardDrawBounds(data.points, data.size);
|
|
172
|
-
const tolerance = Math.max(.01, node.width * 1e-6, node.height * 1e-6);
|
|
173
|
-
if (Math.abs(minX) <= tolerance && Math.abs(minY) <= tolerance && Math.abs(width - node.width) <= tolerance && Math.abs(height - node.height) <= tolerance) return null;
|
|
174
|
-
return {
|
|
175
|
-
severity: "error",
|
|
176
|
-
code: "INVALID_BOARD_GEOMETRY",
|
|
177
|
-
message: `${path}.data.points must use frame-local coordinates and match the node frame`,
|
|
178
|
-
path: `${path}.data.points`,
|
|
179
|
-
expected: `frame-local bounds x=0, y=0, width=${width}, height=${height}`,
|
|
180
|
-
received: {
|
|
181
|
-
frame: {
|
|
182
|
-
x: node.x,
|
|
183
|
-
y: node.y,
|
|
184
|
-
width: node.width,
|
|
185
|
-
height: node.height
|
|
186
|
-
},
|
|
187
|
-
pointsBounds: {
|
|
188
|
-
x: minX,
|
|
189
|
-
y: minY,
|
|
190
|
-
width,
|
|
191
|
-
height
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
coordinateSpace: "frame-local"
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
function validateBoardNodeInput(node, path = "node") {
|
|
198
|
-
const envelopeResult = nodeEnvelopeSchema.safeParse(node);
|
|
199
|
-
if (!envelopeResult.success) return envelopeResult.error.issues.map((issue) => issueDiagnostic(issue, path));
|
|
200
|
-
if (typeof node.type !== "string" || !BOARD_NATIVE_NODE_TYPES.includes(node.type)) return [{
|
|
201
|
-
severity: "error",
|
|
202
|
-
code: "INVALID_BOARD_NODE",
|
|
203
|
-
message: `${path}.type is not supported`,
|
|
204
|
-
path: `${path}.type`,
|
|
205
|
-
expected: "BoardNativeNodeType",
|
|
206
|
-
received: node.type,
|
|
207
|
-
allowedValues: BOARD_NATIVE_NODE_TYPES
|
|
208
|
-
}];
|
|
209
|
-
const type = node.type;
|
|
210
|
-
const dataResult = dataSchemas[type].safeParse(node.data ?? {});
|
|
211
|
-
if (!dataResult.success) return dataResult.error.issues.map((issue) => issueDiagnostic(issue, `${path}.data`));
|
|
212
|
-
const viewResult = viewSchemas[type].safeParse(node.view ?? {});
|
|
213
|
-
if (!viewResult.success) return viewResult.error.issues.map((issue) => issueDiagnostic(issue, `${path}.view`));
|
|
214
|
-
if (type === "image" || type === "video" || type === "audio" || type === "file") {
|
|
215
|
-
if (node.refKind !== "space_file" || typeof node.refPath !== "string" || !node.refPath) return [{
|
|
216
|
-
severity: "error",
|
|
217
|
-
code: "INVALID_BOARD_NODE",
|
|
218
|
-
message: `${path} requires a space file reference`,
|
|
219
|
-
path: `${path}.refPath`,
|
|
220
|
-
expected: "non-empty refPath with refKind space_file"
|
|
221
|
-
}];
|
|
222
|
-
}
|
|
223
|
-
if (type === "draw") {
|
|
224
|
-
const diagnostic = drawGeometryDiagnostic(node, dataResult.data, path);
|
|
225
|
-
return diagnostic ? [diagnostic] : [];
|
|
226
|
-
}
|
|
227
|
-
if (type === "arrow") {
|
|
228
|
-
const data = dataResult.data;
|
|
229
|
-
const expected = boardArrowFrame(data);
|
|
230
|
-
const tolerance = Math.max(.01, node.width * 1e-6, node.height * 1e-6);
|
|
231
|
-
if (Math.abs(node.x - expected.x) > tolerance || Math.abs(node.y - expected.y) > tolerance || Math.abs(node.width - expected.width) > tolerance || Math.abs(node.height - expected.height) > tolerance) return [{
|
|
232
|
-
severity: "error",
|
|
233
|
-
code: "INVALID_BOARD_GEOMETRY",
|
|
234
|
-
message: `${path}.data endpoints must use world-space coordinates and match the arrow frame`,
|
|
235
|
-
path: `${path}.data`,
|
|
236
|
-
expected: `world-space curve bounds x=${expected.x}, y=${expected.y}, width=${expected.width}, height=${expected.height}`,
|
|
237
|
-
received: {
|
|
238
|
-
frame: {
|
|
239
|
-
x: node.x,
|
|
240
|
-
y: node.y,
|
|
241
|
-
width: node.width,
|
|
242
|
-
height: node.height
|
|
243
|
-
},
|
|
244
|
-
curveBounds: expected
|
|
245
|
-
},
|
|
246
|
-
coordinateSpace: "world"
|
|
247
|
-
}];
|
|
248
|
-
}
|
|
249
|
-
return [];
|
|
250
|
-
}
|
|
251
|
-
//#endregion
|
|
252
|
-
export { BOARD_COLOR_IDS, BOARD_GEO_KINDS, BOARD_NATIVE_NODE_TYPES, BoardColorIdSchema, BoardGeoKindSchema, validateBoardNodeInput };
|
|
File without changes
|