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,18 @@
1
+ import { KritzelBaseHandler } from './base.handler';
2
+ export class KritzelHoverHandler extends KritzelBaseHandler {
3
+ constructor(core) {
4
+ super(core);
5
+ }
6
+ handlePointerMove(event) {
7
+ if (event.pointerType === 'mouse') {
8
+ const hoveredObject = this._core.getObjectFromPointerEvent(event, '.object');
9
+ if (!hoveredObject)
10
+ return;
11
+ const x = this._core.store.state.pointerX;
12
+ const y = this._core.store.state.pointerY;
13
+ hoveredObject.isHovered = hoveredObject.hitTest(x, y);
14
+ }
15
+ if (event.pointerType === 'touch' || event.pointerType === 'pen') {
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,76 @@
1
+ import { KritzelToolRegistry } from '../registries/tool.registry';
2
+ import { KritzelBaseHandler } from './base.handler';
3
+ export class KritzelKeyHandler extends KritzelBaseHandler {
4
+ constructor(core) {
5
+ super(core);
6
+ this.shortcuts = [
7
+ // General
8
+ { key: 'Escape', label: 'Clear Selection', category: 'General', condition: c => !!c.store.selectionGroup, action: c => c.clearSelection() },
9
+ { key: 'Delete', label: 'Delete Selected', category: 'General', condition: c => !!c.store.selectionGroup, action: c => c.delete() },
10
+ { key: 'a', ctrl: true, label: 'Select All in Viewport', category: 'General', action: c => c.selectAllObjectsInViewport() },
11
+ { key: 'A', ctrl: true, shift: true, label: 'Select All Objects', category: 'General', action: c => c.selectAllObjects() },
12
+ // Undo/Redo
13
+ { key: 'z', ctrl: true, label: 'Undo', category: 'Undo/Redo', action: c => c.undo() },
14
+ { key: 'y', ctrl: true, label: 'Redo', category: 'Undo/Redo', action: c => c.redo() },
15
+ // Tool selection (Ctrl+1-9)
16
+ { key: '1', ctrl: true, label: 'Tool 1', category: 'Tool Selection', action: () => this.switchToolByIndex(0) },
17
+ { key: '2', ctrl: true, label: 'Tool 2', category: 'Tool Selection', action: () => this.switchToolByIndex(1) },
18
+ { key: '3', ctrl: true, label: 'Tool 3', category: 'Tool Selection', action: () => this.switchToolByIndex(2) },
19
+ { key: '4', ctrl: true, label: 'Tool 4', category: 'Tool Selection', action: () => this.switchToolByIndex(3) },
20
+ { key: '5', ctrl: true, label: 'Tool 5', category: 'Tool Selection', action: () => this.switchToolByIndex(4) },
21
+ { key: '6', ctrl: true, label: 'Tool 6', category: 'Tool Selection', action: () => this.switchToolByIndex(5) },
22
+ { key: '7', ctrl: true, label: 'Tool 7', category: 'Tool Selection', action: () => this.switchToolByIndex(6) },
23
+ { key: '8', ctrl: true, label: 'Tool 8', category: 'Tool Selection', action: () => this.switchToolByIndex(7) },
24
+ { key: '9', ctrl: true, label: 'Tool 9', category: 'Tool Selection', action: () => this.switchToolByIndex(8) },
25
+ // Clipboard
26
+ {
27
+ key: 'c',
28
+ ctrl: true,
29
+ label: 'Copy',
30
+ category: 'Clipboard',
31
+ condition: c => !!c.store.selectionGroup,
32
+ action: c => {
33
+ c.copy();
34
+ c.rerender();
35
+ },
36
+ },
37
+ { key: 'v', ctrl: true, label: 'Paste', category: 'Clipboard', condition: c => !!c.store.state.copiedObjects && !c.store.activeText, action: c => c.paste() },
38
+ // Object layering
39
+ { key: '+', ctrl: true, label: 'Bring Forward', category: 'Object Layering', condition: c => !!c.store.selectionGroup, action: c => c.bringForward() },
40
+ { key: '-', ctrl: true, label: 'Send Backward', category: 'Object Layering', condition: c => !!c.store.selectionGroup, action: c => c.sendBackward() },
41
+ { key: '*', shift: true, label: 'Bring to Front', category: 'Object Layering', condition: c => !!c.store.selectionGroup, action: c => c.bringToFront() },
42
+ { key: '_', shift: true, label: 'Send to Back', category: 'Object Layering', condition: c => !!c.store.selectionGroup, action: c => c.sendToBack() },
43
+ // Grouping
44
+ { key: 'g', ctrl: true, label: 'Group', category: 'Grouping', condition: c => !!c.store.selectionGroup && c.store.selectionGroup.objects.length >= 2, action: c => c.group() },
45
+ { key: 'G', ctrl: true, shift: true, label: 'Ungroup', category: 'Grouping', condition: c => !!c.store.selectionGroup, action: c => c.ungroup() },
46
+ ];
47
+ }
48
+ switchToolByIndex(index) {
49
+ const toolInstance = KritzelToolRegistry.getToolByIndex(index);
50
+ if (toolInstance) {
51
+ this._core.store.setState('activeTool', toolInstance);
52
+ this._core.deselectAllObjects();
53
+ toolInstance.onActivate();
54
+ }
55
+ }
56
+ handleKeyDown(event) {
57
+ this._core.store.state.isCtrlKeyPressed = event.ctrlKey;
58
+ const shortcut = this.shortcuts.find(s => s.key === event.key && !!s.ctrl === event.ctrlKey && !!s.shift === event.shiftKey && (!s.condition || s.condition(this._core)));
59
+ if (shortcut) {
60
+ event.preventDefault();
61
+ shortcut.action(this._core);
62
+ }
63
+ }
64
+ handleKeyUp(event) {
65
+ this._core.store.state.isCtrlKeyPressed = event.ctrlKey;
66
+ }
67
+ getDisplayableShortcuts() {
68
+ return this.shortcuts.map(({ key, ctrl, shift, label, category }) => ({
69
+ key,
70
+ ctrl,
71
+ shift,
72
+ label,
73
+ category,
74
+ }));
75
+ }
76
+ }
@@ -0,0 +1,382 @@
1
+ import { KritzelEventHelper } from '../../helpers/event.helper';
2
+ import { KritzelLine } from '../objects/line.class';
3
+ import { KritzelBaseHandler } from './base.handler';
4
+ import { KritzelColorHelper } from '../../helpers/color.helper';
5
+ export class KritzelLineHandleHandler extends KritzelBaseHandler {
6
+ constructor(core) {
7
+ super(core);
8
+ this.initialMouseX = 0;
9
+ this.initialMouseY = 0;
10
+ this.initialStartX = 0;
11
+ this.initialStartY = 0;
12
+ this.initialEndX = 0;
13
+ this.initialEndY = 0;
14
+ this.initialTranslateX = 0;
15
+ this.initialTranslateY = 0;
16
+ this.hasMoved = false;
17
+ /** Current snap target during drag, if any */
18
+ this.currentSnapTarget = null;
19
+ }
20
+ reset() {
21
+ this.initialMouseX = 0;
22
+ this.initialMouseY = 0;
23
+ this.initialStartX = 0;
24
+ this.initialStartY = 0;
25
+ this.initialEndX = 0;
26
+ this.initialEndY = 0;
27
+ this.initialControlX = undefined;
28
+ this.initialControlY = undefined;
29
+ this.initialTranslateX = 0;
30
+ this.initialTranslateY = 0;
31
+ this.hasMoved = false;
32
+ this.currentSnapTarget = null;
33
+ this._core.anchorManager.clearSnapCandidate();
34
+ }
35
+ handlePointerDown(event) {
36
+ if (event.pointerType === 'mouse') {
37
+ if (KritzelEventHelper.isLeftClick(event)) {
38
+ this.startHandleDrag(event);
39
+ }
40
+ }
41
+ if (event.pointerType === 'touch' || event.pointerType === 'pen') {
42
+ const activePointers = Array.from(this._core.store.state.pointers.values());
43
+ if (activePointers.length === 1) {
44
+ this.startHandleDrag(event);
45
+ }
46
+ }
47
+ }
48
+ startHandleDrag(event) {
49
+ const line = this.getSelectedLine();
50
+ if (!line || !this._core.store.state.isLineHandleSelected) {
51
+ return;
52
+ }
53
+ const clientX = event.clientX - this._core.store.offsetX;
54
+ const clientY = event.clientY - this._core.store.offsetY;
55
+ this._core.store.state.isLineHandleDragging = true;
56
+ this.initialMouseX = clientX;
57
+ this.initialMouseY = clientY;
58
+ // Store initial line state
59
+ this.initialStartX = line.startX;
60
+ this.initialStartY = line.startY;
61
+ this.initialEndX = line.endX;
62
+ this.initialEndY = line.endY;
63
+ this.initialControlX = line.controlX;
64
+ this.initialControlY = line.controlY;
65
+ this.initialTranslateX = line.translateX;
66
+ this.initialTranslateY = line.translateY;
67
+ // Remove existing anchor for this endpoint when starting to drag
68
+ const handleType = this._core.store.state.lineHandleType;
69
+ if (handleType === 'start' || handleType === 'end') {
70
+ this._core.anchorManager.removeAnchor(line.id, handleType);
71
+ }
72
+ clearTimeout(this._core.store.state.longTouchTimeout);
73
+ }
74
+ handlePointerMove(event) {
75
+ var _a, _b, _c, _d, _e, _f, _g, _h;
76
+ const line = this.getSelectedLine();
77
+ if (!line || !this._core.store.state.isLineHandleDragging) {
78
+ return;
79
+ }
80
+ const clientX = event.clientX - this._core.store.offsetX;
81
+ const clientY = event.clientY - this._core.store.offsetY;
82
+ const dx = clientX - this.initialMouseX;
83
+ const dy = clientY - this.initialMouseY;
84
+ const moveThreshold = 3;
85
+ if (Math.abs(dx) > moveThreshold || Math.abs(dy) > moveThreshold) {
86
+ this.hasMoved = true;
87
+ }
88
+ if (!this.hasMoved) {
89
+ return;
90
+ }
91
+ const viewportScale = this._core.store.state.scale;
92
+ const objectScale = line.scale || 1;
93
+ const rotation = line.rotation;
94
+ // Convert mouse delta to world coordinates
95
+ const worldDx = dx / viewportScale;
96
+ const worldDy = dy / viewportScale;
97
+ // Rotate the delta into the line's local coordinate system
98
+ const cos = Math.cos(-rotation);
99
+ const sin = Math.sin(-rotation);
100
+ const localDx = (worldDx * cos - worldDy * sin) * objectScale;
101
+ const localDy = (worldDx * sin + worldDy * cos) * objectScale;
102
+ const handleType = this._core.store.state.lineHandleType;
103
+ if (handleType === 'start') {
104
+ // Calculate world position directly from mouse position for snap detection
105
+ const worldX = (clientX - this._core.store.state.translateX) / viewportScale;
106
+ const worldY = (clientY - this._core.store.state.translateY) / viewportScale;
107
+ // Get other endpoint's anchor to prevent anchoring both to same object
108
+ const otherAnchorId = (_a = line.endAnchor) === null || _a === void 0 ? void 0 : _a.objectId;
109
+ // Check for snap target
110
+ const snapTarget = this._core.anchorManager.findSnapTarget(worldX, worldY, line.id, otherAnchorId);
111
+ this.currentSnapTarget = snapTarget;
112
+ if (snapTarget) {
113
+ // Snap to target center - convert world coords to local
114
+ const localCoords = this.worldToLineLocal(line, snapTarget.centerX, snapTarget.centerY);
115
+ this.updateLineEndpoint(line, localCoords.x, localCoords.y, this.initialEndX, this.initialEndY);
116
+ // Get the other endpoint's world position for edge intersection calculation
117
+ const otherEndpointWorld = this.lineLocalToWorld(line, this.initialEndX, this.initialEndY);
118
+ // Calculate edge intersection point using AnchorManager to support curves
119
+ const targetObject = this._core.store.allNonSelectionObjects.find(obj => obj.id === snapTarget.objectId);
120
+ let edgeX;
121
+ let edgeY;
122
+ let t;
123
+ if (targetObject) {
124
+ const clipInfo = this._core.anchorManager.computeAnchorClipInfo(line, 'start', targetObject);
125
+ if (clipInfo) {
126
+ edgeX = clipInfo.worldX;
127
+ edgeY = clipInfo.worldY;
128
+ t = clipInfo.t;
129
+ }
130
+ }
131
+ // Calculate control point in world coordinates if it exists
132
+ let controlWorld = undefined;
133
+ if (line.controlX !== undefined && line.controlY !== undefined) {
134
+ controlWorld = this.lineLocalToWorld(line, line.controlX, line.controlY);
135
+ }
136
+ // Update snap indicator
137
+ this._core.anchorManager.setSnapCandidate({
138
+ objectId: snapTarget.objectId,
139
+ endpoint: 'start',
140
+ centerX: snapTarget.centerX,
141
+ centerY: snapTarget.centerY,
142
+ lineEndpointX: otherEndpointWorld.x,
143
+ lineEndpointY: otherEndpointWorld.y,
144
+ controlX: controlWorld === null || controlWorld === void 0 ? void 0 : controlWorld.x,
145
+ controlY: controlWorld === null || controlWorld === void 0 ? void 0 : controlWorld.y,
146
+ t,
147
+ edgeX,
148
+ edgeY,
149
+ lineStroke: KritzelColorHelper.resolveThemeColor(line.stroke),
150
+ lineStrokeWidth: line.strokeWidth / line.scale,
151
+ arrowOffset: line.hasStartArrow ? line.getArrowSize('start') / line.scale : undefined,
152
+ arrowStyle: line.hasStartArrow ? (_c = (_b = line.arrows) === null || _b === void 0 ? void 0 : _b.start) === null || _c === void 0 ? void 0 : _c.style : undefined,
153
+ arrowFill: line.hasStartArrow ? line.getArrowFill('start') : undefined,
154
+ });
155
+ }
156
+ else {
157
+ // No snap - use regular position
158
+ const newStartX = this.initialStartX + localDx;
159
+ const newStartY = this.initialStartY + localDy;
160
+ this.updateLineEndpoint(line, newStartX, newStartY, this.initialEndX, this.initialEndY);
161
+ // Clear snap indicator
162
+ this._core.anchorManager.clearSnapCandidate();
163
+ }
164
+ }
165
+ else if (handleType === 'end') {
166
+ // Calculate world position directly from mouse position for snap detection
167
+ const worldX = (clientX - this._core.store.state.translateX) / viewportScale;
168
+ const worldY = (clientY - this._core.store.state.translateY) / viewportScale;
169
+ // Get other endpoint's anchor to prevent anchoring both to same object
170
+ const otherAnchorId = (_d = line.startAnchor) === null || _d === void 0 ? void 0 : _d.objectId;
171
+ // Check for snap target
172
+ const snapTarget = this._core.anchorManager.findSnapTarget(worldX, worldY, line.id, otherAnchorId);
173
+ this.currentSnapTarget = snapTarget;
174
+ if (snapTarget) {
175
+ // Snap to target center - convert world coords to local
176
+ const localCoords = this.worldToLineLocal(line, snapTarget.centerX, snapTarget.centerY);
177
+ this.updateLineEndpoint(line, this.initialStartX, this.initialStartY, localCoords.x, localCoords.y);
178
+ // Get the other endpoint's world position for edge intersection calculation
179
+ const otherEndpointWorld = this.lineLocalToWorld(line, this.initialStartX, this.initialStartY);
180
+ // Calculate edge intersection point using AnchorManager to support curves
181
+ const targetObject = this._core.store.allNonSelectionObjects.find(obj => obj.id === snapTarget.objectId);
182
+ let edgeX;
183
+ let edgeY;
184
+ let t;
185
+ if (targetObject) {
186
+ const clipInfo = this._core.anchorManager.computeAnchorClipInfo(line, 'end', targetObject);
187
+ if (clipInfo) {
188
+ edgeX = clipInfo.worldX;
189
+ edgeY = clipInfo.worldY;
190
+ t = clipInfo.t;
191
+ }
192
+ }
193
+ // Calculate control point in world coordinates if it exists
194
+ let controlWorld = undefined;
195
+ if (line.controlX !== undefined && line.controlY !== undefined) {
196
+ controlWorld = this.lineLocalToWorld(line, line.controlX, line.controlY);
197
+ }
198
+ // Update snap indicator
199
+ this._core.anchorManager.setSnapCandidate({
200
+ objectId: snapTarget.objectId,
201
+ endpoint: 'end',
202
+ centerX: snapTarget.centerX,
203
+ centerY: snapTarget.centerY,
204
+ lineEndpointX: otherEndpointWorld.x,
205
+ lineEndpointY: otherEndpointWorld.y,
206
+ controlX: controlWorld === null || controlWorld === void 0 ? void 0 : controlWorld.x,
207
+ controlY: controlWorld === null || controlWorld === void 0 ? void 0 : controlWorld.y,
208
+ t,
209
+ edgeX,
210
+ edgeY,
211
+ lineStroke: KritzelColorHelper.resolveThemeColor(line.stroke),
212
+ lineStrokeWidth: line.strokeWidth / line.scale,
213
+ arrowOffset: line.hasEndArrow ? line.getArrowSize('end') / line.scale : undefined,
214
+ arrowStyle: line.hasEndArrow ? (_f = (_e = line.arrows) === null || _e === void 0 ? void 0 : _e.end) === null || _f === void 0 ? void 0 : _f.style : undefined,
215
+ arrowFill: line.hasEndArrow ? line.getArrowFill('end') : undefined,
216
+ });
217
+ }
218
+ else {
219
+ // No snap - use regular position
220
+ const newEndX = this.initialEndX + localDx;
221
+ const newEndY = this.initialEndY + localDy;
222
+ this.updateLineEndpoint(line, this.initialStartX, this.initialStartY, newEndX, newEndY);
223
+ // Clear snap indicator
224
+ this._core.anchorManager.clearSnapCandidate();
225
+ }
226
+ }
227
+ else if (handleType === 'center') {
228
+ const startControlX = (_g = this.initialControlX) !== null && _g !== void 0 ? _g : (this.initialStartX + this.initialEndX) / 2;
229
+ const startControlY = (_h = this.initialControlY) !== null && _h !== void 0 ? _h : (this.initialStartY + this.initialEndY) / 2;
230
+ const newControlX = startControlX + localDx * 2;
231
+ const newControlY = startControlY + localDy * 2;
232
+ // Check distance to line segment for snapping back to straight
233
+ const x1 = line.startX;
234
+ const y1 = line.startY;
235
+ const x2 = line.endX;
236
+ const y2 = line.endY;
237
+ const A = newControlX - x1;
238
+ const B = newControlY - y1;
239
+ const C = x2 - x1;
240
+ const D = y2 - y1;
241
+ const dot = A * C + B * D;
242
+ const len_sq = C * C + D * D;
243
+ let param = -1;
244
+ if (len_sq !== 0) {
245
+ param = dot / len_sq;
246
+ }
247
+ let xx, yy;
248
+ if (param < 0) {
249
+ xx = x1;
250
+ yy = y1;
251
+ }
252
+ else if (param > 1) {
253
+ xx = x2;
254
+ yy = y2;
255
+ }
256
+ else {
257
+ xx = x1 + param * C;
258
+ yy = y1 + param * D;
259
+ }
260
+ const dx = newControlX - xx;
261
+ const dy = newControlY - yy;
262
+ const distance = Math.sqrt(dx * dx + dy * dy);
263
+ // Threshold for snapping back to straight line
264
+ const snapToStraightThreshold = 15;
265
+ if (distance < snapToStraightThreshold) {
266
+ line.updateControlPoint(undefined, undefined);
267
+ }
268
+ else {
269
+ line.updateControlPoint(newControlX, newControlY);
270
+ }
271
+ }
272
+ this._core.rerender();
273
+ }
274
+ /**
275
+ * Converts world coordinates to a line's local coordinate system.
276
+ */
277
+ worldToLineLocal(line, worldX, worldY) {
278
+ const dx = (worldX - line.translateX) * line.scale;
279
+ const dy = (worldY - line.translateY) * line.scale;
280
+ const cx = line.totalWidth / 2;
281
+ const cy = line.totalHeight / 2;
282
+ const cos = Math.cos(-line.rotation);
283
+ const sin = Math.sin(-line.rotation);
284
+ const rotatedX = (dx - cx) * cos - (dy - cy) * sin + cx;
285
+ const rotatedY = (dx - cx) * sin + (dy - cy) * cos + cy;
286
+ return {
287
+ x: rotatedX + line.x,
288
+ y: rotatedY + line.y,
289
+ };
290
+ }
291
+ /**
292
+ * Converts a line's local coordinate system to world coordinates.
293
+ */
294
+ lineLocalToWorld(line, localX, localY) {
295
+ const px = localX - line.x;
296
+ const py = localY - line.y;
297
+ const cx = line.totalWidth / 2;
298
+ const cy = line.totalHeight / 2;
299
+ const cos = Math.cos(line.rotation);
300
+ const sin = Math.sin(line.rotation);
301
+ const rotatedX = (px - cx) * cos - (py - cy) * sin + cx;
302
+ const rotatedY = (px - cx) * sin + (py - cy) * cos + cy;
303
+ return {
304
+ x: rotatedX / line.scale + line.translateX,
305
+ y: rotatedY / line.scale + line.translateY,
306
+ };
307
+ }
308
+ updateLineEndpoint(line, startX, startY, endX, endY) {
309
+ // Calculate new bounding box using the static method that accounts for curve extrema
310
+ const { minX, minY, maxX, maxY } = KritzelLine.calculateBoundingBox(startX, startY, endX, endY, line.controlX, line.controlY, line.strokeWidth);
311
+ const newWidth = maxX - minX;
312
+ const newHeight = maxY - minY;
313
+ // Calculate old bounding box
314
+ const { minX: oldMinX, minY: oldMinY, maxX: oldMaxX, maxY: oldMaxY, } = KritzelLine.calculateBoundingBox(this.initialStartX, this.initialStartY, this.initialEndX, this.initialEndY, this.initialControlX, this.initialControlY, line.strokeWidth);
315
+ const oldWidth = oldMaxX - oldMinX;
316
+ const oldHeight = oldMaxY - oldMinY;
317
+ // Calculate center shift in local space
318
+ const shiftX = minX - oldMinX;
319
+ const shiftY = minY - oldMinY;
320
+ const deltaCx = shiftX + (newWidth - oldWidth) / 2;
321
+ const deltaCy = shiftY + (newHeight - oldHeight) / 2;
322
+ // Convert the center shift to world coordinates
323
+ const rotation = line.rotation;
324
+ const cos = Math.cos(rotation);
325
+ const sin = Math.sin(rotation);
326
+ const scale = 1 / line.scale;
327
+ const rotatedDeltaCx = deltaCx * cos - deltaCy * sin;
328
+ const rotatedDeltaCy = deltaCx * sin + deltaCy * cos;
329
+ // Calculate new translate
330
+ const newTranslateX = this.initialTranslateX + scale * (oldWidth - newWidth) / 2 + scale * rotatedDeltaCx;
331
+ const newTranslateY = this.initialTranslateY + scale * (oldHeight - newHeight) / 2 + scale * rotatedDeltaCy;
332
+ // Update the line properties
333
+ line.startX = startX;
334
+ line.startY = startY;
335
+ line.endX = endX;
336
+ line.endY = endY;
337
+ line.x = minX;
338
+ line.y = minY;
339
+ line.width = newWidth;
340
+ line.height = newHeight;
341
+ // Adjust translateX/Y to compensate for the bounding box shift
342
+ line.translateX = newTranslateX;
343
+ line.translateY = newTranslateY;
344
+ // Clear cached adjusted points
345
+ line._adjustedPoints = null;
346
+ this._core.store.state.objects.update(line);
347
+ }
348
+ handlePointerUp(_event) {
349
+ if (this._core.store.state.isLineHandleDragging) {
350
+ const line = this.getSelectedLine();
351
+ const handleType = this._core.store.state.lineHandleType;
352
+ if (line && this.hasMoved) {
353
+ // If we were snapped to a target, create the anchor
354
+ if (this.currentSnapTarget && (handleType === 'start' || handleType === 'end')) {
355
+ this._core.anchorManager.setAnchor(line.id, handleType, this.currentSnapTarget.objectId);
356
+ }
357
+ // Refresh the selection group dimensions after line endpoint change
358
+ const selectionGroup = this._core.store.selectionGroup;
359
+ if (selectionGroup) {
360
+ selectionGroup.refreshObjectDimensions();
361
+ selectionGroup.update();
362
+ this._core.engine.emitObjectsChange();
363
+ this._core.store.state.hasObjectsChanged = true;
364
+ }
365
+ }
366
+ this._core.store.state.isLineHandleDragging = false;
367
+ this.reset();
368
+ this._core.rerender();
369
+ }
370
+ }
371
+ getSelectedLine() {
372
+ const selectionGroup = this._core.store.selectionGroup;
373
+ if (!selectionGroup || selectionGroup.objects.length !== 1) {
374
+ return null;
375
+ }
376
+ const object = selectionGroup.objects[0];
377
+ if (object instanceof KritzelLine) {
378
+ return object;
379
+ }
380
+ return null;
381
+ }
382
+ }