@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.
Files changed (67) hide show
  1. package/dist/board/editor/context.d.ts +1 -0
  2. package/dist/board/editor/context.js +1 -0
  3. package/dist/board/editor/editor.d.ts +1 -0
  4. package/dist/board/editor/editor.js +7 -0
  5. package/dist/board/editor/interaction.d.ts +4 -0
  6. package/dist/board/editor/interaction.js +16 -7
  7. package/dist/board/editor/selection-transform.d.ts +1 -1
  8. package/dist/board/editor/selection-transform.js +13 -2
  9. package/dist/board/export/index.d.ts +2 -0
  10. package/dist/board/export/index.js +1 -0
  11. package/dist/board/export/scene.d.ts +2 -0
  12. package/dist/board/export/scene.js +4 -0
  13. package/dist/board/model/file-preview.d.ts +0 -1
  14. package/dist/board/model/file-preview.js +10 -1
  15. package/dist/board/render/audio-waveform.d.ts +1 -1
  16. package/dist/board/render/audio-waveform.js +8 -5
  17. package/dist/board/render/card-tag.d.ts +24 -0
  18. package/dist/board/render/card-tag.js +205 -0
  19. package/dist/board/render/index.d.ts +7 -4
  20. package/dist/board/render/index.js +7 -4
  21. package/dist/board/render/media-interaction.d.ts +2 -1
  22. package/dist/board/render/media-interaction.js +14 -6
  23. package/dist/board/render/palette.js +2 -2
  24. package/dist/board/render/renderers/arrow-card-renderer.js +20 -16
  25. package/dist/board/render/renderers/audio-card-renderer.d.ts +8 -1
  26. package/dist/board/render/renderers/audio-card-renderer.js +64 -60
  27. package/dist/board/render/renderers/base-card-renderer.d.ts +1 -26
  28. package/dist/board/render/renderers/base-card-renderer.js +6 -92
  29. package/dist/board/render/renderers/board-renderer-registry.d.ts +8 -0
  30. package/dist/board/render/renderers/board-renderer-registry.js +3 -3
  31. package/dist/board/render/renderers/custom-card-renderer.js +4 -7
  32. package/dist/board/render/renderers/effect-card-renderer.js +0 -5
  33. package/dist/board/render/renderers/file-card-renderer.d.ts +1 -11
  34. package/dist/board/render/renderers/file-card-renderer.js +43 -105
  35. package/dist/board/render/renderers/frame-card-renderer.js +14 -15
  36. package/dist/board/render/renderers/image-card-renderer.js +62 -67
  37. package/dist/board/render/renderers/media-key.d.ts +6 -0
  38. package/dist/board/render/renderers/media-key.js +39 -0
  39. package/dist/board/render/renderers/shape-card-renderer.js +6 -12
  40. package/dist/board/render/renderers/task-card-renderer.d.ts +1 -9
  41. package/dist/board/render/renderers/task-card-renderer.js +82 -56
  42. package/dist/board/render/renderers/unknown-card-renderer.js +17 -16
  43. package/dist/board/render/renderers/video-card-renderer.js +73 -80
  44. package/dist/board/render/stroke.d.ts +1 -1
  45. package/dist/board/render/stroke.js +5 -4
  46. package/dist/board/render/style.d.ts +29 -0
  47. package/dist/board/render/style.js +54 -0
  48. package/dist/board/render/surface.d.ts +34 -0
  49. package/dist/board/render/surface.js +132 -0
  50. package/dist/board/render/text-fit.d.ts +8 -0
  51. package/dist/board/render/text-fit.js +60 -0
  52. package/dist/board/render/text-resolution.d.ts +2 -1
  53. package/dist/board/render/text-resolution.js +4 -1
  54. package/dist/board/stage/index.d.ts +3 -2
  55. package/dist/board/stage/index.js +2 -1
  56. package/dist/board/stage/overlay.d.ts +41 -0
  57. package/dist/board/stage/overlay.js +182 -0
  58. package/dist/board/stage/scene.d.ts +2 -43
  59. package/dist/board/stage/scene.js +23 -131
  60. package/dist/board/stage/stage.d.ts +2 -0
  61. package/dist/board/stage/stage.js +100 -33
  62. package/dist/chunks/environment.d.ts +997 -3
  63. package/dist/chunks/http.d.ts +48 -1
  64. package/dist/chunks/http.js +8 -0
  65. package/dist/http.d.ts +2 -2
  66. package/dist/index.d.ts +2 -2
  67. 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 = selected ? size + 1 : size;
35
+ const width = size;
39
36
  const stroke = {
40
37
  color,
41
38
  width,
42
- alpha: selected || hovered ? 1 : .92,
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
- context.palette.text,
67
- context.palette.bg,
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 * .4;
76
- const padY = props.fontSize * .15;
71
+ const padX = props.fontSize * .5;
72
+ const padY = props.fontSize * .25;
77
73
  const { width, height } = parts.label;
78
- parts.backdrop.clear();
79
- parts.backdrop.roundRect(-width / 2 - padX, -height / 2 - padY, width + padX * 2, height + padY * 2, props.fontSize * .3).fill({
80
- color: context.palette.bg,
81
- alpha: .92
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 { syncTextResolution, syncTextWrapWidth, textResolutionForZoom } from "../text-resolution.js";
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 RADIUS = 4;
10
- const PLAY_RADIUS = 18;
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
- syncTextResolution(parts.label, parts, context.zoom);
21
- if (parts.label.text !== title) parts.label.text = title;
22
- syncTextWrapWidth(parts.label, parts, Math.max(1, width - 24), false);
23
- parts.label.position.set(12, Math.max(8, height - parts.label.height - 8));
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
- parts.label.height,
31
- context.palette.surface,
32
- context.palette.brand,
33
- context.palette.border,
34
- context.palette.muted,
35
- context.palette.text
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().roundRect(0, 0, width, height, RADIUS).fill({
40
- color: context.palette.surface,
41
- alpha: .98
42
- }).roundRect(0, 0, width, height, RADIUS).stroke({
43
- color: selected ? context.palette.brand : hovered ? context.palette.muted : context.palette.border,
44
- width: selected ? 2 : 1,
45
- alpha: selected ? .96 : .84
46
- });
47
- const labelBand = Math.min(height * .38, parts.label.height + 16);
48
- const waveformInset = Math.min(24, width * .08);
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
- parts.label.style.fill = context.palette.text;
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 waveform = new Graphics();
76
- const chrome = new Graphics();
85
+ const wave = new Graphics();
77
86
  const resolution = textResolutionForZoom(context.zoom);
78
- const label = new Text({
87
+ const title = new Text({
79
88
  text: "",
80
89
  style: {
81
- fill: context.palette.text,
82
- fontFamily: BOARD_FONT_STACK,
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, waveform, chrome, label);
96
+ root.addChild(plate, wave, title);
91
97
  partsByContainer.set(root, {
92
98
  root,
93
99
  plate,
94
- waveform,
95
- chrome,
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 { CARD_PADDING, CARD_RADIUS, CardShell, CardShellState, FOOTER_HEIGHT, createCardShell, createLabel, positionShell };
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 { Container, Graphics, Text } from "pixi.js";
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 { CARD_PADDING, CARD_RADIUS, FOOTER_HEIGHT, createCardShell, createLabel, positionShell };
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.palette.border,
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 || selected || error) parts.placeholder.rect(0, 0, width, height).stroke({
41
- color: selected ? context.palette.brand : context.palette.border,
42
- width: selected ? 2 : 1,
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 { containCoverRect, ellipsizeWrappedLines, fileCardRenderer, fitLineWithEllipsis, fitTextToLines, isFileItem };
9
+ export { fileCardRenderer, isFileItem };