kritzel-stencil 0.0.131 → 0.0.132

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 (356) hide show
  1. package/dist/cjs/index-nzUNdMPh.js +6 -2
  2. package/dist/cjs/{index-BwINBV6L.js → index-ouFX0OVi.js} +715 -676
  3. package/dist/cjs/index-ouFX0OVi.js.map +1 -0
  4. package/dist/cjs/index.cjs.js +1 -1
  5. package/dist/cjs/kritzel-brush-style.cjs.entry.js +32 -0
  6. package/dist/cjs/kritzel-brush-style.entry.cjs.js.map +1 -0
  7. package/dist/cjs/{kritzel-brush-style_23.cjs.entry.js → kritzel-color_22.cjs.entry.js} +1044 -873
  8. package/dist/cjs/loader.cjs.js +1 -1
  9. package/dist/cjs/stencil.cjs.js +1 -1
  10. package/dist/collection/classes/commands/add-object.command.js +6 -7
  11. package/dist/collection/classes/commands/add-object.command.js.map +1 -1
  12. package/dist/collection/classes/commands/add-selection-group.command.js +9 -9
  13. package/dist/collection/classes/commands/add-selection-group.command.js.map +1 -1
  14. package/dist/collection/classes/commands/base.command.js +3 -3
  15. package/dist/collection/classes/commands/base.command.js.map +1 -1
  16. package/dist/collection/classes/commands/batch.command.js +2 -2
  17. package/dist/collection/classes/commands/batch.command.js.map +1 -1
  18. package/dist/collection/classes/commands/move-selection-group.command.js +7 -7
  19. package/dist/collection/classes/commands/move-selection-group.command.js.map +1 -1
  20. package/dist/collection/classes/commands/remove-object.command.js +8 -9
  21. package/dist/collection/classes/commands/remove-object.command.js.map +1 -1
  22. package/dist/collection/classes/commands/remove-selection-group.command.js +7 -7
  23. package/dist/collection/classes/commands/remove-selection-group.command.js.map +1 -1
  24. package/dist/collection/classes/commands/resize-selection-group.command.js +7 -7
  25. package/dist/collection/classes/commands/resize-selection-group.command.js.map +1 -1
  26. package/dist/collection/classes/commands/rotate-selection-group.command.js +12 -12
  27. package/dist/collection/classes/commands/rotate-selection-group.command.js.map +1 -1
  28. package/dist/collection/classes/commands/update-object.command.js +4 -5
  29. package/dist/collection/classes/commands/update-object.command.js.map +1 -1
  30. package/dist/collection/classes/commands/update-viewport.command.js +11 -11
  31. package/dist/collection/classes/commands/update-viewport.command.js.map +1 -1
  32. package/dist/collection/classes/{store.class.js → core/core.class.js} +120 -145
  33. package/dist/collection/classes/core/core.class.js.map +1 -0
  34. package/dist/collection/classes/{database.class.js → core/database.class.js} +28 -20
  35. package/dist/collection/classes/core/database.class.js.map +1 -0
  36. package/dist/collection/classes/core/history.class.js +88 -0
  37. package/dist/collection/classes/core/history.class.js.map +1 -0
  38. package/dist/collection/classes/{reviver.class.js → core/reviver.class.js} +27 -23
  39. package/dist/collection/classes/core/reviver.class.js.map +1 -0
  40. package/dist/collection/classes/core/store.class.js +51 -0
  41. package/dist/collection/classes/core/store.class.js.map +1 -0
  42. package/dist/collection/classes/core/viewport.class.js +165 -0
  43. package/dist/collection/classes/core/viewport.class.js.map +1 -0
  44. package/dist/collection/classes/core/workspace.class.js +42 -0
  45. package/dist/collection/classes/core/workspace.class.js.map +1 -0
  46. package/dist/collection/classes/handlers/base.handler.js +4 -4
  47. package/dist/collection/classes/handlers/base.handler.js.map +1 -1
  48. package/dist/collection/classes/handlers/context-menu.handler.js +24 -19
  49. package/dist/collection/classes/handlers/context-menu.handler.js.map +1 -1
  50. package/dist/collection/classes/handlers/hover.handler.js +5 -5
  51. package/dist/collection/classes/handlers/hover.handler.js.map +1 -1
  52. package/dist/collection/classes/handlers/key.handler.js +38 -44
  53. package/dist/collection/classes/handlers/key.handler.js.map +1 -1
  54. package/dist/collection/classes/handlers/move.handler.js +34 -34
  55. package/dist/collection/classes/handlers/move.handler.js.map +1 -1
  56. package/dist/collection/classes/handlers/resize.handler.js +53 -56
  57. package/dist/collection/classes/handlers/resize.handler.js.map +1 -1
  58. package/dist/collection/classes/handlers/rotation.handler.js +53 -55
  59. package/dist/collection/classes/handlers/rotation.handler.js.map +1 -1
  60. package/dist/collection/classes/handlers/selection.handler.js +73 -72
  61. package/dist/collection/classes/handlers/selection.handler.js.map +1 -1
  62. package/dist/collection/classes/objects/base-object.class.js +22 -17
  63. package/dist/collection/classes/objects/base-object.class.js.map +1 -1
  64. package/dist/collection/classes/objects/custom-element.class.js +3 -3
  65. package/dist/collection/classes/objects/custom-element.class.js.map +1 -1
  66. package/dist/collection/classes/objects/image.class.js +5 -5
  67. package/dist/collection/classes/objects/image.class.js.map +1 -1
  68. package/dist/collection/classes/objects/path.class.js +7 -7
  69. package/dist/collection/classes/objects/path.class.js.map +1 -1
  70. package/dist/collection/classes/objects/selection-box.class.js +4 -4
  71. package/dist/collection/classes/objects/selection-box.class.js.map +1 -1
  72. package/dist/collection/classes/objects/selection-group.class.js +16 -16
  73. package/dist/collection/classes/objects/selection-group.class.js.map +1 -1
  74. package/dist/collection/classes/objects/text.class.js +13 -13
  75. package/dist/collection/classes/objects/text.class.js.map +1 -1
  76. package/dist/collection/classes/registries/tool.registry.js +2 -2
  77. package/dist/collection/classes/registries/tool.registry.js.map +1 -1
  78. package/dist/collection/classes/tools/base-tool.class.js +11 -5
  79. package/dist/collection/classes/tools/base-tool.class.js.map +1 -1
  80. package/dist/collection/classes/tools/brush-tool.class.js +57 -53
  81. package/dist/collection/classes/tools/brush-tool.class.js.map +1 -1
  82. package/dist/collection/classes/tools/eraser-tool.class.js +26 -26
  83. package/dist/collection/classes/tools/eraser-tool.class.js.map +1 -1
  84. package/dist/collection/classes/tools/image-tool.class.js +11 -11
  85. package/dist/collection/classes/tools/image-tool.class.js.map +1 -1
  86. package/dist/collection/classes/tools/selection-tool.class.js +39 -37
  87. package/dist/collection/classes/tools/selection-tool.class.js.map +1 -1
  88. package/dist/collection/classes/tools/text-tool.class.js +37 -37
  89. package/dist/collection/classes/tools/text-tool.class.js.map +1 -1
  90. package/dist/collection/components/core/kritzel-cursor-trail/kritzel-cursor-trail.js +28 -28
  91. package/dist/collection/components/core/kritzel-cursor-trail/kritzel-cursor-trail.js.map +1 -1
  92. package/dist/collection/components/core/kritzel-editor/kritzel-editor.css +7 -9
  93. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +177 -7
  94. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js.map +1 -1
  95. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +236 -233
  96. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js.map +1 -1
  97. package/dist/collection/components/shared/kritzel-brush-style/kritzel-brush-style.js +1 -1
  98. package/dist/collection/components/shared/kritzel-brush-style/kritzel-brush-style.js.map +1 -1
  99. package/dist/collection/components/shared/kritzel-color/kritzel-color.js +2 -2
  100. package/dist/collection/components/shared/kritzel-color/kritzel-color.js.map +1 -1
  101. package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.css +5 -0
  102. package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.js +3 -3
  103. package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.js.map +1 -1
  104. package/dist/collection/components/shared/kritzel-dropdown/kritzel-dropdown.js +12 -12
  105. package/dist/collection/components/shared/kritzel-dropdown/kritzel-dropdown.js.map +1 -1
  106. package/dist/collection/components/shared/kritzel-font/kritzel-font.js +1 -1
  107. package/dist/collection/components/shared/kritzel-font/kritzel-font.js.map +1 -1
  108. package/dist/collection/components/shared/kritzel-font-family/kritzel-font-family.js +1 -1
  109. package/dist/collection/components/shared/kritzel-font-family/kritzel-font-family.js.map +1 -1
  110. package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.js +1 -1
  111. package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.js.map +1 -1
  112. package/dist/collection/components/shared/kritzel-icon/kritzel-icon.css +1 -0
  113. package/dist/collection/components/shared/kritzel-icon/kritzel-icon.js.map +1 -1
  114. package/dist/collection/components/shared/kritzel-menu/kritzel-menu.css +5 -1
  115. package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js +2 -2
  116. package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js.map +1 -1
  117. package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.css +18 -7
  118. package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.js +24 -9
  119. package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.js.map +1 -1
  120. package/dist/collection/components/shared/kritzel-portal/kritzel-portal.js +4 -42
  121. package/dist/collection/components/shared/kritzel-portal/kritzel-portal.js.map +1 -1
  122. package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.css +0 -4
  123. package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js +52 -10
  124. package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js.map +1 -1
  125. package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.css +4 -0
  126. package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.js +1 -1
  127. package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.js.map +1 -1
  128. package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.js +79 -7
  129. package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.js.map +1 -1
  130. package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.js +47 -15
  131. package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.js.map +1 -1
  132. package/dist/collection/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.css +4 -0
  133. package/dist/collection/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.js +6 -6
  134. package/dist/collection/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.js.map +1 -1
  135. package/dist/collection/components/ui/kritzel-control-text-config/kritzel-control-text-config.js +2 -2
  136. package/dist/collection/components/ui/kritzel-control-text-config/kritzel-control-text-config.js.map +1 -1
  137. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.css +12 -1
  138. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +23 -7
  139. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js.map +1 -1
  140. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.css +5 -0
  141. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js +1 -1
  142. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js.map +1 -1
  143. package/dist/collection/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.js +25 -15
  144. package/dist/collection/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.js.map +1 -1
  145. package/dist/collection/configs/default-engine-state.js +0 -1
  146. package/dist/collection/configs/default-engine-state.js.map +1 -1
  147. package/dist/collection/helpers/devices.helper.js +20 -0
  148. package/dist/collection/helpers/devices.helper.js.map +1 -1
  149. package/dist/collection/helpers/event.helper.js +1 -5
  150. package/dist/collection/helpers/event.helper.js.map +1 -1
  151. package/dist/collection/helpers/html.helper.js +29 -0
  152. package/dist/collection/helpers/html.helper.js.map +1 -1
  153. package/dist/collection/helpers/object.helper.js +1 -1
  154. package/dist/collection/helpers/object.helper.js.map +1 -1
  155. package/dist/collection/index.js +1 -1
  156. package/dist/collection/index.js.map +1 -1
  157. package/dist/collection/interfaces/engine-state.interface.js.map +1 -1
  158. package/dist/collection/interfaces/serializable.interface.js.map +1 -1
  159. package/dist/collection/types/deep-readonly.type.js +2 -0
  160. package/dist/collection/types/deep-readonly.type.js.map +1 -0
  161. package/dist/components/index.js +3 -3
  162. package/dist/components/kritzel-brush-style.js +59 -1
  163. package/dist/components/kritzel-brush-style.js.map +1 -1
  164. package/dist/components/kritzel-color-palette.js +1 -1
  165. package/dist/components/kritzel-color.js +1 -1
  166. package/dist/components/kritzel-context-menu.js +1 -1
  167. package/dist/components/kritzel-control-brush-config.js +1 -1
  168. package/dist/components/kritzel-control-text-config.js +1 -1
  169. package/dist/components/kritzel-controls.js +1 -1
  170. package/dist/components/kritzel-cursor-trail.js +1 -1
  171. package/dist/components/kritzel-dropdown.js +1 -1
  172. package/dist/components/kritzel-editor.js +80 -37
  173. package/dist/components/kritzel-editor.js.map +1 -1
  174. package/dist/components/kritzel-engine.js +1 -1
  175. package/dist/components/kritzel-font-family.js +1 -1
  176. package/dist/components/kritzel-font-size.js +1 -1
  177. package/dist/components/kritzel-font.js +1 -1
  178. package/dist/components/kritzel-icon.js +1 -1
  179. package/dist/components/kritzel-menu-item.js +1 -1
  180. package/dist/components/kritzel-menu.js +1 -1
  181. package/dist/components/kritzel-portal.js +1 -1
  182. package/dist/components/kritzel-split-button.js +1 -1
  183. package/dist/components/kritzel-stroke-size.js +1 -1
  184. package/dist/components/kritzel-tooltip.js +1 -1
  185. package/dist/components/kritzel-utility-panel.js +1 -1
  186. package/dist/components/kritzel-workspace-manager.js +1 -1
  187. package/dist/components/{p-CMJ3P0Vw.js → p-0iJh9Z6m.js} +5 -5
  188. package/dist/components/p-0iJh9Z6m.js.map +1 -0
  189. package/dist/components/{p-DHSEK3rF.js → p-B3VQubt_.js} +164 -153
  190. package/dist/components/p-B3VQubt_.js.map +1 -0
  191. package/dist/components/{p-BB0_-X42.js → p-B7kZ1_RH.js} +4 -4
  192. package/dist/components/{p-BB0_-X42.js.map → p-B7kZ1_RH.js.map} +1 -1
  193. package/dist/components/{p-t4NIsuX9.js → p-B7w19kIk.js} +15 -27
  194. package/dist/components/p-B7w19kIk.js.map +1 -0
  195. package/dist/components/{p-B1BLgWL1.js → p-BGdsAz54.js} +27 -18
  196. package/dist/components/p-BGdsAz54.js.map +1 -0
  197. package/dist/components/{p-BhiYvSBc.js → p-BM9IjvnD.js} +3 -3
  198. package/dist/components/p-BM9IjvnD.js.map +1 -0
  199. package/dist/components/{p-BrBQUN0Q.js → p-BPsQrpzN.js} +40 -11
  200. package/dist/components/p-BPsQrpzN.js.map +1 -0
  201. package/dist/components/{p-BB5R2k1o.js → p-BiCgeOiJ.js} +41 -31
  202. package/dist/components/p-BiCgeOiJ.js.map +1 -0
  203. package/dist/components/{p-CGmS8wnN.js → p-C1-nvBx9.js} +26 -16
  204. package/dist/components/p-C1-nvBx9.js.map +1 -0
  205. package/dist/components/p-C6qB08BS.js +68 -0
  206. package/dist/components/p-C6qB08BS.js.map +1 -0
  207. package/dist/components/{p-DxTu1aoJ.js → p-CTvJDYFQ.js} +7 -45
  208. package/dist/components/p-CTvJDYFQ.js.map +1 -0
  209. package/dist/components/{p-DMrtdhBD.js → p-CsyM5q2M.js} +7 -7
  210. package/dist/components/p-CsyM5q2M.js.map +1 -0
  211. package/dist/components/{p-BPz_H-EG.js → p-CvmWmUK9.js} +28 -16
  212. package/dist/components/p-CvmWmUK9.js.map +1 -0
  213. package/dist/components/{p-BgmKrd5Z.js → p-DCx3703u.js} +5 -5
  214. package/dist/components/p-DCx3703u.js.map +1 -0
  215. package/dist/components/{p-trncBp_6.js → p-DFO-6kuA.js} +15 -15
  216. package/dist/components/p-DFO-6kuA.js.map +1 -0
  217. package/dist/components/{p-BeljsQ-8.js → p-D_907-Wd.js} +32 -17
  218. package/dist/components/p-D_907-Wd.js.map +1 -0
  219. package/dist/components/{p-BuewJQNl.js → p-Davd1R_4.js} +1111 -1085
  220. package/dist/components/p-Davd1R_4.js.map +1 -0
  221. package/dist/components/{p-BubxwvMA.js → p-Db3kxVe2.js} +24 -24
  222. package/dist/components/p-Db3kxVe2.js.map +1 -0
  223. package/dist/components/{p-BexTdWaX.js → p-Ddlbt3Bj.js} +4 -4
  224. package/dist/components/p-Ddlbt3Bj.js.map +1 -0
  225. package/dist/components/{p-CHxPWeZd.js → p-DjU7p3od.js} +11 -11
  226. package/dist/components/{p-CHxPWeZd.js.map → p-DjU7p3od.js.map} +1 -1
  227. package/dist/components/{p-DnUKql15.js → p-EXPChOF6.js} +3 -3
  228. package/dist/components/{p-DnUKql15.js.map → p-EXPChOF6.js.map} +1 -1
  229. package/dist/components/p-YqK8ch2R.js +46 -0
  230. package/dist/components/p-YqK8ch2R.js.map +1 -0
  231. package/dist/components/p-l10It7Nm.js +30 -0
  232. package/dist/components/p-l10It7Nm.js.map +1 -0
  233. package/dist/components/{p-p1Jkec_q.js → p-sq9jgfX0.js} +3 -3
  234. package/dist/components/p-sq9jgfX0.js.map +1 -0
  235. package/dist/components/{p-yZ48g7-u.js → p-sreNwi0N.js} +4 -4
  236. package/dist/components/{p-yZ48g7-u.js.map → p-sreNwi0N.js.map} +1 -1
  237. package/dist/esm/{index-B-oSk-v8.js → index-C_uHp-ur.js} +716 -677
  238. package/dist/esm/index-C_uHp-ur.js.map +1 -0
  239. package/dist/esm/index-oCOlsFCN.js +6 -2
  240. package/dist/esm/index.js +1 -1
  241. package/dist/esm/kritzel-brush-style.entry.js +30 -0
  242. package/dist/esm/kritzel-brush-style.entry.js.map +1 -0
  243. package/dist/esm/{kritzel-brush-style_23.entry.js → kritzel-color_22.entry.js} +1046 -874
  244. package/dist/esm/loader.js +1 -1
  245. package/dist/esm/stencil.js +1 -1
  246. package/dist/stencil/index.esm.js +1 -1
  247. package/dist/stencil/kritzel-brush-style.entry.esm.js.map +1 -0
  248. package/dist/stencil/p-25d1e040.entry.js +2 -0
  249. package/dist/stencil/p-25d1e040.entry.js.map +1 -0
  250. package/dist/stencil/p-C_uHp-ur.js +2 -0
  251. package/dist/stencil/p-C_uHp-ur.js.map +1 -0
  252. package/dist/stencil/p-a6f8283e.entry.js +2 -0
  253. package/dist/stencil/p-a6f8283e.entry.js.map +1 -0
  254. package/dist/stencil/stencil.esm.js +1 -1
  255. package/dist/types/classes/commands/add-object.command.d.ts +2 -2
  256. package/dist/types/classes/commands/add-selection-group.command.d.ts +2 -1
  257. package/dist/types/classes/commands/base.command.d.ts +3 -3
  258. package/dist/types/classes/commands/batch.command.d.ts +2 -1
  259. package/dist/types/classes/commands/move-selection-group.command.d.ts +2 -1
  260. package/dist/types/classes/commands/remove-object.command.d.ts +2 -2
  261. package/dist/types/classes/commands/remove-selection-group.command.d.ts +2 -2
  262. package/dist/types/classes/commands/resize-selection-group.command.d.ts +2 -1
  263. package/dist/types/classes/commands/rotate-selection-group.command.d.ts +2 -1
  264. package/dist/types/classes/commands/update-object.command.d.ts +2 -2
  265. package/dist/types/classes/commands/update-viewport.command.d.ts +2 -1
  266. package/dist/types/classes/{store.class.d.ts → core/core.class.d.ts} +9 -19
  267. package/dist/types/classes/{database.class.d.ts → core/database.class.d.ts} +3 -2
  268. package/dist/types/classes/{history.class.d.ts → core/history.class.d.ts} +5 -5
  269. package/dist/types/classes/core/reviver.class.d.ts +6 -0
  270. package/dist/types/classes/core/store.class.d.ts +17 -0
  271. package/dist/types/classes/{viewport.class.d.ts → core/viewport.class.d.ts} +3 -3
  272. package/dist/types/classes/core/workspace.class.d.ts +24 -0
  273. package/dist/types/classes/handlers/base.handler.d.ts +3 -3
  274. package/dist/types/classes/handlers/context-menu.handler.d.ts +2 -2
  275. package/dist/types/classes/handlers/hover.handler.d.ts +2 -2
  276. package/dist/types/classes/handlers/key.handler.d.ts +2 -2
  277. package/dist/types/classes/handlers/move.handler.d.ts +2 -2
  278. package/dist/types/classes/handlers/resize.handler.d.ts +2 -2
  279. package/dist/types/classes/handlers/rotation.handler.d.ts +2 -2
  280. package/dist/types/classes/handlers/selection.handler.d.ts +2 -2
  281. package/dist/types/classes/objects/base-object.class.d.ts +5 -4
  282. package/dist/types/classes/objects/custom-element.class.d.ts +2 -2
  283. package/dist/types/classes/objects/image.class.d.ts +2 -2
  284. package/dist/types/classes/objects/path.class.d.ts +2 -2
  285. package/dist/types/classes/objects/selection-box.class.d.ts +2 -2
  286. package/dist/types/classes/objects/selection-group.class.d.ts +2 -2
  287. package/dist/types/classes/objects/text.class.d.ts +2 -2
  288. package/dist/types/classes/registries/tool.registry.d.ts +2 -2
  289. package/dist/types/classes/tools/base-tool.class.d.ts +8 -4
  290. package/dist/types/classes/tools/brush-tool.class.d.ts +2 -2
  291. package/dist/types/classes/tools/eraser-tool.class.d.ts +2 -2
  292. package/dist/types/classes/tools/image-tool.class.d.ts +2 -2
  293. package/dist/types/classes/tools/selection-tool.class.d.ts +2 -2
  294. package/dist/types/classes/tools/text-tool.class.d.ts +2 -2
  295. package/dist/types/components/core/kritzel-cursor-trail/kritzel-cursor-trail.d.ts +5 -5
  296. package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +13 -3
  297. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +21 -22
  298. package/dist/types/components/shared/kritzel-dropdown/kritzel-dropdown.d.ts +2 -2
  299. package/dist/types/components/shared/kritzel-menu-item/kritzel-menu-item.d.ts +2 -0
  300. package/dist/types/components/shared/kritzel-portal/kritzel-portal.d.ts +0 -1
  301. package/dist/types/components/shared/kritzel-split-button/kritzel-split-button.d.ts +4 -2
  302. package/dist/types/components/shared/kritzel-tooltip/kritzel-tooltip.d.ts +8 -2
  303. package/dist/types/components/ui/kritzel-context-menu/kritzel-context-menu.d.ts +5 -3
  304. package/dist/types/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.d.ts +1 -1
  305. package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +3 -1
  306. package/dist/types/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.d.ts +3 -2
  307. package/dist/types/components.d.ts +41 -12
  308. package/dist/types/helpers/devices.helper.d.ts +4 -0
  309. package/dist/types/helpers/event.helper.d.ts +1 -1
  310. package/dist/types/helpers/html.helper.d.ts +1 -0
  311. package/dist/types/index.d.ts +1 -1
  312. package/dist/types/interfaces/engine-state.interface.d.ts +1 -2
  313. package/dist/types/interfaces/serializable.interface.d.ts +2 -1
  314. package/dist/types/types/deep-readonly.type.d.ts +7 -0
  315. package/package.json +64 -63
  316. package/dist/cjs/index-BwINBV6L.js.map +0 -1
  317. package/dist/collection/classes/database.class.js.map +0 -1
  318. package/dist/collection/classes/history.class.js +0 -88
  319. package/dist/collection/classes/history.class.js.map +0 -1
  320. package/dist/collection/classes/reviver.class.js.map +0 -1
  321. package/dist/collection/classes/store.class.js.map +0 -1
  322. package/dist/collection/classes/viewport.class.js +0 -153
  323. package/dist/collection/classes/viewport.class.js.map +0 -1
  324. package/dist/collection/classes/workspace.class.js +0 -15
  325. package/dist/collection/classes/workspace.class.js.map +0 -1
  326. package/dist/components/p-B1BLgWL1.js.map +0 -1
  327. package/dist/components/p-BB5R2k1o.js.map +0 -1
  328. package/dist/components/p-BPz_H-EG.js.map +0 -1
  329. package/dist/components/p-B_lb1FGi.js +0 -19
  330. package/dist/components/p-B_lb1FGi.js.map +0 -1
  331. package/dist/components/p-BeljsQ-8.js.map +0 -1
  332. package/dist/components/p-BexTdWaX.js.map +0 -1
  333. package/dist/components/p-BgmKrd5Z.js.map +0 -1
  334. package/dist/components/p-BhiYvSBc.js.map +0 -1
  335. package/dist/components/p-BrBQUN0Q.js.map +0 -1
  336. package/dist/components/p-BubxwvMA.js.map +0 -1
  337. package/dist/components/p-BuewJQNl.js.map +0 -1
  338. package/dist/components/p-CGmS8wnN.js.map +0 -1
  339. package/dist/components/p-CJKA5zIE.js +0 -10
  340. package/dist/components/p-CJKA5zIE.js.map +0 -1
  341. package/dist/components/p-CMJ3P0Vw.js.map +0 -1
  342. package/dist/components/p-DHSEK3rF.js.map +0 -1
  343. package/dist/components/p-DMrtdhBD.js.map +0 -1
  344. package/dist/components/p-DxTu1aoJ.js.map +0 -1
  345. package/dist/components/p-p1Jkec_q.js.map +0 -1
  346. package/dist/components/p-rIRXQdie.js +0 -64
  347. package/dist/components/p-rIRXQdie.js.map +0 -1
  348. package/dist/components/p-t4NIsuX9.js.map +0 -1
  349. package/dist/components/p-trncBp_6.js.map +0 -1
  350. package/dist/esm/index-B-oSk-v8.js.map +0 -1
  351. package/dist/stencil/p-3bb80782.entry.js +0 -2
  352. package/dist/stencil/p-3bb80782.entry.js.map +0 -1
  353. package/dist/stencil/p-B-oSk-v8.js +0 -2
  354. package/dist/stencil/p-B-oSk-v8.js.map +0 -1
  355. package/dist/types/classes/reviver.class.d.ts +0 -6
  356. package/dist/types/classes/workspace.class.d.ts +0 -16
@@ -1,11 +1,12 @@
1
1
  import { p as proxyCustomElement, H, c as createEvent, h, d as Host } from './p-BYanlgdq.js';
2
2
  import { K as KritzelMouseButton } from './p-D8W6LE-c.js';
3
- import { e as KritzelBaseObject, f as KritzelBaseCommand, g as KritzelBaseTool, h as KritzelEventHelper, U as UpdateObjectCommand, c as KritzelTextTool, b as KritzelBrushTool, K as KritzelText, a as KritzelPath, A as AddObjectCommand, i as KritzelToolRegistry, d as KritzelKeyboardHelper } from './p-DHSEK3rF.js';
4
- import { O as ObjectHelper } from './p-DnUKql15.js';
5
- import { K as KritzelContextMenu, d as defineCustomElement$3 } from './p-B1BLgWL1.js';
6
- import { K as KritzelWorkspace } from './p-B_lb1FGi.js';
7
- import { d as defineCustomElement$2 } from './p-BubxwvMA.js';
8
- import { d as defineCustomElement$1 } from './p-p1Jkec_q.js';
3
+ import { e as KritzelBaseObject, f as KritzelBaseCommand, g as KritzelBaseTool, h as KritzelEventHelper, U as UpdateObjectCommand, c as KritzelTextTool, b as KritzelBrushTool, K as KritzelText, a as KritzelPath, A as AddObjectCommand, i as KritzelToolRegistry, d as KritzelKeyboardHelper } from './p-B3VQubt_.js';
4
+ import { O as ObjectHelper } from './p-EXPChOF6.js';
5
+ import { K as KritzelWorkspace } from './p-YqK8ch2R.js';
6
+ import { K as KritzelContextMenu, d as defineCustomElement$3 } from './p-BGdsAz54.js';
7
+ import { K as KritzelDevicesHelper } from './p-l10It7Nm.js';
8
+ import { d as defineCustomElement$2 } from './p-Db3kxVe2.js';
9
+ import { d as defineCustomElement$1 } from './p-sq9jgfX0.js';
9
10
 
10
11
  class KritzelImage extends KritzelBaseObject {
11
12
  __class__ = 'KritzelImage';
@@ -23,17 +24,17 @@ class KritzelImage extends KritzelBaseObject {
23
24
  this.translateY = config?.translateY || 0;
24
25
  this.scale = config?.scale || 1;
25
26
  }
26
- static create(store) {
27
+ static create(core) {
27
28
  const object = new KritzelImage();
28
- object._store = store;
29
+ object._core = core;
29
30
  object.id = object.generateId();
30
- object.workspaceId = store.state.activeWorkspace.id;
31
+ object.workspaceId = core.store.state.activeWorkspace.id;
31
32
  object.x = 0;
32
33
  object.y = 0;
33
34
  object.translateX = 0;
34
35
  object.translateY = 0;
35
- object.scale = object._store.state.scale;
36
- object.zIndex = store.currentZIndex;
36
+ object.scale = object._core.store.state.scale;
37
+ object.zIndex = core.store.currentZIndex;
37
38
  return object;
38
39
  }
39
40
  resize(x, y, width, height) {
@@ -62,8 +63,8 @@ class KritzelImage extends KritzelBaseObject {
62
63
 
63
64
  class BatchCommand extends KritzelBaseCommand {
64
65
  commands;
65
- constructor(store, initiator, commands, skipHistory = false) {
66
- super(store, initiator, skipHistory);
66
+ constructor(core, initiator, commands, skipHistory = false) {
67
+ super(core, initiator, skipHistory);
67
68
  this.commands = commands;
68
69
  }
69
70
  execute() {
@@ -89,11 +90,11 @@ class KritzelCustomElement extends KritzelBaseObject {
89
90
  this.width = config.width || 0;
90
91
  }
91
92
  }
92
- static create(store, config) {
93
+ static create(core, config) {
93
94
  const object = new KritzelCustomElement(config);
94
- object._store = store;
95
+ object._core = core;
95
96
  object.id = object.generateId();
96
- object.workspaceId = store.state.activeWorkspace.id;
97
+ object.workspaceId = core.store.state.activeWorkspace.id;
97
98
  return object;
98
99
  }
99
100
  mount(element) {
@@ -129,98 +130,98 @@ class KritzelCustomElement extends KritzelBaseObject {
129
130
 
130
131
  class RemoveObjectCommand extends KritzelBaseCommand {
131
132
  object;
132
- constructor(store, initiator, object, skipHistory = false) {
133
- super(store, initiator, skipHistory);
133
+ constructor(core, initiator, object, skipHistory = false) {
134
+ super(core, initiator, skipHistory);
134
135
  this.object = object;
135
136
  }
136
137
  execute() {
137
- this._store.state.objectsMap.remove(object => object.id === this.object.id);
138
- this._store.state.objectsMap.filter(object => object instanceof KritzelCustomElement).forEach(object => object.remount());
139
- this._store.deleteObjectFromDatabase(this.object.id);
138
+ this._core.store.state.objectsMap.remove(object => object.id === this.object.id);
139
+ this._core.store.state.objectsMap.filter(object => object instanceof KritzelCustomElement).forEach(object => object.remount());
140
+ this._core.deleteObjectFromDatabase(this.object.id);
140
141
  }
141
142
  undo() {
142
- this._store.state.objectsMap.insert(this.object);
143
- this._store.state.objectsMap.filter(object => object instanceof KritzelCustomElement).forEach(object => object.remount());
144
- this._store.addObjectToDatabase(ObjectHelper.clone(this.object));
143
+ this._core.store.state.objectsMap.insert(this.object);
144
+ this._core.store.state.objectsMap.filter(object => object instanceof KritzelCustomElement).forEach(object => object.remount());
145
+ this._core.addObjectToDatabase(this.object);
145
146
  }
146
147
  }
147
148
 
148
149
  class KritzelEraserTool extends KritzelBaseTool {
149
150
  touchStartTimeout = null;
150
- constructor(store) {
151
- super(store);
151
+ constructor(core) {
152
+ super(core);
152
153
  }
153
154
  handlePointerDown(event) {
154
155
  if (event.pointerType === 'mouse') {
155
156
  if (KritzelEventHelper.isLeftClick(event)) {
156
- this._store.state.isErasing = true;
157
+ this._core.store.setState('isErasing', true);
157
158
  }
158
159
  }
159
160
  if (event.pointerType === 'touch') {
160
161
  this.touchStartTimeout = setTimeout(() => {
161
- if (this._store.state.pointers.size === 1 && !this._store.state.isScaling) {
162
- this._store.state.isErasing = true;
162
+ if (this._core.store.state.pointers.size === 1 && !this._core.store.state.isScaling) {
163
+ this._core.store.setState('isErasing', true);
163
164
  }
164
165
  }, 80);
165
166
  }
166
167
  }
167
168
  handlePointerMove(event) {
168
169
  if (event.pointerType === 'mouse') {
169
- if (this._store.state.isErasing) {
170
- const selectedObjects = this._store.getObjectsFromPointerEvent(event, '.object');
170
+ if (this._core.store.state.isErasing) {
171
+ const selectedObjects = this._core.getObjectsFromPointerEvent(event, '.object');
171
172
  if (selectedObjects.length === 0)
172
173
  return;
173
- const x = this._store.state.pointerX;
174
- const y = this._store.state.pointerY;
174
+ const x = this._core.store.state.pointerX;
175
+ const y = this._core.store.state.pointerY;
175
176
  selectedObjects.forEach(selectedObject => {
176
177
  selectedObject.markedForRemoval = selectedObject.hitTest(x, y);
177
178
  });
178
- this._store.rerender();
179
+ this._core.rerender();
179
180
  }
180
181
  }
181
182
  if (event.pointerType === 'touch') {
182
- if (this._store.state.pointers.size === 1 && this._store.state.isErasing) {
183
- const shadowRoot = this._store.state.host?.shadowRoot;
183
+ if (this._core.store.state.pointers.size === 1 && this._core.store.state.isErasing) {
184
+ const shadowRoot = this._core.store.state.host?.shadowRoot;
184
185
  if (!shadowRoot)
185
186
  return;
186
- const selectedObjects = this._store.getObjectsFromPointerEvent(event, '.object');
187
+ const selectedObjects = this._core.getObjectsFromPointerEvent(event, '.object');
187
188
  if (selectedObjects.length === 0)
188
189
  return;
189
- const x = this._store.state.pointerX;
190
- const y = this._store.state.pointerY;
190
+ const x = this._core.store.state.pointerX;
191
+ const y = this._core.store.state.pointerY;
191
192
  selectedObjects.forEach(selectedObject => {
192
193
  selectedObject.markedForRemoval = selectedObject.hitTest(x, y);
193
194
  });
194
- this._store.rerender();
195
+ this._core.rerender();
195
196
  }
196
197
  }
197
198
  }
198
199
  handlePointerUp(event) {
199
200
  if (event.pointerType === 'mouse') {
200
- if (this._store.state.isErasing) {
201
- const removeCommands = this._store.allObjects.filter(object => object.markedForRemoval).map(object => {
201
+ if (this._core.store.state.isErasing) {
202
+ const removeCommands = this._core.store.allObjects.filter(object => object.markedForRemoval).map(object => {
202
203
  object.markedForRemoval = false;
203
- return new RemoveObjectCommand(this._store, this, object);
204
+ return new RemoveObjectCommand(this._core, this, object);
204
205
  });
205
206
  if (removeCommands.length > 0) {
206
- this._store.history.executeCommand(new BatchCommand(this._store, this, removeCommands));
207
+ this._core.history.executeCommand(new BatchCommand(this._core, this, removeCommands));
207
208
  }
208
- this._store.state.isErasing = false;
209
+ this._core.store.setState('isErasing', false);
209
210
  }
210
211
  }
211
212
  if (event.pointerType === 'touch') {
212
213
  clearTimeout(this.touchStartTimeout);
213
- if (this._store.state.isErasing) {
214
- const removeCommands = this._store.allObjects
214
+ if (this._core.store.state.isErasing) {
215
+ const removeCommands = this._core.store.allObjects
215
216
  .filter(object => object.markedForRemoval)
216
217
  .map(object => {
217
218
  object.markedForRemoval = false;
218
- return new RemoveObjectCommand(this._store, this, object);
219
+ return new RemoveObjectCommand(this._core, this, object);
219
220
  });
220
221
  if (removeCommands.length > 0) {
221
- this._store.history.executeCommand(new BatchCommand(this._store, this, removeCommands));
222
+ this._core.history.executeCommand(new BatchCommand(this._core, this, removeCommands));
222
223
  }
223
- this._store.state.isErasing = false;
224
+ this._core.store.setState('isErasing', false);
224
225
  }
225
226
  }
226
227
  }
@@ -228,18 +229,18 @@ class KritzelEraserTool extends KritzelBaseTool {
228
229
 
229
230
  class RemoveSelectionGroupCommand extends KritzelBaseCommand {
230
231
  previousSelectionGroup;
231
- constructor(store, initiator, skipHistory = false) {
232
- super(store, initiator, skipHistory);
233
- this.previousSelectionGroup = this._store.state.selectionGroup;
232
+ constructor(core, initiator, skipHistory = false) {
233
+ super(core, initiator, skipHistory);
234
+ this.previousSelectionGroup = this._core.store.state.selectionGroup;
234
235
  }
235
236
  execute() {
236
- this._store.state.objectsMap.remove(object => object.id === this.previousSelectionGroup?.id);
237
- this._store.state.selectionGroup = null;
237
+ this._core.store.state.objectsMap.remove(object => object.id === this.previousSelectionGroup?.id);
238
+ this._core.store.setState('selectionGroup', null);
238
239
  }
239
240
  undo() {
240
241
  if (this.previousSelectionGroup) {
241
- this._store.state.objectsMap.insert(this.previousSelectionGroup);
242
- this._store.state.selectionGroup = this.previousSelectionGroup;
242
+ this._core.store.state.objectsMap.insert(this.previousSelectionGroup);
243
+ this._core.store.setState('selectionGroup', this.previousSelectionGroup);
243
244
  }
244
245
  }
245
246
  }
@@ -251,33 +252,33 @@ class MoveSelectionGroupCommand extends KritzelBaseCommand {
251
252
  endX;
252
253
  endY;
253
254
  skipExecution;
254
- constructor(store, initiator, startX, startY, endX, endY, skipFirstExecution = false, skipHistory = false) {
255
- super(store, initiator, skipHistory);
255
+ constructor(core, initiator, startX, startY, endX, endY, skipFirstExecution = false, skipHistory = false) {
256
+ super(core, initiator, skipHistory);
256
257
  this.startX = startX;
257
258
  this.startY = startY;
258
259
  this.endX = endX;
259
260
  this.endY = endY;
260
261
  this.skipExecution = skipFirstExecution;
261
- this.selectionGroup = this._store.state.selectionGroup;
262
+ this.selectionGroup = this._core.store.state.selectionGroup;
262
263
  }
263
264
  execute() {
264
265
  if (this.skipExecution) {
265
266
  this.skipExecution = false;
266
267
  return;
267
268
  }
268
- this._store.state.selectionGroup = this.selectionGroup;
269
- this._store.state.selectionGroup.move(this.startX, this.startY, this.endX, this.endY);
269
+ this._core.store.setState('selectionGroup', this.selectionGroup);
270
+ this._core.store.state.selectionGroup.move(this.startX, this.startY, this.endX, this.endY);
270
271
  }
271
272
  undo() {
272
- this._store.state.selectionGroup = this.selectionGroup;
273
- this._store.state.selectionGroup.move(this.endX, this.endY, this.startX, this.startY);
273
+ this._core.store.setState('selectionGroup', this.selectionGroup);
274
+ this._core.store.state.selectionGroup.move(this.endX, this.endY, this.startX, this.startY);
274
275
  }
275
276
  }
276
277
 
277
278
  class KritzelBaseHandler {
278
- _store;
279
- constructor(store) {
280
- this._store = store;
279
+ _core;
280
+ constructor(core) {
281
+ this._core = core;
281
282
  }
282
283
  }
283
284
 
@@ -288,16 +289,16 @@ class KritzelMoveHandler extends KritzelBaseHandler {
288
289
  startY;
289
290
  endX;
290
291
  endY;
291
- constructor(store) {
292
- super(store);
292
+ constructor(core) {
293
+ super(core);
293
294
  }
294
295
  handlePointerDown(event) {
295
296
  if (event.pointerType === 'mouse') {
296
297
  if (KritzelEventHelper.isLeftClick(event)) {
297
- if (this._store.state.selectionGroup?.isSelected && !this._store.state.isResizeHandleSelected && !this._store.state.isRotationHandleSelected) {
298
- const clientX = event.clientX - this._store.offsetX;
299
- const clientY = event.clientY - this._store.offsetY;
300
- this._store.state.isDragging = true;
298
+ if (this._core.store.state.selectionGroup?.isSelected && !this._core.store.state.isResizeHandleSelected && !this._core.store.state.isRotationHandleSelected) {
299
+ const clientX = event.clientX - this._core.store.offsetX;
300
+ const clientY = event.clientY - this._core.store.offsetY;
301
+ this._core.store.setState('isDragging', true);
301
302
  this.dragStartX = clientX;
302
303
  this.dragStartY = clientY;
303
304
  this.startX = this.dragStartX;
@@ -306,11 +307,11 @@ class KritzelMoveHandler extends KritzelBaseHandler {
306
307
  }
307
308
  }
308
309
  if (event.pointerType === 'touch') {
309
- const activePointers = Array.from(this._store.state.pointers.values());
310
- if (this._store.state.pointers.size === 1) {
311
- if (this._store.state.selectionGroup?.isSelected && !this._store.state.isResizeHandleSelected && !this._store.state.isRotationHandleSelected) {
312
- const x = Math.round(activePointers[0].clientX - this._store.offsetX);
313
- const y = Math.round(activePointers[0].clientY - this._store.offsetY);
310
+ const activePointers = Array.from(this._core.store.state.pointers.values());
311
+ if (this._core.store.state.pointers.size === 1) {
312
+ if (this._core.store.state.selectionGroup?.isSelected && !this._core.store.state.isResizeHandleSelected && !this._core.store.state.isRotationHandleSelected) {
313
+ const x = Math.round(activePointers[0].clientX - this._core.store.offsetX);
314
+ const y = Math.round(activePointers[0].clientY - this._core.store.offsetY);
314
315
  this.dragStartX = x;
315
316
  this.dragStartY = y;
316
317
  this.startX = x;
@@ -321,30 +322,30 @@ class KritzelMoveHandler extends KritzelBaseHandler {
321
322
  }
322
323
  handlePointerMove(event) {
323
324
  if (event.pointerType === 'mouse') {
324
- if (this._store.state.isDragging && this._store.state.selectionGroup) {
325
- const clientX = event.clientX - this._store.offsetX;
326
- const clientY = event.clientY - this._store.offsetY;
325
+ if (this._core.store.state.isDragging && this._core.store.state.selectionGroup) {
326
+ const clientX = event.clientX - this._core.store.offsetX;
327
+ const clientY = event.clientY - this._core.store.offsetY;
327
328
  this.endX = clientX;
328
329
  this.endY = clientY;
329
- this._store.state.selectionGroup.move(clientX, clientY, this.dragStartX, this.dragStartY);
330
+ this._core.store.state.selectionGroup.move(clientX, clientY, this.dragStartX, this.dragStartY);
330
331
  this.dragStartX = clientX;
331
332
  this.dragStartY = clientY;
332
333
  }
333
334
  }
334
335
  if (event.pointerType === 'touch') {
335
- const activePointers = Array.from(this._store.state.pointers.values());
336
- if (this._store.state.pointers.size === 1 && this._store.state.selectionGroup && !this._store.state.isResizeHandleSelected && !this._store.state.isRotationHandleSelected) {
337
- const x = Math.round(activePointers[0].clientX - this._store.offsetX);
338
- const y = Math.round(activePointers[0].clientY - this._store.offsetY);
339
- this._store.state.isDragging = true;
336
+ const activePointers = Array.from(this._core.store.state.pointers.values());
337
+ if (this._core.store.state.pointers.size === 1 && this._core.store.state.selectionGroup && !this._core.store.state.isResizeHandleSelected && !this._core.store.state.isRotationHandleSelected) {
338
+ const x = Math.round(activePointers[0].clientX - this._core.store.offsetX);
339
+ const y = Math.round(activePointers[0].clientY - this._core.store.offsetY);
340
+ this._core.store.setState('isDragging', true);
340
341
  this.endX = x;
341
342
  this.endY = y;
342
343
  const moveDeltaX = Math.abs(x - this.startX);
343
344
  const moveDeltaY = Math.abs(y - this.startY);
344
345
  const moveThreshold = 5;
345
346
  if (moveDeltaX > moveThreshold || moveDeltaY > moveThreshold) {
346
- clearTimeout(this._store.state.longTouchTimeout);
347
- this._store.state.selectionGroup.move(x, y, this.dragStartX, this.dragStartY);
347
+ clearTimeout(this._core.store.state.longTouchTimeout);
348
+ this._core.store.state.selectionGroup.move(x, y, this.dragStartX, this.dragStartY);
348
349
  this.dragStartX = x;
349
350
  this.dragStartY = y;
350
351
  }
@@ -353,29 +354,29 @@ class KritzelMoveHandler extends KritzelBaseHandler {
353
354
  }
354
355
  handlePointerUp(event) {
355
356
  if (event.pointerType === 'mouse') {
356
- if (this._store.state.isDragging) {
357
- this._store.state.isDragging = false;
358
- const moveSelectionGroupCommand = new MoveSelectionGroupCommand(this._store, this, this.endX, this.endY, this.startX, this.startY, true);
359
- const updateObjectsCommand = this._store.state.selectionGroup.objects.map(object => {
360
- return new UpdateObjectCommand(this._store, this, object, {
357
+ if (this._core.store.state.isDragging) {
358
+ this._core.store.setState('isDragging', false);
359
+ const moveSelectionGroupCommand = new MoveSelectionGroupCommand(this._core, this, this.endX, this.endY, this.startX, this.startY, true);
360
+ const updateObjectsCommand = this._core.store.state.selectionGroup.objects.map(object => {
361
+ return new UpdateObjectCommand(this._core, this, object, {
361
362
  translateX: object.translateX,
362
363
  translateY: object.translateY
363
364
  });
364
365
  });
365
- this._store.history.executeCommand(new BatchCommand(this._store, this, [moveSelectionGroupCommand, ...updateObjectsCommand]));
366
+ this._core.history.executeCommand(new BatchCommand(this._core, this, [moveSelectionGroupCommand, ...updateObjectsCommand]));
366
367
  }
367
368
  }
368
369
  if (event.pointerType === 'touch') {
369
- if (this._store.state.isDragging) {
370
- this._store.state.isDragging = false;
371
- const moveSelectionGroupCommand = new MoveSelectionGroupCommand(this._store, this, this.endX, this.endY, this.startX, this.startY, true);
372
- const updateObjectsCommand = this._store.state.selectionGroup.objects.map(object => {
373
- return new UpdateObjectCommand(this._store, this, object, {
370
+ if (this._core.store.state.isDragging) {
371
+ this._core.store.setState('isDragging', false);
372
+ const moveSelectionGroupCommand = new MoveSelectionGroupCommand(this._core, this, this.endX, this.endY, this.startX, this.startY, true);
373
+ const updateObjectsCommand = this._core.store.state.selectionGroup.objects.map(object => {
374
+ return new UpdateObjectCommand(this._core, this, object, {
374
375
  translateX: object.translateX,
375
376
  translateY: object.translateY
376
377
  });
377
378
  });
378
- this._store.history.executeCommand(new BatchCommand(this._store, this, [moveSelectionGroupCommand, ...updateObjectsCommand]));
379
+ this._core.history.executeCommand(new BatchCommand(this._core, this, [moveSelectionGroupCommand, ...updateObjectsCommand]));
379
380
  }
380
381
  }
381
382
  }
@@ -393,19 +394,19 @@ class ResizeSelectionGroupCommand extends KritzelBaseCommand {
393
394
  newSize;
394
395
  previousSize;
395
396
  selectionGroup;
396
- constructor(store, initiator, previousSize, newSize, skipHistory = false) {
397
- super(store, initiator, skipHistory);
397
+ constructor(core, initiator, previousSize, newSize, skipHistory = false) {
398
+ super(core, initiator, skipHistory);
398
399
  this.previousSize = previousSize;
399
400
  this.newSize = newSize;
400
- this.selectionGroup = this._store.state.selectionGroup;
401
+ this.selectionGroup = this._core.store.state.selectionGroup;
401
402
  }
402
403
  execute() {
403
- this._store.state.selectionGroup = this.selectionGroup;
404
- this._store.state.selectionGroup.resize(this.newSize.x, this.newSize.y, this.newSize.width, this.newSize.height);
404
+ this._core.store.setState('selectionGroup', this.selectionGroup);
405
+ this._core.store.state.selectionGroup.resize(this.newSize.x, this.newSize.y, this.newSize.width, this.newSize.height);
405
406
  }
406
407
  undo() {
407
- this._store.state.selectionGroup = this.selectionGroup;
408
- this._store.state.selectionGroup.resize(this.previousSize.x, this.previousSize.y, this.previousSize.width, this.previousSize.height);
408
+ this._core.store.setState('selectionGroup', this.selectionGroup);
409
+ this._core.store.state.selectionGroup.resize(this.previousSize.x, this.previousSize.y, this.previousSize.width, this.previousSize.height);
409
410
  }
410
411
  }
411
412
 
@@ -414,71 +415,71 @@ class KritzelResizeHandler extends KritzelBaseHandler {
414
415
  initialMouseY = 0;
415
416
  initialSize = { x: 0, y: 0, width: 0, height: 0 };
416
417
  newSize = { x: 0, y: 0, width: 0, height: 0 };
417
- constructor(store) {
418
- super(store);
418
+ constructor(core) {
419
+ super(core);
419
420
  }
420
421
  handlePointerDown(event) {
421
422
  if (event.pointerType === 'mouse') {
422
423
  if (KritzelEventHelper.isLeftClick(event)) {
423
- if (this._store.state.selectionGroup && this._store.state.isResizeHandleSelected) {
424
- const clientX = event.clientX - this._store.offsetX;
425
- const clientY = event.clientY - this._store.offsetY;
426
- this._store.state.isResizing = true;
424
+ if (this._core.store.state.selectionGroup && this._core.store.state.isResizeHandleSelected) {
425
+ const clientX = event.clientX - this._core.store.offsetX;
426
+ const clientY = event.clientY - this._core.store.offsetY;
427
+ this._core.store.setState('isResizing', true);
427
428
  this.initialMouseX = clientX;
428
429
  this.initialMouseY = clientY;
429
- this.initialSize.width = this._store.state.selectionGroup.width;
430
- this.initialSize.height = this._store.state.selectionGroup.height;
431
- this.initialSize.x = this._store.state.selectionGroup.translateX;
432
- this.initialSize.y = this._store.state.selectionGroup.translateY;
430
+ this.initialSize.width = this._core.store.state.selectionGroup.width;
431
+ this.initialSize.height = this._core.store.state.selectionGroup.height;
432
+ this.initialSize.x = this._core.store.state.selectionGroup.translateX;
433
+ this.initialSize.y = this._core.store.state.selectionGroup.translateY;
433
434
  }
434
435
  }
435
436
  }
436
437
  if (event.pointerType === 'touch') {
437
- const activePointers = Array.from(this._store.state.pointers.values());
438
+ const activePointers = Array.from(this._core.store.state.pointers.values());
438
439
  const firstTouch = activePointers[0];
439
440
  if (!firstTouch) {
440
441
  return;
441
442
  }
442
443
  if (activePointers.length === 1) {
443
- if (this._store.state.selectionGroup && this._store.state.isResizeHandleSelected) {
444
- const clientX = Math.round(firstTouch.clientX - this._store.offsetX);
445
- const clientY = Math.round(firstTouch.clientY - this._store.offsetY);
446
- this._store.state.isResizing = true;
444
+ if (this._core.store.state.selectionGroup && this._core.store.state.isResizeHandleSelected) {
445
+ const clientX = Math.round(firstTouch.clientX - this._core.store.offsetX);
446
+ const clientY = Math.round(firstTouch.clientY - this._core.store.offsetY);
447
+ this._core.store.setState('isResizing', true);
447
448
  this.initialMouseX = clientX;
448
449
  this.initialMouseY = clientY;
449
- this.initialSize.width = this._store.state.selectionGroup.width;
450
- this.initialSize.height = this._store.state.selectionGroup.height;
451
- this.initialSize.x = this._store.state.selectionGroup.translateX;
452
- this.initialSize.y = this._store.state.selectionGroup.translateY;
453
- clearTimeout(this._store.state.longTouchTimeout);
450
+ this.initialSize.width = this._core.store.state.selectionGroup.width;
451
+ this.initialSize.height = this._core.store.state.selectionGroup.height;
452
+ this.initialSize.x = this._core.store.state.selectionGroup.translateX;
453
+ this.initialSize.y = this._core.store.state.selectionGroup.translateY;
454
+ clearTimeout(this._core.store.state.longTouchTimeout);
454
455
  }
455
456
  }
456
457
  }
457
458
  }
458
459
  handlePointerMove(event) {
459
460
  if (event.pointerType === 'mouse') {
460
- if (this._store.state.isResizing && this._store.state.selectionGroup) {
461
- const clientX = event.clientX - this._store.offsetX;
462
- const clientY = event.clientY - this._store.offsetY;
461
+ if (this._core.store.state.isResizing && this._core.store.state.selectionGroup) {
462
+ const clientX = event.clientX - this._core.store.offsetX;
463
+ const clientY = event.clientY - this._core.store.offsetY;
463
464
  const dx = clientX - this.initialMouseX;
464
465
  const dy = clientY - this.initialMouseY;
465
- switch (this._store.state.resizeHandleType) {
466
+ switch (this._core.store.state.resizeHandleType) {
466
467
  case KritzelHandleType.TopLeft:
467
468
  this.newSize.width = this.initialSize.width - dx;
468
469
  this.newSize.height = this.initialSize.height - dy;
469
- this.newSize.x = dx / this._store.state.scale + this.initialSize.x;
470
- this.newSize.y = dy / this._store.state.scale + this.initialSize.y;
470
+ this.newSize.x = dx / this._core.store.state.scale + this.initialSize.x;
471
+ this.newSize.y = dy / this._core.store.state.scale + this.initialSize.y;
471
472
  break;
472
473
  case KritzelHandleType.TopRight:
473
474
  this.newSize.width = this.initialSize.width + dx;
474
475
  this.newSize.height = this.initialSize.height - dy;
475
476
  this.newSize.x = this.initialSize.x;
476
- this.newSize.y = dy / this._store.state.scale + this.initialSize.y;
477
+ this.newSize.y = dy / this._core.store.state.scale + this.initialSize.y;
477
478
  break;
478
479
  case KritzelHandleType.BottomLeft:
479
480
  this.newSize.width = this.initialSize.width - dx;
480
481
  this.newSize.height = this.initialSize.height + dy;
481
- this.newSize.x = dx / this._store.state.scale + this.initialSize.x;
482
+ this.newSize.x = dx / this._core.store.state.scale + this.initialSize.x;
482
483
  this.newSize.y = this.initialSize.y;
483
484
  break;
484
485
  case KritzelHandleType.BottomRight:
@@ -488,38 +489,37 @@ class KritzelResizeHandler extends KritzelBaseHandler {
488
489
  this.newSize.y = this.initialSize.y;
489
490
  break;
490
491
  }
491
- this._store.state.selectionGroup.resize(this.newSize.x, this.newSize.y, this.newSize.width, this.newSize.height);
492
- this._store.rerender();
492
+ this._core.store.state.selectionGroup.resize(this.newSize.x, this.newSize.y, this.newSize.width, this.newSize.height);
493
493
  }
494
494
  }
495
495
  if (event.pointerType === 'touch') {
496
- const activePointers = Array.from(this._store.state.pointers.values());
496
+ const activePointers = Array.from(this._core.store.state.pointers.values());
497
497
  const oneFingerTouch = activePointers[0];
498
498
  if (!oneFingerTouch) {
499
499
  return;
500
500
  }
501
- if (this._store.state.isResizing && this._store.state.selectionGroup) {
502
- const clientX = Math.round(oneFingerTouch.clientX - this._store.offsetX);
503
- const clientY = Math.round(oneFingerTouch.clientY - this._store.offsetY);
501
+ if (this._core.store.state.isResizing && this._core.store.state.selectionGroup) {
502
+ const clientX = Math.round(oneFingerTouch.clientX - this._core.store.offsetX);
503
+ const clientY = Math.round(oneFingerTouch.clientY - this._core.store.offsetY);
504
504
  const dx = clientX - this.initialMouseX;
505
505
  const dy = clientY - this.initialMouseY;
506
- switch (this._store.state.resizeHandleType) {
506
+ switch (this._core.store.state.resizeHandleType) {
507
507
  case KritzelHandleType.TopLeft:
508
508
  this.newSize.width = this.initialSize.width - dx;
509
509
  this.newSize.height = this.initialSize.height - dy;
510
- this.newSize.x = dx / this._store.state.scale + this.initialSize.x;
511
- this.newSize.y = dy / this._store.state.scale + this.initialSize.y;
510
+ this.newSize.x = dx / this._core.store.state.scale + this.initialSize.x;
511
+ this.newSize.y = dy / this._core.store.state.scale + this.initialSize.y;
512
512
  break;
513
513
  case KritzelHandleType.TopRight:
514
514
  this.newSize.width = this.initialSize.width + dx;
515
515
  this.newSize.height = this.initialSize.height - dy;
516
516
  this.newSize.x = this.initialSize.x;
517
- this.newSize.y = dy / this._store.state.scale + this.initialSize.y;
517
+ this.newSize.y = dy / this._core.store.state.scale + this.initialSize.y;
518
518
  break;
519
519
  case KritzelHandleType.BottomLeft:
520
520
  this.newSize.width = this.initialSize.width - dx;
521
521
  this.newSize.height = this.initialSize.height + dy;
522
- this.newSize.x = dx / this._store.state.scale + this.initialSize.x;
522
+ this.newSize.x = dx / this._core.store.state.scale + this.initialSize.x;
523
523
  this.newSize.y = this.initialSize.y;
524
524
  break;
525
525
  case KritzelHandleType.BottomRight:
@@ -529,33 +529,31 @@ class KritzelResizeHandler extends KritzelBaseHandler {
529
529
  this.newSize.y = this.initialSize.y;
530
530
  break;
531
531
  }
532
- this._store.state.selectionGroup.resize(this.newSize.x, this.newSize.y, this.newSize.width, this.newSize.height);
533
- clearTimeout(this._store.state.longTouchTimeout);
532
+ this._core.store.state.selectionGroup.resize(this.newSize.x, this.newSize.y, this.newSize.width, this.newSize.height);
533
+ clearTimeout(this._core.store.state.longTouchTimeout);
534
534
  }
535
535
  }
536
536
  }
537
537
  handlePointerUp(event) {
538
538
  if (event.pointerType === 'mouse') {
539
- if (this._store.state.isResizing) {
540
- const resizeSelectionGroupCommand = new ResizeSelectionGroupCommand(this._store, this, structuredClone(this.initialSize), structuredClone(this.newSize));
541
- const updateObjectsCommand = this._store.state.selectionGroup.objects.map(object => {
542
- return new UpdateObjectCommand(this._store, this, object, { ...object });
539
+ if (this._core.store.state.isResizing) {
540
+ const resizeSelectionGroupCommand = new ResizeSelectionGroupCommand(this._core, this, structuredClone(this.initialSize), structuredClone(this.newSize));
541
+ const updateObjectsCommand = this._core.store.state.selectionGroup.objects.map(object => {
542
+ return new UpdateObjectCommand(this._core, this, object, { ...object });
543
543
  });
544
- this._store.history.executeCommand(new BatchCommand(this._store, this, [resizeSelectionGroupCommand, ...updateObjectsCommand]));
545
- this._store.state.isResizing = false;
546
- this._store.rerender();
544
+ this._core.history.executeCommand(new BatchCommand(this._core, this, [resizeSelectionGroupCommand, ...updateObjectsCommand]));
545
+ this._core.store.setState('isResizing', false);
547
546
  }
548
547
  }
549
548
  if (event.pointerType === 'touch') {
550
- if (this._store.state.isResizing) {
551
- const resizeSelectionGroupCommand = new ResizeSelectionGroupCommand(this._store, this, structuredClone(this.initialSize), structuredClone(this.newSize));
552
- const updateObjectsCommand = this._store.state.selectionGroup.objects.map(object => {
553
- return new UpdateObjectCommand(this._store, this, object, { ...object });
549
+ if (this._core.store.state.isResizing) {
550
+ const resizeSelectionGroupCommand = new ResizeSelectionGroupCommand(this._core, this, structuredClone(this.initialSize), structuredClone(this.newSize));
551
+ const updateObjectsCommand = this._core.store.state.selectionGroup.objects.map(object => {
552
+ return new UpdateObjectCommand(this._core, this, object, { ...object });
554
553
  });
555
- this._store.history.executeCommand(new BatchCommand(this._store, this, [resizeSelectionGroupCommand, ...updateObjectsCommand]));
556
- this._store.state.isResizing = false;
557
- this._store.rerender();
558
- clearTimeout(this._store.state.longTouchTimeout);
554
+ this._core.history.executeCommand(new BatchCommand(this._core, this, [resizeSelectionGroupCommand, ...updateObjectsCommand]));
555
+ this._core.store.setState('isResizing', false);
556
+ clearTimeout(this._core.store.state.longTouchTimeout);
559
557
  }
560
558
  }
561
559
  }
@@ -565,24 +563,24 @@ class RotateSelectionGroupCommand extends KritzelBaseCommand {
565
563
  rotation;
566
564
  initialRotation;
567
565
  selectionGroup;
568
- constructor(store, initiator, rotation, skipHistory = false) {
569
- super(store, initiator, skipHistory);
566
+ constructor(core, initiator, rotation, skipHistory = false) {
567
+ super(core, initiator, skipHistory);
570
568
  this.rotation = rotation;
571
- this.initialRotation = this._store.state.selectionGroup.rotation;
572
- this.selectionGroup = this._store.state.selectionGroup;
569
+ this.initialRotation = this._core.store.state.selectionGroup.rotation;
570
+ this.selectionGroup = this._core.store.state.selectionGroup;
573
571
  }
574
572
  execute() {
575
- this._store.state.selectionGroup = this.selectionGroup;
576
- this._store.state.selectionGroup.rotate(this.rotation);
577
- this._store.state.selectionGroup.objects.forEach(object => {
578
- this._store.state.objectsMap.update(object);
573
+ this._core.store.setState('selectionGroup', this.selectionGroup);
574
+ this._core.store.state.selectionGroup.rotate(this.rotation);
575
+ this._core.store.state.selectionGroup.objects.forEach(object => {
576
+ this._core.store.state.objectsMap.update(object);
579
577
  });
580
578
  }
581
579
  undo() {
582
- this._store.state.selectionGroup = this.selectionGroup;
583
- this._store.state.selectionGroup.rotate(this.rotation - this.initialRotation);
584
- this._store.state.selectionGroup.objects.forEach(object => {
585
- this._store.state.objectsMap.update(object);
580
+ this._core.store.setState('selectionGroup', this.selectionGroup);
581
+ this._core.store.state.selectionGroup.rotate(this.rotation - this.initialRotation);
582
+ this._core.store.state.selectionGroup.objects.forEach(object => {
583
+ this._core.store.state.objectsMap.update(object);
586
584
  });
587
585
  }
588
586
  }
@@ -590,111 +588,109 @@ class RotateSelectionGroupCommand extends KritzelBaseCommand {
590
588
  class KritzelRotationHandler extends KritzelBaseHandler {
591
589
  initialRotation = 0;
592
590
  rotation = 0;
593
- constructor(store) {
594
- super(store);
591
+ constructor(core) {
592
+ super(core);
595
593
  }
596
594
  handlePointerDown(event) {
597
595
  if (event.pointerType === 'mouse') {
598
596
  if (KritzelEventHelper.isLeftClick(event)) {
599
- if (this._store.state.selectionGroup && this._store.state.isRotationHandleSelected) {
600
- const clientX = event.clientX - this._store.offsetX;
601
- const clientY = event.clientY - this._store.offsetY;
602
- this._store.state.isRotating = true;
603
- const centerX = this._store.state.selectionGroup.translateX + this._store.state.selectionGroup.width / 2 / this._store.state.scale;
604
- const centerY = this._store.state.selectionGroup.translateY + this._store.state.selectionGroup.height / 2 / this._store.state.scale;
605
- const cursorX = (clientX - this._store.state.translateX) / this._store.state.scale;
606
- const cursorY = (clientY - this._store.state.translateY) / this._store.state.scale;
607
- this.initialRotation = Math.atan2(centerY - cursorY, centerX - cursorX) - this._store.state.selectionGroup.rotation;
597
+ if (this._core.store.state.selectionGroup && this._core.store.state.isRotationHandleSelected) {
598
+ const clientX = event.clientX - this._core.store.offsetX;
599
+ const clientY = event.clientY - this._core.store.offsetY;
600
+ this._core.store.setState('isRotating', true);
601
+ const centerX = this._core.store.state.selectionGroup.translateX + this._core.store.state.selectionGroup.width / 2 / this._core.store.state.scale;
602
+ const centerY = this._core.store.state.selectionGroup.translateY + this._core.store.state.selectionGroup.height / 2 / this._core.store.state.scale;
603
+ const cursorX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
604
+ const cursorY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
605
+ this.initialRotation = Math.atan2(centerY - cursorY, centerX - cursorX) - this._core.store.state.selectionGroup.rotation;
608
606
  }
609
607
  }
610
608
  }
611
609
  if (event.pointerType === 'touch') {
612
- const activePointers = Array.from(this._store.state.pointers.values());
610
+ const activePointers = Array.from(this._core.store.state.pointers.values());
613
611
  const firstTouch = activePointers[0];
614
612
  if (!firstTouch) {
615
613
  return;
616
614
  }
617
615
  if (activePointers.length === 1) {
618
- if (this._store.state.selectionGroup && this._store.state.isRotationHandleSelected) {
619
- const clientX = Math.round(firstTouch.clientX - this._store.offsetX);
620
- const clientY = Math.round(firstTouch.clientY - this._store.offsetY);
621
- this._store.state.isRotating = true;
622
- const centerX = this._store.state.selectionGroup.translateX + this._store.state.selectionGroup.width / 2 / this._store.state.scale;
623
- const centerY = this._store.state.selectionGroup.translateY + this._store.state.selectionGroup.height / 2 / this._store.state.scale;
624
- const cursorX = (clientX - this._store.state.translateX) / this._store.state.scale;
625
- const cursorY = (clientY - this._store.state.translateY) / this._store.state.scale;
626
- this.initialRotation = Math.atan2(centerY - cursorY, centerX - cursorX) - this._store.state.selectionGroup.rotation;
627
- clearTimeout(this._store.state.longTouchTimeout);
616
+ if (this._core.store.state.selectionGroup && this._core.store.state.isRotationHandleSelected) {
617
+ const clientX = Math.round(firstTouch.clientX - this._core.store.offsetX);
618
+ const clientY = Math.round(firstTouch.clientY - this._core.store.offsetY);
619
+ this._core.store.setState('isRotating', true);
620
+ const centerX = this._core.store.state.selectionGroup.translateX + this._core.store.state.selectionGroup.width / 2 / this._core.store.state.scale;
621
+ const centerY = this._core.store.state.selectionGroup.translateY + this._core.store.state.selectionGroup.height / 2 / this._core.store.state.scale;
622
+ const cursorX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
623
+ const cursorY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
624
+ this.initialRotation = Math.atan2(centerY - cursorY, centerX - cursorX) - this._core.store.state.selectionGroup.rotation;
625
+ clearTimeout(this._core.store.state.longTouchTimeout);
628
626
  }
629
627
  }
630
628
  }
631
629
  }
632
630
  handlePointerMove(event) {
633
631
  if (event.pointerType === 'mouse') {
634
- if (this._store.state.isRotating && this._store.state.selectionGroup) {
635
- const clientX = event.clientX - this._store.offsetX;
636
- const clientY = event.clientY - this._store.offsetY;
637
- const groupCenterX = this._store.state.selectionGroup.translateX + this._store.state.selectionGroup.width / 2 / this._store.state.scale;
638
- const groupCenterY = this._store.state.selectionGroup.translateY + this._store.state.selectionGroup.height / 2 / this._store.state.scale;
639
- const cursorX = (clientX - this._store.state.translateX) / this._store.state.scale;
640
- const cursorY = (clientY - this._store.state.translateY) / this._store.state.scale;
632
+ if (this._core.store.state.isRotating && this._core.store.state.selectionGroup) {
633
+ const clientX = event.clientX - this._core.store.offsetX;
634
+ const clientY = event.clientY - this._core.store.offsetY;
635
+ const groupCenterX = this._core.store.state.selectionGroup.translateX + this._core.store.state.selectionGroup.width / 2 / this._core.store.state.scale;
636
+ const groupCenterY = this._core.store.state.selectionGroup.translateY + this._core.store.state.selectionGroup.height / 2 / this._core.store.state.scale;
637
+ const cursorX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
638
+ const cursorY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
641
639
  const currentRotation = Math.atan2(groupCenterY - cursorY, groupCenterX - cursorX);
642
640
  this.rotation = currentRotation - this.initialRotation;
643
- this._store.state.selectionGroup.rotate(this.rotation);
644
- this._store.rerender();
641
+ this._core.store.state.selectionGroup.rotate(this.rotation);
645
642
  }
646
643
  }
647
644
  if (event.pointerType === 'touch') {
648
- const activePointers = Array.from(this._store.state.pointers.values());
645
+ const activePointers = Array.from(this._core.store.state.pointers.values());
649
646
  const firstTouch = activePointers[0];
650
647
  if (!firstTouch) {
651
648
  return;
652
649
  }
653
- if (this._store.state.isRotating && this._store.state.selectionGroup) {
654
- const clientX = Math.round(firstTouch.clientX - this._store.offsetX);
655
- const clientY = Math.round(firstTouch.clientY - this._store.offsetY);
656
- const groupCenterX = this._store.state.selectionGroup.translateX + this._store.state.selectionGroup.width / 2 / this._store.state.scale;
657
- const groupCenterY = this._store.state.selectionGroup.translateY + this._store.state.selectionGroup.height / 2 / this._store.state.scale;
658
- const cursorX = (clientX - this._store.state.translateX) / this._store.state.scale;
659
- const cursorY = (clientY - this._store.state.translateY) / this._store.state.scale;
650
+ if (this._core.store.state.isRotating && this._core.store.state.selectionGroup) {
651
+ const clientX = Math.round(firstTouch.clientX - this._core.store.offsetX);
652
+ const clientY = Math.round(firstTouch.clientY - this._core.store.offsetY);
653
+ const groupCenterX = this._core.store.state.selectionGroup.translateX + this._core.store.state.selectionGroup.width / 2 / this._core.store.state.scale;
654
+ const groupCenterY = this._core.store.state.selectionGroup.translateY + this._core.store.state.selectionGroup.height / 2 / this._core.store.state.scale;
655
+ const cursorX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
656
+ const cursorY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
660
657
  const currentRotation = Math.atan2(groupCenterY - cursorY, groupCenterX - cursorX);
661
658
  this.rotation = currentRotation - this.initialRotation;
662
- this._store.state.selectionGroup.rotate(this.rotation);
663
- this._store.rerender();
664
- clearTimeout(this._store.state.longTouchTimeout);
659
+ this._core.store.state.selectionGroup.rotate(this.rotation);
660
+ clearTimeout(this._core.store.state.longTouchTimeout);
665
661
  }
666
662
  }
667
663
  }
668
664
  handlePointerUp(event) {
669
665
  if (event.pointerType === 'mouse') {
670
- if (this._store.state.isRotating) {
671
- const rotateSelectionGroupCommand = new RotateSelectionGroupCommand(this._store, this, this.rotation);
672
- const updateObjectsCommand = this._store.state.selectionGroup.objects.map(object => {
673
- return new UpdateObjectCommand(this._store, this, object, {
666
+ if (this._core.store.state.isRotating) {
667
+ const rotateSelectionGroupCommand = new RotateSelectionGroupCommand(this._core, this, this.rotation);
668
+ const updateObjectsCommand = this._core.store.state.selectionGroup.objects.map(object => {
669
+ return new UpdateObjectCommand(this._core, this, object, {
674
670
  rotation: object.rotation,
675
671
  translateX: object.translateX,
676
672
  translateY: object.translateY,
677
673
  });
678
674
  });
679
- this._store.history.executeCommand(new BatchCommand(this._store, this, [rotateSelectionGroupCommand, ...updateObjectsCommand]));
680
- this._store.state.isRotating = false;
675
+ this._core.history.executeCommand(new BatchCommand(this._core, this, [rotateSelectionGroupCommand, ...updateObjectsCommand]));
676
+ this._core.store.setState('isRotating', false);
681
677
  this.initialRotation = 0;
682
678
  this.rotation = 0;
683
679
  }
684
680
  }
685
681
  if (event.pointerType === 'touch') {
686
- if (this._store.state.isRotating) {
687
- const rotateSelectionGroupCommand = new RotateSelectionGroupCommand(this._store, this, this.rotation);
688
- const updateObjectsCommand = this._store.state.selectionGroup.objects.map(object => {
689
- return new UpdateObjectCommand(this._store, this, object, {
682
+ if (this._core.store.state.isRotating) {
683
+ const rotateSelectionGroupCommand = new RotateSelectionGroupCommand(this._core, this, this.rotation);
684
+ const updateObjectsCommand = this._core.store.state.selectionGroup.objects.map(object => {
685
+ return new UpdateObjectCommand(this._core, this, object, {
690
686
  rotation: object.rotation,
691
687
  });
692
688
  });
693
- this._store.history.executeCommand(new BatchCommand(this._store, this, [rotateSelectionGroupCommand, ...updateObjectsCommand]));
694
- this._store.state.isRotating = false;
689
+ this._core.history.executeCommand(new BatchCommand(this._core, this, [rotateSelectionGroupCommand, ...updateObjectsCommand]));
690
+ this._core.store.setState('isRotating', false);
695
691
  this.initialRotation = 0;
696
692
  this.rotation = 0;
697
- clearTimeout(this._store.state.longTouchTimeout);
693
+ clearTimeout(this._core.store.state.longTouchTimeout);
698
694
  }
699
695
  }
700
696
  }
@@ -703,12 +699,12 @@ class KritzelRotationHandler extends KritzelBaseHandler {
703
699
  class KrtizelSelectionBox extends KritzelBaseObject {
704
700
  __class__ = 'KrtizelSelectionBox';
705
701
  objects = [];
706
- static create(store) {
702
+ static create(core) {
707
703
  const object = new KrtizelSelectionBox();
708
- object._store = store;
704
+ object._core = core;
709
705
  object.id = object.generateId();
710
- object.workspaceId = store.state.activeWorkspace.id;
711
- object.scale = store.state.scale;
706
+ object.workspaceId = core.store.state.activeWorkspace.id;
707
+ object.scale = core.store.state.scale;
712
708
  object.zIndex = 99999;
713
709
  object.backgroundColor = 'var(--kritzel-selection-box-background-color, rgba(0, 122, 255, 0.2))';
714
710
  object.borderColor = 'var(--kritzel-selection-box-border-color, rgba(0, 122, 255, 0.5))';
@@ -721,20 +717,20 @@ class KrtizelSelectionBox extends KritzelBaseObject {
721
717
 
722
718
  class AddSelectionGroupCommand extends KritzelBaseCommand {
723
719
  selectionGroup;
724
- constructor(store, initiator, selectionGroup, skipHistory = false) {
725
- super(store, initiator, skipHistory);
720
+ constructor(core, initiator, selectionGroup, skipHistory = false) {
721
+ super(core, initiator, skipHistory);
726
722
  this.selectionGroup = selectionGroup;
727
723
  }
728
724
  execute() {
729
- this._store.state.objectsMap.remove(object => object instanceof KrtizelSelectionBox);
730
- this._store.state.objectsMap.insert(this.selectionGroup);
731
- this._store.state.selectionGroup = this.selectionGroup;
732
- this._store.state.selectionBox = null;
725
+ this._core.store.state.objectsMap.remove(object => object instanceof KrtizelSelectionBox);
726
+ this._core.store.state.objectsMap.insert(this.selectionGroup);
727
+ this._core.store.setState('selectionGroup', this.selectionGroup);
728
+ this._core.store.setState('selectionBox', null);
733
729
  }
734
730
  undo() {
735
- this._store.state.objectsMap.remove(object => object.id === this.selectionGroup.id);
736
- this._store.state.selectionGroup = null;
737
- this._store.state.selectionBox = null;
731
+ this._core.store.state.objectsMap.remove(object => object.id === this.selectionGroup.id);
732
+ this._core.store.setState('selectionGroup', null);
733
+ this._core.store.setState('selectionBox', null);
738
734
  }
739
735
  }
740
736
 
@@ -745,23 +741,23 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
745
741
  touchStartY = 0;
746
742
  touchStartTimeout = null;
747
743
  get isSelectionClick() {
748
- return this._store.state.selectionBox && this._store.state.selectionBox.width === 0 && this._store.state.selectionBox.height === 0;
744
+ return this._core.store.state.selectionBox && this._core.store.state.selectionBox.width === 0 && this._core.store.state.selectionBox.height === 0;
749
745
  }
750
746
  get isSelectionDrag() {
751
- return this._store.state.selectionBox && (this._store.state.selectionBox.width > 0 || this._store.state.selectionBox.height > 0);
747
+ return this._core.store.state.selectionBox && (this._core.store.state.selectionBox.width > 0 || this._core.store.state.selectionBox.height > 0);
752
748
  }
753
- constructor(store) {
754
- super(store);
749
+ constructor(core) {
750
+ super(core);
755
751
  }
756
752
  handlePointerDown(event) {
757
753
  if (event.pointerType === 'mouse') {
758
- if (KritzelEventHelper.isLeftClick(event) && !this._store.state.selectionGroup) {
754
+ if (KritzelEventHelper.isLeftClick(event) && !this._core.store.state.selectionGroup) {
759
755
  this.startMouseSelection(event);
760
756
  }
761
757
  }
762
758
  if (event.pointerType === 'touch') {
763
759
  this.touchStartTimeout = setTimeout(() => {
764
- if (this._store.state.pointers.size === 1 && !this._store.state.isScaling && !this._store.state.selectionGroup) {
760
+ if (this._core.store.state.pointers.size === 1 && !this._core.store.state.isScaling && !this._core.store.state.selectionGroup) {
765
761
  this.startTouchSelection();
766
762
  this.updateTouchSelection();
767
763
  }
@@ -770,30 +766,30 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
770
766
  }
771
767
  handlePointerMove(event) {
772
768
  if (event.pointerType === 'mouse') {
773
- if (this._store.state.isSelecting) {
769
+ if (this._core.store.state.isSelecting) {
774
770
  this.updateMouseSelection(event);
775
771
  }
776
772
  }
777
773
  if (event.pointerType === 'touch') {
778
- const activePointers = Array.from(this._store.state.pointers.values());
779
- const x = Math.round(activePointers[0].clientX - this._store.offsetX);
780
- const y = Math.round(activePointers[0].clientY - this._store.offsetY);
774
+ const activePointers = Array.from(this._core.store.state.pointers.values());
775
+ const x = Math.round(activePointers[0].clientX - this._core.store.offsetX);
776
+ const y = Math.round(activePointers[0].clientY - this._core.store.offsetY);
781
777
  const moveDeltaX = Math.abs(x - this.touchStartX);
782
778
  const moveDeltaY = Math.abs(y - this.touchStartY);
783
779
  const moveThreshold = 5;
784
- if ((moveDeltaX > moveThreshold || moveDeltaY > moveThreshold) && this._store.state.isSelecting) {
780
+ if ((moveDeltaX > moveThreshold || moveDeltaY > moveThreshold) && this._core.store.state.isSelecting) {
785
781
  this.updateTouchSelection();
786
- clearTimeout(this._store.state.longTouchTimeout);
782
+ clearTimeout(this._core.store.state.longTouchTimeout);
787
783
  }
788
784
  }
789
785
  }
790
786
  handlePointerUp(event) {
791
787
  if (event.pointerType === 'mouse') {
792
- if (KritzelEventHelper.isLeftClick(event) && this._store.state.isSelecting) {
788
+ if (KritzelEventHelper.isLeftClick(event) && this._core.store.state.isSelecting) {
793
789
  if (this.isSelectionClick) {
794
- const x = this._store.state.pointerX;
795
- const y = this._store.state.pointerY;
796
- const selectedObject = this._store.getObjectsFromPointerEvent(event, '.object').find(obj => obj.hitTest(x, y));
790
+ const x = this._core.store.state.pointerX;
791
+ const y = this._core.store.state.pointerY;
792
+ const selectedObject = this._core.getObjectsFromPointerEvent(event, '.object').find(obj => obj.hitTest(x, y));
797
793
  this.addObjectToSelectionGroup(selectedObject);
798
794
  this.removeSelectionBox();
799
795
  }
@@ -806,11 +802,11 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
806
802
  }
807
803
  if (event.pointerType === 'touch') {
808
804
  clearTimeout(this.touchStartTimeout);
809
- if (this._store.state.isSelecting) {
805
+ if (this._core.store.state.isSelecting) {
810
806
  if (this.isSelectionClick) {
811
- const x = this._store.state.pointerX;
812
- const y = this._store.state.pointerY;
813
- const selectedObject = this._store.getObjectsFromPointerEvent(event, '.object').find(obj => obj.hitTest(x, y));
807
+ const x = this._core.store.state.pointerX;
808
+ const y = this._core.store.state.pointerY;
809
+ const selectedObject = this._core.getObjectsFromPointerEvent(event, '.object').find(obj => obj.hitTest(x, y));
814
810
  this.addObjectToSelectionGroup(selectedObject);
815
811
  this.removeSelectionBox();
816
812
  }
@@ -819,82 +815,80 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
819
815
  this.addSelectedObjectsToSelectionGroup();
820
816
  this.removeSelectionBox();
821
817
  }
822
- this._store.state.skipContextMenu = false;
818
+ this._core.store.setState('skipContextMenu', false);
823
819
  }
824
820
  }
825
821
  }
826
822
  removeSelectionBox() {
827
- this._store.state.selectionBox = null;
828
- this._store.state.isSelecting = false;
829
- this._store.state.objectsMap.remove(o => o instanceof KrtizelSelectionBox);
830
- this._store.rerender();
823
+ this._core.store.setState('selectionBox', null);
824
+ this._core.store.setState('isSelecting', false);
825
+ this._core.store.state.objectsMap.remove(o => o instanceof KrtizelSelectionBox);
831
826
  }
832
827
  startMouseSelection(event) {
833
828
  let clientX, clientY;
834
- clientX = event.clientX - this._store.offsetX;
835
- clientY = event.clientY - this._store.offsetY;
836
- const selectionBox = KrtizelSelectionBox.create(this._store);
837
- this.startX = (clientX - this._store.state.translateX) / this._store.state.scale;
838
- this.startY = (clientY - this._store.state.translateY) / this._store.state.scale;
829
+ clientX = event.clientX - this._core.store.offsetX;
830
+ clientY = event.clientY - this._core.store.offsetY;
831
+ const selectionBox = KrtizelSelectionBox.create(this._core);
832
+ this.startX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
833
+ this.startY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
839
834
  selectionBox.translateX = this.startX;
840
835
  selectionBox.translateY = this.startY;
841
- this._store.state.selectionGroup = null;
842
- this._store.state.selectionBox = selectionBox;
843
- this._store.state.isSelecting = true;
844
- this._store.state.objectsMap.remove(o => o instanceof KrtizelSelectionBox || o instanceof KritzelSelectionGroup);
845
- this._store.state.objectsMap.insert(selectionBox);
836
+ this._core.store.setState('selectionGroup', null);
837
+ this._core.store.setState('selectionBox', selectionBox);
838
+ this._core.store.setState('isSelecting', true);
839
+ this._core.store.state.objectsMap.remove(o => o instanceof KrtizelSelectionBox || o instanceof KritzelSelectionGroup);
840
+ this._core.store.state.objectsMap.insert(selectionBox);
846
841
  }
847
842
  startTouchSelection() {
848
- const activePointers = Array.from(this._store.state.pointers.values());
843
+ const activePointers = Array.from(this._core.store.state.pointers.values());
849
844
  const firstTouch = activePointers[0];
850
845
  if (!firstTouch) {
851
846
  return;
852
847
  }
853
848
  let clientX, clientY;
854
- clientX = Math.round(firstTouch.clientX - this._store.offsetX);
855
- clientY = Math.round(firstTouch.clientY - this._store.offsetY);
849
+ clientX = Math.round(firstTouch.clientX - this._core.store.offsetX);
850
+ clientY = Math.round(firstTouch.clientY - this._core.store.offsetY);
856
851
  this.touchStartX = clientX;
857
852
  this.touchStartY = clientY;
858
- const selectionBox = KrtizelSelectionBox.create(this._store);
859
- this.startX = (clientX - this._store.state.translateX) / this._store.state.scale;
860
- this.startY = (clientY - this._store.state.translateY) / this._store.state.scale;
853
+ const selectionBox = KrtizelSelectionBox.create(this._core);
854
+ this.startX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
855
+ this.startY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
861
856
  selectionBox.translateX = this.startX;
862
857
  selectionBox.translateY = this.startY;
863
- this._store.state.selectionGroup = null;
864
- this._store.state.selectionBox = selectionBox;
865
- this._store.state.isSelecting = true;
866
- this._store.state.objectsMap.remove(o => o instanceof KrtizelSelectionBox || o instanceof KritzelSelectionGroup);
867
- this._store.state.objectsMap.insert(selectionBox);
858
+ this._core.store.setState('selectionGroup', null);
859
+ this._core.store.setState('selectionBox', selectionBox);
860
+ this._core.store.setState('isSelecting', true);
861
+ this._core.store.state.objectsMap.remove(o => o instanceof KrtizelSelectionBox || o instanceof KritzelSelectionGroup);
862
+ this._core.store.state.objectsMap.insert(selectionBox);
868
863
  }
869
864
  updateMouseSelection(event) {
870
865
  let clientX, clientY;
871
- clientX = event.clientX - this._store.offsetX;
872
- clientY = event.clientY - this._store.offsetY;
873
- const selectionBox = this._store.state.selectionBox;
866
+ clientX = event.clientX - this._core.store.offsetX;
867
+ clientY = event.clientY - this._core.store.offsetY;
868
+ const selectionBox = this._core.store.state.selectionBox;
874
869
  if (selectionBox) {
875
- const currentX = (clientX - this._store.state.translateX) / selectionBox.scale;
876
- const currentY = (clientY - this._store.state.translateY) / selectionBox.scale;
870
+ const currentX = (clientX - this._core.store.state.translateX) / selectionBox.scale;
871
+ const currentY = (clientY - this._core.store.state.translateY) / selectionBox.scale;
877
872
  selectionBox.width = Math.abs(currentX - this.startX) * selectionBox.scale;
878
873
  selectionBox.height = Math.abs(currentY - this.startY) * selectionBox.scale;
879
874
  selectionBox.translateX = Math.min(currentX, this.startX);
880
875
  selectionBox.translateY = Math.min(currentY, this.startY);
881
876
  this.updateSelectedObjects();
882
- this._store.rerender();
883
877
  }
884
878
  }
885
879
  updateTouchSelection() {
886
- const activePointers = Array.from(this._store.state.pointers.values());
880
+ const activePointers = Array.from(this._core.store.state.pointers.values());
887
881
  const firstTouch = activePointers[0];
888
882
  if (!firstTouch) {
889
883
  return;
890
884
  }
891
885
  let clientX, clientY;
892
- clientX = Math.round(firstTouch.clientX - this._store.offsetX);
893
- clientY = Math.round(firstTouch.clientY - this._store.offsetY);
894
- const selectionBox = this._store.state.selectionBox;
886
+ clientX = Math.round(firstTouch.clientX - this._core.store.offsetX);
887
+ clientY = Math.round(firstTouch.clientY - this._core.store.offsetY);
888
+ const selectionBox = this._core.store.state.selectionBox;
895
889
  if (selectionBox) {
896
- const currentX = (clientX - this._store.state.translateX) / selectionBox.scale;
897
- const currentY = (clientY - this._store.state.translateY) / selectionBox.scale;
890
+ const currentX = (clientX - this._core.store.state.translateX) / selectionBox.scale;
891
+ const currentY = (clientY - this._core.store.state.translateY) / selectionBox.scale;
898
892
  selectionBox.width = Math.abs(currentX - this.startX) * selectionBox.scale;
899
893
  selectionBox.height = Math.abs(currentY - this.startY) * selectionBox.scale;
900
894
  selectionBox.translateX = Math.min(currentX, this.startX);
@@ -903,49 +897,52 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
903
897
  }
904
898
  }
905
899
  updateSelectedObjects() {
906
- this._store.allObjects
900
+ this._core.store.allObjects
907
901
  .filter(o => !(o instanceof KrtizelSelectionBox))
908
- .forEach(object => (object.isSelected = object.hitTestPolygon(this._store.state.selectionBox.rotatedPolygon)));
902
+ .forEach(object => (object.isSelected = object.hitTestPolygon(this._core.store.state.selectionBox.rotatedPolygon)));
909
903
  }
910
904
  addObjectToSelectionGroup(object) {
911
905
  if (!object) {
912
906
  return;
913
907
  }
914
- this._store.state.selectionGroup = KritzelSelectionGroup.create(this._store);
915
- this._store.state.selectionGroup.addOrRemove(object);
916
- this._store.state.selectionGroup.isSelected = true;
917
- this._store.state.selectionGroup.rotation = object.rotation;
918
- this._store.history.executeCommand(new AddSelectionGroupCommand(this._store, this, this._store.state.selectionGroup));
908
+ const selectionGroup = KritzelSelectionGroup.create(this._core);
909
+ selectionGroup.addOrRemove(object);
910
+ selectionGroup.isSelected = true;
911
+ selectionGroup.rotation = object.rotation;
912
+ this._core.store.setState('selectionGroup', selectionGroup);
913
+ this._core.history.executeCommand(new AddSelectionGroupCommand(this._core, this, this._core.store.state.selectionGroup));
919
914
  }
920
915
  addSelectedObjectsToSelectionGroup() {
921
- const selectedObjects = this._store.selectedObjects;
916
+ const selectedObjects = this._core.store.selectedObjects;
922
917
  if (selectedObjects.length === 0) {
923
918
  return;
924
919
  }
925
- this._store.state.selectionGroup = KritzelSelectionGroup.create(this._store);
920
+ this._core.store.setState('selectionGroup', KritzelSelectionGroup.create(this._core));
926
921
  selectedObjects.forEach(o => {
927
922
  o.isSelected = false;
928
- this._store.state.selectionGroup.addOrRemove(o);
923
+ this._core.store.state.selectionGroup.addOrRemove(o);
929
924
  });
930
- this._store.state.selectionGroup.isSelected = true;
931
- if (this._store.state.selectionGroup.length === 1) {
932
- this._store.state.selectionGroup.rotation = this._store.state.selectionGroup.objects[0].rotation;
925
+ const selectionGroup = this._core.store.state.selectionGroup;
926
+ selectionGroup.isSelected = true;
927
+ if (selectionGroup.length === 1) {
928
+ selectionGroup.rotation = selectionGroup.objects[0].rotation;
933
929
  }
934
- this._store.history.executeCommand(new AddSelectionGroupCommand(this._store, this, this._store.state.selectionGroup));
930
+ this._core.store.setState('selectionGroup', selectionGroup);
931
+ this._core.history.executeCommand(new AddSelectionGroupCommand(this._core, this, this._core.store.state.selectionGroup));
935
932
  }
936
933
  }
937
934
 
938
935
  class KritzelHoverHandler extends KritzelBaseHandler {
939
- constructor(store) {
940
- super(store);
936
+ constructor(core) {
937
+ super(core);
941
938
  }
942
939
  handlePointerMove(event) {
943
940
  if (event.pointerType === 'mouse') {
944
- const hoveredObject = this._store.getObjectFromPointerEvent(event, '.object');
941
+ const hoveredObject = this._core.getObjectFromPointerEvent(event, '.object');
945
942
  if (!hoveredObject)
946
943
  return;
947
- const x = this._store.state.pointerX;
948
- const y = this._store.state.pointerY;
944
+ const x = this._core.store.state.pointerX;
945
+ const y = this._core.store.state.pointerY;
949
946
  hoveredObject.isHovered = hoveredObject.hitTest(x, y);
950
947
  }
951
948
  }
@@ -957,13 +954,13 @@ class KritzelSelectionTool extends KritzelBaseTool {
957
954
  hoverHandler;
958
955
  resizeHandler;
959
956
  rotationHandler;
960
- constructor(store) {
961
- super(store);
962
- this.selectionHandler = new KritzelSelectionHandler(this._store);
963
- this.moveHandler = new KritzelMoveHandler(this._store);
964
- this.hoverHandler = new KritzelHoverHandler(this._store);
965
- this.resizeHandler = new KritzelResizeHandler(this._store);
966
- this.rotationHandler = new KritzelRotationHandler(this._store);
957
+ constructor(core) {
958
+ super(core);
959
+ this.selectionHandler = new KritzelSelectionHandler(this._core);
960
+ this.moveHandler = new KritzelMoveHandler(this._core);
961
+ this.hoverHandler = new KritzelHoverHandler(this._core);
962
+ this.resizeHandler = new KritzelResizeHandler(this._core);
963
+ this.rotationHandler = new KritzelRotationHandler(this._core);
967
964
  }
968
965
  handlePointerDown(event) {
969
966
  if (event.cancelable) {
@@ -971,16 +968,16 @@ class KritzelSelectionTool extends KritzelBaseTool {
971
968
  }
972
969
  if (event.pointerType === 'mouse') {
973
970
  if (KritzelEventHelper.isLeftClick(event)) {
974
- this._store.state.isResizeHandleSelected = this.isHandleSelected(event);
975
- this._store.state.isRotationHandleSelected = this.isRotationHandleSelected(event);
976
- this._store.state.resizeHandleType = this.getHandleType(event);
971
+ this._core.store.setState('isResizeHandleSelected', this.isHandleSelected(event));
972
+ this._core.store.setState('isRotationHandleSelected', this.isRotationHandleSelected(event));
973
+ this._core.store.setState('resizeHandleType', this.getHandleType(event));
977
974
  const selectedObject = this.getSelectedObject(event);
978
- const isDifferentObject = selectedObject && this._store.state.selectionGroup && selectedObject.id !== this._store.state.selectionGroup.id;
975
+ const isDifferentObject = selectedObject && this._core.store.state.selectionGroup && selectedObject.id !== this._core.store.state.selectionGroup.id;
979
976
  if ((selectedObject === null || isDifferentObject) &&
980
- this._store.state.selectionGroup &&
981
- !this._store.state.isResizeHandleSelected &&
982
- !this._store.state.isRotationHandleSelected) {
983
- this._store.history.executeCommand(new RemoveSelectionGroupCommand(this._store, this._store.state.selectionGroup));
977
+ this._core.store.state.selectionGroup &&
978
+ !this._core.store.state.isResizeHandleSelected &&
979
+ !this._core.store.state.isRotationHandleSelected) {
980
+ this._core.history.executeCommand(new RemoveSelectionGroupCommand(this._core, this._core.store.state.selectionGroup));
984
981
  }
985
982
  if (selectedObject && selectedObject.isSelected === false && selectedObject?.objects.length === 1 && selectedObject.objects[0].isInteractive) {
986
983
  return;
@@ -990,32 +987,33 @@ class KritzelSelectionTool extends KritzelBaseTool {
990
987
  this.selectionHandler.handlePointerDown(event);
991
988
  this.resizeHandler.handlePointerDown(event);
992
989
  this.rotationHandler.handlePointerDown(event);
993
- this._store.rerender();
990
+ this._core.rerender();
994
991
  }
995
992
  if (event.pointerType === 'touch') {
996
- if (this._store.state.isScaling === true) {
993
+ if (this._core.store.state.isScaling === true) {
997
994
  return;
998
995
  }
999
- if (this._store.state.pointers.size === 1) {
1000
- this._store.state.isResizeHandleSelected = this.isHandleSelected(event);
1001
- this._store.state.isRotationHandleSelected = this.isRotationHandleSelected(event);
1002
- this._store.state.resizeHandleType = this.getHandleType(event);
996
+ if (this._core.store.state.pointers.size === 1) {
997
+ this._core.store.setState('isResizeHandleSelected', this.isHandleSelected(event));
998
+ this._core.store.setState('isRotationHandleSelected', this.isRotationHandleSelected(event));
999
+ this._core.store.setState('resizeHandleType', this.getHandleType(event));
1003
1000
  const selectedObject = this.getSelectedObject(event);
1004
- const isDifferentObject = selectedObject && this._store.state.selectionGroup && selectedObject.id !== this._store.state.selectionGroup.id;
1005
- if (!this._store.state.selectionGroup && selectedObject) {
1006
- this._store.state.skipContextMenu = true;
1001
+ const isDifferentObject = selectedObject && this._core.store.state.selectionGroup && selectedObject.id !== this._core.store.state.selectionGroup.id;
1002
+ if (!this._core.store.state.selectionGroup && selectedObject) {
1003
+ this._core.store.setState('skipContextMenu', true);
1007
1004
  }
1008
1005
  if ((selectedObject === null || isDifferentObject) &&
1009
- this._store.state.selectionGroup &&
1010
- !this._store.state.isResizeHandleSelected &&
1011
- !this._store.state.isRotationHandleSelected) {
1012
- this._store.history.executeCommand(new RemoveSelectionGroupCommand(this._store, this._store.state.selectionGroup));
1006
+ this._core.store.state.selectionGroup &&
1007
+ !this._core.store.state.isResizeHandleSelected &&
1008
+ !this._core.store.state.isRotationHandleSelected) {
1009
+ this._core.history.executeCommand(new RemoveSelectionGroupCommand(this._core, this._core.store.state.selectionGroup));
1013
1010
  }
1014
1011
  }
1015
1012
  this.rotationHandler.handlePointerDown(event);
1016
1013
  this.resizeHandler.handlePointerDown(event);
1017
1014
  this.moveHandler.handlePointerDown(event);
1018
1015
  this.selectionHandler.handlePointerDown(event);
1016
+ this._core.rerender();
1019
1017
  }
1020
1018
  }
1021
1019
  handlePointerMove(event) {
@@ -1028,17 +1026,17 @@ class KritzelSelectionTool extends KritzelBaseTool {
1028
1026
  this.selectionHandler.handlePointerMove(event);
1029
1027
  this.resizeHandler.handlePointerMove(event);
1030
1028
  this.rotationHandler.handlePointerMove(event);
1031
- this._store.rerender();
1029
+ this._core.rerender();
1032
1030
  }
1033
1031
  if (event.pointerType === 'touch') {
1034
- if (this._store.state.isScaling === true) {
1032
+ if (this._core.store.state.isScaling === true) {
1035
1033
  return;
1036
1034
  }
1037
1035
  this.rotationHandler.handlePointerMove(event);
1038
1036
  this.resizeHandler.handlePointerMove(event);
1039
1037
  this.moveHandler.handlePointerMove(event);
1040
1038
  this.selectionHandler.handlePointerMove(event);
1041
- this._store.rerender();
1039
+ this._core.rerender();
1042
1040
  }
1043
1041
  }
1044
1042
  handlePointerUp(event) {
@@ -1050,22 +1048,23 @@ class KritzelSelectionTool extends KritzelBaseTool {
1050
1048
  this.selectionHandler.handlePointerUp(event);
1051
1049
  this.resizeHandler.handlePointerUp(event);
1052
1050
  this.rotationHandler.handlePointerUp(event);
1053
- this._store.rerender();
1051
+ this._core.rerender();
1054
1052
  }
1055
1053
  if (event.pointerType === 'touch') {
1056
- if (this._store.state.isScaling === true) {
1054
+ if (this._core.store.state.isScaling === true) {
1057
1055
  return;
1058
1056
  }
1059
1057
  this.rotationHandler.handlePointerUp(event);
1060
1058
  this.resizeHandler.handlePointerUp(event);
1061
1059
  this.moveHandler.handlePointerUp(event);
1062
1060
  this.selectionHandler.handlePointerUp(event);
1061
+ this._core.rerender();
1063
1062
  }
1064
1063
  }
1065
1064
  getSelectedObject(event) {
1066
1065
  const path = event.composedPath().slice(1);
1067
1066
  const objectElement = path.find(element => element.classList && element.classList.contains('object'));
1068
- const object = this._store.findObjectById(objectElement?.id);
1067
+ const object = this._core.findObjectById(objectElement?.id);
1069
1068
  if (!object) {
1070
1069
  return null;
1071
1070
  }
@@ -1073,7 +1072,7 @@ class KritzelSelectionTool extends KritzelBaseTool {
1073
1072
  return object;
1074
1073
  }
1075
1074
  else {
1076
- const group = KritzelSelectionGroup.create(this._store);
1075
+ const group = KritzelSelectionGroup.create(this._core);
1077
1076
  group.translateX = 0;
1078
1077
  group.translateY = 0;
1079
1078
  group.addOrRemove(object);
@@ -1081,7 +1080,7 @@ class KritzelSelectionTool extends KritzelBaseTool {
1081
1080
  }
1082
1081
  }
1083
1082
  getHandleType(event) {
1084
- const shadowRoot = this._store.state.host?.shadowRoot;
1083
+ const shadowRoot = this._core.store.state.host?.shadowRoot;
1085
1084
  if (!shadowRoot)
1086
1085
  return;
1087
1086
  const elementAtPoint = shadowRoot.elementFromPoint(event.clientX, event.clientY);
@@ -1089,7 +1088,7 @@ class KritzelSelectionTool extends KritzelBaseTool {
1089
1088
  return handle?.classList[1];
1090
1089
  }
1091
1090
  isHandleSelected(event) {
1092
- const shadowRoot = this._store.state.host?.shadowRoot;
1091
+ const shadowRoot = this._core.store.state.host?.shadowRoot;
1093
1092
  if (!shadowRoot)
1094
1093
  return false;
1095
1094
  const elementAtPoint = shadowRoot.elementFromPoint(event.clientX, event.clientY);
@@ -1102,9 +1101,9 @@ class KritzelSelectionTool extends KritzelBaseTool {
1102
1101
  }
1103
1102
 
1104
1103
  class KritzelReviver {
1105
- _store;
1106
- constructor(store) {
1107
- this._store = store;
1104
+ _core;
1105
+ constructor(core) {
1106
+ this._core = core;
1108
1107
  }
1109
1108
  revive(obj) {
1110
1109
  if (obj && typeof obj === 'object') {
@@ -1112,34 +1111,37 @@ class KritzelReviver {
1112
1111
  let revivedObj;
1113
1112
  switch (obj.__class__) {
1114
1113
  case 'KritzelPath':
1115
- revivedObj = KritzelPath.create(this._store).revive(obj);
1114
+ revivedObj = KritzelPath.create(this._core).deserialize(obj);
1116
1115
  break;
1117
1116
  case 'KritzelText':
1118
- revivedObj = KritzelText.create(this._store, obj.fontSize, obj.fontFamily).revive(obj);
1117
+ revivedObj = KritzelText.create(this._core, obj.fontSize, obj.fontFamily).deserialize(obj);
1119
1118
  break;
1120
1119
  case 'KritzelImage':
1121
- revivedObj = KritzelImage.create(this._store).revive(obj);
1120
+ revivedObj = KritzelImage.create(this._core).deserialize(obj);
1122
1121
  break;
1123
1122
  case 'KritzelCustomElement':
1124
- revivedObj = KritzelCustomElement.create(this._store).revive(obj);
1123
+ revivedObj = KritzelCustomElement.create(this._core).deserialize(obj);
1125
1124
  break;
1126
1125
  case 'KritzelSelectionGroup':
1127
- revivedObj = KritzelSelectionGroup.create(this._store).revive(obj);
1126
+ revivedObj = KritzelSelectionGroup.create(this._core).deserialize(obj);
1127
+ break;
1128
+ case 'KritzelWorkspace':
1129
+ revivedObj = KritzelWorkspace.create(this._core, obj).deserialize(obj);
1128
1130
  break;
1129
1131
  case 'KritzelBrushTool':
1130
- revivedObj = new KritzelBrushTool(this._store);
1132
+ revivedObj = new KritzelBrushTool(this._core);
1131
1133
  break;
1132
1134
  case 'KritzelEraserTool':
1133
- revivedObj = new KritzelEraserTool(this._store);
1135
+ revivedObj = new KritzelEraserTool(this._core);
1134
1136
  break;
1135
1137
  case 'KritzelImageTool':
1136
- revivedObj = new KritzelImageTool(this._store);
1138
+ revivedObj = new KritzelImageTool(this._core);
1137
1139
  break;
1138
1140
  case 'KritzelSelectionTool':
1139
- revivedObj = new KritzelSelectionTool(this._store);
1141
+ revivedObj = new KritzelSelectionTool(this._core);
1140
1142
  break;
1141
1143
  case 'KritzelTextTool':
1142
- revivedObj = new KritzelTextTool(this._store);
1144
+ revivedObj = new KritzelTextTool(this._core);
1143
1145
  break;
1144
1146
  default:
1145
1147
  revivedObj = obj;
@@ -1169,12 +1171,12 @@ class KritzelSelectionGroup extends KritzelBaseObject {
1169
1171
  get length() {
1170
1172
  return this.objects.length;
1171
1173
  }
1172
- static create(store) {
1174
+ static create(core) {
1173
1175
  const object = new KritzelSelectionGroup();
1174
- object._store = store;
1176
+ object._core = core;
1175
1177
  object.id = object.generateId();
1176
- object.workspaceId = store.state.activeWorkspace.id;
1177
- object.scale = store.state.scale;
1178
+ object.workspaceId = core.store.state.activeWorkspace.id;
1179
+ object.scale = core.store.state.scale;
1178
1180
  object.zIndex = 99999;
1179
1181
  return object;
1180
1182
  }
@@ -1206,17 +1208,17 @@ class KritzelSelectionGroup extends KritzelBaseObject {
1206
1208
  });
1207
1209
  this.translateX = x;
1208
1210
  this.translateY = y;
1209
- this._store.state.objectsMap.update(this);
1211
+ this._core.store.state.objectsMap.update(this);
1210
1212
  }
1211
1213
  move(startX, startY, endX, endY) {
1212
- const deltaX = (startX - endX) / this._store.state.scale;
1213
- const deltaY = (startY - endY) / this._store.state.scale;
1214
+ const deltaX = (startX - endX) / this._core.store.state.scale;
1215
+ const deltaY = (startY - endY) / this._core.store.state.scale;
1214
1216
  this.translateX += deltaX;
1215
1217
  this.translateY += deltaY;
1216
- this._store.state.objectsMap.update(this);
1218
+ this._core.store.state.objectsMap.update(this);
1217
1219
  this.objects.forEach(obj => {
1218
1220
  obj.move(startX, startY, endX, endY);
1219
- this._store.state.objectsMap.update(obj);
1221
+ this._core.store.state.objectsMap.update(obj);
1220
1222
  });
1221
1223
  this.unchangedObjects.forEach(obj => {
1222
1224
  obj.translateX += deltaX;
@@ -1234,7 +1236,7 @@ class KritzelSelectionGroup extends KritzelBaseObject {
1234
1236
  const updatedX = child.translateX + deltaX + (child.translateX - this.translateX) * (widthScaleFactor - 1);
1235
1237
  const updatedY = child.translateY + deltaY + (child.translateY - this.translateY) * (heightScaleFactor - 1);
1236
1238
  child.resize(updatedX, updatedY, updatedWidth, updatedHeight);
1237
- this._store.state.objectsMap.update(child);
1239
+ this._core.store.state.objectsMap.update(child);
1238
1240
  });
1239
1241
  this.refreshObjectDimensions();
1240
1242
  this.unchangedObjects = ObjectHelper.clone(this.objects);
@@ -1255,12 +1257,12 @@ class KritzelSelectionGroup extends KritzelBaseObject {
1255
1257
  child.translateX = centerX + rotatedX - child.totalWidth / 2 / child.scale;
1256
1258
  child.translateY = centerY + rotatedY - child.totalHeight / 2 / child.scale;
1257
1259
  child.rotate(this.objects.length === 1 ? value : value + unchangedChild.rotation);
1258
- this._store.state.objectsMap.update(child);
1260
+ this._core.store.state.objectsMap.update(child);
1259
1261
  });
1260
1262
  }
1261
1263
  copy() {
1262
- const selectionGroup = KritzelSelectionGroup.create(this._store);
1263
- let currentZIndex = this._store.currentZIndex;
1264
+ const selectionGroup = KritzelSelectionGroup.create(this._core);
1265
+ let currentZIndex = this._core.store.currentZIndex;
1264
1266
  this.objects.sort((a, b) => a.zIndex - b.zIndex).forEach(obj => {
1265
1267
  const copiedObject = obj.copy();
1266
1268
  copiedObject.zIndex = currentZIndex;
@@ -1295,7 +1297,7 @@ class KritzelSelectionGroup extends KritzelBaseObject {
1295
1297
  this.width = (this.maxX - this.minX - this.padding) * this.scale;
1296
1298
  this.height = (this.maxY - this.minY - this.padding) * this.scale;
1297
1299
  }
1298
- this._store.state.objectsMap.update(this);
1300
+ this._core.store.state.objectsMap.update(this);
1299
1301
  }
1300
1302
  getOffsetXToCenter(obj) {
1301
1303
  const objCenterX = obj.translateX + obj.totalWidth / obj.scale / 2;
@@ -1309,7 +1311,7 @@ class KritzelSelectionGroup extends KritzelBaseObject {
1309
1311
  }
1310
1312
  getUnchangedObject(objectId) {
1311
1313
  const obj = this.unchangedObjects.find(obj => obj.id === objectId);
1312
- const reviver = new KritzelReviver(this._store);
1314
+ const reviver = new KritzelReviver(this._core);
1313
1315
  return reviver.revive(obj);
1314
1316
  }
1315
1317
  }
@@ -1326,15 +1328,15 @@ function _mergeNamespaces(e,t){return t.forEach((function(t){t&&"string"!=typeof
1326
1328
  class KritzelImageTool extends KritzelBaseTool {
1327
1329
  fileInput = null;
1328
1330
  maxCompressionSize = 300;
1329
- constructor(store) {
1330
- super(store);
1331
+ constructor(core) {
1332
+ super(core);
1331
1333
  this.setupFileInput();
1332
1334
  }
1333
1335
  onActivate() {
1334
1336
  this.openFilePicker();
1335
1337
  }
1336
1338
  openFilePicker() {
1337
- if (this._store.isDisabled) {
1339
+ if (this._core.store.isDisabled) {
1338
1340
  return;
1339
1341
  }
1340
1342
  this.fileInput.click();
@@ -1381,27 +1383,27 @@ class KritzelImageTool extends KritzelBaseTool {
1381
1383
  reader.readAsDataURL(file);
1382
1384
  }
1383
1385
  createKritzelImage(img) {
1384
- const image = KritzelImage.create(this._store);
1386
+ const image = KritzelImage.create(this._core);
1385
1387
  const { scaledWidth, scaledHeight } = image.calculateScaledDimensions(img);
1386
1388
  image.src = img.src;
1387
1389
  image.width = scaledWidth;
1388
1390
  image.height = scaledHeight;
1389
- image.zIndex = this._store.currentZIndex;
1391
+ image.zIndex = this._core.store.currentZIndex;
1390
1392
  image.centerInViewport();
1391
1393
  this.addImageToStore(image);
1392
1394
  return image;
1393
1395
  }
1394
1396
  addImageToStore(image) {
1395
- const selectionGroup = KritzelSelectionGroup.create(this._store);
1397
+ const selectionGroup = KritzelSelectionGroup.create(this._core);
1396
1398
  selectionGroup.addOrRemove(image);
1397
1399
  selectionGroup.isSelected = true;
1398
- const addImageCommand = new AddObjectCommand(this._store, this, image);
1399
- const addSelectionGroupCommand = new AddSelectionGroupCommand(this._store, this, selectionGroup);
1400
- this._store.history.executeCommand(new BatchCommand(this._store, this, [addImageCommand, addSelectionGroupCommand]));
1401
- this._store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
1400
+ const addImageCommand = new AddObjectCommand(this._core, this, image);
1401
+ const addSelectionGroupCommand = new AddSelectionGroupCommand(this._core, this, selectionGroup);
1402
+ this._core.history.executeCommand(new BatchCommand(this._core, this, [addImageCommand, addSelectionGroupCommand]));
1403
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
1402
1404
  }
1403
1405
  handleCancel() {
1404
- this._store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
1406
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
1405
1407
  }
1406
1408
  }
1407
1409
 
@@ -1409,117 +1411,119 @@ const ABSOLUTE_SCALE_MAX = 1000;
1409
1411
  const ABSOLUTE_SCALE_MIN = 0.0001;
1410
1412
 
1411
1413
  class KritzelViewport {
1412
- _store;
1414
+ _core;
1413
1415
  initialTouchDistance = 0;
1414
1416
  startX = 0;
1415
1417
  startY = 0;
1416
- constructor(store, host) {
1417
- this._store = store;
1418
- this._store.state.host = host;
1419
- this._store.state.viewportWidth = host.clientWidth;
1420
- this._store.state.viewportHeight = host.clientHeight;
1421
- this._store.state.startX = 0;
1422
- this._store.state.startY = 0;
1423
- this._store.state.translateX = 0;
1424
- this._store.state.translateY = 0;
1418
+ constructor(core, host) {
1419
+ this._core = core;
1420
+ this._core.store.setState('host', host);
1421
+ this._core.store.setState('viewportWidth', host.clientWidth);
1422
+ this._core.store.setState('viewportHeight', host.clientHeight);
1423
+ this._core.store.setState('startX', 0);
1424
+ this._core.store.setState('startY', 0);
1425
+ this._core.store.setState('translateX', 0);
1426
+ this._core.store.setState('translateY', 0);
1425
1427
  }
1426
1428
  handleResize() {
1427
- this._store.state.viewportWidth = this._store.state.host.clientWidth;
1428
- this._store.state.viewportHeight = this._store.state.host.clientHeight;
1429
- this._store.state.hasViewportChanged = true;
1430
- this._store.rerender();
1429
+ this._core.store.setState('viewportWidth', this._core.store.state.host.clientWidth);
1430
+ this._core.store.setState('viewportHeight', this._core.store.state.host.clientHeight);
1431
+ this._core.store.setState('hasViewportChanged', true);
1432
+ this._core.rerender();
1431
1433
  }
1432
1434
  handlePointerDown(event) {
1433
1435
  if (event.pointerType === 'mouse') {
1434
- const adjustedClientX = event.clientX - this._store.offsetX;
1435
- const adjustedClientY = event.clientY - this._store.offsetY;
1436
+ const adjustedClientX = event.clientX - this._core.store.offsetX;
1437
+ const adjustedClientY = event.clientY - this._core.store.offsetY;
1436
1438
  if (event.button === KritzelMouseButton.Right) {
1437
- this._store.state.isPanning = true;
1438
- this._store.state.startX = adjustedClientX;
1439
- this._store.state.startY = adjustedClientY;
1439
+ this._core.store.setState('isPanning', true);
1440
+ this._core.store.setState('startX', adjustedClientX);
1441
+ this._core.store.setState('startY', adjustedClientY);
1440
1442
  }
1441
1443
  }
1442
1444
  if (event.pointerType === 'touch') {
1443
- const activePointers = Array.from(this._store.state.pointers.values());
1445
+ const activePointers = Array.from(this._core.store.state.pointers.values());
1444
1446
  if (activePointers.length === 2) {
1445
- this._store.state.currentPath = null;
1446
- this._store.state.isScaling = true;
1447
- const firstTouchX = activePointers[0].clientX - this._store.offsetX;
1448
- const firstTouchY = activePointers[0].clientY - this._store.offsetY;
1449
- const secondTouchX = activePointers[1].clientX - this._store.offsetX;
1450
- const secondTouchY = activePointers[1].clientY - this._store.offsetY;
1447
+ this._core.store.setState('currentPath', null);
1448
+ this._core.store.setState('isScaling', true);
1449
+ const firstTouchX = activePointers[0].clientX - this._core.store.offsetX;
1450
+ const firstTouchY = activePointers[0].clientY - this._core.store.offsetY;
1451
+ const secondTouchX = activePointers[1].clientX - this._core.store.offsetX;
1452
+ const secondTouchY = activePointers[1].clientY - this._core.store.offsetY;
1451
1453
  this.initialTouchDistance = Math.sqrt(Math.pow(firstTouchX - secondTouchX, 2) + Math.pow(firstTouchY - secondTouchY, 2));
1452
1454
  this.startX = (firstTouchX + secondTouchX) / 2;
1453
1455
  this.startY = (firstTouchY + secondTouchY) / 2;
1454
- this._store.rerender();
1456
+ this._core.rerender();
1455
1457
  }
1456
1458
  }
1457
1459
  }
1458
1460
  handlePointerMove(event) {
1459
1461
  if (event.pointerType === 'mouse') {
1460
- const hostRect = this._store.state.host.getBoundingClientRect();
1462
+ const hostRect = this._core.store.state.host.getBoundingClientRect();
1461
1463
  const xRelativeToHost = event.clientX - hostRect.left;
1462
1464
  const yRelativeToHost = event.clientY - hostRect.top;
1463
- this._store.state.pointerX = (xRelativeToHost - this._store.state.translateX) / this._store.state.scale;
1464
- this._store.state.pointerY = (yRelativeToHost - this._store.state.translateY) / this._store.state.scale;
1465
- if (this._store.state.isPanning) {
1466
- this._store.state.translateX -= this._store.state.startX - xRelativeToHost;
1467
- this._store.state.translateY -= this._store.state.startY - yRelativeToHost;
1468
- this._store.state.startX = xRelativeToHost;
1469
- this._store.state.startY = yRelativeToHost;
1470
- this._store.state.hasViewportChanged = true;
1471
- this._store.state.skipContextMenu = true;
1472
- this._store.rerender();
1473
- this._store.updateWorkspaceViewport(this._store.state.translateX, this._store.state.translateY, this._store.state.scale);
1465
+ this._core.store.setState('pointerX', (xRelativeToHost - this._core.store.state.translateX) / this._core.store.state.scale);
1466
+ this._core.store.setState('pointerY', (yRelativeToHost - this._core.store.state.translateY) / this._core.store.state.scale);
1467
+ if (this._core.store.state.isPanning) {
1468
+ const dx = xRelativeToHost - this._core.store.state.startX;
1469
+ const dy = yRelativeToHost - this._core.store.state.startY;
1470
+ this._core.store.setState('translateX', this._core.store.state.translateX + dx);
1471
+ this._core.store.setState('translateY', this._core.store.state.translateY + dy);
1472
+ this._core.store.setState('startX', xRelativeToHost);
1473
+ this._core.store.setState('startY', yRelativeToHost);
1474
+ this._core.store.setState('hasViewportChanged', true);
1475
+ this._core.store.setState('skipContextMenu', true);
1476
+ this._core.rerender();
1477
+ this._core.updateWorkspaceViewport(this._core.store.state.translateX, this._core.store.state.translateY, this._core.store.state.scale);
1474
1478
  }
1475
1479
  }
1476
1480
  if (event.pointerType === 'touch') {
1477
- const hostRect = this._store.state.host.getBoundingClientRect();
1481
+ const hostRect = this._core.store.state.host.getBoundingClientRect();
1478
1482
  const xRelativeToHost = event.clientX - hostRect.left;
1479
1483
  const yRelativeToHost = event.clientY - hostRect.top;
1480
- this._store.state.pointerX = (xRelativeToHost - this._store.state.translateX) / this._store.state.scale;
1481
- this._store.state.pointerY = (yRelativeToHost - this._store.state.translateY) / this._store.state.scale;
1482
- const activePointers = Array.from(this._store.state.pointers.values());
1484
+ this._core.store.setState('pointerX', (xRelativeToHost - this._core.store.state.translateX) / this._core.store.state.scale);
1485
+ this._core.store.setState('pointerY', (yRelativeToHost - this._core.store.state.translateY) / this._core.store.state.scale);
1486
+ const activePointers = Array.from(this._core.store.state.pointers.values());
1483
1487
  if (activePointers.length === 2) {
1484
- const firstTouchX = activePointers[0].clientX - this._store.offsetX;
1485
- const firstTouchY = activePointers[0].clientY - this._store.offsetY;
1486
- const secondTouchX = activePointers[1].clientX - this._store.offsetX;
1487
- const secondTouchY = activePointers[1].clientY - this._store.offsetY;
1488
+ const firstTouchX = activePointers[0].clientX - this._core.store.offsetX;
1489
+ const firstTouchY = activePointers[0].clientY - this._core.store.offsetY;
1490
+ const secondTouchX = activePointers[1].clientX - this._core.store.offsetX;
1491
+ const secondTouchY = activePointers[1].clientY - this._core.store.offsetY;
1488
1492
  const currentTouchDistance = Math.sqrt(Math.pow(firstTouchX - secondTouchX, 2) + Math.pow(firstTouchY - secondTouchY, 2));
1489
1493
  const midpointX = (firstTouchX + secondTouchX) / 2;
1490
1494
  const midpointY = (firstTouchY + secondTouchY) / 2;
1491
1495
  const scaleRatio = currentTouchDistance / this.initialTouchDistance;
1492
- const newScale = this._store.state.scale * scaleRatio;
1493
- if (newScale > this._store.state.scaleMax || newScale < this._store.state.scaleMin) {
1494
- this._store.state.translateX += midpointX - this.startX;
1495
- this._store.state.translateY += midpointY - this.startY;
1496
+ const newScale = this._core.store.state.scale * scaleRatio;
1497
+ if (newScale > this._core.store.state.scaleMax || newScale < this._core.store.state.scaleMin) {
1498
+ this._core.store.setState('translateX', this._core.store.state.translateX + midpointX - this.startX);
1499
+ this._core.store.setState('translateY', this._core.store.state.translateY + midpointY - this.startY);
1496
1500
  }
1497
1501
  else {
1498
- const translateXAdjustment = (midpointX - this._store.state.translateX) * (scaleRatio - 1);
1499
- const translateYAdjustment = (midpointY - this._store.state.translateY) * (scaleRatio - 1);
1500
- this._store.state.translateX += midpointX - this.startX - translateXAdjustment;
1501
- this._store.state.translateY += midpointY - this.startY - translateYAdjustment;
1502
- this._store.state.scale = newScale;
1502
+ const translateXAdjustment = (midpointX - this._core.store.state.translateX) * (scaleRatio - 1);
1503
+ const translateYAdjustment = (midpointY - this._core.store.state.translateY) * (scaleRatio - 1);
1504
+ this._core.store.setState('translateX', this._core.store.state.translateX + midpointX - this.startX - translateXAdjustment);
1505
+ this._core.store.setState('translateY', this._core.store.state.translateY + midpointY - this.startY - translateYAdjustment);
1506
+ this._core.store.setState('scale', newScale);
1503
1507
  this.initialTouchDistance = currentTouchDistance;
1504
1508
  }
1505
1509
  this.startX = midpointX;
1506
1510
  this.startY = midpointY;
1507
- this._store.state.hasViewportChanged = true;
1508
- this._store.rerender();
1509
- this._store.updateWorkspaceViewport(this._store.state.translateX, this._store.state.translateY, this._store.state.scale);
1511
+ this._core.store.setState('hasViewportChanged', true);
1512
+ this._core.rerender();
1513
+ this._core.updateWorkspaceViewport(this._core.store.state.translateX, this._core.store.state.translateY, this._core.store.state.scale);
1510
1514
  }
1511
1515
  }
1512
1516
  }
1513
1517
  handlePointerUp(event) {
1514
1518
  if (event.pointerType === 'mouse') {
1515
- if (this._store.state.isPanning) {
1516
- this._store.state.isPanning = false;
1517
- this._store.rerender();
1519
+ if (this._core.store.state.isPanning) {
1520
+ this._core.store.setState('isPanning', false);
1521
+ this._core.rerender();
1518
1522
  }
1519
1523
  }
1520
1524
  if (event.pointerType === 'touch') {
1521
- this._store.state.isScaling = false;
1522
- this._store.rerender();
1525
+ this._core.store.setState('isScaling', false);
1526
+ this._core.rerender();
1523
1527
  }
1524
1528
  }
1525
1529
  handleWheel(event) {
@@ -1532,188 +1536,166 @@ class KritzelViewport {
1532
1536
  }
1533
1537
  }
1534
1538
  handleZoom(event) {
1535
- const rect = this._store.state.host.getBoundingClientRect();
1539
+ this._core.store.setState('isScaling', true);
1540
+ const rect = this._core.store.state.host.getBoundingClientRect();
1536
1541
  const xRelativeToHost = event.clientX - rect.left;
1537
1542
  const yRelativeToHost = event.clientY - rect.top;
1538
- this._store.state.pointerX = (xRelativeToHost - this._store.state.translateX) / this._store.state.scale;
1539
- this._store.state.pointerY = (yRelativeToHost - this._store.state.translateY) / this._store.state.scale;
1540
- const delta = event.deltaY > 0 ? -this._store.state.scaleStep * this._store.state.scale : this._store.state.scaleStep * this._store.state.scale;
1541
- const newScale = Math.min(this._store.state.scaleMax, Math.max(this._store.state.scaleMin, this._store.state.scale + delta));
1542
- const scaleRatio = newScale / this._store.state.scale;
1543
- const translateXAdjustment = (xRelativeToHost - this._store.state.translateX) * (scaleRatio - 1);
1544
- const translateYAdjustment = (yRelativeToHost - this._store.state.translateY) * (scaleRatio - 1);
1545
- this._store.state.scale = newScale;
1546
- this._store.state.translateX -= translateXAdjustment;
1547
- this._store.state.translateY -= translateYAdjustment;
1548
- this._store.state.hasViewportChanged = true;
1549
- this._store.rerender();
1550
- this._store.updateWorkspaceViewport(this._store.state.translateX, this._store.state.translateY, this._store.state.scale);
1543
+ this._core.store.setState('pointerX', (xRelativeToHost - this._core.store.state.translateX) / this._core.store.state.scale);
1544
+ this._core.store.setState('pointerY', (yRelativeToHost - this._core.store.state.translateY) / this._core.store.state.scale);
1545
+ const delta = event.deltaY > 0 ? -this._core.store.state.scaleStep * this._core.store.state.scale : this._core.store.state.scaleStep * this._core.store.state.scale;
1546
+ const newScale = Math.min(this._core.store.state.scaleMax, Math.max(this._core.store.state.scaleMin, this._core.store.state.scale + delta));
1547
+ const scaleRatio = newScale / this._core.store.state.scale;
1548
+ const translateXAdjustment = (xRelativeToHost - this._core.store.state.translateX) * (scaleRatio - 1);
1549
+ const translateYAdjustment = (yRelativeToHost - this._core.store.state.translateY) * (scaleRatio - 1);
1550
+ this._core.store.setState('scale', newScale);
1551
+ this._core.store.setState('translateX', this._core.store.state.translateX - translateXAdjustment);
1552
+ this._core.store.setState('translateY', this._core.store.state.translateY - translateYAdjustment);
1553
+ this._core.store.setState('hasViewportChanged', true);
1554
+ this._core.rerender();
1555
+ this._core.updateWorkspaceViewport(this._core.store.state.translateX, this._core.store.state.translateY, this._core.store.state.scale);
1556
+ setTimeout(() => {
1557
+ this._core.store.setState('isScaling', false);
1558
+ this._core.rerender();
1559
+ }, 300);
1551
1560
  }
1552
1561
  handlePan(event) {
1562
+ this._core.store.setState('isPanning', true);
1553
1563
  const panSpeed = 0.8;
1554
- this._store.state.translateX -= event.deltaX * panSpeed;
1555
- this._store.state.translateY -= event.deltaY * panSpeed;
1556
- this._store.state.hasViewportChanged = true;
1557
- this._store.rerender();
1558
- this._store.updateWorkspaceViewport(this._store.state.translateX, this._store.state.translateY, this._store.state.scale);
1559
- }
1560
- }
1561
-
1562
- class UpdateViewportCommand extends KritzelBaseCommand {
1563
- currentViewport;
1564
- previousViewport;
1565
- constructor(store, initiator, previousViewport, skipHistory = false) {
1566
- super(store, initiator, skipHistory);
1567
- this.previousViewport = previousViewport;
1568
- this.currentViewport = {
1569
- scale: this._store.state.scale,
1570
- translateX: this._store.state.translateX,
1571
- translateY: this._store.state.translateY,
1572
- };
1573
- }
1574
- execute() {
1575
- this._store.state.scale = this.currentViewport.scale;
1576
- this._store.state.translateX = this.currentViewport.translateX;
1577
- this._store.state.translateY = this.currentViewport.translateY;
1578
- }
1579
- undo() {
1580
- this._store.state.scale = this.previousViewport.scale;
1581
- this._store.state.translateX = this.previousViewport.translateX;
1582
- this._store.state.translateY = this.previousViewport.translateY;
1564
+ this._core.store.setState('translateX', this._core.store.state.translateX - event.deltaX * panSpeed);
1565
+ this._core.store.setState('translateY', this._core.store.state.translateY - event.deltaY * panSpeed);
1566
+ this._core.store.setState('hasViewportChanged', true);
1567
+ this._core.rerender();
1568
+ this._core.updateWorkspaceViewport(this._core.store.state.translateX, this._core.store.state.translateY, this._core.store.state.scale);
1569
+ setTimeout(() => {
1570
+ this._core.store.setState('isPanning', false);
1571
+ this._core.rerender();
1572
+ }, 300);
1583
1573
  }
1584
1574
  }
1585
1575
 
1586
- class KritzelCircularBuffer {
1587
- buffer;
1588
- capacity;
1589
- head = 0;
1590
- tail = 0;
1591
- size = 0;
1592
- constructor(capacity) {
1593
- this.capacity = capacity;
1594
- this.buffer = new Array(capacity).fill(null);
1576
+ class KritzelKeyHandler extends KritzelBaseHandler {
1577
+ constructor(core) {
1578
+ super(core);
1595
1579
  }
1596
- add(item) {
1597
- this.buffer[this.head] = item;
1598
- this.head = (this.head + 1) % this.capacity;
1599
- if (this.size < this.capacity) {
1600
- this.size++;
1580
+ handleKeyDown(event) {
1581
+ this._core.store.setState('isCtrlKeyPressed', event.ctrlKey);
1582
+ if (this._core.store.state.isCtrlKeyPressed) {
1583
+ event.preventDefault();
1601
1584
  }
1602
- else {
1603
- this.tail = (this.tail + 1) % this.capacity;
1585
+ if (event.key === 'Escape' && this._core.store.state.selectionGroup) {
1586
+ this._core.clearSelection();
1604
1587
  }
1605
- }
1606
- pop() {
1607
- if (this.size === 0) {
1608
- return null;
1588
+ if (event.key === 'Delete' && this._core.store.state.selectionGroup) {
1589
+ this._core.delete();
1609
1590
  }
1610
- this.head = (this.head - 1 + this.capacity) % this.capacity;
1611
- const item = this.buffer[this.head];
1612
- this.buffer[this.head] = null;
1613
- this.size--;
1614
- return item;
1615
- }
1616
- peek() {
1617
- if (this.size === 0) {
1618
- return null;
1591
+ if (event.key === 'z' && event.ctrlKey) {
1592
+ this._core.history.undo();
1593
+ }
1594
+ if (event.key === 'y' && event.ctrlKey) {
1595
+ this._core.history.redo();
1596
+ }
1597
+ if (event.key === 's' && event.ctrlKey) {
1598
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
1599
+ this._core.deselectAllObjects();
1600
+ }
1601
+ if (event.key === 'b' && event.ctrlKey) {
1602
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('brush'));
1603
+ this._core.deselectAllObjects();
1604
+ }
1605
+ if (event.key === 'e' && event.ctrlKey) {
1606
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('eraser'));
1607
+ this._core.deselectAllObjects();
1608
+ }
1609
+ if (event.key === 'i' && event.ctrlKey) {
1610
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('image'));
1611
+ this._core.deselectAllObjects();
1612
+ }
1613
+ if (event.key === 'x' && event.ctrlKey) {
1614
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('text'));
1615
+ this._core.deselectAllObjects();
1616
+ }
1617
+ if (event.key === 'c' && event.ctrlKey && this._core.store.state.selectionGroup) {
1618
+ this._core.copy();
1619
+ this._core.rerender();
1620
+ }
1621
+ if (event.key === 'v' && event.ctrlKey && this._core.store.state.copiedObjects) {
1622
+ this._core.paste();
1623
+ }
1624
+ if (event.key === '+' && event.ctrlKey && this._core.store.state.selectionGroup) {
1625
+ this._core.bringForward();
1626
+ }
1627
+ if (event.key === '-' && event.ctrlKey && this._core.store.state.selectionGroup) {
1628
+ this._core.sendBackward();
1629
+ }
1630
+ if (event.key === '*' && event.shiftKey && this._core.store.state.selectionGroup) {
1631
+ this._core.bringToFront();
1632
+ }
1633
+ if (event.key === '_' && event.shiftKey && this._core.store.state.selectionGroup) {
1634
+ this._core.sendToBack();
1635
+ }
1636
+ if (event.key === 'a' && event.ctrlKey && this._core.store.state.activeText) {
1637
+ this._core.store.state.activeText.selectAll();
1638
+ }
1639
+ if (event.key === 'v' && event.ctrlKey && this._core.store.state.activeText) {
1640
+ this._core.store.state.activeText.insertFromClipboard();
1619
1641
  }
1620
- const lastIndex = (this.head - 1 + this.capacity) % this.capacity;
1621
- return this.buffer[lastIndex];
1622
- }
1623
- isEmpty() {
1624
- return this.size === 0;
1625
1642
  }
1626
- clear() {
1627
- this.buffer.fill(null);
1628
- this.head = 0;
1629
- this.tail = 0;
1630
- this.size = 0;
1643
+ handleKeyUp(event) {
1644
+ this._core.store.setState('isCtrlKeyPressed', event.ctrlKey);
1631
1645
  }
1632
1646
  }
1633
1647
 
1634
- class KritzelHistory {
1635
- _store;
1636
- undoStack;
1637
- redoStack;
1638
- previousViewport;
1639
- constructor(store) {
1640
- this._store = store;
1641
- this.undoStack = new KritzelCircularBuffer(this._store.state.historyBufferSize);
1642
- this.redoStack = new KritzelCircularBuffer(this._store.state.historyBufferSize);
1643
- this.previousViewport = {
1644
- scale: this._store.state.scale,
1645
- scaleStep: this._store.state.scaleStep,
1646
- translateX: this._store.state.translateX,
1647
- translateY: this._store.state.translateY,
1648
- };
1649
- }
1650
- reset() {
1651
- this.undoStack.clear();
1652
- this.redoStack.clear();
1653
- this.previousViewport = {
1654
- scale: this._store.state.scale,
1655
- scaleStep: this._store.state.scaleStep,
1656
- translateX: this._store.state.translateX,
1657
- translateY: this._store.state.translateY
1658
- };
1648
+ class KritzelContextMenuHandler extends KritzelBaseHandler {
1649
+ globalContextMenuItems = [];
1650
+ objectContextMenuItems = [];
1651
+ constructor(core, globalContextMenuItems, objectContextMenuItems) {
1652
+ super(core);
1653
+ this.globalContextMenuItems = globalContextMenuItems;
1654
+ this.objectContextMenuItems = objectContextMenuItems;
1659
1655
  }
1660
- executeCommand(command) {
1661
- if (this._store.state.hasViewportChanged) {
1662
- this.addUpdateViewportCommand();
1663
- }
1664
- command.execute();
1665
- if (command.skipHistory === false) {
1666
- if (this._store.state.debugInfo.logCommands) {
1667
- console.info('add', command);
1668
- }
1669
- this.undoStack.add(command);
1670
- if (this.redoStack.isEmpty() === false) {
1671
- this.redoStack.clear();
1672
- }
1656
+ handleContextMenu(event) {
1657
+ if (!(this._core.store.state.activeTool instanceof KritzelSelectionTool)) {
1658
+ return;
1673
1659
  }
1674
- this._store.rerender();
1675
- }
1676
- undo() {
1677
- if (this._store.state.hasViewportChanged) {
1678
- const command = new UpdateViewportCommand(this._store, this, this.previousViewport);
1679
- command.undo();
1680
- this._store.state.hasViewportChanged = false;
1681
- this._store.rerender();
1660
+ if (this._core.store.state.skipContextMenu) {
1661
+ this._core.store.setState('skipContextMenu', false);
1682
1662
  return;
1683
1663
  }
1684
- const command = this.undoStack.pop();
1685
- if (command) {
1686
- command.undo();
1687
- if (this._store.state.debugInfo.logCommands)
1688
- console.info('undo', command);
1689
- this.redoStack.add(command);
1664
+ const selectedObject = this._core.getObjectFromPointerEvent(event, '.object');
1665
+ if (selectedObject && !(selectedObject instanceof KritzelSelectionGroup)) {
1666
+ const selectionGroup = KritzelSelectionGroup.create(this._core);
1667
+ selectionGroup.addOrRemove(selectedObject);
1668
+ selectionGroup.isSelected = true;
1669
+ selectionGroup.rotation = selectedObject.rotation;
1670
+ this._core.store.setState('selectionGroup', selectionGroup);
1671
+ this._core.store.setState('isSelecting', false);
1672
+ this._core.history.executeCommand(new AddSelectionGroupCommand(this._core, this, this._core.store.state.selectionGroup));
1673
+ }
1674
+ this._core.store.setState('contextMenuItems', this._core.store.state.selectionGroup ? this.objectContextMenuItems : this.globalContextMenuItems);
1675
+ let x = event.clientX - this._core.store.offsetX;
1676
+ let y = event.clientY - this._core.store.offsetY;
1677
+ const menuWidthEstimate = 150;
1678
+ const menuHeightEstimate = 200;
1679
+ const margin = 10;
1680
+ if (x + menuWidthEstimate > window.innerWidth - margin) {
1681
+ x = window.innerWidth - menuWidthEstimate - margin;
1690
1682
  }
1691
- this._store.rerender();
1692
- }
1693
- redo() {
1694
- const command = this.redoStack.pop();
1695
- if (command) {
1696
- command.execute();
1697
- if (this._store.state.debugInfo.logCommands)
1698
- console.info('redo', command);
1699
- this.undoStack.add(command);
1683
+ if (y + menuHeightEstimate > window.innerHeight - margin) {
1684
+ y = window.innerHeight - menuHeightEstimate - margin;
1700
1685
  }
1701
- this._store.rerender();
1686
+ x = Math.max(margin, x);
1687
+ y = Math.max(margin, y);
1688
+ this._core.store.setState('contextMenuX', x);
1689
+ this._core.store.setState('contextMenuY', y);
1690
+ this._core.store.setState('isContextMenuVisible', true);
1691
+ this._core.store.setState('isEnabled', false);
1692
+ this._core.rerender();
1702
1693
  }
1703
- addUpdateViewportCommand() {
1704
- const command = new UpdateViewportCommand(this._store, this, this.previousViewport);
1705
- command.execute();
1706
- this.undoStack.add(command);
1707
- if (this.redoStack.isEmpty() === false) {
1708
- this.redoStack.clear();
1709
- }
1710
- this._store.state.hasViewportChanged = false;
1711
- this.previousViewport = {
1712
- scale: this._store.state.scale,
1713
- scaleStep: this._store.state.scaleStep,
1714
- translateX: this._store.state.translateX,
1715
- translateY: this._store.state.translateY,
1716
- };
1694
+ }
1695
+
1696
+ class KritzelClassHelper {
1697
+ static isInstanceOf(object, className) {
1698
+ return !!object && object.__class__ === className;
1717
1699
  }
1718
1700
  }
1719
1701
 
@@ -1732,7 +1714,6 @@ const DEFAULT_ENGINE_STATE = {
1732
1714
  isEnabled: true,
1733
1715
  isScaling: false,
1734
1716
  isPanning: false,
1735
- isFocused: false,
1736
1717
  isSelecting: false,
1737
1718
  isResizing: false,
1738
1719
  isResizeHandleSelected: false,
@@ -1795,7 +1776,7 @@ class KritzelDatabase {
1795
1776
  return;
1796
1777
  }
1797
1778
  if (this.isLoggingEnabled) {
1798
- console.log(`[IndexedDB] Opening database: ${this.dbName}, version: ${this.dbVersion}`);
1779
+ console.info(`[IndexedDB] Opening database: ${this.dbName}, version: ${this.dbVersion}`);
1799
1780
  }
1800
1781
  const request = indexedDB.open(this.dbName, this.dbVersion);
1801
1782
  request.onerror = () => {
@@ -1805,25 +1786,25 @@ class KritzelDatabase {
1805
1786
  request.onsuccess = () => {
1806
1787
  this.db = request.result;
1807
1788
  if (this.isLoggingEnabled) {
1808
- console.log(`[IndexedDB] Database opened successfully.`);
1789
+ console.info(`[IndexedDB] Database opened successfully.`);
1809
1790
  }
1810
1791
  resolve();
1811
1792
  };
1812
1793
  request.onupgradeneeded = event => {
1813
1794
  if (this.isLoggingEnabled) {
1814
- console.log(`[IndexedDB] Upgrade needed for database: ${this.dbName}`);
1795
+ console.info(`[IndexedDB] Upgrade needed for database: ${this.dbName}`);
1815
1796
  }
1816
1797
  const db = event.target.result;
1817
1798
  stores.forEach(storeConfig => {
1818
1799
  if (!db.objectStoreNames.contains(storeConfig.name)) {
1819
1800
  if (this.isLoggingEnabled) {
1820
- console.log(`[IndexedDB] Creating store: ${storeConfig.name}`);
1801
+ console.info(`[IndexedDB] Creating store: ${storeConfig.name}`);
1821
1802
  }
1822
1803
  const store = db.createObjectStore(storeConfig.name, storeConfig.options);
1823
1804
  if (storeConfig.indices) {
1824
1805
  storeConfig.indices.forEach(index => {
1825
1806
  if (this.isLoggingEnabled) {
1826
- console.log(`[IndexedDB] Creating index: ${index.name} on store: ${storeConfig.name}`);
1807
+ console.info(`[IndexedDB] Creating index: ${index.name} on store: ${storeConfig.name}`);
1827
1808
  }
1828
1809
  store.createIndex(index.name, index.keyPath, index.options);
1829
1810
  });
@@ -1836,7 +1817,7 @@ class KritzelDatabase {
1836
1817
  close() {
1837
1818
  if (this.db) {
1838
1819
  if (this.isLoggingEnabled) {
1839
- console.log(`[IndexedDB] Closing database: ${this.dbName}`);
1820
+ console.info(`[IndexedDB] Closing database: ${this.dbName}`);
1840
1821
  }
1841
1822
  this.db.close();
1842
1823
  this.db = null;
@@ -1844,43 +1825,51 @@ class KritzelDatabase {
1844
1825
  }
1845
1826
  async add(storeName, item) {
1846
1827
  if (this.isLoggingEnabled) {
1847
- console.log('[IndexedDB] Add:', { storeName, item });
1828
+ console.info('[IndexedDB] Add:', { storeName, item });
1848
1829
  }
1849
- return this.executeTransaction(storeName, 'readwrite', store => store.add(item));
1830
+ if (item.serialize === undefined) {
1831
+ throw new Error('Item does not implement KritzelSerializable interface.');
1832
+ }
1833
+ const serializedItem = item.serialize();
1834
+ return this.executeTransaction(storeName, 'readwrite', store => store.add(serializedItem));
1850
1835
  }
1851
1836
  async get(storeName, key) {
1852
1837
  if (this.isLoggingEnabled) {
1853
- console.log('[IndexedDB] Get:', { storeName, key });
1838
+ console.info('[IndexedDB] Get:', { storeName, key });
1854
1839
  }
1855
1840
  return this.executeTransaction(storeName, 'readonly', store => store.get(key));
1856
1841
  }
1857
1842
  async getAll(storeName) {
1858
1843
  if (this.isLoggingEnabled) {
1859
- console.log('[IndexedDB] GetAll:', { storeName });
1844
+ console.info('[IndexedDB] GetAll:', { storeName });
1860
1845
  }
1861
1846
  return this.executeTransaction(storeName, 'readonly', store => store.getAll());
1862
1847
  }
1863
1848
  async update(storeName, item) {
1864
1849
  if (this.isLoggingEnabled) {
1865
- console.log('[IndexedDB] Update:', { storeName, item });
1850
+ console.info('[IndexedDB] Update:', { storeName, item });
1851
+ }
1852
+ if (item.serialize === undefined) {
1853
+ throw new Error('Item does not implement KritzelSerializable interface.');
1866
1854
  }
1867
- return this.executeTransaction(storeName, 'readwrite', store => store.put(item));
1855
+ const serializedItem = item.serialize();
1856
+ return this.executeTransaction(storeName, 'readwrite', store => store.put(serializedItem));
1868
1857
  }
1869
1858
  async delete(storeName, key) {
1870
1859
  if (this.isLoggingEnabled) {
1871
- console.log('[IndexedDB] Delete:', { storeName, key });
1860
+ console.info('[IndexedDB] Delete:', { storeName, key });
1872
1861
  }
1873
1862
  return this.executeTransaction(storeName, 'readwrite', store => store.delete(key));
1874
1863
  }
1875
1864
  async deleteByRange(storeName, range) {
1876
1865
  if (this.isLoggingEnabled) {
1877
- console.log('[IndexedDB] DeleteByRange:', { storeName, range });
1866
+ console.info('[IndexedDB] DeleteByRange:', { storeName, range });
1878
1867
  }
1879
1868
  return this.executeTransaction(storeName, 'readwrite', store => store.delete(range));
1880
1869
  }
1881
1870
  async getAllByRange(storeName, range) {
1882
1871
  if (this.isLoggingEnabled) {
1883
- console.log('[IndexedDB] GetAllByRange:', { storeName, range });
1872
+ console.info('[IndexedDB] GetAllByRange:', { storeName, range });
1884
1873
  }
1885
1874
  return this.executeTransaction(storeName, 'readonly', store => {
1886
1875
  return store.getAll(range);
@@ -1888,7 +1877,7 @@ class KritzelDatabase {
1888
1877
  }
1889
1878
  async getAllByIndex(storeName, indexName, query) {
1890
1879
  if (this.isLoggingEnabled) {
1891
- console.log('[IndexedDB] GetAllByIndex:', { storeName, indexName, query });
1880
+ console.info('[IndexedDB] GetAllByIndex:', { storeName, indexName, query });
1892
1881
  }
1893
1882
  return this.executeTransaction(storeName, 'readonly', store => {
1894
1883
  const index = store.index(indexName);
@@ -1924,7 +1913,7 @@ class KritzelDatabase {
1924
1913
  }
1925
1914
  const storeNames = await this.extractStoreNamesFromActions(actions);
1926
1915
  if (this.isLoggingEnabled) {
1927
- console.log('[IndexedDB] Starting batch transaction:', { storeNames });
1916
+ console.info('[IndexedDB] Starting batch transaction:', { storeNames });
1928
1917
  }
1929
1918
  return new Promise((resolve, reject) => {
1930
1919
  const transaction = this.db.transaction(storeNames, 'readwrite');
@@ -1942,13 +1931,13 @@ class KritzelDatabase {
1942
1931
  executeTransaction: (storeName, mode, action) => {
1943
1932
  return new Promise((resolveRequest, rejectRequest) => {
1944
1933
  if (this.isLoggingEnabled) {
1945
- console.log('[IndexedDB] Executing batch action:', { storeName, mode });
1934
+ console.info('[IndexedDB] Executing batch action:', { storeName, mode });
1946
1935
  }
1947
1936
  const store = transaction.objectStore(storeName);
1948
1937
  const request = action(store);
1949
1938
  request.onsuccess = () => {
1950
1939
  if (this.isLoggingEnabled) {
1951
- console.log('[IndexedDB] Batch action request successful:', { result: request.result });
1940
+ console.info('[IndexedDB] Batch action request successful:', { result: request.result });
1952
1941
  }
1953
1942
  resolveRequest(request.result);
1954
1943
  };
@@ -1961,7 +1950,7 @@ class KritzelDatabase {
1961
1950
  };
1962
1951
  transaction.oncomplete = () => {
1963
1952
  if (this.isLoggingEnabled) {
1964
- console.log('[IndexedDB] Batch transaction complete.');
1953
+ console.info('[IndexedDB] Batch transaction complete.');
1965
1954
  }
1966
1955
  Promise.all(promises).then(() => resolve(results));
1967
1956
  };
@@ -2006,6 +1995,164 @@ class KritzelDatabase {
2006
1995
  }
2007
1996
  }
2008
1997
 
1998
+ class UpdateViewportCommand extends KritzelBaseCommand {
1999
+ currentViewport;
2000
+ previousViewport;
2001
+ constructor(core, initiator, previousViewport, skipHistory = false) {
2002
+ super(core, initiator, skipHistory);
2003
+ this.previousViewport = previousViewport;
2004
+ this.currentViewport = {
2005
+ scale: this._core.store.state.scale,
2006
+ translateX: this._core.store.state.translateX,
2007
+ translateY: this._core.store.state.translateY,
2008
+ };
2009
+ }
2010
+ execute() {
2011
+ this._core.store.setState('scale', this.currentViewport.scale);
2012
+ this._core.store.setState('translateX', this.currentViewport.translateX);
2013
+ this._core.store.setState('translateY', this.currentViewport.translateY);
2014
+ }
2015
+ undo() {
2016
+ this._core.store.setState('scale', this.previousViewport.scale);
2017
+ this._core.store.setState('translateX', this.previousViewport.translateX);
2018
+ this._core.store.setState('translateY', this.previousViewport.translateY);
2019
+ }
2020
+ }
2021
+
2022
+ class KritzelCircularBuffer {
2023
+ buffer;
2024
+ capacity;
2025
+ head = 0;
2026
+ tail = 0;
2027
+ size = 0;
2028
+ constructor(capacity) {
2029
+ this.capacity = capacity;
2030
+ this.buffer = new Array(capacity).fill(null);
2031
+ }
2032
+ add(item) {
2033
+ this.buffer[this.head] = item;
2034
+ this.head = (this.head + 1) % this.capacity;
2035
+ if (this.size < this.capacity) {
2036
+ this.size++;
2037
+ }
2038
+ else {
2039
+ this.tail = (this.tail + 1) % this.capacity;
2040
+ }
2041
+ }
2042
+ pop() {
2043
+ if (this.size === 0) {
2044
+ return null;
2045
+ }
2046
+ this.head = (this.head - 1 + this.capacity) % this.capacity;
2047
+ const item = this.buffer[this.head];
2048
+ this.buffer[this.head] = null;
2049
+ this.size--;
2050
+ return item;
2051
+ }
2052
+ peek() {
2053
+ if (this.size === 0) {
2054
+ return null;
2055
+ }
2056
+ const lastIndex = (this.head - 1 + this.capacity) % this.capacity;
2057
+ return this.buffer[lastIndex];
2058
+ }
2059
+ isEmpty() {
2060
+ return this.size === 0;
2061
+ }
2062
+ clear() {
2063
+ this.buffer.fill(null);
2064
+ this.head = 0;
2065
+ this.tail = 0;
2066
+ this.size = 0;
2067
+ }
2068
+ }
2069
+
2070
+ class KritzelHistory {
2071
+ _core;
2072
+ undoStack;
2073
+ redoStack;
2074
+ previousViewport;
2075
+ constructor(core) {
2076
+ this._core = core;
2077
+ this.undoStack = new KritzelCircularBuffer(this._core.store.state.historyBufferSize);
2078
+ this.redoStack = new KritzelCircularBuffer(this._core.store.state.historyBufferSize);
2079
+ this.previousViewport = {
2080
+ scale: this._core.store.state.scale,
2081
+ scaleStep: this._core.store.state.scaleStep,
2082
+ translateX: this._core.store.state.translateX,
2083
+ translateY: this._core.store.state.translateY,
2084
+ };
2085
+ }
2086
+ reset() {
2087
+ this.undoStack.clear();
2088
+ this.redoStack.clear();
2089
+ this.previousViewport = {
2090
+ scale: this._core.store.state.scale,
2091
+ scaleStep: this._core.store.state.scaleStep,
2092
+ translateX: this._core.store.state.translateX,
2093
+ translateY: this._core.store.state.translateY
2094
+ };
2095
+ }
2096
+ executeCommand(command) {
2097
+ if (this._core.store.state.hasViewportChanged) {
2098
+ this.addUpdateViewportCommand();
2099
+ }
2100
+ command.execute();
2101
+ if (command.skipHistory === false) {
2102
+ if (this._core.store.state.debugInfo.logCommands) {
2103
+ console.info('add', command);
2104
+ }
2105
+ this.undoStack.add(command);
2106
+ if (this.redoStack.isEmpty() === false) {
2107
+ this.redoStack.clear();
2108
+ }
2109
+ }
2110
+ this._core.rerender();
2111
+ }
2112
+ undo() {
2113
+ if (this._core.store.state.hasViewportChanged) {
2114
+ const command = new UpdateViewportCommand(this._core, this, this.previousViewport);
2115
+ command.undo();
2116
+ this._core.store.setState('hasViewportChanged', false);
2117
+ this._core.rerender();
2118
+ return;
2119
+ }
2120
+ const command = this.undoStack.pop();
2121
+ if (command) {
2122
+ command.undo();
2123
+ if (this._core.store.state.debugInfo.logCommands)
2124
+ console.info('undo', command);
2125
+ this.redoStack.add(command);
2126
+ }
2127
+ this._core.rerender();
2128
+ }
2129
+ redo() {
2130
+ const command = this.redoStack.pop();
2131
+ if (command) {
2132
+ command.execute();
2133
+ if (this._core.store.state.debugInfo.logCommands)
2134
+ console.info('redo', command);
2135
+ this.undoStack.add(command);
2136
+ }
2137
+ this._core.rerender();
2138
+ }
2139
+ addUpdateViewportCommand() {
2140
+ const command = new UpdateViewportCommand(this._core, this, this.previousViewport);
2141
+ command.execute();
2142
+ this.undoStack.add(command);
2143
+ if (this.redoStack.isEmpty() === false) {
2144
+ this.redoStack.clear();
2145
+ }
2146
+ this._core.store.setState('hasViewportChanged', false);
2147
+ this.previousViewport = {
2148
+ scale: this._core.store.state.scale,
2149
+ scaleStep: this._core.store.state.scaleStep,
2150
+ translateX: this._core.store.state.translateX,
2151
+ translateY: this._core.store.state.translateY,
2152
+ };
2153
+ }
2154
+ }
2155
+
2009
2156
  class KritzelObjectMap {
2010
2157
  map;
2011
2158
  constructor() {
@@ -2050,18 +2197,8 @@ class KritzelObjectMap {
2050
2197
  }
2051
2198
 
2052
2199
  class KritzelStore {
2053
- _kritzelEngine;
2054
2200
  _state;
2055
- _history;
2056
- _database;
2057
2201
  _listeners = new Map();
2058
- objects = [];
2059
- get history() {
2060
- return this._history;
2061
- }
2062
- get database() {
2063
- return this._database;
2064
- }
2065
2202
  get state() {
2066
2203
  return this._state;
2067
2204
  }
@@ -2083,12 +2220,52 @@ class KritzelStore {
2083
2220
  get isDisabled() {
2084
2221
  return this._state.isEnabled === false || this._state.isReady === false || this._state.activeWorkspace === null;
2085
2222
  }
2223
+ constructor(state) {
2224
+ this._state = state;
2225
+ this._state.objectsMap = new KritzelObjectMap();
2226
+ }
2227
+ onStateChange(property, listener) {
2228
+ if (!this._listeners.has(property)) {
2229
+ this._listeners.set(property, new Set());
2230
+ }
2231
+ this._listeners.get(property).add(listener);
2232
+ }
2233
+ getState(property) {
2234
+ return this._state[property];
2235
+ }
2236
+ setState(property, value) {
2237
+ const oldValue = this._state[property];
2238
+ if (oldValue !== value) {
2239
+ this._state[property] = value;
2240
+ if (this._listeners.has(property)) {
2241
+ this._listeners.get(property).forEach(listener => listener(value, oldValue, String(property)));
2242
+ }
2243
+ }
2244
+ }
2245
+ }
2246
+
2247
+ class KritzelCore {
2248
+ _kritzelEngine;
2249
+ _store;
2250
+ _history;
2251
+ _database;
2252
+ get engine() {
2253
+ return this._kritzelEngine;
2254
+ }
2255
+ get history() {
2256
+ return this._history;
2257
+ }
2258
+ get database() {
2259
+ return this._database;
2260
+ }
2261
+ get store() {
2262
+ return this._store;
2263
+ }
2086
2264
  constructor(kritzelEngine) {
2087
- this._state = DEFAULT_ENGINE_STATE;
2088
2265
  this._kritzelEngine = kritzelEngine;
2266
+ this._store = new KritzelStore(DEFAULT_ENGINE_STATE);
2089
2267
  this._history = new KritzelHistory(this);
2090
- this._database = new KritzelDatabase('kritzelDB', 1, this._state.debugInfo.logDatabase);
2091
- this._state.objectsMap = new KritzelObjectMap();
2268
+ this._database = new KritzelDatabase('kritzelDB', 1, this._store.state.debugInfo.logDatabase);
2092
2269
  }
2093
2270
  async initializeDatabase() {
2094
2271
  await this._database.open([
@@ -2104,52 +2281,50 @@ class KritzelStore {
2104
2281
  const workspaces = await this.getWorkspaces();
2105
2282
  const mostRecentWorkspace = [...workspaces].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime())[0];
2106
2283
  const fallbackWorkspace = new KritzelWorkspace(ObjectHelper.generateUUID(), 'New Workspace');
2107
- this._state.activeWorkspace = workspace ?? mostRecentWorkspace ?? fallbackWorkspace;
2108
- const isExistingWorkspace = await this.getWorkspace(this._state.activeWorkspace.id);
2284
+ this._store.setState('activeWorkspace', workspace ?? mostRecentWorkspace ?? fallbackWorkspace);
2285
+ const isExistingWorkspace = await this.getWorkspace(this._store.state.activeWorkspace.id);
2109
2286
  if (isExistingWorkspace) {
2110
- await this.updateWorkspace(this._state.activeWorkspace);
2287
+ await this.updateWorkspace(this._store.state.activeWorkspace);
2111
2288
  }
2112
2289
  else {
2113
- await this.createWorkspace(this._state.activeWorkspace);
2290
+ await this.createWorkspace(this._store.state.activeWorkspace);
2114
2291
  }
2115
- this._state.workspaces = await this.getWorkspaces();
2116
- this.state.translateX = this._state.activeWorkspace.viewport.translateX;
2117
- this.state.translateY = this._state.activeWorkspace.viewport.translateY;
2118
- this.state.scale = this._state.activeWorkspace.viewport.scale;
2119
- await this.initializeWorkspaceObjects(this._state.activeWorkspace.id);
2292
+ this._store.setState('workspaces', await this.getWorkspaces());
2293
+ this._store.setState('translateX', this._store.state.activeWorkspace.viewport.translateX);
2294
+ this._store.setState('translateY', this._store.state.activeWorkspace.viewport.translateY);
2295
+ this._store.setState('scale', this._store.state.activeWorkspace.viewport.scale);
2296
+ await this.initializeWorkspaceObjects(this._store.state.activeWorkspace.id);
2120
2297
  }
2121
2298
  async initializeWorkspaceObjects(workspaceId) {
2122
- this._state.objectsMap.reset();
2299
+ this._store.state.objectsMap.reset();
2123
2300
  this._history.reset();
2124
2301
  const objectsFromDb = await this._database.getAllByRange('objects', IDBKeyRange.bound([workspaceId], [workspaceId, '\uffff']));
2125
2302
  const reviver = new KritzelReviver(this);
2126
2303
  objectsFromDb.forEach(element => {
2127
2304
  const revivedObject = reviver.revive(element);
2128
- this._state.objectsMap.insert(revivedObject);
2305
+ this._store.state.objectsMap.insert(revivedObject);
2129
2306
  });
2130
2307
  this.rerender();
2131
2308
  }
2132
2309
  async updateWorkspaceViewport(translateX, translateY, scale) {
2133
- if (!this.state.activeWorkspace) {
2310
+ const activeWorkspace = this._store.state.activeWorkspace;
2311
+ if (!activeWorkspace) {
2134
2312
  throw new Error('Workspace not initialized');
2135
2313
  }
2136
- this.state.activeWorkspace.viewport = {
2137
- translateX,
2138
- translateY,
2139
- scale,
2140
- };
2141
- this.state.activeWorkspace.updatedAt = new Date();
2142
- await this._database.update('workspaces', this.state.activeWorkspace);
2314
+ activeWorkspace.viewport = { translateX, translateY, scale };
2315
+ activeWorkspace.updatedAt = new Date();
2316
+ await this._database.update('workspaces', activeWorkspace);
2143
2317
  }
2144
2318
  async addObjectToDatabase(object) {
2145
2319
  if (!this._database) {
2146
2320
  throw new Error('Database not initialized');
2147
2321
  }
2148
- if (!this.state.activeWorkspace) {
2322
+ const activeWorkspace = this._store.state.activeWorkspace;
2323
+ if (!activeWorkspace) {
2149
2324
  throw new Error('Workspace not initialized');
2150
2325
  }
2151
- this.state.activeWorkspace.updatedAt = new Date();
2152
- await this._database.batch([db => db.add('objects', object), db => db.update('workspaces', this.state.activeWorkspace)]).catch(err => {
2326
+ activeWorkspace.updatedAt = new Date();
2327
+ await this._database.batch([db => db.add('objects', object), db => db.update('workspaces', activeWorkspace)]).catch(err => {
2153
2328
  console.error('Error adding object to database:', err);
2154
2329
  });
2155
2330
  }
@@ -2157,11 +2332,12 @@ class KritzelStore {
2157
2332
  if (!this._database) {
2158
2333
  throw new Error('Database not initialized');
2159
2334
  }
2160
- if (!this.state.activeWorkspace) {
2335
+ const activeWorkspace = this._store.state.activeWorkspace;
2336
+ if (!activeWorkspace) {
2161
2337
  throw new Error('Workspace not initialized');
2162
2338
  }
2163
- this.state.activeWorkspace.updatedAt = new Date();
2164
- await this._database.batch([db => db.update('objects', object), db => db.update('workspaces', this.state.activeWorkspace)]).catch(err => {
2339
+ activeWorkspace.updatedAt = new Date();
2340
+ await this._database.batch([db => db.update('objects', object), db => db.update('workspaces', activeWorkspace)]).catch(err => {
2165
2341
  console.error('Error updating object in database:', err);
2166
2342
  });
2167
2343
  }
@@ -2169,25 +2345,32 @@ class KritzelStore {
2169
2345
  if (!this._database) {
2170
2346
  throw new Error('Database not initialized');
2171
2347
  }
2172
- if (!this.state.activeWorkspace) {
2348
+ const activeWorkspace = this._store.state.activeWorkspace;
2349
+ if (!activeWorkspace) {
2173
2350
  throw new Error('Workspace not initialized');
2174
2351
  }
2175
- this.state.activeWorkspace.updatedAt = new Date();
2176
- await this._database.batch([db => db.delete('objects', [this.state.activeWorkspace.id, objectId]), db => db.update('workspaces', this.state.activeWorkspace)]).catch(err => {
2352
+ activeWorkspace.updatedAt = new Date();
2353
+ await this._database.batch([db => db.delete('objects', [activeWorkspace.id, objectId]), db => db.update('workspaces', activeWorkspace)]).catch(err => {
2177
2354
  console.error('Error deleting object from database:', err);
2178
2355
  });
2179
2356
  }
2180
- getWorkspace(id) {
2357
+ async getWorkspace(id) {
2181
2358
  if (!this._database) {
2182
2359
  throw new Error('Database not initialized');
2183
2360
  }
2184
- return this._database.get('workspaces', id);
2361
+ const reviver = new KritzelReviver(this);
2362
+ return this._database
2363
+ .get('workspaces', id)
2364
+ .then(rawWorkspace => rawWorkspace ? reviver.revive(rawWorkspace) : null);
2185
2365
  }
2186
- getWorkspaces() {
2366
+ async getWorkspaces() {
2187
2367
  if (!this._database) {
2188
2368
  throw new Error('Database not initialized');
2189
2369
  }
2190
- return this._database.getAll('workspaces');
2370
+ const reviver = new KritzelReviver(this);
2371
+ return this._database
2372
+ .getAll('workspaces')
2373
+ .then(rawWorkspaces => rawWorkspaces.map(ws => reviver.revive(ws)));
2191
2374
  }
2192
2375
  async createWorkspace(workspace) {
2193
2376
  if (!this._database) {
@@ -2196,7 +2379,7 @@ class KritzelStore {
2196
2379
  workspace.createdAt = new Date();
2197
2380
  workspace.updatedAt = new Date();
2198
2381
  await this._database.add('workspaces', workspace);
2199
- this.state.workspaces.push(workspace);
2382
+ this._store.state.workspaces.push(workspace);
2200
2383
  }
2201
2384
  async updateWorkspace(workspace) {
2202
2385
  if (!this._database) {
@@ -2204,9 +2387,11 @@ class KritzelStore {
2204
2387
  }
2205
2388
  workspace.updatedAt = new Date();
2206
2389
  await this._database.update('workspaces', workspace);
2207
- const index = this.state.workspaces.findIndex(w => w.id === workspace.id);
2390
+ const workspaces = this._store.state.workspaces;
2391
+ const index = workspaces.findIndex(w => w.id === workspace.id);
2208
2392
  if (index !== -1) {
2209
- this.state.workspaces[index] = workspace;
2393
+ workspaces[index] = workspace;
2394
+ this._store.setState('workspaces', workspaces);
2210
2395
  }
2211
2396
  }
2212
2397
  async deleteWorkspace(workspace) {
@@ -2216,7 +2401,7 @@ class KritzelStore {
2216
2401
  const objectRange = IDBKeyRange.bound([workspace.id], [workspace.id, '\uffff']);
2217
2402
  await this._database.deleteByRange('objects', objectRange);
2218
2403
  await this._database.delete('workspaces', workspace.id);
2219
- this.state.workspaces = this.state.workspaces.filter(ws => ws.id !== workspace.id);
2404
+ this._store.setState('workspaces', this._store.state.workspaces.filter(ws => ws.id !== workspace.id));
2220
2405
  }
2221
2406
  rerender() {
2222
2407
  if (this._kritzelEngine) {
@@ -2224,7 +2409,7 @@ class KritzelStore {
2224
2409
  }
2225
2410
  }
2226
2411
  findObjectById(id) {
2227
- for (const object of this.allObjects) {
2412
+ for (const object of this._store.allObjects) {
2228
2413
  if (object.id === id) {
2229
2414
  return object;
2230
2415
  }
@@ -2232,33 +2417,18 @@ class KritzelStore {
2232
2417
  return null;
2233
2418
  }
2234
2419
  deselectAllObjects() {
2235
- if (this._state.selectionGroup) {
2420
+ if (this._store.state.selectionGroup) {
2236
2421
  this._history.executeCommand(new RemoveSelectionGroupCommand(this, this));
2237
2422
  }
2238
2423
  }
2239
- onStateChange(property, listener) {
2240
- if (!this._listeners.has(property)) {
2241
- this._listeners.set(property, new Set());
2242
- }
2243
- this._listeners.get(property).add(listener);
2244
- }
2245
- setState(property, value) {
2246
- const oldValue = this._state[property];
2247
- if (oldValue !== value) {
2248
- this._state[property] = value;
2249
- if (this._listeners.has(property)) {
2250
- this._listeners.get(property).forEach(listener => listener(value, oldValue, String(property)));
2251
- }
2252
- }
2253
- }
2254
2424
  delete() {
2255
- if (!this.state.selectionGroup) {
2425
+ if (!this._store.state.selectionGroup) {
2256
2426
  return;
2257
2427
  }
2258
- const deleteSelectedObjectsCommand = this.state.selectionGroup.objects.map(obj => new RemoveObjectCommand(this, this.state.selectionGroup, obj));
2259
- const removeSelectionGroupCommand = new RemoveSelectionGroupCommand(this, this.state.selectionGroup);
2428
+ const deleteSelectedObjectsCommand = this._store.state.selectionGroup.objects.map(obj => new RemoveObjectCommand(this, this._store.state.selectionGroup, obj));
2429
+ const removeSelectionGroupCommand = new RemoveSelectionGroupCommand(this, this._store.state.selectionGroup);
2260
2430
  const commands = [...deleteSelectedObjectsCommand, removeSelectionGroupCommand];
2261
- this.history.executeCommand(new BatchCommand(this, this.state.selectionGroup, commands));
2431
+ this.history.executeCommand(new BatchCommand(this, this._store.state.selectionGroup, commands));
2262
2432
  }
2263
2433
  deleteObject(id, skipHistory = false) {
2264
2434
  const object = this.findObjectById(id);
@@ -2268,28 +2438,30 @@ class KritzelStore {
2268
2438
  }
2269
2439
  }
2270
2440
  copy() {
2271
- this.state.copiedObjects = this.state.selectionGroup.copy();
2441
+ this._store.setState('copiedObjects', this._store.state.selectionGroup.copy());
2272
2442
  }
2273
2443
  paste(x, y) {
2274
- this.state.copiedObjects.isSelected = true;
2275
- const adjustedX = x !== undefined ? x : this.state.copiedObjects.translateX + 25;
2276
- const adjustedY = y !== undefined ? y : this.state.copiedObjects.translateY + 25;
2277
- this.state.copiedObjects.updatePosition(adjustedX, adjustedY);
2444
+ const copiedObjects = this._store.state.copiedObjects;
2445
+ copiedObjects.isSelected = true;
2446
+ this._store.setState('copiedObjects', copiedObjects);
2447
+ const adjustedX = x !== undefined ? x : this._store.state.copiedObjects.translateX + 25;
2448
+ const adjustedY = y !== undefined ? y : this._store.state.copiedObjects.translateY + 25;
2449
+ this._store.state.copiedObjects.updatePosition(adjustedX, adjustedY);
2278
2450
  const commands = [];
2279
- if (this.state.selectionGroup !== null) {
2280
- commands.push(new RemoveSelectionGroupCommand(this, this.state.selectionGroup));
2451
+ if (this._store.state.selectionGroup !== null) {
2452
+ commands.push(new RemoveSelectionGroupCommand(this, this._store.state.selectionGroup));
2281
2453
  }
2282
- const addCopiedObjectsCommands = this.state.copiedObjects.objects.map(obj => new AddObjectCommand(this, this, obj));
2283
- const addCopiedObjectsAsSelectionGroupCommand = new AddSelectionGroupCommand(this, this, this.state.copiedObjects);
2454
+ const addCopiedObjectsCommands = this._store.state.copiedObjects.objects.map(obj => new AddObjectCommand(this, this, obj));
2455
+ const addCopiedObjectsAsSelectionGroupCommand = new AddSelectionGroupCommand(this, this, this._store.state.copiedObjects);
2284
2456
  commands.push(...addCopiedObjectsCommands, addCopiedObjectsAsSelectionGroupCommand);
2285
2457
  this.history.executeCommand(new BatchCommand(this, this, commands));
2286
- this.state.isSelecting = false;
2287
- this.state.copiedObjects = this.state.selectionGroup.copy();
2288
- this.setState('activeTool', KritzelToolRegistry.getTool('selection'));
2458
+ this._store.setState('isSelecting', false);
2459
+ this._store.setState('copiedObjects', this._store.state.selectionGroup.copy());
2460
+ this._store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
2289
2461
  }
2290
2462
  bringForward(object) {
2291
- const max = this.allObjects.length + 1;
2292
- const objects = object ? [object] : this.state.selectionGroup.objects;
2463
+ const max = this._store.allObjects.length + 1;
2464
+ const objects = object ? [object] : this._store.state.selectionGroup.objects;
2293
2465
  const increaseZIndexCommands = objects.map(obj => {
2294
2466
  if (obj.zIndex === max) {
2295
2467
  return;
@@ -2300,7 +2472,7 @@ class KritzelStore {
2300
2472
  }
2301
2473
  sendBackward(object) {
2302
2474
  const min = 0;
2303
- const objects = object ? [object] : this.state.selectionGroup.objects;
2475
+ const objects = object ? [object] : this._store.state.selectionGroup.objects;
2304
2476
  const decreaseZIndexCommands = objects.map(obj => {
2305
2477
  if (obj.zIndex === min) {
2306
2478
  return;
@@ -2310,16 +2482,16 @@ class KritzelStore {
2310
2482
  this.history.executeCommand(new BatchCommand(this, this, decreaseZIndexCommands));
2311
2483
  }
2312
2484
  bringToFront(object) {
2313
- const max = Math.max(...this.allObjects.map(obj => obj.zIndex)) + 1;
2314
- const objects = object ? [object] : this.state.selectionGroup.objects;
2485
+ const max = Math.max(...this._store.allObjects.map(obj => obj.zIndex)) + 1;
2486
+ const objects = object ? [object] : this._store.state.selectionGroup.objects;
2315
2487
  const increaseZIndexCommands = objects.map(obj => {
2316
2488
  return new UpdateObjectCommand(this, this, obj, { zIndex: max });
2317
2489
  });
2318
2490
  this.history.executeCommand(new BatchCommand(this, this, increaseZIndexCommands));
2319
2491
  }
2320
2492
  sendToBack(object) {
2321
- const min = Math.min(...this.allObjects.map(obj => obj.zIndex)) - 1;
2322
- const objects = object ? [object] : this.state.selectionGroup.objects;
2493
+ const min = Math.min(...this._store.allObjects.map(obj => obj.zIndex)) - 1;
2494
+ const objects = object ? [object] : this._store.state.selectionGroup.objects;
2323
2495
  const decreaseZIndexCommands = objects.map(obj => {
2324
2496
  return new UpdateObjectCommand(this, this, obj, { zIndex: min });
2325
2497
  });
@@ -2335,14 +2507,14 @@ class KritzelStore {
2335
2507
  selectionGroup.addOrRemove(obj);
2336
2508
  });
2337
2509
  selectionGroup.isSelected = true;
2338
- this.state.selectionGroup = selectionGroup;
2510
+ this._store.setState('selectionGroup', selectionGroup);
2339
2511
  if (objects.length === 1) {
2340
2512
  selectionGroup.rotation = selectionGroup.objects[0].rotation;
2341
2513
  }
2342
2514
  this.history.executeCommand(new AddSelectionGroupCommand(this, this, selectionGroup));
2343
2515
  }
2344
2516
  selectAllObjectsInViewport() {
2345
- const objectsInViewport = this._state.objectsMap
2517
+ const objectsInViewport = this._store.state.objectsMap
2346
2518
  .filter(o => o.isInViewport())
2347
2519
  .filter(o => !(o instanceof KritzelSelectionGroup) && !(o instanceof KrtizelSelectionBox) && !(o instanceof KritzelContextMenu));
2348
2520
  if (objectsInViewport.length > 0) {
@@ -2352,31 +2524,31 @@ class KritzelStore {
2352
2524
  selectionGroup.addOrRemove(obj);
2353
2525
  });
2354
2526
  selectionGroup.isSelected = true;
2355
- this.state.isSelecting = false;
2527
+ this._store.setState('isSelecting', false);
2356
2528
  if (objectsInViewport.length === 1) {
2357
2529
  selectionGroup.rotation = selectionGroup.objects[0].rotation;
2358
2530
  }
2359
2531
  this.history.executeCommand(new AddSelectionGroupCommand(this, this, selectionGroup));
2360
- this.setState('activeTool', KritzelToolRegistry.getTool('selection'));
2532
+ this._store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
2361
2533
  }
2362
2534
  }
2363
2535
  clearSelection() {
2364
- const command = new RemoveSelectionGroupCommand(this, this.state.selectionGroup);
2536
+ const command = new RemoveSelectionGroupCommand(this, this._store.state.selectionGroup);
2365
2537
  this.history.executeCommand(command);
2366
- this.state.selectionGroup = null;
2367
- this.state.selectionBox = null;
2368
- this.state.isSelecting = false;
2369
- this.state.isResizeHandleSelected = false;
2370
- this.state.isRotationHandleSelected = false;
2538
+ this._store.setState('selectionGroup', null);
2539
+ this._store.setState('selectionBox', null);
2540
+ this._store.setState('isSelecting', false);
2541
+ this._store.setState('isResizeHandleSelected', false);
2542
+ this._store.setState('isRotationHandleSelected', false);
2371
2543
  }
2372
2544
  resetActiveText() {
2373
- if (this.state.activeText && this.state.activeText.value === ' ') {
2374
- this.deleteObject(this.state.activeText.id, true);
2545
+ if (this._store.state.activeText && this._store.state.activeText.value === ' ') {
2546
+ this.deleteObject(this._store.state.activeText.id, true);
2375
2547
  }
2376
- this.state.activeText = null;
2548
+ this._store.setState('activeText', null);
2377
2549
  }
2378
2550
  getObjectFromPointerEvent(event, selector = '.object') {
2379
- const shadowRoot = this.state.host?.shadowRoot;
2551
+ const shadowRoot = this._store.state.host?.shadowRoot;
2380
2552
  if (!shadowRoot)
2381
2553
  return null;
2382
2554
  const clientX = event.clientX;
@@ -2386,12 +2558,14 @@ class KritzelStore {
2386
2558
  return null;
2387
2559
  const selectedObject = elementAtPoint.closest(selector);
2388
2560
  if (selectedObject) {
2389
- return this.allObjects.find(object => selectedObject.id === object.id);
2561
+ const foundObject = this._store.allObjects.find(object => selectedObject.id === object.id);
2562
+ const isHit = foundObject?.hitTest(clientX, clientY);
2563
+ return isHit ? foundObject : null;
2390
2564
  }
2391
2565
  return null;
2392
2566
  }
2393
2567
  getObjectsFromPointerEvent(event, selector = '.object') {
2394
- const shadowRoot = this.state.host?.shadowRoot;
2568
+ const shadowRoot = this._store.state.host?.shadowRoot;
2395
2569
  if (!shadowRoot)
2396
2570
  return [];
2397
2571
  const clientX = event.clientX;
@@ -2407,292 +2581,117 @@ class KritzelStore {
2407
2581
  }
2408
2582
  });
2409
2583
  if (objectIds.size > 0) {
2410
- return this.allObjects.filter(object => objectIds.has(object.id)).sort((a, b) => b.zIndex - a.zIndex);
2584
+ return this._store.allObjects.filter(object => objectIds.has(object.id)).sort((a, b) => b.zIndex - a.zIndex);
2411
2585
  }
2412
2586
  return [];
2413
2587
  }
2414
2588
  getCanvasPoint(event) {
2415
- if (!this.state.host) {
2589
+ if (!this._store.state.host) {
2416
2590
  return { x: 0, y: 0 };
2417
2591
  }
2418
- // Get the position of the kritzel-engine host element relative to the viewport
2419
- const hostRect = this.state.host.getBoundingClientRect();
2420
- // 1. Make the pointer coordinates relative to the host element
2592
+ const hostRect = this._store.state.host.getBoundingClientRect();
2421
2593
  const xRelativeToHost = event.clientX - hostRect.left;
2422
2594
  const yRelativeToHost = event.clientY - hostRect.top;
2423
- // 2. Reverse the translation applied to the #origin div
2424
- const xWithoutTranslate = xRelativeToHost - this.state.translateX;
2425
- const yWithoutTranslate = yRelativeToHost - this.state.translateY;
2426
- // 3. Reverse the scaling to get the final world coordinates
2427
- const worldX = xWithoutTranslate / this.state.scale;
2428
- const worldY = yWithoutTranslate / this.state.scale;
2595
+ const xWithoutTranslate = xRelativeToHost - this._store.state.translateX;
2596
+ const yWithoutTranslate = yRelativeToHost - this._store.state.translateY;
2597
+ const worldX = xWithoutTranslate / this._store.state.scale;
2598
+ const worldY = yWithoutTranslate / this._store.state.scale;
2429
2599
  return { x: worldX, y: worldY };
2430
2600
  }
2431
2601
  }
2432
2602
 
2433
- class KritzelKeyHandler extends KritzelBaseHandler {
2434
- constructor(store) {
2435
- super(store);
2436
- }
2437
- handleKeyDown(event) {
2438
- if (this._store.state.isFocused === false) {
2439
- return;
2440
- }
2441
- this._store.state.isCtrlKeyPressed = event.ctrlKey;
2442
- if (this._store.state.isCtrlKeyPressed) {
2443
- event.preventDefault();
2444
- }
2445
- if (event.key === 'Escape' && this._store.state.selectionGroup) {
2446
- this._store.clearSelection();
2447
- }
2448
- if (event.key === 'Delete' && this._store.state.selectionGroup) {
2449
- this._store.delete();
2450
- }
2451
- if (event.key === 'z' && event.ctrlKey) {
2452
- this._store.history.undo();
2453
- }
2454
- if (event.key === 'y' && event.ctrlKey) {
2455
- this._store.history.redo();
2456
- }
2457
- if (event.key === 's' && event.ctrlKey) {
2458
- this._store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
2459
- this._store.deselectAllObjects();
2460
- }
2461
- if (event.key === 'b' && event.ctrlKey) {
2462
- this._store.setState('activeTool', KritzelToolRegistry.getTool('brush'));
2463
- this._store.deselectAllObjects();
2464
- }
2465
- if (event.key === 'e' && event.ctrlKey) {
2466
- this._store.setState('activeTool', KritzelToolRegistry.getTool('eraser'));
2467
- this._store.deselectAllObjects();
2468
- }
2469
- if (event.key === 'i' && event.ctrlKey) {
2470
- this._store.setState('activeTool', KritzelToolRegistry.getTool('image'));
2471
- this._store.deselectAllObjects();
2472
- }
2473
- if (event.key === 'x' && event.ctrlKey) {
2474
- this._store.setState('activeTool', KritzelToolRegistry.getTool('text'));
2475
- this._store.deselectAllObjects();
2476
- }
2477
- if (event.key === 'c' && event.ctrlKey && this._store.state.selectionGroup) {
2478
- this._store.copy();
2479
- this._store.rerender();
2480
- }
2481
- if (event.key === 'v' && event.ctrlKey && this._store.state.copiedObjects) {
2482
- this._store.paste();
2483
- }
2484
- if (event.key === '+' && event.ctrlKey && this._store.state.selectionGroup) {
2485
- this._store.bringForward();
2486
- }
2487
- if (event.key === '-' && event.ctrlKey && this._store.state.selectionGroup) {
2488
- this._store.sendBackward();
2489
- }
2490
- if (event.key === '*' && event.shiftKey && this._store.state.selectionGroup) {
2491
- this._store.bringToFront();
2492
- }
2493
- if (event.key === '_' && event.shiftKey && this._store.state.selectionGroup) {
2494
- this._store.sendToBack();
2495
- }
2496
- if (event.key === 'a' && event.ctrlKey && this._store.state.activeText) {
2497
- this._store.state.activeText.selectAll();
2498
- }
2499
- if (event.key === 'v' && event.ctrlKey && this._store.state.activeText) {
2500
- this._store.state.activeText.insertFromClipboard();
2501
- }
2502
- }
2503
- handleKeyUp(event) {
2504
- if (this._store.state.isFocused === false) {
2505
- return;
2506
- }
2507
- this._store.state.isCtrlKeyPressed = event.ctrlKey;
2508
- }
2509
- }
2510
-
2511
- class KritzelContextMenuHandler extends KritzelBaseHandler {
2512
- globalContextMenuItems = [];
2513
- objectContextMenuItems = [];
2514
- constructor(store, globalContextMenuItems, objectContextMenuItems) {
2515
- super(store);
2516
- this.globalContextMenuItems = globalContextMenuItems;
2517
- this.objectContextMenuItems = objectContextMenuItems;
2518
- }
2519
- handleContextMenu(event) {
2520
- if (this._store.state.skipContextMenu) {
2521
- this._store.state.skipContextMenu = false;
2522
- return;
2523
- }
2524
- const selectedObject = this._store.getObjectFromPointerEvent(event, '.object');
2525
- if (selectedObject && !(selectedObject instanceof KritzelSelectionGroup)) {
2526
- this._store.state.selectionGroup = KritzelSelectionGroup.create(this._store);
2527
- this._store.state.selectionGroup.addOrRemove(selectedObject);
2528
- this._store.state.selectionGroup.isSelected = true;
2529
- this._store.state.selectionGroup.rotation = selectedObject.rotation;
2530
- this._store.state.isSelecting = false;
2531
- this._store.history.executeCommand(new AddSelectionGroupCommand(this._store, this, this._store.state.selectionGroup));
2532
- }
2533
- this._store.state.contextMenuItems = this._store.state.selectionGroup ? this.objectContextMenuItems : this.globalContextMenuItems;
2534
- let x = event.clientX - this._store.offsetX;
2535
- let y = event.clientY - this._store.offsetY;
2536
- const menuWidthEstimate = 150;
2537
- const menuHeightEstimate = 200;
2538
- const margin = 10;
2539
- if (x + menuWidthEstimate > window.innerWidth - margin) {
2540
- x = window.innerWidth - menuWidthEstimate - margin;
2541
- }
2542
- if (y + menuHeightEstimate > window.innerHeight - margin) {
2543
- y = window.innerHeight - menuHeightEstimate - margin;
2544
- }
2545
- x = Math.max(margin, x);
2546
- y = Math.max(margin, y);
2547
- this._store.state.contextMenuX = x;
2548
- this._store.state.contextMenuY = y;
2549
- this._store.state.isContextMenuVisible = true;
2550
- this._store.state.isEnabled = false;
2551
- this._store.rerender();
2552
- }
2553
- }
2554
-
2555
- class KritzelClassHelper {
2556
- static isInstanceOf(object, className) {
2557
- return !!object && object.__class__ === className;
2558
- }
2559
- }
2560
-
2561
2603
  const kritzelEngineCss = ":host{display:block;position:relative;height:100%;width:100%;overflow:hidden;background-color:var(--kritzel-engine-background-color, #ffffff)}:host,:host *{touch-action:none;user-select:none}.debug-panel{position:absolute;pointer-events:none;top:0;right:0}.origin{position:relative;top:0;left:0;height:0;width:0;pointer-events:none;-webkit-transform-origin:top left;-moz-transform-origin:top left;transform-origin:top left;overflow:visible}.object{overflow:visible}textarea{all:unset;box-sizing:border-box;outline:none !important;border:none !important;overflow:visible}.resize-handle-overlay.top-left,.resize-handle-overlay.bottom-right{cursor:nwse-resize}.resize-handle-overlay.top-right,.resize-handle-overlay.bottom-left{cursor:nesw-resize}.rotation-handle-overlay{cursor:grab}";
2562
2604
 
2563
2605
  const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine extends H {
2606
+ get host() { return this; }
2564
2607
  workspace;
2608
+ onWorkspaceChange(newWorkspace) {
2609
+ if (this.core.store.state.activeWorkspace !== newWorkspace) {
2610
+ this.core.initializeWorkspace(newWorkspace);
2611
+ }
2612
+ }
2565
2613
  activeTool;
2566
2614
  globalContextMenuItems;
2567
2615
  objectContextMenuItems;
2568
2616
  scaleMax = ABSOLUTE_SCALE_MAX;
2569
- scaleMin = ABSOLUTE_SCALE_MIN;
2570
- isEngineReady;
2571
- activeToolChange;
2572
- workspacesChange;
2573
- get host() { return this; }
2574
- forceUpdate = 0;
2575
- onWorkspaceChange(newWorkspace) {
2576
- if (newWorkspace) {
2577
- this.store.initializeWorkspace(newWorkspace);
2578
- }
2579
- }
2580
2617
  validateScaleMax(newValue) {
2581
2618
  if (newValue > ABSOLUTE_SCALE_MAX) {
2582
2619
  console.warn(`scaleMax cannot be greater than ${ABSOLUTE_SCALE_MAX}.`);
2583
2620
  this.scaleMax = ABSOLUTE_SCALE_MAX;
2584
- this.store.state.scaleMax = this.scaleMax;
2621
+ this.core.store.setState('scaleMax', this.scaleMax);
2585
2622
  }
2586
2623
  else {
2587
- this.store.state.scaleMax = newValue;
2624
+ this.core.store.setState('scaleMax', newValue);
2588
2625
  }
2589
2626
  }
2627
+ scaleMin = ABSOLUTE_SCALE_MIN;
2590
2628
  validateScaleMin(newValue) {
2591
2629
  if (newValue < ABSOLUTE_SCALE_MIN) {
2592
2630
  console.warn(`scaleMin cannot be less than ${ABSOLUTE_SCALE_MIN}.`);
2593
2631
  this.scaleMin = ABSOLUTE_SCALE_MIN;
2594
- this.store.state.scaleMin = this.scaleMin;
2632
+ this.core.store.setState('scaleMin', this.scaleMin);
2595
2633
  }
2596
2634
  else {
2597
- this.store.state.scaleMin = newValue;
2598
- }
2599
- }
2600
- store;
2601
- viewport;
2602
- contextMenuHandler;
2603
- keyHandler;
2604
- contextMenuElement = null;
2605
- get isSelecting() {
2606
- return this.store.state.activeTool instanceof KritzelSelectionTool && this.store.state.isSelecting;
2607
- }
2608
- get isSelectionActive() {
2609
- return this.store.state.activeTool instanceof KritzelSelectionTool && this.store.state.selectionGroup !== null;
2610
- }
2611
- constructor(registerHost) {
2612
- super();
2613
- if (registerHost !== false) {
2614
- this.__registerHost();
2615
- }
2616
- this.__attachShadow();
2617
- this.isEngineReady = createEvent(this, "isEngineReady");
2618
- this.activeToolChange = createEvent(this, "activeToolChange");
2619
- this.workspacesChange = createEvent(this, "workspacesChange");
2620
- this.store = new KritzelStore(this);
2621
- }
2622
- componentWillLoad() {
2623
- this.validateScaleMax(this.scaleMax);
2624
- this.validateScaleMin(this.scaleMin);
2625
- }
2626
- async componentDidLoad() {
2627
- this.contextMenuHandler = new KritzelContextMenuHandler(this.store, this.globalContextMenuItems, this.objectContextMenuItems);
2628
- this.keyHandler = new KritzelKeyHandler(this.store);
2629
- this.viewport = new KritzelViewport(this.store, this.host);
2630
- this._registerStateChangeListeners();
2631
- await this.store.initializeDatabase();
2632
- await this.store.initializeWorkspace(this.workspace);
2633
- if (this.store.state.isReady === false) {
2634
- this.store.state.isReady = true;
2635
- this.isEngineReady.emit(this.store.state);
2635
+ this.core.store.setState('scaleMin', newValue);
2636
2636
  }
2637
2637
  }
2638
+ isEngineReady;
2639
+ activeToolChange;
2640
+ workspacesChange;
2641
+ longpress;
2642
+ forceUpdate = 0;
2638
2643
  handleWheel(ev) {
2639
- if (this.store.isDisabled) {
2644
+ if (this.core.store.isDisabled) {
2640
2645
  return;
2641
2646
  }
2642
- if (this.store.state.isContextMenuVisible) {
2647
+ if (this.core.store.state.isContextMenuVisible) {
2643
2648
  this.hideContextMenu();
2644
2649
  }
2645
2650
  this.viewport.handleWheel(ev);
2646
- this.store.state?.activeTool?.handleWheel(ev);
2651
+ this.core.store.state?.activeTool?.handleWheel(ev);
2647
2652
  }
2648
2653
  handlePointerDown(ev) {
2649
- if (this.store.isDisabled) {
2650
- return;
2651
- }
2652
- if (KritzelEventHelper.isPointerEventOnContextMenu(ev) === false && this.store.state.isContextMenuVisible) {
2653
- this.hideContextMenu();
2654
+ if (this.core.store.isDisabled) {
2654
2655
  return;
2655
2656
  }
2656
- KritzelEventHelper.onLongTouchPress(ev, (event) => {
2657
- if (!(this.store.state.activeTool instanceof KritzelSelectionTool)) {
2658
- return;
2659
- }
2660
- this.contextMenuHandler.handleContextMenu(event);
2661
- });
2657
+ KritzelEventHelper.onLongPress(ev, (event) => this.longpress.emit(event));
2662
2658
  this.host.setPointerCapture(ev.pointerId);
2663
- this.store.state.pointers.set(ev.pointerId, ev);
2659
+ this.core.store.state.pointers.set(ev.pointerId, ev);
2664
2660
  this.viewport.handlePointerDown(ev);
2665
- this.store.state?.activeTool?.handlePointerDown(ev);
2661
+ this.core.store.state?.activeTool?.handlePointerDown(ev);
2666
2662
  }
2667
2663
  handlePointerMove(ev) {
2668
- if (this.store.isDisabled) {
2664
+ if (this.core.store.isDisabled) {
2669
2665
  return;
2670
2666
  }
2671
- this.store.state.pointers.set(ev.pointerId, ev);
2667
+ this.core.store.state.pointers.set(ev.pointerId, ev);
2672
2668
  this.viewport.handlePointerMove(ev);
2673
- this.store.state?.activeTool?.handlePointerMove(ev);
2669
+ this.core.store.state?.activeTool?.handlePointerMove(ev);
2674
2670
  }
2675
2671
  handlePointerUp(ev) {
2676
- if (this.store.isDisabled) {
2672
+ if (this.core.store.isDisabled) {
2677
2673
  return;
2678
2674
  }
2679
- this.store.state.pointers.delete(ev.pointerId);
2675
+ this.core.store.state.pointers.delete(ev.pointerId);
2680
2676
  this.host.releasePointerCapture(ev.pointerId);
2681
2677
  this.viewport.handlePointerUp(ev);
2682
- this.store.state?.activeTool?.handlePointerUp(ev);
2678
+ this.core.store.state?.activeTool?.handlePointerUp(ev);
2683
2679
  }
2684
2680
  handlePointerCancel(ev) {
2685
- if (this.store.isDisabled) {
2681
+ if (this.core.store.isDisabled) {
2686
2682
  return;
2687
2683
  }
2688
2684
  this.host.releasePointerCapture(ev.pointerId);
2689
- this.store.state.pointers.delete(ev.pointerId);
2685
+ this.core.store.state.pointers.delete(ev.pointerId);
2690
2686
  this.viewport.handlePointerUp(ev);
2691
- this.store.state?.activeTool?.handlePointerUp(ev);
2687
+ this.core.store.state?.activeTool?.handlePointerUp(ev);
2688
+ }
2689
+ handleLongPress(ev) {
2690
+ this.contextMenuHandler.handleContextMenu(ev.detail);
2692
2691
  }
2693
2692
  handleContextMenu(ev) {
2694
2693
  ev.preventDefault();
2695
- if (this.store.isDisabled) {
2694
+ if (this.core.store.isDisabled) {
2696
2695
  return;
2697
2696
  }
2698
2697
  if (ev.pointerType === 'touch') {
@@ -2709,26 +2708,12 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
2709
2708
  handleKeyUp(ev) {
2710
2709
  this.keyHandler.handleKeyUp(ev);
2711
2710
  }
2712
- updateFocus(ev) {
2713
- if (this.store.isDisabled) {
2714
- return;
2715
- }
2716
- const rect = this.store.state.host.getBoundingClientRect();
2717
- const isInside = ev.clientX >= rect.left && ev.clientX <= rect.right && ev.clientY >= rect.top && ev.clientY <= rect.bottom;
2718
- const path = ev.composedPath();
2719
- const kritzelEngineElement = this.host.closest('kritzel-engine');
2720
- const isInKritzelEngine = path.includes(kritzelEngineElement || this.host);
2721
- this.store.setState('isFocused', isInside && isInKritzelEngine);
2722
- }
2723
- handleClick() {
2724
- this.enable();
2725
- }
2726
2711
  async registerTool(toolName, toolClass, toolConfig) {
2727
2712
  if (typeof toolClass !== 'function' || !(toolClass.prototype instanceof KritzelBaseTool)) {
2728
2713
  console.error(`Failed to register tool "${toolName}": Tool class must be a constructor function`);
2729
2714
  return null;
2730
2715
  }
2731
- const registeredTool = KritzelToolRegistry.registerTool(toolName, toolClass, this.store);
2716
+ const registeredTool = KritzelToolRegistry.registerTool(toolName, toolClass, this.core);
2732
2717
  if (toolConfig) {
2733
2718
  Object.entries(toolConfig).forEach(([key, value]) => {
2734
2719
  registeredTool[key] = value;
@@ -2737,153 +2722,192 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
2737
2722
  return Promise.resolve(registeredTool);
2738
2723
  }
2739
2724
  async changeActiveTool(tool) {
2740
- this.store.state.activeTool?.onDeactivate();
2741
- this.store.setState('activeTool', tool);
2742
- this.store.deselectAllObjects();
2725
+ this.core.store.state.activeTool?.onDeactivate();
2726
+ this.core.store.setState('activeTool', tool);
2727
+ this.core.deselectAllObjects();
2743
2728
  tool?.onActivate();
2744
2729
  }
2745
- async setFocus() {
2746
- this.host.focus();
2747
- this.store.state.isFocused = true;
2748
- }
2749
2730
  async disable() {
2750
- this.store.state.isEnabled = false;
2751
- this.forceUpdate++;
2731
+ this.core.store.setState('isEnabled', false);
2732
+ this.core.rerender();
2752
2733
  }
2753
2734
  async enable() {
2754
- this.store.state.isEnabled = true;
2755
- this.forceUpdate++;
2735
+ this.core.store.setState('isEnabled', true);
2736
+ this.core.rerender();
2756
2737
  }
2757
2738
  async delete() {
2758
- this.store.delete();
2739
+ this.core.delete();
2759
2740
  }
2760
2741
  async copy() {
2761
- this.store.copy();
2742
+ this.core.copy();
2762
2743
  }
2763
2744
  async paste(x, y) {
2764
- this.store.paste(x, y);
2745
+ this.core.paste(x, y);
2765
2746
  }
2766
2747
  async bringForward(object) {
2767
- this.store.bringForward(object);
2748
+ this.core.bringForward(object);
2768
2749
  }
2769
2750
  async sendBackward(object) {
2770
- this.store.sendBackward(object);
2751
+ this.core.sendBackward(object);
2771
2752
  }
2772
2753
  async bringToFront(object) {
2773
- this.store.bringToFront(object);
2754
+ this.core.bringToFront(object);
2774
2755
  }
2775
2756
  async sendToBack(object) {
2776
- this.store.sendToBack(object);
2757
+ this.core.sendToBack(object);
2777
2758
  }
2778
2759
  async undo() {
2779
- this.store.history.undo();
2760
+ this.core.history.undo();
2780
2761
  }
2781
2762
  async redo() {
2782
- this.store.history.redo();
2763
+ this.core.history.redo();
2783
2764
  }
2784
2765
  async hideContextMenu() {
2785
- this.store.state.pointers.clear();
2786
- this.store.state.isContextMenuVisible = false;
2787
- this.store.state.selectionBox = null;
2788
- this.store.state.isSelecting = false;
2766
+ this.core.store.state.pointers.clear();
2767
+ this.core.store.setState('isContextMenuVisible', false);
2768
+ this.core.store.setState('selectionBox', null);
2769
+ this.core.store.setState('isSelecting', false);
2770
+ this.core.store.setState('isEnabled', true);
2771
+ this.core.rerender();
2789
2772
  }
2790
2773
  async getObjectById(id) {
2791
- const object = this.store.objects.find(obj => obj.id === id);
2774
+ const object = this.core.store.allObjects.find(obj => obj.id === id);
2792
2775
  return object || null;
2793
2776
  }
2794
2777
  async addObject(object) {
2795
- this.store.deselectAllObjects();
2778
+ this.core.deselectAllObjects();
2796
2779
  object.id = object.generateId();
2797
- object._store = this.store;
2798
- object.scale = object.scale ? object.scale : this.store.state.scale;
2799
- object.zIndex = this.store.currentZIndex;
2800
- const command = new AddObjectCommand(this.store, this, object);
2801
- this.store.history.executeCommand(command);
2780
+ object._core = this.core;
2781
+ object.scale = object.scale ? object.scale : this.core.store.state.scale;
2782
+ object.zIndex = this.core.store.currentZIndex;
2783
+ const command = new AddObjectCommand(this.core, this, object);
2784
+ this.core.history.executeCommand(command);
2802
2785
  return object;
2803
2786
  }
2804
2787
  async updateObject(object, updatedProperties) {
2805
- this.store.deselectAllObjects();
2806
- const command = new UpdateObjectCommand(this.store, this, object, updatedProperties);
2807
- this.store.history.executeCommand(command);
2788
+ this.core.deselectAllObjects();
2789
+ const command = new UpdateObjectCommand(this.core, this, object, updatedProperties);
2790
+ this.core.history.executeCommand(command);
2808
2791
  return object;
2809
2792
  }
2810
2793
  async removeObject(object) {
2811
- this.store.deselectAllObjects();
2812
- const command = new RemoveObjectCommand(this.store, this, object);
2813
- this.store.history.executeCommand(command);
2794
+ this.core.deselectAllObjects();
2795
+ const command = new RemoveObjectCommand(this.core, this, object);
2796
+ this.core.history.executeCommand(command);
2814
2797
  return object;
2815
2798
  }
2816
2799
  async getSelectedObjects() {
2817
- return this.store.state.selectionGroup ? this.store.state.selectionGroup.objects : [];
2800
+ return this.core.store.state.selectionGroup ? this.core.store.state.selectionGroup.objects : [];
2818
2801
  }
2819
2802
  async selectObjects(objects) {
2820
- this.store.state.activeTool?.onDeactivate();
2821
- this.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
2822
- this.store.deselectAllObjects();
2823
- this.store.selectObjects(objects);
2803
+ this.core.store.state.activeTool?.onDeactivate();
2804
+ this.core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
2805
+ this.core.deselectAllObjects();
2806
+ this.core.selectObjects(objects);
2824
2807
  }
2825
2808
  async selectAllObjectsInViewport() {
2826
- this.store.state.activeTool?.onDeactivate();
2827
- this.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
2828
- this.store.deselectAllObjects();
2829
- this.store.selectAllObjectsInViewport();
2809
+ this.core.store.state.activeTool?.onDeactivate();
2810
+ this.core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
2811
+ this.core.deselectAllObjects();
2812
+ this.core.selectAllObjectsInViewport();
2830
2813
  }
2831
2814
  async clearSelection() {
2832
- this.store.clearSelection();
2815
+ this.core.clearSelection();
2833
2816
  }
2834
2817
  async centerObjectInViewport(object) {
2835
2818
  object.centerInViewport();
2836
- const command = new UpdateObjectCommand(this.store, this, object, object);
2837
- this.store.history.executeCommand(command);
2819
+ const command = new UpdateObjectCommand(this.core, this, object, object);
2820
+ this.core.history.executeCommand(command);
2838
2821
  return object;
2839
2822
  }
2840
2823
  async getCopiedObjects() {
2841
- return this.store.state.copiedObjects?.objects || [];
2824
+ return this.core.store.state.copiedObjects?.objects || [];
2842
2825
  }
2843
2826
  async createWorkspace(workspace) {
2844
- return this.store.createWorkspace(workspace).then(() => {
2845
- this.workspacesChange.emit(this.store.state.workspaces);
2846
- });
2827
+ workspace._core = this.core;
2828
+ await this.core.createWorkspace(workspace);
2829
+ this.workspacesChange.emit(this.core.store.state.workspaces);
2830
+ return workspace;
2847
2831
  }
2848
2832
  async updateWorkspace(workspace) {
2849
- return this.store.updateWorkspace(workspace).then(() => {
2850
- this.workspacesChange.emit(this.store.state.workspaces);
2851
- });
2833
+ await this.core.updateWorkspace(workspace);
2834
+ this.workspacesChange.emit(this.core.store.state.workspaces);
2852
2835
  }
2853
2836
  async deleteWorkspace(workspace) {
2854
- return this.store.deleteWorkspace(workspace).then(async () => {
2855
- this.workspacesChange.emit(this.store.state.workspaces);
2856
- });
2837
+ await this.core.deleteWorkspace(workspace);
2838
+ this.workspacesChange.emit(this.core.store.state.workspaces);
2857
2839
  }
2858
2840
  async getWorkspaces() {
2859
- return this.store.getWorkspaces();
2841
+ return this.core.getWorkspaces();
2842
+ }
2843
+ async getActiveWorkspace() {
2844
+ return this.core.store.state.activeWorkspace;
2845
+ }
2846
+ core;
2847
+ viewport;
2848
+ contextMenuHandler;
2849
+ keyHandler;
2850
+ contextMenuElement = null;
2851
+ get isSelecting() {
2852
+ return this.core.store.state.activeTool instanceof KritzelSelectionTool && this.core.store.state.isSelecting;
2853
+ }
2854
+ get isSelectionActive() {
2855
+ return this.core.store.state.activeTool instanceof KritzelSelectionTool && this.core.store.state.selectionGroup !== null;
2856
+ }
2857
+ constructor(registerHost) {
2858
+ super();
2859
+ if (registerHost !== false) {
2860
+ this.__registerHost();
2861
+ }
2862
+ this.__attachShadow();
2863
+ this.isEngineReady = createEvent(this, "isEngineReady");
2864
+ this.activeToolChange = createEvent(this, "activeToolChange");
2865
+ this.workspacesChange = createEvent(this, "workspacesChange");
2866
+ this.longpress = createEvent(this, "longpress");
2867
+ this.core = new KritzelCore(this);
2868
+ }
2869
+ componentWillLoad() {
2870
+ this.validateScaleMax(this.scaleMax);
2871
+ this.validateScaleMin(this.scaleMin);
2872
+ }
2873
+ async componentDidLoad() {
2874
+ this.contextMenuHandler = new KritzelContextMenuHandler(this.core, this.globalContextMenuItems, this.objectContextMenuItems);
2875
+ this.keyHandler = new KritzelKeyHandler(this.core);
2876
+ this.viewport = new KritzelViewport(this.core, this.host);
2877
+ await this.core.initializeDatabase();
2878
+ await this.core.initializeWorkspace(this.workspace);
2879
+ this._registerStateChangeListeners();
2880
+ if (this.core.store.state.isReady === false) {
2881
+ this.core.store.setState('isReady', true);
2882
+ this.isEngineReady.emit(this.core.store.state);
2883
+ }
2860
2884
  }
2861
2885
  _registerStateChangeListeners() {
2862
- this.store.onStateChange('activeTool', this._handleActiveToolChange.bind(this));
2863
- this.store.onStateChange('isFocused', this._handleIsFocusedChange.bind(this));
2886
+ this.core.store.onStateChange('activeTool', this._handleActiveToolChange.bind(this));
2864
2887
  }
2865
2888
  _handleActiveToolChange(activeTool) {
2866
2889
  if (!(activeTool instanceof KritzelSelectionTool)) {
2867
- this.store.clearSelection();
2890
+ this.core.clearSelection();
2868
2891
  }
2869
- this.store.state.skipContextMenu = false;
2892
+ this.core.store.setState('skipContextMenu', false);
2870
2893
  this.activeToolChange.emit(activeTool);
2871
2894
  KritzelKeyboardHelper.forceHideKeyboard();
2872
2895
  }
2873
- _handleIsFocusedChange(isFocused) {
2874
- if (!isFocused) {
2875
- this.store.resetActiveText();
2876
- }
2877
- }
2878
2896
  render() {
2879
2897
  const computedStyle = window.getComputedStyle(this.host);
2880
2898
  const baseHandleSizePx = computedStyle.getPropertyValue('--kritzel-selection-handle-size').trim() || '6px';
2881
2899
  const baseHandleSize = parseFloat(baseHandleSizePx);
2882
2900
  const baseHandleTouchSize = baseHandleSize * 2 < 14 ? 14 : baseHandleSize;
2883
- return (h(Host, { key: 'fd353ff17bcde1a9ab646b6f463d1c6ce00a3dff' }, h("div", { key: '45bc2af8f1a3a2bfa3aa76a478c7bf208027da0c', class: "debug-panel", style: { display: this.store.state.debugInfo.showViewportInfo ? 'block' : 'none' } }, h("div", { key: '50e932febc35c7dbe852ad99d96ca4f0e0b742fc' }, "ActiveWorkspaceId: ", this.store.state?.activeWorkspace?.id), h("div", { key: 'af94b5061f0803588fece6cccdf540f46f13ca05' }, "ActiveWorkspaceName: ", this.store.state?.activeWorkspace?.name), h("div", { key: '89c0d21ce94f4eda72153554fadbd6942e785edc' }, "TranslateX: ", this.store.state?.translateX), h("div", { key: '340b5165265241972a7a940268c7940063ba8c12' }, "TranslateY: ", this.store.state?.translateY), h("div", { key: '428054b3ea4a1c327f03d6b37bfe6331dea6c57b' }, "ViewportWidth: ", this.store.state?.viewportWidth), h("div", { key: 'd67420ef633627413066a28b8ef9ac43c520015d' }, "ViewportHeight: ", this.store.state?.viewportHeight), h("div", { key: 'dedf9eb89c79fa496f7b6d0df9c646898f66b3d4' }, "ObjectsInViewport. ", this.store.objects.length), h("div", { key: '59bb8416941fd84305f2892f24098f6f4a084401' }, "Scale: ", this.store.state?.scale), h("div", { key: '6705a4cec22e4e33f75e296e17bc2952a3d1cba7' }, "ActiveTool: ", this.store.state?.activeTool?.name), h("div", { key: 'ca22e0a377a11fdca851b38f1bf425648cd3b9dd' }, "HasViewportChanged: ", this.store.state?.hasViewportChanged ? 'true' : 'false'), h("div", { key: '57508b9ee24a5af631e6bb1eace404c39af14f82' }, "IsEnabled: ", this.store.state?.isEnabled ? 'true' : 'false'), h("div", { key: 'f6cea367b5007f767afb25a033215abda734de9d' }, "IsScaling: ", this.store.state?.isScaling ? 'true' : 'false'), h("div", { key: '4386ef749facd2e54da7f58aa2713b87ed76f2df' }, "IsPanning: ", this.store.state?.isPanning ? 'true' : 'false'), h("div", { key: '1713185b36a50dfe0f9efa0c92394222db80a377' }, "IsFocused: ", this.store.state.isFocused ? 'true' : 'false'), h("div", { key: '5104f428b808e7d843712302ad2e58b619876bee' }, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), h("div", { key: '2cb3b27a00627188e7082fa94169eb961a1ae6ed' }, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), h("div", { key: '7407656e61be665f27e706738faa6d318e2c1d04' }, "IsResizeHandleSelected: ", this.store.state.isResizeHandleSelected ? 'true' : 'false'), h("div", { key: '701bf05c25cb3d3728af6602f694e6064627ea59' }, "IsRotationHandleSelected: ", this.store.state.isRotationHandleSelected ? 'true' : 'false'), h("div", { key: '772c345ea9c64ef800fdbb26919f1a54ca889025' }, "IsDrawing: ", this.store.state.isDrawing ? 'true' : 'false'), h("div", { key: 'dc687c8ba24182b8b61979ad334b989d3be72ec6' }, "IsWriting: ", this.store.state.isWriting ? 'true' : 'false'), h("div", { key: '10cbc575a7905396a76eca4e7b56be719755aeb4' }, "PointerX: ", this.store.state?.pointerX), h("div", { key: '4f21199328ffadddcc58b7d6b102a89e5079f676' }, "PointerY: ", this.store.state?.pointerY), h("div", { key: 'ac705f38cb323b8dc8cbf95f875657c5dec5c9ae' }, "SelectedObjects: ", this.store.state.selectionGroup?.objects.length || 0)), h("div", { key: '2ca55c53246e64520af6720a3f87d2357295ca7f', id: "origin", class: "origin", style: {
2884
- transform: `matrix(${this.store.state?.scale}, 0, 0, ${this.store.state?.scale}, ${this.store.state?.translateX}, ${this.store.state?.translateY})`,
2885
- } }, this.store.state.objectsMap.allObjects()?.map(object => {
2886
- return (h("div", { key: object.id, style: { display: object.isInViewport() ? 'block' : 'none', transform: object?.transformationMatrix, transformOrigin: 'top left', zIndex: object.zIndex.toString(), position: 'absolute' } }, h("svg", { xmlns: "http://www.w3.org/2000/svg", id: object.id, class: "object", style: {
2901
+ return (h(Host, { key: '05b345f98a4548591946d1295da4d4b288767da6' }, h("div", { key: 'c8399a8968a39448120f3123b39c755b0f9b5e49', class: "debug-panel", style: { display: this.core.store.state.debugInfo.showViewportInfo ? 'block' : 'none' } }, h("div", { key: '2cedd93f88f1a1e6ddc99e648375549ca5254f04' }, "ActiveWorkspaceId: ", this.core.store.state?.activeWorkspace?.id), h("div", { key: '30ed15a98512b0efd91123773963d6266fa8426a' }, "ActiveWorkspaceName: ", this.core.store.state?.activeWorkspace?.name), h("div", { key: 'a0eb11088673a9e0e2e22880ae8a7a89c6705609' }, "TranslateX: ", this.core.store.state?.translateX), h("div", { key: '97c7ccfc77342d4122f85136ab4c81709046a4e4' }, "TranslateY: ", this.core.store.state?.translateY), h("div", { key: 'ff832aa8a779a4adb2fca5b7ecd8d9b992cf7b99' }, "ViewportWidth: ", this.core.store.state?.viewportWidth), h("div", { key: '6867ad7ee7f4fbe8725ac6edbe1bd999942fd729' }, "ViewportHeight: ", this.core.store.state?.viewportHeight), h("div", { key: 'f54768467cace934702bd3fd6f26970515f669f0' }, "Scale: ", this.core.store.state?.scale), h("div", { key: '4aaa2cec8688e42249a6f0f7e2d67a13c57fa155' }, "ActiveTool: ", this.core.store.state?.activeTool?.name), h("div", { key: '0bec60557f2a1271c69226b477fde02f4c2857a1' }, "HasViewportChanged: ", this.core.store.state?.hasViewportChanged ? 'true' : 'false'), h("div", { key: 'bd342af473102a1c2095a3a2810de25630c8a717' }, "IsEnabled: ", this.core.store.state?.isEnabled ? 'true' : 'false'), h("div", { key: '62477d9f931903bff3fa6fa85f1ecd3b2944884f' }, "IsScaling: ", this.core.store.state?.isScaling ? 'true' : 'false'), h("div", { key: '80fba2f64cec36d9c7b2d5f2081ef21190c61768' }, "IsPanning: ", this.core.store.state?.isPanning ? 'true' : 'false'), h("div", { key: 'da75419ac806f146a6ac69607b64095eb1f37de4' }, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), h("div", { key: '11b3bf816afa3d64fea468de92a351d9e96dee9e' }, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), h("div", { key: 'e12cf1412d0e48a1245ae923c595e737deb4dffb' }, "IsResizeHandleSelected: ", this.core.store.state.isResizeHandleSelected ? 'true' : 'false'), h("div", { key: 'fa79c455e0ae7d68259003ce63a58eda4c250eba' }, "IsRotationHandleSelected: ", this.core.store.state.isRotationHandleSelected ? 'true' : 'false'), h("div", { key: 'bc7b25568bac9ef9cd6f1341a7415e4b93d8e8e9' }, "IsDrawing: ", this.core.store.state.isDrawing ? 'true' : 'false'), h("div", { key: 'a62eef5e0e277b629a11bb13809a4ab211d9428c' }, "IsWriting: ", this.core.store.state.isWriting ? 'true' : 'false'), h("div", { key: '285815884e83a3d5d8ec3726034ff4853225f216' }, "PointerX: ", this.core.store.state?.pointerX), h("div", { key: 'f267eb928ccb57736229d3a7fbc5bfdfd0d51819' }, "PointerY: ", this.core.store.state?.pointerY), h("div", { key: '55977bf82d326a128a5da8d303875603c2850aac' }, "SelectedObjects: ", this.core.store.state.selectionGroup?.objects.length || 0)), h("div", { key: '8c91eaf482ce6cbd7400ba5342ec6c866fc0a049', id: "origin", class: "origin", style: {
2902
+ transform: `matrix(${this.core.store.state?.scale}, 0, 0, ${this.core.store.state?.scale}, ${this.core.store.state?.translateX}, ${this.core.store.state?.translateY})`,
2903
+ } }, this.core.store.state.objectsMap.allObjects()?.map(object => {
2904
+ return (h("div", { key: object.id, style: {
2905
+ display: object.isInViewport() ? 'block' : 'none',
2906
+ transform: object?.transformationMatrix,
2907
+ transformOrigin: 'top left',
2908
+ zIndex: object.zIndex.toString(),
2909
+ position: 'absolute',
2910
+ } }, h("svg", { xmlns: "http://www.w3.org/2000/svg", id: object.id, class: "object", style: {
2887
2911
  height: object?.totalHeight.toString(),
2888
2912
  width: object?.totalWidth.toString(),
2889
2913
  left: '0',
@@ -2940,69 +2964,71 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
2940
2964
  } })), KritzelClassHelper.isInstanceOf(object, 'KrtizelSelectionBox') && (h("div", { ref: el => (el ? object.mount(el) : object.unmount()), style: {
2941
2965
  width: '100%',
2942
2966
  height: '100%',
2967
+ backgroundColor: KritzelDevicesHelper.isFirefox() ? object.backgroundColor : 'transparent',
2968
+ borderWidth: KritzelDevicesHelper.isFirefox() ? object.borderWidth + 'px' : '0',
2969
+ borderStyle: KritzelDevicesHelper.isFirefox() ? 'solid' : 'none',
2970
+ borderColor: KritzelDevicesHelper.isFirefox() ? object.borderColor : 'transparent',
2943
2971
  } }))), h("line", { x1: "0", y1: "0", x2: object.totalWidth, y2: "0", style: {
2944
2972
  stroke: 'var(--kritzel-selection-border-color, #007AFF)',
2945
- strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.store.state?.scale})`,
2973
+ strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.core.store.state?.scale})`,
2946
2974
  strokeLinecap: 'square',
2947
2975
  }, visibility: object.isSelected ? 'visible' : 'hidden' }), h("line", { x1: "0", y1: "0", x2: "0", y2: object.totalHeight, style: {
2948
2976
  stroke: 'var(--kritzel-selection-border-color, #007AFF)',
2949
- strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.store.state?.scale})`,
2977
+ strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.core.store.state?.scale})`,
2950
2978
  strokeLinecap: 'square',
2951
2979
  }, visibility: object.isSelected ? 'visible' : 'hidden' }), h("line", { x1: "0", y1: object.totalHeight, x2: object.totalWidth, y2: object.totalHeight, style: {
2952
2980
  stroke: 'var(--kritzel-selection-border-color, #007AFF)',
2953
- strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.store.state?.scale})`,
2981
+ strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.core.store.state?.scale})`,
2954
2982
  strokeLinecap: 'square',
2955
2983
  }, visibility: object.isSelected ? 'visible' : 'hidden' }), h("line", { x1: object.totalWidth, y1: "0", x2: object.totalWidth, y2: object.totalHeight, style: {
2956
2984
  stroke: 'var(--kritzel-selection-border-color, #007AFF)',
2957
- strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.store.state?.scale})`,
2985
+ strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.core.store.state?.scale})`,
2958
2986
  strokeLinecap: 'square',
2959
- }, visibility: object.isSelected ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle top-left", cx: "0", cy: "0", r: `${(baseHandleSize * object.scale) / this.store.state?.scale}`, style: {
2987
+ }, visibility: object.isSelected ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle top-left", cx: "0", cy: "0", r: `${(baseHandleSize * object.scale) / this.core.store.state?.scale}`, style: {
2960
2988
  fill: 'var(--kritzel-selection-handle-color, #000000)',
2961
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle-overlay top-left", cx: "0", cy: "0", r: `${(baseHandleTouchSize * object.scale) / this.store.state?.scale}`, style: {
2989
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle-overlay top-left", cx: "0", cy: "0", r: `${(baseHandleTouchSize * object.scale) / this.core.store.state?.scale}`, style: {
2962
2990
  fill: 'transparent',
2963
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle top-right", cx: object.totalWidth, cy: "0", r: `${(baseHandleSize * object.scale) / this.store.state?.scale}`, style: {
2991
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle top-right", cx: object.totalWidth, cy: "0", r: `${(baseHandleSize * object.scale) / this.core.store.state?.scale}`, style: {
2964
2992
  fill: 'var(--kritzel-selection-handle-color, #000000)',
2965
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle-overlay top-right", cx: object.totalWidth, cy: "0", r: `${(baseHandleTouchSize * object.scale) / this.store.state?.scale}`, style: {
2993
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle-overlay top-right", cx: object.totalWidth, cy: "0", r: `${(baseHandleTouchSize * object.scale) / this.core.store.state?.scale}`, style: {
2966
2994
  fill: 'transparent',
2967
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle bottom-left", cx: "0", cy: object.totalHeight, r: `${(baseHandleSize * object.scale) / this.store.state?.scale}`, style: {
2995
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle bottom-left", cx: "0", cy: object.totalHeight, r: `${(baseHandleSize * object.scale) / this.core.store.state?.scale}`, style: {
2968
2996
  fill: 'var(--kritzel-selection-handle-color, #000000)',
2969
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle-overlay bottom-left", cx: "0", cy: object.totalHeight, r: `${(baseHandleTouchSize * object.scale) / this.store.state?.scale}`, style: {
2997
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle-overlay bottom-left", cx: "0", cy: object.totalHeight, r: `${(baseHandleTouchSize * object.scale) / this.core.store.state?.scale}`, style: {
2970
2998
  fill: 'transparent',
2971
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle bottom-right", cx: object.totalWidth, cy: object.totalHeight, r: `${(baseHandleSize * object.scale) / this.store.state?.scale}`, style: {
2999
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle bottom-right", cx: object.totalWidth, cy: object.totalHeight, r: `${(baseHandleSize * object.scale) / this.core.store.state?.scale}`, style: {
2972
3000
  fill: 'var(--kritzel-selection-handle-color, #000000)',
2973
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle-overlay bottom-right", cx: object.totalWidth, cy: object.totalHeight, r: `${(baseHandleTouchSize * object.scale) / this.store.state?.scale}`, style: {
3001
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "resize-handle-overlay bottom-right", cx: object.totalWidth, cy: object.totalHeight, r: `${(baseHandleTouchSize * object.scale) / this.core.store.state?.scale}`, style: {
2974
3002
  fill: 'transparent',
2975
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("line", { x1: object.totalWidth / 2, y1: "0", x2: object.totalWidth / 2, y2: -((15 * object.scale) / this.store.state?.scale), style: {
3003
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("line", { x1: object.totalWidth / 2, y1: "0", x2: object.totalWidth / 2, y2: -((15 * object.scale) / this.core.store.state?.scale), style: {
2976
3004
  stroke: 'var(--kritzel-selection-border-color, #007AFF)',
2977
- strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.store.state?.scale})`,
2978
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "rotation-handle", cx: object.totalWidth / 2, cy: -((15 * object.scale) / this.store.state?.scale), r: `${(baseHandleSize * object.scale) / this.store.state?.scale}`, style: {
3005
+ strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.core.store.state?.scale})`,
3006
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "rotation-handle", cx: object.totalWidth / 2, cy: -((15 * object.scale) / this.core.store.state?.scale), r: `${(baseHandleSize * object.scale) / this.core.store.state?.scale}`, style: {
2979
3007
  fill: 'var(--kritzel-selection-handle-color, #000000)',
2980
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "rotation-handle-overlay", cx: object.totalWidth / 2, cy: -((15 * object.scale) / this.store.state?.scale), r: `${(baseHandleTouchSize * object.scale) / this.store.state?.scale}`, style: {
3008
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("circle", { class: "rotation-handle-overlay", cx: object.totalWidth / 2, cy: -((15 * object.scale) / this.core.store.state?.scale), r: `${(baseHandleTouchSize * object.scale) / this.core.store.state?.scale}`, style: {
2981
3009
  fill: 'transparent',
2982
3010
  cursor: 'grab',
2983
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("g", { style: { display: this.store.state.debugInfo.showObjectInfo ? 'block' : 'none', pointerEvents: 'none' } }, h("foreignObject", { x: object.totalWidth.toString(), y: "0", width: "400px", height: "160px", style: { minHeight: '0', minWidth: '0', display: object.isDebugInfoVisible ? 'block' : 'none' } }, h("div", { style: { width: '100%', height: '100%' } }, h("div", { style: { whiteSpace: 'nowrap' } }, "zIndex: ", object.zIndex), h("div", { style: { whiteSpace: 'nowrap' } }, "translateX: ", object.translateX), h("div", { style: { whiteSpace: 'nowrap' } }, "translateY: ", object.translateY), h("div", { style: { whiteSpace: 'nowrap' } }, "width: ", object.width), h("div", { style: { whiteSpace: 'nowrap' } }, "height: ", object.height), h("div", { style: { whiteSpace: 'nowrap' } }, "scale: ", object.scale), h("div", { style: { whiteSpace: 'nowrap' } }, "rotation: ", object.rotation), h("div", { style: { whiteSpace: 'nowrap' } }, "x: ", object.x), h("div", { style: { whiteSpace: 'nowrap' } }, "y: ", object.y)))))));
2984
- }), h("svg", { key: '0098f1b8233d45f49dc8bdcc13c08f20c04b65e1', class: "object", xmlns: "http://www.w3.org/2000/svg", style: {
2985
- height: this.store.state.currentPath?.height.toString(),
2986
- width: this.store.state.currentPath?.width.toString(),
3011
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), h("g", { style: { display: this.core.store.state.debugInfo.showObjectInfo ? 'block' : 'none', pointerEvents: 'none' } }, h("foreignObject", { x: object.totalWidth.toString(), y: "0", width: "400px", height: "160px", style: { minHeight: '0', minWidth: '0', display: object.isDebugInfoVisible ? 'block' : 'none' } }, h("div", { style: { width: '100%', height: '100%' } }, h("div", { style: { whiteSpace: 'nowrap' } }, "zIndex: ", object.zIndex), h("div", { style: { whiteSpace: 'nowrap' } }, "translateX: ", object.translateX), h("div", { style: { whiteSpace: 'nowrap' } }, "translateY: ", object.translateY), h("div", { style: { whiteSpace: 'nowrap' } }, "width: ", object.width), h("div", { style: { whiteSpace: 'nowrap' } }, "height: ", object.height), h("div", { style: { whiteSpace: 'nowrap' } }, "scale: ", object.scale), h("div", { style: { whiteSpace: 'nowrap' } }, "rotation: ", object.rotation), h("div", { style: { whiteSpace: 'nowrap' } }, "x: ", object.x), h("div", { style: { whiteSpace: 'nowrap' } }, "y: ", object.y)))))));
3012
+ }), h("svg", { key: "current-path", class: "object", xmlns: "http://www.w3.org/2000/svg", width: this.core.store.state.currentPath?.width, height: this.core.store.state.currentPath?.height, style: {
2987
3013
  left: '0',
2988
3014
  top: '0',
2989
- zIndex: this.store.state.currentPath?.zIndex.toString(),
3015
+ zIndex: this.core.store.state.currentPath?.zIndex.toString(),
2990
3016
  position: 'absolute',
2991
- transform: this.store.state.currentPath?.transformationMatrix,
3017
+ transform: this.core.store.state.currentPath?.transformationMatrix,
2992
3018
  transformOrigin: 'top left',
2993
3019
  overflow: 'visible',
2994
- }, viewBox: this.store.state.currentPath?.viewBox }, h("path", { key: '08310713fa8f2f1f695b1b61bb2b6e5a5f77f192', d: this.store.state.currentPath?.d, fill: this.store.state.currentPath?.fill, stroke: this.store.state.currentPath?.stroke }))), this.store.state.isContextMenuVisible && (h("kritzel-context-menu", { key: '2529447e26ba02689303be39cc593dfafc25b96c', class: "context-menu", ref: el => (this.contextMenuElement = el), items: this.store.state.contextMenuItems, objects: this.store.state.selectionGroup?.objects || [], style: {
3020
+ }, viewBox: this.core.store.state.currentPath?.viewBox }, h("path", { key: '1cdae549bc53dc30eb397f27702054ac6c5122f7', d: this.core.store.state.currentPath?.d, fill: this.core.store.state.currentPath?.fill, stroke: this.core.store.state.currentPath?.stroke }))), this.core.store.state.isContextMenuVisible && (h("kritzel-context-menu", { key: '2428e653f61d7ac5a71da1dbf94155b02e870406', class: "context-menu", ref: el => (this.contextMenuElement = el), items: this.core.store.state.contextMenuItems, objects: this.core.store.state.selectionGroup?.objects || [], style: {
2995
3021
  position: 'fixed',
2996
- left: `${this.store.state.contextMenuX}px`,
2997
- top: `${this.store.state.contextMenuY}px`,
3022
+ left: `${this.core.store.state.contextMenuX}px`,
3023
+ top: `${this.core.store.state.contextMenuY}px`,
2998
3024
  zIndex: '10000',
2999
3025
  }, onActionSelected: event => {
3000
3026
  event.detail.action({
3001
- x: (-this.store.state.translateX + this.store.state.contextMenuX) / this.store.state.scale,
3002
- y: (-this.store.state.translateY + this.store.state.contextMenuY) / this.store.state.scale,
3003
- }, this.store.state.selectionGroup?.objects);
3027
+ x: (-this.core.store.state.translateX + this.core.store.state.contextMenuX) / this.core.store.state.scale,
3028
+ y: (-this.core.store.state.translateY + this.core.store.state.contextMenuY) / this.core.store.state.scale,
3029
+ }, this.core.store.state.selectionGroup?.objects);
3004
3030
  this.hideContextMenu();
3005
- } })), this.store.state?.activeTool instanceof KritzelEraserTool && !this.store.state.isScaling && h("kritzel-cursor-trail", { key: '7c10277160eb1bc51581e4dfbdd4d0cdf626ed8c', store: this.store })));
3031
+ }, onClose: () => this.hideContextMenu() })), this.core.store.state?.activeTool instanceof KritzelEraserTool && !this.core.store.state.isScaling && h("kritzel-cursor-trail", { key: '94bdb8b137c50bb7499a37e4784ae36989258ee2', core: this.core })));
3006
3032
  }
3007
3033
  static get watchers() { return {
3008
3034
  "workspace": ["onWorkspaceChange"],
@@ -3020,7 +3046,6 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
3020
3046
  "forceUpdate": [32],
3021
3047
  "registerTool": [64],
3022
3048
  "changeActiveTool": [64],
3023
- "setFocus": [64],
3024
3049
  "disable": [64],
3025
3050
  "enable": [64],
3026
3051
  "delete": [64],
@@ -3046,8 +3071,9 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
3046
3071
  "createWorkspace": [64],
3047
3072
  "updateWorkspace": [64],
3048
3073
  "deleteWorkspace": [64],
3049
- "getWorkspaces": [64]
3050
- }, [[0, "wheel", "handleWheel"], [0, "pointerdown", "handlePointerDown"], [0, "pointermove", "handlePointerMove"], [0, "pointerup", "handlePointerUp"], [0, "pointercancel", "handlePointerCancel"], [0, "contextmenu", "handleContextMenu"], [9, "resize", "handleResize"], [8, "keydown", "handleKeyDown"], [8, "keyup", "handleKeyUp"], [9, "mousedown", "updateFocus"], [0, "click", "handleClick"]], {
3074
+ "getWorkspaces": [64],
3075
+ "getActiveWorkspace": [64]
3076
+ }, [[0, "wheel", "handleWheel"], [0, "pointerdown", "handlePointerDown"], [0, "pointermove", "handlePointerMove"], [0, "pointerup", "handlePointerUp"], [0, "pointercancel", "handlePointerCancel"], [0, "longpress", "handleLongPress"], [0, "contextmenu", "handleContextMenu"], [9, "resize", "handleResize"], [8, "keydown", "handleKeyDown"], [8, "keyup", "handleKeyUp"]], {
3051
3077
  "workspace": ["onWorkspaceChange"],
3052
3078
  "scaleMax": ["validateScaleMax"],
3053
3079
  "scaleMin": ["validateScaleMin"]
@@ -3082,6 +3108,6 @@ function defineCustomElement() {
3082
3108
  }
3083
3109
 
3084
3110
  export { ABSOLUTE_SCALE_MAX as A, KritzelImage as K, KritzelEraserTool as a, KritzelImageTool as b, KritzelSelectionTool as c, KritzelEngine as d, defineCustomElement as e, ABSOLUTE_SCALE_MIN as f };
3085
- //# sourceMappingURL=p-BuewJQNl.js.map
3111
+ //# sourceMappingURL=p-Davd1R_4.js.map
3086
3112
 
3087
- //# sourceMappingURL=p-BuewJQNl.js.map
3113
+ //# sourceMappingURL=p-Davd1R_4.js.map