@ibodr/driver 0.2.6 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -17,12 +17,12 @@ declare class Driver {
17
17
  readonly editor: Editor;
18
18
  /** The underlying Editor instance. */
19
19
  private _cleanup;
20
+ private _lastCreatedShapes;
20
21
  constructor(editor: Editor);
21
22
  /** Remove all registered side-effect handlers. Call when this controller is no longer needed. */
22
23
  dispose(): void;
23
24
  /** Local clipboard content. Used by copy, cut, and paste. */
24
25
  clipboard: DrContent | null;
25
- private _lastCreatedShapes;
26
26
  /**
27
27
  * Get the last created shapes.
28
28
  * @param count - The number of shapes to get.
@@ -81,6 +81,7 @@ declare class Driver {
81
81
  * @param shapeId - The shape ID to find arrows bound to.
82
82
  */
83
83
  getArrowsBoundTo(shapeId: DrShapeId): DrArrowShape[];
84
+ private getModifierKeys;
84
85
  /**
85
86
  * Builds a DrPointerEventInfo object for input simulation.
86
87
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -185,6 +186,7 @@ declare class Driver {
185
186
  * @param offset - The pan delta (x, y) in page coordinates.
186
187
  */
187
188
  pan(offset: VecLike): this;
189
+ private pinch;
188
190
  /**
189
191
  * Dispatches a pinch start event.
190
192
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -218,12 +220,6 @@ declare class Driver {
218
220
  * @param options - Partial pinch event overrides.
219
221
  */
220
222
  pinchEnd(x: number | undefined, y: number | undefined, z: number, dx: number, dy: number, dz: number, options?: Partial<Omit<DrPinchEventInfo, "point" | "delta" | "offset">>): this;
221
- /**
222
- * Converts a point from page coordinates to screen coordinates.
223
- * Pointer events operate in screen space, so page-space points must be
224
- * converted before being passed to pointerDown/Move/Up.
225
- */
226
- private pageToScreen;
227
223
  /**
228
224
  * Simulates rotating the current selection by the given angle in radians via the rotation handle.
229
225
  * @param angleRadians - Rotation angle in radians.
package/dist/index.mjs CHANGED
@@ -2,6 +2,18 @@ import { registerDrawLibraryVersion } from '@ibodr/utils';
2
2
  import { createShapeId, PageRecordType, Vec, Mat, compact, isAccelKey, tlenv, ROTATE_CORNER_TO_SELECTION_CORNER, rotateSelectionHandle } from '@ibodr/editor';
3
3
 
4
4
  // src/index.ts
5
+ var KEY_CODES = {
6
+ Shift: "ShiftLeft",
7
+ Alt: "AltLeft",
8
+ Control: "CtrlLeft",
9
+ Meta: "MetaLeft",
10
+ " ": "Space",
11
+ Enter: "Enter",
12
+ ArrowRight: "ArrowRight",
13
+ ArrowLeft: "ArrowLeft",
14
+ ArrowUp: "ArrowUp",
15
+ ArrowDown: "ArrowDown"
16
+ };
5
17
  var Driver = class {
6
18
  constructor(editor) {
7
19
  this.editor = editor;
@@ -14,7 +26,8 @@ var Driver = class {
14
26
  }
15
27
  editor;
16
28
  /** The underlying Editor instance. */
17
- _cleanup = null;
29
+ _cleanup;
30
+ _lastCreatedShapes = [];
18
31
  /** Remove all registered side-effect handlers. Call when this controller is no longer needed. */
19
32
  dispose() {
20
33
  this._cleanup?.();
@@ -22,7 +35,6 @@ var Driver = class {
22
35
  }
23
36
  /** Local clipboard content. Used by copy, cut, and paste. */
24
37
  clipboard = null;
25
- _lastCreatedShapes = [];
26
38
  /**
27
39
  * Get the last created shapes.
28
40
  * @param count - The number of shapes to get.
@@ -72,10 +84,7 @@ var Driver = class {
72
84
  */
73
85
  cut(ids = this.editor.getSelectedShapeIds()) {
74
86
  if (ids.length > 0) {
75
- const content = this.editor.getContentFromCurrentPage(ids);
76
- if (content) {
77
- this.clipboard = content;
78
- }
87
+ this.copy(ids);
79
88
  this.editor.deleteShapes(ids);
80
89
  }
81
90
  return this;
@@ -123,10 +132,7 @@ var Driver = class {
123
132
  */
124
133
  getPageRotationById(id) {
125
134
  const pageTransform = this.editor.getShapePageTransform(id);
126
- if (pageTransform) {
127
- return Mat.Decompose(pageTransform).rotation;
128
- }
129
- return 0;
135
+ return pageTransform ? pageTransform.rotation() : 0;
130
136
  }
131
137
  /**
132
138
  * Returns the rotation of a shape in page space, in radians.
@@ -144,6 +150,16 @@ var Driver = class {
144
150
  return compact(Array.from(ids, (id) => this.editor.getShape(id)));
145
151
  }
146
152
  /* --------------- Event building --------------- */
153
+ getModifierKeys() {
154
+ const { inputs } = this.editor;
155
+ return {
156
+ shiftKey: inputs.getShiftKey(),
157
+ ctrlKey: inputs.getCtrlKey(),
158
+ altKey: inputs.getAltKey(),
159
+ metaKey: inputs.getMetaKey(),
160
+ accelKey: isAccelKey(inputs)
161
+ };
162
+ }
147
163
  /**
148
164
  * Builds a DrPointerEventInfo object for input simulation.
149
165
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -157,14 +173,11 @@ var Driver = class {
157
173
  } else if (options === void 0) {
158
174
  options = { target: "canvas" };
159
175
  }
160
- return {
176
+ const info = {
161
177
  name: "pointer_down",
162
178
  type: "pointer",
163
179
  pointerId: 1,
164
- shiftKey: this.editor.inputs.getShiftKey(),
165
- ctrlKey: this.editor.inputs.getCtrlKey(),
166
- altKey: this.editor.inputs.getAltKey(),
167
- metaKey: this.editor.inputs.getMetaKey(),
180
+ ...this.getModifierKeys(),
168
181
  accelKey: isAccelKey({ ...this.editor.inputs.toJson(), ...modifiers }),
169
182
  point: { x, y, z: null },
170
183
  button: 0,
@@ -172,6 +185,11 @@ var Driver = class {
172
185
  ...options,
173
186
  ...modifiers
174
187
  };
188
+ if (info.isPenDirect === void 0) info.isPenDirect = info.isPen;
189
+ if (tlenv.isDarwin && info.button === 0 && info.ctrlKey && !info.metaKey) {
190
+ info.button = 2;
191
+ }
192
+ return info;
175
193
  }
176
194
  /**
177
195
  * Builds a DrKeyboardEventInfo object for input simulation.
@@ -180,15 +198,18 @@ var Driver = class {
180
198
  * @param options - Partial event info overrides.
181
199
  */
182
200
  getKeyboardEventInfo(key, name, options = {}) {
201
+ const flags = {
202
+ shiftKey: key === "Shift" || this.editor.inputs.getShiftKey(),
203
+ ctrlKey: key === "Control" || key === "Meta" || this.editor.inputs.getCtrlKey(),
204
+ altKey: key === "Alt" || this.editor.inputs.getAltKey(),
205
+ metaKey: key === "Meta" || this.editor.inputs.getMetaKey(),
206
+ ...options
207
+ };
183
208
  return {
184
- shiftKey: key === "Shift",
185
- ctrlKey: key === "Control" || key === "Meta",
186
- altKey: key === "Alt",
187
- metaKey: key === "Meta",
188
- accelKey: tlenv.isDarwin ? key === "Meta" : key === "Control" || key === "Meta",
189
- ...options,
209
+ ...flags,
210
+ accelKey: flags.accelKey ?? isAccelKey(flags),
190
211
  name,
191
- 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),
212
+ code: options.code ?? KEY_CODES[key] ?? "Key" + key[0].toUpperCase() + key.slice(1),
192
213
  type: "keyboard",
193
214
  key
194
215
  };
@@ -291,8 +312,7 @@ var Driver = class {
291
312
  * @param modifiers - Override shift, ctrl, or alt key state.
292
313
  */
293
314
  doubleClick(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, options, modifiers) {
294
- this.pointerDown(x, y, options, modifiers);
295
- this.pointerUp(x, y, options, modifiers);
315
+ this.click(x, y, options, modifiers);
296
316
  this.editor.dispatch({
297
317
  ...this.getPointerEventInfo(x, y, options, modifiers),
298
318
  type: "click",
@@ -324,7 +344,7 @@ var Driver = class {
324
344
  * @param options - Partial keyboard event overrides.
325
345
  */
326
346
  keyDown(key, options = {}) {
327
- this.editor.dispatch({ ...this.getKeyboardEventInfo(key, "key_down", options) });
347
+ this.editor.dispatch(this.getKeyboardEventInfo(key, "key_down", options));
328
348
  this.forceTick();
329
349
  return this;
330
350
  }
@@ -334,7 +354,7 @@ var Driver = class {
334
354
  * @param options - Partial keyboard event overrides.
335
355
  */
336
356
  keyRepeat(key, options = {}) {
337
- this.editor.dispatch({ ...this.getKeyboardEventInfo(key, "key_repeat", options) });
357
+ this.editor.dispatch(this.getKeyboardEventInfo(key, "key_repeat", options));
338
358
  this.forceTick();
339
359
  return this;
340
360
  }
@@ -344,15 +364,15 @@ var Driver = class {
344
364
  * @param options - Partial keyboard event overrides.
345
365
  */
346
366
  keyUp(key, options = {}) {
347
- this.editor.dispatch({
348
- ...this.getKeyboardEventInfo(key, "key_up", {
367
+ this.editor.dispatch(
368
+ this.getKeyboardEventInfo(key, "key_up", {
349
369
  shiftKey: this.editor.inputs.getShiftKey() && key !== "Shift",
350
370
  ctrlKey: this.editor.inputs.getCtrlKey() && !(key === "Control" || key === "Meta"),
351
371
  altKey: this.editor.inputs.getAltKey() && key !== "Alt",
352
372
  metaKey: this.editor.inputs.getMetaKey() && key !== "Meta",
353
373
  ...options
354
374
  })
355
- });
375
+ );
356
376
  this.forceTick();
357
377
  return this;
358
378
  }
@@ -368,11 +388,7 @@ var Driver = class {
368
388
  type: "wheel",
369
389
  name: "wheel",
370
390
  point: new Vec(currentScreenPoint.x, currentScreenPoint.y),
371
- shiftKey: this.editor.inputs.getShiftKey(),
372
- ctrlKey: this.editor.inputs.getCtrlKey(),
373
- altKey: this.editor.inputs.getAltKey(),
374
- metaKey: this.editor.inputs.getMetaKey(),
375
- accelKey: isAccelKey(this.editor.inputs),
391
+ ...this.getModifierKeys(),
376
392
  ...options,
377
393
  delta: { x: dx, y: dy }
378
394
  });
@@ -393,6 +409,16 @@ var Driver = class {
393
409
  );
394
410
  return this;
395
411
  }
412
+ pinch(name, x, y, z, dx, dy, dz, options) {
413
+ this.editor.dispatch({
414
+ type: "pinch",
415
+ name,
416
+ ...this.getModifierKeys(),
417
+ ...options,
418
+ point: { x, y, z },
419
+ delta: { x: dx, y: dy, z: dz }
420
+ });
421
+ }
396
422
  /**
397
423
  * Dispatches a pinch start event.
398
424
  * @param x - Screen x coordinate. Defaults to current pointer.
@@ -404,18 +430,7 @@ var Driver = class {
404
430
  * @param options - Partial pinch event overrides.
405
431
  */
406
432
  pinchStart(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, z, dx, dy, dz, options = {}) {
407
- this.editor.dispatch({
408
- type: "pinch",
409
- name: "pinch_start",
410
- shiftKey: this.editor.inputs.getShiftKey(),
411
- ctrlKey: this.editor.inputs.getCtrlKey(),
412
- altKey: this.editor.inputs.getAltKey(),
413
- metaKey: this.editor.inputs.getMetaKey(),
414
- accelKey: isAccelKey(this.editor.inputs),
415
- ...options,
416
- point: { x, y, z },
417
- delta: { x: dx, y: dy, z: dz }
418
- });
433
+ this.pinch("pinch_start", x, y, z, dx, dy, dz, options);
419
434
  this.forceTick();
420
435
  return this;
421
436
  }
@@ -430,18 +445,7 @@ var Driver = class {
430
445
  * @param options - Partial pinch event overrides.
431
446
  */
432
447
  pinchTo(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, z, dx, dy, dz, options = {}) {
433
- this.editor.dispatch({
434
- type: "pinch",
435
- name: "pinch",
436
- shiftKey: this.editor.inputs.getShiftKey(),
437
- ctrlKey: this.editor.inputs.getCtrlKey(),
438
- altKey: this.editor.inputs.getAltKey(),
439
- metaKey: this.editor.inputs.getMetaKey(),
440
- accelKey: isAccelKey(this.editor.inputs),
441
- ...options,
442
- point: { x, y, z },
443
- delta: { x: dx, y: dy, z: dz }
444
- });
448
+ this.pinch("pinch", x, y, z, dx, dy, dz, options);
445
449
  return this;
446
450
  }
447
451
  /**
@@ -455,30 +459,11 @@ var Driver = class {
455
459
  * @param options - Partial pinch event overrides.
456
460
  */
457
461
  pinchEnd(x = this.editor.inputs.getCurrentScreenPoint().x, y = this.editor.inputs.getCurrentScreenPoint().y, z, dx, dy, dz, options = {}) {
458
- this.editor.dispatch({
459
- type: "pinch",
460
- name: "pinch_end",
461
- shiftKey: this.editor.inputs.getShiftKey(),
462
- ctrlKey: this.editor.inputs.getCtrlKey(),
463
- altKey: this.editor.inputs.getAltKey(),
464
- metaKey: this.editor.inputs.getMetaKey(),
465
- accelKey: isAccelKey(this.editor.inputs),
466
- ...options,
467
- point: { x, y, z },
468
- delta: { x: dx, y: dy, z: dz }
469
- });
462
+ this.pinch("pinch_end", x, y, z, dx, dy, dz, options);
470
463
  this.forceTick();
471
464
  return this;
472
465
  }
473
466
  /* --------------- Interaction helpers --------------- */
474
- /**
475
- * Converts a point from page coordinates to screen coordinates.
476
- * Pointer events operate in screen space, so page-space points must be
477
- * converted before being passed to pointerDown/Move/Up.
478
- */
479
- pageToScreen(point) {
480
- return this.editor.pageToScreen(point);
481
- }
482
467
  /**
483
468
  * Simulates rotating the current selection by the given angle in radians via the rotation handle.
484
469
  * @param angleRadians - Rotation angle in radians.
@@ -490,13 +475,11 @@ var Driver = class {
490
475
  throw new Error("No selection");
491
476
  }
492
477
  this.editor.setCurrentTool("select");
493
- const handlePoint = this.editor.getSelectionRotatedPageBounds().getHandlePoint(ROTATE_CORNER_TO_SELECTION_CORNER[handle]).clone().rotWith(
494
- this.editor.getSelectionRotatedPageBounds().point,
495
- this.editor.getSelectionRotation()
496
- );
478
+ const bounds = this.editor.getSelectionRotatedPageBounds();
479
+ const handlePoint = bounds.getHandlePoint(ROTATE_CORNER_TO_SELECTION_CORNER[handle]).clone().rotWith(bounds.point, this.editor.getSelectionRotation());
497
480
  const targetHandlePoint = Vec.RotWith(handlePoint, this.getSelectionPageCenter(), angleRadians);
498
- const screenHandle = this.pageToScreen(handlePoint);
499
- const screenTarget = this.pageToScreen(targetHandlePoint);
481
+ const screenHandle = this.editor.pageToScreen(handlePoint);
482
+ const screenTarget = this.editor.pageToScreen(targetHandlePoint);
500
483
  this.pointerDown(screenHandle.x, screenHandle.y, { target: "selection", handle });
501
484
  this.pointerMove(screenTarget.x, screenTarget.y, { shiftKey });
502
485
  this.pointerUp();
@@ -514,17 +497,17 @@ var Driver = class {
514
497
  }
515
498
  this.editor.setCurrentTool("select");
516
499
  const center = this.getSelectionPageCenter();
517
- const screenCenter = this.pageToScreen(center);
500
+ const screenCenter = this.editor.pageToScreen(center);
518
501
  this.pointerDown(screenCenter.x, screenCenter.y, this.editor.getSelectedShapeIds()[0]);
519
502
  const numSteps = 10;
520
503
  for (let i = 1; i < numSteps; i++) {
521
- const p = this.pageToScreen({
504
+ const p = this.editor.pageToScreen({
522
505
  x: center.x + i * dx / numSteps,
523
506
  y: center.y + i * dy / numSteps
524
507
  });
525
508
  this.pointerMove(p.x, p.y, options);
526
509
  }
527
- const endScreen = this.pageToScreen({ x: center.x + dx, y: center.y + dy });
510
+ const endScreen = this.editor.pageToScreen({ x: center.x + dx, y: center.y + dy });
528
511
  this.pointerUp(endScreen.x, endScreen.y, options);
529
512
  return this;
530
513
  }
@@ -541,6 +524,7 @@ var Driver = class {
541
524
  }
542
525
  this.editor.setCurrentTool("select");
543
526
  const bounds = this.editor.getSelectionRotatedPageBounds();
527
+ const rotation = this.editor.getSelectionRotation();
544
528
  const preRotationHandlePoint = bounds.getHandlePoint(handle);
545
529
  const preRotationScaleOriginPoint = options?.altKey ? bounds.center : bounds.getHandlePoint(rotateSelectionHandle(handle, Math.PI));
546
530
  const preRotationTargetHandlePoint = Vec.Add(
@@ -550,18 +534,10 @@ var Driver = class {
550
534
  }),
551
535
  preRotationScaleOriginPoint
552
536
  );
553
- const handlePoint = Vec.RotWith(
554
- preRotationHandlePoint,
555
- bounds.point,
556
- this.editor.getSelectionRotation()
557
- );
558
- const targetHandlePoint = Vec.RotWith(
559
- preRotationTargetHandlePoint,
560
- bounds.point,
561
- this.editor.getSelectionRotation()
562
- );
563
- const screenHandle = this.pageToScreen(handlePoint);
564
- const screenTarget = this.pageToScreen(targetHandlePoint);
537
+ const handlePoint = Vec.RotWith(preRotationHandlePoint, bounds.point, rotation);
538
+ const targetHandlePoint = Vec.RotWith(preRotationTargetHandlePoint, bounds.point, rotation);
539
+ const screenHandle = this.editor.pageToScreen(handlePoint);
540
+ const screenTarget = this.editor.pageToScreen(targetHandlePoint);
565
541
  this.pointerDown(screenHandle.x, screenHandle.y, { target: "selection", handle }, options);
566
542
  this.pointerMove(screenTarget.x, screenTarget.y, options);
567
543
  this.pointerUp(screenTarget.x, screenTarget.y, options);
@@ -572,7 +548,7 @@ var Driver = class {
572
548
  // src/index.ts
573
549
  registerDrawLibraryVersion(
574
550
  "@ibodr/driver",
575
- "0.2.6",
551
+ "0.2.7",
576
552
  "esm"
577
553
  );
578
554
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/Driver.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import {\n\tEditor,\n\tMat,\n\tPageRecordType,\n\tROTATE_CORNER_TO_SELECTION_CORNER,\n\tRotateCorner,\n\tSelectionHandle,\n\tDrArrowShape,\n\tDrContent,\n\tDrKeyboardEventInfo,\n\tDrPinchEventInfo,\n\tDrPointerEventInfo,\n\tDrShape,\n\tDrShapeId,\n\tDrWheelEventInfo,\n\tVec,\n\tVecLike,\n\tcompact,\n\tcreateShapeId,\n\tisAccelKey,\n\trotateSelectionHandle,\n\ttlenv,\n} from '@ibodr/editor'\n\n/** Options for pointer events. Either partial pointer event info or a shape ID to target. @public */\nexport type PointerEventInit = Partial<DrPointerEventInfo> | DrShapeId\n\n/** Modifier keys for events. @public */\nexport type EventModifiers = Partial<Pick<DrPointerEventInfo, '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: DrContent | null = null\n\n\tprivate _lastCreatedShapes: DrShape[] = []\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 DrShape>() {\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: DrShape) {\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: DrShapeId): 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: DrShape) {\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: DrShapeId) {\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<DrArrowShape>(id)))\n\t}\n\n\t/* --------------- Event building --------------- */\n\n\t/**\n\t * Builds a DrPointerEventInfo 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): DrPointerEventInfo {\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\treturn {\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 DrPointerEventInfo\n\t}\n\n\t/**\n\t * Builds a DrKeyboardEventInfo 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: DrKeyboardEventInfo['name'],\n\t\toptions = {} as Partial<Omit<DrKeyboardEventInfo, 'point'>>\n\t): DrKeyboardEventInfo {\n\t\treturn {\n\t\t\tshiftKey: key === 'Shift',\n\t\t\tctrlKey: key === 'Control' || key === 'Meta',\n\t\t\taltKey: key === 'Alt',\n\t\t\tmetaKey: key === 'Meta',\n\t\t\taccelKey: tlenv.isDarwin ? key === 'Meta' : key === 'Control' || key === 'Meta',\n\t\t\t...options,\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<DrKeyboardEventInfo, '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<DrKeyboardEventInfo, '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<DrKeyboardEventInfo, '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<DrKeyboardEventInfo, '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<DrWheelEventInfo, '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<DrPinchEventInfo, '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<DrPinchEventInfo, '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<DrPinchEventInfo, '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<DrPointerEventInfo>) {\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<DrPointerEventInfo>\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","import { registerDrawLibraryVersion } from '@ibodr/utils'\n\nexport { Driver } from './lib/Driver'\nexport type { EventModifiers, PointerEventInit } from './lib/Driver'\n\nregisterDrawLibraryVersion(\n\t(globalThis as any).DRAW_LIBRARY_NAME,\n\t(globalThis as any).DRAW_LIBRARY_VERSION,\n\t(globalThis as any).DRAW_LIBRARY_MODULES\n)\n"]}
1
+ {"version":3,"sources":["../src/lib/Driver.ts","../src/index.ts"],"names":[],"mappings":";;;;AA8BA,IAAM,SAAA,GAAoC;AAAA,EACzC,KAAA,EAAO,WAAA;AAAA,EACP,GAAA,EAAK,SAAA;AAAA,EACL,OAAA,EAAS,UAAA;AAAA,EACT,IAAA,EAAM,UAAA;AAAA,EACN,GAAA,EAAK,OAAA;AAAA,EACL,KAAA,EAAO,OAAA;AAAA,EACP,UAAA,EAAY,YAAA;AAAA,EACZ,SAAA,EAAW,WAAA;AAAA,EACX,OAAA,EAAS,SAAA;AAAA,EACT,SAAA,EAAW;AACZ,CAAA;AAUO,IAAM,SAAN,MAAa;AAAA,EAKnB,YAA4B,MAAA,EAAgB;AAAhB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAC3B,IAAA,IAAA,CAAK,WAAW,IAAA,CAAK,MAAA,CAAO,YAAY,0BAAA,CAA2B,OAAA,EAAS,CAAC,MAAA,KAAW;AACvF,MAAA,IAAA,CAAK,kBAAA,CAAmB,KAAK,MAAM,CAAA;AACnC,MAAA,IAAI,IAAA,CAAK,kBAAA,CAAmB,MAAA,GAAS,GAAA,EAAM;AAC1C,QAAA,IAAA,CAAK,kBAAA,GAAqB,IAAA,CAAK,kBAAA,CAAmB,KAAA,CAAM,IAAI,CAAA;AAAA,MAC7D;AAAA,IACD,CAAC,CAAA;AAAA,EACF;AAAA,EAP4B,MAAA;AAAA;AAAA,EAHpB,QAAA;AAAA,EACA,qBAAgC,EAAC;AAAA;AAAA,EAYzC,OAAA,GAAU;AACT,IAAA,IAAA,CAAK,QAAA,IAAW;AAChB,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,EACjB;AAAA;AAAA,EAGA,SAAA,GAA8B,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM9B,oBAAA,CAAqB,QAAQ,CAAA,EAAG;AAC/B,IAAA,OAAO,IAAA,CAAK,kBAAA,CAAmB,KAAA,CAAM,CAAC,KAAK,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,CAAC,CAAE,CAAA;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAA,GAAyC;AACxC,IAAA,MAAM,YAAY,IAAA,CAAK,kBAAA,CAAmB,IAAA,CAAK,kBAAA,CAAmB,SAAS,CAAC,CAAA;AAC5E,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,QAAA,CAAY,SAAS,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAc,EAAA,EAAY;AACzB,IAAA,OAAO,cAAc,EAAE,CAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,EAAA,EAAY;AACxB,IAAA,OAAO,cAAA,CAAe,SAAS,EAAE,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAA,CAAK,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,qBAAoB,EAAG;AAC7C,IAAA,IAAI,GAAA,CAAI,SAAS,CAAA,EAAG;AACnB,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,yBAAA,CAA0B,GAAG,CAAA;AACzD,MAAA,IAAI,OAAA,EAAS;AACZ,QAAA,IAAA,CAAK,SAAA,GAAY,OAAA;AAAA,MAClB;AAAA,IACD;AACA,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,GAAA,CAAI,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,qBAAoB,EAAG;AAC5C,IAAA,IAAI,GAAA,CAAI,SAAS,CAAA,EAAG;AACnB,MAAA,IAAA,CAAK,KAAK,GAAG,CAAA;AACb,MAAA,IAAA,CAAK,MAAA,CAAO,aAAa,GAAG,CAAA;AAAA,IAC7B;AACA,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,KAAA,EAAiB;AACtB,IAAA,IAAI,IAAA,CAAK,cAAc,IAAA,EAAM;AAC5B,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,WAAA,KAAgB,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,mBAAA,EAAoB,GAAI,KAAA;AAExF,MAAA,IAAA,CAAK,MAAA,CAAO,yBAAyB,SAAS,CAAA;AAC9C,MAAA,IAAA,CAAK,MAAA,CAAO,yBAAA,CAA0B,IAAA,CAAK,SAAA,EAAW;AAAA,QACrD,KAAA,EAAO,CAAA;AAAA,QACP,MAAA,EAAQ;AAAA,OACR,CAAA;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA,EAKA,qBAAA,GAAwB;AACvB,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,qBAAA,EAAsB,CAAE,MAAA;AAAA,EAC5C;AAAA;AAAA,EAGA,sBAAA,GAAyB;AACxB,IAAA,MAAM,iBAAA,GAAoB,IAAA,CAAK,MAAA,CAAO,oBAAA,EAAqB;AAC3D,IAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,MAAA,CAAO,6BAAA,EAA8B;AAClE,IAAA,IAAI,CAAC,iBAAiB,OAAO,IAAA;AAC7B,IAAA,OAAO,IAAI,OAAA,CAAQ,eAAA,CAAgB,MAAA,EAAQ,eAAA,CAAgB,OAAO,iBAAiB,CAAA;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,KAAA,EAAgB;AAC7B,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,qBAAA,CAAsB,MAAM,EAAE,CAAA;AAChE,IAAA,IAAI,CAAC,eAAe,OAAO,IAAA;AAC3B,IAAA,MAAM,SAAS,IAAA,CAAK,MAAA,CAAO,gBAAA,CAAiB,KAAK,EAAE,MAAA,CAAO,MAAA;AAC1D,IAAA,OAAO,GAAA,CAAI,YAAA,CAAa,aAAA,EAAe,MAAM,CAAA;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,EAAA,EAAuB;AAC1C,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,qBAAA,CAAsB,EAAE,CAAA;AAC1D,IAAA,OAAO,aAAA,GAAgB,aAAA,CAAc,QAAA,EAAS,GAAI,CAAA;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,KAAA,EAAgB;AAC/B,IAAA,OAAO,IAAA,CAAK,mBAAA,CAAoB,KAAA,CAAM,EAAE,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAiB,OAAA,EAAoB;AACpC,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,IAAA,CAAK,OAAO,kBAAA,CAAmB,OAAA,EAAS,OAAO,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,MAAM,CAAC,CAAA;AACzF,IAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,GAAA,EAAK,CAAC,EAAA,KAAO,IAAA,CAAK,MAAA,CAAO,QAAA,CAAuB,EAAE,CAAC,CAAC,CAAA;AAAA,EAC/E;AAAA;AAAA,EAIQ,eAAA,GAAkB;AACzB,IAAA,MAAM,EAAE,MAAA,EAAO,GAAI,IAAA,CAAK,MAAA;AACxB,IAAA,OAAO;AAAA,MACN,QAAA,EAAU,OAAO,WAAA,EAAY;AAAA,MAC7B,OAAA,EAAS,OAAO,UAAA,EAAW;AAAA,MAC3B,MAAA,EAAQ,OAAO,SAAA,EAAU;AAAA,MACzB,OAAA,EAAS,OAAO,UAAA,EAAW;AAAA,MAC3B,QAAA,EAAU,WAAW,MAAM;AAAA,KAC5B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,oBACP,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,uBAAsB,CAAE,CAAA,EAC/C,CAAA,GAAI,IAAA,CAAK,OAAO,MAAA,CAAO,qBAAA,EAAsB,CAAE,CAAA,EAC/C,SACA,SAAA,EACqB;AACrB,IAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAChC,MAAA,OAAA,GAAU,EAAE,QAAQ,OAAA,EAAS,KAAA,EAAO,KAAK,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA,EAAE;AAAA,IACnE,CAAA,MAAA,IAAW,YAAY,MAAA,EAAW;AACjC,MAAA,OAAA,GAAU,EAAE,QAAQ,QAAA,EAAS;AAAA,IAC9B;AACA,IAAA,MAAM,IAAA,GAAO;AAAA,MACZ,IAAA,EAAM,cAAA;AAAA,MACN,IAAA,EAAM,SAAA;AAAA,MACN,SAAA,EAAW,CAAA;AAAA,MACX,GAAG,KAAK,eAAA,EAAgB;AAAA,MACxB,QAAA,EAAU,UAAA,CAAW,EAAE,GAAG,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,MAAA,EAAO,EAAG,GAAG,SAAA,EAAW,CAAA;AAAA,MACrE,KAAA,EAAO,EAAE,CAAA,EAAG,CAAA,EAAG,GAAG,IAAA,EAAK;AAAA,MACvB,MAAA,EAAQ,CAAA;AAAA,MACR,KAAA,EAAO,KAAA;AAAA,MACP,GAAG,OAAA;AAAA,MACH,GAAG;AAAA,KACJ;AAIA,IAAA,IAAI,IAAA,CAAK,WAAA,KAAgB,MAAA,EAAW,IAAA,CAAK,cAAc,IAAA,CAAK,KAAA;AAE5D,IAAA,IAAI,KAAA,CAAM,YAAY,IAAA,CAAK,MAAA,KAAW,KAAK,IAAA,CAAK,OAAA,IAAW,CAAC,IAAA,CAAK,OAAA,EAAS;AACzE,MAAA,IAAA,CAAK,MAAA,GAAS,CAAA;AAAA,IACf;AAEA,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,oBAAA,CACP,GAAA,EACA,IAAA,EACA,OAAA,GAAU,EAAC,EACW;AAKtB,IAAA,MAAM,KAAA,GAAQ;AAAA,MACb,UAAU,GAAA,KAAQ,OAAA,IAAW,IAAA,CAAK,MAAA,CAAO,OAAO,WAAA,EAAY;AAAA,MAC5D,OAAA,EAAS,QAAQ,SAAA,IAAa,GAAA,KAAQ,UAAU,IAAA,CAAK,MAAA,CAAO,OAAO,UAAA,EAAW;AAAA,MAC9E,QAAQ,GAAA,KAAQ,KAAA,IAAS,IAAA,CAAK,MAAA,CAAO,OAAO,SAAA,EAAU;AAAA,MACtD,SAAS,GAAA,KAAQ,MAAA,IAAU,IAAA,CAAK,MAAA,CAAO,OAAO,UAAA,EAAW;AAAA,MACzD,GAAG;AAAA,KACJ;AACA,IAAA,OAAO;AAAA,MACN,GAAG,KAAA;AAAA,MACH,QAAA,EAAU,KAAA,CAAM,QAAA,IAAY,UAAA,CAAW,KAAK,CAAA;AAAA,MAC5C,IAAA;AAAA,MACA,IAAA,EAAM,OAAA,CAAQ,IAAA,IAAQ,SAAA,CAAU,GAAG,CAAA,IAAK,KAAA,GAAQ,GAAA,CAAI,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,GAAA,CAAI,MAAM,CAAC,CAAA;AAAA,MAClF,IAAA,EAAM,UAAA;AAAA,MACN;AAAA,KACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAA,CAAU,QAAQ,CAAA,EAAG;AACpB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,EAAO,CAAA,EAAA,EAAK;AAC/B,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,MAAA,EAAQ,EAAE,CAAA;AAAA,IAC5B;AACA,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACC,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,uBAAsB,CAAE,CAAA,EAC/C,CAAA,GAAI,IAAA,CAAK,OAAO,MAAA,CAAO,qBAAA,EAAsB,CAAE,CAAA,EAC/C,SACA,SAAA,EACC;AACD,IAAA,IAAA,CAAK,OAAO,QAAA,CAAS;AAAA,MACpB,GAAG,IAAA,CAAK,mBAAA,CAAoB,CAAA,EAAG,CAAA,EAAG,SAAS,SAAS,CAAA;AAAA,MACpD,IAAA,EAAM;AAAA,KACN,CAAA;AACD,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACC,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,uBAAsB,CAAE,CAAA,EAC/C,CAAA,GAAI,IAAA,CAAK,OAAO,MAAA,CAAO,qBAAA,EAAsB,CAAE,CAAA,EAC/C,SACA,SAAA,EACC;AACD,IAAA,IAAA,CAAK,OAAO,QAAA,CAAS;AAAA,MACpB,GAAG,IAAA,CAAK,mBAAA,CAAoB,CAAA,EAAG,CAAA,EAAG,SAAS,SAAS,CAAA;AAAA,MACpD,IAAA,EAAM;AAAA,KACN,CAAA;AACD,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UACC,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,uBAAsB,CAAE,CAAA,EAC/C,CAAA,GAAI,IAAA,CAAK,OAAO,MAAA,CAAO,qBAAA,EAAsB,CAAE,CAAA,EAC/C,SACA,SAAA,EACC;AACD,IAAA,IAAA,CAAK,OAAO,QAAA,CAAS;AAAA,MACpB,GAAG,IAAA,CAAK,mBAAA,CAAoB,CAAA,EAAG,CAAA,EAAG,SAAS,SAAS,CAAA;AAAA,MACpD,IAAA,EAAM;AAAA,KACN,CAAA;AACD,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MACC,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,uBAAsB,CAAE,CAAA,EAC/C,CAAA,GAAI,IAAA,CAAK,OAAO,MAAA,CAAO,qBAAA,EAAsB,CAAE,CAAA,EAC/C,SACA,SAAA,EACC;AACD,IAAA,IAAA,CAAK,WAAA,CAAY,CAAA,EAAG,CAAA,EAAG,OAAA,EAAS,SAAS,CAAA;AACzC,IAAA,IAAA,CAAK,SAAA,CAAU,CAAA,EAAG,CAAA,EAAG,OAAA,EAAS,SAAS,CAAA;AACvC,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WACC,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,uBAAsB,CAAE,CAAA,EAC/C,CAAA,GAAI,IAAA,CAAK,OAAO,MAAA,CAAO,qBAAA,EAAsB,CAAE,CAAA,EAC/C,SACA,SAAA,EACC;AACD,IAAA,IAAA,CAAK,OAAO,QAAA,CAAS;AAAA,MACpB,GAAG,IAAA,CAAK,mBAAA,CAAoB,CAAA,EAAG,CAAA,EAAG,SAAS,SAAS,CAAA;AAAA,MACpD,IAAA,EAAM,cAAA;AAAA,MACN,MAAA,EAAQ;AAAA,KACR,CAAA;AACD,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,IAAA,CAAK,OAAO,QAAA,CAAS;AAAA,MACpB,GAAG,IAAA,CAAK,mBAAA,CAAoB,CAAA,EAAG,CAAA,EAAG,SAAS,SAAS,CAAA;AAAA,MACpD,IAAA,EAAM,YAAA;AAAA,MACN,MAAA,EAAQ;AAAA,KACR,CAAA;AACD,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACC,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,uBAAsB,CAAE,CAAA,EAC/C,CAAA,GAAI,IAAA,CAAK,OAAO,MAAA,CAAO,qBAAA,EAAsB,CAAE,CAAA,EAC/C,SACA,SAAA,EACC;AACD,IAAA,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,CAAA,EAAG,OAAA,EAAS,SAAS,CAAA;AACnC,IAAA,IAAA,CAAK,OAAO,QAAA,CAAS;AAAA,MACpB,GAAG,IAAA,CAAK,mBAAA,CAAoB,CAAA,EAAG,CAAA,EAAG,SAAS,SAAS,CAAA;AAAA,MACpD,IAAA,EAAM,OAAA;AAAA,MACN,IAAA,EAAM,cAAA;AAAA,MACN,KAAA,EAAO;AAAA,KACP,CAAA;AACD,IAAA,IAAA,CAAK,OAAO,QAAA,CAAS;AAAA,MACpB,GAAG,IAAA,CAAK,mBAAA,CAAoB,CAAA,EAAG,CAAA,EAAG,SAAS,SAAS,CAAA;AAAA,MACpD,IAAA,EAAM,OAAA;AAAA,MACN,IAAA,EAAM,cAAA;AAAA,MACN,KAAA,EAAO;AAAA,KACP,CAAA;AACD,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAA,CAAS,GAAA,EAAa,OAAA,GAAU,EAAC,EAAgD;AAChF,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,OAAO,CAAA;AACzB,IAAA,IAAA,CAAK,KAAA,CAAM,KAAK,OAAO,CAAA;AACvB,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAA,CAAQ,GAAA,EAAa,OAAA,GAAU,EAAC,EAAgD;AAC/E,IAAA,IAAA,CAAK,OAAO,QAAA,CAAS,IAAA,CAAK,qBAAqB,GAAA,EAAK,UAAA,EAAY,OAAO,CAAC,CAAA;AACxE,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAA,CAAU,GAAA,EAAa,OAAA,GAAU,EAAC,EAAgD;AACjF,IAAA,IAAA,CAAK,OAAO,QAAA,CAAS,IAAA,CAAK,qBAAqB,GAAA,EAAK,YAAA,EAAc,OAAO,CAAC,CAAA;AAC1E,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAA,CAAM,GAAA,EAAa,OAAA,GAAU,EAAC,EAAgD;AAC7E,IAAA,IAAA,CAAK,MAAA,CAAO,QAAA;AAAA,MACX,IAAA,CAAK,oBAAA,CAAqB,GAAA,EAAK,QAAA,EAAU;AAAA,QACxC,UAAU,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,WAAA,MAAiB,GAAA,KAAQ,OAAA;AAAA,QACtD,OAAA,EAAS,KAAK,MAAA,CAAO,MAAA,CAAO,YAAW,IAAK,EAAE,GAAA,KAAQ,SAAA,IAAa,GAAA,KAAQ,MAAA,CAAA;AAAA,QAC3E,QAAQ,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,SAAA,MAAe,GAAA,KAAQ,KAAA;AAAA,QAClD,SAAS,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,UAAA,MAAgB,GAAA,KAAQ,MAAA;AAAA,QACpD,GAAG;AAAA,OACH;AAAA,KACF;AACA,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,KAAA,CAAM,EAAA,EAAY,EAAA,EAAY,OAAA,GAAU,EAAC,EAA+C;AACvF,IAAA,MAAM,kBAAA,GAAqB,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,qBAAA,EAAsB;AACpE,IAAA,IAAA,CAAK,OAAO,QAAA,CAAS;AAAA,MACpB,IAAA,EAAM,OAAA;AAAA,MACN,IAAA,EAAM,OAAA;AAAA,MACN,OAAO,IAAI,GAAA,CAAI,kBAAA,CAAmB,CAAA,EAAG,mBAAmB,CAAC,CAAA;AAAA,MACzD,GAAG,KAAK,eAAA,EAAgB;AAAA,MACxB,GAAG,OAAA;AAAA,MACH,KAAA,EAAO,EAAE,CAAA,EAAG,EAAA,EAAI,GAAG,EAAA;AAAG,KACtB,CAAA;AACD,IAAA,IAAA,CAAK,UAAU,CAAC,CAAA;AAChB,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,MAAA,EAAiB;AACpB,IAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAS,GAAI,IAAA,CAAK,OAAO,gBAAA,EAAiB;AAC5D,IAAA,IAAI,UAAU,OAAO,IAAA;AACrB,IAAA,MAAM,EAAE,CAAA,EAAG,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,GAAG,EAAA,EAAG,GAAI,IAAA,CAAK,MAAA,CAAO,SAAA,EAAU;AACtD,IAAA,IAAA,CAAK,MAAA,CAAO,SAAA;AAAA,MACX,IAAI,GAAA,CAAI,EAAA,GAAM,MAAA,CAAO,CAAA,GAAI,QAAA,GAAY,EAAA,EAAI,EAAA,GAAM,MAAA,CAAO,CAAA,GAAI,QAAA,GAAY,EAAA,EAAI,EAAE,CAAA;AAAA,MAC5E,EAAE,WAAW,IAAA;AAAK,KACnB;AACA,IAAA,OAAO,IAAA;AAAA,EACR;AAAA,EAEQ,KAAA,CACP,MACA,CAAA,EACA,CAAA,EACA,GACA,EAAA,EACA,EAAA,EACA,IACA,OAAA,EACC;AACD,IAAA,IAAA,CAAK,OAAO,QAAA,CAAS;AAAA,MACpB,IAAA,EAAM,OAAA;AAAA,MACN,IAAA;AAAA,MACA,GAAG,KAAK,eAAA,EAAgB;AAAA,MACxB,GAAG,OAAA;AAAA,MACH,KAAA,EAAO,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE;AAAA,MACjB,OAAO,EAAE,CAAA,EAAG,IAAI,CAAA,EAAG,EAAA,EAAI,GAAG,EAAA;AAAG,KAC7B,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,UAAA,CACC,IAAI,IAAA,CAAK,MAAA,CAAO,OAAO,qBAAA,EAAsB,CAAE,GAC/C,CAAA,GAAI,IAAA,CAAK,OAAO,MAAA,CAAO,qBAAA,GAAwB,CAAA,EAC/C,CAAA,EACA,IACA,EAAA,EACA,EAAA,EACA,OAAA,GAAU,EAAC,EACV;AACD,IAAA,IAAA,CAAK,KAAA,CAAM,eAAe,CAAA,EAAG,CAAA,EAAG,GAAG,EAAA,EAAI,EAAA,EAAI,IAAI,OAAO,CAAA;AACtD,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAA,CACC,IAAI,IAAA,CAAK,MAAA,CAAO,OAAO,qBAAA,EAAsB,CAAE,GAC/C,CAAA,GAAI,IAAA,CAAK,OAAO,MAAA,CAAO,qBAAA,GAAwB,CAAA,EAC/C,CAAA,EACA,IACA,EAAA,EACA,EAAA,EACA,OAAA,GAAU,EAAC,EACV;AACD,IAAA,IAAA,CAAK,KAAA,CAAM,SAAS,CAAA,EAAG,CAAA,EAAG,GAAG,EAAA,EAAI,EAAA,EAAI,IAAI,OAAO,CAAA;AAChD,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,QAAA,CACC,IAAI,IAAA,CAAK,MAAA,CAAO,OAAO,qBAAA,EAAsB,CAAE,GAC/C,CAAA,GAAI,IAAA,CAAK,OAAO,MAAA,CAAO,qBAAA,GAAwB,CAAA,EAC/C,CAAA,EACA,IACA,EAAA,EACA,EAAA,EACA,OAAA,GAAU,EAAC,EACV;AACD,IAAA,IAAA,CAAK,KAAA,CAAM,aAAa,CAAA,EAAG,CAAA,EAAG,GAAG,EAAA,EAAI,EAAA,EAAI,IAAI,OAAO,CAAA;AACpD,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,eAAA,CACC,YAAA,EACA,OAAA,GAAyD,EAAC,EACzD;AACD,IAAA,MAAM,EAAE,MAAA,GAAS,iBAAA,EAAmB,QAAA,GAAW,OAAM,GAAI,OAAA;AACzD,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,mBAAA,EAAoB,CAAE,WAAW,CAAA,EAAG;AACnD,MAAA,MAAM,IAAI,MAAM,cAAc,CAAA;AAAA,IAC/B;AAEA,IAAA,IAAA,CAAK,MAAA,CAAO,eAAe,QAAQ,CAAA;AAEnC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,6BAAA,EAA8B;AACzD,IAAA,MAAM,WAAA,GAAc,MAAA,CAClB,cAAA,CAAe,iCAAA,CAAkC,MAAM,CAAC,CAAA,CACxD,KAAA,EAAM,CACN,QAAQ,MAAA,CAAO,KAAA,EAAO,IAAA,CAAK,MAAA,CAAO,sBAAsB,CAAA;AAE1D,IAAA,MAAM,oBAAoB,GAAA,CAAI,OAAA,CAAQ,aAAa,IAAA,CAAK,sBAAA,IAA2B,YAAY,CAAA;AAE/F,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,WAAW,CAAA;AACzD,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,iBAAiB,CAAA;AAE/D,IAAA,IAAA,CAAK,WAAA,CAAY,aAAa,CAAA,EAAG,YAAA,CAAa,GAAG,EAAE,MAAA,EAAQ,WAAA,EAAa,MAAA,EAAQ,CAAA;AAChF,IAAA,IAAA,CAAK,YAAY,YAAA,CAAa,CAAA,EAAG,aAAa,CAAA,EAAG,EAAE,UAAU,CAAA;AAC7D,IAAA,IAAA,CAAK,SAAA,EAAU;AACf,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,kBAAA,CAAmB,EAAA,EAAY,EAAA,EAAY,OAAA,EAAuC;AACjF,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,mBAAA,EAAoB,CAAE,WAAW,CAAA,EAAG;AACnD,MAAA,MAAM,IAAI,MAAM,cAAc,CAAA;AAAA,IAC/B;AACA,IAAA,IAAA,CAAK,MAAA,CAAO,eAAe,QAAQ,CAAA;AAEnC,IAAA,MAAM,MAAA,GAAS,KAAK,sBAAA,EAAuB;AAC3C,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,MAAM,CAAA;AAEpD,IAAA,IAAA,CAAK,WAAA,CAAY,YAAA,CAAa,CAAA,EAAG,YAAA,CAAa,CAAA,EAAG,KAAK,MAAA,CAAO,mBAAA,EAAoB,CAAE,CAAC,CAAC,CAAA;AACrF,IAAA,MAAM,QAAA,GAAW,EAAA;AACjB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,EAAU,CAAA,EAAA,EAAK;AAClC,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa;AAAA,QAClC,CAAA,EAAG,MAAA,CAAO,CAAA,GAAK,CAAA,GAAI,EAAA,GAAM,QAAA;AAAA,QACzB,CAAA,EAAG,MAAA,CAAO,CAAA,GAAK,CAAA,GAAI,EAAA,GAAM;AAAA,OACzB,CAAA;AACD,MAAA,IAAA,CAAK,WAAA,CAAY,CAAA,CAAE,CAAA,EAAG,CAAA,CAAE,GAAG,OAAO,CAAA;AAAA,IACnC;AACA,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,EAAE,CAAA,EAAG,MAAA,CAAO,CAAA,GAAI,EAAA,EAAI,CAAA,EAAG,MAAA,CAAO,CAAA,GAAI,IAAI,CAAA;AACjF,IAAA,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,CAAA,EAAG,SAAA,CAAU,GAAG,OAAO,CAAA;AAChD,IAAA,OAAO,IAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAAA,CACC,KAAA,GAA8C,EAAC,EAC/C,QACA,OAAA,EACC;AACD,IAAA,MAAM,EAAE,MAAA,GAAS,CAAA,EAAG,MAAA,GAAS,GAAE,GAAI,KAAA;AACnC,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,mBAAA,EAAoB,CAAE,WAAW,CAAA,EAAG;AACnD,MAAA,MAAM,IAAI,MAAM,cAAc,CAAA;AAAA,IAC/B;AACA,IAAA,IAAA,CAAK,MAAA,CAAO,eAAe,QAAQ,CAAA;AACnC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,6BAAA,EAA8B;AACzD,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,MAAA,CAAO,oBAAA,EAAqB;AAClD,IAAA,MAAM,sBAAA,GAAyB,MAAA,CAAO,cAAA,CAAe,MAAM,CAAA;AAE3D,IAAA,MAAM,2BAAA,GAA8B,OAAA,EAAS,MAAA,GAC1C,MAAA,CAAO,MAAA,GACP,MAAA,CAAO,cAAA,CAAe,qBAAA,CAAsB,MAAA,EAAQ,IAAA,CAAK,EAAE,CAAC,CAAA;AAE/D,IAAA,MAAM,+BAA+B,GAAA,CAAI,GAAA;AAAA,MACxC,GAAA,CAAI,GAAA,CAAI,sBAAA,EAAwB,2BAA2B,EAAE,IAAA,CAAK;AAAA,QACjE,CAAA,EAAG,MAAA;AAAA,QACH,CAAA,EAAG;AAAA,OACH,CAAA;AAAA,MACD;AAAA,KACD;AAEA,IAAA,MAAM,cAAc,GAAA,CAAI,OAAA,CAAQ,sBAAA,EAAwB,MAAA,CAAO,OAAO,QAAQ,CAAA;AAC9E,IAAA,MAAM,oBAAoB,GAAA,CAAI,OAAA,CAAQ,4BAAA,EAA8B,MAAA,CAAO,OAAO,QAAQ,CAAA;AAE1F,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,WAAW,CAAA;AACzD,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,iBAAiB,CAAA;AAE/D,IAAA,IAAA,CAAK,WAAA,CAAY,YAAA,CAAa,CAAA,EAAG,YAAA,CAAa,CAAA,EAAG,EAAE,MAAA,EAAQ,WAAA,EAAa,MAAA,EAAO,EAAG,OAAO,CAAA;AACzF,IAAA,IAAA,CAAK,WAAA,CAAY,YAAA,CAAa,CAAA,EAAG,YAAA,CAAa,GAAG,OAAO,CAAA;AACxD,IAAA,IAAA,CAAK,SAAA,CAAU,YAAA,CAAa,CAAA,EAAG,YAAA,CAAa,GAAG,OAAO,CAAA;AACtD,IAAA,OAAO,IAAA;AAAA,EACR;AACD;;;ACptBA,0BAAA;AAAA,EACE,eAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA","file":"index.mjs","sourcesContent":["import {\n\tDrArrowShape,\n\tDrContent,\n\tDrKeyboardEventInfo,\n\tDrPinchEventInfo,\n\tDrPointerEventInfo,\n\tDrShape,\n\tDrShapeId,\n\tDrWheelEventInfo,\n\tEditor,\n\tMat,\n\tPageRecordType,\n\tROTATE_CORNER_TO_SELECTION_CORNER,\n\tRotateCorner,\n\tSelectionHandle,\n\tVec,\n\tVecLike,\n\tcompact,\n\tcreateShapeId,\n\tisAccelKey,\n\trotateSelectionHandle,\n\ttlenv,\n} from '@ibodr/editor'\n\n/** Options for pointer events. Either partial pointer event info or a shape ID to target. @public */\nexport type PointerEventInit = Partial<DrPointerEventInfo> | DrShapeId\n\n/** Modifier keys for events. @public */\nexport type EventModifiers = Partial<Pick<DrPointerEventInfo, '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: DrShape[] = []\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: DrContent | 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 DrShape>() {\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: DrShape) {\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: DrShapeId): 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: DrShape) {\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: DrShapeId) {\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<DrArrowShape>(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 DrPointerEventInfo 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): DrPointerEventInfo {\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 DrPointerEventInfo\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 DrKeyboardEventInfo 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: DrKeyboardEventInfo['name'],\n\t\toptions = {} as Partial<Omit<DrKeyboardEventInfo, 'point'>>\n\t): DrKeyboardEventInfo {\n\t\t// Like a real DOM keyboard event, the flags reflect every modifier currently held — 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: options.code ?? 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<DrKeyboardEventInfo, '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<DrKeyboardEventInfo, '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<DrKeyboardEventInfo, '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<DrKeyboardEventInfo, '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<DrWheelEventInfo, '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: DrPinchEventInfo['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<DrPinchEventInfo, '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<DrPinchEventInfo, '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<DrPinchEventInfo, '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<DrPinchEventInfo, '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<DrPointerEventInfo>) {\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<DrPointerEventInfo>\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","import { registerDrawLibraryVersion } from '@ibodr/utils'\n\nexport { Driver } from './lib/Driver'\nexport type { EventModifiers, PointerEventInit } from './lib/Driver'\n\nregisterDrawLibraryVersion(\n\t(globalThis as any).DRAW_LIBRARY_NAME,\n\t(globalThis as any).DRAW_LIBRARY_VERSION,\n\t(globalThis as any).DRAW_LIBRARY_MODULES\n)\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibodr/driver",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -19,8 +19,8 @@
19
19
  }
20
20
  },
21
21
  "dependencies": {
22
- "@ibodr/editor": "0.2.6",
23
- "@ibodr/utils": "0.2.6"
22
+ "@ibodr/utils": "0.2.7",
23
+ "@ibodr/editor": "0.2.7"
24
24
  },
25
25
  "devDependencies": {
26
26
  "vitest": "^3.2.4"