kritzel-stencil 0.2.3 → 0.2.4

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 (38) hide show
  1. package/dist/cjs/index.cjs.js +1 -1
  2. package/dist/cjs/kritzel-active-users_42.cjs.entry.js +55 -7
  3. package/dist/cjs/{workspace.migrations-CYeB_XRB.js → workspace.migrations-B89-6fP-.js} +34 -8
  4. package/dist/collection/classes/core/core.class.js +9 -2
  5. package/dist/collection/classes/handlers/line-handle.handler.js +1 -0
  6. package/dist/collection/classes/handlers/move.handler.js +2 -0
  7. package/dist/collection/classes/handlers/resize.handler.js +2 -0
  8. package/dist/collection/classes/handlers/rotation.handler.js +2 -0
  9. package/dist/collection/classes/structures/object-map.structure.js +44 -3
  10. package/dist/collection/classes/tools/brush-tool.class.js +2 -0
  11. package/dist/collection/classes/tools/eraser-tool.class.js +22 -8
  12. package/dist/collection/classes/tools/line-tool.class.js +2 -0
  13. package/dist/collection/classes/tools/shape-tool.class.js +1 -0
  14. package/dist/collection/constants/version.js +1 -1
  15. package/dist/components/index.js +1 -1
  16. package/dist/components/kritzel-controls.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/kritzel-tool-config.js +1 -1
  21. package/dist/components/{p-yX5Zk5pS.js → p-3YivOJM2.js} +1 -1
  22. package/dist/components/p-B2dVTxsc.js +9 -0
  23. package/dist/components/{p-CdaOQi45.js → p-BabNumqA.js} +1 -1
  24. package/dist/components/{p-BeeKeeeo.js → p-DMYfjC1C.js} +1 -1
  25. package/dist/components/p-Dqpa31TI.js +1 -0
  26. package/dist/esm/index.js +2 -2
  27. package/dist/esm/kritzel-active-users_42.entry.js +55 -7
  28. package/dist/esm/{workspace.migrations-BrA5xRPn.js → workspace.migrations-D_y5zlxK.js} +34 -8
  29. package/dist/stencil/index.esm.js +1 -1
  30. package/dist/stencil/p-74898384.entry.js +9 -0
  31. package/dist/stencil/{p-BrA5xRPn.js → p-D_y5zlxK.js} +1 -1
  32. package/dist/stencil/stencil.esm.js +1 -1
  33. package/dist/types/classes/structures/object-map.structure.d.ts +19 -0
  34. package/dist/types/constants/version.d.ts +1 -1
  35. package/package.json +1 -1
  36. package/dist/components/p-Bs7lEBy5.js +0 -9
  37. package/dist/components/p-C1UNiqO2.js +0 -1
  38. package/dist/stencil/p-56b81681.entry.js +0 -9
package/dist/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { H as HocuspocusProvider, a as HocuspocusProviderWebsocket } from './workspace.migrations-BrA5xRPn.js';
2
- export { E as APP_STATE_MIGRATIONS, A as AssetNotFoundError, C as CURRENT_APP_STATE_SCHEMA_VERSION, z as CURRENT_WORKSPACE_SCHEMA_VERSION, v as DEFAULT_ASSET_STORAGE_CONFIG, D as DEFAULT_BRUSH_CONFIG, u as DEFAULT_LINE_TOOL_CONFIG, t as DEFAULT_TEXT_CONFIG, p as IndexedDBAssetProvider, I as IndexedDBSyncProvider, y as KritzelAlignment, r as KritzelAnchorManager, o as KritzelAssetResolver, g as KritzelBrushTool, m as KritzelCursorHelper, i as KritzelEraserTool, e as KritzelGroup, c as KritzelImage, j as KritzelImageTool, d as KritzelLine, h as KritzelLineTool, b as KritzelPath, n as KritzelSelectionTool, f as KritzelShape, l as KritzelShapeTool, K as KritzelText, k as KritzelTextTool, s as KritzelThemeManager, q as KritzelWorkspace, S as ShapeType, W as WORKSPACE_EXPORT_VERSION, F as WORKSPACE_MIGRATIONS, x as darkTheme, w as lightTheme, B as runMigrations } from './workspace.migrations-BrA5xRPn.js';
1
+ import { H as HocuspocusProvider, a as HocuspocusProviderWebsocket } from './workspace.migrations-D_y5zlxK.js';
2
+ export { E as APP_STATE_MIGRATIONS, A as AssetNotFoundError, C as CURRENT_APP_STATE_SCHEMA_VERSION, z as CURRENT_WORKSPACE_SCHEMA_VERSION, v as DEFAULT_ASSET_STORAGE_CONFIG, D as DEFAULT_BRUSH_CONFIG, u as DEFAULT_LINE_TOOL_CONFIG, t as DEFAULT_TEXT_CONFIG, p as IndexedDBAssetProvider, I as IndexedDBSyncProvider, y as KritzelAlignment, r as KritzelAnchorManager, o as KritzelAssetResolver, g as KritzelBrushTool, m as KritzelCursorHelper, i as KritzelEraserTool, e as KritzelGroup, c as KritzelImage, j as KritzelImageTool, d as KritzelLine, h as KritzelLineTool, b as KritzelPath, n as KritzelSelectionTool, f as KritzelShape, l as KritzelShapeTool, K as KritzelText, k as KritzelTextTool, s as KritzelThemeManager, q as KritzelWorkspace, S as ShapeType, W as WORKSPACE_EXPORT_VERSION, F as WORKSPACE_MIGRATIONS, x as darkTheme, w as lightTheme, B as runMigrations } from './workspace.migrations-D_y5zlxK.js';
3
3
  import * as Y from 'yjs';
4
4
  import { WebsocketProvider } from 'y-websocket';
5
5
  import 'y-indexeddb';
@@ -1,5 +1,5 @@
1
1
  import { r as registerInstance, h, H as Host, c as createEvent, g as getElement } from './index-D9HaikfQ.js';
2
- import { b as KritzelPath, d as KritzelLine, G as KritzelColorHelper, n as KritzelSelectionTool, g as KritzelBrushTool, h as KritzelLineTool, l as KritzelShapeTool, k as KritzelTextTool, J as KritzelDevicesHelper, L as KritzelMouseButton, M as DEFAULT_COLOR_PALETTE, S as ShapeType, I as IndexedDBSyncProvider, D as DEFAULT_BRUSH_CONFIG, i as KritzelEraserTool, u as DEFAULT_LINE_TOOL_CONFIG, t as DEFAULT_TEXT_CONFIG, j as KritzelImageTool, y as KritzelAlignment, v as DEFAULT_ASSET_STORAGE_CONFIG, N as KritzelSelectionGroup, O as KritzelSelectionBox, P as KritzelIconRegistry, Q as KritzelKeyboardHelper, R as KritzelBaseHandler, T as KritzelToolRegistry, U as KritzelBaseObject, q as KritzelWorkspace, e as KritzelGroup, c as KritzelImage, f as KritzelShape, K as KritzelText, B as runMigrations, z as CURRENT_WORKSPACE_SCHEMA_VERSION, F as WORKSPACE_MIGRATIONS, C as CURRENT_APP_STATE_SCHEMA_VERSION, E as APP_STATE_MIGRATIONS, V as ObjectHelper, m as KritzelCursorHelper, r as KritzelAnchorManager, s as KritzelThemeManager, o as KritzelAssetResolver, X as KritzelClassHelper, Y as KritzelEventHelper, Z as KritzelBaseTool, W as WORKSPACE_EXPORT_VERSION } from './workspace.migrations-BrA5xRPn.js';
2
+ import { b as KritzelPath, d as KritzelLine, G as KritzelColorHelper, n as KritzelSelectionTool, g as KritzelBrushTool, h as KritzelLineTool, l as KritzelShapeTool, k as KritzelTextTool, J as KritzelDevicesHelper, L as KritzelMouseButton, M as DEFAULT_COLOR_PALETTE, S as ShapeType, I as IndexedDBSyncProvider, D as DEFAULT_BRUSH_CONFIG, i as KritzelEraserTool, u as DEFAULT_LINE_TOOL_CONFIG, t as DEFAULT_TEXT_CONFIG, j as KritzelImageTool, y as KritzelAlignment, v as DEFAULT_ASSET_STORAGE_CONFIG, N as KritzelSelectionGroup, O as KritzelSelectionBox, P as KritzelIconRegistry, Q as KritzelKeyboardHelper, R as KritzelBaseHandler, T as KritzelToolRegistry, U as KritzelBaseObject, q as KritzelWorkspace, e as KritzelGroup, c as KritzelImage, f as KritzelShape, K as KritzelText, B as runMigrations, z as CURRENT_WORKSPACE_SCHEMA_VERSION, F as WORKSPACE_MIGRATIONS, C as CURRENT_APP_STATE_SCHEMA_VERSION, E as APP_STATE_MIGRATIONS, V as ObjectHelper, m as KritzelCursorHelper, r as KritzelAnchorManager, s as KritzelThemeManager, o as KritzelAssetResolver, X as KritzelClassHelper, Y as KritzelEventHelper, Z as KritzelBaseTool, W as WORKSPACE_EXPORT_VERSION } from './workspace.migrations-D_y5zlxK.js';
3
3
  import * as Y from 'yjs';
4
4
  import 'y-indexeddb';
5
5
  import 'y-websocket';
@@ -21423,6 +21423,12 @@ class KritzelObjectMap {
21423
21423
  * redundant full serializations of every child object per frame.
21424
21424
  */
21425
21425
  _localOnlyMode = false;
21426
+ /**
21427
+ * Tracks whether we're currently executing inside a `transaction()`
21428
+ * callback. While true, `markUndoBoundary()` is a no-op so nested
21429
+ * insert/remove calls don't split the in-progress undo step.
21430
+ */
21431
+ _inTransaction = false;
21426
21432
  /**
21427
21433
  * Indicates whether the object map has been initialized and is ready for use.
21428
21434
  * @returns `true` if providers are connected and the map is operational
@@ -21661,9 +21667,12 @@ class KritzelObjectMap {
21661
21667
  }
21662
21668
  this._providers.push(provider);
21663
21669
  }
21664
- // Set up undo/redo manager for this workspace
21670
+ // captureTimeout is effectively infinite undo-step boundaries are
21671
+ // marked explicitly via markUndoBoundary() in insert/remove/reset and
21672
+ // at stroke/gesture boundaries in the tools. This prevents a single
21673
+ // brush stroke from being split when the user pauses after pointerdown.
21665
21674
  this._undoManager = new Y.UndoManager([this._objectsMap], {
21666
- captureTimeout: 200,
21675
+ captureTimeout: Number.MAX_SAFE_INTEGER,
21667
21676
  trackedOrigins: new Set(['local', 'temporary']),
21668
21677
  ignoreRemoteMapChanges: true,
21669
21678
  });
@@ -21981,8 +21990,34 @@ class KritzelObjectMap {
21981
21990
  */
21982
21991
  transaction(callback) {
21983
21992
  if (this._ydoc) {
21984
- this._ydoc.transact(callback, 'local');
21993
+ this._inTransaction = true;
21994
+ try {
21995
+ this._ydoc.transact(callback, 'local');
21996
+ }
21997
+ finally {
21998
+ this._inTransaction = false;
21999
+ }
22000
+ }
22001
+ }
22002
+ /**
22003
+ * Closes the current undo stack item so the next tracked change starts
22004
+ * a new one. Call at gesture/stroke boundaries (e.g. drag/resize/rotate
22005
+ * end, brush/line/shape stroke end).
22006
+ *
22007
+ * No-op while a transaction() is open.
22008
+ */
22009
+ stopUndoCapturing() {
22010
+ this.markUndoBoundary();
22011
+ }
22012
+ /**
22013
+ * Internal: closes the current undo stack item. No-op while inside a
22014
+ * transaction() so wrapped multi-op work stays a single undo step.
22015
+ */
22016
+ markUndoBoundary() {
22017
+ if (this._inTransaction) {
22018
+ return;
21985
22019
  }
22020
+ this._undoManager?.stopCapturing();
21986
22021
  }
21987
22022
  /**
21988
22023
  * Executes a callback where all update() calls only modify local state
@@ -22047,6 +22082,7 @@ class KritzelObjectMap {
22047
22082
  reset() {
22048
22083
  this.quadtree.reset();
22049
22084
  this._idMap.clear();
22085
+ this.markUndoBoundary();
22050
22086
  this._ydoc?.transact(() => {
22051
22087
  this._objectsMap?.clear();
22052
22088
  }, 'local');
@@ -22067,6 +22103,7 @@ class KritzelObjectMap {
22067
22103
  this._idMap.set(object.id, object);
22068
22104
  if (this._objectsMap && this.isPersistable(object)) {
22069
22105
  const serialized = object.serialize();
22106
+ this.markUndoBoundary();
22070
22107
  this._ydoc?.transact(() => {
22071
22108
  this._objectsMap?.set(object.id, serialized);
22072
22109
  }, 'local');
@@ -22111,6 +22148,10 @@ class KritzelObjectMap {
22111
22148
  */
22112
22149
  remove(predicate) {
22113
22150
  const objectsToRemove = this.quadtree.filter(predicate);
22151
+ if (objectsToRemove.length === 0) {
22152
+ return;
22153
+ }
22154
+ this.markUndoBoundary();
22114
22155
  for (const object of objectsToRemove) {
22115
22156
  this.quadtree.remove(o => o.id === object.id);
22116
22157
  this._idMap.delete(object.id);
@@ -23801,8 +23842,15 @@ class KritzelCore {
23801
23842
  if (!selectionGroup) {
23802
23843
  return;
23803
23844
  }
23804
- selectionGroup.objects.forEach(obj => this.removeObject(obj));
23805
- this.removeSelectionGroup();
23845
+ // Seal the selection group's creation into its own undo step so Yjs
23846
+ // doesn't collapse create+delete of the SG into a no-op on undo.
23847
+ this._store.objects.stopUndoCapturing();
23848
+ this._store.objects.transaction(() => {
23849
+ selectionGroup.objects.forEach(obj => this.removeObject(obj));
23850
+ this.removeSelectionGroup();
23851
+ });
23852
+ // Close the deletion step so subsequent unrelated changes start a new step.
23853
+ this._store.objects.stopUndoCapturing();
23806
23854
  this.engine.emitObjectsInViewportChange();
23807
23855
  this.rerender();
23808
23856
  }
@@ -29019,7 +29067,7 @@ const KritzelPortal = class {
29019
29067
  * This file is auto-generated by the version bump scripts.
29020
29068
  * Do not modify manually.
29021
29069
  */
29022
- const KRITZEL_VERSION = '0.2.3';
29070
+ const KRITZEL_VERSION = '0.2.4';
29023
29071
 
29024
29072
  const kritzelSettingsCss = () => `:host{display:contents}kritzel-dialog{--kritzel-dialog-body-padding:0;--kritzel-dialog-width-large:800px;--kritzel-dialog-height-large:500px}.footer-button{padding:8px 16px;border-radius:6px;cursor:pointer;font-size:14px}.cancel-button{border:1px solid #ebebeb;background:#fff;color:inherit}.cancel-button:hover{background:#f5f5f5}.settings-content{padding:0}.settings-content h3{margin:0 0 16px 0;font-size:18px;font-weight:600;color:var(--kritzel-settings-content-heading-color, #333333)}.settings-content p{margin:0;font-size:14px;color:var(--kritzel-settings-content-text-color, #666666);line-height:1.5}.settings-group{display:flex;flex-direction:column;gap:24px}.settings-item{display:flex;flex-direction:column;gap:8px}.settings-row{display:flex;align-items:center;justify-content:space-between;gap:16px}.settings-label{font-size:14px;font-weight:600;color:var(--kritzel-settings-label-color, #333333);margin:0 0 4px 0}.settings-description{font-size:12px;color:var(--kritzel-settings-description-color, #888888);margin:0;line-height:1.4}.shortcuts-list{display:flex;flex-direction:column;gap:24px}.shortcuts-category{display:flex;flex-direction:column;gap:8px}.shortcuts-category-title{font-size:14px;font-weight:600;color:var(--kritzel-settings-label-color, #333333);margin:0 0 4px 0}.shortcuts-group{display:flex;flex-direction:column;gap:4px}.shortcut-item{display:flex;justify-content:space-between;align-items:center;padding:6px 8px;border-radius:4px;background:var(--kritzel-settings-shortcut-item-bg, rgba(0, 0, 0, 0.02))}.shortcut-label{font-size:14px;color:var(--kritzel-settings-content-text-color, #666666)}.shortcut-key{font-family:monospace;font-size:12px;padding:2px 8px;border-radius:4px;background:var(--kritzel-settings-shortcut-key-bg, #f0f0f0);color:var(--kritzel-settings-shortcut-key-color, #333333);border:1px solid var(--kritzel-settings-shortcut-key-border, #ddd)}`;
29025
29073
 
@@ -19657,6 +19657,7 @@ class KritzelBrushTool extends KritzelBaseTool {
19657
19657
  }
19658
19658
  this._core.store.objects?.setActiveDrawingObject(null);
19659
19659
  this._currentPathId = null;
19660
+ this._core.store.objects?.stopUndoCapturing();
19660
19661
  }
19661
19662
  }
19662
19663
  }
@@ -19673,6 +19674,7 @@ class KritzelBrushTool extends KritzelBaseTool {
19673
19674
  }
19674
19675
  this._core.store.objects?.setActiveDrawingObject(null);
19675
19676
  this._currentPathId = null;
19677
+ this._core.store.objects?.stopUndoCapturing();
19676
19678
  }
19677
19679
  }
19678
19680
  }
@@ -20504,6 +20506,7 @@ class KritzelLineTool extends KritzelBaseTool {
20504
20506
  }
20505
20507
  this._core.store.objects?.setActiveDrawingObject(null);
20506
20508
  this._currentLineId = null;
20509
+ this._core.store.objects?.stopUndoCapturing();
20507
20510
  }
20508
20511
  }
20509
20512
  }
@@ -20522,6 +20525,7 @@ class KritzelLineTool extends KritzelBaseTool {
20522
20525
  }
20523
20526
  this._core.store.objects?.setActiveDrawingObject(null);
20524
20527
  this._currentLineId = null;
20528
+ this._core.store.objects?.stopUndoCapturing();
20525
20529
  }
20526
20530
  }
20527
20531
  }
@@ -20628,17 +20632,24 @@ class KritzelEraserTool extends KritzelBaseTool {
20628
20632
  if (event.pointerType === 'mouse') {
20629
20633
  if (this._core.store.state.isErasing) {
20630
20634
  const objectsToRemove = this._core.store.allObjects.filter(object => object.markedForRemoval);
20631
- objectsToRemove.forEach(object => {
20632
- object.markedForRemoval = false;
20633
- this._core.removeObject(object);
20634
- });
20635
20635
  if (objectsToRemove.length > 0) {
20636
+ // Seal the previous undo step so create+delete of the same object
20637
+ // (e.g. just-drawn shape) don't collapse into a no-op on undo.
20638
+ this._core.store.objects.stopUndoCapturing();
20639
+ // Group all removals from this sweep into a single undo step.
20640
+ this._core.store.objects.transaction(() => {
20641
+ objectsToRemove.forEach(object => {
20642
+ object.markedForRemoval = false;
20643
+ this._core.removeObject(object);
20644
+ });
20645
+ });
20636
20646
  this._core.rerender();
20637
20647
  }
20638
20648
  this._core.store.state.isErasing = false;
20639
20649
  this._core.engine.emitObjectsChange();
20640
20650
  if (objectsToRemove.length > 0) {
20641
20651
  this._core.engine.emitObjectsRemoved(objectsToRemove);
20652
+ this._core.store.objects.stopUndoCapturing();
20642
20653
  }
20643
20654
  }
20644
20655
  }
@@ -20646,17 +20657,24 @@ class KritzelEraserTool extends KritzelBaseTool {
20646
20657
  clearTimeout(this.touchStartTimeout);
20647
20658
  if (this._core.store.state.isErasing) {
20648
20659
  const objectsToRemove = this._core.store.allObjects.filter(object => object.markedForRemoval);
20649
- objectsToRemove.forEach(object => {
20650
- object.markedForRemoval = false;
20651
- this._core.removeObject(object);
20652
- });
20653
20660
  if (objectsToRemove.length > 0) {
20661
+ // Seal the previous undo step so create+delete of the same object
20662
+ // (e.g. just-drawn shape) don't collapse into a no-op on undo.
20663
+ this._core.store.objects.stopUndoCapturing();
20664
+ // Group all removals from this sweep into a single undo step.
20665
+ this._core.store.objects.transaction(() => {
20666
+ objectsToRemove.forEach(object => {
20667
+ object.markedForRemoval = false;
20668
+ this._core.removeObject(object);
20669
+ });
20670
+ });
20654
20671
  this._core.rerender();
20655
20672
  }
20656
20673
  this._core.store.state.isErasing = false;
20657
20674
  this._core.engine.emitObjectsChange();
20658
20675
  if (objectsToRemove.length > 0) {
20659
20676
  this._core.engine.emitObjectsRemoved(objectsToRemove);
20677
+ this._core.store.objects.stopUndoCapturing();
20660
20678
  }
20661
20679
  }
20662
20680
  }
@@ -21261,6 +21279,7 @@ class KritzelShapeTool extends KritzelBaseTool {
21261
21279
  this.isDrawing = false;
21262
21280
  this._core.store.objects?.setActiveDrawingObject(null);
21263
21281
  this.currentShape = null;
21282
+ this._core.store.objects?.stopUndoCapturing();
21264
21283
  this._core.rerender();
21265
21284
  }
21266
21285
  }
@@ -21670,6 +21689,7 @@ class KritzelMoveHandler extends KritzelBaseHandler {
21670
21689
  this._core.store.selectionGroup.update();
21671
21690
  this._core.engine.emitObjectsChange();
21672
21691
  this._core.store.state.hasObjectsChanged = true;
21692
+ this._core.store.objects.stopUndoCapturing();
21673
21693
  }
21674
21694
  }
21675
21695
  }
@@ -21681,6 +21701,7 @@ class KritzelMoveHandler extends KritzelBaseHandler {
21681
21701
  this._core.store.selectionGroup.update();
21682
21702
  this._core.engine.emitObjectsChange();
21683
21703
  this._core.store.state.hasObjectsChanged = true;
21704
+ this._core.store.objects.stopUndoCapturing();
21684
21705
  }
21685
21706
  }
21686
21707
  }
@@ -22033,6 +22054,7 @@ class KritzelResizeHandler extends KritzelBaseHandler {
22033
22054
  this._core.store.selectionGroup.update();
22034
22055
  this._core.engine.emitObjectsChange();
22035
22056
  this._core.store.state.hasObjectsChanged = true;
22057
+ this._core.store.objects.stopUndoCapturing();
22036
22058
  }
22037
22059
  this.reset();
22038
22060
  }
@@ -22044,6 +22066,7 @@ class KritzelResizeHandler extends KritzelBaseHandler {
22044
22066
  this._core.store.selectionGroup.update();
22045
22067
  this._core.engine.emitObjectsChange();
22046
22068
  this._core.store.state.hasObjectsChanged = true;
22069
+ this._core.store.objects.stopUndoCapturing();
22047
22070
  }
22048
22071
  this.reset();
22049
22072
  const timeout = this._core.store.state.longTouchTimeout;
@@ -22195,6 +22218,7 @@ class KritzelRotationHandler extends KritzelBaseHandler {
22195
22218
  this._core.engine.emitObjectsChange();
22196
22219
  this._core.store.state.isRotating = false;
22197
22220
  this._core.store.state.hasObjectsChanged = true;
22221
+ this._core.store.objects.stopUndoCapturing();
22198
22222
  this.reset();
22199
22223
  }
22200
22224
  }
@@ -22204,6 +22228,7 @@ class KritzelRotationHandler extends KritzelBaseHandler {
22204
22228
  this._core.engine.emitObjectsChange();
22205
22229
  this._core.store.state.isRotating = false;
22206
22230
  this._core.store.state.hasObjectsChanged = true;
22231
+ this._core.store.objects.stopUndoCapturing();
22207
22232
  this.reset();
22208
22233
  const timeout = this._core.store.state.longTouchTimeout;
22209
22234
  if (timeout) {
@@ -23221,6 +23246,7 @@ class KritzelLineHandleHandler extends KritzelBaseHandler {
23221
23246
  this._core.engine.emitObjectsChange();
23222
23247
  this._core.store.state.hasObjectsChanged = true;
23223
23248
  }
23249
+ this._core.store.objects.stopUndoCapturing();
23224
23250
  }
23225
23251
  this._core.store.state.isLineHandleDragging = false;
23226
23252
  this.reset();
@@ -1 +1 @@
1
- import{H as a,a as T}from"./p-BrA5xRPn.js";export{E as APP_STATE_MIGRATIONS,A as AssetNotFoundError,C as CURRENT_APP_STATE_SCHEMA_VERSION,z as CURRENT_WORKSPACE_SCHEMA_VERSION,v as DEFAULT_ASSET_STORAGE_CONFIG,D as DEFAULT_BRUSH_CONFIG,u as DEFAULT_LINE_TOOL_CONFIG,t as DEFAULT_TEXT_CONFIG,p as IndexedDBAssetProvider,I as IndexedDBSyncProvider,y as KritzelAlignment,r as KritzelAnchorManager,o as KritzelAssetResolver,g as KritzelBrushTool,m as KritzelCursorHelper,i as KritzelEraserTool,e as KritzelGroup,c as KritzelImage,j as KritzelImageTool,d as KritzelLine,h as KritzelLineTool,b as KritzelPath,n as KritzelSelectionTool,f as KritzelShape,l as KritzelShapeTool,K as KritzelText,k as KritzelTextTool,s as KritzelThemeManager,q as KritzelWorkspace,S as ShapeType,W as WORKSPACE_EXPORT_VERSION,F as WORKSPACE_MIGRATIONS,x as darkTheme,w as lightTheme,B as runMigrations}from"./p-BrA5xRPn.js";import*as P from"yjs";import{WebsocketProvider as $}from"y-websocket";import"y-indexeddb";const _=Math.floor,R=127,U=Number.MAX_SAFE_INTEGER;class H{constructor(){this.cpos=0,this.cbuf=new Uint8Array(100),this.bufs=[]}}const O=()=>new H,N=t=>{const e=new Uint8Array((t=>{let e=t.cpos;for(let s=0;s<t.bufs.length;s++)e+=t.bufs[s].length;return e})(t));let s=0;for(let i=0;i<t.bufs.length;i++){const n=t.bufs[i];e.set(n,s),s+=n.length}return e.set(new Uint8Array(t.cbuf.buffer,0,t.cpos),s),e},M=(t,e)=>{const s=t.cbuf.length;t.cpos===s&&(t.bufs.push(t.cbuf),t.cbuf=new Uint8Array(2*s),t.cpos=0),t.cbuf[t.cpos++]=e},L=(t,e)=>{for(;e>R;)M(t,128|R&e),e=_(e/128);M(t,R&e)},G=(t,e)=>{L(t,e.byteLength),((t,e)=>{const s=t.cbuf.length,i=t.cpos,n=((t,e)=>t<e?t:e)(s-i,e.length),o=e.length-n;t.cbuf.set(e.subarray(0,n),i),t.cpos+=n,o>0&&(t.bufs.push(t.cbuf),t.cbuf=new Uint8Array(((t,e)=>t>e?t:e)(2*s,o)),t.cbuf.set(e.subarray(n)),t.cpos=o)})(t,e)},V=t=>new Error(t),X=V("Unexpected end of array"),J=V("Integer out of Range");class Q{constructor(t){this.arr=t,this.pos=0}}const Y=t=>((t,e)=>{const s=new Uint8Array(t.arr.buffer,t.pos+t.arr.byteOffset,e);return t.pos+=e,s})(t,Z(t)),Z=t=>{let e=0,s=1;const i=t.arr.length;for(;t.pos<i;){const i=t.arr[t.pos++];if(e+=(i&R)*s,s*=128,i<128)return e;if(e>U)throw J}throw X};class tt{type="local";doc;channel;_synced=!1;constructor(t,e,s){this.doc=e,this.channel=new BroadcastChannel(t),this.channel.onmessage=t=>{this.handleMessage(t.data)},this.doc.on("update",this.handleDocUpdate),this.broadcastSync(),setTimeout((()=>{this._synced=!0}),100),s?.quiet||console.info(`BroadcastChannel Provider initialized: ${t}`)}handleDocUpdate=(t,e)=>{if(e!==this){const e=O();L(e,0),G(e,t),this.channel.postMessage(N(e))}};handleMessage(t){const e=(s=new Uint8Array(t),new Q(s));var s;switch(Z(e)){case 0:const t=Y(e);P.applyUpdate(this.doc,t,this);break;case 1:this.broadcastSync();break;case 2:const s=Y(e),i=P.encodeStateAsUpdate(this.doc,s);if(i.length>0){const t=O();L(t,0),G(t,i),this.channel.postMessage(N(t))}}}broadcastSync(){const t=O();L(t,2),G(t,P.encodeStateVector(this.doc)),this.channel.postMessage(N(t))}async connect(){if(!this._synced)return new Promise((t=>{const e=()=>{this._synced?t():setTimeout(e,50)};e()}))}disconnect(){}async reconnect(){return this.disconnect(),this.connect()}destroy(){this.doc.off("update",this.handleDocUpdate),this.channel.close()}}class et{type="network";provider;isConnected=!1;_quiet=!1;get awareness(){return this.provider.awareness}constructor(t,e,s){const i=s?.url||"ws://localhost:1234",n=s?.roomName||t;this.provider=new $(i,n,e,{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: ${i}/${n}`)}static with(t){return{create:(e,s,i)=>{const n=i?{...t,...i}:t;return new et(e,s,n)}}}setupEventListeners(){this.provider.on("status",(({status:t})=>{"connected"===t?(this.isConnected=!0,this._quiet||console.info("WebSocket connected")):"disconnected"===t&&(this.isConnected=!1,this._quiet||console.info("WebSocket disconnected"))})),this.provider.on("sync",(t=>{t&&!this._quiet&&console.info("WebSocket synced")}))}async connect(){if(!this.isConnected)return new Promise(((t,e)=>{const s=setTimeout((()=>{e(new Error("WebSocket connection timeout"))}),1e4),i=({status:e})=>{"connected"===e&&(clearTimeout(s),this.provider.off("status",i),this.isConnected=!0,t())};this.provider.on("status",i),this.provider.wsconnected&&(clearTimeout(s),this.provider.off("status",i),this.isConnected=!0,t())}))}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 st{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(t,e,s){const i=s?.name||t,n=s?.url||"ws://localhost:1234";this.connectionTimeoutMs=s?.connectionTimeout??1e4;const o=s?.websocketProvider||st.sharedWebSocketProvider,r={};void 0!==s?.delay&&(r.delay=s.delay),void 0!==s?.factor&&(r.factor=s.factor),void 0!==s?.maxAttempts&&(r.maxAttempts=s.maxAttempts),void 0!==s?.minDelay&&(r.minDelay=s.minDelay),void 0!==s?.maxDelay&&(r.maxDelay=s.maxDelay);const c=()=>{this.isDestroyed||(this.isConnected=!0,this._connectionStatus="connected",s?.quiet||console.info(`Hocuspocus connected: ${i}`),s?.onConnect&&s.onConnect())},h=()=>{this.isDestroyed||(this.isConnected=!1,this.isSynced=!1,this._connectionStatus="disconnected",s?.quiet||console.info(`Hocuspocus disconnected: ${i}`),s?.onDisconnect&&s.onDisconnect())},d=()=>{this.isDestroyed||(this.isSynced=!0,this._connectionStatus="synced",s?.quiet||console.info(`Hocuspocus synced: ${i}`),s?.onSynced&&s.onSynced())},l=t=>{this.isDestroyed||("connecting"===t.status&&(this._connectionStatus="connecting"),s?.onStatus&&s.onStatus(t))};if(o){this.usesSharedSocket=!0;const t={websocketProvider:o,name:i,document:e,token:s?.token||null,onStatus:l,onConnect:c,onDisconnect:h,onSynced:d,...r};void 0!==s?.forceSyncInterval&&(t.forceSyncInterval=s.forceSyncInterval),s?.onAuthenticationFailed&&(t.onAuthenticationFailed=s.onAuthenticationFailed),this.provider=new a(t),this.provider.attach(),s?.quiet||console.info(`Hocuspocus Provider initialized (multiplexed): ${i}`)}else{this.usesSharedSocket=!1;const t={url:n,name:i,document:e,token:s?.token||null,autoConnect:!1,onStatus:l,onConnect:c,onDisconnect:h,onSynced:d,...r};void 0!==s?.forceSyncInterval&&(t.forceSyncInterval=s.forceSyncInterval),s?.onAuthenticationFailed&&(t.onAuthenticationFailed=s.onAuthenticationFailed),s?.WebSocketPolyfill&&(t.WebSocketPolyfill=s.WebSocketPolyfill),this.provider=new a(t),s?.quiet||console.info(`Hocuspocus Provider initialized: ${n}/${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(t){if(st.sharedWebSocketProvider)return console.warn("Shared WebSocket already exists. Returning existing instance."),st.sharedWebSocketProvider;const e={url:t.url};return t.WebSocketPolyfill&&(e.WebSocketPolyfill=t.WebSocketPolyfill),t.onConnect&&(e.onConnect=t.onConnect),t.onDisconnect&&(e.onDisconnect=t.onDisconnect),t.onStatus&&(e.onStatus=t.onStatus),st.sharedWebSocketProvider=new T(e),console.info(`Shared Hocuspocus WebSocket created: ${t.url}`),st.sharedWebSocketProvider}static destroySharedWebSocket(){st.sharedWebSocketProvider&&(st.sharedWebSocketProvider.destroy(),st.sharedWebSocketProvider=null,console.info("Shared Hocuspocus WebSocket destroyed"))}static getSharedWebSocket(){return st.sharedWebSocketProvider}static with(t){return{create:(e,s,i)=>{const n=i?{...t,...i}:t;return new st(e,s,n)}}}async connect(){if(!this.isSynced&&!this.isDestroyed)return this._connectionStatus="connecting",new Promise(((t,e)=>{this.pendingConnectReject=e,this.connectTimeout=setTimeout((()=>{this.pendingConnectReject=null,this.connectTimeout=null,e(new 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||t()};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 t();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"}}class it{type="remote";name="HttpAssetProvider";_options;constructor(t){this._options=t}static with(t){return{create:()=>new it(t)}}async init(){this._options.quiet||console.info("HttpAssetProvider initialized")}destroy(){}canResolve(t){return!0}async put(t,e){const s=e.id??this.generateUuid(),i={...e,id:s},n=await(this._options.headers?.())??{},o=await this._options.uploadUrl(i),r=this._options.upload??this.defaultUpload;return{id:(await r(o,t,i,n)).id??s,kind:e.kind??"file",mimeType:e.mimeType,size:t.size,createdAt:Date.now(),width:e.width,height:e.height,durationMs:e.durationMs,originalFilename:e.originalFilename}}async resolve(t){return this._options.resolveUrl(t)}async fetch(t){const e=await this._options.resolveUrl(t),s=await(this._options.headers?.())??{},i=await fetch(e,{headers:s});if(!i.ok)throw new Error(`[HttpAssetProvider] Failed to fetch asset ${t}: ${i.status} ${i.statusText}`);return i.blob()}async delete(t){if(!this._options.deleteUrl)return;const e=await this._options.deleteUrl(t),s=await(this._options.headers?.())??{},i=await fetch(e,{method:"DELETE",headers:s});if(!i.ok)throw new Error(`[HttpAssetProvider] Failed to delete asset ${t}: ${i.status} ${i.statusText}`);this._options.quiet||console.info(`HttpAssetProvider: deleted asset ${t}`)}defaultUpload=async(t,e,s,i)=>{const n=new FormData;n.append("metadata",JSON.stringify(s)),n.append("file",e,s.originalFilename||`${s.id}.${this.extensionFromMime(s.mimeType)}`);const o=await fetch(t,{method:"POST",headers:i,body:n});if(!o.ok)throw new Error(`[HttpAssetProvider] Upload failed: ${o.status} ${o.statusText}`);return(o.headers.get("content-type")||"").includes("application/json")?await o.json():{}};extensionFromMime(t){const e=t.indexOf("/");return e>=0?t.slice(e+1):"bin"}generateUuid(){if("undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID)return crypto.randomUUID();const t=crypto.getRandomValues(new Uint8Array(16));t[6]=15&t[6]|64,t[8]=63&t[8]|128;const e=Array.from(t,(t=>t.toString(16).padStart(2,"0"))).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}}class nt{type="remote";name="PresignedAssetProvider";_options;constructor(t){this._options=t}static with(t){return{create:()=>new nt(t)}}async init(){this._options.quiet||console.info("PresignedAssetProvider initialized")}destroy(){}canResolve(t){return!0}async put(t,e){const s=await this._options.getUploadDescriptor(e),i=s.method??"PUT",n={...s.headers??{}};let o;if(n["Content-Type"]||n["content-type"]||(n["Content-Type"]=e.mimeType),"POST"===i&&s.fields){const e=new FormData;for(const[t,i]of Object.entries(s.fields))e.append(t,i);e.append("file",t),o=e,delete n["Content-Type"],delete n["content-type"]}else o=t;const r=await fetch(s.url,{method:i,headers:n,body:o});if(!r.ok)throw new Error(`[PresignedAssetProvider] Upload failed: ${r.status} ${r.statusText}`);return{id:s.id,kind:e.kind??"file",mimeType:e.mimeType,size:t.size,createdAt:Date.now(),width:e.width,height:e.height,durationMs:e.durationMs,originalFilename:e.originalFilename}}async resolve(t){return this._options.getDownloadUrl(t)}async fetch(t){const e=await this._options.getDownloadUrl(t),s=await fetch(e);if(!s.ok)throw new Error(`[PresignedAssetProvider] Failed to fetch asset ${t}: ${s.status} ${s.statusText}`);return s.blob()}async delete(t){this._options.deleteAsset&&(await this._options.deleteAsset(t),this._options.quiet||console.info(`PresignedAssetProvider: deleted asset ${t}`))}}export{tt as BroadcastSyncProvider,st as HocuspocusSyncProvider,it as HttpAssetProvider,nt as PresignedAssetProvider,et as WebSocketSyncProvider}
1
+ import{H as a,a as T}from"./p-D_y5zlxK.js";export{E as APP_STATE_MIGRATIONS,A as AssetNotFoundError,C as CURRENT_APP_STATE_SCHEMA_VERSION,z as CURRENT_WORKSPACE_SCHEMA_VERSION,v as DEFAULT_ASSET_STORAGE_CONFIG,D as DEFAULT_BRUSH_CONFIG,u as DEFAULT_LINE_TOOL_CONFIG,t as DEFAULT_TEXT_CONFIG,p as IndexedDBAssetProvider,I as IndexedDBSyncProvider,y as KritzelAlignment,r as KritzelAnchorManager,o as KritzelAssetResolver,g as KritzelBrushTool,m as KritzelCursorHelper,i as KritzelEraserTool,e as KritzelGroup,c as KritzelImage,j as KritzelImageTool,d as KritzelLine,h as KritzelLineTool,b as KritzelPath,n as KritzelSelectionTool,f as KritzelShape,l as KritzelShapeTool,K as KritzelText,k as KritzelTextTool,s as KritzelThemeManager,q as KritzelWorkspace,S as ShapeType,W as WORKSPACE_EXPORT_VERSION,F as WORKSPACE_MIGRATIONS,x as darkTheme,w as lightTheme,B as runMigrations}from"./p-D_y5zlxK.js";import*as P from"yjs";import{WebsocketProvider as $}from"y-websocket";import"y-indexeddb";const _=Math.floor,U=127,H=Number.MAX_SAFE_INTEGER;class R{constructor(){this.cpos=0,this.cbuf=new Uint8Array(100),this.bufs=[]}}const O=()=>new R,N=t=>{const e=new Uint8Array((t=>{let e=t.cpos;for(let s=0;s<t.bufs.length;s++)e+=t.bufs[s].length;return e})(t));let s=0;for(let i=0;i<t.bufs.length;i++){const n=t.bufs[i];e.set(n,s),s+=n.length}return e.set(new Uint8Array(t.cbuf.buffer,0,t.cpos),s),e},M=(t,e)=>{const s=t.cbuf.length;t.cpos===s&&(t.bufs.push(t.cbuf),t.cbuf=new Uint8Array(2*s),t.cpos=0),t.cbuf[t.cpos++]=e},L=(t,e)=>{for(;e>U;)M(t,128|U&e),e=_(e/128);M(t,U&e)},G=(t,e)=>{L(t,e.byteLength),((t,e)=>{const s=t.cbuf.length,i=t.cpos,n=((t,e)=>t<e?t:e)(s-i,e.length),o=e.length-n;t.cbuf.set(e.subarray(0,n),i),t.cpos+=n,o>0&&(t.bufs.push(t.cbuf),t.cbuf=new Uint8Array(((t,e)=>t>e?t:e)(2*s,o)),t.cbuf.set(e.subarray(n)),t.cpos=o)})(t,e)},V=t=>new Error(t),X=V("Unexpected end of array"),J=V("Integer out of Range");class Q{constructor(t){this.arr=t,this.pos=0}}const Y=t=>((t,e)=>{const s=new Uint8Array(t.arr.buffer,t.pos+t.arr.byteOffset,e);return t.pos+=e,s})(t,Z(t)),Z=t=>{let e=0,s=1;const i=t.arr.length;for(;t.pos<i;){const i=t.arr[t.pos++];if(e+=(i&U)*s,s*=128,i<128)return e;if(e>H)throw J}throw X};class tt{type="local";doc;channel;_synced=!1;constructor(t,e,s){this.doc=e,this.channel=new BroadcastChannel(t),this.channel.onmessage=t=>{this.handleMessage(t.data)},this.doc.on("update",this.handleDocUpdate),this.broadcastSync(),setTimeout((()=>{this._synced=!0}),100),s?.quiet||console.info(`BroadcastChannel Provider initialized: ${t}`)}handleDocUpdate=(t,e)=>{if(e!==this){const e=O();L(e,0),G(e,t),this.channel.postMessage(N(e))}};handleMessage(t){const e=(s=new Uint8Array(t),new Q(s));var s;switch(Z(e)){case 0:const t=Y(e);P.applyUpdate(this.doc,t,this);break;case 1:this.broadcastSync();break;case 2:const s=Y(e),i=P.encodeStateAsUpdate(this.doc,s);if(i.length>0){const t=O();L(t,0),G(t,i),this.channel.postMessage(N(t))}}}broadcastSync(){const t=O();L(t,2),G(t,P.encodeStateVector(this.doc)),this.channel.postMessage(N(t))}async connect(){if(!this._synced)return new Promise((t=>{const e=()=>{this._synced?t():setTimeout(e,50)};e()}))}disconnect(){}async reconnect(){return this.disconnect(),this.connect()}destroy(){this.doc.off("update",this.handleDocUpdate),this.channel.close()}}class et{type="network";provider;isConnected=!1;_quiet=!1;get awareness(){return this.provider.awareness}constructor(t,e,s){const i=s?.url||"ws://localhost:1234",n=s?.roomName||t;this.provider=new $(i,n,e,{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: ${i}/${n}`)}static with(t){return{create:(e,s,i)=>{const n=i?{...t,...i}:t;return new et(e,s,n)}}}setupEventListeners(){this.provider.on("status",(({status:t})=>{"connected"===t?(this.isConnected=!0,this._quiet||console.info("WebSocket connected")):"disconnected"===t&&(this.isConnected=!1,this._quiet||console.info("WebSocket disconnected"))})),this.provider.on("sync",(t=>{t&&!this._quiet&&console.info("WebSocket synced")}))}async connect(){if(!this.isConnected)return new Promise(((t,e)=>{const s=setTimeout((()=>{e(new Error("WebSocket connection timeout"))}),1e4),i=({status:e})=>{"connected"===e&&(clearTimeout(s),this.provider.off("status",i),this.isConnected=!0,t())};this.provider.on("status",i),this.provider.wsconnected&&(clearTimeout(s),this.provider.off("status",i),this.isConnected=!0,t())}))}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 st{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(t,e,s){const i=s?.name||t,n=s?.url||"ws://localhost:1234";this.connectionTimeoutMs=s?.connectionTimeout??1e4;const o=s?.websocketProvider||st.sharedWebSocketProvider,r={};void 0!==s?.delay&&(r.delay=s.delay),void 0!==s?.factor&&(r.factor=s.factor),void 0!==s?.maxAttempts&&(r.maxAttempts=s.maxAttempts),void 0!==s?.minDelay&&(r.minDelay=s.minDelay),void 0!==s?.maxDelay&&(r.maxDelay=s.maxDelay);const c=()=>{this.isDestroyed||(this.isConnected=!0,this._connectionStatus="connected",s?.quiet||console.info(`Hocuspocus connected: ${i}`),s?.onConnect&&s.onConnect())},h=()=>{this.isDestroyed||(this.isConnected=!1,this.isSynced=!1,this._connectionStatus="disconnected",s?.quiet||console.info(`Hocuspocus disconnected: ${i}`),s?.onDisconnect&&s.onDisconnect())},d=()=>{this.isDestroyed||(this.isSynced=!0,this._connectionStatus="synced",s?.quiet||console.info(`Hocuspocus synced: ${i}`),s?.onSynced&&s.onSynced())},l=t=>{this.isDestroyed||("connecting"===t.status&&(this._connectionStatus="connecting"),s?.onStatus&&s.onStatus(t))};if(o){this.usesSharedSocket=!0;const t={websocketProvider:o,name:i,document:e,token:s?.token||null,onStatus:l,onConnect:c,onDisconnect:h,onSynced:d,...r};void 0!==s?.forceSyncInterval&&(t.forceSyncInterval=s.forceSyncInterval),s?.onAuthenticationFailed&&(t.onAuthenticationFailed=s.onAuthenticationFailed),this.provider=new a(t),this.provider.attach(),s?.quiet||console.info(`Hocuspocus Provider initialized (multiplexed): ${i}`)}else{this.usesSharedSocket=!1;const t={url:n,name:i,document:e,token:s?.token||null,autoConnect:!1,onStatus:l,onConnect:c,onDisconnect:h,onSynced:d,...r};void 0!==s?.forceSyncInterval&&(t.forceSyncInterval=s.forceSyncInterval),s?.onAuthenticationFailed&&(t.onAuthenticationFailed=s.onAuthenticationFailed),s?.WebSocketPolyfill&&(t.WebSocketPolyfill=s.WebSocketPolyfill),this.provider=new a(t),s?.quiet||console.info(`Hocuspocus Provider initialized: ${n}/${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(t){if(st.sharedWebSocketProvider)return console.warn("Shared WebSocket already exists. Returning existing instance."),st.sharedWebSocketProvider;const e={url:t.url};return t.WebSocketPolyfill&&(e.WebSocketPolyfill=t.WebSocketPolyfill),t.onConnect&&(e.onConnect=t.onConnect),t.onDisconnect&&(e.onDisconnect=t.onDisconnect),t.onStatus&&(e.onStatus=t.onStatus),st.sharedWebSocketProvider=new T(e),console.info(`Shared Hocuspocus WebSocket created: ${t.url}`),st.sharedWebSocketProvider}static destroySharedWebSocket(){st.sharedWebSocketProvider&&(st.sharedWebSocketProvider.destroy(),st.sharedWebSocketProvider=null,console.info("Shared Hocuspocus WebSocket destroyed"))}static getSharedWebSocket(){return st.sharedWebSocketProvider}static with(t){return{create:(e,s,i)=>{const n=i?{...t,...i}:t;return new st(e,s,n)}}}async connect(){if(!this.isSynced&&!this.isDestroyed)return this._connectionStatus="connecting",new Promise(((t,e)=>{this.pendingConnectReject=e,this.connectTimeout=setTimeout((()=>{this.pendingConnectReject=null,this.connectTimeout=null,e(new 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||t()};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 t();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"}}class it{type="remote";name="HttpAssetProvider";_options;constructor(t){this._options=t}static with(t){return{create:()=>new it(t)}}async init(){this._options.quiet||console.info("HttpAssetProvider initialized")}destroy(){}canResolve(t){return!0}async put(t,e){const s=e.id??this.generateUuid(),i={...e,id:s},n=await(this._options.headers?.())??{},o=await this._options.uploadUrl(i),r=this._options.upload??this.defaultUpload;return{id:(await r(o,t,i,n)).id??s,kind:e.kind??"file",mimeType:e.mimeType,size:t.size,createdAt:Date.now(),width:e.width,height:e.height,durationMs:e.durationMs,originalFilename:e.originalFilename}}async resolve(t){return this._options.resolveUrl(t)}async fetch(t){const e=await this._options.resolveUrl(t),s=await(this._options.headers?.())??{},i=await fetch(e,{headers:s});if(!i.ok)throw new Error(`[HttpAssetProvider] Failed to fetch asset ${t}: ${i.status} ${i.statusText}`);return i.blob()}async delete(t){if(!this._options.deleteUrl)return;const e=await this._options.deleteUrl(t),s=await(this._options.headers?.())??{},i=await fetch(e,{method:"DELETE",headers:s});if(!i.ok)throw new Error(`[HttpAssetProvider] Failed to delete asset ${t}: ${i.status} ${i.statusText}`);this._options.quiet||console.info(`HttpAssetProvider: deleted asset ${t}`)}defaultUpload=async(t,e,s,i)=>{const n=new FormData;n.append("metadata",JSON.stringify(s)),n.append("file",e,s.originalFilename||`${s.id}.${this.extensionFromMime(s.mimeType)}`);const o=await fetch(t,{method:"POST",headers:i,body:n});if(!o.ok)throw new Error(`[HttpAssetProvider] Upload failed: ${o.status} ${o.statusText}`);return(o.headers.get("content-type")||"").includes("application/json")?await o.json():{}};extensionFromMime(t){const e=t.indexOf("/");return e>=0?t.slice(e+1):"bin"}generateUuid(){if("undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID)return crypto.randomUUID();const t=crypto.getRandomValues(new Uint8Array(16));t[6]=15&t[6]|64,t[8]=63&t[8]|128;const e=Array.from(t,(t=>t.toString(16).padStart(2,"0"))).join("");return`${e.slice(0,8)}-${e.slice(8,12)}-${e.slice(12,16)}-${e.slice(16,20)}-${e.slice(20)}`}}class nt{type="remote";name="PresignedAssetProvider";_options;constructor(t){this._options=t}static with(t){return{create:()=>new nt(t)}}async init(){this._options.quiet||console.info("PresignedAssetProvider initialized")}destroy(){}canResolve(t){return!0}async put(t,e){const s=await this._options.getUploadDescriptor(e),i=s.method??"PUT",n={...s.headers??{}};let o;if(n["Content-Type"]||n["content-type"]||(n["Content-Type"]=e.mimeType),"POST"===i&&s.fields){const e=new FormData;for(const[t,i]of Object.entries(s.fields))e.append(t,i);e.append("file",t),o=e,delete n["Content-Type"],delete n["content-type"]}else o=t;const r=await fetch(s.url,{method:i,headers:n,body:o});if(!r.ok)throw new Error(`[PresignedAssetProvider] Upload failed: ${r.status} ${r.statusText}`);return{id:s.id,kind:e.kind??"file",mimeType:e.mimeType,size:t.size,createdAt:Date.now(),width:e.width,height:e.height,durationMs:e.durationMs,originalFilename:e.originalFilename}}async resolve(t){return this._options.getDownloadUrl(t)}async fetch(t){const e=await this._options.getDownloadUrl(t),s=await fetch(e);if(!s.ok)throw new Error(`[PresignedAssetProvider] Failed to fetch asset ${t}: ${s.status} ${s.statusText}`);return s.blob()}async delete(t){this._options.deleteAsset&&(await this._options.deleteAsset(t),this._options.quiet||console.info(`PresignedAssetProvider: deleted asset ${t}`))}}export{tt as BroadcastSyncProvider,st as HocuspocusSyncProvider,it as HttpAssetProvider,nt as PresignedAssetProvider,et as WebSocketSyncProvider}