@tldraw/driver 5.3.2 → 5.4.0-canary.02cd0bd3b597

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.
@@ -4,7 +4,7 @@ import { SelectionHandle } from '@tldraw/editor';
4
4
  import { TLArrowShape } from '@tldraw/editor';
5
5
  import { TLContent } from '@tldraw/editor';
6
6
  import { TLKeyboardEventInfo } from '@tldraw/editor';
7
- import { TLPageId } from '@tldraw/editor';
7
+ import { TLPageId } from '@tldraw/tlschema';
8
8
  import { TLPinchEventInfo } from '@tldraw/editor';
9
9
  import { TLPointerEventInfo } from '@tldraw/editor';
10
10
  import { TLShape } from '@tldraw/editor';
@@ -25,12 +25,12 @@ export declare class Driver {
25
25
  readonly editor: Editor;
26
26
  /** The underlying Editor instance. */
27
27
  private _cleanup;
28
+ private _lastCreatedShapes;
28
29
  constructor(editor: Editor);
29
30
  /** Remove all registered side-effect handlers. Call when this controller is no longer needed. */
30
31
  dispose(): void;
31
32
  /** Local clipboard content. Used by copy, cut, and paste. */
32
33
  clipboard: null | TLContent;
33
- private _lastCreatedShapes;
34
34
  /**
35
35
  * Get the last created shapes.
36
36
  * @param count - The number of shapes to get.
@@ -89,6 +89,7 @@ export declare class Driver {
89
89
  * @param shapeId - The shape ID to find arrows bound to.
90
90
  */
91
91
  getArrowsBoundTo(shapeId: TLShapeId): TLArrowShape[];
92
+ private getModifierKeys;
92
93
  /**
93
94
  * Builds a TLPointerEventInfo object for input simulation.
94
95
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -162,37 +163,38 @@ export declare class Driver {
162
163
  * @param key - The key to press (e.g. 'a', 'Enter', 'Shift').
163
164
  * @param options - Partial keyboard event overrides.
164
165
  */
165
- keyPress(key: string, options?: Partial<Omit<TLKeyboardEventInfo, "key">>): this;
166
+ keyPress(key: string, options?: Partial<Omit<TLKeyboardEventInfo, 'key'>>): this;
166
167
  /**
167
168
  * Dispatches a key down event for the given key.
168
169
  * @param key - The key to press (e.g. 'a', 'Enter', 'Shift').
169
170
  * @param options - Partial keyboard event overrides.
170
171
  */
171
- keyDown(key: string, options?: Partial<Omit<TLKeyboardEventInfo, "key">>): this;
172
+ keyDown(key: string, options?: Partial<Omit<TLKeyboardEventInfo, 'key'>>): this;
172
173
  /**
173
174
  * Dispatches a key repeat event for the given key.
174
175
  * @param key - The key that is repeating (e.g. 'a', 'ArrowDown').
175
176
  * @param options - Partial keyboard event overrides.
176
177
  */
177
- keyRepeat(key: string, options?: Partial<Omit<TLKeyboardEventInfo, "key">>): this;
178
+ keyRepeat(key: string, options?: Partial<Omit<TLKeyboardEventInfo, 'key'>>): this;
178
179
  /**
179
180
  * Dispatches a key up event for the given key.
180
181
  * @param key - The key to release (e.g. 'a', 'Enter', 'Shift').
181
182
  * @param options - Partial keyboard event overrides.
182
183
  */
183
- keyUp(key: string, options?: Partial<Omit<TLKeyboardEventInfo, "key">>): this;
184
+ keyUp(key: string, options?: Partial<Omit<TLKeyboardEventInfo, 'key'>>): this;
184
185
  /**
185
186
  * Dispatches a wheel event with the given delta values.
186
187
  * @param dx - Horizontal scroll delta.
187
188
  * @param dy - Vertical scroll delta.
188
189
  * @param options - Partial wheel event overrides.
189
190
  */
190
- wheel(dx: number, dy: number, options?: Partial<Omit<TLWheelEventInfo, "delta">>): this;
191
+ wheel(dx: number, dy: number, options?: Partial<Omit<TLWheelEventInfo, 'delta'>>): this;
191
192
  /**
192
193
  * Pans the camera by the given offset (in page coordinates). Does nothing if camera is locked.
193
194
  * @param offset - The pan delta (x, y) in page coordinates.
194
195
  */
195
196
  pan(offset: VecLike): this;
197
+ private pinch;
196
198
  /**
197
199
  * Dispatches a pinch start event.
198
200
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -203,7 +205,7 @@ export declare class Driver {
203
205
  * @param dz - Delta z for pinch.
204
206
  * @param options - Partial pinch event overrides.
205
207
  */
206
- pinchStart(x: number | undefined, y: number | undefined, z: number, dx: number, dy: number, dz: number, options?: Partial<Omit<TLPinchEventInfo, "delta" | "offset" | "point">>): this;
208
+ pinchStart(x: number | undefined, y: number | undefined, z: number, dx: number, dy: number, dz: number, options?: Partial<Omit<TLPinchEventInfo, 'delta' | 'offset' | 'point'>>): this;
207
209
  /**
208
210
  * Dispatches a pinch move event (pinch_to).
209
211
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -214,7 +216,7 @@ export declare class Driver {
214
216
  * @param dz - Delta z for pinch.
215
217
  * @param options - Partial pinch event overrides.
216
218
  */
217
- pinchTo(x: number | undefined, y: number | undefined, z: number, dx: number, dy: number, dz: number, options?: Partial<Omit<TLPinchEventInfo, "delta" | "offset" | "point">>): this;
219
+ pinchTo(x: number | undefined, y: number | undefined, z: number, dx: number, dy: number, dz: number, options?: Partial<Omit<TLPinchEventInfo, 'delta' | 'offset' | 'point'>>): this;
218
220
  /**
219
221
  * Dispatches a pinch end event.
220
222
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -225,13 +227,7 @@ export declare class Driver {
225
227
  * @param dz - Delta z for pinch.
226
228
  * @param options - Partial pinch event overrides.
227
229
  */
228
- pinchEnd(x: number | undefined, y: number | undefined, z: number, dx: number, dy: number, dz: number, options?: Partial<Omit<TLPinchEventInfo, "delta" | "offset" | "point">>): this;
229
- /**
230
- * Converts a point from page coordinates to screen coordinates.
231
- * Pointer events operate in screen space, so page-space points must be
232
- * converted before being passed to pointerDown/Move/Up.
233
- */
234
- private pageToScreen;
230
+ pinchEnd(x: number | undefined, y: number | undefined, z: number, dx: number, dy: number, dz: number, options?: Partial<Omit<TLPinchEventInfo, 'delta' | 'offset' | 'point'>>): this;
235
231
  /**
236
232
  * Simulates rotating the current selection by the given angle in radians via the rotation handle.
237
233
  * @param angleRadians - Rotation angle in radians.
@@ -255,8 +251,8 @@ export declare class Driver {
255
251
  * @param options - Partial pointer event overrides (e.g. altKey to scale from center).
256
252
  */
257
253
  resizeSelection(scale: {
258
- scaleX?: number | undefined;
259
- scaleY?: number | undefined;
254
+ scaleX?: number;
255
+ scaleY?: number;
260
256
  } | undefined, handle: SelectionHandle, options?: Partial<TLPointerEventInfo>): this;
261
257
  }
262
258
 
@@ -2,7 +2,7 @@ import { registerTldrawLibraryVersion } from "@tldraw/utils";
2
2
  import { Driver } from "./lib/Driver.mjs";
3
3
  registerTldrawLibraryVersion(
4
4
  "@tldraw/driver",
5
- "5.3.2",
5
+ "5.4.0-canary.02cd0bd3b597",
6
6
  "esm"
7
7
  );
8
8
  export {
@@ -9,6 +9,18 @@ import {
9
9
  rotateSelectionHandle,
10
10
  tlenv
11
11
  } from "@tldraw/editor";
12
+ const KEY_CODES = {
13
+ Shift: "ShiftLeft",
14
+ Alt: "AltLeft",
15
+ Control: "CtrlLeft",
16
+ Meta: "MetaLeft",
17
+ " ": "Space",
18
+ Enter: "Enter",
19
+ ArrowRight: "ArrowRight",
20
+ ArrowLeft: "ArrowLeft",
21
+ ArrowUp: "ArrowUp",
22
+ ArrowDown: "ArrowDown"
23
+ };
12
24
  class Driver {
13
25
  constructor(editor) {
14
26
  this.editor = editor;
@@ -21,7 +33,8 @@ class Driver {
21
33
  }
22
34
  editor;
23
35
  /** The underlying Editor instance. */
24
- _cleanup = null;
36
+ _cleanup;
37
+ _lastCreatedShapes = [];
25
38
  /** Remove all registered side-effect handlers. Call when this controller is no longer needed. */
26
39
  dispose() {
27
40
  this._cleanup?.();
@@ -29,7 +42,6 @@ class Driver {
29
42
  }
30
43
  /** Local clipboard content. Used by copy, cut, and paste. */
31
44
  clipboard = null;
32
- _lastCreatedShapes = [];
33
45
  /**
34
46
  * Get the last created shapes.
35
47
  * @param count - The number of shapes to get.
@@ -79,10 +91,7 @@ class Driver {
79
91
  */
80
92
  cut(ids = this.editor.getSelectedShapeIds()) {
81
93
  if (ids.length > 0) {
82
- const content = this.editor.getContentFromCurrentPage(ids);
83
- if (content) {
84
- this.clipboard = content;
85
- }
94
+ this.copy(ids);
86
95
  this.editor.deleteShapes(ids);
87
96
  }
88
97
  return this;
@@ -130,10 +139,7 @@ class Driver {
130
139
  */
131
140
  getPageRotationById(id) {
132
141
  const pageTransform = this.editor.getShapePageTransform(id);
133
- if (pageTransform) {
134
- return Mat.Decompose(pageTransform).rotation;
135
- }
136
- return 0;
142
+ return pageTransform ? pageTransform.rotation() : 0;
137
143
  }
138
144
  /**
139
145
  * Returns the rotation of a shape in page space, in radians.
@@ -151,6 +157,16 @@ class Driver {
151
157
  return compact(Array.from(ids, (id) => this.editor.getShape(id)));
152
158
  }
153
159
  /* --------------- Event building --------------- */
160
+ getModifierKeys() {
161
+ const { inputs } = this.editor;
162
+ return {
163
+ shiftKey: inputs.getShiftKey(),
164
+ ctrlKey: inputs.getCtrlKey(),
165
+ altKey: inputs.getAltKey(),
166
+ metaKey: inputs.getMetaKey(),
167
+ accelKey: isAccelKey(inputs)
168
+ };
169
+ }
154
170
  /**
155
171
  * Builds a TLPointerEventInfo object for input simulation.
156
172
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -168,10 +184,7 @@ class Driver {
168
184
  name: "pointer_down",
169
185
  type: "pointer",
170
186
  pointerId: 1,
171
- shiftKey: this.editor.inputs.getShiftKey(),
172
- ctrlKey: this.editor.inputs.getCtrlKey(),
173
- altKey: this.editor.inputs.getAltKey(),
174
- metaKey: this.editor.inputs.getMetaKey(),
187
+ ...this.getModifierKeys(),
175
188
  accelKey: isAccelKey({ ...this.editor.inputs.toJson(), ...modifiers }),
176
189
  point: { x, y, z: null },
177
190
  button: 0,
@@ -201,9 +214,9 @@ class Driver {
201
214
  };
202
215
  return {
203
216
  ...flags,
204
- accelKey: flags.accelKey ?? (tlenv.isDarwin ? flags.metaKey : flags.ctrlKey || flags.metaKey),
217
+ accelKey: flags.accelKey ?? isAccelKey(flags),
205
218
  name,
206
- code: key === "Shift" ? "ShiftLeft" : key === "Alt" ? "AltLeft" : key === "Control" ? "CtrlLeft" : key === "Meta" ? "MetaLeft" : key === " " ? "Space" : key === "Enter" || key === "ArrowRight" || key === "ArrowLeft" || key === "ArrowUp" || key === "ArrowDown" ? key : "Key" + key[0].toUpperCase() + key.slice(1),
219
+ code: KEY_CODES[key] ?? "Key" + key[0].toUpperCase() + key.slice(1),
207
220
  type: "keyboard",
208
221
  key
209
222
  };
@@ -306,8 +319,7 @@ class Driver {
306
319
  * @param modifiers - Override shift, ctrl, or alt key state.
307
320
  */
308
321
  doubleClick(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, options, modifiers) {
309
- this.pointerDown(x, y, options, modifiers);
310
- this.pointerUp(x, y, options, modifiers);
322
+ this.click(x, y, options, modifiers);
311
323
  this.editor.dispatch({
312
324
  ...this.getPointerEventInfo(x, y, options, modifiers),
313
325
  type: "click",
@@ -339,7 +351,7 @@ class Driver {
339
351
  * @param options - Partial keyboard event overrides.
340
352
  */
341
353
  keyDown(key, options = {}) {
342
- this.editor.dispatch({ ...this.getKeyboardEventInfo(key, "key_down", options) });
354
+ this.editor.dispatch(this.getKeyboardEventInfo(key, "key_down", options));
343
355
  this.forceTick();
344
356
  return this;
345
357
  }
@@ -349,7 +361,7 @@ class Driver {
349
361
  * @param options - Partial keyboard event overrides.
350
362
  */
351
363
  keyRepeat(key, options = {}) {
352
- this.editor.dispatch({ ...this.getKeyboardEventInfo(key, "key_repeat", options) });
364
+ this.editor.dispatch(this.getKeyboardEventInfo(key, "key_repeat", options));
353
365
  this.forceTick();
354
366
  return this;
355
367
  }
@@ -359,15 +371,15 @@ class Driver {
359
371
  * @param options - Partial keyboard event overrides.
360
372
  */
361
373
  keyUp(key, options = {}) {
362
- this.editor.dispatch({
363
- ...this.getKeyboardEventInfo(key, "key_up", {
374
+ this.editor.dispatch(
375
+ this.getKeyboardEventInfo(key, "key_up", {
364
376
  shiftKey: this.editor.inputs.getShiftKey() && key !== "Shift",
365
377
  ctrlKey: this.editor.inputs.getCtrlKey() && !(key === "Control" || key === "Meta"),
366
378
  altKey: this.editor.inputs.getAltKey() && key !== "Alt",
367
379
  metaKey: this.editor.inputs.getMetaKey() && key !== "Meta",
368
380
  ...options
369
381
  })
370
- });
382
+ );
371
383
  this.forceTick();
372
384
  return this;
373
385
  }
@@ -383,11 +395,7 @@ class Driver {
383
395
  type: "wheel",
384
396
  name: "wheel",
385
397
  point: new Vec(currentScreenPoint.x, currentScreenPoint.y),
386
- shiftKey: this.editor.inputs.getShiftKey(),
387
- ctrlKey: this.editor.inputs.getCtrlKey(),
388
- altKey: this.editor.inputs.getAltKey(),
389
- metaKey: this.editor.inputs.getMetaKey(),
390
- accelKey: isAccelKey(this.editor.inputs),
398
+ ...this.getModifierKeys(),
391
399
  ...options,
392
400
  delta: { x: dx, y: dy }
393
401
  });
@@ -408,6 +416,16 @@ class Driver {
408
416
  );
409
417
  return this;
410
418
  }
419
+ pinch(name, x, y, z, dx, dy, dz, options) {
420
+ this.editor.dispatch({
421
+ type: "pinch",
422
+ name,
423
+ ...this.getModifierKeys(),
424
+ ...options,
425
+ point: { x, y, z },
426
+ delta: { x: dx, y: dy, z: dz }
427
+ });
428
+ }
411
429
  /**
412
430
  * Dispatches a pinch start event.
413
431
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -419,18 +437,7 @@ class Driver {
419
437
  * @param options - Partial pinch event overrides.
420
438
  */
421
439
  pinchStart(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, z, dx, dy, dz, options = {}) {
422
- this.editor.dispatch({
423
- type: "pinch",
424
- name: "pinch_start",
425
- shiftKey: this.editor.inputs.getShiftKey(),
426
- ctrlKey: this.editor.inputs.getCtrlKey(),
427
- altKey: this.editor.inputs.getAltKey(),
428
- metaKey: this.editor.inputs.getMetaKey(),
429
- accelKey: isAccelKey(this.editor.inputs),
430
- ...options,
431
- point: { x, y, z },
432
- delta: { x: dx, y: dy, z: dz }
433
- });
440
+ this.pinch("pinch_start", x, y, z, dx, dy, dz, options);
434
441
  this.forceTick();
435
442
  return this;
436
443
  }
@@ -445,18 +452,7 @@ class Driver {
445
452
  * @param options - Partial pinch event overrides.
446
453
  */
447
454
  pinchTo(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, z, dx, dy, dz, options = {}) {
448
- this.editor.dispatch({
449
- type: "pinch",
450
- name: "pinch",
451
- shiftKey: this.editor.inputs.getShiftKey(),
452
- ctrlKey: this.editor.inputs.getCtrlKey(),
453
- altKey: this.editor.inputs.getAltKey(),
454
- metaKey: this.editor.inputs.getMetaKey(),
455
- accelKey: isAccelKey(this.editor.inputs),
456
- ...options,
457
- point: { x, y, z },
458
- delta: { x: dx, y: dy, z: dz }
459
- });
455
+ this.pinch("pinch", x, y, z, dx, dy, dz, options);
460
456
  return this;
461
457
  }
462
458
  /**
@@ -470,30 +466,11 @@ class Driver {
470
466
  * @param options - Partial pinch event overrides.
471
467
  */
472
468
  pinchEnd(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, z, dx, dy, dz, options = {}) {
473
- this.editor.dispatch({
474
- type: "pinch",
475
- name: "pinch_end",
476
- shiftKey: this.editor.inputs.getShiftKey(),
477
- ctrlKey: this.editor.inputs.getCtrlKey(),
478
- altKey: this.editor.inputs.getAltKey(),
479
- metaKey: this.editor.inputs.getMetaKey(),
480
- accelKey: isAccelKey(this.editor.inputs),
481
- ...options,
482
- point: { x, y, z },
483
- delta: { x: dx, y: dy, z: dz }
484
- });
469
+ this.pinch("pinch_end", x, y, z, dx, dy, dz, options);
485
470
  this.forceTick();
486
471
  return this;
487
472
  }
488
473
  /* --------------- Interaction helpers --------------- */
489
- /**
490
- * Converts a point from page coordinates to screen coordinates.
491
- * Pointer events operate in screen space, so page-space points must be
492
- * converted before being passed to pointerDown/Move/Up.
493
- */
494
- pageToScreen(point) {
495
- return this.editor.pageToScreen(point);
496
- }
497
474
  /**
498
475
  * Simulates rotating the current selection by the given angle in radians via the rotation handle.
499
476
  * @param angleRadians - Rotation angle in radians.
@@ -505,13 +482,11 @@ class Driver {
505
482
  throw new Error("No selection");
506
483
  }
507
484
  this.editor.setCurrentTool("select");
508
- const handlePoint = this.editor.getSelectionRotatedPageBounds().getHandlePoint(ROTATE_CORNER_TO_SELECTION_CORNER[handle]).clone().rotWith(
509
- this.editor.getSelectionRotatedPageBounds().point,
510
- this.editor.getSelectionRotation()
511
- );
485
+ const bounds = this.editor.getSelectionRotatedPageBounds();
486
+ const handlePoint = bounds.getHandlePoint(ROTATE_CORNER_TO_SELECTION_CORNER[handle]).clone().rotWith(bounds.point, this.editor.getSelectionRotation());
512
487
  const targetHandlePoint = Vec.RotWith(handlePoint, this.getSelectionPageCenter(), angleRadians);
513
- const screenHandle = this.pageToScreen(handlePoint);
514
- const screenTarget = this.pageToScreen(targetHandlePoint);
488
+ const screenHandle = this.editor.pageToScreen(handlePoint);
489
+ const screenTarget = this.editor.pageToScreen(targetHandlePoint);
515
490
  this.pointerDown(screenHandle.x, screenHandle.y, { target: "selection", handle });
516
491
  this.pointerMove(screenTarget.x, screenTarget.y, { shiftKey });
517
492
  this.pointerUp();
@@ -529,17 +504,17 @@ class Driver {
529
504
  }
530
505
  this.editor.setCurrentTool("select");
531
506
  const center = this.getSelectionPageCenter();
532
- const screenCenter = this.pageToScreen(center);
507
+ const screenCenter = this.editor.pageToScreen(center);
533
508
  this.pointerDown(screenCenter.x, screenCenter.y, this.editor.getSelectedShapeIds()[0]);
534
509
  const numSteps = 10;
535
510
  for (let i = 1; i < numSteps; i++) {
536
- const p = this.pageToScreen({
511
+ const p = this.editor.pageToScreen({
537
512
  x: center.x + i * dx / numSteps,
538
513
  y: center.y + i * dy / numSteps
539
514
  });
540
515
  this.pointerMove(p.x, p.y, options);
541
516
  }
542
- const endScreen = this.pageToScreen({ x: center.x + dx, y: center.y + dy });
517
+ const endScreen = this.editor.pageToScreen({ x: center.x + dx, y: center.y + dy });
543
518
  this.pointerUp(endScreen.x, endScreen.y, options);
544
519
  return this;
545
520
  }
@@ -556,6 +531,7 @@ class Driver {
556
531
  }
557
532
  this.editor.setCurrentTool("select");
558
533
  const bounds = this.editor.getSelectionRotatedPageBounds();
534
+ const rotation = this.editor.getSelectionRotation();
559
535
  const preRotationHandlePoint = bounds.getHandlePoint(handle);
560
536
  const preRotationScaleOriginPoint = options?.altKey ? bounds.center : bounds.getHandlePoint(rotateSelectionHandle(handle, Math.PI));
561
537
  const preRotationTargetHandlePoint = Vec.Add(
@@ -565,18 +541,10 @@ class Driver {
565
541
  }),
566
542
  preRotationScaleOriginPoint
567
543
  );
568
- const handlePoint = Vec.RotWith(
569
- preRotationHandlePoint,
570
- bounds.point,
571
- this.editor.getSelectionRotation()
572
- );
573
- const targetHandlePoint = Vec.RotWith(
574
- preRotationTargetHandlePoint,
575
- bounds.point,
576
- this.editor.getSelectionRotation()
577
- );
578
- const screenHandle = this.pageToScreen(handlePoint);
579
- const screenTarget = this.pageToScreen(targetHandlePoint);
544
+ const handlePoint = Vec.RotWith(preRotationHandlePoint, bounds.point, rotation);
545
+ const targetHandlePoint = Vec.RotWith(preRotationTargetHandlePoint, bounds.point, rotation);
546
+ const screenHandle = this.editor.pageToScreen(handlePoint);
547
+ const screenTarget = this.editor.pageToScreen(targetHandlePoint);
580
548
  this.pointerDown(screenHandle.x, screenHandle.y, { target: "selection", handle }, options);
581
549
  this.pointerMove(screenTarget.x, screenTarget.y, options);
582
550
  this.pointerUp(screenTarget.x, screenTarget.y, options);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/Driver.ts"],
4
- "sourcesContent": ["import {\n\tEditor,\n\tMat,\n\tPageRecordType,\n\tROTATE_CORNER_TO_SELECTION_CORNER,\n\tRotateCorner,\n\tSelectionHandle,\n\tTLArrowShape,\n\tTLContent,\n\tTLKeyboardEventInfo,\n\tTLPinchEventInfo,\n\tTLPointerEventInfo,\n\tTLShape,\n\tTLShapeId,\n\tTLWheelEventInfo,\n\tVec,\n\tVecLike,\n\tcompact,\n\tcreateShapeId,\n\tisAccelKey,\n\trotateSelectionHandle,\n\ttlenv,\n} from '@tldraw/editor'\n\n/** Options for pointer events. Either partial pointer event info or a shape ID to target. @public */\nexport type PointerEventInit = Partial<TLPointerEventInfo> | TLShapeId\n\n/** Modifier keys for events. @public */\nexport type EventModifiers = Partial<Pick<TLPointerEventInfo, 'shiftKey' | 'ctrlKey' | 'altKey'>>\n\n/**\n * Driver wraps an Editor instance and provides an imperative API for driving it\n * programmatically. Useful for scripting, automation, REPL usage, and testing.\n *\n * All methods use only public Editor APIs and return `this` for fluent chaining.\n *\n * @public\n */\nexport class Driver {\n\t/** The underlying Editor instance. */\n\tprivate _cleanup: (() => void) | null = null\n\n\tconstructor(public readonly editor: Editor) {\n\t\tthis._cleanup = this.editor.sideEffects.registerAfterCreateHandler('shape', (record) => {\n\t\t\tthis._lastCreatedShapes.push(record)\n\t\t\tif (this._lastCreatedShapes.length > 1000) {\n\t\t\t\tthis._lastCreatedShapes = this._lastCreatedShapes.slice(-500)\n\t\t\t}\n\t\t})\n\t}\n\n\t/** Remove all registered side-effect handlers. Call when this controller is no longer needed. */\n\tdispose() {\n\t\tthis._cleanup?.()\n\t\tthis._cleanup = null\n\t}\n\n\t/** Local clipboard content. Used by copy, cut, and paste. */\n\tclipboard: TLContent | null = null\n\n\tprivate _lastCreatedShapes: TLShape[] = []\n\n\t/**\n\t * Get the last created shapes.\n\t * @param count - The number of shapes to get.\n\t */\n\tgetLastCreatedShapes(count = 1) {\n\t\treturn this._lastCreatedShapes.slice(-count).map((s) => this.editor.getShape(s)!)\n\t}\n\n\t/**\n\t * Get the last created shape.\n\t */\n\tgetLastCreatedShape<T extends TLShape>() {\n\t\tconst lastShape = this._lastCreatedShapes[this._lastCreatedShapes.length - 1] as T\n\t\treturn this.editor.getShape<T>(lastShape)!\n\t}\n\n\t/* ---------------------- IDs ---------------------- */\n\n\t/**\n\t * Creates a shape ID from a string.\n\t * @param id - The string to convert to a shape ID.\n\t */\n\tcreateShapeID(id: string) {\n\t\treturn createShapeId(id)\n\t}\n\n\t/**\n\t * Creates a page ID from a string.\n\t * @param id - The string to convert to a page ID.\n\t */\n\tcreatePageID(id: string) {\n\t\treturn PageRecordType.createId(id)\n\t}\n\n\t/* ------------------- Clipboard ------------------- */\n\n\t/**\n\t * Copies the given shapes to the controller clipboard. Defaults to the current selection.\n\t * @param ids - Shape IDs to copy. Defaults to the current selection.\n\t */\n\tcopy(ids = this.editor.getSelectedShapeIds()) {\n\t\tif (ids.length > 0) {\n\t\t\tconst content = this.editor.getContentFromCurrentPage(ids)\n\t\t\tif (content) {\n\t\t\t\tthis.clipboard = content\n\t\t\t}\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Cuts the given shapes (copy to clipboard, then delete). Defaults to the current selection.\n\t * @param ids - Shape IDs to cut. Defaults to the current selection.\n\t */\n\tcut(ids = this.editor.getSelectedShapeIds()) {\n\t\tif (ids.length > 0) {\n\t\t\tconst content = this.editor.getContentFromCurrentPage(ids)\n\t\t\tif (content) {\n\t\t\t\tthis.clipboard = content\n\t\t\t}\n\t\t\tthis.editor.deleteShapes(ids)\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Pastes content from the controller clipboard. If shift is held, uses current pointer. Otherwise uses the given point.\n\t * @param point - Page coordinates for paste location. If omitted and shift is not held, placement may vary.\n\t */\n\tpaste(point?: VecLike) {\n\t\tif (this.clipboard !== null) {\n\t\t\tconst p = this.editor.inputs.getShiftKey() ? this.editor.inputs.getCurrentPagePoint() : point\n\n\t\t\tthis.editor.markHistoryStoppingPoint('pasting')\n\t\t\tthis.editor.putContentOntoCurrentPage(this.clipboard, {\n\t\t\t\tpoint: p,\n\t\t\t\tselect: true,\n\t\t\t})\n\t\t}\n\t\treturn this\n\t}\n\n\t/* ------------------- Queries ------------------- */\n\n\t/** Returns the center of the viewport in page coordinates. */\n\tgetViewportPageCenter() {\n\t\treturn this.editor.getViewportPageBounds().center\n\t}\n\n\t/** Returns the center of the current selection in page coordinates, or null if nothing is selected. */\n\tgetSelectionPageCenter() {\n\t\tconst selectionRotation = this.editor.getSelectionRotation()\n\t\tconst selectionBounds = this.editor.getSelectionRotatedPageBounds()\n\t\tif (!selectionBounds) return null\n\t\treturn Vec.RotWith(selectionBounds.center, selectionBounds.point, selectionRotation)\n\t}\n\n\t/**\n\t * Returns the center of a shape in page coordinates, or null if the shape has no page transform.\n\t * @param shape - The shape to get the center of.\n\t */\n\tgetPageCenter(shape: TLShape) {\n\t\tconst pageTransform = this.editor.getShapePageTransform(shape.id)\n\t\tif (!pageTransform) return null\n\t\tconst center = this.editor.getShapeGeometry(shape).bounds.center\n\t\treturn Mat.applyToPoint(pageTransform, center)\n\t}\n\n\t/**\n\t * Returns the rotation of a shape in page space by ID, in radians.\n\t * @param id - The shape ID.\n\t */\n\tgetPageRotationById(id: TLShapeId): number {\n\t\tconst pageTransform = this.editor.getShapePageTransform(id)\n\t\tif (pageTransform) {\n\t\t\treturn Mat.Decompose(pageTransform).rotation\n\t\t}\n\t\treturn 0\n\t}\n\n\t/**\n\t * Returns the rotation of a shape in page space, in radians.\n\t * @param shape - The shape to get the rotation of.\n\t */\n\tgetPageRotation(shape: TLShape) {\n\t\treturn this.getPageRotationById(shape.id)\n\t}\n\n\t/**\n\t * Returns all arrow shapes bound to the given shape.\n\t * @param shapeId - The shape ID to find arrows bound to.\n\t */\n\tgetArrowsBoundTo(shapeId: TLShapeId) {\n\t\tconst ids = new Set(this.editor.getBindingsToShape(shapeId, 'arrow').map((b) => b.fromId))\n\t\treturn compact(Array.from(ids, (id) => this.editor.getShape<TLArrowShape>(id)))\n\t}\n\n\t/* --------------- Event building --------------- */\n\n\t/**\n\t * Builds a TLPointerEventInfo object for input simulation.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tprivate getPointerEventInfo(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t): TLPointerEventInfo {\n\t\tif (typeof options === 'string') {\n\t\t\toptions = { target: 'shape', shape: this.editor.getShape(options) }\n\t\t} else if (options === undefined) {\n\t\t\toptions = { target: 'canvas' }\n\t\t}\n\t\tconst info = {\n\t\t\tname: 'pointer_down',\n\t\t\ttype: 'pointer',\n\t\t\tpointerId: 1,\n\t\t\tshiftKey: this.editor.inputs.getShiftKey(),\n\t\t\tctrlKey: this.editor.inputs.getCtrlKey(),\n\t\t\taltKey: this.editor.inputs.getAltKey(),\n\t\t\tmetaKey: this.editor.inputs.getMetaKey(),\n\t\t\taccelKey: isAccelKey({ ...this.editor.inputs.toJson(), ...modifiers }),\n\t\t\tpoint: { x, y, z: null },\n\t\t\tbutton: 0,\n\t\t\tisPen: false,\n\t\t\t...options,\n\t\t\t...modifiers,\n\t\t} as TLPointerEventInfo\n\n\t\t// In simulated input, a pen is assumed to be a direct-display pen (which auto-enables pen\n\t\t// mode) unless a test explicitly opts out with `isPenDirect: false`.\n\t\tif (info.isPenDirect === undefined) info.isPenDirect = info.isPen\n\n\t\tif (tlenv.isDarwin && info.button === 0 && info.ctrlKey && !info.metaKey) {\n\t\t\tinfo.button = 2\n\t\t}\n\n\t\treturn info\n\t}\n\n\t/**\n\t * Builds a TLKeyboardEventInfo object for input simulation.\n\t * @param key - The key being pressed.\n\t * @param name - The event name (key_down, key_up, key_repeat).\n\t * @param options - Partial event info overrides.\n\t */\n\tprivate getKeyboardEventInfo(\n\t\tkey: string,\n\t\tname: TLKeyboardEventInfo['name'],\n\t\toptions = {} as Partial<Omit<TLKeyboardEventInfo, 'point'>>\n\t): TLKeyboardEventInfo {\n\t\t// Like a real DOM keyboard event, the flags reflect every modifier currently held \u2014 not\n\t\t// just the key being pressed. We OR in the editor's current modifier state so that, e.g.,\n\t\t// pressing Shift while Control is held still reports ctrlKey: true. (keyUp passes explicit\n\t\t// flag overrides for its release semantics, so those win over these defaults.)\n\t\tconst flags = {\n\t\t\tshiftKey: key === 'Shift' || this.editor.inputs.getShiftKey(),\n\t\t\tctrlKey: key === 'Control' || key === 'Meta' || this.editor.inputs.getCtrlKey(),\n\t\t\taltKey: key === 'Alt' || this.editor.inputs.getAltKey(),\n\t\t\tmetaKey: key === 'Meta' || this.editor.inputs.getMetaKey(),\n\t\t\t...options,\n\t\t}\n\t\treturn {\n\t\t\t...flags,\n\t\t\taccelKey: flags.accelKey ?? (tlenv.isDarwin ? flags.metaKey : flags.ctrlKey || flags.metaKey),\n\t\t\tname,\n\t\t\tcode:\n\t\t\t\tkey === 'Shift'\n\t\t\t\t\t? 'ShiftLeft'\n\t\t\t\t\t: key === 'Alt'\n\t\t\t\t\t\t? 'AltLeft'\n\t\t\t\t\t\t: key === 'Control'\n\t\t\t\t\t\t\t? 'CtrlLeft'\n\t\t\t\t\t\t\t: key === 'Meta'\n\t\t\t\t\t\t\t\t? 'MetaLeft'\n\t\t\t\t\t\t\t\t: key === ' '\n\t\t\t\t\t\t\t\t\t? 'Space'\n\t\t\t\t\t\t\t\t\t: key === 'Enter' ||\n\t\t\t\t\t\t\t\t\t\t key === 'ArrowRight' ||\n\t\t\t\t\t\t\t\t\t\t key === 'ArrowLeft' ||\n\t\t\t\t\t\t\t\t\t\t key === 'ArrowUp' ||\n\t\t\t\t\t\t\t\t\t\t key === 'ArrowDown'\n\t\t\t\t\t\t\t\t\t\t? key\n\t\t\t\t\t\t\t\t\t\t: 'Key' + key[0].toUpperCase() + key.slice(1),\n\t\t\ttype: 'keyboard',\n\t\t\tkey,\n\t\t}\n\t}\n\n\t/* --------------- Input events --------------- */\n\n\t/**\n\t * Emits tick events to advance the editor by the given number of frames (default 1).\n\t * @param count - Number of tick events to emit. Defaults to 1.\n\t */\n\tforceTick(count = 1) {\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tthis.editor.emit('tick', 16)\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pointer move event at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tpointerMove(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\tname: 'pointer_move',\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pointer down event at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tpointerDown(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\tname: 'pointer_down',\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pointer up event at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tpointerUp(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\tname: 'pointer_up',\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pointer down followed by pointer up at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tclick(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.pointerDown(x, y, options, modifiers)\n\t\tthis.pointerUp(x, y, options, modifiers)\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a right-click (button 2) down and up at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\trightClick(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\tname: 'pointer_down',\n\t\t\tbutton: 2,\n\t\t})\n\t\tthis.forceTick()\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\tname: 'pointer_up',\n\t\t\tbutton: 2,\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a double-click sequence at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tdoubleClick(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.pointerDown(x, y, options, modifiers)\n\t\tthis.pointerUp(x, y, options, modifiers)\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\ttype: 'click',\n\t\t\tname: 'double_click',\n\t\t\tphase: 'down',\n\t\t})\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\ttype: 'click',\n\t\t\tname: 'double_click',\n\t\t\tphase: 'up',\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a key down followed by key up for the given key.\n\t * @param key - The key to press (e.g. 'a', 'Enter', 'Shift').\n\t * @param options - Partial keyboard event overrides.\n\t */\n\tkeyPress(key: string, options = {} as Partial<Omit<TLKeyboardEventInfo, 'key'>>) {\n\t\tthis.keyDown(key, options)\n\t\tthis.keyUp(key, options)\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a key down event for the given key.\n\t * @param key - The key to press (e.g. 'a', 'Enter', 'Shift').\n\t * @param options - Partial keyboard event overrides.\n\t */\n\tkeyDown(key: string, options = {} as Partial<Omit<TLKeyboardEventInfo, 'key'>>) {\n\t\tthis.editor.dispatch({ ...this.getKeyboardEventInfo(key, 'key_down', options) })\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a key repeat event for the given key.\n\t * @param key - The key that is repeating (e.g. 'a', 'ArrowDown').\n\t * @param options - Partial keyboard event overrides.\n\t */\n\tkeyRepeat(key: string, options = {} as Partial<Omit<TLKeyboardEventInfo, 'key'>>) {\n\t\tthis.editor.dispatch({ ...this.getKeyboardEventInfo(key, 'key_repeat', options) })\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a key up event for the given key.\n\t * @param key - The key to release (e.g. 'a', 'Enter', 'Shift').\n\t * @param options - Partial keyboard event overrides.\n\t */\n\tkeyUp(key: string, options = {} as Partial<Omit<TLKeyboardEventInfo, 'key'>>) {\n\t\tthis.editor.dispatch({\n\t\t\t...this.getKeyboardEventInfo(key, 'key_up', {\n\t\t\t\tshiftKey: this.editor.inputs.getShiftKey() && key !== 'Shift',\n\t\t\t\tctrlKey: this.editor.inputs.getCtrlKey() && !(key === 'Control' || key === 'Meta'),\n\t\t\t\taltKey: this.editor.inputs.getAltKey() && key !== 'Alt',\n\t\t\t\tmetaKey: this.editor.inputs.getMetaKey() && key !== 'Meta',\n\t\t\t\t...options,\n\t\t\t}),\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a wheel event with the given delta values.\n\t * @param dx - Horizontal scroll delta.\n\t * @param dy - Vertical scroll delta.\n\t * @param options - Partial wheel event overrides.\n\t */\n\twheel(dx: number, dy: number, options = {} as Partial<Omit<TLWheelEventInfo, 'delta'>>) {\n\t\tconst currentScreenPoint = this.editor.inputs.getCurrentScreenPoint()\n\t\tthis.editor.dispatch({\n\t\t\ttype: 'wheel',\n\t\t\tname: 'wheel',\n\t\t\tpoint: new Vec(currentScreenPoint.x, currentScreenPoint.y),\n\t\t\tshiftKey: this.editor.inputs.getShiftKey(),\n\t\t\tctrlKey: this.editor.inputs.getCtrlKey(),\n\t\t\taltKey: this.editor.inputs.getAltKey(),\n\t\t\tmetaKey: this.editor.inputs.getMetaKey(),\n\t\t\taccelKey: isAccelKey(this.editor.inputs),\n\t\t\t...options,\n\t\t\tdelta: { x: dx, y: dy },\n\t\t})\n\t\tthis.forceTick(2)\n\t\treturn this\n\t}\n\n\t/**\n\t * Pans the camera by the given offset (in page coordinates). Does nothing if camera is locked.\n\t * @param offset - The pan delta (x, y) in page coordinates.\n\t */\n\tpan(offset: VecLike) {\n\t\tconst { isLocked, panSpeed } = this.editor.getCameraOptions()\n\t\tif (isLocked) return this\n\t\tconst { x: cx, y: cy, z: cz } = this.editor.getCamera()\n\t\tthis.editor.setCamera(\n\t\t\tnew Vec(cx + (offset.x * panSpeed) / cz, cy + (offset.y * panSpeed) / cz, cz),\n\t\t\t{ immediate: true }\n\t\t)\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pinch start event.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param z - Pinch scale/factor.\n\t * @param dx - Delta x for pinch.\n\t * @param dy - Delta y for pinch.\n\t * @param dz - Delta z for pinch.\n\t * @param options - Partial pinch event overrides.\n\t */\n\tpinchStart(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\tz: number,\n\t\tdx: number,\n\t\tdy: number,\n\t\tdz: number,\n\t\toptions = {} as Partial<Omit<TLPinchEventInfo, 'point' | 'delta' | 'offset'>>\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\ttype: 'pinch',\n\t\t\tname: 'pinch_start',\n\t\t\tshiftKey: this.editor.inputs.getShiftKey(),\n\t\t\tctrlKey: this.editor.inputs.getCtrlKey(),\n\t\t\taltKey: this.editor.inputs.getAltKey(),\n\t\t\tmetaKey: this.editor.inputs.getMetaKey(),\n\t\t\taccelKey: isAccelKey(this.editor.inputs),\n\t\t\t...options,\n\t\t\tpoint: { x, y, z },\n\t\t\tdelta: { x: dx, y: dy, z: dz },\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pinch move event (pinch_to).\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param z - Pinch scale/factor.\n\t * @param dx - Delta x for pinch.\n\t * @param dy - Delta y for pinch.\n\t * @param dz - Delta z for pinch.\n\t * @param options - Partial pinch event overrides.\n\t */\n\tpinchTo(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\tz: number,\n\t\tdx: number,\n\t\tdy: number,\n\t\tdz: number,\n\t\toptions = {} as Partial<Omit<TLPinchEventInfo, 'point' | 'delta' | 'offset'>>\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\ttype: 'pinch',\n\t\t\tname: 'pinch',\n\t\t\tshiftKey: this.editor.inputs.getShiftKey(),\n\t\t\tctrlKey: this.editor.inputs.getCtrlKey(),\n\t\t\taltKey: this.editor.inputs.getAltKey(),\n\t\t\tmetaKey: this.editor.inputs.getMetaKey(),\n\t\t\taccelKey: isAccelKey(this.editor.inputs),\n\t\t\t...options,\n\t\t\tpoint: { x, y, z },\n\t\t\tdelta: { x: dx, y: dy, z: dz },\n\t\t})\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pinch end event.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param z - Pinch scale/factor.\n\t * @param dx - Delta x for pinch.\n\t * @param dy - Delta y for pinch.\n\t * @param dz - Delta z for pinch.\n\t * @param options - Partial pinch event overrides.\n\t */\n\tpinchEnd(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\tz: number,\n\t\tdx: number,\n\t\tdy: number,\n\t\tdz: number,\n\t\toptions = {} as Partial<Omit<TLPinchEventInfo, 'point' | 'delta' | 'offset'>>\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\ttype: 'pinch',\n\t\t\tname: 'pinch_end',\n\t\t\tshiftKey: this.editor.inputs.getShiftKey(),\n\t\t\tctrlKey: this.editor.inputs.getCtrlKey(),\n\t\t\taltKey: this.editor.inputs.getAltKey(),\n\t\t\tmetaKey: this.editor.inputs.getMetaKey(),\n\t\t\taccelKey: isAccelKey(this.editor.inputs),\n\t\t\t...options,\n\t\t\tpoint: { x, y, z },\n\t\t\tdelta: { x: dx, y: dy, z: dz },\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/* --------------- Interaction helpers --------------- */\n\n\t/**\n\t * Converts a point from page coordinates to screen coordinates.\n\t * Pointer events operate in screen space, so page-space points must be\n\t * converted before being passed to pointerDown/Move/Up.\n\t */\n\tprivate pageToScreen(point: VecLike) {\n\t\treturn this.editor.pageToScreen(point)\n\t}\n\n\t/**\n\t * Simulates rotating the current selection by the given angle in radians via the rotation handle.\n\t * @param angleRadians - Rotation angle in radians.\n\t * @param options - Optional handle and shiftKey. handle defaults to 'top_left_rotate'.\n\t */\n\trotateSelection(\n\t\tangleRadians: number,\n\t\toptions: { handle?: RotateCorner; shiftKey?: boolean } = {}\n\t) {\n\t\tconst { handle = 'top_left_rotate', shiftKey = false } = options\n\t\tif (this.editor.getSelectedShapeIds().length === 0) {\n\t\t\tthrow new Error('No selection')\n\t\t}\n\n\t\tthis.editor.setCurrentTool('select')\n\n\t\tconst handlePoint = this.editor\n\t\t\t.getSelectionRotatedPageBounds()!\n\t\t\t.getHandlePoint(ROTATE_CORNER_TO_SELECTION_CORNER[handle])\n\t\t\t.clone()\n\t\t\t.rotWith(\n\t\t\t\tthis.editor.getSelectionRotatedPageBounds()!.point,\n\t\t\t\tthis.editor.getSelectionRotation()\n\t\t\t)\n\n\t\tconst targetHandlePoint = Vec.RotWith(handlePoint, this.getSelectionPageCenter()!, angleRadians)\n\n\t\tconst screenHandle = this.pageToScreen(handlePoint)\n\t\tconst screenTarget = this.pageToScreen(targetHandlePoint)\n\n\t\tthis.pointerDown(screenHandle.x, screenHandle.y, { target: 'selection', handle })\n\t\tthis.pointerMove(screenTarget.x, screenTarget.y, { shiftKey })\n\t\tthis.pointerUp()\n\t\treturn this\n\t}\n\n\t/**\n\t * Simulates translating the current selection by the given delta in page coordinates.\n\t * @param dx - Horizontal delta in page coordinates.\n\t * @param dy - Vertical delta in page coordinates.\n\t * @param options - Partial pointer event overrides (e.g. altKey for center-based scaling).\n\t */\n\ttranslateSelection(dx: number, dy: number, options?: Partial<TLPointerEventInfo>) {\n\t\tif (this.editor.getSelectedShapeIds().length === 0) {\n\t\t\tthrow new Error('No selection')\n\t\t}\n\t\tthis.editor.setCurrentTool('select')\n\n\t\tconst center = this.getSelectionPageCenter()!\n\t\tconst screenCenter = this.pageToScreen(center)\n\n\t\tthis.pointerDown(screenCenter.x, screenCenter.y, this.editor.getSelectedShapeIds()[0])\n\t\tconst numSteps = 10\n\t\tfor (let i = 1; i < numSteps; i++) {\n\t\t\tconst p = this.pageToScreen({\n\t\t\t\tx: center.x + (i * dx) / numSteps,\n\t\t\t\ty: center.y + (i * dy) / numSteps,\n\t\t\t})\n\t\t\tthis.pointerMove(p.x, p.y, options)\n\t\t}\n\t\tconst endScreen = this.pageToScreen({ x: center.x + dx, y: center.y + dy })\n\t\tthis.pointerUp(endScreen.x, endScreen.y, options)\n\t\treturn this\n\t}\n\n\t/**\n\t * Simulates resizing the current selection via the given handle, with optional scale factors.\n\t * @param scale - Scale factors for x and y. Defaults to `\\{ scaleX: 1, scaleY: 1 \\}`.\n\t * @param handle - The selection handle to drag (e.g. 'top', 'bottom_right').\n\t * @param options - Partial pointer event overrides (e.g. altKey to scale from center).\n\t */\n\tresizeSelection(\n\t\tscale: { scaleX?: number; scaleY?: number } = {},\n\t\thandle: SelectionHandle,\n\t\toptions?: Partial<TLPointerEventInfo>\n\t) {\n\t\tconst { scaleX = 1, scaleY = 1 } = scale\n\t\tif (this.editor.getSelectedShapeIds().length === 0) {\n\t\t\tthrow new Error('No selection')\n\t\t}\n\t\tthis.editor.setCurrentTool('select')\n\t\tconst bounds = this.editor.getSelectionRotatedPageBounds()!\n\t\tconst preRotationHandlePoint = bounds.getHandlePoint(handle)\n\n\t\tconst preRotationScaleOriginPoint = options?.altKey\n\t\t\t? bounds.center\n\t\t\t: bounds.getHandlePoint(rotateSelectionHandle(handle, Math.PI))\n\n\t\tconst preRotationTargetHandlePoint = Vec.Add(\n\t\t\tVec.Sub(preRotationHandlePoint, preRotationScaleOriginPoint).mulV({\n\t\t\t\tx: scaleX,\n\t\t\t\ty: scaleY,\n\t\t\t}),\n\t\t\tpreRotationScaleOriginPoint\n\t\t)\n\n\t\tconst handlePoint = Vec.RotWith(\n\t\t\tpreRotationHandlePoint,\n\t\t\tbounds.point,\n\t\t\tthis.editor.getSelectionRotation()\n\t\t)\n\t\tconst targetHandlePoint = Vec.RotWith(\n\t\t\tpreRotationTargetHandlePoint,\n\t\t\tbounds.point,\n\t\t\tthis.editor.getSelectionRotation()\n\t\t)\n\n\t\tconst screenHandle = this.pageToScreen(handlePoint)\n\t\tconst screenTarget = this.pageToScreen(targetHandlePoint)\n\n\t\tthis.pointerDown(screenHandle.x, screenHandle.y, { target: 'selection', handle }, options)\n\t\tthis.pointerMove(screenTarget.x, screenTarget.y, options)\n\t\tthis.pointerUp(screenTarget.x, screenTarget.y, options)\n\t\treturn this\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tEditor,\n\tMat,\n\tPageRecordType,\n\tROTATE_CORNER_TO_SELECTION_CORNER,\n\tRotateCorner,\n\tSelectionHandle,\n\tTLArrowShape,\n\tTLContent,\n\tTLKeyboardEventInfo,\n\tTLPinchEventInfo,\n\tTLPointerEventInfo,\n\tTLShape,\n\tTLShapeId,\n\tTLWheelEventInfo,\n\tVec,\n\tVecLike,\n\tcompact,\n\tcreateShapeId,\n\tisAccelKey,\n\trotateSelectionHandle,\n\ttlenv,\n} from '@tldraw/editor'\n\n/** Options for pointer events. Either partial pointer event info or a shape ID to target. @public */\nexport type PointerEventInit = Partial<TLPointerEventInfo> | TLShapeId\n\n/** Modifier keys for events. @public */\nexport type EventModifiers = Partial<Pick<TLPointerEventInfo, 'shiftKey' | 'ctrlKey' | 'altKey'>>\n\nconst KEY_CODES: Record<string, string> = {\n\tShift: 'ShiftLeft',\n\tAlt: 'AltLeft',\n\tControl: 'CtrlLeft',\n\tMeta: 'MetaLeft',\n\t' ': 'Space',\n\tEnter: 'Enter',\n\tArrowRight: 'ArrowRight',\n\tArrowLeft: 'ArrowLeft',\n\tArrowUp: 'ArrowUp',\n\tArrowDown: 'ArrowDown',\n}\n\n/**\n * Driver wraps an Editor instance and provides an imperative API for driving it\n * programmatically. Useful for scripting, automation, REPL usage, and testing.\n *\n * All methods use only public Editor APIs and return `this` for fluent chaining.\n *\n * @public\n */\nexport class Driver {\n\t/** The underlying Editor instance. */\n\tprivate _cleanup: (() => void) | null\n\tprivate _lastCreatedShapes: TLShape[] = []\n\n\tconstructor(public readonly editor: Editor) {\n\t\tthis._cleanup = this.editor.sideEffects.registerAfterCreateHandler('shape', (record) => {\n\t\t\tthis._lastCreatedShapes.push(record)\n\t\t\tif (this._lastCreatedShapes.length > 1000) {\n\t\t\t\tthis._lastCreatedShapes = this._lastCreatedShapes.slice(-500)\n\t\t\t}\n\t\t})\n\t}\n\n\t/** Remove all registered side-effect handlers. Call when this controller is no longer needed. */\n\tdispose() {\n\t\tthis._cleanup?.()\n\t\tthis._cleanup = null\n\t}\n\n\t/** Local clipboard content. Used by copy, cut, and paste. */\n\tclipboard: TLContent | null = null\n\n\t/**\n\t * Get the last created shapes.\n\t * @param count - The number of shapes to get.\n\t */\n\tgetLastCreatedShapes(count = 1) {\n\t\treturn this._lastCreatedShapes.slice(-count).map((s) => this.editor.getShape(s)!)\n\t}\n\n\t/**\n\t * Get the last created shape.\n\t */\n\tgetLastCreatedShape<T extends TLShape>() {\n\t\tconst lastShape = this._lastCreatedShapes[this._lastCreatedShapes.length - 1] as T\n\t\treturn this.editor.getShape<T>(lastShape)!\n\t}\n\n\t/* ---------------------- IDs ---------------------- */\n\n\t/**\n\t * Creates a shape ID from a string.\n\t * @param id - The string to convert to a shape ID.\n\t */\n\tcreateShapeID(id: string) {\n\t\treturn createShapeId(id)\n\t}\n\n\t/**\n\t * Creates a page ID from a string.\n\t * @param id - The string to convert to a page ID.\n\t */\n\tcreatePageID(id: string) {\n\t\treturn PageRecordType.createId(id)\n\t}\n\n\t/* ------------------- Clipboard ------------------- */\n\n\t/**\n\t * Copies the given shapes to the controller clipboard. Defaults to the current selection.\n\t * @param ids - Shape IDs to copy. Defaults to the current selection.\n\t */\n\tcopy(ids = this.editor.getSelectedShapeIds()) {\n\t\tif (ids.length > 0) {\n\t\t\tconst content = this.editor.getContentFromCurrentPage(ids)\n\t\t\tif (content) {\n\t\t\t\tthis.clipboard = content\n\t\t\t}\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Cuts the given shapes (copy to clipboard, then delete). Defaults to the current selection.\n\t * @param ids - Shape IDs to cut. Defaults to the current selection.\n\t */\n\tcut(ids = this.editor.getSelectedShapeIds()) {\n\t\tif (ids.length > 0) {\n\t\t\tthis.copy(ids)\n\t\t\tthis.editor.deleteShapes(ids)\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Pastes content from the controller clipboard. If shift is held, uses current pointer. Otherwise uses the given point.\n\t * @param point - Page coordinates for paste location. If omitted and shift is not held, placement may vary.\n\t */\n\tpaste(point?: VecLike) {\n\t\tif (this.clipboard !== null) {\n\t\t\tconst p = this.editor.inputs.getShiftKey() ? this.editor.inputs.getCurrentPagePoint() : point\n\n\t\t\tthis.editor.markHistoryStoppingPoint('pasting')\n\t\t\tthis.editor.putContentOntoCurrentPage(this.clipboard, {\n\t\t\t\tpoint: p,\n\t\t\t\tselect: true,\n\t\t\t})\n\t\t}\n\t\treturn this\n\t}\n\n\t/* ------------------- Queries ------------------- */\n\n\t/** Returns the center of the viewport in page coordinates. */\n\tgetViewportPageCenter() {\n\t\treturn this.editor.getViewportPageBounds().center\n\t}\n\n\t/** Returns the center of the current selection in page coordinates, or null if nothing is selected. */\n\tgetSelectionPageCenter() {\n\t\tconst selectionRotation = this.editor.getSelectionRotation()\n\t\tconst selectionBounds = this.editor.getSelectionRotatedPageBounds()\n\t\tif (!selectionBounds) return null\n\t\treturn Vec.RotWith(selectionBounds.center, selectionBounds.point, selectionRotation)\n\t}\n\n\t/**\n\t * Returns the center of a shape in page coordinates, or null if the shape has no page transform.\n\t * @param shape - The shape to get the center of.\n\t */\n\tgetPageCenter(shape: TLShape) {\n\t\tconst pageTransform = this.editor.getShapePageTransform(shape.id)\n\t\tif (!pageTransform) return null\n\t\tconst center = this.editor.getShapeGeometry(shape).bounds.center\n\t\treturn Mat.applyToPoint(pageTransform, center)\n\t}\n\n\t/**\n\t * Returns the rotation of a shape in page space by ID, in radians.\n\t * @param id - The shape ID.\n\t */\n\tgetPageRotationById(id: TLShapeId): number {\n\t\tconst pageTransform = this.editor.getShapePageTransform(id)\n\t\treturn pageTransform ? pageTransform.rotation() : 0\n\t}\n\n\t/**\n\t * Returns the rotation of a shape in page space, in radians.\n\t * @param shape - The shape to get the rotation of.\n\t */\n\tgetPageRotation(shape: TLShape) {\n\t\treturn this.getPageRotationById(shape.id)\n\t}\n\n\t/**\n\t * Returns all arrow shapes bound to the given shape.\n\t * @param shapeId - The shape ID to find arrows bound to.\n\t */\n\tgetArrowsBoundTo(shapeId: TLShapeId) {\n\t\tconst ids = new Set(this.editor.getBindingsToShape(shapeId, 'arrow').map((b) => b.fromId))\n\t\treturn compact(Array.from(ids, (id) => this.editor.getShape<TLArrowShape>(id)))\n\t}\n\n\t/* --------------- Event building --------------- */\n\n\tprivate getModifierKeys() {\n\t\tconst { inputs } = this.editor\n\t\treturn {\n\t\t\tshiftKey: inputs.getShiftKey(),\n\t\t\tctrlKey: inputs.getCtrlKey(),\n\t\t\taltKey: inputs.getAltKey(),\n\t\t\tmetaKey: inputs.getMetaKey(),\n\t\t\taccelKey: isAccelKey(inputs),\n\t\t}\n\t}\n\n\t/**\n\t * Builds a TLPointerEventInfo object for input simulation.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tprivate getPointerEventInfo(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t): TLPointerEventInfo {\n\t\tif (typeof options === 'string') {\n\t\t\toptions = { target: 'shape', shape: this.editor.getShape(options) }\n\t\t} else if (options === undefined) {\n\t\t\toptions = { target: 'canvas' }\n\t\t}\n\t\tconst info = {\n\t\t\tname: 'pointer_down',\n\t\t\ttype: 'pointer',\n\t\t\tpointerId: 1,\n\t\t\t...this.getModifierKeys(),\n\t\t\taccelKey: isAccelKey({ ...this.editor.inputs.toJson(), ...modifiers }),\n\t\t\tpoint: { x, y, z: null },\n\t\t\tbutton: 0,\n\t\t\tisPen: false,\n\t\t\t...options,\n\t\t\t...modifiers,\n\t\t} as TLPointerEventInfo\n\n\t\t// In simulated input, a pen is assumed to be a direct-display pen (which auto-enables pen\n\t\t// mode) unless a test explicitly opts out with `isPenDirect: false`.\n\t\tif (info.isPenDirect === undefined) info.isPenDirect = info.isPen\n\n\t\tif (tlenv.isDarwin && info.button === 0 && info.ctrlKey && !info.metaKey) {\n\t\t\tinfo.button = 2\n\t\t}\n\n\t\treturn info\n\t}\n\n\t/**\n\t * Builds a TLKeyboardEventInfo object for input simulation.\n\t * @param key - The key being pressed.\n\t * @param name - The event name (key_down, key_up, key_repeat).\n\t * @param options - Partial event info overrides.\n\t */\n\tprivate getKeyboardEventInfo(\n\t\tkey: string,\n\t\tname: TLKeyboardEventInfo['name'],\n\t\toptions = {} as Partial<Omit<TLKeyboardEventInfo, 'point'>>\n\t): TLKeyboardEventInfo {\n\t\t// Like a real DOM keyboard event, the flags reflect every modifier currently held \u2014 not\n\t\t// just the key being pressed. We OR in the editor's current modifier state so that, e.g.,\n\t\t// pressing Shift while Control is held still reports ctrlKey: true. (keyUp passes explicit\n\t\t// flag overrides for its release semantics, so those win over these defaults.)\n\t\tconst flags = {\n\t\t\tshiftKey: key === 'Shift' || this.editor.inputs.getShiftKey(),\n\t\t\tctrlKey: key === 'Control' || key === 'Meta' || this.editor.inputs.getCtrlKey(),\n\t\t\taltKey: key === 'Alt' || this.editor.inputs.getAltKey(),\n\t\t\tmetaKey: key === 'Meta' || this.editor.inputs.getMetaKey(),\n\t\t\t...options,\n\t\t}\n\t\treturn {\n\t\t\t...flags,\n\t\t\taccelKey: flags.accelKey ?? isAccelKey(flags),\n\t\t\tname,\n\t\t\tcode: KEY_CODES[key] ?? 'Key' + key[0].toUpperCase() + key.slice(1),\n\t\t\ttype: 'keyboard',\n\t\t\tkey,\n\t\t}\n\t}\n\n\t/* --------------- Input events --------------- */\n\n\t/**\n\t * Emits tick events to advance the editor by the given number of frames (default 1).\n\t * @param count - Number of tick events to emit. Defaults to 1.\n\t */\n\tforceTick(count = 1) {\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tthis.editor.emit('tick', 16)\n\t\t}\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pointer move event at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tpointerMove(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\tname: 'pointer_move',\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pointer down event at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tpointerDown(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\tname: 'pointer_down',\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pointer up event at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tpointerUp(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\tname: 'pointer_up',\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pointer down followed by pointer up at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tclick(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.pointerDown(x, y, options, modifiers)\n\t\tthis.pointerUp(x, y, options, modifiers)\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a right-click (button 2) down and up at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\trightClick(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\tname: 'pointer_down',\n\t\t\tbutton: 2,\n\t\t})\n\t\tthis.forceTick()\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\tname: 'pointer_up',\n\t\t\tbutton: 2,\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a double-click sequence at the given screen coordinates.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param options - Target shape/selection or partial event info.\n\t * @param modifiers - Override shift, ctrl, or alt key state.\n\t */\n\tdoubleClick(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\toptions?: PointerEventInit,\n\t\tmodifiers?: EventModifiers\n\t) {\n\t\tthis.click(x, y, options, modifiers)\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\ttype: 'click',\n\t\t\tname: 'double_click',\n\t\t\tphase: 'down',\n\t\t})\n\t\tthis.editor.dispatch({\n\t\t\t...this.getPointerEventInfo(x, y, options, modifiers),\n\t\t\ttype: 'click',\n\t\t\tname: 'double_click',\n\t\t\tphase: 'up',\n\t\t})\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a key down followed by key up for the given key.\n\t * @param key - The key to press (e.g. 'a', 'Enter', 'Shift').\n\t * @param options - Partial keyboard event overrides.\n\t */\n\tkeyPress(key: string, options = {} as Partial<Omit<TLKeyboardEventInfo, 'key'>>) {\n\t\tthis.keyDown(key, options)\n\t\tthis.keyUp(key, options)\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a key down event for the given key.\n\t * @param key - The key to press (e.g. 'a', 'Enter', 'Shift').\n\t * @param options - Partial keyboard event overrides.\n\t */\n\tkeyDown(key: string, options = {} as Partial<Omit<TLKeyboardEventInfo, 'key'>>) {\n\t\tthis.editor.dispatch(this.getKeyboardEventInfo(key, 'key_down', options))\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a key repeat event for the given key.\n\t * @param key - The key that is repeating (e.g. 'a', 'ArrowDown').\n\t * @param options - Partial keyboard event overrides.\n\t */\n\tkeyRepeat(key: string, options = {} as Partial<Omit<TLKeyboardEventInfo, 'key'>>) {\n\t\tthis.editor.dispatch(this.getKeyboardEventInfo(key, 'key_repeat', options))\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a key up event for the given key.\n\t * @param key - The key to release (e.g. 'a', 'Enter', 'Shift').\n\t * @param options - Partial keyboard event overrides.\n\t */\n\tkeyUp(key: string, options = {} as Partial<Omit<TLKeyboardEventInfo, 'key'>>) {\n\t\tthis.editor.dispatch(\n\t\t\tthis.getKeyboardEventInfo(key, 'key_up', {\n\t\t\t\tshiftKey: this.editor.inputs.getShiftKey() && key !== 'Shift',\n\t\t\t\tctrlKey: this.editor.inputs.getCtrlKey() && !(key === 'Control' || key === 'Meta'),\n\t\t\t\taltKey: this.editor.inputs.getAltKey() && key !== 'Alt',\n\t\t\t\tmetaKey: this.editor.inputs.getMetaKey() && key !== 'Meta',\n\t\t\t\t...options,\n\t\t\t})\n\t\t)\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a wheel event with the given delta values.\n\t * @param dx - Horizontal scroll delta.\n\t * @param dy - Vertical scroll delta.\n\t * @param options - Partial wheel event overrides.\n\t */\n\twheel(dx: number, dy: number, options = {} as Partial<Omit<TLWheelEventInfo, 'delta'>>) {\n\t\tconst currentScreenPoint = this.editor.inputs.getCurrentScreenPoint()\n\t\tthis.editor.dispatch({\n\t\t\ttype: 'wheel',\n\t\t\tname: 'wheel',\n\t\t\tpoint: new Vec(currentScreenPoint.x, currentScreenPoint.y),\n\t\t\t...this.getModifierKeys(),\n\t\t\t...options,\n\t\t\tdelta: { x: dx, y: dy },\n\t\t})\n\t\tthis.forceTick(2)\n\t\treturn this\n\t}\n\n\t/**\n\t * Pans the camera by the given offset (in page coordinates). Does nothing if camera is locked.\n\t * @param offset - The pan delta (x, y) in page coordinates.\n\t */\n\tpan(offset: VecLike) {\n\t\tconst { isLocked, panSpeed } = this.editor.getCameraOptions()\n\t\tif (isLocked) return this\n\t\tconst { x: cx, y: cy, z: cz } = this.editor.getCamera()\n\t\tthis.editor.setCamera(\n\t\t\tnew Vec(cx + (offset.x * panSpeed) / cz, cy + (offset.y * panSpeed) / cz, cz),\n\t\t\t{ immediate: true }\n\t\t)\n\t\treturn this\n\t}\n\n\tprivate pinch(\n\t\tname: TLPinchEventInfo['name'],\n\t\tx: number,\n\t\ty: number,\n\t\tz: number,\n\t\tdx: number,\n\t\tdy: number,\n\t\tdz: number,\n\t\toptions: Partial<Omit<TLPinchEventInfo, 'point' | 'delta' | 'offset'>>\n\t) {\n\t\tthis.editor.dispatch({\n\t\t\ttype: 'pinch',\n\t\t\tname,\n\t\t\t...this.getModifierKeys(),\n\t\t\t...options,\n\t\t\tpoint: { x, y, z },\n\t\t\tdelta: { x: dx, y: dy, z: dz },\n\t\t})\n\t}\n\n\t/**\n\t * Dispatches a pinch start event.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param z - Pinch scale/factor.\n\t * @param dx - Delta x for pinch.\n\t * @param dy - Delta y for pinch.\n\t * @param dz - Delta z for pinch.\n\t * @param options - Partial pinch event overrides.\n\t */\n\tpinchStart(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\tz: number,\n\t\tdx: number,\n\t\tdy: number,\n\t\tdz: number,\n\t\toptions = {} as Partial<Omit<TLPinchEventInfo, 'point' | 'delta' | 'offset'>>\n\t) {\n\t\tthis.pinch('pinch_start', x, y, z, dx, dy, dz, options)\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pinch move event (pinch_to).\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param z - Pinch scale/factor.\n\t * @param dx - Delta x for pinch.\n\t * @param dy - Delta y for pinch.\n\t * @param dz - Delta z for pinch.\n\t * @param options - Partial pinch event overrides.\n\t */\n\tpinchTo(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\tz: number,\n\t\tdx: number,\n\t\tdy: number,\n\t\tdz: number,\n\t\toptions = {} as Partial<Omit<TLPinchEventInfo, 'point' | 'delta' | 'offset'>>\n\t) {\n\t\tthis.pinch('pinch', x, y, z, dx, dy, dz, options)\n\t\treturn this\n\t}\n\n\t/**\n\t * Dispatches a pinch end event.\n\t * @param x - Screen x coordinate. Defaults to current pointer.\n\t * @param y - Screen y coordinate. Defaults to current pointer.\n\t * @param z - Pinch scale/factor.\n\t * @param dx - Delta x for pinch.\n\t * @param dy - Delta y for pinch.\n\t * @param dz - Delta z for pinch.\n\t * @param options - Partial pinch event overrides.\n\t */\n\tpinchEnd(\n\t\tx = this.editor.inputs.getCurrentScreenPoint().x,\n\t\ty = this.editor.inputs.getCurrentScreenPoint().y,\n\t\tz: number,\n\t\tdx: number,\n\t\tdy: number,\n\t\tdz: number,\n\t\toptions = {} as Partial<Omit<TLPinchEventInfo, 'point' | 'delta' | 'offset'>>\n\t) {\n\t\tthis.pinch('pinch_end', x, y, z, dx, dy, dz, options)\n\t\tthis.forceTick()\n\t\treturn this\n\t}\n\n\t/* --------------- Interaction helpers --------------- */\n\n\t/**\n\t * Simulates rotating the current selection by the given angle in radians via the rotation handle.\n\t * @param angleRadians - Rotation angle in radians.\n\t * @param options - Optional handle and shiftKey. handle defaults to 'top_left_rotate'.\n\t */\n\trotateSelection(\n\t\tangleRadians: number,\n\t\toptions: { handle?: RotateCorner; shiftKey?: boolean } = {}\n\t) {\n\t\tconst { handle = 'top_left_rotate', shiftKey = false } = options\n\t\tif (this.editor.getSelectedShapeIds().length === 0) {\n\t\t\tthrow new Error('No selection')\n\t\t}\n\n\t\tthis.editor.setCurrentTool('select')\n\n\t\tconst bounds = this.editor.getSelectionRotatedPageBounds()!\n\t\tconst handlePoint = bounds\n\t\t\t.getHandlePoint(ROTATE_CORNER_TO_SELECTION_CORNER[handle])\n\t\t\t.clone()\n\t\t\t.rotWith(bounds.point, this.editor.getSelectionRotation())\n\n\t\tconst targetHandlePoint = Vec.RotWith(handlePoint, this.getSelectionPageCenter()!, angleRadians)\n\n\t\tconst screenHandle = this.editor.pageToScreen(handlePoint)\n\t\tconst screenTarget = this.editor.pageToScreen(targetHandlePoint)\n\n\t\tthis.pointerDown(screenHandle.x, screenHandle.y, { target: 'selection', handle })\n\t\tthis.pointerMove(screenTarget.x, screenTarget.y, { shiftKey })\n\t\tthis.pointerUp()\n\t\treturn this\n\t}\n\n\t/**\n\t * Simulates translating the current selection by the given delta in page coordinates.\n\t * @param dx - Horizontal delta in page coordinates.\n\t * @param dy - Vertical delta in page coordinates.\n\t * @param options - Partial pointer event overrides (e.g. altKey for center-based scaling).\n\t */\n\ttranslateSelection(dx: number, dy: number, options?: Partial<TLPointerEventInfo>) {\n\t\tif (this.editor.getSelectedShapeIds().length === 0) {\n\t\t\tthrow new Error('No selection')\n\t\t}\n\t\tthis.editor.setCurrentTool('select')\n\n\t\tconst center = this.getSelectionPageCenter()!\n\t\tconst screenCenter = this.editor.pageToScreen(center)\n\n\t\tthis.pointerDown(screenCenter.x, screenCenter.y, this.editor.getSelectedShapeIds()[0])\n\t\tconst numSteps = 10\n\t\tfor (let i = 1; i < numSteps; i++) {\n\t\t\tconst p = this.editor.pageToScreen({\n\t\t\t\tx: center.x + (i * dx) / numSteps,\n\t\t\t\ty: center.y + (i * dy) / numSteps,\n\t\t\t})\n\t\t\tthis.pointerMove(p.x, p.y, options)\n\t\t}\n\t\tconst endScreen = this.editor.pageToScreen({ x: center.x + dx, y: center.y + dy })\n\t\tthis.pointerUp(endScreen.x, endScreen.y, options)\n\t\treturn this\n\t}\n\n\t/**\n\t * Simulates resizing the current selection via the given handle, with optional scale factors.\n\t * @param scale - Scale factors for x and y. Defaults to `\\{ scaleX: 1, scaleY: 1 \\}`.\n\t * @param handle - The selection handle to drag (e.g. 'top', 'bottom_right').\n\t * @param options - Partial pointer event overrides (e.g. altKey to scale from center).\n\t */\n\tresizeSelection(\n\t\tscale: { scaleX?: number; scaleY?: number } = {},\n\t\thandle: SelectionHandle,\n\t\toptions?: Partial<TLPointerEventInfo>\n\t) {\n\t\tconst { scaleX = 1, scaleY = 1 } = scale\n\t\tif (this.editor.getSelectedShapeIds().length === 0) {\n\t\t\tthrow new Error('No selection')\n\t\t}\n\t\tthis.editor.setCurrentTool('select')\n\t\tconst bounds = this.editor.getSelectionRotatedPageBounds()!\n\t\tconst rotation = this.editor.getSelectionRotation()\n\t\tconst preRotationHandlePoint = bounds.getHandlePoint(handle)\n\n\t\tconst preRotationScaleOriginPoint = options?.altKey\n\t\t\t? bounds.center\n\t\t\t: bounds.getHandlePoint(rotateSelectionHandle(handle, Math.PI))\n\n\t\tconst preRotationTargetHandlePoint = Vec.Add(\n\t\t\tVec.Sub(preRotationHandlePoint, preRotationScaleOriginPoint).mulV({\n\t\t\t\tx: scaleX,\n\t\t\t\ty: scaleY,\n\t\t\t}),\n\t\t\tpreRotationScaleOriginPoint\n\t\t)\n\n\t\tconst handlePoint = Vec.RotWith(preRotationHandlePoint, bounds.point, rotation)\n\t\tconst targetHandlePoint = Vec.RotWith(preRotationTargetHandlePoint, bounds.point, rotation)\n\n\t\tconst screenHandle = this.editor.pageToScreen(handlePoint)\n\t\tconst screenTarget = this.editor.pageToScreen(targetHandlePoint)\n\n\t\tthis.pointerDown(screenHandle.x, screenHandle.y, { target: 'selection', handle }, options)\n\t\tthis.pointerMove(screenTarget.x, screenTarget.y, options)\n\t\tthis.pointerUp(screenTarget.x, screenTarget.y, options)\n\t\treturn this\n\t}\n}\n"],
5
+ "mappings": "AAAA;AAAA,EAEC;AAAA,EACA;AAAA,EACA;AAAA,EAWA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAQP,MAAM,YAAoC;AAAA,EACzC,OAAO;AAAA,EACP,KAAK;AAAA,EACL,SAAS;AAAA,EACT,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,SAAS;AAAA,EACT,WAAW;AACZ;AAUO,MAAM,OAAO;AAAA,EAKnB,YAA4B,QAAgB;AAAhB;AAC3B,SAAK,WAAW,KAAK,OAAO,YAAY,2BAA2B,SAAS,CAAC,WAAW;AACvF,WAAK,mBAAmB,KAAK,MAAM;AACnC,UAAI,KAAK,mBAAmB,SAAS,KAAM;AAC1C,aAAK,qBAAqB,KAAK,mBAAmB,MAAM,IAAI;AAAA,MAC7D;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAP4B;AAAA;AAAA,EAHpB;AAAA,EACA,qBAAgC,CAAC;AAAA;AAAA,EAYzC,UAAU;AACT,SAAK,WAAW;AAChB,SAAK,WAAW;AAAA,EACjB;AAAA;AAAA,EAGA,YAA8B;AAAA;AAAA;AAAA;AAAA;AAAA,EAM9B,qBAAqB,QAAQ,GAAG;AAC/B,WAAO,KAAK,mBAAmB,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,KAAK,OAAO,SAAS,CAAC,CAAE;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA,EAKA,sBAAyC;AACxC,UAAM,YAAY,KAAK,mBAAmB,KAAK,mBAAmB,SAAS,CAAC;AAC5E,WAAO,KAAK,OAAO,SAAY,SAAS;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAc,IAAY;AACzB,WAAO,cAAc,EAAE;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,IAAY;AACxB,WAAO,eAAe,SAAS,EAAE;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KAAK,MAAM,KAAK,OAAO,oBAAoB,GAAG;AAC7C,QAAI,IAAI,SAAS,GAAG;AACnB,YAAM,UAAU,KAAK,OAAO,0BAA0B,GAAG;AACzD,UAAI,SAAS;AACZ,aAAK,YAAY;AAAA,MAClB;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,MAAM,KAAK,OAAO,oBAAoB,GAAG;AAC5C,QAAI,IAAI,SAAS,GAAG;AACnB,WAAK,KAAK,GAAG;AACb,WAAK,OAAO,aAAa,GAAG;AAAA,IAC7B;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAiB;AACtB,QAAI,KAAK,cAAc,MAAM;AAC5B,YAAM,IAAI,KAAK,OAAO,OAAO,YAAY,IAAI,KAAK,OAAO,OAAO,oBAAoB,IAAI;AAExF,WAAK,OAAO,yBAAyB,SAAS;AAC9C,WAAK,OAAO,0BAA0B,KAAK,WAAW;AAAA,QACrD,OAAO;AAAA,QACP,QAAQ;AAAA,MACT,CAAC;AAAA,IACF;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA,EAKA,wBAAwB;AACvB,WAAO,KAAK,OAAO,sBAAsB,EAAE;AAAA,EAC5C;AAAA;AAAA,EAGA,yBAAyB;AACxB,UAAM,oBAAoB,KAAK,OAAO,qBAAqB;AAC3D,UAAM,kBAAkB,KAAK,OAAO,8BAA8B;AAClE,QAAI,CAAC,gBAAiB,QAAO;AAC7B,WAAO,IAAI,QAAQ,gBAAgB,QAAQ,gBAAgB,OAAO,iBAAiB;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,OAAgB;AAC7B,UAAM,gBAAgB,KAAK,OAAO,sBAAsB,MAAM,EAAE;AAChE,QAAI,CAAC,cAAe,QAAO;AAC3B,UAAM,SAAS,KAAK,OAAO,iBAAiB,KAAK,EAAE,OAAO;AAC1D,WAAO,IAAI,aAAa,eAAe,MAAM;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,IAAuB;AAC1C,UAAM,gBAAgB,KAAK,OAAO,sBAAsB,EAAE;AAC1D,WAAO,gBAAgB,cAAc,SAAS,IAAI;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,OAAgB;AAC/B,WAAO,KAAK,oBAAoB,MAAM,EAAE;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAiB,SAAoB;AACpC,UAAM,MAAM,IAAI,IAAI,KAAK,OAAO,mBAAmB,SAAS,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AACzF,WAAO,QAAQ,MAAM,KAAK,KAAK,CAAC,OAAO,KAAK,OAAO,SAAuB,EAAE,CAAC,CAAC;AAAA,EAC/E;AAAA;AAAA,EAIQ,kBAAkB;AACzB,UAAM,EAAE,OAAO,IAAI,KAAK;AACxB,WAAO;AAAA,MACN,UAAU,OAAO,YAAY;AAAA,MAC7B,SAAS,OAAO,WAAW;AAAA,MAC3B,QAAQ,OAAO,UAAU;AAAA,MACzB,SAAS,OAAO,WAAW;AAAA,MAC3B,UAAU,WAAW,MAAM;AAAA,IAC5B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,oBACP,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,SACA,WACqB;AACrB,QAAI,OAAO,YAAY,UAAU;AAChC,gBAAU,EAAE,QAAQ,SAAS,OAAO,KAAK,OAAO,SAAS,OAAO,EAAE;AAAA,IACnE,WAAW,YAAY,QAAW;AACjC,gBAAU,EAAE,QAAQ,SAAS;AAAA,IAC9B;AACA,UAAM,OAAO;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAW;AAAA,MACX,GAAG,KAAK,gBAAgB;AAAA,MACxB,UAAU,WAAW,EAAE,GAAG,KAAK,OAAO,OAAO,OAAO,GAAG,GAAG,UAAU,CAAC;AAAA,MACrE,OAAO,EAAE,GAAG,GAAG,GAAG,KAAK;AAAA,MACvB,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,GAAG;AAAA,MACH,GAAG;AAAA,IACJ;AAIA,QAAI,KAAK,gBAAgB,OAAW,MAAK,cAAc,KAAK;AAE5D,QAAI,MAAM,YAAY,KAAK,WAAW,KAAK,KAAK,WAAW,CAAC,KAAK,SAAS;AACzE,WAAK,SAAS;AAAA,IACf;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBACP,KACA,MACA,UAAU,CAAC,GACW;AAKtB,UAAM,QAAQ;AAAA,MACb,UAAU,QAAQ,WAAW,KAAK,OAAO,OAAO,YAAY;AAAA,MAC5D,SAAS,QAAQ,aAAa,QAAQ,UAAU,KAAK,OAAO,OAAO,WAAW;AAAA,MAC9E,QAAQ,QAAQ,SAAS,KAAK,OAAO,OAAO,UAAU;AAAA,MACtD,SAAS,QAAQ,UAAU,KAAK,OAAO,OAAO,WAAW;AAAA,MACzD,GAAG;AAAA,IACJ;AACA,WAAO;AAAA,MACN,GAAG;AAAA,MACH,UAAU,MAAM,YAAY,WAAW,KAAK;AAAA,MAC5C;AAAA,MACA,MAAM,UAAU,GAAG,KAAK,QAAQ,IAAI,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC;AAAA,MAClE,MAAM;AAAA,MACN;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,QAAQ,GAAG;AACpB,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC/B,WAAK,OAAO,KAAK,QAAQ,EAAE;AAAA,IAC5B;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACC,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,SACA,WACC;AACD,SAAK,OAAO,SAAS;AAAA,MACpB,GAAG,KAAK,oBAAoB,GAAG,GAAG,SAAS,SAAS;AAAA,MACpD,MAAM;AAAA,IACP,CAAC;AACD,SAAK,UAAU;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACC,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,SACA,WACC;AACD,SAAK,OAAO,SAAS;AAAA,MACpB,GAAG,KAAK,oBAAoB,GAAG,GAAG,SAAS,SAAS;AAAA,MACpD,MAAM;AAAA,IACP,CAAC;AACD,SAAK,UAAU;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UACC,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,SACA,WACC;AACD,SAAK,OAAO,SAAS;AAAA,MACpB,GAAG,KAAK,oBAAoB,GAAG,GAAG,SAAS,SAAS;AAAA,MACpD,MAAM;AAAA,IACP,CAAC;AACD,SAAK,UAAU;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MACC,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,SACA,WACC;AACD,SAAK,YAAY,GAAG,GAAG,SAAS,SAAS;AACzC,SAAK,UAAU,GAAG,GAAG,SAAS,SAAS;AACvC,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WACC,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,SACA,WACC;AACD,SAAK,OAAO,SAAS;AAAA,MACpB,GAAG,KAAK,oBAAoB,GAAG,GAAG,SAAS,SAAS;AAAA,MACpD,MAAM;AAAA,MACN,QAAQ;AAAA,IACT,CAAC;AACD,SAAK,UAAU;AACf,SAAK,OAAO,SAAS;AAAA,MACpB,GAAG,KAAK,oBAAoB,GAAG,GAAG,SAAS,SAAS;AAAA,MACpD,MAAM;AAAA,MACN,QAAQ;AAAA,IACT,CAAC;AACD,SAAK,UAAU;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACC,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,SACA,WACC;AACD,SAAK,MAAM,GAAG,GAAG,SAAS,SAAS;AACnC,SAAK,OAAO,SAAS;AAAA,MACpB,GAAG,KAAK,oBAAoB,GAAG,GAAG,SAAS,SAAS;AAAA,MACpD,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,IACR,CAAC;AACD,SAAK,OAAO,SAAS;AAAA,MACpB,GAAG,KAAK,oBAAoB,GAAG,GAAG,SAAS,SAAS;AAAA,MACpD,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,IACR,CAAC;AACD,SAAK,UAAU;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS,KAAa,UAAU,CAAC,GAAgD;AAChF,SAAK,QAAQ,KAAK,OAAO;AACzB,SAAK,MAAM,KAAK,OAAO;AACvB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,KAAa,UAAU,CAAC,GAAgD;AAC/E,SAAK,OAAO,SAAS,KAAK,qBAAqB,KAAK,YAAY,OAAO,CAAC;AACxE,SAAK,UAAU;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,KAAa,UAAU,CAAC,GAAgD;AACjF,SAAK,OAAO,SAAS,KAAK,qBAAqB,KAAK,cAAc,OAAO,CAAC;AAC1E,SAAK,UAAU;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,KAAa,UAAU,CAAC,GAAgD;AAC7E,SAAK,OAAO;AAAA,MACX,KAAK,qBAAqB,KAAK,UAAU;AAAA,QACxC,UAAU,KAAK,OAAO,OAAO,YAAY,KAAK,QAAQ;AAAA,QACtD,SAAS,KAAK,OAAO,OAAO,WAAW,KAAK,EAAE,QAAQ,aAAa,QAAQ;AAAA,QAC3E,QAAQ,KAAK,OAAO,OAAO,UAAU,KAAK,QAAQ;AAAA,QAClD,SAAS,KAAK,OAAO,OAAO,WAAW,KAAK,QAAQ;AAAA,QACpD,GAAG;AAAA,MACJ,CAAC;AAAA,IACF;AACA,SAAK,UAAU;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,IAAY,IAAY,UAAU,CAAC,GAA+C;AACvF,UAAM,qBAAqB,KAAK,OAAO,OAAO,sBAAsB;AACpE,SAAK,OAAO,SAAS;AAAA,MACpB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO,IAAI,IAAI,mBAAmB,GAAG,mBAAmB,CAAC;AAAA,MACzD,GAAG,KAAK,gBAAgB;AAAA,MACxB,GAAG;AAAA,MACH,OAAO,EAAE,GAAG,IAAI,GAAG,GAAG;AAAA,IACvB,CAAC;AACD,SAAK,UAAU,CAAC;AAChB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,QAAiB;AACpB,UAAM,EAAE,UAAU,SAAS,IAAI,KAAK,OAAO,iBAAiB;AAC5D,QAAI,SAAU,QAAO;AACrB,UAAM,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,KAAK,OAAO,UAAU;AACtD,SAAK,OAAO;AAAA,MACX,IAAI,IAAI,KAAM,OAAO,IAAI,WAAY,IAAI,KAAM,OAAO,IAAI,WAAY,IAAI,EAAE;AAAA,MAC5E,EAAE,WAAW,KAAK;AAAA,IACnB;AACA,WAAO;AAAA,EACR;AAAA,EAEQ,MACP,MACA,GACA,GACA,GACA,IACA,IACA,IACA,SACC;AACD,SAAK,OAAO,SAAS;AAAA,MACpB,MAAM;AAAA,MACN;AAAA,MACA,GAAG,KAAK,gBAAgB;AAAA,MACxB,GAAG;AAAA,MACH,OAAO,EAAE,GAAG,GAAG,EAAE;AAAA,MACjB,OAAO,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG;AAAA,IAC9B,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,WACC,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,GACA,IACA,IACA,IACA,UAAU,CAAC,GACV;AACD,SAAK,MAAM,eAAe,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,OAAO;AACtD,SAAK,UAAU;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,QACC,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,GACA,IACA,IACA,IACA,UAAU,CAAC,GACV;AACD,SAAK,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,OAAO;AAChD,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,SACC,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,IAAI,KAAK,OAAO,OAAO,sBAAsB,EAAE,GAC/C,GACA,IACA,IACA,IACA,UAAU,CAAC,GACV;AACD,SAAK,MAAM,aAAa,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,OAAO;AACpD,SAAK,UAAU;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,gBACC,cACA,UAAyD,CAAC,GACzD;AACD,UAAM,EAAE,SAAS,mBAAmB,WAAW,MAAM,IAAI;AACzD,QAAI,KAAK,OAAO,oBAAoB,EAAE,WAAW,GAAG;AACnD,YAAM,IAAI,MAAM,cAAc;AAAA,IAC/B;AAEA,SAAK,OAAO,eAAe,QAAQ;AAEnC,UAAM,SAAS,KAAK,OAAO,8BAA8B;AACzD,UAAM,cAAc,OAClB,eAAe,kCAAkC,MAAM,CAAC,EACxD,MAAM,EACN,QAAQ,OAAO,OAAO,KAAK,OAAO,qBAAqB,CAAC;AAE1D,UAAM,oBAAoB,IAAI,QAAQ,aAAa,KAAK,uBAAuB,GAAI,YAAY;AAE/F,UAAM,eAAe,KAAK,OAAO,aAAa,WAAW;AACzD,UAAM,eAAe,KAAK,OAAO,aAAa,iBAAiB;AAE/D,SAAK,YAAY,aAAa,GAAG,aAAa,GAAG,EAAE,QAAQ,aAAa,OAAO,CAAC;AAChF,SAAK,YAAY,aAAa,GAAG,aAAa,GAAG,EAAE,SAAS,CAAC;AAC7D,SAAK,UAAU;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,mBAAmB,IAAY,IAAY,SAAuC;AACjF,QAAI,KAAK,OAAO,oBAAoB,EAAE,WAAW,GAAG;AACnD,YAAM,IAAI,MAAM,cAAc;AAAA,IAC/B;AACA,SAAK,OAAO,eAAe,QAAQ;AAEnC,UAAM,SAAS,KAAK,uBAAuB;AAC3C,UAAM,eAAe,KAAK,OAAO,aAAa,MAAM;AAEpD,SAAK,YAAY,aAAa,GAAG,aAAa,GAAG,KAAK,OAAO,oBAAoB,EAAE,CAAC,CAAC;AACrF,UAAM,WAAW;AACjB,aAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAClC,YAAM,IAAI,KAAK,OAAO,aAAa;AAAA,QAClC,GAAG,OAAO,IAAK,IAAI,KAAM;AAAA,QACzB,GAAG,OAAO,IAAK,IAAI,KAAM;AAAA,MAC1B,CAAC;AACD,WAAK,YAAY,EAAE,GAAG,EAAE,GAAG,OAAO;AAAA,IACnC;AACA,UAAM,YAAY,KAAK,OAAO,aAAa,EAAE,GAAG,OAAO,IAAI,IAAI,GAAG,OAAO,IAAI,GAAG,CAAC;AACjF,SAAK,UAAU,UAAU,GAAG,UAAU,GAAG,OAAO;AAChD,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBACC,QAA8C,CAAC,GAC/C,QACA,SACC;AACD,UAAM,EAAE,SAAS,GAAG,SAAS,EAAE,IAAI;AACnC,QAAI,KAAK,OAAO,oBAAoB,EAAE,WAAW,GAAG;AACnD,YAAM,IAAI,MAAM,cAAc;AAAA,IAC/B;AACA,SAAK,OAAO,eAAe,QAAQ;AACnC,UAAM,SAAS,KAAK,OAAO,8BAA8B;AACzD,UAAM,WAAW,KAAK,OAAO,qBAAqB;AAClD,UAAM,yBAAyB,OAAO,eAAe,MAAM;AAE3D,UAAM,8BAA8B,SAAS,SAC1C,OAAO,SACP,OAAO,eAAe,sBAAsB,QAAQ,KAAK,EAAE,CAAC;AAE/D,UAAM,+BAA+B,IAAI;AAAA,MACxC,IAAI,IAAI,wBAAwB,2BAA2B,EAAE,KAAK;AAAA,QACjE,GAAG;AAAA,QACH,GAAG;AAAA,MACJ,CAAC;AAAA,MACD;AAAA,IACD;AAEA,UAAM,cAAc,IAAI,QAAQ,wBAAwB,OAAO,OAAO,QAAQ;AAC9E,UAAM,oBAAoB,IAAI,QAAQ,8BAA8B,OAAO,OAAO,QAAQ;AAE1F,UAAM,eAAe,KAAK,OAAO,aAAa,WAAW;AACzD,UAAM,eAAe,KAAK,OAAO,aAAa,iBAAiB;AAE/D,SAAK,YAAY,aAAa,GAAG,aAAa,GAAG,EAAE,QAAQ,aAAa,OAAO,GAAG,OAAO;AACzF,SAAK,YAAY,aAAa,GAAG,aAAa,GAAG,OAAO;AACxD,SAAK,UAAU,aAAa,GAAG,aAAa,GAAG,OAAO;AACtD,WAAO;AAAA,EACR;AACD;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tldraw/driver",
3
3
  "description": "Imperative API for driving the tldraw editor programmatically.",
4
- "version": "5.3.2",
4
+ "version": "5.4.0-canary.02cd0bd3b597",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -42,8 +42,8 @@
42
42
  "lint": "yarn run -T tsx ../../internal/scripts/lint.ts"
43
43
  },
44
44
  "dependencies": {
45
- "@tldraw/editor": "5.3.2",
46
- "@tldraw/utils": "5.3.2"
45
+ "@tldraw/editor": "5.4.0-canary.02cd0bd3b597",
46
+ "@tldraw/utils": "5.4.0-canary.02cd0bd3b597"
47
47
  },
48
48
  "devDependencies": {
49
49
  "lazyrepo": "0.0.0-alpha.27",