@neta-art/cohub 12.0.0 → 12.1.1
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/export/index.js +1 -1
- package/dist/board/export/node/index.d.ts +1 -0
- package/dist/board/export/node/index.js +5 -0
- package/dist/board/export/scene.js +2 -1
- package/dist/board/render/card-tag.d.ts +0 -1
- package/dist/board/render/card-tag.js +15 -17
- package/dist/board/render/index.d.ts +2 -2
- package/dist/board/render/index.js +6 -6
- package/dist/board/render/renderers/arrow-card-renderer.js +5 -7
- package/dist/board/render/renderers/audio-card-renderer.js +8 -7
- package/dist/board/render/renderers/base-card-renderer.d.ts +1 -1
- package/dist/board/render/renderers/base-card-renderer.js +2 -3
- package/dist/board/render/renderers/board-renderer-registry.d.ts +3 -1
- package/dist/board/render/renderers/custom-card-renderer.js +19 -17
- package/dist/board/render/renderers/file-card-renderer.js +10 -8
- package/dist/board/render/renderers/frame-card-renderer.js +5 -6
- package/dist/board/render/renderers/shape-card-renderer.js +5 -7
- package/dist/board/render/renderers/task-card-renderer.js +9 -9
- package/dist/board/render/renderers/text-card-renderer.js +5 -7
- package/dist/board/render/renderers/unknown-card-renderer.js +5 -7
- package/dist/board/render/text-resolution.d.ts +4 -7
- package/dist/board/render/text-resolution.js +20 -22
- package/dist/board/stage/canvas-size.d.ts +18 -0
- package/dist/board/stage/canvas-size.js +31 -0
- package/dist/board/stage/scene.d.ts +5 -1
- package/dist/board/stage/scene.js +35 -9
- package/dist/board/stage/stage.js +34 -13
- package/dist/board/stage/text-resolution-tracker.d.ts +8 -0
- package/dist/board/stage/text-resolution-tracker.js +33 -0
- package/dist/chunks/app-realtime.js +1 -1
- package/dist/chunks/{transport.js → http-error.js} +37 -1
- package/dist/chunks/http.js +30 -10
- package/dist/http.js +1 -1
- package/dist/index.js +2 -2
- package/dist/websocket.js +951 -1
- package/package.json +1 -1
- package/dist/chunks/websocket.js +0 -988
|
@@ -2,9 +2,9 @@ import { buildBoardScene } from "../model/scene.js";
|
|
|
2
2
|
import { resolveBoardAnimationCamera } from "../model/sampling.js";
|
|
3
3
|
import { normalizeBoardDocument, planBoardExport } from "../model/export-plan.js";
|
|
4
4
|
import { parseBoardCssColor } from "../render/css-color.js";
|
|
5
|
-
import { ensureBoardTextMeasurement } from "../render/text-measurement.js";
|
|
6
5
|
import { defaultBoardPalette } from "../render/palette.js";
|
|
7
6
|
import { createBoardRenderSampler } from "../render/sampling.js";
|
|
7
|
+
import { ensureBoardTextMeasurement } from "../render/text-measurement.js";
|
|
8
8
|
import { createBoardExportScene } from "./scene.js";
|
|
9
9
|
import { Rectangle, RendererType } from "pixi.js";
|
|
10
10
|
//#region src/board/export/index.ts
|
|
@@ -9,6 +9,7 @@ import { Renderer } from "pixi.js";
|
|
|
9
9
|
type NodeCanvasModule = {
|
|
10
10
|
createCanvas: (width: number, height: number) => unknown;
|
|
11
11
|
Image: new () => unknown;
|
|
12
|
+
DOMMatrix: new (init?: number[]) => unknown;
|
|
12
13
|
GlobalFonts: BoardFontRegistry;
|
|
13
14
|
};
|
|
14
15
|
type BoardNodeRendererOptions = {
|
|
@@ -24,6 +24,10 @@ async function loadCanvasModule() {
|
|
|
24
24
|
throw new Error("Board image export needs the optional '@napi-rs/canvas' package. Install it with: npm i @napi-rs/canvas", { cause });
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
+
function installDOMMatrix(canvasModule) {
|
|
28
|
+
const globals = globalThis;
|
|
29
|
+
globals.DOMMatrix ??= canvasModule.DOMMatrix;
|
|
30
|
+
}
|
|
27
31
|
function installAnimationFrameShim() {
|
|
28
32
|
const globals = globalThis;
|
|
29
33
|
if (globals.requestAnimationFrame) return () => {};
|
|
@@ -78,6 +82,7 @@ async function createNodeBoardRenderer(options = {}) {
|
|
|
78
82
|
throw new Error("XML parsing is not available in Node board export.");
|
|
79
83
|
}
|
|
80
84
|
});
|
|
85
|
+
installDOMMatrix(canvasModule);
|
|
81
86
|
installBoardTextMeasurement();
|
|
82
87
|
const restoreAnimationFrame = installAnimationFrameShim();
|
|
83
88
|
const renderer = new CanvasRenderer();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { buildFallbackShapeColors } from "../model/palette.js";
|
|
2
2
|
import { imageAssetKey } from "../model/image-key.js";
|
|
3
|
-
import { clippingAncestor, isClippingFrame, syncClipGroup } from "../render/clip.js";
|
|
4
3
|
import { defaultBoardPalette } from "../render/palette.js";
|
|
4
|
+
import { clippingAncestor, isClippingFrame, syncClipGroup } from "../render/clip.js";
|
|
5
5
|
import { DEFAULT_BOARD_RENDER_LABELS, getBoardCardRenderer } from "../render/renderers/board-renderer-registry.js";
|
|
6
6
|
import { resolveBoardRenderStyle } from "../render/style.js";
|
|
7
7
|
import { Container, Graphics, Sprite, TilingSprite } from "pixi.js";
|
|
@@ -29,6 +29,7 @@ function buildContext(input) {
|
|
|
29
29
|
themeKey: "export",
|
|
30
30
|
rendererType: "canvas",
|
|
31
31
|
zoom: input.scale,
|
|
32
|
+
textResolution: input.scale,
|
|
32
33
|
reducedMotion: true,
|
|
33
34
|
labels: DEFAULT_BOARD_RENDER_LABELS,
|
|
34
35
|
taskRun: () => null,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { fitTextToWidth } from "./text-fit.js";
|
|
2
|
-
import { syncTextResolution
|
|
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 =
|
|
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
|
|
221
|
-
|
|
222
|
-
|
|
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.
|
|
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
|
|
@@ -15,6 +15,6 @@ import { CardCrop, CardElevation, CardRect, CardSurface, PIXEL_STEP, cardElevati
|
|
|
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,
|
|
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, CardCrop, 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, 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,
|
|
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 };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { parseBoardCssColor, parseBoardCssPaint } from "./css-color.js";
|
|
2
|
+
import { defaultBoardPalette, itemAlpha, itemColor } from "./palette.js";
|
|
3
|
+
import { createBoardRenderSampler } from "./sampling.js";
|
|
4
|
+
import { BOARD_FONT_STACKS, ensureBoardTextMeasurement, installBoardTextMeasurement } from "./text-measurement.js";
|
|
5
|
+
import { inspectBoardItems, inspectBoardScene, measureBoardText } from "./diagnostics.js";
|
|
2
6
|
import { createBoardBackground, updateBoardBackground } from "./board-background.js";
|
|
3
7
|
import { ellipsizeWrappedLines, fitLineWithEllipsis, fitTextToLines, fitTextToWidth } from "./text-fit.js";
|
|
4
|
-
import { boardCardDetailed, getBoardResolution, syncTextResolution, syncTextWrapWidth,
|
|
8
|
+
import { boardCardDetailed, boardTextResolution, getBoardResolution, syncTextResolution, syncTextWrapWidth, textZoomBucket } from "./text-resolution.js";
|
|
5
9
|
import { CARD_TAG_SIZE, createCardTag, drawCardGlyph, formatBoardDuration, syncCardTag, traceCube, zoomCardTag } from "./card-tag.js";
|
|
6
10
|
import { clippingAncestor, isClippingFrame, syncClipGroup, traceFrameOutline } from "./clip.js";
|
|
7
|
-
import { BOARD_FONT_STACKS, ensureBoardTextMeasurement, installBoardTextMeasurement } from "./text-measurement.js";
|
|
8
|
-
import { inspectBoardItems, inspectBoardScene, measureBoardText } from "./diagnostics.js";
|
|
9
|
-
import { defaultBoardPalette, itemAlpha, itemColor } from "./palette.js";
|
|
10
|
-
import { createBoardRenderSampler } from "./sampling.js";
|
|
11
11
|
import { dashPattern, endAngle, roundRectPoints, traceArrowhead, tracePolyline, trimPolyline } from "./stroke.js";
|
|
12
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";
|
|
@@ -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, 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,
|
|
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
|
-
import { syncTextResolution, textResolutionForZoom } from "../text-resolution.js";
|
|
4
3
|
import { itemAlpha, itemColor } from "../palette.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;
|
|
@@ -130,7 +128,7 @@ const arrowCardRenderer = {
|
|
|
130
128
|
},
|
|
131
129
|
resolution: (container, _item, context) => {
|
|
132
130
|
const parts = partsByContainer.get(container);
|
|
133
|
-
if (parts) syncTextResolution(parts.label,
|
|
131
|
+
if (parts) syncTextResolution(parts.label, context.textResolution);
|
|
134
132
|
},
|
|
135
133
|
renderFar: (graphics, item, context) => {
|
|
136
134
|
if (item.type !== "arrow") return;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getMediaResourceTitle } from "../../model/media.js";
|
|
2
|
-
import { drawAudioWaveform } from "../audio-waveform.js";
|
|
3
2
|
import { fitTextToWidth } from "../text-fit.js";
|
|
4
|
-
import { boardCardDetailed, syncTextResolution
|
|
3
|
+
import { boardCardDetailed, syncTextResolution } from "../text-resolution.js";
|
|
5
4
|
import { formatBoardDuration } from "../card-tag.js";
|
|
5
|
+
import { drawAudioWaveform } from "../audio-waveform.js";
|
|
6
6
|
import { cardElevation, drawCardSurface } from "../surface.js";
|
|
7
7
|
import { positionShell } from "./base-card-renderer.js";
|
|
8
8
|
import { drawFarPlate } from "./far-plate.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;
|
|
@@ -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
|
|
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
|
|
6
|
+
resolution,
|
|
8
7
|
roundPixels: true,
|
|
9
8
|
text,
|
|
10
9
|
style: {
|
|
@@ -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;
|
|
@@ -73,7 +75,7 @@ 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;
|
|
76
|
-
/** Called
|
|
78
|
+
/** Called when the zoom bucket or text resolution changes. */
|
|
77
79
|
resolution?: (container: Container, item: BoardSceneItem, context: BoardRenderContext) => void;
|
|
78
80
|
/** Runs on every zoom step; only update transforms and visibility. */
|
|
79
81
|
zoom?: (container: Container, zoom: number) => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BOARD_MONO_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
|
-
import {
|
|
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,7 +13,6 @@ 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
17
|
const texture = context.scripts?.frame(item, context.time) ?? null;
|
|
19
18
|
const error = context.scripts?.error(item.id) ?? null;
|
|
@@ -31,19 +30,21 @@ function sync(container, item, context) {
|
|
|
31
30
|
message,
|
|
32
31
|
context.themeKey
|
|
33
32
|
].join("|");
|
|
34
|
-
if (sig
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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);
|
|
47
48
|
}
|
|
48
49
|
const customCardRenderer = {
|
|
49
50
|
id: "custom-card",
|
|
@@ -62,7 +63,8 @@ const customCardRenderer = {
|
|
|
62
63
|
wordWrap: true,
|
|
63
64
|
breakWords: true
|
|
64
65
|
},
|
|
65
|
-
resolution:
|
|
66
|
+
resolution: context.textResolution,
|
|
67
|
+
roundPixels: true
|
|
66
68
|
});
|
|
67
69
|
label.anchor.set(.5);
|
|
68
70
|
root.addChild(sprite, placeholder, label);
|
|
@@ -82,7 +84,7 @@ const customCardRenderer = {
|
|
|
82
84
|
},
|
|
83
85
|
resolution: (container, _item, context) => {
|
|
84
86
|
const parts = partsByContainer.get(container);
|
|
85
|
-
if (parts) syncTextResolution(parts.label,
|
|
87
|
+
if (parts) syncTextResolution(parts.label, context.textResolution);
|
|
86
88
|
},
|
|
87
89
|
renderFar: (graphics, item, context) => {
|
|
88
90
|
drawFarPlate(graphics, item.frame, {
|
|
@@ -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,9 +72,6 @@ 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,
|
|
@@ -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 =
|
|
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;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
|
-
import { syncTextResolution } from "../text-resolution.js";
|
|
3
2
|
import { itemAlpha, itemColor } from "../palette.js";
|
|
3
|
+
import { syncTextResolution } from "../text-resolution.js";
|
|
4
4
|
import { dashPattern, roundRectPoints, tracePolyline, trimPolyline } from "../stroke.js";
|
|
5
5
|
import { createLabel, positionShell } from "./base-card-renderer.js";
|
|
6
6
|
import { drawFarPlate } from "./far-plate.js";
|
|
@@ -13,7 +13,6 @@ function sync(container, item, context) {
|
|
|
13
13
|
if (!parts) return;
|
|
14
14
|
const { frame, style, props, locked } = item;
|
|
15
15
|
positionShell(parts.root, item);
|
|
16
|
-
syncTextResolution(parts.label, parts, context.zoom);
|
|
17
16
|
const fill = itemColor(context, style.fill ?? style.stroke, "neutral", "fill");
|
|
18
17
|
const fillAlpha = (style.fillOpacity ?? (style.fill ? 1 : DEFAULT_WASH)) * itemAlpha(context, style.fill ?? style.stroke);
|
|
19
18
|
const baseStroke = itemColor(context, style.stroke, "neutral");
|
|
@@ -69,6 +68,7 @@ function sync(container, item, context) {
|
|
|
69
68
|
parts.label.style.fill = labelColor;
|
|
70
69
|
parts.label.style.fontFamily = context.style.font;
|
|
71
70
|
}
|
|
71
|
+
syncTextResolution(parts.label, context.textResolution);
|
|
72
72
|
parts.label.position.set(4, -18);
|
|
73
73
|
}
|
|
74
74
|
const frameCardRenderer = {
|
|
@@ -82,15 +82,14 @@ const frameCardRenderer = {
|
|
|
82
82
|
fontFamily: BOARD_FONT_STACK,
|
|
83
83
|
fontSize: 12,
|
|
84
84
|
fontWeight: "600"
|
|
85
|
-
});
|
|
85
|
+
}, context.textResolution);
|
|
86
86
|
root.addChild(box, label);
|
|
87
87
|
partsByContainer.set(root, {
|
|
88
88
|
root,
|
|
89
89
|
box,
|
|
90
90
|
label,
|
|
91
91
|
visualSig: "",
|
|
92
|
-
textSig: ""
|
|
93
|
-
resolution: label.resolution
|
|
92
|
+
textSig: ""
|
|
94
93
|
});
|
|
95
94
|
if (item.type === "frame") sync(root, item, context);
|
|
96
95
|
return root;
|
|
@@ -100,7 +99,7 @@ const frameCardRenderer = {
|
|
|
100
99
|
},
|
|
101
100
|
resolution: (container, _item, context) => {
|
|
102
101
|
const parts = partsByContainer.get(container);
|
|
103
|
-
if (parts) syncTextResolution(parts.label,
|
|
102
|
+
if (parts) syncTextResolution(parts.label, context.textResolution);
|
|
104
103
|
},
|
|
105
104
|
renderFar: (graphics, item, context) => {
|
|
106
105
|
if (item.type !== "frame" || item.props.decoration === "none") return;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
2
|
import { worldPoint } from "../../model/geometry.js";
|
|
3
|
-
import { syncTextResolution, syncTextWrapWidth, textResolutionForZoom } from "../text-resolution.js";
|
|
4
3
|
import { itemAlpha, itemColor } from "../palette.js";
|
|
4
|
+
import { syncTextResolution, syncTextWrapWidth } from "../text-resolution.js";
|
|
5
5
|
import { dashPattern, roundRectPoints, tracePolyline, trimPolyline } from "../stroke.js";
|
|
6
6
|
import { positionShell } from "./base-card-renderer.js";
|
|
7
7
|
import { drawFarPlate } from "./far-plate.js";
|
|
@@ -100,7 +100,6 @@ function sync(container, item, context) {
|
|
|
100
100
|
const fillOpacity = (style.fillOpacity ?? (style.fill ? 1 : 0)) * itemAlpha(context, style.fill ?? style.stroke);
|
|
101
101
|
const strokeAlpha = itemAlpha(context, style.stroke ?? style.fill);
|
|
102
102
|
const strokeWidth = style.strokeWidth ?? 1.75;
|
|
103
|
-
syncTextResolution(parts.label, parts, context.zoom);
|
|
104
103
|
const visualSig = [
|
|
105
104
|
width,
|
|
106
105
|
height,
|
|
@@ -159,6 +158,7 @@ function sync(container, item, context) {
|
|
|
159
158
|
parts.label.style.align = props.align;
|
|
160
159
|
}
|
|
161
160
|
syncTextWrapWidth(parts.label, parts, Math.max(1, width - 16), context.resizingIds.has(item.id));
|
|
161
|
+
syncTextResolution(parts.label, context.textResolution);
|
|
162
162
|
parts.label.position.set(width / 2, height / 2);
|
|
163
163
|
}
|
|
164
164
|
const shapeCardRenderer = {
|
|
@@ -167,7 +167,6 @@ const shapeCardRenderer = {
|
|
|
167
167
|
create: (item, context) => {
|
|
168
168
|
const root = new Container();
|
|
169
169
|
const shape = new Graphics();
|
|
170
|
-
const resolution = textResolutionForZoom(context.zoom);
|
|
171
170
|
const label = new Text({
|
|
172
171
|
text: "",
|
|
173
172
|
style: {
|
|
@@ -179,7 +178,7 @@ const shapeCardRenderer = {
|
|
|
179
178
|
wordWrap: true,
|
|
180
179
|
lineHeight: 28
|
|
181
180
|
},
|
|
182
|
-
resolution,
|
|
181
|
+
resolution: context.textResolution,
|
|
183
182
|
roundPixels: true
|
|
184
183
|
});
|
|
185
184
|
label.anchor.set(.5);
|
|
@@ -190,8 +189,7 @@ const shapeCardRenderer = {
|
|
|
190
189
|
label,
|
|
191
190
|
visualSig: "",
|
|
192
191
|
textSig: "",
|
|
193
|
-
wrapWidth: 0
|
|
194
|
-
resolution
|
|
192
|
+
wrapWidth: 0
|
|
195
193
|
});
|
|
196
194
|
if (item.type === "shape") sync(root, item, context);
|
|
197
195
|
return root;
|
|
@@ -201,7 +199,7 @@ const shapeCardRenderer = {
|
|
|
201
199
|
},
|
|
202
200
|
resolution: (container, _item, context) => {
|
|
203
201
|
const parts = partsByContainer.get(container);
|
|
204
|
-
if (parts) syncTextResolution(parts.label,
|
|
202
|
+
if (parts) syncTextResolution(parts.label, context.textResolution);
|
|
205
203
|
},
|
|
206
204
|
renderFar: (graphics, item, context) => {
|
|
207
205
|
if (item.type !== "shape") return;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BOARD_FONT_STACK, BOARD_MONO_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
2
|
import { featuredTaskArtifact } from "../../../protocol/dist/board-task.js";
|
|
3
|
-
import { drawAudioWaveform } from "../audio-waveform.js";
|
|
4
3
|
import { fitTextToLines } from "../text-fit.js";
|
|
5
|
-
import { boardCardDetailed, syncTextResolution
|
|
4
|
+
import { boardCardDetailed, syncTextResolution } from "../text-resolution.js";
|
|
6
5
|
import { createCardTag, formatBoardDuration, syncCardTag, zoomCardTag } from "../card-tag.js";
|
|
6
|
+
import { drawAudioWaveform } from "../audio-waveform.js";
|
|
7
7
|
import { cardElevation, containRect, drawCardSurface, traceCardOutline } from "../surface.js";
|
|
8
8
|
import { positionShell } from "./base-card-renderer.js";
|
|
9
9
|
import { drawFarPlate } from "./far-plate.js";
|
|
@@ -283,10 +283,6 @@ function sync(container, item, context) {
|
|
|
283
283
|
const detailText = !full || !surface ? "" : status === "failed" ? snapshot.errorExcerpt ?? "" : working ? snapshot.promptExcerpt ?? "" : "";
|
|
284
284
|
const textArtifact = kind === "text" && artifact?.type === "text";
|
|
285
285
|
const bodyText = textArtifact ? artifact.textExcerpt : counting ? `${label} · ${elapsed}` : label;
|
|
286
|
-
syncTextResolution(parts.body, parts, context.zoom);
|
|
287
|
-
syncTextResolution(parts.detail, parts, context.zoom);
|
|
288
|
-
syncTextResolution(parts.meta, parts, context.zoom);
|
|
289
|
-
syncTextResolution(parts.badge, parts, context.zoom);
|
|
290
286
|
const textSig = [
|
|
291
287
|
counting ? label : bodyText,
|
|
292
288
|
detailText,
|
|
@@ -317,6 +313,12 @@ function sync(container, item, context) {
|
|
|
317
313
|
parts.badge.style.fill = context.palette.text;
|
|
318
314
|
if (parts.badge.text !== count) parts.badge.text = count;
|
|
319
315
|
}
|
|
316
|
+
for (const text of [
|
|
317
|
+
parts.body,
|
|
318
|
+
parts.detail,
|
|
319
|
+
parts.meta,
|
|
320
|
+
parts.badge
|
|
321
|
+
]) syncTextResolution(text, context.textResolution);
|
|
320
322
|
const badgeWidth = Math.max(22, parts.badge.width + 12);
|
|
321
323
|
const visualSig = [
|
|
322
324
|
width,
|
|
@@ -434,7 +436,6 @@ const taskCardRenderer = {
|
|
|
434
436
|
const previewMask = new Graphics();
|
|
435
437
|
const shimmer = new Graphics();
|
|
436
438
|
const previewArt = new Graphics();
|
|
437
|
-
const resolution = textResolutionForZoom(context.zoom);
|
|
438
439
|
const text = (fontFamily, fontSize, fontWeight) => new Text({
|
|
439
440
|
text: "",
|
|
440
441
|
style: {
|
|
@@ -444,7 +445,7 @@ const taskCardRenderer = {
|
|
|
444
445
|
wordWrap: true,
|
|
445
446
|
breakWords: true
|
|
446
447
|
},
|
|
447
|
-
resolution,
|
|
448
|
+
resolution: context.textResolution,
|
|
448
449
|
roundPixels: true
|
|
449
450
|
});
|
|
450
451
|
const body = text(BOARD_FONT_STACK, 11.5, "500");
|
|
@@ -478,7 +479,6 @@ const taskCardRenderer = {
|
|
|
478
479
|
assetKey: null,
|
|
479
480
|
visualSig: "",
|
|
480
481
|
textSig: "",
|
|
481
|
-
resolution,
|
|
482
482
|
motion: {
|
|
483
483
|
itemId: "",
|
|
484
484
|
width: 0,
|