@neta-art/cohub 12.5.0 → 13.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/README.md +35 -13
- package/dist/board/editor/editor.d.ts +7 -5
- package/dist/board/editor/index.js +1 -1
- package/dist/board/editor/interaction.js +1 -1
- package/dist/board/export/index.d.ts +1 -6
- package/dist/board/export/index.js +16 -10
- package/dist/board/export/node/index.d.ts +2 -7
- package/dist/board/export/node/index.js +2 -5
- package/dist/board/export/scene.d.ts +3 -7
- package/dist/board/export/scene.js +22 -26
- package/dist/board/model/asset-key.d.ts +5 -2
- package/dist/board/model/asset-key.js +13 -5
- package/dist/board/model/index.d.ts +5 -4
- package/dist/board/model/index.js +4 -3
- package/dist/board/model/media-playback.d.ts +4 -6
- package/dist/board/model/media-playback.js +4 -4
- package/dist/board/model/read.d.ts +7 -0
- package/dist/board/model/read.js +18 -0
- package/dist/board/model/themes.d.ts +50 -0
- package/dist/board/model/themes.js +44 -6
- package/dist/board/render/backdrop-layer.d.ts +21 -0
- package/dist/board/render/backdrop-layer.js +227 -0
- package/dist/board/render/backdrop.d.ts +45 -0
- package/dist/board/render/backdrop.js +62 -0
- package/dist/board/render/index.d.ts +3 -2
- package/dist/board/render/index.js +7 -6
- package/dist/board/render/renderers/arrow-card-renderer.js +1 -1
- package/dist/board/render/renderers/audio-card-renderer.js +2 -2
- package/dist/board/render/renderers/file-card-renderer.js +1 -1
- package/dist/board/render/renderers/frame-card-renderer.js +1 -1
- package/dist/board/render/renderers/model-card-renderer.js +1 -1
- package/dist/board/render/renderers/shape-card-renderer.js +1 -1
- package/dist/board/render/renderers/task-card-renderer.js +2 -2
- package/dist/board/render/renderers/text-card-renderer.js +2 -2
- package/dist/board/render/renderers/video-card-renderer.js +1 -1
- package/dist/board/render/theme.d.ts +2 -0
- package/dist/board/render/theme.js +4 -2
- package/dist/board/replica/index.d.ts +3 -2
- package/dist/board/replica/index.js +34 -24
- package/dist/board/replica/indexeddb.js +14 -85
- package/dist/board/stage/assets.d.ts +4 -3
- package/dist/board/stage/assets.js +186 -83
- package/dist/board/stage/backdrop.d.ts +25 -0
- package/dist/board/stage/backdrop.js +104 -0
- package/dist/board/stage/index.d.ts +2 -1
- package/dist/board/stage/scene.js +12 -5
- package/dist/board/stage/stage.d.ts +7 -2
- package/dist/board/stage/stage.js +44 -24
- package/dist/board/stage/texture-pool.d.ts +1 -1
- package/dist/board/stage/texture-pool.js +4 -5
- package/dist/chunks/app-realtime.js +1 -1
- package/dist/chunks/environment.d.ts +34 -21
- package/dist/chunks/environment.js +4 -3
- package/dist/chunks/http-error.js +28 -5
- package/dist/chunks/http.d.ts +87 -18
- package/dist/chunks/http.js +1855 -59
- package/dist/chunks/websocket.d.ts +9 -1
- package/dist/http.d.ts +2 -2
- package/dist/http.js +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.js +6 -1080
- package/dist/indexeddb.js +79 -0
- package/dist/media.d.ts +18 -32
- package/dist/media.js +81 -67
- package/dist/protocol/dist/board-model.d.ts +33 -26
- package/dist/protocol/dist/board-model.js +21 -18
- package/dist/protocol/dist/board.d.ts +21 -1
- package/dist/protocol/dist/board.js +5 -1
- package/dist/protocol/dist/core/media.d.ts +32 -9
- package/dist/protocol/dist/core/media.js +203 -48
- package/dist/protocol/dist/index.d.ts +3 -3
- package/dist/voice-input.js +1 -1
- package/dist/websocket.js +37 -5
- package/package.json +1 -1
- package/dist/board/render/board-background.d.ts +0 -18
- package/dist/board/render/board-background.js +0 -104
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { c as AppRtcError, i as WorkRoom, n as AppRoom, o as AppRoomRtc, r as WorkRealtimeApi, s as AppRtcChannel, t as AppRealtimeApi } from "./chunks/app-realtime.js";
|
|
2
|
-
import { $ as
|
|
2
|
+
import { $ as defaultDesktopCommandTimeoutMs, B as ModelsApi, C as createSessionGenerationStreamClient, D as SpaceDisplaysApi, E as createSessionPatchReducer, F as ReferencesApi, G as DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS, H as CronJobsApi, I as SearchApi, J as DESKTOP_COMMAND_PAYLOAD_MAX_BYTES, K as DESKTOP_COMMAND_MAX_TIMEOUT_MS, L as PublicAssetsApi, M as BoardClient, N as ensureRealtimeConnected, O as DisplayConnection, P as SessionAccessApi, Q as DESKTOP_COMMAND_VERSION, R as SkillsApi, S as SessionGenerationStreamClient, T as SessionPatchReducer, U as ChannelsApi, V as GenerationsApi, W as DESKTOP_COMMAND_ACCEPT_TIMEOUT_MS, X as DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS, Y as DESKTOP_COMMAND_PENDING_TTL_SECONDS, Z as DESKTOP_COMMAND_TERMINAL_TTL_SECONDS, _ as createSpaceFileServices, _t as BoardAnimationSchema, a as WorkCommerceApi, at as NAVIGATION_ERROR_MESSAGE_MAX_LENGTH, b as buildSpaceInvitePath, bt as parseBoardItem, c as AppsApi, ct as DISPLAY_INPUT_MAX_TEXT, d as UserApi, dt as splitDisplayText, et as isDesktopCallMethod, f as TasksApi, ft as parseBoardDocument, g as SpacesApi, gt as BOARD_ITEM_TYPES, h as SpaceWebhooksApi, ht as BOARD_COLOR_TOKENS, i as AppCommerceApi, it as resolveOpenSurface, k as connectDisplay, l as ReferralsApi, lt as DISPLAY_SYSTEM_ACTIONS, m as SpacePublicFilesApi, mt as BOARD_MIME_TYPE, n as createHttpClient, nt as parseDesktopCommand, o as DesktopCommandsApi, ot as DISPLAY_ELEMENT_REF_PATTERN, p as SpaceClient, pt as BOARD_EXTENSION, q as DESKTOP_COMMAND_OPEN_TIMEOUT_MS, r as RoomsApi, rt as parseDesktopCommandId, s as UiCommandsApi, t as CohubHttpClient, tt as isTerminalDesktopCommandStatus, u as UsersApi, ut as normalizeDisplayPoint, v as clearFileUrlCache, vt as BoardPatchSchema, w as parseAssistantMessageCommit, x as buildSpacePath, xt as normalizeBoardRemoteUrl, y as PublicInviteApi, yt as BoardTrackSchema, z as PromptsApi } from "./chunks/http.js";
|
|
3
3
|
import { A as isRequestSourceClientId, B as isUuidLike, D as COHUB_SOURCE_HEADER_NAMES, E as COHUB_SOURCE_HEADER, F as parseRequestSourceFromHeaders, I as readRequestSourceFromEnv, L as requestSourceToHeaders, M as isRequestSourceUuid, N as mergeRequestSourceIntoMeta, O as REQUEST_SOURCE_VIA_MAX_LENGTH, P as normalizeRequestSource, R as resolveRequestSourceChannel, V as isUuidOrShortUuid, a as isBillingAccessBlockedError, c as HttpError, d as matchesUnauthorizedErrorToken, f as sanitizeAccessToken, i as isBillingAccessBlockedCode, j as isRequestSourceEmpty, k as hasRequestSourceIdentity, l as HttpTransport, n as FEATURE_NOT_ENTITLED_ERROR_CODE, o as isFeatureNotEntitledError, r as extractBillingPayload, s as isHttpErrorCode, t as BILLING_ACCESS_BLOCKED_ERROR_CODE, u as joinApiUrl, z as isUuid } from "./chunks/http-error.js";
|
|
4
|
-
import { a as
|
|
4
|
+
import { _ as scopeListHasPermission, a as normalizeVoiceInputWebsocketUrl, c as resolveCohubEnvironment, d as resolveVoiceInputWebsocketUrl, f as resolveWebBaseUrl, g as isUserLevelPermission, h as USER_LEVEL_PERMISSIONS, i as normalizeBaseUrl, l as resolveExecutionAppId, m as PERMISSIONS, o as normalizeWebsocketUrl, p as resolveWebsocketUrl, r as getCohubContext, s as resolveApiBaseUrl, t as COHUB_ENVIRONMENTS, u as resolveExecutionToken } from "./chunks/environment.js";
|
|
5
5
|
import { WebsocketClient, createWebsocketClient } from "./websocket.js";
|
|
6
6
|
import { VoiceApi, VoiceInputClient, createVoiceInputClient } from "./voice-input.js";
|
|
7
7
|
import { filterSpacePickerItems, normalizeSpacePickerQuery, orderSpacePickerItems, selectSpacePickerItems } from "./space-picker.js";
|
|
@@ -182,21 +182,6 @@ function batchUploadEntries(entries, sizeOf, options = {}) {
|
|
|
182
182
|
return batches;
|
|
183
183
|
}
|
|
184
184
|
//#endregion
|
|
185
|
-
//#region ../protocol/dist/board-json.js
|
|
186
|
-
/** Structural equality for JSON-shaped semantic values. */
|
|
187
|
-
function boardJsonEquals(a, b) {
|
|
188
|
-
if (a === b) return true;
|
|
189
|
-
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return Number.isNaN(a) && Number.isNaN(b);
|
|
190
|
-
const aArray = Array.isArray(a);
|
|
191
|
-
const bArray = Array.isArray(b);
|
|
192
|
-
if (aArray !== bArray) return false;
|
|
193
|
-
if (aArray && bArray) return a.length === b.length && a.every((value, index) => boardJsonEquals(value, b[index]));
|
|
194
|
-
const aRecord = a;
|
|
195
|
-
const bRecord = b;
|
|
196
|
-
const keys = Object.keys(aRecord);
|
|
197
|
-
return keys.length === Object.keys(bRecord).length && keys.every((key) => Object.hasOwn(bRecord, key) && boardJsonEquals(aRecord[key], bRecord[key]));
|
|
198
|
-
}
|
|
199
|
-
//#endregion
|
|
200
185
|
//#region ../protocol/dist/generation/blocks.js
|
|
201
186
|
const EXCERPT_LIMIT = 240;
|
|
202
187
|
function asRecord(value) {
|
|
@@ -319,1067 +304,6 @@ function generationCovers(blocks) {
|
|
|
319
304
|
return covers;
|
|
320
305
|
}
|
|
321
306
|
//#endregion
|
|
322
|
-
//#region ../protocol/dist/board-layout.js
|
|
323
|
-
const IDENTITY_MATRIX = [
|
|
324
|
-
1,
|
|
325
|
-
0,
|
|
326
|
-
0,
|
|
327
|
-
1,
|
|
328
|
-
0,
|
|
329
|
-
0
|
|
330
|
-
];
|
|
331
|
-
function multiplyMatrix(parent, child) {
|
|
332
|
-
const [a1, b1, c1, d1, tx1, ty1] = parent;
|
|
333
|
-
const [a2, b2, c2, d2, tx2, ty2] = child;
|
|
334
|
-
return [
|
|
335
|
-
a1 * a2 + c1 * b2,
|
|
336
|
-
b1 * a2 + d1 * b2,
|
|
337
|
-
a1 * c2 + c1 * d2,
|
|
338
|
-
b1 * c2 + d1 * d2,
|
|
339
|
-
a1 * tx2 + c1 * ty2 + tx1,
|
|
340
|
-
b1 * tx2 + d1 * ty2 + ty1
|
|
341
|
-
];
|
|
342
|
-
}
|
|
343
|
-
function invertMatrix(matrix) {
|
|
344
|
-
const [a, b, c, d, tx, ty] = matrix;
|
|
345
|
-
const det = a * d - b * c || 1e-12;
|
|
346
|
-
return [
|
|
347
|
-
d / det,
|
|
348
|
-
-b / det,
|
|
349
|
-
-c / det,
|
|
350
|
-
a / det,
|
|
351
|
-
(c * ty - d * tx) / det,
|
|
352
|
-
(b * tx - a * ty) / det
|
|
353
|
-
];
|
|
354
|
-
}
|
|
355
|
-
function applyMatrix(matrix, point) {
|
|
356
|
-
const [a, b, c, d, tx, ty] = matrix;
|
|
357
|
-
return {
|
|
358
|
-
x: a * point.x + c * point.y + tx,
|
|
359
|
-
y: b * point.x + d * point.y + ty
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
function scaleVector(scale) {
|
|
363
|
-
return typeof scale === "number" ? {
|
|
364
|
-
x: scale,
|
|
365
|
-
y: scale
|
|
366
|
-
} : scale;
|
|
367
|
-
}
|
|
368
|
-
function isWideCharacter(code) {
|
|
369
|
-
return code >= 4352 && code <= 4447 || code >= 11904 && code <= 42191 || code >= 44032 && code <= 55203 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65103 || code >= 65280 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 127744 && code <= 129791 || code >= 131072 && code <= 262141;
|
|
370
|
-
}
|
|
371
|
-
function estimateTextWidth(text, fontSize) {
|
|
372
|
-
let ems = 0;
|
|
373
|
-
for (const character of text) {
|
|
374
|
-
const code = character.codePointAt(0) ?? 0;
|
|
375
|
-
if (character === " ") ems += .28;
|
|
376
|
-
else if (isWideCharacter(code)) ems += 1;
|
|
377
|
-
else if (/[il.,:;'|!]/.test(character)) ems += .3;
|
|
378
|
-
else if (/[mwMW@]/.test(character)) ems += .85;
|
|
379
|
-
else if (/[A-Z0-9]/.test(character)) ems += .64;
|
|
380
|
-
else ems += .55;
|
|
381
|
-
}
|
|
382
|
-
return ems * fontSize;
|
|
383
|
-
}
|
|
384
|
-
function estimateLines(text, { fontSize }, maxWidth) {
|
|
385
|
-
const measure = (line) => estimateTextWidth(line, fontSize);
|
|
386
|
-
const paragraphs = text.split("\n");
|
|
387
|
-
const lines = maxWidth ? paragraphs.flatMap((paragraph) => wrapParagraph(paragraph, maxWidth, measure)) : paragraphs;
|
|
388
|
-
return {
|
|
389
|
-
lines,
|
|
390
|
-
width: lines.reduce((max, line) => Math.max(max, measure(line)), 0)
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
function wrapParagraph(paragraph, width, measure) {
|
|
394
|
-
if (!paragraph) return [""];
|
|
395
|
-
const tokens = paragraph.match(/[\u1100-\u115f\u2e80-\ua4cf\uac00-\ud7a3\uf900-\ufaff\uff00-\uff60]|[^\s\u1100-\u115f\u2e80-\ua4cf\uac00-\ud7a3\uf900-\ufaff\uff00-\uff60]+|\s+/g) ?? [paragraph];
|
|
396
|
-
const lines = [];
|
|
397
|
-
let line = "";
|
|
398
|
-
for (const token of tokens) {
|
|
399
|
-
const candidate = line + token;
|
|
400
|
-
if (!line || measure(candidate.trimEnd()) <= width) {
|
|
401
|
-
line = candidate;
|
|
402
|
-
continue;
|
|
403
|
-
}
|
|
404
|
-
lines.push(line.trimEnd());
|
|
405
|
-
line = /^\s+$/.test(token) ? "" : token;
|
|
406
|
-
}
|
|
407
|
-
lines.push(line.trimEnd());
|
|
408
|
-
return lines;
|
|
409
|
-
}
|
|
410
|
-
const textSizeCache = /* @__PURE__ */ new Map();
|
|
411
|
-
const TEXT_CACHE_LIMIT = 4096;
|
|
412
|
-
function clampBoardFontSize(fontSize) {
|
|
413
|
-
return Math.min(512, Math.max(2, fontSize));
|
|
414
|
-
}
|
|
415
|
-
function layoutBoardText(props) {
|
|
416
|
-
const fontSize = clampBoardFontSize(props.fontSize ?? 24);
|
|
417
|
-
const key = `${fontSize}|${props.fontWeight}|${props.font}|${props.lineHeight}|${props.width ?? ""}|${props.text}`;
|
|
418
|
-
const cached = textSizeCache.get(key);
|
|
419
|
-
if (cached) return cached;
|
|
420
|
-
const font = {
|
|
421
|
-
fontSize,
|
|
422
|
-
fontWeight: props.fontWeight ?? 500,
|
|
423
|
-
font: props.font ?? "sans"
|
|
424
|
-
};
|
|
425
|
-
const { lines, width } = estimateLines(props.text || "", font, props.width || void 0);
|
|
426
|
-
const lineHeight = fontSize * (props.lineHeight ?? 4 / 3);
|
|
427
|
-
const layout = {
|
|
428
|
-
width: Math.max(props.width ?? 0, width, fontSize * .5),
|
|
429
|
-
height: Math.max(1, lines.length) * lineHeight,
|
|
430
|
-
lines,
|
|
431
|
-
lineHeight
|
|
432
|
-
};
|
|
433
|
-
if (textSizeCache.size >= TEXT_CACHE_LIMIT) textSizeCache.clear();
|
|
434
|
-
textSizeCache.set(key, layout);
|
|
435
|
-
return layout;
|
|
436
|
-
}
|
|
437
|
-
function drawSampleRadius(strokeWidth, pressure) {
|
|
438
|
-
const clamped = Math.min(1, Math.max(0, pressure));
|
|
439
|
-
return Math.max(.5, strokeWidth / 2 * (.5 + clamped));
|
|
440
|
-
}
|
|
441
|
-
function drawPointsBounds(points, strokeWidth) {
|
|
442
|
-
if (points.length === 0) return {
|
|
443
|
-
x: 0,
|
|
444
|
-
y: 0,
|
|
445
|
-
width: 1,
|
|
446
|
-
height: 1
|
|
447
|
-
};
|
|
448
|
-
let minX = Number.POSITIVE_INFINITY;
|
|
449
|
-
let minY = Number.POSITIVE_INFINITY;
|
|
450
|
-
let maxX = Number.NEGATIVE_INFINITY;
|
|
451
|
-
let maxY = Number.NEGATIVE_INFINITY;
|
|
452
|
-
for (const point of points) {
|
|
453
|
-
const radius = drawSampleRadius(strokeWidth, point.p);
|
|
454
|
-
minX = Math.min(minX, point.x - radius);
|
|
455
|
-
minY = Math.min(minY, point.y - radius);
|
|
456
|
-
maxX = Math.max(maxX, point.x + radius);
|
|
457
|
-
maxY = Math.max(maxY, point.y + radius);
|
|
458
|
-
}
|
|
459
|
-
return {
|
|
460
|
-
x: minX,
|
|
461
|
-
y: minY,
|
|
462
|
-
width: Math.max(1, maxX - minX),
|
|
463
|
-
height: Math.max(1, maxY - minY)
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
function pointsRect(points) {
|
|
467
|
-
let minX = Number.POSITIVE_INFINITY;
|
|
468
|
-
let minY = Number.POSITIVE_INFINITY;
|
|
469
|
-
let maxX = Number.NEGATIVE_INFINITY;
|
|
470
|
-
let maxY = Number.NEGATIVE_INFINITY;
|
|
471
|
-
for (const point of points) {
|
|
472
|
-
minX = Math.min(minX, point.x);
|
|
473
|
-
minY = Math.min(minY, point.y);
|
|
474
|
-
maxX = Math.max(maxX, point.x);
|
|
475
|
-
maxY = Math.max(maxY, point.y);
|
|
476
|
-
}
|
|
477
|
-
if (!Number.isFinite(minX)) return {
|
|
478
|
-
x: 0,
|
|
479
|
-
y: 0,
|
|
480
|
-
width: 1,
|
|
481
|
-
height: 1
|
|
482
|
-
};
|
|
483
|
-
return {
|
|
484
|
-
x: minX,
|
|
485
|
-
y: minY,
|
|
486
|
-
width: Math.max(1, maxX - minX),
|
|
487
|
-
height: Math.max(1, maxY - minY)
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
function isArrowBinding(end) {
|
|
491
|
-
return typeof end.item === "string";
|
|
492
|
-
}
|
|
493
|
-
function arrowBindings(item) {
|
|
494
|
-
if (item.type !== "arrow") return [];
|
|
495
|
-
const props = item.props;
|
|
496
|
-
const ids = [props.start, props.end].filter(isArrowBinding).map((end) => end.item);
|
|
497
|
-
return [...new Set(ids)];
|
|
498
|
-
}
|
|
499
|
-
function bendControl(start, end, bend) {
|
|
500
|
-
const mid = {
|
|
501
|
-
x: (start.x + end.x) / 2,
|
|
502
|
-
y: (start.y + end.y) / 2
|
|
503
|
-
};
|
|
504
|
-
if (!bend) return mid;
|
|
505
|
-
const dx = end.x - start.x;
|
|
506
|
-
const dy = end.y - start.y;
|
|
507
|
-
const length = Math.hypot(dx, dy) || 1;
|
|
508
|
-
const offset = bend * length;
|
|
509
|
-
return {
|
|
510
|
-
x: mid.x + -dy / length * offset,
|
|
511
|
-
y: mid.y + dx / length * offset
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
const MAX_DEPTH = 64;
|
|
515
|
-
function createBoardLayout(initialLookup, dependents) {
|
|
516
|
-
let lookup = initialLookup;
|
|
517
|
-
const boxes = /* @__PURE__ */ new Map();
|
|
518
|
-
const matrices = /* @__PURE__ */ new Map();
|
|
519
|
-
const bounds = /* @__PURE__ */ new Map();
|
|
520
|
-
function matrixOf(id, depth = 0) {
|
|
521
|
-
const cached = matrices.get(id);
|
|
522
|
-
if (cached) return cached;
|
|
523
|
-
const item = lookup(id);
|
|
524
|
-
if (!item) return IDENTITY_MATRIX;
|
|
525
|
-
const matrix = multiplyMatrix(item.parent && depth < MAX_DEPTH && lookup(item.parent) ? matrixOf(item.parent, depth + 1) : IDENTITY_MATRIX, localMatrixOf(id));
|
|
526
|
-
matrices.set(id, matrix);
|
|
527
|
-
return matrix;
|
|
528
|
-
}
|
|
529
|
-
function localMatrixOf(id) {
|
|
530
|
-
const item = lookup(id);
|
|
531
|
-
if (!item) return IDENTITY_MATRIX;
|
|
532
|
-
if (item.type === "arrow") return translate(item.position);
|
|
533
|
-
const box = boxOf(id);
|
|
534
|
-
const scale = scaleVector(item.scale);
|
|
535
|
-
const radians = item.rotation * Math.PI / 180;
|
|
536
|
-
const cos = Math.cos(radians);
|
|
537
|
-
const sin = Math.sin(radians);
|
|
538
|
-
const ox = box.x + item.origin.x * box.width;
|
|
539
|
-
const oy = box.y + item.origin.y * box.height;
|
|
540
|
-
const a = cos * scale.x;
|
|
541
|
-
const b = sin * scale.x;
|
|
542
|
-
const c = -sin * scale.y;
|
|
543
|
-
const d = cos * scale.y;
|
|
544
|
-
return [
|
|
545
|
-
a,
|
|
546
|
-
b,
|
|
547
|
-
c,
|
|
548
|
-
d,
|
|
549
|
-
item.position.x + ox - (a * ox + c * oy),
|
|
550
|
-
item.position.y + oy - (b * ox + d * oy)
|
|
551
|
-
];
|
|
552
|
-
}
|
|
553
|
-
function boxOf(id, depth = 0) {
|
|
554
|
-
const cached = boxes.get(id);
|
|
555
|
-
if (cached) return cached;
|
|
556
|
-
const item = lookup(id);
|
|
557
|
-
let box;
|
|
558
|
-
if (!item) box = {
|
|
559
|
-
x: 0,
|
|
560
|
-
y: 0,
|
|
561
|
-
width: 1,
|
|
562
|
-
height: 1
|
|
563
|
-
};
|
|
564
|
-
else if ("size" in item && item.size) box = {
|
|
565
|
-
x: 0,
|
|
566
|
-
y: 0,
|
|
567
|
-
width: item.size.width,
|
|
568
|
-
height: item.size.height
|
|
569
|
-
};
|
|
570
|
-
else if (item.type === "text") {
|
|
571
|
-
const layout = layoutBoardText(item.props);
|
|
572
|
-
box = {
|
|
573
|
-
x: 0,
|
|
574
|
-
y: 0,
|
|
575
|
-
width: layout.width,
|
|
576
|
-
height: layout.height
|
|
577
|
-
};
|
|
578
|
-
} else if (item.type === "draw") box = drawPointsBounds(item.props.points, item.style.strokeWidth ?? 4);
|
|
579
|
-
else if (item.type === "arrow") {
|
|
580
|
-
const props = item.props;
|
|
581
|
-
const toLocal = invertMatrix(multiplyMatrix(parentOf(item, depth), translate(item.position)));
|
|
582
|
-
const start = isArrowBinding(props.start) ? applyMatrix(toLocal, resolveBoundEnd(item, props.start, props.end, depth)) : props.start;
|
|
583
|
-
const end = isArrowBinding(props.end) ? applyMatrix(toLocal, resolveBoundEnd(item, props.end, props.start, depth)) : props.end;
|
|
584
|
-
const points = [
|
|
585
|
-
start,
|
|
586
|
-
end,
|
|
587
|
-
...props.waypoints
|
|
588
|
-
];
|
|
589
|
-
if (props.bend) points.push(bendControl(start, end, props.bend));
|
|
590
|
-
const rect = pointsRect(points);
|
|
591
|
-
const pad = Math.max(8, (item.style.strokeWidth ?? 2.5) * 2);
|
|
592
|
-
box = {
|
|
593
|
-
x: rect.x - pad,
|
|
594
|
-
y: rect.y - pad,
|
|
595
|
-
width: rect.width + pad * 2,
|
|
596
|
-
height: rect.height + pad * 2
|
|
597
|
-
};
|
|
598
|
-
} else box = {
|
|
599
|
-
x: 0,
|
|
600
|
-
y: 0,
|
|
601
|
-
...boardDefaultSize(item.type)
|
|
602
|
-
};
|
|
603
|
-
boxes.set(id, box);
|
|
604
|
-
return box;
|
|
605
|
-
}
|
|
606
|
-
function parentOf(item, depth) {
|
|
607
|
-
return item.parent && depth < MAX_DEPTH && lookup(item.parent) ? matrixOf(item.parent, depth + 1) : IDENTITY_MATRIX;
|
|
608
|
-
}
|
|
609
|
-
function resolveBoundEnd(arrow, end, other, depth) {
|
|
610
|
-
const target = lookup(end.item);
|
|
611
|
-
const arrowSpace = multiplyMatrix(parentOf(arrow, depth), translate(arrow.position));
|
|
612
|
-
if (!target || target.type === "arrow" || depth >= MAX_DEPTH) return applyMatrix(arrowSpace, {
|
|
613
|
-
x: 0,
|
|
614
|
-
y: 0
|
|
615
|
-
});
|
|
616
|
-
const frame = frameOf(end.item, depth + 1);
|
|
617
|
-
const toward = isArrowBinding(other) ? lookup(other.item) && lookup(other.item)?.type !== "arrow" ? center(frameOf(other.item, depth + 1)) : center(frame) : applyMatrix(arrowSpace, other);
|
|
618
|
-
return anchorPoint(frame, end.anchor, toward);
|
|
619
|
-
}
|
|
620
|
-
function frameOf(id, depth = 0) {
|
|
621
|
-
boxOf(id, depth);
|
|
622
|
-
const box = boxes.get(id);
|
|
623
|
-
const matrix = matrixOf(id, depth);
|
|
624
|
-
const [a, b, c, d] = matrix;
|
|
625
|
-
const centerPoint = applyMatrix(matrix, {
|
|
626
|
-
x: box.x + box.width / 2,
|
|
627
|
-
y: box.y + box.height / 2
|
|
628
|
-
});
|
|
629
|
-
const width = box.width * Math.hypot(a, b);
|
|
630
|
-
const height = box.height * Math.hypot(c, d);
|
|
631
|
-
return {
|
|
632
|
-
x: centerPoint.x - width / 2,
|
|
633
|
-
y: centerPoint.y - height / 2,
|
|
634
|
-
width,
|
|
635
|
-
height,
|
|
636
|
-
rotation: Math.atan2(b, a) * 180 / Math.PI
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
function boundsOf(id) {
|
|
640
|
-
const cached = bounds.get(id);
|
|
641
|
-
if (cached) return cached;
|
|
642
|
-
const box = boxOf(id);
|
|
643
|
-
const matrix = matrixOf(id);
|
|
644
|
-
const rect = pointsRect([
|
|
645
|
-
applyMatrix(matrix, {
|
|
646
|
-
x: box.x,
|
|
647
|
-
y: box.y
|
|
648
|
-
}),
|
|
649
|
-
applyMatrix(matrix, {
|
|
650
|
-
x: box.x + box.width,
|
|
651
|
-
y: box.y
|
|
652
|
-
}),
|
|
653
|
-
applyMatrix(matrix, {
|
|
654
|
-
x: box.x + box.width,
|
|
655
|
-
y: box.y + box.height
|
|
656
|
-
}),
|
|
657
|
-
applyMatrix(matrix, {
|
|
658
|
-
x: box.x,
|
|
659
|
-
y: box.y + box.height
|
|
660
|
-
})
|
|
661
|
-
]);
|
|
662
|
-
bounds.set(id, rect);
|
|
663
|
-
return rect;
|
|
664
|
-
}
|
|
665
|
-
function setLookup(nextLookup) {
|
|
666
|
-
lookup = nextLookup;
|
|
667
|
-
}
|
|
668
|
-
function invalidate(ids) {
|
|
669
|
-
if (!ids) {
|
|
670
|
-
boxes.clear();
|
|
671
|
-
matrices.clear();
|
|
672
|
-
bounds.clear();
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
|
-
const queue = [...ids];
|
|
676
|
-
const seen = /* @__PURE__ */ new Set();
|
|
677
|
-
while (queue.length) {
|
|
678
|
-
const id = queue.pop();
|
|
679
|
-
if (seen.has(id)) continue;
|
|
680
|
-
seen.add(id);
|
|
681
|
-
boxes.delete(id);
|
|
682
|
-
matrices.delete(id);
|
|
683
|
-
bounds.delete(id);
|
|
684
|
-
if (dependents) for (const next of dependents(id)) queue.push(next);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
return {
|
|
688
|
-
has: (id) => lookup(id) !== void 0,
|
|
689
|
-
box: (id) => boxOf(id),
|
|
690
|
-
matrix: (id) => matrixOf(id),
|
|
691
|
-
localMatrix: (id) => localMatrixOf(id),
|
|
692
|
-
parentMatrix: (id) => {
|
|
693
|
-
const item = lookup(id);
|
|
694
|
-
return item ? parentOf(item, 0) : IDENTITY_MATRIX;
|
|
695
|
-
},
|
|
696
|
-
bounds: boundsOf,
|
|
697
|
-
frame: (id) => frameOf(id),
|
|
698
|
-
arrowEnd: (id, which) => {
|
|
699
|
-
const item = lookup(id);
|
|
700
|
-
if (item?.type !== "arrow") return {
|
|
701
|
-
x: 0,
|
|
702
|
-
y: 0
|
|
703
|
-
};
|
|
704
|
-
const arrow = item;
|
|
705
|
-
const [end, other] = which === "start" ? [arrow.props.start, arrow.props.end] : [arrow.props.end, arrow.props.start];
|
|
706
|
-
return isArrowBinding(end) ? resolveBoundEnd(arrow, end, other, 0) : applyMatrix(matrixOf(id), end);
|
|
707
|
-
},
|
|
708
|
-
invalidate,
|
|
709
|
-
setLookup
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
function translate(point) {
|
|
713
|
-
return [
|
|
714
|
-
1,
|
|
715
|
-
0,
|
|
716
|
-
0,
|
|
717
|
-
1,
|
|
718
|
-
point.x,
|
|
719
|
-
point.y
|
|
720
|
-
];
|
|
721
|
-
}
|
|
722
|
-
function center(frame) {
|
|
723
|
-
return {
|
|
724
|
-
x: frame.x + frame.width / 2,
|
|
725
|
-
y: frame.y + frame.height / 2
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
function rotateAround(point, pivot, degrees) {
|
|
729
|
-
if (!degrees) return point;
|
|
730
|
-
const radians = degrees * Math.PI / 180;
|
|
731
|
-
const cos = Math.cos(radians);
|
|
732
|
-
const sin = Math.sin(radians);
|
|
733
|
-
const dx = point.x - pivot.x;
|
|
734
|
-
const dy = point.y - pivot.y;
|
|
735
|
-
return {
|
|
736
|
-
x: pivot.x + dx * cos - dy * sin,
|
|
737
|
-
y: pivot.y + dx * sin + dy * cos
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
function framePoint(frame, nx, ny) {
|
|
741
|
-
return rotateAround({
|
|
742
|
-
x: frame.x + nx * frame.width,
|
|
743
|
-
y: frame.y + ny * frame.height
|
|
744
|
-
}, center(frame), frame.rotation);
|
|
745
|
-
}
|
|
746
|
-
function autoAnchorSide(frame, toward) {
|
|
747
|
-
const local = rotateAround(toward, center(frame), -frame.rotation);
|
|
748
|
-
const c = center(frame);
|
|
749
|
-
const dx = (local.x - c.x) / Math.max(frame.width / 2, 1e-4);
|
|
750
|
-
const dy = (local.y - c.y) / Math.max(frame.height / 2, 1e-4);
|
|
751
|
-
if (Math.abs(dx) >= Math.abs(dy)) return dx >= 0 ? "right" : "left";
|
|
752
|
-
return dy >= 0 ? "bottom" : "top";
|
|
753
|
-
}
|
|
754
|
-
function sideAnchor(side, offset) {
|
|
755
|
-
switch (side) {
|
|
756
|
-
case "top": return {
|
|
757
|
-
x: offset,
|
|
758
|
-
y: 0
|
|
759
|
-
};
|
|
760
|
-
case "bottom": return {
|
|
761
|
-
x: offset,
|
|
762
|
-
y: 1
|
|
763
|
-
};
|
|
764
|
-
case "left": return {
|
|
765
|
-
x: 0,
|
|
766
|
-
y: offset
|
|
767
|
-
};
|
|
768
|
-
default: return {
|
|
769
|
-
x: 1,
|
|
770
|
-
y: offset
|
|
771
|
-
};
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
function anchorPoint(frame, anchor, toward) {
|
|
775
|
-
if (anchor === "auto") {
|
|
776
|
-
const normalized = sideAnchor(autoAnchorSide(frame, toward), .5);
|
|
777
|
-
return framePoint(frame, normalized.x, normalized.y);
|
|
778
|
-
}
|
|
779
|
-
if ("side" in anchor) {
|
|
780
|
-
const normalized = sideAnchor(anchor.side, anchor.offset);
|
|
781
|
-
return framePoint(frame, normalized.x, normalized.y);
|
|
782
|
-
}
|
|
783
|
-
return framePoint(frame, anchor.x, anchor.y);
|
|
784
|
-
}
|
|
785
|
-
//#endregion
|
|
786
|
-
//#region ../protocol/dist/board-patch.js
|
|
787
|
-
function slot(map, key) {
|
|
788
|
-
let value = map[key];
|
|
789
|
-
if (!value) {
|
|
790
|
-
value = {};
|
|
791
|
-
map[key] = value;
|
|
792
|
-
}
|
|
793
|
-
return value;
|
|
794
|
-
}
|
|
795
|
-
function emptyDelta() {
|
|
796
|
-
return {
|
|
797
|
-
items: {},
|
|
798
|
-
animations: {},
|
|
799
|
-
tracks: {}
|
|
800
|
-
};
|
|
801
|
-
}
|
|
802
|
-
function withoutEmpty(value) {
|
|
803
|
-
for (const [key, entry] of Object.entries(value)) if (entry === void 0 || isRecord$6(entry) && Object.keys(entry).length === 0) delete value[key];
|
|
804
|
-
return value;
|
|
805
|
-
}
|
|
806
|
-
function isRecord$6(value) {
|
|
807
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
808
|
-
}
|
|
809
|
-
function mergePatch(target, patch) {
|
|
810
|
-
if (!isRecord$6(patch)) return patch;
|
|
811
|
-
const result = isRecord$6(target) ? { ...target } : {};
|
|
812
|
-
for (const [key, value] of Object.entries(patch)) if (value === null) delete result[key];
|
|
813
|
-
else result[key] = mergePatch(result[key], value);
|
|
814
|
-
return result;
|
|
815
|
-
}
|
|
816
|
-
function def(schema) {
|
|
817
|
-
return schema._zod.def;
|
|
818
|
-
}
|
|
819
|
-
function unwrap(schema) {
|
|
820
|
-
let current = schema;
|
|
821
|
-
for (let guard = 0; guard < 16; guard += 1) {
|
|
822
|
-
const d = def(current);
|
|
823
|
-
if (d.type === "optional" || d.type === "default" || d.type === "nullable" || d.type === "readonly" || d.type === "prefault") current = d.innerType;
|
|
824
|
-
else if (d.type === "pipe") current = d.in;
|
|
825
|
-
else return current;
|
|
826
|
-
}
|
|
827
|
-
return current;
|
|
828
|
-
}
|
|
829
|
-
function unwrapObjectShape(schema) {
|
|
830
|
-
const d = def(unwrap(schema));
|
|
831
|
-
return d.type === "object" ? d.shape : null;
|
|
832
|
-
}
|
|
833
|
-
function schemaAtPath(schema, path) {
|
|
834
|
-
let current = schema;
|
|
835
|
-
for (const segment of path) {
|
|
836
|
-
const d = def(unwrap(current));
|
|
837
|
-
if (d.type === "object") {
|
|
838
|
-
const shape = d.shape;
|
|
839
|
-
if (!Object.hasOwn(shape, segment)) return null;
|
|
840
|
-
current = shape[segment];
|
|
841
|
-
} else if (d.type === "record") current = d.valueType;
|
|
842
|
-
else if (d.type === "union") {
|
|
843
|
-
const branch = d.options.find((option) => unwrapObjectShape(option)?.[segment]);
|
|
844
|
-
if (!branch) return null;
|
|
845
|
-
current = unwrapObjectShape(branch)[segment];
|
|
846
|
-
} else return null;
|
|
847
|
-
}
|
|
848
|
-
return current;
|
|
849
|
-
}
|
|
850
|
-
const NOT_ANIMATABLE = /* @__PURE__ */ new Set([
|
|
851
|
-
"type",
|
|
852
|
-
"parent",
|
|
853
|
-
"z",
|
|
854
|
-
"locked",
|
|
855
|
-
"metadata",
|
|
856
|
-
"script"
|
|
857
|
-
]);
|
|
858
|
-
const CAMERA_PROPERTIES = {
|
|
859
|
-
focus: {
|
|
860
|
-
kind: "discrete",
|
|
861
|
-
schema: z.union([z.string().min(1), z.object({
|
|
862
|
-
x: z.number().finite(),
|
|
863
|
-
y: z.number().finite(),
|
|
864
|
-
width: z.number().finite().positive(),
|
|
865
|
-
height: z.number().finite().positive()
|
|
866
|
-
}).strict()]).describe("Item id or world-space rect to fit with 48 px padding; holds until the next focus keyframe.")
|
|
867
|
-
},
|
|
868
|
-
zoom: {
|
|
869
|
-
kind: "number",
|
|
870
|
-
schema: z.number().finite().positive().describe("Pixels per world unit; overrides the zoom computed by focus."),
|
|
871
|
-
multiplicative: true
|
|
872
|
-
},
|
|
873
|
-
center: {
|
|
874
|
-
kind: "vec2",
|
|
875
|
-
schema: BoardVec2Schema.describe("World-space viewport center; overrides focus positioning using the resolved zoom.")
|
|
876
|
-
},
|
|
877
|
-
shake: {
|
|
878
|
-
kind: "number",
|
|
879
|
-
schema: z.number().finite().nonnegative().describe("Shake amplitude in screen pixels, applied after focus, zoom and center.")
|
|
880
|
-
}
|
|
881
|
-
};
|
|
882
|
-
const ANIMATION_PROPERTIES = { time: {
|
|
883
|
-
kind: "number",
|
|
884
|
-
schema: z.number().finite().nonnegative()
|
|
885
|
-
} };
|
|
886
|
-
function kindOf(schema, path) {
|
|
887
|
-
const leaf = path[path.length - 1];
|
|
888
|
-
if (path.length === 1 && leaf === "scale") return "scale";
|
|
889
|
-
if (schema === BoardColorSchema || unwrap(schema) === BoardColorSchema) return "color";
|
|
890
|
-
if (def(unwrap(schema)).type === "number") return "number";
|
|
891
|
-
const shape = unwrapObjectShape(schema);
|
|
892
|
-
if (shape && Object.keys(shape).length === 2 && "x" in shape && "y" in shape) return "vec2";
|
|
893
|
-
return "discrete";
|
|
894
|
-
}
|
|
895
|
-
function resolveBoardProperty(targetType, property) {
|
|
896
|
-
if (targetType === "camera") {
|
|
897
|
-
const spec = CAMERA_PROPERTIES[property];
|
|
898
|
-
return spec ? {
|
|
899
|
-
ok: true,
|
|
900
|
-
spec
|
|
901
|
-
} : {
|
|
902
|
-
ok: false,
|
|
903
|
-
message: `camera has no property ${property}; expected ${Object.keys(CAMERA_PROPERTIES).join(", ")}`
|
|
904
|
-
};
|
|
905
|
-
}
|
|
906
|
-
if (targetType === "animation") {
|
|
907
|
-
const spec = ANIMATION_PROPERTIES[property];
|
|
908
|
-
return spec ? {
|
|
909
|
-
ok: true,
|
|
910
|
-
spec
|
|
911
|
-
} : {
|
|
912
|
-
ok: false,
|
|
913
|
-
message: `animations are driven through time`
|
|
914
|
-
};
|
|
915
|
-
}
|
|
916
|
-
const path = property.split(".");
|
|
917
|
-
if (path.some((segment) => !segment) || NOT_ANIMATABLE.has(path[0])) return {
|
|
918
|
-
ok: false,
|
|
919
|
-
message: `${property} cannot be animated`
|
|
920
|
-
};
|
|
921
|
-
const schema = boardItemSchema(targetType);
|
|
922
|
-
if (!schema) return {
|
|
923
|
-
ok: false,
|
|
924
|
-
message: `unknown item type ${targetType}`
|
|
925
|
-
};
|
|
926
|
-
if (!isBuiltinItemType(targetType) && path[0] === "props") return {
|
|
927
|
-
ok: true,
|
|
928
|
-
spec: {
|
|
929
|
-
kind: "discrete",
|
|
930
|
-
schema: z.unknown()
|
|
931
|
-
}
|
|
932
|
-
};
|
|
933
|
-
const leaf = schemaAtPath(schema, path);
|
|
934
|
-
if (!leaf) return {
|
|
935
|
-
ok: false,
|
|
936
|
-
message: `${targetType} has no property ${property}`
|
|
937
|
-
};
|
|
938
|
-
const kind = kindOf(leaf, path);
|
|
939
|
-
return {
|
|
940
|
-
ok: true,
|
|
941
|
-
spec: {
|
|
942
|
-
kind,
|
|
943
|
-
schema: unwrap(leaf),
|
|
944
|
-
...property === "opacity" || kind === "scale" ? { multiplicative: true } : {}
|
|
945
|
-
}
|
|
946
|
-
};
|
|
947
|
-
}
|
|
948
|
-
function lastKeyframeAt(trackPatches) {
|
|
949
|
-
let end = 0;
|
|
950
|
-
for (const track of trackPatches) {
|
|
951
|
-
const keyframes = track?.keyframes;
|
|
952
|
-
if (!Array.isArray(keyframes)) continue;
|
|
953
|
-
for (const keyframe of keyframes) {
|
|
954
|
-
const at = keyframe?.at;
|
|
955
|
-
if (typeof at === "number" && Number.isFinite(at)) end = Math.max(end, at);
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
return end > 0 ? end : void 0;
|
|
959
|
-
}
|
|
960
|
-
function trackReferences(track) {
|
|
961
|
-
const refs = /* @__PURE__ */ new Set([track.target]);
|
|
962
|
-
if (track.target === "camera" && track.property === "focus") {
|
|
963
|
-
for (const keyframe of track.keyframes) if (typeof keyframe.value === "string") refs.add(keyframe.value);
|
|
964
|
-
}
|
|
965
|
-
refs.delete(BOARD_CAMERA_TARGET);
|
|
966
|
-
return [...refs];
|
|
967
|
-
}
|
|
968
|
-
function pruneBoardTrack(track, deleted) {
|
|
969
|
-
if (deleted.has(track.target)) return null;
|
|
970
|
-
if (track.target !== "camera" || track.property !== "focus") return track;
|
|
971
|
-
const keyframes = track.keyframes.filter((entry) => typeof entry.value !== "string" || !deleted.has(entry.value));
|
|
972
|
-
if (keyframes.length === track.keyframes.length) return track;
|
|
973
|
-
return keyframes.length ? {
|
|
974
|
-
...track,
|
|
975
|
-
keyframes
|
|
976
|
-
} : null;
|
|
977
|
-
}
|
|
978
|
-
function error(path, code, message) {
|
|
979
|
-
return {
|
|
980
|
-
severity: "error",
|
|
981
|
-
code,
|
|
982
|
-
path,
|
|
983
|
-
message
|
|
984
|
-
};
|
|
985
|
-
}
|
|
986
|
-
function stripId(value) {
|
|
987
|
-
if (!("id" in value)) return value;
|
|
988
|
-
const { id: _id, ...rest } = value;
|
|
989
|
-
return rest;
|
|
990
|
-
}
|
|
991
|
-
function applyBoardPatch(state, input, options = {}) {
|
|
992
|
-
const parsedPatch = BoardPatchSchema.safeParse(input);
|
|
993
|
-
if (!parsedPatch.success) return {
|
|
994
|
-
ok: false,
|
|
995
|
-
diagnostics: parsedPatch.error.issues.map((issue) => error(issue.path.map(String).join("."), "INVALID_PATCH", issue.message))
|
|
996
|
-
};
|
|
997
|
-
const patch = parsedPatch.data;
|
|
998
|
-
const diagnostics = [];
|
|
999
|
-
const nextItems = /* @__PURE__ */ new Map();
|
|
1000
|
-
const nextAnimations = /* @__PURE__ */ new Map();
|
|
1001
|
-
const nextTracks = /* @__PURE__ */ new Map();
|
|
1002
|
-
let nextSettings;
|
|
1003
|
-
const item = (id) => nextItems.has(id) ? nextItems.get(id) ?? void 0 : state.item(id);
|
|
1004
|
-
const animation = (id) => nextAnimations.has(id) ? nextAnimations.get(id) ?? void 0 : state.animation(id);
|
|
1005
|
-
const setTrack = (animationId, trackId, value) => {
|
|
1006
|
-
const tracks = nextTracks.get(animationId) ?? /* @__PURE__ */ new Map();
|
|
1007
|
-
tracks.set(trackId, value);
|
|
1008
|
-
nextTracks.set(animationId, tracks);
|
|
1009
|
-
};
|
|
1010
|
-
const track = (animationId, trackId) => {
|
|
1011
|
-
const pending = nextTracks.get(animationId);
|
|
1012
|
-
if (pending?.has(trackId)) return pending.get(trackId) ?? void 0;
|
|
1013
|
-
return state.track(animationId, trackId);
|
|
1014
|
-
};
|
|
1015
|
-
if (patch.board !== void 0) {
|
|
1016
|
-
const merged = patch.board === null ? {} : mergePatch(state.settings(), patch.board);
|
|
1017
|
-
const parsed = BoardSettingsSchema.safeParse(merged);
|
|
1018
|
-
if (parsed.success) nextSettings = parsed.data;
|
|
1019
|
-
else for (const issue of parsed.error.issues) diagnostics.push(error(["board", ...issue.path.map(String)].join("."), "INVALID_BOARD", issue.message));
|
|
1020
|
-
}
|
|
1021
|
-
const zByParent = /* @__PURE__ */ new Map();
|
|
1022
|
-
for (const [id, value] of Object.entries(patch.items ?? {})) {
|
|
1023
|
-
if (value === null) {
|
|
1024
|
-
if (state.item(id)) nextItems.set(id, null);
|
|
1025
|
-
continue;
|
|
1026
|
-
}
|
|
1027
|
-
const current = state.item(id);
|
|
1028
|
-
const body = stripId(value);
|
|
1029
|
-
const candidate = !current || typeof body.type === "string" && body.type !== current.type ? { ...body } : mergePatch(current, body);
|
|
1030
|
-
if (candidate.z === void 0) {
|
|
1031
|
-
const parent = typeof candidate.parent === "string" ? candidate.parent : void 0;
|
|
1032
|
-
const key = parent ?? "";
|
|
1033
|
-
const top = zByParent.get(key) ?? state.maxZ(parent);
|
|
1034
|
-
candidate.z = current?.z ?? top + 1;
|
|
1035
|
-
if (!current) zByParent.set(key, top + 1);
|
|
1036
|
-
}
|
|
1037
|
-
const parsed = parseBoardItem(candidate, `items.${id}`);
|
|
1038
|
-
if (!parsed.ok) {
|
|
1039
|
-
diagnostics.push(...parsed.diagnostics);
|
|
1040
|
-
continue;
|
|
1041
|
-
}
|
|
1042
|
-
if (current && boardJsonEquals(current, parsed.item)) continue;
|
|
1043
|
-
nextItems.set(id, parsed.item);
|
|
1044
|
-
}
|
|
1045
|
-
for (const [id, value] of Object.entries(patch.animations ?? {})) {
|
|
1046
|
-
if (value === null) {
|
|
1047
|
-
if (!state.animation(id)) continue;
|
|
1048
|
-
nextAnimations.set(id, null);
|
|
1049
|
-
for (const trackId of state.trackIds(id)) setTrack(id, trackId, null);
|
|
1050
|
-
continue;
|
|
1051
|
-
}
|
|
1052
|
-
const { tracks, ...headerPatch } = stripId(value);
|
|
1053
|
-
if (state.item(id) || nextItems.get(id)) {
|
|
1054
|
-
diagnostics.push(error(`animations.${id}`, "ID_CONFLICT", `${id} is already an item id`));
|
|
1055
|
-
continue;
|
|
1056
|
-
}
|
|
1057
|
-
const current = state.animation(id);
|
|
1058
|
-
if (!current || Object.keys(headerPatch).length > 0) {
|
|
1059
|
-
const header = current ? mergePatch(current, headerPatch) : {
|
|
1060
|
-
...headerPatch,
|
|
1061
|
-
...headerPatch.duration === void 0 ? { duration: lastKeyframeAt([...Object.values(tracks ?? {}), ...state.trackIds(id).map((trackId) => state.track(id, trackId))]) } : {}
|
|
1062
|
-
};
|
|
1063
|
-
const parsed = BoardAnimationHeaderSchema.safeParse(header);
|
|
1064
|
-
if (!parsed.success) {
|
|
1065
|
-
for (const issue of parsed.error.issues) diagnostics.push(error([
|
|
1066
|
-
"animations",
|
|
1067
|
-
id,
|
|
1068
|
-
...issue.path.map(String)
|
|
1069
|
-
].join("."), "INVALID_ANIMATION", issue.message));
|
|
1070
|
-
continue;
|
|
1071
|
-
}
|
|
1072
|
-
if (!current || !boardJsonEquals(current, parsed.data)) nextAnimations.set(id, parsed.data);
|
|
1073
|
-
}
|
|
1074
|
-
for (const [trackId, trackPatch] of Object.entries(tracks ?? {})) {
|
|
1075
|
-
const existing = state.track(id, trackId);
|
|
1076
|
-
if (trackPatch === null) {
|
|
1077
|
-
if (existing) setTrack(id, trackId, null);
|
|
1078
|
-
continue;
|
|
1079
|
-
}
|
|
1080
|
-
const parsed = BoardTrackSchema.safeParse(existing ? mergePatch(existing, trackPatch) : trackPatch);
|
|
1081
|
-
if (!parsed.success) {
|
|
1082
|
-
for (const issue of parsed.error.issues) diagnostics.push(error([
|
|
1083
|
-
"animations",
|
|
1084
|
-
id,
|
|
1085
|
-
"tracks",
|
|
1086
|
-
trackId,
|
|
1087
|
-
...issue.path.map(String)
|
|
1088
|
-
].join("."), "INVALID_TRACK", issue.message));
|
|
1089
|
-
continue;
|
|
1090
|
-
}
|
|
1091
|
-
if (!existing || !boardJsonEquals(existing, parsed.data)) setTrack(id, trackId, parsed.data);
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
for (const id of nextItems.keys()) if (nextItems.get(id) && animation(id)) diagnostics.push(error(`items.${id}`, "ID_CONFLICT", `${id} is already an animation id`));
|
|
1095
|
-
if (diagnostics.length) return {
|
|
1096
|
-
ok: false,
|
|
1097
|
-
diagnostics
|
|
1098
|
-
};
|
|
1099
|
-
const deletedItems = [...nextItems].filter(([, value]) => value === null).map(([id]) => id);
|
|
1100
|
-
const deletionLayout = createBoardLayout((id) => item(id) ?? state.item(id));
|
|
1101
|
-
const pendingDeletes = [...deletedItems];
|
|
1102
|
-
while (pendingDeletes.length) {
|
|
1103
|
-
const id = pendingDeletes.pop();
|
|
1104
|
-
for (const child of state.children(id)) {
|
|
1105
|
-
if (nextItems.has(child) && nextItems.get(child)?.parent !== id) continue;
|
|
1106
|
-
if (options.cascade) {
|
|
1107
|
-
if (nextItems.get(child) !== null) {
|
|
1108
|
-
nextItems.set(child, null);
|
|
1109
|
-
pendingDeletes.push(child);
|
|
1110
|
-
}
|
|
1111
|
-
} else diagnostics.push(error(`items.${id}`, "ITEM_REFERENCED", `${id} still has child ${child}; delete it too or use cascade`));
|
|
1112
|
-
}
|
|
1113
|
-
for (const arrowId of state.binders(id)) {
|
|
1114
|
-
const arrow = item(arrowId);
|
|
1115
|
-
if (arrow?.type !== "arrow") continue;
|
|
1116
|
-
const props = { ...arrow.props };
|
|
1117
|
-
for (const which of ["start", "end"]) {
|
|
1118
|
-
const end = props[which];
|
|
1119
|
-
if (!isArrowBinding(end) || end.item !== id) continue;
|
|
1120
|
-
const world = options.resolveArrowEnd?.(arrowId, which) ?? deletionLayout.arrowEnd(arrowId, which);
|
|
1121
|
-
props[which] = applyMatrix(invertMatrix(deletionLayout.matrix(arrowId)), world);
|
|
1122
|
-
}
|
|
1123
|
-
nextItems.set(arrowId, {
|
|
1124
|
-
...arrow,
|
|
1125
|
-
props
|
|
1126
|
-
});
|
|
1127
|
-
}
|
|
1128
|
-
for (const ref of state.trackRefs(id)) {
|
|
1129
|
-
const current = track(ref.animation, ref.track);
|
|
1130
|
-
if (!current || !trackReferences(current).includes(id)) continue;
|
|
1131
|
-
if (options.cascade) setTrack(ref.animation, ref.track, pruneBoardTrack(current, /* @__PURE__ */ new Set([id])));
|
|
1132
|
-
else diagnostics.push(error(`items.${id}`, "ITEM_REFERENCED", `${id} is animated by ${ref.animation}.${ref.track}; delete the track or use cascade`));
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
for (const [id, value] of nextAnimations) {
|
|
1136
|
-
if (value !== null) continue;
|
|
1137
|
-
for (const ref of state.trackRefs(id)) {
|
|
1138
|
-
if (ref.animation === id || track(ref.animation, ref.track) === void 0) continue;
|
|
1139
|
-
if (options.cascade) setTrack(ref.animation, ref.track, null);
|
|
1140
|
-
else diagnostics.push(error(`animations.${id}`, "ANIMATION_REFERENCED", `${id} is nested in ${ref.animation}.${ref.track}; delete the track or use cascade`));
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
const validationState = {
|
|
1144
|
-
...state,
|
|
1145
|
-
trackIds: (id) => [.../* @__PURE__ */ new Set([...state.trackIds(id), ...nextTracks.get(id)?.keys() ?? []])]
|
|
1146
|
-
};
|
|
1147
|
-
const validationItems = new Map(nextItems);
|
|
1148
|
-
const descendants = [];
|
|
1149
|
-
for (const [id, value] of nextItems) if (value && value.parent !== state.item(id)?.parent) descendants.push(...state.children(id));
|
|
1150
|
-
const seenDescendants = /* @__PURE__ */ new Set();
|
|
1151
|
-
while (descendants.length) {
|
|
1152
|
-
const id = descendants.pop();
|
|
1153
|
-
if (seenDescendants.has(id)) continue;
|
|
1154
|
-
seenDescendants.add(id);
|
|
1155
|
-
validationItems.set(id, item(id) ?? null);
|
|
1156
|
-
descendants.push(...state.children(id));
|
|
1157
|
-
}
|
|
1158
|
-
for (const [id, value] of validationItems) {
|
|
1159
|
-
if (!value) continue;
|
|
1160
|
-
if (value.parent !== void 0) {
|
|
1161
|
-
const parent = item(value.parent);
|
|
1162
|
-
if (!parent) diagnostics.push(error(`items.${id}.parent`, "PARENT_NOT_FOUND", `parent ${value.parent} does not exist`));
|
|
1163
|
-
else if (parent.type !== "frame") diagnostics.push(error(`items.${id}.parent`, "INVALID_PARENT", `parent ${value.parent} is a ${parent.type}; only frames contain items`));
|
|
1164
|
-
else {
|
|
1165
|
-
let cursor = value.parent;
|
|
1166
|
-
for (let depth = 0; cursor; depth += 1) {
|
|
1167
|
-
if (depth >= 64) {
|
|
1168
|
-
diagnostics.push(error(`items.${id}.parent`, "PARENT_DEPTH", "parent hierarchy exceeds 64 levels"));
|
|
1169
|
-
break;
|
|
1170
|
-
}
|
|
1171
|
-
if (cursor === id) {
|
|
1172
|
-
diagnostics.push(error(`items.${id}.parent`, "PARENT_CYCLE", `${id} cannot be inside itself`));
|
|
1173
|
-
break;
|
|
1174
|
-
}
|
|
1175
|
-
cursor = item(cursor)?.parent;
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
for (const bound of arrowBindings(value)) {
|
|
1180
|
-
const target = item(bound);
|
|
1181
|
-
if (!target) diagnostics.push(error(`items.${id}.props`, "BINDING_NOT_FOUND", `bound item ${bound} does not exist`));
|
|
1182
|
-
else if (bound === id || target.type === "arrow") diagnostics.push(error(`items.${id}.props`, "INVALID_BINDING", "arrows bind to items other than arrows"));
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
for (const [id, value] of nextItems) {
|
|
1186
|
-
if (!value || !state.item(id) || state.item(id)?.type === value.type) continue;
|
|
1187
|
-
if (value.type !== "frame") {
|
|
1188
|
-
for (const child of state.children(id)) if (item(child)?.parent === id) diagnostics.push(error(`items.${child}.parent`, "INVALID_PARENT", `${id} is not a frame`));
|
|
1189
|
-
}
|
|
1190
|
-
if (value.type === "arrow") for (const binder of state.binders(id)) {
|
|
1191
|
-
const arrow = item(binder);
|
|
1192
|
-
if (arrow && arrowBindings(arrow).includes(id)) diagnostics.push(error(`items.${binder}.props`, "INVALID_BINDING", "arrows cannot bind to arrows"));
|
|
1193
|
-
}
|
|
1194
|
-
for (const ref of state.trackRefs(id)) {
|
|
1195
|
-
const current = track(ref.animation, ref.track);
|
|
1196
|
-
if (current) diagnostics.push(...validateTrack(`animations.${ref.animation}.tracks.${ref.track}`, ref.animation, current, item, animation, track, validationState));
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
for (const [animationId, tracks] of nextTracks) {
|
|
1200
|
-
if (!animation(animationId)) {
|
|
1201
|
-
for (const [trackId, value] of tracks) if (value) diagnostics.push(error(`animations.${animationId}.tracks.${trackId}`, "ANIMATION_NOT_FOUND", `animation ${animationId} does not exist`));
|
|
1202
|
-
continue;
|
|
1203
|
-
}
|
|
1204
|
-
for (const [trackId, value] of tracks) {
|
|
1205
|
-
if (!value) continue;
|
|
1206
|
-
diagnostics.push(...validateTrack(`animations.${animationId}.tracks.${trackId}`, animationId, value, item, animation, track, validationState));
|
|
1207
|
-
}
|
|
1208
|
-
}
|
|
1209
|
-
if (diagnostics.length) return {
|
|
1210
|
-
ok: false,
|
|
1211
|
-
diagnostics
|
|
1212
|
-
};
|
|
1213
|
-
const before = emptyDelta();
|
|
1214
|
-
const after = emptyDelta();
|
|
1215
|
-
if (nextSettings && !boardJsonEquals(nextSettings, state.settings())) {
|
|
1216
|
-
before.board = state.settings();
|
|
1217
|
-
after.board = nextSettings;
|
|
1218
|
-
}
|
|
1219
|
-
for (const [id, value] of nextItems) {
|
|
1220
|
-
const previous = state.item(id) ?? null;
|
|
1221
|
-
if (boardJsonEquals(previous, value)) continue;
|
|
1222
|
-
before.items[id] = previous;
|
|
1223
|
-
after.items[id] = value;
|
|
1224
|
-
}
|
|
1225
|
-
for (const [id, value] of nextAnimations) {
|
|
1226
|
-
before.animations[id] = state.animation(id) ?? null;
|
|
1227
|
-
after.animations[id] = value;
|
|
1228
|
-
}
|
|
1229
|
-
for (const [animationId, tracks] of nextTracks) for (const [trackId, value] of tracks) {
|
|
1230
|
-
const previous = state.track(animationId, trackId) ?? null;
|
|
1231
|
-
if (boardJsonEquals(previous, value)) continue;
|
|
1232
|
-
slot(before.tracks, animationId)[trackId] = previous;
|
|
1233
|
-
slot(after.tracks, animationId)[trackId] = value;
|
|
1234
|
-
}
|
|
1235
|
-
return {
|
|
1236
|
-
ok: true,
|
|
1237
|
-
before: withoutEmpty(before),
|
|
1238
|
-
after: withoutEmpty(after),
|
|
1239
|
-
diagnostics: []
|
|
1240
|
-
};
|
|
1241
|
-
}
|
|
1242
|
-
function validateTrack(path, animationId, value, item, animation, track, state) {
|
|
1243
|
-
const diagnostics = [];
|
|
1244
|
-
let targetType;
|
|
1245
|
-
if (value.target === "camera") targetType = BOARD_CAMERA_TARGET;
|
|
1246
|
-
else if (item(value.target)) targetType = item(value.target).type;
|
|
1247
|
-
else if (animation(value.target)) {
|
|
1248
|
-
targetType = "animation";
|
|
1249
|
-
if (value.target === animationId || nestsInto(value.target, animationId, animation, track, state)) return [error(`${path}.target`, "ANIMATION_CYCLE", `${animationId} cannot contain itself through ${value.target}`)];
|
|
1250
|
-
} else return [error(`${path}.target`, "TARGET_NOT_FOUND", `target ${value.target} is not an item, animation or camera`)];
|
|
1251
|
-
const resolved = resolveBoardProperty(targetType, value.property);
|
|
1252
|
-
if (!resolved.ok) return [error(`${path}.property`, "INVALID_PROPERTY", resolved.message)];
|
|
1253
|
-
for (const [index, keyframe] of value.keyframes.entries()) {
|
|
1254
|
-
const parsed = resolved.spec.schema.safeParse(keyframe.value);
|
|
1255
|
-
if (!parsed.success) {
|
|
1256
|
-
diagnostics.push(error(`${path}.keyframes.${index}.value`, "INVALID_KEYFRAME", parsed.error.issues[0]?.message ?? "invalid value"));
|
|
1257
|
-
continue;
|
|
1258
|
-
}
|
|
1259
|
-
if (value.property === "focus" && typeof keyframe.value === "string" && !item(keyframe.value)) diagnostics.push(error(`${path}.keyframes.${index}.value`, "TARGET_NOT_FOUND", `focus item ${keyframe.value} does not exist`));
|
|
1260
|
-
}
|
|
1261
|
-
if (value.interpolation === "spline" && resolved.spec.kind !== "vec2") diagnostics.push(error(`${path}.interpolation`, "INVALID_TRACK", "spline interpolation needs a position-like property"));
|
|
1262
|
-
return diagnostics;
|
|
1263
|
-
}
|
|
1264
|
-
function nestsInto(from, into, animation, track, state) {
|
|
1265
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1266
|
-
const stack = [from];
|
|
1267
|
-
while (stack.length) {
|
|
1268
|
-
const current = stack.pop();
|
|
1269
|
-
if (current === into) return true;
|
|
1270
|
-
if (seen.has(current) || !animation(current)) continue;
|
|
1271
|
-
seen.add(current);
|
|
1272
|
-
for (const trackId of state.trackIds(current)) {
|
|
1273
|
-
const value = track(current, trackId);
|
|
1274
|
-
if (value && value.property === "time" && animation(value.target)) stack.push(value.target);
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
return false;
|
|
1278
|
-
}
|
|
1279
|
-
function createDocumentState(document) {
|
|
1280
|
-
let children = null;
|
|
1281
|
-
let binders = null;
|
|
1282
|
-
let refs = null;
|
|
1283
|
-
const index = () => {
|
|
1284
|
-
if (children) return;
|
|
1285
|
-
children = /* @__PURE__ */ new Map();
|
|
1286
|
-
binders = /* @__PURE__ */ new Map();
|
|
1287
|
-
refs = /* @__PURE__ */ new Map();
|
|
1288
|
-
for (const [id, value] of Object.entries(document.items)) {
|
|
1289
|
-
if (value.parent) children.set(value.parent, [...children.get(value.parent) ?? [], id]);
|
|
1290
|
-
for (const bound of arrowBindings(value)) binders.set(bound, [...binders.get(bound) ?? [], id]);
|
|
1291
|
-
}
|
|
1292
|
-
for (const [animationId, value] of Object.entries(document.animations)) for (const [trackId, track] of Object.entries(value.tracks)) for (const ref of trackReferences(track)) refs.set(ref, [...refs.get(ref) ?? [], {
|
|
1293
|
-
animation: animationId,
|
|
1294
|
-
track: trackId
|
|
1295
|
-
}]);
|
|
1296
|
-
};
|
|
1297
|
-
return {
|
|
1298
|
-
settings: () => document.board,
|
|
1299
|
-
item: (id) => document.items[id],
|
|
1300
|
-
animation: (id) => {
|
|
1301
|
-
const value = document.animations[id];
|
|
1302
|
-
if (!value) return void 0;
|
|
1303
|
-
const { tracks: _tracks, ...header } = value;
|
|
1304
|
-
return header;
|
|
1305
|
-
},
|
|
1306
|
-
track: (animationId, trackId) => document.animations[animationId]?.tracks[trackId],
|
|
1307
|
-
trackIds: (animationId) => Object.keys(document.animations[animationId]?.tracks ?? {}),
|
|
1308
|
-
children: (id) => {
|
|
1309
|
-
index();
|
|
1310
|
-
return children?.get(id) ?? [];
|
|
1311
|
-
},
|
|
1312
|
-
binders: (id) => {
|
|
1313
|
-
index();
|
|
1314
|
-
return binders?.get(id) ?? [];
|
|
1315
|
-
},
|
|
1316
|
-
trackRefs: (id) => {
|
|
1317
|
-
index();
|
|
1318
|
-
return refs?.get(id) ?? [];
|
|
1319
|
-
},
|
|
1320
|
-
maxZ: (parent) => {
|
|
1321
|
-
let max = 0;
|
|
1322
|
-
for (const value of Object.values(document.items)) if (value.parent === parent && (value.z ?? 0) > max) max = value.z ?? 0;
|
|
1323
|
-
return max;
|
|
1324
|
-
}
|
|
1325
|
-
};
|
|
1326
|
-
}
|
|
1327
|
-
function applyBoardDelta(document, delta) {
|
|
1328
|
-
const items = delta.items ? { ...document.items } : document.items;
|
|
1329
|
-
for (const [id, value] of Object.entries(delta.items ?? {})) if (value) items[id] = value;
|
|
1330
|
-
else delete items[id];
|
|
1331
|
-
const animations = delta.animations || delta.tracks ? { ...document.animations } : document.animations;
|
|
1332
|
-
for (const [id, value] of Object.entries(delta.animations ?? {})) if (value) animations[id] = {
|
|
1333
|
-
...value,
|
|
1334
|
-
tracks: animations[id]?.tracks ?? {}
|
|
1335
|
-
};
|
|
1336
|
-
else delete animations[id];
|
|
1337
|
-
for (const [animationId, tracks] of Object.entries(delta.tracks ?? {})) {
|
|
1338
|
-
const current = animations[animationId];
|
|
1339
|
-
if (!current) continue;
|
|
1340
|
-
const nextTracks = { ...current.tracks };
|
|
1341
|
-
for (const [trackId, value] of Object.entries(tracks)) if (value) nextTracks[trackId] = value;
|
|
1342
|
-
else delete nextTracks[trackId];
|
|
1343
|
-
animations[animationId] = {
|
|
1344
|
-
...current,
|
|
1345
|
-
tracks: nextTracks
|
|
1346
|
-
};
|
|
1347
|
-
}
|
|
1348
|
-
return {
|
|
1349
|
-
board: delta.board ?? document.board,
|
|
1350
|
-
items,
|
|
1351
|
-
animations
|
|
1352
|
-
};
|
|
1353
|
-
}
|
|
1354
|
-
function applyBoardPatchToDocument(document, patch, options = {}) {
|
|
1355
|
-
const result = applyBoardPatch(createDocumentState(document), patch, options);
|
|
1356
|
-
return result.ok ? {
|
|
1357
|
-
ok: true,
|
|
1358
|
-
document: applyBoardDelta(document, result.after),
|
|
1359
|
-
before: result.before,
|
|
1360
|
-
after: result.after
|
|
1361
|
-
} : result;
|
|
1362
|
-
}
|
|
1363
|
-
function parseBoardDocument(input) {
|
|
1364
|
-
if (!isRecord$6(input)) return {
|
|
1365
|
-
ok: false,
|
|
1366
|
-
diagnostics: [error("", "INVALID_DOCUMENT", "expected an object")]
|
|
1367
|
-
};
|
|
1368
|
-
const result = applyBoardPatchToDocument({
|
|
1369
|
-
board: BoardSettingsSchema.parse({}),
|
|
1370
|
-
items: {},
|
|
1371
|
-
animations: {}
|
|
1372
|
-
}, {
|
|
1373
|
-
...isRecord$6(input.board) ? { board: input.board } : {},
|
|
1374
|
-
...isRecord$6(input.items) ? { items: input.items } : {},
|
|
1375
|
-
...isRecord$6(input.animations) ? { animations: input.animations } : {}
|
|
1376
|
-
});
|
|
1377
|
-
return result.ok ? {
|
|
1378
|
-
ok: true,
|
|
1379
|
-
document: result.document
|
|
1380
|
-
} : result;
|
|
1381
|
-
}
|
|
1382
|
-
//#endregion
|
|
1383
307
|
//#region ../protocol/dist/turn-origin.js
|
|
1384
308
|
const record$1 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
1385
309
|
const normalizeSessionTurnOrigin = (value) => {
|
|
@@ -5217,6 +4141,7 @@ var CohubClient = class {
|
|
|
5217
4141
|
}
|
|
5218
4142
|
transport;
|
|
5219
4143
|
websocketClient;
|
|
4144
|
+
fileServices;
|
|
5220
4145
|
appRuntime;
|
|
5221
4146
|
appWindow;
|
|
5222
4147
|
constructor(options = {}) {
|
|
@@ -5256,6 +4181,7 @@ var CohubClient = class {
|
|
|
5256
4181
|
...options.websocket,
|
|
5257
4182
|
getAccessToken: options.websocket?.getAccessToken ?? getAccessToken
|
|
5258
4183
|
});
|
|
4184
|
+
this.fileServices = createSpaceFileServices(this.transport, this.websocketClient);
|
|
5259
4185
|
this.voice = new VoiceApi({
|
|
5260
4186
|
env: options.voice?.env ?? options.env,
|
|
5261
4187
|
url: options.voice?.url,
|
|
@@ -5396,7 +4322,7 @@ attach: attachAppEmbed },
|
|
|
5396
4322
|
}
|
|
5397
4323
|
};
|
|
5398
4324
|
space(spaceId) {
|
|
5399
|
-
return new SpaceClient(spaceId, this.transport, this.websocketClient);
|
|
4325
|
+
return new SpaceClient(spaceId, this.transport, this.websocketClient, this.fileServices);
|
|
5400
4326
|
}
|
|
5401
4327
|
onUserEvent(handler) {
|
|
5402
4328
|
ensureRealtimeConnected(this.websocketClient);
|
|
@@ -7162,4 +6088,4 @@ function generationOutputSource(result, outputIndex) {
|
|
|
7162
6088
|
return `data:${declared && MEDIA_TYPE_PATTERN.test(declared) ? declared : DEFAULT_MEDIA_TYPES[String(block.type)] ?? "application/octet-stream"};base64,${data}`;
|
|
7163
6089
|
}
|
|
7164
6090
|
//#endregion
|
|
7165
|
-
export { APP_APPEARANCE_TOKENS, APP_COMPOSER_CHIP_CONTENT_MAX_BYTES, APP_COMPOSER_CHIP_KEY_MAX_LENGTH, APP_COMPOSER_CHIP_LABEL_MAX_LENGTH, APP_DEVICES, APP_DOMAIN_PRICE_USD, APP_SURFACE_READY_TIMEOUT_MS, APP_SURFACE_REQUEST_TIMEOUT_MS, AppCommerceApi, AppRealtimeApi, AppRefParseError, AppRoom, AppRoomRtc, AppRtcChannel, AppRtcError, AppRuntimeApi, AppRuntimeApi as WorkRuntimeApi, AppRuntimeError, AppSurfaceApi, AppWindowApi, AppsApi, BILLING_ACCESS_BLOCKED_ERROR_CODE, BOARD_COLOR_TOKENS, BOARD_ITEM_TYPES, BillingApi, BoardAnimationSchema, BoardClient, BoardPatchSchema, BoardTrackSchema, COHUB_ENVIRONMENTS, COHUB_SOURCE_HEADER, COHUB_SOURCE_HEADER_NAMES, CohubClient, CohubHttpClient, DESKTOP_COMMAND_ACCEPT_TIMEOUT_MS, DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS, DESKTOP_COMMAND_MAX_TIMEOUT_MS, DESKTOP_COMMAND_OPEN_TIMEOUT_MS, DESKTOP_COMMAND_PAYLOAD_MAX_BYTES, DESKTOP_COMMAND_PENDING_TTL_SECONDS, DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS, DESKTOP_COMMAND_TERMINAL_TTL_SECONDS, DESKTOP_COMMAND_VERSION, DISPLAY_ACTION_TYPES, DISPLAY_ELEMENT_REF_PATTERN, DISPLAY_SYSTEM_ACTIONS, DesktopCommandsApi, DisplayActionError, DisplayConnection, FEATURE_NOT_ENTITLED_ERROR_CODE, GenerationPolicyError, HOME_SPACE_SLUG, HttpError, LOCAL_HARNESSES, LOCAL_HARNESS_SPECS, NATIVE_INGEST_MAX_TURNS, NATIVE_SYNC_SOURCE, OriginBrokerTransport, PERMISSIONS, ParentBridgeTransport, PopupBrokerTransport, REQUEST_SOURCE_VIA_MAX_LENGTH, RUNTIME_ARCHIVE_SEGMENT_BYTES, RUNTIME_MAX_FRAME_BYTES, RUNTIME_PROTOCOL_VERSION, RUNTIME_RECOVERY_BATCH_SIZE, ReferencesApi, ReferralsApi, RoomsApi, SETTLED_TURN_STATUSES, SessionGenerationStreamClient, SessionPatchReducer, SpaceDisplaysApi, SpacePublicFilesApi, SpaceWebhooksApi, UPLOAD_ERROR_BATCH_TOO_LARGE, UPLOAD_ERROR_FILE_TOO_LARGE, UPLOAD_ERROR_RATE_LIMITED, UPLOAD_ERROR_TOO_MANY_FILES, UPLOAD_MAX_BATCH_BYTES, UPLOAD_MAX_BATCH_FILES, UPLOAD_MAX_FILE_BYTES, USER_LEVEL_PERMISSIONS, UiCommandsApi, UsersApi, VoiceApi, VoiceInputClient, WebsocketClient, WorkCommerceApi, WorkRealtimeApi, WorkRefParseError, WorkRoom, WorkSurfaceApi, appAppearanceVar, applyAppAppearance, assertGenerationRequestAllowedByPolicy, assertHarnessAccess, attachAppEmbed, batchUploadEntries, buildAppSurfaceRequest, buildSpaceInvitePath, buildSpacePath, buildViewportContentBlock, clearGrantedAppScopes, compileDisplayActions, connectDisplay, contextToPiMessages, createAppBridgeCore, createAppBridgeCore as createWorkBridgeCore, createAppRuntime, createAppRuntime as createWorkRuntime, createCohubClient, createHttpClient, createOriginAppResolver, createSessionGenerationStreamClient, createSessionPatchReducer, createSlugAppIdResolver, createSlugAppIdResolver as createSlugWorkIdResolver, createVoiceInputClient, createWebsocketClient, decodeGenerationPolicy, defaultDesktopCommandTimeoutMs, encodeGenerationPolicy, extractBillingPayload, filterDiscoverableGenerationModels, filterGenerationDeclarationsByPolicy, filterSpacePickerItems, findGenerationModelPolicy, fingerprintProjectionTurns, formatAppRef, formatWorkRef, generationOutputSource, getAllowedGenerationModelIds, getCohubContext, harnessArchiveIndexSchema, harnessLabel, harnessSchema, hasGrantedAppScopes, hasRequestSourceIdentity, isActiveGenerationTask, isAppId, isBillingAccessBlockedCode, isBillingAccessBlockedError, isDesktopCallMethod, isFeatureNotEntitledError, isGenerationModelHidden, isHttpErrorCode, isLocalHarness, isNativeClientTurn, isProjectionCompaction, isProjectionPendingGeneration, isRequestSourceClientId, isRequestSourceEmpty, isRequestSourceUuid, isTerminalDesktopCommandStatus, isTextMime, isUserLevelPermission, isUuid, isWorkId, joinApiUrl, localHarnessSchema, matchesUnauthorizedErrorToken, mergeRequestSourceIntoMeta, mimeTypeForPath, nativeIngestTurnSchema, nativeRuntimeEventSchema, nativeTurnCompleteSchema, nativeTurnProgressSchema, normalizeAppDomainHostname, normalizeBaseUrl, normalizeDisplayPoint, normalizeGenerationPolicy, normalizeRequestSource, normalizeSessionTurnOrigin, normalizeSpacePickerQuery, normalizeVoiceInputWebsocketUrl, normalizeWebsocketUrl, orderSpacePickerItems, parseAppRef, parseAppSurfaceReady, parseAppSurfaceResponse, parseAssistantMessageCommit, parseBoardDocument, parseBoardItem, parseDesktopCommand, parseGenerationPolicyFromEnv, parseRequestSourceFromHeaders, parseSpaceRef, parseWorkRef, projectNativeMessageMeta, projectNativeSession, readRequestSourceFromEnv, readSentTurns, readSessionTurnOrigin, requestSourceToHeaders, resolveApiBaseUrl, resolveAppTransport, resolveAppTransport as resolveWorkTransport, resolveCohubEnvironment, resolveExecutionAppId, resolveExecutionToken, resolveHarness, resolveOpenSurface, resolveRequestSourceChannel, resolveVoiceInputWebsocketUrl, resolveWebBaseUrl, resolveWebsocketUrl, runtimeCommandSchema, runtimeEventSchema, runtimeNativeStopSchema, runtimeReadySchema, sanitizeAccessToken, scopeListHasPermission, selectRuntimeContextMessages, selectSpacePickerItems, serializeProjection, serializeProjectionRecords, setGrantedAppScopes, toGenerationTaskView, trimProjectionTurnsToCompaction, validateArchiveBoundary };
|
|
6091
|
+
export { APP_APPEARANCE_TOKENS, APP_COMPOSER_CHIP_CONTENT_MAX_BYTES, APP_COMPOSER_CHIP_KEY_MAX_LENGTH, APP_COMPOSER_CHIP_LABEL_MAX_LENGTH, APP_DEVICES, APP_DOMAIN_PRICE_USD, APP_SURFACE_READY_TIMEOUT_MS, APP_SURFACE_REQUEST_TIMEOUT_MS, AppCommerceApi, AppRealtimeApi, AppRefParseError, AppRoom, AppRoomRtc, AppRtcChannel, AppRtcError, AppRuntimeApi, AppRuntimeApi as WorkRuntimeApi, AppRuntimeError, AppSurfaceApi, AppWindowApi, AppsApi, BILLING_ACCESS_BLOCKED_ERROR_CODE, BOARD_COLOR_TOKENS, BOARD_ITEM_TYPES, BillingApi, BoardAnimationSchema, BoardClient, BoardPatchSchema, BoardTrackSchema, COHUB_ENVIRONMENTS, COHUB_SOURCE_HEADER, COHUB_SOURCE_HEADER_NAMES, CohubClient, CohubHttpClient, DESKTOP_COMMAND_ACCEPT_TIMEOUT_MS, DESKTOP_COMMAND_DEFAULT_TIMEOUT_MS, DESKTOP_COMMAND_MAX_TIMEOUT_MS, DESKTOP_COMMAND_OPEN_TIMEOUT_MS, DESKTOP_COMMAND_PAYLOAD_MAX_BYTES, DESKTOP_COMMAND_PENDING_TTL_SECONDS, DESKTOP_COMMAND_SETTLEMENT_GRACE_SECONDS, DESKTOP_COMMAND_TERMINAL_TTL_SECONDS, DESKTOP_COMMAND_VERSION, DISPLAY_ACTION_TYPES, DISPLAY_ELEMENT_REF_PATTERN, DISPLAY_SYSTEM_ACTIONS, DesktopCommandsApi, DisplayActionError, DisplayConnection, FEATURE_NOT_ENTITLED_ERROR_CODE, GenerationPolicyError, HOME_SPACE_SLUG, HttpError, LOCAL_HARNESSES, LOCAL_HARNESS_SPECS, NATIVE_INGEST_MAX_TURNS, NATIVE_SYNC_SOURCE, OriginBrokerTransport, PERMISSIONS, ParentBridgeTransport, PopupBrokerTransport, REQUEST_SOURCE_VIA_MAX_LENGTH, RUNTIME_ARCHIVE_SEGMENT_BYTES, RUNTIME_MAX_FRAME_BYTES, RUNTIME_PROTOCOL_VERSION, RUNTIME_RECOVERY_BATCH_SIZE, ReferencesApi, ReferralsApi, RoomsApi, SETTLED_TURN_STATUSES, SessionGenerationStreamClient, SessionPatchReducer, SpaceDisplaysApi, SpacePublicFilesApi, SpaceWebhooksApi, UPLOAD_ERROR_BATCH_TOO_LARGE, UPLOAD_ERROR_FILE_TOO_LARGE, UPLOAD_ERROR_RATE_LIMITED, UPLOAD_ERROR_TOO_MANY_FILES, UPLOAD_MAX_BATCH_BYTES, UPLOAD_MAX_BATCH_FILES, UPLOAD_MAX_FILE_BYTES, USER_LEVEL_PERMISSIONS, UiCommandsApi, UsersApi, VoiceApi, VoiceInputClient, WebsocketClient, WorkCommerceApi, WorkRealtimeApi, WorkRefParseError, WorkRoom, WorkSurfaceApi, appAppearanceVar, applyAppAppearance, assertGenerationRequestAllowedByPolicy, assertHarnessAccess, attachAppEmbed, batchUploadEntries, buildAppSurfaceRequest, buildSpaceInvitePath, buildSpacePath, buildViewportContentBlock, clearFileUrlCache, clearGrantedAppScopes, compileDisplayActions, connectDisplay, contextToPiMessages, createAppBridgeCore, createAppBridgeCore as createWorkBridgeCore, createAppRuntime, createAppRuntime as createWorkRuntime, createCohubClient, createHttpClient, createOriginAppResolver, createSessionGenerationStreamClient, createSessionPatchReducer, createSlugAppIdResolver, createSlugAppIdResolver as createSlugWorkIdResolver, createVoiceInputClient, createWebsocketClient, decodeGenerationPolicy, defaultDesktopCommandTimeoutMs, encodeGenerationPolicy, extractBillingPayload, filterDiscoverableGenerationModels, filterGenerationDeclarationsByPolicy, filterSpacePickerItems, findGenerationModelPolicy, fingerprintProjectionTurns, formatAppRef, formatWorkRef, generationOutputSource, getAllowedGenerationModelIds, getCohubContext, harnessArchiveIndexSchema, harnessLabel, harnessSchema, hasGrantedAppScopes, hasRequestSourceIdentity, isActiveGenerationTask, isAppId, isBillingAccessBlockedCode, isBillingAccessBlockedError, isDesktopCallMethod, isFeatureNotEntitledError, isGenerationModelHidden, isHttpErrorCode, isLocalHarness, isNativeClientTurn, isProjectionCompaction, isProjectionPendingGeneration, isRequestSourceClientId, isRequestSourceEmpty, isRequestSourceUuid, isTerminalDesktopCommandStatus, isTextMime, isUserLevelPermission, isUuid, isWorkId, joinApiUrl, localHarnessSchema, matchesUnauthorizedErrorToken, mergeRequestSourceIntoMeta, mimeTypeForPath, nativeIngestTurnSchema, nativeRuntimeEventSchema, nativeTurnCompleteSchema, nativeTurnProgressSchema, normalizeAppDomainHostname, normalizeBaseUrl, normalizeDisplayPoint, normalizeGenerationPolicy, normalizeRequestSource, normalizeSessionTurnOrigin, normalizeSpacePickerQuery, normalizeVoiceInputWebsocketUrl, normalizeWebsocketUrl, orderSpacePickerItems, parseAppRef, parseAppSurfaceReady, parseAppSurfaceResponse, parseAssistantMessageCommit, parseBoardDocument, parseBoardItem, parseDesktopCommand, parseGenerationPolicyFromEnv, parseRequestSourceFromHeaders, parseSpaceRef, parseWorkRef, projectNativeMessageMeta, projectNativeSession, readRequestSourceFromEnv, readSentTurns, readSessionTurnOrigin, requestSourceToHeaders, resolveApiBaseUrl, resolveAppTransport, resolveAppTransport as resolveWorkTransport, resolveCohubEnvironment, resolveExecutionAppId, resolveExecutionToken, resolveHarness, resolveOpenSurface, resolveRequestSourceChannel, resolveVoiceInputWebsocketUrl, resolveWebBaseUrl, resolveWebsocketUrl, runtimeCommandSchema, runtimeEventSchema, runtimeNativeStopSchema, runtimeReadySchema, sanitizeAccessToken, scopeListHasPermission, selectRuntimeContextMessages, selectSpacePickerItems, serializeProjection, serializeProjectionRecords, setGrantedAppScopes, toGenerationTaskView, trimProjectionTurnsToCompaction, validateArchiveBoundary };
|