@scrawl-board/board 0.1.0-beta.7 → 0.1.0-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -184,6 +184,21 @@ interface CustomObjectDefinition<Props extends JsonValue = JsonValue> {
184
184
  /** One pure, synchronous step per consecutive schema version. */
185
185
  migrate?: Readonly<Record<number, (oldProps: JsonValue) => JsonValue>>;
186
186
  describe(object: ReadonlyCustomObject<Props>, context: ObjectDescribeContext): BoardScene;
187
+ /**
188
+ * Optional point-level hit-test precision (Phase 8). Every custom object
189
+ * hit-tests against its bounding box (`fallback.bounds`) by default — this
190
+ * lets a non-rectangular shape (e.g. a circular card, an L-shaped region)
191
+ * reject a point that's inside that box but outside its actual visible
192
+ * silhouette, tightening a click/marquee/raycast hit to the shape's real
193
+ * outline. `point` is in this object's own local space — the same
194
+ * untransformed space `describe`'s returned geometry already lives in
195
+ * (the caller inverse-transforms the pointer's board point through
196
+ * `object.transform` before calling this). Absent means every point
197
+ * inside the bounding box hits, matching pre-Phase-8 behavior exactly.
198
+ * Rejecting a point here does not fall through to whatever's underneath —
199
+ * the gesture simply misses this object, same as clicking empty space.
200
+ */
201
+ hitTest?(object: ReadonlyCustomObject<Props>, point: BoardPoint): boolean;
187
202
  }
188
203
  interface SceneNodeBase {
189
204
  key: string;
@@ -217,6 +232,15 @@ interface SceneGroup extends SceneNodeBase {
217
232
  kind: "group";
218
233
  children: readonly BoardScene[];
219
234
  }
235
+ /**
236
+ * **No renderer or SVG-export interpreter exists for this node kind yet**
237
+ * (tracked as deferred work — see `renderer/shapes/customObjects.ts`'s
238
+ * `"path"` case). Returning a `ScenePath` from `describe()` renders nothing,
239
+ * exports nothing, and contributes no hit-test bounds — it neither errors
240
+ * nor emits a diagnostic. Until an interpreter ships, build custom shapes
241
+ * from `SceneRect`/`SceneEllipse`/`SceneGroup`/`SceneText`/`SceneImage`
242
+ * instead.
243
+ */
220
244
  interface ScenePath extends SceneNodeBase {
221
245
  kind: "path";
222
246
  /** SVG-style path data, board-local coordinates. */
@@ -389,8 +413,23 @@ declare function canUnlockItem(item: Lockable | undefined, userId: string | unde
389
413
  /** Wire fields for a locked item; omitted entirely when unlocked. */
390
414
  declare function serializeLock(item: Lockable): Lockable;
391
415
 
416
+ /**
417
+ * Per-object visibility (Phase 8) — mirrors `itemLock.ts`'s `Lockable`
418
+ * pattern exactly, but simpler: unlike a lock, hidden state carries no
419
+ * holder/ownership concept, so there's no analogue to `LockHolder`/
420
+ * `canUnlockItem`. A hidden object stays fully present in the Document
421
+ * (still serializes, persists, syncs, undoes/redoes) — it just skips
422
+ * rendering and hit-testing/selection candidacy. `hidden` absent or
423
+ * `false` means visible; this keeps every pre-Phase-8 document (which has
424
+ * no `hidden` field on any object at all) implicitly fully visible with
425
+ * zero migration needed.
426
+ */
427
+ interface Hideable {
428
+ hidden?: boolean;
429
+ }
430
+
392
431
  /** A kitchen timer sitting on the board. Remaining time is derived, not ticked. */
393
- interface KitchenTimer extends Lockable {
432
+ interface KitchenTimer extends Lockable, Hideable {
394
433
  id: string;
395
434
  x: number;
396
435
  y: number;
@@ -416,9 +455,25 @@ declare function setTimerDuration(timer: KitchenTimer, durationMs: number): Kitc
416
455
  declare function formatTimer(ms: number): string;
417
456
 
418
457
  declare const SHAPE_MIN_SIZE = 0.5;
419
- declare const SHAPE_DEFAULT_STROKE = "#1C1C1E";
420
- declare const SHAPE_DEFAULT_STROKE_WIDTH = 0.12;
421
- interface RectangleObject extends Lockable {
458
+ /**
459
+ * Centralized shape style defaults (Phase 8) — one object a Host can read
460
+ * to know (or, by not relying on the standalone constants below, override
461
+ * via its own UI state) what a newly drawn Rectangle/Ellipse/Line/Arrow/
462
+ * Polygon/Star/Heart starts with when the user hasn't picked a stroke/width
463
+ * yet. `shapeTool.ts` (commit-time), `renderer/shapes/lines.ts` (render-time
464
+ * fallback for an object missing these fields), and
465
+ * `persistence/serialization/svg.ts` (export-time fallback) all read from
466
+ * here — the two standalone constants below are kept for source
467
+ * compatibility and simply mirror this object's values, not a second
468
+ * source of truth.
469
+ */
470
+ declare const SHAPE_STYLE_DEFAULTS: {
471
+ readonly stroke: "#1C1C1E";
472
+ readonly strokeWidth: 0.12;
473
+ };
474
+ declare const SHAPE_DEFAULT_STROKE: "#1C1C1E";
475
+ declare const SHAPE_DEFAULT_STROKE_WIDTH: 0.12;
476
+ interface RectangleObject extends Lockable, Hideable {
422
477
  id: string;
423
478
  x: number;
424
479
  y: number;
@@ -440,7 +495,7 @@ interface RectangleObject extends Lockable {
440
495
  */
441
496
  rotation?: number;
442
497
  }
443
- interface EllipseObject extends Lockable {
498
+ interface EllipseObject extends Lockable, Hideable {
444
499
  id: string;
445
500
  x: number;
446
501
  y: number;
@@ -458,7 +513,7 @@ declare function cloneRectangle(rect: RectangleObject): RectangleObject;
458
513
  declare function cloneEllipse(ellipse: EllipseObject): EllipseObject;
459
514
  /** `"none"` is a plain line with no arrowhead; today's only real head shape is `"triangle"`. New head shapes extend this union without touching `ArrowObject`'s own fields. */
460
515
  type ArrowHeadStyle = "triangle" | "none";
461
- interface LineObject extends Lockable {
516
+ interface LineObject extends Lockable, Hideable {
462
517
  id: string;
463
518
  start: BoardPoint;
464
519
  end: BoardPoint;
@@ -466,7 +521,7 @@ interface LineObject extends Lockable {
466
521
  strokeWidth?: number;
467
522
  opacity?: number;
468
523
  }
469
- interface ArrowObject extends Lockable {
524
+ interface ArrowObject extends Lockable, Hideable {
470
525
  id: string;
471
526
  start: BoardPoint;
472
527
  end: BoardPoint;
@@ -485,7 +540,7 @@ interface ArrowObject extends Lockable {
485
540
  * `polygonStartAngle`, which encodes each side count's own vertex
486
541
  * orientation so the outline always matches the legacy drag-preview shape.
487
542
  */
488
- interface PolygonObject extends Lockable {
543
+ interface PolygonObject extends Lockable, Hideable {
489
544
  id: string;
490
545
  x: number;
491
546
  y: number;
@@ -501,7 +556,7 @@ interface PolygonObject extends Lockable {
501
556
  }
502
557
  declare function clonePolygon(polygon: PolygonObject): PolygonObject;
503
558
  /** Same bounding-box/rotation convention as Rectangle; a 5-pointed star with a tuned inner-radius ratio, matching the legacy tool's own default (see `polygonGeometry.ts`'s `starPoints`). */
504
- interface StarObject extends Lockable {
559
+ interface StarObject extends Lockable, Hideable {
505
560
  id: string;
506
561
  x: number;
507
562
  y: number;
@@ -519,7 +574,7 @@ interface StarObject extends Lockable {
519
574
  }
520
575
  declare function cloneStar(star: StarObject): StarObject;
521
576
  /** Same bounding-box/rotation convention as Rectangle; the standard parametric heart curve (see `polygonGeometry.ts`'s `heartPoints`), no extra parameters beyond the shared shape fields. */
522
- interface HeartObject extends Lockable {
577
+ interface HeartObject extends Lockable, Hideable {
523
578
  id: string;
524
579
  x: number;
525
580
  y: number;
@@ -547,7 +602,7 @@ declare function cloneArrow(arrow: ArrowObject): ArrowObject;
547
602
  * a group into its leaf members is always done by the caller (recursively,
548
603
  * with cycle protection), never assumed here.
549
604
  */
550
- interface GroupObject extends Lockable {
605
+ interface GroupObject extends Lockable, Hideable {
551
606
  id: string;
552
607
  children: string[];
553
608
  }
@@ -573,7 +628,7 @@ interface StrokePoint extends BoardPoint {
573
628
  * geometric outline, not an expressive ink mark.
574
629
  */
575
630
  type StrokeTool = "marker" | "highlighter" | "shape";
576
- interface Stroke extends Lockable {
631
+ interface Stroke extends Lockable, Hideable {
577
632
  id: string;
578
633
  color: string;
579
634
  baseWidth: number;
@@ -592,7 +647,7 @@ interface Stroke extends Lockable {
592
647
  declare const ERASE_THRESHOLD = 0.95;
593
648
  declare function cloneStroke(stroke: Stroke): Stroke;
594
649
  type SerializedPoint = [number, number, number, number];
595
- interface SerializedStroke extends Lockable {
650
+ interface SerializedStroke extends Lockable, Hideable {
596
651
  id: string;
597
652
  color: string;
598
653
  baseWidth: number;
@@ -686,7 +741,7 @@ interface NoteVote {
686
741
  * A sticky note: content floating above the board at a z-offset (pillar 3 —
687
742
  * depth as an organizational axis). Center position in board space.
688
743
  */
689
- interface StickyNote extends Lockable {
744
+ interface StickyNote extends Lockable, Hideable {
690
745
  id: string;
691
746
  x: number;
692
747
  y: number;
@@ -704,7 +759,7 @@ interface StickyNote extends Lockable {
704
759
  * top-left corner; lines flow downward (-y). Text joins the clustering
705
760
  * system like handwriting (build prompt §6.4).
706
761
  */
707
- interface TextBlock extends Lockable {
762
+ interface TextBlock extends Lockable, Hideable {
708
763
  id: string;
709
764
  x: number;
710
765
  y: number;
@@ -734,7 +789,7 @@ declare function cloneNote(note: StickyNote): StickyNote;
734
789
  * Interactive structured table on the board. Position (x, y) is top-left in board units.
735
790
  * Cells are indexed as `${row},${col}` keys mapping to cell text content.
736
791
  */
737
- interface TableBlock extends Lockable {
792
+ interface TableBlock extends Lockable, Hideable {
738
793
  id: string;
739
794
  x: number;
740
795
  y: number;
@@ -760,7 +815,7 @@ declare const FOG_COLOR = "#FFFFFF";
760
815
  * An imported image block on the board plane.
761
816
  * Coordinates (x, y) represent the center of the image in board space.
762
817
  */
763
- interface ImageBlock extends Lockable {
818
+ interface ImageBlock extends Lockable, Hideable {
764
819
  id: string;
765
820
  /**
766
821
  * A legacy, read-only data URL (or, historically, an arbitrary string) —
@@ -810,6 +865,15 @@ type DocumentLoadResult = {
810
865
  declare function loadDocumentBytes(originalBytes: string): DocumentLoadResult;
811
866
  declare function migrateDocument(raw: unknown): DocumentLoadResult;
812
867
  declare function serializeDocument(document: unknown): string;
868
+ /**
869
+ * A Document's serialized size in bytes (Phase 5) — UTF-8, not UTF-16
870
+ * `string.length`, since a Document with non-ASCII note/text content (most
871
+ * of them, eventually) would otherwise under-report. Useful for a Host
872
+ * deciding when to warn about an unusually large board, or for logging/
873
+ * telemetry around save size — not consulted by anything inside this
874
+ * package itself, which has no size limit of its own.
875
+ */
876
+ declare function documentSize(document: CurrentSerializedDocument): number;
813
877
 
814
878
  interface SearchableComment {
815
879
  id: string;
@@ -1019,6 +1083,16 @@ declare class BoardDocument {
1019
1083
  * `getSelectedItemInfo`'s custom branch hardcodes `isLocked: false`).
1020
1084
  */
1021
1085
  isLocked(id: string): boolean;
1086
+ /**
1087
+ * True if `id` exists and is hidden, for any type — the same per-type
1088
+ * probe pattern as {@link isLocked} (Phase 8). Custom objects are
1089
+ * excluded for the same reason `isLocked` excludes them: they have no
1090
+ * `Hideable` field at all, so "hidden" isn't a concept that applies to
1091
+ * them yet. Used by marquee selection (`selectTool.ts`) to keep a hidden
1092
+ * object out of a rubber-band selection even for object types whose own
1093
+ * renderer doesn't yet suppress click-based hit-testing.
1094
+ */
1095
+ isHidden(id: string): boolean;
1022
1096
  subscribe(listener: Listener): () => void;
1023
1097
  addStrokes(strokes: Stroke[]): void;
1024
1098
  removeStrokes(ids: string[]): void;
@@ -1145,7 +1219,17 @@ declare class BoardDocument {
1145
1219
  static deserializeNotes(data: SerializedDocument): StickyNote[];
1146
1220
  static deserializeTexts(data: SerializedDocument): TextBlock[];
1147
1221
  static deserializeTables(data: SerializedDocument): TableBlock[];
1148
- static deserializeStrokes(data: SerializedDocument): Stroke[];
1222
+ /**
1223
+ * `onSkip` (Phase 9) replaces an unconditional `console.error` — `core`
1224
+ * must never do raw console I/O (no dev-gate, no way for a Host to
1225
+ * suppress or redirect it), so a skipped stroke is now reported only if
1226
+ * the caller asks for it, via whatever diagnostic channel it already
1227
+ * has (e.g. `controller-internal.ts` routes this into the same typed
1228
+ * `"error"` event every other diagnostic already uses). Silent by
1229
+ * default, matching how every other `deserialize*` method here already
1230
+ * behaves (no diagnostics at all).
1231
+ */
1232
+ static deserializeStrokes(data: SerializedDocument, onSkip?: (id: string, cause: unknown) => void): Stroke[];
1149
1233
  /**
1150
1234
  * Every mutation funnels through here, so paint-order tracking lives in
1151
1235
  * exactly one place rather than at every individual add/remove call site
@@ -1156,17 +1240,18 @@ declare class BoardDocument {
1156
1240
  * ids already tracked (idempotent by construction: `orderIndex.has` gates
1157
1241
  * every append).
1158
1242
  *
1159
- * `orderChanged` is populated here whenever `objectOrder` actually
1160
- * changed — not just for an explicit reorder, but for any add/remove too.
1161
- * A pure append never shifts an existing id's rank (new ids land at the
1162
- * tail), but a removal splices a middle id out, which *does* shift every
1163
- * id after it down by one — a renderer that only resynced Z on an
1164
- * explicit reorder would silently render those with a stale rank until
1165
- * something else happened to touch them, eventually colliding with a
1166
- * freshly-added object's freshly-computed Z. Firing this on every
1167
- * order-touching change (not just removes) is simpler than special-
1168
- * casing which kind of change actually needs it, at the cost of a
1169
- * redundant same-value resync on a pure append.
1243
+ * `orderChanged` (Phase 9) reports exactly the ids whose rank actually
1244
+ * changed, using `orderIndex` throughout instead of `indexOf` — a pure
1245
+ * append never shifts any existing id's rank (new ids land at the tail,
1246
+ * already covered by this same change's own `Added` field, so
1247
+ * `orderChanged` stays unset), while a removal shifts every id at-or-
1248
+ * after the lowest removed rank down by one, computed in a single O(n)
1249
+ * filter pass (not one `indexOf`+`splice` per removed id) regardless of
1250
+ * how many ids this one change removes. Every renderer's `onChange` now
1251
+ * looks up only the ids actually in `orderChanged` instead of walking
1252
+ * its entire mesh map on any order-touching change — a broad, unfiltered
1253
+ * `orderChanged` here would silently defeat that fix, not just waste
1254
+ * cycles here.
1170
1255
  */
1171
1256
  private emit;
1172
1257
  }
@@ -1943,6 +2028,8 @@ interface BoardEventMap {
1943
2028
  "asset-diagnostic": AssetDiagnostic;
1944
2029
  /** A batch of Ops was reconciled (not applied as-sent) by the persistence adapter (ticket #24). */
1945
2030
  "persistence-diagnostic": PersistenceDiagnostic;
2031
+ /** The collaboration server has confirmed receipt of these op ids (Phase 7) — observability only; the Document was already correct via optimistic local apply before this ever fires. */
2032
+ "collaboration-ops-acknowledged": CollaborationAckDiagnostic;
1946
2033
  audit: unknown;
1947
2034
  error: BoardControllerError;
1948
2035
  disposed: undefined;
@@ -2006,9 +2093,12 @@ interface PresenceView {
2006
2093
  readonly height: number;
2007
2094
  }
2008
2095
  /**
2009
- * A Host-owned collaborator, synced in for cursor/roster rendering only.
2010
- * Presence is ephemeral — it never touches the Document, Ops, undo/redo,
2011
- * or persistence — so this is a read/query capability, not an adapter.
2096
+ * A collaborator, synced in for cursor/roster rendering only. Presence is
2097
+ * ephemeral — it never touches the Document, Ops, undo/redo, or persistence
2098
+ * (ADR 0006/0007). Two ways a roster gets populated (`presence.sync`
2099
+ * directly, or a `CollaborationAdapter`'s optional presence channel —
2100
+ * Phase 6, ADR 0015) both feed the exact same read/query capability below;
2101
+ * a Host picks one, not both, for a given controller.
2012
2102
  */
2013
2103
  interface PresenceUser {
2014
2104
  readonly id: string;
@@ -2017,6 +2107,14 @@ interface PresenceUser {
2017
2107
  readonly tool?: string;
2018
2108
  readonly cursor?: PresenceCursor;
2019
2109
  readonly view?: PresenceView;
2110
+ /** Host-supplied extras (avatar URL, role, etc.) — opaque to Scrawl, never interpreted. */
2111
+ readonly metadata?: Record<string, unknown>;
2112
+ }
2113
+ /** This client's own local presence, published via `presence.broadcast()` (Phase 6). */
2114
+ interface LocalPresence {
2115
+ readonly cursor?: PresenceCursor | null;
2116
+ readonly view?: PresenceView | null;
2117
+ readonly tool?: string;
2020
2118
  }
2021
2119
  /**
2022
2120
  * The Custom arm wraps `CustomBoardObject` under the same `type` discriminant
@@ -2142,10 +2240,34 @@ type LoadResult = {
2142
2240
  } | {
2143
2241
  state: "missing";
2144
2242
  };
2243
+ /**
2244
+ * Result of a whole-document `PersistenceAdapter.replace()` call (ADR 0006:
2245
+ * "Whole-document writes survive only for create, clear-board and import,
2246
+ * where replacing everything is the actual intent"). Revision-gated, unlike
2247
+ * `applyOps` — `conflict` means `baseRevision` was stale (someone else's
2248
+ * write landed first); the caller must reload and never overwrites blind.
2249
+ */
2250
+ type ReplaceResult = {
2251
+ state: "applied";
2252
+ revision: string;
2253
+ } | {
2254
+ state: "conflict";
2255
+ currentRevision: string;
2256
+ };
2257
+ /**
2258
+ * The one sanctioned seam for persisting a Board's Document to a Host's own
2259
+ * storage — implement this against a database, an HTTP API, IndexedDB
2260
+ * (see `@scrawl-board/board/local`'s `createIndexedDBPersistence`), or
2261
+ * anything else. `load()` fetches the current state on connect; `applyOps()`
2262
+ * streams incremental Ops as edits happen; `replace()` is only for
2263
+ * whole-document writes (create, clear-board, import — see ADR 0006) and is
2264
+ * revision-gated so a stale write never silently clobbers a newer one.
2265
+ * Passed via `createBoardController({ adapters: { persistence } })`.
2266
+ */
2145
2267
  interface PersistenceAdapter {
2146
2268
  load(context: DocumentContext): Promise<LoadResult>;
2147
2269
  applyOps(context: DocumentContext, ops: readonly ControllerOp[]): Promise<ApplyOpsResult>;
2148
- replace(context: DocumentContext, document: CurrentSerializedDocument, baseRevision: string): Promise<unknown>;
2270
+ replace(context: DocumentContext, document: CurrentSerializedDocument, baseRevision: string): Promise<ReplaceResult>;
2149
2271
  }
2150
2272
  /**
2151
2273
  * `"reconcile"` (ticket #24) means the server authoritatively resolved the
@@ -2169,6 +2291,10 @@ interface PersistenceDiagnostic {
2169
2291
  rejectedOpIds: readonly string[];
2170
2292
  revision: string;
2171
2293
  }
2294
+ /** Emitted as `"collaboration-ops-acknowledged"` (Phase 7) — the server has confirmed receipt of these op ids on the live pipe. */
2295
+ interface CollaborationAckDiagnostic {
2296
+ opIds: readonly string[];
2297
+ }
2172
2298
  interface ControllerOp {
2173
2299
  id: string;
2174
2300
  schemaVersion: 1;
@@ -2185,7 +2311,39 @@ interface ControllerOp {
2185
2311
  | "order";
2186
2312
  objectId: string;
2187
2313
  payload?: unknown;
2314
+ /**
2315
+ * This op's position in its own originating client's local sequence
2316
+ * (Phase 7) — 1, 2, 3, ... per controller instance, distinct from `id`
2317
+ * (an opaque, globally-unique identifier used for dedup/ack, not
2318
+ * ordering) and from a server's own authoritative ordering (e.g.
2319
+ * `referenceCollaborationServer.ts`'s per-room `version` counter).
2320
+ * Present on every op this SDK originates locally; a remote peer's op
2321
+ * carries whatever its own origin set, unchanged — never renumbered in
2322
+ * transit. Absent on an op minted by decoding the legacy wire envelope
2323
+ * (`scrawlOpEnvelope.ts`), which predates this field and has no
2324
+ * per-client sequence concept of its own.
2325
+ */
2326
+ clientSequence?: number;
2327
+ /**
2328
+ * The `CollaboratorIdentity.id` of this op's originating client (Phase
2329
+ * 7) — set for every op this SDK originates locally when `identity` is
2330
+ * configured, omitted entirely otherwise (never sent as `undefined`).
2331
+ * The explicit foundation for a future per-author undo filter (a local
2332
+ * user's own undo should only ever touch their own ops) — no undo-stack
2333
+ * behavior itself changes this phase.
2334
+ */
2335
+ clientId?: string;
2188
2336
  }
2337
+ /**
2338
+ * The one sanctioned seam for real-time multiplayer — implement this against
2339
+ * a Host's own collaboration backend (WebSocket relay, CRDT server, etc.).
2340
+ * `connect()` is called once per controller with the local user's
2341
+ * `identity` and a `receive` callback the adapter invokes with incoming
2342
+ * Ops, presence updates, acks, and connection status; it resolves with a
2343
+ * `CollaborationSession` the controller uses to send local Ops and presence
2344
+ * back out. Passed via `createBoardController({ adapters: { collaboration } })`;
2345
+ * omit it entirely to run single-player.
2346
+ */
2189
2347
  interface CollaborationAdapter {
2190
2348
  connect(options: DocumentContext & {
2191
2349
  identity: CollaboratorIdentity;
@@ -2196,14 +2354,72 @@ interface CollaboratorIdentity {
2196
2354
  id: string;
2197
2355
  name: string;
2198
2356
  color?: string;
2357
+ /** Host-supplied extras (avatar URL, role, etc.) — opaque to Scrawl, forwarded into any resulting `PresenceUser` unread and never interpreted. */
2358
+ metadata?: Record<string, unknown>;
2199
2359
  }
2200
2360
  interface CollaborationReceiver {
2201
2361
  ops(ops: readonly ControllerOp[]): void;
2362
+ /**
2363
+ * The current presence roster (Phase 6, ADR 0015) — always a full
2364
+ * replacement, never a delta, matching `presence.sync`'s existing
2365
+ * semantics exactly (an adapter that aggregates wire deltas into a full
2366
+ * roster before calling this is the adapter's own job, not the
2367
+ * controller's). Required on this interface (not optional) because a
2368
+ * Host only ever *consumes* `CollaborationReceiver` — never implements
2369
+ * it — so adding a required method here cannot break an existing custom
2370
+ * `CollaborationAdapter`. An adapter with no presence support simply
2371
+ * never calls it.
2372
+ */
2373
+ presence(users: readonly PresenceUser[]): void;
2374
+ /**
2375
+ * The server has confirmed receipt of these op ids (Phase 7) —
2376
+ * distinguishes "sent" from "server accepted," which `sendOps` alone
2377
+ * (fire-and-forget) cannot. Required for the same reason `presence` is:
2378
+ * Hosts only ever consume this interface, never implement it, so this
2379
+ * cannot break an existing custom `CollaborationAdapter`. An adapter with
2380
+ * no ack support simply never calls it — the collaboration pipe still
2381
+ * works exactly as it did before this existed, just without the
2382
+ * bookkeeping/observability this enables.
2383
+ */
2384
+ acknowledged(opIds: readonly string[]): void;
2202
2385
  status(state: "online" | "reconnecting" | "offline"): void;
2203
2386
  error(cause: unknown): void;
2204
2387
  }
2388
+ /**
2389
+ * Result of `CollaborationSession.requestSync()` (Phase 7). `"ops"` means
2390
+ * the adapter's own live-pipe cache fully covered the gap since the
2391
+ * caller's last known revision — apply `ops` and the client is caught up,
2392
+ * no persistence reload needed. `"unavailable"` means it couldn't (gap too
2393
+ * large, server restarted, or the adapter has no retained history at all)
2394
+ * — the caller must fall back to a persistence-backed reload. This is a
2395
+ * best-effort *liveness* cache, deliberately never a durable source of
2396
+ * truth (ADR 0006's "collaboration is never a second source of document
2397
+ * truth" — see ADR 0015's own extension of that principle to presence,
2398
+ * now extended once more, the same way, to this).
2399
+ */
2400
+ type CollaborationSyncResult = {
2401
+ state: "ops";
2402
+ ops: readonly ControllerOp[];
2403
+ serverRevision: string;
2404
+ } | {
2405
+ state: "unavailable";
2406
+ };
2205
2407
  interface CollaborationSession {
2206
2408
  sendOps(ops: readonly ControllerOp[]): void;
2409
+ /**
2410
+ * Publishes this client's own local presence (Phase 6, ADR 0015) —
2411
+ * best-effort, unordered, never persisted, never an Op. Optional: an
2412
+ * adapter that doesn't support presence simply omits this method, and
2413
+ * `presence.broadcast()` becomes a silent no-op.
2414
+ */
2415
+ updatePresence?(presence: LocalPresence): void;
2416
+ /**
2417
+ * Requests an incremental catch-up after a reconnect (Phase 7) — optional;
2418
+ * an adapter that doesn't support this simply omits the method, and the
2419
+ * caller (`resyncAfterReconnect`) goes straight to its existing
2420
+ * persistence-backed full reload, unchanged from Phase 6.
2421
+ */
2422
+ requestSync?(): Promise<CollaborationSyncResult>;
2207
2423
  close(): Promise<void>;
2208
2424
  }
2209
2425
  interface CreateBoardControllerOptions {
@@ -2243,6 +2459,87 @@ interface CreateBoardControllerOptions {
2243
2459
  * doesn't use the React theme system can set this directly instead.
2244
2460
  */
2245
2461
  boardTheme?: BoardThemeOptions;
2462
+ /**
2463
+ * Debounced auto-flush of pending persistence Ops after document changes
2464
+ * settle (Phase 5). Enabled by default (1000ms debounce) whenever
2465
+ * `adapters.persistence` is configured — today, without this, a Host must
2466
+ * call `flush()` manually after every edit for anything to persist. Pass
2467
+ * `false` to opt out entirely and drive `flush()` yourself, preserving
2468
+ * prior behavior exactly. Never fires on a per-change basis — rapid edits
2469
+ * coalesce into one flush of their final state (ADR 0006).
2470
+ */
2471
+ autosave?: boolean | {
2472
+ debounceMs?: number;
2473
+ };
2474
+ /**
2475
+ * Throttle for `presence.broadcast()` (Phase 6, ADR 0015) — the minimum
2476
+ * interval between outgoing presence updates sent via the configured
2477
+ * `CollaborationAdapter`. Defaults to 50ms. A trailing throttle: the
2478
+ * latest value passed to `broadcast()` always eventually sends, even if
2479
+ * calls arrive faster than this interval.
2480
+ */
2481
+ presenceThrottleMs?: number;
2482
+ /**
2483
+ * Caps how many `ControllerOp`s can sit queued, unsent, for the
2484
+ * persistence pipe (`pendingOps`) or the collaboration pipe
2485
+ * (`pendingCollaborationOps`) at once (Phase 7) — each pipe is capped
2486
+ * independently. Prevents unbounded memory growth from a long-lived
2487
+ * offline session or a stuck adapter. Exceeding it never fails or drops
2488
+ * the local edit itself (the Document already applied it optimistically)
2489
+ * — only queueing for that one pipe is skipped, and a
2490
+ * `{code:"queue-overflow", retryable:false}` error is emitted so a Host
2491
+ * can react. Defaults to 1000 — the Phase 9 collaboration coalescing
2492
+ * above (`collaborationCoalesceMs`) already keeps a busy drag from
2493
+ * approaching this on its own, so hitting it in practice means a pipe
2494
+ * has been offline/stuck for a genuinely long editing session.
2495
+ *
2496
+ * **Recovery** (Phase 9): the dropped op itself is gone from that one
2497
+ * pipe's queue — there is no automatic backfill, and the live
2498
+ * controller keeps running with that pipe now silently missing one
2499
+ * edit. Two things stay true regardless: (1) the in-memory Document is
2500
+ * never affected — a queue-overflow can never corrupt or roll back a
2501
+ * local edit, only skip sending it; (2) staleness is per-object, not
2502
+ * permanent — any *later* edit to that same object produces a brand
2503
+ * new, undropped Op carrying its full current state, which naturally
2504
+ * supersedes the gap (the Op model is already last-write-wins/
2505
+ * idempotent, so a superseding Op doesn't need the earlier one to have
2506
+ * arrived). The real risk is an object that's dropped and never edited
2507
+ * again before the controller is disposed or the page reloads — a Host
2508
+ * that needs strict durability should treat `queue-overflow` as a
2509
+ * signal to check `persistence.state`/`pendingOps` pressure (via
2510
+ * `usePersistenceStatus`/`getSnapshot().connection.persistence`)
2511
+ * before disposing, not assume disposing and reconnecting alone
2512
+ * repairs the gap (a fresh `load()` only returns what the backend
2513
+ * already has, which is exactly what's missing the dropped edit).
2514
+ */
2515
+ maxPendingOps?: number;
2516
+ /**
2517
+ * Coalescing window (ms) for outgoing collaboration Ops (Phase 9) — same
2518
+ * trailing-throttle shape as `presenceThrottleMs`: the first Op after an
2519
+ * idle period sends immediately, and subsequent Ops for the *same*
2520
+ * object within this window replace each other (latest value wins,
2521
+ * matching the already-idempotent Op model) rather than each triggering
2522
+ * its own send. A multi-second drag that previously sent one full Op per
2523
+ * pointer-move now sends at most one per window per touched object.
2524
+ * Persistence (`pendingOps`) is unaffected — it already debounces via
2525
+ * `autosave`, so this option only changes live collaboration traffic.
2526
+ * Defaults to 50ms.
2527
+ */
2528
+ collaborationCoalesceMs?: number;
2529
+ /**
2530
+ * Caps how many resolved objects a single `content.copy`/`content.cut`
2531
+ * (or their Cmd/Ctrl+C/X keyboard equivalents) will hold in the
2532
+ * in-memory clipboard at once (Phase 9) — `expandSelection` recursively
2533
+ * expands groups, so an unbounded selection (a huge group, or thousands
2534
+ * of individually selected strokes) could otherwise clone and retain an
2535
+ * arbitrarily large snapshot indefinitely, until the next copy/cut
2536
+ * replaces it. Exceeding it rejects the whole copy/cut (nothing is
2537
+ * cloned, and — for cut — nothing is removed from the Document either,
2538
+ * never a partial copy of an arbitrary subset) and emits a
2539
+ * `{code:"clipboard-overflow", retryable:false}` error. Defaults to
2540
+ * 5000.
2541
+ */
2542
+ maxClipboardItems?: number;
2246
2543
  }
2247
2544
  interface BoardController {
2248
2545
  readonly document: ReadonlyBoardDocument;
@@ -2274,6 +2571,15 @@ interface BoardController {
2274
2571
  };
2275
2572
  readonly view: {
2276
2573
  fit(): void;
2574
+ /**
2575
+ * Frame the current selection (Phase 8), the same way `fit()` frames the
2576
+ * whole board. A no-op with nothing selected — deliberately doesn't fall
2577
+ * back to `fit()`'s "frame everything," which would be a surprising
2578
+ * result for an empty selection. On a headless board this can only
2579
+ * re-center the view (no viewport to compute a real zoom-to-fit from),
2580
+ * matching `fit()`'s own headless limitation exactly.
2581
+ */
2582
+ zoomToSelection(): void;
2277
2583
  zoomTo(value: number): void;
2278
2584
  centerOn(point: BoardPoint): void;
2279
2585
  get(): BoardView;
@@ -2345,6 +2651,14 @@ interface BoardController {
2345
2651
  * aren't listed separately. `[]` when the clipboard is empty.
2346
2652
  */
2347
2653
  paste(): readonly string[];
2654
+ /**
2655
+ * Select every top-level object (Phase 8) — a group's own id stands for
2656
+ * its children, which aren't selected separately, matching `paste`'s own
2657
+ * "what the user sees" id list. Hidden objects are excluded, consistent
2658
+ * with them already being excluded from marquee selection. Works with
2659
+ * no canvas/engine, same as {@link toggleSelectionVisibility}.
2660
+ */
2661
+ selectAll(): void;
2348
2662
  table: {
2349
2663
  addRow(tableId: string): void;
2350
2664
  addCol(tableId: string): void;
@@ -2363,6 +2677,21 @@ interface BoardController {
2363
2677
  * another collaborator who isn't the current lock holder.
2364
2678
  */
2365
2679
  toggleSelectionLock(): void;
2680
+ /**
2681
+ * Toggle hidden state for the current selection, as one undo entry
2682
+ * (Phase 8). If any selected object is hidden, shows every selected
2683
+ * object; otherwise hides them all — same "any wins" semantics as
2684
+ * {@link toggleSelectionLock}. Hidden objects stay fully present in the
2685
+ * document (they still serialize, persist, sync, undo/redo) — they just
2686
+ * stop rendering and stop being hit-testable/selectable via pointer
2687
+ * interaction. Unlike `toggleSelectionLock`, this works on a headless
2688
+ * board too: it only touches `selection`/the document, no canvas or
2689
+ * engine involved. Custom objects have no visibility concept (no
2690
+ * `Hideable` field) and are silently skipped, matching how
2691
+ * `toggleSelectionLock` already excludes them. A no-op with nothing
2692
+ * selected or when the selection is only custom objects.
2693
+ */
2694
+ toggleSelectionVisibility(): void;
2366
2695
  };
2367
2696
  readonly query: {
2368
2697
  get(id: string): DeepReadonly<BoardObject> | undefined;
@@ -2391,6 +2720,15 @@ interface BoardController {
2391
2720
  follow(view: PresenceView): void;
2392
2721
  /** Ease the camera to a peer's view; returns false (no-op) while mid-stroke. */
2393
2722
  gather(view: PresenceView): boolean;
2723
+ /**
2724
+ * Publishes this client's own cursor/tool/view for other collaborators
2725
+ * (Phase 6, ADR 0015), via the configured `CollaborationAdapter` —
2726
+ * throttled internally (`presenceThrottleMs` option, default 50ms) so
2727
+ * a raw pointermove stream never becomes a message-per-event flood. A
2728
+ * no-op if no collaboration adapter is configured, or if the
2729
+ * configured one doesn't implement `updatePresence`.
2730
+ */
2731
+ broadcast(local: LocalPresence): void;
2394
2732
  };
2395
2733
  readonly export: {
2396
2734
  svg(): string;
@@ -2416,7 +2754,19 @@ interface BoardController {
2416
2754
  }>;
2417
2755
  dispose(): Promise<void>;
2418
2756
  }
2757
+ /**
2758
+ * Creates a {@link BoardController} — the SDK's canonical, capability-grouped
2759
+ * entry point (`content`, `tools`, `style`, `history`, `view`, `query`,
2760
+ * `comments`, `presence`, `export`, `assets`, plus top-level `getSnapshot`/
2761
+ * `subscribe`/`on`/`setReadOnly`/`flush`/`dispose`) for driving a Board
2762
+ * imperatively from any JS/TS runtime. Supply a `canvas` to render, or omit
2763
+ * it to run headless (SSR, tests, or a document/history-only integration).
2764
+ * Persistence and Collaboration are opt-in via `options.adapters` — without
2765
+ * them the controller runs entirely in memory. Call `dispose()` when done to
2766
+ * release the renderer, adapters, and any pending timers.
2767
+ */
2419
2768
  declare function createBoardController(options: CreateBoardControllerOptions): BoardController;
2769
+ /** @deprecated Use `BoardController.getSnapshot()`'s return type instead. */
2420
2770
  type LocalBoardSnapshot = {
2421
2771
  documentId: string;
2422
2772
  selectedStrokeId: string | null;
@@ -2425,10 +2775,12 @@ type LocalBoardSnapshot = {
2425
2775
  canRedo: boolean;
2426
2776
  disposed: boolean;
2427
2777
  };
2778
+ /** @deprecated Use `CreateBoardControllerOptions` with `createBoardController` instead. */
2428
2779
  type LocalBoardOptions = {
2429
2780
  documentId: string;
2430
2781
  initialDocument?: SerializedBoardDocument;
2431
2782
  };
2783
+ /** @deprecated Use `BoardController` (from `createBoardController`) instead — this stroke-only, single-tool surface predates the full capability-grouped controller. */
2432
2784
  type LocalBoard = {
2433
2785
  drawStroke(stroke: Stroke): void;
2434
2786
  selectAt(point: BoardPoint): string | null;
@@ -2439,8 +2791,21 @@ type LocalBoard = {
2439
2791
  subscribe(listener: () => void): () => void;
2440
2792
  dispose(): Promise<void>;
2441
2793
  };
2794
+ /** @deprecated Use `createBoardController` instead — this is a thin, stroke-only wrapper kept for the original Phase 1 tracer's compatibility. */
2442
2795
  declare function createLocalBoard(options: LocalBoardOptions): LocalBoard;
2443
2796
 
2797
+ interface CreateMemoryPersistenceOptions {
2798
+ /** Pre-seeded documents, keyed by document id — as if a prior session had already saved them. Seeded documents start at revision "1". */
2799
+ seed?: Record<string, CurrentSerializedDocument>;
2800
+ }
2801
+ /**
2802
+ * Creates a real, in-memory `PersistenceAdapter`. One instance can back
2803
+ * multiple documents (keyed by `DocumentContext.documentId`, like every
2804
+ * other adapter in this package). State lives only in this instance —
2805
+ * discarded on garbage collection, never written to disk.
2806
+ */
2807
+ declare function createMemoryPersistence(options?: CreateMemoryPersistenceOptions): PersistenceAdapter;
2808
+
2444
2809
  type ScrawlThemePreset = "light" | "dark";
2445
2810
  type ScrawlDensity = "comfortable" | "compact";
2446
2811
  type ScrawlGridMode = "none" | "line" | "dot";
@@ -2683,6 +3048,16 @@ interface ScrawlProviderProps {
2683
3048
  className?: string;
2684
3049
  style?: ThemeStyle;
2685
3050
  }
3051
+ /**
3052
+ * Wraps a Board `controller` you created yourself (via `createBoardController`)
3053
+ * so its descendants can use `useScrawlController`/`useScrawlSnapshot`/etc.
3054
+ * and render its default UI pieces (`DefaultBoardChrome`, `StyleShelf`, ...).
3055
+ * Prefer `Scrawl` unless you need to construct or own the controller's
3056
+ * lifecycle yourself (e.g. you create it outside React, or need it before
3057
+ * first render). Set `disposeOnUnmount` to have this provider call
3058
+ * `controller.dispose()` on unmount; otherwise disposal remains your own
3059
+ * responsibility.
3060
+ */
2686
3061
  declare function ScrawlProvider({ controller, children, preset, theme, portalContainer: customPortal, disposeOnUnmount, onThemeDiagnostic, className, style }: ScrawlProviderProps): react.JSX.Element;
2687
3062
  interface ScrawlProps extends Omit<CreateBoardControllerOptions, "canvas"> {
2688
3063
  children?: ReactNode;
@@ -2703,6 +3078,17 @@ interface ScrawlProps extends Omit<CreateBoardControllerOptions, "canvas"> {
2703
3078
  */
2704
3079
  icons?: Partial<Record<BuiltInTool, ReactNode>>;
2705
3080
  }
3081
+ /**
3082
+ * The fastest path to an embedded Board: creates and owns a
3083
+ * `BoardController` for you (constructed once, disposed on unmount) and
3084
+ * renders it into a canvas. Render with no `children` to get the SDK's
3085
+ * default toolbar/UI chrome, or supply your own `children` (using the
3086
+ * `useScrawlController`/`useScrawlSnapshot` hooks, or the exported
3087
+ * `DefaultBoardChrome`/`StyleShelf`/etc. pieces) to build a custom UI on
3088
+ * top of the same controller. Accepts every `CreateBoardControllerOptions`
3089
+ * field except `canvas` (pass `canvas={null}` for a headless board, or an
3090
+ * existing `<canvas>` element to control its identity yourself).
3091
+ */
2706
3092
  declare function Scrawl({ children, preset, theme, portalContainer, className, style, onReady, onError, onThemeDiagnostic, canvas: suppliedCanvas, icons, ...options }: ScrawlProps): react.JSX.Element;
2707
3093
  interface ScrawlCanvasProps {
2708
3094
  element?: HTMLCanvasElement;
@@ -2728,6 +3114,38 @@ declare function ScrawlPortal({ children }: {
2728
3114
  declare function useScrawlController(): BoardController;
2729
3115
  declare function useScrawlTheme(): ScrawlResolvedTheme;
2730
3116
  declare function useScrawlSnapshot(): BoardSnapshot;
3117
+ /**
3118
+ * A thin, purely-derived convenience over
3119
+ * `useScrawlSnapshot().connection.persistence` (Phase 5) — for a Host
3120
+ * component that only cares about save status (e.g. a
3121
+ * "Saving…"/"Saved"/"Offline" indicator) and would otherwise re-derive
3122
+ * this same field access itself. Adds no state and no behavior of its
3123
+ * own: React still owns none of persistence, exactly as before — this
3124
+ * hook only re-reads what the controller already tracks.
3125
+ *
3126
+ * Deliberately does *not* go through `useScrawlSnapshot()` (Phase 9):
3127
+ * `changed()` rebuilds the whole `BoardSnapshot` — including a fresh
3128
+ * `connection.persistence` object — on every document mutation, even ones
3129
+ * that never touch persistence at all, so a component using only this
3130
+ * hook would otherwise re-render on every stroke draw. `useSyncStatus`
3131
+ * below memoizes on the value (`state`/`error`), not just the object
3132
+ * reference, and returns the same cached value across renders where
3133
+ * nothing relevant changed — the same shape `usePresence` already uses
3134
+ * for its own independently-scoped store.
3135
+ */
3136
+ declare function usePersistenceStatus(): PersistenceSnapshot;
3137
+ /** The `CollaborationSnapshot` equivalent of `usePersistenceStatus` (Phase 6) — same value-memoized convenience over `useScrawlSnapshot().connection.collaboration` (Phase 9: see `usePersistenceStatus`'s doc comment for why it doesn't derive from the full snapshot). */
3138
+ declare function useCollaborationStatus(): CollaborationSnapshot;
3139
+ /**
3140
+ * The current presence roster (Phase 6), live-updating — wraps
3141
+ * `controller.presence.list()`/`subscribe` the same way `useScrawlSnapshot`
3142
+ * wraps the controller's main snapshot, via `useSyncExternalStore`. Does
3143
+ * not re-render on every remote pointer move by itself; it re-renders
3144
+ * whenever the roster the controller already tracks changes, at whatever
3145
+ * rate that arrives at (throttled adapter-side, per `presenceThrottleMs`).
3146
+ */
3147
+ declare function usePresence(): readonly PresenceUser[];
3148
+ /** @deprecated Use `Scrawl` instead — this predates the full capability-grouped `BoardController` and only exposes the stroke-only `LocalBoard` surface. */
2731
3149
  type ScrawlBoardProps = {
2732
3150
  documentId: string;
2733
3151
  initialDocument?: SerializedBoardDocument;
@@ -2735,7 +3153,8 @@ type ScrawlBoardProps = {
2735
3153
  className?: string;
2736
3154
  style?: CSSProperties;
2737
3155
  };
3156
+ /** @deprecated Use `Scrawl` instead — this predates the full capability-grouped `BoardController` and only exposes the stroke-only `LocalBoard` surface. */
2738
3157
  declare function ScrawlBoard({ documentId, initialDocument, onReady, className, style }: ScrawlBoardProps): react.JSX.Element;
2739
3158
 
2740
- export { ASSET_CACHE_BYTES_DEFAULT, ASSET_CACHE_BYTES_MAX, ASSET_CACHE_BYTES_MIN, ASSET_EXPORT_MAX_DECODED_MEGAPIXELS, ASSET_EXPORT_MAX_ENCODED_BYTES, ASSET_MAX_CONCURRENT_RESOLUTIONS, ASSET_MAX_DECODED_MEGAPIXELS, ASSET_MAX_DIMENSION_PX, ASSET_MAX_ENCODED_BYTES, ASSET_REF_MAX_BYTES, ASSET_REF_PATTERN, AddArrowCommand, AddEllipseCommand, AddGroupCommand, AddHeartCommand, AddImageCommand, AddLineCommand, AddNoteCommand, AddPolygonCommand, AddRectangleCommand, AddStarCommand, AddStrokesCommand, AddTableCommand, AddTextCommand, AddTimerCommand, AssetResolutionError, BEACON_INSET, BoardDocument, CURRENT_DOCUMENT_SCHEMA_VERSION, ClusterStore, CommandBatch, DefaultBoardChrome, DeleteArrowCommand, DeleteEllipseCommand, DeleteGroupCommand, DeleteHeartCommand, DeleteImageCommand, DeleteLineCommand, DeleteNoteCommand, DeletePolygonCommand, DeleteRectangleCommand, DeleteStarCommand, DeleteStrokesCommand, DeleteTableCommand, DeleteTextCommand, DeleteTimerCommand, DocumentRecoveryError, END_TAPER, ERASE_THRESHOLD, EraseCommand, FOG_COLOR, FocusedItemToolbar, HIGHLIGHT_COLORS, History, IDENTITY, INK_COLORS, InlineEditors, LockItemsCommand, MIN_WIDTH_FACTOR, MultiplayerCursors, NOTE_COLORS, NOTE_DEFAULT_SIZE, NOTE_DEFAULT_Z, NOTE_MAX_Z, NOTE_MIN_Z, NOTE_PEEL_STEP, ReorderObjectCommand, SDK_DEVELOPMENT_VERSION, SDK_PACKAGE_NAME, SHAPE_DEFAULT_STROKE, SHAPE_DEFAULT_STROKE_WIDTH, SHAPE_MIN_SIZE, STAMPS, STAMP_SIZE, SUPPORTED_ASSET_MEDIA_TYPES, Scrawl, ScrawlBoard, ScrawlCanvas, ScrawlDefaultUI, ScrawlPortal, ScrawlProvider, SpatialIndex, StyleShelf, TABLE_DEFAULT_CELL_HEIGHT, TABLE_DEFAULT_CELL_WIDTH, TABLE_DEFAULT_FONT_SIZE, TEXT_DEFAULT_SIZE, TIMER_DEFAULT_DURATION_MS, TIMER_DEFAULT_SIZE, TIMER_PRESETS_MS, TransformCommand, TransformObjectsCommand, UpdateArrowCommand, UpdateEllipseCommand, UpdateGroupCommand, UpdateHeartCommand, UpdateImageCommand, UpdateLineCommand, UpdateNoteCommand, UpdatePolygonCommand, UpdateRectangleCommand, UpdateStarCommand, UpdateTableCommand, UpdateTextCommand, UpdateTimerCommand, apply, applyItemLock, assetRef, avgScale, canUnlockItem, changeToOps, clampAssetCacheBytes, cloneArrow, cloneCustomObject, cloneEllipse, cloneGroup, cloneHeart, cloneImage, cloneLine, cloneNote, clonePolygon, cloneRectangle, cloneStar, cloneStroke, cloneTable, cloneText, cloneTimer, createBoardController, createLocalBoard, documentId, documentToSVG, formatTimer, invert, isAssetRef, isIdentity, isStampKind, loadDocumentBytes, measureTable, measureTextBlock, migrateDocument, mul, pauseTimer, placePresenceBeacon, resolveScrawlTheme, ribbonEdges, rotationAbout, scalingAbout, scrawlThemePresets, searchBoard, serializeDocument, serializeLock, serializeStroke, setTimerDuration, stampDataUrl, startTimer, strokeId, timerExpired, timerRemaining, toggleTimer, translation, useScrawlController, useScrawlSnapshot, useScrawlTheme, validateScrawlTheme };
2741
- export type { ApplyOpsResult, ArrowHeadStyle, ArrowObject, AssetDiagnostic, AssetIngestRequest, AssetIngestResult, AssetIngestor, AssetKind, AssetPurpose, AssetRef, AssetResolutionErrorCode, AssetResolveRequest, AssetResolveResult, AssetResolver, BBox, BoardController, BoardControllerError, BoardEventMap, BoardKeyInput, BoardObject, BoardObjectInput, BoardObjectPatch, BoardPoint, BoardPointerInput, BoardScene, BoardSlotProps, BoardSnapshot, BoardStroke, BoardStyle, BoardThemeOptions, BoardView, BuiltInTool, ClusterIdFactory, CollaborationAdapter, CollaborationReceiver, CollaborationSession, CollaborationSnapshot, CollaboratorIdentity, Command, CommandKind, CommentMarker, ControllerOp, CreateBoardControllerOptions, CurrentSerializedDocument, CurrentSerializedStroke, CustomBoardObject, CustomObjectAddInput, CustomObjectDefinition, CustomTool, CustomToolDefinition, DeepReadonly, DefaultBoardChromeProps, DefaultUIRegion, DefaultUISlot, DefaultUISlots, DialogSlotProps, DocumentChange, DocumentContext, DocumentId, DocumentLoadResult, DocumentRecoveryCode, EllipseObject, ExtensionCommand, ExtensionDiagnostic, ExtensionHitResult, ExtensionId, ExtensionRequirement, FocusedItem, FocusedItemToolbarProps, GroupObject, HeartObject, ImageBlock, InlineEditorsProps, InputModifiers, JsonObject, JsonValue, KitchenTimer, LineObject, LoadResult, LocalBoard, LocalBoardOptions, LocalBoardSnapshot, LockHolder, LockTarget, Lockable, Mat2x3, MultiplayerCursorsProps, NoteVote, ObjectDescribeContext, ObjectIntent, ObjectType, Op, OpCollection, PersistenceAdapter, PersistenceDiagnostic, PersistenceSnapshot, PolygonObject, PresenceCursor, PresencePlacement, PresenceUser, PresenceView, QueryableBoardObject, ReadonlyBoardDocument, ReadonlyCustomObject, ReadonlyDocumentChange, RectangleObject, ReorderDirection, RibbonEdgePoint, SceneEllipse, SceneGroup, SceneImage, ScenePath, SceneRect, SceneText, ScrawlBoardProps, ScrawlCanvasProps, ScrawlDefaultUIProps, ScrawlDensity, ScrawlExtension, ScrawlGridMode, ScrawlProps, ScrawlProviderProps, ScrawlResolvedTheme, ScrawlSurfaceTexture, ScrawlTheme, ScrawlThemeDiagnostic, ScrawlThemePreset, ScreenPoint, ScreenRect, SearchHit, SearchHitKind, SearchableBoard, SearchableComment, SerializedBoardDocument, SerializedBoardStroke, SerializedPoint, SerializedStroke, StampKind, StarObject, StickyNote, Stroke, StrokeId, StrokePoint, StrokeTool, StyleShelfProps, SupportedAssetMediaType, TableBlock, TextBlock, ToolCancelReason, ToolCapabilities, ToolCursor, ToolId, ViewportInset };
3159
+ export { ASSET_CACHE_BYTES_DEFAULT, ASSET_CACHE_BYTES_MAX, ASSET_CACHE_BYTES_MIN, ASSET_EXPORT_MAX_DECODED_MEGAPIXELS, ASSET_EXPORT_MAX_ENCODED_BYTES, ASSET_MAX_CONCURRENT_RESOLUTIONS, ASSET_MAX_DECODED_MEGAPIXELS, ASSET_MAX_DIMENSION_PX, ASSET_MAX_ENCODED_BYTES, ASSET_REF_MAX_BYTES, ASSET_REF_PATTERN, AddArrowCommand, AddEllipseCommand, AddGroupCommand, AddHeartCommand, AddImageCommand, AddLineCommand, AddNoteCommand, AddPolygonCommand, AddRectangleCommand, AddStarCommand, AddStrokesCommand, AddTableCommand, AddTextCommand, AddTimerCommand, AssetResolutionError, BEACON_INSET, BoardDocument, CURRENT_DOCUMENT_SCHEMA_VERSION, ClusterStore, CommandBatch, DefaultBoardChrome, DeleteArrowCommand, DeleteEllipseCommand, DeleteGroupCommand, DeleteHeartCommand, DeleteImageCommand, DeleteLineCommand, DeleteNoteCommand, DeletePolygonCommand, DeleteRectangleCommand, DeleteStarCommand, DeleteStrokesCommand, DeleteTableCommand, DeleteTextCommand, DeleteTimerCommand, DocumentRecoveryError, END_TAPER, ERASE_THRESHOLD, EraseCommand, FOG_COLOR, FocusedItemToolbar, HIGHLIGHT_COLORS, History, IDENTITY, INK_COLORS, InlineEditors, LockItemsCommand, MIN_WIDTH_FACTOR, MultiplayerCursors, NOTE_COLORS, NOTE_DEFAULT_SIZE, NOTE_DEFAULT_Z, NOTE_MAX_Z, NOTE_MIN_Z, NOTE_PEEL_STEP, ReorderObjectCommand, SDK_DEVELOPMENT_VERSION, SDK_PACKAGE_NAME, SHAPE_DEFAULT_STROKE, SHAPE_DEFAULT_STROKE_WIDTH, SHAPE_MIN_SIZE, SHAPE_STYLE_DEFAULTS, STAMPS, STAMP_SIZE, SUPPORTED_ASSET_MEDIA_TYPES, Scrawl, ScrawlBoard, ScrawlCanvas, ScrawlDefaultUI, ScrawlPortal, ScrawlProvider, SpatialIndex, StyleShelf, TABLE_DEFAULT_CELL_HEIGHT, TABLE_DEFAULT_CELL_WIDTH, TABLE_DEFAULT_FONT_SIZE, TEXT_DEFAULT_SIZE, TIMER_DEFAULT_DURATION_MS, TIMER_DEFAULT_SIZE, TIMER_PRESETS_MS, TransformCommand, TransformObjectsCommand, UpdateArrowCommand, UpdateEllipseCommand, UpdateGroupCommand, UpdateHeartCommand, UpdateImageCommand, UpdateLineCommand, UpdateNoteCommand, UpdatePolygonCommand, UpdateRectangleCommand, UpdateStarCommand, UpdateTableCommand, UpdateTextCommand, UpdateTimerCommand, apply, applyItemLock, assetRef, avgScale, canUnlockItem, changeToOps, clampAssetCacheBytes, cloneArrow, cloneCustomObject, cloneEllipse, cloneGroup, cloneHeart, cloneImage, cloneLine, cloneNote, clonePolygon, cloneRectangle, cloneStar, cloneStroke, cloneTable, cloneText, cloneTimer, createBoardController, createLocalBoard, createMemoryPersistence, documentId, documentSize, documentToSVG, formatTimer, invert, isAssetRef, isIdentity, isStampKind, loadDocumentBytes, measureTable, measureTextBlock, migrateDocument, mul, pauseTimer, placePresenceBeacon, resolveScrawlTheme, ribbonEdges, rotationAbout, scalingAbout, scrawlThemePresets, searchBoard, serializeDocument, serializeLock, serializeStroke, setTimerDuration, stampDataUrl, startTimer, strokeId, timerExpired, timerRemaining, toggleTimer, translation, useCollaborationStatus, usePersistenceStatus, usePresence, useScrawlController, useScrawlSnapshot, useScrawlTheme, validateScrawlTheme };
3160
+ export type { ApplyOpsResult, ArrowHeadStyle, ArrowObject, AssetDiagnostic, AssetExportFailure, AssetIngestRequest, AssetIngestResult, AssetIngestor, AssetKind, AssetPurpose, AssetRef, AssetResolutionErrorCode, AssetResolveRequest, AssetResolveResult, AssetResolver, BBox, BoardController, BoardControllerError, BoardEventMap, BoardKeyInput, BoardObject, BoardObjectInput, BoardObjectPatch, BoardPoint, BoardPointerInput, BoardScene, BoardSlotProps, BoardSnapshot, BoardStroke, BoardStyle, BoardThemeOptions, BoardView, BuiltInTool, ClusterIdFactory, CollaborationAckDiagnostic, CollaborationAdapter, CollaborationReceiver, CollaborationSession, CollaborationSnapshot, CollaborationSyncResult, CollaboratorIdentity, Command, CommandKind, CommentMarker, ControllerOp, CreateBoardControllerOptions, CreateMemoryPersistenceOptions, CurrentSerializedDocument, CurrentSerializedStroke, CustomBoardObject, CustomObjectAddInput, CustomObjectDefinition, CustomTool, CustomToolDefinition, DeepReadonly, DefaultBoardChromeProps, DefaultUIRegion, DefaultUISlot, DefaultUISlots, DialogSlotProps, DocumentChange, DocumentContext, DocumentId, DocumentLoadResult, DocumentRecoveryCode, EllipseObject, ExportDocumentSVGOptions, ExportDocumentSVGResult, ExtensionCommand, ExtensionDiagnostic, ExtensionHitResult, ExtensionId, ExtensionRequirement, FocusedItem, FocusedItemToolbarProps, GroupObject, HeartObject, ImageBlock, InlineEditorsProps, InputModifiers, JsonObject, JsonValue, KitchenTimer, LineObject, LoadResult, LocalBoard, LocalBoardOptions, LocalBoardSnapshot, LocalPresence, LockHolder, LockTarget, Lockable, Mat2x3, MultiplayerCursorsProps, NoteVote, ObjectDescribeContext, ObjectIntent, ObjectType, Op, OpCollection, PersistenceAdapter, PersistenceDiagnostic, PersistenceSnapshot, PolygonObject, PresenceCursor, PresencePlacement, PresenceUser, PresenceView, QueryableBoardObject, ReadonlyBoardDocument, ReadonlyCustomObject, ReadonlyDocumentChange, RectangleObject, ReorderDirection, ReplaceResult, RibbonEdgePoint, SceneEllipse, SceneGroup, SceneImage, ScenePath, SceneRect, SceneText, ScrawlBoardProps, ScrawlCanvasProps, ScrawlDefaultUIProps, ScrawlDensity, ScrawlExtension, ScrawlGridMode, ScrawlProps, ScrawlProviderProps, ScrawlResolvedTheme, ScrawlSurfaceTexture, ScrawlTheme, ScrawlThemeDiagnostic, ScrawlThemePreset, ScreenPoint, ScreenRect, SearchHit, SearchHitKind, SearchableBoard, SearchableComment, SerializedBoardDocument, SerializedBoardStroke, SerializedPoint, SerializedStroke, StampKind, StarObject, StickyNote, Stroke, StrokeId, StrokePoint, StrokeTool, StyleShelfProps, SupportedAssetMediaType, TableBlock, TextBlock, ToolCancelReason, ToolCapabilities, ToolCursor, ToolId, ViewportInset };