@tldraw/driver 5.4.0-canary.b8ec00e16e3a → 5.4.0-canary.b902bfb68544

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/LICENSE.md ADDED
@@ -0,0 +1 @@
1
+ This code is licensed under the [tldraw license](https://github.com/tldraw/tldraw/blob/main/LICENSE.md)
@@ -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
 
package/dist-cjs/index.js CHANGED
@@ -25,7 +25,7 @@ var import_utils = require("@tldraw/utils");
25
25
  var import_Driver = require("./lib/Driver");
26
26
  (0, import_utils.registerTldrawLibraryVersion)(
27
27
  "@tldraw/driver",
28
- "5.4.0-canary.b8ec00e16e3a",
28
+ "5.4.0-canary.b902bfb68544",
29
29
  "cjs"
30
30
  );
31
31
  //# sourceMappingURL=index.js.map
@@ -22,6 +22,18 @@ __export(Driver_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(Driver_exports);
24
24
  var import_editor = require("@tldraw/editor");
25
+ const KEY_CODES = {
26
+ Shift: "ShiftLeft",
27
+ Alt: "AltLeft",
28
+ Control: "CtrlLeft",
29
+ Meta: "MetaLeft",
30
+ " ": "Space",
31
+ Enter: "Enter",
32
+ ArrowRight: "ArrowRight",
33
+ ArrowLeft: "ArrowLeft",
34
+ ArrowUp: "ArrowUp",
35
+ ArrowDown: "ArrowDown"
36
+ };
25
37
  class Driver {
26
38
  constructor(editor) {
27
39
  this.editor = editor;
@@ -34,7 +46,8 @@ class Driver {
34
46
  }
35
47
  editor;
36
48
  /** The underlying Editor instance. */
37
- _cleanup = null;
49
+ _cleanup;
50
+ _lastCreatedShapes = [];
38
51
  /** Remove all registered side-effect handlers. Call when this controller is no longer needed. */
39
52
  dispose() {
40
53
  this._cleanup?.();
@@ -42,7 +55,6 @@ class Driver {
42
55
  }
43
56
  /** Local clipboard content. Used by copy, cut, and paste. */
44
57
  clipboard = null;
45
- _lastCreatedShapes = [];
46
58
  /**
47
59
  * Get the last created shapes.
48
60
  * @param count - The number of shapes to get.
@@ -92,10 +104,7 @@ class Driver {
92
104
  */
93
105
  cut(ids = this.editor.getSelectedShapeIds()) {
94
106
  if (ids.length > 0) {
95
- const content = this.editor.getContentFromCurrentPage(ids);
96
- if (content) {
97
- this.clipboard = content;
98
- }
107
+ this.copy(ids);
99
108
  this.editor.deleteShapes(ids);
100
109
  }
101
110
  return this;
@@ -143,10 +152,7 @@ class Driver {
143
152
  */
144
153
  getPageRotationById(id) {
145
154
  const pageTransform = this.editor.getShapePageTransform(id);
146
- if (pageTransform) {
147
- return import_editor.Mat.Decompose(pageTransform).rotation;
148
- }
149
- return 0;
155
+ return pageTransform ? pageTransform.rotation() : 0;
150
156
  }
151
157
  /**
152
158
  * Returns the rotation of a shape in page space, in radians.
@@ -164,6 +170,16 @@ class Driver {
164
170
  return (0, import_editor.compact)(Array.from(ids, (id) => this.editor.getShape(id)));
165
171
  }
166
172
  /* --------------- Event building --------------- */
173
+ getModifierKeys() {
174
+ const { inputs } = this.editor;
175
+ return {
176
+ shiftKey: inputs.getShiftKey(),
177
+ ctrlKey: inputs.getCtrlKey(),
178
+ altKey: inputs.getAltKey(),
179
+ metaKey: inputs.getMetaKey(),
180
+ accelKey: (0, import_editor.isAccelKey)(inputs)
181
+ };
182
+ }
167
183
  /**
168
184
  * Builds a TLPointerEventInfo object for input simulation.
169
185
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -181,10 +197,7 @@ class Driver {
181
197
  name: "pointer_down",
182
198
  type: "pointer",
183
199
  pointerId: 1,
184
- shiftKey: this.editor.inputs.getShiftKey(),
185
- ctrlKey: this.editor.inputs.getCtrlKey(),
186
- altKey: this.editor.inputs.getAltKey(),
187
- metaKey: this.editor.inputs.getMetaKey(),
200
+ ...this.getModifierKeys(),
188
201
  accelKey: (0, import_editor.isAccelKey)({ ...this.editor.inputs.toJson(), ...modifiers }),
189
202
  point: { x, y, z: null },
190
203
  button: 0,
@@ -214,9 +227,9 @@ class Driver {
214
227
  };
215
228
  return {
216
229
  ...flags,
217
- accelKey: flags.accelKey ?? (import_editor.tlenv.isDarwin ? flags.metaKey : flags.ctrlKey || flags.metaKey),
230
+ accelKey: flags.accelKey ?? (0, import_editor.isAccelKey)(flags),
218
231
  name,
219
- 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),
232
+ code: KEY_CODES[key] ?? "Key" + key[0].toUpperCase() + key.slice(1),
220
233
  type: "keyboard",
221
234
  key
222
235
  };
@@ -319,8 +332,7 @@ class Driver {
319
332
  * @param modifiers - Override shift, ctrl, or alt key state.
320
333
  */
321
334
  doubleClick(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, options, modifiers) {
322
- this.pointerDown(x, y, options, modifiers);
323
- this.pointerUp(x, y, options, modifiers);
335
+ this.click(x, y, options, modifiers);
324
336
  this.editor.dispatch({
325
337
  ...this.getPointerEventInfo(x, y, options, modifiers),
326
338
  type: "click",
@@ -352,7 +364,7 @@ class Driver {
352
364
  * @param options - Partial keyboard event overrides.
353
365
  */
354
366
  keyDown(key, options = {}) {
355
- this.editor.dispatch({ ...this.getKeyboardEventInfo(key, "key_down", options) });
367
+ this.editor.dispatch(this.getKeyboardEventInfo(key, "key_down", options));
356
368
  this.forceTick();
357
369
  return this;
358
370
  }
@@ -362,7 +374,7 @@ class Driver {
362
374
  * @param options - Partial keyboard event overrides.
363
375
  */
364
376
  keyRepeat(key, options = {}) {
365
- this.editor.dispatch({ ...this.getKeyboardEventInfo(key, "key_repeat", options) });
377
+ this.editor.dispatch(this.getKeyboardEventInfo(key, "key_repeat", options));
366
378
  this.forceTick();
367
379
  return this;
368
380
  }
@@ -372,15 +384,15 @@ class Driver {
372
384
  * @param options - Partial keyboard event overrides.
373
385
  */
374
386
  keyUp(key, options = {}) {
375
- this.editor.dispatch({
376
- ...this.getKeyboardEventInfo(key, "key_up", {
387
+ this.editor.dispatch(
388
+ this.getKeyboardEventInfo(key, "key_up", {
377
389
  shiftKey: this.editor.inputs.getShiftKey() && key !== "Shift",
378
390
  ctrlKey: this.editor.inputs.getCtrlKey() && !(key === "Control" || key === "Meta"),
379
391
  altKey: this.editor.inputs.getAltKey() && key !== "Alt",
380
392
  metaKey: this.editor.inputs.getMetaKey() && key !== "Meta",
381
393
  ...options
382
394
  })
383
- });
395
+ );
384
396
  this.forceTick();
385
397
  return this;
386
398
  }
@@ -396,11 +408,7 @@ class Driver {
396
408
  type: "wheel",
397
409
  name: "wheel",
398
410
  point: new import_editor.Vec(currentScreenPoint.x, currentScreenPoint.y),
399
- shiftKey: this.editor.inputs.getShiftKey(),
400
- ctrlKey: this.editor.inputs.getCtrlKey(),
401
- altKey: this.editor.inputs.getAltKey(),
402
- metaKey: this.editor.inputs.getMetaKey(),
403
- accelKey: (0, import_editor.isAccelKey)(this.editor.inputs),
411
+ ...this.getModifierKeys(),
404
412
  ...options,
405
413
  delta: { x: dx, y: dy }
406
414
  });
@@ -421,6 +429,16 @@ class Driver {
421
429
  );
422
430
  return this;
423
431
  }
432
+ pinch(name, x, y, z, dx, dy, dz, options) {
433
+ this.editor.dispatch({
434
+ type: "pinch",
435
+ name,
436
+ ...this.getModifierKeys(),
437
+ ...options,
438
+ point: { x, y, z },
439
+ delta: { x: dx, y: dy, z: dz }
440
+ });
441
+ }
424
442
  /**
425
443
  * Dispatches a pinch start event.
426
444
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -432,18 +450,7 @@ class Driver {
432
450
  * @param options - Partial pinch event overrides.
433
451
  */
434
452
  pinchStart(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, z, dx, dy, dz, options = {}) {
435
- this.editor.dispatch({
436
- type: "pinch",
437
- name: "pinch_start",
438
- shiftKey: this.editor.inputs.getShiftKey(),
439
- ctrlKey: this.editor.inputs.getCtrlKey(),
440
- altKey: this.editor.inputs.getAltKey(),
441
- metaKey: this.editor.inputs.getMetaKey(),
442
- accelKey: (0, import_editor.isAccelKey)(this.editor.inputs),
443
- ...options,
444
- point: { x, y, z },
445
- delta: { x: dx, y: dy, z: dz }
446
- });
453
+ this.pinch("pinch_start", x, y, z, dx, dy, dz, options);
447
454
  this.forceTick();
448
455
  return this;
449
456
  }
@@ -458,18 +465,7 @@ class Driver {
458
465
  * @param options - Partial pinch event overrides.
459
466
  */
460
467
  pinchTo(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, z, dx, dy, dz, options = {}) {
461
- this.editor.dispatch({
462
- type: "pinch",
463
- name: "pinch",
464
- shiftKey: this.editor.inputs.getShiftKey(),
465
- ctrlKey: this.editor.inputs.getCtrlKey(),
466
- altKey: this.editor.inputs.getAltKey(),
467
- metaKey: this.editor.inputs.getMetaKey(),
468
- accelKey: (0, import_editor.isAccelKey)(this.editor.inputs),
469
- ...options,
470
- point: { x, y, z },
471
- delta: { x: dx, y: dy, z: dz }
472
- });
468
+ this.pinch("pinch", x, y, z, dx, dy, dz, options);
473
469
  return this;
474
470
  }
475
471
  /**
@@ -483,30 +479,11 @@ class Driver {
483
479
  * @param options - Partial pinch event overrides.
484
480
  */
485
481
  pinchEnd(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, z, dx, dy, dz, options = {}) {
486
- this.editor.dispatch({
487
- type: "pinch",
488
- name: "pinch_end",
489
- shiftKey: this.editor.inputs.getShiftKey(),
490
- ctrlKey: this.editor.inputs.getCtrlKey(),
491
- altKey: this.editor.inputs.getAltKey(),
492
- metaKey: this.editor.inputs.getMetaKey(),
493
- accelKey: (0, import_editor.isAccelKey)(this.editor.inputs),
494
- ...options,
495
- point: { x, y, z },
496
- delta: { x: dx, y: dy, z: dz }
497
- });
482
+ this.pinch("pinch_end", x, y, z, dx, dy, dz, options);
498
483
  this.forceTick();
499
484
  return this;
500
485
  }
501
486
  /* --------------- Interaction helpers --------------- */
502
- /**
503
- * Converts a point from page coordinates to screen coordinates.
504
- * Pointer events operate in screen space, so page-space points must be
505
- * converted before being passed to pointerDown/Move/Up.
506
- */
507
- pageToScreen(point) {
508
- return this.editor.pageToScreen(point);
509
- }
510
487
  /**
511
488
  * Simulates rotating the current selection by the given angle in radians via the rotation handle.
512
489
  * @param angleRadians - Rotation angle in radians.
@@ -518,13 +495,11 @@ class Driver {
518
495
  throw new Error("No selection");
519
496
  }
520
497
  this.editor.setCurrentTool("select");
521
- const handlePoint = this.editor.getSelectionRotatedPageBounds().getHandlePoint(import_editor.ROTATE_CORNER_TO_SELECTION_CORNER[handle]).clone().rotWith(
522
- this.editor.getSelectionRotatedPageBounds().point,
523
- this.editor.getSelectionRotation()
524
- );
498
+ const bounds = this.editor.getSelectionRotatedPageBounds();
499
+ const handlePoint = bounds.getHandlePoint(import_editor.ROTATE_CORNER_TO_SELECTION_CORNER[handle]).clone().rotWith(bounds.point, this.editor.getSelectionRotation());
525
500
  const targetHandlePoint = import_editor.Vec.RotWith(handlePoint, this.getSelectionPageCenter(), angleRadians);
526
- const screenHandle = this.pageToScreen(handlePoint);
527
- const screenTarget = this.pageToScreen(targetHandlePoint);
501
+ const screenHandle = this.editor.pageToScreen(handlePoint);
502
+ const screenTarget = this.editor.pageToScreen(targetHandlePoint);
528
503
  this.pointerDown(screenHandle.x, screenHandle.y, { target: "selection", handle });
529
504
  this.pointerMove(screenTarget.x, screenTarget.y, { shiftKey });
530
505
  this.pointerUp();
@@ -542,17 +517,17 @@ class Driver {
542
517
  }
543
518
  this.editor.setCurrentTool("select");
544
519
  const center = this.getSelectionPageCenter();
545
- const screenCenter = this.pageToScreen(center);
520
+ const screenCenter = this.editor.pageToScreen(center);
546
521
  this.pointerDown(screenCenter.x, screenCenter.y, this.editor.getSelectedShapeIds()[0]);
547
522
  const numSteps = 10;
548
523
  for (let i = 1; i < numSteps; i++) {
549
- const p = this.pageToScreen({
524
+ const p = this.editor.pageToScreen({
550
525
  x: center.x + i * dx / numSteps,
551
526
  y: center.y + i * dy / numSteps
552
527
  });
553
528
  this.pointerMove(p.x, p.y, options);
554
529
  }
555
- const endScreen = this.pageToScreen({ x: center.x + dx, y: center.y + dy });
530
+ const endScreen = this.editor.pageToScreen({ x: center.x + dx, y: center.y + dy });
556
531
  this.pointerUp(endScreen.x, endScreen.y, options);
557
532
  return this;
558
533
  }
@@ -569,6 +544,7 @@ class Driver {
569
544
  }
570
545
  this.editor.setCurrentTool("select");
571
546
  const bounds = this.editor.getSelectionRotatedPageBounds();
547
+ const rotation = this.editor.getSelectionRotation();
572
548
  const preRotationHandlePoint = bounds.getHandlePoint(handle);
573
549
  const preRotationScaleOriginPoint = options?.altKey ? bounds.center : bounds.getHandlePoint((0, import_editor.rotateSelectionHandle)(handle, Math.PI));
574
550
  const preRotationTargetHandlePoint = import_editor.Vec.Add(
@@ -578,18 +554,10 @@ class Driver {
578
554
  }),
579
555
  preRotationScaleOriginPoint
580
556
  );
581
- const handlePoint = import_editor.Vec.RotWith(
582
- preRotationHandlePoint,
583
- bounds.point,
584
- this.editor.getSelectionRotation()
585
- );
586
- const targetHandlePoint = import_editor.Vec.RotWith(
587
- preRotationTargetHandlePoint,
588
- bounds.point,
589
- this.editor.getSelectionRotation()
590
- );
591
- const screenHandle = this.pageToScreen(handlePoint);
592
- const screenTarget = this.pageToScreen(targetHandlePoint);
557
+ const handlePoint = import_editor.Vec.RotWith(preRotationHandlePoint, bounds.point, rotation);
558
+ const targetHandlePoint = import_editor.Vec.RotWith(preRotationTargetHandlePoint, bounds.point, rotation);
559
+ const screenHandle = this.editor.pageToScreen(handlePoint);
560
+ const screenTarget = this.editor.pageToScreen(targetHandlePoint);
593
561
  this.pointerDown(screenHandle.x, screenHandle.y, { target: "selection", handle }, options);
594
562
  this.pointerMove(screenTarget.x, screenTarget.y, options);
595
563
  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": "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",
6
6
  "names": []
7
7
  }