kritzel-react 0.1.30 → 0.1.32
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.
- package/dist/kritzel-react/lib/components/stencil-generated/components.js +122 -0
- package/dist/kritzel-react/lib/index.js +2 -0
- package/dist/kritzel-stencil/src/classes/core/core.class.js +797 -0
- package/dist/kritzel-stencil/src/classes/core/reviver.class.js +97 -0
- package/dist/kritzel-stencil/src/classes/core/store.class.js +153 -0
- package/dist/kritzel-stencil/src/classes/core/viewport.class.js +311 -0
- package/dist/kritzel-stencil/src/classes/core/workspace.class.js +34 -0
- package/dist/kritzel-stencil/src/classes/handlers/base.handler.js +6 -0
- package/dist/kritzel-stencil/src/classes/handlers/context-menu.handler.js +63 -0
- package/dist/kritzel-stencil/src/classes/handlers/hover.handler.js +18 -0
- package/dist/kritzel-stencil/src/classes/handlers/key.handler.js +76 -0
- package/dist/kritzel-stencil/src/classes/handlers/line-handle.handler.js +382 -0
- package/dist/kritzel-stencil/src/classes/handlers/move.handler.js +213 -0
- package/dist/kritzel-stencil/src/classes/handlers/resize.handler.js +205 -0
- package/dist/kritzel-stencil/src/classes/handlers/rotation.handler.js +117 -0
- package/dist/kritzel-stencil/src/classes/handlers/selection.handler.js +313 -0
- package/dist/kritzel-stencil/src/classes/managers/anchor.manager.js +1056 -0
- package/dist/kritzel-stencil/src/classes/managers/cursor.manager.js +117 -0
- package/dist/kritzel-stencil/src/classes/managers/theme.manager.js +103 -0
- package/dist/kritzel-stencil/src/classes/objects/base-object.class.js +249 -0
- package/dist/kritzel-stencil/src/classes/objects/custom-element.class.js +60 -0
- package/dist/kritzel-stencil/src/classes/objects/group.class.js +407 -0
- package/dist/kritzel-stencil/src/classes/objects/image.class.js +55 -0
- package/dist/kritzel-stencil/src/classes/objects/line.class.js +608 -0
- package/dist/kritzel-stencil/src/classes/objects/path.class.js +401 -0
- package/dist/kritzel-stencil/src/classes/objects/selection-box.class.js +21 -0
- package/dist/kritzel-stencil/src/classes/objects/selection-group.class.js +409 -0
- package/dist/kritzel-stencil/src/classes/objects/shape.class.js +412 -0
- package/dist/kritzel-stencil/src/classes/objects/text.class.js +292 -0
- package/dist/kritzel-stencil/src/classes/providers/broadcast-sync-provider.class.js +101 -0
- package/dist/kritzel-stencil/src/classes/providers/hocuspocus-sync-provider.class.js +241 -0
- package/dist/kritzel-stencil/src/classes/providers/indexeddb-sync-provider.class.js +43 -0
- package/dist/kritzel-stencil/src/classes/providers/websocket-sync-provider.class.js +98 -0
- package/dist/kritzel-stencil/src/classes/registries/icon-registry.class.js +66 -0
- package/dist/kritzel-stencil/src/classes/registries/tool.registry.js +21 -0
- package/dist/kritzel-stencil/src/classes/structures/app-state-map.structure.js +212 -0
- package/dist/kritzel-stencil/src/classes/structures/object-map.structure.js +414 -0
- package/dist/kritzel-stencil/src/classes/structures/quadtree.structure.js +151 -0
- package/dist/kritzel-stencil/src/classes/tools/base-tool.class.js +36 -0
- package/dist/kritzel-stencil/src/classes/tools/brush-tool.class.js +161 -0
- package/dist/kritzel-stencil/src/classes/tools/eraser-tool.class.js +85 -0
- package/dist/kritzel-stencil/src/classes/tools/image-tool.class.js +83 -0
- package/dist/kritzel-stencil/src/classes/tools/line-tool.class.js +187 -0
- package/dist/kritzel-stencil/src/classes/tools/selection-tool.class.js +429 -0
- package/dist/kritzel-stencil/src/classes/tools/shape-tool.class.js +196 -0
- package/dist/kritzel-stencil/src/classes/tools/text-tool.class.js +100 -0
- package/dist/kritzel-stencil/src/components/core/kritzel-engine/kritzel-engine.js +1343 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-brush-style/kritzel-brush-style.js +46 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-dropdown/kritzel-dropdown.js +312 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-font-family/kritzel-font-family.js +60 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-line-endings/kritzel-line-endings.js +105 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-shape-fill/kritzel-shape-fill.js +53 -0
- package/dist/kritzel-stencil/src/components/ui/kritzel-context-menu/kritzel-context-menu.js +137 -0
- package/dist/kritzel-stencil/src/configs/default-brush-tool.config.js +9 -0
- package/dist/kritzel-stencil/src/configs/default-engine-config.js +63 -0
- package/dist/kritzel-stencil/src/configs/default-line-tool.config.js +9 -0
- package/dist/kritzel-stencil/src/configs/default-sync.config.js +9 -0
- package/dist/kritzel-stencil/src/configs/default-text-tool.config.js +7 -0
- package/dist/kritzel-stencil/src/constants/color-palette.constants.js +37 -0
- package/dist/kritzel-stencil/src/constants/engine.constants.js +2 -0
- package/dist/kritzel-stencil/src/enums/event-button.enum.js +6 -0
- package/dist/kritzel-stencil/src/enums/handle-type.enum.js +7 -0
- package/dist/kritzel-stencil/src/enums/shape-type.enum.js +6 -0
- package/dist/kritzel-stencil/src/helpers/class.helper.js +5 -0
- package/dist/kritzel-stencil/src/helpers/color.helper.js +106 -0
- package/dist/kritzel-stencil/src/helpers/cursor.helper.js +57 -0
- package/dist/kritzel-stencil/src/helpers/devices.helper.js +28 -0
- package/dist/kritzel-stencil/src/helpers/event.helper.js +58 -0
- package/dist/kritzel-stencil/src/helpers/geometry.helper.js +149 -0
- package/dist/kritzel-stencil/src/helpers/keyboard.helper.js +51 -0
- package/dist/kritzel-stencil/src/helpers/math.helper.js +5 -0
- package/dist/kritzel-stencil/src/helpers/object.helper.js +11 -0
- package/dist/kritzel-stencil/src/helpers/theme.helper.js +69 -0
- package/dist/kritzel-stencil/src/index.js +41 -0
- package/dist/kritzel-stencil/src/interfaces/anchor.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/arrow-head.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/bounding-box.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/clonable.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/context-menu-item.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/debug-info.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/dialog.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/displayable-shortcut.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/engine-state.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/line-options.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/master-detail.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/menu-item.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/object.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/path-options.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/point.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/polygon.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/serializable.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/settings.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/shortcut.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/sync-config.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/sync-provider.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/theme.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/tool-config.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/tool.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/toolbar-control.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/undo-state.interface.js +1 -0
- package/dist/kritzel-stencil/src/themes/dark-theme.js +198 -0
- package/dist/kritzel-stencil/src/themes/light-theme.js +199 -0
- package/dist/kritzel-stencil/src/types/shortcut.type.js +1 -0
- package/dist/kritzel-stencil/src/types/state.types.js +1 -0
- package/dist/types/kritzel-react/lib/components/stencil-generated/components.d.ts +74 -0
- package/dist/types/kritzel-react/lib/index.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/classes/core/core.class.d.ts +101 -0
- package/dist/types/kritzel-stencil/src/classes/core/reviver.class.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/classes/core/store.class.d.ts +53 -0
- package/dist/types/kritzel-stencil/src/classes/core/viewport.class.d.ts +48 -0
- package/dist/types/kritzel-stencil/src/classes/core/workspace.class.d.ts +24 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/base.handler.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/context-menu.handler.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/hover.handler.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/key.handler.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/line-handle.handler.d.ts +34 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/move.handler.d.ts +29 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/resize.handler.d.ts +24 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/rotation.handler.d.ts +12 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/selection.handler.d.ts +27 -0
- package/dist/types/kritzel-stencil/src/classes/managers/anchor.manager.d.ts +180 -0
- package/dist/types/kritzel-stencil/src/classes/managers/cursor.manager.d.ts +43 -0
- package/dist/types/kritzel-stencil/src/classes/managers/theme.manager.d.ts +56 -0
- package/dist/types/kritzel-stencil/src/classes/objects/base-object.class.d.ts +76 -0
- package/dist/types/kritzel-stencil/src/classes/objects/custom-element.class.d.ts +26 -0
- package/dist/types/kritzel-stencil/src/classes/objects/group.class.d.ts +97 -0
- package/dist/types/kritzel-stencil/src/classes/objects/image.class.d.ts +17 -0
- package/dist/types/kritzel-stencil/src/classes/objects/line.class.d.ts +101 -0
- package/dist/types/kritzel-stencil/src/classes/objects/path.class.d.ts +62 -0
- package/dist/types/kritzel-stencil/src/classes/objects/selection-box.class.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/classes/objects/selection-group.class.d.ts +67 -0
- package/dist/types/kritzel-stencil/src/classes/objects/shape.class.d.ts +124 -0
- package/dist/types/kritzel-stencil/src/classes/objects/text.class.d.ts +56 -0
- package/dist/types/kritzel-stencil/src/classes/providers/broadcast-sync-provider.class.d.ts +18 -0
- package/dist/types/kritzel-stencil/src/classes/providers/hocuspocus-sync-provider.class.d.ts +120 -0
- package/dist/types/kritzel-stencil/src/classes/providers/indexeddb-sync-provider.class.d.ts +22 -0
- package/dist/types/kritzel-stencil/src/classes/providers/websocket-sync-provider.class.d.ts +52 -0
- package/dist/types/kritzel-stencil/src/classes/registries/icon-registry.class.d.ts +9 -0
- package/dist/types/kritzel-stencil/src/classes/registries/tool.registry.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/classes/structures/app-state-map.structure.d.ts +31 -0
- package/dist/types/kritzel-stencil/src/classes/structures/object-map.structure.d.ts +63 -0
- package/dist/types/kritzel-stencil/src/classes/structures/quadtree.structure.d.ts +36 -0
- package/dist/types/kritzel-stencil/src/classes/tools/base-tool.class.d.ts +20 -0
- package/dist/types/kritzel-stencil/src/classes/tools/brush-tool.class.d.ts +14 -0
- package/dist/types/kritzel-stencil/src/classes/tools/eraser-tool.class.d.ts +9 -0
- package/dist/types/kritzel-stencil/src/classes/tools/image-tool.class.d.ts +15 -0
- package/dist/types/kritzel-stencil/src/classes/tools/line-tool.class.d.ts +19 -0
- package/dist/types/kritzel-stencil/src/classes/tools/selection-tool.class.d.ts +54 -0
- package/dist/types/kritzel-stencil/src/classes/tools/shape-tool.class.d.ts +39 -0
- package/dist/types/kritzel-stencil/src/classes/tools/text-tool.class.d.ts +13 -0
- package/dist/types/kritzel-stencil/src/components/core/kritzel-engine/kritzel-engine.d.ts +111 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-brush-style/kritzel-brush-style.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-dropdown/kritzel-dropdown.d.ts +46 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-font-family/kritzel-font-family.d.ts +13 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-line-endings/kritzel-line-endings.d.ts +21 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-shape-fill/kritzel-shape-fill.d.ts +10 -0
- package/dist/types/kritzel-stencil/src/components/ui/kritzel-context-menu/kritzel-context-menu.d.ts +21 -0
- package/dist/types/kritzel-stencil/src/configs/default-brush-tool.config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/configs/default-engine-config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/configs/default-line-tool.config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/configs/default-sync.config.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/configs/default-text-tool.config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/constants/color-palette.constants.d.ts +29 -0
- package/dist/types/kritzel-stencil/src/constants/engine.constants.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/enums/event-button.enum.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/enums/handle-type.enum.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/enums/shape-type.enum.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/helpers/class.helper.d.ts +3 -0
- package/dist/types/kritzel-stencil/src/helpers/color.helper.d.ts +33 -0
- package/dist/types/kritzel-stencil/src/helpers/cursor.helper.d.ts +22 -0
- package/dist/types/kritzel-stencil/src/helpers/devices.helper.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/helpers/event.helper.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/helpers/geometry.helper.d.ts +38 -0
- package/dist/types/kritzel-stencil/src/helpers/keyboard.helper.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/helpers/math.helper.d.ts +3 -0
- package/dist/types/kritzel-stencil/src/helpers/object.helper.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/helpers/theme.helper.d.ts +41 -0
- package/dist/types/kritzel-stencil/src/index.d.ts +42 -0
- package/dist/types/kritzel-stencil/src/interfaces/anchor.interface.d.ts +137 -0
- package/dist/types/kritzel-stencil/src/interfaces/arrow-head.interface.d.ts +27 -0
- package/dist/types/kritzel-stencil/src/interfaces/bounding-box.interface.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/interfaces/clonable.interface.d.ts +3 -0
- package/dist/types/kritzel-stencil/src/interfaces/context-menu-item.interface.d.ts +17 -0
- package/dist/types/kritzel-stencil/src/interfaces/debug-info.interface.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/interfaces/dialog.interface.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/interfaces/displayable-shortcut.interface.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/interfaces/engine-state.interface.d.ts +73 -0
- package/dist/types/kritzel-stencil/src/interfaces/line-options.interface.d.ts +23 -0
- package/dist/types/kritzel-stencil/src/interfaces/master-detail.interface.d.ts +14 -0
- package/dist/types/kritzel-stencil/src/interfaces/menu-item.interface.d.ts +24 -0
- package/dist/types/kritzel-stencil/src/interfaces/object.interface.d.ts +53 -0
- package/dist/types/kritzel-stencil/src/interfaces/path-options.interface.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/interfaces/point.interface.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/interfaces/polygon.interface.d.ts +7 -0
- package/dist/types/kritzel-stencil/src/interfaces/serializable.interface.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/interfaces/settings.interface.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/interfaces/shortcut.interface.d.ts +10 -0
- package/dist/types/kritzel-stencil/src/interfaces/sync-config.interface.d.ts +22 -0
- package/dist/types/kritzel-stencil/src/interfaces/sync-provider.interface.d.ts +29 -0
- package/dist/types/kritzel-stencil/src/interfaces/theme.interface.d.ts +330 -0
- package/dist/types/kritzel-stencil/src/interfaces/tool-config.interface.d.ts +26 -0
- package/dist/types/kritzel-stencil/src/interfaces/tool.interface.d.ts +7 -0
- package/dist/types/kritzel-stencil/src/interfaces/toolbar-control.interface.d.ts +58 -0
- package/dist/types/kritzel-stencil/src/interfaces/undo-state.interface.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/themes/dark-theme.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/themes/light-theme.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/types/shortcut.type.d.ts +1 -0
- package/dist/types/kritzel-stencil/src/types/state.types.d.ts +3 -0
- package/package.json +2 -2
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { KritzelToolRegistry } from '../registries/tool.registry';
|
|
13
|
+
import { KritzelBaseObject } from './base-object.class';
|
|
14
|
+
import { KritzelKeyboardHelper } from '../../helpers/keyboard.helper';
|
|
15
|
+
import { KritzelDevicesHelper } from '../../helpers/devices.helper';
|
|
16
|
+
import { EditorState, TextSelection } from 'prosemirror-state';
|
|
17
|
+
import { EditorView } from 'prosemirror-view';
|
|
18
|
+
import { Schema } from 'prosemirror-model';
|
|
19
|
+
import { schema } from 'prosemirror-schema-basic';
|
|
20
|
+
import { addListNodes } from 'prosemirror-schema-list';
|
|
21
|
+
import { keymap } from 'prosemirror-keymap';
|
|
22
|
+
import { baseKeymap } from 'prosemirror-commands';
|
|
23
|
+
import { KritzelColorHelper } from '../../helpers/color.helper';
|
|
24
|
+
export class KritzelText extends KritzelBaseObject {
|
|
25
|
+
get isEmpty() {
|
|
26
|
+
if (!this.editor) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
const doc = this.editor.state.doc;
|
|
30
|
+
if (doc.content.size === 0) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
const text = doc.textContent.trim();
|
|
34
|
+
return text.length === 0;
|
|
35
|
+
}
|
|
36
|
+
constructor(config) {
|
|
37
|
+
var _a;
|
|
38
|
+
super();
|
|
39
|
+
this.__class__ = 'KritzelText';
|
|
40
|
+
this.fontFamily = 'Arial';
|
|
41
|
+
this.fontSize = 8;
|
|
42
|
+
this.fontColor = { light: '#000000', dark: '#ffffff' };
|
|
43
|
+
this.initialWidth = 1;
|
|
44
|
+
this.initialHeight = 1;
|
|
45
|
+
this.scale = 1;
|
|
46
|
+
this.scaleFactor = 1;
|
|
47
|
+
this.isDebugInfoVisible = true;
|
|
48
|
+
this.isEditable = true;
|
|
49
|
+
this.isEditing = false;
|
|
50
|
+
this.editor = null;
|
|
51
|
+
this.content = null;
|
|
52
|
+
this._schema = new Schema({
|
|
53
|
+
nodes: addListNodes(schema.spec.nodes, 'paragraph block*', 'block'),
|
|
54
|
+
marks: schema.spec.marks,
|
|
55
|
+
});
|
|
56
|
+
this.uneditedObject = null;
|
|
57
|
+
this.rows = 1;
|
|
58
|
+
if (config) {
|
|
59
|
+
this.translateX = config.translateX || 0;
|
|
60
|
+
this.translateY = config.translateY || 0;
|
|
61
|
+
this.fontSize = config.fontSize || 8;
|
|
62
|
+
this.fontFamily = config.fontFamily || 'Arial';
|
|
63
|
+
this.fontColor = config.fontColor || { light: '#000000', dark: '#ffffff' };
|
|
64
|
+
this.width = this.initialWidth / (this._core.store.state.scale < 0 ? this._core.store.state.scale : 1);
|
|
65
|
+
this.height = (this.fontSize * 1.2) / (this._core.store.state.scale < 0 ? this._core.store.state.scale : 1);
|
|
66
|
+
this.scale = config.scale || 1;
|
|
67
|
+
this.scaleFactor = (_a = config.scaleX) !== null && _a !== void 0 ? _a : 1;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
static create(core, fontSize, fontFamily, scale) {
|
|
71
|
+
const object = new KritzelText();
|
|
72
|
+
object._core = core;
|
|
73
|
+
object.id = object.generateId();
|
|
74
|
+
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
75
|
+
object.fontSize = fontSize;
|
|
76
|
+
object.fontFamily = fontFamily;
|
|
77
|
+
object.translateX = 0;
|
|
78
|
+
object.translateY = 0;
|
|
79
|
+
object.width = object.initialWidth / (object._core.store.state.scale < 0 ? object._core.store.state.scale : 1);
|
|
80
|
+
object.height = (object.fontSize * 1.2) / (object._core.store.state.scale < 0 ? object._core.store.state.scale : 1);
|
|
81
|
+
object.backgroundColor = { light: 'transparent', dark: 'transparent' };
|
|
82
|
+
object.initialWidth = object.width;
|
|
83
|
+
object.initialHeight = object.height;
|
|
84
|
+
object.scaleFactor = 1;
|
|
85
|
+
object.scale = scale !== null && scale !== void 0 ? scale : object._core.store.state.scale;
|
|
86
|
+
object.zIndex = core.store.currentZIndex;
|
|
87
|
+
object.editor = object.createEditor();
|
|
88
|
+
return object;
|
|
89
|
+
}
|
|
90
|
+
mount(element) {
|
|
91
|
+
if (element === null || this.isInViewport() === false) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
element.style.fontFamily = this.fontFamily;
|
|
95
|
+
element.style.fontSize = `${this.fontSize}pt`;
|
|
96
|
+
element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
|
|
97
|
+
if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
|
|
98
|
+
if (!this._core.store.state.isScaling && !this._core.store.state.isPanning) {
|
|
99
|
+
requestAnimationFrame(() => this.adjustSizeOnInput());
|
|
100
|
+
}
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
this.elementRef = element;
|
|
104
|
+
this.elementRef.style.whiteSpace = 'pre-wrap';
|
|
105
|
+
this.elementRef.style.wordWrap = 'break-word';
|
|
106
|
+
this.elementRef.innerHTML = '';
|
|
107
|
+
this.elementRef.appendChild(this.editor.dom);
|
|
108
|
+
this.isMounted = true;
|
|
109
|
+
requestAnimationFrame(() => this.adjustSizeOnInput());
|
|
110
|
+
}
|
|
111
|
+
createEditor() {
|
|
112
|
+
const doc = this._schema.node('doc', null, [this._schema.node('paragraph')]);
|
|
113
|
+
return new EditorView(null, {
|
|
114
|
+
state: EditorState.create({
|
|
115
|
+
doc: doc,
|
|
116
|
+
plugins: [keymap(baseKeymap)],
|
|
117
|
+
}),
|
|
118
|
+
editable: () => false,
|
|
119
|
+
dispatchTransaction: transaction => {
|
|
120
|
+
const newState = this.editor.state.apply(transaction);
|
|
121
|
+
this.editor.updateState(newState);
|
|
122
|
+
if (transaction.docChanged) {
|
|
123
|
+
this.content = newState.doc.toJSON();
|
|
124
|
+
this.adjustSizeOnInput();
|
|
125
|
+
if (!transaction.getMeta('fromRemote')) {
|
|
126
|
+
this._core.store.state.objects.update(this, { temporary: true });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
setContent(content) {
|
|
133
|
+
this.content = content;
|
|
134
|
+
if (this.editor && content) {
|
|
135
|
+
const newDoc = this.editor.state.schema.nodeFromJSON(content);
|
|
136
|
+
const tr = this.editor.state.tr.replaceWith(0, this.editor.state.doc.content.size, newDoc.content);
|
|
137
|
+
tr.setMeta('fromRemote', true);
|
|
138
|
+
this.editor.dispatch(tr);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
adjustSizeOnInput() {
|
|
142
|
+
const element = this.elementRef;
|
|
143
|
+
if (element && this.isMounted && element.scrollWidth > 0) {
|
|
144
|
+
const previousTotalWidth = this.totalWidth;
|
|
145
|
+
const previousTotalHeight = this.totalHeight;
|
|
146
|
+
const newWidth = element.scrollWidth;
|
|
147
|
+
const newHeight = element.scrollHeight;
|
|
148
|
+
this.width = newWidth * this.scaleFactor;
|
|
149
|
+
this.height = newHeight * this.scaleFactor;
|
|
150
|
+
if (this.rotation !== 0) {
|
|
151
|
+
const newTotalWidth = this.totalWidth;
|
|
152
|
+
const newTotalHeight = this.totalHeight;
|
|
153
|
+
const deltaWidth = (newTotalWidth - previousTotalWidth) / 2 / this.scale;
|
|
154
|
+
const deltaHeight = (newTotalHeight - previousTotalHeight) / 2 / this.scale;
|
|
155
|
+
if (deltaWidth !== 0 || deltaHeight !== 0) {
|
|
156
|
+
const cos = Math.cos(this.rotation);
|
|
157
|
+
const sin = Math.sin(this.rotation);
|
|
158
|
+
const rotatedDeltaX = cos * deltaWidth - sin * deltaHeight;
|
|
159
|
+
const rotatedDeltaY = sin * deltaWidth + cos * deltaHeight;
|
|
160
|
+
this.translateX += rotatedDeltaX - deltaWidth;
|
|
161
|
+
this.translateY += rotatedDeltaY - deltaHeight;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
resize(x, y, width, height) {
|
|
167
|
+
if (width <= 1 || height <= 1) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const originalWidth = this.width / this.scaleFactor;
|
|
171
|
+
const originalHeight = this.height / this.scaleFactor;
|
|
172
|
+
const scaleX = width / originalWidth;
|
|
173
|
+
const scaleY = height / originalHeight;
|
|
174
|
+
this.scaleFactor = Math.min(scaleX, scaleY);
|
|
175
|
+
this.width = originalWidth * this.scaleFactor;
|
|
176
|
+
this.height = originalHeight * this.scaleFactor;
|
|
177
|
+
this.translateX = x;
|
|
178
|
+
this.translateY = y;
|
|
179
|
+
this._core.store.state.objects.update(this);
|
|
180
|
+
}
|
|
181
|
+
focus(coords) {
|
|
182
|
+
if (this.editor) {
|
|
183
|
+
const doc = this.editor.state.doc;
|
|
184
|
+
if (coords.x && coords.y && !this.isEmpty) {
|
|
185
|
+
const pos = this.editor.posAtCoords({ left: coords.x, top: coords.y });
|
|
186
|
+
if (pos) {
|
|
187
|
+
this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, pos.pos)));
|
|
188
|
+
this.editor.focus();
|
|
189
|
+
if (KritzelDevicesHelper.isIOS()) {
|
|
190
|
+
this.scrollIntoViewOnIOS();
|
|
191
|
+
}
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const end = Math.max(1, doc.content.size - 1);
|
|
196
|
+
this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, end)));
|
|
197
|
+
this.editor.focus();
|
|
198
|
+
if (KritzelDevicesHelper.isIOS()) {
|
|
199
|
+
this.scrollIntoViewOnIOS();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
scrollIntoViewOnIOS() {
|
|
204
|
+
setTimeout(() => {
|
|
205
|
+
if (this.editor && this.editor.dom) {
|
|
206
|
+
this.editor.dom.scrollIntoView({
|
|
207
|
+
behavior: 'smooth',
|
|
208
|
+
block: 'center',
|
|
209
|
+
inline: 'nearest'
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}, 300);
|
|
213
|
+
}
|
|
214
|
+
edit(event) {
|
|
215
|
+
KritzelKeyboardHelper.disableInteractiveWidget();
|
|
216
|
+
this.uneditedObject = this.clone();
|
|
217
|
+
this._core.store.setState('activeTool', KritzelToolRegistry.getTool('text'));
|
|
218
|
+
this.editor.setProps({ editable: () => true });
|
|
219
|
+
this.isEditing = true;
|
|
220
|
+
this._core.rerender();
|
|
221
|
+
this.adjustSizeOnInput();
|
|
222
|
+
this.focus({ x: event === null || event === void 0 ? void 0 : event.clientX, y: event === null || event === void 0 ? void 0 : event.clientY });
|
|
223
|
+
KritzelKeyboardHelper.enableInteractiveWidget();
|
|
224
|
+
}
|
|
225
|
+
save() {
|
|
226
|
+
requestAnimationFrame(() => this.adjustSizeOnInput());
|
|
227
|
+
this.content = this.editor.state.doc.toJSON();
|
|
228
|
+
this.editor.setProps({ editable: () => false });
|
|
229
|
+
this.editor.dom.blur();
|
|
230
|
+
this.isEditing = false;
|
|
231
|
+
this._core.store.state.objects.consolidateTemporaryItems();
|
|
232
|
+
this._core.store.state.objects.update(this);
|
|
233
|
+
this._core.engine.emitObjectsChange();
|
|
234
|
+
}
|
|
235
|
+
handlePointerDown(event) {
|
|
236
|
+
if (!this.isEditing) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
event.stopPropagation();
|
|
240
|
+
}
|
|
241
|
+
handlePointerMove(event) {
|
|
242
|
+
if (!this.isEditing) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
// Only stop propagation if the engine is not tracking this pointer.
|
|
246
|
+
// During text creation, the engine adds the pointer before the text element
|
|
247
|
+
// is in the DOM. We must let move events propagate so the engine can
|
|
248
|
+
// update its pointer state.
|
|
249
|
+
if (!this._core.store.state.pointers.has(event.pointerId)) {
|
|
250
|
+
event.stopPropagation();
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
handlePointerUp(event) {
|
|
254
|
+
if (!this.isEditing) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
// Only stop propagation if the engine is not tracking this pointer.
|
|
258
|
+
// When a text is created during pointerdown, the engine adds the pointer
|
|
259
|
+
// to its map before the text element exists in the DOM. By the time
|
|
260
|
+
// pointerup fires, the text element may intercept the event (especially
|
|
261
|
+
// on iOS where pointer capture may not redirect events in shadow DOM).
|
|
262
|
+
// We must let the event propagate so the engine can clean up the pointer.
|
|
263
|
+
// Without this, stale pointers accumulate and single-finger touches
|
|
264
|
+
// get misinterpreted as two-finger zoom gestures.
|
|
265
|
+
if (!this._core.store.state.pointers.has(event.pointerId)) {
|
|
266
|
+
event.stopPropagation();
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
copy() {
|
|
270
|
+
const copiedObject = super.copy();
|
|
271
|
+
copiedObject.editor = copiedObject.createEditor();
|
|
272
|
+
if (this.content) {
|
|
273
|
+
copiedObject.setContent(this.content);
|
|
274
|
+
}
|
|
275
|
+
return copiedObject;
|
|
276
|
+
}
|
|
277
|
+
serialize() {
|
|
278
|
+
const _a = this, { _core, _elementRef, _schema, element, totalWidth, totalHeight, editor, uneditedObject } = _a, remainingProps = __rest(_a, ["_core", "_elementRef", "_schema", "element", "totalWidth", "totalHeight", "editor", "uneditedObject"]);
|
|
279
|
+
const clonedProps = structuredClone(remainingProps);
|
|
280
|
+
if (element && typeof element === 'object' && 'nodeType' in element && element.nodeType === 1) {
|
|
281
|
+
clonedProps.element = element.cloneNode(true);
|
|
282
|
+
}
|
|
283
|
+
return clonedProps;
|
|
284
|
+
}
|
|
285
|
+
deserialize(object) {
|
|
286
|
+
super.deserialize(object);
|
|
287
|
+
if (object.content) {
|
|
288
|
+
this.setContent(object.content);
|
|
289
|
+
}
|
|
290
|
+
return this;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import * as Y from 'yjs';
|
|
11
|
+
import * as encoding from 'lib0/encoding';
|
|
12
|
+
import * as decoding from 'lib0/decoding';
|
|
13
|
+
/**
|
|
14
|
+
* BroadcastChannel sync provider for cross-tab synchronization
|
|
15
|
+
* This is a lightweight alternative to y-webrtc for browser-tab-only sync
|
|
16
|
+
*/
|
|
17
|
+
export class BroadcastSyncProvider {
|
|
18
|
+
constructor(docName, doc, _options) {
|
|
19
|
+
this._synced = false;
|
|
20
|
+
this.handleDocUpdate = (update, origin) => {
|
|
21
|
+
// Don't broadcast updates that came from other tabs (to prevent loops)
|
|
22
|
+
if (origin !== this) {
|
|
23
|
+
const encoder = encoding.createEncoder();
|
|
24
|
+
encoding.writeVarUint(encoder, 0); // Message type: sync update
|
|
25
|
+
encoding.writeVarUint8Array(encoder, update);
|
|
26
|
+
this.channel.postMessage(encoding.toUint8Array(encoder));
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
this.doc = doc;
|
|
30
|
+
this.channel = new BroadcastChannel(docName);
|
|
31
|
+
// Handle incoming messages from other tabs
|
|
32
|
+
this.channel.onmessage = (event) => {
|
|
33
|
+
this.handleMessage(event.data);
|
|
34
|
+
};
|
|
35
|
+
// Listen to document updates and broadcast them
|
|
36
|
+
this.doc.on('update', this.handleDocUpdate);
|
|
37
|
+
// Send initial sync request
|
|
38
|
+
this.broadcastSync();
|
|
39
|
+
// Mark as synced after a short delay (to receive any pending updates)
|
|
40
|
+
setTimeout(() => {
|
|
41
|
+
this._synced = true;
|
|
42
|
+
}, 100);
|
|
43
|
+
console.info(`BroadcastChannel Provider initialized: ${docName}`);
|
|
44
|
+
}
|
|
45
|
+
handleMessage(message) {
|
|
46
|
+
const decoder = decoding.createDecoder(new Uint8Array(message));
|
|
47
|
+
const messageType = decoding.readVarUint(decoder);
|
|
48
|
+
switch (messageType) {
|
|
49
|
+
case 0: // Sync update
|
|
50
|
+
const update = decoding.readVarUint8Array(decoder);
|
|
51
|
+
Y.applyUpdate(this.doc, update, this);
|
|
52
|
+
break;
|
|
53
|
+
case 1: // Sync request
|
|
54
|
+
this.broadcastSync();
|
|
55
|
+
break;
|
|
56
|
+
case 2: // Sync response
|
|
57
|
+
const stateVector = decoding.readVarUint8Array(decoder);
|
|
58
|
+
const updateResponse = Y.encodeStateAsUpdate(this.doc, stateVector);
|
|
59
|
+
if (updateResponse.length > 0) {
|
|
60
|
+
const encoder = encoding.createEncoder();
|
|
61
|
+
encoding.writeVarUint(encoder, 0); // Send as regular update
|
|
62
|
+
encoding.writeVarUint8Array(encoder, updateResponse);
|
|
63
|
+
this.channel.postMessage(encoding.toUint8Array(encoder));
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
broadcastSync() {
|
|
69
|
+
// Broadcast our current state vector to request missing updates
|
|
70
|
+
const encoder = encoding.createEncoder();
|
|
71
|
+
encoding.writeVarUint(encoder, 2); // Message type: sync response
|
|
72
|
+
encoding.writeVarUint8Array(encoder, Y.encodeStateVector(this.doc));
|
|
73
|
+
this.channel.postMessage(encoding.toUint8Array(encoder));
|
|
74
|
+
}
|
|
75
|
+
connect() {
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
// Wait for initial sync to complete
|
|
78
|
+
if (this._synced) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
return new Promise((resolve) => {
|
|
82
|
+
const checkSync = () => {
|
|
83
|
+
if (this._synced) {
|
|
84
|
+
resolve();
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
setTimeout(checkSync, 50);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
checkSync();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
disconnect() {
|
|
95
|
+
// BroadcastChannel doesn't have explicit disconnect
|
|
96
|
+
}
|
|
97
|
+
destroy() {
|
|
98
|
+
this.doc.off('update', this.handleDocUpdate);
|
|
99
|
+
this.channel.close();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { HocuspocusProvider, HocuspocusProviderWebsocket } from '@hocuspocus/provider';
|
|
11
|
+
/**
|
|
12
|
+
* Hocuspocus sync provider for real-time collaboration
|
|
13
|
+
* Supports multiplexing - multiple documents can share the same WebSocket connection
|
|
14
|
+
*/
|
|
15
|
+
export class HocuspocusSyncProvider {
|
|
16
|
+
constructor(docName, doc, options) {
|
|
17
|
+
this.isConnected = false;
|
|
18
|
+
this.isSynced = false;
|
|
19
|
+
this.usesSharedSocket = false;
|
|
20
|
+
const name = (options === null || options === void 0 ? void 0 : options.name) || docName;
|
|
21
|
+
const url = (options === null || options === void 0 ? void 0 : options.url) || 'ws://localhost:1234';
|
|
22
|
+
// Use provided websocketProvider or the static shared one
|
|
23
|
+
const websocketProvider = (options === null || options === void 0 ? void 0 : options.websocketProvider) || HocuspocusSyncProvider.sharedWebSocketProvider;
|
|
24
|
+
if (websocketProvider) {
|
|
25
|
+
// Multiplexing mode - use shared WebSocket connection
|
|
26
|
+
this.usesSharedSocket = true;
|
|
27
|
+
const config = {
|
|
28
|
+
websocketProvider,
|
|
29
|
+
name,
|
|
30
|
+
document: doc,
|
|
31
|
+
token: (options === null || options === void 0 ? void 0 : options.token) || null,
|
|
32
|
+
onConnect: () => {
|
|
33
|
+
this.isConnected = true;
|
|
34
|
+
if (!(options === null || options === void 0 ? void 0 : options.quiet)) {
|
|
35
|
+
console.info(`Hocuspocus connected: ${name}`);
|
|
36
|
+
}
|
|
37
|
+
if (options === null || options === void 0 ? void 0 : options.onConnect) {
|
|
38
|
+
options.onConnect();
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
onDisconnect: () => {
|
|
42
|
+
this.isConnected = false;
|
|
43
|
+
this.isSynced = false;
|
|
44
|
+
if (!(options === null || options === void 0 ? void 0 : options.quiet)) {
|
|
45
|
+
console.info(`Hocuspocus disconnected: ${name}`);
|
|
46
|
+
}
|
|
47
|
+
if (options === null || options === void 0 ? void 0 : options.onDisconnect) {
|
|
48
|
+
options.onDisconnect();
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
onSynced: () => {
|
|
52
|
+
this.isSynced = true;
|
|
53
|
+
if (!(options === null || options === void 0 ? void 0 : options.quiet)) {
|
|
54
|
+
console.info(`Hocuspocus synced: ${name}`);
|
|
55
|
+
}
|
|
56
|
+
if (options === null || options === void 0 ? void 0 : options.onSynced) {
|
|
57
|
+
options.onSynced();
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
// Add optional settings
|
|
62
|
+
if ((options === null || options === void 0 ? void 0 : options.forceSyncInterval) !== undefined) {
|
|
63
|
+
config.forceSyncInterval = options.forceSyncInterval;
|
|
64
|
+
}
|
|
65
|
+
if (options === null || options === void 0 ? void 0 : options.onAuthenticationFailed) {
|
|
66
|
+
config.onAuthenticationFailed = options.onAuthenticationFailed;
|
|
67
|
+
}
|
|
68
|
+
if (options === null || options === void 0 ? void 0 : options.onStatus) {
|
|
69
|
+
config.onStatus = options.onStatus;
|
|
70
|
+
}
|
|
71
|
+
this.provider = new HocuspocusProvider(config);
|
|
72
|
+
// Must call attach() explicitly when using shared socket
|
|
73
|
+
this.provider.attach();
|
|
74
|
+
if (!(options === null || options === void 0 ? void 0 : options.quiet)) {
|
|
75
|
+
console.info(`Hocuspocus Provider initialized (multiplexed): ${name}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// Standalone mode - create own WebSocket connection
|
|
80
|
+
this.usesSharedSocket = false;
|
|
81
|
+
const config = {
|
|
82
|
+
url,
|
|
83
|
+
name,
|
|
84
|
+
document: doc,
|
|
85
|
+
token: (options === null || options === void 0 ? void 0 : options.token) || null,
|
|
86
|
+
onConnect: () => {
|
|
87
|
+
this.isConnected = true;
|
|
88
|
+
if (!(options === null || options === void 0 ? void 0 : options.quiet)) {
|
|
89
|
+
console.info(`Hocuspocus connected: ${name}`);
|
|
90
|
+
}
|
|
91
|
+
if (options === null || options === void 0 ? void 0 : options.onConnect) {
|
|
92
|
+
options.onConnect();
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
onDisconnect: () => {
|
|
96
|
+
this.isConnected = false;
|
|
97
|
+
this.isSynced = false;
|
|
98
|
+
if (!(options === null || options === void 0 ? void 0 : options.quiet)) {
|
|
99
|
+
console.info(`Hocuspocus disconnected: ${name}`);
|
|
100
|
+
}
|
|
101
|
+
if (options === null || options === void 0 ? void 0 : options.onDisconnect) {
|
|
102
|
+
options.onDisconnect();
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
onSynced: () => {
|
|
106
|
+
this.isSynced = true;
|
|
107
|
+
if (!(options === null || options === void 0 ? void 0 : options.quiet)) {
|
|
108
|
+
console.info(`Hocuspocus synced: ${name}`);
|
|
109
|
+
}
|
|
110
|
+
if (options === null || options === void 0 ? void 0 : options.onSynced) {
|
|
111
|
+
options.onSynced();
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
// Add optional settings
|
|
116
|
+
if ((options === null || options === void 0 ? void 0 : options.forceSyncInterval) !== undefined) {
|
|
117
|
+
config.forceSyncInterval = options.forceSyncInterval;
|
|
118
|
+
}
|
|
119
|
+
if (options === null || options === void 0 ? void 0 : options.onAuthenticationFailed) {
|
|
120
|
+
config.onAuthenticationFailed = options.onAuthenticationFailed;
|
|
121
|
+
}
|
|
122
|
+
if (options === null || options === void 0 ? void 0 : options.onStatus) {
|
|
123
|
+
config.onStatus = options.onStatus;
|
|
124
|
+
}
|
|
125
|
+
if (options === null || options === void 0 ? void 0 : options.WebSocketPolyfill) {
|
|
126
|
+
config.WebSocketPolyfill = options.WebSocketPolyfill;
|
|
127
|
+
}
|
|
128
|
+
this.provider = new HocuspocusProvider(config);
|
|
129
|
+
if (!(options === null || options === void 0 ? void 0 : options.quiet)) {
|
|
130
|
+
console.info(`Hocuspocus Provider initialized: ${url}/${name}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Create a shared WebSocket connection for multiplexing
|
|
136
|
+
* Call this once to create a shared connection that multiple providers can use
|
|
137
|
+
*/
|
|
138
|
+
static createSharedWebSocket(options) {
|
|
139
|
+
if (HocuspocusSyncProvider.sharedWebSocketProvider) {
|
|
140
|
+
console.warn('Shared WebSocket already exists. Returning existing instance.');
|
|
141
|
+
return HocuspocusSyncProvider.sharedWebSocketProvider;
|
|
142
|
+
}
|
|
143
|
+
const config = {
|
|
144
|
+
url: options.url,
|
|
145
|
+
};
|
|
146
|
+
if (options.WebSocketPolyfill) {
|
|
147
|
+
config.WebSocketPolyfill = options.WebSocketPolyfill;
|
|
148
|
+
}
|
|
149
|
+
if (options.onConnect) {
|
|
150
|
+
config.onConnect = options.onConnect;
|
|
151
|
+
}
|
|
152
|
+
if (options.onDisconnect) {
|
|
153
|
+
config.onDisconnect = options.onDisconnect;
|
|
154
|
+
}
|
|
155
|
+
if (options.onStatus) {
|
|
156
|
+
config.onStatus = options.onStatus;
|
|
157
|
+
}
|
|
158
|
+
HocuspocusSyncProvider.sharedWebSocketProvider = new HocuspocusProviderWebsocket(config);
|
|
159
|
+
console.info(`Shared Hocuspocus WebSocket created: ${options.url}`);
|
|
160
|
+
return HocuspocusSyncProvider.sharedWebSocketProvider;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Destroy the shared WebSocket connection
|
|
164
|
+
* Call this when you're done with all multiplexed providers
|
|
165
|
+
*/
|
|
166
|
+
static destroySharedWebSocket() {
|
|
167
|
+
if (HocuspocusSyncProvider.sharedWebSocketProvider) {
|
|
168
|
+
HocuspocusSyncProvider.sharedWebSocketProvider.destroy();
|
|
169
|
+
HocuspocusSyncProvider.sharedWebSocketProvider = null;
|
|
170
|
+
console.info('Shared Hocuspocus WebSocket destroyed');
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get the shared WebSocket provider instance (if it exists)
|
|
175
|
+
*/
|
|
176
|
+
static getSharedWebSocket() {
|
|
177
|
+
return HocuspocusSyncProvider.sharedWebSocketProvider;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Static factory method for creating HocuspocusSyncProvider with configuration options
|
|
181
|
+
* Returns a ProviderFactory that can be used in sync configuration
|
|
182
|
+
*/
|
|
183
|
+
static with(options) {
|
|
184
|
+
return {
|
|
185
|
+
create: (docName, doc) => {
|
|
186
|
+
return new HocuspocusSyncProvider(docName, doc, options);
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
connect() {
|
|
191
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
192
|
+
if (this.isSynced) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
return new Promise((resolve, reject) => {
|
|
196
|
+
const timeout = setTimeout(() => {
|
|
197
|
+
reject(new Error('Hocuspocus connection timeout'));
|
|
198
|
+
}, 10000); // 10 second timeout
|
|
199
|
+
const syncHandler = () => {
|
|
200
|
+
clearTimeout(timeout);
|
|
201
|
+
this.provider.off('synced', syncHandler);
|
|
202
|
+
resolve();
|
|
203
|
+
};
|
|
204
|
+
this.provider.on('synced', syncHandler);
|
|
205
|
+
// If already synced, resolve immediately
|
|
206
|
+
if (this.provider.isSynced) {
|
|
207
|
+
clearTimeout(timeout);
|
|
208
|
+
this.provider.off('synced', syncHandler);
|
|
209
|
+
resolve();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
// Connect if not already connected (standalone mode only)
|
|
213
|
+
if (!this.isConnected && !this.usesSharedSocket) {
|
|
214
|
+
this.provider.connect();
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
disconnect() {
|
|
220
|
+
if (this.provider) {
|
|
221
|
+
if (this.usesSharedSocket) {
|
|
222
|
+
// Detach from shared socket instead of disconnecting
|
|
223
|
+
this.provider.detach();
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
this.provider.disconnect();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
this.isConnected = false;
|
|
230
|
+
this.isSynced = false;
|
|
231
|
+
}
|
|
232
|
+
destroy() {
|
|
233
|
+
if (this.provider) {
|
|
234
|
+
this.provider.destroy();
|
|
235
|
+
}
|
|
236
|
+
this.isConnected = false;
|
|
237
|
+
this.isSynced = false;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// Static shared WebSocket instance for multiplexing
|
|
241
|
+
HocuspocusSyncProvider.sharedWebSocketProvider = null;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { IndexeddbPersistence } from 'y-indexeddb';
|
|
11
|
+
/**
|
|
12
|
+
* IndexedDB sync provider for local persistence
|
|
13
|
+
*/
|
|
14
|
+
export class IndexedDBSyncProvider {
|
|
15
|
+
constructor(docName, doc, options) {
|
|
16
|
+
this.isConnected = false;
|
|
17
|
+
const dbName = (options === null || options === void 0 ? void 0 : options.name) || docName;
|
|
18
|
+
this.provider = new IndexeddbPersistence(dbName, doc);
|
|
19
|
+
}
|
|
20
|
+
connect() {
|
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
if (this.isConnected) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
return new Promise(resolve => {
|
|
26
|
+
this.provider.on('synced', () => {
|
|
27
|
+
this.isConnected = true;
|
|
28
|
+
resolve();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
disconnect() {
|
|
34
|
+
// IndexedDB doesn't need explicit disconnect
|
|
35
|
+
this.isConnected = false;
|
|
36
|
+
}
|
|
37
|
+
destroy() {
|
|
38
|
+
if (this.provider) {
|
|
39
|
+
this.provider.destroy();
|
|
40
|
+
}
|
|
41
|
+
this.isConnected = false;
|
|
42
|
+
}
|
|
43
|
+
}
|