@tldraw/tlschema 5.2.0-next.ee0fa4d6244f → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/DOCS.md +682 -0
  2. package/README.md +9 -1
  3. package/dist-cjs/index.d.ts +85 -11
  4. package/dist-cjs/index.js +3 -1
  5. package/dist-cjs/index.js.map +2 -2
  6. package/dist-cjs/misc/b64Vecs.js +175 -10
  7. package/dist-cjs/misc/b64Vecs.js.map +2 -2
  8. package/dist-cjs/records/TLInstance.js +3 -2
  9. package/dist-cjs/records/TLInstance.js.map +2 -2
  10. package/dist-cjs/records/TLPageState.js +5 -1
  11. package/dist-cjs/records/TLPageState.js.map +2 -2
  12. package/dist-cjs/records/TLPresence.js +3 -2
  13. package/dist-cjs/records/TLPresence.js.map +2 -2
  14. package/dist-cjs/shapes/TLDrawShape.js +16 -2
  15. package/dist-cjs/shapes/TLDrawShape.js.map +2 -2
  16. package/dist-cjs/shapes/TLHighlightShape.js +14 -1
  17. package/dist-cjs/shapes/TLHighlightShape.js.map +2 -2
  18. package/dist-cjs/shapes/TLNoteShape.js +14 -2
  19. package/dist-cjs/shapes/TLNoteShape.js.map +2 -2
  20. package/dist-esm/index.d.mts +85 -11
  21. package/dist-esm/index.mjs +4 -2
  22. package/dist-esm/index.mjs.map +2 -2
  23. package/dist-esm/misc/b64Vecs.mjs +175 -10
  24. package/dist-esm/misc/b64Vecs.mjs.map +2 -2
  25. package/dist-esm/records/TLInstance.mjs +3 -2
  26. package/dist-esm/records/TLInstance.mjs.map +2 -2
  27. package/dist-esm/records/TLPageState.mjs +5 -1
  28. package/dist-esm/records/TLPageState.mjs.map +2 -2
  29. package/dist-esm/records/TLPresence.mjs +3 -2
  30. package/dist-esm/records/TLPresence.mjs.map +2 -2
  31. package/dist-esm/shapes/TLDrawShape.mjs +17 -3
  32. package/dist-esm/shapes/TLDrawShape.mjs.map +2 -2
  33. package/dist-esm/shapes/TLHighlightShape.mjs +15 -2
  34. package/dist-esm/shapes/TLHighlightShape.mjs.map +2 -2
  35. package/dist-esm/shapes/TLNoteShape.mjs +14 -2
  36. package/dist-esm/shapes/TLNoteShape.mjs.map +2 -2
  37. package/package.json +11 -7
  38. package/src/index.ts +1 -1
  39. package/src/migrations.test.ts +136 -1
  40. package/src/misc/b64Vecs.test.ts +112 -0
  41. package/src/misc/b64Vecs.ts +230 -15
  42. package/src/records/TLInstance.ts +5 -4
  43. package/src/records/TLPageState.ts +5 -1
  44. package/src/records/TLPresence.ts +5 -4
  45. package/src/shapes/TLDrawShape.ts +30 -1
  46. package/src/shapes/TLHighlightShape.ts +19 -1
  47. package/src/shapes/TLNoteShape.ts +15 -3
@@ -1,11 +1,16 @@
1
- import { assert } from "@tldraw/utils";
2
1
  const _POINT_B64_LENGTH = 8;
3
2
  const FIRST_POINT_B64_LENGTH = 16;
3
+ const FIRST_POINT_2D_B64_LENGTH = 12;
4
+ const DEFAULT_PRESSURE = 0.5;
5
+ const DIM_2D = 2;
6
+ const DIM_3D = 3;
4
7
  const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5
8
  const B64_LOOKUP = new Uint8Array(128);
6
9
  for (let i = 0; i < 64; i++) {
7
10
  B64_LOOKUP[BASE64_CHARS.charCodeAt(i)] = i;
8
11
  }
12
+ const SIX_BIT_MASK = 63;
13
+ const PADDING_CHAR_CODE = "=".charCodeAt(0);
9
14
  const POW2 = new Float64Array(31);
10
15
  for (let i = 0; i < 31; i++) {
11
16
  POW2[i] = Math.pow(2, i - 15);
@@ -34,10 +39,19 @@ function nativeBase64ToUint8Array(base64) {
34
39
  return Uint8Array.fromBase64(base64);
35
40
  }
36
41
  function fallbackBase64ToUint8Array(base64) {
37
- const numBytes = Math.floor(base64.length * 3 / 4);
42
+ const paddedLength = base64.length;
43
+ let padding = 0;
44
+ if (paddedLength > 0 && base64.charCodeAt(paddedLength - 1) === PADDING_CHAR_CODE) {
45
+ padding++;
46
+ if (paddedLength > 1 && base64.charCodeAt(paddedLength - 2) === PADDING_CHAR_CODE) {
47
+ padding++;
48
+ }
49
+ }
50
+ const numBytes = Math.floor(paddedLength * 3 / 4) - padding;
38
51
  const bytes = new Uint8Array(numBytes);
39
52
  let byteIndex = 0;
40
- for (let i = 0; i < base64.length; i += 4) {
53
+ const fullGroups = Math.floor((paddedLength - padding) / 4) * 4;
54
+ for (let i = 0; i < fullGroups; i += 4) {
41
55
  const c0 = B64_LOOKUP[base64.charCodeAt(i)];
42
56
  const c1 = B64_LOOKUP[base64.charCodeAt(i + 1)];
43
57
  const c2 = B64_LOOKUP[base64.charCodeAt(i + 2)];
@@ -47,20 +61,45 @@ function fallbackBase64ToUint8Array(base64) {
47
61
  bytes[byteIndex++] = bitmap >> 8 & 255;
48
62
  bytes[byteIndex++] = bitmap & 255;
49
63
  }
64
+ if (padding === 1) {
65
+ const c0 = B64_LOOKUP[base64.charCodeAt(fullGroups)];
66
+ const c1 = B64_LOOKUP[base64.charCodeAt(fullGroups + 1)];
67
+ const c2 = B64_LOOKUP[base64.charCodeAt(fullGroups + 2)];
68
+ const bitmap = c0 << 18 | c1 << 12 | c2 << 6;
69
+ bytes[byteIndex++] = bitmap >> 16 & 255;
70
+ bytes[byteIndex++] = bitmap >> 8 & 255;
71
+ } else if (padding === 2) {
72
+ const c0 = B64_LOOKUP[base64.charCodeAt(fullGroups)];
73
+ const c1 = B64_LOOKUP[base64.charCodeAt(fullGroups + 1)];
74
+ const bitmap = c0 << 18 | c1 << 12;
75
+ bytes[byteIndex++] = bitmap >> 16 & 255;
76
+ }
50
77
  return bytes;
51
78
  }
52
79
  function nativeUint8ArrayToBase64(uint8Array) {
53
80
  return uint8Array.toBase64();
54
81
  }
55
82
  function fallbackUint8ArrayToBase64(uint8Array) {
56
- assert(uint8Array.length % 3 === 0, "Uint8Array length must be a multiple of 3");
83
+ const len = uint8Array.length;
84
+ const fullGroups = Math.floor(len / 3) * 3;
57
85
  let result = "";
58
- for (let i = 0; i < uint8Array.length; i += 3) {
86
+ for (let i = 0; i < fullGroups; i += 3) {
59
87
  const byte1 = uint8Array[i];
60
88
  const byte2 = uint8Array[i + 1];
61
89
  const byte3 = uint8Array[i + 2];
62
90
  const bitmap = byte1 << 16 | byte2 << 8 | byte3;
63
- result += BASE64_CHARS[bitmap >> 18 & 63] + BASE64_CHARS[bitmap >> 12 & 63] + BASE64_CHARS[bitmap >> 6 & 63] + BASE64_CHARS[bitmap & 63];
91
+ result += BASE64_CHARS[bitmap >> 18 & SIX_BIT_MASK] + // bits 23–18 (top sextet)
92
+ BASE64_CHARS[bitmap >> 12 & SIX_BIT_MASK] + // bits 17–12
93
+ BASE64_CHARS[bitmap >> 6 & SIX_BIT_MASK] + // bits 11–6
94
+ BASE64_CHARS[bitmap & SIX_BIT_MASK];
95
+ }
96
+ const remaining = len - fullGroups;
97
+ if (remaining === 1) {
98
+ const bitmap = uint8Array[fullGroups] << 16;
99
+ result += BASE64_CHARS[bitmap >> 18 & SIX_BIT_MASK] + BASE64_CHARS[bitmap >> 12 & SIX_BIT_MASK] + "==";
100
+ } else if (remaining === 2) {
101
+ const bitmap = uint8Array[fullGroups] << 16 | uint8Array[fullGroups + 1] << 8;
102
+ result += BASE64_CHARS[bitmap >> 18 & SIX_BIT_MASK] + BASE64_CHARS[bitmap >> 12 & SIX_BIT_MASK] + BASE64_CHARS[bitmap >> 6 & SIX_BIT_MASK] + "=";
64
103
  }
65
104
  return result;
66
105
  }
@@ -181,10 +220,12 @@ class b64Vecs {
181
220
  * - Delta points: 3 Float16 values each = 6 bytes = 8 base64 chars each
182
221
  *
183
222
  * @param points - An array of VecModel objects to encode
223
+ * @param dim - Encoding dimension; `2` routes through the 2D variant (drops z), `3` (default) keeps x, y, z
184
224
  * @returns A base64-encoded string containing delta-encoded points
185
225
  * @public
186
226
  */
187
- static encodePoints(points) {
227
+ static encodePoints(points, dim) {
228
+ if (dim === DIM_2D) return b64Vecs.encodePoints2D(points);
188
229
  if (points.length === 0) return "";
189
230
  const firstPointBytes = 12;
190
231
  const deltaBytes = (points.length - 1) * 6;
@@ -217,10 +258,12 @@ class b64Vecs {
217
258
  * Float16 deltas that are accumulated to reconstruct absolute positions.
218
259
  *
219
260
  * @param base64 - The base64-encoded string containing delta-encoded point data
261
+ * @param dim - Encoding dimension; `2` expects x/y only (z supplied as 0.5), `3` (default) expects x/y/z
220
262
  * @returns An array of VecModel objects with absolute coordinates
221
263
  * @public
222
264
  */
223
- static decodePoints(base64) {
265
+ static decodePoints(base64, dim) {
266
+ if (dim === DIM_2D) return b64Vecs.decodePoints2D(base64);
224
267
  if (base64.length === 0) return [];
225
268
  const bytes = base64ToUint8Array(base64);
226
269
  const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
@@ -243,10 +286,12 @@ class b64Vecs {
243
286
  * The first point is stored as Float32 for full precision.
244
287
  *
245
288
  * @param b64Points - The delta-encoded base64 string
289
+ * @param dim - Encoding dimension; `2` expects x/y only (z supplied as 0.5), `3` (default) expects x/y/z
246
290
  * @returns The first point as a VecModel, or null if the string is too short
247
291
  * @public
248
292
  */
249
- static decodeFirstPoint(b64Points) {
293
+ static decodeFirstPoint(b64Points, dim) {
294
+ if (dim === DIM_2D) return b64Vecs.decodeFirstPoint2D(b64Points);
250
295
  if (b64Points.length < FIRST_POINT_B64_LENGTH) return null;
251
296
  const bytes = base64ToUint8Array(b64Points.slice(0, FIRST_POINT_B64_LENGTH));
252
297
  const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
@@ -261,10 +306,12 @@ class b64Vecs {
261
306
  * Requires decoding all points to accumulate deltas.
262
307
  *
263
308
  * @param b64Points - The delta-encoded base64 string
309
+ * @param dim - Encoding dimension; `2` expects x/y only (z supplied as 0.5), `3` (default) expects x/y/z
264
310
  * @returns The last point as a VecModel, or null if the string is too short
265
311
  * @public
266
312
  */
267
- static decodeLastPoint(b64Points) {
313
+ static decodeLastPoint(b64Points, dim) {
314
+ if (dim === DIM_2D) return b64Vecs.decodeLastPoint2D(b64Points);
268
315
  if (b64Points.length < FIRST_POINT_B64_LENGTH) return null;
269
316
  const bytes = base64ToUint8Array(b64Points);
270
317
  const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
@@ -279,8 +326,126 @@ class b64Vecs {
279
326
  }
280
327
  return { x, y, z };
281
328
  }
329
+ /**
330
+ * Encode an array of VecModels as 2D delta-encoded points, dropping z entirely.
331
+ * Use for draw shapes from devices that don't report pressure, where z is a
332
+ * constant 0.5 and storing it wastes ~33% of per-point bytes.
333
+ *
334
+ * Format:
335
+ * - First point: 2 Float32 values (x, y) = 8 bytes
336
+ * - Delta points: 2 Float16 values (dx, dy) = 4 bytes each
337
+ *
338
+ * @param points - An array of VecModel objects to encode (z is discarded)
339
+ * @returns A base64-encoded string containing 2D delta-encoded points
340
+ * @public
341
+ */
342
+ static encodePoints2D(points) {
343
+ if (points.length === 0) return "";
344
+ const firstPointBytes = 8;
345
+ const deltaBytes = (points.length - 1) * 4;
346
+ const buffer = new Uint8Array(firstPointBytes + deltaBytes);
347
+ const dataView = new DataView(buffer.buffer);
348
+ const first = points[0];
349
+ dataView.setFloat32(0, first.x, true);
350
+ dataView.setFloat32(4, first.y, true);
351
+ let prevX = first.x;
352
+ let prevY = first.y;
353
+ for (let i = 1; i < points.length; i++) {
354
+ const p = points[i];
355
+ const offset = firstPointBytes + (i - 1) * 4;
356
+ setFloat16(dataView, offset, p.x - prevX);
357
+ setFloat16(dataView, offset + 2, p.y - prevY);
358
+ prevX = p.x;
359
+ prevY = p.y;
360
+ }
361
+ return uint8ArrayToBase64(buffer);
362
+ }
363
+ /**
364
+ * Decode a 2D delta-encoded base64 string back to an array of absolute VecModels.
365
+ * The z coordinate is always set to 0.5 (the default pressure value) so downstream
366
+ * consumers don't need a separate code path.
367
+ *
368
+ * @param base64 - The base64-encoded string containing 2D delta-encoded point data
369
+ * @returns An array of VecModel objects with absolute (x, y) and z = 0.5
370
+ * @public
371
+ */
372
+ static decodePoints2D(base64) {
373
+ if (base64.length === 0) return [];
374
+ const bytes = base64ToUint8Array(base64);
375
+ const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
376
+ const result = [];
377
+ let x = dataView.getFloat32(0, true);
378
+ let y = dataView.getFloat32(4, true);
379
+ result.push({ x, y, z: DEFAULT_PRESSURE });
380
+ const firstPointBytes = 8;
381
+ for (let offset = firstPointBytes; offset < bytes.length; offset += 4) {
382
+ x += getFloat16(dataView, offset);
383
+ y += getFloat16(dataView, offset + 2);
384
+ result.push({ x, y, z: DEFAULT_PRESSURE });
385
+ }
386
+ return result;
387
+ }
388
+ /**
389
+ * Get the first point from a 2D delta-encoded base64 string.
390
+ *
391
+ * @param b64Points - The 2D delta-encoded base64 string
392
+ * @returns The first point with z = 0.5, or null if the string is too short
393
+ * @public
394
+ */
395
+ static decodeFirstPoint2D(b64Points) {
396
+ if (b64Points.length < FIRST_POINT_2D_B64_LENGTH) return null;
397
+ const bytes = base64ToUint8Array(b64Points.slice(0, FIRST_POINT_2D_B64_LENGTH));
398
+ const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
399
+ return {
400
+ x: dataView.getFloat32(0, true),
401
+ y: dataView.getFloat32(4, true),
402
+ z: DEFAULT_PRESSURE
403
+ };
404
+ }
405
+ /**
406
+ * Get the last point from a 2D delta-encoded base64 string.
407
+ * Requires decoding all points to accumulate deltas.
408
+ *
409
+ * @param b64Points - The 2D delta-encoded base64 string
410
+ * @returns The last point with z = 0.5, or null if the string is too short
411
+ * @public
412
+ */
413
+ static decodeLastPoint2D(b64Points) {
414
+ if (b64Points.length < FIRST_POINT_2D_B64_LENGTH) return null;
415
+ const bytes = base64ToUint8Array(b64Points);
416
+ const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
417
+ let x = dataView.getFloat32(0, true);
418
+ let y = dataView.getFloat32(4, true);
419
+ const firstPointBytes = 8;
420
+ for (let offset = firstPointBytes; offset < bytes.length; offset += 4) {
421
+ x += getFloat16(dataView, offset);
422
+ y += getFloat16(dataView, offset + 2);
423
+ }
424
+ return { x, y, z: DEFAULT_PRESSURE };
425
+ }
426
+ /**
427
+ * Whether an encoded path contains only a single point (a "dot"), inferred from
428
+ * the encoded length without decoding — cheap enough for the render path.
429
+ *
430
+ * The single-point length depends on the encoding dimension, so this takes the
431
+ * segment's `dim`: a one-point path is `FIRST_POINT_B64_LENGTH` chars (3D) or
432
+ * `FIRST_POINT_2D_B64_LENGTH` chars (2D). Keeping this beside the layout constants
433
+ * is deliberate — it is the single source of truth for "how long is one point", so
434
+ * callers never hard-code a length threshold (which silently breaks when a new
435
+ * encoding is added).
436
+ *
437
+ * @param b64Points - The encoded path string
438
+ * @param dim - Encoding dimension; `2` for (x, y), `3` (default) for (x, y, z)
439
+ * @returns true if the path encodes exactly one point
440
+ * @public
441
+ */
442
+ static isSinglePoint(b64Points, dim) {
443
+ return b64Points.length <= (dim === DIM_2D ? FIRST_POINT_2D_B64_LENGTH : FIRST_POINT_B64_LENGTH);
444
+ }
282
445
  }
283
446
  export {
447
+ DIM_2D,
448
+ DIM_3D,
284
449
  b64Vecs,
285
450
  fallbackBase64ToUint8Array,
286
451
  fallbackUint8ArrayToBase64,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/misc/b64Vecs.ts"],
4
- "sourcesContent": ["import { assert } from '@tldraw/utils'\nimport { VecModel } from './geometry-types'\n\n// Each point = 3 Float16s = 6 bytes = 8 base64 chars (legacy format)\nconst _POINT_B64_LENGTH = 8\n\n// First point in delta encoding = 3 Float32s = 12 bytes = 16 base64 chars\nconst FIRST_POINT_B64_LENGTH = 16\n\n// O(1) lookup table for base64 decoding (maps char code -> 6-bit value)\nconst BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nconst B64_LOOKUP = new Uint8Array(128)\nfor (let i = 0; i < 64; i++) {\n\tB64_LOOKUP[BASE64_CHARS.charCodeAt(i)] = i\n}\n\n// Precomputed powers of 2 for Float16 exponents (exp - 15, so indices 0-30 map to 2^-15 to 2^15)\nconst POW2 = new Float64Array(31)\nfor (let i = 0; i < 31; i++) {\n\tPOW2[i] = Math.pow(2, i - 15)\n}\nconst POW2_SUBNORMAL = Math.pow(2, -14) / 1024 // For subnormal numbers\n\n// Precomputed mantissa values: 1 + frac/1024 for all 1024 possible frac values\n// Avoids division in hot path\nconst MANTISSA = new Float64Array(1024)\nfor (let i = 0; i < 1024; i++) {\n\tMANTISSA[i] = 1 + i / 1024\n}\n\ndeclare global {\n\tinterface Uint8Array {\n\t\ttoBase64?(): string\n\t}\n\tinterface Uint8ArrayConstructor {\n\t\tfromBase64?(base64: string): Uint8Array\n\t}\n}\n\nfunction nativeGetFloat16(dataView: DataView, offset: number): number {\n\treturn (dataView as any).getFloat16(offset, true)\n}\nfunction fallbackGetFloat16(dataView: DataView, offset: number): number {\n\treturn float16BitsToNumber(dataView.getUint16(offset, true))\n}\n\nconst getFloat16 =\n\ttypeof (DataView.prototype as any).getFloat16 === 'function'\n\t\t? nativeGetFloat16\n\t\t: fallbackGetFloat16\n\nfunction nativeSetFloat16(dataView: DataView, offset: number, value: number): void {\n\t;(dataView as any).setFloat16(offset, value, true)\n}\nfunction fallbackSetFloat16(dataView: DataView, offset: number, value: number): void {\n\tdataView.setUint16(offset, numberToFloat16Bits(value), true)\n}\n\nconst setFloat16 =\n\ttypeof (DataView.prototype as any).setFloat16 === 'function'\n\t\t? nativeSetFloat16\n\t\t: fallbackSetFloat16\n\nfunction nativeBase64ToUint8Array(base64: string): Uint8Array {\n\treturn Uint8Array.fromBase64!(base64)\n}\n\n/** @internal */\nexport function fallbackBase64ToUint8Array(base64: string): Uint8Array {\n\tconst numBytes = Math.floor((base64.length * 3) / 4)\n\tconst bytes = new Uint8Array(numBytes)\n\tlet byteIndex = 0\n\n\tfor (let i = 0; i < base64.length; i += 4) {\n\t\tconst c0 = B64_LOOKUP[base64.charCodeAt(i)]\n\t\tconst c1 = B64_LOOKUP[base64.charCodeAt(i + 1)]\n\t\tconst c2 = B64_LOOKUP[base64.charCodeAt(i + 2)]\n\t\tconst c3 = B64_LOOKUP[base64.charCodeAt(i + 3)]\n\n\t\tconst bitmap = (c0 << 18) | (c1 << 12) | (c2 << 6) | c3\n\n\t\tbytes[byteIndex++] = (bitmap >> 16) & 255\n\t\tbytes[byteIndex++] = (bitmap >> 8) & 255\n\t\tbytes[byteIndex++] = bitmap & 255\n\t}\n\n\treturn bytes\n}\n\nfunction nativeUint8ArrayToBase64(uint8Array: Uint8Array): string {\n\treturn uint8Array.toBase64!()\n}\n\n/** @internal */\nexport function fallbackUint8ArrayToBase64(uint8Array: Uint8Array): string {\n\tassert(uint8Array.length % 3 === 0, 'Uint8Array length must be a multiple of 3')\n\tlet result = ''\n\n\t// Process bytes in groups of 3 -> 4 base64 chars\n\tfor (let i = 0; i < uint8Array.length; i += 3) {\n\t\tconst byte1 = uint8Array[i]\n\t\tconst byte2 = uint8Array[i + 1]\n\t\tconst byte3 = uint8Array[i + 2]\n\n\t\tconst bitmap = (byte1 << 16) | (byte2 << 8) | byte3\n\t\tresult +=\n\t\t\tBASE64_CHARS[(bitmap >> 18) & 63] +\n\t\t\tBASE64_CHARS[(bitmap >> 12) & 63] +\n\t\t\tBASE64_CHARS[(bitmap >> 6) & 63] +\n\t\t\tBASE64_CHARS[bitmap & 63]\n\t}\n\n\treturn result\n}\n\n/**\n * Convert a Uint8Array to base64.\n * Processes bytes in groups of 3 to produce 4 base64 characters.\n *\n * @internal\n */\nconst uint8ArrayToBase64 =\n\ttypeof Uint8Array.prototype.toBase64 === 'function'\n\t\t? nativeUint8ArrayToBase64\n\t\t: fallbackUint8ArrayToBase64\n\n/**\n * Convert a base64 string to Uint8Array.\n *\n * @internal\n */\nconst base64ToUint8Array =\n\ttypeof Uint8Array.fromBase64 === 'function'\n\t\t? nativeBase64ToUint8Array\n\t\t: fallbackBase64ToUint8Array\n\n/**\n * Convert Float16 bits to a number using optimized lookup tables.\n * Handles normal numbers, subnormal numbers, zero, infinity, and NaN.\n *\n * @param bits - The 16-bit Float16 value to decode\n * @returns The decoded number value\n * @internal\n */\nexport function float16BitsToNumber(bits: number): number {\n\tconst sign = bits >> 15\n\tconst exp = (bits >> 10) & 0x1f\n\tconst frac = bits & 0x3ff\n\n\tif (exp === 0) {\n\t\t// Subnormal or zero - rare case\n\t\treturn sign ? -frac * POW2_SUBNORMAL : frac * POW2_SUBNORMAL\n\t}\n\tif (exp === 31) {\n\t\t// Infinity or NaN - very rare\n\t\treturn frac ? NaN : sign ? -Infinity : Infinity\n\t}\n\t// Normal case - two table lookups, one multiply, no division\n\tconst magnitude = POW2[exp] * MANTISSA[frac]\n\treturn sign ? -magnitude : magnitude\n}\n\n/**\n * Convert a number to Float16 bits.\n * Handles normal numbers, subnormal numbers, zero, infinity, and NaN.\n *\n * @param value - The number to encode as Float16\n * @returns The 16-bit Float16 representation of the number\n * @internal\n */\nexport function numberToFloat16Bits(value: number): number {\n\tif (value === 0) return Object.is(value, -0) ? 0x8000 : 0\n\tif (!Number.isFinite(value)) {\n\t\tif (Number.isNaN(value)) return 0x7e00\n\t\treturn value > 0 ? 0x7c00 : 0xfc00\n\t}\n\n\tconst sign = value < 0 ? 1 : 0\n\tvalue = Math.abs(value)\n\n\t// Find exponent and mantissa\n\tconst exp = Math.floor(Math.log2(value))\n\tlet expBiased = exp + 15\n\n\tif (expBiased >= 31) {\n\t\t// Overflow to infinity\n\t\treturn (sign << 15) | 0x7c00\n\t}\n\tif (expBiased <= 0) {\n\t\t// Subnormal or underflow\n\t\tconst frac = Math.round(value * Math.pow(2, 14) * 1024)\n\t\treturn (sign << 15) | (frac & 0x3ff)\n\t}\n\n\t// Normal number\n\tconst mantissa = value / Math.pow(2, exp) - 1\n\tlet frac = Math.round(mantissa * 1024)\n\n\t// Handle rounding overflow: if frac rounds to 1024, increment exponent\n\tif (frac >= 1024) {\n\t\tfrac = 0\n\t\texpBiased++\n\t\tif (expBiased >= 31) {\n\t\t\t// Overflow to infinity\n\t\t\treturn (sign << 15) | 0x7c00\n\t\t}\n\t}\n\n\treturn (sign << 15) | (expBiased << 10) | frac\n}\n\n/**\n * Utilities for encoding and decoding points using base64 and Float16 encoding.\n * Provides functions for converting between VecModel arrays and compact base64 strings,\n * as well as individual point encoding/decoding operations.\n *\n * @public\n */\nexport class b64Vecs {\n\t/**\n\t * Encode a single point (x, y, z) to 8 base64 characters using legacy Float16 encoding.\n\t * Each coordinate is encoded as a Float16 value, resulting in 6 bytes total.\n\t *\n\t * @param x - The x coordinate\n\t * @param y - The y coordinate\n\t * @param z - The z coordinate\n\t * @returns An 8-character base64 string representing the point\n\t * @internal\n\t */\n\tstatic _legacyEncodePoint(x: number, y: number, z: number): string {\n\t\tconst buffer = new Uint8Array(6)\n\t\tconst dataView = new DataView(buffer.buffer)\n\n\t\tsetFloat16(dataView, 0, x)\n\t\tsetFloat16(dataView, 2, y)\n\t\tsetFloat16(dataView, 4, z)\n\n\t\treturn uint8ArrayToBase64(buffer)\n\t}\n\n\t/**\n\t * Convert an array of VecModels to a base64 string using legacy Float16 encoding.\n\t * Uses Float16 encoding for each coordinate (x, y, z). If a point's z value is\n\t * undefined, it defaults to 0.5.\n\t *\n\t * @param points - An array of VecModel objects to encode\n\t * @returns A base64-encoded string containing all points\n\t * @internal Used only for migrations from legacy format\n\t */\n\tstatic _legacyEncodePoints(points: VecModel[]): string {\n\t\tif (points.length === 0) return ''\n\n\t\t// 3 Float16s per point = 6 bytes per point\n\t\tconst buffer = new Uint8Array(points.length * 6)\n\t\tconst dataView = new DataView(buffer.buffer)\n\n\t\tfor (let i = 0; i < points.length; i++) {\n\t\t\tconst p = points[i]\n\t\t\tconst offset = i * 6\n\t\t\tsetFloat16(dataView, offset, p.x)\n\t\t\tsetFloat16(dataView, offset + 2, p.y)\n\t\t\tsetFloat16(dataView, offset + 4, p.z ?? 0.5)\n\t\t}\n\n\t\treturn uint8ArrayToBase64(buffer)\n\t}\n\n\t/**\n\t * Convert a legacy base64 string back to an array of VecModels.\n\t * Decodes Float16-encoded coordinates (x, y, z) from the base64 string.\n\t *\n\t * @param base64 - The base64-encoded string containing point data\n\t * @returns An array of VecModel objects decoded from the string\n\t * @internal Used only for migrations from legacy format\n\t */\n\tstatic _legacyDecodePoints(base64: string): VecModel[] {\n\t\tconst bytes = base64ToUint8Array(base64)\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\t\tconst result: VecModel[] = []\n\t\tfor (let offset = 0; offset < bytes.length; offset += 6) {\n\t\t\tresult.push({\n\t\t\t\tx: getFloat16(dataView, offset),\n\t\t\t\ty: getFloat16(dataView, offset + 2),\n\t\t\t\tz: getFloat16(dataView, offset + 4),\n\t\t\t})\n\t\t}\n\t\treturn result\n\t}\n\n\t/**\n\t * Encode an array of VecModels using delta encoding for improved precision.\n\t * The first point is stored as Float32 (high precision for absolute position),\n\t * subsequent points are stored as Float16 deltas from the previous point.\n\t * This provides full precision for the starting position and excellent precision\n\t * for deltas between consecutive points (which are typically small values).\n\t *\n\t * Format:\n\t * - First point: 3 Float32 values = 12 bytes = 16 base64 chars\n\t * - Delta points: 3 Float16 values each = 6 bytes = 8 base64 chars each\n\t *\n\t * @param points - An array of VecModel objects to encode\n\t * @returns A base64-encoded string containing delta-encoded points\n\t * @public\n\t */\n\tstatic encodePoints(points: VecModel[]): string {\n\t\tif (points.length === 0) return ''\n\n\t\t// First point: 3 Float32s = 12 bytes\n\t\t// Remaining points: 3 Float16s each = 6 bytes each\n\t\tconst firstPointBytes = 12\n\t\tconst deltaBytes = (points.length - 1) * 6\n\t\tconst totalBytes = firstPointBytes + deltaBytes\n\n\t\tconst buffer = new Uint8Array(totalBytes)\n\t\tconst dataView = new DataView(buffer.buffer)\n\n\t\t// First point is stored as Float32 for full precision\n\t\tconst first = points[0]\n\t\tdataView.setFloat32(0, first.x, true) // little-endian\n\t\tdataView.setFloat32(4, first.y, true)\n\t\tdataView.setFloat32(8, first.z ?? 0.5, true)\n\n\t\t// Subsequent points are Float16 deltas from the previous point\n\t\tlet prevX = first.x\n\t\tlet prevY = first.y\n\t\tlet prevZ = first.z ?? 0.5\n\n\t\tfor (let i = 1; i < points.length; i++) {\n\t\t\tconst p = points[i]\n\t\t\tconst z = p.z ?? 0.5\n\n\t\t\tconst offset = firstPointBytes + (i - 1) * 6\n\t\t\tsetFloat16(dataView, offset, p.x - prevX)\n\t\t\tsetFloat16(dataView, offset + 2, p.y - prevY)\n\t\t\tsetFloat16(dataView, offset + 4, z - prevZ)\n\n\t\t\tprevX = p.x\n\t\t\tprevY = p.y\n\t\t\tprevZ = z\n\t\t}\n\n\t\treturn uint8ArrayToBase64(buffer)\n\t}\n\n\t/**\n\t * Decode a delta-encoded base64 string back to an array of absolute VecModels.\n\t * The first point is stored as Float32 (high precision), subsequent points are\n\t * Float16 deltas that are accumulated to reconstruct absolute positions.\n\t *\n\t * @param base64 - The base64-encoded string containing delta-encoded point data\n\t * @returns An array of VecModel objects with absolute coordinates\n\t * @public\n\t */\n\tstatic decodePoints(base64: string): VecModel[] {\n\t\tif (base64.length === 0) return []\n\n\t\tconst bytes = base64ToUint8Array(base64)\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\t\tconst result: VecModel[] = []\n\n\t\t// First point is Float32 (12 bytes)\n\t\tlet x = dataView.getFloat32(0, true)\n\t\tlet y = dataView.getFloat32(4, true)\n\t\tlet z = dataView.getFloat32(8, true)\n\t\tresult.push({ x, y, z })\n\n\t\t// Subsequent points are Float16 deltas - accumulate to get absolute positions\n\t\tconst firstPointBytes = 12\n\t\tfor (let offset = firstPointBytes; offset < bytes.length; offset += 6) {\n\t\t\tx += getFloat16(dataView, offset)\n\t\t\ty += getFloat16(dataView, offset + 2)\n\t\t\tz += getFloat16(dataView, offset + 4)\n\t\t\tresult.push({ x, y, z })\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Get the first point from a delta-encoded base64 string.\n\t * The first point is stored as Float32 for full precision.\n\t *\n\t * @param b64Points - The delta-encoded base64 string\n\t * @returns The first point as a VecModel, or null if the string is too short\n\t * @public\n\t */\n\tstatic decodeFirstPoint(b64Points: string): VecModel | null {\n\t\t// First point needs 16 base64 chars (12 bytes as Float32)\n\t\tif (b64Points.length < FIRST_POINT_B64_LENGTH) return null\n\n\t\tconst bytes = base64ToUint8Array(b64Points.slice(0, FIRST_POINT_B64_LENGTH))\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\n\t\treturn {\n\t\t\tx: dataView.getFloat32(0, true),\n\t\t\ty: dataView.getFloat32(4, true),\n\t\t\tz: dataView.getFloat32(8, true),\n\t\t}\n\t}\n\n\t/**\n\t * Get the last point from a delta-encoded base64 string.\n\t * Requires decoding all points to accumulate deltas.\n\t *\n\t * @param b64Points - The delta-encoded base64 string\n\t * @returns The last point as a VecModel, or null if the string is too short\n\t * @public\n\t */\n\tstatic decodeLastPoint(b64Points: string): VecModel | null {\n\t\tif (b64Points.length < FIRST_POINT_B64_LENGTH) return null\n\n\t\tconst bytes = base64ToUint8Array(b64Points)\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\n\t\t// Start with first point (Float32)\n\t\tlet x = dataView.getFloat32(0, true)\n\t\tlet y = dataView.getFloat32(4, true)\n\t\tlet z = dataView.getFloat32(8, true)\n\n\t\t// Accumulate all Float16 deltas to get the last point\n\t\tconst firstPointBytes = 12\n\t\tfor (let offset = firstPointBytes; offset < bytes.length; offset += 6) {\n\t\t\tx += getFloat16(dataView, offset)\n\t\t\ty += getFloat16(dataView, offset + 2)\n\t\t\tz += getFloat16(dataView, offset + 4)\n\t\t}\n\n\t\treturn { x, y, z }\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { VecModel } from './geometry-types'\n\n// Each point = 3 Float16s = 6 bytes = 8 base64 chars (legacy format)\nconst _POINT_B64_LENGTH = 8\n\n// First point in delta encoding = 3 Float32s = 12 bytes = 16 base64 chars\nconst FIRST_POINT_B64_LENGTH = 16\n\n// First point in 2D delta encoding = 2 Float32s = 8 bytes = 12 base64 chars (incl. padding)\nconst FIRST_POINT_2D_B64_LENGTH = 12\n\n// Pressure value supplied when decoding non-pressure (2D) paths\nconst DEFAULT_PRESSURE = 0.5\n\n/** Draw segment path encoded with 2 dimensions, XY \u2014 the constant pressure Z is dropped. @public */\nexport const DIM_2D = 2\n/** Draw segment path encoded with 3 dimensions, XYZ. @public */\nexport const DIM_3D = 3\n\n// O(1) lookup table for base64 decoding (maps char code -> 6-bit value)\nconst BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nconst B64_LOOKUP = new Uint8Array(128)\nfor (let i = 0; i < 64; i++) {\n\tB64_LOOKUP[BASE64_CHARS.charCodeAt(i)] = i\n}\n\n// Mask for one base64 sextet: the low 6 bits select an index into BASE64_CHARS (0\u201363).\nconst SIX_BIT_MASK = 0x3f\n// '=' padding character, appended on encode so the output length is a multiple of 4.\nconst PADDING_CHAR_CODE = '='.charCodeAt(0)\n\n// Precomputed powers of 2 for Float16 exponents (exp - 15, so indices 0-30 map to 2^-15 to 2^15)\nconst POW2 = new Float64Array(31)\nfor (let i = 0; i < 31; i++) {\n\tPOW2[i] = Math.pow(2, i - 15)\n}\nconst POW2_SUBNORMAL = Math.pow(2, -14) / 1024 // For subnormal numbers\n\n// Precomputed mantissa values: 1 + frac/1024 for all 1024 possible frac values\n// Avoids division in hot path\nconst MANTISSA = new Float64Array(1024)\nfor (let i = 0; i < 1024; i++) {\n\tMANTISSA[i] = 1 + i / 1024\n}\n\ndeclare global {\n\tinterface Uint8Array {\n\t\ttoBase64?(): string\n\t}\n\tinterface Uint8ArrayConstructor {\n\t\tfromBase64?(base64: string): Uint8Array\n\t}\n}\n\nfunction nativeGetFloat16(dataView: DataView, offset: number): number {\n\treturn (dataView as any).getFloat16(offset, true)\n}\nfunction fallbackGetFloat16(dataView: DataView, offset: number): number {\n\treturn float16BitsToNumber(dataView.getUint16(offset, true))\n}\n\nconst getFloat16 =\n\ttypeof (DataView.prototype as any).getFloat16 === 'function'\n\t\t? nativeGetFloat16\n\t\t: fallbackGetFloat16\n\nfunction nativeSetFloat16(dataView: DataView, offset: number, value: number): void {\n\t;(dataView as any).setFloat16(offset, value, true)\n}\nfunction fallbackSetFloat16(dataView: DataView, offset: number, value: number): void {\n\tdataView.setUint16(offset, numberToFloat16Bits(value), true)\n}\n\nconst setFloat16 =\n\ttypeof (DataView.prototype as any).setFloat16 === 'function'\n\t\t? nativeSetFloat16\n\t\t: fallbackSetFloat16\n\nfunction nativeBase64ToUint8Array(base64: string): Uint8Array {\n\treturn Uint8Array.fromBase64!(base64)\n}\n\n/** @internal */\nexport function fallbackBase64ToUint8Array(base64: string): Uint8Array {\n\t// Strip up to 2 '=' padding characters to determine the real byte count.\n\t// The 2D point layout (8 + 4(n-1) bytes) is not a multiple of 3, so encoded\n\t// paths can carry padding the original multiple-of-3-only decoder couldn't read.\n\tconst paddedLength = base64.length\n\tlet padding = 0\n\tif (paddedLength > 0 && base64.charCodeAt(paddedLength - 1) === PADDING_CHAR_CODE) {\n\t\tpadding++\n\t\tif (paddedLength > 1 && base64.charCodeAt(paddedLength - 2) === PADDING_CHAR_CODE) {\n\t\t\tpadding++\n\t\t}\n\t}\n\tconst numBytes = Math.floor((paddedLength * 3) / 4) - padding\n\tconst bytes = new Uint8Array(numBytes)\n\tlet byteIndex = 0\n\n\t// The reverse of encoding: each 4 chars are 4 six-bit values that pack back into\n\t// one 24-bit number, which we then read out as 3 bytes (& 255 keeps one byte).\n\tconst fullGroups = Math.floor((paddedLength - padding) / 4) * 4\n\tfor (let i = 0; i < fullGroups; i += 4) {\n\t\tconst c0 = B64_LOOKUP[base64.charCodeAt(i)]\n\t\tconst c1 = B64_LOOKUP[base64.charCodeAt(i + 1)]\n\t\tconst c2 = B64_LOOKUP[base64.charCodeAt(i + 2)]\n\t\tconst c3 = B64_LOOKUP[base64.charCodeAt(i + 3)]\n\n\t\tconst bitmap = (c0 << 18) | (c1 << 12) | (c2 << 6) | c3\n\n\t\tbytes[byteIndex++] = (bitmap >> 16) & 255 // top byte (bits 23\u201316)\n\t\tbytes[byteIndex++] = (bitmap >> 8) & 255 // middle byte (bits 15\u20138)\n\t\tbytes[byteIndex++] = bitmap & 255 // bottom byte (bits 7\u20130)\n\t}\n\n\t// Final group when padded: 3 valid chars -> 2 bytes, 2 valid chars -> 1 byte.\n\tif (padding === 1) {\n\t\tconst c0 = B64_LOOKUP[base64.charCodeAt(fullGroups)]\n\t\tconst c1 = B64_LOOKUP[base64.charCodeAt(fullGroups + 1)]\n\t\tconst c2 = B64_LOOKUP[base64.charCodeAt(fullGroups + 2)]\n\t\tconst bitmap = (c0 << 18) | (c1 << 12) | (c2 << 6)\n\t\tbytes[byteIndex++] = (bitmap >> 16) & 255\n\t\tbytes[byteIndex++] = (bitmap >> 8) & 255\n\t} else if (padding === 2) {\n\t\tconst c0 = B64_LOOKUP[base64.charCodeAt(fullGroups)]\n\t\tconst c1 = B64_LOOKUP[base64.charCodeAt(fullGroups + 1)]\n\t\tconst bitmap = (c0 << 18) | (c1 << 12)\n\t\tbytes[byteIndex++] = (bitmap >> 16) & 255\n\t}\n\n\treturn bytes\n}\n\nfunction nativeUint8ArrayToBase64(uint8Array: Uint8Array): string {\n\treturn uint8Array.toBase64!()\n}\n\n/** @internal */\nexport function fallbackUint8ArrayToBase64(uint8Array: Uint8Array): string {\n\tconst len = uint8Array.length\n\tconst fullGroups = Math.floor(len / 3) * 3\n\tlet result = ''\n\n\t// base64 represents 3 bytes (24 bits) as 4 characters of 6 bits each. For each\n\t// group of 3 bytes we pack them into one 24-bit number, then read it back out as\n\t// four 6-bit slices and use each slice (a value 0\u201363) to index into the 64-char\n\t// alphabet. `>> n` shifts the wanted slice down to the bottom; SIX_BIT_MASK then\n\t// discards everything above those 6 bits.\n\tfor (let i = 0; i < fullGroups; i += 3) {\n\t\tconst byte1 = uint8Array[i]\n\t\tconst byte2 = uint8Array[i + 1]\n\t\tconst byte3 = uint8Array[i + 2]\n\n\t\tconst bitmap = (byte1 << 16) | (byte2 << 8) | byte3\n\t\tresult +=\n\t\t\tBASE64_CHARS[(bitmap >> 18) & SIX_BIT_MASK] + // bits 23\u201318 (top sextet)\n\t\t\tBASE64_CHARS[(bitmap >> 12) & SIX_BIT_MASK] + // bits 17\u201312\n\t\t\tBASE64_CHARS[(bitmap >> 6) & SIX_BIT_MASK] + // bits 11\u20136\n\t\t\tBASE64_CHARS[bitmap & SIX_BIT_MASK] // bits 5\u20130 (bottom sextet)\n\t}\n\n\t// A trailing 1 or 2 bytes can't fill a whole 4-char group, so we emit only the\n\t// chars their bits cover and pad the rest with '=' to keep the length a multiple\n\t// of 4. Standard base64 \u2014 matches the native API and Node's Buffer, so a path\n\t// encoded by the fallback round-trips on a runtime that decodes with the native one.\n\tconst remaining = len - fullGroups\n\tif (remaining === 1) {\n\t\t// 8 bits \u2192 2 sextets (the 2nd only partly filled), then \"==\"\n\t\tconst bitmap = uint8Array[fullGroups] << 16\n\t\tresult +=\n\t\t\tBASE64_CHARS[(bitmap >> 18) & SIX_BIT_MASK] +\n\t\t\tBASE64_CHARS[(bitmap >> 12) & SIX_BIT_MASK] +\n\t\t\t'=='\n\t} else if (remaining === 2) {\n\t\t// 16 bits \u2192 3 sextets (the 3rd only partly filled), then \"=\"\n\t\tconst bitmap = (uint8Array[fullGroups] << 16) | (uint8Array[fullGroups + 1] << 8)\n\t\tresult +=\n\t\t\tBASE64_CHARS[(bitmap >> 18) & SIX_BIT_MASK] +\n\t\t\tBASE64_CHARS[(bitmap >> 12) & SIX_BIT_MASK] +\n\t\t\tBASE64_CHARS[(bitmap >> 6) & SIX_BIT_MASK] +\n\t\t\t'='\n\t}\n\n\treturn result\n}\n\n/**\n * Convert a Uint8Array to base64.\n * Processes bytes in groups of 3 to produce 4 base64 characters.\n *\n * @internal\n */\nconst uint8ArrayToBase64 =\n\ttypeof Uint8Array.prototype.toBase64 === 'function'\n\t\t? nativeUint8ArrayToBase64\n\t\t: fallbackUint8ArrayToBase64\n\n/**\n * Convert a base64 string to Uint8Array.\n *\n * @internal\n */\nconst base64ToUint8Array =\n\ttypeof Uint8Array.fromBase64 === 'function'\n\t\t? nativeBase64ToUint8Array\n\t\t: fallbackBase64ToUint8Array\n\n/**\n * Convert Float16 bits to a number using optimized lookup tables.\n * Handles normal numbers, subnormal numbers, zero, infinity, and NaN.\n *\n * @param bits - The 16-bit Float16 value to decode\n * @returns The decoded number value\n * @internal\n */\nexport function float16BitsToNumber(bits: number): number {\n\tconst sign = bits >> 15\n\tconst exp = (bits >> 10) & 0x1f\n\tconst frac = bits & 0x3ff\n\n\tif (exp === 0) {\n\t\t// Subnormal or zero - rare case\n\t\treturn sign ? -frac * POW2_SUBNORMAL : frac * POW2_SUBNORMAL\n\t}\n\tif (exp === 31) {\n\t\t// Infinity or NaN - very rare\n\t\treturn frac ? NaN : sign ? -Infinity : Infinity\n\t}\n\t// Normal case - two table lookups, one multiply, no division\n\tconst magnitude = POW2[exp] * MANTISSA[frac]\n\treturn sign ? -magnitude : magnitude\n}\n\n/**\n * Convert a number to Float16 bits.\n * Handles normal numbers, subnormal numbers, zero, infinity, and NaN.\n *\n * @param value - The number to encode as Float16\n * @returns The 16-bit Float16 representation of the number\n * @internal\n */\nexport function numberToFloat16Bits(value: number): number {\n\tif (value === 0) return Object.is(value, -0) ? 0x8000 : 0\n\tif (!Number.isFinite(value)) {\n\t\tif (Number.isNaN(value)) return 0x7e00\n\t\treturn value > 0 ? 0x7c00 : 0xfc00\n\t}\n\n\tconst sign = value < 0 ? 1 : 0\n\tvalue = Math.abs(value)\n\n\t// Find exponent and mantissa\n\tconst exp = Math.floor(Math.log2(value))\n\tlet expBiased = exp + 15\n\n\tif (expBiased >= 31) {\n\t\t// Overflow to infinity\n\t\treturn (sign << 15) | 0x7c00\n\t}\n\tif (expBiased <= 0) {\n\t\t// Subnormal or underflow\n\t\tconst frac = Math.round(value * Math.pow(2, 14) * 1024)\n\t\treturn (sign << 15) | (frac & 0x3ff)\n\t}\n\n\t// Normal number\n\tconst mantissa = value / Math.pow(2, exp) - 1\n\tlet frac = Math.round(mantissa * 1024)\n\n\t// Handle rounding overflow: if frac rounds to 1024, increment exponent\n\tif (frac >= 1024) {\n\t\tfrac = 0\n\t\texpBiased++\n\t\tif (expBiased >= 31) {\n\t\t\t// Overflow to infinity\n\t\t\treturn (sign << 15) | 0x7c00\n\t\t}\n\t}\n\n\treturn (sign << 15) | (expBiased << 10) | frac\n}\n\n/**\n * Utilities for encoding and decoding points using base64 and Float16 encoding.\n * Provides functions for converting between VecModel arrays and compact base64 strings,\n * as well as individual point encoding/decoding operations.\n *\n * @public\n */\nexport class b64Vecs {\n\t/**\n\t * Encode a single point (x, y, z) to 8 base64 characters using legacy Float16 encoding.\n\t * Each coordinate is encoded as a Float16 value, resulting in 6 bytes total.\n\t *\n\t * @param x - The x coordinate\n\t * @param y - The y coordinate\n\t * @param z - The z coordinate\n\t * @returns An 8-character base64 string representing the point\n\t * @internal\n\t */\n\tstatic _legacyEncodePoint(x: number, y: number, z: number): string {\n\t\tconst buffer = new Uint8Array(6)\n\t\tconst dataView = new DataView(buffer.buffer)\n\n\t\tsetFloat16(dataView, 0, x)\n\t\tsetFloat16(dataView, 2, y)\n\t\tsetFloat16(dataView, 4, z)\n\n\t\treturn uint8ArrayToBase64(buffer)\n\t}\n\n\t/**\n\t * Convert an array of VecModels to a base64 string using legacy Float16 encoding.\n\t * Uses Float16 encoding for each coordinate (x, y, z). If a point's z value is\n\t * undefined, it defaults to 0.5.\n\t *\n\t * @param points - An array of VecModel objects to encode\n\t * @returns A base64-encoded string containing all points\n\t * @internal Used only for migrations from legacy format\n\t */\n\tstatic _legacyEncodePoints(points: VecModel[]): string {\n\t\tif (points.length === 0) return ''\n\n\t\t// 3 Float16s per point = 6 bytes per point\n\t\tconst buffer = new Uint8Array(points.length * 6)\n\t\tconst dataView = new DataView(buffer.buffer)\n\n\t\tfor (let i = 0; i < points.length; i++) {\n\t\t\tconst p = points[i]\n\t\t\tconst offset = i * 6\n\t\t\tsetFloat16(dataView, offset, p.x)\n\t\t\tsetFloat16(dataView, offset + 2, p.y)\n\t\t\tsetFloat16(dataView, offset + 4, p.z ?? 0.5)\n\t\t}\n\n\t\treturn uint8ArrayToBase64(buffer)\n\t}\n\n\t/**\n\t * Convert a legacy base64 string back to an array of VecModels.\n\t * Decodes Float16-encoded coordinates (x, y, z) from the base64 string.\n\t *\n\t * @param base64 - The base64-encoded string containing point data\n\t * @returns An array of VecModel objects decoded from the string\n\t * @internal Used only for migrations from legacy format\n\t */\n\tstatic _legacyDecodePoints(base64: string): VecModel[] {\n\t\tconst bytes = base64ToUint8Array(base64)\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\t\tconst result: VecModel[] = []\n\t\tfor (let offset = 0; offset < bytes.length; offset += 6) {\n\t\t\tresult.push({\n\t\t\t\tx: getFloat16(dataView, offset),\n\t\t\t\ty: getFloat16(dataView, offset + 2),\n\t\t\t\tz: getFloat16(dataView, offset + 4),\n\t\t\t})\n\t\t}\n\t\treturn result\n\t}\n\n\t/**\n\t * Encode an array of VecModels using delta encoding for improved precision.\n\t * The first point is stored as Float32 (high precision for absolute position),\n\t * subsequent points are stored as Float16 deltas from the previous point.\n\t * This provides full precision for the starting position and excellent precision\n\t * for deltas between consecutive points (which are typically small values).\n\t *\n\t * Format:\n\t * - First point: 3 Float32 values = 12 bytes = 16 base64 chars\n\t * - Delta points: 3 Float16 values each = 6 bytes = 8 base64 chars each\n\t *\n\t * @param points - An array of VecModel objects to encode\n\t * @param dim - Encoding dimension; `2` routes through the 2D variant (drops z), `3` (default) keeps x, y, z\n\t * @returns A base64-encoded string containing delta-encoded points\n\t * @public\n\t */\n\tstatic encodePoints(points: VecModel[], dim?: 2 | 3): string {\n\t\tif (dim === DIM_2D) return b64Vecs.encodePoints2D(points)\n\t\tif (points.length === 0) return ''\n\n\t\t// First point: 3 Float32s = 12 bytes\n\t\t// Remaining points: 3 Float16s each = 6 bytes each\n\t\tconst firstPointBytes = 12\n\t\tconst deltaBytes = (points.length - 1) * 6\n\t\tconst totalBytes = firstPointBytes + deltaBytes\n\n\t\tconst buffer = new Uint8Array(totalBytes)\n\t\tconst dataView = new DataView(buffer.buffer)\n\n\t\t// First point is stored as Float32 for full precision\n\t\tconst first = points[0]\n\t\tdataView.setFloat32(0, first.x, true) // little-endian\n\t\tdataView.setFloat32(4, first.y, true)\n\t\tdataView.setFloat32(8, first.z ?? 0.5, true)\n\n\t\t// Subsequent points are Float16 deltas from the previous point\n\t\tlet prevX = first.x\n\t\tlet prevY = first.y\n\t\tlet prevZ = first.z ?? 0.5\n\n\t\tfor (let i = 1; i < points.length; i++) {\n\t\t\tconst p = points[i]\n\t\t\tconst z = p.z ?? 0.5\n\n\t\t\tconst offset = firstPointBytes + (i - 1) * 6\n\t\t\tsetFloat16(dataView, offset, p.x - prevX)\n\t\t\tsetFloat16(dataView, offset + 2, p.y - prevY)\n\t\t\tsetFloat16(dataView, offset + 4, z - prevZ)\n\n\t\t\tprevX = p.x\n\t\t\tprevY = p.y\n\t\t\tprevZ = z\n\t\t}\n\n\t\treturn uint8ArrayToBase64(buffer)\n\t}\n\n\t/**\n\t * Decode a delta-encoded base64 string back to an array of absolute VecModels.\n\t * The first point is stored as Float32 (high precision), subsequent points are\n\t * Float16 deltas that are accumulated to reconstruct absolute positions.\n\t *\n\t * @param base64 - The base64-encoded string containing delta-encoded point data\n\t * @param dim - Encoding dimension; `2` expects x/y only (z supplied as 0.5), `3` (default) expects x/y/z\n\t * @returns An array of VecModel objects with absolute coordinates\n\t * @public\n\t */\n\tstatic decodePoints(base64: string, dim?: 2 | 3): VecModel[] {\n\t\tif (dim === DIM_2D) return b64Vecs.decodePoints2D(base64)\n\t\tif (base64.length === 0) return []\n\n\t\tconst bytes = base64ToUint8Array(base64)\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\t\tconst result: VecModel[] = []\n\n\t\t// First point is Float32 (12 bytes)\n\t\tlet x = dataView.getFloat32(0, true)\n\t\tlet y = dataView.getFloat32(4, true)\n\t\tlet z = dataView.getFloat32(8, true)\n\t\tresult.push({ x, y, z })\n\n\t\t// Subsequent points are Float16 deltas - accumulate to get absolute positions\n\t\tconst firstPointBytes = 12\n\t\tfor (let offset = firstPointBytes; offset < bytes.length; offset += 6) {\n\t\t\tx += getFloat16(dataView, offset)\n\t\t\ty += getFloat16(dataView, offset + 2)\n\t\t\tz += getFloat16(dataView, offset + 4)\n\t\t\tresult.push({ x, y, z })\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Get the first point from a delta-encoded base64 string.\n\t * The first point is stored as Float32 for full precision.\n\t *\n\t * @param b64Points - The delta-encoded base64 string\n\t * @param dim - Encoding dimension; `2` expects x/y only (z supplied as 0.5), `3` (default) expects x/y/z\n\t * @returns The first point as a VecModel, or null if the string is too short\n\t * @public\n\t */\n\tstatic decodeFirstPoint(b64Points: string, dim?: 2 | 3): VecModel | null {\n\t\tif (dim === DIM_2D) return b64Vecs.decodeFirstPoint2D(b64Points)\n\t\t// First point needs 16 base64 chars (12 bytes as Float32)\n\t\tif (b64Points.length < FIRST_POINT_B64_LENGTH) return null\n\n\t\tconst bytes = base64ToUint8Array(b64Points.slice(0, FIRST_POINT_B64_LENGTH))\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\n\t\treturn {\n\t\t\tx: dataView.getFloat32(0, true),\n\t\t\ty: dataView.getFloat32(4, true),\n\t\t\tz: dataView.getFloat32(8, true),\n\t\t}\n\t}\n\n\t/**\n\t * Get the last point from a delta-encoded base64 string.\n\t * Requires decoding all points to accumulate deltas.\n\t *\n\t * @param b64Points - The delta-encoded base64 string\n\t * @param dim - Encoding dimension; `2` expects x/y only (z supplied as 0.5), `3` (default) expects x/y/z\n\t * @returns The last point as a VecModel, or null if the string is too short\n\t * @public\n\t */\n\tstatic decodeLastPoint(b64Points: string, dim?: 2 | 3): VecModel | null {\n\t\tif (dim === DIM_2D) return b64Vecs.decodeLastPoint2D(b64Points)\n\t\tif (b64Points.length < FIRST_POINT_B64_LENGTH) return null\n\n\t\tconst bytes = base64ToUint8Array(b64Points)\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\n\t\t// Start with first point (Float32)\n\t\tlet x = dataView.getFloat32(0, true)\n\t\tlet y = dataView.getFloat32(4, true)\n\t\tlet z = dataView.getFloat32(8, true)\n\n\t\t// Accumulate all Float16 deltas to get the last point\n\t\tconst firstPointBytes = 12\n\t\tfor (let offset = firstPointBytes; offset < bytes.length; offset += 6) {\n\t\t\tx += getFloat16(dataView, offset)\n\t\t\ty += getFloat16(dataView, offset + 2)\n\t\t\tz += getFloat16(dataView, offset + 4)\n\t\t}\n\n\t\treturn { x, y, z }\n\t}\n\n\t/**\n\t * Encode an array of VecModels as 2D delta-encoded points, dropping z entirely.\n\t * Use for draw shapes from devices that don't report pressure, where z is a\n\t * constant 0.5 and storing it wastes ~33% of per-point bytes.\n\t *\n\t * Format:\n\t * - First point: 2 Float32 values (x, y) = 8 bytes\n\t * - Delta points: 2 Float16 values (dx, dy) = 4 bytes each\n\t *\n\t * @param points - An array of VecModel objects to encode (z is discarded)\n\t * @returns A base64-encoded string containing 2D delta-encoded points\n\t * @public\n\t */\n\tstatic encodePoints2D(points: VecModel[]): string {\n\t\tif (points.length === 0) return ''\n\n\t\tconst firstPointBytes = 8\n\t\tconst deltaBytes = (points.length - 1) * 4\n\t\tconst buffer = new Uint8Array(firstPointBytes + deltaBytes)\n\t\tconst dataView = new DataView(buffer.buffer)\n\n\t\tconst first = points[0]\n\t\tdataView.setFloat32(0, first.x, true)\n\t\tdataView.setFloat32(4, first.y, true)\n\n\t\tlet prevX = first.x\n\t\tlet prevY = first.y\n\n\t\tfor (let i = 1; i < points.length; i++) {\n\t\t\tconst p = points[i]\n\t\t\tconst offset = firstPointBytes + (i - 1) * 4\n\t\t\tsetFloat16(dataView, offset, p.x - prevX)\n\t\t\tsetFloat16(dataView, offset + 2, p.y - prevY)\n\t\t\tprevX = p.x\n\t\t\tprevY = p.y\n\t\t}\n\n\t\treturn uint8ArrayToBase64(buffer)\n\t}\n\n\t/**\n\t * Decode a 2D delta-encoded base64 string back to an array of absolute VecModels.\n\t * The z coordinate is always set to 0.5 (the default pressure value) so downstream\n\t * consumers don't need a separate code path.\n\t *\n\t * @param base64 - The base64-encoded string containing 2D delta-encoded point data\n\t * @returns An array of VecModel objects with absolute (x, y) and z = 0.5\n\t * @public\n\t */\n\tstatic decodePoints2D(base64: string): VecModel[] {\n\t\tif (base64.length === 0) return []\n\n\t\tconst bytes = base64ToUint8Array(base64)\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\t\tconst result: VecModel[] = []\n\n\t\tlet x = dataView.getFloat32(0, true)\n\t\tlet y = dataView.getFloat32(4, true)\n\t\tresult.push({ x, y, z: DEFAULT_PRESSURE })\n\n\t\tconst firstPointBytes = 8\n\t\tfor (let offset = firstPointBytes; offset < bytes.length; offset += 4) {\n\t\t\tx += getFloat16(dataView, offset)\n\t\t\ty += getFloat16(dataView, offset + 2)\n\t\t\tresult.push({ x, y, z: DEFAULT_PRESSURE })\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Get the first point from a 2D delta-encoded base64 string.\n\t *\n\t * @param b64Points - The 2D delta-encoded base64 string\n\t * @returns The first point with z = 0.5, or null if the string is too short\n\t * @public\n\t */\n\tstatic decodeFirstPoint2D(b64Points: string): VecModel | null {\n\t\tif (b64Points.length < FIRST_POINT_2D_B64_LENGTH) return null\n\n\t\tconst bytes = base64ToUint8Array(b64Points.slice(0, FIRST_POINT_2D_B64_LENGTH))\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\n\t\treturn {\n\t\t\tx: dataView.getFloat32(0, true),\n\t\t\ty: dataView.getFloat32(4, true),\n\t\t\tz: DEFAULT_PRESSURE,\n\t\t}\n\t}\n\n\t/**\n\t * Get the last point from a 2D delta-encoded base64 string.\n\t * Requires decoding all points to accumulate deltas.\n\t *\n\t * @param b64Points - The 2D delta-encoded base64 string\n\t * @returns The last point with z = 0.5, or null if the string is too short\n\t * @public\n\t */\n\tstatic decodeLastPoint2D(b64Points: string): VecModel | null {\n\t\tif (b64Points.length < FIRST_POINT_2D_B64_LENGTH) return null\n\n\t\tconst bytes = base64ToUint8Array(b64Points)\n\t\tconst dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)\n\n\t\tlet x = dataView.getFloat32(0, true)\n\t\tlet y = dataView.getFloat32(4, true)\n\n\t\tconst firstPointBytes = 8\n\t\tfor (let offset = firstPointBytes; offset < bytes.length; offset += 4) {\n\t\t\tx += getFloat16(dataView, offset)\n\t\t\ty += getFloat16(dataView, offset + 2)\n\t\t}\n\n\t\treturn { x, y, z: DEFAULT_PRESSURE }\n\t}\n\n\t/**\n\t * Whether an encoded path contains only a single point (a \"dot\"), inferred from\n\t * the encoded length without decoding \u2014 cheap enough for the render path.\n\t *\n\t * The single-point length depends on the encoding dimension, so this takes the\n\t * segment's `dim`: a one-point path is `FIRST_POINT_B64_LENGTH` chars (3D) or\n\t * `FIRST_POINT_2D_B64_LENGTH` chars (2D). Keeping this beside the layout constants\n\t * is deliberate \u2014 it is the single source of truth for \"how long is one point\", so\n\t * callers never hard-code a length threshold (which silently breaks when a new\n\t * encoding is added).\n\t *\n\t * @param b64Points - The encoded path string\n\t * @param dim - Encoding dimension; `2` for (x, y), `3` (default) for (x, y, z)\n\t * @returns true if the path encodes exactly one point\n\t * @public\n\t */\n\tstatic isSinglePoint(b64Points: string, dim?: 2 | 3): boolean {\n\t\treturn b64Points.length <= (dim === DIM_2D ? FIRST_POINT_2D_B64_LENGTH : FIRST_POINT_B64_LENGTH)\n\t}\n}\n"],
5
+ "mappings": "AAGA,MAAM,oBAAoB;AAG1B,MAAM,yBAAyB;AAG/B,MAAM,4BAA4B;AAGlC,MAAM,mBAAmB;AAGlB,MAAM,SAAS;AAEf,MAAM,SAAS;AAGtB,MAAM,eAAe;AACrB,MAAM,aAAa,IAAI,WAAW,GAAG;AACrC,SAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC5B,aAAW,aAAa,WAAW,CAAC,CAAC,IAAI;AAC1C;AAGA,MAAM,eAAe;AAErB,MAAM,oBAAoB,IAAI,WAAW,CAAC;AAG1C,MAAM,OAAO,IAAI,aAAa,EAAE;AAChC,SAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC5B,OAAK,CAAC,IAAI,KAAK,IAAI,GAAG,IAAI,EAAE;AAC7B;AACA,MAAM,iBAAiB,KAAK,IAAI,GAAG,GAAG,IAAI;AAI1C,MAAM,WAAW,IAAI,aAAa,IAAI;AACtC,SAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC9B,WAAS,CAAC,IAAI,IAAI,IAAI;AACvB;AAWA,SAAS,iBAAiB,UAAoB,QAAwB;AACrE,SAAQ,SAAiB,WAAW,QAAQ,IAAI;AACjD;AACA,SAAS,mBAAmB,UAAoB,QAAwB;AACvE,SAAO,oBAAoB,SAAS,UAAU,QAAQ,IAAI,CAAC;AAC5D;AAEA,MAAM,aACL,OAAQ,SAAS,UAAkB,eAAe,aAC/C,mBACA;AAEJ,SAAS,iBAAiB,UAAoB,QAAgB,OAAqB;AAClF;AAAC,EAAC,SAAiB,WAAW,QAAQ,OAAO,IAAI;AAClD;AACA,SAAS,mBAAmB,UAAoB,QAAgB,OAAqB;AACpF,WAAS,UAAU,QAAQ,oBAAoB,KAAK,GAAG,IAAI;AAC5D;AAEA,MAAM,aACL,OAAQ,SAAS,UAAkB,eAAe,aAC/C,mBACA;AAEJ,SAAS,yBAAyB,QAA4B;AAC7D,SAAO,WAAW,WAAY,MAAM;AACrC;AAGO,SAAS,2BAA2B,QAA4B;AAItE,QAAM,eAAe,OAAO;AAC5B,MAAI,UAAU;AACd,MAAI,eAAe,KAAK,OAAO,WAAW,eAAe,CAAC,MAAM,mBAAmB;AAClF;AACA,QAAI,eAAe,KAAK,OAAO,WAAW,eAAe,CAAC,MAAM,mBAAmB;AAClF;AAAA,IACD;AAAA,EACD;AACA,QAAM,WAAW,KAAK,MAAO,eAAe,IAAK,CAAC,IAAI;AACtD,QAAM,QAAQ,IAAI,WAAW,QAAQ;AACrC,MAAI,YAAY;AAIhB,QAAM,aAAa,KAAK,OAAO,eAAe,WAAW,CAAC,IAAI;AAC9D,WAAS,IAAI,GAAG,IAAI,YAAY,KAAK,GAAG;AACvC,UAAM,KAAK,WAAW,OAAO,WAAW,CAAC,CAAC;AAC1C,UAAM,KAAK,WAAW,OAAO,WAAW,IAAI,CAAC,CAAC;AAC9C,UAAM,KAAK,WAAW,OAAO,WAAW,IAAI,CAAC,CAAC;AAC9C,UAAM,KAAK,WAAW,OAAO,WAAW,IAAI,CAAC,CAAC;AAE9C,UAAM,SAAU,MAAM,KAAO,MAAM,KAAO,MAAM,IAAK;AAErD,UAAM,WAAW,IAAK,UAAU,KAAM;AACtC,UAAM,WAAW,IAAK,UAAU,IAAK;AACrC,UAAM,WAAW,IAAI,SAAS;AAAA,EAC/B;AAGA,MAAI,YAAY,GAAG;AAClB,UAAM,KAAK,WAAW,OAAO,WAAW,UAAU,CAAC;AACnD,UAAM,KAAK,WAAW,OAAO,WAAW,aAAa,CAAC,CAAC;AACvD,UAAM,KAAK,WAAW,OAAO,WAAW,aAAa,CAAC,CAAC;AACvD,UAAM,SAAU,MAAM,KAAO,MAAM,KAAO,MAAM;AAChD,UAAM,WAAW,IAAK,UAAU,KAAM;AACtC,UAAM,WAAW,IAAK,UAAU,IAAK;AAAA,EACtC,WAAW,YAAY,GAAG;AACzB,UAAM,KAAK,WAAW,OAAO,WAAW,UAAU,CAAC;AACnD,UAAM,KAAK,WAAW,OAAO,WAAW,aAAa,CAAC,CAAC;AACvD,UAAM,SAAU,MAAM,KAAO,MAAM;AACnC,UAAM,WAAW,IAAK,UAAU,KAAM;AAAA,EACvC;AAEA,SAAO;AACR;AAEA,SAAS,yBAAyB,YAAgC;AACjE,SAAO,WAAW,SAAU;AAC7B;AAGO,SAAS,2BAA2B,YAAgC;AAC1E,QAAM,MAAM,WAAW;AACvB,QAAM,aAAa,KAAK,MAAM,MAAM,CAAC,IAAI;AACzC,MAAI,SAAS;AAOb,WAAS,IAAI,GAAG,IAAI,YAAY,KAAK,GAAG;AACvC,UAAM,QAAQ,WAAW,CAAC;AAC1B,UAAM,QAAQ,WAAW,IAAI,CAAC;AAC9B,UAAM,QAAQ,WAAW,IAAI,CAAC;AAE9B,UAAM,SAAU,SAAS,KAAO,SAAS,IAAK;AAC9C,cACC,aAAc,UAAU,KAAM,YAAY;AAAA,IAC1C,aAAc,UAAU,KAAM,YAAY;AAAA,IAC1C,aAAc,UAAU,IAAK,YAAY;AAAA,IACzC,aAAa,SAAS,YAAY;AAAA,EACpC;AAMA,QAAM,YAAY,MAAM;AACxB,MAAI,cAAc,GAAG;AAEpB,UAAM,SAAS,WAAW,UAAU,KAAK;AACzC,cACC,aAAc,UAAU,KAAM,YAAY,IAC1C,aAAc,UAAU,KAAM,YAAY,IAC1C;AAAA,EACF,WAAW,cAAc,GAAG;AAE3B,UAAM,SAAU,WAAW,UAAU,KAAK,KAAO,WAAW,aAAa,CAAC,KAAK;AAC/E,cACC,aAAc,UAAU,KAAM,YAAY,IAC1C,aAAc,UAAU,KAAM,YAAY,IAC1C,aAAc,UAAU,IAAK,YAAY,IACzC;AAAA,EACF;AAEA,SAAO;AACR;AAQA,MAAM,qBACL,OAAO,WAAW,UAAU,aAAa,aACtC,2BACA;AAOJ,MAAM,qBACL,OAAO,WAAW,eAAe,aAC9B,2BACA;AAUG,SAAS,oBAAoB,MAAsB;AACzD,QAAM,OAAO,QAAQ;AACrB,QAAM,MAAO,QAAQ,KAAM;AAC3B,QAAM,OAAO,OAAO;AAEpB,MAAI,QAAQ,GAAG;AAEd,WAAO,OAAO,CAAC,OAAO,iBAAiB,OAAO;AAAA,EAC/C;AACA,MAAI,QAAQ,IAAI;AAEf,WAAO,OAAO,MAAM,OAAO,YAAY;AAAA,EACxC;AAEA,QAAM,YAAY,KAAK,GAAG,IAAI,SAAS,IAAI;AAC3C,SAAO,OAAO,CAAC,YAAY;AAC5B;AAUO,SAAS,oBAAoB,OAAuB;AAC1D,MAAI,UAAU,EAAG,QAAO,OAAO,GAAG,OAAO,EAAE,IAAI,QAAS;AACxD,MAAI,CAAC,OAAO,SAAS,KAAK,GAAG;AAC5B,QAAI,OAAO,MAAM,KAAK,EAAG,QAAO;AAChC,WAAO,QAAQ,IAAI,QAAS;AAAA,EAC7B;AAEA,QAAM,OAAO,QAAQ,IAAI,IAAI;AAC7B,UAAQ,KAAK,IAAI,KAAK;AAGtB,QAAM,MAAM,KAAK,MAAM,KAAK,KAAK,KAAK,CAAC;AACvC,MAAI,YAAY,MAAM;AAEtB,MAAI,aAAa,IAAI;AAEpB,WAAQ,QAAQ,KAAM;AAAA,EACvB;AACA,MAAI,aAAa,GAAG;AAEnB,UAAMA,QAAO,KAAK,MAAM,QAAQ,KAAK,IAAI,GAAG,EAAE,IAAI,IAAI;AACtD,WAAQ,QAAQ,KAAOA,QAAO;AAAA,EAC/B;AAGA,QAAM,WAAW,QAAQ,KAAK,IAAI,GAAG,GAAG,IAAI;AAC5C,MAAI,OAAO,KAAK,MAAM,WAAW,IAAI;AAGrC,MAAI,QAAQ,MAAM;AACjB,WAAO;AACP;AACA,QAAI,aAAa,IAAI;AAEpB,aAAQ,QAAQ,KAAM;AAAA,IACvB;AAAA,EACD;AAEA,SAAQ,QAAQ,KAAO,aAAa,KAAM;AAC3C;AASO,MAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWpB,OAAO,mBAAmB,GAAW,GAAW,GAAmB;AAClE,UAAM,SAAS,IAAI,WAAW,CAAC;AAC/B,UAAM,WAAW,IAAI,SAAS,OAAO,MAAM;AAE3C,eAAW,UAAU,GAAG,CAAC;AACzB,eAAW,UAAU,GAAG,CAAC;AACzB,eAAW,UAAU,GAAG,CAAC;AAEzB,WAAO,mBAAmB,MAAM;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,oBAAoB,QAA4B;AACtD,QAAI,OAAO,WAAW,EAAG,QAAO;AAGhC,UAAM,SAAS,IAAI,WAAW,OAAO,SAAS,CAAC;AAC/C,UAAM,WAAW,IAAI,SAAS,OAAO,MAAM;AAE3C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,YAAM,IAAI,OAAO,CAAC;AAClB,YAAM,SAAS,IAAI;AACnB,iBAAW,UAAU,QAAQ,EAAE,CAAC;AAChC,iBAAW,UAAU,SAAS,GAAG,EAAE,CAAC;AACpC,iBAAW,UAAU,SAAS,GAAG,EAAE,KAAK,GAAG;AAAA,IAC5C;AAEA,WAAO,mBAAmB,MAAM;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,oBAAoB,QAA4B;AACtD,UAAM,QAAQ,mBAAmB,MAAM;AACvC,UAAM,WAAW,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAC9E,UAAM,SAAqB,CAAC;AAC5B,aAAS,SAAS,GAAG,SAAS,MAAM,QAAQ,UAAU,GAAG;AACxD,aAAO,KAAK;AAAA,QACX,GAAG,WAAW,UAAU,MAAM;AAAA,QAC9B,GAAG,WAAW,UAAU,SAAS,CAAC;AAAA,QAClC,GAAG,WAAW,UAAU,SAAS,CAAC;AAAA,MACnC,CAAC;AAAA,IACF;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,OAAO,aAAa,QAAoB,KAAqB;AAC5D,QAAI,QAAQ,OAAQ,QAAO,QAAQ,eAAe,MAAM;AACxD,QAAI,OAAO,WAAW,EAAG,QAAO;AAIhC,UAAM,kBAAkB;AACxB,UAAM,cAAc,OAAO,SAAS,KAAK;AACzC,UAAM,aAAa,kBAAkB;AAErC,UAAM,SAAS,IAAI,WAAW,UAAU;AACxC,UAAM,WAAW,IAAI,SAAS,OAAO,MAAM;AAG3C,UAAM,QAAQ,OAAO,CAAC;AACtB,aAAS,WAAW,GAAG,MAAM,GAAG,IAAI;AACpC,aAAS,WAAW,GAAG,MAAM,GAAG,IAAI;AACpC,aAAS,WAAW,GAAG,MAAM,KAAK,KAAK,IAAI;AAG3C,QAAI,QAAQ,MAAM;AAClB,QAAI,QAAQ,MAAM;AAClB,QAAI,QAAQ,MAAM,KAAK;AAEvB,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,YAAM,IAAI,OAAO,CAAC;AAClB,YAAM,IAAI,EAAE,KAAK;AAEjB,YAAM,SAAS,mBAAmB,IAAI,KAAK;AAC3C,iBAAW,UAAU,QAAQ,EAAE,IAAI,KAAK;AACxC,iBAAW,UAAU,SAAS,GAAG,EAAE,IAAI,KAAK;AAC5C,iBAAW,UAAU,SAAS,GAAG,IAAI,KAAK;AAE1C,cAAQ,EAAE;AACV,cAAQ,EAAE;AACV,cAAQ;AAAA,IACT;AAEA,WAAO,mBAAmB,MAAM;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAO,aAAa,QAAgB,KAAyB;AAC5D,QAAI,QAAQ,OAAQ,QAAO,QAAQ,eAAe,MAAM;AACxD,QAAI,OAAO,WAAW,EAAG,QAAO,CAAC;AAEjC,UAAM,QAAQ,mBAAmB,MAAM;AACvC,UAAM,WAAW,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAC9E,UAAM,SAAqB,CAAC;AAG5B,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,WAAO,KAAK,EAAE,GAAG,GAAG,EAAE,CAAC;AAGvB,UAAM,kBAAkB;AACxB,aAAS,SAAS,iBAAiB,SAAS,MAAM,QAAQ,UAAU,GAAG;AACtE,WAAK,WAAW,UAAU,MAAM;AAChC,WAAK,WAAW,UAAU,SAAS,CAAC;AACpC,WAAK,WAAW,UAAU,SAAS,CAAC;AACpC,aAAO,KAAK,EAAE,GAAG,GAAG,EAAE,CAAC;AAAA,IACxB;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,iBAAiB,WAAmB,KAA8B;AACxE,QAAI,QAAQ,OAAQ,QAAO,QAAQ,mBAAmB,SAAS;AAE/D,QAAI,UAAU,SAAS,uBAAwB,QAAO;AAEtD,UAAM,QAAQ,mBAAmB,UAAU,MAAM,GAAG,sBAAsB,CAAC;AAC3E,UAAM,WAAW,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAE9E,WAAO;AAAA,MACN,GAAG,SAAS,WAAW,GAAG,IAAI;AAAA,MAC9B,GAAG,SAAS,WAAW,GAAG,IAAI;AAAA,MAC9B,GAAG,SAAS,WAAW,GAAG,IAAI;AAAA,IAC/B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,gBAAgB,WAAmB,KAA8B;AACvE,QAAI,QAAQ,OAAQ,QAAO,QAAQ,kBAAkB,SAAS;AAC9D,QAAI,UAAU,SAAS,uBAAwB,QAAO;AAEtD,UAAM,QAAQ,mBAAmB,SAAS;AAC1C,UAAM,WAAW,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAG9E,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AAGnC,UAAM,kBAAkB;AACxB,aAAS,SAAS,iBAAiB,SAAS,MAAM,QAAQ,UAAU,GAAG;AACtE,WAAK,WAAW,UAAU,MAAM;AAChC,WAAK,WAAW,UAAU,SAAS,CAAC;AACpC,WAAK,WAAW,UAAU,SAAS,CAAC;AAAA,IACrC;AAEA,WAAO,EAAE,GAAG,GAAG,EAAE;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,OAAO,eAAe,QAA4B;AACjD,QAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,UAAM,kBAAkB;AACxB,UAAM,cAAc,OAAO,SAAS,KAAK;AACzC,UAAM,SAAS,IAAI,WAAW,kBAAkB,UAAU;AAC1D,UAAM,WAAW,IAAI,SAAS,OAAO,MAAM;AAE3C,UAAM,QAAQ,OAAO,CAAC;AACtB,aAAS,WAAW,GAAG,MAAM,GAAG,IAAI;AACpC,aAAS,WAAW,GAAG,MAAM,GAAG,IAAI;AAEpC,QAAI,QAAQ,MAAM;AAClB,QAAI,QAAQ,MAAM;AAElB,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,YAAM,IAAI,OAAO,CAAC;AAClB,YAAM,SAAS,mBAAmB,IAAI,KAAK;AAC3C,iBAAW,UAAU,QAAQ,EAAE,IAAI,KAAK;AACxC,iBAAW,UAAU,SAAS,GAAG,EAAE,IAAI,KAAK;AAC5C,cAAQ,EAAE;AACV,cAAQ,EAAE;AAAA,IACX;AAEA,WAAO,mBAAmB,MAAM;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,eAAe,QAA4B;AACjD,QAAI,OAAO,WAAW,EAAG,QAAO,CAAC;AAEjC,UAAM,QAAQ,mBAAmB,MAAM;AACvC,UAAM,WAAW,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAC9E,UAAM,SAAqB,CAAC;AAE5B,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,WAAO,KAAK,EAAE,GAAG,GAAG,GAAG,iBAAiB,CAAC;AAEzC,UAAM,kBAAkB;AACxB,aAAS,SAAS,iBAAiB,SAAS,MAAM,QAAQ,UAAU,GAAG;AACtE,WAAK,WAAW,UAAU,MAAM;AAChC,WAAK,WAAW,UAAU,SAAS,CAAC;AACpC,aAAO,KAAK,EAAE,GAAG,GAAG,GAAG,iBAAiB,CAAC;AAAA,IAC1C;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,mBAAmB,WAAoC;AAC7D,QAAI,UAAU,SAAS,0BAA2B,QAAO;AAEzD,UAAM,QAAQ,mBAAmB,UAAU,MAAM,GAAG,yBAAyB,CAAC;AAC9E,UAAM,WAAW,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAE9E,WAAO;AAAA,MACN,GAAG,SAAS,WAAW,GAAG,IAAI;AAAA,MAC9B,GAAG,SAAS,WAAW,GAAG,IAAI;AAAA,MAC9B,GAAG;AAAA,IACJ;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO,kBAAkB,WAAoC;AAC5D,QAAI,UAAU,SAAS,0BAA2B,QAAO;AAEzD,UAAM,QAAQ,mBAAmB,SAAS;AAC1C,UAAM,WAAW,IAAI,SAAS,MAAM,QAAQ,MAAM,YAAY,MAAM,UAAU;AAE9E,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AACnC,QAAI,IAAI,SAAS,WAAW,GAAG,IAAI;AAEnC,UAAM,kBAAkB;AACxB,aAAS,SAAS,iBAAiB,SAAS,MAAM,QAAQ,UAAU,GAAG;AACtE,WAAK,WAAW,UAAU,MAAM;AAChC,WAAK,WAAW,UAAU,SAAS,CAAC;AAAA,IACrC;AAEA,WAAO,EAAE,GAAG,GAAG,GAAG,iBAAiB;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,OAAO,cAAc,WAAmB,KAAsB;AAC7D,WAAO,UAAU,WAAW,QAAQ,SAAS,4BAA4B;AAAA,EAC1E;AACD;",
6
6
  "names": ["frac"]
7
7
  }
@@ -11,6 +11,7 @@ import { cursorValidator } from "../misc/TLCursor.mjs";
11
11
  import { opacityValidator } from "../misc/TLOpacity.mjs";
12
12
  import { scribbleValidator } from "../misc/TLScribble.mjs";
13
13
  import { pageIdValidator } from "./TLPage.mjs";
14
+ import { userIdValidator } from "./TLUser.mjs";
14
15
  const shouldKeyBePreservedBetweenSessions = {
15
16
  // This object defines keys that should be preserved across calls to loadSnapshot()
16
17
  id: false,
@@ -93,7 +94,7 @@ function createInstanceRecordType(stylesById) {
93
94
  typeName: T.literal("instance"),
94
95
  id: idValidator("instance"),
95
96
  currentPageId: pageIdValidator,
96
- followingUserId: T.string.nullable(),
97
+ followingUserId: userIdValidator.nullable(),
97
98
  brush: boxModelValidator.nullable(),
98
99
  opacityForNextShape: opacityValidator,
99
100
  stylesForNextShape: T.object(stylesForNextShapeValidators),
@@ -110,7 +111,7 @@ function createInstanceRecordType(stylesById) {
110
111
  isGridMode: T.boolean,
111
112
  chatMessage: T.string,
112
113
  isChatting: T.boolean,
113
- highlightedUserIds: T.arrayOf(T.string),
114
+ highlightedUserIds: T.arrayOf(userIdValidator),
114
115
  isFocused: T.boolean,
115
116
  devicePixelRatio: T.number,
116
117
  isCoarsePointer: T.boolean,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/records/TLInstance.ts"],
4
- "sourcesContent": ["import {\n\tBaseRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n\tRecordId,\n} from '@tldraw/store'\nimport { filterEntries, JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { BoxModel, boxModelValidator } from '../misc/geometry-types'\nimport { idValidator } from '../misc/id-validator'\nimport { cursorValidator, TLCursor } from '../misc/TLCursor'\nimport { opacityValidator, TLOpacityType } from '../misc/TLOpacity'\nimport { scribbleValidator, TLScribble } from '../misc/TLScribble'\nimport { StyleProp } from '../styles/StyleProp'\nimport { pageIdValidator, TLPageId } from './TLPage'\nimport { TLShapeId } from './TLShape'\n\n/**\n * State that is particular to a single browser tab. The TLInstance record stores\n * all session-specific state including cursor position, selected tools, UI preferences,\n * and temporary interaction state.\n *\n * Each browser tab has exactly one TLInstance record that persists for the duration\n * of the session and tracks the user's current interaction state.\n *\n * @example\n * ```ts\n * const instance: TLInstance = {\n * id: 'instance:instance',\n * typeName: 'instance',\n * currentPageId: 'page:page1',\n * cursor: { type: 'default', rotation: 0 },\n * screenBounds: { x: 0, y: 0, w: 1920, h: 1080 },\n * isFocusMode: false,\n * isGridMode: true\n * }\n * ```\n *\n * @public\n */\nexport interface TLInstance extends BaseRecord<'instance', TLInstanceId> {\n\tcurrentPageId: TLPageId\n\topacityForNextShape: TLOpacityType\n\tstylesForNextShape: Record<string, unknown>\n\tfollowingUserId: string | null\n\thighlightedUserIds: string[]\n\tbrush: BoxModel | null\n\tcursor: TLCursor\n\tscribbles: TLScribble[]\n\tisFocusMode: boolean\n\tisDebugMode: boolean\n\tisToolLocked: boolean\n\texportBackground: boolean\n\tscreenBounds: BoxModel\n\tinsets: boolean[]\n\tzoomBrush: BoxModel | null\n\tchatMessage: string\n\tisChatting: boolean\n\tisPenMode: boolean\n\tisGridMode: boolean\n\tisFocused: boolean\n\tdevicePixelRatio: number\n\t/**\n\t * This is whether the primary input mechanism includes a pointing device of limited accuracy,\n\t * such as a finger on a touchscreen.\n\t */\n\tisCoarsePointer: boolean\n\t/**\n\t * Will be null if the pointer doesn't support hovering (e.g. touch), but true or false\n\t * otherwise\n\t */\n\tisHoveringCanvas: boolean | null\n\topenMenus: string[]\n\tisChangingStyle: boolean\n\tisReadonly: boolean\n\tmeta: JsonObject\n\tduplicateProps: {\n\t\tshapeIds: TLShapeId[]\n\t\toffset: {\n\t\t\tx: number\n\t\t\ty: number\n\t\t}\n\t} | null\n\t/**\n\t * Whether the camera is currently moving or idle. Used to optimize rendering\n\t * and hit-testing during panning/zooming.\n\t */\n\tcameraState: 'idle' | 'moving'\n}\n\n/**\n * Configuration object defining which TLInstance properties should be preserved\n * when loading snapshots across browser sessions. Properties marked as `true`\n * represent user preferences that should persist, while `false` indicates\n * temporary state that should reset.\n *\n * @internal\n */\nexport const shouldKeyBePreservedBetweenSessions = {\n\t// This object defines keys that should be preserved across calls to loadSnapshot()\n\n\tid: false, // meta\n\ttypeName: false, // meta\n\n\tcurrentPageId: false, // does not preserve because who knows if the page still exists\n\topacityForNextShape: false, // does not preserve because it's a temporary state\n\tstylesForNextShape: false, // does not preserve because it's a temporary state\n\tfollowingUserId: false, // does not preserve because it's a temporary state\n\thighlightedUserIds: false, // does not preserve because it's a temporary state\n\tbrush: false, // does not preserve because it's a temporary state\n\tcursor: false, // does not preserve because it's a temporary state\n\tscribbles: false, // does not preserve because it's a temporary state\n\n\tisFocusMode: true, // preserves because it's a user preference\n\tisDebugMode: true, // preserves because it's a user preference\n\tisToolLocked: true, // preserves because it's a user preference\n\texportBackground: true, // preserves because it's a user preference\n\tscreenBounds: true, // preserves because it's capturing the user's screen state\n\tinsets: true, // preserves because it's capturing the user's screen state\n\n\tzoomBrush: false, // does not preserve because it's a temporary state\n\tchatMessage: false, // does not preserve because it's a temporary state\n\tisChatting: false, // does not preserve because it's a temporary state\n\tisPenMode: false, // does not preserve because it's a temporary state\n\n\tisGridMode: true, // preserves because it's a user preference\n\tisFocused: true, // preserves because obviously\n\tdevicePixelRatio: true, // preserves because it captures the user's screen state\n\tisCoarsePointer: true, // preserves because it captures the user's screen state\n\tisHoveringCanvas: false, // does not preserve because it's a temporary state\n\topenMenus: false, // does not preserve because it's a temporary state\n\tisChangingStyle: false, // does not preserve because it's a temporary state\n\tisReadonly: true, // preserves because it's a config option\n\tmeta: false, // does not preserve because who knows what's in there, leave it up to sdk users to save and reinstate\n\tduplicateProps: false, //\n\tcameraState: false, // does not preserve because it's a temporary state\n} as const satisfies { [K in keyof TLInstance]: boolean }\n\n/**\n * Extracts only the properties from a TLInstance that should be preserved\n * between browser sessions, filtering out temporary state.\n *\n * @param val - The TLInstance to filter, or null/undefined\n * @returns A partial TLInstance containing only preservable properties, or null\n *\n * @internal\n */\nexport function pluckPreservingValues(val?: TLInstance | null): null | Partial<TLInstance> {\n\treturn val\n\t\t? (filterEntries(val, (key) => {\n\t\t\t\treturn shouldKeyBePreservedBetweenSessions[key as keyof TLInstance]\n\t\t\t}) as Partial<TLInstance>)\n\t\t: null\n}\n\n/**\n * A unique identifier for TLInstance records.\n *\n * TLInstance IDs are always the constant 'instance:instance' since there\n * is exactly one instance record per browser tab.\n *\n * @public\n */\nexport type TLInstanceId = RecordId<TLInstance>\n\n/**\n * Validator for TLInstanceId values. Ensures the ID follows the correct\n * format for instance records.\n *\n * @example\n * ```ts\n * const isValid = instanceIdValidator.isValid('instance:instance') // true\n * const isValid2 = instanceIdValidator.isValid('invalid') // false\n * ```\n *\n * @public\n */\nexport const instanceIdValidator = idValidator<TLInstanceId>('instance')\n\n/**\n * Creates the record type definition for TLInstance records, including validation\n * and default properties. The function takes a map of available style properties\n * to configure validation for the stylesForNextShape field.\n *\n * @param stylesById - Map of style property IDs to their corresponding StyleProp definitions\n * @returns A configured RecordType for TLInstance records\n *\n * @example\n * ```ts\n * const stylesMap = new Map([['color', DefaultColorStyle]])\n * const InstanceRecordType = createInstanceRecordType(stylesMap)\n *\n * const instance = InstanceRecordType.create({\n * id: 'instance:instance',\n * currentPageId: 'page:page1'\n * })\n * ```\n *\n * @public\n */\nexport function createInstanceRecordType(stylesById: Map<string, StyleProp<unknown>>) {\n\tconst stylesForNextShapeValidators = {} as Record<string, T.Validator<unknown>>\n\tfor (const [id, style] of stylesById) {\n\t\tstylesForNextShapeValidators[id] = T.optional(style)\n\t}\n\n\tconst instanceTypeValidator: T.Validator<TLInstance> = T.model(\n\t\t'instance',\n\t\tT.object({\n\t\t\ttypeName: T.literal('instance'),\n\t\t\tid: idValidator<TLInstanceId>('instance'),\n\t\t\tcurrentPageId: pageIdValidator,\n\t\t\tfollowingUserId: T.string.nullable(),\n\t\t\tbrush: boxModelValidator.nullable(),\n\t\t\topacityForNextShape: opacityValidator,\n\t\t\tstylesForNextShape: T.object(stylesForNextShapeValidators),\n\t\t\tcursor: cursorValidator,\n\t\t\tscribbles: T.arrayOf(scribbleValidator),\n\t\t\tisFocusMode: T.boolean,\n\t\t\tisDebugMode: T.boolean,\n\t\t\tisToolLocked: T.boolean,\n\t\t\texportBackground: T.boolean,\n\t\t\tscreenBounds: boxModelValidator,\n\t\t\tinsets: T.arrayOf(T.boolean),\n\t\t\tzoomBrush: boxModelValidator.nullable(),\n\t\t\tisPenMode: T.boolean,\n\t\t\tisGridMode: T.boolean,\n\t\t\tchatMessage: T.string,\n\t\t\tisChatting: T.boolean,\n\t\t\thighlightedUserIds: T.arrayOf(T.string),\n\t\t\tisFocused: T.boolean,\n\t\t\tdevicePixelRatio: T.number,\n\t\t\tisCoarsePointer: T.boolean,\n\t\t\tisHoveringCanvas: T.boolean.nullable(),\n\t\t\topenMenus: T.arrayOf(T.string),\n\t\t\tisChangingStyle: T.boolean,\n\t\t\tisReadonly: T.boolean,\n\t\t\tmeta: T.jsonValue as T.ObjectValidator<JsonObject>,\n\t\t\tduplicateProps: T.object({\n\t\t\t\tshapeIds: T.arrayOf(idValidator<TLShapeId>('shape')),\n\t\t\t\toffset: T.object({\n\t\t\t\t\tx: T.number,\n\t\t\t\t\ty: T.number,\n\t\t\t\t}),\n\t\t\t}).nullable(),\n\t\t\tcameraState: T.literalEnum('idle', 'moving'),\n\t\t})\n\t)\n\n\treturn createRecordType<TLInstance>('instance', {\n\t\tvalidator: instanceTypeValidator,\n\t\tscope: 'session',\n\t\tephemeralKeys: {\n\t\t\tcurrentPageId: false,\n\t\t\tmeta: false,\n\n\t\t\tfollowingUserId: true,\n\t\t\topacityForNextShape: true,\n\t\t\tstylesForNextShape: true,\n\t\t\tbrush: true,\n\t\t\tcursor: true,\n\t\t\tscribbles: true,\n\t\t\tisFocusMode: true,\n\t\t\tisDebugMode: true,\n\t\t\tisToolLocked: true,\n\t\t\texportBackground: true,\n\t\t\tscreenBounds: true,\n\t\t\tinsets: true,\n\t\t\tzoomBrush: true,\n\t\t\tisPenMode: true,\n\t\t\tisGridMode: true,\n\t\t\tchatMessage: true,\n\t\t\tisChatting: true,\n\t\t\thighlightedUserIds: true,\n\t\t\tisFocused: true,\n\t\t\tdevicePixelRatio: true,\n\t\t\tisCoarsePointer: true,\n\t\t\tisHoveringCanvas: true,\n\t\t\topenMenus: true,\n\t\t\tisChangingStyle: true,\n\t\t\tisReadonly: true,\n\t\t\tduplicateProps: true,\n\t\t\tcameraState: true,\n\t\t},\n\t}).withDefaultProperties(\n\t\t(): Omit<TLInstance, 'typeName' | 'id' | 'currentPageId'> => ({\n\t\t\tfollowingUserId: null,\n\t\t\topacityForNextShape: 1,\n\t\t\tstylesForNextShape: {},\n\t\t\tbrush: null,\n\t\t\tscribbles: [],\n\t\t\tcursor: {\n\t\t\t\ttype: 'default',\n\t\t\t\trotation: 0,\n\t\t\t},\n\t\t\tisFocusMode: false,\n\t\t\texportBackground: false,\n\t\t\tisDebugMode: false,\n\t\t\tisToolLocked: false,\n\t\t\tscreenBounds: { x: 0, y: 0, w: 1080, h: 720 },\n\t\t\tinsets: [false, false, false, false],\n\t\t\tzoomBrush: null,\n\t\t\tisGridMode: false,\n\t\t\tisPenMode: false,\n\t\t\tchatMessage: '',\n\t\t\tisChatting: false,\n\t\t\thighlightedUserIds: [],\n\t\t\tisFocused: false,\n\t\t\tdevicePixelRatio: typeof window === 'undefined' ? 1 : window.devicePixelRatio,\n\t\t\tisCoarsePointer: false,\n\t\t\tisHoveringCanvas: null,\n\t\t\topenMenus: [] as string[],\n\t\t\tisChangingStyle: false,\n\t\t\tisReadonly: false,\n\t\t\tmeta: {},\n\t\t\tduplicateProps: null,\n\t\t\tcameraState: 'idle',\n\t\t})\n\t)\n}\n\n/**\n * Migration version identifiers for TLInstance records. Each version represents\n * a schema change that requires data transformation when loading older documents.\n *\n * The versions track the evolution of the instance record structure over time,\n * enabling backward and forward compatibility.\n *\n * @public\n */\nexport const instanceVersions = createMigrationIds('com.tldraw.instance', {\n\tAddTransparentExportBgs: 1,\n\tRemoveDialog: 2,\n\tAddToolLockMode: 3,\n\tRemoveExtraPropsForNextShape: 4,\n\tAddLabelColor: 5,\n\tAddFollowingUserId: 6,\n\tRemoveAlignJustify: 7,\n\tAddZoom: 8,\n\tAddVerticalAlign: 9,\n\tAddScribbleDelay: 10,\n\tRemoveUserId: 11,\n\tAddIsPenModeAndIsGridMode: 12,\n\tHoistOpacity: 13,\n\tAddChat: 14,\n\tAddHighlightedUserIds: 15,\n\tReplacePropsForNextShapeWithStylesForNextShape: 16,\n\tAddMeta: 17,\n\tRemoveCursorColor: 18,\n\tAddLonelyProperties: 19,\n\tReadOnlyReadonly: 20,\n\tAddHoveringCanvas: 21,\n\tAddScribbles: 22,\n\tAddInset: 23,\n\tAddDuplicateProps: 24,\n\tRemoveCanMoveCamera: 25,\n\tAddCameraState: 26,\n} as const)\n\n// TODO: rewrite these to use mutation\n\n/**\n * Migration sequence for TLInstance records. Defines how to transform instance\n * records between different schema versions, ensuring data compatibility when\n * loading documents created with different versions of tldraw.\n *\n * Each migration includes an 'up' function to migrate forward and optionally\n * a 'down' function for reverse migration.\n *\n * @example\n * ```ts\n * // Migrations are applied automatically when loading documents\n * const migratedInstance = instanceMigrations.migrate(oldInstance, targetVersion)\n * ```\n *\n * @public\n */\nexport const instanceMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.instance',\n\trecordType: 'instance',\n\tsequence: [\n\t\t{\n\t\t\tid: instanceVersions.AddTransparentExportBgs,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, exportBackground: true }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveDialog,\n\t\t\tup: ({ dialog: _, ...instance }: any) => {\n\t\t\t\treturn instance\n\t\t\t},\n\t\t},\n\n\t\t{\n\t\t\tid: instanceVersions.AddToolLockMode,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, isToolLocked: false }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveExtraPropsForNextShape,\n\t\t\tup: ({ propsForNextShape, ...instance }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...instance,\n\t\t\t\t\tpropsForNextShape: Object.fromEntries(\n\t\t\t\t\t\tObject.entries(propsForNextShape).filter(([key]) =>\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'color',\n\t\t\t\t\t\t\t\t'labelColor',\n\t\t\t\t\t\t\t\t'dash',\n\t\t\t\t\t\t\t\t'fill',\n\t\t\t\t\t\t\t\t'size',\n\t\t\t\t\t\t\t\t'font',\n\t\t\t\t\t\t\t\t'align',\n\t\t\t\t\t\t\t\t'verticalAlign',\n\t\t\t\t\t\t\t\t'icon',\n\t\t\t\t\t\t\t\t'geo',\n\t\t\t\t\t\t\t\t'arrowheadStart',\n\t\t\t\t\t\t\t\t'arrowheadEnd',\n\t\t\t\t\t\t\t\t'spline',\n\t\t\t\t\t\t\t].includes(key)\n\t\t\t\t\t\t)\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddLabelColor,\n\t\t\tup: ({ propsForNextShape, ...instance }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...instance,\n\t\t\t\t\tpropsForNextShape: {\n\t\t\t\t\t\t...propsForNextShape,\n\t\t\t\t\t\tlabelColor: 'black',\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddFollowingUserId,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, followingUserId: null }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveAlignJustify,\n\t\t\tup: (instance: any) => {\n\t\t\t\tlet newAlign = instance.propsForNextShape.align\n\t\t\t\tif (newAlign === 'justify') {\n\t\t\t\t\tnewAlign = 'start'\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\t...instance,\n\t\t\t\t\tpropsForNextShape: {\n\t\t\t\t\t\t...instance.propsForNextShape,\n\t\t\t\t\t\talign: newAlign,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddZoom,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, zoomBrush: null }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddVerticalAlign,\n\t\t\tup: (instance: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...instance,\n\t\t\t\t\tpropsForNextShape: {\n\t\t\t\t\t\t...instance.propsForNextShape,\n\t\t\t\t\t\tverticalAlign: 'middle',\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddScribbleDelay,\n\t\t\tup: (instance: any) => {\n\t\t\t\tif (instance.scribble !== null) {\n\t\t\t\t\treturn { ...instance, scribble: { ...instance.scribble, delay: 0 } }\n\t\t\t\t}\n\t\t\t\treturn { ...instance }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveUserId,\n\t\t\tup: ({ userId: _, ...instance }: any) => {\n\t\t\t\treturn instance\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddIsPenModeAndIsGridMode,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, isPenMode: false, isGridMode: false }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.HoistOpacity,\n\t\t\tup: ({ propsForNextShape: { opacity, ...propsForNextShape }, ...instance }: any) => {\n\t\t\t\treturn { ...instance, opacityForNextShape: Number(opacity ?? '1'), propsForNextShape }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddChat,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, chatMessage: '', isChatting: false }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddHighlightedUserIds,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, highlightedUserIds: [] }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.ReplacePropsForNextShapeWithStylesForNextShape,\n\t\t\tup: ({ propsForNextShape: _, ...instance }: any) => {\n\t\t\t\treturn { ...instance, stylesForNextShape: {} }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddMeta,\n\t\t\tup: (record) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tmeta: {},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveCursorColor,\n\t\t\tup: (record: any) => {\n\t\t\t\tconst { color: _, ...cursor } = record.cursor\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tcursor,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddLonelyProperties,\n\t\t\tup: (record) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tcanMoveCamera: true,\n\t\t\t\t\tisFocused: false,\n\t\t\t\t\tdevicePixelRatio: 1,\n\t\t\t\t\tisCoarsePointer: false,\n\t\t\t\t\topenMenus: [],\n\t\t\t\t\tisChangingStyle: false,\n\t\t\t\t\tisReadOnly: false,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.ReadOnlyReadonly,\n\t\t\tup: ({ isReadOnly: _isReadOnly, ...record }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tisReadonly: _isReadOnly,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddHoveringCanvas,\n\t\t\tup: (record) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tisHoveringCanvas: null,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddScribbles,\n\t\t\tup: ({ scribble: _, ...record }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tscribbles: [],\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddInset,\n\t\t\tup: (record) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tinsets: [false, false, false, false],\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: ({ insets: _, ...record }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddDuplicateProps,\n\t\t\tup: (record) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tduplicateProps: null,\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: ({ duplicateProps: _, ...record }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveCanMoveCamera,\n\t\t\tup: ({ canMoveCamera: _, ...record }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: (instance) => {\n\t\t\t\treturn { ...instance, canMoveCamera: true }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddCameraState,\n\t\t\tup: (record) => {\n\t\t\t\treturn { ...record, cameraState: 'idle' }\n\t\t\t},\n\t\t\tdown: ({ cameraState: _, ...record }: any) => {\n\t\t\t\treturn record\n\t\t\t},\n\t\t},\n\t],\n})\n\n/**\n * The constant ID used for the singleton TLInstance record.\n *\n * Since each browser tab has exactly one instance, this constant ID\n * is used universally across the application.\n *\n * @example\n * ```ts\n * const instance = store.get(TLINSTANCE_ID)\n * if (instance) {\n * console.log('Current page:', instance.currentPageId)\n * }\n * ```\n *\n * @public\n */\nexport const TLINSTANCE_ID = 'instance:instance' as TLInstanceId\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tBaseRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n\tRecordId,\n} from '@tldraw/store'\nimport { filterEntries, JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { BoxModel, boxModelValidator } from '../misc/geometry-types'\nimport { idValidator } from '../misc/id-validator'\nimport { cursorValidator, TLCursor } from '../misc/TLCursor'\nimport { opacityValidator, TLOpacityType } from '../misc/TLOpacity'\nimport { scribbleValidator, TLScribble } from '../misc/TLScribble'\nimport { StyleProp } from '../styles/StyleProp'\nimport { pageIdValidator, TLPageId } from './TLPage'\nimport { TLShapeId } from './TLShape'\nimport { TLUserId, userIdValidator } from './TLUser'\n\n/**\n * State that is particular to a single browser tab. The TLInstance record stores\n * all session-specific state including cursor position, selected tools, UI preferences,\n * and temporary interaction state.\n *\n * Each browser tab has exactly one TLInstance record that persists for the duration\n * of the session and tracks the user's current interaction state.\n *\n * @example\n * ```ts\n * const instance: TLInstance = {\n * id: 'instance:instance',\n * typeName: 'instance',\n * currentPageId: 'page:page1',\n * cursor: { type: 'default', rotation: 0 },\n * screenBounds: { x: 0, y: 0, w: 1920, h: 1080 },\n * isFocusMode: false,\n * isGridMode: true\n * }\n * ```\n *\n * @public\n */\nexport interface TLInstance extends BaseRecord<'instance', TLInstanceId> {\n\tcurrentPageId: TLPageId\n\topacityForNextShape: TLOpacityType\n\tstylesForNextShape: Record<string, unknown>\n\tfollowingUserId: TLUserId | null\n\thighlightedUserIds: TLUserId[]\n\tbrush: BoxModel | null\n\tcursor: TLCursor\n\tscribbles: TLScribble[]\n\tisFocusMode: boolean\n\tisDebugMode: boolean\n\tisToolLocked: boolean\n\texportBackground: boolean\n\tscreenBounds: BoxModel\n\tinsets: boolean[]\n\tzoomBrush: BoxModel | null\n\tchatMessage: string\n\tisChatting: boolean\n\tisPenMode: boolean\n\tisGridMode: boolean\n\tisFocused: boolean\n\tdevicePixelRatio: number\n\t/**\n\t * This is whether the primary input mechanism includes a pointing device of limited accuracy,\n\t * such as a finger on a touchscreen.\n\t */\n\tisCoarsePointer: boolean\n\t/**\n\t * Will be null if the pointer doesn't support hovering (e.g. touch), but true or false\n\t * otherwise\n\t */\n\tisHoveringCanvas: boolean | null\n\topenMenus: string[]\n\tisChangingStyle: boolean\n\tisReadonly: boolean\n\tmeta: JsonObject\n\tduplicateProps: {\n\t\tshapeIds: TLShapeId[]\n\t\toffset: {\n\t\t\tx: number\n\t\t\ty: number\n\t\t}\n\t} | null\n\t/**\n\t * Whether the camera is currently moving or idle. Used to optimize rendering\n\t * and hit-testing during panning/zooming.\n\t */\n\tcameraState: 'idle' | 'moving'\n}\n\n/**\n * Configuration object defining which TLInstance properties should be preserved\n * when loading snapshots across browser sessions. Properties marked as `true`\n * represent user preferences that should persist, while `false` indicates\n * temporary state that should reset.\n *\n * @internal\n */\nexport const shouldKeyBePreservedBetweenSessions = {\n\t// This object defines keys that should be preserved across calls to loadSnapshot()\n\n\tid: false, // meta\n\ttypeName: false, // meta\n\n\tcurrentPageId: false, // does not preserve because who knows if the page still exists\n\topacityForNextShape: false, // does not preserve because it's a temporary state\n\tstylesForNextShape: false, // does not preserve because it's a temporary state\n\tfollowingUserId: false, // does not preserve because it's a temporary state\n\thighlightedUserIds: false, // does not preserve because it's a temporary state\n\tbrush: false, // does not preserve because it's a temporary state\n\tcursor: false, // does not preserve because it's a temporary state\n\tscribbles: false, // does not preserve because it's a temporary state\n\n\tisFocusMode: true, // preserves because it's a user preference\n\tisDebugMode: true, // preserves because it's a user preference\n\tisToolLocked: true, // preserves because it's a user preference\n\texportBackground: true, // preserves because it's a user preference\n\tscreenBounds: true, // preserves because it's capturing the user's screen state\n\tinsets: true, // preserves because it's capturing the user's screen state\n\n\tzoomBrush: false, // does not preserve because it's a temporary state\n\tchatMessage: false, // does not preserve because it's a temporary state\n\tisChatting: false, // does not preserve because it's a temporary state\n\tisPenMode: false, // does not preserve because it's a temporary state\n\n\tisGridMode: true, // preserves because it's a user preference\n\tisFocused: true, // preserves because obviously\n\tdevicePixelRatio: true, // preserves because it captures the user's screen state\n\tisCoarsePointer: true, // preserves because it captures the user's screen state\n\tisHoveringCanvas: false, // does not preserve because it's a temporary state\n\topenMenus: false, // does not preserve because it's a temporary state\n\tisChangingStyle: false, // does not preserve because it's a temporary state\n\tisReadonly: true, // preserves because it's a config option\n\tmeta: false, // does not preserve because who knows what's in there, leave it up to sdk users to save and reinstate\n\tduplicateProps: false, //\n\tcameraState: false, // does not preserve because it's a temporary state\n} as const satisfies { [K in keyof TLInstance]: boolean }\n\n/**\n * Extracts only the properties from a TLInstance that should be preserved\n * between browser sessions, filtering out temporary state.\n *\n * @param val - The TLInstance to filter, or null/undefined\n * @returns A partial TLInstance containing only preservable properties, or null\n *\n * @internal\n */\nexport function pluckPreservingValues(val?: TLInstance | null): null | Partial<TLInstance> {\n\treturn val\n\t\t? (filterEntries(val, (key) => {\n\t\t\t\treturn shouldKeyBePreservedBetweenSessions[key as keyof TLInstance]\n\t\t\t}) as Partial<TLInstance>)\n\t\t: null\n}\n\n/**\n * A unique identifier for TLInstance records.\n *\n * TLInstance IDs are always the constant 'instance:instance' since there\n * is exactly one instance record per browser tab.\n *\n * @public\n */\nexport type TLInstanceId = RecordId<TLInstance>\n\n/**\n * Validator for TLInstanceId values. Ensures the ID follows the correct\n * format for instance records.\n *\n * @example\n * ```ts\n * const isValid = instanceIdValidator.isValid('instance:instance') // true\n * const isValid2 = instanceIdValidator.isValid('invalid') // false\n * ```\n *\n * @public\n */\nexport const instanceIdValidator = idValidator<TLInstanceId>('instance')\n\n/**\n * Creates the record type definition for TLInstance records, including validation\n * and default properties. The function takes a map of available style properties\n * to configure validation for the stylesForNextShape field.\n *\n * @param stylesById - Map of style property IDs to their corresponding StyleProp definitions\n * @returns A configured RecordType for TLInstance records\n *\n * @example\n * ```ts\n * const stylesMap = new Map([['color', DefaultColorStyle]])\n * const InstanceRecordType = createInstanceRecordType(stylesMap)\n *\n * const instance = InstanceRecordType.create({\n * id: 'instance:instance',\n * currentPageId: 'page:page1'\n * })\n * ```\n *\n * @public\n */\nexport function createInstanceRecordType(stylesById: Map<string, StyleProp<unknown>>) {\n\tconst stylesForNextShapeValidators = {} as Record<string, T.Validator<unknown>>\n\tfor (const [id, style] of stylesById) {\n\t\tstylesForNextShapeValidators[id] = T.optional(style)\n\t}\n\n\tconst instanceTypeValidator: T.Validator<TLInstance> = T.model(\n\t\t'instance',\n\t\tT.object({\n\t\t\ttypeName: T.literal('instance'),\n\t\t\tid: idValidator<TLInstanceId>('instance'),\n\t\t\tcurrentPageId: pageIdValidator,\n\t\t\tfollowingUserId: userIdValidator.nullable(),\n\t\t\tbrush: boxModelValidator.nullable(),\n\t\t\topacityForNextShape: opacityValidator,\n\t\t\tstylesForNextShape: T.object(stylesForNextShapeValidators),\n\t\t\tcursor: cursorValidator,\n\t\t\tscribbles: T.arrayOf(scribbleValidator),\n\t\t\tisFocusMode: T.boolean,\n\t\t\tisDebugMode: T.boolean,\n\t\t\tisToolLocked: T.boolean,\n\t\t\texportBackground: T.boolean,\n\t\t\tscreenBounds: boxModelValidator,\n\t\t\tinsets: T.arrayOf(T.boolean),\n\t\t\tzoomBrush: boxModelValidator.nullable(),\n\t\t\tisPenMode: T.boolean,\n\t\t\tisGridMode: T.boolean,\n\t\t\tchatMessage: T.string,\n\t\t\tisChatting: T.boolean,\n\t\t\thighlightedUserIds: T.arrayOf(userIdValidator),\n\t\t\tisFocused: T.boolean,\n\t\t\tdevicePixelRatio: T.number,\n\t\t\tisCoarsePointer: T.boolean,\n\t\t\tisHoveringCanvas: T.boolean.nullable(),\n\t\t\topenMenus: T.arrayOf(T.string),\n\t\t\tisChangingStyle: T.boolean,\n\t\t\tisReadonly: T.boolean,\n\t\t\tmeta: T.jsonValue as T.ObjectValidator<JsonObject>,\n\t\t\tduplicateProps: T.object({\n\t\t\t\tshapeIds: T.arrayOf(idValidator<TLShapeId>('shape')),\n\t\t\t\toffset: T.object({\n\t\t\t\t\tx: T.number,\n\t\t\t\t\ty: T.number,\n\t\t\t\t}),\n\t\t\t}).nullable(),\n\t\t\tcameraState: T.literalEnum('idle', 'moving'),\n\t\t})\n\t)\n\n\treturn createRecordType<TLInstance>('instance', {\n\t\tvalidator: instanceTypeValidator,\n\t\tscope: 'session',\n\t\tephemeralKeys: {\n\t\t\tcurrentPageId: false,\n\t\t\tmeta: false,\n\n\t\t\tfollowingUserId: true,\n\t\t\topacityForNextShape: true,\n\t\t\tstylesForNextShape: true,\n\t\t\tbrush: true,\n\t\t\tcursor: true,\n\t\t\tscribbles: true,\n\t\t\tisFocusMode: true,\n\t\t\tisDebugMode: true,\n\t\t\tisToolLocked: true,\n\t\t\texportBackground: true,\n\t\t\tscreenBounds: true,\n\t\t\tinsets: true,\n\t\t\tzoomBrush: true,\n\t\t\tisPenMode: true,\n\t\t\tisGridMode: true,\n\t\t\tchatMessage: true,\n\t\t\tisChatting: true,\n\t\t\thighlightedUserIds: true,\n\t\t\tisFocused: true,\n\t\t\tdevicePixelRatio: true,\n\t\t\tisCoarsePointer: true,\n\t\t\tisHoveringCanvas: true,\n\t\t\topenMenus: true,\n\t\t\tisChangingStyle: true,\n\t\t\tisReadonly: true,\n\t\t\tduplicateProps: true,\n\t\t\tcameraState: true,\n\t\t},\n\t}).withDefaultProperties(\n\t\t(): Omit<TLInstance, 'typeName' | 'id' | 'currentPageId'> => ({\n\t\t\tfollowingUserId: null,\n\t\t\topacityForNextShape: 1,\n\t\t\tstylesForNextShape: {},\n\t\t\tbrush: null,\n\t\t\tscribbles: [],\n\t\t\tcursor: {\n\t\t\t\ttype: 'default',\n\t\t\t\trotation: 0,\n\t\t\t},\n\t\t\tisFocusMode: false,\n\t\t\texportBackground: false,\n\t\t\tisDebugMode: false,\n\t\t\tisToolLocked: false,\n\t\t\tscreenBounds: { x: 0, y: 0, w: 1080, h: 720 },\n\t\t\tinsets: [false, false, false, false],\n\t\t\tzoomBrush: null,\n\t\t\tisGridMode: false,\n\t\t\tisPenMode: false,\n\t\t\tchatMessage: '',\n\t\t\tisChatting: false,\n\t\t\thighlightedUserIds: [],\n\t\t\tisFocused: false,\n\t\t\tdevicePixelRatio: typeof window === 'undefined' ? 1 : window.devicePixelRatio,\n\t\t\tisCoarsePointer: false,\n\t\t\tisHoveringCanvas: null,\n\t\t\topenMenus: [] as string[],\n\t\t\tisChangingStyle: false,\n\t\t\tisReadonly: false,\n\t\t\tmeta: {},\n\t\t\tduplicateProps: null,\n\t\t\tcameraState: 'idle',\n\t\t})\n\t)\n}\n\n/**\n * Migration version identifiers for TLInstance records. Each version represents\n * a schema change that requires data transformation when loading older documents.\n *\n * The versions track the evolution of the instance record structure over time,\n * enabling backward and forward compatibility.\n *\n * @public\n */\nexport const instanceVersions = createMigrationIds('com.tldraw.instance', {\n\tAddTransparentExportBgs: 1,\n\tRemoveDialog: 2,\n\tAddToolLockMode: 3,\n\tRemoveExtraPropsForNextShape: 4,\n\tAddLabelColor: 5,\n\tAddFollowingUserId: 6,\n\tRemoveAlignJustify: 7,\n\tAddZoom: 8,\n\tAddVerticalAlign: 9,\n\tAddScribbleDelay: 10,\n\tRemoveUserId: 11,\n\tAddIsPenModeAndIsGridMode: 12,\n\tHoistOpacity: 13,\n\tAddChat: 14,\n\tAddHighlightedUserIds: 15,\n\tReplacePropsForNextShapeWithStylesForNextShape: 16,\n\tAddMeta: 17,\n\tRemoveCursorColor: 18,\n\tAddLonelyProperties: 19,\n\tReadOnlyReadonly: 20,\n\tAddHoveringCanvas: 21,\n\tAddScribbles: 22,\n\tAddInset: 23,\n\tAddDuplicateProps: 24,\n\tRemoveCanMoveCamera: 25,\n\tAddCameraState: 26,\n} as const)\n\n// TODO: rewrite these to use mutation\n\n/**\n * Migration sequence for TLInstance records. Defines how to transform instance\n * records between different schema versions, ensuring data compatibility when\n * loading documents created with different versions of tldraw.\n *\n * Each migration includes an 'up' function to migrate forward and optionally\n * a 'down' function for reverse migration.\n *\n * @example\n * ```ts\n * // Migrations are applied automatically when loading documents\n * const migratedInstance = instanceMigrations.migrate(oldInstance, targetVersion)\n * ```\n *\n * @public\n */\nexport const instanceMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.instance',\n\trecordType: 'instance',\n\tsequence: [\n\t\t{\n\t\t\tid: instanceVersions.AddTransparentExportBgs,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, exportBackground: true }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveDialog,\n\t\t\tup: ({ dialog: _, ...instance }: any) => {\n\t\t\t\treturn instance\n\t\t\t},\n\t\t},\n\n\t\t{\n\t\t\tid: instanceVersions.AddToolLockMode,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, isToolLocked: false }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveExtraPropsForNextShape,\n\t\t\tup: ({ propsForNextShape, ...instance }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...instance,\n\t\t\t\t\tpropsForNextShape: Object.fromEntries(\n\t\t\t\t\t\tObject.entries(propsForNextShape).filter(([key]) =>\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\t'color',\n\t\t\t\t\t\t\t\t'labelColor',\n\t\t\t\t\t\t\t\t'dash',\n\t\t\t\t\t\t\t\t'fill',\n\t\t\t\t\t\t\t\t'size',\n\t\t\t\t\t\t\t\t'font',\n\t\t\t\t\t\t\t\t'align',\n\t\t\t\t\t\t\t\t'verticalAlign',\n\t\t\t\t\t\t\t\t'icon',\n\t\t\t\t\t\t\t\t'geo',\n\t\t\t\t\t\t\t\t'arrowheadStart',\n\t\t\t\t\t\t\t\t'arrowheadEnd',\n\t\t\t\t\t\t\t\t'spline',\n\t\t\t\t\t\t\t].includes(key)\n\t\t\t\t\t\t)\n\t\t\t\t\t),\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddLabelColor,\n\t\t\tup: ({ propsForNextShape, ...instance }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...instance,\n\t\t\t\t\tpropsForNextShape: {\n\t\t\t\t\t\t...propsForNextShape,\n\t\t\t\t\t\tlabelColor: 'black',\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddFollowingUserId,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, followingUserId: null }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveAlignJustify,\n\t\t\tup: (instance: any) => {\n\t\t\t\tlet newAlign = instance.propsForNextShape.align\n\t\t\t\tif (newAlign === 'justify') {\n\t\t\t\t\tnewAlign = 'start'\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\t...instance,\n\t\t\t\t\tpropsForNextShape: {\n\t\t\t\t\t\t...instance.propsForNextShape,\n\t\t\t\t\t\talign: newAlign,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddZoom,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, zoomBrush: null }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddVerticalAlign,\n\t\t\tup: (instance: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...instance,\n\t\t\t\t\tpropsForNextShape: {\n\t\t\t\t\t\t...instance.propsForNextShape,\n\t\t\t\t\t\tverticalAlign: 'middle',\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddScribbleDelay,\n\t\t\tup: (instance: any) => {\n\t\t\t\tif (instance.scribble !== null) {\n\t\t\t\t\treturn { ...instance, scribble: { ...instance.scribble, delay: 0 } }\n\t\t\t\t}\n\t\t\t\treturn { ...instance }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveUserId,\n\t\t\tup: ({ userId: _, ...instance }: any) => {\n\t\t\t\treturn instance\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddIsPenModeAndIsGridMode,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, isPenMode: false, isGridMode: false }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.HoistOpacity,\n\t\t\tup: ({ propsForNextShape: { opacity, ...propsForNextShape }, ...instance }: any) => {\n\t\t\t\treturn { ...instance, opacityForNextShape: Number(opacity ?? '1'), propsForNextShape }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddChat,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, chatMessage: '', isChatting: false }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddHighlightedUserIds,\n\t\t\tup: (instance) => {\n\t\t\t\treturn { ...instance, highlightedUserIds: [] }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.ReplacePropsForNextShapeWithStylesForNextShape,\n\t\t\tup: ({ propsForNextShape: _, ...instance }: any) => {\n\t\t\t\treturn { ...instance, stylesForNextShape: {} }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddMeta,\n\t\t\tup: (record) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tmeta: {},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveCursorColor,\n\t\t\tup: (record: any) => {\n\t\t\t\tconst { color: _, ...cursor } = record.cursor\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tcursor,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddLonelyProperties,\n\t\t\tup: (record) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tcanMoveCamera: true,\n\t\t\t\t\tisFocused: false,\n\t\t\t\t\tdevicePixelRatio: 1,\n\t\t\t\t\tisCoarsePointer: false,\n\t\t\t\t\topenMenus: [],\n\t\t\t\t\tisChangingStyle: false,\n\t\t\t\t\tisReadOnly: false,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.ReadOnlyReadonly,\n\t\t\tup: ({ isReadOnly: _isReadOnly, ...record }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tisReadonly: _isReadOnly,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddHoveringCanvas,\n\t\t\tup: (record) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tisHoveringCanvas: null,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddScribbles,\n\t\t\tup: ({ scribble: _, ...record }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tscribbles: [],\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddInset,\n\t\t\tup: (record) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tinsets: [false, false, false, false],\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: ({ insets: _, ...record }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddDuplicateProps,\n\t\t\tup: (record) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t\tduplicateProps: null,\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: ({ duplicateProps: _, ...record }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.RemoveCanMoveCamera,\n\t\t\tup: ({ canMoveCamera: _, ...record }: any) => {\n\t\t\t\treturn {\n\t\t\t\t\t...record,\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: (instance) => {\n\t\t\t\treturn { ...instance, canMoveCamera: true }\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instanceVersions.AddCameraState,\n\t\t\tup: (record) => {\n\t\t\t\treturn { ...record, cameraState: 'idle' }\n\t\t\t},\n\t\t\tdown: ({ cameraState: _, ...record }: any) => {\n\t\t\t\treturn record\n\t\t\t},\n\t\t},\n\t],\n})\n\n/**\n * The constant ID used for the singleton TLInstance record.\n *\n * Since each browser tab has exactly one instance, this constant ID\n * is used universally across the application.\n *\n * @example\n * ```ts\n * const instance = store.get(TLINSTANCE_ID)\n * if (instance) {\n * console.log('Current page:', instance.currentPageId)\n * }\n * ```\n *\n * @public\n */\nexport const TLINSTANCE_ID = 'instance:instance' as TLInstanceId\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -107,7 +107,11 @@ const InstancePageStateRecordType = createRecordType(
107
107
  ephemeralKeys: {
108
108
  pageId: false,
109
109
  selectedShapeIds: false,
110
- editingShapeId: false,
110
+ // editingShapeId is set with `history: 'ignore'`, so entering the editing
111
+ // state is never undoable. Marking it ephemeral keeps undo/redo from
112
+ // reapplying a stale editingShapeId (e.g. after a shape it pointed at was
113
+ // deleted), which could leave the editor pointing at a missing shape.
114
+ editingShapeId: true,
111
115
  croppingShapeId: false,
112
116
  meta: false,
113
117
  hintingShapeIds: true,