kritzel-stencil 0.1.76 → 0.1.77

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 (40) hide show
  1. package/dist/cjs/index.cjs.js +2 -330
  2. package/dist/cjs/kritzel-active-users_42.cjs.entry.js +36 -18
  3. package/dist/cjs/{workspace.migrations-DkmVO6dE.js → workspace.migrations-OULs44dI.js} +331 -2
  4. package/dist/collection/classes/objects/selection-group.class.js +2 -0
  5. package/dist/collection/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.css +6 -1
  6. package/dist/collection/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.js +5 -2
  7. package/dist/collection/components/core/kritzel-editor/kritzel-editor.css +2 -0
  8. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +12 -6
  9. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +18 -8
  10. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.css +1 -0
  11. package/dist/collection/constants/version.js +1 -1
  12. package/dist/components/index.js +1 -1
  13. package/dist/components/kritzel-awareness-cursors.js +1 -1
  14. package/dist/components/kritzel-controls.js +1 -1
  15. package/dist/components/kritzel-editor.js +1 -1
  16. package/dist/components/kritzel-engine.js +1 -1
  17. package/dist/components/kritzel-settings.js +1 -1
  18. package/dist/components/kritzel-tool-config.js +1 -1
  19. package/dist/components/kritzel-utility-panel.js +1 -1
  20. package/dist/components/{p-DvIEvoZu.js → p-BK1hLBTd.js} +1 -1
  21. package/dist/components/{p-jdYmu4SA.js → p-BdGcOXa5.js} +2 -2
  22. package/dist/components/{p-CsoDfhD5.js → p-C_X8stam.js} +1 -1
  23. package/dist/components/p-WotNmY5q.js +1 -0
  24. package/dist/components/{p-31FVoNWR.js → p-XS5J5W5_.js} +1 -1
  25. package/dist/components/{p-CJ2eHeoV.js → p-_CqLIbO6.js} +1 -1
  26. package/dist/components/{p-2OYw6GJ7.js → p-_LbtY-TA.js} +1 -1
  27. package/dist/esm/index.js +2 -331
  28. package/dist/esm/kritzel-active-users_42.entry.js +36 -18
  29. package/dist/esm/{workspace.migrations-D48_Bqvh.js → workspace.migrations-D6whgl7G.js} +331 -1
  30. package/dist/stencil/index.esm.js +1 -1
  31. package/dist/stencil/p-8fe1ec39.entry.js +9 -0
  32. package/dist/stencil/p-D6whgl7G.js +1 -0
  33. package/dist/stencil/stencil.esm.js +1 -1
  34. package/dist/types/classes/objects/selection-group.class.d.ts +1 -0
  35. package/dist/types/components.d.ts +8 -2
  36. package/dist/types/constants/version.d.ts +1 -1
  37. package/package.json +1 -1
  38. package/dist/components/p-xNwOWoiT.js +0 -1
  39. package/dist/stencil/p-775a7246.entry.js +0 -9
  40. package/dist/stencil/p-D48_Bqvh.js +0 -1
@@ -18492,6 +18492,7 @@ class KritzelSelectionGroup extends KritzelBaseObject {
18492
18492
  snapshotHeight = 0;
18493
18493
  snapshotTranslateX = 0;
18494
18494
  snapshotTranslateY = 0;
18495
+ clientId;
18495
18496
  minX;
18496
18497
  maxX;
18497
18498
  minY;
@@ -18564,6 +18565,7 @@ class KritzelSelectionGroup extends KritzelBaseObject {
18564
18565
  object.id = object.generateId();
18565
18566
  object.workspaceId = core.store.state.activeWorkspace.id;
18566
18567
  object.userId = core.user?.id;
18568
+ object.clientId = core.store.state.objects?.localClientId ?? undefined;
18567
18569
  object.scale = core.store.state.scale;
18568
18570
  object.zIndex = 99999;
18569
18571
  // Initialize styling with theme-aware defaults
@@ -25224,6 +25226,334 @@ class HocuspocusProvider extends EventEmitter {
25224
25226
  }
25225
25227
  }
25226
25228
 
25229
+ /**
25230
+ * Hocuspocus sync provider for real-time collaboration
25231
+ * Supports multiplexing - multiple documents can share the same WebSocket connection
25232
+ */
25233
+ class HocuspocusSyncProvider {
25234
+ type = 'network';
25235
+ provider;
25236
+ isConnected = false;
25237
+ isSynced = false;
25238
+ usesSharedSocket = false;
25239
+ isDestroyed = false;
25240
+ connectTimeout = null;
25241
+ pendingConnectReject = null;
25242
+ connectionTimeoutMs;
25243
+ _connectionStatus = 'disconnected';
25244
+ visibilityHandler = null;
25245
+ onlineHandler = null;
25246
+ get awareness() {
25247
+ return this.provider.awareness;
25248
+ }
25249
+ get connectionStatus() {
25250
+ return this._connectionStatus;
25251
+ }
25252
+ // Static shared WebSocket instance for multiplexing
25253
+ static sharedWebSocketProvider = null;
25254
+ constructor(docName, doc, options) {
25255
+ const name = options?.name || docName;
25256
+ const url = options?.url || 'ws://localhost:1234';
25257
+ this.connectionTimeoutMs = options?.connectionTimeout ?? 10000;
25258
+ // Use provided websocketProvider or the static shared one
25259
+ const websocketProvider = options?.websocketProvider || HocuspocusSyncProvider.sharedWebSocketProvider;
25260
+ // Build reconnect config from options
25261
+ const reconnectConfig = {};
25262
+ if (options?.delay !== undefined)
25263
+ reconnectConfig.delay = options.delay;
25264
+ if (options?.factor !== undefined)
25265
+ reconnectConfig.factor = options.factor;
25266
+ if (options?.maxAttempts !== undefined)
25267
+ reconnectConfig.maxAttempts = options.maxAttempts;
25268
+ if (options?.minDelay !== undefined)
25269
+ reconnectConfig.minDelay = options.minDelay;
25270
+ if (options?.maxDelay !== undefined)
25271
+ reconnectConfig.maxDelay = options.maxDelay;
25272
+ const onConnect = () => {
25273
+ if (this.isDestroyed) {
25274
+ return;
25275
+ }
25276
+ this.isConnected = true;
25277
+ this._connectionStatus = 'connected';
25278
+ if (!options?.quiet) {
25279
+ console.info(`Hocuspocus connected: ${name}`);
25280
+ }
25281
+ if (options?.onConnect) {
25282
+ options.onConnect();
25283
+ }
25284
+ };
25285
+ const onDisconnect = () => {
25286
+ if (this.isDestroyed) {
25287
+ return;
25288
+ }
25289
+ this.isConnected = false;
25290
+ this.isSynced = false;
25291
+ this._connectionStatus = 'disconnected';
25292
+ if (!options?.quiet) {
25293
+ console.info(`Hocuspocus disconnected: ${name}`);
25294
+ }
25295
+ if (options?.onDisconnect) {
25296
+ options.onDisconnect();
25297
+ }
25298
+ };
25299
+ const onSynced = () => {
25300
+ if (this.isDestroyed) {
25301
+ return;
25302
+ }
25303
+ this.isSynced = true;
25304
+ this._connectionStatus = 'synced';
25305
+ if (!options?.quiet) {
25306
+ console.info(`Hocuspocus synced: ${name}`);
25307
+ }
25308
+ if (options?.onSynced) {
25309
+ options.onSynced();
25310
+ }
25311
+ };
25312
+ const onStatus = (data) => {
25313
+ if (this.isDestroyed) {
25314
+ return;
25315
+ }
25316
+ if (data.status === 'connecting') {
25317
+ this._connectionStatus = 'connecting';
25318
+ }
25319
+ if (options?.onStatus) {
25320
+ options.onStatus(data);
25321
+ }
25322
+ };
25323
+ if (websocketProvider) {
25324
+ // Multiplexing mode - use shared WebSocket connection
25325
+ this.usesSharedSocket = true;
25326
+ const config = {
25327
+ websocketProvider,
25328
+ name,
25329
+ document: doc,
25330
+ token: options?.token || null,
25331
+ onStatus,
25332
+ onConnect,
25333
+ onDisconnect,
25334
+ onSynced,
25335
+ ...reconnectConfig,
25336
+ };
25337
+ // Add optional settings
25338
+ if (options?.forceSyncInterval !== undefined) {
25339
+ config.forceSyncInterval = options.forceSyncInterval;
25340
+ }
25341
+ if (options?.onAuthenticationFailed) {
25342
+ config.onAuthenticationFailed = options.onAuthenticationFailed;
25343
+ }
25344
+ this.provider = new HocuspocusProvider(config);
25345
+ // Must call attach() explicitly when using shared socket
25346
+ this.provider.attach();
25347
+ if (!options?.quiet) {
25348
+ console.info(`Hocuspocus Provider initialized (multiplexed): ${name}`);
25349
+ }
25350
+ }
25351
+ else {
25352
+ // Standalone mode - create own WebSocket connection
25353
+ this.usesSharedSocket = false;
25354
+ const config = {
25355
+ url,
25356
+ name,
25357
+ document: doc,
25358
+ token: options?.token || null,
25359
+ autoConnect: false,
25360
+ onStatus,
25361
+ onConnect,
25362
+ onDisconnect,
25363
+ onSynced,
25364
+ ...reconnectConfig,
25365
+ };
25366
+ // Add optional settings
25367
+ if (options?.forceSyncInterval !== undefined) {
25368
+ config.forceSyncInterval = options.forceSyncInterval;
25369
+ }
25370
+ if (options?.onAuthenticationFailed) {
25371
+ config.onAuthenticationFailed = options.onAuthenticationFailed;
25372
+ }
25373
+ if (options?.WebSocketPolyfill) {
25374
+ config.WebSocketPolyfill = options.WebSocketPolyfill;
25375
+ }
25376
+ this.provider = new HocuspocusProvider(config);
25377
+ if (!options?.quiet) {
25378
+ console.info(`Hocuspocus Provider initialized: ${url}/${name}`);
25379
+ }
25380
+ }
25381
+ this.setupBrowserEventListeners();
25382
+ }
25383
+ setupBrowserEventListeners() {
25384
+ if (typeof document !== 'undefined') {
25385
+ this.visibilityHandler = () => {
25386
+ if (document.visibilityState === 'visible' && !this.isConnected && !this.isDestroyed) {
25387
+ this.provider.connect();
25388
+ }
25389
+ };
25390
+ document.addEventListener('visibilitychange', this.visibilityHandler);
25391
+ }
25392
+ if (typeof window !== 'undefined') {
25393
+ this.onlineHandler = () => {
25394
+ if (!this.isConnected && !this.isDestroyed) {
25395
+ this.provider.connect();
25396
+ }
25397
+ };
25398
+ window.addEventListener('online', this.onlineHandler);
25399
+ }
25400
+ }
25401
+ removeBrowserEventListeners() {
25402
+ if (this.visibilityHandler && typeof document !== 'undefined') {
25403
+ document.removeEventListener('visibilitychange', this.visibilityHandler);
25404
+ this.visibilityHandler = null;
25405
+ }
25406
+ if (this.onlineHandler && typeof window !== 'undefined') {
25407
+ window.removeEventListener('online', this.onlineHandler);
25408
+ this.onlineHandler = null;
25409
+ }
25410
+ }
25411
+ /**
25412
+ * Create a shared WebSocket connection for multiplexing
25413
+ * Call this once to create a shared connection that multiple providers can use
25414
+ */
25415
+ static createSharedWebSocket(options) {
25416
+ if (HocuspocusSyncProvider.sharedWebSocketProvider) {
25417
+ console.warn('Shared WebSocket already exists. Returning existing instance.');
25418
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
25419
+ }
25420
+ const config = {
25421
+ url: options.url,
25422
+ };
25423
+ if (options.WebSocketPolyfill) {
25424
+ config.WebSocketPolyfill = options.WebSocketPolyfill;
25425
+ }
25426
+ if (options.onConnect) {
25427
+ config.onConnect = options.onConnect;
25428
+ }
25429
+ if (options.onDisconnect) {
25430
+ config.onDisconnect = options.onDisconnect;
25431
+ }
25432
+ if (options.onStatus) {
25433
+ config.onStatus = options.onStatus;
25434
+ }
25435
+ HocuspocusSyncProvider.sharedWebSocketProvider = new HocuspocusProviderWebsocket(config);
25436
+ console.info(`Shared Hocuspocus WebSocket created: ${options.url}`);
25437
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
25438
+ }
25439
+ /**
25440
+ * Destroy the shared WebSocket connection
25441
+ * Call this when you're done with all multiplexed providers
25442
+ */
25443
+ static destroySharedWebSocket() {
25444
+ if (HocuspocusSyncProvider.sharedWebSocketProvider) {
25445
+ HocuspocusSyncProvider.sharedWebSocketProvider.destroy();
25446
+ HocuspocusSyncProvider.sharedWebSocketProvider = null;
25447
+ console.info('Shared Hocuspocus WebSocket destroyed');
25448
+ }
25449
+ }
25450
+ /**
25451
+ * Get the shared WebSocket provider instance (if it exists)
25452
+ */
25453
+ static getSharedWebSocket() {
25454
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
25455
+ }
25456
+ /**
25457
+ * Static factory method for creating HocuspocusSyncProvider with configuration options
25458
+ * Returns a ProviderFactory that can be used in sync configuration
25459
+ */
25460
+ static with(options) {
25461
+ return {
25462
+ create: (docName, doc, runtimeOptions) => {
25463
+ const mergedOptions = runtimeOptions ? { ...options, ...runtimeOptions } : options;
25464
+ return new HocuspocusSyncProvider(docName, doc, mergedOptions);
25465
+ },
25466
+ };
25467
+ }
25468
+ async connect() {
25469
+ if (this.isSynced || this.isDestroyed) {
25470
+ return;
25471
+ }
25472
+ this._connectionStatus = 'connecting';
25473
+ return new Promise((resolve, reject) => {
25474
+ // Store reject function so we can cancel the connection if destroyed
25475
+ this.pendingConnectReject = reject;
25476
+ this.connectTimeout = setTimeout(() => {
25477
+ this.pendingConnectReject = null;
25478
+ this.connectTimeout = null;
25479
+ reject(new Error('Hocuspocus connection timeout'));
25480
+ }, this.connectionTimeoutMs);
25481
+ const syncHandler = () => {
25482
+ if (this.connectTimeout) {
25483
+ clearTimeout(this.connectTimeout);
25484
+ this.connectTimeout = null;
25485
+ }
25486
+ this.pendingConnectReject = null;
25487
+ this.provider.off('synced', syncHandler);
25488
+ if (!this.isDestroyed) {
25489
+ resolve();
25490
+ }
25491
+ };
25492
+ this.provider.on('synced', syncHandler);
25493
+ // If already synced, resolve immediately
25494
+ if (this.provider.isSynced) {
25495
+ if (this.connectTimeout) {
25496
+ clearTimeout(this.connectTimeout);
25497
+ this.connectTimeout = null;
25498
+ }
25499
+ this.pendingConnectReject = null;
25500
+ this.provider.off('synced', syncHandler);
25501
+ resolve();
25502
+ return;
25503
+ }
25504
+ // Connect if not already connected (standalone mode only)
25505
+ if (!this.isConnected && !this.usesSharedSocket) {
25506
+ this.provider.connect();
25507
+ }
25508
+ });
25509
+ }
25510
+ async reconnect() {
25511
+ this.disconnect();
25512
+ return this.connect();
25513
+ }
25514
+ disconnect() {
25515
+ // Cancel any pending connection attempt
25516
+ if (this.connectTimeout) {
25517
+ clearTimeout(this.connectTimeout);
25518
+ this.connectTimeout = null;
25519
+ }
25520
+ if (this.pendingConnectReject) {
25521
+ this.pendingConnectReject = null; // Don't reject, just abandon the promise
25522
+ }
25523
+ if (this.provider) {
25524
+ if (this.usesSharedSocket) {
25525
+ // Detach from shared socket instead of disconnecting
25526
+ this.provider.detach();
25527
+ }
25528
+ else {
25529
+ this.provider.disconnect();
25530
+ }
25531
+ }
25532
+ this.isConnected = false;
25533
+ this.isSynced = false;
25534
+ this._connectionStatus = 'disconnected';
25535
+ }
25536
+ destroy() {
25537
+ // Mark as destroyed first to prevent any callbacks from doing work
25538
+ this.isDestroyed = true;
25539
+ // Cancel any pending connection attempt
25540
+ if (this.connectTimeout) {
25541
+ clearTimeout(this.connectTimeout);
25542
+ this.connectTimeout = null;
25543
+ }
25544
+ if (this.pendingConnectReject) {
25545
+ this.pendingConnectReject = null; // Don't reject, just abandon the promise
25546
+ }
25547
+ this.removeBrowserEventListeners();
25548
+ if (this.provider) {
25549
+ this.provider.destroy();
25550
+ }
25551
+ this.isConnected = false;
25552
+ this.isSynced = false;
25553
+ this._connectionStatus = 'disconnected';
25554
+ }
25555
+ }
25556
+
25227
25557
  /** Current version of the workspace export format */
25228
25558
  const WORKSPACE_EXPORT_VERSION = '1.2.0';
25229
25559
  /**
@@ -26882,8 +27212,7 @@ exports.DEFAULT_BRUSH_CONFIG = DEFAULT_BRUSH_CONFIG;
26882
27212
  exports.DEFAULT_COLOR_PALETTE = DEFAULT_COLOR_PALETTE;
26883
27213
  exports.DEFAULT_LINE_TOOL_CONFIG = DEFAULT_LINE_TOOL_CONFIG;
26884
27214
  exports.DEFAULT_TEXT_CONFIG = DEFAULT_TEXT_CONFIG;
26885
- exports.HocuspocusProvider = HocuspocusProvider;
26886
- exports.HocuspocusProviderWebsocket = HocuspocusProviderWebsocket;
27215
+ exports.HocuspocusSyncProvider = HocuspocusSyncProvider;
26887
27216
  exports.IndexedDBSyncProvider = IndexedDBSyncProvider;
26888
27217
  exports.KritzelAnchorManager = KritzelAnchorManager;
26889
27218
  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
@@ -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 {
@@ -35,7 +35,11 @@ export class KritzelEditor {
35
35
  showSyncProviderInfo: true,
36
36
  showMigrationInfo: true,
37
37
  };
38
- user;
38
+ user = {
39
+ id: `guest-1`,
40
+ displayName: 'Guest',
41
+ isGuest: false,
42
+ };
39
43
  activeUsers;
40
44
  controls = [
41
45
  {
@@ -180,7 +184,8 @@ export class KritzelEditor {
180
184
  isControlsVisible = true;
181
185
  isUtilityPanelVisible = true;
182
186
  syncConfig = {
183
- providers: [IndexedDBSyncProvider]
187
+ appStateId: 'kritzel-app-test',
188
+ providers: [HocuspocusSyncProvider, IndexedDBSyncProvider]
184
189
  };
185
190
  /** Optional login configuration. When provided, a "Sign in" button is shown that opens a login dialog with the configured providers. */
186
191
  loginConfig;
@@ -697,7 +702,7 @@ export class KritzelEditor {
697
702
  const isLoggedIn = this.isLoggedIn;
698
703
  const shouldShowCurrentUser = isLoggedIn;
699
704
  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 })))));
705
+ return (h(Host, { key: 'b52c23bf28392a0061034c0909aadb7abf4d86a7' }, h("div", { key: '7bf75101bef73a2c8481258060e3236a8ca939b4', class: "top-left-buttons" }, h("kritzel-workspace-manager", { key: '69adc1756e00ed56c9980e78929543ad4ecc7b0e', workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), h("kritzel-back-to-content", { key: 'd802fe454738919d9108a807eb379b2f31e94ab6', visible: this.isBackToContentButtonVisible, onBackToContent: () => this.backToContent() })), h("kritzel-engine", { key: '2d3ce8937285956d978f3947ffa86872e156b04d', 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: '6d9b0640b205143c7dc21572616624ef707cfe06', 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: 'c65f16c40d78d8e3eb585e870e414f496e816e82', class: "top-right-buttons" }, h("kritzel-settings", { key: 'a84d5de344011a32be1b4178acc3a5fff246d702', ref: el => (this.settingsRef = el), shortcuts: this.shortcuts, editorId: this.editorId, onSettingsChange: event => this.handleSettingsChange(event) }), h("kritzel-export", { key: '67748d0376f4e7ac39edfc61c1c2cd639664ad78', 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: '1155b8784de2353ae208a2910844bad1e945a891', users: this.activeUsers }), shouldShowCurrentUser && h("kritzel-current-user", { key: 'fb8951eed7f7f5c9117bb0027e9af1aae95088ed', user: this.user }), shouldShowLoginButton && h("kritzel-button", { key: 'd4288b1577082c207696331de4d9fcb1e749fa2a', onButtonClick: () => this.loginDialogRef?.open() }, "Sign in"), h("kritzel-more-menu", { key: '66f0990868bf034a172e6e8db3162a1af0637cf8', items: this.moreMenuItems }), h("kritzel-share-dialog", { key: 'ce3ab2b6db71bf0a4998c16f04521ee39c1715b7', ref: el => (this.shareDialogRef = el), isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: 'd3ec7461c2e6a8fcdac4ce13a51f80835888cb44', ref: el => (this.loginDialogRef = el), providers: this.loginConfig.providers, dialogTitle: this.loginConfig.title, subtitle: this.loginConfig.subtitle, onProviderLogin: this.handleProviderLogin })))));
701
706
  }
702
707
  static get is() { return "kritzel-editor"; }
703
708
  static get originalStyleUrls() {
@@ -919,7 +924,8 @@ export class KritzelEditor {
919
924
  "text": ""
920
925
  },
921
926
  "getter": false,
922
- "setter": false
927
+ "setter": false,
928
+ "defaultValue": "{\r\n id: `guest-1`,\r\n displayName: 'Guest',\r\n isGuest: false,\r\n }"
923
929
  },
924
930
  "activeUsers": {
925
931
  "type": "unknown",
@@ -1106,7 +1112,7 @@ export class KritzelEditor {
1106
1112
  },
1107
1113
  "getter": false,
1108
1114
  "setter": false,
1109
- "defaultValue": "{\r\n providers: [IndexedDBSyncProvider]\r\n }"
1115
+ "defaultValue": "{\r\n appStateId: 'kritzel-app-test',\r\n providers: [HocuspocusSyncProvider, IndexedDBSyncProvider]\r\n }"
1110
1116
  },
1111
1117
  "loginConfig": {
1112
1118
  "type": "unknown",
@@ -1542,18 +1542,28 @@ export class KritzelEngine {
1542
1542
  zIndex: (object.zIndex + 2).toString(),
1543
1543
  } }, h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "Id: ", object.id), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "userId: ", object.userId), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "width: ", object.width), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "height: ", object.height), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateX: ", object.translateX), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateY: ", object.translateY), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "rotationDegrees: ", object.rotationDegrees), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "zIndex: ", object.zIndex))), (this.core.displaySelectionGroupUI(object) || this.core.displaySelectionLineUI(object)) &&
1544
1544
  (() => {
1545
- const isRemoteSelection = KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') &&
1546
- object.userId != null &&
1547
- this.core.user?.id != null &&
1548
- object.userId !== this.core.user.id;
1545
+ const isSelectionGroup = KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup');
1546
+ const localClientId = this.core.store.state.objects?.localClientId;
1547
+ const isRemoteSelection = isSelectionGroup && (
1548
+ // Different user
1549
+ (object.userId != null && this.core.user?.id != null && object.userId !== this.core.user.id) ||
1550
+ // Same user but different client (e.g. same account in two browser tabs)
1551
+ (object.clientId != null && localClientId != null && object.clientId !== localClientId));
1549
1552
  let remoteUserColor;
1550
1553
  if (isRemoteSelection) {
1551
1554
  const awarenessStates = this.core.store.state.objects?.awareness?.getStates();
1552
1555
  if (awarenessStates) {
1553
- for (const state of awarenessStates.values()) {
1554
- if (state.user?.id === object.userId) {
1555
- remoteUserColor = state.user.color;
1556
- break;
1556
+ // Try direct lookup by clientId first (most precise)
1557
+ if (isSelectionGroup && object.clientId != null) {
1558
+ remoteUserColor = awarenessStates.get(object.clientId)?.user?.color;
1559
+ }
1560
+ // Fall back to userId match (for selection groups without clientId)
1561
+ if (!remoteUserColor) {
1562
+ for (const state of awarenessStates.values()) {
1563
+ if (state.user?.id === object.userId) {
1564
+ remoteUserColor = state.user.color;
1565
+ break;
1566
+ }
1557
1567
  }
1558
1568
  }
1559
1569
  }
@@ -9,6 +9,7 @@
9
9
  background-color: var(--kritzel-utility-panel-background-color, #e2e2e2);
10
10
  width: fit-content;
11
11
  user-select: none;
12
+ z-index: 10000;
12
13
  }
13
14
 
14
15
  .utility-button {
@@ -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.76';
6
+ export const KRITZEL_VERSION = '0.1.77';
@@ -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-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
+ 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-_CqLIbO6.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-BdGcOXa5.js";import*as t from"yjs";import{WebsocketProvider as i}from"y-websocket";export{D as DEFAULT_BRUSH_CONFIG,b as DEFAULT_LINE_TOOL_CONFIG,a as DEFAULT_TEXT_CONFIG,H as HocuspocusSyncProvider,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 o=Math.floor,n=127,m=Number.MAX_SAFE_INTEGER;class u{constructor(){this.cpos=0,this.cbuf=new Uint8Array(100),this.bufs=[]}}const z=()=>new u,E=e=>{const t=new Uint8Array((e=>{let t=e.cpos;for(let r=0;r<e.bufs.length;r++)t+=e.bufs[r].length;return t})(e));let r=0;for(let s=0;s<e.bufs.length;s++){const i=e.bufs[s];t.set(i,r),r+=i.length}return t.set(new Uint8Array(e.cbuf.buffer,0,e.cpos),r),t},p=(e,t)=>{const r=e.cbuf.length;e.cpos===r&&(e.bufs.push(e.cbuf),e.cbuf=new Uint8Array(2*r),e.cpos=0),e.cbuf[e.cpos++]=t},k=(e,t)=>{for(;t>n;)p(e,128|n&t),t=o(t/128);p(e,n&t)},x=(e,t)=>{k(e,t.byteLength),((e,t)=>{const r=e.cbuf.length,s=e.cpos,i=((e,t)=>e<t?e:t)(r-s,t.length),o=t.length-i;e.cbuf.set(t.subarray(0,i),s),e.cpos+=i,o>0&&(e.bufs.push(e.cbuf),e.cbuf=new Uint8Array(((e,t)=>e>t?e:t)(2*r,o)),e.cbuf.set(t.subarray(i)),e.cpos=o)})(e,t)},j=e=>Error(e),T=j("Unexpected end of array"),y=j("Integer out of Range");class w{constructor(e){this.arr=e,this.pos=0}}const P=e=>((e,t)=>{const r=new Uint8Array(e.arr.buffer,e.pos+e.arr.byteOffset,t);return e.pos+=t,r})(e,M(e)),M=e=>{let t=0,r=1;const s=e.arr.length;for(;e.pos<s;){const s=e.arr[e.pos++];if(t+=(s&n)*r,r*=128,s<128)return t;if(t>m)throw y}throw T};class U{type="local";doc;channel;_synced=!1;constructor(e,t,r){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),r?.quiet||console.info("BroadcastChannel Provider initialized: "+e)}handleDocUpdate=(e,t)=>{if(t!==this){const t=z();k(t,0),x(t,e),this.channel.postMessage(E(t))}};handleMessage(e){const r=(e=>new w(e))(new Uint8Array(e));switch(M(r)){case 0:const e=P(r);t.applyUpdate(this.doc,e,this);break;case 1:this.broadcastSync();break;case 2:const s=P(r),i=t.encodeStateAsUpdate(this.doc,s);if(i.length>0){const e=z();k(e,0),x(e,i),this.channel.postMessage(E(e))}}}broadcastSync(){const e=z();k(e,2),x(e,t.encodeStateVector(this.doc)),this.channel.postMessage(E(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 _{type="network";provider;isConnected=!1;_quiet=!1;get awareness(){return this.provider.awareness}constructor(e,t,r){const s=r?.url||"ws://localhost:1234",o=r?.roomName||e;this.provider=new i(s,o,t,{params:r?.params,protocols:r?.protocols,WebSocketPolyfill:r?.WebSocketPolyfill,awareness:r?.awareness,maxBackoffTime:r?.maxBackoffTime,disableBc:!0}),this._quiet=r?.quiet??!1,this.setupEventListeners(),this._quiet||console.info(`WebSocket Provider initialized: ${s}/${o}`)}static with(e){return{create:(t,r,s)=>{const i=s?{...e,...s}:e;return new _(t,r,i)}}}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 r=setTimeout((()=>{t(Error("WebSocket connection timeout"))}),1e4),s=({status:t})=>{"connected"===t&&(clearTimeout(r),this.provider.off("status",s),this.isConnected=!0,e())};this.provider.on("status",s),this.provider.wsconnected&&(clearTimeout(r),this.provider.off("status",s),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}}export{U as BroadcastSyncProvider,_ as WebSocketSyncProvider}
@@ -1 +1 @@
1
- import{K as o,d as s}from"./p-xNwOWoiT.js";const p=o,r=s;export{p as KritzelAwarenessCursors,r as defineCustomElement}
1
+ import{K as o,d as s}from"./p-WotNmY5q.js";const t=o,m=s;export{t as KritzelAwarenessCursors,m as defineCustomElement}
@@ -1 +1 @@
1
- import{K as o,d as s}from"./p-CsoDfhD5.js";const p=o,r=s;export{p as KritzelControls,r as defineCustomElement}
1
+ import{K as s,d as o}from"./p-C_X8stam.js";const t=s,a=o;export{t as KritzelControls,a as defineCustomElement}