@neta-art/cohub 10.0.0 → 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 +11 -2
- 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 +5 -1
- package/dist/board/editor/creation.js +2 -1
- 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 +18 -3
- package/dist/board/editor/editor.js +11 -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/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 +20 -6
- 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 +6 -2
- package/dist/board/model/index.d.ts +13 -6
- package/dist/board/model/index.js +14 -8
- package/dist/board/model/items/builtin.js +2 -2
- package/dist/board/model/items/create.d.ts +4 -2
- package/dist/board/model/items/create.js +6 -5
- 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 +14 -4
- package/dist/board/model/media.js +7 -1
- 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 +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/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 +9 -6
- 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 +10 -5
- package/dist/board/render/renderers/board-renderer-registry.js +3 -3
- 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 +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/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 +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 +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 +6 -1
- package/dist/board/stage/maintenance.d.ts +5 -0
- package/dist/board/stage/maintenance.js +11 -0
- package/dist/board/stage/scene.js +5 -2
- 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 +10 -0
- package/dist/board/stage/stage.js +249 -43
- package/dist/board/stage/texture-pool.js +2 -3
- package/dist/chunks/environment.d.ts +266 -23
- package/dist/chunks/host-bridge.d.ts +2 -2
- package/dist/chunks/http.d.ts +88 -7
- package/dist/chunks/http.js +155 -63
- 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 +1374 -126
- 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 +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/display/index.d.ts +1 -0
- package/dist/protocol/dist/index.d.ts +4 -2
- package/dist/protocol/dist/realtime/types.d.ts +1 -0
- package/dist/protocol/dist/rtc/index.d.ts +1 -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/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
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
|
+
import { itemAlpha, itemColor } from "../palette.js";
|
|
2
3
|
import { syncTextResolution } from "../text-resolution.js";
|
|
3
4
|
import { createLabel, positionShell } from "./base-card-renderer.js";
|
|
4
5
|
import { drawFarPlate } from "./far-plate.js";
|
|
5
|
-
import {
|
|
6
|
+
import { dashPattern, roundRectPoints, tracePolyline, trimPolyline } from "../stroke.js";
|
|
6
7
|
import { Container, Graphics } from "pixi.js";
|
|
7
8
|
//#region src/board/render/renderers/frame-card-renderer.ts
|
|
8
9
|
const partsByContainer = /* @__PURE__ */ new WeakMap();
|
|
@@ -16,13 +17,15 @@ function sync(container, item, context) {
|
|
|
16
17
|
const selected = context.selectedIds.has(item.id);
|
|
17
18
|
const hovered = context.hoveredId === item.id;
|
|
18
19
|
const fill = itemColor(context, style.fill ?? style.stroke, "neutral", "fill");
|
|
19
|
-
const fillAlpha = style.fillOpacity ?? (style.fill ? 1 : DEFAULT_WASH);
|
|
20
|
+
const fillAlpha = (style.fillOpacity ?? (style.fill ? 1 : DEFAULT_WASH)) * itemAlpha(context, style.fill ?? style.stroke);
|
|
20
21
|
const baseStroke = itemColor(context, style.stroke, "neutral");
|
|
21
|
-
const stroke = selected ? context.palette.brand : baseStroke;
|
|
22
|
-
const alpha = selected ? 1 : hovered ? .85 : .55;
|
|
22
|
+
const stroke = selected ? context.palette.brand : hovered && style.stroke ? context.palette.muted : baseStroke;
|
|
23
|
+
const alpha = (selected || style.stroke ? 1 : hovered ? .85 : .55) * itemAlpha(context, style.stroke);
|
|
23
24
|
const radius = style.radius ?? 4;
|
|
24
25
|
const strokeWidth = style.strokeWidth ?? 1.5;
|
|
26
|
+
const decorated = props.decoration !== "none";
|
|
25
27
|
const visualSig = [
|
|
28
|
+
props.decoration,
|
|
26
29
|
frame.width,
|
|
27
30
|
frame.height,
|
|
28
31
|
selected,
|
|
@@ -30,23 +33,36 @@ function sync(container, item, context) {
|
|
|
30
33
|
fill,
|
|
31
34
|
fillAlpha,
|
|
32
35
|
stroke,
|
|
36
|
+
alpha,
|
|
33
37
|
radius,
|
|
34
|
-
strokeWidth
|
|
38
|
+
strokeWidth,
|
|
39
|
+
style.dash,
|
|
40
|
+
style.trim
|
|
35
41
|
].join("|");
|
|
36
42
|
if (visualSig !== parts.visualSig) {
|
|
37
43
|
parts.visualSig = visualSig;
|
|
38
44
|
parts.box.clear();
|
|
39
|
-
parts.box.roundRect(0, 0, frame.width, frame.height, radius).fill({
|
|
45
|
+
if (decorated) parts.box.roundRect(0, 0, frame.width, frame.height, radius).fill({
|
|
40
46
|
color: fill,
|
|
41
47
|
alpha: fillAlpha
|
|
42
48
|
});
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
const width = selected ? Math.max(2, strokeWidth) : strokeWidth;
|
|
50
|
+
const pattern = decorated ? dashPattern(style.dash, width) : null;
|
|
51
|
+
const trim = decorated ? style.trim ?? 1 : 1;
|
|
52
|
+
if ((decorated && strokeWidth > 0 || selected || hovered) && trim > 0) {
|
|
53
|
+
if (pattern || trim < 1) tracePolyline(parts.box, trimPolyline(roundRectPoints(frame.width, frame.height, radius), trim), pattern);
|
|
54
|
+
else parts.box.roundRect(0, 0, frame.width, frame.height, radius);
|
|
55
|
+
parts.box.stroke({
|
|
56
|
+
color: stroke,
|
|
57
|
+
width,
|
|
58
|
+
alpha,
|
|
59
|
+
cap: pattern || trim < 1 ? "round" : "butt",
|
|
60
|
+
join: "round"
|
|
61
|
+
});
|
|
62
|
+
}
|
|
48
63
|
}
|
|
49
|
-
|
|
64
|
+
parts.label.visible = decorated;
|
|
65
|
+
const title = locked ? `🔒 ${props.label}`.trim() : props.label;
|
|
50
66
|
const labelColor = style.stroke ? baseStroke : context.palette.muted;
|
|
51
67
|
const textSig = [title, labelColor].join("|");
|
|
52
68
|
if (textSig !== parts.textSig) {
|
|
@@ -84,10 +100,10 @@ const frameCardRenderer = {
|
|
|
84
100
|
if (item.type === "frame") sync(container, item, context);
|
|
85
101
|
},
|
|
86
102
|
renderFar: (graphics, item, context) => {
|
|
87
|
-
if (item.type !== "frame") return;
|
|
103
|
+
if (item.type !== "frame" || item.props.decoration === "none") return;
|
|
88
104
|
drawFarPlate(graphics, item.frame, {
|
|
89
105
|
fill: itemColor(context, item.style.fill ?? item.style.stroke, "neutral", "fill"),
|
|
90
|
-
fillAlpha: Math.max(.07, item.style.fillOpacity ?? (item.style.fill ? 1 : 0))
|
|
106
|
+
fillAlpha: Math.max(.07, item.style.fillOpacity ?? (item.style.fill ? 1 : 0)) * itemAlpha(context, item.style.fill ?? item.style.stroke)
|
|
91
107
|
});
|
|
92
108
|
},
|
|
93
109
|
destroy: (container) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { positionShell } from "./base-card-renderer.js";
|
|
2
2
|
import { drawFarPlate } from "./far-plate.js";
|
|
3
|
-
import { Container, Graphics, Sprite, Texture } from "pixi.js";
|
|
3
|
+
import { Container, Graphics, Rectangle, Sprite, Texture } from "pixi.js";
|
|
4
4
|
//#region src/board/render/renderers/image-card-renderer.ts
|
|
5
5
|
const partsByContainer = /* @__PURE__ */ new WeakMap();
|
|
6
6
|
const RADIUS = 2;
|
|
@@ -15,6 +15,39 @@ function layoutContain(sprite, width, height) {
|
|
|
15
15
|
sprite.x = (width - sprite.width) / 2;
|
|
16
16
|
sprite.y = (height - sprite.height) / 2;
|
|
17
17
|
}
|
|
18
|
+
function cropRect(crop) {
|
|
19
|
+
if (!crop) return null;
|
|
20
|
+
const w = Math.min(crop.w, 1 - crop.x);
|
|
21
|
+
const h = Math.min(crop.h, 1 - crop.y);
|
|
22
|
+
return w > 0 && h > 0 ? {
|
|
23
|
+
x: crop.x,
|
|
24
|
+
y: crop.y,
|
|
25
|
+
w,
|
|
26
|
+
h
|
|
27
|
+
} : null;
|
|
28
|
+
}
|
|
29
|
+
function showTexture(parts, texture, crop) {
|
|
30
|
+
const rect = texture ? cropRect(crop) : null;
|
|
31
|
+
const key = rect ? `${rect.x}|${rect.y}|${rect.w}|${rect.h}` : "";
|
|
32
|
+
const previous = parts.cropped;
|
|
33
|
+
const reusable = previous && parts.cropSource === texture && parts.cropKey === key;
|
|
34
|
+
if (texture && rect && !reusable) {
|
|
35
|
+
const { frame } = texture;
|
|
36
|
+
const width = Math.max(1, frame.width * rect.w);
|
|
37
|
+
const height = Math.max(1, frame.height * rect.h);
|
|
38
|
+
const x = frame.x + Math.min(frame.width * rect.x, frame.width - width);
|
|
39
|
+
const y = frame.y + Math.min(frame.height * rect.y, frame.height - height);
|
|
40
|
+
parts.cropped = new Texture({
|
|
41
|
+
source: texture.source,
|
|
42
|
+
frame: new Rectangle(x, y, width, height)
|
|
43
|
+
});
|
|
44
|
+
} else if (!rect) parts.cropped = null;
|
|
45
|
+
parts.cropSource = rect ? texture : null;
|
|
46
|
+
parts.cropKey = key;
|
|
47
|
+
const display = parts.cropped ?? texture ?? Texture.EMPTY;
|
|
48
|
+
if (parts.sprite.texture !== display) parts.sprite.texture = display;
|
|
49
|
+
if (previous && previous !== parts.cropped) previous.destroy(false);
|
|
50
|
+
}
|
|
18
51
|
function sync(container, item, context) {
|
|
19
52
|
const parts = partsByContainer.get(container);
|
|
20
53
|
if (!parts) return;
|
|
@@ -33,12 +66,13 @@ function sync(container, item, context) {
|
|
|
33
66
|
selected,
|
|
34
67
|
hovered,
|
|
35
68
|
texId,
|
|
69
|
+
JSON.stringify(item.props.crop ?? null),
|
|
36
70
|
failed,
|
|
37
71
|
context.colorScheme
|
|
38
72
|
].join("|");
|
|
39
73
|
if (sig === parts.sig) return;
|
|
40
74
|
parts.sig = sig;
|
|
41
|
-
|
|
75
|
+
showTexture(parts, texture, item.props.crop);
|
|
42
76
|
parts.sprite.visible = Boolean(texture);
|
|
43
77
|
if (texture) layoutContain(parts.sprite, width, height);
|
|
44
78
|
parts.placeholder.clear();
|
|
@@ -98,7 +132,10 @@ const imageCardRenderer = {
|
|
|
98
132
|
root,
|
|
99
133
|
sprite,
|
|
100
134
|
placeholder,
|
|
101
|
-
sig: ""
|
|
135
|
+
sig: "",
|
|
136
|
+
cropped: null,
|
|
137
|
+
cropSource: null,
|
|
138
|
+
cropKey: ""
|
|
102
139
|
});
|
|
103
140
|
if (item.type === "image") sync(root, item, context);
|
|
104
141
|
return root;
|
|
@@ -118,7 +155,9 @@ const imageCardRenderer = {
|
|
|
118
155
|
});
|
|
119
156
|
},
|
|
120
157
|
destroy: (container) => {
|
|
121
|
-
partsByContainer.get(container)
|
|
158
|
+
const parts = partsByContainer.get(container);
|
|
159
|
+
parts?.root.destroy({ children: true });
|
|
160
|
+
parts?.cropped?.destroy(false);
|
|
122
161
|
partsByContainer.delete(container);
|
|
123
162
|
}
|
|
124
163
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
2
|
import { worldPoint } from "../../model/geometry.js";
|
|
3
|
+
import { itemAlpha, itemColor } from "../palette.js";
|
|
3
4
|
import { syncTextResolution, syncTextWrapWidth, textResolutionForZoom } from "../text-resolution.js";
|
|
4
5
|
import { positionShell } from "./base-card-renderer.js";
|
|
5
6
|
import { drawFarPlate } from "./far-plate.js";
|
|
6
|
-
import {
|
|
7
|
-
import { dashPattern, tracePolyline, trimPolyline } from "../stroke.js";
|
|
7
|
+
import { dashPattern, roundRectPoints, tracePolyline, trimPolyline } from "../stroke.js";
|
|
8
8
|
import { Container, Graphics, GraphicsPath, Matrix, Text } from "pixi.js";
|
|
9
9
|
//#region src/board/render/renderers/shape-card-renderer.ts
|
|
10
10
|
const DEFAULT_ROUNDED_RADIUS = 8;
|
|
@@ -86,27 +86,7 @@ function outlinePoints(geometry, width, height, radius) {
|
|
|
86
86
|
p(0, height),
|
|
87
87
|
p(width / 2, 0)
|
|
88
88
|
];
|
|
89
|
-
default:
|
|
90
|
-
const r = Math.min(radius, width / 2, height / 2);
|
|
91
|
-
if (r <= 0) return [
|
|
92
|
-
p(0, 0),
|
|
93
|
-
p(width, 0),
|
|
94
|
-
p(width, height),
|
|
95
|
-
p(0, height),
|
|
96
|
-
p(0, 0)
|
|
97
|
-
];
|
|
98
|
-
const corner = (cx, cy, from) => Array.from({ length: 9 }, (_, index) => {
|
|
99
|
-
const angle = from + index / 8 * (Math.PI / 2);
|
|
100
|
-
return p(cx + Math.cos(angle) * r, cy + Math.sin(angle) * r);
|
|
101
|
-
});
|
|
102
|
-
return [
|
|
103
|
-
...corner(width - r, r, -Math.PI / 2),
|
|
104
|
-
...corner(width - r, height - r, 0),
|
|
105
|
-
...corner(r, height - r, Math.PI / 2),
|
|
106
|
-
...corner(r, r, Math.PI),
|
|
107
|
-
p(width - r, 0)
|
|
108
|
-
];
|
|
109
|
-
}
|
|
89
|
+
default: return roundRectPoints(width, height, radius);
|
|
110
90
|
}
|
|
111
91
|
}
|
|
112
92
|
function sync(container, item, context) {
|
|
@@ -119,7 +99,8 @@ function sync(container, item, context) {
|
|
|
119
99
|
const hovered = context.hoveredId === item.id;
|
|
120
100
|
const stroke = itemColor(context, style.stroke ?? style.fill, "brand");
|
|
121
101
|
const fill = itemColor(context, style.fill ?? style.stroke, "brand", "fill");
|
|
122
|
-
const fillOpacity = style.fillOpacity ?? (style.fill ? 1 : 0);
|
|
102
|
+
const fillOpacity = (style.fillOpacity ?? (style.fill ? 1 : 0)) * itemAlpha(context, style.fill ?? style.stroke);
|
|
103
|
+
const strokeAlpha = itemAlpha(context, style.stroke ?? style.fill);
|
|
123
104
|
const strokeWidth = style.strokeWidth ?? 1.75;
|
|
124
105
|
syncTextResolution(parts.label, parts, context.zoom);
|
|
125
106
|
const visualSig = [
|
|
@@ -132,6 +113,7 @@ function sync(container, item, context) {
|
|
|
132
113
|
fill,
|
|
133
114
|
fillOpacity,
|
|
134
115
|
stroke,
|
|
116
|
+
strokeAlpha,
|
|
135
117
|
strokeWidth,
|
|
136
118
|
style.dash,
|
|
137
119
|
style.radius,
|
|
@@ -159,12 +141,13 @@ function sync(container, item, context) {
|
|
|
159
141
|
parts.shape.stroke({
|
|
160
142
|
color: hovered && !selected ? context.palette.muted : stroke,
|
|
161
143
|
width: lineWidth,
|
|
162
|
-
alpha: selected ? 1 : hovered ? .95 : .85,
|
|
144
|
+
alpha: (selected ? 1 : hovered ? .95 : .85) * strokeAlpha,
|
|
163
145
|
cap: partial || pattern ? "round" : "butt",
|
|
164
146
|
join: "round"
|
|
165
147
|
});
|
|
166
148
|
}
|
|
167
149
|
}
|
|
150
|
+
parts.label.alpha = itemAlpha(context, style.stroke);
|
|
168
151
|
const label = itemColor(context, style.stroke, "neutral", "label");
|
|
169
152
|
const textSig = [
|
|
170
153
|
props.text,
|
|
@@ -226,9 +209,9 @@ const shapeCardRenderer = {
|
|
|
226
209
|
if (item.type !== "shape") return;
|
|
227
210
|
drawFarPlate(graphics, item.frame, {
|
|
228
211
|
fill: itemColor(context, item.style.fill ?? item.style.stroke, "brand", "fill"),
|
|
229
|
-
fillAlpha: Math.max(.18, item.style.fillOpacity ?? 0),
|
|
212
|
+
fillAlpha: Math.max(.18, item.style.fillOpacity ?? 0) * itemAlpha(context, item.style.fill ?? item.style.stroke),
|
|
230
213
|
accent: itemColor(context, item.style.stroke, "brand"),
|
|
231
|
-
accentAlpha: .9
|
|
214
|
+
accentAlpha: .9 * itemAlpha(context, item.style.stroke)
|
|
232
215
|
});
|
|
233
216
|
},
|
|
234
217
|
destroy: (container) => {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { layoutBoardText } from "../../../protocol/dist/board-layout.js";
|
|
2
2
|
import { boardFontFamily } from "../../model/text-metrics.js";
|
|
3
|
+
import { itemAlpha, itemColor } from "../palette.js";
|
|
4
|
+
import { BOARD_FONT_STACKS } from "../text-measurement.js";
|
|
3
5
|
import { syncTextResolution, textResolutionForZoom } from "../text-resolution.js";
|
|
4
6
|
import { positionShell } from "./base-card-renderer.js";
|
|
5
7
|
import { drawFarPlate } from "./far-plate.js";
|
|
6
|
-
import { itemColor } from "../palette.js";
|
|
7
|
-
import { BOARD_FONT_STACKS } from "../text-measurement.js";
|
|
8
8
|
import { Container, Graphics, Text } from "pixi.js";
|
|
9
9
|
//#region src/board/render/renderers/text-card-renderer.ts
|
|
10
10
|
const partsByContainer = /* @__PURE__ */ new WeakMap();
|
|
@@ -33,6 +33,8 @@ function sync(container, item, context) {
|
|
|
33
33
|
parts.body.anchor.set(anchorX, 0);
|
|
34
34
|
parts.body.position.set(item.frame.width * anchorX, 0);
|
|
35
35
|
syncTextResolution(parts.body, parts, context.zoom * Math.max(1, previewScale));
|
|
36
|
+
parts.body.alpha = itemAlpha(context, item.style.fill);
|
|
37
|
+
parts.caret.alpha = parts.body.alpha;
|
|
36
38
|
const ink = itemColor(context, item.style.fill, "neutral");
|
|
37
39
|
const text = revealed(props.text, props.reveal);
|
|
38
40
|
const contentSig = [
|
|
@@ -93,7 +95,7 @@ const textCardRenderer = {
|
|
|
93
95
|
if (item.type !== "text") return;
|
|
94
96
|
drawFarPlate(graphics, item.frame, {
|
|
95
97
|
fill: itemColor(context, item.style.fill, "neutral"),
|
|
96
|
-
fillAlpha: .35
|
|
98
|
+
fillAlpha: .35 * itemAlpha(context, item.style.fill)
|
|
97
99
|
});
|
|
98
100
|
},
|
|
99
101
|
destroy: (container) => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
|
+
import { getMediaResourceTitle } from "../../model/media.js";
|
|
2
3
|
import { syncTextResolution, syncTextWrapWidth, textResolutionForZoom } from "../text-resolution.js";
|
|
3
4
|
import { positionShell } from "./base-card-renderer.js";
|
|
4
5
|
import { drawFarPlate } from "./far-plate.js";
|
|
@@ -23,7 +24,7 @@ function sync(container, item, context) {
|
|
|
23
24
|
const selected = context.selectedIds.has(item.id);
|
|
24
25
|
const hovered = context.hoveredId === item.id;
|
|
25
26
|
const resizing = context.resizingIds.has(item.id);
|
|
26
|
-
const title = item.props.snapshot?.title ?? item.props.src
|
|
27
|
+
const title = item.props.snapshot?.title ?? getMediaResourceTitle(item.props.src);
|
|
27
28
|
const key = context.assetKey(item);
|
|
28
29
|
const texture = key ? context.getTexture(key) : null;
|
|
29
30
|
const failed = Boolean(key && !texture && context.hasError(key));
|
|
@@ -0,0 +1,22 @@
|
|
|
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 { BoardScene } from "../model/scene.js";
|
|
5
|
+
import { BoardEvaluation } from "../model/animation.js";
|
|
6
|
+
import { BoardShapeColors } from "../model/palette.js";
|
|
7
|
+
import { BoardRenderPalette } from "./renderers/board-renderer-registry.js";
|
|
8
|
+
//#region src/board/render/sampling.d.ts
|
|
9
|
+
declare function createBoardRenderSampler(document: BoardDocument, animation: string | null, options?: {
|
|
10
|
+
colorScheme?: "dark" | "light";
|
|
11
|
+
colors?: BoardShapeColors;
|
|
12
|
+
palette?: Partial<BoardRenderPalette>;
|
|
13
|
+
}): {
|
|
14
|
+
frameAt(id: string, time: number): BoardFrame | undefined;
|
|
15
|
+
at(time: number): {
|
|
16
|
+
document: BoardDocument;
|
|
17
|
+
evaluation: BoardEvaluation;
|
|
18
|
+
scene: BoardScene;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { createBoardRenderSampler };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createBoardAnimationSampler } from "../model/sampling.js";
|
|
2
|
+
import { buildFallbackShapeColors } from "../model/palette.js";
|
|
3
|
+
import { defaultBoardPalette, itemAlpha, itemColor } from "./palette.js";
|
|
4
|
+
//#region src/board/render/sampling.ts
|
|
5
|
+
function createBoardRenderSampler(document, animation, options = {}) {
|
|
6
|
+
const colorScheme = options.colorScheme ?? "dark";
|
|
7
|
+
const context = {
|
|
8
|
+
colorScheme,
|
|
9
|
+
colors: options.colors ?? buildFallbackShapeColors(colorScheme),
|
|
10
|
+
palette: {
|
|
11
|
+
...defaultBoardPalette(colorScheme),
|
|
12
|
+
...options.palette
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
return createBoardAnimationSampler(document, animation, { resolveColor: (color) => ({
|
|
16
|
+
color: itemColor(context, color, "brand", "fill"),
|
|
17
|
+
alpha: itemAlpha(context, color)
|
|
18
|
+
}) });
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { createBoardRenderSampler };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BoardDocument } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import "../../protocol/dist/index.js";
|
|
3
|
+
import { BoardScriptSnapshot } from "../model/script.js";
|
|
4
|
+
import { BoardScriptHost } from "./renderers/board-renderer-registry.js";
|
|
5
|
+
//#region src/board/render/script-export.d.ts
|
|
6
|
+
declare function prepareBrowserBoardScripts(document: BoardDocument, time: number, readModule: (path: string) => Promise<string>, snapshots?: Readonly<Record<string, BoardScriptSnapshot>>): Promise<{
|
|
7
|
+
host: BoardScriptHost;
|
|
8
|
+
dispose(): void;
|
|
9
|
+
}>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { prepareBrowserBoardScripts };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { composeBoardScriptItems } from "../model/script-scene.js";
|
|
2
|
+
import { buildBoardScene } from "../model/scene.js";
|
|
3
|
+
import { createBoardScriptHost } from "./script-host.js";
|
|
4
|
+
//#region src/board/render/script-export.ts
|
|
5
|
+
async function prepareBrowserBoardScripts(document, time, readModule, snapshots) {
|
|
6
|
+
if (!Number.isFinite(time) || time < 0 || time > 6e5) throw new Error("Script export time must be between 0 and 600000 ms.");
|
|
7
|
+
const element = globalThis.document.createElement("div");
|
|
8
|
+
element.style.cssText = "position:fixed;left:-10000px;top:0;width:1px;height:1px;visibility:hidden;pointer-events:none";
|
|
9
|
+
globalThis.document.body.appendChild(element);
|
|
10
|
+
const outputs = /* @__PURE__ */ new Map();
|
|
11
|
+
const scene = buildBoardScene(document);
|
|
12
|
+
const ids = Object.entries(document.items).filter(([, item]) => item.script?.enabled).map(([id]) => id);
|
|
13
|
+
let schedule = () => {};
|
|
14
|
+
const host = createBoardScriptHost({
|
|
15
|
+
host: element,
|
|
16
|
+
readModule,
|
|
17
|
+
export: true,
|
|
18
|
+
snapshots,
|
|
19
|
+
timeoutMs: 15e3,
|
|
20
|
+
onFrame: () => schedule(),
|
|
21
|
+
onOutput(id, output) {
|
|
22
|
+
if (output) outputs.set(id, output);
|
|
23
|
+
else outputs.delete(id);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
const dispose = () => {
|
|
27
|
+
schedule = () => {};
|
|
28
|
+
host.destroy();
|
|
29
|
+
element.remove();
|
|
30
|
+
};
|
|
31
|
+
try {
|
|
32
|
+
await new Promise((resolve, reject) => {
|
|
33
|
+
const timer = setTimeout(() => reject(/* @__PURE__ */ new Error("Script export preparation timed out.")), 2e4);
|
|
34
|
+
let queued = false;
|
|
35
|
+
const sync = () => {
|
|
36
|
+
queued = false;
|
|
37
|
+
try {
|
|
38
|
+
host.sync(document, scene, {
|
|
39
|
+
x: 0,
|
|
40
|
+
y: 0,
|
|
41
|
+
zoom: 1
|
|
42
|
+
}, time, false);
|
|
43
|
+
for (const id of ids) {
|
|
44
|
+
const error = host.error(id);
|
|
45
|
+
if (error) throw new Error(error);
|
|
46
|
+
}
|
|
47
|
+
if (ids.every((id) => host.ready?.(id))) {
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
schedule = () => {};
|
|
50
|
+
resolve();
|
|
51
|
+
}
|
|
52
|
+
} catch (error) {
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
schedule = () => {};
|
|
55
|
+
reject(error);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
schedule = () => {
|
|
59
|
+
if (!queued) {
|
|
60
|
+
queued = true;
|
|
61
|
+
queueMicrotask(sync);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
schedule();
|
|
65
|
+
});
|
|
66
|
+
return {
|
|
67
|
+
host: {
|
|
68
|
+
...host,
|
|
69
|
+
document(input) {
|
|
70
|
+
const items = { ...input.items };
|
|
71
|
+
for (const [id, item] of composeBoardScriptItems(input, buildBoardScene(input), outputs)) items[id] = item;
|
|
72
|
+
return {
|
|
73
|
+
...input,
|
|
74
|
+
items
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
dispose
|
|
79
|
+
};
|
|
80
|
+
} catch (error) {
|
|
81
|
+
dispose();
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { prepareBrowserBoardScripts };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BoardDocument } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import "../../protocol/dist/index.js";
|
|
3
|
+
import { BoardScriptEvent, BoardScriptOutput, BoardScriptSnapshot } from "../model/script.js";
|
|
4
|
+
import { BoardViewport } from "../model/geometry.js";
|
|
5
|
+
import { BoardScene } from "../model/scene.js";
|
|
6
|
+
import { BoardScriptHost } from "./renderers/board-renderer-registry.js";
|
|
7
|
+
//#region src/board/render/script-host.d.ts
|
|
8
|
+
type BoardScriptHostOptions = {
|
|
9
|
+
readModule(path: string): Promise<string>;
|
|
10
|
+
host: HTMLElement;
|
|
11
|
+
onFrame(): void;
|
|
12
|
+
onOutput(id: string, output: BoardScriptOutput | null): void;
|
|
13
|
+
capabilities?: Record<string, (id: string, input: unknown) => Promise<unknown>>;
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
export?: boolean;
|
|
16
|
+
snapshots?: Readonly<Record<string, BoardScriptSnapshot>>;
|
|
17
|
+
};
|
|
18
|
+
type BrowserBoardScriptHost = BoardScriptHost & {
|
|
19
|
+
sync(document: BoardDocument, scene: BoardScene, camera: BoardViewport, time: number, interactive: boolean, visibleIds?: ReadonlySet<string> | null): void;
|
|
20
|
+
event(id: string, event: BoardScriptEvent): void;
|
|
21
|
+
output(id: string): BoardScriptOutput | null;
|
|
22
|
+
snapshot(id: string): Promise<BoardScriptSnapshot | null>;
|
|
23
|
+
restore(id: string, snapshot: BoardScriptSnapshot): void;
|
|
24
|
+
fault(id: string, message: string): void;
|
|
25
|
+
readonly animated: boolean;
|
|
26
|
+
invalidate(src?: string): void;
|
|
27
|
+
destroy(): void;
|
|
28
|
+
};
|
|
29
|
+
declare function createBoardScriptHost(options: BoardScriptHostOptions): BrowserBoardScriptHost;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { BoardScriptHostOptions, BrowserBoardScriptHost, createBoardScriptHost };
|