@neta-art/cohub 8.24.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/board/animation.d.ts +57 -181
- package/dist/board/animation.js +374 -220
- package/dist/board/core/arrow-geometry.d.ts +33 -18
- package/dist/board/core/arrow-geometry.js +283 -52
- package/dist/board/core/draw-geometry.d.ts +22 -36
- package/dist/board/core/draw-geometry.js +148 -85
- package/dist/board/core/export-assets.d.ts +3 -6
- package/dist/board/core/export-assets.js +0 -2
- package/dist/board/core/export-plan.d.ts +12 -63
- package/dist/board/core/export-plan.js +55 -94
- package/dist/board/core/palette.d.ts +4 -21
- package/dist/board/core/palette.js +8 -13
- package/dist/board/core/scene.d.ts +33 -0
- package/dist/board/core/scene.js +302 -0
- package/dist/board/core/shape-definition.d.ts +12 -24
- package/dist/board/core/shape-definition.js +0 -19
- package/dist/board/core/shape-types.d.ts +6 -120
- package/dist/board/core/shape-types.js +5 -5
- package/dist/board/core/text-metrics.d.ts +8 -11
- package/dist/board/core/text-metrics.js +5 -34
- package/dist/board/core/tool-styles.d.ts +6 -16
- package/dist/board/core/tool-styles.js +17 -25
- package/dist/board/export/index.d.ts +10 -17
- package/dist/board/export/index.js +22 -21
- package/dist/board/export/scene.d.ts +10 -16
- package/dist/board/export/scene.js +17 -30
- package/dist/board/geometry.d.ts +27 -56
- package/dist/board/geometry.js +7 -67
- package/dist/board/headless/index.d.ts +6 -27
- package/dist/board/headless/index.js +4 -19
- package/dist/board/headless/sketch.d.ts +19 -0
- package/dist/board/headless/sketch.js +146 -0
- package/dist/board/image-key.d.ts +2 -12
- package/dist/board/image-key.js +3 -13
- package/dist/board/index.d.ts +18 -20
- package/dist/board/index.js +17 -17
- package/dist/board/media-playback.d.ts +3 -6
- package/dist/board/media-playback.js +6 -6
- package/dist/board/presets.d.ts +150 -0
- package/dist/board/presets.js +226 -0
- package/dist/board/render/board-background.d.ts +5 -3
- package/dist/board/render/board-background.js +8 -7
- package/dist/board/render/clip.d.ts +14 -0
- package/dist/board/render/clip.js +47 -0
- package/dist/board/render/index.d.ts +8 -5
- package/dist/board/render/index.js +7 -4
- package/dist/board/render/media-interaction.d.ts +4 -5
- package/dist/board/render/media-interaction.js +1 -2
- package/dist/board/render/palette.d.ts +6 -2
- package/dist/board/render/palette.js +7 -1
- package/dist/board/render/renderers/arrow-card-renderer.js +69 -71
- package/dist/board/render/renderers/audio-card-renderer.js +3 -3
- package/dist/board/render/renderers/base-card-renderer.d.ts +6 -17
- package/dist/board/render/renderers/base-card-renderer.js +1 -24
- package/dist/board/render/renderers/board-renderer-registry.d.ts +20 -50
- package/dist/board/render/renderers/board-renderer-registry.js +6 -7
- package/dist/board/render/renderers/draw-card-renderer.js +89 -56
- package/dist/board/render/renderers/effect-card-renderer.d.ts +6 -0
- package/dist/board/render/renderers/effect-card-renderer.js +197 -0
- package/dist/board/render/renderers/far-plate.d.ts +4 -21
- package/dist/board/render/renderers/far-plate.js +15 -34
- package/dist/board/render/renderers/file-card-renderer.d.ts +4 -25
- package/dist/board/render/renderers/file-card-renderer.js +8 -58
- package/dist/board/render/renderers/frame-card-renderer.js +28 -28
- package/dist/board/render/renderers/image-card-renderer.d.ts +4 -3
- package/dist/board/render/renderers/image-card-renderer.js +0 -9
- package/dist/board/render/renderers/shape-card-renderer.d.ts +9 -0
- package/dist/board/render/renderers/shape-card-renderer.js +240 -0
- package/dist/board/render/renderers/sketch-card-renderer.d.ts +5 -0
- package/dist/board/render/renderers/sketch-card-renderer.js +98 -0
- package/dist/board/render/renderers/task-card-renderer.d.ts +0 -1
- package/dist/board/render/renderers/task-card-renderer.js +14 -16
- package/dist/board/render/renderers/text-card-renderer.d.ts +1 -3
- package/dist/board/render/renderers/text-card-renderer.js +56 -46
- package/dist/board/render/renderers/unknown-card-renderer.js +4 -10
- package/dist/board/render/renderers/video-card-renderer.d.ts +4 -2
- package/dist/board/render/renderers/video-card-renderer.js +2 -1
- package/dist/board/render/sketch-host.d.ts +14 -0
- package/dist/board/render/sketch-host.js +216 -0
- package/dist/board/render/stroke.d.ts +12 -0
- package/dist/board/render/stroke.js +90 -0
- package/dist/board/render/text-measurement.d.ts +6 -26
- package/dist/board/render/text-measurement.js +11 -30
- package/dist/board/replay.d.ts +6 -31
- package/dist/board/replay.js +45 -203
- package/dist/board/runtime/board-player.d.ts +24 -0
- package/dist/board/runtime/board-player.js +161 -0
- package/dist/board/task.d.ts +2 -10
- package/dist/board/task.js +1 -10
- package/dist/chunks/environment.d.ts +2291 -3864
- package/dist/chunks/host-bridge.d.ts +253 -0
- package/dist/chunks/http.d.ts +233 -58
- package/dist/chunks/http.js +1046 -1028
- package/dist/chunks/transport.js +113 -59
- package/dist/chunks/websocket.d.ts +1 -1
- package/dist/chunks/websocket.js +1 -1
- package/dist/host-bridge.d.ts +54 -0
- package/dist/host-bridge.js +322 -0
- package/dist/http.d.ts +3 -3
- package/dist/index.d.ts +74 -191
- package/dist/index.js +2032 -1186
- package/dist/protocol/dist/board-constants.d.ts +1 -29
- package/dist/protocol/dist/board-constants.js +2 -115
- package/dist/protocol/dist/board-layout.d.ts +59 -0
- package/dist/protocol/dist/board-layout.js +482 -0
- package/dist/protocol/dist/board-model.d.ts +2052 -0
- package/dist/protocol/dist/board-model.js +592 -0
- package/dist/protocol/dist/board-patch.d.ts +86 -0
- package/dist/protocol/dist/board-patch.js +734 -0
- package/dist/protocol/dist/board-schema.d.ts +33 -0
- package/dist/protocol/dist/board-schema.js +59 -0
- package/dist/protocol/dist/board-upgrade.d.ts +1 -0
- package/dist/protocol/dist/board-url.d.ts +1 -3
- package/dist/protocol/dist/board-url.js +2 -2
- package/dist/protocol/dist/board.d.ts +37 -232
- package/dist/protocol/dist/board.js +62 -160
- package/dist/protocol/dist/display/actions.d.ts +1 -0
- package/dist/protocol/dist/display/index.d.ts +2 -0
- package/dist/protocol/dist/index.d.ts +11 -12
- package/dist/protocol/dist/model/metrics.d.ts +2 -0
- package/dist/protocol/dist/model/session.d.ts +2 -1
- package/dist/protocol/dist/realtime/types.d.ts +2 -2
- package/dist/protocol/dist/runtime/index.d.ts +1 -0
- package/dist/space-picker.d.ts +1 -0
- package/dist/space-picker.js +1 -0
- package/dist/types.d.ts +2 -5
- package/package.json +9 -1
- package/dist/board/core/connections.d.ts +0 -108
- package/dist/board/core/connections.js +0 -455
- package/dist/board/mutation.d.ts +0 -6
- package/dist/board/mutation.js +0 -14
- package/dist/board/render/connection-layer.d.ts +0 -53
- package/dist/board/render/connection-layer.js +0 -375
- package/dist/board/render/renderers/geo-card-renderer.d.ts +0 -5
- package/dist/board/render/renderers/geo-card-renderer.js +0 -127
- package/dist/board/semantic-document.d.ts +0 -37
- package/dist/board/semantic-document.js +0 -288
- package/dist/board/semantic-mutation.d.ts +0 -10
- package/dist/board/semantic-mutation.js +0 -209
- package/dist/protocol/dist/board-animation.js +0 -34
- package/dist/protocol/dist/board-authoring.d.ts +0 -1326
- package/dist/protocol/dist/board-authoring.js +0 -302
- package/dist/protocol/dist/board-capability-registry.d.ts +0 -2
- package/dist/protocol/dist/board-capability-registry.js +0 -123
- package/dist/protocol/dist/board-codec.d.ts +0 -3
- package/dist/protocol/dist/board-codec.js +0 -383
- package/dist/protocol/dist/board-composition.d.ts +0 -383
- package/dist/protocol/dist/board-composition.js +0 -310
- package/dist/protocol/dist/board-connection.d.ts +0 -317
- package/dist/protocol/dist/board-connection.js +0 -219
- package/dist/protocol/dist/board-document.d.ts +0 -1566
- package/dist/protocol/dist/board-document.js +0 -456
- package/dist/protocol/dist/board-effect.d.ts +0 -96
- package/dist/protocol/dist/board-effect.js +0 -54
- package/dist/protocol/dist/board-geometry.d.ts +0 -15
- package/dist/protocol/dist/board-geometry.js +0 -137
- package/dist/protocol/dist/board-node.d.ts +0 -8
- package/dist/protocol/dist/board-node.js +0 -252
- /package/dist/protocol/dist/{board-animation.d.ts → host-bridge.d.ts} +0 -0
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
import { BOARD_FONT_STACK } from "../../protocol/dist/board-constants.js";
|
|
2
|
-
import { rectsIntersect } from "../geometry.js";
|
|
3
|
-
import { connectionArrowheads, createConnectionGeometryCache } from "../core/connections.js";
|
|
4
|
-
import { pickBoardColor } from "../core/palette.js";
|
|
5
|
-
import { syncTextResolution, textResolutionForZoom, textZoomBucket } from "./text-resolution.js";
|
|
6
|
-
import { Container, Graphics, Text } from "pixi.js";
|
|
7
|
-
//#region src/board/render/connection-layer.ts
|
|
8
|
-
/**
|
|
9
|
-
* Connection drawing.
|
|
10
|
-
*
|
|
11
|
-
* Connections render into shared layers beneath the cards rather than as a
|
|
12
|
-
* container per relation. A connection is a thin stroke with no texture and no
|
|
13
|
-
* interactive chrome of its own, so a per-connection container would add a
|
|
14
|
-
* transform, a render group and a draw call each for geometry that batches
|
|
15
|
-
* perfectly — on a densely connected board that is the difference between a few
|
|
16
|
-
* draw calls and a few thousand.
|
|
17
|
-
*
|
|
18
|
-
* Tessellation is the real cost, so both layers are cached: `base` holds idle
|
|
19
|
-
* relations, `live` those touching manipulated, selected or hovered nodes.
|
|
20
|
-
* Details too small to read degrade to plain strokes; the document never changes.
|
|
21
|
-
*
|
|
22
|
-
* Labels are the exception to batching: text needs its own object to rasterise,
|
|
23
|
-
* so a `Text` is materialised only for visible connections that carry one and is
|
|
24
|
-
* pooled by connection id.
|
|
25
|
-
*/
|
|
26
|
-
/** Arrowhead length relative to stroke width, and its floor in world units. */
|
|
27
|
-
const HEAD_SCALE = 5.5;
|
|
28
|
-
const HEAD_MIN = 11;
|
|
29
|
-
const HEAD_SPREAD = Math.PI / 6;
|
|
30
|
-
/** Dash pattern for `dashed` connections, in world units. */
|
|
31
|
-
const DASH_LENGTH = 10;
|
|
32
|
-
const DASH_GAP = 7;
|
|
33
|
-
const LABEL_FONT_SIZE = 12;
|
|
34
|
-
/** Minimum on-screen sizes before a detail is drawn. */
|
|
35
|
-
const MIN_DASH_PX = 4;
|
|
36
|
-
const MIN_HEAD_PX = 3;
|
|
37
|
-
const MIN_LABEL_PX = 5;
|
|
38
|
-
const MIN_SEGMENT_PX = 2;
|
|
39
|
-
const MIN_ROUND_PX = 2;
|
|
40
|
-
/** Dashes per frame; past it all dashed relations draw solid (with hysteresis). */
|
|
41
|
-
const DASH_BUDGET = 4e4;
|
|
42
|
-
const DASH_RESUME_RATIO = .8;
|
|
43
|
-
function detailForZoom(zoom) {
|
|
44
|
-
const bucket = 2 ** (Math.floor(Math.log2(Math.max(zoom, 1e-4)) * 2) / 2);
|
|
45
|
-
return {
|
|
46
|
-
zoom: bucket,
|
|
47
|
-
dashes: DASH_LENGTH * bucket >= MIN_DASH_PX,
|
|
48
|
-
labels: LABEL_FONT_SIZE * bucket >= MIN_LABEL_PX,
|
|
49
|
-
minWidth: 1 / bucket,
|
|
50
|
-
minStep: MIN_SEGMENT_PX / bucket
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
/** Visit each dash piece inside `clip`; `start` marks the first piece of a dash. */
|
|
54
|
-
function walkDashes(path, clip, visit) {
|
|
55
|
-
let penDown = true;
|
|
56
|
-
let remaining = DASH_LENGTH;
|
|
57
|
-
let open = false;
|
|
58
|
-
for (let index = 1; index < path.length; index += 1) {
|
|
59
|
-
const a = path[index - 1];
|
|
60
|
-
const b = path[index];
|
|
61
|
-
if (!a || !b) continue;
|
|
62
|
-
const dx = b.x - a.x;
|
|
63
|
-
const dy = b.y - a.y;
|
|
64
|
-
const length = Math.hypot(dx, dy);
|
|
65
|
-
let travelled = 0;
|
|
66
|
-
while (length - travelled > 1e-4) {
|
|
67
|
-
const step = Math.min(length - travelled, remaining);
|
|
68
|
-
if (penDown) {
|
|
69
|
-
const t0 = travelled / length;
|
|
70
|
-
const t1 = (travelled + step) / length;
|
|
71
|
-
const x0 = a.x + dx * t0;
|
|
72
|
-
const y0 = a.y + dy * t0;
|
|
73
|
-
const x1 = a.x + dx * t1;
|
|
74
|
-
const y1 = a.y + dy * t1;
|
|
75
|
-
if (!clip || Math.max(x0, x1) >= clip.x && Math.min(x0, x1) <= clip.x + clip.width && Math.max(y0, y1) >= clip.y && Math.min(y0, y1) <= clip.y + clip.height) {
|
|
76
|
-
visit(x0, y0, x1, y1, !open);
|
|
77
|
-
open = true;
|
|
78
|
-
} else open = false;
|
|
79
|
-
}
|
|
80
|
-
travelled += step;
|
|
81
|
-
remaining -= step;
|
|
82
|
-
if (remaining <= 1e-4) {
|
|
83
|
-
penDown = !penDown;
|
|
84
|
-
remaining = penDown ? DASH_LENGTH : DASH_GAP;
|
|
85
|
-
open = false;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
function countDashes(entries, clip) {
|
|
91
|
-
let count = 0;
|
|
92
|
-
for (const { connection, resolved } of entries) {
|
|
93
|
-
if (connection.style.line !== "dashed") continue;
|
|
94
|
-
walkDashes(resolved.path, clip, (_x0, _y0, _x1, _y1, start) => {
|
|
95
|
-
if (start) count += 1;
|
|
96
|
-
});
|
|
97
|
-
if (count > DASH_BUDGET) break;
|
|
98
|
-
}
|
|
99
|
-
return count;
|
|
100
|
-
}
|
|
101
|
-
function traceSolid(graphics, path, minStep) {
|
|
102
|
-
const first = path[0];
|
|
103
|
-
const last = path[path.length - 1];
|
|
104
|
-
if (!first || !last) return;
|
|
105
|
-
graphics.moveTo(first.x, first.y);
|
|
106
|
-
let previous = first;
|
|
107
|
-
for (let index = 1; index < path.length - 1; index += 1) {
|
|
108
|
-
const point = path[index];
|
|
109
|
-
if (!point) continue;
|
|
110
|
-
if (Math.abs(point.x - previous.x) + Math.abs(point.y - previous.y) < minStep) continue;
|
|
111
|
-
graphics.lineTo(point.x, point.y);
|
|
112
|
-
previous = point;
|
|
113
|
-
}
|
|
114
|
-
graphics.lineTo(last.x, last.y);
|
|
115
|
-
}
|
|
116
|
-
/** Trace an open chevron arrowhead aimed along `angle`. */
|
|
117
|
-
function traceArrowhead(graphics, tip, angle, size) {
|
|
118
|
-
graphics.moveTo(tip.x - size * Math.cos(angle - HEAD_SPREAD), tip.y - size * Math.sin(angle - HEAD_SPREAD)).lineTo(tip.x, tip.y).lineTo(tip.x - size * Math.cos(angle + HEAD_SPREAD), tip.y - size * Math.sin(angle + HEAD_SPREAD));
|
|
119
|
-
}
|
|
120
|
-
/** Stroke each style once instead of once per relation. */
|
|
121
|
-
function createStrokeBatch(graphics) {
|
|
122
|
-
const groups = /* @__PURE__ */ new Map();
|
|
123
|
-
return {
|
|
124
|
-
add(style, trace) {
|
|
125
|
-
const key = `${style.color}|${style.width}|${style.alpha}|${style.cap}|${style.join}`;
|
|
126
|
-
const group = groups.get(key);
|
|
127
|
-
if (group) group.traces.push(trace);
|
|
128
|
-
else groups.set(key, {
|
|
129
|
-
style,
|
|
130
|
-
traces: [trace]
|
|
131
|
-
});
|
|
132
|
-
},
|
|
133
|
-
flush() {
|
|
134
|
-
for (const { style, traces } of groups.values()) {
|
|
135
|
-
for (const trace of traces) trace();
|
|
136
|
-
graphics.stroke(style);
|
|
137
|
-
}
|
|
138
|
-
groups.clear();
|
|
139
|
-
}
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
function drawConnections(graphics, entries, states, input, detail, clip, dashes) {
|
|
143
|
-
const batch = createStrokeBatch(graphics);
|
|
144
|
-
entries.forEach(({ connection, resolved }, index) => {
|
|
145
|
-
const state = states[index] ?? "idle";
|
|
146
|
-
const color = pickBoardColor(input.colors, connection.style.color, input.colorScheme);
|
|
147
|
-
const width = Math.max(connection.style.size + (state === "selected" ? 1 : 0), detail.minWidth);
|
|
148
|
-
const round = width * detail.zoom >= MIN_ROUND_PX;
|
|
149
|
-
const alpha = state === "idle" ? .9 : 1;
|
|
150
|
-
const path = resolved.path;
|
|
151
|
-
const dashed = dashes && connection.style.line === "dashed";
|
|
152
|
-
batch.add({
|
|
153
|
-
color: color.stroke,
|
|
154
|
-
width,
|
|
155
|
-
alpha,
|
|
156
|
-
cap: dashed || !round ? "butt" : "round",
|
|
157
|
-
join: round ? "round" : "miter"
|
|
158
|
-
}, dashed ? () => walkDashes(path, clip, (x0, y0, x1, y1, start) => {
|
|
159
|
-
if (start) graphics.moveTo(x0, y0);
|
|
160
|
-
graphics.lineTo(x1, y1);
|
|
161
|
-
}) : () => traceSolid(graphics, path, detail.minStep));
|
|
162
|
-
const headSize = Math.max(HEAD_MIN, connection.style.size * HEAD_SCALE);
|
|
163
|
-
if (headSize * detail.zoom < MIN_HEAD_PX) return;
|
|
164
|
-
const heads = connectionArrowheads(connection);
|
|
165
|
-
const headStyle = {
|
|
166
|
-
color: color.stroke,
|
|
167
|
-
width,
|
|
168
|
-
alpha,
|
|
169
|
-
cap: round ? "round" : "butt",
|
|
170
|
-
join: round ? "round" : "miter"
|
|
171
|
-
};
|
|
172
|
-
const tip = path[path.length - 1];
|
|
173
|
-
const beforeTip = path[path.length - 2];
|
|
174
|
-
if (heads.atTarget && tip && beforeTip) {
|
|
175
|
-
const angle = Math.atan2(tip.y - beforeTip.y, tip.x - beforeTip.x);
|
|
176
|
-
batch.add(headStyle, () => traceArrowhead(graphics, tip, angle, headSize));
|
|
177
|
-
}
|
|
178
|
-
const origin = path[0];
|
|
179
|
-
const afterOrigin = path[1];
|
|
180
|
-
if (heads.atSource && origin && afterOrigin) {
|
|
181
|
-
const angle = Math.atan2(origin.y - afterOrigin.y, origin.x - afterOrigin.x);
|
|
182
|
-
batch.add(headStyle, () => traceArrowhead(graphics, origin, angle, headSize));
|
|
183
|
-
}
|
|
184
|
-
});
|
|
185
|
-
batch.flush();
|
|
186
|
-
}
|
|
187
|
-
function isCurrent(drawn, entries, states, view, colors) {
|
|
188
|
-
return drawn !== null && drawn.view === view && drawn.colors === colors && sameItems(drawn.entries, entries) && sameItems(drawn.states, states);
|
|
189
|
-
}
|
|
190
|
-
function sameItems(a, b) {
|
|
191
|
-
if (a.length !== b.length) return false;
|
|
192
|
-
for (let index = 0; index < a.length; index += 1) if (a[index] !== b[index]) return false;
|
|
193
|
-
return true;
|
|
194
|
-
}
|
|
195
|
-
function createConnectionLayer(options) {
|
|
196
|
-
let layers = null;
|
|
197
|
-
const geometry = createConnectionGeometryCache();
|
|
198
|
-
const labels = /* @__PURE__ */ new Map();
|
|
199
|
-
let lastConnections = null;
|
|
200
|
-
let drawnBase = null;
|
|
201
|
-
let drawnLive = null;
|
|
202
|
-
let withinBudget = true;
|
|
203
|
-
function ensureAttached() {
|
|
204
|
-
if (layers) return layers;
|
|
205
|
-
const next = {
|
|
206
|
-
base: new Graphics({ label: "board-connections" }),
|
|
207
|
-
live: new Graphics({ label: "board-connections-live" }),
|
|
208
|
-
labels: new Container({ label: "board-connection-labels" })
|
|
209
|
-
};
|
|
210
|
-
if (options.zIndex !== void 0) {
|
|
211
|
-
next.base.zIndex = options.zIndex;
|
|
212
|
-
next.live.zIndex = options.zIndex;
|
|
213
|
-
next.labels.zIndex = options.zIndex;
|
|
214
|
-
}
|
|
215
|
-
options.parent.addChild(next.base, next.live, next.labels);
|
|
216
|
-
layers = next;
|
|
217
|
-
return next;
|
|
218
|
-
}
|
|
219
|
-
function releaseLabel(connectionId) {
|
|
220
|
-
const entry = labels.get(connectionId);
|
|
221
|
-
if (!entry) return;
|
|
222
|
-
layers?.labels.removeChild(entry.text);
|
|
223
|
-
entry.text.destroy();
|
|
224
|
-
labels.delete(connectionId);
|
|
225
|
-
}
|
|
226
|
-
function syncLabel({ connection, resolved }, input, host) {
|
|
227
|
-
const value = connection.label.trim();
|
|
228
|
-
if (!value) return false;
|
|
229
|
-
const color = pickBoardColor(input.colors, connection.style.color, input.colorScheme).label;
|
|
230
|
-
let entry = labels.get(connection.id);
|
|
231
|
-
if (!entry) {
|
|
232
|
-
const resolution = textResolutionForZoom(input.zoom);
|
|
233
|
-
const text = new Text({
|
|
234
|
-
text: value,
|
|
235
|
-
style: {
|
|
236
|
-
fill: color,
|
|
237
|
-
fontFamily: BOARD_FONT_STACK,
|
|
238
|
-
fontSize: LABEL_FONT_SIZE,
|
|
239
|
-
fontWeight: "500"
|
|
240
|
-
},
|
|
241
|
-
resolution,
|
|
242
|
-
roundPixels: true
|
|
243
|
-
});
|
|
244
|
-
text.anchor.set(.5);
|
|
245
|
-
host.addChild(text);
|
|
246
|
-
entry = {
|
|
247
|
-
text,
|
|
248
|
-
resolution,
|
|
249
|
-
sig: ""
|
|
250
|
-
};
|
|
251
|
-
labels.set(connection.id, entry);
|
|
252
|
-
}
|
|
253
|
-
syncTextResolution(entry.text, entry, input.zoom);
|
|
254
|
-
const sig = `${value}|${color}`;
|
|
255
|
-
if (sig !== entry.sig) {
|
|
256
|
-
entry.sig = sig;
|
|
257
|
-
entry.text.text = value;
|
|
258
|
-
entry.text.style.fill = color;
|
|
259
|
-
}
|
|
260
|
-
entry.text.position.set(resolved.mid.x, resolved.mid.y);
|
|
261
|
-
return true;
|
|
262
|
-
}
|
|
263
|
-
function drawLayer(graphics, layer, input, detail, clip) {
|
|
264
|
-
graphics.clear();
|
|
265
|
-
drawConnections(graphics, layer.entries, layer.states, input, detail, clip, layer.dashes);
|
|
266
|
-
const labelIds = /* @__PURE__ */ new Set();
|
|
267
|
-
if (detail.labels && layers) {
|
|
268
|
-
for (const entry of layer.entries) if (syncLabel(entry, input, layers.labels)) labelIds.add(entry.connection.id);
|
|
269
|
-
}
|
|
270
|
-
return {
|
|
271
|
-
...layer,
|
|
272
|
-
labelIds
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
function sync(input) {
|
|
276
|
-
if (input.connections.length === 0 && !layers) return;
|
|
277
|
-
const host = ensureAttached();
|
|
278
|
-
if (input.connections !== lastConnections) {
|
|
279
|
-
geometry.retain(input.connections);
|
|
280
|
-
lastConnections = input.connections;
|
|
281
|
-
}
|
|
282
|
-
const detail = detailForZoom(input.zoom);
|
|
283
|
-
const cull = input.cullRect ?? null;
|
|
284
|
-
const clip = detail.dashes ? cull : null;
|
|
285
|
-
const selected = input.selectedIds;
|
|
286
|
-
const liveNodes = input.liveNodeIds;
|
|
287
|
-
const baseEntries = [];
|
|
288
|
-
const baseStates = [];
|
|
289
|
-
const liveEntries = [];
|
|
290
|
-
const liveStates = [];
|
|
291
|
-
let hovered = null;
|
|
292
|
-
for (const connection of input.connections) {
|
|
293
|
-
const entry = geometry.get(connection, input.getFrame);
|
|
294
|
-
if (!entry || input.skipIds?.has(connection.id)) continue;
|
|
295
|
-
if (cull && !rectsIntersect(entry.bounds, cull)) continue;
|
|
296
|
-
if (selected?.has(connection.id)) {
|
|
297
|
-
liveEntries.push(entry);
|
|
298
|
-
liveStates.push("selected");
|
|
299
|
-
} else if (liveNodes?.has(connection.source.itemId) || liveNodes?.has(connection.target.itemId)) {
|
|
300
|
-
liveEntries.push(entry);
|
|
301
|
-
liveStates.push(connection.id === input.hoveredId ? "hovered" : "idle");
|
|
302
|
-
} else {
|
|
303
|
-
baseEntries.push(entry);
|
|
304
|
-
baseStates.push("idle");
|
|
305
|
-
if (connection.id === input.hoveredId) hovered = entry;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
if (hovered) {
|
|
309
|
-
liveEntries.push(hovered);
|
|
310
|
-
liveStates.push("hovered");
|
|
311
|
-
}
|
|
312
|
-
const view = `${detail.zoom}|${textZoomBucket(input.zoom)}|${input.colorScheme}|${clip ? `${clip.x},${clip.y},${clip.width},${clip.height}` : ""}`;
|
|
313
|
-
const baseCurrent = isCurrent(drawnBase, baseEntries, baseStates, view, input.colors);
|
|
314
|
-
const liveCurrent = isCurrent(drawnLive, liveEntries, liveStates, view, input.colors);
|
|
315
|
-
const countFor = (current, drawn, entries) => !detail.dashes ? 0 : current && drawn ? drawn.dashCount : countDashes(entries, clip);
|
|
316
|
-
const baseDashes = countFor(baseCurrent, drawnBase, baseEntries);
|
|
317
|
-
const liveDashes = countFor(liveCurrent, drawnLive, hovered ? liveEntries.slice(0, -1) : liveEntries);
|
|
318
|
-
const total = baseDashes + liveDashes;
|
|
319
|
-
withinBudget = withinBudget ? total <= DASH_BUDGET : total <= DASH_BUDGET * DASH_RESUME_RATIO;
|
|
320
|
-
const dashes = detail.dashes && withinBudget;
|
|
321
|
-
const redraw = (graphics, entries, states, dashCount) => drawLayer(graphics, {
|
|
322
|
-
entries,
|
|
323
|
-
states,
|
|
324
|
-
view,
|
|
325
|
-
colors: input.colors,
|
|
326
|
-
dashCount,
|
|
327
|
-
dashes
|
|
328
|
-
}, input, detail, clip);
|
|
329
|
-
let labelsChanged = false;
|
|
330
|
-
if (!baseCurrent || drawnBase?.dashes !== dashes) {
|
|
331
|
-
drawnBase = redraw(host.base, baseEntries, baseStates, baseDashes);
|
|
332
|
-
labelsChanged = true;
|
|
333
|
-
}
|
|
334
|
-
if (!liveCurrent || drawnLive?.dashes !== dashes) {
|
|
335
|
-
drawnLive = redraw(host.live, liveEntries, liveStates, liveDashes);
|
|
336
|
-
labelsChanged = true;
|
|
337
|
-
}
|
|
338
|
-
if (!labelsChanged) return;
|
|
339
|
-
const wanted = /* @__PURE__ */ new Set([...drawnBase?.labelIds ?? [], ...drawnLive?.labelIds ?? []]);
|
|
340
|
-
for (const connectionId of [...labels.keys()]) if (!wanted.has(connectionId)) releaseLabel(connectionId);
|
|
341
|
-
}
|
|
342
|
-
return {
|
|
343
|
-
sync,
|
|
344
|
-
resolved: (connectionId) => geometry.peek(connectionId)?.resolved ?? null,
|
|
345
|
-
get children() {
|
|
346
|
-
return layers ? [
|
|
347
|
-
layers.base,
|
|
348
|
-
layers.live,
|
|
349
|
-
layers.labels
|
|
350
|
-
] : [];
|
|
351
|
-
},
|
|
352
|
-
destroy: () => {
|
|
353
|
-
for (const entry of labels.values()) entry.text.destroy();
|
|
354
|
-
labels.clear();
|
|
355
|
-
if (layers) {
|
|
356
|
-
layers.base.destroy();
|
|
357
|
-
layers.live.destroy();
|
|
358
|
-
layers.labels.destroy({ children: true });
|
|
359
|
-
}
|
|
360
|
-
layers = null;
|
|
361
|
-
drawnBase = null;
|
|
362
|
-
drawnLive = null;
|
|
363
|
-
withinBudget = true;
|
|
364
|
-
lastConnections = null;
|
|
365
|
-
geometry.clear();
|
|
366
|
-
}
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
/** Frame lookup over a plain item list, for hosts without an index. */
|
|
370
|
-
function framesFromItems(items) {
|
|
371
|
-
const frames = new Map(items.map((item) => [item.id, item.frame]));
|
|
372
|
-
return (id) => frames.get(id);
|
|
373
|
-
}
|
|
374
|
-
//#endregion
|
|
375
|
-
export { createConnectionLayer, framesFromItems };
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { BOARD_FONT_STACK } from "../../../protocol/dist/board-constants.js";
|
|
2
|
-
import { pickBoardColor } from "../../core/palette.js";
|
|
3
|
-
import { syncTextResolution, syncTextWrapWidth, textResolutionForZoom } from "../text-resolution.js";
|
|
4
|
-
import { positionShell } from "./base-card-renderer.js";
|
|
5
|
-
import { drawFarPlate } from "./far-plate.js";
|
|
6
|
-
import { Container, Graphics, Text } from "pixi.js";
|
|
7
|
-
//#region src/board/render/renderers/geo-card-renderer.ts
|
|
8
|
-
const RADIUS = 8;
|
|
9
|
-
const partsByContainer = /* @__PURE__ */ new WeakMap();
|
|
10
|
-
function traceOutline(graphics, geo, width, height) {
|
|
11
|
-
switch (geo) {
|
|
12
|
-
case "ellipse":
|
|
13
|
-
graphics.ellipse(width / 2, height / 2, width / 2, height / 2);
|
|
14
|
-
return;
|
|
15
|
-
case "diamond":
|
|
16
|
-
graphics.moveTo(width / 2, 0).lineTo(width, height / 2).lineTo(width / 2, height).lineTo(0, height / 2).closePath();
|
|
17
|
-
return;
|
|
18
|
-
case "triangle":
|
|
19
|
-
graphics.moveTo(width / 2, 0).lineTo(width, height).lineTo(0, height).closePath();
|
|
20
|
-
return;
|
|
21
|
-
case "rounded":
|
|
22
|
-
graphics.roundRect(0, 0, width, height, RADIUS);
|
|
23
|
-
return;
|
|
24
|
-
default: graphics.rect(0, 0, width, height);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function sync(container, item, context) {
|
|
28
|
-
const parts = partsByContainer.get(container);
|
|
29
|
-
if (!parts) return;
|
|
30
|
-
positionShell(parts.root, item);
|
|
31
|
-
const { width, height } = item.frame;
|
|
32
|
-
const selected = context.selectedIds.has(item.id);
|
|
33
|
-
const hovered = context.hoveredId === item.id;
|
|
34
|
-
const color = pickBoardColor(context.colors, item.color, context.colorScheme);
|
|
35
|
-
syncTextResolution(parts.label, parts, context.zoom);
|
|
36
|
-
const resizing = context.resizingIds.has(item.id);
|
|
37
|
-
const visualSig = [
|
|
38
|
-
width,
|
|
39
|
-
height,
|
|
40
|
-
selected,
|
|
41
|
-
hovered,
|
|
42
|
-
item.geo,
|
|
43
|
-
item.fillOpacity,
|
|
44
|
-
color.fill,
|
|
45
|
-
color.stroke,
|
|
46
|
-
context.palette.muted
|
|
47
|
-
].join("|");
|
|
48
|
-
if (visualSig !== parts.visualSig) {
|
|
49
|
-
parts.visualSig = visualSig;
|
|
50
|
-
parts.shape.clear();
|
|
51
|
-
traceOutline(parts.shape, item.geo, width, height);
|
|
52
|
-
if (item.fillOpacity > 0) parts.shape.fill({
|
|
53
|
-
color: color.fill,
|
|
54
|
-
alpha: item.fillOpacity
|
|
55
|
-
});
|
|
56
|
-
traceOutline(parts.shape, item.geo, width, height);
|
|
57
|
-
parts.shape.stroke({
|
|
58
|
-
color: selected ? color.stroke : hovered ? context.palette.muted : color.stroke,
|
|
59
|
-
width: selected ? 2.5 : 1.75,
|
|
60
|
-
alpha: selected ? 1 : hovered ? .95 : .85
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
const textSig = [item.text, color.label].join("|");
|
|
64
|
-
if (textSig !== parts.textSig) {
|
|
65
|
-
parts.textSig = textSig;
|
|
66
|
-
parts.label.text = item.text;
|
|
67
|
-
parts.label.visible = item.text.length > 0;
|
|
68
|
-
parts.label.style.fill = color.label;
|
|
69
|
-
}
|
|
70
|
-
syncTextWrapWidth(parts.label, parts, Math.max(1, width - 16), resizing);
|
|
71
|
-
parts.label.position.set(width / 2, height / 2);
|
|
72
|
-
}
|
|
73
|
-
const geoCardRenderer = {
|
|
74
|
-
id: "geo-card",
|
|
75
|
-
canRender: (item) => item.type === "geo",
|
|
76
|
-
create: (item, context) => {
|
|
77
|
-
const root = new Container();
|
|
78
|
-
const shape = new Graphics();
|
|
79
|
-
const resolution = textResolutionForZoom(context.zoom);
|
|
80
|
-
const label = new Text({
|
|
81
|
-
text: "",
|
|
82
|
-
style: {
|
|
83
|
-
fill: 16777215,
|
|
84
|
-
fontFamily: BOARD_FONT_STACK,
|
|
85
|
-
fontSize: 14,
|
|
86
|
-
fontWeight: "500",
|
|
87
|
-
align: "center",
|
|
88
|
-
wordWrap: true,
|
|
89
|
-
lineHeight: 20
|
|
90
|
-
},
|
|
91
|
-
resolution,
|
|
92
|
-
roundPixels: true
|
|
93
|
-
});
|
|
94
|
-
label.anchor.set(.5);
|
|
95
|
-
root.addChild(shape, label);
|
|
96
|
-
partsByContainer.set(root, {
|
|
97
|
-
root,
|
|
98
|
-
shape,
|
|
99
|
-
label,
|
|
100
|
-
visualSig: "",
|
|
101
|
-
textSig: "",
|
|
102
|
-
wrapWidth: 0,
|
|
103
|
-
resolution
|
|
104
|
-
});
|
|
105
|
-
if (item.type === "geo") sync(root, item, context);
|
|
106
|
-
return root;
|
|
107
|
-
},
|
|
108
|
-
update: (container, item, context) => {
|
|
109
|
-
if (item.type === "geo") sync(container, item, context);
|
|
110
|
-
},
|
|
111
|
-
renderFar: (graphics, item, context) => {
|
|
112
|
-
if (item.type !== "geo") return;
|
|
113
|
-
const color = pickBoardColor(context.colors, item.color, context.colorScheme);
|
|
114
|
-
drawFarPlate(graphics, item.frame, {
|
|
115
|
-
fill: color.fill,
|
|
116
|
-
fillAlpha: Math.max(.18, item.fillOpacity),
|
|
117
|
-
accent: color.stroke,
|
|
118
|
-
accentAlpha: .9
|
|
119
|
-
});
|
|
120
|
-
},
|
|
121
|
-
destroy: (container) => {
|
|
122
|
-
partsByContainer.get(container)?.root.destroy({ children: true });
|
|
123
|
-
partsByContainer.delete(container);
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
//#endregion
|
|
127
|
-
export { geoCardRenderer };
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { BoardAuthoringItem, BoardAuthoringSnapshot } from "../protocol/dist/board-authoring.js";
|
|
2
|
-
import { BoardMutationReceipt } from "../protocol/dist/board.js";
|
|
3
|
-
import { BoardDocument, BoardItem } from "../protocol/dist/board-document.js";
|
|
4
|
-
import "../protocol/dist/index.js";
|
|
5
|
-
//#region src/board/semantic-document.d.ts
|
|
6
|
-
declare const DEFAULT_BOARD_APPEARANCE: {
|
|
7
|
-
theme?: string | undefined;
|
|
8
|
-
motion?: {
|
|
9
|
-
enter?: {
|
|
10
|
-
kind: string;
|
|
11
|
-
kindVersion: number;
|
|
12
|
-
params: Record<string, unknown>;
|
|
13
|
-
} | undefined;
|
|
14
|
-
} | undefined;
|
|
15
|
-
mood?: "arcane" | "clean" | "cyber" | "natural" | "playful" | undefined;
|
|
16
|
-
background: {
|
|
17
|
-
kind: "custom" | "dots" | "grid" | "image" | "shader" | "solid";
|
|
18
|
-
color?: string | undefined;
|
|
19
|
-
imageUrl?: string | undefined;
|
|
20
|
-
fit?: "contain" | "cover" | "repeat" | undefined;
|
|
21
|
-
position?: "bottom" | "center" | "left" | "right" | "top" | undefined;
|
|
22
|
-
opacity?: number | undefined;
|
|
23
|
-
};
|
|
24
|
-
grid: {
|
|
25
|
-
visible: boolean;
|
|
26
|
-
size: number;
|
|
27
|
-
opacity: number;
|
|
28
|
-
};
|
|
29
|
-
};
|
|
30
|
-
/** Convert a public authoring Item to the renderer/editor document shape. */
|
|
31
|
-
declare function boardAuthoringItemToDocumentItem(item: BoardAuthoringItem): BoardItem;
|
|
32
|
-
/** Convert the renderer/editor item back to the public authoring envelope. */
|
|
33
|
-
declare function boardItemToAuthoringItem(item: BoardItem): BoardAuthoringItem | null;
|
|
34
|
-
declare function boardAuthoringSnapshotToDocument(input: BoardAuthoringSnapshot): BoardDocument;
|
|
35
|
-
declare function applyBoardAuthoringSnapshot(document: BoardDocument, input: BoardAuthoringSnapshot, changed: BoardMutationReceipt["changed"]): BoardDocument;
|
|
36
|
-
//#endregion
|
|
37
|
-
export { DEFAULT_BOARD_APPEARANCE, applyBoardAuthoringSnapshot, boardAuthoringItemToDocumentItem, boardAuthoringSnapshotToDocument, boardItemToAuthoringItem };
|