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