@neta-art/cohub 8.23.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 +7 -27
- package/dist/board/headless/index.js +20 -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 +2296 -3864
- package/dist/chunks/host-bridge.d.ts +253 -0
- package/dist/chunks/http.d.ts +238 -58
- package/dist/chunks/http.js +1061 -1034
- 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 +76 -193
- package/dist/index.js +2037 -1191
- 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,15 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { drawPointsBounds, drawSampleRadius } from "../../protocol/dist/board-layout.js";
|
|
2
2
|
import { getStroke } from "perfect-freehand";
|
|
3
3
|
//#region src/board/core/draw-geometry.ts
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
/** Axis-aligned bounds of a stroke in its local space, padded by stroke width. */
|
|
7
|
-
const computeDrawBounds = boardDrawBounds;
|
|
8
|
-
/**
|
|
9
|
-
* Ramer–Douglas–Peucker simplification. Reduces point count for low-zoom
|
|
10
|
-
* rendering without touching the persisted raw samples. Returns indices into
|
|
11
|
-
* the input so callers can keep pressure alongside the simplified path.
|
|
12
|
-
*/
|
|
4
|
+
const sampleRadius = drawSampleRadius;
|
|
5
|
+
const computeDrawBounds = drawPointsBounds;
|
|
13
6
|
function simplifyDrawIndices(points, tolerance) {
|
|
14
7
|
const n = points.length;
|
|
15
8
|
if (n <= 2 || tolerance <= 0) return points.map((_, i) => i);
|
|
@@ -54,11 +47,36 @@ function perpendicularDistance(point, a, b) {
|
|
|
54
47
|
const projY = a.y + t * dy;
|
|
55
48
|
return Math.hypot(point.x - projX, point.y - projY);
|
|
56
49
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
50
|
+
function trimDrawPoints(points, trim) {
|
|
51
|
+
if (trim === void 0 || trim >= 1) return points;
|
|
52
|
+
if (trim <= 0) return [];
|
|
53
|
+
if (points.length < 2) return points;
|
|
54
|
+
let total = 0;
|
|
55
|
+
for (let i = 1; i < points.length; i += 1) {
|
|
56
|
+
const a = points[i - 1];
|
|
57
|
+
const b = points[i];
|
|
58
|
+
total += Math.hypot(b.x - a.x, b.y - a.y);
|
|
59
|
+
}
|
|
60
|
+
let remaining = total * trim;
|
|
61
|
+
const out = [points[0]];
|
|
62
|
+
for (let i = 1; i < points.length; i += 1) {
|
|
63
|
+
const a = points[i - 1];
|
|
64
|
+
const b = points[i];
|
|
65
|
+
const length = Math.hypot(b.x - a.x, b.y - a.y);
|
|
66
|
+
if (length >= remaining) {
|
|
67
|
+
const t = length > 0 ? remaining / length : 0;
|
|
68
|
+
out.push({
|
|
69
|
+
x: a.x + (b.x - a.x) * t,
|
|
70
|
+
y: a.y + (b.y - a.y) * t,
|
|
71
|
+
p: a.p + (b.p - a.p) * t
|
|
72
|
+
});
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
out.push(b);
|
|
76
|
+
remaining -= length;
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
62
80
|
function buildStrokeOutline(points, size) {
|
|
63
81
|
const n = points.length;
|
|
64
82
|
if (n === 0) return [];
|
|
@@ -122,7 +140,6 @@ function buildStrokeOutline(points, size) {
|
|
|
122
140
|
}));
|
|
123
141
|
}
|
|
124
142
|
const RIBBON_CIRCLE_SIDES = 8;
|
|
125
|
-
/** Whether a sample needs a round join rather than the neighboring segment caps. */
|
|
126
143
|
function isStrokeCorner(points, index) {
|
|
127
144
|
if (index === 0 || index === points.length - 1) return true;
|
|
128
145
|
const before = points[index - 1];
|
|
@@ -138,83 +155,129 @@ function isStrokeCorner(points, index) {
|
|
|
138
155
|
if (aLength < 1e-6 || bLength < 1e-6) return true;
|
|
139
156
|
return (ax * bx + ay * by) / (aLength * bLength) < .92;
|
|
140
157
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const indices = [];
|
|
151
|
-
const uvs = [];
|
|
152
|
-
const progress = [];
|
|
153
|
-
if (points.length === 0) return {
|
|
154
|
-
positions: /* @__PURE__ */ new Float32Array(),
|
|
155
|
-
indices: /* @__PURE__ */ new Uint32Array(),
|
|
156
|
-
uvs: /* @__PURE__ */ new Float32Array(),
|
|
157
|
-
progress: /* @__PURE__ */ new Float32Array()
|
|
158
|
+
const SAMPLE_VERTICES = 13;
|
|
159
|
+
function segmentNormal(points, index) {
|
|
160
|
+
const from = points[index];
|
|
161
|
+
const to = points[index + 1];
|
|
162
|
+
if (!from || !to) return null;
|
|
163
|
+
const length = Math.hypot(to.x - from.x, to.y - from.y);
|
|
164
|
+
return length < 1e-6 ? null : {
|
|
165
|
+
x: -(to.y - from.y) / length,
|
|
166
|
+
y: (to.x - from.x) / length
|
|
158
167
|
};
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
}
|
|
169
|
+
function edgeOffset(points, index, own) {
|
|
170
|
+
if (isStrokeCorner(points, index)) return own;
|
|
171
|
+
const before = segmentNormal(points, index - 1);
|
|
172
|
+
const after = segmentNormal(points, index);
|
|
173
|
+
if (!before || !after) return own;
|
|
174
|
+
const x = before.x + after.x;
|
|
175
|
+
const y = before.y + after.y;
|
|
176
|
+
const length = Math.hypot(x, y);
|
|
177
|
+
if (length < 1e-6) return own;
|
|
178
|
+
const scale = 1 / Math.max(.5, (x * own.x + y * own.y) / length);
|
|
179
|
+
return {
|
|
180
|
+
x: x / length * scale,
|
|
181
|
+
y: y / length * scale
|
|
172
182
|
};
|
|
173
|
-
|
|
174
|
-
|
|
183
|
+
}
|
|
184
|
+
/** A growing stroke re-emits only its last two samples. */
|
|
185
|
+
function createStrokeRibbonBuilder(size) {
|
|
186
|
+
let positions = /* @__PURE__ */ new Float32Array(1664);
|
|
187
|
+
let distances = /* @__PURE__ */ new Float32Array(832);
|
|
188
|
+
let indices = /* @__PURE__ */ new Uint32Array(1920);
|
|
189
|
+
let lengths = /* @__PURE__ */ new Float64Array(64);
|
|
190
|
+
let marks = /* @__PURE__ */ new Uint32Array(128);
|
|
191
|
+
let source = null;
|
|
192
|
+
let built = 0;
|
|
193
|
+
let vertexCount = 0;
|
|
194
|
+
let indexCount = 0;
|
|
195
|
+
function grow(buffer, needed) {
|
|
196
|
+
if (buffer.length >= needed) return buffer;
|
|
197
|
+
const next = new buffer.constructor(Math.max(needed, buffer.length * 2));
|
|
198
|
+
next.set(buffer);
|
|
199
|
+
return next;
|
|
200
|
+
}
|
|
201
|
+
function vertex(x, y, at) {
|
|
202
|
+
positions[vertexCount * 2] = x;
|
|
203
|
+
positions[vertexCount * 2 + 1] = y;
|
|
204
|
+
distances[vertexCount] = at;
|
|
205
|
+
return vertexCount++;
|
|
206
|
+
}
|
|
207
|
+
function triangle(a, b, c) {
|
|
208
|
+
indices[indexCount++] = a;
|
|
209
|
+
indices[indexCount++] = b;
|
|
210
|
+
indices[indexCount++] = c;
|
|
211
|
+
}
|
|
212
|
+
function emit(points, index) {
|
|
213
|
+
positions = grow(positions, (vertexCount + SAMPLE_VERTICES) * 2);
|
|
214
|
+
distances = grow(distances, vertexCount + SAMPLE_VERTICES);
|
|
215
|
+
indices = grow(indices, indexCount + 30);
|
|
216
|
+
const point = points[index];
|
|
217
|
+
const at = lengths[index] ?? 0;
|
|
175
218
|
const radius = sampleRadius(size, point.p);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
219
|
+
if (isStrokeCorner(points, index)) {
|
|
220
|
+
const center = vertex(point.x, point.y, at);
|
|
221
|
+
for (let side = 0; side < RIBBON_CIRCLE_SIDES; side += 1) {
|
|
222
|
+
const angle = side / RIBBON_CIRCLE_SIDES * Math.PI * 2;
|
|
223
|
+
vertex(point.x + Math.cos(angle) * radius, point.y + Math.sin(angle) * radius, at);
|
|
224
|
+
}
|
|
225
|
+
for (let side = 0; side < RIBBON_CIRCLE_SIDES; side += 1) triangle(center, center + 1 + side, center + 1 + (side + 1) % RIBBON_CIRCLE_SIDES);
|
|
181
226
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (i === points.length - 1) continue;
|
|
189
|
-
const next = points[i + 1];
|
|
190
|
-
if (!next) continue;
|
|
191
|
-
const dx = next.x - point.x;
|
|
192
|
-
const dy = next.y - point.y;
|
|
193
|
-
const length = Math.hypot(dx, dy);
|
|
194
|
-
if (length < 1e-6) continue;
|
|
195
|
-
const normalX = -dy / length;
|
|
196
|
-
const normalY = dx / length;
|
|
197
|
-
const radius = sampleRadius(size, point.p);
|
|
198
|
-
const leftA = addVertex(point.x + normalX * radius, point.y + normalY * radius, lengths[i] ?? 0);
|
|
199
|
-
const rightA = addVertex(point.x - normalX * radius, point.y - normalY * radius, lengths[i] ?? 0);
|
|
227
|
+
const next = points[index + 1];
|
|
228
|
+
const normal = segmentNormal(points, index);
|
|
229
|
+
if (!next || !normal) return;
|
|
230
|
+
const start = edgeOffset(points, index, normal);
|
|
231
|
+
const end = edgeOffset(points, index + 1, normal);
|
|
232
|
+
const nextAt = lengths[index + 1] ?? at;
|
|
200
233
|
const nextRadius = sampleRadius(size, next.p);
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
234
|
+
const leftA = vertex(point.x + start.x * radius, point.y + start.y * radius, at);
|
|
235
|
+
const rightA = vertex(point.x - start.x * radius, point.y - start.y * radius, at);
|
|
236
|
+
const leftB = vertex(next.x + end.x * nextRadius, next.y + end.y * nextRadius, nextAt);
|
|
237
|
+
const rightB = vertex(next.x - end.x * nextRadius, next.y - end.y * nextRadius, nextAt);
|
|
238
|
+
triangle(leftA, rightA, leftB);
|
|
239
|
+
triangle(rightA, rightB, leftB);
|
|
205
240
|
}
|
|
241
|
+
return { build(points) {
|
|
242
|
+
const count = points.length;
|
|
243
|
+
const from = points === source && count >= built ? Math.max(0, built - 2) : 0;
|
|
244
|
+
source = points;
|
|
245
|
+
built = count;
|
|
246
|
+
lengths = grow(lengths, count);
|
|
247
|
+
marks = grow(marks, count * 2);
|
|
248
|
+
vertexCount = from > 0 ? marks[from * 2] : 0;
|
|
249
|
+
indexCount = from > 0 ? marks[from * 2 + 1] : 0;
|
|
250
|
+
for (let index = from; index < count; index += 1) {
|
|
251
|
+
const before = points[index - 1];
|
|
252
|
+
const point = points[index];
|
|
253
|
+
lengths[index] = before ? lengths[index - 1] + Math.hypot(point.x - before.x, point.y - before.y) : 0;
|
|
254
|
+
}
|
|
255
|
+
for (let index = from; index < count; index += 1) {
|
|
256
|
+
marks[index * 2] = vertexCount;
|
|
257
|
+
marks[index * 2 + 1] = indexCount;
|
|
258
|
+
emit(points, index);
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
positions: positions.subarray(0, vertexCount * 2),
|
|
262
|
+
indices: indices.subarray(0, indexCount),
|
|
263
|
+
distances: distances.subarray(0, vertexCount),
|
|
264
|
+
length: count ? lengths[count - 1] : 0
|
|
265
|
+
};
|
|
266
|
+
} };
|
|
267
|
+
}
|
|
268
|
+
function buildStrokeRibbonGeometry(points, size) {
|
|
269
|
+
const mesh = createStrokeRibbonBuilder(size).build(points);
|
|
270
|
+
const total = Math.max(mesh.length, 1e-6);
|
|
271
|
+
const progress = mesh.distances.map((at) => at / total);
|
|
272
|
+
const uvs = new Float32Array(progress.length * 2);
|
|
273
|
+
for (let index = 0; index < progress.length; index += 1) uvs[index * 2] = progress[index];
|
|
206
274
|
return {
|
|
207
|
-
positions:
|
|
208
|
-
indices:
|
|
209
|
-
uvs
|
|
210
|
-
progress
|
|
275
|
+
positions: mesh.positions.slice(),
|
|
276
|
+
indices: mesh.indices.slice(),
|
|
277
|
+
uvs,
|
|
278
|
+
progress
|
|
211
279
|
};
|
|
212
280
|
}
|
|
213
|
-
/**
|
|
214
|
-
* Distance from a world point to the stroke's polyline, in the shape's local
|
|
215
|
-
* space. Used for hit testing: a hit registers within half the stroke width plus
|
|
216
|
-
* a small tolerance. `local` is the point expressed in the draw item's frame.
|
|
217
|
-
*/
|
|
218
281
|
function distanceToStroke(points, local) {
|
|
219
282
|
if (points.length === 0) return Number.POSITIVE_INFINITY;
|
|
220
283
|
const first = points[0];
|
|
@@ -235,4 +298,4 @@ function distanceToStroke(points, local) {
|
|
|
235
298
|
return min;
|
|
236
299
|
}
|
|
237
300
|
//#endregion
|
|
238
|
-
export { buildStrokeOutline, buildStrokeRibbonGeometry, computeDrawBounds, distanceToStroke, isStrokeCorner, sampleRadius, simplifyDrawIndices };
|
|
301
|
+
export { buildStrokeOutline, buildStrokeRibbonGeometry, computeDrawBounds, createStrokeRibbonBuilder, distanceToStroke, isStrokeCorner, sampleRadius, simplifyDrawIndices, trimDrawPoints };
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BoardSceneItem } from "./scene.js";
|
|
2
2
|
//#region src/board/core/export-assets.d.ts
|
|
3
|
-
/** Bound source textures independently from the final output bitmap budget. */
|
|
4
3
|
declare const BOARD_EXPORT_MAX_TEXTURES = 64;
|
|
5
4
|
type BoardExportAssetSelection = {
|
|
6
|
-
|
|
7
|
-
items: BoardItem[];
|
|
5
|
+
items: BoardSceneItem[];
|
|
8
6
|
keys: string[];
|
|
9
7
|
omittedKeys: string[];
|
|
10
8
|
};
|
|
11
|
-
|
|
12
|
-
declare function selectBoardExportAssets(items: BoardItem[], assetKey: (item: BoardItem) => string | null, maxTextures?: number): BoardExportAssetSelection;
|
|
9
|
+
declare function selectBoardExportAssets(items: BoardSceneItem[], assetKey: (item: BoardSceneItem) => string | null, maxTextures?: number): BoardExportAssetSelection;
|
|
13
10
|
//#endregion
|
|
14
11
|
export { BOARD_EXPORT_MAX_TEXTURES, BoardExportAssetSelection, selectBoardExportAssets };
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
//#region src/board/core/export-assets.ts
|
|
2
|
-
/** Bound source textures independently from the final output bitmap budget. */
|
|
3
2
|
const BOARD_EXPORT_MAX_TEXTURES = 64;
|
|
4
|
-
/** Select a stable, document-ordered set of unique preview assets to load. */
|
|
5
3
|
function selectBoardExportAssets(items, assetKey, maxTextures = 64) {
|
|
6
4
|
const limit = Number.isSafeInteger(maxTextures) ? Math.max(0, maxTextures) : 64;
|
|
7
5
|
const selected = /* @__PURE__ */ new Map();
|
|
@@ -1,95 +1,44 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { BoardDocument } from "../../protocol/dist/board-model.js";
|
|
2
|
+
import "../../protocol/dist/index.js";
|
|
3
3
|
import { Rect } from "../geometry.js";
|
|
4
|
-
import {
|
|
4
|
+
import { BoardScene, BoardSceneItem } from "./scene.js";
|
|
5
5
|
//#region src/board/core/export-plan.d.ts
|
|
6
|
-
|
|
7
|
-
type BoardExportRegion =
|
|
8
|
-
/** Everything in the document. */
|
|
9
|
-
{
|
|
6
|
+
type BoardExportRegion = {
|
|
10
7
|
kind: "all";
|
|
11
|
-
} |
|
|
12
|
-
/** Exactly these items, whatever else overlaps them. */
|
|
13
|
-
{
|
|
8
|
+
} | {
|
|
14
9
|
kind: "items";
|
|
15
10
|
ids: string[];
|
|
16
|
-
} |
|
|
17
|
-
/** A frame item's rect, treated as a page: its chrome is excluded. */
|
|
18
|
-
{
|
|
11
|
+
} | {
|
|
19
12
|
kind: "frame";
|
|
20
13
|
id: string;
|
|
21
|
-
} |
|
|
22
|
-
/** An explicit world-space rect. */
|
|
23
|
-
{
|
|
14
|
+
} | {
|
|
24
15
|
kind: "rect";
|
|
25
16
|
rect: Rect;
|
|
26
17
|
};
|
|
27
18
|
type BoardExportPlanInput = {
|
|
28
|
-
|
|
19
|
+
scene: BoardScene;
|
|
29
20
|
region: BoardExportRegion;
|
|
30
|
-
/** Output pixels per world unit. Defaults to 2 (retina-grade). */
|
|
31
21
|
scale?: number;
|
|
32
|
-
/** World-space breathing room around the content. Frames use 0. */
|
|
33
22
|
padding?: number;
|
|
34
23
|
maxEdge?: number;
|
|
35
24
|
maxPixels?: number;
|
|
36
25
|
};
|
|
37
26
|
type BoardExportPlan = {
|
|
38
|
-
/** World-space rect captured, padding included. */
|
|
39
27
|
world: Rect;
|
|
40
|
-
/** Scale actually used, after clamping. */
|
|
41
28
|
scale: number;
|
|
42
|
-
/** Scale asked for, before clamping. */
|
|
43
29
|
requestedScale: number;
|
|
44
|
-
/** Output size in pixels. */
|
|
45
30
|
width: number;
|
|
46
31
|
height: number;
|
|
47
|
-
|
|
48
|
-
items: BoardItem[];
|
|
49
|
-
/**
|
|
50
|
-
* Connections to draw.
|
|
51
|
-
*
|
|
52
|
-
* A relation is only included when both of its nodes are in `items`: half a
|
|
53
|
-
* connection would render as a line into empty space, which reads as a defect
|
|
54
|
-
* rather than as a clipped edge.
|
|
55
|
-
*/
|
|
56
|
-
connections: BoardConnection[];
|
|
57
|
-
/** True when `scale` had to be reduced to fit the size budget. */
|
|
32
|
+
items: BoardSceneItem[];
|
|
58
33
|
clamped: boolean;
|
|
59
34
|
};
|
|
60
|
-
|
|
61
|
-
* Normalise a document before it reaches the renderers.
|
|
62
|
-
*
|
|
63
|
-
* Renderers read shape fields directly and assume schema defaults have been
|
|
64
|
-
* applied — a hand-built or partially-migrated document would otherwise reach
|
|
65
|
-
* them with missing fields. Parsing here means every entry point (CLI, web,
|
|
66
|
-
* tests) gets the same guarantee, and an invalid document fails with a schema
|
|
67
|
-
* error instead of a render-time crash.
|
|
68
|
-
*/
|
|
69
|
-
declare function normalizeBoardDocument(document: BoardDocument): BoardDocument;
|
|
70
|
-
/**
|
|
71
|
-
* Hard ceilings.
|
|
72
|
-
*
|
|
73
|
-
* `MAX_EDGE` stays under the 8192 texture limit that essentially every WebGL2
|
|
74
|
-
* and Canvas2D backend guarantees. `MAX_PIXELS` bounds peak memory instead of
|
|
75
|
-
* edge length — a 8192×8192 RGBA buffer alone is 256MB, which is enough to kill
|
|
76
|
-
* a browser tab, so the total is capped well below the square of the edge.
|
|
77
|
-
*/
|
|
35
|
+
declare function normalizeBoardDocument(document: unknown): BoardDocument;
|
|
78
36
|
declare const BOARD_EXPORT_MAX_EDGE = 8192;
|
|
79
37
|
declare const BOARD_EXPORT_MAX_PIXELS = 32000000;
|
|
80
38
|
declare const BOARD_EXPORT_DEFAULT_SCALE = 2;
|
|
81
39
|
declare const BOARD_EXPORT_DEFAULT_PADDING = 32;
|
|
82
|
-
/** Above this, an export is still produced but the caller is warned. */
|
|
83
40
|
declare const BOARD_EXPORT_ITEM_WARN_THRESHOLD = 2000;
|
|
84
|
-
declare function
|
|
85
|
-
/** Bounds of a single item. Arrows resolve through their own curve geometry. */
|
|
86
|
-
declare function exportItemBounds(item: BoardItem, _getFrame?: FrameLookup): Rect;
|
|
87
|
-
/** Bounds of a connection, resolved against the document's node frames. */
|
|
88
|
-
declare function exportConnectionBounds(connection: BoardConnection, getFrame: FrameLookup): Rect | null;
|
|
89
|
-
/**
|
|
90
|
-
* Resolve a region into a concrete capture plan, or null when there is nothing
|
|
91
|
-
* to draw. Callers treat null as "empty selection", not as an error.
|
|
92
|
-
*/
|
|
41
|
+
declare function exportItemBounds(item: BoardSceneItem, scene: BoardScene): Rect | null;
|
|
93
42
|
declare function planBoardExport(input: BoardExportPlanInput): BoardExportPlan | null;
|
|
94
43
|
//#endregion
|
|
95
|
-
export { BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BoardExportPlan, BoardExportPlanInput, BoardExportRegion,
|
|
44
|
+
export { BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BoardExportPlan, BoardExportPlanInput, BoardExportRegion, exportItemBounds, normalizeBoardDocument, planBoardExport };
|
|
@@ -1,141 +1,103 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { arrowBindings } from "../../protocol/dist/board-layout.js";
|
|
2
|
+
import { parseBoardDocument } from "../../protocol/dist/board-patch.js";
|
|
2
3
|
import { itemBounds, rectsIntersect, unionRects } from "../geometry.js";
|
|
3
|
-
import {
|
|
4
|
-
import { connectionBounds, resolveConnection } from "./connections.js";
|
|
4
|
+
import { arrowPathBounds, resolveSceneArrow } from "./arrow-geometry.js";
|
|
5
5
|
//#region src/board/core/export-plan.ts
|
|
6
|
-
/**
|
|
7
|
-
* Export planning — pure geometry, no renderer.
|
|
8
|
-
*
|
|
9
|
-
* Every platform (browser, CLI) resolves *what* to capture and *how large* the
|
|
10
|
-
* result may be through this module, so a `--scale 4` on a huge board behaves
|
|
11
|
-
* identically everywhere and no caller can accidentally ask the GPU for a
|
|
12
|
-
* texture it cannot allocate.
|
|
13
|
-
*/
|
|
14
|
-
/**
|
|
15
|
-
* Normalise a document before it reaches the renderers.
|
|
16
|
-
*
|
|
17
|
-
* Renderers read shape fields directly and assume schema defaults have been
|
|
18
|
-
* applied — a hand-built or partially-migrated document would otherwise reach
|
|
19
|
-
* them with missing fields. Parsing here means every entry point (CLI, web,
|
|
20
|
-
* tests) gets the same guarantee, and an invalid document fails with a schema
|
|
21
|
-
* error instead of a render-time crash.
|
|
22
|
-
*/
|
|
23
6
|
function normalizeBoardDocument(document) {
|
|
24
|
-
|
|
7
|
+
const parsed = parseBoardDocument(document);
|
|
8
|
+
if (!parsed.ok) throw new Error(`Invalid Board document: ${parsed.diagnostics.map((entry) => `${entry.path}: ${entry.message}`).join("; ")}`);
|
|
9
|
+
return parsed.document;
|
|
25
10
|
}
|
|
26
|
-
/**
|
|
27
|
-
* Hard ceilings.
|
|
28
|
-
*
|
|
29
|
-
* `MAX_EDGE` stays under the 8192 texture limit that essentially every WebGL2
|
|
30
|
-
* and Canvas2D backend guarantees. `MAX_PIXELS` bounds peak memory instead of
|
|
31
|
-
* edge length — a 8192×8192 RGBA buffer alone is 256MB, which is enough to kill
|
|
32
|
-
* a browser tab, so the total is capped well below the square of the edge.
|
|
33
|
-
*/
|
|
34
11
|
const BOARD_EXPORT_MAX_EDGE = 8192;
|
|
35
12
|
const BOARD_EXPORT_MAX_PIXELS = 32e6;
|
|
36
13
|
const BOARD_EXPORT_DEFAULT_SCALE = 2;
|
|
37
14
|
const BOARD_EXPORT_DEFAULT_PADDING = 32;
|
|
38
|
-
/** Above this, an export is still produced but the caller is warned. */
|
|
39
15
|
const BOARD_EXPORT_ITEM_WARN_THRESHOLD = 2e3;
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function exportConnectionBounds(connection, getFrame) {
|
|
51
|
-
const resolved = resolveConnection(connection, getFrame);
|
|
52
|
-
return resolved ? connectionBounds(resolved, connection.style.size) : null;
|
|
16
|
+
function exportItemBounds(item, scene) {
|
|
17
|
+
let bounds = item.type === "arrow" ? arrowPathBounds(resolveSceneArrow(item, scene), item.style.strokeWidth) : itemBounds(item.frame);
|
|
18
|
+
let cursor = item.parent;
|
|
19
|
+
for (let depth = 0; cursor && bounds && depth < 64; depth += 1) {
|
|
20
|
+
const parent = scene.get(cursor);
|
|
21
|
+
if (!parent) break;
|
|
22
|
+
if (parent.type === "frame" && parent.props.clip !== false) bounds = intersectRects(bounds, itemBounds(parent.frame));
|
|
23
|
+
cursor = parent.parent;
|
|
24
|
+
}
|
|
25
|
+
return bounds;
|
|
53
26
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
27
|
+
function intersectRects(a, b) {
|
|
28
|
+
const x = Math.max(a.x, b.x);
|
|
29
|
+
const y = Math.max(a.y, b.y);
|
|
30
|
+
const right = Math.min(a.x + a.width, b.x + b.width);
|
|
31
|
+
const bottom = Math.min(a.y + a.height, b.y + b.height);
|
|
32
|
+
return right > x && bottom > y ? {
|
|
33
|
+
x,
|
|
34
|
+
y,
|
|
35
|
+
width: right - x,
|
|
36
|
+
height: bottom - y
|
|
37
|
+
} : null;
|
|
59
38
|
}
|
|
60
|
-
function resolveRegion(
|
|
39
|
+
function resolveRegion(scene, region) {
|
|
40
|
+
const boundsOf = /* @__PURE__ */ new Map();
|
|
41
|
+
const bounds = (item) => {
|
|
42
|
+
if (!boundsOf.has(item.id)) boundsOf.set(item.id, exportItemBounds(item, scene));
|
|
43
|
+
return boundsOf.get(item.id) ?? null;
|
|
44
|
+
};
|
|
45
|
+
const visible = (item, rect) => {
|
|
46
|
+
const box = bounds(item);
|
|
47
|
+
return box !== null && rectsIntersect(box, rect);
|
|
48
|
+
};
|
|
49
|
+
const union = (items) => unionRects(items.flatMap((item) => bounds(item) ?? []));
|
|
61
50
|
switch (region.kind) {
|
|
62
|
-
case "all": {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
rect: unionRects([...document.items.map((item) => exportItemBounds(item)), ...connectionBoundsList(connections, getFrame)]),
|
|
68
|
-
padding: null
|
|
69
|
-
};
|
|
70
|
-
}
|
|
51
|
+
case "all": return {
|
|
52
|
+
items: [...scene.items],
|
|
53
|
+
rect: union(scene.items),
|
|
54
|
+
padding: null
|
|
55
|
+
};
|
|
71
56
|
case "items": {
|
|
72
|
-
const wanted = new Set(region.ids);
|
|
73
|
-
const
|
|
74
|
-
|
|
57
|
+
const wanted = new Set(region.ids.flatMap((id) => scene.get(id) ? [id, ...scene.descendants(id)] : []));
|
|
58
|
+
for (const id of [...wanted]) for (const arrowId of scene.binders(id)) {
|
|
59
|
+
const arrow = scene.get(arrowId);
|
|
60
|
+
if (arrow && arrowBindings(arrow).every((bound) => wanted.has(bound))) wanted.add(arrowId);
|
|
61
|
+
}
|
|
62
|
+
const items = scene.items.filter((item) => wanted.has(item.id));
|
|
75
63
|
return {
|
|
76
64
|
items,
|
|
77
|
-
|
|
78
|
-
rect: unionRects([...items.map((item) => exportItemBounds(item)), ...connectionBoundsList(connections, getFrame)]),
|
|
65
|
+
rect: union(items),
|
|
79
66
|
padding: null
|
|
80
67
|
};
|
|
81
68
|
}
|
|
82
69
|
case "frame": {
|
|
83
|
-
const frame =
|
|
70
|
+
const frame = scene.get(region.id);
|
|
84
71
|
if (!frame) return {
|
|
85
72
|
items: [],
|
|
86
|
-
connections: [],
|
|
87
73
|
rect: null,
|
|
88
74
|
padding: null
|
|
89
75
|
};
|
|
90
76
|
const rect = itemBounds(frame.frame);
|
|
91
|
-
const items = document.items.filter((item) => item.id !== region.id && rectsIntersect(exportItemBounds(item), rect));
|
|
92
77
|
return {
|
|
93
|
-
items,
|
|
94
|
-
connections: connectionsWithin(document, items),
|
|
78
|
+
items: scene.items.filter((item) => item.id !== region.id && visible(item, rect)),
|
|
95
79
|
rect,
|
|
96
80
|
padding: 0
|
|
97
81
|
};
|
|
98
82
|
}
|
|
99
83
|
case "rect": {
|
|
100
84
|
const rect = region.rect;
|
|
101
|
-
const items = document.items.filter((item) => rectsIntersect(exportItemBounds(item), rect));
|
|
102
85
|
return {
|
|
103
|
-
items,
|
|
104
|
-
connections: connectionsWithin(document, items),
|
|
86
|
+
items: scene.items.filter((item) => visible(item, rect)),
|
|
105
87
|
rect,
|
|
106
88
|
padding: 0
|
|
107
89
|
};
|
|
108
90
|
}
|
|
109
91
|
}
|
|
110
92
|
}
|
|
111
|
-
function connectionBoundsList(connections, getFrame) {
|
|
112
|
-
const rects = [];
|
|
113
|
-
for (const connection of connections) {
|
|
114
|
-
const bounds = exportConnectionBounds(connection, getFrame);
|
|
115
|
-
if (bounds) rects.push(bounds);
|
|
116
|
-
}
|
|
117
|
-
return rects;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Largest scale that keeps the output inside both the edge and pixel budgets.
|
|
121
|
-
*
|
|
122
|
-
* There is deliberately no lower bound: a floor here would silently let a very
|
|
123
|
-
* large world exceed the budgets it exists to enforce (a 1e6×1e6 region at a
|
|
124
|
-
* 0.01 floor is 1e8 pixels). Callers see the reduction via `plan.clamped`.
|
|
125
|
-
*/
|
|
126
93
|
function clampScale(requested, world, maxEdge, maxPixels) {
|
|
127
94
|
const byEdge = Math.min(maxEdge / world.width, maxEdge / world.height);
|
|
128
95
|
const byArea = Math.sqrt(maxPixels / (world.width * world.height));
|
|
129
96
|
return Math.min(requested, byEdge, byArea);
|
|
130
97
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Resolve a region into a concrete capture plan, or null when there is nothing
|
|
133
|
-
* to draw. Callers treat null as "empty selection", not as an error.
|
|
134
|
-
*/
|
|
135
98
|
function planBoardExport(input) {
|
|
136
99
|
const { region, scale: requestedScale = 2, maxEdge = BOARD_EXPORT_MAX_EDGE, maxPixels = BOARD_EXPORT_MAX_PIXELS } = input;
|
|
137
|
-
const
|
|
138
|
-
const resolved = resolveRegion(document, region, boardFrameLookup(document));
|
|
100
|
+
const resolved = resolveRegion(input.scene, region);
|
|
139
101
|
if (!resolved.rect) return null;
|
|
140
102
|
const padding = input.padding ?? resolved.padding ?? 32;
|
|
141
103
|
const world = {
|
|
@@ -153,9 +115,8 @@ function planBoardExport(input) {
|
|
|
153
115
|
width: Math.max(1, Math.floor(world.width * scale)),
|
|
154
116
|
height: Math.max(1, Math.floor(world.height * scale)),
|
|
155
117
|
items: resolved.items,
|
|
156
|
-
connections: resolved.connections,
|
|
157
118
|
clamped: scale < safeRequest - 1e-6
|
|
158
119
|
};
|
|
159
120
|
}
|
|
160
121
|
//#endregion
|
|
161
|
-
export { BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS,
|
|
122
|
+
export { BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, exportItemBounds, normalizeBoardDocument, planBoardExport };
|
|
@@ -1,22 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BoardColor, BoardColorToken } from "../../protocol/dist/board-model.js";
|
|
2
2
|
import "../../protocol/dist/index.js";
|
|
3
3
|
//#region src/board/core/palette.d.ts
|
|
4
|
-
|
|
5
|
-
* Board color palette — a small, named set of shape colors shared by text,
|
|
6
|
-
* geo, draw and arrow shapes. Colors are stored by id in shape props (never
|
|
7
|
-
* raw hex), so themes and space `.cohub/theme.css` can remap them via CSS
|
|
8
|
-
* tokens while persisted data stays compact and forward-compatible.
|
|
9
|
-
*
|
|
10
|
-
* Concrete values are resolved from CSS variables at render time:
|
|
11
|
-
* --board-color-{id}-stroke | -fill | -label
|
|
12
|
-
* with hard-coded light/dark tables as offline / export fallbacks.
|
|
13
|
-
*/
|
|
4
|
+
type BoardColorId = BoardColorToken;
|
|
14
5
|
type BoardColorValue = {
|
|
15
|
-
/** Stroke / accent color (sRGB hex). */
|
|
16
6
|
stroke: number;
|
|
17
|
-
/** Translucent fill used behind shapes (sRGB hex). */
|
|
18
7
|
fill: number;
|
|
19
|
-
/** Readable label color on top of the fill. */
|
|
20
8
|
label: number;
|
|
21
9
|
};
|
|
22
10
|
type BoardColorEntry = {
|
|
@@ -29,15 +17,10 @@ declare const BOARD_COLORS: readonly BoardColorEntry[];
|
|
|
29
17
|
declare const DEFAULT_BOARD_COLOR: BoardColorId;
|
|
30
18
|
declare function isBoardColorId(value: unknown): value is BoardColorId;
|
|
31
19
|
declare function boardColorCssVar(id: BoardColorId, part: keyof BoardColorValue): string;
|
|
32
|
-
/** Resolve a color id to concrete values for a color mode. Unknown → brand. */
|
|
33
20
|
declare function resolveBoardColor(id: unknown, mode: "dark" | "light"): BoardColorValue;
|
|
34
21
|
type BoardShapeColors = Record<BoardColorId, BoardColorValue>;
|
|
35
|
-
/** Build a full shape-color table from hard-coded fallbacks (export / SSR). */
|
|
36
22
|
declare function buildFallbackShapeColors(mode: "dark" | "light"): BoardShapeColors;
|
|
37
|
-
/**
|
|
38
|
-
* Pick a concrete color from a live shape-color table, falling back to the
|
|
39
|
-
* default brand entry when the id is unknown.
|
|
40
|
-
*/
|
|
41
23
|
declare function pickBoardColor(colors: BoardShapeColors | null | undefined, id: unknown, mode?: "dark" | "light"): BoardColorValue;
|
|
24
|
+
declare function resolveItemColor(color: BoardColor | undefined, fallback: BoardColorId, colors: BoardShapeColors | null | undefined, mode: "dark" | "light", parseCss: (value: string) => number | null, part?: keyof BoardColorValue): number;
|
|
42
25
|
//#endregion
|
|
43
|
-
export { BOARD_COLORS, BoardColorEntry,
|
|
26
|
+
export { BOARD_COLORS, BoardColorEntry, BoardColorId, BoardColorValue, BoardShapeColors, DEFAULT_BOARD_COLOR, boardColorCssVar, buildFallbackShapeColors, isBoardColorId, pickBoardColor, resolveBoardColor, resolveItemColor };
|