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,409 @@
|
|
|
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 { KritzelGeometryHelper } from '../../helpers/geometry.helper';
|
|
13
|
+
import { KritzelBaseObject } from './base-object.class';
|
|
14
|
+
import { KritzelGroup } from './group.class';
|
|
15
|
+
export class KritzelSelectionGroup extends KritzelBaseObject {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(...arguments);
|
|
18
|
+
this.__class__ = 'KritzelSelectionGroup';
|
|
19
|
+
// Store only object IDs instead of full objects
|
|
20
|
+
this._objectIds = [];
|
|
21
|
+
// Cached objects array - invalidated when objectIds changes
|
|
22
|
+
this._cachedObjects = null;
|
|
23
|
+
this._cachedObjectIdsHash = '';
|
|
24
|
+
// Store snapshots of object state for transformations (rotation, resize)
|
|
25
|
+
this.unchangedObjectSnapshots = new Map();
|
|
26
|
+
this.snapshotRotation = 0;
|
|
27
|
+
}
|
|
28
|
+
get objectIds() {
|
|
29
|
+
return this._objectIds;
|
|
30
|
+
}
|
|
31
|
+
set objectIds(value) {
|
|
32
|
+
this._objectIds = value;
|
|
33
|
+
this._cachedObjects = null; // Invalidate cache
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Invalidate the cached objects array. Call this when objects might have changed
|
|
37
|
+
* externally (e.g., after undo/redo operations).
|
|
38
|
+
*/
|
|
39
|
+
invalidateObjectsCache() {
|
|
40
|
+
this._cachedObjects = null;
|
|
41
|
+
}
|
|
42
|
+
// Getter to retrieve actual objects from the store by their IDs
|
|
43
|
+
// Optimized: Caches result and only recomputes when objectIds changes
|
|
44
|
+
get objects() {
|
|
45
|
+
const currentHash = this._objectIds.join(',');
|
|
46
|
+
if (this._cachedObjects !== null && this._cachedObjectIdsHash === currentHash) {
|
|
47
|
+
return this._cachedObjects;
|
|
48
|
+
}
|
|
49
|
+
const idSet = new Set(this._objectIds);
|
|
50
|
+
const foundObjects = this._core.store.state.objects.filter(obj => idSet.has(obj.id));
|
|
51
|
+
// Preserve the original order from objectIds
|
|
52
|
+
const objectMap = new Map(foundObjects.map(obj => [obj.id, obj]));
|
|
53
|
+
this._cachedObjects = this._objectIds
|
|
54
|
+
.map(id => objectMap.get(id))
|
|
55
|
+
.filter((obj) => obj !== undefined);
|
|
56
|
+
this._cachedObjectIdsHash = currentHash;
|
|
57
|
+
return this._cachedObjects;
|
|
58
|
+
}
|
|
59
|
+
get length() {
|
|
60
|
+
return this.objectIds.length;
|
|
61
|
+
}
|
|
62
|
+
static create(core) {
|
|
63
|
+
const object = new KritzelSelectionGroup();
|
|
64
|
+
object._core = core;
|
|
65
|
+
object.id = object.generateId();
|
|
66
|
+
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
67
|
+
object.scale = core.store.state.scale;
|
|
68
|
+
object.zIndex = 99999;
|
|
69
|
+
return object;
|
|
70
|
+
}
|
|
71
|
+
addOrRemove(object) {
|
|
72
|
+
const index = this._objectIds.findIndex(id => id === object.id);
|
|
73
|
+
if (index === -1) {
|
|
74
|
+
this._objectIds.push(object.id);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
this._objectIds.splice(index, 1);
|
|
78
|
+
}
|
|
79
|
+
this._cachedObjects = null; // Invalidate cache
|
|
80
|
+
const children = this.objects; // Get cached objects once
|
|
81
|
+
this.captureUnchangedSnapshots(children);
|
|
82
|
+
this.refreshObjectDimensions(children);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Prepares the selection group and its children for a transform interaction (rotate/resize).
|
|
86
|
+
* Ensures snapshot state is aligned with the current visual state.
|
|
87
|
+
*/
|
|
88
|
+
beginTransform() {
|
|
89
|
+
const children = this.objects; // Get cached objects once
|
|
90
|
+
// Keep the selection group's bounding box current before snapshotting.
|
|
91
|
+
this.refreshObjectDimensions(children);
|
|
92
|
+
this.captureUnchangedSnapshots(children);
|
|
93
|
+
// Groups need their own child snapshots aligned with the current transform.
|
|
94
|
+
for (const obj of children) {
|
|
95
|
+
if (obj instanceof KritzelGroup) {
|
|
96
|
+
obj.finalize();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
deselectAllChildren() {
|
|
101
|
+
const children = this.objects;
|
|
102
|
+
for (const obj of children) {
|
|
103
|
+
obj.isSelected = false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
updateWorkspaceId(workspaceId) {
|
|
107
|
+
this.workspaceId = workspaceId;
|
|
108
|
+
const children = this.objects;
|
|
109
|
+
for (const obj of children) {
|
|
110
|
+
obj.workspaceId = workspaceId;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
updateZIndices(startZIndex) {
|
|
114
|
+
const children = this.objects;
|
|
115
|
+
for (let i = 0; i < children.length; i++) {
|
|
116
|
+
children[i].zIndex = startZIndex + i;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
updatePosition(x, y) {
|
|
120
|
+
const children = this.objects;
|
|
121
|
+
for (const obj of children) {
|
|
122
|
+
const deltaX = obj.translateX - this.translateX;
|
|
123
|
+
const deltaY = obj.translateY - this.translateY;
|
|
124
|
+
obj.updatePosition(x + deltaX, y + deltaY);
|
|
125
|
+
}
|
|
126
|
+
// Update snapshots
|
|
127
|
+
this.unchangedObjectSnapshots.forEach(snapshot => {
|
|
128
|
+
const deltaX = snapshot.translateX - this.translateX;
|
|
129
|
+
const deltaY = snapshot.translateY - this.translateY;
|
|
130
|
+
snapshot.translateX = x + deltaX;
|
|
131
|
+
snapshot.translateY = y + deltaY;
|
|
132
|
+
});
|
|
133
|
+
this.translateX = x;
|
|
134
|
+
this.translateY = y;
|
|
135
|
+
this._core.store.state.objects.update(this);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Capture snapshots of current object states for undo/redo operations
|
|
139
|
+
* @param cachedObjects Optional pre-fetched objects array to avoid redundant getter calls
|
|
140
|
+
*/
|
|
141
|
+
captureUnchangedSnapshots(cachedObjects) {
|
|
142
|
+
this.unchangedObjectSnapshots.clear();
|
|
143
|
+
this.snapshotRotation = this.rotation;
|
|
144
|
+
const children = cachedObjects !== null && cachedObjects !== void 0 ? cachedObjects : this.objects;
|
|
145
|
+
children.forEach(obj => {
|
|
146
|
+
this.unchangedObjectSnapshots.set(obj.id, {
|
|
147
|
+
id: obj.id,
|
|
148
|
+
translateX: obj.translateX,
|
|
149
|
+
translateY: obj.translateY,
|
|
150
|
+
rotation: obj.rotation,
|
|
151
|
+
width: obj.width,
|
|
152
|
+
height: obj.height,
|
|
153
|
+
totalWidth: obj.totalWidth,
|
|
154
|
+
totalHeight: obj.totalHeight,
|
|
155
|
+
scale: obj.scale,
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
serialize() {
|
|
160
|
+
const _a = this, { _core, _elementRef, element, totalWidth, totalHeight, unchangedObjectSnapshots, _cachedObjects, _cachedObjectIdsHash } = _a, remainingProps = __rest(_a, ["_core", "_elementRef", "element", "totalWidth", "totalHeight", "unchangedObjectSnapshots", "_cachedObjects", "_cachedObjectIdsHash"]);
|
|
161
|
+
const clonedProps = structuredClone(remainingProps);
|
|
162
|
+
// Ensure objectIds is serialized with the correct key name (getter returns _objectIds)
|
|
163
|
+
clonedProps.objectIds = this.objectIds;
|
|
164
|
+
delete clonedProps._objectIds;
|
|
165
|
+
if (element && typeof element === 'object' && 'nodeType' in element && element.nodeType === 1) {
|
|
166
|
+
clonedProps.element = element.cloneNode(true);
|
|
167
|
+
}
|
|
168
|
+
// Convert Map to plain object for serialization
|
|
169
|
+
clonedProps.unchangedObjectSnapshots = Object.fromEntries(this.unchangedObjectSnapshots);
|
|
170
|
+
return clonedProps;
|
|
171
|
+
}
|
|
172
|
+
deserialize(object) {
|
|
173
|
+
// First, deserialize all base properties using parent's deserialize
|
|
174
|
+
super.deserialize(object);
|
|
175
|
+
// Restore objectIds through setter
|
|
176
|
+
if (object.objectIds) {
|
|
177
|
+
this.objectIds = object.objectIds;
|
|
178
|
+
}
|
|
179
|
+
// Restore the Map from serialized object
|
|
180
|
+
if (object.unchangedObjectSnapshots) {
|
|
181
|
+
this.unchangedObjectSnapshots = new Map(Object.entries(object.unchangedObjectSnapshots));
|
|
182
|
+
}
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
update() {
|
|
186
|
+
// Only update the selection group itself
|
|
187
|
+
// Child objects are already updated during move/resize/rotate operations
|
|
188
|
+
// Updating them again here would create redundant y.js updates
|
|
189
|
+
this._core.store.state.objects.update(this);
|
|
190
|
+
}
|
|
191
|
+
move(startX, startY, endX, endY) {
|
|
192
|
+
const deltaX = (startX - endX) / this._core.store.state.scale;
|
|
193
|
+
const deltaY = (startY - endY) / this._core.store.state.scale;
|
|
194
|
+
this.translateX += deltaX;
|
|
195
|
+
this.translateY += deltaY;
|
|
196
|
+
this._core.store.state.objects.transaction(() => {
|
|
197
|
+
this._core.store.state.objects.update(this);
|
|
198
|
+
const children = this.objects;
|
|
199
|
+
for (const obj of children) {
|
|
200
|
+
obj.move(startX, startY, endX, endY);
|
|
201
|
+
// Update any lines that are anchored to this object
|
|
202
|
+
this._core.anchorManager.updateAnchorsForObject(obj.id);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
// Update snapshots
|
|
206
|
+
this.unchangedObjectSnapshots.forEach(snapshot => {
|
|
207
|
+
snapshot.translateX += deltaX;
|
|
208
|
+
snapshot.translateY += deltaY;
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
resize(x, y, width, height) {
|
|
212
|
+
const widthScaleFactor = width / this.width;
|
|
213
|
+
const heightScaleFactor = height / this.height;
|
|
214
|
+
// Calculate old center
|
|
215
|
+
const oldCenterX = this.translateX + this.totalWidth / 2 / this.scale;
|
|
216
|
+
const oldCenterY = this.translateY + this.totalHeight / 2 / this.scale;
|
|
217
|
+
// Calculate new center
|
|
218
|
+
const newTotalWidth = width + this.padding * 2;
|
|
219
|
+
const newTotalHeight = height + this.padding * 2;
|
|
220
|
+
const newCenterX = x + newTotalWidth / 2 / this.scale;
|
|
221
|
+
const newCenterY = y + newTotalHeight / 2 / this.scale;
|
|
222
|
+
const rotation = this.rotation;
|
|
223
|
+
const cos = Math.cos(-rotation);
|
|
224
|
+
const sin = Math.sin(-rotation);
|
|
225
|
+
const cosR = Math.cos(rotation);
|
|
226
|
+
const sinR = Math.sin(rotation);
|
|
227
|
+
this._core.store.state.objects.transaction(() => {
|
|
228
|
+
// Cache objects once to avoid repeated getter calls during resize
|
|
229
|
+
const children = this.objects;
|
|
230
|
+
children.forEach(child => {
|
|
231
|
+
// Calculate child center
|
|
232
|
+
const childCenterX = child.translateX + child.totalWidth / 2 / child.scale;
|
|
233
|
+
const childCenterY = child.translateY + child.totalHeight / 2 / child.scale;
|
|
234
|
+
// Vector from old group center to child center
|
|
235
|
+
const dx = childCenterX - oldCenterX;
|
|
236
|
+
const dy = childCenterY - oldCenterY;
|
|
237
|
+
// Rotate to local space (align with group axes)
|
|
238
|
+
const localX = dx * cos - dy * sin;
|
|
239
|
+
const localY = dx * sin + dy * cos;
|
|
240
|
+
// Scale in local space
|
|
241
|
+
const scaledLocalX = localX * widthScaleFactor;
|
|
242
|
+
const scaledLocalY = localY * heightScaleFactor;
|
|
243
|
+
// Rotate back to world space
|
|
244
|
+
const rotatedX = scaledLocalX * cosR - scaledLocalY * sinR;
|
|
245
|
+
const rotatedY = scaledLocalX * sinR + scaledLocalY * cosR;
|
|
246
|
+
// New child center
|
|
247
|
+
const newChildCenterX = newCenterX + rotatedX;
|
|
248
|
+
const newChildCenterY = newCenterY + rotatedY;
|
|
249
|
+
// New child top-left
|
|
250
|
+
// Calculate relative rotation
|
|
251
|
+
const relativeRotation = child.rotation - rotation;
|
|
252
|
+
const cosRel = Math.cos(relativeRotation);
|
|
253
|
+
const sinRel = Math.sin(relativeRotation);
|
|
254
|
+
// Project the group's scale factors onto the child's local axes
|
|
255
|
+
// We use absolute values because scaling is magnitude-based
|
|
256
|
+
// If the child is aligned (0 deg), cos=1, sin=0 -> scales match
|
|
257
|
+
// If the child is 90 deg, cos=0, sin=1 -> scales swap
|
|
258
|
+
const newChildWidthScale = Math.sqrt(Math.pow(widthScaleFactor * cosRel, 2) + Math.pow(heightScaleFactor * sinRel, 2));
|
|
259
|
+
const newChildHeightScale = Math.sqrt(Math.pow(widthScaleFactor * sinRel, 2) + Math.pow(heightScaleFactor * cosRel, 2));
|
|
260
|
+
const updatedWidth = child.width * newChildWidthScale;
|
|
261
|
+
const updatedHeight = child.height * newChildHeightScale;
|
|
262
|
+
const updatedTotalWidth = updatedWidth + child.padding * 2;
|
|
263
|
+
const updatedTotalHeight = updatedHeight + child.padding * 2;
|
|
264
|
+
const updatedX = newChildCenterX - updatedTotalWidth / 2 / child.scale;
|
|
265
|
+
const updatedY = newChildCenterY - updatedTotalHeight / 2 / child.scale;
|
|
266
|
+
child.resize(updatedX, updatedY, updatedWidth, updatedHeight);
|
|
267
|
+
// Update any lines that are anchored to this child object
|
|
268
|
+
this._core.anchorManager.updateAnchorsForObject(child.id);
|
|
269
|
+
});
|
|
270
|
+
// Refresh dimensions and update the SelectionGroup to propagate changes to other tabs
|
|
271
|
+
this.refreshObjectDimensions(children);
|
|
272
|
+
this.captureUnchangedSnapshots(children);
|
|
273
|
+
this._core.store.state.objects.update(this);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
rotate(value) {
|
|
277
|
+
this.rotation = value;
|
|
278
|
+
const centerX = this.translateX + this.totalWidth / 2 / this.scale;
|
|
279
|
+
const centerY = this.translateY + this.totalHeight / 2 / this.scale;
|
|
280
|
+
const angle = value - this.snapshotRotation;
|
|
281
|
+
const cos = Math.cos(angle);
|
|
282
|
+
const sin = Math.sin(angle);
|
|
283
|
+
// Cache objects once to avoid repeated getter calls during rotation
|
|
284
|
+
const children = this.objects;
|
|
285
|
+
this._core.store.state.objects.transaction(() => {
|
|
286
|
+
// Update the SelectionGroup itself to propagate rotation to other tabs
|
|
287
|
+
this._core.store.state.objects.update(this);
|
|
288
|
+
const childCount = children.length;
|
|
289
|
+
for (const child of children) {
|
|
290
|
+
const unchangedSnapshot = this.unchangedObjectSnapshots.get(child.id);
|
|
291
|
+
if (!unchangedSnapshot)
|
|
292
|
+
continue;
|
|
293
|
+
const offsetX = this.getOffsetXToCenterFromSnapshot(unchangedSnapshot);
|
|
294
|
+
const offsetY = this.getOffsetYToCenterFromSnapshot(unchangedSnapshot);
|
|
295
|
+
const rotatedX = cos * offsetX - sin * offsetY;
|
|
296
|
+
const rotatedY = sin * offsetX + cos * offsetY;
|
|
297
|
+
child.translateX = centerX + rotatedX - child.totalWidth / 2 / child.scale;
|
|
298
|
+
child.translateY = centerY + rotatedY - child.totalHeight / 2 / child.scale;
|
|
299
|
+
child.rotate(childCount === 1 ? value : unchangedSnapshot.rotation + angle);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
copy() {
|
|
304
|
+
const selectionGroup = KritzelSelectionGroup.create(this._core);
|
|
305
|
+
const children = this.objects;
|
|
306
|
+
// Sort children by zIndex and copy them
|
|
307
|
+
const sortedChildren = [...children].sort((a, b) => a.zIndex - b.zIndex);
|
|
308
|
+
for (const obj of sortedChildren) {
|
|
309
|
+
const copiedObject = obj.copy();
|
|
310
|
+
selectionGroup.addOrRemove(copiedObject);
|
|
311
|
+
}
|
|
312
|
+
selectionGroup.captureUnchangedSnapshots();
|
|
313
|
+
if (children.length === 1) {
|
|
314
|
+
selectionGroup.rotation = children[0].rotation;
|
|
315
|
+
}
|
|
316
|
+
return selectionGroup;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Refreshes the selection group's bounding box dimensions based on contained objects.
|
|
320
|
+
* @param cachedObjects Optional pre-fetched objects array to avoid redundant getter calls
|
|
321
|
+
* @param skipPersist If true, only updates local state without persisting to Yjs (used during undo/redo)
|
|
322
|
+
*/
|
|
323
|
+
refreshObjectDimensions(cachedObjects, skipPersist = false) {
|
|
324
|
+
const children = cachedObjects !== null && cachedObjects !== void 0 ? cachedObjects : this.objects;
|
|
325
|
+
if (children.length === 1) {
|
|
326
|
+
const obj = children[0];
|
|
327
|
+
this.minX = obj.boundingBox.x / this.scale;
|
|
328
|
+
this.maxX = obj.boundingBox.x / this.scale + obj.boundingBox.width;
|
|
329
|
+
this.minY = obj.boundingBox.y / this.scale;
|
|
330
|
+
this.maxY = obj.boundingBox.y / this.scale + obj.boundingBox.height;
|
|
331
|
+
this.translateX = (this.minX - this.padding) * this.scale;
|
|
332
|
+
this.translateY = (this.minY - this.padding) * this.scale;
|
|
333
|
+
this.width = (this.maxX - this.minX - this.padding) * this.scale;
|
|
334
|
+
this.height = (this.maxY - this.minY - this.padding) * this.scale;
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
const rotation = this.rotation;
|
|
338
|
+
const cos = Math.cos(-rotation);
|
|
339
|
+
const sin = Math.sin(-rotation);
|
|
340
|
+
let minX = Infinity;
|
|
341
|
+
let maxX = -Infinity;
|
|
342
|
+
let minY = Infinity;
|
|
343
|
+
let maxY = -Infinity;
|
|
344
|
+
children.forEach(obj => {
|
|
345
|
+
const polygon = obj.rotatedPolygon;
|
|
346
|
+
const corners = [polygon.topLeft, polygon.topRight, polygon.bottomRight, polygon.bottomLeft];
|
|
347
|
+
corners.forEach(corner => {
|
|
348
|
+
// Rotate corner into local space (aligned with group rotation)
|
|
349
|
+
const rx = corner.x * cos - corner.y * sin;
|
|
350
|
+
const ry = corner.x * sin + corner.y * cos;
|
|
351
|
+
if (rx < minX)
|
|
352
|
+
minX = rx;
|
|
353
|
+
if (rx > maxX)
|
|
354
|
+
maxX = rx;
|
|
355
|
+
if (ry < minY)
|
|
356
|
+
minY = ry;
|
|
357
|
+
if (ry > maxY)
|
|
358
|
+
maxY = ry;
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
// Dimensions in world units (unrotated)
|
|
362
|
+
const worldWidth = maxX - minX;
|
|
363
|
+
const worldHeight = maxY - minY;
|
|
364
|
+
this.width = (worldWidth - this.padding) * this.scale;
|
|
365
|
+
this.height = (worldHeight - this.padding) * this.scale;
|
|
366
|
+
// Center of the box in rotated space
|
|
367
|
+
const cRx = (minX + maxX) / 2;
|
|
368
|
+
const cRy = (minY + maxY) / 2;
|
|
369
|
+
// Rotate center back to world space
|
|
370
|
+
const cosR = Math.cos(rotation);
|
|
371
|
+
const sinR = Math.sin(rotation);
|
|
372
|
+
const cx = cRx * cosR - cRy * sinR;
|
|
373
|
+
const cy = cRx * sinR + cRy * cosR;
|
|
374
|
+
this.translateX = cx - (this.width / this.scale + 2 * this.padding) / 2;
|
|
375
|
+
this.translateY = cy - (this.height / this.scale + 2 * this.padding) / 2;
|
|
376
|
+
}
|
|
377
|
+
if (!skipPersist) {
|
|
378
|
+
this._core.store.state.objects.update(this);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
getOffsetXToCenterFromSnapshot(snapshot) {
|
|
382
|
+
const objCenterX = snapshot.translateX + snapshot.totalWidth / snapshot.scale / 2;
|
|
383
|
+
const groupCenterX = this.translateX + this.totalWidth / this.scale / 2;
|
|
384
|
+
return objCenterX - groupCenterX;
|
|
385
|
+
}
|
|
386
|
+
getOffsetYToCenterFromSnapshot(snapshot) {
|
|
387
|
+
const objCenterY = snapshot.translateY + snapshot.totalHeight / snapshot.scale / 2;
|
|
388
|
+
const groupCenterY = this.translateY + this.totalHeight / this.scale / 2;
|
|
389
|
+
return objCenterY - groupCenterY;
|
|
390
|
+
}
|
|
391
|
+
hitTest(x, y) {
|
|
392
|
+
const children = this.objects;
|
|
393
|
+
const isSingleLine = children.length === 1 && children[0].__class__ === 'KritzelLine';
|
|
394
|
+
if (isSingleLine) {
|
|
395
|
+
return children[0].hitTest(x, y);
|
|
396
|
+
}
|
|
397
|
+
const polygon = this.rotatedPolygon;
|
|
398
|
+
const polyPoints = [polygon.topLeft, polygon.topRight, polygon.bottomRight, polygon.bottomLeft];
|
|
399
|
+
if (KritzelGeometryHelper.isPointInPolygon({ x, y }, polyPoints)) {
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
for (const obj of children) {
|
|
403
|
+
if (obj.hitTest(x, y)) {
|
|
404
|
+
return true;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
}
|