@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
|
@@ -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,6 +1,7 @@
|
|
|
1
1
|
import { BoardCardRenderer } from "./board-renderer-registry.js";
|
|
2
2
|
//#region src/board/render/renderers/task-card-renderer.d.ts
|
|
3
3
|
declare const TASK_CARD_FULL_DETAIL_ZOOM = 0.55;
|
|
4
|
+
declare function formatTaskElapsed(ms: number): string;
|
|
4
5
|
declare function containTaskPreviewRect(width: number, height: number, imageWidth: number, imageHeight: number): {
|
|
5
6
|
x: number;
|
|
6
7
|
y: number;
|
|
@@ -9,4 +10,4 @@ declare function containTaskPreviewRect(width: number, height: number, imageWidt
|
|
|
9
10
|
};
|
|
10
11
|
declare const taskCardRenderer: BoardCardRenderer;
|
|
11
12
|
//#endregion
|
|
12
|
-
export { TASK_CARD_FULL_DETAIL_ZOOM, containTaskPreviewRect, taskCardRenderer };
|
|
13
|
+
export { TASK_CARD_FULL_DETAIL_ZOOM, containTaskPreviewRect, formatTaskElapsed, taskCardRenderer };
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { BOARD_FONT_STACK, BOARD_MONO_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
|
-
import { featuredTaskArtifact } from "
|
|
2
|
+
import { featuredTaskArtifact } from "../../../protocol/dist/board-task.js";
|
|
3
3
|
import { drawAudioWaveform } from "../audio-waveform.js";
|
|
4
4
|
import { syncTextResolution, textResolutionForZoom } from "../text-resolution.js";
|
|
5
5
|
import { positionShell } from "./base-card-renderer.js";
|
|
6
6
|
import { drawFarPlate } from "./far-plate.js";
|
|
7
7
|
import { fitTextToLines } from "./file-card-renderer.js";
|
|
8
|
-
import { Container, Graphics, Sprite, Text } from "pixi.js";
|
|
8
|
+
import { Container, FillGradient, Graphics, Sprite, Text } from "pixi.js";
|
|
9
9
|
//#region src/board/render/renderers/task-card-renderer.ts
|
|
10
10
|
const RADIUS = 4;
|
|
11
11
|
const PADDING = 12;
|
|
12
12
|
const META_HEIGHT = 28;
|
|
13
13
|
const TASK_CARD_FULL_DETAIL_ZOOM = .55;
|
|
14
14
|
const PLAY_BADGE_RADIUS = 15;
|
|
15
|
+
const SHIMMER_PERIOD_MS = 1600;
|
|
16
|
+
const SHIMMER_FRAME_MS = 33;
|
|
17
|
+
const REVEAL_MS = 180;
|
|
18
|
+
const SECOND = 1e3;
|
|
15
19
|
const partsByContainer = /* @__PURE__ */ new WeakMap();
|
|
16
20
|
function previewKindFor(artifact) {
|
|
17
21
|
if (!artifact) return "empty";
|
|
@@ -19,36 +23,51 @@ function previewKindFor(artifact) {
|
|
|
19
23
|
if (artifact.type === "audio") return artifact.previewUrl ? "texture" : "waveform";
|
|
20
24
|
return artifact.textExcerpt ? "text" : "empty";
|
|
21
25
|
}
|
|
22
|
-
function
|
|
26
|
+
function liveStatus(item, context) {
|
|
27
|
+
const { snapshot } = item.props;
|
|
28
|
+
const live = snapshot.status === "completed" ? null : context.taskRun(item.props.taskRunId);
|
|
29
|
+
const liveStart = Date.parse(live?.startedAt ?? "");
|
|
30
|
+
const working = live?.status === "pending" || live?.status === "running";
|
|
31
|
+
const adopt = snapshot.status === "failed" ? working && liveStart > Date.parse(snapshot.updatedAt ?? "") : live?.status === "running" || live?.status === "pending" && snapshot.status === "pending";
|
|
32
|
+
const status = adopt && live ? live.status : snapshot.status;
|
|
33
|
+
const started = adopt ? liveStart : Date.parse(snapshot.startedAt ?? "");
|
|
34
|
+
return {
|
|
35
|
+
status,
|
|
36
|
+
startedAt: Number.isFinite(started) ? started : null
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function stateSurfaceFor(status, kind, hasTexture, previewFailed) {
|
|
23
40
|
if (kind === "texture" && !hasTexture) {
|
|
24
|
-
if (
|
|
41
|
+
if (status === "failed") return "failed";
|
|
25
42
|
return previewFailed ? "unavailable" : "media-loading";
|
|
26
43
|
}
|
|
27
44
|
if (kind !== "empty") return null;
|
|
28
|
-
if (
|
|
29
|
-
if (
|
|
30
|
-
if (
|
|
45
|
+
if (status === "failed") return "failed";
|
|
46
|
+
if (status === "running") return "generating";
|
|
47
|
+
if (status === "pending") return "queued";
|
|
31
48
|
return "empty";
|
|
32
49
|
}
|
|
33
|
-
function stateLabel(surface) {
|
|
50
|
+
function stateLabel(surface, context) {
|
|
34
51
|
switch (surface) {
|
|
35
|
-
case "generating": return
|
|
36
|
-
case "queued": return
|
|
37
|
-
case "failed": return
|
|
38
|
-
case "unavailable": return
|
|
39
|
-
case "empty": return
|
|
52
|
+
case "generating": return context.labels.generating;
|
|
53
|
+
case "queued": return context.labels.queued;
|
|
54
|
+
case "failed": return context.labels.failed;
|
|
55
|
+
case "unavailable": return context.labels.previewUnavailable;
|
|
56
|
+
case "empty": return context.labels.noPreview;
|
|
40
57
|
default: return "";
|
|
41
58
|
}
|
|
42
59
|
}
|
|
43
|
-
function statusColor(
|
|
44
|
-
if (
|
|
45
|
-
if (
|
|
60
|
+
function statusColor(status, context) {
|
|
61
|
+
if (status === "failed") return context.colors.rose.stroke;
|
|
62
|
+
if (status === "running") return context.colors.brand.stroke;
|
|
46
63
|
return context.colors.neutral.stroke;
|
|
47
64
|
}
|
|
48
|
-
function
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
65
|
+
function formatTaskElapsed(ms) {
|
|
66
|
+
const total = Math.max(0, Math.floor(ms / SECOND));
|
|
67
|
+
const hours = Math.floor(total / 3600);
|
|
68
|
+
const minutes = Math.floor(total % 3600 / 60);
|
|
69
|
+
const seconds = String(total % 60).padStart(2, "0");
|
|
70
|
+
return hours > 0 ? `${hours}:${String(minutes).padStart(2, "0")}:${seconds}` : `${minutes}:${seconds}`;
|
|
52
71
|
}
|
|
53
72
|
function containTaskPreviewRect(width, height, imageWidth, imageHeight) {
|
|
54
73
|
if (width <= 0 || height <= 0 || imageWidth <= 0 || imageHeight <= 0) return {
|
|
@@ -150,15 +169,83 @@ function drawFailedBadge(graphics, width, color, context) {
|
|
|
150
169
|
cap: "round"
|
|
151
170
|
});
|
|
152
171
|
}
|
|
172
|
+
const shimmerGradients = /* @__PURE__ */ new Map();
|
|
173
|
+
function shimmerGradient(color) {
|
|
174
|
+
let gradient = shimmerGradients.get(color);
|
|
175
|
+
if (!gradient) {
|
|
176
|
+
const rgb = `${color >> 16 & 255}, ${color >> 8 & 255}, ${color & 255}`;
|
|
177
|
+
gradient = new FillGradient({
|
|
178
|
+
type: "linear",
|
|
179
|
+
start: {
|
|
180
|
+
x: 0,
|
|
181
|
+
y: 0
|
|
182
|
+
},
|
|
183
|
+
end: {
|
|
184
|
+
x: 1,
|
|
185
|
+
y: 0
|
|
186
|
+
},
|
|
187
|
+
textureSpace: "local",
|
|
188
|
+
colorStops: [
|
|
189
|
+
{
|
|
190
|
+
offset: 0,
|
|
191
|
+
color: `rgba(${rgb}, 0)`
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
offset: .5,
|
|
195
|
+
color: `rgba(${rgb}, 0.07)`
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
offset: 1,
|
|
199
|
+
color: `rgba(${rgb}, 0)`
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
});
|
|
203
|
+
shimmerGradients.set(color, gradient);
|
|
204
|
+
}
|
|
205
|
+
return gradient;
|
|
206
|
+
}
|
|
207
|
+
function drawShimmerBand(graphics, width, height, color) {
|
|
208
|
+
const band = Math.max(48, width * .45);
|
|
209
|
+
graphics.clear().rect(-band, 0, band, height).fill(shimmerGradient(color));
|
|
210
|
+
}
|
|
211
|
+
function advance(parts, clock) {
|
|
212
|
+
const { motion } = parts;
|
|
213
|
+
let next = null;
|
|
214
|
+
if (motion.shimmer) {
|
|
215
|
+
const travel = motion.width + parts.shimmer.width;
|
|
216
|
+
parts.shimmer.x = clock % SHIMMER_PERIOD_MS / SHIMMER_PERIOD_MS * travel;
|
|
217
|
+
next = SHIMMER_FRAME_MS;
|
|
218
|
+
}
|
|
219
|
+
if (motion.startedAt !== null) {
|
|
220
|
+
const elapsedMs = Date.now() - motion.startedAt;
|
|
221
|
+
const elapsed = formatTaskElapsed(elapsedMs);
|
|
222
|
+
if (elapsed !== motion.elapsed) {
|
|
223
|
+
motion.elapsed = elapsed;
|
|
224
|
+
parts.body.text = `${motion.label} · ${elapsed}`;
|
|
225
|
+
}
|
|
226
|
+
const untilNextSecond = SECOND - Math.max(0, elapsedMs) % SECOND;
|
|
227
|
+
next = next === null ? untilNextSecond : Math.min(next, untilNextSecond);
|
|
228
|
+
}
|
|
229
|
+
if (motion.revealFrom !== null) {
|
|
230
|
+
const progress = Math.min(1, (clock - motion.revealFrom) / REVEAL_MS);
|
|
231
|
+
parts.preview.alpha = progress * (2 - progress);
|
|
232
|
+
if (progress >= 1) motion.revealFrom = null;
|
|
233
|
+
else next = 0;
|
|
234
|
+
}
|
|
235
|
+
return next;
|
|
236
|
+
}
|
|
153
237
|
function sync(container, item, context) {
|
|
154
238
|
const parts = partsByContainer.get(container);
|
|
155
239
|
if (!parts) return;
|
|
156
240
|
positionShell(parts.root, item);
|
|
157
241
|
const { width, height } = item.frame;
|
|
242
|
+
const { snapshot } = item.props;
|
|
243
|
+
const { status, startedAt } = liveStatus(item, context);
|
|
158
244
|
const selected = context.selectedIds.has(item.id);
|
|
159
245
|
const hovered = context.hoveredId === item.id;
|
|
160
246
|
const full = context.zoom >= TASK_CARD_FULL_DETAIL_ZOOM;
|
|
161
|
-
const
|
|
247
|
+
const working = status === "pending" || status === "running";
|
|
248
|
+
const color = statusColor(status, context);
|
|
162
249
|
const key = context.assetKey(item);
|
|
163
250
|
if (key !== parts.assetKey) {
|
|
164
251
|
if (parts.assetKey) context.releaseTexture(parts.assetKey);
|
|
@@ -167,20 +254,58 @@ function sync(container, item, context) {
|
|
|
167
254
|
}
|
|
168
255
|
const texture = key ? context.getTexture(key) : null;
|
|
169
256
|
const previewFailed = Boolean(key && !texture && context.hasError(key));
|
|
170
|
-
const artifact = featuredTaskArtifact(
|
|
257
|
+
const artifact = featuredTaskArtifact(snapshot.artifacts);
|
|
171
258
|
const kind = previewKindFor(artifact);
|
|
172
|
-
const surface = stateSurfaceFor(
|
|
259
|
+
const surface = stateSurfaceFor(status, kind, Boolean(texture), previewFailed);
|
|
173
260
|
const frame = {
|
|
174
261
|
x: 1,
|
|
175
262
|
y: 1,
|
|
176
263
|
width: Math.max(1, width - 2),
|
|
177
264
|
height: Math.max(1, height - 2)
|
|
178
265
|
};
|
|
179
|
-
const metaText = artifact ?
|
|
266
|
+
const metaText = artifact || working ? snapshot.model ?? "" : "";
|
|
180
267
|
const showMeta = full && Boolean(metaText);
|
|
181
|
-
const failedWithOutput =
|
|
268
|
+
const failedWithOutput = status === "failed" && kind !== "empty";
|
|
269
|
+
const count = artifact && snapshot.artifactCount > 1 ? String(snapshot.artifactCount) : "";
|
|
270
|
+
const showBadge = full && Boolean(count);
|
|
271
|
+
const label = stateLabel(surface, context);
|
|
272
|
+
const counting = full && working && startedAt !== null && surface !== null;
|
|
273
|
+
const elapsed = counting ? formatTaskElapsed(Date.now() - startedAt) : "";
|
|
274
|
+
const detailText = !full || !surface ? "" : status === "failed" ? snapshot.errorExcerpt ?? "" : working ? snapshot.promptExcerpt ?? "" : "";
|
|
275
|
+
const textArtifact = kind === "text" && artifact?.type === "text";
|
|
276
|
+
const bodyText = textArtifact ? artifact.textExcerpt : counting ? `${label} · ${elapsed}` : label;
|
|
182
277
|
syncTextResolution(parts.body, parts, context.zoom);
|
|
278
|
+
syncTextResolution(parts.detail, parts, context.zoom);
|
|
183
279
|
syncTextResolution(parts.meta, parts, context.zoom);
|
|
280
|
+
syncTextResolution(parts.badge, parts, context.zoom);
|
|
281
|
+
const textSig = [
|
|
282
|
+
counting ? label : bodyText,
|
|
283
|
+
detailText,
|
|
284
|
+
metaText,
|
|
285
|
+
count,
|
|
286
|
+
kind,
|
|
287
|
+
surface,
|
|
288
|
+
full,
|
|
289
|
+
width,
|
|
290
|
+
height,
|
|
291
|
+
color,
|
|
292
|
+
context.palette.text,
|
|
293
|
+
context.palette.muted
|
|
294
|
+
].join("|");
|
|
295
|
+
if (textSig !== parts.textSig) {
|
|
296
|
+
parts.textSig = textSig;
|
|
297
|
+
const wrap = Math.max(24, width - 24);
|
|
298
|
+
parts.body.style.fill = surface === "failed" ? color : context.palette.text;
|
|
299
|
+
parts.body.anchor.set(textArtifact ? 0 : .5, 0);
|
|
300
|
+
fitTextToLines(parts.body, bodyText, textArtifact ? Math.max(1, Math.floor((height - 24 - (showMeta ? META_HEIGHT : 0)) / 16)) : 1, wrap);
|
|
301
|
+
parts.detail.style.fill = context.palette.muted;
|
|
302
|
+
fitTextToLines(parts.detail, detailText, height - 24 > 120 ? 2 : 1, Math.min(wrap, 360));
|
|
303
|
+
parts.meta.style.fill = context.palette.text;
|
|
304
|
+
fitTextToLines(parts.meta, metaText, 1, wrap);
|
|
305
|
+
parts.badge.style.fill = context.palette.text;
|
|
306
|
+
if (parts.badge.text !== count) parts.badge.text = count;
|
|
307
|
+
}
|
|
308
|
+
const badgeWidth = Math.max(22, parts.badge.width + 12);
|
|
184
309
|
const visualSig = [
|
|
185
310
|
width,
|
|
186
311
|
height,
|
|
@@ -191,6 +316,7 @@ function sync(container, item, context) {
|
|
|
191
316
|
kind,
|
|
192
317
|
surface,
|
|
193
318
|
showMeta,
|
|
319
|
+
showBadge && badgeWidth,
|
|
194
320
|
failedWithOutput,
|
|
195
321
|
artifact?.type ?? "none",
|
|
196
322
|
artifact?.id ?? "none",
|
|
@@ -199,7 +325,8 @@ function sync(container, item, context) {
|
|
|
199
325
|
context.palette.surface,
|
|
200
326
|
context.palette.hover,
|
|
201
327
|
context.palette.border,
|
|
202
|
-
context.palette.bg
|
|
328
|
+
context.palette.bg,
|
|
329
|
+
context.palette.text
|
|
203
330
|
].join("|");
|
|
204
331
|
if (visualSig !== parts.visualSig) {
|
|
205
332
|
parts.visualSig = visualSig;
|
|
@@ -217,6 +344,8 @@ function sync(container, item, context) {
|
|
|
217
344
|
alpha: .5
|
|
218
345
|
});
|
|
219
346
|
parts.previewMask.clear().rect(frame.x, frame.y, frame.width, frame.height).fill({ color: 16777215 });
|
|
347
|
+
drawShimmerBand(parts.shimmer, frame.width, frame.height, context.palette.text);
|
|
348
|
+
parts.shimmer.y = frame.y;
|
|
220
349
|
parts.previewArt.clear();
|
|
221
350
|
if (kind === "waveform") {
|
|
222
351
|
const bottomInset = showMeta ? META_HEIGHT : 0;
|
|
@@ -229,47 +358,52 @@ function sync(container, item, context) {
|
|
|
229
358
|
}
|
|
230
359
|
if (full && (artifact?.type === "audio" || artifact?.type === "video" && texture)) drawPlayBadge(parts.previewArt, frame, context);
|
|
231
360
|
if (surface) {
|
|
232
|
-
const markY = frame.y + frame.height / 2 - (full &&
|
|
361
|
+
const markY = frame.y + frame.height / 2 - (full && label ? 18 : 0);
|
|
233
362
|
drawStateMark(parts.previewArt, surface, frame.x + frame.width / 2, markY, surface === "failed" ? color : context.colors.neutral.stroke);
|
|
234
363
|
}
|
|
235
364
|
if (showMeta) parts.previewArt.rect(frame.x, frame.y + frame.height - META_HEIGHT, frame.width, META_HEIGHT).fill({
|
|
236
365
|
color: context.palette.bg,
|
|
237
366
|
alpha: .68
|
|
238
367
|
});
|
|
368
|
+
if (showBadge) parts.previewArt.roundRect(width - badgeWidth - 8, 8, badgeWidth, 20, 10).fill({
|
|
369
|
+
color: context.palette.bg,
|
|
370
|
+
alpha: .72
|
|
371
|
+
});
|
|
239
372
|
if (failedWithOutput) drawFailedBadge(parts.previewArt, width, color, context);
|
|
240
373
|
}
|
|
241
|
-
|
|
242
|
-
|
|
374
|
+
const showPreview = kind === "texture" && Boolean(texture);
|
|
375
|
+
const revealKey = showPreview ? `${artifact?.id}:${texture?.uid}` : null;
|
|
376
|
+
const sameCard = parts.motion.itemId === item.id;
|
|
377
|
+
parts.motion.itemId = item.id;
|
|
378
|
+
if (revealKey !== parts.motion.revealKey || !sameCard) {
|
|
379
|
+
const appearing = sameCard && parts.motion.revealKey === null && revealKey !== null;
|
|
380
|
+
parts.motion.revealKey = revealKey;
|
|
381
|
+
parts.motion.revealFrom = appearing && !context.reducedMotion ? performance.now() : null;
|
|
382
|
+
parts.preview.alpha = parts.motion.revealFrom === null ? 1 : 0;
|
|
383
|
+
}
|
|
384
|
+
parts.preview.visible = showPreview;
|
|
385
|
+
if (showPreview && texture) {
|
|
243
386
|
if (parts.preview.texture !== texture) parts.preview.texture = texture;
|
|
244
387
|
const fitted = containTaskPreviewRect(frame.width, frame.height, texture.width, texture.height);
|
|
245
388
|
parts.preview.position.set(frame.x + fitted.x, frame.y + fitted.y);
|
|
246
389
|
parts.preview.width = fitted.width;
|
|
247
390
|
parts.preview.height = fitted.height;
|
|
248
391
|
}
|
|
249
|
-
const bodyText = kind === "text" && artifact?.type === "text" ? artifact.textExcerpt : stateLabel(surface);
|
|
250
|
-
const textSig = [
|
|
251
|
-
bodyText,
|
|
252
|
-
metaText,
|
|
253
|
-
kind,
|
|
254
|
-
surface,
|
|
255
|
-
full,
|
|
256
|
-
width,
|
|
257
|
-
height,
|
|
258
|
-
context.palette.text,
|
|
259
|
-
context.palette.muted
|
|
260
|
-
].join("|");
|
|
261
|
-
if (textSig !== parts.textSig) {
|
|
262
|
-
parts.textSig = textSig;
|
|
263
|
-
parts.body.style.fill = surface === "failed" ? color : context.palette.text;
|
|
264
|
-
fitTextToLines(parts.body, bodyText, kind === "text" ? Math.max(1, Math.floor((height - 24 - (showMeta ? META_HEIGHT : 0)) / 16)) : 1, Math.max(24, width - 24));
|
|
265
|
-
parts.meta.style.fill = context.palette.text;
|
|
266
|
-
fitTextToLines(parts.meta, metaText, 1, Math.max(24, width - 24));
|
|
267
|
-
}
|
|
268
392
|
parts.body.visible = full && Boolean(bodyText);
|
|
393
|
+
parts.detail.visible = full && Boolean(detailText);
|
|
269
394
|
parts.meta.visible = showMeta;
|
|
270
|
-
|
|
271
|
-
|
|
395
|
+
parts.badge.visible = showBadge;
|
|
396
|
+
if (textArtifact) parts.body.position.set(PADDING, PADDING);
|
|
397
|
+
else parts.body.position.set(width / 2, height / 2 + 2);
|
|
398
|
+
parts.detail.position.set(width / 2, height / 2 + 2 + parts.body.height + 4);
|
|
272
399
|
parts.meta.position.set(PADDING, height - META_HEIGHT + 7);
|
|
400
|
+
parts.badge.position.set(width - 8 - badgeWidth / 2, 18);
|
|
401
|
+
parts.motion.width = frame.width;
|
|
402
|
+
parts.motion.shimmer = full && working && kind !== "texture" && !context.reducedMotion;
|
|
403
|
+
parts.shimmer.visible = parts.motion.shimmer;
|
|
404
|
+
parts.motion.startedAt = counting ? startedAt : null;
|
|
405
|
+
parts.motion.label = label;
|
|
406
|
+
parts.motion.elapsed = elapsed;
|
|
273
407
|
}
|
|
274
408
|
const taskCardRenderer = {
|
|
275
409
|
id: "task-card",
|
|
@@ -281,35 +415,32 @@ const taskCardRenderer = {
|
|
|
281
415
|
const previewBg = new Graphics();
|
|
282
416
|
const preview = new Sprite();
|
|
283
417
|
const previewMask = new Graphics();
|
|
418
|
+
const shimmer = new Graphics();
|
|
284
419
|
const previewArt = new Graphics();
|
|
285
420
|
const resolution = textResolutionForZoom(context.zoom);
|
|
286
|
-
const
|
|
287
|
-
text: "",
|
|
288
|
-
style: {
|
|
289
|
-
fontFamily: BOARD_FONT_STACK,
|
|
290
|
-
fontSize: 11.5,
|
|
291
|
-
fontWeight: "500",
|
|
292
|
-
wordWrap: true,
|
|
293
|
-
breakWords: true
|
|
294
|
-
},
|
|
295
|
-
resolution,
|
|
296
|
-
roundPixels: true
|
|
297
|
-
});
|
|
298
|
-
const meta = new Text({
|
|
421
|
+
const text = (fontFamily, fontSize, fontWeight) => new Text({
|
|
299
422
|
text: "",
|
|
300
423
|
style: {
|
|
301
|
-
fontFamily
|
|
302
|
-
fontSize
|
|
303
|
-
fontWeight
|
|
424
|
+
fontFamily,
|
|
425
|
+
fontSize,
|
|
426
|
+
fontWeight,
|
|
304
427
|
wordWrap: true,
|
|
305
428
|
breakWords: true
|
|
306
429
|
},
|
|
307
430
|
resolution,
|
|
308
431
|
roundPixels: true
|
|
309
432
|
});
|
|
433
|
+
const body = text(BOARD_FONT_STACK, 11.5, "500");
|
|
434
|
+
const detail = text(BOARD_FONT_STACK, 10.5, "400");
|
|
435
|
+
const meta = text(BOARD_MONO_FONT_STACK, 10, "500");
|
|
436
|
+
const badge = text(BOARD_MONO_FONT_STACK, 10, "500");
|
|
437
|
+
badge.style.wordWrap = false;
|
|
438
|
+
badge.anchor.set(.5);
|
|
439
|
+
detail.anchor.set(.5, 0);
|
|
440
|
+
detail.style.align = "center";
|
|
310
441
|
preview.mask = previewMask;
|
|
311
442
|
root.mask = clip;
|
|
312
|
-
root.addChild(plate, clip, previewBg, preview, previewMask, previewArt, body, meta);
|
|
443
|
+
root.addChild(plate, clip, previewBg, shimmer, preview, previewMask, previewArt, body, detail, meta, badge);
|
|
313
444
|
partsByContainer.set(root, {
|
|
314
445
|
root,
|
|
315
446
|
plate,
|
|
@@ -317,13 +448,26 @@ const taskCardRenderer = {
|
|
|
317
448
|
previewBg,
|
|
318
449
|
preview,
|
|
319
450
|
previewMask,
|
|
451
|
+
shimmer,
|
|
320
452
|
previewArt,
|
|
453
|
+
badge,
|
|
321
454
|
body,
|
|
455
|
+
detail,
|
|
322
456
|
meta,
|
|
323
457
|
assetKey: null,
|
|
324
458
|
visualSig: "",
|
|
325
459
|
textSig: "",
|
|
326
|
-
resolution
|
|
460
|
+
resolution,
|
|
461
|
+
motion: {
|
|
462
|
+
itemId: "",
|
|
463
|
+
width: 0,
|
|
464
|
+
shimmer: false,
|
|
465
|
+
startedAt: null,
|
|
466
|
+
label: "",
|
|
467
|
+
elapsed: "",
|
|
468
|
+
revealFrom: null,
|
|
469
|
+
revealKey: null
|
|
470
|
+
}
|
|
327
471
|
});
|
|
328
472
|
if (item.type === "task") sync(root, item, context);
|
|
329
473
|
return root;
|
|
@@ -331,14 +475,19 @@ const taskCardRenderer = {
|
|
|
331
475
|
update: (container, item, context) => {
|
|
332
476
|
if (item.type === "task") sync(container, item, context);
|
|
333
477
|
},
|
|
478
|
+
tick: (container, clock) => {
|
|
479
|
+
const parts = partsByContainer.get(container);
|
|
480
|
+
return parts ? advance(parts, clock) : null;
|
|
481
|
+
},
|
|
334
482
|
renderFar: (graphics, item, context) => {
|
|
335
483
|
if (item.type !== "task") return;
|
|
336
|
-
const
|
|
484
|
+
const { status } = liveStatus(item, context);
|
|
485
|
+
const active = status === "failed" || status === "running" || status === "pending";
|
|
337
486
|
drawFarPlate(graphics, item.frame, {
|
|
338
487
|
fill: context.palette.surface,
|
|
339
488
|
fillAlpha: .82,
|
|
340
489
|
...active ? {
|
|
341
|
-
accent: statusColor(
|
|
490
|
+
accent: statusColor(status, context),
|
|
342
491
|
accentAlpha: .9
|
|
343
492
|
} : {}
|
|
344
493
|
});
|
|
@@ -351,4 +500,4 @@ const taskCardRenderer = {
|
|
|
351
500
|
}
|
|
352
501
|
};
|
|
353
502
|
//#endregion
|
|
354
|
-
export { TASK_CARD_FULL_DETAIL_ZOOM, containTaskPreviewRect, taskCardRenderer };
|
|
503
|
+
export { TASK_CARD_FULL_DETAIL_ZOOM, containTaskPreviewRect, formatTaskElapsed, taskCardRenderer };
|
|
@@ -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) => {
|