@neta-art/cohub 9.0.1 → 11.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/README.md +108 -102
- package/dist/board/editor/align.d.ts +11 -0
- package/dist/board/editor/align.js +72 -0
- package/dist/board/editor/animation.d.ts +17 -0
- package/dist/board/editor/animation.js +187 -0
- package/dist/board/editor/camera.d.ts +32 -0
- package/dist/board/editor/camera.js +137 -0
- package/dist/board/editor/clipboard.d.ts +41 -0
- package/dist/board/editor/clipboard.js +129 -0
- package/dist/board/editor/connection-ports.d.ts +19 -0
- package/dist/board/editor/connection-ports.js +85 -0
- package/dist/board/editor/context.d.ts +111 -0
- package/dist/board/editor/context.js +30 -0
- package/dist/board/editor/copy.d.ts +17 -0
- package/dist/board/editor/copy.js +121 -0
- package/dist/board/editor/creation.d.ts +51 -0
- package/dist/board/editor/creation.js +225 -0
- package/dist/board/editor/deletion.d.ts +9 -0
- package/dist/board/editor/deletion.js +90 -0
- package/dist/board/editor/document-edits.d.ts +22 -0
- package/dist/board/editor/document-edits.js +193 -0
- package/dist/board/editor/document.d.ts +41 -0
- package/dist/board/editor/document.js +302 -0
- package/dist/board/editor/editor.d.ts +225 -0
- package/dist/board/editor/editor.js +439 -0
- package/dist/board/editor/index.d.ts +18 -0
- package/dist/board/editor/index.js +12 -0
- package/dist/board/editor/interaction.d.ts +115 -0
- package/dist/board/editor/interaction.js +584 -0
- package/dist/board/editor/query.d.ts +27 -0
- package/dist/board/editor/query.js +203 -0
- package/dist/board/editor/remote.d.ts +11 -0
- package/dist/board/editor/remote.js +55 -0
- package/dist/board/editor/selection-transform.d.ts +24 -0
- package/dist/board/editor/selection-transform.js +81 -0
- package/dist/board/editor/selection.d.ts +33 -0
- package/dist/board/editor/selection.js +197 -0
- package/dist/board/editor/snapping.d.ts +33 -0
- package/dist/board/editor/snapping.js +75 -0
- package/dist/board/editor/snapshots.d.ts +27 -0
- package/dist/board/editor/snapshots.js +132 -0
- package/dist/board/editor/spatial.d.ts +41 -0
- package/dist/board/editor/spatial.js +191 -0
- package/dist/board/editor/state.d.ts +12 -0
- package/dist/board/editor/state.js +49 -0
- package/dist/board/editor/tool.d.ts +10 -0
- package/dist/board/editor/tool.js +19 -0
- package/dist/board/editor/wheel.d.ts +5 -0
- package/dist/board/editor/wheel.js +17 -0
- package/dist/board/export/index.d.ts +28 -6
- package/dist/board/export/index.js +47 -13
- package/dist/board/export/node/index.d.ts +56 -0
- package/dist/board/{headless → export/node}/index.js +26 -21
- 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 +8 -5
- package/dist/board/export/scene.js +24 -9
- package/dist/board/{animation.d.ts → model/animation.d.ts} +8 -5
- package/dist/board/{animation.js → model/animation.js} +37 -10
- package/dist/board/{core → model}/arrow-geometry.d.ts +2 -2
- package/dist/board/{core → model}/arrow-geometry.js +2 -2
- package/dist/board/model/authoring.d.ts +20 -0
- package/dist/board/model/authoring.js +185 -0
- package/dist/board/{core → model}/draw-geometry.d.ts +2 -2
- package/dist/board/{core → model}/draw-geometry.js +1 -1
- package/dist/board/model/draw-input.d.ts +14 -0
- package/dist/board/model/draw-input.js +28 -0
- package/dist/board/{core → model}/export-assets.d.ts +1 -1
- package/dist/board/{core → model}/export-assets.js +1 -1
- package/dist/board/{core → model}/export-plan.d.ts +2 -2
- package/dist/board/{core → model}/export-plan.js +3 -2
- package/dist/board/{core → model}/file-preview.d.ts +1 -1
- package/dist/board/{core → model}/file-preview.js +2 -2
- package/dist/board/{core → model}/file-snapshot.d.ts +1 -1
- package/dist/board/{core → model}/file-snapshot.js +4 -3
- package/dist/board/{geometry.d.ts → model/geometry.d.ts} +3 -3
- package/dist/board/{geometry.js → model/geometry.js} +1 -1
- package/dist/board/{image-key.d.ts → model/image-key.d.ts} +2 -2
- package/dist/board/{image-key.js → model/image-key.js} +7 -3
- package/dist/board/model/index.d.ts +42 -0
- package/dist/board/model/index.js +39 -0
- package/dist/board/model/items/builtin.d.ts +5 -0
- package/dist/board/model/items/builtin.js +119 -0
- package/dist/board/model/items/create.d.ts +61 -0
- package/dist/board/model/items/create.js +272 -0
- package/dist/board/model/items/definition.d.ts +35 -0
- package/dist/board/model/items/definition.js +18 -0
- package/dist/board/model/items/id.d.ts +5 -0
- package/dist/board/model/items/id.js +11 -0
- package/dist/board/model/items/index.d.ts +6 -0
- package/dist/board/model/items/index.js +6 -0
- package/dist/board/model/items/registry.d.ts +35 -0
- package/dist/board/model/items/registry.js +84 -0
- package/dist/board/{media-playback.d.ts → model/media-playback.d.ts} +4 -3
- package/dist/board/{media-playback.js → model/media-playback.js} +15 -5
- package/dist/board/{media.d.ts → model/media.d.ts} +1 -1
- package/dist/board/{media.js → model/media.js} +8 -2
- package/dist/board/{core → model}/palette.d.ts +1 -1
- package/dist/board/{core → model}/palette.js +1 -1
- package/dist/board/{presets.d.ts → model/presets.d.ts} +3 -3
- package/dist/board/{presets.js → model/presets.js} +1 -1
- package/dist/board/{replay.d.ts → model/replay.d.ts} +5 -5
- package/dist/board/{replay.js → model/replay.js} +2 -2
- package/dist/board/model/sampling.d.ts +19 -0
- package/dist/board/model/sampling.js +96 -0
- package/dist/board/{core → model}/scene.d.ts +1 -1
- package/dist/board/{core → model}/scene.js +1 -1
- 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 +10 -0
- package/dist/board/model/script-hit.js +52 -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-scene.d.ts +24 -0
- package/dist/board/model/script-scene.js +267 -0
- package/dist/board/model/script.d.ts +105 -0
- package/dist/board/model/script.js +1 -0
- package/dist/board/model/shape-types.d.ts +8 -0
- package/dist/board/model/shape-types.js +8 -0
- package/dist/board/{task.d.ts → model/task.d.ts} +4 -4
- package/dist/board/{task.js → model/task.js} +3 -3
- package/dist/board/{core → model}/text-metrics.d.ts +1 -1
- package/dist/board/{core → model}/text-metrics.js +1 -1
- package/dist/board/{core → model}/tool-styles.d.ts +1 -1
- package/dist/board/{core → model}/tool-styles.js +1 -1
- package/dist/board/{runtime/board-player.d.ts → player/index.d.ts} +2 -2
- package/dist/board/{runtime/board-player.js → player/index.js} +5 -4
- package/dist/board/render/board-background.d.ts +1 -1
- package/dist/board/render/clip.d.ts +1 -1
- 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.d.ts +2 -2
- package/dist/board/render/media-interaction.js +1 -1
- package/dist/board/render/palette.d.ts +3 -2
- package/dist/board/render/palette.js +7 -3
- package/dist/board/render/renderers/arrow-card-renderer.js +4 -3
- package/dist/board/render/renderers/audio-card-renderer.js +2 -1
- package/dist/board/render/renderers/board-renderer-registry.d.ts +20 -10
- package/dist/board/render/renderers/board-renderer-registry.js +17 -17
- 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} +16 -15
- package/dist/board/render/renderers/draw-card-renderer.js +4 -3
- package/dist/board/render/renderers/effect-card-renderer.js +22 -5
- package/dist/board/render/renderers/far-plate.js +1 -1
- package/dist/board/render/renderers/file-card-renderer.d.ts +1 -1
- package/dist/board/render/renderers/file-card-renderer.js +2 -2
- package/dist/board/render/renderers/frame-card-renderer.js +30 -14
- package/dist/board/render/renderers/image-card-renderer.d.ts +1 -1
- package/dist/board/render/renderers/image-card-renderer.js +43 -4
- package/dist/board/render/renderers/shape-card-renderer.js +11 -28
- package/dist/board/render/renderers/task-card-renderer.js +1 -1
- package/dist/board/render/renderers/text-card-renderer.js +6 -4
- package/dist/board/render/renderers/unknown-card-renderer.js +1 -0
- package/dist/board/render/renderers/video-card-renderer.d.ts +1 -1
- 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 +421 -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 +213 -0
- package/dist/board/render/script-sandbox.d.ts +4 -0
- package/dist/board/render/script-sandbox.js +173 -0
- package/dist/board/render/stroke.d.ts +3 -2
- package/dist/board/render/stroke.js +23 -2
- package/dist/board/render/text-measurement.js +2 -2
- package/dist/board/replica/index.d.ts +70 -0
- package/dist/board/replica/index.js +276 -0
- package/dist/board/stage/assets.d.ts +41 -0
- package/dist/board/stage/assets.js +355 -0
- package/dist/board/stage/index.d.ts +8 -0
- package/dist/board/stage/index.js +8 -0
- package/dist/board/stage/lru.d.ts +32 -0
- package/dist/board/stage/lru.js +29 -0
- package/dist/board/stage/maintenance.d.ts +5 -0
- package/dist/board/stage/maintenance.js +11 -0
- package/dist/board/stage/pointer.d.ts +8 -0
- package/dist/board/stage/pointer.js +33 -0
- package/dist/board/stage/scene.d.ts +85 -0
- package/dist/board/stage/scene.js +515 -0
- package/dist/board/stage/script-pointer.d.ts +19 -0
- package/dist/board/stage/script-pointer.js +35 -0
- package/dist/board/stage/stage.d.ts +76 -0
- package/dist/board/stage/stage.js +774 -0
- package/dist/board/stage/texture-pool.d.ts +24 -0
- package/dist/board/stage/texture-pool.js +153 -0
- package/dist/board/stage/views.d.ts +38 -0
- package/dist/board/stage/views.js +93 -0
- package/dist/chunks/environment.d.ts +289 -23
- package/dist/chunks/host-bridge.d.ts +2 -2
- package/dist/chunks/http.d.ts +185 -71
- package/dist/chunks/http.js +368 -269
- package/dist/chunks/transport.js +3 -1
- 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 +2 -2
- package/dist/index.d.ts +182 -4
- package/dist/index.js +1393 -129
- package/dist/media.d.ts +1 -10
- package/dist/media.js +16 -27
- 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 +201 -11
- package/dist/protocol/dist/board-model.js +33 -14
- package/dist/protocol/dist/board-patch.js +3 -2
- 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.d.ts +28 -2
- package/dist/protocol/dist/board.js +3 -1
- package/dist/protocol/dist/core/media.d.ts +5 -0
- package/dist/protocol/dist/core/media.js +39 -0
- package/dist/protocol/dist/display/index.d.ts +1 -0
- package/dist/protocol/dist/index.d.ts +7 -5
- package/dist/protocol/dist/realtime/types.d.ts +1 -0
- package/dist/protocol/dist/rtc/index.d.ts +1 -0
- package/dist/types.d.ts +1 -1
- package/package.json +21 -8
- package/dist/board/core/shape-definition.d.ts +0 -23
- package/dist/board/core/shape-definition.js +0 -45
- package/dist/board/core/shape-types.d.ts +0 -38
- package/dist/board/core/shape-types.js +0 -22
- package/dist/board/headless/index.d.ts +0 -55
- package/dist/board/headless/sketch.d.ts +0 -19
- package/dist/board/headless/sketch.js +0 -146
- package/dist/board/index.d.ts +0 -30
- package/dist/board/index.js +0 -29
- 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
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { hasAuthoredSize, parseBoardItem } from "../../../protocol/dist/board-model.js";
|
|
2
|
+
import { frameContainsPoint, itemBounds } from "../geometry.js";
|
|
3
|
+
import { FULL_CAPABILITIES } from "./definition.js";
|
|
4
|
+
import { builtinBoardItems } from "./builtin.js";
|
|
5
|
+
import { createBoardItemId } from "./id.js";
|
|
6
|
+
//#region src/board/model/items/registry.ts
|
|
7
|
+
const DEFAULT_ITEM_SIZE = {
|
|
8
|
+
width: 240,
|
|
9
|
+
height: 160
|
|
10
|
+
};
|
|
11
|
+
function createBoardRegistry(definitions = []) {
|
|
12
|
+
const byType = /* @__PURE__ */ new Map();
|
|
13
|
+
for (const definition of [...builtinBoardItems, ...definitions]) byType.set(definition.type, definition);
|
|
14
|
+
const capabilities = /* @__PURE__ */ new Map();
|
|
15
|
+
function capabilitiesOf(type) {
|
|
16
|
+
let value = capabilities.get(type);
|
|
17
|
+
if (!value) {
|
|
18
|
+
value = {
|
|
19
|
+
...FULL_CAPABILITIES,
|
|
20
|
+
...byType.get(type)?.capabilities
|
|
21
|
+
};
|
|
22
|
+
capabilities.set(type, value);
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
function validateProps(type, props) {
|
|
27
|
+
const schema = byType.get(type)?.props;
|
|
28
|
+
if (!schema) return { ok: true };
|
|
29
|
+
const parsed = schema.safeParse(props);
|
|
30
|
+
if (parsed.success) return { ok: true };
|
|
31
|
+
const issue = parsed.error.issues[0];
|
|
32
|
+
return {
|
|
33
|
+
ok: false,
|
|
34
|
+
message: `${type} props${issue?.path.length ? `.${issue.path.join(".")}` : ""}: ${issue?.message ?? "invalid"}`
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
definitions: [...byType.values()],
|
|
39
|
+
get: (type) => byType.get(type),
|
|
40
|
+
capabilities: (item) => capabilitiesOf(item.type),
|
|
41
|
+
resizeMode(item) {
|
|
42
|
+
const value = capabilitiesOf(item.type);
|
|
43
|
+
if (!value.canResize) return "none";
|
|
44
|
+
return value.aspectLocked ? "uniform" : "free";
|
|
45
|
+
},
|
|
46
|
+
bounds: (item) => byType.get(item.type)?.bounds?.(item) ?? itemBounds(item.frame),
|
|
47
|
+
hitTest(item, point) {
|
|
48
|
+
const hitTest = byType.get(item.type)?.hitTest;
|
|
49
|
+
return hitTest ? hitTest(item, point) : frameContainsPoint(item.frame, point);
|
|
50
|
+
},
|
|
51
|
+
validateProps,
|
|
52
|
+
create(type, { props = {}, at, size, id = createBoardItemId() }) {
|
|
53
|
+
const valid = validateProps(type, props);
|
|
54
|
+
if (!valid.ok) throw new Error(valid.message);
|
|
55
|
+
const box = size ?? byType.get(type)?.size ?? DEFAULT_ITEM_SIZE;
|
|
56
|
+
const placement = hasAuthoredSize(type) ? {
|
|
57
|
+
position: {
|
|
58
|
+
x: at.x - box.width / 2,
|
|
59
|
+
y: at.y - box.height / 2
|
|
60
|
+
},
|
|
61
|
+
size: { ...box }
|
|
62
|
+
} : { position: {
|
|
63
|
+
x: at.x,
|
|
64
|
+
y: at.y
|
|
65
|
+
} };
|
|
66
|
+
const parsed = parseBoardItem({
|
|
67
|
+
type,
|
|
68
|
+
...placement,
|
|
69
|
+
props
|
|
70
|
+
});
|
|
71
|
+
if (!parsed.ok) {
|
|
72
|
+
const diagnostic = parsed.diagnostics[0];
|
|
73
|
+
throw new Error(`Invalid ${type} item: ${diagnostic?.path}: ${diagnostic?.message}`);
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
id,
|
|
77
|
+
item: parsed.item
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const defaultBoardRegistry = createBoardRegistry();
|
|
83
|
+
//#endregion
|
|
84
|
+
export { createBoardRegistry, defaultBoardRegistry };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { BoardSceneItem } from "./
|
|
2
|
-
//#region src/board/media-playback.d.ts
|
|
1
|
+
import { BoardSceneItem } from "./scene.js";
|
|
2
|
+
//#region src/board/model/media-playback.d.ts
|
|
3
3
|
type BoardAssetSource = {
|
|
4
4
|
resolveFileUrl: (path: string) => Promise<string | null>;
|
|
5
5
|
resolvePlaybackUrl?: (path: string) => Promise<string | null>;
|
|
6
6
|
};
|
|
7
|
+
declare function resolveBoardMediaUrl(src: string, source: BoardAssetSource, purpose?: "preview" | "playback"): Promise<string | null>;
|
|
7
8
|
type BoardPlayableMedia = {
|
|
8
9
|
id: string;
|
|
9
10
|
kind: "video" | "audio";
|
|
@@ -16,4 +17,4 @@ declare function playableBoardMediaList(item: BoardSceneItem | null, assetSource
|
|
|
16
17
|
declare function playableBoardMedia(item: BoardSceneItem | null, assetSource: BoardAssetSource, artifactId?: string | null): BoardPlayableMedia | null;
|
|
17
18
|
declare function resetBoardPlaybackUrlCache(): void;
|
|
18
19
|
//#endregion
|
|
19
|
-
export { BoardAssetSource, BoardPlayableMedia, playableBoardMedia, playableBoardMediaList, resetBoardPlaybackUrlCache };
|
|
20
|
+
export { BoardAssetSource, BoardPlayableMedia, playableBoardMedia, playableBoardMediaList, resetBoardPlaybackUrlCache, resolveBoardMediaUrl };
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
import { parseBoardMediaSource } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import { getMediaResourceTitle } from "./media.js";
|
|
1
3
|
import { rankedTaskArtifacts } from "./task.js";
|
|
2
|
-
//#region src/board/media-playback.ts
|
|
4
|
+
//#region src/board/model/media-playback.ts
|
|
5
|
+
function resolveBoardMediaUrl(src, source, purpose = "preview") {
|
|
6
|
+
const parsed = parseBoardMediaSource(src);
|
|
7
|
+
if (!parsed) return Promise.resolve(null);
|
|
8
|
+
if (parsed.kind === "url") return Promise.resolve(parsed.value);
|
|
9
|
+
return purpose === "playback" && source.resolvePlaybackUrl ? source.resolvePlaybackUrl(parsed.value) : source.resolveFileUrl(parsed.value);
|
|
10
|
+
}
|
|
3
11
|
const resolvedUrls = /* @__PURE__ */ new Map();
|
|
4
12
|
const sourceIds = /* @__PURE__ */ new WeakMap();
|
|
5
13
|
const URL_CACHE_LIMIT = 64;
|
|
@@ -34,15 +42,17 @@ function cachedUrl(key, resolve) {
|
|
|
34
42
|
function playableBoardMediaList(item, assetSource) {
|
|
35
43
|
if (item?.type === "video" || item?.type === "audio") {
|
|
36
44
|
const path = item.props.src;
|
|
45
|
+
const source = parseBoardMediaSource(path);
|
|
46
|
+
if (!source) return [];
|
|
37
47
|
const version = item.props.snapshot?.mtimeMs ?? "unknown";
|
|
38
|
-
const cacheKey = `${sourceId(assetSource)}:${item.type}
|
|
48
|
+
const cacheKey = `${sourceId(assetSource)}:${item.type}:${source.kind}:${path}:${version}`;
|
|
39
49
|
const durationMs = item.type === "audio" ? item.props.snapshot?.durationMs : void 0;
|
|
40
50
|
return [{
|
|
41
51
|
id: item.id,
|
|
42
52
|
kind: item.type,
|
|
43
|
-
title: item.props.snapshot?.title ?? path
|
|
53
|
+
title: item.props.snapshot?.title ?? getMediaResourceTitle(path),
|
|
44
54
|
...durationMs ? { durationMs } : {},
|
|
45
|
-
resolveUrl: () => cachedUrl(cacheKey, () => (assetSource
|
|
55
|
+
resolveUrl: () => cachedUrl(cacheKey, () => resolveBoardMediaUrl(path, assetSource, "playback")),
|
|
46
56
|
invalidateUrl: () => invalidateCachedUrl(cacheKey)
|
|
47
57
|
}];
|
|
48
58
|
}
|
|
@@ -64,4 +74,4 @@ function resetBoardPlaybackUrlCache() {
|
|
|
64
74
|
resolvedUrls.clear();
|
|
65
75
|
}
|
|
66
76
|
//#endregion
|
|
67
|
-
export { playableBoardMedia, playableBoardMediaList, resetBoardPlaybackUrlCache };
|
|
77
|
+
export { playableBoardMedia, playableBoardMediaList, resetBoardPlaybackUrlCache, resolveBoardMediaUrl };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region src/board/media.d.ts
|
|
1
|
+
//#region src/board/model/media.d.ts
|
|
2
2
|
type BoardMediaKind = "image" | "video" | "audio" | "text" | "file";
|
|
3
3
|
declare function getMediaExtension(value: string): string;
|
|
4
4
|
declare function inferBoardMediaKind(value: string, mimeType?: string | null): BoardMediaKind;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//#region src/board/media.ts
|
|
1
|
+
//#region src/board/model/media.ts
|
|
2
2
|
const IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
3
3
|
"png",
|
|
4
4
|
"jpg",
|
|
@@ -59,9 +59,15 @@ function inferBoardMediaKind(value, mimeType) {
|
|
|
59
59
|
return "file";
|
|
60
60
|
}
|
|
61
61
|
function getMediaResourceTitle(value) {
|
|
62
|
+
if (!/^[a-z][a-z\d+.-]*:/i.test(value)) return value.split("/").filter(Boolean).pop() || value;
|
|
62
63
|
try {
|
|
63
64
|
const url = new URL(value);
|
|
64
|
-
|
|
65
|
+
const title = url.pathname.split("/").filter(Boolean).pop() || url.hostname;
|
|
66
|
+
try {
|
|
67
|
+
return decodeURIComponent(title);
|
|
68
|
+
} catch {
|
|
69
|
+
return title;
|
|
70
|
+
}
|
|
65
71
|
} catch {
|
|
66
72
|
return value.split("/").filter(Boolean).pop() || value;
|
|
67
73
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BoardColor, BoardColorToken } from "../../protocol/dist/board-model.js";
|
|
2
2
|
import "../../protocol/dist/index.js";
|
|
3
|
-
//#region src/board/
|
|
3
|
+
//#region src/board/model/palette.d.ts
|
|
4
4
|
type BoardColorId = BoardColorToken;
|
|
5
5
|
type BoardColorValue = {
|
|
6
6
|
stroke: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { BoardTrack } from "
|
|
2
|
-
import "
|
|
3
|
-
//#region src/board/presets.d.ts
|
|
1
|
+
import { BoardTrack } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import "../../protocol/dist/index.js";
|
|
3
|
+
//#region src/board/model/presets.d.ts
|
|
4
4
|
declare const PRESETS: {
|
|
5
5
|
"fade-in": {
|
|
6
6
|
description: string;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BoardDocument } from "
|
|
2
|
-
import { RequestSource } from "
|
|
3
|
-
import { BoardHistoryPage } from "
|
|
4
|
-
import "
|
|
5
|
-
//#region src/board/replay.d.ts
|
|
1
|
+
import { BoardDocument } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import { RequestSource } from "../../protocol/dist/provenance.js";
|
|
3
|
+
import { BoardHistoryPage } from "../../protocol/dist/board.js";
|
|
4
|
+
import "../../protocol/dist/index.js";
|
|
5
|
+
//#region src/board/model/replay.d.ts
|
|
6
6
|
type BoardReplayActorKind = "human" | "cli" | "agent";
|
|
7
7
|
type BoardReplayEntry = {
|
|
8
8
|
version: number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { applyBoardDelta } from "
|
|
2
|
-
//#region src/board/replay.ts
|
|
1
|
+
import { applyBoardDelta } from "../../protocol/dist/board-patch.js";
|
|
2
|
+
//#region src/board/model/replay.ts
|
|
3
3
|
function boardReplayActorKind(source) {
|
|
4
4
|
if (!source) return "human";
|
|
5
5
|
if (source.toolCallId) return "agent";
|
|
@@ -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 };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BoardDocument, BoardItem } from "../../protocol/dist/board-model.js";
|
|
2
2
|
import { BoardFrame, BoardItemLookup, BoardLayout, BoardMatrix, BoardRect } from "../../protocol/dist/board-layout.js";
|
|
3
3
|
import "../../protocol/dist/index.js";
|
|
4
|
-
//#region src/board/
|
|
4
|
+
//#region src/board/model/scene.d.ts
|
|
5
5
|
type SceneItem<T extends BoardItem = BoardItem> = T & {
|
|
6
6
|
readonly id: string;
|
|
7
7
|
readonly frame: BoardFrame;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IDENTITY_MATRIX, applyMatrix, arrowBindings, clampBoardFontSize, createBoardLayout, drawPointsBounds, invertMatrix, layoutBoardText, scaleVector } from "../../protocol/dist/board-layout.js";
|
|
2
|
-
//#region src/board/
|
|
2
|
+
//#region src/board/model/scene.ts
|
|
3
3
|
const EPSILON = 1e-6;
|
|
4
4
|
function stripScene(item) {
|
|
5
5
|
if (!("frame" in item) && !("id" in item)) return item;
|
|
@@ -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,10 @@
|
|
|
1
|
+
import { BoardScriptOutput } from "./script.js";
|
|
2
|
+
import { WorldPoint } from "./geometry.js";
|
|
3
|
+
import { BoardScene, BoardSceneItem } from "./scene.js";
|
|
4
|
+
//#region src/board/model/script-hit.d.ts
|
|
5
|
+
declare function boardScriptTarget(scene: BoardScene, candidates: readonly string[], point: WorldPoint, outputs: ReadonlyMap<string, BoardScriptOutput>, hitTest: (item: BoardSceneItem, point: WorldPoint) => boolean): {
|
|
6
|
+
owner: string;
|
|
7
|
+
target: string;
|
|
8
|
+
} | null;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { boardScriptTarget };
|
|
@@ -0,0 +1,52 @@
|
|
|
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 boardScriptTarget(scene, candidates, point, outputs, hitTest) {
|
|
6
|
+
const owners = new Map([...outputs.keys()].map((id) => [scriptTemporaryPrefix(id), id]));
|
|
7
|
+
for (const id of [...candidates].sort((a, b) => scene.indexOf(b) - scene.indexOf(a))) {
|
|
8
|
+
const item = scene.get(id);
|
|
9
|
+
if (!item || scene.opacity(id) <= 0 || id.endsWith("root") && owners.has(id.slice(0, -4))) continue;
|
|
10
|
+
let parent = item.parent;
|
|
11
|
+
let clipped = false;
|
|
12
|
+
for (let depth = 0; parent && depth < 64; depth++) {
|
|
13
|
+
const ancestor = scene.get(parent);
|
|
14
|
+
if (!ancestor) break;
|
|
15
|
+
if (ancestor.type === "frame" && ancestor.props.clip && !frameContainsPoint(ancestor.frame, point)) {
|
|
16
|
+
clipped = true;
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
parent = ancestor.parent;
|
|
20
|
+
}
|
|
21
|
+
if (clipped) continue;
|
|
22
|
+
const output = outputs.get(id);
|
|
23
|
+
if (output) {
|
|
24
|
+
const local = applyMatrix(invertMatrix(scene.layout.matrix(id)), point);
|
|
25
|
+
for (const [target, region] of Object.entries(output.hits).reverse()) if (local.x >= region.x && local.y >= region.y && local.x <= region.x + region.width && local.y <= region.y + region.height) return {
|
|
26
|
+
owner: id,
|
|
27
|
+
target
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (!hitTest(item, point)) continue;
|
|
31
|
+
let current = item;
|
|
32
|
+
for (let depth = 0; current && depth < 64; depth++) {
|
|
33
|
+
if (outputs.has(current.id)) return {
|
|
34
|
+
owner: current.id,
|
|
35
|
+
target: id
|
|
36
|
+
};
|
|
37
|
+
for (const [prefix, owner] of owners) {
|
|
38
|
+
if (current.id === `${prefix}root`) break;
|
|
39
|
+
if (current.id.startsWith(prefix)) return {
|
|
40
|
+
owner,
|
|
41
|
+
target: current.id.slice(prefix.length)
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
current = current.parent ? scene.get(current.parent) : void 0;
|
|
45
|
+
}
|
|
46
|
+
if (item.type === "frame" && item.props.decoration === "none") continue;
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { boardScriptTarget };
|
|
@@ -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,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): Map<string, BoardItem>;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { boardScriptScope, composeBoardScriptItems, prepareBoardScriptOutput, scriptTemporaryPrefix, validateBoardScriptCommit, validateBoardScriptOutput };
|