kritzel-stencil 0.0.141 → 0.0.143

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/cjs/{index-BKstgWru.js → index-Cg50mv2K.js} +293 -811
  2. package/dist/cjs/index-Cg50mv2K.js.map +1 -0
  3. package/dist/cjs/index.cjs.js +1 -1
  4. package/dist/cjs/kritzel-color_22.cjs.entry.js +116 -79
  5. package/dist/collection/classes/commands/add-object.command.js +1 -0
  6. package/dist/collection/classes/commands/add-object.command.js.map +1 -1
  7. package/dist/collection/classes/commands/base.command.js +2 -0
  8. package/dist/collection/classes/commands/base.command.js.map +1 -1
  9. package/dist/collection/classes/commands/remove-object.command.js +1 -3
  10. package/dist/collection/classes/commands/remove-object.command.js.map +1 -1
  11. package/dist/collection/classes/commands/update-object.command.js +2 -0
  12. package/dist/collection/classes/commands/update-object.command.js.map +1 -1
  13. package/dist/collection/classes/core/command-manager.class.js +51 -0
  14. package/dist/collection/classes/core/command-manager.class.js.map +1 -0
  15. package/dist/collection/classes/core/core.class.js +23 -14
  16. package/dist/collection/classes/core/core.class.js.map +1 -1
  17. package/dist/collection/classes/core/history.class.js +2 -40
  18. package/dist/collection/classes/core/history.class.js.map +1 -1
  19. package/dist/collection/classes/core/viewport.class.js +17 -7
  20. package/dist/collection/classes/core/viewport.class.js.map +1 -1
  21. package/dist/collection/classes/handlers/context-menu.handler.js +1 -1
  22. package/dist/collection/classes/handlers/context-menu.handler.js.map +1 -1
  23. package/dist/collection/classes/handlers/move.handler.js +11 -6
  24. package/dist/collection/classes/handlers/move.handler.js.map +1 -1
  25. package/dist/collection/classes/handlers/resize.handler.js +29 -5
  26. package/dist/collection/classes/handlers/resize.handler.js.map +1 -1
  27. package/dist/collection/classes/handlers/rotation.handler.js +2 -2
  28. package/dist/collection/classes/handlers/rotation.handler.js.map +1 -1
  29. package/dist/collection/classes/handlers/selection.handler.js +4 -4
  30. package/dist/collection/classes/handlers/selection.handler.js.map +1 -1
  31. package/dist/collection/classes/objects/base-object.class.js +15 -14
  32. package/dist/collection/classes/objects/base-object.class.js.map +1 -1
  33. package/dist/collection/classes/objects/custom-element.class.js +7 -1
  34. package/dist/collection/classes/objects/custom-element.class.js.map +1 -1
  35. package/dist/collection/classes/objects/text.class.js +126 -52
  36. package/dist/collection/classes/objects/text.class.js.map +1 -1
  37. package/dist/collection/classes/tools/brush-tool.class.js +2 -2
  38. package/dist/collection/classes/tools/brush-tool.class.js.map +1 -1
  39. package/dist/collection/classes/tools/eraser-tool.class.js +2 -2
  40. package/dist/collection/classes/tools/eraser-tool.class.js.map +1 -1
  41. package/dist/collection/classes/tools/image-tool.class.js +1 -1
  42. package/dist/collection/classes/tools/image-tool.class.js.map +1 -1
  43. package/dist/collection/classes/tools/selection-tool.class.js +2 -2
  44. package/dist/collection/classes/tools/selection-tool.class.js.map +1 -1
  45. package/dist/collection/classes/tools/text-tool.class.js +17 -11
  46. package/dist/collection/classes/tools/text-tool.class.js.map +1 -1
  47. package/dist/collection/components/core/kritzel-engine/kritzel-engine.css +1 -1
  48. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +22 -16
  49. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js.map +1 -1
  50. package/dist/collection/helpers/event.helper.js +0 -3
  51. package/dist/collection/helpers/event.helper.js.map +1 -1
  52. package/dist/collection/interfaces/object.interface.js.map +1 -1
  53. package/dist/components/index.js +2 -2
  54. package/dist/components/kritzel-controls.js +1 -1
  55. package/dist/components/kritzel-editor.js +3 -3
  56. package/dist/components/kritzel-engine.js +1 -1
  57. package/dist/components/{p-ChLi4Ufe.js → p-BAw249L9.js} +3 -3
  58. package/dist/components/{p-ChLi4Ufe.js.map → p-BAw249L9.js.map} +1 -1
  59. package/dist/components/{p-BuDVaqTF.js → p-CoFmi-t6.js} +182 -734
  60. package/dist/components/p-CoFmi-t6.js.map +1 -0
  61. package/dist/components/{p-C4nj29RW.js → p-EO13AYoE.js} +229 -158
  62. package/dist/components/p-EO13AYoE.js.map +1 -0
  63. package/dist/esm/{index-D0Q2MKPn.js → index-Bj5QIJYQ.js} +294 -812
  64. package/dist/esm/index-Bj5QIJYQ.js.map +1 -0
  65. package/dist/esm/index.js +1 -1
  66. package/dist/esm/kritzel-color_22.entry.js +116 -79
  67. package/dist/stencil/index.esm.js +1 -1
  68. package/dist/stencil/p-Bj5QIJYQ.js +2 -0
  69. package/dist/stencil/p-Bj5QIJYQ.js.map +1 -0
  70. package/dist/stencil/p-b4185842.entry.js +2 -0
  71. package/dist/stencil/p-b4185842.entry.js.map +1 -0
  72. package/dist/stencil/stencil.esm.js +1 -1
  73. package/dist/types/classes/commands/add-object.command.d.ts +2 -2
  74. package/dist/types/classes/commands/base.command.d.ts +2 -1
  75. package/dist/types/classes/commands/remove-object.command.d.ts +2 -2
  76. package/dist/types/classes/commands/update-object.command.d.ts +2 -2
  77. package/dist/types/classes/core/command-manager.class.d.ts +16 -0
  78. package/dist/types/classes/core/core.class.d.ts +4 -0
  79. package/dist/types/classes/core/history.class.d.ts +0 -8
  80. package/dist/types/classes/core/viewport.class.d.ts +2 -0
  81. package/dist/types/classes/handlers/resize.handler.d.ts +1 -0
  82. package/dist/types/classes/objects/base-object.class.d.ts +6 -4
  83. package/dist/types/classes/objects/text.class.d.ts +13 -2
  84. package/dist/types/helpers/event.helper.d.ts +0 -1
  85. package/dist/types/interfaces/object.interface.d.ts +1 -3
  86. package/package.json +1 -1
  87. package/dist/cjs/index-BKstgWru.js.map +0 -1
  88. package/dist/components/p-BuDVaqTF.js.map +0 -1
  89. package/dist/components/p-C4nj29RW.js.map +0 -1
  90. package/dist/esm/index-D0Q2MKPn.js.map +0 -1
  91. package/dist/stencil/p-73784709.entry.js +0 -2
  92. package/dist/stencil/p-73784709.entry.js.map +0 -1
  93. package/dist/stencil/p-D0Q2MKPn.js +0 -2
  94. package/dist/stencil/p-D0Q2MKPn.js.map +0 -1
@@ -211,18 +211,6 @@ class KritzelBaseObject {
211
211
  this.elementRef = element;
212
212
  this.isMounted = true;
213
213
  }
214
- unmount() {
215
- if (!this.isMounted) {
216
- return;
217
- }
218
- this.isMounted = false;
219
- }
220
- remount() {
221
- if (!this.isMounted) {
222
- return;
223
- }
224
- this.isMounted = false;
225
- }
226
214
  generateId() {
227
215
  return ObjectHelper.generateUUID();
228
216
  }
@@ -268,8 +256,9 @@ class KritzelBaseObject {
268
256
  this.rotation = value;
269
257
  }
270
258
  clone() {
271
- const clone = new KritzelBaseObject();
259
+ const clone = Object.create(Object.getPrototypeOf(this));
272
260
  Object.assign(clone, this);
261
+ clone.id = this.id;
273
262
  return clone;
274
263
  }
275
264
  copy() {
@@ -297,7 +286,7 @@ class KritzelBaseObject {
297
286
  isClass(className) {
298
287
  return this.__class__ === className;
299
288
  }
300
- edit() {
289
+ edit(_event) {
301
290
  // This method can be overridden by subclasses to handle edit actions.
302
291
  }
303
292
  hitTest(_x, _y) {
@@ -312,6 +301,18 @@ class KritzelBaseObject {
312
301
  this.translateY = y;
313
302
  this._core.store.state.objectsMap.update(this);
314
303
  }
304
+ onExecuteAddCommand(_object) {
305
+ // This method can be overridden by subclasses to handle actions after an add command is executed.
306
+ }
307
+ onUndoAddCommand(_object) {
308
+ // This method can be overridden by subclasses to handle actions after an add command is undone.
309
+ }
310
+ onExecuteUpdateCommand(_updatedProperties) {
311
+ // This method can be overridden by subclasses to handle actions after an update command is executed.
312
+ }
313
+ onUndoUpdateCommand(_previousProperties) {
314
+ // This method can be overridden by subclasses to handle actions after an update command is undone.
315
+ }
315
316
  }
316
317
 
317
318
  class KritzelKeyboardHelper {
@@ -367,10 +368,12 @@ class KritzelBaseCommand {
367
368
  _core;
368
369
  initiator;
369
370
  skipHistory;
371
+ timestamp;
370
372
  constructor(core, initiator, skipHistory = false) {
371
373
  this._core = core;
372
374
  this.initiator = initiator?.constructor?.name ?? 'Unknown';
373
375
  this.skipHistory = skipHistory;
376
+ this.timestamp = new Date();
374
377
  }
375
378
  execute() {
376
379
  throw new Error('Method not implemented.');
@@ -401,6 +404,7 @@ class UpdateObjectCommand extends KritzelBaseCommand {
401
404
  this.object[key] = this.updatedProperties[key];
402
405
  }
403
406
  }
407
+ this.object.onExecuteUpdateCommand(this.updatedProperties);
404
408
  this._core.store.state.objectsMap.update(this.object);
405
409
  this._core.updateObjectInDatabase(this.object);
406
410
  }
@@ -410,6 +414,7 @@ class UpdateObjectCommand extends KritzelBaseCommand {
410
414
  this.object[key] = this.previousProperties[key];
411
415
  }
412
416
  }
417
+ this.object.onUndoUpdateCommand(this.previousProperties);
413
418
  this._core.store.state.objectsMap.update(this.object);
414
419
  this._core.updateObjectInDatabase(this.object);
415
420
  }
@@ -7072,27 +7077,6 @@ function createKey(name) {
7072
7077
  keys[name] = 0;
7073
7078
  return name + "$";
7074
7079
  }
7075
- /**
7076
- A key is used to [tag](https://prosemirror.net/docs/ref/#state.PluginSpec.key) plugins in a way
7077
- that makes it possible to find them, given an editor state.
7078
- Assigning a key does mean only one plugin of that type can be
7079
- active in a state.
7080
- */
7081
- class PluginKey {
7082
- /**
7083
- Create a plugin key.
7084
- */
7085
- constructor(name = "key") { this.key = createKey(name); }
7086
- /**
7087
- Get the active plugin with this key, if any, from an editor
7088
- state.
7089
- */
7090
- get(state) { return state.config.pluginsByKey[this.key]; }
7091
- /**
7092
- Get the plugin's state from an editor state.
7093
- */
7094
- getState(state) { return state[this.key]; }
7095
- }
7096
7080
 
7097
7081
  const domIndex = function (node) {
7098
7082
  for (var index = 0;; index++) {
@@ -13386,621 +13370,6 @@ function keydownHandler(bindings) {
13386
13370
  };
13387
13371
  }
13388
13372
 
13389
- var GOOD_LEAF_SIZE = 200;
13390
-
13391
- // :: class<T> A rope sequence is a persistent sequence data structure
13392
- // that supports appending, prepending, and slicing without doing a
13393
- // full copy. It is represented as a mostly-balanced tree.
13394
- var RopeSequence = function RopeSequence () {};
13395
-
13396
- RopeSequence.prototype.append = function append (other) {
13397
- if (!other.length) { return this }
13398
- other = RopeSequence.from(other);
13399
-
13400
- return (!this.length && other) ||
13401
- (other.length < GOOD_LEAF_SIZE && this.leafAppend(other)) ||
13402
- (this.length < GOOD_LEAF_SIZE && other.leafPrepend(this)) ||
13403
- this.appendInner(other)
13404
- };
13405
-
13406
- // :: (union<[T], RopeSequence<T>>) → RopeSequence<T>
13407
- // Prepend an array or other rope to this one, returning a new rope.
13408
- RopeSequence.prototype.prepend = function prepend (other) {
13409
- if (!other.length) { return this }
13410
- return RopeSequence.from(other).append(this)
13411
- };
13412
-
13413
- RopeSequence.prototype.appendInner = function appendInner (other) {
13414
- return new Append(this, other)
13415
- };
13416
-
13417
- // :: (?number, ?number) → RopeSequence<T>
13418
- // Create a rope repesenting a sub-sequence of this rope.
13419
- RopeSequence.prototype.slice = function slice (from, to) {
13420
- if ( from === void 0 ) from = 0;
13421
- if ( to === void 0 ) to = this.length;
13422
-
13423
- if (from >= to) { return RopeSequence.empty }
13424
- return this.sliceInner(Math.max(0, from), Math.min(this.length, to))
13425
- };
13426
-
13427
- // :: (number) → T
13428
- // Retrieve the element at the given position from this rope.
13429
- RopeSequence.prototype.get = function get (i) {
13430
- if (i < 0 || i >= this.length) { return undefined }
13431
- return this.getInner(i)
13432
- };
13433
-
13434
- // :: ((element: T, index: number) → ?bool, ?number, ?number)
13435
- // Call the given function for each element between the given
13436
- // indices. This tends to be more efficient than looping over the
13437
- // indices and calling `get`, because it doesn't have to descend the
13438
- // tree for every element.
13439
- RopeSequence.prototype.forEach = function forEach (f, from, to) {
13440
- if ( from === void 0 ) from = 0;
13441
- if ( to === void 0 ) to = this.length;
13442
-
13443
- if (from <= to)
13444
- { this.forEachInner(f, from, to, 0); }
13445
- else
13446
- { this.forEachInvertedInner(f, from, to, 0); }
13447
- };
13448
-
13449
- // :: ((element: T, index: number) → U, ?number, ?number) → [U]
13450
- // Map the given functions over the elements of the rope, producing
13451
- // a flat array.
13452
- RopeSequence.prototype.map = function map (f, from, to) {
13453
- if ( from === void 0 ) from = 0;
13454
- if ( to === void 0 ) to = this.length;
13455
-
13456
- var result = [];
13457
- this.forEach(function (elt, i) { return result.push(f(elt, i)); }, from, to);
13458
- return result
13459
- };
13460
-
13461
- // :: (?union<[T], RopeSequence<T>>) → RopeSequence<T>
13462
- // Create a rope representing the given array, or return the rope
13463
- // itself if a rope was given.
13464
- RopeSequence.from = function from (values) {
13465
- if (values instanceof RopeSequence) { return values }
13466
- return values && values.length ? new Leaf(values) : RopeSequence.empty
13467
- };
13468
-
13469
- var Leaf = /*@__PURE__*/(function (RopeSequence) {
13470
- function Leaf(values) {
13471
- RopeSequence.call(this);
13472
- this.values = values;
13473
- }
13474
-
13475
- if ( RopeSequence ) Leaf.__proto__ = RopeSequence;
13476
- Leaf.prototype = Object.create( RopeSequence && RopeSequence.prototype );
13477
- Leaf.prototype.constructor = Leaf;
13478
-
13479
- var prototypeAccessors = { length: { configurable: true },depth: { configurable: true } };
13480
-
13481
- Leaf.prototype.flatten = function flatten () {
13482
- return this.values
13483
- };
13484
-
13485
- Leaf.prototype.sliceInner = function sliceInner (from, to) {
13486
- if (from == 0 && to == this.length) { return this }
13487
- return new Leaf(this.values.slice(from, to))
13488
- };
13489
-
13490
- Leaf.prototype.getInner = function getInner (i) {
13491
- return this.values[i]
13492
- };
13493
-
13494
- Leaf.prototype.forEachInner = function forEachInner (f, from, to, start) {
13495
- for (var i = from; i < to; i++)
13496
- { if (f(this.values[i], start + i) === false) { return false } }
13497
- };
13498
-
13499
- Leaf.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) {
13500
- for (var i = from - 1; i >= to; i--)
13501
- { if (f(this.values[i], start + i) === false) { return false } }
13502
- };
13503
-
13504
- Leaf.prototype.leafAppend = function leafAppend (other) {
13505
- if (this.length + other.length <= GOOD_LEAF_SIZE)
13506
- { return new Leaf(this.values.concat(other.flatten())) }
13507
- };
13508
-
13509
- Leaf.prototype.leafPrepend = function leafPrepend (other) {
13510
- if (this.length + other.length <= GOOD_LEAF_SIZE)
13511
- { return new Leaf(other.flatten().concat(this.values)) }
13512
- };
13513
-
13514
- prototypeAccessors.length.get = function () { return this.values.length };
13515
-
13516
- prototypeAccessors.depth.get = function () { return 0 };
13517
-
13518
- Object.defineProperties( Leaf.prototype, prototypeAccessors );
13519
-
13520
- return Leaf;
13521
- }(RopeSequence));
13522
-
13523
- // :: RopeSequence
13524
- // The empty rope sequence.
13525
- RopeSequence.empty = new Leaf([]);
13526
-
13527
- var Append = /*@__PURE__*/(function (RopeSequence) {
13528
- function Append(left, right) {
13529
- RopeSequence.call(this);
13530
- this.left = left;
13531
- this.right = right;
13532
- this.length = left.length + right.length;
13533
- this.depth = Math.max(left.depth, right.depth) + 1;
13534
- }
13535
-
13536
- if ( RopeSequence ) Append.__proto__ = RopeSequence;
13537
- Append.prototype = Object.create( RopeSequence && RopeSequence.prototype );
13538
- Append.prototype.constructor = Append;
13539
-
13540
- Append.prototype.flatten = function flatten () {
13541
- return this.left.flatten().concat(this.right.flatten())
13542
- };
13543
-
13544
- Append.prototype.getInner = function getInner (i) {
13545
- return i < this.left.length ? this.left.get(i) : this.right.get(i - this.left.length)
13546
- };
13547
-
13548
- Append.prototype.forEachInner = function forEachInner (f, from, to, start) {
13549
- var leftLen = this.left.length;
13550
- if (from < leftLen &&
13551
- this.left.forEachInner(f, from, Math.min(to, leftLen), start) === false)
13552
- { return false }
13553
- if (to > leftLen &&
13554
- this.right.forEachInner(f, Math.max(from - leftLen, 0), Math.min(this.length, to) - leftLen, start + leftLen) === false)
13555
- { return false }
13556
- };
13557
-
13558
- Append.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) {
13559
- var leftLen = this.left.length;
13560
- if (from > leftLen &&
13561
- this.right.forEachInvertedInner(f, from - leftLen, Math.max(to, leftLen) - leftLen, start + leftLen) === false)
13562
- { return false }
13563
- if (to < leftLen &&
13564
- this.left.forEachInvertedInner(f, Math.min(from, leftLen), to, start) === false)
13565
- { return false }
13566
- };
13567
-
13568
- Append.prototype.sliceInner = function sliceInner (from, to) {
13569
- if (from == 0 && to == this.length) { return this }
13570
- var leftLen = this.left.length;
13571
- if (to <= leftLen) { return this.left.slice(from, to) }
13572
- if (from >= leftLen) { return this.right.slice(from - leftLen, to - leftLen) }
13573
- return this.left.slice(from, leftLen).append(this.right.slice(0, to - leftLen))
13574
- };
13575
-
13576
- Append.prototype.leafAppend = function leafAppend (other) {
13577
- var inner = this.right.leafAppend(other);
13578
- if (inner) { return new Append(this.left, inner) }
13579
- };
13580
-
13581
- Append.prototype.leafPrepend = function leafPrepend (other) {
13582
- var inner = this.left.leafPrepend(other);
13583
- if (inner) { return new Append(inner, this.right) }
13584
- };
13585
-
13586
- Append.prototype.appendInner = function appendInner (other) {
13587
- if (this.left.depth >= Math.max(this.right.depth, other.depth) + 1)
13588
- { return new Append(this.left, new Append(this.right, other)) }
13589
- return new Append(this, other)
13590
- };
13591
-
13592
- return Append;
13593
- }(RopeSequence));
13594
-
13595
- // ProseMirror's history isn't simply a way to roll back to a previous
13596
- // state, because ProseMirror supports applying changes without adding
13597
- // them to the history (for example during collaboration).
13598
- //
13599
- // To this end, each 'Branch' (one for the undo history and one for
13600
- // the redo history) keeps an array of 'Items', which can optionally
13601
- // hold a step (an actual undoable change), and always hold a position
13602
- // map (which is needed to move changes below them to apply to the
13603
- // current document).
13604
- //
13605
- // An item that has both a step and a selection bookmark is the start
13606
- // of an 'event' — a group of changes that will be undone or redone at
13607
- // once. (It stores only the bookmark, since that way we don't have to
13608
- // provide a document until the selection is actually applied, which
13609
- // is useful when compressing.)
13610
- // Used to schedule history compression
13611
- const max_empty_items = 500;
13612
- class Branch {
13613
- constructor(items, eventCount) {
13614
- this.items = items;
13615
- this.eventCount = eventCount;
13616
- }
13617
- // Pop the latest event off the branch's history and apply it
13618
- // to a document transform.
13619
- popEvent(state, preserveItems) {
13620
- if (this.eventCount == 0)
13621
- return null;
13622
- let end = this.items.length;
13623
- for (;; end--) {
13624
- let next = this.items.get(end - 1);
13625
- if (next.selection) {
13626
- --end;
13627
- break;
13628
- }
13629
- }
13630
- let remap, mapFrom;
13631
- if (preserveItems) {
13632
- remap = this.remapping(end, this.items.length);
13633
- mapFrom = remap.maps.length;
13634
- }
13635
- let transform = state.tr;
13636
- let selection, remaining;
13637
- let addAfter = [], addBefore = [];
13638
- this.items.forEach((item, i) => {
13639
- if (!item.step) {
13640
- if (!remap) {
13641
- remap = this.remapping(end, i + 1);
13642
- mapFrom = remap.maps.length;
13643
- }
13644
- mapFrom--;
13645
- addBefore.push(item);
13646
- return;
13647
- }
13648
- if (remap) {
13649
- addBefore.push(new Item(item.map));
13650
- let step = item.step.map(remap.slice(mapFrom)), map;
13651
- if (step && transform.maybeStep(step).doc) {
13652
- map = transform.mapping.maps[transform.mapping.maps.length - 1];
13653
- addAfter.push(new Item(map, undefined, undefined, addAfter.length + addBefore.length));
13654
- }
13655
- mapFrom--;
13656
- if (map)
13657
- remap.appendMap(map, mapFrom);
13658
- }
13659
- else {
13660
- transform.maybeStep(item.step);
13661
- }
13662
- if (item.selection) {
13663
- selection = remap ? item.selection.map(remap.slice(mapFrom)) : item.selection;
13664
- remaining = new Branch(this.items.slice(0, end).append(addBefore.reverse().concat(addAfter)), this.eventCount - 1);
13665
- return false;
13666
- }
13667
- }, this.items.length, 0);
13668
- return { remaining: remaining, transform, selection: selection };
13669
- }
13670
- // Create a new branch with the given transform added.
13671
- addTransform(transform, selection, histOptions, preserveItems) {
13672
- let newItems = [], eventCount = this.eventCount;
13673
- let oldItems = this.items, lastItem = !preserveItems && oldItems.length ? oldItems.get(oldItems.length - 1) : null;
13674
- for (let i = 0; i < transform.steps.length; i++) {
13675
- let step = transform.steps[i].invert(transform.docs[i]);
13676
- let item = new Item(transform.mapping.maps[i], step, selection), merged;
13677
- if (merged = lastItem && lastItem.merge(item)) {
13678
- item = merged;
13679
- if (i)
13680
- newItems.pop();
13681
- else
13682
- oldItems = oldItems.slice(0, oldItems.length - 1);
13683
- }
13684
- newItems.push(item);
13685
- if (selection) {
13686
- eventCount++;
13687
- selection = undefined;
13688
- }
13689
- if (!preserveItems)
13690
- lastItem = item;
13691
- }
13692
- let overflow = eventCount - histOptions.depth;
13693
- if (overflow > DEPTH_OVERFLOW) {
13694
- oldItems = cutOffEvents(oldItems, overflow);
13695
- eventCount -= overflow;
13696
- }
13697
- return new Branch(oldItems.append(newItems), eventCount);
13698
- }
13699
- remapping(from, to) {
13700
- let maps = new Mapping;
13701
- this.items.forEach((item, i) => {
13702
- let mirrorPos = item.mirrorOffset != null && i - item.mirrorOffset >= from
13703
- ? maps.maps.length - item.mirrorOffset : undefined;
13704
- maps.appendMap(item.map, mirrorPos);
13705
- }, from, to);
13706
- return maps;
13707
- }
13708
- addMaps(array) {
13709
- if (this.eventCount == 0)
13710
- return this;
13711
- return new Branch(this.items.append(array.map(map => new Item(map))), this.eventCount);
13712
- }
13713
- // When the collab module receives remote changes, the history has
13714
- // to know about those, so that it can adjust the steps that were
13715
- // rebased on top of the remote changes, and include the position
13716
- // maps for the remote changes in its array of items.
13717
- rebased(rebasedTransform, rebasedCount) {
13718
- if (!this.eventCount)
13719
- return this;
13720
- let rebasedItems = [], start = Math.max(0, this.items.length - rebasedCount);
13721
- let mapping = rebasedTransform.mapping;
13722
- let newUntil = rebasedTransform.steps.length;
13723
- let eventCount = this.eventCount;
13724
- this.items.forEach(item => { if (item.selection)
13725
- eventCount--; }, start);
13726
- let iRebased = rebasedCount;
13727
- this.items.forEach(item => {
13728
- let pos = mapping.getMirror(--iRebased);
13729
- if (pos == null)
13730
- return;
13731
- newUntil = Math.min(newUntil, pos);
13732
- let map = mapping.maps[pos];
13733
- if (item.step) {
13734
- let step = rebasedTransform.steps[pos].invert(rebasedTransform.docs[pos]);
13735
- let selection = item.selection && item.selection.map(mapping.slice(iRebased + 1, pos));
13736
- if (selection)
13737
- eventCount++;
13738
- rebasedItems.push(new Item(map, step, selection));
13739
- }
13740
- else {
13741
- rebasedItems.push(new Item(map));
13742
- }
13743
- }, start);
13744
- let newMaps = [];
13745
- for (let i = rebasedCount; i < newUntil; i++)
13746
- newMaps.push(new Item(mapping.maps[i]));
13747
- let items = this.items.slice(0, start).append(newMaps).append(rebasedItems);
13748
- let branch = new Branch(items, eventCount);
13749
- if (branch.emptyItemCount() > max_empty_items)
13750
- branch = branch.compress(this.items.length - rebasedItems.length);
13751
- return branch;
13752
- }
13753
- emptyItemCount() {
13754
- let count = 0;
13755
- this.items.forEach(item => { if (!item.step)
13756
- count++; });
13757
- return count;
13758
- }
13759
- // Compressing a branch means rewriting it to push the air (map-only
13760
- // items) out. During collaboration, these naturally accumulate
13761
- // because each remote change adds one. The `upto` argument is used
13762
- // to ensure that only the items below a given level are compressed,
13763
- // because `rebased` relies on a clean, untouched set of items in
13764
- // order to associate old items with rebased steps.
13765
- compress(upto = this.items.length) {
13766
- let remap = this.remapping(0, upto), mapFrom = remap.maps.length;
13767
- let items = [], events = 0;
13768
- this.items.forEach((item, i) => {
13769
- if (i >= upto) {
13770
- items.push(item);
13771
- if (item.selection)
13772
- events++;
13773
- }
13774
- else if (item.step) {
13775
- let step = item.step.map(remap.slice(mapFrom)), map = step && step.getMap();
13776
- mapFrom--;
13777
- if (map)
13778
- remap.appendMap(map, mapFrom);
13779
- if (step) {
13780
- let selection = item.selection && item.selection.map(remap.slice(mapFrom));
13781
- if (selection)
13782
- events++;
13783
- let newItem = new Item(map.invert(), step, selection), merged, last = items.length - 1;
13784
- if (merged = items.length && items[last].merge(newItem))
13785
- items[last] = merged;
13786
- else
13787
- items.push(newItem);
13788
- }
13789
- }
13790
- else if (item.map) {
13791
- mapFrom--;
13792
- }
13793
- }, this.items.length, 0);
13794
- return new Branch(RopeSequence.from(items.reverse()), events);
13795
- }
13796
- }
13797
- Branch.empty = new Branch(RopeSequence.empty, 0);
13798
- function cutOffEvents(items, n) {
13799
- let cutPoint;
13800
- items.forEach((item, i) => {
13801
- if (item.selection && (n-- == 0)) {
13802
- cutPoint = i;
13803
- return false;
13804
- }
13805
- });
13806
- return items.slice(cutPoint);
13807
- }
13808
- class Item {
13809
- constructor(
13810
- // The (forward) step map for this item.
13811
- map,
13812
- // The inverted step
13813
- step,
13814
- // If this is non-null, this item is the start of a group, and
13815
- // this selection is the starting selection for the group (the one
13816
- // that was active before the first step was applied)
13817
- selection,
13818
- // If this item is the inverse of a previous mapping on the stack,
13819
- // this points at the inverse's offset
13820
- mirrorOffset) {
13821
- this.map = map;
13822
- this.step = step;
13823
- this.selection = selection;
13824
- this.mirrorOffset = mirrorOffset;
13825
- }
13826
- merge(other) {
13827
- if (this.step && other.step && !other.selection) {
13828
- let step = other.step.merge(this.step);
13829
- if (step)
13830
- return new Item(step.getMap().invert(), step, this.selection);
13831
- }
13832
- }
13833
- }
13834
- // The value of the state field that tracks undo/redo history for that
13835
- // state. Will be stored in the plugin state when the history plugin
13836
- // is active.
13837
- class HistoryState {
13838
- constructor(done, undone, prevRanges, prevTime, prevComposition) {
13839
- this.done = done;
13840
- this.undone = undone;
13841
- this.prevRanges = prevRanges;
13842
- this.prevTime = prevTime;
13843
- this.prevComposition = prevComposition;
13844
- }
13845
- }
13846
- const DEPTH_OVERFLOW = 20;
13847
- // Record a transformation in undo history.
13848
- function applyTransaction(history, state, tr, options) {
13849
- let historyTr = tr.getMeta(historyKey), rebased;
13850
- if (historyTr)
13851
- return historyTr.historyState;
13852
- if (tr.getMeta(closeHistoryKey))
13853
- history = new HistoryState(history.done, history.undone, null, 0, -1);
13854
- let appended = tr.getMeta("appendedTransaction");
13855
- if (tr.steps.length == 0) {
13856
- return history;
13857
- }
13858
- else if (appended && appended.getMeta(historyKey)) {
13859
- if (appended.getMeta(historyKey).redo)
13860
- return new HistoryState(history.done.addTransform(tr, undefined, options, mustPreserveItems(state)), history.undone, rangesFor(tr.mapping.maps), history.prevTime, history.prevComposition);
13861
- else
13862
- return new HistoryState(history.done, history.undone.addTransform(tr, undefined, options, mustPreserveItems(state)), null, history.prevTime, history.prevComposition);
13863
- }
13864
- else if (tr.getMeta("addToHistory") !== false && !(appended && appended.getMeta("addToHistory") === false)) {
13865
- // Group transforms that occur in quick succession into one event.
13866
- let composition = tr.getMeta("composition");
13867
- let newGroup = history.prevTime == 0 ||
13868
- (!appended && history.prevComposition != composition &&
13869
- (history.prevTime < (tr.time || 0) - options.newGroupDelay || !isAdjacentTo(tr, history.prevRanges)));
13870
- let prevRanges = appended ? mapRanges(history.prevRanges, tr.mapping) : rangesFor(tr.mapping.maps);
13871
- return new HistoryState(history.done.addTransform(tr, newGroup ? state.selection.getBookmark() : undefined, options, mustPreserveItems(state)), Branch.empty, prevRanges, tr.time, composition == null ? history.prevComposition : composition);
13872
- }
13873
- else if (rebased = tr.getMeta("rebased")) {
13874
- // Used by the collab module to tell the history that some of its
13875
- // content has been rebased.
13876
- return new HistoryState(history.done.rebased(tr, rebased), history.undone.rebased(tr, rebased), mapRanges(history.prevRanges, tr.mapping), history.prevTime, history.prevComposition);
13877
- }
13878
- else {
13879
- return new HistoryState(history.done.addMaps(tr.mapping.maps), history.undone.addMaps(tr.mapping.maps), mapRanges(history.prevRanges, tr.mapping), history.prevTime, history.prevComposition);
13880
- }
13881
- }
13882
- function isAdjacentTo(transform, prevRanges) {
13883
- if (!prevRanges)
13884
- return false;
13885
- if (!transform.docChanged)
13886
- return true;
13887
- let adjacent = false;
13888
- transform.mapping.maps[0].forEach((start, end) => {
13889
- for (let i = 0; i < prevRanges.length; i += 2)
13890
- if (start <= prevRanges[i + 1] && end >= prevRanges[i])
13891
- adjacent = true;
13892
- });
13893
- return adjacent;
13894
- }
13895
- function rangesFor(maps) {
13896
- let result = [];
13897
- for (let i = maps.length - 1; i >= 0 && result.length == 0; i--)
13898
- maps[i].forEach((_from, _to, from, to) => result.push(from, to));
13899
- return result;
13900
- }
13901
- function mapRanges(ranges, mapping) {
13902
- if (!ranges)
13903
- return null;
13904
- let result = [];
13905
- for (let i = 0; i < ranges.length; i += 2) {
13906
- let from = mapping.map(ranges[i], 1), to = mapping.map(ranges[i + 1], -1);
13907
- if (from <= to)
13908
- result.push(from, to);
13909
- }
13910
- return result;
13911
- }
13912
- // Apply the latest event from one branch to the document and shift the event
13913
- // onto the other branch.
13914
- function histTransaction(history, state, redo) {
13915
- let preserveItems = mustPreserveItems(state);
13916
- let histOptions = historyKey.get(state).spec.config;
13917
- let pop = (redo ? history.undone : history.done).popEvent(state, preserveItems);
13918
- if (!pop)
13919
- return null;
13920
- let selection = pop.selection.resolve(pop.transform.doc);
13921
- let added = (redo ? history.done : history.undone).addTransform(pop.transform, state.selection.getBookmark(), histOptions, preserveItems);
13922
- let newHist = new HistoryState(redo ? added : pop.remaining, redo ? pop.remaining : added, null, 0, -1);
13923
- return pop.transform.setSelection(selection).setMeta(historyKey, { redo, historyState: newHist });
13924
- }
13925
- let cachedPreserveItems = false, cachedPreserveItemsPlugins = null;
13926
- // Check whether any plugin in the given state has a
13927
- // `historyPreserveItems` property in its spec, in which case we must
13928
- // preserve steps exactly as they came in, so that they can be
13929
- // rebased.
13930
- function mustPreserveItems(state) {
13931
- let plugins = state.plugins;
13932
- if (cachedPreserveItemsPlugins != plugins) {
13933
- cachedPreserveItems = false;
13934
- cachedPreserveItemsPlugins = plugins;
13935
- for (let i = 0; i < plugins.length; i++)
13936
- if (plugins[i].spec.historyPreserveItems) {
13937
- cachedPreserveItems = true;
13938
- break;
13939
- }
13940
- }
13941
- return cachedPreserveItems;
13942
- }
13943
- const historyKey = new PluginKey("history");
13944
- const closeHistoryKey = new PluginKey("closeHistory");
13945
- /**
13946
- Returns a plugin that enables the undo history for an editor. The
13947
- plugin will track undo and redo stacks, which can be used with the
13948
- [`undo`](https://prosemirror.net/docs/ref/#history.undo) and [`redo`](https://prosemirror.net/docs/ref/#history.redo) commands.
13949
-
13950
- You can set an `"addToHistory"` [metadata
13951
- property](https://prosemirror.net/docs/ref/#state.Transaction.setMeta) of `false` on a transaction
13952
- to prevent it from being rolled back by undo.
13953
- */
13954
- function history(config = {}) {
13955
- config = { depth: config.depth || 100,
13956
- newGroupDelay: config.newGroupDelay || 500 };
13957
- return new Plugin({
13958
- key: historyKey,
13959
- state: {
13960
- init() {
13961
- return new HistoryState(Branch.empty, Branch.empty, null, 0, -1);
13962
- },
13963
- apply(tr, hist, state) {
13964
- return applyTransaction(hist, state, tr, config);
13965
- }
13966
- },
13967
- config,
13968
- props: {
13969
- handleDOMEvents: {
13970
- beforeinput(view, e) {
13971
- let inputType = e.inputType;
13972
- let command = inputType == "historyUndo" ? undo : inputType == "historyRedo" ? redo : null;
13973
- if (!command)
13974
- return false;
13975
- e.preventDefault();
13976
- return command(view.state, view.dispatch);
13977
- }
13978
- }
13979
- }
13980
- });
13981
- }
13982
- function buildCommand(redo, scroll) {
13983
- return (state, dispatch) => {
13984
- let hist = historyKey.getState(state);
13985
- if (!hist || (redo ? hist.undone : hist.done).eventCount == 0)
13986
- return false;
13987
- if (dispatch) {
13988
- let tr = histTransaction(hist, state, redo);
13989
- if (tr)
13990
- dispatch(scroll ? tr.scrollIntoView() : tr);
13991
- }
13992
- return true;
13993
- };
13994
- }
13995
- /**
13996
- A command function that undoes the last change, if any.
13997
- */
13998
- const undo = buildCommand(false, true);
13999
- /**
14000
- A command function that redoes the last undone change, if any.
14001
- */
14002
- const redo = buildCommand(true, true);
14003
-
14004
13373
  /**
14005
13374
  Delete the selection, if there is one.
14006
13375
  */
@@ -14508,6 +13877,23 @@ Depending on the detected platform, this will hold
14508
13877
  */
14509
13878
  const baseKeymap = mac ? macBaseKeymap : pcBaseKeymap;
14510
13879
 
13880
+ class AddObjectCommand extends KritzelBaseCommand {
13881
+ object;
13882
+ constructor(core, initiator, object, skipHistory = false) {
13883
+ super(core, initiator, skipHistory);
13884
+ this.object = object;
13885
+ }
13886
+ execute() {
13887
+ this._core.store.state.objectsMap.insert(this.object);
13888
+ this._core.addObjectToDatabase(this.object);
13889
+ }
13890
+ undo() {
13891
+ this.object.isMounted = false;
13892
+ this._core.store.state.objectsMap.remove(object => object.id === this.object.id);
13893
+ this._core.deleteObjectFromDatabase(this.object.id);
13894
+ }
13895
+ }
13896
+
14511
13897
  class KritzelText extends KritzelBaseObject {
14512
13898
  __class__ = 'KritzelText';
14513
13899
  fontFamily = 'Arial';
@@ -14522,19 +13908,21 @@ class KritzelText extends KritzelBaseObject {
14522
13908
  isEditable = true;
14523
13909
  isEditing = false;
14524
13910
  editor = null;
14525
- content = null; // Store ProseMirror document content
13911
+ content = null;
13912
+ _schema = new Schema({
13913
+ nodes: addListNodes(schema.spec.nodes, 'paragraph block*', 'block'),
13914
+ marks: schema.spec.marks,
13915
+ });
13916
+ uneditedObject = null;
14526
13917
  rows = 1;
14527
13918
  get isEmpty() {
14528
13919
  if (!this.editor) {
14529
13920
  return true;
14530
13921
  }
14531
13922
  const doc = this.editor.state.doc;
14532
- // Check if document is empty (only has empty paragraph(s))
14533
- // A truly empty doc has size of 4: start of doc (1) + paragraph (1) + end of paragraph (1) + end of doc (1)
14534
13923
  if (doc.content.size === 0) {
14535
13924
  return true;
14536
13925
  }
14537
- // Check if all content is whitespace
14538
13926
  const text = doc.textContent.trim();
14539
13927
  return text.length === 0;
14540
13928
  }
@@ -14569,49 +13957,80 @@ class KritzelText extends KritzelBaseObject {
14569
13957
  object.scaleFactor = 1;
14570
13958
  object.scale = object._core.store.state.scale;
14571
13959
  object.zIndex = core.store.currentZIndex;
13960
+ object.editor = object.createEditor();
14572
13961
  return object;
14573
13962
  }
14574
13963
  mount(element) {
14575
- if ((this.isMounted && this.elementRef === element) || this.isInViewport() === false) {
13964
+ if (element === null || this.isInViewport() === false) {
13965
+ return;
13966
+ }
13967
+ if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
14576
13968
  return;
14577
13969
  }
14578
- console.log('Mounting text object', this.id);
14579
13970
  this.elementRef = element;
14580
- setTimeout(() => {
14581
- const mySchema = new Schema({
14582
- nodes: addListNodes(schema.spec.nodes, 'paragraph block*', 'block'),
14583
- marks: schema.spec.marks,
14584
- });
14585
- const doc = this.content
14586
- ? mySchema.nodeFromJSON(this.content)
14587
- : mySchema.node('doc', null, [mySchema.node('paragraph')]);
14588
- this.editor = new EditorView(this.elementRef, {
14589
- state: EditorState.create({
14590
- doc: doc,
14591
- plugins: [history(), keymap({ 'Mod-z': undo, 'Mod-y': redo }), keymap(baseKeymap)],
14592
- }),
14593
- editable: () => false, // Start disabled, enable in edit()
14594
- dispatchTransaction: (transaction) => {
14595
- const newState = this.editor.state.apply(transaction);
14596
- this.editor.updateState(newState);
14597
- // Adjust size after content changes
14598
- this.adjustSizeOnInput();
14599
- },
14600
- });
14601
- }, 0);
13971
+ this.elementRef.style.fontFamily = this.fontFamily;
13972
+ this.elementRef.style.fontSize = `${this.fontSize}pt`;
13973
+ this.elementRef.style.color = this.fontColor;
13974
+ this.elementRef.style.whiteSpace = 'pre-wrap';
13975
+ this.elementRef.style.wordWrap = 'break-word';
13976
+ this.elementRef.innerHTML = '';
13977
+ this.elementRef.appendChild(this.editor.dom);
14602
13978
  this.isMounted = true;
13979
+ requestAnimationFrame(() => this.adjustSizeOnInput());
13980
+ }
13981
+ createEditor() {
13982
+ const doc = this._schema.node('doc', null, [this._schema.node('paragraph')]);
13983
+ return new EditorView(null, {
13984
+ state: EditorState.create({
13985
+ doc: doc,
13986
+ plugins: [keymap(baseKeymap)],
13987
+ }),
13988
+ editable: () => false,
13989
+ dispatchTransaction: transaction => {
13990
+ const newState = this.editor.state.apply(transaction);
13991
+ this.editor.updateState(newState);
13992
+ this.adjustSizeOnInput();
13993
+ this._core.store.state.objectsMap.update(this);
13994
+ this._core.rerender();
13995
+ },
13996
+ });
13997
+ }
13998
+ setContent(content) {
13999
+ this.content = content;
14000
+ if (this.editor) {
14001
+ const newDoc = this.editor.state.schema.nodeFromJSON(content);
14002
+ const tr = this.editor.state.tr.replaceWith(0, this.editor.state.doc.content.size, newDoc.content);
14003
+ this.editor.dispatch(tr);
14004
+ }
14603
14005
  }
14604
14006
  adjustSizeOnInput() {
14605
14007
  const element = this.elementRef;
14606
- if (element) {
14008
+ if (element && this.isMounted && element.scrollWidth > 0) {
14009
+ const previousTotalWidth = this.totalWidth;
14010
+ const previousTotalHeight = this.totalHeight;
14607
14011
  const newWidth = element.scrollWidth;
14608
14012
  const newHeight = element.scrollHeight;
14609
- if (this.width !== newWidth * this.scaleFactor || this.height !== newHeight * this.scaleFactor) {
14610
- this.width = newWidth * this.scaleFactor;
14611
- this.height = newHeight * this.scaleFactor;
14612
- this._core.rerender();
14013
+ this.width = newWidth * this.scaleFactor;
14014
+ this.height = newHeight * this.scaleFactor;
14015
+ if (this.rotation !== 0) {
14016
+ const newTotalWidth = this.totalWidth;
14017
+ const newTotalHeight = this.totalHeight;
14018
+ const deltaWidth = (newTotalWidth - previousTotalWidth) / 2;
14019
+ const deltaHeight = (newTotalHeight - previousTotalHeight) / 2;
14020
+ if (deltaWidth !== 0 || deltaHeight !== 0) {
14021
+ const cos = Math.cos(this.rotation);
14022
+ const sin = Math.sin(this.rotation);
14023
+ const rotatedDeltaX = cos * deltaWidth - sin * deltaHeight;
14024
+ const rotatedDeltaY = sin * deltaWidth + cos * deltaHeight;
14025
+ this.translateX += rotatedDeltaX - deltaWidth;
14026
+ this.translateY += rotatedDeltaY - deltaHeight;
14027
+ }
14613
14028
  }
14614
14029
  }
14030
+ if (this._core) {
14031
+ this._core.store.state.objectsMap.update(this);
14032
+ this._core.rerender();
14033
+ }
14615
14034
  }
14616
14035
  resize(x, y, width, height) {
14617
14036
  if (width <= 1 || height <= 1) {
@@ -14627,38 +14046,56 @@ class KritzelText extends KritzelBaseObject {
14627
14046
  this.translateX = x;
14628
14047
  this.translateY = y;
14629
14048
  }
14630
- focus() {
14049
+ focus(coords) {
14631
14050
  if (this.editor) {
14632
- const end = this.editor.state.doc.content.size;
14633
- this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(this.editor.state.doc, end)));
14051
+ const doc = this.editor.state.doc;
14052
+ if (coords) {
14053
+ const pos = this.editor.posAtCoords({ left: coords.x, top: coords.y });
14054
+ if (pos) {
14055
+ this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, pos.pos)));
14056
+ this.editor.focus();
14057
+ return;
14058
+ }
14059
+ }
14060
+ const end = Math.max(1, doc.content.size - 1);
14061
+ this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, end)));
14634
14062
  this.editor.focus();
14635
14063
  }
14636
14064
  }
14637
- edit() {
14638
- console.log('Editing text object', this.id);
14065
+ edit(event) {
14639
14066
  KritzelKeyboardHelper.disableInteractiveWidget();
14067
+ this.uneditedObject = this.clone();
14640
14068
  this._core.store.setState('activeTool', KritzelToolRegistry.getTool('text'));
14641
14069
  this._core.store.state.activeText = this;
14642
- this._core.clearSelection();
14643
- // Enable the ProseMirror editor
14644
14070
  if (this.editor) {
14645
14071
  this.editor.setProps({ editable: () => true });
14646
14072
  }
14647
14073
  this.isEditing = true;
14648
- this.focus();
14074
+ if (event) {
14075
+ this.focus({ x: event.clientX, y: event.clientY });
14076
+ }
14077
+ else {
14078
+ this.focus();
14079
+ }
14080
+ this._core.rerender();
14081
+ requestAnimationFrame(() => this.adjustSizeOnInput());
14649
14082
  KritzelKeyboardHelper.enableInteractiveWidget();
14650
14083
  }
14651
14084
  save() {
14652
- console.log('Saving text object', this.id);
14653
- // Store the current editor content
14654
- if (this.editor) {
14655
- this.content = this.editor.state.doc.toJSON();
14656
- // Disable the ProseMirror editor
14657
- this.editor.setProps({ editable: () => false });
14658
- this.editor.dom.blur(); // Remove focus
14659
- }
14085
+ requestAnimationFrame(() => this.adjustSizeOnInput());
14086
+ this.content = this.editor.state.doc.toJSON();
14087
+ this.editor.setProps({ editable: () => false });
14088
+ this.editor.dom.blur();
14660
14089
  this.isEditing = false;
14661
- this._core.history.executeCommand(new UpdateObjectCommand(this._core, this, this, this));
14090
+ let saveCommand;
14091
+ if (this.isNew) {
14092
+ this.isNew = false;
14093
+ saveCommand = new AddObjectCommand(this._core, this, this);
14094
+ }
14095
+ else {
14096
+ saveCommand = new UpdateObjectCommand(this._core, this, this.uneditedObject, { ...this });
14097
+ }
14098
+ this._core.commandManager.executeCommand(saveCommand);
14662
14099
  }
14663
14100
  handlePointerDown(event) {
14664
14101
  if (!this.isEditing) {
@@ -14678,14 +14115,37 @@ class KritzelText extends KritzelBaseObject {
14678
14115
  }
14679
14116
  event.stopPropagation();
14680
14117
  }
14118
+ copy() {
14119
+ const copiedObject = super.copy();
14120
+ copiedObject.editor = copiedObject.createEditor();
14121
+ if (this.content) {
14122
+ copiedObject.setContent(this.content);
14123
+ }
14124
+ return copiedObject;
14125
+ }
14681
14126
  serialize() {
14682
- const { _core, _elementRef, element, totalWidth, totalHeight, editor, ...remainingProps } = this;
14127
+ const { _core, _elementRef, _schema, element, totalWidth, totalHeight, editor, uneditedObject, ...remainingProps } = this;
14683
14128
  const clonedProps = structuredClone(remainingProps);
14684
14129
  if (element && typeof element === 'object' && 'nodeType' in element && element.nodeType === 1) {
14685
14130
  clonedProps.element = element.cloneNode(true);
14686
14131
  }
14687
14132
  return clonedProps;
14688
14133
  }
14134
+ deserialize(object) {
14135
+ super.deserialize(object);
14136
+ this.setContent(object.content);
14137
+ return this;
14138
+ }
14139
+ onExecuteUpdateCommand(updatedProperties) {
14140
+ if ('content' in updatedProperties) {
14141
+ this.setContent(updatedProperties.content);
14142
+ }
14143
+ }
14144
+ onUndoUpdateCommand(previousProperties) {
14145
+ if ('content' in previousProperties && this.editor) {
14146
+ this.setContent(previousProperties.content);
14147
+ }
14148
+ }
14689
14149
  }
14690
14150
 
14691
14151
  var cjs = {};
@@ -15043,9 +14503,6 @@ class KritzelEventHelper {
15043
14503
  static isLeftClick(ev) {
15044
14504
  return ev.button === exports.KritzelMouseButton.Left;
15045
14505
  }
15046
- static isMainMouseWheel(event) {
15047
- return Math.abs(event.deltaY) > 0 && Math.abs(event.deltaX) === 0 && Number.isInteger(event.deltaY);
15048
- }
15049
14506
  static isPointerEventOnContextMenu(event) {
15050
14507
  const path = event.composedPath();
15051
14508
  const contextMenu = path.find(element => element.classList && element.classList.contains('context-menu'));
@@ -15089,22 +14546,6 @@ class KritzelEventHelper {
15089
14546
  }
15090
14547
  }
15091
14548
 
15092
- class AddObjectCommand extends KritzelBaseCommand {
15093
- object;
15094
- constructor(core, initiator, object, skipHistory = false) {
15095
- super(core, initiator, skipHistory);
15096
- this.object = object;
15097
- }
15098
- execute() {
15099
- this._core.store.state.objectsMap.insert(this.object);
15100
- this._core.addObjectToDatabase(this.object);
15101
- }
15102
- undo() {
15103
- this._core.store.state.objectsMap.remove(object => object.id === this.object.id);
15104
- this._core.deleteObjectFromDatabase(this.object.id);
15105
- }
15106
- }
15107
-
15108
14549
  class KritzelBaseTool {
15109
14550
  __class__ = this.constructor.name;
15110
14551
  name = 'base-tool';
@@ -15237,7 +14678,7 @@ class KritzelBrushTool extends KritzelBaseTool {
15237
14678
  const currentPath = this._core.store.state.currentPath;
15238
14679
  currentPath.zIndex = this._core.store.currentZIndex;
15239
14680
  this._core.store.state.currentPath = currentPath;
15240
- this._core.history.executeCommand(new AddObjectCommand(this._core, this, this._core.store.state.currentPath));
14681
+ this._core.commandManager.executeCommand(new AddObjectCommand(this._core, this, this._core.store.state.currentPath));
15241
14682
  }
15242
14683
  this._core.store.state.currentPath = undefined;
15243
14684
  }
@@ -15249,7 +14690,7 @@ class KritzelBrushTool extends KritzelBaseTool {
15249
14690
  const currentPath = this._core.store.state.currentPath;
15250
14691
  currentPath.zIndex = this._core.store.currentZIndex;
15251
14692
  this._core.store.state.currentPath = currentPath;
15252
- this._core.history.executeCommand(new AddObjectCommand(this._core, this, currentPath));
14693
+ this._core.commandManager.executeCommand(new AddObjectCommand(this._core, this, currentPath));
15253
14694
  }
15254
14695
  this._core.store.state.currentPath = undefined;
15255
14696
  this._core.rerender();
@@ -15272,59 +14713,6 @@ class BatchCommand extends KritzelBaseCommand {
15272
14713
  }
15273
14714
  }
15274
14715
 
15275
- class KritzelCustomElement extends KritzelBaseObject {
15276
- __class__ = 'KritzelCustomElement';
15277
- element;
15278
- isInteractive = true;
15279
- constructor(config) {
15280
- super();
15281
- if (config) {
15282
- this.translateX = config.translateX || 0;
15283
- this.translateY = config.translateY || 0;
15284
- this.scale = config.scale || 1;
15285
- this.element = config.element;
15286
- this.height = config.height || 0;
15287
- this.width = config.width || 0;
15288
- }
15289
- }
15290
- static create(core, config) {
15291
- const object = new KritzelCustomElement(config);
15292
- object._core = core;
15293
- object.id = object.generateId();
15294
- object.workspaceId = core.store.state.activeWorkspace.id;
15295
- return object;
15296
- }
15297
- mount(element) {
15298
- if (this.isMounted) {
15299
- return;
15300
- }
15301
- this.elementRef = element;
15302
- this.isMounted = true;
15303
- this.elementRef.appendChild(this.element);
15304
- }
15305
- resize(x, y, width, height) {
15306
- if (width <= 1 || height <= 1) {
15307
- return;
15308
- }
15309
- this.width = width;
15310
- this.height = height;
15311
- this.translateX = x;
15312
- this.translateY = y;
15313
- if (this.element) {
15314
- this.element.style.width = `${width}px`;
15315
- this.element.style.height = `${height}px`;
15316
- }
15317
- }
15318
- copy() {
15319
- const copiedObject = Object.create(Object.getPrototypeOf(this));
15320
- Object.assign(copiedObject, this);
15321
- copiedObject.id = this.generateId();
15322
- copiedObject.isMounted = false;
15323
- copiedObject.element = this.element.cloneNode(true);
15324
- return copiedObject;
15325
- }
15326
- }
15327
-
15328
14716
  class RemoveObjectCommand extends KritzelBaseCommand {
15329
14717
  object;
15330
14718
  constructor(core, initiator, object, skipHistory = false) {
@@ -15332,13 +14720,12 @@ class RemoveObjectCommand extends KritzelBaseCommand {
15332
14720
  this.object = object;
15333
14721
  }
15334
14722
  execute() {
14723
+ this.object.isMounted = false;
15335
14724
  this._core.store.state.objectsMap.remove(object => object.id === this.object.id);
15336
- this._core.store.state.objectsMap.filter(object => object instanceof KritzelCustomElement).forEach(object => object.remount());
15337
14725
  this._core.deleteObjectFromDatabase(this.object.id);
15338
14726
  }
15339
14727
  undo() {
15340
14728
  this._core.store.state.objectsMap.insert(this.object);
15341
- this._core.store.state.objectsMap.filter(object => object instanceof KritzelCustomElement).forEach(object => object.remount());
15342
14729
  this._core.addObjectToDatabase(this.object);
15343
14730
  }
15344
14731
  }
@@ -15401,7 +14788,7 @@ class KritzelEraserTool extends KritzelBaseTool {
15401
14788
  return new RemoveObjectCommand(this._core, this, object);
15402
14789
  });
15403
14790
  if (removeCommands.length > 0) {
15404
- this._core.history.executeCommand(new BatchCommand(this._core, this, removeCommands));
14791
+ this._core.commandManager.executeCommand(new BatchCommand(this._core, this, removeCommands));
15405
14792
  }
15406
14793
  this._core.store.state.isErasing = false;
15407
14794
  }
@@ -15416,7 +14803,7 @@ class KritzelEraserTool extends KritzelBaseTool {
15416
14803
  return new RemoveObjectCommand(this._core, this, object);
15417
14804
  });
15418
14805
  if (removeCommands.length > 0) {
15419
- this._core.history.executeCommand(new BatchCommand(this._core, this, removeCommands));
14806
+ this._core.commandManager.executeCommand(new BatchCommand(this._core, this, removeCommands));
15420
14807
  }
15421
14808
  this._core.store.state.isErasing = false;
15422
14809
  }
@@ -15567,10 +14954,15 @@ class KritzelMoveHandler extends KritzelBaseHandler {
15567
14954
  const clientY = event.clientY - this._core.store.offsetY;
15568
14955
  this.endX = clientX;
15569
14956
  this.endY = clientY;
15570
- this._core.store.state.selectionGroup.move(clientX, clientY, this.dragStartX, this.dragStartY);
15571
- this.dragStartX = clientX;
15572
- this.dragStartY = clientY;
15573
- this.hasMoved = true;
14957
+ const moveDeltaX = Math.abs(clientX - this.startX);
14958
+ const moveDeltaY = Math.abs(clientY - this.startY);
14959
+ const moveThreshold = 5;
14960
+ if (moveDeltaX > moveThreshold || moveDeltaY > moveThreshold) {
14961
+ this._core.store.state.selectionGroup.move(clientX, clientY, this.dragStartX, this.dragStartY);
14962
+ this.dragStartX = clientX;
14963
+ this.dragStartY = clientY;
14964
+ this.hasMoved = true;
14965
+ }
15574
14966
  }
15575
14967
  }
15576
14968
  if (event.pointerType === 'touch') {
@@ -15605,7 +14997,7 @@ class KritzelMoveHandler extends KritzelBaseHandler {
15605
14997
  if (this._core.store.state.isDragging) {
15606
14998
  this._core.store.state.isDragging = false;
15607
14999
  if (this.hasMoved) {
15608
- this._core.history.executeCommand(new MoveSelectionGroupCommand(this._core, this, this.endX, this.endY, this.startX, this.startY, true));
15000
+ this._core.commandManager.executeCommand(new MoveSelectionGroupCommand(this._core, this, this.endX, this.endY, this.startX, this.startY, true));
15609
15001
  this._core.store.state.hasObjectsChanged = true;
15610
15002
  }
15611
15003
  }
@@ -15614,7 +15006,7 @@ class KritzelMoveHandler extends KritzelBaseHandler {
15614
15006
  if (this._core.store.state.isDragging) {
15615
15007
  this._core.store.state.isDragging = false;
15616
15008
  if (this.hasMoved) {
15617
- this._core.history.executeCommand(new MoveSelectionGroupCommand(this._core, this, this.endX, this.endY, this.startX, this.startY, true));
15009
+ this._core.commandManager.executeCommand(new MoveSelectionGroupCommand(this._core, this, this.endX, this.endY, this.startX, this.startY, true));
15618
15010
  this._core.store.state.hasObjectsChanged = true;
15619
15011
  }
15620
15012
  }
@@ -15664,6 +15056,7 @@ class KritzelResizeHandler extends KritzelBaseHandler {
15664
15056
  initialMouseY = 0;
15665
15057
  initialSize = { x: 0, y: 0, width: 0, height: 0 };
15666
15058
  newSize = { x: 0, y: 0, width: 0, height: 0 };
15059
+ hasResized = false;
15667
15060
  constructor(core) {
15668
15061
  super(core);
15669
15062
  }
@@ -15672,6 +15065,7 @@ class KritzelResizeHandler extends KritzelBaseHandler {
15672
15065
  this.initialMouseY = 0;
15673
15066
  this.initialSize = { x: 0, y: 0, width: 0, height: 0 };
15674
15067
  this.newSize = { x: 0, y: 0, width: 0, height: 0 };
15068
+ this.hasResized = false;
15675
15069
  }
15676
15070
  handlePointerDown(event) {
15677
15071
  if (event.pointerType === 'mouse') {
@@ -15718,6 +15112,15 @@ class KritzelResizeHandler extends KritzelBaseHandler {
15718
15112
  const clientY = event.clientY - this._core.store.offsetY;
15719
15113
  const dx = clientX - this.initialMouseX;
15720
15114
  const dy = clientY - this.initialMouseY;
15115
+ const resizeDeltaX = Math.abs(dx);
15116
+ const resizeDeltaY = Math.abs(dy);
15117
+ const resizeThreshold = 5;
15118
+ if (resizeDeltaX > resizeThreshold || resizeDeltaY > resizeThreshold) {
15119
+ this.hasResized = true;
15120
+ }
15121
+ if (!this.hasResized) {
15122
+ return;
15123
+ }
15721
15124
  switch (this._core.store.state.resizeHandleType) {
15722
15125
  case KritzelHandleType.TopLeft:
15723
15126
  this.newSize.width = this.initialSize.width - dx;
@@ -15758,6 +15161,16 @@ class KritzelResizeHandler extends KritzelBaseHandler {
15758
15161
  const clientY = Math.round(oneFingerTouch.clientY - this._core.store.offsetY);
15759
15162
  const dx = clientX - this.initialMouseX;
15760
15163
  const dy = clientY - this.initialMouseY;
15164
+ const resizeDeltaX = Math.abs(dx);
15165
+ const resizeDeltaY = Math.abs(dy);
15166
+ const resizeThreshold = 5;
15167
+ if (resizeDeltaX > resizeThreshold || resizeDeltaY > resizeThreshold) {
15168
+ clearTimeout(this._core.store.state.longTouchTimeout);
15169
+ this.hasResized = true;
15170
+ }
15171
+ if (!this.hasResized) {
15172
+ return;
15173
+ }
15761
15174
  switch (this._core.store.state.resizeHandleType) {
15762
15175
  case KritzelHandleType.TopLeft:
15763
15176
  this.newSize.width = this.initialSize.width - dx;
@@ -15785,24 +15198,27 @@ class KritzelResizeHandler extends KritzelBaseHandler {
15785
15198
  break;
15786
15199
  }
15787
15200
  this._core.store.state.selectionGroup.resize(this.newSize.x, this.newSize.y, this.newSize.width, this.newSize.height);
15788
- clearTimeout(this._core.store.state.longTouchTimeout);
15789
15201
  }
15790
15202
  }
15791
15203
  }
15792
15204
  handlePointerUp(event) {
15793
15205
  if (event.pointerType === 'mouse') {
15794
15206
  if (this._core.store.state.isResizing) {
15795
- this._core.history.executeCommand(new ResizeSelectionGroupCommand(this._core, this, structuredClone(this.initialSize), structuredClone(this.newSize)));
15796
15207
  this._core.store.state.isResizing = false;
15797
- this._core.store.state.hasObjectsChanged = true;
15208
+ if (this.hasResized) {
15209
+ this._core.commandManager.executeCommand(new ResizeSelectionGroupCommand(this._core, this, structuredClone(this.initialSize), structuredClone(this.newSize)));
15210
+ this._core.store.state.hasObjectsChanged = true;
15211
+ }
15798
15212
  this.reset();
15799
15213
  }
15800
15214
  }
15801
15215
  if (event.pointerType === 'touch') {
15802
15216
  if (this._core.store.state.isResizing) {
15803
- this._core.history.executeCommand(new ResizeSelectionGroupCommand(this._core, this, structuredClone(this.initialSize), structuredClone(this.newSize)));
15804
15217
  this._core.store.state.isResizing = false;
15805
- this._core.store.state.hasObjectsChanged = true;
15218
+ if (this.hasResized) {
15219
+ this._core.commandManager.executeCommand(new ResizeSelectionGroupCommand(this._core, this, structuredClone(this.initialSize), structuredClone(this.newSize)));
15220
+ this._core.store.state.hasObjectsChanged = true;
15221
+ }
15806
15222
  this.reset();
15807
15223
  clearTimeout(this._core.store.state.longTouchTimeout);
15808
15224
  }
@@ -15928,7 +15344,7 @@ class KritzelRotationHandler extends KritzelBaseHandler {
15928
15344
  handlePointerUp(event) {
15929
15345
  if (event.pointerType === 'mouse') {
15930
15346
  if (this._core.store.state.isRotating) {
15931
- this._core.history.executeCommand(new RotateSelectionGroupCommand(this._core, this, this.rotation, this.initialSelectionGroupRotation));
15347
+ this._core.commandManager.executeCommand(new RotateSelectionGroupCommand(this._core, this, this.rotation, this.initialSelectionGroupRotation));
15932
15348
  this._core.store.state.isRotating = false;
15933
15349
  this._core.store.state.hasObjectsChanged = true;
15934
15350
  this.reset();
@@ -15936,7 +15352,7 @@ class KritzelRotationHandler extends KritzelBaseHandler {
15936
15352
  }
15937
15353
  if (event.pointerType === 'touch') {
15938
15354
  if (this._core.store.state.isRotating) {
15939
- this._core.history.executeCommand(new RotateSelectionGroupCommand(this._core, this, this.rotation, this.initialSelectionGroupRotation));
15355
+ this._core.commandManager.executeCommand(new RotateSelectionGroupCommand(this._core, this, this.rotation, this.initialSelectionGroupRotation));
15940
15356
  this._core.store.state.isRotating = false;
15941
15357
  this._core.store.state.hasObjectsChanged = true;
15942
15358
  this.reset();
@@ -16040,7 +15456,7 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
16040
15456
  if (KritzelEventHelper.isLeftClick(event)) {
16041
15457
  const hasObjectsMoved = this._core.store.state.hasObjectsChanged;
16042
15458
  if (this._core.store.state.selectionGroup?.objects.length === 1 && hasObjectsMoved === false) {
16043
- this._core.store.state.selectionGroup.objects[0].edit();
15459
+ this._core.store.state.selectionGroup.objects[0].edit(event);
16044
15460
  }
16045
15461
  this._core.store.state.hasObjectsChanged = false;
16046
15462
  if (this._core.store.state.isSelecting) {
@@ -16059,7 +15475,7 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
16059
15475
  clearTimeout(this.touchStartTimeout);
16060
15476
  const hasObjectsMoved = this._core.store.state.hasObjectsChanged;
16061
15477
  if (this._core.store.state.selectionGroup?.objects.length === 1 && hasObjectsMoved === false) {
16062
- this._core.store.state.selectionGroup.objects[0].edit();
15478
+ this._core.store.state.selectionGroup.objects[0].edit(event);
16063
15479
  }
16064
15480
  this._core.store.state.hasObjectsChanged = false;
16065
15481
  if (this._core.store.state.isSelecting) {
@@ -16202,7 +15618,7 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
16202
15618
  selectionGroup.addOrRemove(object);
16203
15619
  selectionGroup.isSelected = true;
16204
15620
  selectionGroup.rotation = object.rotation;
16205
- this._core.history.executeCommand(new AddSelectionGroupCommand(this._core, this, selectionGroup));
15621
+ this._core.commandManager.executeCommand(new AddSelectionGroupCommand(this._core, this, selectionGroup));
16206
15622
  }
16207
15623
  addSelectedObjectsToSelectionGroup() {
16208
15624
  const selectedObjects = this._core.store.selectedObjects;
@@ -16219,7 +15635,7 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
16219
15635
  if (selectionGroup.length === 1) {
16220
15636
  selectionGroup.rotation = selectionGroup.objects[0].rotation;
16221
15637
  }
16222
- this._core.history.executeCommand(new AddSelectionGroupCommand(this._core, this, selectionGroup));
15638
+ this._core.commandManager.executeCommand(new AddSelectionGroupCommand(this._core, this, selectionGroup));
16223
15639
  }
16224
15640
  }
16225
15641
 
@@ -16268,7 +15684,7 @@ class KritzelSelectionTool extends KritzelBaseTool {
16268
15684
  this._core.store.state.selectionGroup &&
16269
15685
  !this._core.store.state.isResizeHandleSelected &&
16270
15686
  !this._core.store.state.isRotationHandleSelected) {
16271
- this._core.history.executeCommand(new RemoveSelectionGroupCommand(this._core, this._core.store.state.selectionGroup));
15687
+ this._core.commandManager.executeCommand(new RemoveSelectionGroupCommand(this._core, this._core.store.state.selectionGroup));
16272
15688
  }
16273
15689
  if (selectedObject && selectedObject.isSelected === false && selectedObject?.objects.length === 1 && selectedObject.objects[0].isInteractive) {
16274
15690
  return;
@@ -16297,7 +15713,7 @@ class KritzelSelectionTool extends KritzelBaseTool {
16297
15713
  this._core.store.state.selectionGroup &&
16298
15714
  !this._core.store.state.isResizeHandleSelected &&
16299
15715
  !this._core.store.state.isRotationHandleSelected) {
16300
- this._core.history.executeCommand(new RemoveSelectionGroupCommand(this._core, this._core.store.state.selectionGroup));
15716
+ this._core.commandManager.executeCommand(new RemoveSelectionGroupCommand(this._core, this._core.store.state.selectionGroup));
16301
15717
  }
16302
15718
  }
16303
15719
  this.rotationHandler.handlePointerDown(event);
@@ -16423,14 +15839,15 @@ class KritzelTextTool extends KritzelBaseTool {
16423
15839
  const path = event.composedPath().slice(1);
16424
15840
  const objectElement = path.find(element => element.classList && element.classList.contains('object'));
16425
15841
  const object = this._core.findObjectById(objectElement?.id);
16426
- if (object instanceof KritzelText) {
15842
+ if (this._core.store.state.activeText === null && object instanceof KritzelText) {
16427
15843
  this._core.store.state.activeText = object;
16428
- object.focus();
15844
+ object.edit(event);
16429
15845
  return;
16430
15846
  }
16431
15847
  if (this._core.store.state.activeText !== null && object instanceof KritzelText) {
15848
+ this._core.store.state.activeText.save();
16432
15849
  this._core.store.state.activeText = object;
16433
- object.focus();
15850
+ object.edit(event);
16434
15851
  return;
16435
15852
  }
16436
15853
  if (this._core.store.state.activeText !== null && object instanceof KritzelText === false) {
@@ -16444,26 +15861,30 @@ class KritzelTextTool extends KritzelBaseTool {
16444
15861
  const clientX = event.clientX - this._core.store.offsetX;
16445
15862
  const clientY = event.clientY - this._core.store.offsetY;
16446
15863
  const text = KritzelText.create(this._core, this.fontSize, this.fontFamily);
15864
+ text.isNew = true;
16447
15865
  text.fontColor = this.fontColor;
16448
15866
  text.translateX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
16449
15867
  text.translateY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
16450
15868
  text.zIndex = this._core.store.currentZIndex;
16451
15869
  this._core.store.state.activeText = text;
16452
- this._core.history.executeCommand(new AddObjectCommand(this._core, this, text));
15870
+ this._core.store.state.objectsMap.insert(text);
15871
+ this._core.rerender();
15872
+ requestAnimationFrame(() => text.edit(event));
16453
15873
  }
16454
15874
  if (event.pointerType === 'touch') {
16455
15875
  const activePointers = Array.from(this._core.store.state.pointers.values());
16456
15876
  const path = event.composedPath().slice(1);
16457
15877
  const objectElement = path.find(element => element.classList && element.classList.contains('object'));
16458
15878
  const object = this._core.findObjectById(objectElement?.id);
16459
- if (object instanceof KritzelText) {
15879
+ if (this._core.store.state.activeText === null && object instanceof KritzelText) {
16460
15880
  this._core.store.state.activeText = object;
16461
- object.focus();
15881
+ object.edit(event);
16462
15882
  return;
16463
15883
  }
16464
15884
  if (this._core.store.state.activeText !== null && object instanceof KritzelText) {
15885
+ this._core.store.state.activeText.save();
16465
15886
  this._core.store.state.activeText = object;
16466
- object.focus();
15887
+ object.edit(event);
16467
15888
  return;
16468
15889
  }
16469
15890
  if (this._core.store.state.activeText !== null && object instanceof KritzelText === false) {
@@ -16478,12 +15899,14 @@ class KritzelTextTool extends KritzelBaseTool {
16478
15899
  const clientX = Math.round(activePointers[0].clientX - this._core.store.offsetX);
16479
15900
  const clientY = Math.round(activePointers[0].clientY - this._core.store.offsetY);
16480
15901
  const text = KritzelText.create(this._core, this.fontSize, this.fontFamily);
15902
+ text.isNew = true;
16481
15903
  text.fontColor = this.fontColor;
16482
15904
  text.translateX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
16483
15905
  text.translateY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
16484
15906
  text.zIndex = this._core.store.currentZIndex;
16485
15907
  this._core.store.state.activeText = text;
16486
- this._core.history.executeCommand(new AddObjectCommand(this._core, this, text));
15908
+ this._core.store.state.objectsMap.insert(text);
15909
+ this._core.rerender();
16487
15910
  }
16488
15911
  }
16489
15912
  handlePointerUp(event) {
@@ -16491,15 +15914,74 @@ class KritzelTextTool extends KritzelBaseTool {
16491
15914
  event.preventDefault();
16492
15915
  }
16493
15916
  if (event.pointerType === 'mouse') {
16494
- this._core.store.state.activeText?.edit();
15917
+ this._core.store.state.activeText?.edit(event);
16495
15918
  }
16496
15919
  if (event.pointerType === 'touch') {
16497
- this._core.store.state.activeText?.edit();
15920
+ this._core.store.state.activeText?.edit(event);
16498
15921
  KritzelKeyboardHelper.enableInteractiveWidget();
16499
15922
  }
16500
15923
  }
16501
15924
  }
16502
15925
 
15926
+ class KritzelCustomElement extends KritzelBaseObject {
15927
+ __class__ = 'KritzelCustomElement';
15928
+ element;
15929
+ isInteractive = true;
15930
+ constructor(config) {
15931
+ super();
15932
+ if (config) {
15933
+ this.translateX = config.translateX || 0;
15934
+ this.translateY = config.translateY || 0;
15935
+ this.scale = config.scale || 1;
15936
+ this.element = config.element;
15937
+ this.height = config.height || 0;
15938
+ this.width = config.width || 0;
15939
+ }
15940
+ }
15941
+ static create(core, config) {
15942
+ const object = new KritzelCustomElement(config);
15943
+ object._core = core;
15944
+ object.id = object.generateId();
15945
+ object.workspaceId = core.store.state.activeWorkspace.id;
15946
+ return object;
15947
+ }
15948
+ mount(element) {
15949
+ if (element === null) {
15950
+ return;
15951
+ }
15952
+ // If already mounted to the same element and content is still attached, skip
15953
+ if (this.isMounted && this.elementRef === element && this.element.parentElement === element) {
15954
+ return;
15955
+ }
15956
+ this.elementRef = element;
15957
+ this.isMounted = true;
15958
+ // Clear existing content and append the element
15959
+ this.elementRef.innerHTML = '';
15960
+ this.elementRef.appendChild(this.element);
15961
+ }
15962
+ resize(x, y, width, height) {
15963
+ if (width <= 1 || height <= 1) {
15964
+ return;
15965
+ }
15966
+ this.width = width;
15967
+ this.height = height;
15968
+ this.translateX = x;
15969
+ this.translateY = y;
15970
+ if (this.element) {
15971
+ this.element.style.width = `${width}px`;
15972
+ this.element.style.height = `${height}px`;
15973
+ }
15974
+ }
15975
+ copy() {
15976
+ const copiedObject = Object.create(Object.getPrototypeOf(this));
15977
+ Object.assign(copiedObject, this);
15978
+ copiedObject.id = this.generateId();
15979
+ copiedObject.isMounted = false;
15980
+ copiedObject.element = this.element.cloneNode(true);
15981
+ return copiedObject;
15982
+ }
15983
+ }
15984
+
16503
15985
  const DEFAULT_BRUSH_CONFIG = {
16504
15986
  type: 'pen',
16505
15987
  color: '#000000',
@@ -16941,7 +16423,7 @@ class KritzelImageTool extends KritzelBaseTool {
16941
16423
  selectionGroup.isSelected = true;
16942
16424
  const addImageCommand = new AddObjectCommand(this._core, this, image);
16943
16425
  const addSelectionGroupCommand = new AddSelectionGroupCommand(this._core, this, selectionGroup);
16944
- this._core.history.executeCommand(new BatchCommand(this._core, this, [addImageCommand, addSelectionGroupCommand]));
16426
+ this._core.commandManager.executeCommand(new BatchCommand(this._core, this, [addImageCommand, addSelectionGroupCommand]));
16945
16427
  this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
16946
16428
  }
16947
16429
  handleCancel() {
@@ -16976,6 +16458,6 @@ exports.ObjectHelper = ObjectHelper;
16976
16458
  exports.RemoveObjectCommand = RemoveObjectCommand;
16977
16459
  exports.RemoveSelectionGroupCommand = RemoveSelectionGroupCommand;
16978
16460
  exports.UpdateObjectCommand = UpdateObjectCommand;
16979
- //# sourceMappingURL=index-BKstgWru.js.map
16461
+ //# sourceMappingURL=index-Cg50mv2K.js.map
16980
16462
 
16981
- //# sourceMappingURL=index-BKstgWru.js.map
16463
+ //# sourceMappingURL=index-Cg50mv2K.js.map