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.
Files changed (209) hide show
  1. package/dist/kritzel-react/lib/components/stencil-generated/components.js +122 -0
  2. package/dist/kritzel-react/lib/index.js +2 -0
  3. package/dist/kritzel-stencil/src/classes/core/core.class.js +797 -0
  4. package/dist/kritzel-stencil/src/classes/core/reviver.class.js +97 -0
  5. package/dist/kritzel-stencil/src/classes/core/store.class.js +153 -0
  6. package/dist/kritzel-stencil/src/classes/core/viewport.class.js +311 -0
  7. package/dist/kritzel-stencil/src/classes/core/workspace.class.js +34 -0
  8. package/dist/kritzel-stencil/src/classes/handlers/base.handler.js +6 -0
  9. package/dist/kritzel-stencil/src/classes/handlers/context-menu.handler.js +63 -0
  10. package/dist/kritzel-stencil/src/classes/handlers/hover.handler.js +18 -0
  11. package/dist/kritzel-stencil/src/classes/handlers/key.handler.js +76 -0
  12. package/dist/kritzel-stencil/src/classes/handlers/line-handle.handler.js +382 -0
  13. package/dist/kritzel-stencil/src/classes/handlers/move.handler.js +213 -0
  14. package/dist/kritzel-stencil/src/classes/handlers/resize.handler.js +205 -0
  15. package/dist/kritzel-stencil/src/classes/handlers/rotation.handler.js +117 -0
  16. package/dist/kritzel-stencil/src/classes/handlers/selection.handler.js +313 -0
  17. package/dist/kritzel-stencil/src/classes/managers/anchor.manager.js +1056 -0
  18. package/dist/kritzel-stencil/src/classes/managers/cursor.manager.js +117 -0
  19. package/dist/kritzel-stencil/src/classes/managers/theme.manager.js +103 -0
  20. package/dist/kritzel-stencil/src/classes/objects/base-object.class.js +249 -0
  21. package/dist/kritzel-stencil/src/classes/objects/custom-element.class.js +60 -0
  22. package/dist/kritzel-stencil/src/classes/objects/group.class.js +407 -0
  23. package/dist/kritzel-stencil/src/classes/objects/image.class.js +55 -0
  24. package/dist/kritzel-stencil/src/classes/objects/line.class.js +608 -0
  25. package/dist/kritzel-stencil/src/classes/objects/path.class.js +401 -0
  26. package/dist/kritzel-stencil/src/classes/objects/selection-box.class.js +21 -0
  27. package/dist/kritzel-stencil/src/classes/objects/selection-group.class.js +409 -0
  28. package/dist/kritzel-stencil/src/classes/objects/shape.class.js +412 -0
  29. package/dist/kritzel-stencil/src/classes/objects/text.class.js +292 -0
  30. package/dist/kritzel-stencil/src/classes/providers/broadcast-sync-provider.class.js +101 -0
  31. package/dist/kritzel-stencil/src/classes/providers/hocuspocus-sync-provider.class.js +241 -0
  32. package/dist/kritzel-stencil/src/classes/providers/indexeddb-sync-provider.class.js +43 -0
  33. package/dist/kritzel-stencil/src/classes/providers/websocket-sync-provider.class.js +98 -0
  34. package/dist/kritzel-stencil/src/classes/registries/icon-registry.class.js +66 -0
  35. package/dist/kritzel-stencil/src/classes/registries/tool.registry.js +21 -0
  36. package/dist/kritzel-stencil/src/classes/structures/app-state-map.structure.js +212 -0
  37. package/dist/kritzel-stencil/src/classes/structures/object-map.structure.js +414 -0
  38. package/dist/kritzel-stencil/src/classes/structures/quadtree.structure.js +151 -0
  39. package/dist/kritzel-stencil/src/classes/tools/base-tool.class.js +36 -0
  40. package/dist/kritzel-stencil/src/classes/tools/brush-tool.class.js +161 -0
  41. package/dist/kritzel-stencil/src/classes/tools/eraser-tool.class.js +85 -0
  42. package/dist/kritzel-stencil/src/classes/tools/image-tool.class.js +83 -0
  43. package/dist/kritzel-stencil/src/classes/tools/line-tool.class.js +187 -0
  44. package/dist/kritzel-stencil/src/classes/tools/selection-tool.class.js +429 -0
  45. package/dist/kritzel-stencil/src/classes/tools/shape-tool.class.js +196 -0
  46. package/dist/kritzel-stencil/src/classes/tools/text-tool.class.js +100 -0
  47. package/dist/kritzel-stencil/src/components/core/kritzel-engine/kritzel-engine.js +1343 -0
  48. package/dist/kritzel-stencil/src/components/shared/kritzel-brush-style/kritzel-brush-style.js +46 -0
  49. package/dist/kritzel-stencil/src/components/shared/kritzel-dropdown/kritzel-dropdown.js +312 -0
  50. package/dist/kritzel-stencil/src/components/shared/kritzel-font-family/kritzel-font-family.js +60 -0
  51. package/dist/kritzel-stencil/src/components/shared/kritzel-line-endings/kritzel-line-endings.js +105 -0
  52. package/dist/kritzel-stencil/src/components/shared/kritzel-shape-fill/kritzel-shape-fill.js +53 -0
  53. package/dist/kritzel-stencil/src/components/ui/kritzel-context-menu/kritzel-context-menu.js +137 -0
  54. package/dist/kritzel-stencil/src/configs/default-brush-tool.config.js +9 -0
  55. package/dist/kritzel-stencil/src/configs/default-engine-config.js +63 -0
  56. package/dist/kritzel-stencil/src/configs/default-line-tool.config.js +9 -0
  57. package/dist/kritzel-stencil/src/configs/default-sync.config.js +9 -0
  58. package/dist/kritzel-stencil/src/configs/default-text-tool.config.js +7 -0
  59. package/dist/kritzel-stencil/src/constants/color-palette.constants.js +37 -0
  60. package/dist/kritzel-stencil/src/constants/engine.constants.js +2 -0
  61. package/dist/kritzel-stencil/src/enums/event-button.enum.js +6 -0
  62. package/dist/kritzel-stencil/src/enums/handle-type.enum.js +7 -0
  63. package/dist/kritzel-stencil/src/enums/shape-type.enum.js +6 -0
  64. package/dist/kritzel-stencil/src/helpers/class.helper.js +5 -0
  65. package/dist/kritzel-stencil/src/helpers/color.helper.js +106 -0
  66. package/dist/kritzel-stencil/src/helpers/cursor.helper.js +57 -0
  67. package/dist/kritzel-stencil/src/helpers/devices.helper.js +28 -0
  68. package/dist/kritzel-stencil/src/helpers/event.helper.js +58 -0
  69. package/dist/kritzel-stencil/src/helpers/geometry.helper.js +149 -0
  70. package/dist/kritzel-stencil/src/helpers/keyboard.helper.js +51 -0
  71. package/dist/kritzel-stencil/src/helpers/math.helper.js +5 -0
  72. package/dist/kritzel-stencil/src/helpers/object.helper.js +11 -0
  73. package/dist/kritzel-stencil/src/helpers/theme.helper.js +69 -0
  74. package/dist/kritzel-stencil/src/index.js +41 -0
  75. package/dist/kritzel-stencil/src/interfaces/anchor.interface.js +1 -0
  76. package/dist/kritzel-stencil/src/interfaces/arrow-head.interface.js +1 -0
  77. package/dist/kritzel-stencil/src/interfaces/bounding-box.interface.js +1 -0
  78. package/dist/kritzel-stencil/src/interfaces/clonable.interface.js +1 -0
  79. package/dist/kritzel-stencil/src/interfaces/context-menu-item.interface.js +1 -0
  80. package/dist/kritzel-stencil/src/interfaces/debug-info.interface.js +1 -0
  81. package/dist/kritzel-stencil/src/interfaces/dialog.interface.js +1 -0
  82. package/dist/kritzel-stencil/src/interfaces/displayable-shortcut.interface.js +1 -0
  83. package/dist/kritzel-stencil/src/interfaces/engine-state.interface.js +1 -0
  84. package/dist/kritzel-stencil/src/interfaces/line-options.interface.js +1 -0
  85. package/dist/kritzel-stencil/src/interfaces/master-detail.interface.js +1 -0
  86. package/dist/kritzel-stencil/src/interfaces/menu-item.interface.js +1 -0
  87. package/dist/kritzel-stencil/src/interfaces/object.interface.js +1 -0
  88. package/dist/kritzel-stencil/src/interfaces/path-options.interface.js +1 -0
  89. package/dist/kritzel-stencil/src/interfaces/point.interface.js +1 -0
  90. package/dist/kritzel-stencil/src/interfaces/polygon.interface.js +1 -0
  91. package/dist/kritzel-stencil/src/interfaces/serializable.interface.js +1 -0
  92. package/dist/kritzel-stencil/src/interfaces/settings.interface.js +1 -0
  93. package/dist/kritzel-stencil/src/interfaces/shortcut.interface.js +1 -0
  94. package/dist/kritzel-stencil/src/interfaces/sync-config.interface.js +1 -0
  95. package/dist/kritzel-stencil/src/interfaces/sync-provider.interface.js +1 -0
  96. package/dist/kritzel-stencil/src/interfaces/theme.interface.js +1 -0
  97. package/dist/kritzel-stencil/src/interfaces/tool-config.interface.js +1 -0
  98. package/dist/kritzel-stencil/src/interfaces/tool.interface.js +1 -0
  99. package/dist/kritzel-stencil/src/interfaces/toolbar-control.interface.js +1 -0
  100. package/dist/kritzel-stencil/src/interfaces/undo-state.interface.js +1 -0
  101. package/dist/kritzel-stencil/src/themes/dark-theme.js +198 -0
  102. package/dist/kritzel-stencil/src/themes/light-theme.js +199 -0
  103. package/dist/kritzel-stencil/src/types/shortcut.type.js +1 -0
  104. package/dist/kritzel-stencil/src/types/state.types.js +1 -0
  105. package/dist/types/kritzel-react/lib/components/stencil-generated/components.d.ts +74 -0
  106. package/dist/types/kritzel-react/lib/index.d.ts +2 -0
  107. package/dist/types/kritzel-stencil/src/classes/core/core.class.d.ts +101 -0
  108. package/dist/types/kritzel-stencil/src/classes/core/reviver.class.d.ts +6 -0
  109. package/dist/types/kritzel-stencil/src/classes/core/store.class.d.ts +53 -0
  110. package/dist/types/kritzel-stencil/src/classes/core/viewport.class.d.ts +48 -0
  111. package/dist/types/kritzel-stencil/src/classes/core/workspace.class.d.ts +24 -0
  112. package/dist/types/kritzel-stencil/src/classes/handlers/base.handler.d.ts +5 -0
  113. package/dist/types/kritzel-stencil/src/classes/handlers/context-menu.handler.d.ts +8 -0
  114. package/dist/types/kritzel-stencil/src/classes/handlers/hover.handler.d.ts +6 -0
  115. package/dist/types/kritzel-stencil/src/classes/handlers/key.handler.d.ts +11 -0
  116. package/dist/types/kritzel-stencil/src/classes/handlers/line-handle.handler.d.ts +34 -0
  117. package/dist/types/kritzel-stencil/src/classes/handlers/move.handler.d.ts +29 -0
  118. package/dist/types/kritzel-stencil/src/classes/handlers/resize.handler.d.ts +24 -0
  119. package/dist/types/kritzel-stencil/src/classes/handlers/rotation.handler.d.ts +12 -0
  120. package/dist/types/kritzel-stencil/src/classes/handlers/selection.handler.d.ts +27 -0
  121. package/dist/types/kritzel-stencil/src/classes/managers/anchor.manager.d.ts +180 -0
  122. package/dist/types/kritzel-stencil/src/classes/managers/cursor.manager.d.ts +43 -0
  123. package/dist/types/kritzel-stencil/src/classes/managers/theme.manager.d.ts +56 -0
  124. package/dist/types/kritzel-stencil/src/classes/objects/base-object.class.d.ts +76 -0
  125. package/dist/types/kritzel-stencil/src/classes/objects/custom-element.class.d.ts +26 -0
  126. package/dist/types/kritzel-stencil/src/classes/objects/group.class.d.ts +97 -0
  127. package/dist/types/kritzel-stencil/src/classes/objects/image.class.d.ts +17 -0
  128. package/dist/types/kritzel-stencil/src/classes/objects/line.class.d.ts +101 -0
  129. package/dist/types/kritzel-stencil/src/classes/objects/path.class.d.ts +62 -0
  130. package/dist/types/kritzel-stencil/src/classes/objects/selection-box.class.d.ts +6 -0
  131. package/dist/types/kritzel-stencil/src/classes/objects/selection-group.class.d.ts +67 -0
  132. package/dist/types/kritzel-stencil/src/classes/objects/shape.class.d.ts +124 -0
  133. package/dist/types/kritzel-stencil/src/classes/objects/text.class.d.ts +56 -0
  134. package/dist/types/kritzel-stencil/src/classes/providers/broadcast-sync-provider.class.d.ts +18 -0
  135. package/dist/types/kritzel-stencil/src/classes/providers/hocuspocus-sync-provider.class.d.ts +120 -0
  136. package/dist/types/kritzel-stencil/src/classes/providers/indexeddb-sync-provider.class.d.ts +22 -0
  137. package/dist/types/kritzel-stencil/src/classes/providers/websocket-sync-provider.class.d.ts +52 -0
  138. package/dist/types/kritzel-stencil/src/classes/registries/icon-registry.class.d.ts +9 -0
  139. package/dist/types/kritzel-stencil/src/classes/registries/tool.registry.d.ts +8 -0
  140. package/dist/types/kritzel-stencil/src/classes/structures/app-state-map.structure.d.ts +31 -0
  141. package/dist/types/kritzel-stencil/src/classes/structures/object-map.structure.d.ts +63 -0
  142. package/dist/types/kritzel-stencil/src/classes/structures/quadtree.structure.d.ts +36 -0
  143. package/dist/types/kritzel-stencil/src/classes/tools/base-tool.class.d.ts +20 -0
  144. package/dist/types/kritzel-stencil/src/classes/tools/brush-tool.class.d.ts +14 -0
  145. package/dist/types/kritzel-stencil/src/classes/tools/eraser-tool.class.d.ts +9 -0
  146. package/dist/types/kritzel-stencil/src/classes/tools/image-tool.class.d.ts +15 -0
  147. package/dist/types/kritzel-stencil/src/classes/tools/line-tool.class.d.ts +19 -0
  148. package/dist/types/kritzel-stencil/src/classes/tools/selection-tool.class.d.ts +54 -0
  149. package/dist/types/kritzel-stencil/src/classes/tools/shape-tool.class.d.ts +39 -0
  150. package/dist/types/kritzel-stencil/src/classes/tools/text-tool.class.d.ts +13 -0
  151. package/dist/types/kritzel-stencil/src/components/core/kritzel-engine/kritzel-engine.d.ts +111 -0
  152. package/dist/types/kritzel-stencil/src/components/shared/kritzel-brush-style/kritzel-brush-style.d.ts +11 -0
  153. package/dist/types/kritzel-stencil/src/components/shared/kritzel-dropdown/kritzel-dropdown.d.ts +46 -0
  154. package/dist/types/kritzel-stencil/src/components/shared/kritzel-font-family/kritzel-font-family.d.ts +13 -0
  155. package/dist/types/kritzel-stencil/src/components/shared/kritzel-line-endings/kritzel-line-endings.d.ts +21 -0
  156. package/dist/types/kritzel-stencil/src/components/shared/kritzel-shape-fill/kritzel-shape-fill.d.ts +10 -0
  157. package/dist/types/kritzel-stencil/src/components/ui/kritzel-context-menu/kritzel-context-menu.d.ts +21 -0
  158. package/dist/types/kritzel-stencil/src/configs/default-brush-tool.config.d.ts +2 -0
  159. package/dist/types/kritzel-stencil/src/configs/default-engine-config.d.ts +2 -0
  160. package/dist/types/kritzel-stencil/src/configs/default-line-tool.config.d.ts +2 -0
  161. package/dist/types/kritzel-stencil/src/configs/default-sync.config.d.ts +5 -0
  162. package/dist/types/kritzel-stencil/src/configs/default-text-tool.config.d.ts +2 -0
  163. package/dist/types/kritzel-stencil/src/constants/color-palette.constants.d.ts +29 -0
  164. package/dist/types/kritzel-stencil/src/constants/engine.constants.d.ts +2 -0
  165. package/dist/types/kritzel-stencil/src/enums/event-button.enum.d.ts +5 -0
  166. package/dist/types/kritzel-stencil/src/enums/handle-type.enum.d.ts +6 -0
  167. package/dist/types/kritzel-stencil/src/enums/shape-type.enum.d.ts +5 -0
  168. package/dist/types/kritzel-stencil/src/helpers/class.helper.d.ts +3 -0
  169. package/dist/types/kritzel-stencil/src/helpers/color.helper.d.ts +33 -0
  170. package/dist/types/kritzel-stencil/src/helpers/cursor.helper.d.ts +22 -0
  171. package/dist/types/kritzel-stencil/src/helpers/devices.helper.d.ts +8 -0
  172. package/dist/types/kritzel-stencil/src/helpers/event.helper.d.ts +6 -0
  173. package/dist/types/kritzel-stencil/src/helpers/geometry.helper.d.ts +38 -0
  174. package/dist/types/kritzel-stencil/src/helpers/keyboard.helper.d.ts +6 -0
  175. package/dist/types/kritzel-stencil/src/helpers/math.helper.d.ts +3 -0
  176. package/dist/types/kritzel-stencil/src/helpers/object.helper.d.ts +4 -0
  177. package/dist/types/kritzel-stencil/src/helpers/theme.helper.d.ts +41 -0
  178. package/dist/types/kritzel-stencil/src/index.d.ts +42 -0
  179. package/dist/types/kritzel-stencil/src/interfaces/anchor.interface.d.ts +137 -0
  180. package/dist/types/kritzel-stencil/src/interfaces/arrow-head.interface.d.ts +27 -0
  181. package/dist/types/kritzel-stencil/src/interfaces/bounding-box.interface.d.ts +8 -0
  182. package/dist/types/kritzel-stencil/src/interfaces/clonable.interface.d.ts +3 -0
  183. package/dist/types/kritzel-stencil/src/interfaces/context-menu-item.interface.d.ts +17 -0
  184. package/dist/types/kritzel-stencil/src/interfaces/debug-info.interface.d.ts +4 -0
  185. package/dist/types/kritzel-stencil/src/interfaces/dialog.interface.d.ts +4 -0
  186. package/dist/types/kritzel-stencil/src/interfaces/displayable-shortcut.interface.d.ts +5 -0
  187. package/dist/types/kritzel-stencil/src/interfaces/engine-state.interface.d.ts +73 -0
  188. package/dist/types/kritzel-stencil/src/interfaces/line-options.interface.d.ts +23 -0
  189. package/dist/types/kritzel-stencil/src/interfaces/master-detail.interface.d.ts +14 -0
  190. package/dist/types/kritzel-stencil/src/interfaces/menu-item.interface.d.ts +24 -0
  191. package/dist/types/kritzel-stencil/src/interfaces/object.interface.d.ts +53 -0
  192. package/dist/types/kritzel-stencil/src/interfaces/path-options.interface.d.ts +11 -0
  193. package/dist/types/kritzel-stencil/src/interfaces/point.interface.d.ts +4 -0
  194. package/dist/types/kritzel-stencil/src/interfaces/polygon.interface.d.ts +7 -0
  195. package/dist/types/kritzel-stencil/src/interfaces/serializable.interface.d.ts +5 -0
  196. package/dist/types/kritzel-stencil/src/interfaces/settings.interface.d.ts +11 -0
  197. package/dist/types/kritzel-stencil/src/interfaces/shortcut.interface.d.ts +10 -0
  198. package/dist/types/kritzel-stencil/src/interfaces/sync-config.interface.d.ts +22 -0
  199. package/dist/types/kritzel-stencil/src/interfaces/sync-provider.interface.d.ts +29 -0
  200. package/dist/types/kritzel-stencil/src/interfaces/theme.interface.d.ts +330 -0
  201. package/dist/types/kritzel-stencil/src/interfaces/tool-config.interface.d.ts +26 -0
  202. package/dist/types/kritzel-stencil/src/interfaces/tool.interface.d.ts +7 -0
  203. package/dist/types/kritzel-stencil/src/interfaces/toolbar-control.interface.d.ts +58 -0
  204. package/dist/types/kritzel-stencil/src/interfaces/undo-state.interface.d.ts +6 -0
  205. package/dist/types/kritzel-stencil/src/themes/dark-theme.d.ts +5 -0
  206. package/dist/types/kritzel-stencil/src/themes/light-theme.d.ts +5 -0
  207. package/dist/types/kritzel-stencil/src/types/shortcut.type.d.ts +1 -0
  208. package/dist/types/kritzel-stencil/src/types/state.types.d.ts +3 -0
  209. 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
+ }