@neta-art/cohub 10.0.0 → 11.1.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/README.md +42 -7
- package/dist/board/editor/animation.d.ts +3 -0
- package/dist/board/editor/animation.js +16 -1
- package/dist/board/editor/clipboard.js +7 -0
- package/dist/board/editor/copy.js +23 -18
- package/dist/board/editor/creation.d.ts +7 -3
- package/dist/board/editor/creation.js +5 -4
- package/dist/board/editor/deletion.js +3 -3
- package/dist/board/editor/document.d.ts +8 -2
- package/dist/board/editor/document.js +54 -7
- package/dist/board/editor/editor.d.ts +22 -7
- package/dist/board/editor/editor.js +12 -2
- package/dist/board/editor/index.d.ts +2 -2
- package/dist/board/editor/interaction.d.ts +8 -2
- package/dist/board/editor/interaction.js +34 -1
- package/dist/board/editor/query.d.ts +5 -5
- package/dist/board/editor/query.js +14 -12
- package/dist/board/editor/selection.js +2 -1
- package/dist/board/editor/snapshots.d.ts +0 -2
- package/dist/board/editor/snapshots.js +4 -20
- package/dist/board/export/index.d.ts +25 -4
- package/dist/board/export/index.js +45 -12
- package/dist/board/export/node/index.d.ts +5 -4
- package/dist/board/export/node/index.js +16 -11
- package/dist/board/export/node/scripts.d.ts +16 -0
- package/dist/board/export/node/scripts.js +258 -0
- package/dist/board/export/scene.d.ts +2 -1
- package/dist/board/export/scene.js +24 -7
- package/dist/board/model/animation.d.ts +4 -1
- package/dist/board/model/animation.js +34 -7
- package/dist/board/model/authoring.d.ts +20 -0
- package/dist/board/model/authoring.js +185 -0
- package/dist/board/model/export-plan.js +1 -0
- package/dist/board/model/file-preview.js +1 -1
- package/dist/board/model/file-snapshot.js +3 -2
- package/dist/board/model/image-key.js +7 -3
- package/dist/board/model/index.d.ts +15 -7
- package/dist/board/model/index.js +16 -9
- package/dist/board/model/items/builtin.js +2 -2
- package/dist/board/model/items/create.d.ts +19 -4
- package/dist/board/model/items/create.js +130 -9
- package/dist/board/model/items/index.d.ts +2 -2
- package/dist/board/model/items/index.js +2 -2
- package/dist/board/model/media-playback.d.ts +2 -1
- package/dist/board/model/media-playback.js +15 -5
- package/dist/board/model/media.js +7 -1
- package/dist/board/model/overlay-placement.d.ts +25 -0
- package/dist/board/model/overlay-placement.js +35 -0
- package/dist/board/model/replay.d.ts +1 -1
- package/dist/board/model/replay.js +1 -0
- package/dist/board/model/sampling.d.ts +19 -0
- package/dist/board/model/sampling.js +96 -0
- package/dist/board/model/script-example.d.ts +4 -0
- package/dist/board/model/script-example.js +21 -0
- package/dist/board/model/script-hit.d.ts +27 -0
- package/dist/board/model/script-hit.js +109 -0
- package/dist/board/model/script-index.d.ts +7 -0
- package/dist/board/model/script-index.js +15 -0
- package/dist/board/model/script-observers.d.ts +18 -0
- package/dist/board/model/script-observers.js +92 -0
- package/dist/board/model/script-scene.d.ts +24 -0
- package/dist/board/model/script-scene.js +294 -0
- package/dist/board/model/script.d.ts +149 -0
- package/dist/board/model/script.js +1 -0
- package/dist/board/render/board-background.js +5 -4
- package/dist/board/render/css-color.d.ts +6 -1
- package/dist/board/render/css-color.js +34 -20
- package/dist/board/render/diagnostics.d.ts +20 -0
- package/dist/board/render/diagnostics.js +117 -0
- package/dist/board/render/index.d.ts +9 -6
- package/dist/board/render/index.js +10 -7
- package/dist/board/render/media-interaction.js +1 -1
- package/dist/board/render/palette.d.ts +2 -1
- package/dist/board/render/palette.js +6 -2
- package/dist/board/render/renderers/arrow-card-renderer.js +3 -2
- package/dist/board/render/renderers/audio-card-renderer.js +2 -1
- package/dist/board/render/renderers/board-renderer-registry.d.ts +25 -5
- package/dist/board/render/renderers/board-renderer-registry.js +11 -4
- package/dist/board/render/renderers/custom-card-renderer.d.ts +5 -0
- package/dist/board/render/renderers/{sketch-card-renderer.js → custom-card-renderer.js} +18 -16
- package/dist/board/render/renderers/draw-card-renderer.js +3 -2
- package/dist/board/render/renderers/effect-card-renderer.js +22 -5
- package/dist/board/render/renderers/frame-card-renderer.js +30 -14
- package/dist/board/render/renderers/image-card-renderer.js +43 -4
- package/dist/board/render/renderers/shape-card-renderer.js +10 -27
- package/dist/board/render/renderers/task-card-renderer.d.ts +2 -1
- package/dist/board/render/renderers/task-card-renderer.js +220 -71
- package/dist/board/render/renderers/text-card-renderer.js +5 -3
- package/dist/board/render/renderers/unknown-card-renderer.js +1 -0
- package/dist/board/render/renderers/video-card-renderer.js +2 -1
- package/dist/board/render/sampling.d.ts +22 -0
- package/dist/board/render/sampling.js +21 -0
- package/dist/board/render/script-export.d.ts +11 -0
- package/dist/board/render/script-export.js +86 -0
- package/dist/board/render/script-host.d.ts +31 -0
- package/dist/board/render/script-host.js +446 -0
- package/dist/board/render/script-modules.d.ts +2 -0
- package/dist/board/render/script-modules.js +2 -0
- package/dist/board/render/script-runtime.d.ts +29 -0
- package/dist/board/render/script-runtime.js +223 -0
- package/dist/board/render/script-sandbox.d.ts +4 -0
- package/dist/board/render/script-sandbox.js +173 -0
- package/dist/board/render/script-texture.d.ts +11 -0
- package/dist/board/render/script-texture.js +33 -0
- package/dist/board/render/stroke.d.ts +2 -1
- package/dist/board/render/stroke.js +22 -1
- package/dist/board/render/text-measurement.js +1 -1
- package/dist/board/stage/assets.js +7 -2
- package/dist/board/stage/maintenance.d.ts +5 -0
- package/dist/board/stage/maintenance.js +11 -0
- package/dist/board/stage/scene.d.ts +2 -0
- package/dist/board/stage/scene.js +21 -2
- package/dist/board/stage/script-pointer.d.ts +20 -0
- package/dist/board/stage/script-pointer.js +41 -0
- package/dist/board/stage/stage.d.ts +21 -3
- package/dist/board/stage/stage.js +350 -47
- package/dist/board/stage/texture-pool.js +2 -3
- package/dist/chunks/environment.d.ts +305 -27
- package/dist/chunks/environment.js +12 -4
- package/dist/chunks/host-bridge.d.ts +2 -2
- package/dist/chunks/http.d.ts +90 -7
- package/dist/chunks/http.js +157 -64
- package/dist/chunks/transport.js +4 -2
- package/dist/chunks/websocket.d.ts +9 -1
- package/dist/chunks/websocket.js +16 -2
- package/dist/host-bridge.js +2 -1
- package/dist/http.d.ts +3 -3
- package/dist/index.d.ts +182 -4
- package/dist/index.js +1559 -299
- package/dist/protocol/dist/board-assets.d.ts +1 -0
- package/dist/protocol/dist/board-constants.js +2 -2
- package/dist/protocol/dist/board-model.d.ts +236 -11
- package/dist/protocol/dist/board-model.js +46 -17
- package/dist/protocol/dist/board-patch.js +2 -1
- package/dist/protocol/dist/board-schema.d.ts +4 -2
- package/dist/protocol/dist/board-schema.js +18 -4
- package/dist/protocol/dist/board-script-modules.d.ts +25 -0
- package/dist/protocol/dist/board-script-modules.js +127 -0
- package/dist/protocol/dist/board-task.d.ts +22 -0
- package/dist/{board/model/task.js → protocol/dist/board-task.js} +34 -7
- package/dist/protocol/dist/display/index.d.ts +1 -0
- package/dist/protocol/dist/generation/blocks.d.ts +8 -0
- package/dist/{generation-blocks.js → protocol/dist/generation/blocks.js} +14 -15
- package/dist/protocol/dist/index.d.ts +7 -2
- package/dist/protocol/dist/realtime/types.d.ts +1 -0
- package/dist/protocol/dist/rtc/index.d.ts +1 -0
- package/dist/protocol/dist/task/index.d.ts +4 -0
- package/package.json +2 -1
- package/dist/board/export/node/sketch.d.ts +0 -19
- package/dist/board/export/node/sketch.js +0 -146
- package/dist/board/model/task.d.ts +0 -11
- package/dist/board/render/renderers/sketch-card-renderer.d.ts +0 -5
- package/dist/board/render/sketch-host.d.ts +0 -14
- package/dist/board/render/sketch-host.js +0 -216
- package/dist/types.d.ts +0 -36
|
@@ -3,7 +3,7 @@ import { RequestSource } from "../../protocol/dist/provenance.js";
|
|
|
3
3
|
import { BoardHistoryPage } from "../../protocol/dist/board.js";
|
|
4
4
|
import "../../protocol/dist/index.js";
|
|
5
5
|
//#region src/board/model/replay.d.ts
|
|
6
|
-
type BoardReplayActorKind = "human" | "cli" | "agent";
|
|
6
|
+
type BoardReplayActorKind = "human" | "cli" | "agent" | "task";
|
|
7
7
|
type BoardReplayEntry = {
|
|
8
8
|
version: number;
|
|
9
9
|
actorId: string;
|
|
@@ -3,6 +3,7 @@ import { applyBoardDelta } from "../../protocol/dist/board-patch.js";
|
|
|
3
3
|
function boardReplayActorKind(source) {
|
|
4
4
|
if (!source) return "human";
|
|
5
5
|
if (source.toolCallId) return "agent";
|
|
6
|
+
if (source.via === "task") return "task";
|
|
6
7
|
return source.via === "cli" ? "cli" : "human";
|
|
7
8
|
}
|
|
8
9
|
function entryOf(transaction) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BoardDocument } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import { BoardFrame } from "../../protocol/dist/board-layout.js";
|
|
3
|
+
import "../../protocol/dist/index.js";
|
|
4
|
+
import { BoardViewport, Size } from "./geometry.js";
|
|
5
|
+
import { BoardScene } from "./scene.js";
|
|
6
|
+
import { BoardCameraOverride, BoardEvaluateOptions, BoardEvaluation } from "./animation.js";
|
|
7
|
+
//#region src/board/model/sampling.d.ts
|
|
8
|
+
declare function createBoardAnimationSampler(document: BoardDocument, animation: string | null, options?: BoardEvaluateOptions): {
|
|
9
|
+
frameAt(id: string, time: number): BoardFrame | undefined;
|
|
10
|
+
at(time: number): {
|
|
11
|
+
document: BoardDocument;
|
|
12
|
+
evaluation: BoardEvaluation;
|
|
13
|
+
scene: BoardScene;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
type BoardAnimationSampler = ReturnType<typeof createBoardAnimationSampler>;
|
|
17
|
+
declare function resolveBoardAnimationCamera(override: BoardCameraOverride, bounds: (id: string) => BoardFrame | undefined, surface: Size, time: number, base?: BoardViewport): BoardViewport;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { BoardAnimationSampler, createBoardAnimationSampler, resolveBoardAnimationCamera };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { arrowBindings } from "../../protocol/dist/board-layout.js";
|
|
2
|
+
import { cameraForFocus, cameraForState } from "./geometry.js";
|
|
3
|
+
import { applyBoardEvaluation, boardAnimationTime, compileBoardAnimations, evaluateBoardAnimations } from "./animation.js";
|
|
4
|
+
import { buildBoardScene } from "./scene.js";
|
|
5
|
+
//#region src/board/model/sampling.ts
|
|
6
|
+
function createBoardAnimationSampler(document, animation, options = {}) {
|
|
7
|
+
const selected = animation ? document.animations[animation] : void 0;
|
|
8
|
+
if (animation && !selected) throw new Error(`Animation ${animation} does not exist.`);
|
|
9
|
+
const compiled = compileBoardAnimations(document);
|
|
10
|
+
const cache = /* @__PURE__ */ new Map();
|
|
11
|
+
const geometry = /* @__PURE__ */ new Map();
|
|
12
|
+
function sample(time) {
|
|
13
|
+
const times = /* @__PURE__ */ new Map();
|
|
14
|
+
for (const [id, entry] of compiled.animations) if (entry.header.play === "always") times.set(id, boardAnimationTime(entry.header, time) ?? 0);
|
|
15
|
+
if (animation && selected) times.set(animation, Math.min(time, selected.duration));
|
|
16
|
+
const evaluation = evaluateBoardAnimations(compiled, times, options);
|
|
17
|
+
return {
|
|
18
|
+
document: applyBoardEvaluation(document, evaluation),
|
|
19
|
+
evaluation
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function stateAt(time) {
|
|
23
|
+
if (!Number.isFinite(time) || time < 0) throw new Error("Animation time must be finite and non-negative.");
|
|
24
|
+
let value = cache.get(time);
|
|
25
|
+
if (!value) {
|
|
26
|
+
value = sample(time);
|
|
27
|
+
const oldest = cache.keys().next().value;
|
|
28
|
+
if (cache.size >= 64 && oldest !== void 0) cache.delete(oldest);
|
|
29
|
+
cache.set(time, value);
|
|
30
|
+
}
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
let current;
|
|
34
|
+
return {
|
|
35
|
+
frameAt(id, time) {
|
|
36
|
+
const key = `${time}:${id}`;
|
|
37
|
+
if (geometry.has(key)) return geometry.get(key);
|
|
38
|
+
const sampled = stateAt(time).document;
|
|
39
|
+
const items = {};
|
|
40
|
+
const pending = [id];
|
|
41
|
+
while (pending.length) {
|
|
42
|
+
const next = pending.pop();
|
|
43
|
+
if (!next || items[next]) continue;
|
|
44
|
+
const item = sampled.items[next];
|
|
45
|
+
if (!item) continue;
|
|
46
|
+
items[next] = item;
|
|
47
|
+
if (item.parent) pending.push(item.parent);
|
|
48
|
+
pending.push(...arrowBindings(item));
|
|
49
|
+
}
|
|
50
|
+
const frame = buildBoardScene({
|
|
51
|
+
...sampled,
|
|
52
|
+
items
|
|
53
|
+
}).get(id)?.frame;
|
|
54
|
+
if (geometry.size >= 2048) geometry.clear();
|
|
55
|
+
geometry.set(key, frame);
|
|
56
|
+
return frame;
|
|
57
|
+
},
|
|
58
|
+
at(time) {
|
|
59
|
+
if (current?.time === time) return current.value;
|
|
60
|
+
const sampled = stateAt(time);
|
|
61
|
+
const value = {
|
|
62
|
+
...sampled,
|
|
63
|
+
scene: buildBoardScene(sampled.document)
|
|
64
|
+
};
|
|
65
|
+
current = {
|
|
66
|
+
time,
|
|
67
|
+
value
|
|
68
|
+
};
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function resolveBoardAnimationCamera(override, bounds, surface, time, base = {
|
|
74
|
+
x: 0,
|
|
75
|
+
y: 0,
|
|
76
|
+
zoom: 1
|
|
77
|
+
}) {
|
|
78
|
+
let camera = override.focus === void 0 ? base : cameraForFocus(override.focus, bounds, surface, { padding: 48 }) ?? base;
|
|
79
|
+
if (override.zoom !== void 0) camera = {
|
|
80
|
+
...camera,
|
|
81
|
+
zoom: override.zoom
|
|
82
|
+
};
|
|
83
|
+
if (override.center) camera = cameraForState({
|
|
84
|
+
centerX: override.center.x,
|
|
85
|
+
centerY: override.center.y,
|
|
86
|
+
zoom: camera.zoom
|
|
87
|
+
}, surface);
|
|
88
|
+
if (override.shake) camera = {
|
|
89
|
+
...camera,
|
|
90
|
+
x: camera.x + Math.sin(time / 1e3 * 91.3) * override.shake,
|
|
91
|
+
y: camera.y + Math.cos(time / 1e3 * 77.9) * override.shake
|
|
92
|
+
};
|
|
93
|
+
return camera;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { createBoardAnimationSampler, resolveBoardAnimationCamera };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
//#region src/board/model/script-example.d.ts
|
|
2
|
+
declare const BOARD_SCRIPT_DRAWING_EXAMPLE = "export const animated = true;\n\nexport const parameters = {\n amplitude: { type: \"number\", label: \"Amplitude\", default: 40, min: 0, max: 120 }\n};\n\nexport function draw(ctx, { t, width, height, params }) {\n ctx.strokeStyle = \"#e67845\";\n ctx.lineWidth = 3;\n ctx.beginPath();\n for (let x = 0; x <= width; x += 2) {\n const y = height / 2 + Math.sin(x / 40 - t / 800) * params.amplitude;\n if (x === 0) ctx.moveTo(x, y);\n else ctx.lineTo(x, y);\n }\n ctx.stroke();\n}\n";
|
|
3
|
+
//#endregion
|
|
4
|
+
export { BOARD_SCRIPT_DRAWING_EXAMPLE };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/board/model/script-example.ts
|
|
2
|
+
const BOARD_SCRIPT_DRAWING_EXAMPLE = `export const animated = true;
|
|
3
|
+
|
|
4
|
+
export const parameters = {
|
|
5
|
+
amplitude: { type: "number", label: "Amplitude", default: 40, min: 0, max: 120 }
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function draw(ctx, { t, width, height, params }) {
|
|
9
|
+
ctx.strokeStyle = "#e67845";
|
|
10
|
+
ctx.lineWidth = 3;
|
|
11
|
+
ctx.beginPath();
|
|
12
|
+
for (let x = 0; x <= width; x += 2) {
|
|
13
|
+
const y = height / 2 + Math.sin(x / 40 - t / 800) * params.amplitude;
|
|
14
|
+
if (x === 0) ctx.moveTo(x, y);
|
|
15
|
+
else ctx.lineTo(x, y);
|
|
16
|
+
}
|
|
17
|
+
ctx.stroke();
|
|
18
|
+
}
|
|
19
|
+
`;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { BOARD_SCRIPT_DRAWING_EXAMPLE };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BoardViewport, WorldPoint } from "./geometry.js";
|
|
2
|
+
import { BoardScriptHit, BoardScriptOutput } from "./script.js";
|
|
3
|
+
import { BoardScene, BoardSceneItem } from "./scene.js";
|
|
4
|
+
//#region src/board/model/script-hit.d.ts
|
|
5
|
+
declare function resolveBoardScriptHit(scene: BoardScene, owner: string, hit: BoardScriptHit): {
|
|
6
|
+
id: string;
|
|
7
|
+
item: BoardSceneItem;
|
|
8
|
+
rect: {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
} & {
|
|
14
|
+
label?: string;
|
|
15
|
+
cursor?: string;
|
|
16
|
+
};
|
|
17
|
+
} | null;
|
|
18
|
+
declare function boardScriptHitVisible(scene: BoardScene, hit: NonNullable<ReturnType<typeof resolveBoardScriptHit>>, camera: BoardViewport, surface: {
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
}): boolean;
|
|
22
|
+
declare function boardScriptTarget(scene: BoardScene, candidates: readonly string[], point: WorldPoint, outputs: ReadonlyMap<string, BoardScriptOutput>, hitTest: (item: BoardSceneItem, point: WorldPoint) => boolean): {
|
|
23
|
+
owner: string;
|
|
24
|
+
target: string;
|
|
25
|
+
} | null;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { boardScriptHitVisible, boardScriptTarget, resolveBoardScriptHit };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { applyMatrix, invertMatrix } from "../../protocol/dist/board-layout.js";
|
|
2
|
+
import { frameContainsPoint } from "./geometry.js";
|
|
3
|
+
import { scriptTemporaryPrefix } from "./script-scene.js";
|
|
4
|
+
//#region src/board/model/script-hit.ts
|
|
5
|
+
function resolveBoardScriptHit(scene, owner, hit) {
|
|
6
|
+
const id = "item" in hit ? `${scriptTemporaryPrefix(owner)}${hit.item}` : owner;
|
|
7
|
+
const item = scene.get(id);
|
|
8
|
+
if (!item || scene.opacity(id) <= 0) return null;
|
|
9
|
+
const box = scene.layout.box(id);
|
|
10
|
+
return {
|
|
11
|
+
id,
|
|
12
|
+
item,
|
|
13
|
+
rect: "x" in hit ? hit : {
|
|
14
|
+
x: 0,
|
|
15
|
+
y: 0,
|
|
16
|
+
width: box.width,
|
|
17
|
+
height: box.height
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function boardScriptHitVisible(scene, hit, camera, surface) {
|
|
22
|
+
const { x, y, width, height } = hit.rect;
|
|
23
|
+
if (width <= 0 || height <= 0) return false;
|
|
24
|
+
const matrix = scene.layout.matrix(hit.id);
|
|
25
|
+
const corners = [
|
|
26
|
+
applyMatrix(matrix, {
|
|
27
|
+
x,
|
|
28
|
+
y
|
|
29
|
+
}),
|
|
30
|
+
applyMatrix(matrix, {
|
|
31
|
+
x: x + width,
|
|
32
|
+
y
|
|
33
|
+
}),
|
|
34
|
+
applyMatrix(matrix, {
|
|
35
|
+
x,
|
|
36
|
+
y: y + height
|
|
37
|
+
}),
|
|
38
|
+
applyMatrix(matrix, {
|
|
39
|
+
x: x + width,
|
|
40
|
+
y: y + height
|
|
41
|
+
})
|
|
42
|
+
];
|
|
43
|
+
const xs = corners.map((point) => point.x * camera.zoom + camera.x);
|
|
44
|
+
const ys = corners.map((point) => point.y * camera.zoom + camera.y);
|
|
45
|
+
return Math.max(...xs) > 0 && Math.min(...xs) < surface.width && Math.max(...ys) > 0 && Math.min(...ys) < surface.height;
|
|
46
|
+
}
|
|
47
|
+
const bindings = /* @__PURE__ */ new WeakMap();
|
|
48
|
+
function bindingsFor(owner, output) {
|
|
49
|
+
const cached = bindings.get(output);
|
|
50
|
+
if (cached?.owner === owner) return cached.byItem;
|
|
51
|
+
const byItem = /* @__PURE__ */ new Map();
|
|
52
|
+
for (const [target, hit] of Object.entries(output.hits)) {
|
|
53
|
+
const id = "item" in hit ? `${scriptTemporaryPrefix(owner)}${hit.item}` : owner;
|
|
54
|
+
const list = byItem.get(id) ?? [];
|
|
55
|
+
list.push({
|
|
56
|
+
owner,
|
|
57
|
+
target,
|
|
58
|
+
hit
|
|
59
|
+
});
|
|
60
|
+
byItem.set(id, list);
|
|
61
|
+
}
|
|
62
|
+
bindings.set(output, {
|
|
63
|
+
owner,
|
|
64
|
+
byItem
|
|
65
|
+
});
|
|
66
|
+
return byItem;
|
|
67
|
+
}
|
|
68
|
+
function boardScriptTarget(scene, candidates, point, outputs, hitTest) {
|
|
69
|
+
const declared = [...outputs].map(([owner, output]) => bindingsFor(owner, output));
|
|
70
|
+
const prefixes = [...outputs.keys()].map(scriptTemporaryPrefix);
|
|
71
|
+
for (const id of [...candidates].sort((a, b) => scene.indexOf(b) - scene.indexOf(a))) {
|
|
72
|
+
const item = scene.get(id);
|
|
73
|
+
if (!item || scene.opacity(id) <= 0) continue;
|
|
74
|
+
let parent = item.parent;
|
|
75
|
+
let clipped = false;
|
|
76
|
+
for (let depth = 0; parent && depth < 64; depth++) {
|
|
77
|
+
const ancestor = scene.get(parent);
|
|
78
|
+
if (!ancestor) break;
|
|
79
|
+
if (ancestor.type === "frame" && ancestor.props.clip && !frameContainsPoint(ancestor.frame, point)) {
|
|
80
|
+
clipped = true;
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
parent = ancestor.parent;
|
|
84
|
+
}
|
|
85
|
+
if (clipped) continue;
|
|
86
|
+
for (const byItem of declared) {
|
|
87
|
+
const hits = byItem.get(id);
|
|
88
|
+
if (!hits) continue;
|
|
89
|
+
const local = applyMatrix(invertMatrix(scene.layout.matrix(id)), point);
|
|
90
|
+
for (let i = hits.length - 1; i >= 0; i--) {
|
|
91
|
+
const binding = hits[i];
|
|
92
|
+
if (!binding) continue;
|
|
93
|
+
const resolved = resolveBoardScriptHit(scene, binding.owner, binding.hit);
|
|
94
|
+
if (!resolved) continue;
|
|
95
|
+
const r = resolved.rect;
|
|
96
|
+
if (local.x >= r.x && local.y >= r.y && local.x <= r.x + r.width && local.y <= r.y + r.height && ("x" in binding.hit || hitTest(item, point))) return {
|
|
97
|
+
owner: binding.owner,
|
|
98
|
+
target: binding.target
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (prefixes.some((prefix) => id.startsWith(prefix))) continue;
|
|
103
|
+
if (item.type === "frame" && item.props.decoration === "none") continue;
|
|
104
|
+
if (hitTest(item, point)) return null;
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
//#endregion
|
|
109
|
+
export { boardScriptHitVisible, boardScriptTarget, resolveBoardScriptHit };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BoardDocument, BoardItem } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import "../../protocol/dist/index.js";
|
|
3
|
+
//#region src/board/model/script-index.d.ts
|
|
4
|
+
declare function boardScriptItems(document: Pick<BoardDocument, "items">): readonly (readonly [string, BoardItem])[];
|
|
5
|
+
declare function hasBoardScripts(document: Pick<BoardDocument, "items">): boolean;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { boardScriptItems, hasBoardScripts };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/board/model/script-index.ts
|
|
2
|
+
const scriptsByItems = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
function boardScriptItems(document) {
|
|
4
|
+
let scripts = scriptsByItems.get(document.items);
|
|
5
|
+
if (!scripts) {
|
|
6
|
+
scripts = Object.entries(document.items).filter(([, item]) => item.script?.enabled);
|
|
7
|
+
scriptsByItems.set(document.items, scripts);
|
|
8
|
+
}
|
|
9
|
+
return scripts;
|
|
10
|
+
}
|
|
11
|
+
function hasBoardScripts(document) {
|
|
12
|
+
return boardScriptItems(document).length > 0;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { boardScriptItems, hasBoardScripts };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BoardDocument } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import "../../protocol/dist/index.js";
|
|
3
|
+
import { BoardScriptEvent, BoardScriptOutput, BoardScriptView } from "./script.js";
|
|
4
|
+
//#region src/board/model/script-observers.d.ts
|
|
5
|
+
declare function createBoardScriptObservers(send: (owner: string, event: BoardScriptEvent) => void): {
|
|
6
|
+
readonly size: number;
|
|
7
|
+
readonly transforms: boolean;
|
|
8
|
+
update(owner: string, output: BoardScriptOutput | null): void;
|
|
9
|
+
sync(document: BoardDocument, selection: readonly string[], readView: () => BoardScriptView): void;
|
|
10
|
+
transform(document: BoardDocument, event: {
|
|
11
|
+
ids: readonly string[];
|
|
12
|
+
operation: string;
|
|
13
|
+
cancelled: boolean;
|
|
14
|
+
}): void;
|
|
15
|
+
clear(): void;
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { createBoardScriptObservers };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { boardScriptScope } from "./script-scene.js";
|
|
2
|
+
//#region src/board/model/script-observers.ts
|
|
3
|
+
const EVENTS = [
|
|
4
|
+
"viewchange",
|
|
5
|
+
"selectionchange",
|
|
6
|
+
"transformend"
|
|
7
|
+
];
|
|
8
|
+
function createBoardScriptObservers(send) {
|
|
9
|
+
const subscribers = /* @__PURE__ */ new Map();
|
|
10
|
+
function scope(owner, entry, document) {
|
|
11
|
+
if (entry.document !== document) {
|
|
12
|
+
entry.scope = boardScriptScope(document, owner);
|
|
13
|
+
entry.document = document;
|
|
14
|
+
entry.selection = void 0;
|
|
15
|
+
}
|
|
16
|
+
return entry.scope;
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
get size() {
|
|
20
|
+
return subscribers.size;
|
|
21
|
+
},
|
|
22
|
+
get transforms() {
|
|
23
|
+
return [...subscribers.values()].some((entry) => entry.listens.has("transformend"));
|
|
24
|
+
},
|
|
25
|
+
update(owner, output) {
|
|
26
|
+
const listens = new Set(EVENTS.filter((type) => output?.listens.includes(type)));
|
|
27
|
+
if (!listens.size) {
|
|
28
|
+
subscribers.delete(owner);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const entry = subscribers.get(owner) ?? {
|
|
32
|
+
listens,
|
|
33
|
+
scope: /* @__PURE__ */ new Set()
|
|
34
|
+
};
|
|
35
|
+
if (!listens.has("viewchange")) entry.view = void 0;
|
|
36
|
+
if (!listens.has("selectionchange")) {
|
|
37
|
+
entry.selection = void 0;
|
|
38
|
+
entry.selected = void 0;
|
|
39
|
+
}
|
|
40
|
+
entry.listens = listens;
|
|
41
|
+
subscribers.set(owner, entry);
|
|
42
|
+
},
|
|
43
|
+
sync(document, selection, readView) {
|
|
44
|
+
let view;
|
|
45
|
+
let key;
|
|
46
|
+
for (const [owner, entry] of subscribers) {
|
|
47
|
+
if (entry.listens.has("viewchange")) {
|
|
48
|
+
view ??= readView();
|
|
49
|
+
key ??= JSON.stringify(view);
|
|
50
|
+
if (entry.view !== key) {
|
|
51
|
+
entry.view = key;
|
|
52
|
+
send(owner, {
|
|
53
|
+
type: "viewchange",
|
|
54
|
+
data: view
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (entry.listens.has("selectionchange")) {
|
|
59
|
+
const allowed = scope(owner, entry, document);
|
|
60
|
+
if (entry.selection === selection) continue;
|
|
61
|
+
entry.selection = selection;
|
|
62
|
+
const ids = selection.filter((id) => allowed.has(id));
|
|
63
|
+
if (entry.selected && ids.length === entry.selected.length && ids.every((id, i) => id === entry.selected?.[i])) continue;
|
|
64
|
+
entry.selected = ids;
|
|
65
|
+
send(owner, {
|
|
66
|
+
type: "selectionchange",
|
|
67
|
+
data: { ids }
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
transform(document, event) {
|
|
73
|
+
for (const [owner, entry] of subscribers) {
|
|
74
|
+
if (!entry.listens.has("transformend")) continue;
|
|
75
|
+
const allowed = scope(owner, entry, document);
|
|
76
|
+
const ids = event.ids.filter((id) => allowed.has(id));
|
|
77
|
+
if (ids.length) send(owner, {
|
|
78
|
+
type: "transformend",
|
|
79
|
+
data: {
|
|
80
|
+
...event,
|
|
81
|
+
ids
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
clear() {
|
|
87
|
+
subscribers.clear();
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
export { createBoardScriptObservers };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BoardDocument, BoardItem, BoardPatch } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import { BoardScriptOutput } from "./script.js";
|
|
3
|
+
import { BoardScene } from "./scene.js";
|
|
4
|
+
//#region src/board/model/script-scene.d.ts
|
|
5
|
+
declare function boardScriptScope(document: Pick<BoardDocument, "items">, id: string): Set<string>;
|
|
6
|
+
declare function validateBoardScriptOutput(output: BoardScriptOutput, scope: ReadonlySet<string>): void;
|
|
7
|
+
declare function validateBoardScriptCommit(document: BoardDocument, id: string, patch: BoardPatch): void;
|
|
8
|
+
declare function scriptTemporaryPrefix(owner: string): string;
|
|
9
|
+
type PreparedOutput = {
|
|
10
|
+
document: BoardDocument;
|
|
11
|
+
owner: string;
|
|
12
|
+
rootId: string;
|
|
13
|
+
items: Map<string, BoardItem>;
|
|
14
|
+
presented: Map<string, {
|
|
15
|
+
base: BoardItem;
|
|
16
|
+
item: BoardItem;
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
19
|
+
declare function prepareBoardScriptOutput(document: BoardDocument, owner: string, output: BoardScriptOutput): PreparedOutput;
|
|
20
|
+
declare function composeBoardScriptItems(document: BoardDocument, scene: BoardScene, outputs: ReadonlyMap<string, BoardScriptOutput>, incoming?: ReadonlyMap<string, BoardItem>, screen?: {
|
|
21
|
+
zoom: number;
|
|
22
|
+
}, onError?: (owner: string, error: unknown) => void, gestureLayout?: BoardScene["layout"]): Map<string, BoardItem>;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { boardScriptScope, composeBoardScriptItems, prepareBoardScriptOutput, scriptTemporaryPrefix, validateBoardScriptCommit, validateBoardScriptOutput };
|