kritzel-stencil 0.1.78 → 0.1.80

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 (163) hide show
  1. package/dist/cjs/{index-BRZ6e6oa.js → index-CFnj_FXt.js} +36 -9
  2. package/dist/cjs/index.cjs.js +1 -1
  3. package/dist/cjs/kritzel-active-users_42.cjs.entry.js +333 -177
  4. package/dist/cjs/kritzel-brush-style.cjs.entry.js +1 -1
  5. package/dist/cjs/loader.cjs.js +2 -2
  6. package/dist/cjs/stencil.cjs.js +3 -3
  7. package/dist/cjs/{workspace.migrations-sUPrO23c.js → workspace.migrations-DUXtSb7C.js} +244 -197
  8. package/dist/collection/classes/core/core.class.js +39 -31
  9. package/dist/collection/classes/core/store.class.js +57 -16
  10. package/dist/collection/classes/core/viewport.class.js +12 -12
  11. package/dist/collection/classes/handlers/context-menu.handler.js +1 -1
  12. package/dist/collection/classes/handlers/line-handle.handler.js +7 -4
  13. package/dist/collection/classes/handlers/move.handler.js +11 -8
  14. package/dist/collection/classes/handlers/resize.handler.js +12 -3
  15. package/dist/collection/classes/handlers/rotation.handler.js +12 -3
  16. package/dist/collection/classes/handlers/selection.handler.js +20 -15
  17. package/dist/collection/classes/managers/anchor.manager.js +4 -4
  18. package/dist/collection/classes/objects/base-object.class.js +6 -6
  19. package/dist/collection/classes/objects/custom-element.class.js +2 -2
  20. package/dist/collection/classes/objects/group.class.js +10 -10
  21. package/dist/collection/classes/objects/image.class.js +2 -2
  22. package/dist/collection/classes/objects/line.class.js +7 -7
  23. package/dist/collection/classes/objects/path.class.js +5 -5
  24. package/dist/collection/classes/objects/selection-box.class.js +1 -1
  25. package/dist/collection/classes/objects/selection-group.class.js +16 -16
  26. package/dist/collection/classes/objects/shape.class.js +37 -31
  27. package/dist/collection/classes/objects/text.class.js +40 -32
  28. package/dist/collection/classes/structures/app-state-map.structure.js +18 -16
  29. package/dist/collection/classes/structures/object-map.structure.js +30 -27
  30. package/dist/collection/classes/tools/brush-tool.class.js +14 -14
  31. package/dist/collection/classes/tools/image-tool.class.js +1 -1
  32. package/dist/collection/classes/tools/line-tool.class.js +14 -14
  33. package/dist/collection/classes/tools/selection-tool.class.js +2 -2
  34. package/dist/collection/classes/tools/shape-tool.class.js +6 -6
  35. package/dist/collection/classes/tools/text-tool.class.js +2 -2
  36. package/dist/collection/collection-manifest.json +1 -1
  37. package/dist/collection/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.js +6 -6
  38. package/dist/collection/components/core/kritzel-cursor-trail/kritzel-cursor-trail.js +2 -2
  39. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +70 -11
  40. package/dist/collection/components/core/kritzel-engine/kritzel-engine.css +21 -1
  41. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +159 -60
  42. package/dist/collection/configs/default-engine-config.js +2 -2
  43. package/dist/collection/constants/version.js +1 -1
  44. package/dist/collection/helpers/keyboard.helper.js +15 -11
  45. package/dist/components/index.js +1 -1
  46. package/dist/components/kritzel-active-users.js +1 -1
  47. package/dist/components/kritzel-avatar.js +1 -1
  48. package/dist/components/kritzel-awareness-cursors.js +1 -1
  49. package/dist/components/kritzel-back-to-content.js +1 -1
  50. package/dist/components/kritzel-brush-style.js +1 -1
  51. package/dist/components/kritzel-button.js +1 -1
  52. package/dist/components/kritzel-color-palette.js +1 -1
  53. package/dist/components/kritzel-color.js +1 -1
  54. package/dist/components/kritzel-context-menu.js +1 -1
  55. package/dist/components/kritzel-controls.js +1 -1
  56. package/dist/components/kritzel-current-user-dialog.js +1 -1
  57. package/dist/components/kritzel-current-user.js +1 -1
  58. package/dist/components/kritzel-cursor-trail.js +1 -1
  59. package/dist/components/kritzel-dialog.js +1 -1
  60. package/dist/components/kritzel-dropdown.js +1 -1
  61. package/dist/components/kritzel-editor.js +1 -1
  62. package/dist/components/kritzel-engine.js +1 -1
  63. package/dist/components/kritzel-export.js +1 -1
  64. package/dist/components/kritzel-font-family.js +1 -1
  65. package/dist/components/kritzel-font-size.js +1 -1
  66. package/dist/components/kritzel-font.js +1 -1
  67. package/dist/components/kritzel-icon.js +1 -1
  68. package/dist/components/kritzel-input.js +1 -1
  69. package/dist/components/kritzel-line-endings.js +1 -1
  70. package/dist/components/kritzel-login-dialog.js +1 -1
  71. package/dist/components/kritzel-master-detail.js +1 -1
  72. package/dist/components/kritzel-menu-item.js +1 -1
  73. package/dist/components/kritzel-menu.js +1 -1
  74. package/dist/components/kritzel-more-menu.js +1 -1
  75. package/dist/components/kritzel-numeric-input.js +1 -1
  76. package/dist/components/kritzel-opacity-slider.js +1 -1
  77. package/dist/components/kritzel-pill-tabs.js +1 -1
  78. package/dist/components/kritzel-portal.js +1 -1
  79. package/dist/components/kritzel-settings.js +1 -1
  80. package/dist/components/kritzel-shape-fill.js +1 -1
  81. package/dist/components/kritzel-share-dialog.js +1 -1
  82. package/dist/components/kritzel-slide-toggle.js +1 -1
  83. package/dist/components/kritzel-split-button.js +1 -1
  84. package/dist/components/kritzel-stroke-size.js +1 -1
  85. package/dist/components/kritzel-tool-config.js +1 -1
  86. package/dist/components/kritzel-tooltip.js +1 -1
  87. package/dist/components/kritzel-utility-panel.js +1 -1
  88. package/dist/components/kritzel-workspace-manager.js +1 -1
  89. package/dist/components/{p-Md9Y-b3d.js → p-1ppb4M65.js} +1 -1
  90. package/dist/components/{p-KJ4dHzrS.js → p-7yR-sKH8.js} +1 -1
  91. package/dist/components/{p-CN8IxBlU.js → p-B-Gej_Ak.js} +1 -1
  92. package/dist/components/{p-76W5pG2O.js → p-B4F19Aqj.js} +1 -1
  93. package/dist/components/{p-BuI6Gkzg.js → p-B5WII1Lk.js} +1 -1
  94. package/dist/components/p-BWj1eE2b.js +1 -0
  95. package/dist/components/{p-ZC5YELQJ.js → p-BZ8bK8qT.js} +1 -1
  96. package/dist/components/{p-DkWWzVg8.js → p-BaaFG0p-.js} +1 -1
  97. package/dist/components/{p-6NFl6EB2.js → p-Bat829Bg.js} +1 -1
  98. package/dist/components/p-BcwZ36sO.js +1 -0
  99. package/dist/components/{p-53di1Zko.js → p-BjPmEs5A.js} +1 -1
  100. package/dist/components/{p-D5IhryUR.js → p-Brwz_Dpb.js} +1 -1
  101. package/dist/components/p-BzQmBVwr.js +9 -0
  102. package/dist/components/{p-C2l9mZ1P.js → p-C-MtTi6x.js} +1 -1
  103. package/dist/components/p-C8WnYSHi.js +1 -0
  104. package/dist/components/{p-BLsH_Oi0.js → p-C9zsWWH2.js} +1 -1
  105. package/dist/components/{p-ZQ2bKafG.js → p-CJKsuQun.js} +1 -1
  106. package/dist/components/{p-m1nVDC3G.js → p-CJzg_ejc.js} +1 -1
  107. package/dist/components/{p-Dte67BWd.js → p-CM7rYf9A.js} +1 -1
  108. package/dist/components/{p-Dr3-pKVg.js → p-CMGHx71q.js} +1 -1
  109. package/dist/components/{p-CI9Nbh-x.js → p-CNMpVlot.js} +1 -1
  110. package/dist/components/{p-DDKjsXCe.js → p-CS7r-zhx.js} +1 -1
  111. package/dist/components/{p-DaGZEV0R.js → p-C_fSm7T4.js} +1 -1
  112. package/dist/components/{p-Ck1dhpUQ.js → p-CfEGaTaV.js} +1 -1
  113. package/dist/components/{p-CWMFGEe0.js → p-CvyE2Wg-.js} +1 -1
  114. package/dist/components/{p-D3pNw-SV.js → p-D5BXoK9m.js} +1 -1
  115. package/dist/components/{p-DV7Z_qfa.js → p-D7pwbRUy.js} +1 -1
  116. package/dist/components/{p-CBslLN3-.js → p-DCH4Rlqx.js} +1 -1
  117. package/dist/components/{p-CYh7yV-K.js → p-DEOUiiyI.js} +1 -1
  118. package/dist/components/{p-pCC6t6BH.js → p-DKeBfe_l.js} +1 -1
  119. package/dist/components/{p-DWsCbu01.js → p-DUQmBcTy.js} +1 -1
  120. package/dist/components/{p-D14QNK3X.js → p-DUnKjQN7.js} +1 -1
  121. package/dist/components/{p-BrZ_gL8Q.js → p-DYcsC2zO.js} +1 -1
  122. package/dist/components/{p-D7yzmu1l.js → p-DkT0KZCm.js} +1 -1
  123. package/dist/components/{p-Cns7qSKS.js → p-DrsORMoT.js} +1 -1
  124. package/dist/components/{p-BueaqfA2.js → p-Dw0Obsn5.js} +1 -1
  125. package/dist/components/{p-DxzDda_J.js → p-Gm5hSQ-e.js} +1 -1
  126. package/dist/components/{p-C4fKLlrd.js → p-HK-6khHo.js} +1 -1
  127. package/dist/components/{p-_QEHfsIk.js → p-V3VW2JKl.js} +1 -1
  128. package/dist/components/{p-Lhyh6KeB.js → p-VxgCvVox.js} +1 -1
  129. package/dist/components/{p-l_YGO7RB.js → p-cjeDomsc.js} +1 -1
  130. package/dist/components/{p-gtQlsorg.js → p-rNu5JVNH.js} +1 -1
  131. package/dist/components/p-xYCbKFih.js +1 -0
  132. package/dist/esm/{index-BbOHefEf.js → index-D9HaikfQ.js} +36 -9
  133. package/dist/esm/index.js +1 -1
  134. package/dist/esm/kritzel-active-users_42.entry.js +333 -177
  135. package/dist/esm/kritzel-brush-style.entry.js +1 -1
  136. package/dist/esm/loader.js +3 -3
  137. package/dist/esm/stencil.js +4 -4
  138. package/dist/esm/{workspace.migrations-NhRgr2_H.js → workspace.migrations-OzSSw5kt.js} +244 -197
  139. package/dist/stencil/index.esm.js +1 -1
  140. package/dist/stencil/p-D9HaikfQ.js +2 -0
  141. package/dist/stencil/p-OzSSw5kt.js +1 -0
  142. package/dist/stencil/{p-98238bf9.entry.js → p-b0be4da1.entry.js} +1 -1
  143. package/dist/stencil/p-f7be06a8.entry.js +9 -0
  144. package/dist/stencil/stencil.esm.js +1 -1
  145. package/dist/types/classes/core/store.class.d.ts +23 -0
  146. package/dist/types/classes/objects/shape.class.d.ts +1 -0
  147. package/dist/types/classes/objects/text.class.d.ts +1 -0
  148. package/dist/types/classes/providers/hocuspocus-sync-provider.class.d.ts +1 -1
  149. package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +7 -5
  150. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +10 -4
  151. package/dist/types/components.d.ts +35 -13
  152. package/dist/types/constants/version.d.ts +1 -1
  153. package/dist/types/helpers/tool-config.helper.d.ts +1 -1
  154. package/dist/types/interfaces/engine-state.interface.d.ts +10 -10
  155. package/package.json +1 -1
  156. package/dist/components/p-Ban3OlgZ.js +0 -9
  157. package/dist/components/p-CGGiwvWZ.js +0 -1
  158. package/dist/components/p-CHY71o5B.js +0 -1
  159. package/dist/components/p-DXpYcAnT.js +0 -1
  160. package/dist/components/p-pGzF7PUB.js +0 -1
  161. package/dist/stencil/p-4a4b38e4.entry.js +0 -9
  162. package/dist/stencil/p-BbOHefEf.js +0 -2
  163. package/dist/stencil/p-NhRgr2_H.js +0 -1
@@ -44,6 +44,12 @@ export class KritzelShape extends KritzelBaseObject {
44
44
  get viewBox() {
45
45
  return `${this.x} ${this.y} ${this.width} ${this.height}`;
46
46
  }
47
+ get _editor() {
48
+ if (!this.editor) {
49
+ throw new Error('KritzelShape: editor is not initialized');
50
+ }
51
+ return this.editor;
52
+ }
47
53
  /**
48
54
  * Creates a new KritzelShape instance with optional configuration.
49
55
  * This constructor initializes the shape with default values that can be
@@ -99,7 +105,7 @@ export class KritzelShape extends KritzelBaseObject {
99
105
  const object = new KritzelShape();
100
106
  object._core = core;
101
107
  object.id = object.generateId();
102
- object.workspaceId = core.store.state.activeWorkspace.id;
108
+ object.workspaceId = core.store.activeWorkspace.id;
103
109
  object.userId = core.user?.id;
104
110
  object.x = config?.x ?? 0;
105
111
  object.y = config?.y ?? 0;
@@ -151,7 +157,7 @@ export class KritzelShape extends KritzelBaseObject {
151
157
  if (element === null || this.isInViewport() === false) {
152
158
  return;
153
159
  }
154
- if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
160
+ if (this.isMounted && this.elementRef === element && this._editor.dom.parentElement === element) {
155
161
  return;
156
162
  }
157
163
  this.elementRef = element;
@@ -167,7 +173,7 @@ export class KritzelShape extends KritzelBaseObject {
167
173
  * @returns void
168
174
  */
169
175
  mountTextEditor(element) {
170
- if (element === null) {
176
+ if (element === null || !this.editor) {
171
177
  return;
172
178
  }
173
179
  element.style.fontFamily = this.fontFamily;
@@ -198,12 +204,12 @@ export class KritzelShape extends KritzelBaseObject {
198
204
  }),
199
205
  editable: () => false,
200
206
  dispatchTransaction: transaction => {
201
- const newState = this.editor.state.apply(transaction);
202
- this.editor.updateState(newState);
207
+ const newState = this._editor.state.apply(transaction);
208
+ this._editor.updateState(newState);
203
209
  if (transaction.docChanged) {
204
210
  this.content = newState.doc.toJSON();
205
211
  if (!transaction.getMeta('fromRemote')) {
206
- this._core.store.state.objects.update(this, { temporary: true });
212
+ this._core.store.objects.update(this, { temporary: true });
207
213
  }
208
214
  }
209
215
  },
@@ -247,7 +253,7 @@ export class KritzelShape extends KritzelBaseObject {
247
253
  this.height = height;
248
254
  this.translateX = x;
249
255
  this.translateY = y;
250
- this._core.store.state.objects.update(this);
256
+ this._core.store.objects.update(this);
251
257
  }
252
258
  /**
253
259
  * Focuses the text editor and optionally positions the cursor at specific coordinates.
@@ -261,25 +267,23 @@ export class KritzelShape extends KritzelBaseObject {
261
267
  * @returns void
262
268
  */
263
269
  focus(coords) {
264
- if (this.editor) {
265
- const doc = this.editor.state.doc;
266
- if (coords?.x && coords?.y) {
267
- const pos = this.editor.posAtCoords({ left: coords.x, top: coords.y });
268
- if (pos) {
269
- this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, pos.pos)));
270
- this.editor.focus();
271
- if (KritzelDevicesHelper.isIOS()) {
272
- this.scrollIntoViewOnIOS();
273
- }
274
- return;
270
+ const doc = this._editor.state.doc;
271
+ if (coords?.x && coords?.y) {
272
+ const pos = this._editor.posAtCoords({ left: coords.x, top: coords.y });
273
+ if (pos) {
274
+ this._editor.dispatch(this._editor.state.tr.setSelection(TextSelection.create(doc, pos.pos)));
275
+ this._editor.focus();
276
+ if (KritzelDevicesHelper.isIOS()) {
277
+ this.scrollIntoViewOnIOS();
275
278
  }
279
+ return;
276
280
  }
277
- const end = Math.max(1, doc.content.size - 1);
278
- this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, end)));
279
- this.editor.focus();
280
- if (KritzelDevicesHelper.isIOS()) {
281
- this.scrollIntoViewOnIOS();
282
- }
281
+ }
282
+ const end = Math.max(1, doc.content.size - 1);
283
+ this._editor.dispatch(this._editor.state.tr.setSelection(TextSelection.create(doc, end)));
284
+ this._editor.focus();
285
+ if (KritzelDevicesHelper.isIOS()) {
286
+ this.scrollIntoViewOnIOS();
283
287
  }
284
288
  }
285
289
  /**
@@ -315,10 +319,12 @@ export class KritzelShape extends KritzelBaseObject {
315
319
  KritzelKeyboardHelper.disableInteractiveWidget();
316
320
  this.uneditedObject = this.clone();
317
321
  this._core.store.setState('activeTool', KritzelToolRegistry.getTool('shape'));
318
- this.editor.setProps({ editable: () => true });
322
+ this._editor.setProps({ editable: () => true });
319
323
  this.isEditing = true;
320
324
  this._core.rerender();
321
- this.focus({ x: event?.clientX, y: event?.clientY });
325
+ if (event?.clientX && event?.clientY) {
326
+ this.focus({ x: event.clientX, y: event.clientY });
327
+ }
322
328
  KritzelKeyboardHelper.enableInteractiveWidget();
323
329
  }
324
330
  /**
@@ -330,12 +336,12 @@ export class KritzelShape extends KritzelBaseObject {
330
336
  * @returns void
331
337
  */
332
338
  save() {
333
- this.content = this.editor.state.doc.toJSON();
334
- this.editor.setProps({ editable: () => false });
335
- this.editor.dom.blur();
339
+ this.content = this._editor.state.doc.toJSON();
340
+ this._editor.setProps({ editable: () => false });
341
+ this._editor.dom.blur();
336
342
  this.isEditing = false;
337
- this._core.store.state.objects.consolidateTemporaryItems();
338
- this._core.store.state.objects.update(this);
343
+ this._core.store.objects.consolidateTemporaryItems();
344
+ this._core.store.objects.update(this);
339
345
  this._core.engine.emitObjectsChange();
340
346
  }
341
347
  /**
@@ -28,6 +28,12 @@ export class KritzelText extends KritzelBaseObject {
28
28
  isEditing = false;
29
29
  editor = null;
30
30
  content = null;
31
+ get _editor() {
32
+ if (!this._editor) {
33
+ throw new Error('KritzelShape: editor is not initialized');
34
+ }
35
+ return this._editor;
36
+ }
31
37
  _schema = new Schema({
32
38
  nodes: addListNodes(schema.spec.nodes, 'paragraph block*', 'block'),
33
39
  marks: schema.spec.marks,
@@ -39,10 +45,10 @@ export class KritzelText extends KritzelBaseObject {
39
45
  * @returns `true` if the editor is empty or contains only whitespace, `false` otherwise.
40
46
  */
41
47
  get isEmpty() {
42
- if (!this.editor) {
48
+ if (!this._editor) {
43
49
  return true;
44
50
  }
45
- const doc = this.editor.state.doc;
51
+ const doc = this._editor.state.doc;
46
52
  if (doc.content.size === 0) {
47
53
  return true;
48
54
  }
@@ -115,10 +121,10 @@ export class KritzelText extends KritzelBaseObject {
115
121
  const object = new KritzelText();
116
122
  object._core = core;
117
123
  object.id = object.generateId();
118
- object.workspaceId = core.store.state.activeWorkspace.id;
124
+ object.workspaceId = core.store.activeWorkspace.id;
119
125
  object.userId = core.user?.id;
120
- object.fontSize = fontSize;
121
- object.fontFamily = fontFamily;
126
+ object.fontSize = fontSize || 8;
127
+ object.fontFamily = fontFamily || 'Arial';
122
128
  object.translateX = 0;
123
129
  object.translateY = 0;
124
130
  const coreScale = core.store.state.scale;
@@ -146,7 +152,7 @@ export class KritzelText extends KritzelBaseObject {
146
152
  element.style.fontFamily = this.fontFamily;
147
153
  element.style.fontSize = `${this.fontSize}pt`;
148
154
  element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
149
- if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
155
+ if (this.isMounted && this.elementRef === element && this._editor.dom.parentElement === element) {
150
156
  if (!this._core.store.state.isScaling && !this._core.store.state.isPanning) {
151
157
  requestAnimationFrame(() => this.adjustSizeOnInput());
152
158
  }
@@ -156,7 +162,7 @@ export class KritzelText extends KritzelBaseObject {
156
162
  this.elementRef.style.whiteSpace = 'pre-wrap';
157
163
  this.elementRef.style.wordWrap = 'break-word';
158
164
  this.elementRef.innerHTML = '';
159
- this.elementRef.appendChild(this.editor.dom);
165
+ this.elementRef.appendChild(this._editor.dom);
160
166
  this.isMounted = true;
161
167
  requestAnimationFrame(() => this.adjustSizeOnInput());
162
168
  }
@@ -174,13 +180,13 @@ export class KritzelText extends KritzelBaseObject {
174
180
  }),
175
181
  editable: () => false,
176
182
  dispatchTransaction: transaction => {
177
- const newState = this.editor.state.apply(transaction);
178
- this.editor.updateState(newState);
183
+ const newState = this._editor.state.apply(transaction);
184
+ this._editor.updateState(newState);
179
185
  if (transaction.docChanged) {
180
186
  this.content = newState.doc.toJSON();
181
187
  this.adjustSizeOnInput();
182
188
  if (!transaction.getMeta('fromRemote')) {
183
- this._core.store.state.objects.update(this, { temporary: true });
189
+ this._core.store.objects.update(this, { temporary: true });
184
190
  }
185
191
  }
186
192
  },
@@ -193,11 +199,11 @@ export class KritzelText extends KritzelBaseObject {
193
199
  */
194
200
  setContent(content) {
195
201
  this.content = content;
196
- if (this.editor && content) {
197
- const newDoc = this.editor.state.schema.nodeFromJSON(content);
198
- const tr = this.editor.state.tr.replaceWith(0, this.editor.state.doc.content.size, newDoc.content);
202
+ if (this._editor && content) {
203
+ const newDoc = this._editor.state.schema.nodeFromJSON(content);
204
+ const tr = this._editor.state.tr.replaceWith(0, this._editor.state.doc.content.size, newDoc.content);
199
205
  tr.setMeta('fromRemote', true);
200
- this.editor.dispatch(tr);
206
+ this._editor.dispatch(tr);
201
207
  }
202
208
  }
203
209
  /**
@@ -251,7 +257,7 @@ export class KritzelText extends KritzelBaseObject {
251
257
  this.height = originalHeight * this.scaleFactor;
252
258
  this.translateX = x;
253
259
  this.translateY = y;
254
- this._core.store.state.objects.update(this);
260
+ this._core.store.objects.update(this);
255
261
  }
256
262
  /**
257
263
  * Focuses the text editor and optionally positions the cursor at specific coordinates.
@@ -262,13 +268,13 @@ export class KritzelText extends KritzelBaseObject {
262
268
  * @param coords.y - Y coordinate for cursor placement.
263
269
  */
264
270
  focus(coords) {
265
- if (this.editor) {
266
- const doc = this.editor.state.doc;
271
+ if (this._editor) {
272
+ const doc = this._editor.state.doc;
267
273
  if (coords.x && coords.y && !this.isEmpty) {
268
- const pos = this.editor.posAtCoords({ left: coords.x, top: coords.y });
274
+ const pos = this._editor.posAtCoords({ left: coords.x, top: coords.y });
269
275
  if (pos) {
270
- this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, pos.pos)));
271
- this.editor.focus();
276
+ this._editor.dispatch(this._editor.state.tr.setSelection(TextSelection.create(doc, pos.pos)));
277
+ this._editor.focus();
272
278
  if (KritzelDevicesHelper.isIOS()) {
273
279
  this.scrollIntoViewOnIOS();
274
280
  }
@@ -276,8 +282,8 @@ export class KritzelText extends KritzelBaseObject {
276
282
  }
277
283
  }
278
284
  const end = Math.max(1, doc.content.size - 1);
279
- this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, end)));
280
- this.editor.focus();
285
+ this._editor.dispatch(this._editor.state.tr.setSelection(TextSelection.create(doc, end)));
286
+ this._editor.focus();
281
287
  if (KritzelDevicesHelper.isIOS()) {
282
288
  this.scrollIntoViewOnIOS();
283
289
  }
@@ -289,11 +295,11 @@ export class KritzelText extends KritzelBaseObject {
289
295
  */
290
296
  scrollIntoViewOnIOS() {
291
297
  setTimeout(() => {
292
- if (this.editor && this.editor.dom) {
293
- this.editor.dom.scrollIntoView({
298
+ if (this._editor && this._editor.dom) {
299
+ this._editor.dom.scrollIntoView({
294
300
  behavior: 'smooth',
295
301
  block: 'center',
296
- inline: 'nearest'
302
+ inline: 'nearest',
297
303
  });
298
304
  }
299
305
  }, 300);
@@ -308,11 +314,13 @@ export class KritzelText extends KritzelBaseObject {
308
314
  KritzelKeyboardHelper.disableInteractiveWidget();
309
315
  this.uneditedObject = this.clone();
310
316
  this._core.store.setState('activeTool', KritzelToolRegistry.getTool('text'));
311
- this.editor.setProps({ editable: () => true });
317
+ this._editor.setProps({ editable: () => true });
312
318
  this.isEditing = true;
313
319
  this._core.rerender();
314
320
  this.adjustSizeOnInput();
315
- this.focus({ x: event?.clientX, y: event?.clientY });
321
+ if (event?.clientX && event?.clientY) {
322
+ this.focus({ x: event?.clientX, y: event?.clientY });
323
+ }
316
324
  KritzelKeyboardHelper.enableInteractiveWidget();
317
325
  }
318
326
  /**
@@ -322,12 +330,12 @@ export class KritzelText extends KritzelBaseObject {
322
330
  */
323
331
  save() {
324
332
  requestAnimationFrame(() => this.adjustSizeOnInput());
325
- this.content = this.editor.state.doc.toJSON();
326
- this.editor.setProps({ editable: () => false });
327
- this.editor.dom.blur();
333
+ this.content = this._editor.state.doc.toJSON();
334
+ this._editor.setProps({ editable: () => false });
335
+ this._editor.dom.blur();
328
336
  this.isEditing = false;
329
- this._core.store.state.objects.consolidateTemporaryItems();
330
- this._core.store.state.objects.update(this);
337
+ this._core.store.objects.consolidateTemporaryItems();
338
+ this._core.store.objects.update(this);
331
339
  this._core.engine.emitObjectsChange();
332
340
  }
333
341
  /**
@@ -207,7 +207,9 @@ export class KritzelAppStateMap {
207
207
  };
208
208
  }
209
209
  const workspace = new KritzelWorkspace(serialized.id, serialized.name, viewport);
210
- workspace._core = this._core;
210
+ if (this._core) {
211
+ workspace._core = this._core;
212
+ }
211
213
  workspace.createdAt = new Date(serialized.createdAt);
212
214
  workspace.updatedAt = new Date(serialized.updatedAt);
213
215
  workspace.isPublic = serialized.isPublic ?? false;
@@ -222,14 +224,14 @@ export class KritzelAppStateMap {
222
224
  return;
223
225
  }
224
226
  this._ydoc.transact(() => {
225
- if (!this._metadataMap.get('type')) {
226
- this._metadataMap.set('type', type);
227
+ if (!this._metadataMap?.get('type')) {
228
+ this._metadataMap?.set('type', type);
227
229
  }
228
- if (this._metadataMap.get('isPublic') === undefined) {
229
- this._metadataMap.set('isPublic', false);
230
+ if (this._metadataMap?.get('isPublic') === undefined) {
231
+ this._metadataMap?.set('isPublic', false);
230
232
  }
231
- if (this._metadataMap.get('schemaVersion') === undefined) {
232
- this._metadataMap.set('schemaVersion', CURRENT_APP_STATE_SCHEMA_VERSION);
233
+ if (this._metadataMap?.get('schemaVersion') === undefined) {
234
+ this._metadataMap?.set('schemaVersion', CURRENT_APP_STATE_SCHEMA_VERSION);
233
235
  }
234
236
  }, 'metadata');
235
237
  }
@@ -248,7 +250,7 @@ export class KritzelAppStateMap {
248
250
  return;
249
251
  }
250
252
  this._ydoc.transact(() => {
251
- this._metadataMap.set('isPublic', isPublic);
253
+ this._metadataMap?.set('isPublic', isPublic);
252
254
  }, 'metadata');
253
255
  }
254
256
  /**
@@ -288,8 +290,8 @@ export class KritzelAppStateMap {
288
290
  */
289
291
  reset() {
290
292
  this.map.clear();
291
- this._ydoc.transact(() => {
292
- this._workspacesMap.clear();
293
+ this._ydoc?.transact(() => {
294
+ this._workspacesMap?.clear();
293
295
  }, 'local');
294
296
  }
295
297
  /**
@@ -305,8 +307,8 @@ export class KritzelAppStateMap {
305
307
  this.map.set(workspace.id, workspace);
306
308
  if (this._workspacesMap) {
307
309
  const serialized = workspace.serialize();
308
- this._ydoc.transact(() => {
309
- this._workspacesMap.set(workspace.id, serialized);
310
+ this._ydoc?.transact(() => {
311
+ this._workspacesMap?.set(workspace.id, serialized);
310
312
  }, 'local');
311
313
  }
312
314
  return true;
@@ -324,8 +326,8 @@ export class KritzelAppStateMap {
324
326
  this.map.set(workspace.id, workspace);
325
327
  if (this._workspacesMap) {
326
328
  const serialized = workspace.serialize();
327
- this._ydoc.transact(() => {
328
- this._workspacesMap.set(workspace.id, serialized);
329
+ this._ydoc?.transact(() => {
330
+ this._workspacesMap?.set(workspace.id, serialized);
329
331
  }, 'local');
330
332
  }
331
333
  return true;
@@ -343,8 +345,8 @@ export class KritzelAppStateMap {
343
345
  }
344
346
  this.map.delete(workspaceToRemove.id);
345
347
  if (this._workspacesMap) {
346
- this._ydoc.transact(() => {
347
- this._workspacesMap.delete(workspaceToRemove.id);
348
+ this._ydoc?.transact(() => {
349
+ this._workspacesMap?.delete(workspaceToRemove.id);
348
350
  }, 'local');
349
351
  }
350
352
  return true;
@@ -407,9 +407,9 @@ export class KritzelObjectMap {
407
407
  objectsToDelete.push(key);
408
408
  }
409
409
  else {
410
- const serialized = this._objectsMap.get(key);
410
+ const serialized = this._objectsMap?.get(key);
411
411
  if (serialized) {
412
- const object = this._reviver.revive(serialized);
412
+ const object = this._reviver?.revive(serialized);
413
413
  // Separate SelectionGroups to process them after regular objects
414
414
  if (object instanceof KritzelSelectionGroup) {
415
415
  selectionGroupsToUpdate.push(object);
@@ -516,17 +516,17 @@ export class KritzelObjectMap {
516
516
  return;
517
517
  }
518
518
  this._ydoc.transact(() => {
519
- if (!this._metadataMap.get('type')) {
520
- this._metadataMap.set('type', type);
519
+ if (!this._metadataMap?.get('type')) {
520
+ this._metadataMap?.set('type', type);
521
521
  }
522
- if (this._metadataMap.get('isPublic') === undefined) {
523
- this._metadataMap.set('isPublic', false);
522
+ if (this._metadataMap?.get('isPublic') === undefined) {
523
+ this._metadataMap?.set('isPublic', false);
524
524
  }
525
- if (this._metadataMap.get('schemaVersion') === undefined) {
526
- this._metadataMap.set('schemaVersion', CURRENT_WORKSPACE_SCHEMA_VERSION);
525
+ if (this._metadataMap?.get('schemaVersion') === undefined) {
526
+ this._metadataMap?.set('schemaVersion', CURRENT_WORKSPACE_SCHEMA_VERSION);
527
527
  }
528
- this._metadataMap.set('workspaceId', workspaceId);
529
- this._metadataMap.set('workspaceName', workspaceName);
528
+ this._metadataMap?.set('workspaceId', workspaceId);
529
+ this._metadataMap?.set('workspaceName', workspaceName);
530
530
  }, 'metadata');
531
531
  }
532
532
  /**
@@ -544,8 +544,8 @@ export class KritzelObjectMap {
544
544
  if (!this._metadataMap || !this._ydoc) {
545
545
  return;
546
546
  }
547
- this._ydoc.transact(() => {
548
- this._metadataMap.set('isPublic', isPublic);
547
+ this._ydoc?.transact(() => {
548
+ this._metadataMap?.set('isPublic', isPublic);
549
549
  }, 'metadata');
550
550
  }
551
551
  /**
@@ -569,8 +569,8 @@ export class KritzelObjectMap {
569
569
  if (!this._metadataMap || !this._ydoc) {
570
570
  return;
571
571
  }
572
- this._ydoc.transact(() => {
573
- this._metadataMap.set('workspaceName', name);
572
+ this._ydoc?.transact(() => {
573
+ this._metadataMap?.set('workspaceName', name);
574
574
  }, 'metadata');
575
575
  }
576
576
  /**
@@ -605,13 +605,16 @@ export class KritzelObjectMap {
605
605
  const localUserId = this._core?.user?.id;
606
606
  const staleSelectionGroupIds = [];
607
607
  this._objectsMap.forEach((serialized, key) => {
608
- const object = this._reviver.revive(serialized);
608
+ const object = this._reviver?.revive(serialized);
609
609
  // Remove remote selection groups on startup — they are transient UI state
610
610
  // that should not survive an app restart. The owning user's session is gone.
611
611
  if (object instanceof KritzelSelectionGroup && object.userId != null && object.userId !== localUserId) {
612
612
  staleSelectionGroupIds.push(key);
613
613
  return;
614
614
  }
615
+ if (!object) {
616
+ return;
617
+ }
615
618
  this.quadtree.insert(object);
616
619
  this._idMap.set(object.id, object);
617
620
  });
@@ -632,8 +635,8 @@ export class KritzelObjectMap {
632
635
  reset() {
633
636
  this.quadtree.reset();
634
637
  this._idMap.clear();
635
- this._ydoc.transact(() => {
636
- this._objectsMap.clear();
638
+ this._ydoc?.transact(() => {
639
+ this._objectsMap?.clear();
637
640
  }, 'local');
638
641
  }
639
642
  /**
@@ -652,8 +655,8 @@ export class KritzelObjectMap {
652
655
  this._idMap.set(object.id, object);
653
656
  if (this._objectsMap && this.isPersistable(object)) {
654
657
  const serialized = object.serialize();
655
- this._ydoc.transact(() => {
656
- this._objectsMap.set(object.id, serialized);
658
+ this._ydoc?.transact(() => {
659
+ this._objectsMap?.set(object.id, serialized);
657
660
  }, 'local');
658
661
  }
659
662
  return true;
@@ -682,8 +685,8 @@ export class KritzelObjectMap {
682
685
  if (this._objectsMap && this.isPersistable(object)) {
683
686
  const serialized = object.serialize();
684
687
  const origin = options.temporary ? 'temporary' : 'local';
685
- this._ydoc.transact(() => {
686
- this._objectsMap.set(object.id, serialized);
688
+ this._ydoc?.transact(() => {
689
+ this._objectsMap?.set(object.id, serialized);
687
690
  }, origin);
688
691
  }
689
692
  return true;
@@ -700,8 +703,8 @@ export class KritzelObjectMap {
700
703
  this.quadtree.remove(o => o.id === object.id);
701
704
  this._idMap.delete(object.id);
702
705
  if (this._objectsMap && this.isPersistable(object)) {
703
- this._ydoc.transact(() => {
704
- this._objectsMap.delete(object.id);
706
+ this._ydoc?.transact(() => {
707
+ this._objectsMap?.delete(object.id);
705
708
  }, 'local');
706
709
  }
707
710
  }
@@ -759,7 +762,7 @@ export class KritzelObjectMap {
759
762
  undo() {
760
763
  if (this._undoManager && this._undoManager.canUndo()) {
761
764
  this._undoManager.undo();
762
- this._core.engine.emitObjectsChange();
765
+ this._core?.engine.emitObjectsChange();
763
766
  }
764
767
  }
765
768
  /**
@@ -769,7 +772,7 @@ export class KritzelObjectMap {
769
772
  redo() {
770
773
  if (this._undoManager && this._undoManager.canRedo()) {
771
774
  this._undoManager.redo();
772
- this._core.engine.emitObjectsChange();
775
+ this._core?.engine.emitObjectsChange();
773
776
  }
774
777
  }
775
778
  /**
@@ -841,9 +844,9 @@ export class KritzelObjectMap {
841
844
  }
842
845
  // Now redo them all as a single 'local' transaction
843
846
  // This will consolidate them into one undo item
844
- this._ydoc.transact(() => {
847
+ this._ydoc?.transact(() => {
845
848
  for (let i = itemsToConsolidate - 1; i >= 0; i--) {
846
- if (this._undoManager.canRedo()) {
849
+ if (this._undoManager?.canRedo()) {
847
850
  this._undoManager.redo();
848
851
  }
849
852
  }
@@ -54,8 +54,8 @@ export class KritzelBrushTool extends KritzelBaseTool {
54
54
  });
55
55
  path.isCompleted = false;
56
56
  this._currentPathId = path.id;
57
- this._core.store.state.objects.insert(path);
58
- this._core.store.state.objects?.setActiveDrawingObject(path.id);
57
+ this._core.store.objects.insert(path);
58
+ this._core.store.objects?.setActiveDrawingObject(path.id);
59
59
  }
60
60
  }
61
61
  if (event.pointerType === 'touch' || event.pointerType === 'pen') {
@@ -78,8 +78,8 @@ export class KritzelBrushTool extends KritzelBaseTool {
78
78
  });
79
79
  path.isCompleted = false;
80
80
  this._currentPathId = path.id;
81
- this._core.store.state.objects.insert(path);
82
- this._core.store.state.objects?.setActiveDrawingObject(path.id);
81
+ this._core.store.objects.insert(path);
82
+ this._core.store.objects?.setActiveDrawingObject(path.id);
83
83
  }
84
84
  }
85
85
  }
@@ -95,7 +95,7 @@ export class KritzelBrushTool extends KritzelBaseTool {
95
95
  }
96
96
  if (event.pointerType === 'mouse') {
97
97
  if (this._core.store.state.isDrawing && this._currentPathId) {
98
- const currentPath = this._core.store.state.objects.findById(this._currentPathId);
98
+ const currentPath = this._core.store.objects.findById(this._currentPathId);
99
99
  if (currentPath) {
100
100
  const viewportScale = this._core.store.state.scale;
101
101
  const lockScale = this._core.store.state.lockDrawingScale;
@@ -115,7 +115,7 @@ export class KritzelBrushTool extends KritzelBaseTool {
115
115
  updatedPath.workspaceId = currentPath.workspaceId;
116
116
  updatedPath.zIndex = currentPath.zIndex;
117
117
  updatedPath.isCompleted = false;
118
- this._core.store.state.objects.update(updatedPath);
118
+ this._core.store.objects.update(updatedPath);
119
119
  }
120
120
  }
121
121
  }
@@ -123,7 +123,7 @@ export class KritzelBrushTool extends KritzelBaseTool {
123
123
  const activePointers = Array.from(this._core.store.state.pointers.values());
124
124
  if (activePointers.length === 1) {
125
125
  if (this._currentPathId) {
126
- const currentPath = this._core.store.state.objects.findById(this._currentPathId);
126
+ const currentPath = this._core.store.objects.findById(this._currentPathId);
127
127
  if (currentPath) {
128
128
  const viewportScale = this._core.store.state.scale;
129
129
  const lockScale = this._core.store.state.lockDrawingScale;
@@ -143,7 +143,7 @@ export class KritzelBrushTool extends KritzelBaseTool {
143
143
  updatedPath.workspaceId = currentPath.workspaceId;
144
144
  updatedPath.zIndex = currentPath.zIndex;
145
145
  updatedPath.isCompleted = false;
146
- this._core.store.state.objects.update(updatedPath);
146
+ this._core.store.objects.update(updatedPath);
147
147
  }
148
148
  }
149
149
  }
@@ -163,14 +163,14 @@ export class KritzelBrushTool extends KritzelBaseTool {
163
163
  if (this._core.store.state.isDrawing) {
164
164
  this._core.store.state.isDrawing = false;
165
165
  if (this._currentPathId) {
166
- const currentPath = this._core.store.state.objects.findById(this._currentPathId);
166
+ const currentPath = this._core.store.objects.findById(this._currentPathId);
167
167
  if (currentPath) {
168
168
  currentPath.isCompleted = true;
169
- this._core.store.state.objects.update(currentPath);
169
+ this._core.store.objects.update(currentPath);
170
170
  this._core.engine.emitObjectsChange();
171
171
  this._core.engine.emitObjectsAdded([currentPath]);
172
172
  }
173
- this._core.store.state.objects?.setActiveDrawingObject(null);
173
+ this._core.store.objects?.setActiveDrawingObject(null);
174
174
  this._currentPathId = null;
175
175
  }
176
176
  }
@@ -179,14 +179,14 @@ export class KritzelBrushTool extends KritzelBaseTool {
179
179
  if (this._core.store.state.isDrawing) {
180
180
  this._core.store.state.isDrawing = false;
181
181
  if (this._currentPathId) {
182
- const currentPath = this._core.store.state.objects.findById(this._currentPathId);
182
+ const currentPath = this._core.store.objects.findById(this._currentPathId);
183
183
  if (currentPath) {
184
184
  currentPath.isCompleted = true;
185
- this._core.store.state.objects.update(currentPath);
185
+ this._core.store.objects.update(currentPath);
186
186
  this._core.engine.emitObjectsChange();
187
187
  this._core.engine.emitObjectsAdded([currentPath]);
188
188
  }
189
- this._core.store.state.objects?.setActiveDrawingObject(null);
189
+ this._core.store.objects?.setActiveDrawingObject(null);
190
190
  this._currentPathId = null;
191
191
  }
192
192
  }
@@ -37,7 +37,7 @@ export class KritzelImageTool extends KritzelBaseTool {
37
37
  if (this._core.store.isDisabled) {
38
38
  return;
39
39
  }
40
- this.fileInput.click();
40
+ this.fileInput?.click();
41
41
  }
42
42
  /**
43
43
  * Creates and configures the hidden file input element.