kritzel-stencil 0.1.76 → 0.1.78

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 (128) hide show
  1. package/dist/cjs/{index-Dc7LOVhs.js → index-BRZ6e6oa.js} +1 -1
  2. package/dist/cjs/index.cjs.js +2 -330
  3. package/dist/cjs/kritzel-active-users_42.cjs.entry.js +88 -50
  4. package/dist/cjs/kritzel-brush-style.cjs.entry.js +1 -1
  5. package/dist/cjs/loader.cjs.js +1 -1
  6. package/dist/cjs/stencil.cjs.js +2 -2
  7. package/dist/cjs/{workspace.migrations-DkmVO6dE.js → workspace.migrations-sUPrO23c.js} +378 -13
  8. package/dist/collection/classes/objects/selection-group.class.js +2 -0
  9. package/dist/collection/collection-manifest.json +1 -1
  10. package/dist/collection/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.css +6 -1
  11. package/dist/collection/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.js +5 -2
  12. package/dist/collection/components/core/kritzel-editor/kritzel-editor.css +2 -0
  13. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +16 -6
  14. package/dist/collection/components/core/kritzel-engine/kritzel-engine.css +21 -0
  15. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +24 -10
  16. package/dist/collection/components/ui/kritzel-login-dialog/kritzel-login-dialog.css +3 -0
  17. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.css +1 -0
  18. package/dist/collection/configs/default-engine-config.js +1 -0
  19. package/dist/collection/constants/version.js +1 -1
  20. package/dist/components/index.js +1 -1
  21. package/dist/components/kritzel-active-users.js +1 -1
  22. package/dist/components/kritzel-avatar.js +1 -1
  23. package/dist/components/kritzel-awareness-cursors.js +1 -1
  24. package/dist/components/kritzel-back-to-content.js +1 -1
  25. package/dist/components/kritzel-brush-style.js +1 -1
  26. package/dist/components/kritzel-button.js +1 -1
  27. package/dist/components/kritzel-color-palette.js +1 -1
  28. package/dist/components/kritzel-color.js +1 -1
  29. package/dist/components/kritzel-context-menu.js +1 -1
  30. package/dist/components/kritzel-controls.js +1 -1
  31. package/dist/components/kritzel-current-user-dialog.js +1 -1
  32. package/dist/components/kritzel-current-user.js +1 -1
  33. package/dist/components/kritzel-cursor-trail.js +1 -1
  34. package/dist/components/kritzel-dialog.js +1 -1
  35. package/dist/components/kritzel-dropdown.js +1 -1
  36. package/dist/components/kritzel-editor.js +1 -1
  37. package/dist/components/kritzel-engine.js +1 -1
  38. package/dist/components/kritzel-export.js +1 -1
  39. package/dist/components/kritzel-font-family.js +1 -1
  40. package/dist/components/kritzel-font-size.js +1 -1
  41. package/dist/components/kritzel-font.js +1 -1
  42. package/dist/components/kritzel-icon.js +1 -1
  43. package/dist/components/kritzel-input.js +1 -1
  44. package/dist/components/kritzel-line-endings.js +1 -1
  45. package/dist/components/kritzel-login-dialog.js +1 -1
  46. package/dist/components/kritzel-master-detail.js +1 -1
  47. package/dist/components/kritzel-menu-item.js +1 -1
  48. package/dist/components/kritzel-menu.js +1 -1
  49. package/dist/components/kritzel-more-menu.js +1 -1
  50. package/dist/components/kritzel-numeric-input.js +1 -1
  51. package/dist/components/kritzel-opacity-slider.js +1 -1
  52. package/dist/components/kritzel-pill-tabs.js +1 -1
  53. package/dist/components/kritzel-portal.js +1 -1
  54. package/dist/components/kritzel-settings.js +1 -1
  55. package/dist/components/kritzel-shape-fill.js +1 -1
  56. package/dist/components/kritzel-share-dialog.js +1 -1
  57. package/dist/components/kritzel-slide-toggle.js +1 -1
  58. package/dist/components/kritzel-split-button.js +1 -1
  59. package/dist/components/kritzel-stroke-size.js +1 -1
  60. package/dist/components/kritzel-tool-config.js +1 -1
  61. package/dist/components/kritzel-tooltip.js +1 -1
  62. package/dist/components/kritzel-utility-panel.js +1 -1
  63. package/dist/components/kritzel-workspace-manager.js +1 -1
  64. package/dist/components/{p-Dt-J69xt.js → p-53di1Zko.js} +1 -1
  65. package/dist/components/{p-DS0xx1eT.js → p-6NFl6EB2.js} +1 -1
  66. package/dist/components/{p-DSzQ6H2j.js → p-76W5pG2O.js} +1 -1
  67. package/dist/components/{p-DRbG92F9.js → p-BLsH_Oi0.js} +1 -1
  68. package/dist/components/p-Ban3OlgZ.js +9 -0
  69. package/dist/components/{p-CUkKKbnu.js → p-BrZ_gL8Q.js} +1 -1
  70. package/dist/components/{p-kj9wbLY8.js → p-BuI6Gkzg.js} +1 -1
  71. package/dist/components/{p-BeFUNGEI.js → p-BueaqfA2.js} +1 -1
  72. package/dist/components/{p-BiByyU2C.js → p-C2l9mZ1P.js} +1 -1
  73. package/dist/components/{p-CsR4owzk.js → p-C4fKLlrd.js} +1 -1
  74. package/dist/components/{p-BA0ayKqO.js → p-CBslLN3-.js} +1 -1
  75. package/dist/components/p-CHY71o5B.js +1 -0
  76. package/dist/components/{p-KQzWumjB.js → p-CI9Nbh-x.js} +1 -1
  77. package/dist/components/{p-CsoDfhD5.js → p-CN8IxBlU.js} +1 -1
  78. package/dist/components/{p-2OYw6GJ7.js → p-CWMFGEe0.js} +1 -1
  79. package/dist/components/{p-Dj_Qjga5.js → p-CYh7yV-K.js} +1 -1
  80. package/dist/components/{p-xM-_OeRO.js → p-Ck1dhpUQ.js} +1 -1
  81. package/dist/components/{p-b4gyXoju.js → p-Cns7qSKS.js} +1 -1
  82. package/dist/components/{p-C69Stayh.js → p-D14QNK3X.js} +1 -1
  83. package/dist/components/{p-iRL0wQHQ.js → p-D3pNw-SV.js} +1 -1
  84. package/dist/components/{p-BEJQ2kP7.js → p-D5IhryUR.js} +1 -1
  85. package/dist/components/{p-CZhyKp-f.js → p-D7yzmu1l.js} +1 -1
  86. package/dist/components/{p-HLbqRJGs.js → p-DDKjsXCe.js} +1 -1
  87. package/dist/components/{p-TyR-YTXm.js → p-DV7Z_qfa.js} +1 -1
  88. package/dist/components/{p-ByR0VXeU.js → p-DWsCbu01.js} +1 -1
  89. package/dist/components/{p-31FVoNWR.js → p-DaGZEV0R.js} +1 -1
  90. package/dist/components/{p-Da46jw3N.js → p-DkWWzVg8.js} +1 -1
  91. package/dist/components/{p-D1O7DxL4.js → p-Dr3-pKVg.js} +1 -1
  92. package/dist/components/{p-JdNoaqqb.js → p-Dte67BWd.js} +1 -1
  93. package/dist/components/{p-CHmi1QWx.js → p-DxzDda_J.js} +1 -1
  94. package/dist/components/{p-CAIGuV2J.js → p-KJ4dHzrS.js} +1 -1
  95. package/dist/components/{p-BiouZo1q.js → p-Lhyh6KeB.js} +1 -1
  96. package/dist/components/{p-CFhp1W9F.js → p-Md9Y-b3d.js} +1 -1
  97. package/dist/components/{p-C1uR_ZNW.js → p-ZC5YELQJ.js} +1 -1
  98. package/dist/components/{p-C7SBI_0T.js → p-ZQ2bKafG.js} +1 -1
  99. package/dist/components/{p-0kShCfeb.js → p-_QEHfsIk.js} +1 -1
  100. package/dist/components/{p-DXjuuVq9.js → p-gtQlsorg.js} +1 -1
  101. package/dist/components/{p-GYI7sDxr.js → p-l_YGO7RB.js} +1 -1
  102. package/dist/components/{p-DvIEvoZu.js → p-m1nVDC3G.js} +1 -1
  103. package/dist/components/{p-7o2FWtFx.js → p-pCC6t6BH.js} +1 -1
  104. package/dist/components/p-pGzF7PUB.js +1 -0
  105. package/dist/esm/{index-MV-81ybv.js → index-BbOHefEf.js} +1 -1
  106. package/dist/esm/index.js +2 -331
  107. package/dist/esm/kritzel-active-users_42.entry.js +88 -50
  108. package/dist/esm/kritzel-brush-style.entry.js +1 -1
  109. package/dist/esm/loader.js +2 -2
  110. package/dist/esm/stencil.js +3 -3
  111. package/dist/esm/{workspace.migrations-D48_Bqvh.js → workspace.migrations-NhRgr2_H.js} +378 -12
  112. package/dist/stencil/index.esm.js +1 -1
  113. package/dist/stencil/p-4a4b38e4.entry.js +9 -0
  114. package/dist/stencil/{p-fc21e29c.entry.js → p-98238bf9.entry.js} +1 -1
  115. package/dist/stencil/p-NhRgr2_H.js +1 -0
  116. package/dist/stencil/stencil.esm.js +1 -1
  117. package/dist/types/classes/objects/selection-group.class.d.ts +1 -0
  118. package/dist/types/components.d.ts +4 -2
  119. package/dist/types/constants/version.d.ts +1 -1
  120. package/dist/types/interfaces/engine-state.interface.d.ts +1 -0
  121. package/package.json +2 -2
  122. package/dist/components/p-CJ2eHeoV.js +0 -1
  123. package/dist/components/p-jdYmu4SA.js +0 -9
  124. package/dist/components/p-xNwOWoiT.js +0 -1
  125. package/dist/stencil/p-775a7246.entry.js +0 -9
  126. package/dist/stencil/p-D48_Bqvh.js +0 -1
  127. /package/dist/components/{p-pebXO4LU.js → p-CGGiwvWZ.js} +0 -0
  128. /package/dist/stencil/{p-MV-81ybv.js → p-BbOHefEf.js} +0 -0
@@ -5054,7 +5054,8 @@ class ReplaceStep extends Step {
5054
5054
  return new ReplaceStep(this.from, this.from + this.slice.size, doc.slice(this.from, this.to));
5055
5055
  }
5056
5056
  map(mapping) {
5057
- let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
5057
+ let to = mapping.mapResult(this.to, -1);
5058
+ let from = this.from == this.to && ReplaceStep.MAP_BIAS < 0 ? to : mapping.mapResult(this.from, 1);
5058
5059
  if (from.deletedAcross && to.deletedAcross)
5059
5060
  return null;
5060
5061
  return new ReplaceStep(from.pos, Math.max(from.pos, to.pos), this.slice, this.structure);
@@ -5093,6 +5094,15 @@ class ReplaceStep extends Step {
5093
5094
  return new ReplaceStep(json.from, json.to, Slice.fromJSON(schema, json.slice), !!json.structure);
5094
5095
  }
5095
5096
  }
5097
+ /**
5098
+ By default, for backwards compatibility, an inserting step
5099
+ mapped over an insertion at that same position fill move after
5100
+ the inserted content. In a collaborative editing situation, that
5101
+ can make redone insertions appear in unexpected places. You can
5102
+ set this to -1 to make such mapping keep the step before the
5103
+ insertion instead.
5104
+ */
5105
+ ReplaceStep.MAP_BIAS = 1;
5096
5106
  Step.jsonID("replace", ReplaceStep);
5097
5107
  /**
5098
5108
  Replace a part of the document with a slice of content, but
@@ -6010,6 +6020,26 @@ function replaceRangeWith(tr, from, to, node) {
6010
6020
  }
6011
6021
  function deleteRange(tr, from, to) {
6012
6022
  let $from = tr.doc.resolve(from), $to = tr.doc.resolve(to);
6023
+ // When the deleted range spans from the start of one textblock to
6024
+ // the start of another one, move out of the start of both blocks.
6025
+ if ($from.parent.isTextblock && $to.parent.isTextblock && $from.start() != $to.start() &&
6026
+ $from.parentOffset == 0 && $to.parentOffset == 0) {
6027
+ let shared = $from.sharedDepth(to), isolated = false;
6028
+ for (let d = $from.depth; d > shared; d--)
6029
+ if ($from.node(d).type.spec.isolating)
6030
+ isolated = true;
6031
+ for (let d = $to.depth; d > shared; d--)
6032
+ if ($to.node(d).type.spec.isolating)
6033
+ isolated = true;
6034
+ if (!isolated) {
6035
+ for (let d = $from.depth; d > 0 && from == $from.start(d); d--)
6036
+ from = $from.before(d);
6037
+ for (let d = $to.depth; d > 0 && to == $to.start(d); d--)
6038
+ to = $to.before(d);
6039
+ $from = tr.doc.resolve(from);
6040
+ $to = tr.doc.resolve(to);
6041
+ }
6042
+ }
6013
6043
  let covered = coveredDepths($from, $to);
6014
6044
  for (let i = 0; i < covered.length; i++) {
6015
6045
  let depth = covered[i], last = i == covered.length - 1;
@@ -10778,8 +10808,8 @@ class MouseDown {
10778
10808
  this.target = targetDesc && targetDesc.nodeDOM.nodeType == 1 ? targetDesc.nodeDOM : null;
10779
10809
  let { selection } = view.state;
10780
10810
  if (event.button == 0 &&
10781
- targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
10782
- selection instanceof NodeSelection && selection.from <= targetPos && selection.to > targetPos)
10811
+ (targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
10812
+ selection instanceof NodeSelection && selection.from <= targetPos && selection.to > targetPos))
10783
10813
  this.mightDrag = {
10784
10814
  node: targetNode,
10785
10815
  pos: targetPos,
@@ -11128,8 +11158,9 @@ class Dragging {
11128
11158
  }
11129
11159
  const dragCopyModifier = mac$3 ? "altKey" : "ctrlKey";
11130
11160
  function dragMoves(view, event) {
11131
- let moves = view.someProp("dragCopies", test => !test(event));
11132
- return moves != null ? moves : !event[dragCopyModifier];
11161
+ let copy;
11162
+ view.someProp("dragCopies", test => { copy = copy || test(event); });
11163
+ return copy != null ? !copy : !event[dragCopyModifier];
11133
11164
  }
11134
11165
  handlers.dragstart = (view, _event) => {
11135
11166
  let event = _event;
@@ -11156,7 +11187,7 @@ handlers.dragstart = (view, _event) => {
11156
11187
  if (!event.dataTransfer.files.length || !chrome || chrome_version > 120)
11157
11188
  event.dataTransfer.clearData();
11158
11189
  event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
11159
- // See https://github.com/ProseMirror/prosemirror/issues/1156
11190
+ // See https://code.haverbeke.berlin/prosemirror/prosemirror/issues/1156
11160
11191
  event.dataTransfer.effectAllowed = "copyMove";
11161
11192
  if (!brokenClipboardAPI)
11162
11193
  event.dataTransfer.setData("text/plain", text);
@@ -12155,8 +12186,13 @@ class DOMObserver {
12155
12186
  for (let node of added)
12156
12187
  if (node.nodeName == "BR" && node.parentNode) {
12157
12188
  let after = node.nextSibling;
12158
- if (after && after.nodeType == 1 && after.contentEditable == "false")
12159
- node.parentNode.removeChild(node);
12189
+ while (after && after.nodeType == 1) {
12190
+ if (after.contentEditable == "false") {
12191
+ node.parentNode.removeChild(node);
12192
+ break;
12193
+ }
12194
+ after = after.firstChild;
12195
+ }
12160
12196
  }
12161
12197
  }
12162
12198
  else if (gecko && added.length) {
@@ -12776,7 +12812,7 @@ class EditorView {
12776
12812
  this.pluginViews = [];
12777
12813
  /**
12778
12814
  Holds `true` when a hack node is needed in Firefox to prevent the
12779
- [space is eaten issue](https://github.com/ProseMirror/prosemirror/issues/651)
12815
+ [space is eaten issue](https://code.haverbeke.berlin/prosemirror/prosemirror/issues/651)
12780
12816
  @internal
12781
12817
  */
12782
12818
  this.requiresGeckoHackNode = false;
@@ -12994,12 +13030,12 @@ class EditorView {
12994
13030
  }
12995
13031
  updateDraggedNode(dragging, prev) {
12996
13032
  let sel = dragging.node, found = -1;
12997
- if (this.state.doc.nodeAt(sel.from) == sel.node) {
13033
+ if (sel.from < this.state.doc.content.size && this.state.doc.nodeAt(sel.from) == sel.node) {
12998
13034
  found = sel.from;
12999
13035
  }
13000
13036
  else {
13001
13037
  let movedPos = sel.from + (this.state.doc.content.size - prev.doc.content.size);
13002
- let moved = movedPos > 0 && this.state.doc.nodeAt(movedPos);
13038
+ let moved = movedPos > 0 && movedPos < this.state.doc.content.size && this.state.doc.nodeAt(movedPos);
13003
13039
  if (moved == sel.node)
13004
13040
  found = movedPos;
13005
13041
  }
@@ -18492,6 +18528,7 @@ class KritzelSelectionGroup extends KritzelBaseObject {
18492
18528
  snapshotHeight = 0;
18493
18529
  snapshotTranslateX = 0;
18494
18530
  snapshotTranslateY = 0;
18531
+ clientId;
18495
18532
  minX;
18496
18533
  maxX;
18497
18534
  minY;
@@ -18564,6 +18601,7 @@ class KritzelSelectionGroup extends KritzelBaseObject {
18564
18601
  object.id = object.generateId();
18565
18602
  object.workspaceId = core.store.state.activeWorkspace.id;
18566
18603
  object.userId = core.user?.id;
18604
+ object.clientId = core.store.state.objects?.localClientId ?? undefined;
18567
18605
  object.scale = core.store.state.scale;
18568
18606
  object.zIndex = 99999;
18569
18607
  // Initialize styling with theme-aware defaults
@@ -25224,6 +25262,334 @@ class HocuspocusProvider extends EventEmitter {
25224
25262
  }
25225
25263
  }
25226
25264
 
25265
+ /**
25266
+ * Hocuspocus sync provider for real-time collaboration
25267
+ * Supports multiplexing - multiple documents can share the same WebSocket connection
25268
+ */
25269
+ class HocuspocusSyncProvider {
25270
+ type = 'network';
25271
+ provider;
25272
+ isConnected = false;
25273
+ isSynced = false;
25274
+ usesSharedSocket = false;
25275
+ isDestroyed = false;
25276
+ connectTimeout = null;
25277
+ pendingConnectReject = null;
25278
+ connectionTimeoutMs;
25279
+ _connectionStatus = 'disconnected';
25280
+ visibilityHandler = null;
25281
+ onlineHandler = null;
25282
+ get awareness() {
25283
+ return this.provider.awareness;
25284
+ }
25285
+ get connectionStatus() {
25286
+ return this._connectionStatus;
25287
+ }
25288
+ // Static shared WebSocket instance for multiplexing
25289
+ static sharedWebSocketProvider = null;
25290
+ constructor(docName, doc, options) {
25291
+ const name = options?.name || docName;
25292
+ const url = options?.url || 'ws://localhost:1234';
25293
+ this.connectionTimeoutMs = options?.connectionTimeout ?? 10000;
25294
+ // Use provided websocketProvider or the static shared one
25295
+ const websocketProvider = options?.websocketProvider || HocuspocusSyncProvider.sharedWebSocketProvider;
25296
+ // Build reconnect config from options
25297
+ const reconnectConfig = {};
25298
+ if (options?.delay !== undefined)
25299
+ reconnectConfig.delay = options.delay;
25300
+ if (options?.factor !== undefined)
25301
+ reconnectConfig.factor = options.factor;
25302
+ if (options?.maxAttempts !== undefined)
25303
+ reconnectConfig.maxAttempts = options.maxAttempts;
25304
+ if (options?.minDelay !== undefined)
25305
+ reconnectConfig.minDelay = options.minDelay;
25306
+ if (options?.maxDelay !== undefined)
25307
+ reconnectConfig.maxDelay = options.maxDelay;
25308
+ const onConnect = () => {
25309
+ if (this.isDestroyed) {
25310
+ return;
25311
+ }
25312
+ this.isConnected = true;
25313
+ this._connectionStatus = 'connected';
25314
+ if (!options?.quiet) {
25315
+ console.info(`Hocuspocus connected: ${name}`);
25316
+ }
25317
+ if (options?.onConnect) {
25318
+ options.onConnect();
25319
+ }
25320
+ };
25321
+ const onDisconnect = () => {
25322
+ if (this.isDestroyed) {
25323
+ return;
25324
+ }
25325
+ this.isConnected = false;
25326
+ this.isSynced = false;
25327
+ this._connectionStatus = 'disconnected';
25328
+ if (!options?.quiet) {
25329
+ console.info(`Hocuspocus disconnected: ${name}`);
25330
+ }
25331
+ if (options?.onDisconnect) {
25332
+ options.onDisconnect();
25333
+ }
25334
+ };
25335
+ const onSynced = () => {
25336
+ if (this.isDestroyed) {
25337
+ return;
25338
+ }
25339
+ this.isSynced = true;
25340
+ this._connectionStatus = 'synced';
25341
+ if (!options?.quiet) {
25342
+ console.info(`Hocuspocus synced: ${name}`);
25343
+ }
25344
+ if (options?.onSynced) {
25345
+ options.onSynced();
25346
+ }
25347
+ };
25348
+ const onStatus = (data) => {
25349
+ if (this.isDestroyed) {
25350
+ return;
25351
+ }
25352
+ if (data.status === 'connecting') {
25353
+ this._connectionStatus = 'connecting';
25354
+ }
25355
+ if (options?.onStatus) {
25356
+ options.onStatus(data);
25357
+ }
25358
+ };
25359
+ if (websocketProvider) {
25360
+ // Multiplexing mode - use shared WebSocket connection
25361
+ this.usesSharedSocket = true;
25362
+ const config = {
25363
+ websocketProvider,
25364
+ name,
25365
+ document: doc,
25366
+ token: options?.token || null,
25367
+ onStatus,
25368
+ onConnect,
25369
+ onDisconnect,
25370
+ onSynced,
25371
+ ...reconnectConfig,
25372
+ };
25373
+ // Add optional settings
25374
+ if (options?.forceSyncInterval !== undefined) {
25375
+ config.forceSyncInterval = options.forceSyncInterval;
25376
+ }
25377
+ if (options?.onAuthenticationFailed) {
25378
+ config.onAuthenticationFailed = options.onAuthenticationFailed;
25379
+ }
25380
+ this.provider = new HocuspocusProvider(config);
25381
+ // Must call attach() explicitly when using shared socket
25382
+ this.provider.attach();
25383
+ if (!options?.quiet) {
25384
+ console.info(`Hocuspocus Provider initialized (multiplexed): ${name}`);
25385
+ }
25386
+ }
25387
+ else {
25388
+ // Standalone mode - create own WebSocket connection
25389
+ this.usesSharedSocket = false;
25390
+ const config = {
25391
+ url,
25392
+ name,
25393
+ document: doc,
25394
+ token: options?.token || null,
25395
+ autoConnect: false,
25396
+ onStatus,
25397
+ onConnect,
25398
+ onDisconnect,
25399
+ onSynced,
25400
+ ...reconnectConfig,
25401
+ };
25402
+ // Add optional settings
25403
+ if (options?.forceSyncInterval !== undefined) {
25404
+ config.forceSyncInterval = options.forceSyncInterval;
25405
+ }
25406
+ if (options?.onAuthenticationFailed) {
25407
+ config.onAuthenticationFailed = options.onAuthenticationFailed;
25408
+ }
25409
+ if (options?.WebSocketPolyfill) {
25410
+ config.WebSocketPolyfill = options.WebSocketPolyfill;
25411
+ }
25412
+ this.provider = new HocuspocusProvider(config);
25413
+ if (!options?.quiet) {
25414
+ console.info(`Hocuspocus Provider initialized: ${url}/${name}`);
25415
+ }
25416
+ }
25417
+ this.setupBrowserEventListeners();
25418
+ }
25419
+ setupBrowserEventListeners() {
25420
+ if (typeof document !== 'undefined') {
25421
+ this.visibilityHandler = () => {
25422
+ if (document.visibilityState === 'visible' && !this.isConnected && !this.isDestroyed) {
25423
+ this.provider.connect();
25424
+ }
25425
+ };
25426
+ document.addEventListener('visibilitychange', this.visibilityHandler);
25427
+ }
25428
+ if (typeof window !== 'undefined') {
25429
+ this.onlineHandler = () => {
25430
+ if (!this.isConnected && !this.isDestroyed) {
25431
+ this.provider.connect();
25432
+ }
25433
+ };
25434
+ window.addEventListener('online', this.onlineHandler);
25435
+ }
25436
+ }
25437
+ removeBrowserEventListeners() {
25438
+ if (this.visibilityHandler && typeof document !== 'undefined') {
25439
+ document.removeEventListener('visibilitychange', this.visibilityHandler);
25440
+ this.visibilityHandler = null;
25441
+ }
25442
+ if (this.onlineHandler && typeof window !== 'undefined') {
25443
+ window.removeEventListener('online', this.onlineHandler);
25444
+ this.onlineHandler = null;
25445
+ }
25446
+ }
25447
+ /**
25448
+ * Create a shared WebSocket connection for multiplexing
25449
+ * Call this once to create a shared connection that multiple providers can use
25450
+ */
25451
+ static createSharedWebSocket(options) {
25452
+ if (HocuspocusSyncProvider.sharedWebSocketProvider) {
25453
+ console.warn('Shared WebSocket already exists. Returning existing instance.');
25454
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
25455
+ }
25456
+ const config = {
25457
+ url: options.url,
25458
+ };
25459
+ if (options.WebSocketPolyfill) {
25460
+ config.WebSocketPolyfill = options.WebSocketPolyfill;
25461
+ }
25462
+ if (options.onConnect) {
25463
+ config.onConnect = options.onConnect;
25464
+ }
25465
+ if (options.onDisconnect) {
25466
+ config.onDisconnect = options.onDisconnect;
25467
+ }
25468
+ if (options.onStatus) {
25469
+ config.onStatus = options.onStatus;
25470
+ }
25471
+ HocuspocusSyncProvider.sharedWebSocketProvider = new HocuspocusProviderWebsocket(config);
25472
+ console.info(`Shared Hocuspocus WebSocket created: ${options.url}`);
25473
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
25474
+ }
25475
+ /**
25476
+ * Destroy the shared WebSocket connection
25477
+ * Call this when you're done with all multiplexed providers
25478
+ */
25479
+ static destroySharedWebSocket() {
25480
+ if (HocuspocusSyncProvider.sharedWebSocketProvider) {
25481
+ HocuspocusSyncProvider.sharedWebSocketProvider.destroy();
25482
+ HocuspocusSyncProvider.sharedWebSocketProvider = null;
25483
+ console.info('Shared Hocuspocus WebSocket destroyed');
25484
+ }
25485
+ }
25486
+ /**
25487
+ * Get the shared WebSocket provider instance (if it exists)
25488
+ */
25489
+ static getSharedWebSocket() {
25490
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
25491
+ }
25492
+ /**
25493
+ * Static factory method for creating HocuspocusSyncProvider with configuration options
25494
+ * Returns a ProviderFactory that can be used in sync configuration
25495
+ */
25496
+ static with(options) {
25497
+ return {
25498
+ create: (docName, doc, runtimeOptions) => {
25499
+ const mergedOptions = runtimeOptions ? { ...options, ...runtimeOptions } : options;
25500
+ return new HocuspocusSyncProvider(docName, doc, mergedOptions);
25501
+ },
25502
+ };
25503
+ }
25504
+ async connect() {
25505
+ if (this.isSynced || this.isDestroyed) {
25506
+ return;
25507
+ }
25508
+ this._connectionStatus = 'connecting';
25509
+ return new Promise((resolve, reject) => {
25510
+ // Store reject function so we can cancel the connection if destroyed
25511
+ this.pendingConnectReject = reject;
25512
+ this.connectTimeout = setTimeout(() => {
25513
+ this.pendingConnectReject = null;
25514
+ this.connectTimeout = null;
25515
+ reject(new Error('Hocuspocus connection timeout'));
25516
+ }, this.connectionTimeoutMs);
25517
+ const syncHandler = () => {
25518
+ if (this.connectTimeout) {
25519
+ clearTimeout(this.connectTimeout);
25520
+ this.connectTimeout = null;
25521
+ }
25522
+ this.pendingConnectReject = null;
25523
+ this.provider.off('synced', syncHandler);
25524
+ if (!this.isDestroyed) {
25525
+ resolve();
25526
+ }
25527
+ };
25528
+ this.provider.on('synced', syncHandler);
25529
+ // If already synced, resolve immediately
25530
+ if (this.provider.isSynced) {
25531
+ if (this.connectTimeout) {
25532
+ clearTimeout(this.connectTimeout);
25533
+ this.connectTimeout = null;
25534
+ }
25535
+ this.pendingConnectReject = null;
25536
+ this.provider.off('synced', syncHandler);
25537
+ resolve();
25538
+ return;
25539
+ }
25540
+ // Connect if not already connected (standalone mode only)
25541
+ if (!this.isConnected && !this.usesSharedSocket) {
25542
+ this.provider.connect();
25543
+ }
25544
+ });
25545
+ }
25546
+ async reconnect() {
25547
+ this.disconnect();
25548
+ return this.connect();
25549
+ }
25550
+ disconnect() {
25551
+ // Cancel any pending connection attempt
25552
+ if (this.connectTimeout) {
25553
+ clearTimeout(this.connectTimeout);
25554
+ this.connectTimeout = null;
25555
+ }
25556
+ if (this.pendingConnectReject) {
25557
+ this.pendingConnectReject = null; // Don't reject, just abandon the promise
25558
+ }
25559
+ if (this.provider) {
25560
+ if (this.usesSharedSocket) {
25561
+ // Detach from shared socket instead of disconnecting
25562
+ this.provider.detach();
25563
+ }
25564
+ else {
25565
+ this.provider.disconnect();
25566
+ }
25567
+ }
25568
+ this.isConnected = false;
25569
+ this.isSynced = false;
25570
+ this._connectionStatus = 'disconnected';
25571
+ }
25572
+ destroy() {
25573
+ // Mark as destroyed first to prevent any callbacks from doing work
25574
+ this.isDestroyed = true;
25575
+ // Cancel any pending connection attempt
25576
+ if (this.connectTimeout) {
25577
+ clearTimeout(this.connectTimeout);
25578
+ this.connectTimeout = null;
25579
+ }
25580
+ if (this.pendingConnectReject) {
25581
+ this.pendingConnectReject = null; // Don't reject, just abandon the promise
25582
+ }
25583
+ this.removeBrowserEventListeners();
25584
+ if (this.provider) {
25585
+ this.provider.destroy();
25586
+ }
25587
+ this.isConnected = false;
25588
+ this.isSynced = false;
25589
+ this._connectionStatus = 'disconnected';
25590
+ }
25591
+ }
25592
+
25227
25593
  /** Current version of the workspace export format */
25228
25594
  const WORKSPACE_EXPORT_VERSION = '1.2.0';
25229
25595
  /**
@@ -26882,8 +27248,7 @@ exports.DEFAULT_BRUSH_CONFIG = DEFAULT_BRUSH_CONFIG;
26882
27248
  exports.DEFAULT_COLOR_PALETTE = DEFAULT_COLOR_PALETTE;
26883
27249
  exports.DEFAULT_LINE_TOOL_CONFIG = DEFAULT_LINE_TOOL_CONFIG;
26884
27250
  exports.DEFAULT_TEXT_CONFIG = DEFAULT_TEXT_CONFIG;
26885
- exports.HocuspocusProvider = HocuspocusProvider;
26886
- exports.HocuspocusProviderWebsocket = HocuspocusProviderWebsocket;
27251
+ exports.HocuspocusSyncProvider = HocuspocusSyncProvider;
26887
27252
  exports.IndexedDBSyncProvider = IndexedDBSyncProvider;
26888
27253
  exports.KritzelAnchorManager = KritzelAnchorManager;
26889
27254
  exports.KritzelBaseHandler = KritzelBaseHandler;
@@ -20,6 +20,7 @@ export class KritzelSelectionGroup extends KritzelBaseObject {
20
20
  snapshotHeight = 0;
21
21
  snapshotTranslateX = 0;
22
22
  snapshotTranslateY = 0;
23
+ clientId;
23
24
  minX;
24
25
  maxX;
25
26
  minY;
@@ -92,6 +93,7 @@ export class KritzelSelectionGroup extends KritzelBaseObject {
92
93
  object.id = object.generateId();
93
94
  object.workspaceId = core.store.state.activeWorkspace.id;
94
95
  object.userId = core.user?.id;
96
+ object.clientId = core.store.state.objects?.localClientId ?? undefined;
95
97
  object.scale = core.store.state.scale;
96
98
  object.zIndex = 99999;
97
99
  // Initialize styling with theme-aware defaults
@@ -47,7 +47,7 @@
47
47
  "mixins": [],
48
48
  "compiler": {
49
49
  "name": "@stencil/core",
50
- "version": "4.43.2",
50
+ "version": "4.43.3",
51
51
  "typescriptVersion": "5.8.3"
52
52
  },
53
53
  "collections": [],
@@ -6,7 +6,7 @@
6
6
  width: 100vw;
7
7
  height: 100vh;
8
8
  pointer-events: none;
9
- z-index: 9500;
9
+ z-index: 1;
10
10
  }
11
11
 
12
12
  .awareness-cursor {
@@ -74,6 +74,11 @@
74
74
  .edge-arrow {
75
75
  position: absolute;
76
76
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.3));
77
+ transition: opacity 300ms ease;
78
+ }
79
+
80
+ .edge-arrow.stale {
81
+ opacity: 0;
77
82
  }
78
83
 
79
84
  .edge-label {
@@ -78,6 +78,9 @@ export class KritzelAwarenessCursors {
78
78
  updated.delete(clientId);
79
79
  changed = true;
80
80
  }
81
+ else if (!changed && now - cursor.lastCursorMove > STALE_THRESHOLD_MS) {
82
+ changed = true;
83
+ }
81
84
  }
82
85
  if (changed) {
83
86
  this.remoteCursors = updated;
@@ -182,7 +185,7 @@ export class KritzelAwarenessCursors {
182
185
  void _ty;
183
186
  void this.objectVersion;
184
187
  const cursors = Array.from(this.remoteCursors.values());
185
- return (h(Host, { key: '4dd962322c7e955b9038c55cb10f8ffda1e0b246' }, cursors.map(remoteCursor => {
188
+ return (h(Host, { key: '5a28def6e024249c4309c087502cde9f219f5421' }, cursors.map(remoteCursor => {
186
189
  if (!remoteCursor.cursor)
187
190
  return null;
188
191
  // When a remote user is actively drawing, derive cursor position from
@@ -258,7 +261,7 @@ export class KritzelAwarenessCursors {
258
261
  const displayName = this.getUserDisplayName(cursor.user);
259
262
  return (h("div", { key: `edge-${cursor.clientId}`, class: { 'edge-indicator': true, stale, 'tracking-object': trackingObject }, style: {
260
263
  transform: `translate(${clamped.x}px, ${clamped.y}px)`,
261
- } }, h("svg", { class: "edge-arrow", width: "16", height: "16", viewBox: "0 0 16 16", style: { transform: `rotate(${arrowDeg}deg)` } }, h("path", { d: "M8 1L14 13H2L8 1Z", fill: color, stroke: "#ffffff", "stroke-width": "1.5", "stroke-linejoin": "round" })), h("span", { class: "edge-label", style: {
264
+ } }, h("svg", { class: { 'edge-arrow': true, stale }, width: "16", height: "16", viewBox: "0 0 16 16", style: { transform: `rotate(${arrowDeg}deg)` } }, h("path", { d: "M8 1L14 13H2L8 1Z", fill: color, stroke: "#ffffff", "stroke-width": "1.5", "stroke-linejoin": "round" })), h("span", { class: "edge-label", style: {
262
265
  backgroundColor: color,
263
266
  transform: `translate(${labelX}px, ${labelY}px)`,
264
267
  } }, displayName)));
@@ -34,6 +34,7 @@ kritzel-controls.keyboard-open {
34
34
  display: flex;
35
35
  align-items: flex-start;
36
36
  gap: 8px;
37
+ z-index: 10000;
37
38
  }
38
39
 
39
40
  .top-right-buttons {
@@ -43,6 +44,7 @@ kritzel-controls.keyboard-open {
43
44
  display: flex;
44
45
  align-items: center;
45
46
  gap: 8px;
47
+ z-index: 10000;
46
48
  }
47
49
 
48
50
  .top-right-button {
@@ -16,7 +16,7 @@ import { DEFAULT_SHAPE_CONFIG } from "../../../configs/default-shape-tool.config
16
16
  import { ABSOLUTE_SCALE_MAX, ABSOLUTE_SCALE_MIN } from "../../../constants/engine.constants";
17
17
  import { KritzelKeyboardHelper } from "../../../helpers/keyboard.helper";
18
18
  import { KritzelDevicesHelper } from "../../../helpers/devices.helper";
19
- import { IndexedDBSyncProvider } from "../../..";
19
+ import { HocuspocusSyncProvider, IndexedDBSyncProvider } from "../../..";
20
20
  import { KritzelSelectionGroup } from "../../../classes/objects/selection-group.class";
21
21
  import { KritzelSelectionBox } from "../../../classes/objects/selection-box.class";
22
22
  export class KritzelEditor {
@@ -180,10 +180,19 @@ export class KritzelEditor {
180
180
  isControlsVisible = true;
181
181
  isUtilityPanelVisible = true;
182
182
  syncConfig = {
183
- providers: [IndexedDBSyncProvider]
183
+ appStateId: 'kritzel-app-test',
184
+ providers: [HocuspocusSyncProvider, IndexedDBSyncProvider]
184
185
  };
185
186
  /** Optional login configuration. When provided, a "Sign in" button is shown that opens a login dialog with the configured providers. */
186
- loginConfig;
187
+ loginConfig = {
188
+ providers: [
189
+ {
190
+ label: 'Sign in with Google',
191
+ icon: 'google',
192
+ name: 'Google',
193
+ }
194
+ ]
195
+ };
187
196
  /** Optional unique identifier for namespacing storage keys across multiple editor instances. */
188
197
  editorId;
189
198
  /** Optional workspace ID to set as active. If provided, the editor will automatically activate the workspace with this ID. */
@@ -697,7 +706,7 @@ export class KritzelEditor {
697
706
  const isLoggedIn = this.isLoggedIn;
698
707
  const shouldShowCurrentUser = isLoggedIn;
699
708
  const shouldShowLoginButton = !!this.loginConfig && !isLoggedIn;
700
- return (h(Host, { key: 'd1944655652eb2939e3696ed70050baaca0871e2' }, h("div", { key: 'ce5dfd9b8f8d9927e9a6ace4056f9053163c7e0a', class: "top-left-buttons" }, h("kritzel-workspace-manager", { key: 'e127a667c6e4e853bb4f0c9ffd0edaa6d80d9dfa', workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), h("kritzel-back-to-content", { key: 'a9abb378f3c79f356d2164cbddf6badba10188a8', visible: this.isBackToContentButtonVisible, onBackToContent: () => this.backToContent() })), h("kritzel-engine", { key: 'c5f764580f3623eeb9381e54769a891a48c04620', ref: el => (this.engineRef = el), workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, scaleMin: this.scaleMin, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom, wheelEnabled: this.wheelEnabled, theme: this.currentTheme, debugInfo: this.debugInfo, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.handleWorkspacesChange(event), onActiveWorkspaceChange: event => this.handleActiveWorkspaceChange(event), onObjectsChange: event => this.handleObjectsChange(event), onObjectsAdded: event => this.handleObjectsAdded(event), onObjectsRemoved: event => this.handleObjectsRemoved(event), onObjectsUpdated: event => this.handleObjectsUpdated(event), onUndoStateChange: event => this.handleUndoStateChange(event), onObjectsInViewportChange: event => this.handleObjectsInViewportChange(event), onViewportChange: event => this.handleViewportChange(event), onAwarenessChange: event => this.handleAwarenessChange(event) }), h("kritzel-controls", { key: '2479b6979d5b2b6c55a873bd1d8468b5fd967f72', class: { 'keyboard-open': this.isVirtualKeyboardOpen }, style: { display: this.isControlsVisible ? 'flex' : 'none' }, ref: el => (this.controlsRef = el), controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState, theme: this.currentTheme, onIsControlsReady: () => (this.isControlsReady = true) }), h("div", { key: 'ec6ac72ba154abe0738259464f20cae9e7dbdd9e', class: "top-right-buttons" }, h("kritzel-settings", { key: 'f68f791d673b30331e55f358b9c71b3e2a9a8388', ref: el => (this.settingsRef = el), shortcuts: this.shortcuts, editorId: this.editorId, onSettingsChange: event => this.handleSettingsChange(event) }), h("kritzel-export", { key: 'dfe5a051caccee504df4f347705303fa1f812556', ref: el => (this.exportRef = el), workspaceName: this.activeWorkspace?.name || 'workspace', onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), h("kritzel-active-users", { key: '48983a14d3902cd238cf0d9ed302ed561a655a9a', users: this.activeUsers }), shouldShowCurrentUser && h("kritzel-current-user", { key: '589bdc895741a2d17f60c4b549d14fe8fff74c17', user: this.user }), shouldShowLoginButton && h("kritzel-button", { key: '50414a9d7ade623678c767ce63c49f5e99336bed', onButtonClick: () => this.loginDialogRef?.open() }, "Sign in"), h("kritzel-more-menu", { key: 'db3069ee0b093acd238750df81c6f426139c9b87', items: this.moreMenuItems }), h("kritzel-share-dialog", { key: 'e16057838f00b2c3f239e794b4310bd2690d16e2', ref: el => (this.shareDialogRef = el), isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: 'a6d1fc06c983542c6af95e7bb4b2b2d522a03605', ref: el => (this.loginDialogRef = el), providers: this.loginConfig.providers, dialogTitle: this.loginConfig.title, subtitle: this.loginConfig.subtitle, onProviderLogin: this.handleProviderLogin })))));
709
+ return (h(Host, { key: '6dbc3a8c64dd097ba82e46341b3fb97cbd0194db' }, h("div", { key: '26ceb62f59ad830fd651a1712f57e5d711e7c6f4', class: "top-left-buttons" }, h("kritzel-workspace-manager", { key: 'afb4f5b87c5dc0a673444fb27930e43994df4e02', workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), h("kritzel-back-to-content", { key: 'f3c0f31841cb819917c3277852bc9b5ce291c09a', visible: this.isBackToContentButtonVisible, onBackToContent: () => this.backToContent() })), h("kritzel-engine", { key: '8a9e57132e6b74ec812ee516dc7f0d5fc6c8a2e1', ref: el => (this.engineRef = el), workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, scaleMin: this.scaleMin, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom, wheelEnabled: this.wheelEnabled, theme: this.currentTheme, debugInfo: this.debugInfo, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.handleWorkspacesChange(event), onActiveWorkspaceChange: event => this.handleActiveWorkspaceChange(event), onObjectsChange: event => this.handleObjectsChange(event), onObjectsAdded: event => this.handleObjectsAdded(event), onObjectsRemoved: event => this.handleObjectsRemoved(event), onObjectsUpdated: event => this.handleObjectsUpdated(event), onUndoStateChange: event => this.handleUndoStateChange(event), onObjectsInViewportChange: event => this.handleObjectsInViewportChange(event), onViewportChange: event => this.handleViewportChange(event), onAwarenessChange: event => this.handleAwarenessChange(event) }), h("kritzel-controls", { key: '6caadf512a0208fecdb18b6d68b17daa522161a3', class: { 'keyboard-open': this.isVirtualKeyboardOpen }, style: { display: this.isControlsVisible ? 'flex' : 'none' }, ref: el => (this.controlsRef = el), controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState, theme: this.currentTheme, onIsControlsReady: () => (this.isControlsReady = true) }), h("div", { key: 'e27e5f3965be2fd15c83b91470ef87c4031dd7a2', class: "top-right-buttons" }, h("kritzel-settings", { key: '57f8e75287402aecbb7740d46dfa15839de2169f', ref: el => (this.settingsRef = el), shortcuts: this.shortcuts, editorId: this.editorId, onSettingsChange: event => this.handleSettingsChange(event) }), h("kritzel-export", { key: '5ccf176d4fe1221c5d7597bd1c8537cf3324d3ee', ref: el => (this.exportRef = el), workspaceName: this.activeWorkspace?.name || 'workspace', onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), h("kritzel-active-users", { key: '44a334b808706e11163e89b91074ca4ea8ab4b18', users: this.activeUsers }), shouldShowCurrentUser && h("kritzel-current-user", { key: 'bcb3c966e630b1a8fc4ccd438fc8fbb11cd2b167', user: this.user }), shouldShowLoginButton && h("kritzel-button", { key: 'f1957e56257b7c565311e41b770579f7e2bb910d', onButtonClick: () => this.loginDialogRef?.open() }, "Sign in"), h("kritzel-more-menu", { key: 'd8c1d1b51cf87725d68aaf4457b88828986a40dc', items: this.moreMenuItems }), h("kritzel-share-dialog", { key: 'f5840e7f56cf6897ec28b0f28d9b204037bf3348', ref: el => (this.shareDialogRef = el), isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: 'cfdcc3d5e7a5e29b0a352f0d4423ae79195dbf69', ref: el => (this.loginDialogRef = el), providers: this.loginConfig.providers, dialogTitle: this.loginConfig.title, subtitle: this.loginConfig.subtitle, onProviderLogin: this.handleProviderLogin })))));
701
710
  }
702
711
  static get is() { return "kritzel-editor"; }
703
712
  static get originalStyleUrls() {
@@ -1106,7 +1115,7 @@ export class KritzelEditor {
1106
1115
  },
1107
1116
  "getter": false,
1108
1117
  "setter": false,
1109
- "defaultValue": "{\r\n providers: [IndexedDBSyncProvider]\r\n }"
1118
+ "defaultValue": "{\r\n appStateId: 'kritzel-app-test',\r\n providers: [HocuspocusSyncProvider, IndexedDBSyncProvider]\r\n }"
1110
1119
  },
1111
1120
  "loginConfig": {
1112
1121
  "type": "unknown",
@@ -1130,7 +1139,8 @@ export class KritzelEditor {
1130
1139
  "text": "Optional login configuration. When provided, a \"Sign in\" button is shown that opens a login dialog with the configured providers."
1131
1140
  },
1132
1141
  "getter": false,
1133
- "setter": false
1142
+ "setter": false,
1143
+ "defaultValue": "{\r\n providers: [\r\n {\r\n label: 'Sign in with Google',\r\n icon: 'google',\r\n name: 'Google',\r\n }\r\n ]\r\n }"
1134
1144
  },
1135
1145
  "editorId": {
1136
1146
  "type": "string",