@neta-art/cohub 11.5.1 → 12.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.
Files changed (82) hide show
  1. package/dist/board/editor/animation.js +2 -1
  2. package/dist/board/editor/creation.js +1 -1
  3. package/dist/board/editor/document-edits.d.ts +1 -1
  4. package/dist/board/editor/document-edits.js +1 -19
  5. package/dist/board/editor/document.js +2 -1
  6. package/dist/board/editor/index.d.ts +2 -1
  7. package/dist/board/editor/index.js +2 -1
  8. package/dist/board/editor/snapshots.js +11 -13
  9. package/dist/board/export/scene.js +1 -0
  10. package/dist/board/model/client-geometry.d.ts +22 -0
  11. package/dist/board/model/client-geometry.js +94 -0
  12. package/dist/board/model/document-share.d.ts +5 -0
  13. package/dist/board/model/document-share.js +27 -0
  14. package/dist/board/model/index.d.ts +5 -4
  15. package/dist/board/model/index.js +4 -3
  16. package/dist/board/model/items/create.d.ts +5 -1
  17. package/dist/board/model/items/create.js +29 -58
  18. package/dist/board/model/items/index.d.ts +2 -2
  19. package/dist/board/model/items/index.js +2 -2
  20. package/dist/board/model/items/registry.js +2 -5
  21. package/dist/board/model/json.d.ts +4 -0
  22. package/dist/board/model/json.js +22 -0
  23. package/dist/board/model/media-playback.d.ts +6 -3
  24. package/dist/board/player/index.d.ts +6 -2
  25. package/dist/board/player/index.js +33 -15
  26. package/dist/board/render/card-tag.d.ts +0 -1
  27. package/dist/board/render/card-tag.js +15 -17
  28. package/dist/board/render/index.d.ts +3 -3
  29. package/dist/board/render/index.js +3 -3
  30. package/dist/board/render/renderers/arrow-card-renderer.js +8 -6
  31. package/dist/board/render/renderers/audio-card-renderer.js +10 -6
  32. package/dist/board/render/renderers/base-card-renderer.d.ts +1 -1
  33. package/dist/board/render/renderers/base-card-renderer.js +2 -3
  34. package/dist/board/render/renderers/board-renderer-registry.d.ts +6 -2
  35. package/dist/board/render/renderers/custom-card-renderer.js +23 -18
  36. package/dist/board/render/renderers/file-card-renderer.js +14 -9
  37. package/dist/board/render/renderers/frame-card-renderer.js +7 -4
  38. package/dist/board/render/renderers/image-card-renderer.js +13 -49
  39. package/dist/board/render/renderers/model-card-renderer.js +4 -1
  40. package/dist/board/render/renderers/shape-card-renderer.js +8 -6
  41. package/dist/board/render/renderers/task-card-renderer.js +13 -10
  42. package/dist/board/render/renderers/text-card-renderer.js +7 -5
  43. package/dist/board/render/renderers/unknown-card-renderer.js +8 -6
  44. package/dist/board/render/renderers/video-card-renderer.js +19 -18
  45. package/dist/board/render/script-host.d.ts +2 -0
  46. package/dist/board/render/script-host.js +44 -9
  47. package/dist/board/render/script-resolution.d.ts +4 -0
  48. package/dist/board/render/script-resolution.js +18 -0
  49. package/dist/board/render/surface.d.ts +9 -2
  50. package/dist/board/render/surface.js +15 -1
  51. package/dist/board/render/text-resolution.d.ts +4 -7
  52. package/dist/board/render/text-resolution.js +20 -22
  53. package/dist/board/replica/index.js +4 -1
  54. package/dist/board/stage/assets.d.ts +12 -8
  55. package/dist/board/stage/assets.js +173 -88
  56. package/dist/board/stage/canvas-size.d.ts +18 -0
  57. package/dist/board/stage/canvas-size.js +31 -0
  58. package/dist/board/stage/index.d.ts +3 -3
  59. package/dist/board/stage/index.js +3 -3
  60. package/dist/board/stage/lru.d.ts +3 -2
  61. package/dist/board/stage/lru.js +8 -4
  62. package/dist/board/stage/pointer.d.ts +1 -1
  63. package/dist/board/stage/pointer.js +4 -5
  64. package/dist/board/stage/scene.d.ts +8 -1
  65. package/dist/board/stage/scene.js +72 -10
  66. package/dist/board/stage/stage.d.ts +1 -0
  67. package/dist/board/stage/stage.js +151 -63
  68. package/dist/board/stage/text-resolution-tracker.d.ts +8 -0
  69. package/dist/board/stage/text-resolution-tracker.js +33 -0
  70. package/dist/board/stage/views.d.ts +7 -2
  71. package/dist/board/stage/views.js +50 -21
  72. package/dist/chunks/environment.d.ts +16 -2
  73. package/dist/index.js +65 -22
  74. package/dist/protocol/dist/board-constants.js +56 -1
  75. package/dist/protocol/dist/board-layout.d.ts +8 -1
  76. package/dist/protocol/dist/board-layout.js +16 -4
  77. package/dist/protocol/dist/board-model.js +13 -19
  78. package/dist/protocol/dist/board-schema.d.ts +52 -0
  79. package/dist/protocol/dist/board-schema.js +8 -0
  80. package/dist/protocol/dist/core/media.js +1 -0
  81. package/dist/protocol/dist/index.d.ts +2 -2
  82. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { BoardItemCapabilities, BoardItemDefinition, BoardItemOf, BoardItemResizeMode, FULL_CAPABILITIES, defineBoardItem } from "./definition.js";
2
2
  import { builtinBoardItems } from "./builtin.js";
3
- import { BoardAppMetadata, BoardItemEntry, BoardMediaItemKind, boardItemOrigin, boardOriginKey, createAppBoardItem, createArrowBoardItem, createDrawBoardItem, createFileNodeForPath, createFrameBoardItem, createMediaBoardItem, createShapeBoardItem, createTaskBoardItem, createTaskResultItems, createTextBoardItem, mediaFrameSize, titleForBoardItem } from "./create.js";
3
+ import { BoardAppMetadata, BoardItemEntry, BoardMediaItemKind, boardItemOrigin, boardOriginKey, boardTaskCardSize, createAppBoardItem, createArrowBoardItem, createDrawBoardItem, createFileNodeForPath, createFrameBoardItem, createMediaBoardItem, createShapeBoardItem, createTaskBoardItem, createTaskResultItems, createTextBoardItem, mediaFrameSize, titleForBoardItem } from "./create.js";
4
4
  import { createBoardEntityId, createBoardItemId } from "./id.js";
5
5
  import { BoardItemInput, BoardRegistry, createBoardRegistry, defaultBoardRegistry } from "./registry.js";
6
- export { BoardAppMetadata, BoardItemCapabilities, BoardItemDefinition, BoardItemEntry, BoardItemInput, BoardItemOf, BoardItemResizeMode, BoardMediaItemKind, BoardRegistry, FULL_CAPABILITIES, boardItemOrigin, boardOriginKey, builtinBoardItems, createAppBoardItem, createArrowBoardItem, createBoardEntityId, createBoardItemId, createBoardRegistry, createDrawBoardItem, createFileNodeForPath, createFrameBoardItem, createMediaBoardItem, createShapeBoardItem, createTaskBoardItem, createTaskResultItems, createTextBoardItem, defaultBoardRegistry, defineBoardItem, mediaFrameSize, titleForBoardItem };
6
+ export { BoardAppMetadata, BoardItemCapabilities, BoardItemDefinition, BoardItemEntry, BoardItemInput, BoardItemOf, BoardItemResizeMode, BoardMediaItemKind, BoardRegistry, FULL_CAPABILITIES, boardItemOrigin, boardOriginKey, boardTaskCardSize, builtinBoardItems, createAppBoardItem, createArrowBoardItem, createBoardEntityId, createBoardItemId, createBoardRegistry, createDrawBoardItem, createFileNodeForPath, createFrameBoardItem, createMediaBoardItem, createShapeBoardItem, createTaskBoardItem, createTaskResultItems, createTextBoardItem, defaultBoardRegistry, defineBoardItem, mediaFrameSize, titleForBoardItem };
@@ -1,6 +1,6 @@
1
1
  import { FULL_CAPABILITIES, defineBoardItem } from "./definition.js";
2
2
  import { builtinBoardItems } from "./builtin.js";
3
3
  import { createBoardEntityId, createBoardItemId } from "./id.js";
4
- import { boardItemOrigin, boardOriginKey, createAppBoardItem, createArrowBoardItem, createDrawBoardItem, createFileNodeForPath, createFrameBoardItem, createMediaBoardItem, createShapeBoardItem, createTaskBoardItem, createTaskResultItems, createTextBoardItem, mediaFrameSize, titleForBoardItem } from "./create.js";
4
+ import { boardItemOrigin, boardOriginKey, boardTaskCardSize, createAppBoardItem, createArrowBoardItem, createDrawBoardItem, createFileNodeForPath, createFrameBoardItem, createMediaBoardItem, createShapeBoardItem, createTaskBoardItem, createTaskResultItems, createTextBoardItem, mediaFrameSize, titleForBoardItem } from "./create.js";
5
5
  import { createBoardRegistry, defaultBoardRegistry } from "./registry.js";
6
- export { FULL_CAPABILITIES, boardItemOrigin, boardOriginKey, builtinBoardItems, createAppBoardItem, createArrowBoardItem, createBoardEntityId, createBoardItemId, createBoardRegistry, createDrawBoardItem, createFileNodeForPath, createFrameBoardItem, createMediaBoardItem, createShapeBoardItem, createTaskBoardItem, createTaskResultItems, createTextBoardItem, defaultBoardRegistry, defineBoardItem, mediaFrameSize, titleForBoardItem };
6
+ export { FULL_CAPABILITIES, boardItemOrigin, boardOriginKey, boardTaskCardSize, builtinBoardItems, createAppBoardItem, createArrowBoardItem, createBoardEntityId, createBoardItemId, createBoardRegistry, createDrawBoardItem, createFileNodeForPath, createFrameBoardItem, createMediaBoardItem, createShapeBoardItem, createTaskBoardItem, createTaskResultItems, createTextBoardItem, defaultBoardRegistry, defineBoardItem, mediaFrameSize, titleForBoardItem };
@@ -1,13 +1,10 @@
1
+ import { boardDefaultSize } from "../../../protocol/dist/board-constants.js";
1
2
  import { hasAuthoredSize, parseBoardItem } from "../../../protocol/dist/board-model.js";
2
3
  import { frameContainsPoint, itemBounds } from "../geometry.js";
3
4
  import { FULL_CAPABILITIES } from "./definition.js";
4
5
  import { builtinBoardItems } from "./builtin.js";
5
6
  import { createBoardItemId } from "./id.js";
6
7
  //#region src/board/model/items/registry.ts
7
- const DEFAULT_ITEM_SIZE = {
8
- width: 240,
9
- height: 160
10
- };
11
8
  function createBoardRegistry(definitions = []) {
12
9
  const byType = /* @__PURE__ */ new Map();
13
10
  for (const definition of [...builtinBoardItems, ...definitions]) byType.set(definition.type, definition);
@@ -52,7 +49,7 @@ function createBoardRegistry(definitions = []) {
52
49
  create(type, { props = {}, at, size, id = createBoardItemId() }) {
53
50
  const valid = validateProps(type, props);
54
51
  if (!valid.ok) throw new Error(valid.message);
55
- const box = size ?? byType.get(type)?.size ?? DEFAULT_ITEM_SIZE;
52
+ const box = size ?? byType.get(type)?.size ?? boardDefaultSize(type);
56
53
  const placement = hasAuthoredSize(type) ? {
57
54
  position: {
58
55
  x: at.x - box.width / 2,
@@ -0,0 +1,4 @@
1
+ //#region src/board/model/json.d.ts
2
+ declare function sameJson(a: unknown, b: unknown): boolean;
3
+ //#endregion
4
+ export { sameJson };
@@ -0,0 +1,22 @@
1
+ //#region src/board/model/json.ts
2
+ function sameJson(a, b) {
3
+ if (a === b) return true;
4
+ if (!a || !b || typeof a !== "object" || typeof b !== "object") return false;
5
+ if (Array.isArray(a) || Array.isArray(b)) {
6
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
7
+ for (let index = 0; index < a.length; index += 1) if (!sameJson(a[index], b[index])) return false;
8
+ return true;
9
+ }
10
+ const left = a;
11
+ const right = b;
12
+ let members = 0;
13
+ for (const key of Object.keys(left)) {
14
+ if (left[key] === void 0) continue;
15
+ members += 1;
16
+ if (!sameJson(left[key], right[key])) return false;
17
+ }
18
+ for (const key of Object.keys(right)) if (right[key] !== void 0) members -= 1;
19
+ return members === 0;
20
+ }
21
+ //#endregion
22
+ export { sameJson };
@@ -1,8 +1,11 @@
1
1
  import { BoardSceneItem } from "./scene.js";
2
2
  //#region src/board/model/media-playback.d.ts
3
+ type BoardAssetUrlOptions = {
4
+ fresh?: boolean;
5
+ };
3
6
  type BoardAssetSource = {
4
- resolveFileUrl: (path: string) => Promise<string | null>;
5
- resolvePlaybackUrl?: (path: string) => Promise<string | null>;
7
+ resolveFileUrl: (path: string, options?: BoardAssetUrlOptions) => Promise<string | null>;
8
+ resolvePlaybackUrl?: (path: string, options?: BoardAssetUrlOptions) => Promise<string | null>;
6
9
  };
7
10
  declare function resolveBoardMediaUrl(src: string, source: BoardAssetSource, purpose?: "preview" | "playback"): Promise<string | null>;
8
11
  type BoardPlayableMedia = {
@@ -17,4 +20,4 @@ declare function playableBoardMediaList(item: BoardSceneItem | null, assetSource
17
20
  declare function playableBoardMedia(item: BoardSceneItem | null, assetSource: BoardAssetSource, artifactId?: string | null): BoardPlayableMedia | null;
18
21
  declare function resetBoardPlaybackUrlCache(): void;
19
22
  //#endregion
20
- export { BoardAssetSource, BoardPlayableMedia, playableBoardMedia, playableBoardMediaList, resetBoardPlaybackUrlCache, resolveBoardMediaUrl };
23
+ export { BoardAssetSource, BoardAssetUrlOptions, BoardPlayableMedia, playableBoardMedia, playableBoardMediaList, resetBoardPlaybackUrlCache, resolveBoardMediaUrl };
@@ -10,7 +10,11 @@ type BoardPlayerFrame = {
10
10
  playbackTime: number | null;
11
11
  running: boolean;
12
12
  };
13
- declare function playbackTimeAt(playback: BoardPlaybackSnapshot, document: BoardDocument, now: number): number | null;
13
+ type BoardPlaybackClock = {
14
+ time: number | null;
15
+ advancing: boolean;
16
+ };
17
+ declare function playbackClockAt(playback: BoardPlaybackSnapshot, document: BoardDocument, now: number): BoardPlaybackClock;
14
18
  declare function createBoardPlayer(options?: {
15
19
  resolveColor?: BoardColorResolver;
16
20
  }): {
@@ -21,4 +25,4 @@ declare function createBoardPlayer(options?: {
21
25
  type BoardPlayer = ReturnType<typeof createBoardPlayer>;
22
26
  declare function nextLocalPlayback(current: BoardPlaybackSnapshot | null, command: BoardPlaybackCommand, document: BoardDocument, now?: number): BoardPlaybackSnapshot | null;
23
27
  //#endregion
24
- export { BoardPlayer, BoardPlayerFrame, createBoardPlayer, nextLocalPlayback, playbackTimeAt };
28
+ export { BoardPlaybackClock, BoardPlayer, BoardPlayerFrame, createBoardPlayer, nextLocalPlayback, playbackClockAt };
@@ -5,16 +5,35 @@ import { createBoardEntityId } from "../model/items/id.js";
5
5
  const ENTER_ANIMATION = "\0enter";
6
6
  const ENTER_STAGGER_MS = 45;
7
7
  const ENTER_MAX_ITEMS = 80;
8
- function playbackTimeAt(playback, document, now) {
8
+ const SETTLED = {
9
+ time: null,
10
+ advancing: false
11
+ };
12
+ function playbackClockAt(playback, document, now) {
9
13
  const animation = document.animations[playback.animationId];
10
- if (!animation || playback.status === "stopped") return null;
11
- if (playback.status !== "playing") return Math.min(playback.position, animation.duration);
12
- let position = playback.position + Math.max(0, now - playback.effectiveAt) * playback.timeScale;
14
+ if (!animation || playback.status === "stopped") return SETTLED;
15
+ if (playback.status !== "playing") return {
16
+ time: Math.min(playback.position, animation.duration),
17
+ advancing: false
18
+ };
19
+ const position = playback.position + Math.max(0, now - playback.effectiveAt) * playback.timeScale;
13
20
  const pause = animation.markers.find((marker) => marker.pause && marker.at > playback.position && marker.at <= position);
14
- if (pause) return pause.at;
15
- if (animation.loop || animation.play === "always") return animation.duration > 0 ? position % animation.duration : 0;
16
- position = Math.min(position, animation.duration);
17
- return animation.end === "reset" && position >= animation.duration ? null : position;
21
+ if (pause) return {
22
+ time: pause.at,
23
+ advancing: false
24
+ };
25
+ if (animation.loop || animation.play === "always") return {
26
+ time: position % animation.duration,
27
+ advancing: true
28
+ };
29
+ if (position < animation.duration) return {
30
+ time: position,
31
+ advancing: true
32
+ };
33
+ return {
34
+ time: animation.end === "reset" ? null : animation.duration,
35
+ advancing: false
36
+ };
18
37
  }
19
38
  function createBoardPlayer(options = {}) {
20
39
  let document = null;
@@ -89,11 +108,10 @@ function createBoardPlayer(options = {}) {
89
108
  }
90
109
  let playbackTime = null;
91
110
  if (playback && playback.animationId !== exclude) {
92
- playbackTime = playbackTimeAt(playback, current, wallNow);
93
- if (playbackTime !== null) {
94
- times.set(playback.animationId, playbackTime);
95
- if (playback.status === "playing") running = true;
96
- }
111
+ const clock = playbackClockAt(playback, current, wallNow);
112
+ playbackTime = clock.time;
113
+ if (playbackTime !== null) times.set(playback.animationId, playbackTime);
114
+ if (clock.advancing) running = true;
97
115
  }
98
116
  if (entrance) {
99
117
  times.set(ENTER_ANIMATION, now - entrance.startedAt);
@@ -111,7 +129,7 @@ function createBoardPlayer(options = {}) {
111
129
  };
112
130
  }
113
131
  function nextLocalPlayback(current, command, document, now = Date.now()) {
114
- const position = current ? playbackTimeAt(current, document, now) ?? 0 : 0;
132
+ const position = current ? playbackClockAt(current, document, now).time ?? 0 : 0;
115
133
  const base = {
116
134
  effectiveAt: now,
117
135
  commandId: command.commandId,
@@ -159,4 +177,4 @@ function nextLocalPlayback(current, command, document, now = Date.now()) {
159
177
  }
160
178
  }
161
179
  //#endregion
162
- export { createBoardPlayer, nextLocalPlayback, playbackTimeAt };
180
+ export { createBoardPlayer, nextLocalPlayback, playbackClockAt };
@@ -11,7 +11,6 @@ type CardTag = {
11
11
  icon: Graphics;
12
12
  text: Text | null;
13
13
  sig: string;
14
- resolution: number;
15
14
  width: number;
16
15
  };
17
16
  declare function createCardTag(): CardTag;
@@ -1,5 +1,5 @@
1
1
  import { fitTextToWidth } from "./text-fit.js";
2
- import { syncTextResolution, textResolutionForZoom } from "./text-resolution.js";
2
+ import { syncTextResolution } from "./text-resolution.js";
3
3
  import { Container, Graphics, Text } from "pixi.js";
4
4
  //#region src/board/render/card-tag.ts
5
5
  const CARD_TAG_SIZE = 11;
@@ -177,13 +177,15 @@ function createCardTag() {
177
177
  icon,
178
178
  text: null,
179
179
  sig: "",
180
- resolution: 0,
181
180
  width: 0
182
181
  };
183
182
  }
183
+ function tagScale(zoom) {
184
+ return Math.min(MAX_GROWTH, Math.max(1, 1 / Math.max(zoom, .01)));
185
+ }
184
186
  function zoomCardTag(tag, zoom) {
185
187
  if (!tag.text || !tag.sig) return;
186
- const scale = Math.min(MAX_GROWTH, Math.max(1, 1 / Math.max(zoom, .01)));
188
+ const scale = tagScale(zoom);
187
189
  const span = 17 + tag.text.width;
188
190
  tag.root.scale.set(scale);
189
191
  tag.root.position.set(0, -18 * scale);
@@ -197,7 +199,6 @@ function syncCardTag(tag, input, context) {
197
199
  return;
198
200
  }
199
201
  if (!tag.text) {
200
- tag.resolution = textResolutionForZoom(context.zoom);
201
202
  tag.text = new Text({
202
203
  text: "",
203
204
  style: {
@@ -205,30 +206,27 @@ function syncCardTag(tag, input, context) {
205
206
  fontSize: 11,
206
207
  fontWeight: "500"
207
208
  },
208
- resolution: tag.resolution,
209
209
  roundPixels: true
210
210
  });
211
211
  tag.root.addChild(tag.text);
212
212
  }
213
- syncTextResolution(tag.text, tag, context.zoom);
214
213
  const sig = [
215
214
  input.glyph,
216
215
  input.text,
217
216
  input.width,
218
217
  context.themeKey
219
218
  ].join("|");
220
- if (sig === tag.sig) {
221
- zoomCardTag(tag, context.zoom);
222
- return;
219
+ if (sig !== tag.sig) {
220
+ tag.sig = sig;
221
+ const color = context.palette.muted;
222
+ const pixel = context.style.icons === "pixel";
223
+ drawCardGlyph(tag.icon.clear(), input.glyph, color, pixel);
224
+ tag.text.style.fill = color;
225
+ tag.text.style.fontFamily = context.style.font;
226
+ fitTextToWidth(tag.text, input.text, Math.max(1, input.width - ICON - GAP));
227
+ tag.text.position.set(17, (ICON - tag.text.height) / 2);
223
228
  }
224
- tag.sig = sig;
225
- const color = context.palette.muted;
226
- const pixel = context.style.icons === "pixel";
227
- drawCardGlyph(tag.icon.clear(), input.glyph, color, pixel);
228
- tag.text.style.fill = color;
229
- tag.text.style.fontFamily = context.style.font;
230
- fitTextToWidth(tag.text, input.text, Math.max(1, input.width - ICON - GAP));
231
- tag.text.position.set(17, (ICON - tag.text.height) / 2);
229
+ syncTextResolution(tag.text, context.textResolution * tagScale(context.zoom));
232
230
  zoomCardTag(tag, context.zoom);
233
231
  }
234
232
  //#endregion
@@ -11,10 +11,10 @@ import { defaultBoardPalette, itemAlpha, itemColor } from "./palette.js";
11
11
  import { BoardScriptHostOptions, BrowserBoardScriptHost, createBoardScriptHost } from "./script-host.js";
12
12
  import { prepareBrowserBoardScripts } from "./script-export.js";
13
13
  import { dashPattern, endAngle, roundRectPoints, traceArrowhead, tracePolyline, trimPolyline } from "./stroke.js";
14
- import { CardElevation, CardRect, CardSurface, PIXEL_STEP, cardElevation, cardOutlinePoints, cardShadow, containRect, drawCardShadow, drawCardSurface, isBoardCard, traceCardOutline, tracePixelRect } from "./surface.js";
14
+ import { CardCrop, CardElevation, CardRect, CardSurface, PIXEL_STEP, cardElevation, cardOutlinePoints, cardShadow, containRect, drawCardShadow, drawCardSurface, fillCardPicture, isBoardCard, traceCardOutline, tracePixelRect } from "./surface.js";
15
15
  import { BOARD_EFFECT_MAX_PARTICLES } from "./renderers/effect-card-renderer.js";
16
16
  import { ellipsizeWrappedLines, fitLineWithEllipsis, fitTextToLines, fitTextToWidth } from "./text-fit.js";
17
17
  import { BOARD_FONT_STACKS, ensureBoardTextMeasurement, installBoardTextMeasurement } from "./text-measurement.js";
18
- import { boardCardDetailed, getBoardResolution, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket } from "./text-resolution.js";
18
+ import { boardCardDetailed, boardTextResolution, getBoardResolution, syncTextResolution, syncTextWrapWidth, textZoomBucket } from "./text-resolution.js";
19
19
  import { VIDEO_THUMBNAIL_MAX_EDGE, VideoNaturalSize, loadVideoThumbnailTexture, videoTextureNaturalSize, videoThumbnailSize } from "./video-thumbnail.js";
20
- export { BOARD_EFFECT_MAX_PARTICLES, BOARD_FONT_STACKS, BoardBackgroundContext, BoardCardRenderer, BoardCardRendererResolver, BoardCssPaint, BoardMediaAction, BoardRenderContext, BoardRenderDiagnostic, BoardRenderLabels, BoardRenderPalette, BoardRenderStyle, BoardScriptHost, BoardScriptHostOptions, BoardSelectionStyle, BoardShadowStyle, BrowserBoardScriptHost, CARD_TAG_SIZE, CardElevation, CardGlyph, CardRect, CardSurface, CardTag, ClipGroup, DEFAULT_BOARD_RENDER_LABELS, PIXEL_STEP, VIDEO_THUMBNAIL_MAX_EDGE, VideoNaturalSize, boardCardDetailed, boardMediaActionAt, cardElevation, cardOutlinePoints, cardShadow, clippingAncestor, containRect, createBoardBackground, createBoardCardRendererResolver, createBoardRenderSampler, createBoardScriptHost, createCardTag, dashPattern, defaultBoardPalette, defaultBoardRenderStyle, drawCardGlyph, drawCardShadow, drawCardSurface, ellipsizeWrappedLines, endAngle, ensureBoardTextMeasurement, fitLineWithEllipsis, fitTextToLines, fitTextToWidth, formatBoardDuration, getBoardCardRenderer, getBoardResolution, inspectBoardItems, inspectBoardScene, installBoardTextMeasurement, isBoardCard, isClippingFrame, itemAlpha, itemColor, loadVideoThumbnailTexture, measureBoardText, mediaPlayBadgeHit, mediaPlayBadgeVisible, mediaPlayKeyCenter, parseBoardCssColor, parseBoardCssPaint, prepareBrowserBoardScripts, resolveBoardRenderStyle, roundRectPoints, syncCardTag, syncClipGroup, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket, traceArrowhead, traceCardOutline, traceCube, traceFrameOutline, tracePixelRect, tracePolyline, trimPolyline, updateBoardBackground, videoTextureNaturalSize, videoThumbnailSize, zoomCardTag };
20
+ export { BOARD_EFFECT_MAX_PARTICLES, BOARD_FONT_STACKS, BoardBackgroundContext, BoardCardRenderer, BoardCardRendererResolver, BoardCssPaint, BoardMediaAction, BoardRenderContext, BoardRenderDiagnostic, BoardRenderLabels, BoardRenderPalette, BoardRenderStyle, BoardScriptHost, BoardScriptHostOptions, BoardSelectionStyle, BoardShadowStyle, BrowserBoardScriptHost, CARD_TAG_SIZE, CardCrop, CardElevation, CardGlyph, CardRect, CardSurface, CardTag, ClipGroup, DEFAULT_BOARD_RENDER_LABELS, PIXEL_STEP, VIDEO_THUMBNAIL_MAX_EDGE, VideoNaturalSize, boardCardDetailed, boardMediaActionAt, boardTextResolution, cardElevation, cardOutlinePoints, cardShadow, clippingAncestor, containRect, createBoardBackground, createBoardCardRendererResolver, createBoardRenderSampler, createBoardScriptHost, createCardTag, dashPattern, defaultBoardPalette, defaultBoardRenderStyle, drawCardGlyph, drawCardShadow, drawCardSurface, ellipsizeWrappedLines, endAngle, ensureBoardTextMeasurement, fillCardPicture, fitLineWithEllipsis, fitTextToLines, fitTextToWidth, formatBoardDuration, getBoardCardRenderer, getBoardResolution, inspectBoardItems, inspectBoardScene, installBoardTextMeasurement, isBoardCard, isClippingFrame, itemAlpha, itemColor, loadVideoThumbnailTexture, measureBoardText, mediaPlayBadgeHit, mediaPlayBadgeVisible, mediaPlayKeyCenter, parseBoardCssColor, parseBoardCssPaint, prepareBrowserBoardScripts, resolveBoardRenderStyle, roundRectPoints, syncCardTag, syncClipGroup, syncTextResolution, syncTextWrapWidth, textZoomBucket, traceArrowhead, traceCardOutline, traceCube, traceFrameOutline, tracePixelRect, tracePolyline, trimPolyline, updateBoardBackground, videoTextureNaturalSize, videoThumbnailSize, zoomCardTag };
@@ -5,11 +5,11 @@ import { BOARD_FONT_STACKS, ensureBoardTextMeasurement, installBoardTextMeasurem
5
5
  import { inspectBoardItems, inspectBoardScene, measureBoardText } from "./diagnostics.js";
6
6
  import { createBoardBackground, updateBoardBackground } from "./board-background.js";
7
7
  import { ellipsizeWrappedLines, fitLineWithEllipsis, fitTextToLines, fitTextToWidth } from "./text-fit.js";
8
- import { boardCardDetailed, getBoardResolution, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket } from "./text-resolution.js";
8
+ import { boardCardDetailed, boardTextResolution, getBoardResolution, syncTextResolution, syncTextWrapWidth, textZoomBucket } from "./text-resolution.js";
9
9
  import { CARD_TAG_SIZE, createCardTag, drawCardGlyph, formatBoardDuration, syncCardTag, traceCube, zoomCardTag } from "./card-tag.js";
10
10
  import { clippingAncestor, isClippingFrame, syncClipGroup, traceFrameOutline } from "./clip.js";
11
11
  import { dashPattern, endAngle, roundRectPoints, traceArrowhead, tracePolyline, trimPolyline } from "./stroke.js";
12
- import { PIXEL_STEP, cardElevation, cardOutlinePoints, cardShadow, containRect, drawCardShadow, drawCardSurface, isBoardCard, traceCardOutline, tracePixelRect } from "./surface.js";
12
+ import { PIXEL_STEP, cardElevation, cardOutlinePoints, cardShadow, containRect, drawCardShadow, drawCardSurface, fillCardPicture, isBoardCard, traceCardOutline, tracePixelRect } from "./surface.js";
13
13
  import { boardMediaActionAt, mediaPlayBadgeHit, mediaPlayBadgeVisible, mediaPlayKeyCenter } from "./media-interaction.js";
14
14
  import { BOARD_EFFECT_MAX_PARTICLES } from "./renderers/effect-card-renderer.js";
15
15
  import { DEFAULT_BOARD_RENDER_LABELS, createBoardCardRendererResolver, getBoardCardRenderer } from "./renderers/board-renderer-registry.js";
@@ -17,4 +17,4 @@ import { createBoardScriptHost } from "./script-host.js";
17
17
  import { prepareBrowserBoardScripts } from "./script-export.js";
18
18
  import { defaultBoardRenderStyle, resolveBoardRenderStyle } from "./style.js";
19
19
  import { VIDEO_THUMBNAIL_MAX_EDGE, loadVideoThumbnailTexture, videoTextureNaturalSize, videoThumbnailSize } from "./video-thumbnail.js";
20
- export { BOARD_EFFECT_MAX_PARTICLES, BOARD_FONT_STACKS, CARD_TAG_SIZE, DEFAULT_BOARD_RENDER_LABELS, PIXEL_STEP, VIDEO_THUMBNAIL_MAX_EDGE, boardCardDetailed, boardMediaActionAt, cardElevation, cardOutlinePoints, cardShadow, clippingAncestor, containRect, createBoardBackground, createBoardCardRendererResolver, createBoardRenderSampler, createBoardScriptHost, createCardTag, dashPattern, defaultBoardPalette, defaultBoardRenderStyle, drawCardGlyph, drawCardShadow, drawCardSurface, ellipsizeWrappedLines, endAngle, ensureBoardTextMeasurement, fitLineWithEllipsis, fitTextToLines, fitTextToWidth, formatBoardDuration, getBoardCardRenderer, getBoardResolution, inspectBoardItems, inspectBoardScene, installBoardTextMeasurement, isBoardCard, isClippingFrame, itemAlpha, itemColor, loadVideoThumbnailTexture, measureBoardText, mediaPlayBadgeHit, mediaPlayBadgeVisible, mediaPlayKeyCenter, parseBoardCssColor, parseBoardCssPaint, prepareBrowserBoardScripts, resolveBoardRenderStyle, roundRectPoints, syncCardTag, syncClipGroup, syncTextResolution, syncTextWrapWidth, textResolutionForZoom, textZoomBucket, traceArrowhead, traceCardOutline, traceCube, traceFrameOutline, tracePixelRect, tracePolyline, trimPolyline, updateBoardBackground, videoTextureNaturalSize, videoThumbnailSize, zoomCardTag };
20
+ export { BOARD_EFFECT_MAX_PARTICLES, BOARD_FONT_STACKS, CARD_TAG_SIZE, DEFAULT_BOARD_RENDER_LABELS, PIXEL_STEP, VIDEO_THUMBNAIL_MAX_EDGE, boardCardDetailed, boardMediaActionAt, boardTextResolution, cardElevation, cardOutlinePoints, cardShadow, clippingAncestor, containRect, createBoardBackground, createBoardCardRendererResolver, createBoardRenderSampler, createBoardScriptHost, createCardTag, dashPattern, defaultBoardPalette, defaultBoardRenderStyle, drawCardGlyph, drawCardShadow, drawCardSurface, ellipsizeWrappedLines, endAngle, ensureBoardTextMeasurement, fillCardPicture, fitLineWithEllipsis, fitTextToLines, fitTextToWidth, formatBoardDuration, getBoardCardRenderer, getBoardResolution, inspectBoardItems, inspectBoardScene, installBoardTextMeasurement, isBoardCard, isClippingFrame, itemAlpha, itemColor, loadVideoThumbnailTexture, measureBoardText, mediaPlayBadgeHit, mediaPlayBadgeVisible, mediaPlayKeyCenter, parseBoardCssColor, parseBoardCssPaint, prepareBrowserBoardScripts, resolveBoardRenderStyle, roundRectPoints, syncCardTag, syncClipGroup, syncTextResolution, syncTextWrapWidth, textZoomBucket, traceArrowhead, traceCardOutline, traceCube, traceFrameOutline, tracePixelRect, tracePolyline, trimPolyline, updateBoardBackground, videoTextureNaturalSize, videoThumbnailSize, zoomCardTag };
@@ -1,7 +1,7 @@
1
1
  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
- import { syncTextResolution, textResolutionForZoom } from "../text-resolution.js";
4
+ import { syncTextResolution } from "../text-resolution.js";
5
5
  import { dashPattern, endAngle, traceArrowhead, tracePolyline, trimPolyline } from "../stroke.js";
6
6
  import { drawCardSurface } from "../surface.js";
7
7
  import { drawFarStroke } from "./far-plate.js";
@@ -18,7 +18,6 @@ function sync(container, item, context) {
18
18
  parts.line.alpha = itemAlpha(context, style.stroke);
19
19
  const color = itemColor(context, style.stroke, "brand");
20
20
  const size = style.strokeWidth ?? 2.5;
21
- syncTextResolution(parts.label, parts, context.zoom);
22
21
  const resolved = resolveSceneArrow(item, context.scene);
23
22
  const path = trimPolyline(resolved.path, style.trim);
24
23
  const lineSig = [
@@ -85,6 +84,7 @@ function sync(container, item, context) {
85
84
  border: context.palette.border
86
85
  });
87
86
  }
87
+ syncTextResolution(parts.label, context.textResolution);
88
88
  const visible = props.label.length > 0 && (style.trim === void 0 || style.trim >= .5);
89
89
  parts.label.visible = visible;
90
90
  parts.backdrop.visible = visible;
@@ -98,7 +98,6 @@ const arrowCardRenderer = {
98
98
  create: (item, context) => {
99
99
  const root = new Container();
100
100
  const line = new Graphics();
101
- const resolution = textResolutionForZoom(context.zoom);
102
101
  const label = new Text({
103
102
  text: "",
104
103
  style: {
@@ -107,7 +106,7 @@ const arrowCardRenderer = {
107
106
  fontSize: 14,
108
107
  fontWeight: "500"
109
108
  },
110
- resolution,
109
+ resolution: context.textResolution,
111
110
  roundPixels: true
112
111
  });
113
112
  label.anchor.set(.5);
@@ -119,8 +118,7 @@ const arrowCardRenderer = {
119
118
  backdrop,
120
119
  label,
121
120
  lineSig: "",
122
- labelSig: "",
123
- resolution
121
+ labelSig: ""
124
122
  });
125
123
  if (item.type === "arrow") sync(root, item, context);
126
124
  return root;
@@ -128,6 +126,10 @@ const arrowCardRenderer = {
128
126
  update: (container, item, context) => {
129
127
  if (item.type === "arrow") sync(container, item, context);
130
128
  },
129
+ resolution: (container, _item, context) => {
130
+ const parts = partsByContainer.get(container);
131
+ if (parts) syncTextResolution(parts.label, context.textResolution);
132
+ },
131
133
  renderFar: (graphics, item, context) => {
132
134
  if (item.type !== "arrow") return;
133
135
  const arrow = item;
@@ -1,6 +1,6 @@
1
1
  import { getMediaResourceTitle } from "../../model/media.js";
2
2
  import { fitTextToWidth } from "../text-fit.js";
3
- import { boardCardDetailed, syncTextResolution, textResolutionForZoom } from "../text-resolution.js";
3
+ import { boardCardDetailed, syncTextResolution } from "../text-resolution.js";
4
4
  import { formatBoardDuration } from "../card-tag.js";
5
5
  import { drawAudioWaveform } from "../audio-waveform.js";
6
6
  import { cardElevation, drawCardSurface } from "../surface.js";
@@ -25,12 +25,15 @@ function audioKeyCenter(width, height) {
25
25
  function sync(container, item, context) {
26
26
  const parts = partsByContainer.get(container);
27
27
  if (!parts) return;
28
+ syncContent(parts, item, context);
29
+ syncTextResolution(parts.title, context.textResolution);
30
+ }
31
+ function syncContent(parts, item, context) {
28
32
  positionShell(parts.root, item);
29
33
  const { width, height } = item.frame;
30
34
  const title = item.props.snapshot?.title ?? getMediaResourceTitle(item.props.src);
31
35
  const durationMs = item.props.snapshot?.durationMs;
32
36
  const detailed = boardCardDetailed(context.zoom);
33
- syncTextResolution(parts.title, parts, context.zoom);
34
37
  const elevation = cardElevation(context, item.id);
35
38
  const sig = [
36
39
  width,
@@ -83,14 +86,13 @@ const audioCardRenderer = {
83
86
  const root = new Container();
84
87
  const plate = new Graphics();
85
88
  const wave = new Graphics();
86
- const resolution = textResolutionForZoom(context.zoom);
87
89
  const title = new Text({
88
90
  text: "",
89
91
  style: {
90
92
  fontSize: 13,
91
93
  fontWeight: "600"
92
94
  },
93
- resolution,
95
+ resolution: context.textResolution,
94
96
  roundPixels: true
95
97
  });
96
98
  root.addChild(plate, wave, title);
@@ -99,8 +101,7 @@ const audioCardRenderer = {
99
101
  plate,
100
102
  wave,
101
103
  title,
102
- sig: "",
103
- resolution
104
+ sig: ""
104
105
  });
105
106
  if (item.type === "audio") sync(root, item, context);
106
107
  return root;
@@ -108,6 +109,9 @@ const audioCardRenderer = {
108
109
  update: (container, item, context) => {
109
110
  if (item.type === "audio") sync(container, item, context);
110
111
  },
112
+ resolution: (container, item, context) => {
113
+ if (item.type === "audio") sync(container, item, context);
114
+ },
111
115
  renderFar: (graphics, item, context) => {
112
116
  drawFarPlate(graphics, item.frame, {
113
117
  fill: context.palette.surface,
@@ -2,7 +2,7 @@ import { BoardFrame } from "../../../protocol/dist/board-layout.js";
2
2
  import "../../../protocol/dist/index.js";
3
3
  import { Container, Text } from "pixi.js";
4
4
  //#region src/board/render/renderers/base-card-renderer.d.ts
5
- declare function createLabel(text: string, style: Record<string, unknown>): Text;
5
+ declare function createLabel(text: string, style: Record<string, unknown>, resolution: number): Text;
6
6
  declare function positionShell(root: Container, item: {
7
7
  frame: BoardFrame;
8
8
  }): void;
@@ -1,10 +1,9 @@
1
1
  import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
2
- import { getBoardResolution } from "../text-resolution.js";
3
2
  import { Text } from "pixi.js";
4
3
  //#region src/board/render/renderers/base-card-renderer.ts
5
- function createLabel(text, style) {
4
+ function createLabel(text, style, resolution) {
6
5
  return new Text({
7
- resolution: getBoardResolution(),
6
+ resolution,
8
7
  roundPixels: true,
9
8
  text,
10
9
  style: {
@@ -22,7 +22,7 @@ type BoardScriptHost = {
22
22
  document?: (document: BoardDocument, time: number) => BoardDocument;
23
23
  ready?: (id: string) => boolean;
24
24
  revision?: (id: string) => number;
25
- frame: (item: SceneItem<BoardCustomItem>, time: number, resolution: number) => Texture | null;
25
+ frame: (item: SceneItem<BoardCustomItem>, time: number) => Texture | null;
26
26
  error: (id: string) => string | null;
27
27
  release: (id: string) => void;
28
28
  };
@@ -48,6 +48,8 @@ type BoardRenderContext = {
48
48
  themeKey: string;
49
49
  rendererType: "gpu" | "canvas";
50
50
  zoom: number;
51
+ /** Texture pixels per world unit for text; see `boardTextResolution`. */
52
+ textResolution: number;
51
53
  time: number;
52
54
  reducedMotion: boolean;
53
55
  labels: BoardRenderLabels;
@@ -61,7 +63,7 @@ type BoardRenderContext = {
61
63
  getTexture: (key: string) => Texture | null;
62
64
  hasError: (key: string) => boolean;
63
65
  fileState: (path: string) => "ok" | "missing" | "unavailable";
64
- acquireTexture: (key: string) => void;
66
+ acquireTexture: (key: string, item: BoardSceneItem) => void;
65
67
  releaseTexture: (key: string) => void;
66
68
  };
67
69
  type BoardCardRenderer = {
@@ -73,6 +75,8 @@ type BoardCardRenderer = {
73
75
  tick?: (container: Container, clock: number) => number | null;
74
76
  create: (item: BoardSceneItem, context: BoardRenderContext) => Container;
75
77
  update: (container: Container, item: BoardSceneItem, context: BoardRenderContext) => void;
78
+ /** Called when the zoom bucket or text resolution changes. */
79
+ resolution?: (container: Container, item: BoardSceneItem, context: BoardRenderContext) => void;
76
80
  /** Runs on every zoom step; only update transforms and visibility. */
77
81
  zoom?: (container: Container, zoom: number) => void;
78
82
  renderFar?: (graphics: Graphics, item: BoardSceneItem, context: BoardRenderContext) => void;
@@ -1,5 +1,5 @@
1
1
  import { BOARD_MONO_FONT_STACK } from "../../../protocol/dist/board-constants.js";
2
- import { getBoardResolution, syncTextResolution } from "../text-resolution.js";
2
+ import { syncTextResolution } from "../text-resolution.js";
3
3
  import { positionShell } from "./base-card-renderer.js";
4
4
  import { drawFarPlate } from "./far-plate.js";
5
5
  import { Container, Graphics, Sprite, Text, Texture } from "pixi.js";
@@ -13,10 +13,8 @@ function sync(container, item, context) {
13
13
  parts.id = item.id;
14
14
  }
15
15
  positionShell(parts.root, item);
16
- syncTextResolution(parts.label, parts.label, context.zoom);
17
16
  const { width, height } = item.frame;
18
- const resolution = Math.min(4, Math.max(.25, context.zoom * getBoardResolution()));
19
- const texture = context.scripts?.frame(item, context.time, resolution) ?? null;
17
+ const texture = context.scripts?.frame(item, context.time) ?? null;
20
18
  const error = context.scripts?.error(item.id) ?? null;
21
19
  parts.sprite.visible = Boolean(texture);
22
20
  const display = texture ?? Texture.EMPTY;
@@ -32,19 +30,21 @@ function sync(container, item, context) {
32
30
  message,
33
31
  context.themeKey
34
32
  ].join("|");
35
- if (sig === parts.sig) return;
36
- parts.sig = sig;
37
- parts.placeholder.clear();
38
- if (!ready || error) parts.placeholder.rect(0, 0, width, height).stroke({
39
- color: context.palette.border,
40
- width: 1,
41
- alpha: .8
42
- });
43
- parts.label.visible = !ready || Boolean(error);
44
- parts.label.text = message;
45
- parts.label.style.fill = error ? context.colors.rose.stroke : context.palette.muted;
46
- parts.label.style.wordWrapWidth = Math.max(40, width - 16);
47
- parts.label.position.set(width / 2, height / 2);
33
+ if (sig !== parts.sig) {
34
+ parts.sig = sig;
35
+ parts.placeholder.clear();
36
+ if (!ready || error) parts.placeholder.rect(0, 0, width, height).stroke({
37
+ color: context.palette.border,
38
+ width: 1,
39
+ alpha: .8
40
+ });
41
+ parts.label.visible = !ready || Boolean(error);
42
+ parts.label.text = message;
43
+ parts.label.style.fill = error ? context.colors.rose.stroke : context.palette.muted;
44
+ parts.label.style.wordWrapWidth = Math.max(40, width - 16);
45
+ parts.label.position.set(width / 2, height / 2);
46
+ }
47
+ syncTextResolution(parts.label, context.textResolution);
48
48
  }
49
49
  const customCardRenderer = {
50
50
  id: "custom-card",
@@ -63,7 +63,8 @@ const customCardRenderer = {
63
63
  wordWrap: true,
64
64
  breakWords: true
65
65
  },
66
- resolution: getBoardResolution()
66
+ resolution: context.textResolution,
67
+ roundPixels: true
67
68
  });
68
69
  label.anchor.set(.5);
69
70
  root.addChild(sprite, placeholder, label);
@@ -81,6 +82,10 @@ const customCardRenderer = {
81
82
  update: (container, item, context) => {
82
83
  if (item.type === "custom") sync(container, item, context);
83
84
  },
85
+ resolution: (container, _item, context) => {
86
+ const parts = partsByContainer.get(container);
87
+ if (parts) syncTextResolution(parts.label, context.textResolution);
88
+ },
84
89
  renderFar: (graphics, item, context) => {
85
90
  drawFarPlate(graphics, item.frame, {
86
91
  fill: context.palette.muted,
@@ -47,6 +47,14 @@ function syncClip(parts, rect, style) {
47
47
  function sync(container, item, context) {
48
48
  const parts = partsByContainer.get(container);
49
49
  if (!parts) return;
50
+ syncContent(parts, item, context);
51
+ for (const text of [
52
+ parts.title,
53
+ parts.excerpt,
54
+ parts.typeMark
55
+ ]) syncTextResolution(text, context.textResolution);
56
+ }
57
+ function syncContent(parts, item, context) {
50
58
  positionShell(parts.root, item);
51
59
  const { width, height } = item.frame;
52
60
  const detail = detailFor(context.zoom);
@@ -64,16 +72,13 @@ function sync(container, item, context) {
64
72
  const kind = filePreviewKind(item.props.snapshot);
65
73
  const category = fileCategory(item.props.src, item.props.snapshot?.mimeType);
66
74
  const accent = fileCategoryAccent(category, context.palette);
67
- syncTextResolution(parts.title, parts.titleRes, context.zoom);
68
- syncTextResolution(parts.excerpt, parts.excerptRes, context.zoom);
69
- syncTextResolution(parts.typeMark, parts.typeMarkRes, context.zoom);
70
75
  const visualSig = [
71
76
  key ?? "",
72
77
  width,
73
78
  height,
74
79
  detail,
75
80
  elevation,
76
- texture ? `${texture.width}x${texture.height}` : "none",
81
+ texture?.uid ?? "none",
77
82
  coverFailed,
78
83
  fileState,
79
84
  kind,
@@ -190,7 +195,7 @@ const fileCardRenderer = {
190
195
  const cover = new Sprite(Texture.EMPTY);
191
196
  const coverMask = new Graphics();
192
197
  cover.mask = coverMask;
193
- const resolution = 1;
198
+ const resolution = context.textResolution;
194
199
  const title = new Text({
195
200
  text: "",
196
201
  style: {
@@ -247,10 +252,7 @@ const fileCardRenderer = {
247
252
  title,
248
253
  excerpt,
249
254
  visualSig: "",
250
- textSig: "",
251
- titleRes: { resolution },
252
- excerptRes: { resolution },
253
- typeMarkRes: { resolution }
255
+ textSig: ""
254
256
  });
255
257
  if (item.type === "file") sync(root, item, context);
256
258
  return root;
@@ -258,6 +260,9 @@ const fileCardRenderer = {
258
260
  update: (container, item, context) => {
259
261
  if (item.type === "file") sync(container, item, context);
260
262
  },
263
+ resolution: (container, item, context) => {
264
+ if (item.type === "file") sync(container, item, context);
265
+ },
261
266
  zoom: (container, zoom) => {
262
267
  const tag = partsByContainer.get(container)?.tag;
263
268
  if (tag) zoomCardTag(tag, zoom);