kritzel-stencil 0.1.74 → 0.1.76

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 (43) hide show
  1. package/dist/cjs/index.cjs.js +131 -86
  2. package/dist/cjs/kritzel-active-users_42.cjs.entry.js +132 -19
  3. package/dist/cjs/{workspace.migrations-Dyt35LBC.js → workspace.migrations-DkmVO6dE.js} +106 -44
  4. package/dist/collection/classes/core/viewport.class.js +32 -3
  5. package/dist/collection/classes/managers/anchor.manager.js +101 -44
  6. package/dist/collection/classes/providers/broadcast-sync-provider.class.js +5 -0
  7. package/dist/collection/classes/providers/hocuspocus-sync-provider.class.js +120 -85
  8. package/dist/collection/classes/providers/indexeddb-sync-provider.class.js +5 -0
  9. package/dist/collection/classes/providers/websocket-sync-provider.class.js +5 -0
  10. package/dist/collection/classes/structures/app-state-map.structure.js +15 -4
  11. package/dist/collection/classes/structures/object-map.structure.js +75 -7
  12. package/dist/collection/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.css +2 -2
  13. package/dist/collection/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.js +7 -2
  14. package/dist/collection/constants/version.js +1 -1
  15. package/dist/components/index.js +1 -1
  16. package/dist/components/kritzel-awareness-cursors.js +1 -1
  17. package/dist/components/kritzel-editor.js +1 -1
  18. package/dist/components/kritzel-engine.js +1 -1
  19. package/dist/components/kritzel-settings.js +1 -1
  20. package/dist/components/{p-B4Oqnl55.js → p-31FVoNWR.js} +1 -1
  21. package/dist/components/p-jdYmu4SA.js +9 -0
  22. package/dist/components/p-xNwOWoiT.js +1 -0
  23. package/dist/esm/index.js +132 -87
  24. package/dist/esm/kritzel-active-users_42.entry.js +132 -19
  25. package/dist/esm/{workspace.migrations-B99F1MdT.js → workspace.migrations-D48_Bqvh.js} +106 -44
  26. package/dist/stencil/index.esm.js +1 -1
  27. package/dist/stencil/p-775a7246.entry.js +9 -0
  28. package/dist/stencil/{p-B99F1MdT.js → p-D48_Bqvh.js} +1 -1
  29. package/dist/stencil/stencil.esm.js +1 -1
  30. package/dist/types/classes/core/viewport.class.d.ts +8 -0
  31. package/dist/types/classes/managers/anchor.manager.d.ts +4 -0
  32. package/dist/types/classes/providers/broadcast-sync-provider.class.d.ts +2 -0
  33. package/dist/types/classes/providers/hocuspocus-sync-provider.class.d.ts +37 -1
  34. package/dist/types/classes/providers/indexeddb-sync-provider.class.d.ts +2 -0
  35. package/dist/types/classes/providers/websocket-sync-provider.class.d.ts +2 -0
  36. package/dist/types/classes/structures/object-map.structure.d.ts +6 -0
  37. package/dist/types/constants/version.d.ts +1 -1
  38. package/dist/types/interfaces/remote-cursor.interface.d.ts +1 -0
  39. package/dist/types/interfaces/sync-provider.interface.d.ts +16 -0
  40. package/package.json +1 -1
  41. package/dist/components/p-BSipRoFx.js +0 -1
  42. package/dist/components/p-RJWe82kG.js +0 -9
  43. package/dist/stencil/p-2a60e1bc.entry.js +0 -9
@@ -4,6 +4,7 @@ import { HocuspocusProvider, HocuspocusProviderWebsocket } from "@hocuspocus/pro
4
4
  * Supports multiplexing - multiple documents can share the same WebSocket connection
5
5
  */
6
6
  export class HocuspocusSyncProvider {
7
+ type = 'network';
7
8
  provider;
8
9
  isConnected = false;
9
10
  isSynced = false;
@@ -11,16 +12,87 @@ export class HocuspocusSyncProvider {
11
12
  isDestroyed = false;
12
13
  connectTimeout = null;
13
14
  pendingConnectReject = null;
15
+ connectionTimeoutMs;
16
+ _connectionStatus = 'disconnected';
17
+ visibilityHandler = null;
18
+ onlineHandler = null;
14
19
  get awareness() {
15
20
  return this.provider.awareness;
16
21
  }
22
+ get connectionStatus() {
23
+ return this._connectionStatus;
24
+ }
17
25
  // Static shared WebSocket instance for multiplexing
18
26
  static sharedWebSocketProvider = null;
19
27
  constructor(docName, doc, options) {
20
28
  const name = options?.name || docName;
21
29
  const url = options?.url || 'ws://localhost:1234';
30
+ this.connectionTimeoutMs = options?.connectionTimeout ?? 10000;
22
31
  // Use provided websocketProvider or the static shared one
23
32
  const websocketProvider = options?.websocketProvider || HocuspocusSyncProvider.sharedWebSocketProvider;
33
+ // Build reconnect config from options
34
+ const reconnectConfig = {};
35
+ if (options?.delay !== undefined)
36
+ reconnectConfig.delay = options.delay;
37
+ if (options?.factor !== undefined)
38
+ reconnectConfig.factor = options.factor;
39
+ if (options?.maxAttempts !== undefined)
40
+ reconnectConfig.maxAttempts = options.maxAttempts;
41
+ if (options?.minDelay !== undefined)
42
+ reconnectConfig.minDelay = options.minDelay;
43
+ if (options?.maxDelay !== undefined)
44
+ reconnectConfig.maxDelay = options.maxDelay;
45
+ const onConnect = () => {
46
+ if (this.isDestroyed) {
47
+ return;
48
+ }
49
+ this.isConnected = true;
50
+ this._connectionStatus = 'connected';
51
+ if (!options?.quiet) {
52
+ console.info(`Hocuspocus connected: ${name}`);
53
+ }
54
+ if (options?.onConnect) {
55
+ options.onConnect();
56
+ }
57
+ };
58
+ const onDisconnect = () => {
59
+ if (this.isDestroyed) {
60
+ return;
61
+ }
62
+ this.isConnected = false;
63
+ this.isSynced = false;
64
+ this._connectionStatus = 'disconnected';
65
+ if (!options?.quiet) {
66
+ console.info(`Hocuspocus disconnected: ${name}`);
67
+ }
68
+ if (options?.onDisconnect) {
69
+ options.onDisconnect();
70
+ }
71
+ };
72
+ const onSynced = () => {
73
+ if (this.isDestroyed) {
74
+ return;
75
+ }
76
+ this.isSynced = true;
77
+ this._connectionStatus = 'synced';
78
+ if (!options?.quiet) {
79
+ console.info(`Hocuspocus synced: ${name}`);
80
+ }
81
+ if (options?.onSynced) {
82
+ options.onSynced();
83
+ }
84
+ };
85
+ const onStatus = (data) => {
86
+ if (this.isDestroyed) {
87
+ return;
88
+ }
89
+ if (data.status === 'connecting') {
90
+ this._connectionStatus = 'connecting';
91
+ }
92
+ if (options?.onStatus) {
93
+ options.onStatus(data);
94
+ }
95
+ };
24
96
  if (websocketProvider) {
25
97
  // Multiplexing mode - use shared WebSocket connection
26
98
  this.usesSharedSocket = true;
@@ -29,48 +101,11 @@ export class HocuspocusSyncProvider {
29
101
  name,
30
102
  document: doc,
31
103
  token: options?.token || null,
32
- onStatus: (data) => {
33
- if (options?.onStatus) {
34
- options.onStatus(data);
35
- }
36
- },
37
- onConnect: () => {
38
- if (this.isConnected || this.isDestroyed) {
39
- return;
40
- }
41
- this.isConnected = true;
42
- if (!options?.quiet) {
43
- console.info(`Hocuspocus connected: ${name}`);
44
- }
45
- if (options?.onConnect) {
46
- options.onConnect();
47
- }
48
- },
49
- onDisconnect: () => {
50
- if (this.isDestroyed || (!this.isConnected && !this.isSynced)) {
51
- return;
52
- }
53
- this.isConnected = false;
54
- this.isSynced = false;
55
- if (!options?.quiet) {
56
- console.info(`Hocuspocus disconnected: ${name}`);
57
- }
58
- if (options?.onDisconnect) {
59
- options.onDisconnect();
60
- }
61
- },
62
- onSynced: () => {
63
- if (this.isSynced || this.isDestroyed) {
64
- return;
65
- }
66
- this.isSynced = true;
67
- if (!options?.quiet) {
68
- console.info(`Hocuspocus synced: ${name}`);
69
- }
70
- if (options?.onSynced) {
71
- options.onSynced();
72
- }
73
- },
104
+ onStatus,
105
+ onConnect,
106
+ onDisconnect,
107
+ onSynced,
108
+ ...reconnectConfig,
74
109
  };
75
110
  // Add optional settings
76
111
  if (options?.forceSyncInterval !== undefined) {
@@ -95,48 +130,11 @@ export class HocuspocusSyncProvider {
95
130
  document: doc,
96
131
  token: options?.token || null,
97
132
  autoConnect: false,
98
- onStatus: (data) => {
99
- if (options?.onStatus) {
100
- options.onStatus(data);
101
- }
102
- },
103
- onConnect: () => {
104
- if (this.isConnected || this.isDestroyed) {
105
- return;
106
- }
107
- this.isConnected = true;
108
- if (!options?.quiet) {
109
- console.info(`Hocuspocus connected: ${name}`);
110
- }
111
- if (options?.onConnect) {
112
- options.onConnect();
113
- }
114
- },
115
- onDisconnect: () => {
116
- if (this.isDestroyed || (!this.isConnected && !this.isSynced)) {
117
- return;
118
- }
119
- this.isConnected = false;
120
- this.isSynced = false;
121
- if (!options?.quiet) {
122
- console.info(`Hocuspocus disconnected: ${name}`);
123
- }
124
- if (options?.onDisconnect) {
125
- options.onDisconnect();
126
- }
127
- },
128
- onSynced: () => {
129
- if (this.isSynced || this.isDestroyed) {
130
- return;
131
- }
132
- this.isSynced = true;
133
- if (!options?.quiet) {
134
- console.info(`Hocuspocus synced: ${name}`);
135
- }
136
- if (options?.onSynced) {
137
- options.onSynced();
138
- }
139
- },
133
+ onStatus,
134
+ onConnect,
135
+ onDisconnect,
136
+ onSynced,
137
+ ...reconnectConfig,
140
138
  };
141
139
  // Add optional settings
142
140
  if (options?.forceSyncInterval !== undefined) {
@@ -153,6 +151,35 @@ export class HocuspocusSyncProvider {
153
151
  console.info(`Hocuspocus Provider initialized: ${url}/${name}`);
154
152
  }
155
153
  }
154
+ this.setupBrowserEventListeners();
155
+ }
156
+ setupBrowserEventListeners() {
157
+ if (typeof document !== 'undefined') {
158
+ this.visibilityHandler = () => {
159
+ if (document.visibilityState === 'visible' && !this.isConnected && !this.isDestroyed) {
160
+ this.provider.connect();
161
+ }
162
+ };
163
+ document.addEventListener('visibilitychange', this.visibilityHandler);
164
+ }
165
+ if (typeof window !== 'undefined') {
166
+ this.onlineHandler = () => {
167
+ if (!this.isConnected && !this.isDestroyed) {
168
+ this.provider.connect();
169
+ }
170
+ };
171
+ window.addEventListener('online', this.onlineHandler);
172
+ }
173
+ }
174
+ removeBrowserEventListeners() {
175
+ if (this.visibilityHandler && typeof document !== 'undefined') {
176
+ document.removeEventListener('visibilitychange', this.visibilityHandler);
177
+ this.visibilityHandler = null;
178
+ }
179
+ if (this.onlineHandler && typeof window !== 'undefined') {
180
+ window.removeEventListener('online', this.onlineHandler);
181
+ this.onlineHandler = null;
182
+ }
156
183
  }
157
184
  /**
158
185
  * Create a shared WebSocket connection for multiplexing
@@ -215,6 +242,7 @@ export class HocuspocusSyncProvider {
215
242
  if (this.isSynced || this.isDestroyed) {
216
243
  return;
217
244
  }
245
+ this._connectionStatus = 'connecting';
218
246
  return new Promise((resolve, reject) => {
219
247
  // Store reject function so we can cancel the connection if destroyed
220
248
  this.pendingConnectReject = reject;
@@ -222,7 +250,7 @@ export class HocuspocusSyncProvider {
222
250
  this.pendingConnectReject = null;
223
251
  this.connectTimeout = null;
224
252
  reject(new Error('Hocuspocus connection timeout'));
225
- }, 10000); // 10 second timeout
253
+ }, this.connectionTimeoutMs);
226
254
  const syncHandler = () => {
227
255
  if (this.connectTimeout) {
228
256
  clearTimeout(this.connectTimeout);
@@ -252,6 +280,10 @@ export class HocuspocusSyncProvider {
252
280
  }
253
281
  });
254
282
  }
283
+ async reconnect() {
284
+ this.disconnect();
285
+ return this.connect();
286
+ }
255
287
  disconnect() {
256
288
  // Cancel any pending connection attempt
257
289
  if (this.connectTimeout) {
@@ -272,6 +304,7 @@ export class HocuspocusSyncProvider {
272
304
  }
273
305
  this.isConnected = false;
274
306
  this.isSynced = false;
307
+ this._connectionStatus = 'disconnected';
275
308
  }
276
309
  destroy() {
277
310
  // Mark as destroyed first to prevent any callbacks from doing work
@@ -284,10 +317,12 @@ export class HocuspocusSyncProvider {
284
317
  if (this.pendingConnectReject) {
285
318
  this.pendingConnectReject = null; // Don't reject, just abandon the promise
286
319
  }
320
+ this.removeBrowserEventListeners();
287
321
  if (this.provider) {
288
322
  this.provider.destroy();
289
323
  }
290
324
  this.isConnected = false;
291
325
  this.isSynced = false;
326
+ this._connectionStatus = 'disconnected';
292
327
  }
293
328
  }
@@ -3,6 +3,7 @@ import { IndexeddbPersistence } from "y-indexeddb";
3
3
  * IndexedDB sync provider for local persistence
4
4
  */
5
5
  export class IndexedDBSyncProvider {
6
+ type = 'local';
6
7
  provider;
7
8
  isConnected = false;
8
9
  constructor(docName, doc, options) {
@@ -24,6 +25,10 @@ export class IndexedDBSyncProvider {
24
25
  // IndexedDB doesn't need explicit disconnect
25
26
  this.isConnected = false;
26
27
  }
28
+ async reconnect() {
29
+ this.disconnect();
30
+ return this.connect();
31
+ }
27
32
  destroy() {
28
33
  if (this.provider) {
29
34
  this.provider.destroy();
@@ -3,6 +3,7 @@ import { WebsocketProvider } from "y-websocket";
3
3
  * WebSocket sync provider for real-time collaboration
4
4
  */
5
5
  export class WebSocketSyncProvider {
6
+ type = 'network';
6
7
  provider;
7
8
  isConnected = false;
8
9
  _quiet = false;
@@ -91,6 +92,10 @@ export class WebSocketSyncProvider {
91
92
  }
92
93
  this.isConnected = false;
93
94
  }
95
+ async reconnect() {
96
+ this.disconnect();
97
+ return this.connect();
98
+ }
94
99
  destroy() {
95
100
  if (this.provider) {
96
101
  this.provider.destroy();
@@ -79,13 +79,24 @@ export class KritzelAppStateMap {
79
79
  this.handleWorkspacesChange(event);
80
80
  };
81
81
  this._workspacesMap.observe(this._workspacesObserver);
82
- // Connect all providers in parallel (settle individually so one failure doesn't block the rest)
83
- const results = await Promise.allSettled(this._providers.map(p => p.connect()));
84
- results.forEach((result, i) => {
82
+ // Separate local providers (IndexedDB, BroadcastChannel) from network providers (Hocuspocus, WebSocket)
83
+ // Local providers are awaited so data is available immediately; network providers sync in the background
84
+ // via Yjs observers that are already registered above.
85
+ const localProviders = this._providers.filter(p => p.type === 'local');
86
+ const networkProviders = this._providers.filter(p => p.type === 'network');
87
+ // Await local providers for immediate data availability
88
+ const localResults = await Promise.allSettled(localProviders.map(p => p.connect()));
89
+ localResults.forEach((result, i) => {
85
90
  if (result.status === 'rejected') {
86
- console.error(`[Kritzel] Sync provider "${this._providers[i]?.constructor.name}" failed to connect:`, result.reason);
91
+ console.error(`[Kritzel] Sync provider "${localProviders[i]?.constructor.name}" failed to connect:`, result.reason);
87
92
  }
88
93
  });
94
+ // Connect network providers in the background (remote data arrives via Yjs observers)
95
+ for (const provider of networkProviders) {
96
+ provider.connect().catch(err => {
97
+ console.error(`[Kritzel] Network sync provider "${provider.constructor.name}" failed to connect:`, err);
98
+ });
99
+ }
89
100
  this._isReady = true;
90
101
  // Run any pending schema migrations before loading data
91
102
  const quietMigrations = !core.store.state.debugInfo.showMigrationInfo;
@@ -137,6 +137,42 @@ export class KritzelObjectMap {
137
137
  }
138
138
  this._awareness.setLocalStateField('selectionBox', null);
139
139
  }
140
+ /**
141
+ * Removes selection groups whose owner is no longer present in awareness.
142
+ * Called when remote clients disconnect to prevent orphaned selection groups
143
+ * from persisting in the workspace state.
144
+ */
145
+ removeOrphanedSelectionGroups() {
146
+ if (!this._awareness) {
147
+ return;
148
+ }
149
+ const states = this._awareness.getStates();
150
+ const activeUserIds = new Set();
151
+ states.forEach(state => {
152
+ const userId = state.user?.id;
153
+ if (userId) {
154
+ activeUserIds.add(userId);
155
+ }
156
+ });
157
+ const localUserId = this._core?.user?.id;
158
+ const orphanedGroups = this.quadtree.filter(o => o instanceof KritzelSelectionGroup
159
+ && o.userId != null
160
+ && o.userId !== localUserId
161
+ && !activeUserIds.has(o.userId));
162
+ for (const group of orphanedGroups) {
163
+ this.quadtree.remove(o => o.id === group.id);
164
+ this._idMap.delete(group.id);
165
+ if (this._objectsMap) {
166
+ this._ydoc.transact(() => {
167
+ this._objectsMap.delete(group.id);
168
+ }, 'local');
169
+ }
170
+ }
171
+ if (orphanedGroups.length > 0) {
172
+ this._core?.store.invalidateSelectionCache();
173
+ this._core?.rerender();
174
+ }
175
+ }
140
176
  /**
141
177
  * Registers a callback to be invoked when the awareness state changes.
142
178
  * The callback receives the full awareness states map.
@@ -270,16 +306,28 @@ export class KritzelObjectMap {
270
306
  this.handleObjectsChange(event);
271
307
  };
272
308
  this._objectsMap.observe(this._objectsObserver);
273
- // Connect all providers in parallel (settle individually so one failure doesn't block the rest)
274
- const results = await Promise.allSettled(this._providers.map(p => p.connect()));
275
- results.forEach((result, i) => {
309
+ // Separate local providers (IndexedDB, BroadcastChannel) from network providers (Hocuspocus, WebSocket)
310
+ // Local providers are awaited so data is available immediately; network providers sync in the background
311
+ // via Yjs observers that are already registered above.
312
+ const localProviders = this._providers.filter(p => p.type === 'local');
313
+ const networkProviders = this._providers.filter(p => p.type === 'network');
314
+ // Await local providers for immediate data availability
315
+ const localResults = await Promise.allSettled(localProviders.map(p => p.connect()));
316
+ localResults.forEach((result, i) => {
276
317
  if (result.status === 'rejected') {
277
- console.error(`[Kritzel] Sync provider "${this._providers[i]?.constructor.name}" failed to connect:`, result.reason);
318
+ console.error(`[Kritzel] Sync provider "${localProviders[i]?.constructor.name}" failed to connect:`, result.reason);
278
319
  }
279
320
  });
321
+ // Connect network providers in the background (remote data arrives via Yjs observers)
322
+ for (const provider of networkProviders) {
323
+ provider.connect().catch(err => {
324
+ console.error(`[Kritzel] Network sync provider "${provider.constructor.name}" failed to connect:`, err);
325
+ });
326
+ }
280
327
  this._isReady = true;
281
328
  // Find the first provider that exposes awareness (network providers)
282
- for (const provider of this._providers) {
329
+ // Awareness is available immediately after provider construction, before connect() resolves
330
+ for (const provider of networkProviders) {
283
331
  if (provider.awareness) {
284
332
  this._awareness = provider.awareness;
285
333
  break;
@@ -287,7 +335,11 @@ export class KritzelObjectMap {
287
335
  }
288
336
  // Subscribe to awareness changes
289
337
  if (this._awareness) {
290
- this._awarenessChangeHandler = () => {
338
+ this._awarenessChangeHandler = (change) => {
339
+ // Clean up selection groups belonging to disconnected users
340
+ if (change.removed.length > 0) {
341
+ this.removeOrphanedSelectionGroups();
342
+ }
291
343
  const now = Date.now();
292
344
  const timeSinceLastEmit = now - this._lastAwarenessEmitTime;
293
345
  // Clear any pending timeout since we have a new event
@@ -550,11 +602,27 @@ export class KritzelObjectMap {
550
602
  }
551
603
  this.quadtree.reset();
552
604
  this._idMap.clear();
553
- this._objectsMap.forEach(serialized => {
605
+ const localUserId = this._core?.user?.id;
606
+ const staleSelectionGroupIds = [];
607
+ this._objectsMap.forEach((serialized, key) => {
554
608
  const object = this._reviver.revive(serialized);
609
+ // Remove remote selection groups on startup — they are transient UI state
610
+ // that should not survive an app restart. The owning user's session is gone.
611
+ if (object instanceof KritzelSelectionGroup && object.userId != null && object.userId !== localUserId) {
612
+ staleSelectionGroupIds.push(key);
613
+ return;
614
+ }
555
615
  this.quadtree.insert(object);
556
616
  this._idMap.set(object.id, object);
557
617
  });
618
+ // Clean up stale remote selection groups from Yjs
619
+ if (staleSelectionGroupIds.length > 0) {
620
+ this._ydoc.transact(() => {
621
+ for (const id of staleSelectionGroupIds) {
622
+ this._objectsMap.delete(id);
623
+ }
624
+ }, 'local');
625
+ }
558
626
  }
559
627
  /**
560
628
  * Resets the object map by clearing both the local quadtree and the Yjs objects map.
@@ -19,7 +19,7 @@
19
19
  }
20
20
 
21
21
  .awareness-cursor.stale {
22
- opacity: 0.3;
22
+ opacity: 0;
23
23
  }
24
24
 
25
25
  .awareness-cursor.tracking-object {
@@ -64,7 +64,7 @@
64
64
  }
65
65
 
66
66
  .edge-indicator.stale {
67
- opacity: 0.3;
67
+ opacity: 0;
68
68
  }
69
69
 
70
70
  .edge-indicator.tracking-object {
@@ -47,6 +47,10 @@ export class KritzelAwarenessCursors {
47
47
  const cursor = state.cursor;
48
48
  const activeObjectId = state.activeObjectId || null;
49
49
  const selectionBox = state.selectionBox || null;
50
+ const existing = updated.get(clientId);
51
+ const cursorMoved = !existing ||
52
+ !existing.cursor !== !cursor ||
53
+ (cursor && existing.cursor && (cursor.x !== existing.cursor.x || cursor.y !== existing.cursor.y));
50
54
  updated.set(clientId, {
51
55
  clientId,
52
56
  user,
@@ -54,6 +58,7 @@ export class KritzelAwarenessCursors {
54
58
  activeObjectId,
55
59
  selectionBox,
56
60
  lastUpdated: now,
61
+ lastCursorMove: cursorMoved ? now : (existing?.lastCursorMove ?? now),
57
62
  });
58
63
  });
59
64
  // Remove cursors for disconnected clients
@@ -79,7 +84,7 @@ export class KritzelAwarenessCursors {
79
84
  }
80
85
  }
81
86
  isStale(cursor) {
82
- return Date.now() - cursor.lastUpdated > STALE_THRESHOLD_MS;
87
+ return Date.now() - cursor.lastCursorMove > STALE_THRESHOLD_MS;
83
88
  }
84
89
  hasActiveDrawingCursors() {
85
90
  for (const cursor of this.remoteCursors.values()) {
@@ -177,7 +182,7 @@ export class KritzelAwarenessCursors {
177
182
  void _ty;
178
183
  void this.objectVersion;
179
184
  const cursors = Array.from(this.remoteCursors.values());
180
- return (h(Host, { key: 'b8676d9a7a3d4a79ea8ad9763355ecf4c2f90e17' }, cursors.map(remoteCursor => {
185
+ return (h(Host, { key: '4dd962322c7e955b9038c55cb10f8ffda1e0b246' }, cursors.map(remoteCursor => {
181
186
  if (!remoteCursor.cursor)
182
187
  return null;
183
188
  // When a remote user is actively drawing, derive cursor position from
@@ -3,4 +3,4 @@
3
3
  * This file is auto-generated by the version bump scripts.
4
4
  * Do not modify manually.
5
5
  */
6
- export const KRITZEL_VERSION = '0.1.74';
6
+ export const KRITZEL_VERSION = '0.1.76';
@@ -1 +1 @@
1
- export{g as getAssetPath,r as render,s as setAssetPath,a as setNonce,b as setPlatformOptions}from"./p-pebXO4LU.js";export{d as KritzelBrushTool,b as KritzelGroup,a as KritzelImage,e as KritzelLineTool,h as KritzelSelectionTool,c as KritzelShape,g as KritzelShapeTool,K as KritzelText,f as KritzelTextTool,S as ShapeType}from"./p-CJ2eHeoV.js";export{a as KritzelLine,K as KritzelPath}from"./p-DXpYcAnT.js";export{A as APP_STATE_MIGRATIONS,I as IndexedDBSyncProvider,d as KritzelAlignment,c as KritzelAnchorManager,b as KritzelCursorHelper,K as KritzelEraserTool,a as KritzelImageTool,W as WORKSPACE_MIGRATIONS,r as runMigrations}from"./p-RJWe82kG.js";import*as t from"yjs";import{WebsocketProvider as i}from"y-websocket";import{H as o,a as n}from"./kritzel-editor.js";export{D as DEFAULT_BRUSH_CONFIG,c as DEFAULT_LINE_TOOL_CONFIG,b as DEFAULT_TEXT_CONFIG,KritzelEditor,defineCustomElement as defineCustomElementKritzelEditor}from"./kritzel-editor.js";export{K as KritzelWorkspace,W as WORKSPACE_EXPORT_VERSION}from"./p-DhMlShij.js";export{K as KritzelThemeManager,d as darkTheme,l as lightTheme}from"./p-CjazGGq3.js";export{C as CURRENT_APP_STATE_SCHEMA_VERSION,a as CURRENT_WORKSPACE_SCHEMA_VERSION}from"./p-CW-VyJgK.js";export{KritzelActiveUsers,defineCustomElement as defineCustomElementKritzelActiveUsers}from"./kritzel-active-users.js";export{KritzelAvatar,defineCustomElement as defineCustomElementKritzelAvatar}from"./kritzel-avatar.js";export{KritzelAwarenessCursors,defineCustomElement as defineCustomElementKritzelAwarenessCursors}from"./kritzel-awareness-cursors.js";export{KritzelBackToContent,defineCustomElement as defineCustomElementKritzelBackToContent}from"./kritzel-back-to-content.js";export{KritzelBrushStyle,defineCustomElement as defineCustomElementKritzelBrushStyle}from"./kritzel-brush-style.js";export{KritzelButton,defineCustomElement as defineCustomElementKritzelButton}from"./kritzel-button.js";export{KritzelColor,defineCustomElement as defineCustomElementKritzelColor}from"./kritzel-color.js";export{KritzelColorPalette,defineCustomElement as defineCustomElementKritzelColorPalette}from"./kritzel-color-palette.js";export{KritzelContextMenu,defineCustomElement as defineCustomElementKritzelContextMenu}from"./kritzel-context-menu.js";export{KritzelControls,defineCustomElement as defineCustomElementKritzelControls}from"./kritzel-controls.js";export{KritzelCurrentUser,defineCustomElement as defineCustomElementKritzelCurrentUser}from"./kritzel-current-user.js";export{KritzelCurrentUserDialog,defineCustomElement as defineCustomElementKritzelCurrentUserDialog}from"./kritzel-current-user-dialog.js";export{KritzelCursorTrail,defineCustomElement as defineCustomElementKritzelCursorTrail}from"./kritzel-cursor-trail.js";export{KritzelDialog,defineCustomElement as defineCustomElementKritzelDialog}from"./kritzel-dialog.js";export{KritzelDropdown,defineCustomElement as defineCustomElementKritzelDropdown}from"./kritzel-dropdown.js";export{KritzelEngine,defineCustomElement as defineCustomElementKritzelEngine}from"./kritzel-engine.js";export{KritzelExport,defineCustomElement as defineCustomElementKritzelExport}from"./kritzel-export.js";export{KritzelFont,defineCustomElement as defineCustomElementKritzelFont}from"./kritzel-font.js";export{KritzelFontFamily,defineCustomElement as defineCustomElementKritzelFontFamily}from"./kritzel-font-family.js";export{KritzelFontSize,defineCustomElement as defineCustomElementKritzelFontSize}from"./kritzel-font-size.js";export{KritzelIcon,defineCustomElement as defineCustomElementKritzelIcon}from"./kritzel-icon.js";export{KritzelInput,defineCustomElement as defineCustomElementKritzelInput}from"./kritzel-input.js";export{KritzelLineEndings,defineCustomElement as defineCustomElementKritzelLineEndings}from"./kritzel-line-endings.js";export{KritzelLoginDialog,defineCustomElement as defineCustomElementKritzelLoginDialog}from"./kritzel-login-dialog.js";export{KritzelMasterDetail,defineCustomElement as defineCustomElementKritzelMasterDetail}from"./kritzel-master-detail.js";export{KritzelMenu,defineCustomElement as defineCustomElementKritzelMenu}from"./kritzel-menu.js";export{KritzelMenuItem,defineCustomElement as defineCustomElementKritzelMenuItem}from"./kritzel-menu-item.js";export{KritzelMoreMenu,defineCustomElement as defineCustomElementKritzelMoreMenu}from"./kritzel-more-menu.js";export{KritzelNumericInput,defineCustomElement as defineCustomElementKritzelNumericInput}from"./kritzel-numeric-input.js";export{KritzelOpacitySlider,defineCustomElement as defineCustomElementKritzelOpacitySlider}from"./kritzel-opacity-slider.js";export{KritzelPillTabs,defineCustomElement as defineCustomElementKritzelPillTabs}from"./kritzel-pill-tabs.js";export{KritzelPortal,defineCustomElement as defineCustomElementKritzelPortal}from"./kritzel-portal.js";export{KritzelSettings,defineCustomElement as defineCustomElementKritzelSettings}from"./kritzel-settings.js";export{KritzelShapeFill,defineCustomElement as defineCustomElementKritzelShapeFill}from"./kritzel-shape-fill.js";export{KritzelShareDialog,defineCustomElement as defineCustomElementKritzelShareDialog}from"./kritzel-share-dialog.js";export{KritzelSlideToggle,defineCustomElement as defineCustomElementKritzelSlideToggle}from"./kritzel-slide-toggle.js";export{KritzelSplitButton,defineCustomElement as defineCustomElementKritzelSplitButton}from"./kritzel-split-button.js";export{KritzelStrokeSize,defineCustomElement as defineCustomElementKritzelStrokeSize}from"./kritzel-stroke-size.js";export{KritzelToolConfig,defineCustomElement as defineCustomElementKritzelToolConfig}from"./kritzel-tool-config.js";export{KritzelTooltip,defineCustomElement as defineCustomElementKritzelTooltip}from"./kritzel-tooltip.js";export{KritzelUtilityPanel,defineCustomElement as defineCustomElementKritzelUtilityPanel}from"./kritzel-utility-panel.js";export{KritzelWorkspaceManager,defineCustomElement as defineCustomElementKritzelWorkspaceManager}from"./kritzel-workspace-manager.js";const m=Math.floor,u=127,z=Number.MAX_SAFE_INTEGER;class p{constructor(){this.cpos=0,this.cbuf=new Uint8Array(100),this.bufs=[]}}const E=()=>new p,k=e=>{const t=new Uint8Array((e=>{let t=e.cpos;for(let s=0;s<e.bufs.length;s++)t+=e.bufs[s].length;return t})(e));let s=0;for(let i=0;i<e.bufs.length;i++){const o=e.bufs[i];t.set(o,s),s+=o.length}return t.set(new Uint8Array(e.cbuf.buffer,0,e.cpos),s),t},x=(e,t)=>{const s=e.cbuf.length;e.cpos===s&&(e.bufs.push(e.cbuf),e.cbuf=new Uint8Array(2*s),e.cpos=0),e.cbuf[e.cpos++]=t},j=(e,t)=>{for(;t>u;)x(e,128|u&t),t=m(t/128);x(e,u&t)},T=(e,t)=>{j(e,t.byteLength),((e,t)=>{const s=e.cbuf.length,i=e.cpos,o=((e,t)=>e<t?e:t)(s-i,t.length),r=t.length-o;e.cbuf.set(t.subarray(0,o),i),e.cpos+=o,r>0&&(e.bufs.push(e.cbuf),e.cbuf=new Uint8Array(((e,t)=>e>t?e:t)(2*s,r)),e.cbuf.set(t.subarray(o)),e.cpos=r)})(e,t)},y=e=>Error(e),w=y("Unexpected end of array"),P=y("Integer out of Range");class M{constructor(e){this.arr=e,this.pos=0}}const U=e=>((e,t)=>{const s=new Uint8Array(e.arr.buffer,e.pos+e.arr.byteOffset,t);return e.pos+=t,s})(e,_(e)),_=e=>{let t=0,s=1;const i=e.arr.length;for(;e.pos<i;){const i=e.arr[e.pos++];if(t+=(i&u)*s,s*=128,i<128)return t;if(t>z)throw P}throw w};class v{doc;channel;_synced=!1;constructor(e,t,s){this.doc=t,this.channel=new BroadcastChannel(e),this.channel.onmessage=e=>{this.handleMessage(e.data)},this.doc.on("update",this.handleDocUpdate),this.broadcastSync(),setTimeout((()=>{this._synced=!0}),100),s?.quiet||console.info("BroadcastChannel Provider initialized: "+e)}handleDocUpdate=(e,t)=>{if(t!==this){const t=E();j(t,0),T(t,e),this.channel.postMessage(k(t))}};handleMessage(e){const s=(e=>new M(e))(new Uint8Array(e));switch(_(s)){case 0:const e=U(s);t.applyUpdate(this.doc,e,this);break;case 1:this.broadcastSync();break;case 2:const i=U(s),o=t.encodeStateAsUpdate(this.doc,i);if(o.length>0){const e=E();j(e,0),T(e,o),this.channel.postMessage(k(e))}}}broadcastSync(){const e=E();j(e,2),T(e,t.encodeStateVector(this.doc)),this.channel.postMessage(k(e))}async connect(){if(!this._synced)return new Promise((e=>{const t=()=>{this._synced?e():setTimeout(t,50)};t()}))}disconnect(){}destroy(){this.doc.off("update",this.handleDocUpdate),this.channel.close()}}class O{provider;isConnected=!1;_quiet=!1;get awareness(){return this.provider.awareness}constructor(e,t,s){const o=s?.url||"ws://localhost:1234",r=s?.roomName||e;this.provider=new i(o,r,t,{params:s?.params,protocols:s?.protocols,WebSocketPolyfill:s?.WebSocketPolyfill,awareness:s?.awareness,maxBackoffTime:s?.maxBackoffTime,disableBc:!0}),this._quiet=s?.quiet??!1,this.setupEventListeners(),this._quiet||console.info(`WebSocket Provider initialized: ${o}/${r}`)}static with(e){return{create:(t,s,i)=>{const o=i?{...e,...i}:e;return new O(t,s,o)}}}setupEventListeners(){this.provider.on("status",(({status:e})=>{"connected"===e?(this.isConnected=!0,this._quiet||console.info("WebSocket connected")):"disconnected"===e&&(this.isConnected=!1,this._quiet||console.info("WebSocket disconnected"))})),this.provider.on("sync",(e=>{e&&!this._quiet&&console.info("WebSocket synced")}))}async connect(){if(!this.isConnected)return new Promise(((e,t)=>{const s=setTimeout((()=>{t(Error("WebSocket connection timeout"))}),1e4),i=({status:t})=>{"connected"===t&&(clearTimeout(s),this.provider.off("status",i),this.isConnected=!0,e())};this.provider.on("status",i),this.provider.wsconnected&&(clearTimeout(s),this.provider.off("status",i),this.isConnected=!0,e())}))}disconnect(){this.provider&&this.provider.disconnect(),this.isConnected=!1}destroy(){this.provider&&this.provider.destroy(),this.isConnected=!1}}class R{provider;isConnected=!1;isSynced=!1;usesSharedSocket=!1;isDestroyed=!1;connectTimeout=null;pendingConnectReject=null;get awareness(){return this.provider.awareness}static sharedWebSocketProvider=null;constructor(e,t,s){const i=s?.name||e,r=s?.url||"ws://localhost:1234",n=s?.websocketProvider||R.sharedWebSocketProvider;if(n){this.usesSharedSocket=!0;const e={websocketProvider:n,name:i,document:t,token:s?.token||null,onStatus:e=>{s?.onStatus&&s.onStatus(e)},onConnect:()=>{this.isConnected||this.isDestroyed||(this.isConnected=!0,s?.quiet||console.info("Hocuspocus connected: "+i),s?.onConnect&&s.onConnect())},onDisconnect:()=>{this.isDestroyed||!this.isConnected&&!this.isSynced||(this.isConnected=!1,this.isSynced=!1,s?.quiet||console.info("Hocuspocus disconnected: "+i),s?.onDisconnect&&s.onDisconnect())},onSynced:()=>{this.isSynced||this.isDestroyed||(this.isSynced=!0,s?.quiet||console.info("Hocuspocus synced: "+i),s?.onSynced&&s.onSynced())}};void 0!==s?.forceSyncInterval&&(e.forceSyncInterval=s.forceSyncInterval),s?.onAuthenticationFailed&&(e.onAuthenticationFailed=s.onAuthenticationFailed),this.provider=new o(e),this.provider.attach(),s?.quiet||console.info("Hocuspocus Provider initialized (multiplexed): "+i)}else{this.usesSharedSocket=!1;const e={url:r,name:i,document:t,token:s?.token||null,autoConnect:!1,onStatus:e=>{s?.onStatus&&s.onStatus(e)},onConnect:()=>{this.isConnected||this.isDestroyed||(this.isConnected=!0,s?.quiet||console.info("Hocuspocus connected: "+i),s?.onConnect&&s.onConnect())},onDisconnect:()=>{this.isDestroyed||!this.isConnected&&!this.isSynced||(this.isConnected=!1,this.isSynced=!1,s?.quiet||console.info("Hocuspocus disconnected: "+i),s?.onDisconnect&&s.onDisconnect())},onSynced:()=>{this.isSynced||this.isDestroyed||(this.isSynced=!0,s?.quiet||console.info("Hocuspocus synced: "+i),s?.onSynced&&s.onSynced())}};void 0!==s?.forceSyncInterval&&(e.forceSyncInterval=s.forceSyncInterval),s?.onAuthenticationFailed&&(e.onAuthenticationFailed=s.onAuthenticationFailed),s?.WebSocketPolyfill&&(e.WebSocketPolyfill=s.WebSocketPolyfill),this.provider=new o(e),s?.quiet||console.info(`Hocuspocus Provider initialized: ${r}/${i}`)}}static createSharedWebSocket(e){if(R.sharedWebSocketProvider)return console.warn("Shared WebSocket already exists. Returning existing instance."),R.sharedWebSocketProvider;const t={url:e.url};return e.WebSocketPolyfill&&(t.WebSocketPolyfill=e.WebSocketPolyfill),e.onConnect&&(t.onConnect=e.onConnect),e.onDisconnect&&(t.onDisconnect=e.onDisconnect),e.onStatus&&(t.onStatus=e.onStatus),R.sharedWebSocketProvider=new n(t),console.info("Shared Hocuspocus WebSocket created: "+e.url),R.sharedWebSocketProvider}static destroySharedWebSocket(){R.sharedWebSocketProvider&&(R.sharedWebSocketProvider.destroy(),R.sharedWebSocketProvider=null,console.info("Shared Hocuspocus WebSocket destroyed"))}static getSharedWebSocket(){return R.sharedWebSocketProvider}static with(e){return{create:(t,s,i)=>{const o=i?{...e,...i}:e;return new R(t,s,o)}}}async connect(){if(!this.isSynced&&!this.isDestroyed)return new Promise(((e,t)=>{this.pendingConnectReject=t,this.connectTimeout=setTimeout((()=>{this.pendingConnectReject=null,this.connectTimeout=null,t(Error("Hocuspocus connection timeout"))}),1e4);const s=()=>{this.connectTimeout&&(clearTimeout(this.connectTimeout),this.connectTimeout=null),this.pendingConnectReject=null,this.provider.off("synced",s),this.isDestroyed||e()};if(this.provider.on("synced",s),this.provider.isSynced)return this.connectTimeout&&(clearTimeout(this.connectTimeout),this.connectTimeout=null),this.pendingConnectReject=null,this.provider.off("synced",s),void e();this.isConnected||this.usesSharedSocket||this.provider.connect()}))}disconnect(){this.connectTimeout&&(clearTimeout(this.connectTimeout),this.connectTimeout=null),this.pendingConnectReject&&(this.pendingConnectReject=null),this.provider&&(this.usesSharedSocket?this.provider.detach():this.provider.disconnect()),this.isConnected=!1,this.isSynced=!1}destroy(){this.isDestroyed=!0,this.connectTimeout&&(clearTimeout(this.connectTimeout),this.connectTimeout=null),this.pendingConnectReject&&(this.pendingConnectReject=null),this.provider&&this.provider.destroy(),this.isConnected=!1,this.isSynced=!1}}export{v as BroadcastSyncProvider,R as HocuspocusSyncProvider,O as WebSocketSyncProvider}
1
+ export{g as getAssetPath,r as render,s as setAssetPath,a as setNonce,b as setPlatformOptions}from"./p-pebXO4LU.js";export{d as KritzelBrushTool,b as KritzelGroup,a as KritzelImage,e as KritzelLineTool,h as KritzelSelectionTool,c as KritzelShape,g as KritzelShapeTool,K as KritzelText,f as KritzelTextTool,S as ShapeType}from"./p-CJ2eHeoV.js";export{a as KritzelLine,K as KritzelPath}from"./p-DXpYcAnT.js";export{A as APP_STATE_MIGRATIONS,I as IndexedDBSyncProvider,d as KritzelAlignment,c as KritzelAnchorManager,b as KritzelCursorHelper,K as KritzelEraserTool,a as KritzelImageTool,W as WORKSPACE_MIGRATIONS,r as runMigrations}from"./p-jdYmu4SA.js";import*as t from"yjs";import{WebsocketProvider as i}from"y-websocket";import{H as n,a as o}from"./kritzel-editor.js";export{D as DEFAULT_BRUSH_CONFIG,c as DEFAULT_LINE_TOOL_CONFIG,b as DEFAULT_TEXT_CONFIG,KritzelEditor,defineCustomElement as defineCustomElementKritzelEditor}from"./kritzel-editor.js";export{K as KritzelWorkspace,W as WORKSPACE_EXPORT_VERSION}from"./p-DhMlShij.js";export{K as KritzelThemeManager,d as darkTheme,l as lightTheme}from"./p-CjazGGq3.js";export{C as CURRENT_APP_STATE_SCHEMA_VERSION,a as CURRENT_WORKSPACE_SCHEMA_VERSION}from"./p-CW-VyJgK.js";export{KritzelActiveUsers,defineCustomElement as defineCustomElementKritzelActiveUsers}from"./kritzel-active-users.js";export{KritzelAvatar,defineCustomElement as defineCustomElementKritzelAvatar}from"./kritzel-avatar.js";export{KritzelAwarenessCursors,defineCustomElement as defineCustomElementKritzelAwarenessCursors}from"./kritzel-awareness-cursors.js";export{KritzelBackToContent,defineCustomElement as defineCustomElementKritzelBackToContent}from"./kritzel-back-to-content.js";export{KritzelBrushStyle,defineCustomElement as defineCustomElementKritzelBrushStyle}from"./kritzel-brush-style.js";export{KritzelButton,defineCustomElement as defineCustomElementKritzelButton}from"./kritzel-button.js";export{KritzelColor,defineCustomElement as defineCustomElementKritzelColor}from"./kritzel-color.js";export{KritzelColorPalette,defineCustomElement as defineCustomElementKritzelColorPalette}from"./kritzel-color-palette.js";export{KritzelContextMenu,defineCustomElement as defineCustomElementKritzelContextMenu}from"./kritzel-context-menu.js";export{KritzelControls,defineCustomElement as defineCustomElementKritzelControls}from"./kritzel-controls.js";export{KritzelCurrentUser,defineCustomElement as defineCustomElementKritzelCurrentUser}from"./kritzel-current-user.js";export{KritzelCurrentUserDialog,defineCustomElement as defineCustomElementKritzelCurrentUserDialog}from"./kritzel-current-user-dialog.js";export{KritzelCursorTrail,defineCustomElement as defineCustomElementKritzelCursorTrail}from"./kritzel-cursor-trail.js";export{KritzelDialog,defineCustomElement as defineCustomElementKritzelDialog}from"./kritzel-dialog.js";export{KritzelDropdown,defineCustomElement as defineCustomElementKritzelDropdown}from"./kritzel-dropdown.js";export{KritzelEngine,defineCustomElement as defineCustomElementKritzelEngine}from"./kritzel-engine.js";export{KritzelExport,defineCustomElement as defineCustomElementKritzelExport}from"./kritzel-export.js";export{KritzelFont,defineCustomElement as defineCustomElementKritzelFont}from"./kritzel-font.js";export{KritzelFontFamily,defineCustomElement as defineCustomElementKritzelFontFamily}from"./kritzel-font-family.js";export{KritzelFontSize,defineCustomElement as defineCustomElementKritzelFontSize}from"./kritzel-font-size.js";export{KritzelIcon,defineCustomElement as defineCustomElementKritzelIcon}from"./kritzel-icon.js";export{KritzelInput,defineCustomElement as defineCustomElementKritzelInput}from"./kritzel-input.js";export{KritzelLineEndings,defineCustomElement as defineCustomElementKritzelLineEndings}from"./kritzel-line-endings.js";export{KritzelLoginDialog,defineCustomElement as defineCustomElementKritzelLoginDialog}from"./kritzel-login-dialog.js";export{KritzelMasterDetail,defineCustomElement as defineCustomElementKritzelMasterDetail}from"./kritzel-master-detail.js";export{KritzelMenu,defineCustomElement as defineCustomElementKritzelMenu}from"./kritzel-menu.js";export{KritzelMenuItem,defineCustomElement as defineCustomElementKritzelMenuItem}from"./kritzel-menu-item.js";export{KritzelMoreMenu,defineCustomElement as defineCustomElementKritzelMoreMenu}from"./kritzel-more-menu.js";export{KritzelNumericInput,defineCustomElement as defineCustomElementKritzelNumericInput}from"./kritzel-numeric-input.js";export{KritzelOpacitySlider,defineCustomElement as defineCustomElementKritzelOpacitySlider}from"./kritzel-opacity-slider.js";export{KritzelPillTabs,defineCustomElement as defineCustomElementKritzelPillTabs}from"./kritzel-pill-tabs.js";export{KritzelPortal,defineCustomElement as defineCustomElementKritzelPortal}from"./kritzel-portal.js";export{KritzelSettings,defineCustomElement as defineCustomElementKritzelSettings}from"./kritzel-settings.js";export{KritzelShapeFill,defineCustomElement as defineCustomElementKritzelShapeFill}from"./kritzel-shape-fill.js";export{KritzelShareDialog,defineCustomElement as defineCustomElementKritzelShareDialog}from"./kritzel-share-dialog.js";export{KritzelSlideToggle,defineCustomElement as defineCustomElementKritzelSlideToggle}from"./kritzel-slide-toggle.js";export{KritzelSplitButton,defineCustomElement as defineCustomElementKritzelSplitButton}from"./kritzel-split-button.js";export{KritzelStrokeSize,defineCustomElement as defineCustomElementKritzelStrokeSize}from"./kritzel-stroke-size.js";export{KritzelToolConfig,defineCustomElement as defineCustomElementKritzelToolConfig}from"./kritzel-tool-config.js";export{KritzelTooltip,defineCustomElement as defineCustomElementKritzelTooltip}from"./kritzel-tooltip.js";export{KritzelUtilityPanel,defineCustomElement as defineCustomElementKritzelUtilityPanel}from"./kritzel-utility-panel.js";export{KritzelWorkspaceManager,defineCustomElement as defineCustomElementKritzelWorkspaceManager}from"./kritzel-workspace-manager.js";const m=Math.floor,u=127,z=Number.MAX_SAFE_INTEGER;class p{constructor(){this.cpos=0,this.cbuf=new Uint8Array(100),this.bufs=[]}}const E=()=>new p,k=e=>{const t=new Uint8Array((e=>{let t=e.cpos;for(let s=0;s<e.bufs.length;s++)t+=e.bufs[s].length;return t})(e));let s=0;for(let i=0;i<e.bufs.length;i++){const n=e.bufs[i];t.set(n,s),s+=n.length}return t.set(new Uint8Array(e.cbuf.buffer,0,e.cpos),s),t},x=(e,t)=>{const s=e.cbuf.length;e.cpos===s&&(e.bufs.push(e.cbuf),e.cbuf=new Uint8Array(2*s),e.cpos=0),e.cbuf[e.cpos++]=t},y=(e,t)=>{for(;t>u;)x(e,128|u&t),t=m(t/128);x(e,u&t)},j=(e,t)=>{y(e,t.byteLength),((e,t)=>{const s=e.cbuf.length,i=e.cpos,n=((e,t)=>e<t?e:t)(s-i,t.length),o=t.length-n;e.cbuf.set(t.subarray(0,n),i),e.cpos+=n,o>0&&(e.bufs.push(e.cbuf),e.cbuf=new Uint8Array(((e,t)=>e>t?e:t)(2*s,o)),e.cbuf.set(t.subarray(n)),e.cpos=o)})(e,t)},T=e=>Error(e),w=T("Unexpected end of array"),v=T("Integer out of Range");class P{constructor(e){this.arr=e,this.pos=0}}const M=e=>((e,t)=>{const s=new Uint8Array(e.arr.buffer,e.pos+e.arr.byteOffset,t);return e.pos+=t,s})(e,U(e)),U=e=>{let t=0,s=1;const i=e.arr.length;for(;e.pos<i;){const i=e.arr[e.pos++];if(t+=(i&u)*s,s*=128,i<128)return t;if(t>z)throw v}throw w};class _{type="local";doc;channel;_synced=!1;constructor(e,t,s){this.doc=t,this.channel=new BroadcastChannel(e),this.channel.onmessage=e=>{this.handleMessage(e.data)},this.doc.on("update",this.handleDocUpdate),this.broadcastSync(),setTimeout((()=>{this._synced=!0}),100),s?.quiet||console.info("BroadcastChannel Provider initialized: "+e)}handleDocUpdate=(e,t)=>{if(t!==this){const t=E();y(t,0),j(t,e),this.channel.postMessage(k(t))}};handleMessage(e){const s=(e=>new P(e))(new Uint8Array(e));switch(U(s)){case 0:const e=M(s);t.applyUpdate(this.doc,e,this);break;case 1:this.broadcastSync();break;case 2:const i=M(s),n=t.encodeStateAsUpdate(this.doc,i);if(n.length>0){const e=E();y(e,0),j(e,n),this.channel.postMessage(k(e))}}}broadcastSync(){const e=E();y(e,2),j(e,t.encodeStateVector(this.doc)),this.channel.postMessage(k(e))}async connect(){if(!this._synced)return new Promise((e=>{const t=()=>{this._synced?e():setTimeout(t,50)};t()}))}disconnect(){}async reconnect(){return this.disconnect(),this.connect()}destroy(){this.doc.off("update",this.handleDocUpdate),this.channel.close()}}class O{type="network";provider;isConnected=!1;_quiet=!1;get awareness(){return this.provider.awareness}constructor(e,t,s){const n=s?.url||"ws://localhost:1234",o=s?.roomName||e;this.provider=new i(n,o,t,{params:s?.params,protocols:s?.protocols,WebSocketPolyfill:s?.WebSocketPolyfill,awareness:s?.awareness,maxBackoffTime:s?.maxBackoffTime,disableBc:!0}),this._quiet=s?.quiet??!1,this.setupEventListeners(),this._quiet||console.info(`WebSocket Provider initialized: ${n}/${o}`)}static with(e){return{create:(t,s,i)=>{const n=i?{...e,...i}:e;return new O(t,s,n)}}}setupEventListeners(){this.provider.on("status",(({status:e})=>{"connected"===e?(this.isConnected=!0,this._quiet||console.info("WebSocket connected")):"disconnected"===e&&(this.isConnected=!1,this._quiet||console.info("WebSocket disconnected"))})),this.provider.on("sync",(e=>{e&&!this._quiet&&console.info("WebSocket synced")}))}async connect(){if(!this.isConnected)return new Promise(((e,t)=>{const s=setTimeout((()=>{t(Error("WebSocket connection timeout"))}),1e4),i=({status:t})=>{"connected"===t&&(clearTimeout(s),this.provider.off("status",i),this.isConnected=!0,e())};this.provider.on("status",i),this.provider.wsconnected&&(clearTimeout(s),this.provider.off("status",i),this.isConnected=!0,e())}))}disconnect(){this.provider&&this.provider.disconnect(),this.isConnected=!1}async reconnect(){return this.disconnect(),this.connect()}destroy(){this.provider&&this.provider.destroy(),this.isConnected=!1}}class B{type="network";provider;isConnected=!1;isSynced=!1;usesSharedSocket=!1;isDestroyed=!1;connectTimeout=null;pendingConnectReject=null;connectionTimeoutMs;_connectionStatus="disconnected";visibilityHandler=null;onlineHandler=null;get awareness(){return this.provider.awareness}get connectionStatus(){return this._connectionStatus}static sharedWebSocketProvider=null;constructor(e,t,s){const i=s?.name||e,o=s?.url||"ws://localhost:1234";this.connectionTimeoutMs=s?.connectionTimeout??1e4;const r=s?.websocketProvider||B.sharedWebSocketProvider,l={};void 0!==s?.delay&&(l.delay=s.delay),void 0!==s?.factor&&(l.factor=s.factor),void 0!==s?.maxAttempts&&(l.maxAttempts=s.maxAttempts),void 0!==s?.minDelay&&(l.minDelay=s.minDelay),void 0!==s?.maxDelay&&(l.maxDelay=s.maxDelay);const m=()=>{this.isDestroyed||(this.isConnected=!0,this._connectionStatus="connected",s?.quiet||console.info("Hocuspocus connected: "+i),s?.onConnect&&s.onConnect())},a=()=>{this.isDestroyed||(this.isConnected=!1,this.isSynced=!1,this._connectionStatus="disconnected",s?.quiet||console.info("Hocuspocus disconnected: "+i),s?.onDisconnect&&s.onDisconnect())},c=()=>{this.isDestroyed||(this.isSynced=!0,this._connectionStatus="synced",s?.quiet||console.info("Hocuspocus synced: "+i),s?.onSynced&&s.onSynced())},u=e=>{this.isDestroyed||("connecting"===e.status&&(this._connectionStatus="connecting"),s?.onStatus&&s.onStatus(e))};if(r){this.usesSharedSocket=!0;const e={websocketProvider:r,name:i,document:t,token:s?.token||null,onStatus:u,onConnect:m,onDisconnect:a,onSynced:c,...l};void 0!==s?.forceSyncInterval&&(e.forceSyncInterval=s.forceSyncInterval),s?.onAuthenticationFailed&&(e.onAuthenticationFailed=s.onAuthenticationFailed),this.provider=new n(e),this.provider.attach(),s?.quiet||console.info("Hocuspocus Provider initialized (multiplexed): "+i)}else{this.usesSharedSocket=!1;const e={url:o,name:i,document:t,token:s?.token||null,autoConnect:!1,onStatus:u,onConnect:m,onDisconnect:a,onSynced:c,...l};void 0!==s?.forceSyncInterval&&(e.forceSyncInterval=s.forceSyncInterval),s?.onAuthenticationFailed&&(e.onAuthenticationFailed=s.onAuthenticationFailed),s?.WebSocketPolyfill&&(e.WebSocketPolyfill=s.WebSocketPolyfill),this.provider=new n(e),s?.quiet||console.info(`Hocuspocus Provider initialized: ${o}/${i}`)}this.setupBrowserEventListeners()}setupBrowserEventListeners(){"undefined"!=typeof document&&(this.visibilityHandler=()=>{"visible"!==document.visibilityState||this.isConnected||this.isDestroyed||this.provider.connect()},document.addEventListener("visibilitychange",this.visibilityHandler)),"undefined"!=typeof window&&(this.onlineHandler=()=>{this.isConnected||this.isDestroyed||this.provider.connect()},window.addEventListener("online",this.onlineHandler))}removeBrowserEventListeners(){this.visibilityHandler&&"undefined"!=typeof document&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=null),this.onlineHandler&&"undefined"!=typeof window&&(window.removeEventListener("online",this.onlineHandler),this.onlineHandler=null)}static createSharedWebSocket(e){if(B.sharedWebSocketProvider)return console.warn("Shared WebSocket already exists. Returning existing instance."),B.sharedWebSocketProvider;const t={url:e.url};return e.WebSocketPolyfill&&(t.WebSocketPolyfill=e.WebSocketPolyfill),e.onConnect&&(t.onConnect=e.onConnect),e.onDisconnect&&(t.onDisconnect=e.onDisconnect),e.onStatus&&(t.onStatus=e.onStatus),B.sharedWebSocketProvider=new o(t),console.info("Shared Hocuspocus WebSocket created: "+e.url),B.sharedWebSocketProvider}static destroySharedWebSocket(){B.sharedWebSocketProvider&&(B.sharedWebSocketProvider.destroy(),B.sharedWebSocketProvider=null,console.info("Shared Hocuspocus WebSocket destroyed"))}static getSharedWebSocket(){return B.sharedWebSocketProvider}static with(e){return{create:(t,s,i)=>{const n=i?{...e,...i}:e;return new B(t,s,n)}}}async connect(){if(!this.isSynced&&!this.isDestroyed)return this._connectionStatus="connecting",new Promise(((e,t)=>{this.pendingConnectReject=t,this.connectTimeout=setTimeout((()=>{this.pendingConnectReject=null,this.connectTimeout=null,t(Error("Hocuspocus connection timeout"))}),this.connectionTimeoutMs);const s=()=>{this.connectTimeout&&(clearTimeout(this.connectTimeout),this.connectTimeout=null),this.pendingConnectReject=null,this.provider.off("synced",s),this.isDestroyed||e()};if(this.provider.on("synced",s),this.provider.isSynced)return this.connectTimeout&&(clearTimeout(this.connectTimeout),this.connectTimeout=null),this.pendingConnectReject=null,this.provider.off("synced",s),void e();this.isConnected||this.usesSharedSocket||this.provider.connect()}))}async reconnect(){return this.disconnect(),this.connect()}disconnect(){this.connectTimeout&&(clearTimeout(this.connectTimeout),this.connectTimeout=null),this.pendingConnectReject&&(this.pendingConnectReject=null),this.provider&&(this.usesSharedSocket?this.provider.detach():this.provider.disconnect()),this.isConnected=!1,this.isSynced=!1,this._connectionStatus="disconnected"}destroy(){this.isDestroyed=!0,this.connectTimeout&&(clearTimeout(this.connectTimeout),this.connectTimeout=null),this.pendingConnectReject&&(this.pendingConnectReject=null),this.removeBrowserEventListeners(),this.provider&&this.provider.destroy(),this.isConnected=!1,this.isSynced=!1,this._connectionStatus="disconnected"}}export{_ as BroadcastSyncProvider,B as HocuspocusSyncProvider,O as WebSocketSyncProvider}
@@ -1 +1 @@
1
- import{K as o,d as p}from"./p-BSipRoFx.js";const s=o,r=p;export{s as KritzelAwarenessCursors,r as defineCustomElement}
1
+ import{K as o,d as s}from"./p-xNwOWoiT.js";const p=o,r=s;export{p as KritzelAwarenessCursors,r as defineCustomElement}