@neta-art/cohub 11.1.0 → 11.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/board/editor/context.d.ts +1 -0
- package/dist/board/editor/context.js +1 -0
- package/dist/board/editor/editor.d.ts +1 -0
- package/dist/board/editor/editor.js +7 -0
- package/dist/board/editor/interaction.d.ts +4 -0
- package/dist/board/editor/interaction.js +16 -7
- package/dist/board/editor/selection-transform.d.ts +1 -1
- package/dist/board/editor/selection-transform.js +13 -2
- package/dist/board/export/index.d.ts +2 -0
- package/dist/board/export/index.js +1 -0
- package/dist/board/export/scene.d.ts +2 -0
- package/dist/board/export/scene.js +4 -0
- package/dist/board/model/file-preview.d.ts +0 -1
- package/dist/board/model/file-preview.js +10 -1
- package/dist/board/render/audio-waveform.d.ts +1 -1
- package/dist/board/render/audio-waveform.js +8 -5
- package/dist/board/render/card-tag.d.ts +24 -0
- package/dist/board/render/card-tag.js +205 -0
- package/dist/board/render/index.d.ts +7 -4
- package/dist/board/render/index.js +7 -4
- package/dist/board/render/media-interaction.d.ts +2 -1
- package/dist/board/render/media-interaction.js +14 -6
- package/dist/board/render/palette.js +2 -2
- package/dist/board/render/renderers/arrow-card-renderer.js +20 -16
- package/dist/board/render/renderers/audio-card-renderer.d.ts +8 -1
- package/dist/board/render/renderers/audio-card-renderer.js +64 -60
- package/dist/board/render/renderers/base-card-renderer.d.ts +1 -26
- package/dist/board/render/renderers/base-card-renderer.js +6 -92
- package/dist/board/render/renderers/board-renderer-registry.d.ts +8 -0
- package/dist/board/render/renderers/board-renderer-registry.js +3 -3
- package/dist/board/render/renderers/custom-card-renderer.js +4 -7
- package/dist/board/render/renderers/effect-card-renderer.js +0 -5
- package/dist/board/render/renderers/file-card-renderer.d.ts +1 -11
- package/dist/board/render/renderers/file-card-renderer.js +43 -105
- package/dist/board/render/renderers/frame-card-renderer.js +14 -15
- package/dist/board/render/renderers/image-card-renderer.js +62 -67
- package/dist/board/render/renderers/media-key.d.ts +6 -0
- package/dist/board/render/renderers/media-key.js +39 -0
- package/dist/board/render/renderers/shape-card-renderer.js +6 -12
- package/dist/board/render/renderers/task-card-renderer.d.ts +1 -9
- package/dist/board/render/renderers/task-card-renderer.js +82 -56
- package/dist/board/render/renderers/unknown-card-renderer.js +17 -16
- package/dist/board/render/renderers/video-card-renderer.js +73 -80
- package/dist/board/render/stroke.d.ts +1 -1
- package/dist/board/render/stroke.js +5 -4
- package/dist/board/render/style.d.ts +29 -0
- package/dist/board/render/style.js +54 -0
- package/dist/board/render/surface.d.ts +34 -0
- package/dist/board/render/surface.js +132 -0
- package/dist/board/render/text-fit.d.ts +8 -0
- package/dist/board/render/text-fit.js +60 -0
- package/dist/board/render/text-resolution.d.ts +2 -1
- package/dist/board/render/text-resolution.js +4 -1
- package/dist/board/stage/index.d.ts +3 -2
- package/dist/board/stage/index.js +2 -1
- package/dist/board/stage/overlay.d.ts +41 -0
- package/dist/board/stage/overlay.js +182 -0
- package/dist/board/stage/scene.d.ts +2 -43
- package/dist/board/stage/scene.js +23 -131
- package/dist/board/stage/stage.d.ts +2 -0
- package/dist/board/stage/stage.js +100 -33
- package/dist/chunks/environment.d.ts +997 -3
- package/dist/chunks/http.d.ts +48 -1
- package/dist/chunks/http.js +8 -0
- package/dist/http.d.ts +2 -2
- package/dist/index.d.ts +2 -2
- package/package.json +2 -1
|
@@ -2,8 +2,9 @@ import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
|
2
2
|
import { pathPointAt, resolveSceneArrow } from "../../model/arrow-geometry.js";
|
|
3
3
|
import { itemAlpha, itemColor } from "../palette.js";
|
|
4
4
|
import { syncTextResolution, textResolutionForZoom } from "../text-resolution.js";
|
|
5
|
-
import { drawFarStroke } from "./far-plate.js";
|
|
6
5
|
import { dashPattern, endAngle, traceArrowhead, tracePolyline, trimPolyline } from "../stroke.js";
|
|
6
|
+
import { drawCardSurface } from "../surface.js";
|
|
7
|
+
import { drawFarStroke } from "./far-plate.js";
|
|
7
8
|
import { Container, Graphics, Text } from "pixi.js";
|
|
8
9
|
//#region src/board/render/renderers/arrow-card-renderer.ts
|
|
9
10
|
const partsByContainer = /* @__PURE__ */ new WeakMap();
|
|
@@ -14,8 +15,6 @@ function sync(container, item, context) {
|
|
|
14
15
|
parts.root.rotation = 0;
|
|
15
16
|
parts.root.scale.set(1);
|
|
16
17
|
const { props, style } = item;
|
|
17
|
-
const selected = context.selectedIds.has(item.id);
|
|
18
|
-
const hovered = context.hoveredId === item.id;
|
|
19
18
|
parts.line.alpha = itemAlpha(context, style.stroke);
|
|
20
19
|
const color = itemColor(context, style.stroke, "brand");
|
|
21
20
|
const size = style.strokeWidth ?? 2.5;
|
|
@@ -24,8 +23,6 @@ function sync(container, item, context) {
|
|
|
24
23
|
const path = trimPolyline(resolved.path, style.trim);
|
|
25
24
|
const lineSig = [
|
|
26
25
|
path.map((point) => `${point.x},${point.y}`).join(";"),
|
|
27
|
-
selected,
|
|
28
|
-
hovered,
|
|
29
26
|
color,
|
|
30
27
|
size,
|
|
31
28
|
style.dash,
|
|
@@ -35,11 +32,11 @@ function sync(container, item, context) {
|
|
|
35
32
|
if (lineSig !== parts.lineSig) {
|
|
36
33
|
parts.lineSig = lineSig;
|
|
37
34
|
parts.line.clear();
|
|
38
|
-
const width =
|
|
35
|
+
const width = size;
|
|
39
36
|
const stroke = {
|
|
40
37
|
color,
|
|
41
38
|
width,
|
|
42
|
-
alpha:
|
|
39
|
+
alpha: .92,
|
|
43
40
|
cap: "round",
|
|
44
41
|
join: "round"
|
|
45
42
|
};
|
|
@@ -63,22 +60,29 @@ function sync(container, item, context) {
|
|
|
63
60
|
}
|
|
64
61
|
const labelSig = [
|
|
65
62
|
props.label,
|
|
66
|
-
|
|
67
|
-
context.
|
|
68
|
-
props.fontSize
|
|
63
|
+
props.fontSize,
|
|
64
|
+
context.themeKey
|
|
69
65
|
].join("|");
|
|
70
66
|
if (labelSig !== parts.labelSig) {
|
|
71
67
|
parts.labelSig = labelSig;
|
|
72
68
|
parts.label.text = props.label;
|
|
73
69
|
parts.label.style.fill = context.palette.text;
|
|
74
70
|
parts.label.style.fontSize = props.fontSize;
|
|
75
|
-
const padX = props.fontSize * .
|
|
76
|
-
const padY = props.fontSize * .
|
|
71
|
+
const padX = props.fontSize * .5;
|
|
72
|
+
const padY = props.fontSize * .25;
|
|
77
73
|
const { width, height } = parts.label;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
74
|
+
const plate = {
|
|
75
|
+
x: -width / 2 - padX,
|
|
76
|
+
y: -height / 2 - padY,
|
|
77
|
+
width: width + padX * 2,
|
|
78
|
+
height: height + padY * 2
|
|
79
|
+
};
|
|
80
|
+
drawCardSurface(parts.backdrop.clear(), plate, {
|
|
81
|
+
...context.style,
|
|
82
|
+
radius: Math.min(context.style.radius, plate.height / 2)
|
|
83
|
+
}, {
|
|
84
|
+
fill: context.palette.surface,
|
|
85
|
+
border: context.palette.border
|
|
82
86
|
});
|
|
83
87
|
}
|
|
84
88
|
const visible = props.label.length > 0 && (style.trim === void 0 || style.trim >= .5);
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { BoardCardRenderer } from "./board-renderer-registry.js";
|
|
2
2
|
//#region src/board/render/renderers/audio-card-renderer.d.ts
|
|
3
|
+
declare const AUDIO_PADDING = 14;
|
|
4
|
+
declare const AUDIO_KEY_RADIUS = 16;
|
|
5
|
+
declare function audioKeyCenter(width: number, height: number): {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
radius: number;
|
|
9
|
+
};
|
|
3
10
|
declare const audioCardRenderer: BoardCardRenderer;
|
|
4
11
|
//#endregion
|
|
5
|
-
export { audioCardRenderer };
|
|
12
|
+
export { AUDIO_KEY_RADIUS, AUDIO_PADDING, audioCardRenderer, audioKeyCenter };
|
|
@@ -1,70 +1,80 @@
|
|
|
1
|
-
import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
1
|
import { getMediaResourceTitle } from "../../model/media.js";
|
|
2
|
+
import { fitTextToWidth } from "../text-fit.js";
|
|
3
|
+
import { boardCardDetailed, syncTextResolution, textResolutionForZoom } from "../text-resolution.js";
|
|
4
|
+
import { formatBoardDuration } from "../card-tag.js";
|
|
3
5
|
import { drawAudioWaveform } from "../audio-waveform.js";
|
|
4
|
-
import {
|
|
6
|
+
import { cardElevation, drawCardSurface } from "../surface.js";
|
|
5
7
|
import { positionShell } from "./base-card-renderer.js";
|
|
6
8
|
import { drawFarPlate } from "./far-plate.js";
|
|
9
|
+
import { drawMediaPlayKey } from "./media-key.js";
|
|
7
10
|
import { Container, Graphics, Text } from "pixi.js";
|
|
8
11
|
//#region src/board/render/renderers/audio-card-renderer.ts
|
|
9
|
-
const
|
|
10
|
-
const
|
|
12
|
+
const AUDIO_PADDING = 14;
|
|
13
|
+
const AUDIO_KEY_RADIUS = 16;
|
|
14
|
+
const GAP = 12;
|
|
15
|
+
const WAVE_HEIGHT = 16;
|
|
11
16
|
const partsByContainer = /* @__PURE__ */ new WeakMap();
|
|
17
|
+
function audioKeyCenter(width, height) {
|
|
18
|
+
const radius = Math.min(16, Math.max(8, height / 2 - 8), width / 4);
|
|
19
|
+
return {
|
|
20
|
+
x: 14 + radius,
|
|
21
|
+
y: height / 2,
|
|
22
|
+
radius
|
|
23
|
+
};
|
|
24
|
+
}
|
|
12
25
|
function sync(container, item, context) {
|
|
13
26
|
const parts = partsByContainer.get(container);
|
|
14
27
|
if (!parts) return;
|
|
15
28
|
positionShell(parts.root, item);
|
|
16
29
|
const { width, height } = item.frame;
|
|
17
|
-
const selected = context.selectedIds.has(item.id);
|
|
18
|
-
const hovered = context.hoveredId === item.id;
|
|
19
30
|
const title = item.props.snapshot?.title ?? getMediaResourceTitle(item.props.src);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
const durationMs = item.props.snapshot?.durationMs;
|
|
32
|
+
const detailed = boardCardDetailed(context.zoom);
|
|
33
|
+
syncTextResolution(parts.title, parts, context.zoom);
|
|
34
|
+
const elevation = cardElevation(context, item.id);
|
|
24
35
|
const sig = [
|
|
25
36
|
width,
|
|
26
37
|
height,
|
|
27
|
-
selected,
|
|
28
|
-
hovered,
|
|
29
38
|
title,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
context.
|
|
39
|
+
durationMs ?? "",
|
|
40
|
+
detailed,
|
|
41
|
+
elevation,
|
|
42
|
+
item.props.src,
|
|
43
|
+
item.props.snapshot?.mtimeMs ?? "",
|
|
44
|
+
context.themeKey
|
|
36
45
|
].join("|");
|
|
37
46
|
if (sig === parts.sig) return;
|
|
38
47
|
parts.sig = sig;
|
|
39
|
-
parts.plate.clear()
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
parts.waveform.clear();
|
|
50
|
-
drawAudioWaveform(parts.waveform, `${item.props.src}:${item.props.snapshot?.mtimeMs ?? "unknown"}`, {
|
|
51
|
-
x: waveformInset,
|
|
52
|
-
y: 10,
|
|
53
|
-
width: Math.max(1, width - waveformInset * 2),
|
|
54
|
-
height: Math.max(8, height - labelBand - 16)
|
|
55
|
-
}, context.palette.brand);
|
|
56
|
-
const cx = width / 2;
|
|
57
|
-
const cy = Math.max(24, (height - labelBand) / 2);
|
|
58
|
-
parts.chrome.clear().circle(cx, cy, PLAY_RADIUS).fill({
|
|
59
|
-
color: selected ? context.palette.brand : context.palette.surface,
|
|
60
|
-
alpha: .92
|
|
61
|
-
});
|
|
62
|
-
const triangle = PLAY_RADIUS * .58;
|
|
63
|
-
parts.chrome.moveTo(cx - triangle * .35, cy - triangle * .62).lineTo(cx - triangle * .35, cy + triangle * .62).lineTo(cx + triangle * .72, cy).closePath().fill({
|
|
64
|
-
color: context.palette.text,
|
|
65
|
-
alpha: .96
|
|
48
|
+
drawCardSurface(parts.plate.clear(), {
|
|
49
|
+
x: 0,
|
|
50
|
+
y: 0,
|
|
51
|
+
width,
|
|
52
|
+
height
|
|
53
|
+
}, context.style, {
|
|
54
|
+
fill: context.palette.surface,
|
|
55
|
+
border: context.palette.border,
|
|
56
|
+
borderAlpha: .85,
|
|
57
|
+
elevation
|
|
66
58
|
});
|
|
67
|
-
|
|
59
|
+
const key = audioKeyCenter(width, height);
|
|
60
|
+
drawMediaPlayKey(parts.plate, key.x, key.y, key.radius, context, true);
|
|
61
|
+
const left = key.x + key.radius + GAP;
|
|
62
|
+
const room = width - 14 - left;
|
|
63
|
+
parts.title.visible = detailed && room > 24;
|
|
64
|
+
parts.wave.clear();
|
|
65
|
+
if (!parts.title.visible) return;
|
|
66
|
+
parts.title.style.fontFamily = context.style.font;
|
|
67
|
+
parts.title.style.fill = context.palette.text;
|
|
68
|
+
fitTextToWidth(parts.title, durationMs ? `${title} · ${formatBoardDuration(durationMs)}` : title, room);
|
|
69
|
+
const withWave = height >= 56;
|
|
70
|
+
const top = (height - (parts.title.height + (withWave ? 22 : 0))) / 2;
|
|
71
|
+
parts.title.position.set(left, top);
|
|
72
|
+
if (withWave) drawAudioWaveform(parts.wave, `${item.props.src}:${item.props.snapshot?.mtimeMs ?? "unknown"}`, {
|
|
73
|
+
x: left,
|
|
74
|
+
y: top + parts.title.height + 6,
|
|
75
|
+
width: room,
|
|
76
|
+
height: WAVE_HEIGHT
|
|
77
|
+
}, context.palette.muted, .45, context.style.corner === "pixel");
|
|
68
78
|
}
|
|
69
79
|
const audioCardRenderer = {
|
|
70
80
|
id: "audio-card",
|
|
@@ -72,30 +82,24 @@ const audioCardRenderer = {
|
|
|
72
82
|
create: (item, context) => {
|
|
73
83
|
const root = new Container();
|
|
74
84
|
const plate = new Graphics();
|
|
75
|
-
const
|
|
76
|
-
const chrome = new Graphics();
|
|
85
|
+
const wave = new Graphics();
|
|
77
86
|
const resolution = textResolutionForZoom(context.zoom);
|
|
78
|
-
const
|
|
87
|
+
const title = new Text({
|
|
79
88
|
text: "",
|
|
80
89
|
style: {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
fontSize: 12,
|
|
84
|
-
fontWeight: "500",
|
|
85
|
-
wordWrap: true
|
|
90
|
+
fontSize: 13,
|
|
91
|
+
fontWeight: "600"
|
|
86
92
|
},
|
|
87
93
|
resolution,
|
|
88
94
|
roundPixels: true
|
|
89
95
|
});
|
|
90
|
-
root.addChild(plate,
|
|
96
|
+
root.addChild(plate, wave, title);
|
|
91
97
|
partsByContainer.set(root, {
|
|
92
98
|
root,
|
|
93
99
|
plate,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
label,
|
|
100
|
+
wave,
|
|
101
|
+
title,
|
|
97
102
|
sig: "",
|
|
98
|
-
wrapWidth: 0,
|
|
99
103
|
resolution
|
|
100
104
|
});
|
|
101
105
|
if (item.type === "audio") sync(root, item, context);
|
|
@@ -118,4 +122,4 @@ const audioCardRenderer = {
|
|
|
118
122
|
}
|
|
119
123
|
};
|
|
120
124
|
//#endregion
|
|
121
|
-
export { audioCardRenderer };
|
|
125
|
+
export { AUDIO_KEY_RADIUS, AUDIO_PADDING, audioCardRenderer, audioKeyCenter };
|
|
@@ -1,35 +1,10 @@
|
|
|
1
1
|
import { BoardFrame } from "../../../protocol/dist/board-layout.js";
|
|
2
2
|
import "../../../protocol/dist/index.js";
|
|
3
|
-
import { BoardRenderPalette } from "./board-renderer-registry.js";
|
|
4
3
|
import { Container, Text } from "pixi.js";
|
|
5
4
|
//#region src/board/render/renderers/base-card-renderer.d.ts
|
|
6
|
-
declare const CARD_RADIUS = 10;
|
|
7
|
-
declare const CARD_PADDING = 12;
|
|
8
|
-
declare const FOOTER_HEIGHT = 34;
|
|
9
5
|
declare function createLabel(text: string, style: Record<string, unknown>): Text;
|
|
10
|
-
type CardShellState = {
|
|
11
|
-
width: number;
|
|
12
|
-
height: number;
|
|
13
|
-
selected: boolean;
|
|
14
|
-
hovered: boolean;
|
|
15
|
-
accent: number;
|
|
16
|
-
title: string;
|
|
17
|
-
};
|
|
18
|
-
type CardShell = {
|
|
19
|
-
root: Container;
|
|
20
|
-
content: Container;
|
|
21
|
-
contentRect: () => {
|
|
22
|
-
x: number;
|
|
23
|
-
y: number;
|
|
24
|
-
width: number;
|
|
25
|
-
height: number;
|
|
26
|
-
};
|
|
27
|
-
update: (state: CardShellState, palette: BoardRenderPalette, footer: boolean) => void;
|
|
28
|
-
destroy: () => void;
|
|
29
|
-
};
|
|
30
|
-
declare function createCardShell(): CardShell;
|
|
31
6
|
declare function positionShell(root: Container, item: {
|
|
32
7
|
frame: BoardFrame;
|
|
33
8
|
}): void;
|
|
34
9
|
//#endregion
|
|
35
|
-
export {
|
|
10
|
+
export { createLabel, positionShell };
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
2
|
import { getBoardResolution } from "../text-resolution.js";
|
|
3
|
-
import {
|
|
3
|
+
import { Text } from "pixi.js";
|
|
4
4
|
//#region src/board/render/renderers/base-card-renderer.ts
|
|
5
|
-
const CARD_RADIUS = 10;
|
|
6
|
-
const CARD_PADDING = 12;
|
|
7
|
-
const FOOTER_HEIGHT = 34;
|
|
8
5
|
const TEXT_OPTIONS = {
|
|
9
6
|
resolution: getBoardResolution(),
|
|
10
7
|
roundPixels: true
|
|
@@ -13,94 +10,11 @@ function createLabel(text, style) {
|
|
|
13
10
|
return new Text({
|
|
14
11
|
...TEXT_OPTIONS,
|
|
15
12
|
text,
|
|
16
|
-
style
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
function createCardShell() {
|
|
20
|
-
const root = new Container();
|
|
21
|
-
const background = new Graphics();
|
|
22
|
-
const content = new Container();
|
|
23
|
-
const mask = new Graphics();
|
|
24
|
-
const footerBg = new Graphics();
|
|
25
|
-
const title = createLabel("", {
|
|
26
|
-
fill: 16777215,
|
|
27
|
-
fontFamily: BOARD_FONT_STACK,
|
|
28
|
-
fontSize: 12,
|
|
29
|
-
fontWeight: "500",
|
|
30
|
-
wordWrap: true
|
|
31
|
-
});
|
|
32
|
-
content.mask = mask;
|
|
33
|
-
root.addChild(background, mask, content, footerBg, title);
|
|
34
|
-
let last = null;
|
|
35
|
-
function paletteKeyOf(palette) {
|
|
36
|
-
return `${palette.surface}|${palette.border}|${palette.hover}|${palette.text}|${palette.muted}`;
|
|
37
|
-
}
|
|
38
|
-
function contentRectFor(width, height, footer) {
|
|
39
|
-
const bottom = footer ? 34 : 12;
|
|
40
|
-
return {
|
|
41
|
-
x: 12,
|
|
42
|
-
y: 12,
|
|
43
|
-
width: Math.max(1, width - 24),
|
|
44
|
-
height: Math.max(1, height - 12 - bottom)
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
function draw(state, palette, footer) {
|
|
48
|
-
const { width, height, selected, hovered, accent } = state;
|
|
49
|
-
background.clear();
|
|
50
|
-
background.roundRect(0, 0, width, height, 10).fill({
|
|
51
|
-
color: palette.surface,
|
|
52
|
-
alpha: .98
|
|
53
|
-
});
|
|
54
|
-
const borderColor = selected ? accent : hovered ? palette.muted : palette.border;
|
|
55
|
-
background.roundRect(0, 0, width, height, 10).stroke({
|
|
56
|
-
color: borderColor,
|
|
57
|
-
width: selected ? 2 : 1,
|
|
58
|
-
alpha: selected ? .95 : hovered ? .9 : .8
|
|
59
|
-
});
|
|
60
|
-
mask.clear();
|
|
61
|
-
const rect = contentRectFor(width, height, footer);
|
|
62
|
-
mask.roundRect(rect.x, rect.y, rect.width, rect.height, 4).fill({ color: 16777215 });
|
|
63
|
-
footerBg.clear();
|
|
64
|
-
footerBg.visible = footer;
|
|
65
|
-
title.visible = footer;
|
|
66
|
-
if (footer) {
|
|
67
|
-
const fx = 1;
|
|
68
|
-
const fy = height - 34;
|
|
69
|
-
const fw = width - 2;
|
|
70
|
-
const fh = 33;
|
|
71
|
-
const r = 9;
|
|
72
|
-
footerBg.moveTo(fx, fy).lineTo(fx + fw, fy).lineTo(fx + fw, fy + fh - r).arcTo(fx + fw, fy + fh, fx + fw - r, fy + fh, r).lineTo(10, fy + fh).arcTo(fx, fy + fh, fx, fy + fh - r, r).lineTo(fx, fy).fill({
|
|
73
|
-
color: palette.hover,
|
|
74
|
-
alpha: .55
|
|
75
|
-
});
|
|
76
|
-
title.text = state.title;
|
|
77
|
-
title.style.fill = palette.text;
|
|
78
|
-
title.style.wordWrapWidth = width - 24;
|
|
79
|
-
title.x = 12;
|
|
80
|
-
title.y = height - 34 + (34 - title.height) / 2;
|
|
13
|
+
style: {
|
|
14
|
+
fontFamily: BOARD_FONT_STACK,
|
|
15
|
+
...style
|
|
81
16
|
}
|
|
82
|
-
}
|
|
83
|
-
function update(state, palette, footer) {
|
|
84
|
-
const paletteKey = paletteKeyOf(palette);
|
|
85
|
-
if (!last || last.width !== state.width || last.height !== state.height || last.selected !== state.selected || last.hovered !== state.hovered || last.accent !== state.accent || last.title !== state.title || last.footer !== footer || last.paletteKey !== paletteKey) {
|
|
86
|
-
draw(state, palette, footer);
|
|
87
|
-
last = {
|
|
88
|
-
...state,
|
|
89
|
-
footer,
|
|
90
|
-
paletteKey
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
function destroy() {
|
|
95
|
-
root.destroy({ children: true });
|
|
96
|
-
}
|
|
97
|
-
return {
|
|
98
|
-
root,
|
|
99
|
-
content,
|
|
100
|
-
contentRect: () => contentRectFor(last?.width ?? 0, last?.height ?? 0, last?.footer ?? true),
|
|
101
|
-
update,
|
|
102
|
-
destroy
|
|
103
|
-
};
|
|
17
|
+
});
|
|
104
18
|
}
|
|
105
19
|
function positionShell(root, item) {
|
|
106
20
|
const { x, y, width, height, rotation } = item.frame;
|
|
@@ -110,4 +24,4 @@ function positionShell(root, item) {
|
|
|
110
24
|
root.rotation = (rotation || 0) * Math.PI / 180;
|
|
111
25
|
}
|
|
112
26
|
//#endregion
|
|
113
|
-
export {
|
|
27
|
+
export { createLabel, positionShell };
|
|
@@ -3,6 +3,7 @@ import { BoardFrame } from "../../../protocol/dist/board-layout.js";
|
|
|
3
3
|
import "../../../protocol/dist/index.js";
|
|
4
4
|
import { BoardScene, BoardSceneItem, SceneItem } from "../../model/scene.js";
|
|
5
5
|
import { BoardShapeColors } from "../../model/palette.js";
|
|
6
|
+
import { BoardRenderStyle } from "../style.js";
|
|
6
7
|
import { Container, Graphics, Texture } from "pixi.js";
|
|
7
8
|
//#region src/board/render/renderers/board-renderer-registry.d.ts
|
|
8
9
|
type BoardRenderPalette = {
|
|
@@ -39,9 +40,12 @@ type BoardRenderContext = {
|
|
|
39
40
|
selectedIds: Set<string>;
|
|
40
41
|
hoveredId: string | null;
|
|
41
42
|
resizingIds: Set<string>;
|
|
43
|
+
liftedIds: ReadonlySet<string>;
|
|
42
44
|
palette: BoardRenderPalette;
|
|
43
45
|
colors: BoardShapeColors;
|
|
44
46
|
colorScheme: "dark" | "light";
|
|
47
|
+
style: BoardRenderStyle;
|
|
48
|
+
themeKey: string;
|
|
45
49
|
rendererType: "gpu" | "canvas";
|
|
46
50
|
zoom: number;
|
|
47
51
|
time: number;
|
|
@@ -64,9 +68,13 @@ type BoardCardRenderer = {
|
|
|
64
68
|
id: string;
|
|
65
69
|
canRender: (item: BoardSceneItem, context: BoardRenderContext) => boolean;
|
|
66
70
|
animated?: boolean;
|
|
71
|
+
/** Opt in to updates on selection and hover changes. */
|
|
72
|
+
observesSelection?: boolean;
|
|
67
73
|
tick?: (container: Container, clock: number) => number | null;
|
|
68
74
|
create: (item: BoardSceneItem, context: BoardRenderContext) => Container;
|
|
69
75
|
update: (container: Container, item: BoardSceneItem, context: BoardRenderContext) => void;
|
|
76
|
+
/** Runs on every zoom step; only update transforms and visibility. */
|
|
77
|
+
zoom?: (container: Container, zoom: number) => void;
|
|
70
78
|
renderFar?: (graphics: Graphics, item: BoardSceneItem, context: BoardRenderContext) => void;
|
|
71
79
|
destroy?: (container: Container, context: BoardRenderContext) => void;
|
|
72
80
|
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { ensureBoardTextMeasurement } from "../text-measurement.js";
|
|
2
|
-
import { fileCardRenderer } from "./file-card-renderer.js";
|
|
3
|
-
import { taskCardRenderer } from "./task-card-renderer.js";
|
|
4
|
-
import { arrowCardRenderer } from "./arrow-card-renderer.js";
|
|
5
2
|
import { audioCardRenderer } from "./audio-card-renderer.js";
|
|
3
|
+
import { arrowCardRenderer } from "./arrow-card-renderer.js";
|
|
6
4
|
import { drawCardRenderer } from "./draw-card-renderer.js";
|
|
7
5
|
import { effectCardRenderer } from "./effect-card-renderer.js";
|
|
6
|
+
import { fileCardRenderer } from "./file-card-renderer.js";
|
|
8
7
|
import { frameCardRenderer } from "./frame-card-renderer.js";
|
|
9
8
|
import { shapeCardRenderer } from "./shape-card-renderer.js";
|
|
10
9
|
import { customCardRenderer } from "./custom-card-renderer.js";
|
|
11
10
|
import { imageCardRenderer } from "./image-card-renderer.js";
|
|
11
|
+
import { taskCardRenderer } from "./task-card-renderer.js";
|
|
12
12
|
import { textCardRenderer } from "./text-card-renderer.js";
|
|
13
13
|
import { unknownCardRenderer } from "./unknown-card-renderer.js";
|
|
14
14
|
import { videoCardRenderer } from "./video-card-renderer.js";
|
|
@@ -22,24 +22,21 @@ function sync(container, item, context) {
|
|
|
22
22
|
if (parts.sprite.texture !== display) parts.sprite.texture = display;
|
|
23
23
|
parts.sprite.width = width;
|
|
24
24
|
parts.sprite.height = height;
|
|
25
|
-
const selected = context.selectedIds.has(item.id);
|
|
26
25
|
const ready = Boolean(texture) || context.scripts?.ready?.(item.id) === true;
|
|
27
26
|
const message = error ? `${item.script.src}\n${error}` : ready ? "" : item.script.src;
|
|
28
27
|
const sig = [
|
|
29
28
|
width,
|
|
30
29
|
height,
|
|
31
|
-
selected,
|
|
32
30
|
Boolean(texture),
|
|
33
31
|
message,
|
|
34
|
-
context.
|
|
35
|
-
context.palette.muted
|
|
32
|
+
context.themeKey
|
|
36
33
|
].join("|");
|
|
37
34
|
if (sig === parts.sig) return;
|
|
38
35
|
parts.sig = sig;
|
|
39
36
|
parts.placeholder.clear();
|
|
40
|
-
if (!ready ||
|
|
41
|
-
color:
|
|
42
|
-
width:
|
|
37
|
+
if (!ready || error) parts.placeholder.rect(0, 0, width, height).stroke({
|
|
38
|
+
color: context.palette.border,
|
|
39
|
+
width: 1,
|
|
43
40
|
alpha: .8
|
|
44
41
|
});
|
|
45
42
|
parts.label.visible = !ready || Boolean(error);
|
|
@@ -173,11 +173,6 @@ function sync(container, item, context) {
|
|
|
173
173
|
break;
|
|
174
174
|
case "trail": drawTrail(graphics, parts, item, context, color);
|
|
175
175
|
}
|
|
176
|
-
if (context.selectedIds.has(item.id) || context.hoveredId === item.id) graphics.rect(0, 0, width, height).stroke({
|
|
177
|
-
color: context.palette.muted,
|
|
178
|
-
width: 1,
|
|
179
|
-
alpha: .6
|
|
180
|
-
});
|
|
181
176
|
}
|
|
182
177
|
const effectCardRenderer = {
|
|
183
178
|
id: "effect-card",
|
|
@@ -2,18 +2,8 @@ import { BoardFileItem } from "../../../protocol/dist/board-model.js";
|
|
|
2
2
|
import "../../../protocol/dist/index.js";
|
|
3
3
|
import { BoardSceneItem, SceneItem } from "../../model/scene.js";
|
|
4
4
|
import { BoardCardRenderer } from "./board-renderer-registry.js";
|
|
5
|
-
import { Text } from "pixi.js";
|
|
6
5
|
//#region src/board/render/renderers/file-card-renderer.d.ts
|
|
7
|
-
declare function ellipsizeWrappedLines(lines: string[], maxLines: number): string;
|
|
8
|
-
declare function fitLineWithEllipsis(line: string, wrapWidth: number, measureWidth: (value: string) => number): string;
|
|
9
|
-
declare function fitTextToLines(text: Text, value: string, maxLines: number, wrapWidth: number): void;
|
|
10
|
-
declare function containCoverRect(width: number, height: number, imageWidth: number, imageHeight: number): {
|
|
11
|
-
x: number;
|
|
12
|
-
y: number;
|
|
13
|
-
width: number;
|
|
14
|
-
height: number;
|
|
15
|
-
};
|
|
16
6
|
declare const fileCardRenderer: BoardCardRenderer;
|
|
17
7
|
declare function isFileItem(item: BoardSceneItem): item is SceneItem<BoardFileItem>;
|
|
18
8
|
//#endregion
|
|
19
|
-
export {
|
|
9
|
+
export { fileCardRenderer, isFileItem };
|