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,213 @@
1
+ import { KritzelEventHelper } from '../../helpers/event.helper';
2
+ import { KritzelBaseHandler } from './base.handler';
3
+ import { KritzelLine } from '../objects/line.class';
4
+ /** Threshold in screen pixels for disconnecting anchored lines during drag */
5
+ const ANCHOR_DISCONNECT_THRESHOLD = 30;
6
+ export class KritzelMoveHandler extends KritzelBaseHandler {
7
+ constructor(core) {
8
+ super(core);
9
+ /** Initial position when drag started (for calculating total accumulated distance) */
10
+ this.initialDragX = 0;
11
+ this.initialDragY = 0;
12
+ /** Set of line IDs that have been disconnected from anchors during this drag */
13
+ this.disconnectedLineIds = new Set();
14
+ this.hasMoved = false;
15
+ this.trackedPointerId = null;
16
+ }
17
+ reset() {
18
+ this.dragStartX = 0;
19
+ this.dragStartY = 0;
20
+ this.startX = 0;
21
+ this.startY = 0;
22
+ this.endX = 0;
23
+ this.endY = 0;
24
+ this.initialDragX = 0;
25
+ this.initialDragY = 0;
26
+ this.disconnectedLineIds.clear();
27
+ this.hasMoved = false;
28
+ this.trackedPointerId = null;
29
+ }
30
+ cancelPendingDrag() {
31
+ this._core.store.state.isDragging = false;
32
+ this.reset();
33
+ }
34
+ handlePointerDown(event) {
35
+ if (event.pointerType === 'mouse') {
36
+ if (KritzelEventHelper.isLeftClick(event)) {
37
+ const selectionGroup = this._core.store.selectionGroup;
38
+ if ((selectionGroup === null || selectionGroup === void 0 ? void 0 : selectionGroup.isSelected) && !this._core.store.state.isResizeHandleSelected && !this._core.store.state.isRotationHandleSelected && !this._core.store.state.isLineHandleSelected) {
39
+ const clientX = event.clientX - this._core.store.offsetX;
40
+ const clientY = event.clientY - this._core.store.offsetY;
41
+ this._core.store.state.isDragging = true;
42
+ this.dragStartX = clientX;
43
+ this.dragStartY = clientY;
44
+ this.startX = this.dragStartX;
45
+ this.startY = this.dragStartY;
46
+ this.initialDragX = clientX;
47
+ this.initialDragY = clientY;
48
+ this.disconnectedLineIds.clear();
49
+ this.trackedPointerId = event.pointerId;
50
+ }
51
+ else {
52
+ this.trackedPointerId = null;
53
+ }
54
+ }
55
+ else {
56
+ this.trackedPointerId = null;
57
+ }
58
+ }
59
+ if (event.pointerType === 'touch' || event.pointerType === 'pen') {
60
+ const activePointers = Array.from(this._core.store.state.pointers.values());
61
+ if (this._core.store.state.pointers.size === 1) {
62
+ if (this._core.store.state.isScaling) {
63
+ this.trackedPointerId = null;
64
+ return;
65
+ }
66
+ const selectionGroup = this._core.store.selectionGroup;
67
+ if ((selectionGroup === null || selectionGroup === void 0 ? void 0 : selectionGroup.isSelected) && !this._core.store.state.isResizeHandleSelected && !this._core.store.state.isRotationHandleSelected && !this._core.store.state.isLineHandleSelected) {
68
+ const x = Math.round(activePointers[0].clientX - this._core.store.offsetX);
69
+ const y = Math.round(activePointers[0].clientY - this._core.store.offsetY);
70
+ this.dragStartX = x;
71
+ this.dragStartY = y;
72
+ this.startX = x;
73
+ this.startY = y;
74
+ this.initialDragX = x;
75
+ this.initialDragY = y;
76
+ this.disconnectedLineIds.clear();
77
+ this.trackedPointerId = event.pointerId;
78
+ }
79
+ else {
80
+ this.trackedPointerId = null;
81
+ }
82
+ }
83
+ }
84
+ }
85
+ handlePointerMove(event) {
86
+ if (this.trackedPointerId === null || this.trackedPointerId !== event.pointerId) {
87
+ return;
88
+ }
89
+ if (event.pointerType === 'mouse') {
90
+ const selectionGroup = this._core.store.selectionGroup;
91
+ if (this._core.store.state.isDragging && selectionGroup) {
92
+ const clientX = event.clientX - this._core.store.offsetX;
93
+ const clientY = event.clientY - this._core.store.offsetY;
94
+ this.endX = clientX;
95
+ this.endY = clientY;
96
+ const moveDeltaX = Math.abs(clientX - this.startX);
97
+ const moveDeltaY = Math.abs(clientY - this.startY);
98
+ const moveThreshold = 5;
99
+ if (this.hasMoved || moveDeltaX > moveThreshold || moveDeltaY > moveThreshold) {
100
+ // Check for anchor disconnect threshold on lines
101
+ this.checkAndDisconnectAnchors(clientX, clientY);
102
+ selectionGroup.move(clientX, clientY, this.dragStartX, this.dragStartY);
103
+ this.dragStartX = clientX;
104
+ this.dragStartY = clientY;
105
+ this.hasMoved = true;
106
+ }
107
+ }
108
+ }
109
+ if (event.pointerType === 'touch' || event.pointerType === 'pen') {
110
+ const activePointers = Array.from(this._core.store.state.pointers.values());
111
+ const selectionGroup = this._core.store.selectionGroup;
112
+ if (this._core.store.state.pointers.size === 1 &&
113
+ selectionGroup &&
114
+ !this._core.store.state.isResizeHandleSelected &&
115
+ !this._core.store.state.isRotationHandleSelected &&
116
+ !this._core.store.state.isScaling) {
117
+ const x = Math.round(activePointers[0].clientX - this._core.store.offsetX);
118
+ const y = Math.round(activePointers[0].clientY - this._core.store.offsetY);
119
+ this._core.store.state.isDragging = true;
120
+ this.endX = x;
121
+ this.endY = y;
122
+ const moveDeltaX = Math.abs(x - this.startX);
123
+ const moveDeltaY = Math.abs(y - this.startY);
124
+ const moveThreshold = 5;
125
+ if (this.hasMoved || moveDeltaX > moveThreshold || moveDeltaY > moveThreshold) {
126
+ clearTimeout(this._core.store.state.longTouchTimeout);
127
+ // Check for anchor disconnect threshold on lines
128
+ this.checkAndDisconnectAnchors(x, y);
129
+ selectionGroup.move(x, y, this.dragStartX, this.dragStartY);
130
+ this.dragStartX = x;
131
+ this.dragStartY = y;
132
+ this.hasMoved = true;
133
+ }
134
+ }
135
+ }
136
+ }
137
+ handlePointerUp(event) {
138
+ if (this.trackedPointerId === null || this.trackedPointerId !== event.pointerId) {
139
+ return;
140
+ }
141
+ if (event.pointerType === 'mouse') {
142
+ if (this._core.store.state.isDragging) {
143
+ this._core.store.state.isDragging = false;
144
+ if (this.hasMoved) {
145
+ this._core.store.selectionGroup.update();
146
+ this._core.engine.emitObjectsChange();
147
+ this._core.store.state.hasObjectsChanged = true;
148
+ }
149
+ }
150
+ }
151
+ if (event.pointerType === 'touch' || event.pointerType === 'pen') {
152
+ if (this._core.store.state.isDragging) {
153
+ this._core.store.state.isDragging = false;
154
+ if (this.hasMoved) {
155
+ this._core.store.selectionGroup.update();
156
+ this._core.engine.emitObjectsChange();
157
+ this._core.store.state.hasObjectsChanged = true;
158
+ }
159
+ }
160
+ }
161
+ this.reset();
162
+ }
163
+ /**
164
+ * Checks if the total accumulated drag distance exceeds the anchor disconnect threshold.
165
+ * If so, disconnects all anchors from any KritzelLine objects in the selection group.
166
+ * This allows anchored lines to be freely moved after dragging beyond the threshold.
167
+ */
168
+ checkAndDisconnectAnchors(currentX, currentY) {
169
+ const totalDeltaX = currentX - this.initialDragX;
170
+ const totalDeltaY = currentY - this.initialDragY;
171
+ const totalDistance = Math.sqrt(totalDeltaX * totalDeltaX + totalDeltaY * totalDeltaY);
172
+ if (totalDistance < ANCHOR_DISCONNECT_THRESHOLD) {
173
+ return;
174
+ }
175
+ const selectionGroup = this._core.store.selectionGroup;
176
+ if (!selectionGroup) {
177
+ return;
178
+ }
179
+ // Only disconnect lines if the selection group contains ONLY lines.
180
+ // If moving lines with other objects (e.g. shapes they might be anchored to), prevent auto-disconnect.
181
+ // Cache objects once to avoid repeated getter calls
182
+ const children = selectionGroup.objects;
183
+ const onlyLines = children.every(obj => obj instanceof KritzelLine);
184
+ if (!onlyLines) {
185
+ return;
186
+ }
187
+ // Find and disconnect anchors from all anchored lines in the selection
188
+ for (const obj of children) {
189
+ // Skip if already disconnected in this drag session
190
+ if (this.disconnectedLineIds.has(obj.id)) {
191
+ continue;
192
+ }
193
+ // Check if this is a line with anchors
194
+ if (obj instanceof KritzelLine) {
195
+ const line = obj;
196
+ const hasAnchors = line.startAnchor || line.endAnchor;
197
+ if (hasAnchors) {
198
+ // Disconnect both anchors
199
+ if (line.startAnchor) {
200
+ this._core.anchorManager.removeAnchor(line.id, 'start');
201
+ }
202
+ if (line.endAnchor) {
203
+ this._core.anchorManager.removeAnchor(line.id, 'end');
204
+ }
205
+ // Mark as disconnected so we don't try again
206
+ this.disconnectedLineIds.add(line.id);
207
+ // Update the line to persist the change
208
+ this._core.store.state.objects.update(line);
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
@@ -0,0 +1,205 @@
1
+ import { KritzelHandleType } from '../../enums/handle-type.enum';
2
+ import { KritzelEventHelper } from '../../helpers/event.helper';
3
+ import { KritzelBaseHandler } from './base.handler';
4
+ export class KritzelResizeHandler extends KritzelBaseHandler {
5
+ constructor(core) {
6
+ super(core);
7
+ this.initialMouseX = 0;
8
+ this.initialMouseY = 0;
9
+ this.initialSize = { x: 0, y: 0, width: 0, height: 0 };
10
+ this.newSize = { x: 0, y: 0, width: 0, height: 0 };
11
+ this.hasResized = false;
12
+ }
13
+ reset() {
14
+ this.initialMouseX = 0;
15
+ this.initialMouseY = 0;
16
+ this.initialSize = { x: 0, y: 0, width: 0, height: 0 };
17
+ this.newSize = { x: 0, y: 0, width: 0, height: 0 };
18
+ this.hasResized = false;
19
+ }
20
+ handlePointerDown(event) {
21
+ if (event.pointerType === 'mouse') {
22
+ if (KritzelEventHelper.isLeftClick(event)) {
23
+ const selectionGroup = this._core.store.selectionGroup;
24
+ if (selectionGroup && this._core.store.state.isResizeHandleSelected) {
25
+ const clientX = event.clientX - this._core.store.offsetX;
26
+ const clientY = event.clientY - this._core.store.offsetY;
27
+ this._core.store.state.isResizing = true;
28
+ this.initialMouseX = clientX;
29
+ this.initialMouseY = clientY;
30
+ this.initialSize.width = selectionGroup.width;
31
+ this.initialSize.height = selectionGroup.height;
32
+ this.initialSize.x = selectionGroup.translateX;
33
+ this.initialSize.y = selectionGroup.translateY;
34
+ }
35
+ }
36
+ }
37
+ if (event.pointerType === 'touch' || event.pointerType === 'pen') {
38
+ const activePointers = Array.from(this._core.store.state.pointers.values());
39
+ const firstTouch = activePointers[0];
40
+ if (!firstTouch) {
41
+ return;
42
+ }
43
+ if (activePointers.length === 1) {
44
+ const selectionGroup = this._core.store.selectionGroup;
45
+ if (selectionGroup && this._core.store.state.isResizeHandleSelected) {
46
+ const clientX = Math.round(firstTouch.clientX - this._core.store.offsetX);
47
+ const clientY = Math.round(firstTouch.clientY - this._core.store.offsetY);
48
+ this._core.store.state.isResizing = true;
49
+ this.initialMouseX = clientX;
50
+ this.initialMouseY = clientY;
51
+ this.initialSize.width = selectionGroup.width;
52
+ this.initialSize.height = selectionGroup.height;
53
+ this.initialSize.x = selectionGroup.translateX;
54
+ this.initialSize.y = selectionGroup.translateY;
55
+ clearTimeout(this._core.store.state.longTouchTimeout);
56
+ }
57
+ }
58
+ }
59
+ }
60
+ handlePointerMove(event) {
61
+ if (event.pointerType === 'mouse') {
62
+ const selectionGroup = this._core.store.selectionGroup;
63
+ if (this._core.store.state.isResizing && selectionGroup) {
64
+ const clientX = event.clientX - this._core.store.offsetX;
65
+ const clientY = event.clientY - this._core.store.offsetY;
66
+ const dx = clientX - this.initialMouseX;
67
+ const dy = clientY - this.initialMouseY;
68
+ const resizeDeltaX = Math.abs(dx);
69
+ const resizeDeltaY = Math.abs(dy);
70
+ const resizeThreshold = 5;
71
+ if (resizeDeltaX > resizeThreshold || resizeDeltaY > resizeThreshold) {
72
+ this.hasResized = true;
73
+ }
74
+ if (!this.hasResized) {
75
+ return;
76
+ }
77
+ const rotation = selectionGroup.rotation;
78
+ const sin = Math.sin(rotation);
79
+ const cos = Math.cos(rotation);
80
+ const objectScale = selectionGroup.scale || 1;
81
+ const currentScale = this._core.store.state.scale;
82
+ // Calculate delta in local unrotated space
83
+ // We rotate the screen delta by -rotation to align with the object's axes
84
+ const localDx = (dx * cos + dy * sin) / currentScale;
85
+ const localDy = (-dx * sin + dy * cos) / currentScale;
86
+ // Calculate the center of the selection group before resize
87
+ const initialCenterX = this.initialSize.x + this.initialSize.width / objectScale / 2;
88
+ const initialCenterY = this.initialSize.y + this.initialSize.height / objectScale / 2;
89
+ // The center moves by half of the screen delta (scaled)
90
+ // This is true regardless of rotation because the resize happens symmetrically around the center
91
+ // relative to the fixed point logic
92
+ const newCenterX = initialCenterX + dx / currentScale / 2;
93
+ const newCenterY = initialCenterY + dy / currentScale / 2;
94
+ switch (this._core.store.state.resizeHandleType) {
95
+ case KritzelHandleType.TopLeft:
96
+ this.newSize.width = this.initialSize.width - localDx * objectScale;
97
+ this.newSize.height = this.initialSize.height - localDy * objectScale;
98
+ break;
99
+ case KritzelHandleType.TopRight:
100
+ this.newSize.width = this.initialSize.width + localDx * objectScale;
101
+ this.newSize.height = this.initialSize.height - localDy * objectScale;
102
+ break;
103
+ case KritzelHandleType.BottomLeft:
104
+ this.newSize.width = this.initialSize.width - localDx * objectScale;
105
+ this.newSize.height = this.initialSize.height + localDy * objectScale;
106
+ break;
107
+ case KritzelHandleType.BottomRight:
108
+ this.newSize.width = this.initialSize.width + localDx * objectScale;
109
+ this.newSize.height = this.initialSize.height + localDy * objectScale;
110
+ break;
111
+ }
112
+ this.newSize.x = newCenterX - this.newSize.width / objectScale / 2;
113
+ this.newSize.y = newCenterY - this.newSize.height / objectScale / 2;
114
+ selectionGroup.resize(this.newSize.x, this.newSize.y, this.newSize.width, this.newSize.height);
115
+ }
116
+ }
117
+ if (event.pointerType === 'touch' || event.pointerType === 'pen') {
118
+ const activePointers = Array.from(this._core.store.state.pointers.values());
119
+ const oneFingerTouch = activePointers[0];
120
+ if (!oneFingerTouch) {
121
+ return;
122
+ }
123
+ const selectionGroup = this._core.store.selectionGroup;
124
+ if (this._core.store.state.isResizing && selectionGroup) {
125
+ const clientX = Math.round(oneFingerTouch.clientX - this._core.store.offsetX);
126
+ const clientY = Math.round(oneFingerTouch.clientY - this._core.store.offsetY);
127
+ const dx = clientX - this.initialMouseX;
128
+ const dy = clientY - this.initialMouseY;
129
+ const resizeDeltaX = Math.abs(dx);
130
+ const resizeDeltaY = Math.abs(dy);
131
+ const resizeThreshold = 5;
132
+ if (resizeDeltaX > resizeThreshold || resizeDeltaY > resizeThreshold) {
133
+ clearTimeout(this._core.store.state.longTouchTimeout);
134
+ this.hasResized = true;
135
+ }
136
+ if (!this.hasResized) {
137
+ return;
138
+ }
139
+ const rotation = selectionGroup.rotation;
140
+ const sin = Math.sin(rotation);
141
+ const cos = Math.cos(rotation);
142
+ const objectScale = selectionGroup.scale || 1;
143
+ const currentScale = this._core.store.state.scale;
144
+ // Calculate delta in local unrotated space
145
+ // We rotate the screen delta by -rotation to align with the object's axes
146
+ const localDx = (dx * cos + dy * sin) / currentScale;
147
+ const localDy = (-dx * sin + dy * cos) / currentScale;
148
+ // Calculate the center of the selection group before resize
149
+ const initialCenterX = this.initialSize.x + this.initialSize.width / objectScale / 2;
150
+ const initialCenterY = this.initialSize.y + this.initialSize.height / objectScale / 2;
151
+ // The center moves by half of the screen delta (scaled)
152
+ // This is true regardless of rotation because the resize happens symmetrically around the center
153
+ // relative to the fixed point logic
154
+ const newCenterX = initialCenterX + dx / currentScale / 2;
155
+ const newCenterY = initialCenterY + dy / currentScale / 2;
156
+ switch (this._core.store.state.resizeHandleType) {
157
+ case KritzelHandleType.TopLeft:
158
+ this.newSize.width = this.initialSize.width - localDx * objectScale;
159
+ this.newSize.height = this.initialSize.height - localDy * objectScale;
160
+ break;
161
+ case KritzelHandleType.TopRight:
162
+ this.newSize.width = this.initialSize.width + localDx * objectScale;
163
+ this.newSize.height = this.initialSize.height - localDy * objectScale;
164
+ break;
165
+ case KritzelHandleType.BottomLeft:
166
+ this.newSize.width = this.initialSize.width - localDx * objectScale;
167
+ this.newSize.height = this.initialSize.height + localDy * objectScale;
168
+ break;
169
+ case KritzelHandleType.BottomRight:
170
+ this.newSize.width = this.initialSize.width + localDx * objectScale;
171
+ this.newSize.height = this.initialSize.height + localDy * objectScale;
172
+ break;
173
+ }
174
+ this.newSize.x = newCenterX - this.newSize.width / objectScale / 2;
175
+ this.newSize.y = newCenterY - this.newSize.height / objectScale / 2;
176
+ selectionGroup.resize(this.newSize.x, this.newSize.y, this.newSize.width, this.newSize.height);
177
+ }
178
+ }
179
+ }
180
+ handlePointerUp(event) {
181
+ if (event.pointerType === 'mouse') {
182
+ if (this._core.store.state.isResizing) {
183
+ this._core.store.state.isResizing = false;
184
+ if (this.hasResized) {
185
+ this._core.store.selectionGroup.update();
186
+ this._core.engine.emitObjectsChange();
187
+ this._core.store.state.hasObjectsChanged = true;
188
+ }
189
+ this.reset();
190
+ }
191
+ }
192
+ if (event.pointerType === 'touch' || event.pointerType === 'pen') {
193
+ if (this._core.store.state.isResizing) {
194
+ this._core.store.state.isResizing = false;
195
+ if (this.hasResized) {
196
+ this._core.store.selectionGroup.update();
197
+ this._core.engine.emitObjectsChange();
198
+ this._core.store.state.hasObjectsChanged = true;
199
+ }
200
+ this.reset();
201
+ clearTimeout(this._core.store.state.longTouchTimeout);
202
+ }
203
+ }
204
+ }
205
+ }
@@ -0,0 +1,117 @@
1
+ import { KritzelEventHelper } from '../../helpers/event.helper';
2
+ import { KritzelBaseHandler } from './base.handler';
3
+ export class KritzelRotationHandler extends KritzelBaseHandler {
4
+ constructor(core) {
5
+ super(core);
6
+ this.initialRotation = 0;
7
+ this.rotation = 0;
8
+ this.initialSelectionGroupRotation = 0;
9
+ }
10
+ reset() {
11
+ this.initialRotation = 0;
12
+ this.rotation = 0;
13
+ }
14
+ handlePointerDown(event) {
15
+ if (event.pointerType === 'mouse') {
16
+ if (KritzelEventHelper.isLeftClick(event)) {
17
+ const selectionGroup = this._core.store.selectionGroup;
18
+ if (selectionGroup && this._core.store.state.isRotationHandleSelected) {
19
+ selectionGroup.beginTransform();
20
+ const clientX = event.clientX - this._core.store.offsetX;
21
+ const clientY = event.clientY - this._core.store.offsetY;
22
+ this._core.store.state.isRotating = true;
23
+ const objectScale = selectionGroup.scale || 1;
24
+ const centerX = selectionGroup.translateX + selectionGroup.width / 2 / objectScale;
25
+ const centerY = selectionGroup.translateY + selectionGroup.height / 2 / objectScale;
26
+ const cursorX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
27
+ const cursorY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
28
+ this.initialSelectionGroupRotation = selectionGroup.rotation;
29
+ this.initialRotation = Math.atan2(centerY - cursorY, centerX - cursorX) - selectionGroup.rotation;
30
+ }
31
+ }
32
+ }
33
+ if (event.pointerType === 'touch' || event.pointerType === 'pen') {
34
+ const activePointers = Array.from(this._core.store.state.pointers.values());
35
+ const firstTouch = activePointers[0];
36
+ if (!firstTouch) {
37
+ return;
38
+ }
39
+ if (activePointers.length === 1) {
40
+ const selectionGroup = this._core.store.selectionGroup;
41
+ if (selectionGroup && this._core.store.state.isRotationHandleSelected) {
42
+ selectionGroup.beginTransform();
43
+ const clientX = Math.round(firstTouch.clientX - this._core.store.offsetX);
44
+ const clientY = Math.round(firstTouch.clientY - this._core.store.offsetY);
45
+ this._core.store.state.isRotating = true;
46
+ const objectScale = selectionGroup.scale || 1;
47
+ const centerX = selectionGroup.translateX + selectionGroup.width / 2 / objectScale;
48
+ const centerY = selectionGroup.translateY + selectionGroup.height / 2 / objectScale;
49
+ const cursorX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
50
+ const cursorY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
51
+ this.initialSelectionGroupRotation = selectionGroup.rotation;
52
+ this.initialRotation = Math.atan2(centerY - cursorY, centerX - cursorX) - selectionGroup.rotation;
53
+ clearTimeout(this._core.store.state.longTouchTimeout);
54
+ }
55
+ }
56
+ }
57
+ }
58
+ handlePointerMove(event) {
59
+ if (event.pointerType === 'mouse') {
60
+ const selectionGroup = this._core.store.selectionGroup;
61
+ if (this._core.store.state.isRotating && selectionGroup) {
62
+ const clientX = event.clientX - this._core.store.offsetX;
63
+ const clientY = event.clientY - this._core.store.offsetY;
64
+ const objectScale = selectionGroup.scale || 1;
65
+ const groupCenterX = selectionGroup.translateX + selectionGroup.width / 2 / objectScale;
66
+ const groupCenterY = selectionGroup.translateY + selectionGroup.height / 2 / objectScale;
67
+ const cursorX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
68
+ const cursorY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
69
+ const currentRotation = Math.atan2(groupCenterY - cursorY, groupCenterX - cursorX);
70
+ this.rotation = currentRotation - this.initialRotation;
71
+ selectionGroup.rotate(this.rotation);
72
+ }
73
+ }
74
+ if (event.pointerType === 'touch' || event.pointerType === 'pen') {
75
+ const activePointers = Array.from(this._core.store.state.pointers.values());
76
+ const firstTouch = activePointers[0];
77
+ if (!firstTouch) {
78
+ return;
79
+ }
80
+ const selectionGroup = this._core.store.selectionGroup;
81
+ if (this._core.store.state.isRotating && selectionGroup) {
82
+ const clientX = Math.round(firstTouch.clientX - this._core.store.offsetX);
83
+ const clientY = Math.round(firstTouch.clientY - this._core.store.offsetY);
84
+ const objectScale = selectionGroup.scale || 1;
85
+ const groupCenterX = selectionGroup.translateX + selectionGroup.width / 2 / objectScale;
86
+ const groupCenterY = selectionGroup.translateY + selectionGroup.height / 2 / objectScale;
87
+ const cursorX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
88
+ const cursorY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
89
+ const currentRotation = Math.atan2(groupCenterY - cursorY, groupCenterX - cursorX);
90
+ this.rotation = currentRotation - this.initialRotation;
91
+ selectionGroup.rotate(this.rotation);
92
+ clearTimeout(this._core.store.state.longTouchTimeout);
93
+ }
94
+ }
95
+ }
96
+ handlePointerUp(event) {
97
+ if (event.pointerType === 'mouse') {
98
+ if (this._core.store.state.isRotating) {
99
+ this._core.store.selectionGroup.update();
100
+ this._core.engine.emitObjectsChange();
101
+ this._core.store.state.isRotating = false;
102
+ this._core.store.state.hasObjectsChanged = true;
103
+ this.reset();
104
+ }
105
+ }
106
+ if (event.pointerType === 'touch' || event.pointerType === 'pen') {
107
+ if (this._core.store.state.isRotating) {
108
+ this._core.store.selectionGroup.update();
109
+ this._core.engine.emitObjectsChange();
110
+ this._core.store.state.isRotating = false;
111
+ this._core.store.state.hasObjectsChanged = true;
112
+ this.reset();
113
+ clearTimeout(this._core.store.state.longTouchTimeout);
114
+ }
115
+ }
116
+ }
117
+ }