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,407 @@
|
|
|
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 { KritzelBaseObject } from './base-object.class';
|
|
13
|
+
/**
|
|
14
|
+
* KritzelGroup represents a permanent grouping of objects that act as a single unit.
|
|
15
|
+
*
|
|
16
|
+
* Unlike KritzelSelectionGroup (which is ephemeral and used for temporary multi-selection),
|
|
17
|
+
* KritzelGroup is persisted and saved with the workspace. Grouped objects move, resize,
|
|
18
|
+
* rotate, copy, and delete together as one unit.
|
|
19
|
+
*
|
|
20
|
+
* Key features:
|
|
21
|
+
* - Supports nested groups (groups can contain other groups)
|
|
22
|
+
* - Clicking any child selects the entire group
|
|
23
|
+
* - Can be ungrouped to restore children to top-level objects
|
|
24
|
+
*/
|
|
25
|
+
export class KritzelGroup extends KritzelBaseObject {
|
|
26
|
+
constructor() {
|
|
27
|
+
super(...arguments);
|
|
28
|
+
this.__class__ = 'KritzelGroup';
|
|
29
|
+
/**
|
|
30
|
+
* IDs of child objects within this group.
|
|
31
|
+
* Children can be any KritzelBaseObject, including other KritzelGroups for nesting.
|
|
32
|
+
*/
|
|
33
|
+
this.childIds = [];
|
|
34
|
+
/**
|
|
35
|
+
* Snapshots of child states for transformation operations (resize, rotate).
|
|
36
|
+
* Similar pattern to KritzelSelectionGroup.
|
|
37
|
+
*/
|
|
38
|
+
this.unchangedChildSnapshots = new Map();
|
|
39
|
+
this.snapshotRotation = 0;
|
|
40
|
+
this.snapshotTranslateX = 0;
|
|
41
|
+
this.snapshotTranslateY = 0;
|
|
42
|
+
this.snapshotTotalWidth = 0;
|
|
43
|
+
this.snapshotTotalHeight = 0;
|
|
44
|
+
this.snapshotScale = 1;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Retrieves the actual child objects from the store by their IDs.
|
|
48
|
+
*/
|
|
49
|
+
get children() {
|
|
50
|
+
return this.childIds
|
|
51
|
+
.map(id => {
|
|
52
|
+
const found = this._core.store.state.objects.filter(obj => obj.id === id);
|
|
53
|
+
return found.length > 0 ? found[0] : null;
|
|
54
|
+
})
|
|
55
|
+
.filter((obj) => obj !== null);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns the number of children in this group.
|
|
59
|
+
*/
|
|
60
|
+
get length() {
|
|
61
|
+
return this.childIds.length;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Creates a new empty KritzelGroup.
|
|
65
|
+
*/
|
|
66
|
+
static create(core) {
|
|
67
|
+
const group = new KritzelGroup();
|
|
68
|
+
group._core = core;
|
|
69
|
+
group.id = group.generateId();
|
|
70
|
+
group.workspaceId = core.store.state.activeWorkspace.id;
|
|
71
|
+
group.scale = core.store.state.scale;
|
|
72
|
+
group.zIndex = core.store.currentZIndex;
|
|
73
|
+
return group;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Creates a KritzelGroup from an array of objects.
|
|
77
|
+
* The objects are added as children and their bounding box is calculated.
|
|
78
|
+
*/
|
|
79
|
+
static createFromObjects(core, objects) {
|
|
80
|
+
const group = KritzelGroup.create(core);
|
|
81
|
+
// Add all objects as children
|
|
82
|
+
objects.forEach(obj => {
|
|
83
|
+
group.childIds.push(obj.id);
|
|
84
|
+
});
|
|
85
|
+
// Calculate bounding box from children
|
|
86
|
+
group.refreshBoundingBox();
|
|
87
|
+
group.captureChildSnapshots();
|
|
88
|
+
return group;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Finds the parent KritzelGroup that contains the given object as a child.
|
|
92
|
+
* Returns null if the object is not a child of any group.
|
|
93
|
+
*/
|
|
94
|
+
static findParentGroup(core, objectId) {
|
|
95
|
+
const allGroups = core.store.state.objects
|
|
96
|
+
.filter(obj => obj.__class__ === 'KritzelGroup');
|
|
97
|
+
for (const group of allGroups) {
|
|
98
|
+
if (group.childIds.includes(objectId)) {
|
|
99
|
+
return group;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Adds a child object to this group.
|
|
106
|
+
*/
|
|
107
|
+
addChild(object) {
|
|
108
|
+
if (!this.childIds.includes(object.id)) {
|
|
109
|
+
this.childIds.push(object.id);
|
|
110
|
+
this.refreshBoundingBox();
|
|
111
|
+
this.captureChildSnapshots();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Removes a child object from this group.
|
|
116
|
+
*/
|
|
117
|
+
removeChild(objectId) {
|
|
118
|
+
const index = this.childIds.indexOf(objectId);
|
|
119
|
+
if (index !== -1) {
|
|
120
|
+
this.childIds.splice(index, 1);
|
|
121
|
+
this.refreshBoundingBox();
|
|
122
|
+
this.captureChildSnapshots();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Ungroups this group, returning all children to top-level objects.
|
|
127
|
+
* The group itself should be removed after calling this.
|
|
128
|
+
*/
|
|
129
|
+
ungroup() {
|
|
130
|
+
return this.children;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Finalizes the group after children have been positioned (e.g., after paste).
|
|
134
|
+
* Refreshes the bounding box and captures child snapshots.
|
|
135
|
+
*/
|
|
136
|
+
finalize() {
|
|
137
|
+
this.refreshBoundingBox();
|
|
138
|
+
this.captureChildSnapshots();
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Recalculates the group's bounding box based on its children.
|
|
142
|
+
*/
|
|
143
|
+
refreshBoundingBox() {
|
|
144
|
+
if (this.children.length === 0) {
|
|
145
|
+
this.width = 0;
|
|
146
|
+
this.height = 0;
|
|
147
|
+
this.translateX = 0;
|
|
148
|
+
this.translateY = 0;
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (this.children.length === 1) {
|
|
152
|
+
// Single child: inherit its bounding box
|
|
153
|
+
const child = this.children[0];
|
|
154
|
+
this.translateX = child.boundingBox.x;
|
|
155
|
+
this.translateY = child.boundingBox.y;
|
|
156
|
+
this.width = child.boundingBox.width * this.scale;
|
|
157
|
+
this.height = child.boundingBox.height * this.scale;
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// Multiple children: calculate encompassing bounding box
|
|
161
|
+
const rotation = this.rotation;
|
|
162
|
+
const cos = Math.cos(-rotation);
|
|
163
|
+
const sin = Math.sin(-rotation);
|
|
164
|
+
let minX = Infinity;
|
|
165
|
+
let maxX = -Infinity;
|
|
166
|
+
let minY = Infinity;
|
|
167
|
+
let maxY = -Infinity;
|
|
168
|
+
this.children.forEach(child => {
|
|
169
|
+
const polygon = child.rotatedPolygon;
|
|
170
|
+
const corners = [polygon.topLeft, polygon.topRight, polygon.bottomRight, polygon.bottomLeft];
|
|
171
|
+
corners.forEach(corner => {
|
|
172
|
+
// Rotate corner into local space (aligned with group rotation)
|
|
173
|
+
const rx = corner.x * cos - corner.y * sin;
|
|
174
|
+
const ry = corner.x * sin + corner.y * cos;
|
|
175
|
+
if (rx < minX)
|
|
176
|
+
minX = rx;
|
|
177
|
+
if (rx > maxX)
|
|
178
|
+
maxX = rx;
|
|
179
|
+
if (ry < minY)
|
|
180
|
+
minY = ry;
|
|
181
|
+
if (ry > maxY)
|
|
182
|
+
maxY = ry;
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
// Dimensions in world units (unrotated)
|
|
186
|
+
const worldWidth = maxX - minX;
|
|
187
|
+
const worldHeight = maxY - minY;
|
|
188
|
+
this.width = (worldWidth - this.padding) * this.scale;
|
|
189
|
+
this.height = (worldHeight - this.padding) * this.scale;
|
|
190
|
+
// Center of the box in rotated space
|
|
191
|
+
const cRx = (minX + maxX) / 2;
|
|
192
|
+
const cRy = (minY + maxY) / 2;
|
|
193
|
+
// Rotate center back to world space
|
|
194
|
+
const cosR = Math.cos(rotation);
|
|
195
|
+
const sinR = Math.sin(rotation);
|
|
196
|
+
const cx = cRx * cosR - cRy * sinR;
|
|
197
|
+
const cy = cRx * sinR + cRy * cosR;
|
|
198
|
+
this.translateX = cx - (this.width / this.scale + 2 * this.padding) / 2;
|
|
199
|
+
this.translateY = cy - (this.height / this.scale + 2 * this.padding) / 2;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Captures snapshots of child states for transformation operations.
|
|
203
|
+
*/
|
|
204
|
+
captureChildSnapshots() {
|
|
205
|
+
this.unchangedChildSnapshots.clear();
|
|
206
|
+
this.snapshotRotation = this.rotation;
|
|
207
|
+
this.snapshotTranslateX = this.translateX;
|
|
208
|
+
this.snapshotTranslateY = this.translateY;
|
|
209
|
+
this.snapshotTotalWidth = this.totalWidth;
|
|
210
|
+
this.snapshotTotalHeight = this.totalHeight;
|
|
211
|
+
this.snapshotScale = this.scale || 1;
|
|
212
|
+
this.children.forEach(child => {
|
|
213
|
+
this.unchangedChildSnapshots.set(child.id, {
|
|
214
|
+
id: child.id,
|
|
215
|
+
translateX: child.translateX,
|
|
216
|
+
translateY: child.translateY,
|
|
217
|
+
rotation: child.rotation,
|
|
218
|
+
width: child.width,
|
|
219
|
+
height: child.height,
|
|
220
|
+
totalWidth: child.totalWidth,
|
|
221
|
+
totalHeight: child.totalHeight,
|
|
222
|
+
scale: child.scale,
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
227
|
+
// TRANSFORMATION METHODS
|
|
228
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
229
|
+
move(startX, startY, endX, endY) {
|
|
230
|
+
const deltaX = (startX - endX) / this._core.store.state.scale;
|
|
231
|
+
const deltaY = (startY - endY) / this._core.store.state.scale;
|
|
232
|
+
this.translateX += deltaX;
|
|
233
|
+
this.translateY += deltaY;
|
|
234
|
+
this._core.store.state.objects.transaction(() => {
|
|
235
|
+
this._core.store.state.objects.update(this);
|
|
236
|
+
this.children.forEach(child => {
|
|
237
|
+
child.move(startX, startY, endX, endY);
|
|
238
|
+
// Update any lines anchored to this child
|
|
239
|
+
this._core.anchorManager.updateAnchorsForObject(child.id);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
// Update snapshots
|
|
243
|
+
this.unchangedChildSnapshots.forEach(snapshot => {
|
|
244
|
+
snapshot.translateX += deltaX;
|
|
245
|
+
snapshot.translateY += deltaY;
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
resize(x, y, width, height) {
|
|
249
|
+
const widthScaleFactor = width / this.width;
|
|
250
|
+
const heightScaleFactor = height / this.height;
|
|
251
|
+
// Calculate old center
|
|
252
|
+
const oldCenterX = this.translateX + this.totalWidth / 2 / this.scale;
|
|
253
|
+
const oldCenterY = this.translateY + this.totalHeight / 2 / this.scale;
|
|
254
|
+
// Calculate new center
|
|
255
|
+
const newTotalWidth = width + this.padding * 2;
|
|
256
|
+
const newTotalHeight = height + this.padding * 2;
|
|
257
|
+
const newCenterX = x + newTotalWidth / 2 / this.scale;
|
|
258
|
+
const newCenterY = y + newTotalHeight / 2 / this.scale;
|
|
259
|
+
const rotation = this.rotation;
|
|
260
|
+
const cos = Math.cos(-rotation);
|
|
261
|
+
const sin = Math.sin(-rotation);
|
|
262
|
+
const cosR = Math.cos(rotation);
|
|
263
|
+
const sinR = Math.sin(rotation);
|
|
264
|
+
this._core.store.state.objects.transaction(() => {
|
|
265
|
+
this.children.forEach(child => {
|
|
266
|
+
// Calculate child center
|
|
267
|
+
const childCenterX = child.translateX + child.totalWidth / 2 / child.scale;
|
|
268
|
+
const childCenterY = child.translateY + child.totalHeight / 2 / child.scale;
|
|
269
|
+
// Vector from old group center to child center
|
|
270
|
+
const dx = childCenterX - oldCenterX;
|
|
271
|
+
const dy = childCenterY - oldCenterY;
|
|
272
|
+
// Rotate to local space
|
|
273
|
+
const localX = dx * cos - dy * sin;
|
|
274
|
+
const localY = dx * sin + dy * cos;
|
|
275
|
+
// Scale in local space
|
|
276
|
+
const scaledLocalX = localX * widthScaleFactor;
|
|
277
|
+
const scaledLocalY = localY * heightScaleFactor;
|
|
278
|
+
// Rotate back to world space
|
|
279
|
+
const rotatedX = scaledLocalX * cosR - scaledLocalY * sinR;
|
|
280
|
+
const rotatedY = scaledLocalX * sinR + scaledLocalY * cosR;
|
|
281
|
+
// New child center
|
|
282
|
+
const newChildCenterX = newCenterX + rotatedX;
|
|
283
|
+
const newChildCenterY = newCenterY + rotatedY;
|
|
284
|
+
// Calculate relative rotation for scaling
|
|
285
|
+
const relativeRotation = child.rotation - rotation;
|
|
286
|
+
const cosRel = Math.cos(relativeRotation);
|
|
287
|
+
const sinRel = Math.sin(relativeRotation);
|
|
288
|
+
const newChildWidthScale = Math.sqrt(Math.pow(widthScaleFactor * cosRel, 2) + Math.pow(heightScaleFactor * sinRel, 2));
|
|
289
|
+
const newChildHeightScale = Math.sqrt(Math.pow(widthScaleFactor * sinRel, 2) + Math.pow(heightScaleFactor * cosRel, 2));
|
|
290
|
+
const updatedWidth = child.width * newChildWidthScale;
|
|
291
|
+
const updatedHeight = child.height * newChildHeightScale;
|
|
292
|
+
const updatedTotalWidth = updatedWidth + child.padding * 2;
|
|
293
|
+
const updatedTotalHeight = updatedHeight + child.padding * 2;
|
|
294
|
+
const updatedX = newChildCenterX - updatedTotalWidth / 2 / child.scale;
|
|
295
|
+
const updatedY = newChildCenterY - updatedTotalHeight / 2 / child.scale;
|
|
296
|
+
child.resize(updatedX, updatedY, updatedWidth, updatedHeight);
|
|
297
|
+
// Update anchored lines
|
|
298
|
+
this._core.anchorManager.updateAnchorsForObject(child.id);
|
|
299
|
+
});
|
|
300
|
+
this.refreshBoundingBox();
|
|
301
|
+
this.captureChildSnapshots();
|
|
302
|
+
this._core.store.state.objects.update(this);
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
rotate(value) {
|
|
306
|
+
this.rotation = value;
|
|
307
|
+
const centerX = this.translateX + this.totalWidth / 2 / this.scale;
|
|
308
|
+
const centerY = this.translateY + this.totalHeight / 2 / this.scale;
|
|
309
|
+
const angle = value - this.snapshotRotation;
|
|
310
|
+
const cos = Math.cos(angle);
|
|
311
|
+
const sin = Math.sin(angle);
|
|
312
|
+
this._core.store.state.objects.transaction(() => {
|
|
313
|
+
this._core.store.state.objects.update(this);
|
|
314
|
+
this.children.forEach(child => {
|
|
315
|
+
const unchangedSnapshot = this.unchangedChildSnapshots.get(child.id);
|
|
316
|
+
if (!unchangedSnapshot)
|
|
317
|
+
return;
|
|
318
|
+
const offsetX = this.getOffsetXToCenterFromSnapshot(unchangedSnapshot);
|
|
319
|
+
const offsetY = this.getOffsetYToCenterFromSnapshot(unchangedSnapshot);
|
|
320
|
+
const rotatedX = cos * offsetX - sin * offsetY;
|
|
321
|
+
const rotatedY = sin * offsetX + cos * offsetY;
|
|
322
|
+
child.translateX = centerX + rotatedX - child.totalWidth / 2 / child.scale;
|
|
323
|
+
child.translateY = centerY + rotatedY - child.totalHeight / 2 / child.scale;
|
|
324
|
+
child.rotate(this.children.length === 1 ? value : unchangedSnapshot.rotation + angle);
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
getOffsetXToCenterFromSnapshot(snapshot) {
|
|
329
|
+
const childCenterX = snapshot.translateX + snapshot.totalWidth / snapshot.scale / 2;
|
|
330
|
+
const groupScale = this.snapshotScale || this.scale || 1;
|
|
331
|
+
const groupCenterX = this.snapshotTranslateX + this.snapshotTotalWidth / groupScale / 2;
|
|
332
|
+
return childCenterX - groupCenterX;
|
|
333
|
+
}
|
|
334
|
+
getOffsetYToCenterFromSnapshot(snapshot) {
|
|
335
|
+
const childCenterY = snapshot.translateY + snapshot.totalHeight / snapshot.scale / 2;
|
|
336
|
+
const groupScale = this.snapshotScale || this.scale || 1;
|
|
337
|
+
const groupCenterY = this.snapshotTranslateY + this.snapshotTotalHeight / groupScale / 2;
|
|
338
|
+
return childCenterY - groupCenterY;
|
|
339
|
+
}
|
|
340
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
341
|
+
// HIT TESTING
|
|
342
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
343
|
+
hitTest(x, y) {
|
|
344
|
+
// Check if point is inside any child
|
|
345
|
+
return this.children.some(child => child.hitTest(x, y));
|
|
346
|
+
}
|
|
347
|
+
hitTestPolygon(polygon) {
|
|
348
|
+
// Check if polygon intersects with any child
|
|
349
|
+
return this.children.some(child => child.hitTestPolygon(polygon));
|
|
350
|
+
}
|
|
351
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
352
|
+
// COPY & SERIALIZATION
|
|
353
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
354
|
+
copy() {
|
|
355
|
+
const copiedGroup = KritzelGroup.create(this._core);
|
|
356
|
+
// Deep copy all children but DON'T add to store yet
|
|
357
|
+
// Store the copied children temporarily for paste() to handle
|
|
358
|
+
const copiedChildren = [];
|
|
359
|
+
this.children
|
|
360
|
+
.sort((a, b) => a.zIndex - b.zIndex)
|
|
361
|
+
.forEach(child => {
|
|
362
|
+
const copiedChild = child.copy();
|
|
363
|
+
copiedChildren.push(copiedChild);
|
|
364
|
+
copiedGroup.childIds.push(copiedChild.id);
|
|
365
|
+
});
|
|
366
|
+
// Store copied children on the group for paste() to access
|
|
367
|
+
copiedGroup._pendingChildren = copiedChildren;
|
|
368
|
+
// Copy group properties
|
|
369
|
+
copiedGroup.rotation = this.rotation;
|
|
370
|
+
copiedGroup.translateX = this.translateX;
|
|
371
|
+
copiedGroup.translateY = this.translateY;
|
|
372
|
+
copiedGroup.width = this.width;
|
|
373
|
+
copiedGroup.height = this.height;
|
|
374
|
+
return copiedGroup;
|
|
375
|
+
}
|
|
376
|
+
serialize() {
|
|
377
|
+
const _a = this, { _core, _elementRef, element, totalWidth, totalHeight, unchangedChildSnapshots } = _a, remainingProps = __rest(_a, ["_core", "_elementRef", "element", "totalWidth", "totalHeight", "unchangedChildSnapshots"]);
|
|
378
|
+
const clonedProps = structuredClone(remainingProps);
|
|
379
|
+
// Convert Map to plain object for serialization
|
|
380
|
+
clonedProps.unchangedChildSnapshots = Object.fromEntries(this.unchangedChildSnapshots);
|
|
381
|
+
return clonedProps;
|
|
382
|
+
}
|
|
383
|
+
deserialize(object) {
|
|
384
|
+
super.deserialize(object);
|
|
385
|
+
// Restore the Map from serialized object
|
|
386
|
+
if (object.unchangedChildSnapshots) {
|
|
387
|
+
this.unchangedChildSnapshots = new Map(Object.entries(object.unchangedChildSnapshots));
|
|
388
|
+
}
|
|
389
|
+
return this;
|
|
390
|
+
}
|
|
391
|
+
update() {
|
|
392
|
+
this._core.store.state.objects.update(this);
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Updates the workspace ID for this group and all its children.
|
|
396
|
+
*/
|
|
397
|
+
updateWorkspaceId(workspaceId) {
|
|
398
|
+
this.workspaceId = workspaceId;
|
|
399
|
+
this.children.forEach(child => {
|
|
400
|
+
child.workspaceId = workspaceId;
|
|
401
|
+
// Recursively update nested groups
|
|
402
|
+
if (child instanceof KritzelGroup) {
|
|
403
|
+
child.updateWorkspaceId(workspaceId);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { KritzelBaseObject } from './base-object.class';
|
|
2
|
+
export class KritzelImage extends KritzelBaseObject {
|
|
3
|
+
constructor(config) {
|
|
4
|
+
super();
|
|
5
|
+
this.__class__ = 'KritzelImage';
|
|
6
|
+
this.src = '';
|
|
7
|
+
this.maxWidth = 300;
|
|
8
|
+
this.maxHeight = 300;
|
|
9
|
+
this.maxCompressionSize = 300;
|
|
10
|
+
this.isDebugInfoVisible = true;
|
|
11
|
+
this.src = (config === null || config === void 0 ? void 0 : config.src) || '';
|
|
12
|
+
this.x = (config === null || config === void 0 ? void 0 : config.x) || 0;
|
|
13
|
+
this.y = (config === null || config === void 0 ? void 0 : config.y) || 0;
|
|
14
|
+
this.translateX = (config === null || config === void 0 ? void 0 : config.translateX) || 0;
|
|
15
|
+
this.translateY = (config === null || config === void 0 ? void 0 : config.translateY) || 0;
|
|
16
|
+
this.scale = (config === null || config === void 0 ? void 0 : config.scale) || 1;
|
|
17
|
+
}
|
|
18
|
+
static create(core) {
|
|
19
|
+
const object = new KritzelImage();
|
|
20
|
+
object._core = core;
|
|
21
|
+
object.id = object.generateId();
|
|
22
|
+
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
23
|
+
object.x = 0;
|
|
24
|
+
object.y = 0;
|
|
25
|
+
object.translateX = 0;
|
|
26
|
+
object.translateY = 0;
|
|
27
|
+
object.scale = object._core.store.state.scale;
|
|
28
|
+
object.zIndex = core.store.currentZIndex;
|
|
29
|
+
return object;
|
|
30
|
+
}
|
|
31
|
+
resize(x, y, width, height) {
|
|
32
|
+
if (width <= 1 || height <= 1) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const scaleFactor = height / this.height;
|
|
36
|
+
this.width = this.width * scaleFactor;
|
|
37
|
+
this.height = this.height * scaleFactor;
|
|
38
|
+
this.translateX = x;
|
|
39
|
+
this.translateY = y;
|
|
40
|
+
// Update to sync changes to y.js and propagate to other tabs
|
|
41
|
+
this._core.store.state.objects.update(this);
|
|
42
|
+
}
|
|
43
|
+
calculateScaledDimensions(img) {
|
|
44
|
+
let scaledWidth = img.width;
|
|
45
|
+
let scaledHeight = img.height;
|
|
46
|
+
if (img.width > this.maxWidth || img.height > this.maxHeight) {
|
|
47
|
+
const widthRatio = this.maxWidth / img.width;
|
|
48
|
+
const heightRatio = this.maxHeight / img.height;
|
|
49
|
+
const scaleRatio = Math.min(widthRatio, heightRatio);
|
|
50
|
+
scaledWidth = img.width * scaleRatio;
|
|
51
|
+
scaledHeight = img.height * scaleRatio;
|
|
52
|
+
}
|
|
53
|
+
return { scaledWidth, scaledHeight };
|
|
54
|
+
}
|
|
55
|
+
}
|