kritzel-stencil 0.0.131 → 0.0.133

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 (362) hide show
  1. package/dist/cjs/{index-BwINBV6L.js → index-DCHCVnOl.js} +755 -701
  2. package/dist/cjs/index-DCHCVnOl.js.map +1 -0
  3. package/dist/cjs/index-nzUNdMPh.js +6 -2
  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} +1046 -874
  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 +15 -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 +15 -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 +14 -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 +6 -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} +116 -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 +29 -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 +49 -44
  55. package/dist/collection/classes/handlers/move.handler.js.map +1 -1
  56. package/dist/collection/classes/handlers/resize.handler.js +55 -60
  57. package/dist/collection/classes/handlers/resize.handler.js.map +1 -1
  58. package/dist/collection/classes/handlers/rotation.handler.js +59 -69
  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 +30 -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 +19 -20
  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 +237 -232
  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 +0 -14
  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/clonable.interface.js +2 -0
  158. package/dist/collection/interfaces/clonable.interface.js.map +1 -0
  159. package/dist/collection/interfaces/engine-state.interface.js.map +1 -1
  160. package/dist/collection/interfaces/serializable.interface.js.map +1 -1
  161. package/dist/collection/types/deep-readonly.type.js +2 -0
  162. package/dist/collection/types/deep-readonly.type.js.map +1 -0
  163. package/dist/components/index.js +3 -3
  164. package/dist/components/kritzel-brush-style.js +59 -1
  165. package/dist/components/kritzel-brush-style.js.map +1 -1
  166. package/dist/components/kritzel-color-palette.js +1 -1
  167. package/dist/components/kritzel-color.js +1 -1
  168. package/dist/components/kritzel-context-menu.js +1 -1
  169. package/dist/components/kritzel-control-brush-config.js +1 -1
  170. package/dist/components/kritzel-control-text-config.js +1 -1
  171. package/dist/components/kritzel-controls.js +1 -1
  172. package/dist/components/kritzel-cursor-trail.js +1 -1
  173. package/dist/components/kritzel-dropdown.js +1 -1
  174. package/dist/components/kritzel-editor.js +80 -37
  175. package/dist/components/kritzel-editor.js.map +1 -1
  176. package/dist/components/kritzel-engine.js +1 -1
  177. package/dist/components/kritzel-font-family.js +1 -1
  178. package/dist/components/kritzel-font-size.js +1 -1
  179. package/dist/components/kritzel-font.js +1 -1
  180. package/dist/components/kritzel-icon.js +1 -1
  181. package/dist/components/kritzel-menu-item.js +1 -1
  182. package/dist/components/kritzel-menu.js +1 -1
  183. package/dist/components/kritzel-portal.js +1 -1
  184. package/dist/components/kritzel-split-button.js +1 -1
  185. package/dist/components/kritzel-stroke-size.js +1 -1
  186. package/dist/components/kritzel-tooltip.js +1 -1
  187. package/dist/components/kritzel-utility-panel.js +1 -1
  188. package/dist/components/kritzel-workspace-manager.js +1 -1
  189. package/dist/components/{p-CMJ3P0Vw.js → p-0iJh9Z6m.js} +5 -5
  190. package/dist/components/p-0iJh9Z6m.js.map +1 -0
  191. package/dist/components/p-B0kd2rUI.js +16 -0
  192. package/dist/components/p-B0kd2rUI.js.map +1 -0
  193. package/dist/components/{p-BB5R2k1o.js → p-B3LGnqFz.js} +41 -31
  194. package/dist/components/p-B3LGnqFz.js.map +1 -0
  195. package/dist/components/{p-BB0_-X42.js → p-B7kZ1_RH.js} +4 -4
  196. package/dist/components/{p-BB0_-X42.js.map → p-B7kZ1_RH.js.map} +1 -1
  197. package/dist/components/{p-t4NIsuX9.js → p-B7w19kIk.js} +15 -27
  198. package/dist/components/p-B7w19kIk.js.map +1 -0
  199. package/dist/components/{p-B1BLgWL1.js → p-BGdsAz54.js} +27 -18
  200. package/dist/components/p-BGdsAz54.js.map +1 -0
  201. package/dist/components/{p-CGmS8wnN.js → p-BKvOO7NT.js} +26 -16
  202. package/dist/components/p-BKvOO7NT.js.map +1 -0
  203. package/dist/components/{p-BhiYvSBc.js → p-BM9IjvnD.js} +3 -3
  204. package/dist/components/p-BM9IjvnD.js.map +1 -0
  205. package/dist/components/{p-BrBQUN0Q.js → p-BPsQrpzN.js} +40 -11
  206. package/dist/components/p-BPsQrpzN.js.map +1 -0
  207. package/dist/components/p-C6qB08BS.js +68 -0
  208. package/dist/components/p-C6qB08BS.js.map +1 -0
  209. package/dist/components/{p-BPz_H-EG.js → p-CM8KdFZI.js} +28 -16
  210. package/dist/components/p-CM8KdFZI.js.map +1 -0
  211. package/dist/components/{p-DHSEK3rF.js → p-CNTK3JOp.js} +174 -153
  212. package/dist/components/p-CNTK3JOp.js.map +1 -0
  213. package/dist/components/{p-DMrtdhBD.js → p-CsyM5q2M.js} +7 -7
  214. package/dist/components/p-CsyM5q2M.js.map +1 -0
  215. package/dist/components/{p-BuewJQNl.js → p-CwH-bwjb.js} +1187 -1141
  216. package/dist/components/p-CwH-bwjb.js.map +1 -0
  217. package/dist/components/{p-BgmKrd5Z.js → p-DCx3703u.js} +5 -5
  218. package/dist/components/p-DCx3703u.js.map +1 -0
  219. package/dist/components/{p-trncBp_6.js → p-DFO-6kuA.js} +15 -15
  220. package/dist/components/p-DFO-6kuA.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-BeljsQ-8.js → p-Dw4n-4zp.js} +32 -17
  228. package/dist/components/p-Dw4n-4zp.js.map +1 -0
  229. package/dist/components/{p-DxTu1aoJ.js → p-NP1Htol7.js} +7 -45
  230. package/dist/components/p-NP1Htol7.js.map +1 -0
  231. package/dist/components/p-YqK8ch2R.js +46 -0
  232. package/dist/components/p-YqK8ch2R.js.map +1 -0
  233. package/dist/components/p-l10It7Nm.js +30 -0
  234. package/dist/components/p-l10It7Nm.js.map +1 -0
  235. package/dist/components/{p-p1Jkec_q.js → p-sq9jgfX0.js} +3 -3
  236. package/dist/components/p-sq9jgfX0.js.map +1 -0
  237. package/dist/components/{p-yZ48g7-u.js → p-sreNwi0N.js} +4 -4
  238. package/dist/components/{p-yZ48g7-u.js.map → p-sreNwi0N.js.map} +1 -1
  239. package/dist/esm/{index-B-oSk-v8.js → index-DY3KqYWc.js} +756 -702
  240. package/dist/esm/index-DY3KqYWc.js.map +1 -0
  241. package/dist/esm/index-oCOlsFCN.js +6 -2
  242. package/dist/esm/index.js +1 -1
  243. package/dist/esm/kritzel-brush-style.entry.js +30 -0
  244. package/dist/esm/kritzel-brush-style.entry.js.map +1 -0
  245. package/dist/esm/{kritzel-brush-style_23.entry.js → kritzel-color_22.entry.js} +1048 -875
  246. package/dist/esm/loader.js +1 -1
  247. package/dist/esm/stencil.js +1 -1
  248. package/dist/stencil/index.esm.js +1 -1
  249. package/dist/stencil/kritzel-brush-style.entry.esm.js.map +1 -0
  250. package/dist/stencil/p-25d1e040.entry.js +2 -0
  251. package/dist/stencil/p-25d1e040.entry.js.map +1 -0
  252. package/dist/stencil/p-DY3KqYWc.js +2 -0
  253. package/dist/stencil/p-DY3KqYWc.js.map +1 -0
  254. package/dist/stencil/p-dc534b01.entry.js +2 -0
  255. package/dist/stencil/p-dc534b01.entry.js.map +1 -0
  256. package/dist/stencil/stencil.esm.js +1 -1
  257. package/dist/types/classes/commands/add-object.command.d.ts +2 -2
  258. package/dist/types/classes/commands/add-selection-group.command.d.ts +2 -1
  259. package/dist/types/classes/commands/base.command.d.ts +3 -3
  260. package/dist/types/classes/commands/batch.command.d.ts +2 -1
  261. package/dist/types/classes/commands/move-selection-group.command.d.ts +2 -1
  262. package/dist/types/classes/commands/remove-object.command.d.ts +2 -2
  263. package/dist/types/classes/commands/remove-selection-group.command.d.ts +2 -2
  264. package/dist/types/classes/commands/resize-selection-group.command.d.ts +2 -1
  265. package/dist/types/classes/commands/rotate-selection-group.command.d.ts +2 -1
  266. package/dist/types/classes/commands/update-object.command.d.ts +2 -2
  267. package/dist/types/classes/commands/update-viewport.command.d.ts +2 -1
  268. package/dist/types/classes/{store.class.d.ts → core/core.class.d.ts} +9 -19
  269. package/dist/types/classes/{database.class.d.ts → core/database.class.d.ts} +3 -2
  270. package/dist/types/classes/{history.class.d.ts → core/history.class.d.ts} +5 -5
  271. package/dist/types/classes/core/reviver.class.d.ts +6 -0
  272. package/dist/types/classes/core/store.class.d.ts +17 -0
  273. package/dist/types/classes/{viewport.class.d.ts → core/viewport.class.d.ts} +3 -3
  274. package/dist/types/classes/core/workspace.class.d.ts +24 -0
  275. package/dist/types/classes/handlers/base.handler.d.ts +3 -3
  276. package/dist/types/classes/handlers/context-menu.handler.d.ts +2 -2
  277. package/dist/types/classes/handlers/hover.handler.d.ts +2 -2
  278. package/dist/types/classes/handlers/key.handler.d.ts +2 -2
  279. package/dist/types/classes/handlers/move.handler.d.ts +4 -2
  280. package/dist/types/classes/handlers/resize.handler.d.ts +3 -2
  281. package/dist/types/classes/handlers/rotation.handler.d.ts +6 -2
  282. package/dist/types/classes/handlers/selection.handler.d.ts +2 -2
  283. package/dist/types/classes/objects/base-object.class.d.ts +8 -5
  284. package/dist/types/classes/objects/custom-element.class.d.ts +2 -2
  285. package/dist/types/classes/objects/image.class.d.ts +2 -2
  286. package/dist/types/classes/objects/path.class.d.ts +2 -2
  287. package/dist/types/classes/objects/selection-box.class.d.ts +2 -2
  288. package/dist/types/classes/objects/selection-group.class.d.ts +2 -2
  289. package/dist/types/classes/objects/text.class.d.ts +2 -2
  290. package/dist/types/classes/registries/tool.registry.d.ts +2 -2
  291. package/dist/types/classes/tools/base-tool.class.d.ts +8 -4
  292. package/dist/types/classes/tools/brush-tool.class.d.ts +2 -2
  293. package/dist/types/classes/tools/eraser-tool.class.d.ts +2 -2
  294. package/dist/types/classes/tools/image-tool.class.d.ts +2 -2
  295. package/dist/types/classes/tools/selection-tool.class.d.ts +2 -2
  296. package/dist/types/classes/tools/text-tool.class.d.ts +2 -2
  297. package/dist/types/components/core/kritzel-cursor-trail/kritzel-cursor-trail.d.ts +5 -5
  298. package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +13 -3
  299. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +21 -22
  300. package/dist/types/components/shared/kritzel-dropdown/kritzel-dropdown.d.ts +2 -2
  301. package/dist/types/components/shared/kritzel-menu-item/kritzel-menu-item.d.ts +2 -0
  302. package/dist/types/components/shared/kritzel-portal/kritzel-portal.d.ts +0 -1
  303. package/dist/types/components/shared/kritzel-split-button/kritzel-split-button.d.ts +4 -2
  304. package/dist/types/components/shared/kritzel-tooltip/kritzel-tooltip.d.ts +8 -2
  305. package/dist/types/components/ui/kritzel-context-menu/kritzel-context-menu.d.ts +5 -3
  306. package/dist/types/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.d.ts +1 -1
  307. package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +3 -1
  308. package/dist/types/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.d.ts +3 -2
  309. package/dist/types/components.d.ts +41 -12
  310. package/dist/types/helpers/devices.helper.d.ts +4 -0
  311. package/dist/types/helpers/event.helper.d.ts +1 -1
  312. package/dist/types/helpers/html.helper.d.ts +1 -0
  313. package/dist/types/helpers/object.helper.d.ts +0 -2
  314. package/dist/types/index.d.ts +1 -1
  315. package/dist/types/interfaces/clonable.interface.d.ts +3 -0
  316. package/dist/types/interfaces/engine-state.interface.d.ts +1 -2
  317. package/dist/types/interfaces/serializable.interface.d.ts +2 -1
  318. package/dist/types/types/deep-readonly.type.d.ts +7 -0
  319. package/package.json +3 -2
  320. package/dist/cjs/index-BwINBV6L.js.map +0 -1
  321. package/dist/collection/classes/database.class.js.map +0 -1
  322. package/dist/collection/classes/history.class.js +0 -88
  323. package/dist/collection/classes/history.class.js.map +0 -1
  324. package/dist/collection/classes/reviver.class.js.map +0 -1
  325. package/dist/collection/classes/store.class.js.map +0 -1
  326. package/dist/collection/classes/viewport.class.js +0 -153
  327. package/dist/collection/classes/viewport.class.js.map +0 -1
  328. package/dist/collection/classes/workspace.class.js +0 -15
  329. package/dist/collection/classes/workspace.class.js.map +0 -1
  330. package/dist/components/p-B1BLgWL1.js.map +0 -1
  331. package/dist/components/p-BB5R2k1o.js.map +0 -1
  332. package/dist/components/p-BPz_H-EG.js.map +0 -1
  333. package/dist/components/p-B_lb1FGi.js +0 -19
  334. package/dist/components/p-B_lb1FGi.js.map +0 -1
  335. package/dist/components/p-BeljsQ-8.js.map +0 -1
  336. package/dist/components/p-BexTdWaX.js.map +0 -1
  337. package/dist/components/p-BgmKrd5Z.js.map +0 -1
  338. package/dist/components/p-BhiYvSBc.js.map +0 -1
  339. package/dist/components/p-BrBQUN0Q.js.map +0 -1
  340. package/dist/components/p-BubxwvMA.js.map +0 -1
  341. package/dist/components/p-BuewJQNl.js.map +0 -1
  342. package/dist/components/p-CGmS8wnN.js.map +0 -1
  343. package/dist/components/p-CJKA5zIE.js +0 -10
  344. package/dist/components/p-CJKA5zIE.js.map +0 -1
  345. package/dist/components/p-CMJ3P0Vw.js.map +0 -1
  346. package/dist/components/p-DHSEK3rF.js.map +0 -1
  347. package/dist/components/p-DMrtdhBD.js.map +0 -1
  348. package/dist/components/p-DnUKql15.js +0 -30
  349. package/dist/components/p-DnUKql15.js.map +0 -1
  350. package/dist/components/p-DxTu1aoJ.js.map +0 -1
  351. package/dist/components/p-p1Jkec_q.js.map +0 -1
  352. package/dist/components/p-rIRXQdie.js +0 -64
  353. package/dist/components/p-rIRXQdie.js.map +0 -1
  354. package/dist/components/p-t4NIsuX9.js.map +0 -1
  355. package/dist/components/p-trncBp_6.js.map +0 -1
  356. package/dist/esm/index-B-oSk-v8.js.map +0 -1
  357. package/dist/stencil/p-3bb80782.entry.js +0 -2
  358. package/dist/stencil/p-3bb80782.entry.js.map +0 -1
  359. package/dist/stencil/p-B-oSk-v8.js +0 -2
  360. package/dist/stencil/p-B-oSk-v8.js.map +0 -1
  361. package/dist/types/classes/reviver.class.d.ts +0 -6
  362. package/dist/types/classes/workspace.class.d.ts +0 -16
@@ -1,33 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var index = require('./index-nzUNdMPh.js');
4
- var index$1 = require('./index-BwINBV6L.js');
5
-
6
- const kritzelBrushStyleCss = ":host{display:flex;align-items:flex-start;gap:8px;padding:8px;box-sizing:border-box;width:100%}.brush-style-button{display:flex;justify-content:center;align-items:center;width:42px;height:32px;padding:0;border:none;outline:none;background:none;cursor:default;border-radius:0;color:var(--control-text-color);font-weight:bold;-webkit-tap-highlight-color:transparent}.font-style-button:not(:last-child){border-right:1px solid #333333}.font-style-button:hover{background-color:var(--control-hover-bg)}.font-style-button:active{background-color:var(--control-active-bg)}.font-style-button.selected,.font-style-button.selected:hover,.font-style-button.selected:active{background-color:var(--control-selected-bg);color:var(--control-selected-color)}";
7
-
8
- const KritzelBrushStyle = class {
9
- constructor(hostRef) {
10
- index.registerInstance(this, hostRef);
11
- this.typeChange = index.createEvent(this, "typeChange");
12
- }
13
- type = 'pen';
14
- brushOptions = [
15
- { value: 'pen', label: 'Pen' },
16
- { value: 'highlighter', label: 'Highlighter' },
17
- ];
18
- typeChange;
19
- handleDropdownValueChange(event) {
20
- this.typeChange.emit(event.detail);
21
- }
22
- render() {
23
- const dropdownOptions = this.brushOptions.map(option => ({
24
- value: option.value,
25
- label: option.label,
26
- }));
27
- return (index.h(index.Host, { key: 'd7af382fe6f613aa16a5146785990ad2faa17f60' }, index.h("kritzel-dropdown", { key: '6d6d330d415c210058834b2968774b3db2ab7fc4', options: dropdownOptions, value: this.type, onValueChanged: event => this.handleDropdownValueChange(event) }, index.h("button", { key: 'c9fb33795b8e25f68c1d2ae248dc82a6de29e199', class: "brush-style-button", slot: "prefix" }, index.h("kritzel-icon", { key: '975c95b545a1c27ae2984405ac298592eec9743d', name: this.type, size: 16 })))));
28
- }
29
- };
30
- KritzelBrushStyle.style = kritzelBrushStyleCss;
4
+ var index$1 = require('./index-DCHCVnOl.js');
31
5
 
32
6
  const kritzelColorCss = ":host{display:flex}.checkerboard-bg{background:repeating-conic-gradient(#ccc 0% 25%, #fff 0% 50%) 50% / 8px 8px;position:relative;overflow:hidden}.color-circle{width:24px;height:24px;border-radius:50%;box-sizing:border-box;display:block}.color-circle.white{border:1px solid var(--kritzel-color-palette-circle-border-color, #dddcdc)}";
33
7
 
@@ -63,13 +37,13 @@ const KritzelColor = class {
63
37
  }
64
38
  render() {
65
39
  const isColorVeryLight = this.isLightColor(this.value);
66
- return (index.h(index.Host, { key: '1468f3502f7d10d182ac72a05ce4b1e520353f8a' }, index.h("div", { key: 'd30d47667b1b72a970c4ee0da887dd59a663eae7', class: "checkerboard-bg", style: {
40
+ return (index.h(index.Host, { key: '198dba41e1600d76faace18de78191d2b7a551ec' }, index.h("div", { key: 'ee690cffb7925e09cb2c51022eec607247a4849f', class: "checkerboard-bg", style: {
67
41
  width: `${this.size}px`,
68
42
  height: `${this.size}px`,
69
43
  borderRadius: '50%',
70
44
  display: 'inline-block',
71
45
  position: 'relative',
72
- } }, index.h("div", { key: '073fd85967e53b609103a9fe47028bcda849e5ec', class: {
46
+ } }, index.h("div", { key: '66cc8df8fabd008db8c00942994875e3e8d722ce', class: {
73
47
  'color-circle': true,
74
48
  'white': isColorVeryLight,
75
49
  }, style: {
@@ -86,7 +60,7 @@ const KritzelColor = class {
86
60
  };
87
61
  KritzelColor.style = kritzelColorCss;
88
62
 
89
- const kritzelColorPaletteCss = ":host{display:flex;align-items:flex-start;gap:8px;padding:8px;width:100%;box-sizing:border-box}.color-grid{width:100%;display:grid;grid-template-columns:repeat(6, 32px);gap:8px;justify-items:center;overflow:hidden;height:40px;transition:height 0.1s ease-in-out}.color-grid.expanded{height:500px}.color-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:pointer;border:2px solid transparent;box-sizing:border-box}.color-container:hover{background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.color-container.selected{border-color:var(--kritzel-selection-border-color, #007AFF);background-color:var(--kritzel-color-palette-selected-background-color)}";
63
+ const kritzelColorPaletteCss = ":host{display:flex;align-items:flex-start;gap:8px;padding:8px;width:100%;box-sizing:border-box}.color-grid{width:100%;display:grid;grid-template-columns:repeat(6, 32px);gap:8px;justify-items:center;overflow:hidden;height:40px;transition:height 0.1s ease-in-out}.color-grid.expanded{height:500px}.color-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:pointer;border:2px solid transparent;box-sizing:border-box}.color-container:focus-visible{outline:var(--kritzel-color-palette-focus-outline, 2px auto #e3e3e3)}.color-container:hover{background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.color-container.selected{border-color:var(--kritzel-selection-border-color, #007AFF);background-color:var(--kritzel-color-palette-selected-background-color)}";
90
64
 
91
65
  const KritzelColorPalette = class {
92
66
  constructor(hostRef) {
@@ -112,12 +86,12 @@ const KritzelColorPalette = class {
112
86
  render() {
113
87
  const displayedColors = this.isExpanded ? this.colors : this.colors.slice(0, 6);
114
88
  const expandedHeight = this.isExpanded ? this.calculateHeight() : '32px';
115
- return (index.h(index.Host, { key: 'dddc32b0904800092d45727e833181af32eb8766' }, index.h("div", { key: '293cbed8e9c62b5f409b7dcdca0df5de9d65b758', class: {
89
+ return (index.h(index.Host, { key: '2ead7cd530ce181856e5f582f086a22a1fe69390' }, index.h("div", { key: 'fcc75b267f36e271d50615bfde42a29c28aa2536', class: {
116
90
  'color-grid': true,
117
91
  'expanded': this.isExpanded,
118
92
  }, style: {
119
- height: expandedHeight
120
- } }, displayedColors.map(color => (index.h("div", { class: {
93
+ height: expandedHeight,
94
+ } }, displayedColors.map(color => (index.h("div", { tabIndex: 0, class: {
121
95
  'color-container': true,
122
96
  'selected': this.selectedColor === color,
123
97
  }, onClick: () => this.handleColorClick(color) }, index.h("kritzel-color", { value: color })))))));
@@ -131,16 +105,25 @@ const KritzelContextMenu = class {
131
105
  constructor(hostRef) {
132
106
  index.registerInstance(this, hostRef);
133
107
  this.actionSelected = index.createEvent(this, "actionSelected");
108
+ this.close = index.createEvent(this, "close");
134
109
  }
110
+ get host() { return index.getElement(this); }
135
111
  items;
112
+ onItemsChanged() {
113
+ this.updateMenuItems();
114
+ }
136
115
  objects;
137
116
  actionSelected;
138
- get hostElement() { return index.getElement(this); }
117
+ close;
139
118
  processedItems = [];
140
- componentWillLoad() {
141
- this.updateMenuItems();
119
+ handleOutsideClick(event) {
120
+ event.preventDefault();
121
+ const path = event.composedPath();
122
+ if (!path.includes(this.host)) {
123
+ this.close.emit();
124
+ }
142
125
  }
143
- onItemsChanged() {
126
+ componentWillLoad() {
144
127
  this.updateMenuItems();
145
128
  }
146
129
  handleItemClick(item, isDisabled) {
@@ -148,15 +131,6 @@ const KritzelContextMenu = class {
148
131
  this.actionSelected.emit(item);
149
132
  }
150
133
  }
151
- async evaluateProperty(value, defaultValue) {
152
- if (typeof value === 'boolean') {
153
- return value;
154
- }
155
- if (typeof value === 'function') {
156
- return await Promise.resolve(value(null, this.objects));
157
- }
158
- return defaultValue;
159
- }
160
134
  async updateMenuItems() {
161
135
  const processed = [];
162
136
  for (const item of this.items) {
@@ -168,8 +142,17 @@ const KritzelContextMenu = class {
168
142
  }
169
143
  this.processedItems = processed;
170
144
  }
145
+ async evaluateProperty(value, defaultValue) {
146
+ if (typeof value === 'boolean') {
147
+ return value;
148
+ }
149
+ if (typeof value === 'function') {
150
+ return await Promise.resolve(value(null, this.objects));
151
+ }
152
+ return defaultValue;
153
+ }
171
154
  render() {
172
- return (index.h(index.Host, { key: '96569454f806a6d17380315b4d0200236fe22550' }, index.h("div", { key: '0e5899a2901e1e9ab9d657824e105121ce785bdc', class: "menu-container" }, this.processedItems.map(({ item, isDisabled }, index$1) => (index.h("button", { key: `${item.label}-${index$1}`, class: { 'menu-item': true, disabled: isDisabled }, onClick: () => this.handleItemClick(item, isDisabled), onTouchStart: () => this.handleItemClick(item, isDisabled), disabled: isDisabled }, item.icon && index.h("kritzel-icon", { name: item.icon, size: 16 }), index.h("span", { class: "label" }, item.label)))))));
155
+ return (index.h(index.Host, { key: 'ff72bd31f6c0f3193674710bccab829f14e011d3' }, index.h("div", { key: '80cd7a99dc9bb1fb9ec4edb09a9bacde70dde7c3', class: "menu-container" }, this.processedItems.map(({ item, isDisabled }, index$1) => (index.h("button", { key: `${item.label}-${index$1}`, class: { 'menu-item': true, 'disabled': isDisabled }, onClick: () => this.handleItemClick(item, isDisabled), disabled: isDisabled }, item.icon && index.h("kritzel-icon", { name: item.icon, size: 16 }), index.h("span", { class: "label" }, item.label)))))));
173
156
  }
174
157
  static get watchers() { return {
175
158
  "items": ["onItemsChanged"]
@@ -177,7 +160,7 @@ const KritzelContextMenu = class {
177
160
  };
178
161
  KritzelContextMenu.style = kritzelContextMenuCss;
179
162
 
180
- const kritzelControlBrushConfigCss = ":host{display:flex;flex-direction:column;width:100%}.expand-toggle{background:none;border:none;cursor:pointer;font-size:14px;line-height:1;padding:8px;color:var(--kritzel-color-palette-expand-toggle-color, #666666)}.expand-toggle:hover{color:var(--kritzel-color-palette-expand-toggle-hover-color, #333333)}";
163
+ const kritzelControlBrushConfigCss = ":host{display:flex;flex-direction:column;width:100%}.expand-toggle{background:none;border:none;cursor:pointer;font-size:14px;line-height:1;padding:8px;color:var(--kritzel-color-palette-expand-toggle-color, #666666)}.expand-toggle:focus-visible{outline:var(--kritzel-color-palette-focus-outline, 2px auto #e3e3e3)}.expand-toggle:hover{color:var(--kritzel-color-palette-expand-toggle-hover-color, #333333)}";
181
164
 
182
165
  const KritzelControlBrushConfig = class {
183
166
  constructor(hostRef) {
@@ -185,12 +168,12 @@ const KritzelControlBrushConfig = class {
185
168
  this.toolChange = index.createEvent(this, "toolChange");
186
169
  }
187
170
  tool;
188
- isExpanded = false;
189
- toolChange;
190
- palette = [];
191
171
  handleToolChange(newTool) {
192
172
  this.palette = newTool.palettes[newTool.type];
193
173
  }
174
+ isExpanded = false;
175
+ toolChange;
176
+ palette = [];
194
177
  componentWillLoad() {
195
178
  this.palette = this.tool.palettes[this.tool.type];
196
179
  }
@@ -212,14 +195,14 @@ const KritzelControlBrushConfig = class {
212
195
  this.toolChange.emit(this.tool);
213
196
  }
214
197
  render() {
215
- return (index.h(index.Host, { key: 'a1f04aba4ed04e91c7b375e0f88bcff4fea1cba4' }, index.h("div", { key: 'c7cd734c96498c8cd6a27321fb6d11773e7aa8a9', style: {
198
+ return (index.h(index.Host, { key: '8fe8c0564f491121c0c44c6ff4083034f92dbb67' }, index.h("div", { key: '3e8a69b827785976768bfc1e809126bee7c48c62', style: {
216
199
  display: 'flex',
217
200
  flexDirection: 'row',
218
- alignItems: 'center',
201
+ alignItems: this.isExpanded ? 'flex-start' : 'center',
219
202
  justifyContent: 'flex-start',
220
203
  width: '100%',
221
204
  gap: '8px',
222
- } }, index.h("kritzel-brush-style", { key: '67958dc2a34302eb23fabbafea3c7dc7863f1984', type: this.tool.type, onTypeChange: event => this.handleTypeChange(event) }), index.h("button", { key: '5c84a72d9f337dff253a161abe19acb832275272', class: "expand-toggle", onClick: () => this.handleToggleExpand(), title: this.isExpanded ? 'Collapse' : 'Expand', style: this.palette.length > 6 ? { visibillity: 'visible' } : { visibility: 'hidden' } }, index.h("kritzel-icon", { key: 'b3e0c44db35b53a584757e18b507df09f30bfa8a', name: this.isExpanded ? 'chevron-up' : 'chevron-down' }))), index.h("kritzel-color-palette", { key: 'eb098094ae69aa5901244f9686a3eb990271c07d', colors: this.palette, selectedColor: this.tool.color, isExpanded: this.isExpanded, isOpaque: true, onColorChange: color => this.handleColorChange(color) }), index.h("kritzel-stroke-size", { key: '18ae184b282ca2ec6511a6ac0065914edf66f91b', selectedSize: this.tool.size, onSizeChange: event => this.handleSizeChange(event) })));
205
+ } }, index.h("kritzel-color-palette", { key: 'c9056f81cf47d81fef0a0f5743000dcd6633258a', colors: this.palette, selectedColor: this.tool.color, isExpanded: this.isExpanded, isOpaque: true, onColorChange: color => this.handleColorChange(color) }), index.h("button", { key: '2f307264b80a732d976edeb025d509bc1164606b', class: "expand-toggle", onClick: () => this.handleToggleExpand(), title: this.isExpanded ? 'Collapse' : 'Expand', style: this.palette.length > 6 ? { visibillity: 'visible' } : { visibility: 'hidden' } }, index.h("kritzel-icon", { key: '08133ba0a23353b2bb3f87c685a7a0798b8dd16c', name: this.isExpanded ? 'chevron-up' : 'chevron-down' }))), index.h("kritzel-stroke-size", { key: '3de25cc80029ffdfdc173c4c79e937a7dc329743', selectedSize: this.tool.size, onSizeChange: event => this.handleSizeChange(event) })));
223
206
  }
224
207
  static get watchers() { return {
225
208
  "tool": ["handleToolChange"]
@@ -253,14 +236,14 @@ const KritzelControlTextConfig = class {
253
236
  this.toolChange.emit(this.tool);
254
237
  }
255
238
  render() {
256
- return (index.h(index.Host, { key: 'a5c0e3eb4343637d758888d7d2a0843549fa0c25' }, index.h("div", { key: '1d4d42af117ed9da1a91d1747a7d6f6531e0de9b', style: {
239
+ return (index.h(index.Host, { key: '3695b187943af25566885d63257ae3de9f405ea5' }, index.h("div", { key: '7bb146ae3c188478ba17f18f70fd170ce3536308', style: {
257
240
  display: 'flex',
258
241
  flexDirection: 'row',
259
242
  alignItems: 'center',
260
243
  justifyContent: 'flex-start',
261
244
  width: '100%',
262
245
  gap: '8px',
263
- } }, index.h("kritzel-font-family", { key: 'b19e1edcbc7bafb0829d3e173d33cff37d2a5959', selectedFontFamily: this.tool.fontFamily, onFontFamilyChange: event => this.handleFamilyChange(event) }), index.h("button", { key: 'ca3dce970ee5dd1a7c8c617127777859b45380c4', class: "expand-toggle", onClick: () => this.handleToggleExpand(), title: this.isExpanded ? 'Collapse' : 'Expand' }, index.h("kritzel-icon", { key: '241d82cd06db8d20794a369a4df6e6a71531131a', name: this.isExpanded ? 'chevron-up' : 'chevron-down' }))), index.h("kritzel-color-palette", { key: 'ec82e5c09046e70e904cc1ec9716c53bec9cac2b', colors: this.tool.palette, selectedColor: this.tool.fontColor, isExpanded: this.isExpanded, onColorChange: event => this.handleColorChange(event) }), index.h("kritzel-font-size", { key: '1cbddf6e6de21bd62f3803cca9e21ef9e01f15c0', selectedSize: this.tool.fontSize, fontFamily: this.tool.fontFamily, onSizeChange: event => this.handleSizeChange(event) })));
246
+ } }, index.h("kritzel-font-family", { key: '87f4c5ac2e2a4cfea216b1b828faad231438b9ec', selectedFontFamily: this.tool.fontFamily, onFontFamilyChange: event => this.handleFamilyChange(event) }), index.h("button", { key: '2e73aaf7da659b9e069c247cc762f68394212293', class: "expand-toggle", onClick: () => this.handleToggleExpand(), title: this.isExpanded ? 'Collapse' : 'Expand' }, index.h("kritzel-icon", { key: '785b664697ba266432c535ea26e0665f8d8d657f', name: this.isExpanded ? 'chevron-up' : 'chevron-down' }))), index.h("kritzel-color-palette", { key: 'ed2517a39d254b77f45154914b3ce6a934f66c33', colors: this.tool.palette, selectedColor: this.tool.fontColor, isExpanded: this.isExpanded, onColorChange: event => this.handleColorChange(event) }), index.h("kritzel-font-size", { key: '9b25c9607fa69c991e769852e3e3e378e48387bd', selectedSize: this.tool.fontSize, fontFamily: this.tool.fontFamily, onSizeChange: event => this.handleSizeChange(event) })));
264
247
  }
265
248
  };
266
249
  KritzelControlTextConfig.style = kritzelControlTextConfigCss;
@@ -269,15 +252,36 @@ class KritzelDevicesHelper {
269
252
  static isTouchDevice() {
270
253
  return window.matchMedia('(any-pointer: coarse)').matches;
271
254
  }
255
+ static isAndroid() {
256
+ return /android/i.test(navigator.userAgent);
257
+ }
258
+ static isIOS() {
259
+ return /iPad|iPhone|iPod/.test(navigator.userAgent);
260
+ }
261
+ static detectOS() {
262
+ if (this.isIOS()) {
263
+ return 'iOS';
264
+ }
265
+ else if (this.isAndroid()) {
266
+ return 'Android';
267
+ }
268
+ else {
269
+ return 'Other';
270
+ }
271
+ }
272
+ static isFirefox() {
273
+ return /firefox/i.test(navigator.userAgent);
274
+ }
272
275
  }
273
276
 
274
- const kritzelControlsCss = ":host{display:flex;flex-direction:column;user-select:none}:host(.mobile){--kritzel-controls-control-hover-background-color:transparent;--kritzel-controls-control-active-background-color:transparent}.kritzel-controls{display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:var(--kritzel-controls-gap, 8px);height:100%;padding:var(--kritzel-controls-padding, 8px);background-color:var(--kritzel-controls-background-color, #ffffff);border-radius:var(--kritzel-controls-border-radius, 16px);box-shadow:var(--kritzel-controls-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-controls-border, 1px solid #ebebeb);z-index:10000;position:relative}.kritzel-control{display:flex;justify-content:center;align-items:center;color:var(--kritzel-controls-control-color, #000000);border-radius:var(--kritzel-controls-control-border-radius, 12px);padding:var(--kritzel-controls-control-padding, 8px);border:none;outline:none;background:none;cursor:pointer;-webkit-tap-highlight-color:transparent;font-weight:bold}.kritzel-control:hover{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-control:active{background-color:var(--kritzel-controls-control-active-background-color, hsl(0, 0%, 0%, 8.6%))}.kritzel-control.selected,.kritzel-control.selected:hover,.kritzel-control.selected:active{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF) !important;color:var(--kritzel-controls-control-selected-color, #ffffff) !important}.kritzel-divider{width:var(--kritzel-controls-divider-width, 1px);height:var(--kritzel-controls-divider-height, 24px);background-color:var(--kritzel-controls-divider-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-config-container{position:relative;display:flex;justify-content:center;align-items:center;width:40px;height:40px;box-sizing:border-box;-webkit-tap-highlight-color:transparent}.kritzel-config{display:flex;justify-content:center;align-items:center;cursor:pointer}.color-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:pointer;border:2px solid transparent;box-sizing:border-box;background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.font-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:pointer;border:2px solid transparent;box-sizing:border-box;background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.no-config{height:24px;width:24px;border-radius:50%;border:1px dashed gray}kritzel-tooltip{position:fixed;bottom:66px;left:50%;transform:translateX(-50%);z-index:10001}";
277
+ const kritzelControlsCss = ":host{display:flex;flex-direction:column;user-select:none}:host(.mobile){--kritzel-controls-control-hover-background-color:transparent;--kritzel-controls-control-active-background-color:transparent}.kritzel-controls{display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:var(--kritzel-controls-gap, 8px);height:100%;padding:var(--kritzel-controls-padding, 8px);background-color:var(--kritzel-controls-background-color, #ffffff);border-radius:var(--kritzel-controls-border-radius, 16px);box-shadow:var(--kritzel-controls-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-controls-border, 1px solid #ebebeb);z-index:10000;position:relative}.kritzel-control{display:flex;justify-content:center;align-items:center;color:var(--kritzel-controls-control-color, #000000);border-radius:var(--kritzel-controls-control-border-radius, 12px);padding:var(--kritzel-controls-control-padding, 8px);border:none;outline:none;background:none;cursor:pointer;-webkit-tap-highlight-color:transparent;font-weight:bold}.kritzel-control:focus,.kritzel-control:hover{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-control:active{background-color:var(--kritzel-controls-control-active-background-color, hsl(0, 0%, 0%, 8.6%))}.kritzel-control.selected,.kritzel-control.selected:hover,.kritzel-control.selected:active{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF) !important;color:var(--kritzel-controls-control-selected-color, #ffffff) !important}.kritzel-control.selected:focus{background-color:var(--kritzel-controls-control-selected-background-color, #007bffe3) !important}.kritzel-divider{width:var(--kritzel-controls-divider-width, 1px);height:var(--kritzel-controls-divider-height, 24px);background-color:var(--kritzel-controls-divider-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-config-container{position:relative;display:flex;justify-content:center;align-items:center;width:40px;height:40px;box-sizing:border-box;-webkit-tap-highlight-color:transparent}.kritzel-config{display:flex;justify-content:center;align-items:center;cursor:pointer;border-radius:50%}.kritzel-config:focus{outline:var(--kritzel-menu-focus-outline, 2px solid #e3e3e3)}.color-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:pointer;border:2px solid transparent;box-sizing:border-box;background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.font-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:pointer;border:2px solid transparent;box-sizing:border-box;background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.no-config{height:24px;width:24px;border-radius:50%;border:1px dashed gray}kritzel-tooltip{position:fixed;bottom:56px;left:50%;transform:translateX(-50%);z-index:10001}";
275
278
 
276
279
  const KritzelControls = class {
277
280
  constructor(hostRef) {
278
281
  index.registerInstance(this, hostRef);
279
282
  this.isControlsReady = index.createEvent(this, "isControlsReady");
280
283
  }
284
+ get host() { return index.getElement(this); }
281
285
  controls = [];
282
286
  activeControl = null;
283
287
  isUtilityPanelVisible = true;
@@ -285,7 +289,6 @@ const KritzelControls = class {
285
289
  firstConfig = null;
286
290
  isTooltipVisible = false;
287
291
  isTouchDevice = KritzelDevicesHelper.isTouchDevice();
288
- get host() { return index.getElement(this); }
289
292
  handleDocumentClick(event) {
290
293
  const element = event.target;
291
294
  if (!this.kritzelEngine || element.closest('.kritzel-tooltip')) {
@@ -302,12 +305,12 @@ const KritzelControls = class {
302
305
  }
303
306
  async handleActiveToolChange(event) {
304
307
  this.activeControl = this.controls.find(control => control.tool === event.detail) || null;
305
- await this.kritzelEngine?.setFocus();
306
308
  }
307
309
  async closeTooltip() {
308
310
  this.isTooltipVisible = false;
309
311
  }
310
312
  kritzelEngine = null;
313
+ tooltipRef = null;
311
314
  get activeToolAsTextTool() {
312
315
  return this.activeControl?.tool;
313
316
  }
@@ -354,21 +357,33 @@ const KritzelControls = class {
354
357
  handleConfigClick(event) {
355
358
  event.stopPropagation();
356
359
  this.isTooltipVisible = !this.isTooltipVisible;
357
- this.kritzelEngine?.disable();
360
+ if (this.isTooltipVisible) {
361
+ this.kritzelEngine?.disable();
362
+ }
363
+ else {
364
+ this.kritzelEngine?.enable();
365
+ }
366
+ setTimeout(() => {
367
+ this.tooltipRef?.focusContent();
368
+ }, 100);
358
369
  }
359
370
  async handleToolChange(event) {
360
371
  this.activeControl = { ...this.activeControl, tool: event.detail };
361
372
  await this.kritzelEngine.changeActiveTool(this.activeControl.tool);
362
373
  }
374
+ handleTooltipClosed() {
375
+ this.isTooltipVisible = false;
376
+ this.kritzelEngine?.enable();
377
+ }
363
378
  render() {
364
379
  const hasNoConfig = this.activeControl?.config === undefined || this.activeControl?.config === null;
365
- return (index.h(index.Host, { key: '7ab1f3e176848cb9a34be7e7b90e13c2a861d78b', class: {
380
+ return (index.h(index.Host, { key: 'a463310d88265b71097f838bf775abdcabc99225', class: {
366
381
  mobile: this.isTouchDevice,
367
- } }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: 'f168b27cb9cc3a1a7d0028055cd58c60cec9776f', style: {
382
+ } }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '267e9c26b41a52c655209dbaa8c85cbd72323577', style: {
368
383
  position: 'absolute',
369
384
  bottom: '56px',
370
385
  left: '12px',
371
- }, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '9e568217b23632d73b051350d7f795f0cd7ab9ed', class: "kritzel-controls" }, this.controls.map(control => {
386
+ }, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: 'c55773245c925e1b972f3e83cb4d8f1c93ebe995', class: "kritzel-controls" }, this.controls.map(control => {
372
387
  if (control.type === 'tool') {
373
388
  return (index.h("button", { class: {
374
389
  'kritzel-control': true,
@@ -379,7 +394,11 @@ const KritzelControls = class {
379
394
  return index.h("div", { class: "kritzel-divider", key: control.name });
380
395
  }
381
396
  if (control.type === 'config' && control.name === this.firstConfig?.name && this.activeControl) {
382
- return (index.h("div", { class: "kritzel-config-container", key: control.name }, index.h("kritzel-tooltip", { isVisible: this.isTooltipVisible, anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container') }, index.h("div", { style: { width: '294px', height: '100%' } }, this.activeControl.name === 'brush' && (index.h("kritzel-control-brush-config", { tool: this.activeToolAsBrushTool, onToolChange: event => this.handleToolChange?.(event) })), this.activeControl.name === 'text' && (index.h("kritzel-control-text-config", { tool: this.activeToolAsTextTool, onToolChange: event => this.handleToolChange?.(event) })))), index.h("div", { class: "kritzel-config", onClick: event => this.handleConfigClick?.(event), style: {
397
+ return (index.h("div", { class: "kritzel-config-container", key: control.name }, index.h("kritzel-tooltip", { ref: el => (this.tooltipRef = el), isVisible: this.isTooltipVisible, anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), onTooltipClosed: () => this.handleTooltipClosed() }, index.h("div", { style: { width: '294px', height: '100%' } }, this.activeControl.name === 'brush' && (index.h("kritzel-control-brush-config", { tool: this.activeToolAsBrushTool, onToolChange: event => this.handleToolChange?.(event) })), this.activeControl.name === 'text' && (index.h("kritzel-control-text-config", { tool: this.activeToolAsTextTool, onToolChange: event => this.handleToolChange?.(event) })))), index.h("div", { tabIndex: 0, class: "kritzel-config", onClick: event => this.handleConfigClick?.(event), onKeyDown: event => {
398
+ if (event.key === 'Enter') {
399
+ this.handleConfigClick?.(event);
400
+ }
401
+ }, style: {
383
402
  cursor: this.activeControl.config ? 'pointer' : 'default',
384
403
  pointerEvents: hasNoConfig ? 'none' : 'auto',
385
404
  } }, this.activeControl.tool instanceof index$1.KritzelBrushTool && (index.h("div", { class: "color-container" }, index.h("kritzel-color", { value: this.activeToolAsBrushTool?.color, size: this.activeToolAsBrushTool?.size, style: {
@@ -399,26 +418,9 @@ const KritzelCursorTrail = class {
399
418
  constructor(hostRef) {
400
419
  index.registerInstance(this, hostRef);
401
420
  }
402
- store;
421
+ core;
403
422
  cursorTrailPoints = [];
404
423
  isLeftButtonDown = false;
405
- trailCleanupIntervalId;
406
- TRAIL_DURATION_MS = 100;
407
- MAX_TRAIL_POINTS = 50;
408
- componentDidLoad() {
409
- this.trailCleanupIntervalId = window.setInterval(() => {
410
- const now = Date.now();
411
- const newTrailPoints = this.cursorTrailPoints.filter(p => now - p.timestamp < this.TRAIL_DURATION_MS);
412
- if (newTrailPoints.length !== this.cursorTrailPoints.length) {
413
- this.cursorTrailPoints = newTrailPoints;
414
- }
415
- }, 50);
416
- }
417
- disconnectedCallback() {
418
- if (this.trailCleanupIntervalId) {
419
- window.clearInterval(this.trailCleanupIntervalId);
420
- }
421
- }
422
424
  handleMouseDown(ev) {
423
425
  if (ev.pointerType === 'mouse') {
424
426
  if (ev.button === index$1.KritzelMouseButton.Left) {
@@ -427,7 +429,7 @@ const KritzelCursorTrail = class {
427
429
  }
428
430
  }
429
431
  if (ev.pointerType === 'touch') {
430
- if (this.store.state.pointers.size === 1) {
432
+ if (this.core.store.state.pointers.size === 1) {
431
433
  this.isLeftButtonDown = true;
432
434
  this.cursorTrailPoints = [];
433
435
  }
@@ -454,14 +456,31 @@ const KritzelCursorTrail = class {
454
456
  }
455
457
  }
456
458
  if (ev.pointerType === 'touch') {
457
- if (this.store.state.pointers.size === 0) {
459
+ if (this.core.store.state.pointers.size === 0) {
458
460
  this.isLeftButtonDown = false;
459
461
  this.cursorTrailPoints = [];
460
462
  }
461
463
  }
462
464
  }
465
+ trailCleanupIntervalId;
466
+ TRAIL_DURATION_MS = 100;
467
+ MAX_TRAIL_POINTS = 50;
468
+ componentDidLoad() {
469
+ this.trailCleanupIntervalId = window.setInterval(() => {
470
+ const now = Date.now();
471
+ const newTrailPoints = this.cursorTrailPoints.filter(p => now - p.timestamp < this.TRAIL_DURATION_MS);
472
+ if (newTrailPoints.length !== this.cursorTrailPoints.length) {
473
+ this.cursorTrailPoints = newTrailPoints;
474
+ }
475
+ }, 50);
476
+ }
477
+ disconnectedCallback() {
478
+ if (this.trailCleanupIntervalId) {
479
+ window.clearInterval(this.trailCleanupIntervalId);
480
+ }
481
+ }
463
482
  render() {
464
- return (index.h(index.Host, { key: 'c519ab89ffb793de887a870bafe8772f7584f097' }, this.cursorTrailPoints.length > 1 && (index.h("svg", { key: 'db7ac0975c5a39c0b68d8fd4af4edd4d15f439f3', class: "cursor-trail-svg", xmlns: "http://www.w3.org/2000/svg", style: {
483
+ return (index.h(index.Host, { key: '87003b14680b3cbca302e7b31ff57e74cc774e25' }, this.cursorTrailPoints.length > 1 && (index.h("svg", { key: 'aa6460089c9f3157d2dea9396405b14ab8cc1710', class: "cursor-trail-svg", xmlns: "http://www.w3.org/2000/svg", style: {
465
484
  position: 'absolute',
466
485
  left: '0',
467
486
  top: '0',
@@ -492,7 +511,15 @@ const KritzelDropdown = class {
492
511
  this.valueChanged = index.createEvent(this, "valueChanged");
493
512
  }
494
513
  options = [];
514
+ optionsChanged() {
515
+ this.updateInternalValue(this.internalValue, true);
516
+ }
495
517
  value;
518
+ externalValueChanged(newValue) {
519
+ if (newValue !== this.internalValue) {
520
+ this.updateInternalValue(newValue, false);
521
+ }
522
+ }
496
523
  width;
497
524
  selectStyles = {};
498
525
  internalValue;
@@ -506,14 +533,6 @@ const KritzelDropdown = class {
506
533
  this.evaluateSuffixContent();
507
534
  this.evaluatePrefixContent();
508
535
  }
509
- externalValueChanged(newValue) {
510
- if (newValue !== this.internalValue) {
511
- this.updateInternalValue(newValue, false);
512
- }
513
- }
514
- optionsChanged() {
515
- this.updateInternalValue(this.internalValue, true);
516
- }
517
536
  updateInternalValue(proposedValue, emitChange) {
518
537
  let finalValue = proposedValue;
519
538
  if (this.options && this.options.length > 0) {
@@ -571,11 +590,11 @@ const KritzelDropdown = class {
571
590
  'has-suffix-border': this.hasSuffixContent,
572
591
  'has-prefix-border': this.hasPrefixContent,
573
592
  };
574
- return (index.h(index.Host, { key: '32c5f5a4f807c1e316c91b795c005b8d30ce6189' }, index.h("div", { key: 'b1cbeff18e688da4a2f7472be290b9527a619f07', class: "dropdown-wrapper" }, index.h("slot", { key: 'b3bbb7e21c6f5620cab41aa4b1c7206b6c75fd86', name: "prefix", ref: el => this.prefixSlotElement = el, onSlotchange: this.evaluatePrefixContent }), index.h("select", { key: '8b2dcdc125bee59cf29fce7c980b755e78d5816e', class: selectClasses, style: { ...this.selectStyles, width: this.width }, onInput: this.handleSelectChange }, this.options.map(option => (index.h("option", { value: option.value, style: option.style, selected: option.value === this.internalValue }, option.label)))), index.h("slot", { key: '8d83f0dea41ac959bf2392948efef33bb70d0154', name: "suffix", ref: el => this.suffixSlotElement = el, onSlotchange: this.evaluateSuffixContent }))));
593
+ return (index.h(index.Host, { key: 'f24911715685ced571843ba7be6631248c8519b7' }, index.h("div", { key: '520fdb74afdef8bd5228f76074e51981f44b910d', class: "dropdown-wrapper" }, index.h("slot", { key: 'cf6628437946b57ad0b27c066639e0b64b5a28f8', name: "prefix", ref: el => (this.prefixSlotElement = el), onSlotchange: this.evaluatePrefixContent }), index.h("select", { key: '3203ccd5b9c8b84e8f41bddfcb07786e879f0035', class: selectClasses, style: { ...this.selectStyles, width: this.width }, onInput: this.handleSelectChange }, this.options.map(option => (index.h("option", { value: option.value, style: option.style, selected: option.value === this.internalValue }, option.label)))), index.h("slot", { key: 'd0abb52e082db81860c09d2c48b7c065adb406f3', name: "suffix", ref: el => (this.suffixSlotElement = el), onSlotchange: this.evaluateSuffixContent }))));
575
594
  }
576
595
  static get watchers() { return {
577
- "value": ["externalValueChanged"],
578
- "options": ["optionsChanged"]
596
+ "options": ["optionsChanged"],
597
+ "value": ["externalValueChanged"]
579
598
  }; }
580
599
  };
581
600
  KritzelDropdown.style = kritzelDropdownCss;
@@ -630,13 +649,14 @@ KritzelIconRegistry.registerIcons({
630
649
  const ABSOLUTE_SCALE_MAX = 1000;
631
650
  const ABSOLUTE_SCALE_MIN = 0.0001;
632
651
 
633
- const kritzelEditorCss = "kritzel-editor{display:flex;margin:0;position:relative;overflow:hidden;width:100%;height:100%;align-items:center;justify-content:center;touch-action:manipulation;user-select:none;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}kritzel-workspace-manager{position:absolute;top:14px;left:14px}kritzel-split-button{position:absolute;top:14px;left:14px;z-index:1}kritzel-controls{position:absolute;bottom:28px}";
652
+ const kritzelEditorCss = "kritzel-editor{display:flex;margin:0;position:relative;overflow:hidden;width:100%;height:100%;align-items:center;justify-content:center;touch-action:manipulation;user-select:none;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}kritzel-workspace-manager{position:absolute;top:var(--kritzel-editor-workspace-manager-top, 14px);left:var(--kritzel-editor-workspace-manager-left, 14px)}kritzel-controls{position:absolute;bottom:var(--kritzel-editor-controls-bottom, 14px);transition:transform var(--kritzel-editor-controls-transition-duration, 0.1s) var(--kritzel-editor-controls-transition, ease-in-out)}kritzel-controls.keyboard-open{transform:var(--kritzel-editor-controls-transform, translateY(300%))}";
634
653
 
635
654
  const KritzelEditor = class {
636
655
  constructor(hostRef) {
637
656
  index.registerInstance(this, hostRef);
638
657
  this.isReady = index.createEvent(this, "isReady");
639
658
  }
659
+ get host() { return index.getElement(this); }
640
660
  scaleMax = ABSOLUTE_SCALE_MAX;
641
661
  scaleMin = ABSOLUTE_SCALE_MIN;
642
662
  controls = [
@@ -720,7 +740,6 @@ const KritzelEditor = class {
720
740
  isControlsVisible = true;
721
741
  isUtilityPanelVisible = true;
722
742
  isReady;
723
- get host() { return index.getElement(this); }
724
743
  isEngineReady = false;
725
744
  isControlsReady = false;
726
745
  isWorkspaceManagerReady = false;
@@ -737,6 +756,11 @@ const KritzelEditor = class {
737
756
  this.checkIsReady();
738
757
  }
739
758
  }
759
+ handleTouchStart(event) {
760
+ if (event.cancelable) {
761
+ event.preventDefault();
762
+ }
763
+ }
740
764
  async getObjectById(id) {
741
765
  return this.engineRef.getObjectById(id);
742
766
  }
@@ -764,10 +788,21 @@ const KritzelEditor = class {
764
788
  async centerObjectInViewport(object) {
765
789
  return this.engineRef.centerObjectInViewport(object);
766
790
  }
767
- handleTouchStart(event) {
768
- if (event.cancelable) {
769
- event.preventDefault();
770
- }
791
+ async createWorkspace(name, viewport) {
792
+ const workspace = new index$1.KritzelWorkspace(`workspace-${Date.now()}`, name, viewport);
793
+ return this.engineRef.createWorkspace(workspace);
794
+ }
795
+ async updateWorkspace(workspace) {
796
+ return this.engineRef.updateWorkspace(workspace);
797
+ }
798
+ async deleteWorkspace(workspace) {
799
+ return this.engineRef.deleteWorkspace(workspace);
800
+ }
801
+ async getWorkspaces() {
802
+ return this.engineRef.getWorkspaces();
803
+ }
804
+ async getActiveWorkspace() {
805
+ return this.engineRef.getActiveWorkspace();
771
806
  }
772
807
  engineRef;
773
808
  controlsRef;
@@ -775,6 +810,7 @@ const KritzelEditor = class {
775
810
  componentDidLoad() {
776
811
  this.registerCustomSvgIcons();
777
812
  this.listenForMobileKeyboard();
813
+ this.setOsSpecificCssVariables();
778
814
  }
779
815
  async checkIsReady() {
780
816
  await customElements.whenDefined('kritzel-editor');
@@ -798,12 +834,37 @@ const KritzelEditor = class {
798
834
  }
799
835
  listenForMobileKeyboard() {
800
836
  index$1.KritzelKeyboardHelper.onKeyboardVisibleChanged(isOpen => {
801
- console.log('Mobile keyboard visibility changed:', isOpen);
802
837
  this.isVirtualKeyboardOpen = isOpen;
803
838
  });
804
839
  }
840
+ setOsSpecificCssVariables() {
841
+ const os = KritzelDevicesHelper.detectOS();
842
+ switch (os) {
843
+ case 'iOS':
844
+ // iOS specific adjustments
845
+ this.host.style.setProperty('--kritzel-editor-workspace-manager-top', '14px');
846
+ this.host.style.setProperty('--kritzel-editor-workspace-manager-left', '14px');
847
+ this.host.style.setProperty('--kritzel-editor-controls-bottom', '14px');
848
+ this.host.style.setProperty('--kritzel-editor-controls-transition', 'cubic-bezier(0.25, 0.1, 0.25, 1.0)');
849
+ this.host.style.setProperty('--kritzel-editor-controls-transform', 'translateY(200%)');
850
+ this.host.style.setProperty('--kritzel-editor-controls-transition-duration', '0.25s');
851
+ break;
852
+ case 'Android':
853
+ // Android specific adjustments
854
+ this.host.style.setProperty('--kritzel-editor-workspace-manager-top', '14px');
855
+ this.host.style.setProperty('--kritzel-editor-workspace-manager-left', '14px');
856
+ this.host.style.setProperty('--kritzel-editor-controls-bottom', '24px');
857
+ break;
858
+ default:
859
+ // Default for Windows/Linux
860
+ this.host.style.setProperty('--kritzel-editor-workspace-manager-top', '14px');
861
+ this.host.style.setProperty('--kritzel-editor-workspace-manager-left', '14px');
862
+ this.host.style.setProperty('--kritzel-editor-controls-bottom', '14px');
863
+ break;
864
+ }
865
+ }
805
866
  render() {
806
- return (index.h(index.Host, { key: '0f51215c0ede25bf8edfbf1420fc8d6c64175b8a' }, index.h("kritzel-workspace-manager", { key: '14affeb4c161a401d9cca32d0681d576b67b5199', workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, onWorkspaceChange: event => this.activeWorkspace = event.detail, onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), index.h("kritzel-engine", { key: '0e96fdbfbe412ea0a0bae49c693190b71e78f112', ref: el => (this.engineRef = el), workspace: this.activeWorkspace, scaleMax: this.scaleMax, scaleMin: this.scaleMin, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.workspaces = event.detail }), index.h("kritzel-controls", { key: '6098132ddf95b5dd4b1a1a6492b31f0ef43693c4', style: { display: this.isVirtualKeyboardOpen ? 'none' : (this.isControlsVisible ? 'flex' : 'none') }, ref: el => (this.controlsRef = el), controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, onIsControlsReady: () => (this.isControlsReady = true) })));
867
+ return (index.h(index.Host, { key: '17c4e1ce489a5cd359972e67105019ad64703b19' }, index.h("kritzel-workspace-manager", { key: '963f62afe326d33eccdabda804bc3e260aafc306', workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), index.h("kritzel-engine", { key: 'f60f67d06ce73f5f86716fc0ec68408c71100d82', ref: el => (this.engineRef = el), workspace: this.activeWorkspace, scaleMax: this.scaleMax, scaleMin: this.scaleMin, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => (this.workspaces = event.detail) }), index.h("kritzel-controls", { key: '1dc25c1bbb50978cfac3cdaa2d3ae0a32ca7c4f7', class: { 'keyboard-open': this.isVirtualKeyboardOpen }, style: { display: this.isControlsVisible ? 'flex' : 'none' }, ref: el => (this.controlsRef = el), controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, onIsControlsReady: () => (this.isControlsReady = true) })));
807
868
  }
808
869
  static get watchers() { return {
809
870
  "isEngineReady": ["onIsEngineReady"],
@@ -813,117 +874,119 @@ const KritzelEditor = class {
813
874
  KritzelEditor.style = kritzelEditorCss;
814
875
 
815
876
  class KritzelViewport {
816
- _store;
877
+ _core;
817
878
  initialTouchDistance = 0;
818
879
  startX = 0;
819
880
  startY = 0;
820
- constructor(store, host) {
821
- this._store = store;
822
- this._store.state.host = host;
823
- this._store.state.viewportWidth = host.clientWidth;
824
- this._store.state.viewportHeight = host.clientHeight;
825
- this._store.state.startX = 0;
826
- this._store.state.startY = 0;
827
- this._store.state.translateX = 0;
828
- this._store.state.translateY = 0;
881
+ constructor(core, host) {
882
+ this._core = core;
883
+ this._core.store.setState('host', host);
884
+ this._core.store.setState('viewportWidth', host.clientWidth);
885
+ this._core.store.setState('viewportHeight', host.clientHeight);
886
+ this._core.store.setState('startX', 0);
887
+ this._core.store.setState('startY', 0);
888
+ this._core.store.setState('translateX', 0);
889
+ this._core.store.setState('translateY', 0);
829
890
  }
830
891
  handleResize() {
831
- this._store.state.viewportWidth = this._store.state.host.clientWidth;
832
- this._store.state.viewportHeight = this._store.state.host.clientHeight;
833
- this._store.state.hasViewportChanged = true;
834
- this._store.rerender();
892
+ this._core.store.setState('viewportWidth', this._core.store.state.host.clientWidth);
893
+ this._core.store.setState('viewportHeight', this._core.store.state.host.clientHeight);
894
+ this._core.store.setState('hasViewportChanged', true);
895
+ this._core.rerender();
835
896
  }
836
897
  handlePointerDown(event) {
837
898
  if (event.pointerType === 'mouse') {
838
- const adjustedClientX = event.clientX - this._store.offsetX;
839
- const adjustedClientY = event.clientY - this._store.offsetY;
899
+ const adjustedClientX = event.clientX - this._core.store.offsetX;
900
+ const adjustedClientY = event.clientY - this._core.store.offsetY;
840
901
  if (event.button === index$1.KritzelMouseButton.Right) {
841
- this._store.state.isPanning = true;
842
- this._store.state.startX = adjustedClientX;
843
- this._store.state.startY = adjustedClientY;
902
+ this._core.store.setState('isPanning', true);
903
+ this._core.store.setState('startX', adjustedClientX);
904
+ this._core.store.setState('startY', adjustedClientY);
844
905
  }
845
906
  }
846
907
  if (event.pointerType === 'touch') {
847
- const activePointers = Array.from(this._store.state.pointers.values());
908
+ const activePointers = Array.from(this._core.store.state.pointers.values());
848
909
  if (activePointers.length === 2) {
849
- this._store.state.currentPath = null;
850
- this._store.state.isScaling = true;
851
- const firstTouchX = activePointers[0].clientX - this._store.offsetX;
852
- const firstTouchY = activePointers[0].clientY - this._store.offsetY;
853
- const secondTouchX = activePointers[1].clientX - this._store.offsetX;
854
- const secondTouchY = activePointers[1].clientY - this._store.offsetY;
910
+ this._core.store.setState('currentPath', null);
911
+ this._core.store.setState('isScaling', true);
912
+ const firstTouchX = activePointers[0].clientX - this._core.store.offsetX;
913
+ const firstTouchY = activePointers[0].clientY - this._core.store.offsetY;
914
+ const secondTouchX = activePointers[1].clientX - this._core.store.offsetX;
915
+ const secondTouchY = activePointers[1].clientY - this._core.store.offsetY;
855
916
  this.initialTouchDistance = Math.sqrt(Math.pow(firstTouchX - secondTouchX, 2) + Math.pow(firstTouchY - secondTouchY, 2));
856
917
  this.startX = (firstTouchX + secondTouchX) / 2;
857
918
  this.startY = (firstTouchY + secondTouchY) / 2;
858
- this._store.rerender();
919
+ this._core.rerender();
859
920
  }
860
921
  }
861
922
  }
862
923
  handlePointerMove(event) {
863
924
  if (event.pointerType === 'mouse') {
864
- const hostRect = this._store.state.host.getBoundingClientRect();
925
+ const hostRect = this._core.store.state.host.getBoundingClientRect();
865
926
  const xRelativeToHost = event.clientX - hostRect.left;
866
927
  const yRelativeToHost = event.clientY - hostRect.top;
867
- this._store.state.pointerX = (xRelativeToHost - this._store.state.translateX) / this._store.state.scale;
868
- this._store.state.pointerY = (yRelativeToHost - this._store.state.translateY) / this._store.state.scale;
869
- if (this._store.state.isPanning) {
870
- this._store.state.translateX -= this._store.state.startX - xRelativeToHost;
871
- this._store.state.translateY -= this._store.state.startY - yRelativeToHost;
872
- this._store.state.startX = xRelativeToHost;
873
- this._store.state.startY = yRelativeToHost;
874
- this._store.state.hasViewportChanged = true;
875
- this._store.state.skipContextMenu = true;
876
- this._store.rerender();
877
- this._store.updateWorkspaceViewport(this._store.state.translateX, this._store.state.translateY, this._store.state.scale);
928
+ this._core.store.setState('pointerX', (xRelativeToHost - this._core.store.state.translateX) / this._core.store.state.scale);
929
+ this._core.store.setState('pointerY', (yRelativeToHost - this._core.store.state.translateY) / this._core.store.state.scale);
930
+ if (this._core.store.state.isPanning) {
931
+ const dx = xRelativeToHost - this._core.store.state.startX;
932
+ const dy = yRelativeToHost - this._core.store.state.startY;
933
+ this._core.store.setState('translateX', this._core.store.state.translateX + dx);
934
+ this._core.store.setState('translateY', this._core.store.state.translateY + dy);
935
+ this._core.store.setState('startX', xRelativeToHost);
936
+ this._core.store.setState('startY', yRelativeToHost);
937
+ this._core.store.setState('hasViewportChanged', true);
938
+ this._core.store.setState('skipContextMenu', true);
939
+ this._core.rerender();
940
+ this._core.updateWorkspaceViewport(this._core.store.state.translateX, this._core.store.state.translateY, this._core.store.state.scale);
878
941
  }
879
942
  }
880
943
  if (event.pointerType === 'touch') {
881
- const hostRect = this._store.state.host.getBoundingClientRect();
944
+ const hostRect = this._core.store.state.host.getBoundingClientRect();
882
945
  const xRelativeToHost = event.clientX - hostRect.left;
883
946
  const yRelativeToHost = event.clientY - hostRect.top;
884
- this._store.state.pointerX = (xRelativeToHost - this._store.state.translateX) / this._store.state.scale;
885
- this._store.state.pointerY = (yRelativeToHost - this._store.state.translateY) / this._store.state.scale;
886
- const activePointers = Array.from(this._store.state.pointers.values());
947
+ this._core.store.setState('pointerX', (xRelativeToHost - this._core.store.state.translateX) / this._core.store.state.scale);
948
+ this._core.store.setState('pointerY', (yRelativeToHost - this._core.store.state.translateY) / this._core.store.state.scale);
949
+ const activePointers = Array.from(this._core.store.state.pointers.values());
887
950
  if (activePointers.length === 2) {
888
- const firstTouchX = activePointers[0].clientX - this._store.offsetX;
889
- const firstTouchY = activePointers[0].clientY - this._store.offsetY;
890
- const secondTouchX = activePointers[1].clientX - this._store.offsetX;
891
- const secondTouchY = activePointers[1].clientY - this._store.offsetY;
951
+ const firstTouchX = activePointers[0].clientX - this._core.store.offsetX;
952
+ const firstTouchY = activePointers[0].clientY - this._core.store.offsetY;
953
+ const secondTouchX = activePointers[1].clientX - this._core.store.offsetX;
954
+ const secondTouchY = activePointers[1].clientY - this._core.store.offsetY;
892
955
  const currentTouchDistance = Math.sqrt(Math.pow(firstTouchX - secondTouchX, 2) + Math.pow(firstTouchY - secondTouchY, 2));
893
956
  const midpointX = (firstTouchX + secondTouchX) / 2;
894
957
  const midpointY = (firstTouchY + secondTouchY) / 2;
895
958
  const scaleRatio = currentTouchDistance / this.initialTouchDistance;
896
- const newScale = this._store.state.scale * scaleRatio;
897
- if (newScale > this._store.state.scaleMax || newScale < this._store.state.scaleMin) {
898
- this._store.state.translateX += midpointX - this.startX;
899
- this._store.state.translateY += midpointY - this.startY;
959
+ const newScale = this._core.store.state.scale * scaleRatio;
960
+ if (newScale > this._core.store.state.scaleMax || newScale < this._core.store.state.scaleMin) {
961
+ this._core.store.setState('translateX', this._core.store.state.translateX + midpointX - this.startX);
962
+ this._core.store.setState('translateY', this._core.store.state.translateY + midpointY - this.startY);
900
963
  }
901
964
  else {
902
- const translateXAdjustment = (midpointX - this._store.state.translateX) * (scaleRatio - 1);
903
- const translateYAdjustment = (midpointY - this._store.state.translateY) * (scaleRatio - 1);
904
- this._store.state.translateX += midpointX - this.startX - translateXAdjustment;
905
- this._store.state.translateY += midpointY - this.startY - translateYAdjustment;
906
- this._store.state.scale = newScale;
965
+ const translateXAdjustment = (midpointX - this._core.store.state.translateX) * (scaleRatio - 1);
966
+ const translateYAdjustment = (midpointY - this._core.store.state.translateY) * (scaleRatio - 1);
967
+ this._core.store.setState('translateX', this._core.store.state.translateX + midpointX - this.startX - translateXAdjustment);
968
+ this._core.store.setState('translateY', this._core.store.state.translateY + midpointY - this.startY - translateYAdjustment);
969
+ this._core.store.setState('scale', newScale);
907
970
  this.initialTouchDistance = currentTouchDistance;
908
971
  }
909
972
  this.startX = midpointX;
910
973
  this.startY = midpointY;
911
- this._store.state.hasViewportChanged = true;
912
- this._store.rerender();
913
- this._store.updateWorkspaceViewport(this._store.state.translateX, this._store.state.translateY, this._store.state.scale);
974
+ this._core.store.setState('hasViewportChanged', true);
975
+ this._core.rerender();
976
+ this._core.updateWorkspaceViewport(this._core.store.state.translateX, this._core.store.state.translateY, this._core.store.state.scale);
914
977
  }
915
978
  }
916
979
  }
917
980
  handlePointerUp(event) {
918
981
  if (event.pointerType === 'mouse') {
919
- if (this._store.state.isPanning) {
920
- this._store.state.isPanning = false;
921
- this._store.rerender();
982
+ if (this._core.store.state.isPanning) {
983
+ this._core.store.setState('isPanning', false);
984
+ this._core.rerender();
922
985
  }
923
986
  }
924
987
  if (event.pointerType === 'touch') {
925
- this._store.state.isScaling = false;
926
- this._store.rerender();
988
+ this._core.store.setState('isScaling', false);
989
+ this._core.rerender();
927
990
  }
928
991
  }
929
992
  handleWheel(event) {
@@ -936,188 +999,169 @@ class KritzelViewport {
936
999
  }
937
1000
  }
938
1001
  handleZoom(event) {
939
- const rect = this._store.state.host.getBoundingClientRect();
1002
+ this._core.store.setState('isScaling', true);
1003
+ const rect = this._core.store.state.host.getBoundingClientRect();
940
1004
  const xRelativeToHost = event.clientX - rect.left;
941
1005
  const yRelativeToHost = event.clientY - rect.top;
942
- this._store.state.pointerX = (xRelativeToHost - this._store.state.translateX) / this._store.state.scale;
943
- this._store.state.pointerY = (yRelativeToHost - this._store.state.translateY) / this._store.state.scale;
944
- const delta = event.deltaY > 0 ? -this._store.state.scaleStep * this._store.state.scale : this._store.state.scaleStep * this._store.state.scale;
945
- const newScale = Math.min(this._store.state.scaleMax, Math.max(this._store.state.scaleMin, this._store.state.scale + delta));
946
- const scaleRatio = newScale / this._store.state.scale;
947
- const translateXAdjustment = (xRelativeToHost - this._store.state.translateX) * (scaleRatio - 1);
948
- const translateYAdjustment = (yRelativeToHost - this._store.state.translateY) * (scaleRatio - 1);
949
- this._store.state.scale = newScale;
950
- this._store.state.translateX -= translateXAdjustment;
951
- this._store.state.translateY -= translateYAdjustment;
952
- this._store.state.hasViewportChanged = true;
953
- this._store.rerender();
954
- this._store.updateWorkspaceViewport(this._store.state.translateX, this._store.state.translateY, this._store.state.scale);
1006
+ this._core.store.setState('pointerX', (xRelativeToHost - this._core.store.state.translateX) / this._core.store.state.scale);
1007
+ this._core.store.setState('pointerY', (yRelativeToHost - this._core.store.state.translateY) / this._core.store.state.scale);
1008
+ 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;
1009
+ const newScale = Math.min(this._core.store.state.scaleMax, Math.max(this._core.store.state.scaleMin, this._core.store.state.scale + delta));
1010
+ const scaleRatio = newScale / this._core.store.state.scale;
1011
+ const translateXAdjustment = (xRelativeToHost - this._core.store.state.translateX) * (scaleRatio - 1);
1012
+ const translateYAdjustment = (yRelativeToHost - this._core.store.state.translateY) * (scaleRatio - 1);
1013
+ this._core.store.setState('scale', newScale);
1014
+ this._core.store.setState('translateX', this._core.store.state.translateX - translateXAdjustment);
1015
+ this._core.store.setState('translateY', this._core.store.state.translateY - translateYAdjustment);
1016
+ this._core.store.setState('hasViewportChanged', true);
1017
+ this._core.rerender();
1018
+ this._core.updateWorkspaceViewport(this._core.store.state.translateX, this._core.store.state.translateY, this._core.store.state.scale);
1019
+ setTimeout(() => {
1020
+ this._core.store.setState('isScaling', false);
1021
+ this._core.rerender();
1022
+ }, 300);
955
1023
  }
956
1024
  handlePan(event) {
1025
+ this._core.store.setState('isPanning', true);
957
1026
  const panSpeed = 0.8;
958
- this._store.state.translateX -= event.deltaX * panSpeed;
959
- this._store.state.translateY -= event.deltaY * panSpeed;
960
- this._store.state.hasViewportChanged = true;
961
- this._store.rerender();
962
- this._store.updateWorkspaceViewport(this._store.state.translateX, this._store.state.translateY, this._store.state.scale);
963
- }
964
- }
965
-
966
- class UpdateViewportCommand extends index$1.KritzelBaseCommand {
967
- currentViewport;
968
- previousViewport;
969
- constructor(store, initiator, previousViewport, skipHistory = false) {
970
- super(store, initiator, skipHistory);
971
- this.previousViewport = previousViewport;
972
- this.currentViewport = {
973
- scale: this._store.state.scale,
974
- translateX: this._store.state.translateX,
975
- translateY: this._store.state.translateY,
976
- };
977
- }
978
- execute() {
979
- this._store.state.scale = this.currentViewport.scale;
980
- this._store.state.translateX = this.currentViewport.translateX;
981
- this._store.state.translateY = this.currentViewport.translateY;
982
- }
983
- undo() {
984
- this._store.state.scale = this.previousViewport.scale;
985
- this._store.state.translateX = this.previousViewport.translateX;
986
- this._store.state.translateY = this.previousViewport.translateY;
1027
+ this._core.store.setState('translateX', this._core.store.state.translateX - event.deltaX * panSpeed);
1028
+ this._core.store.setState('translateY', this._core.store.state.translateY - event.deltaY * panSpeed);
1029
+ this._core.store.setState('hasViewportChanged', true);
1030
+ this._core.rerender();
1031
+ this._core.updateWorkspaceViewport(this._core.store.state.translateX, this._core.store.state.translateY, this._core.store.state.scale);
1032
+ setTimeout(() => {
1033
+ this._core.store.setState('isPanning', false);
1034
+ this._core.rerender();
1035
+ }, 300);
987
1036
  }
988
1037
  }
989
1038
 
990
- class KritzelCircularBuffer {
991
- buffer;
992
- capacity;
993
- head = 0;
994
- tail = 0;
995
- size = 0;
996
- constructor(capacity) {
997
- this.capacity = capacity;
998
- this.buffer = new Array(capacity).fill(null);
1039
+ class KritzelKeyHandler extends index$1.KritzelBaseHandler {
1040
+ constructor(core) {
1041
+ super(core);
999
1042
  }
1000
- add(item) {
1001
- this.buffer[this.head] = item;
1002
- this.head = (this.head + 1) % this.capacity;
1003
- if (this.size < this.capacity) {
1004
- this.size++;
1043
+ handleKeyDown(event) {
1044
+ this._core.store.setState('isCtrlKeyPressed', event.ctrlKey);
1045
+ if (this._core.store.state.isCtrlKeyPressed) {
1046
+ event.preventDefault();
1005
1047
  }
1006
- else {
1007
- this.tail = (this.tail + 1) % this.capacity;
1048
+ if (event.key === 'Escape' && this._core.store.state.selectionGroup) {
1049
+ this._core.clearSelection();
1008
1050
  }
1009
- }
1010
- pop() {
1011
- if (this.size === 0) {
1012
- return null;
1051
+ if (event.key === 'Delete' && this._core.store.state.selectionGroup) {
1052
+ this._core.delete();
1013
1053
  }
1014
- this.head = (this.head - 1 + this.capacity) % this.capacity;
1015
- const item = this.buffer[this.head];
1016
- this.buffer[this.head] = null;
1017
- this.size--;
1018
- return item;
1019
- }
1020
- peek() {
1021
- if (this.size === 0) {
1022
- return null;
1054
+ if (event.key === 'z' && event.ctrlKey) {
1055
+ this._core.history.undo();
1056
+ }
1057
+ if (event.key === 'y' && event.ctrlKey) {
1058
+ this._core.history.redo();
1059
+ }
1060
+ if (event.key === 's' && event.ctrlKey) {
1061
+ this._core.store.setState('activeTool', index$1.KritzelToolRegistry.getTool('selection'));
1062
+ this._core.deselectAllObjects();
1063
+ }
1064
+ if (event.key === 'b' && event.ctrlKey) {
1065
+ this._core.store.setState('activeTool', index$1.KritzelToolRegistry.getTool('brush'));
1066
+ this._core.deselectAllObjects();
1067
+ }
1068
+ if (event.key === 'e' && event.ctrlKey) {
1069
+ this._core.store.setState('activeTool', index$1.KritzelToolRegistry.getTool('eraser'));
1070
+ this._core.deselectAllObjects();
1071
+ }
1072
+ if (event.key === 'i' && event.ctrlKey) {
1073
+ this._core.store.setState('activeTool', index$1.KritzelToolRegistry.getTool('image'));
1074
+ this._core.deselectAllObjects();
1075
+ }
1076
+ if (event.key === 'x' && event.ctrlKey) {
1077
+ this._core.store.setState('activeTool', index$1.KritzelToolRegistry.getTool('text'));
1078
+ this._core.deselectAllObjects();
1079
+ }
1080
+ if (event.key === 'c' && event.ctrlKey && this._core.store.state.selectionGroup) {
1081
+ this._core.copy();
1082
+ this._core.rerender();
1083
+ }
1084
+ if (event.key === 'v' && event.ctrlKey && this._core.store.state.copiedObjects) {
1085
+ this._core.paste();
1086
+ }
1087
+ if (event.key === '+' && event.ctrlKey && this._core.store.state.selectionGroup) {
1088
+ this._core.bringForward();
1089
+ }
1090
+ if (event.key === '-' && event.ctrlKey && this._core.store.state.selectionGroup) {
1091
+ this._core.sendBackward();
1092
+ }
1093
+ if (event.key === '*' && event.shiftKey && this._core.store.state.selectionGroup) {
1094
+ this._core.bringToFront();
1095
+ }
1096
+ if (event.key === '_' && event.shiftKey && this._core.store.state.selectionGroup) {
1097
+ this._core.sendToBack();
1098
+ }
1099
+ if (event.key === 'a' && event.ctrlKey && this._core.store.state.activeText) {
1100
+ this._core.store.state.activeText.selectAll();
1101
+ }
1102
+ if (event.key === 'v' && event.ctrlKey && this._core.store.state.activeText) {
1103
+ this._core.store.state.activeText.insertFromClipboard();
1023
1104
  }
1024
- const lastIndex = (this.head - 1 + this.capacity) % this.capacity;
1025
- return this.buffer[lastIndex];
1026
- }
1027
- isEmpty() {
1028
- return this.size === 0;
1029
1105
  }
1030
- clear() {
1031
- this.buffer.fill(null);
1032
- this.head = 0;
1033
- this.tail = 0;
1034
- this.size = 0;
1106
+ handleKeyUp(event) {
1107
+ this._core.store.setState('isCtrlKeyPressed', event.ctrlKey);
1035
1108
  }
1036
1109
  }
1037
1110
 
1038
- class KritzelHistory {
1039
- _store;
1040
- undoStack;
1041
- redoStack;
1042
- previousViewport;
1043
- constructor(store) {
1044
- this._store = store;
1045
- this.undoStack = new KritzelCircularBuffer(this._store.state.historyBufferSize);
1046
- this.redoStack = new KritzelCircularBuffer(this._store.state.historyBufferSize);
1047
- this.previousViewport = {
1048
- scale: this._store.state.scale,
1049
- scaleStep: this._store.state.scaleStep,
1050
- translateX: this._store.state.translateX,
1051
- translateY: this._store.state.translateY,
1052
- };
1053
- }
1054
- reset() {
1055
- this.undoStack.clear();
1056
- this.redoStack.clear();
1057
- this.previousViewport = {
1058
- scale: this._store.state.scale,
1059
- scaleStep: this._store.state.scaleStep,
1060
- translateX: this._store.state.translateX,
1061
- translateY: this._store.state.translateY
1062
- };
1111
+ class KritzelContextMenuHandler extends index$1.KritzelBaseHandler {
1112
+ globalContextMenuItems = [];
1113
+ objectContextMenuItems = [];
1114
+ constructor(core, globalContextMenuItems, objectContextMenuItems) {
1115
+ super(core);
1116
+ this.globalContextMenuItems = globalContextMenuItems;
1117
+ this.objectContextMenuItems = objectContextMenuItems;
1063
1118
  }
1064
- executeCommand(command) {
1065
- if (this._store.state.hasViewportChanged) {
1066
- this.addUpdateViewportCommand();
1067
- }
1068
- command.execute();
1069
- if (command.skipHistory === false) {
1070
- if (this._store.state.debugInfo.logCommands) {
1071
- console.info('add', command);
1072
- }
1073
- this.undoStack.add(command);
1074
- if (this.redoStack.isEmpty() === false) {
1075
- this.redoStack.clear();
1076
- }
1119
+ handleContextMenu(event) {
1120
+ if (!(this._core.store.state.activeTool instanceof index$1.KritzelSelectionTool)) {
1121
+ return;
1077
1122
  }
1078
- this._store.rerender();
1079
- }
1080
- undo() {
1081
- if (this._store.state.hasViewportChanged) {
1082
- const command = new UpdateViewportCommand(this._store, this, this.previousViewport);
1083
- command.undo();
1084
- this._store.state.hasViewportChanged = false;
1085
- this._store.rerender();
1123
+ if (this._core.store.state.skipContextMenu) {
1124
+ this._core.store.setState('skipContextMenu', false);
1086
1125
  return;
1087
1126
  }
1088
- const command = this.undoStack.pop();
1089
- if (command) {
1090
- command.undo();
1091
- if (this._store.state.debugInfo.logCommands)
1092
- console.info('undo', command);
1093
- this.redoStack.add(command);
1127
+ const selectedObject = this._core.getObjectFromPointerEvent(event, '.object');
1128
+ if (selectedObject && !(selectedObject instanceof index$1.KritzelSelectionGroup)) {
1129
+ const selectionGroup = index$1.KritzelSelectionGroup.create(this._core);
1130
+ selectionGroup.addOrRemove(selectedObject);
1131
+ selectionGroup.isSelected = true;
1132
+ selectionGroup.rotation = selectedObject.rotation;
1133
+ this._core.store.setState('isSelecting', false);
1134
+ const batch = new index$1.BatchCommand(this._core, this, [
1135
+ new index$1.RemoveSelectionGroupCommand(this._core, this._core.store.state.selectionGroup),
1136
+ new index$1.AddSelectionGroupCommand(this._core, this, selectionGroup),
1137
+ ]);
1138
+ this._core.history.executeCommand(batch);
1139
+ }
1140
+ this._core.store.setState('contextMenuItems', this._core.store.state.selectionGroup ? this.objectContextMenuItems : this.globalContextMenuItems);
1141
+ let x = event.clientX - this._core.store.offsetX;
1142
+ let y = event.clientY - this._core.store.offsetY;
1143
+ const menuWidthEstimate = 150;
1144
+ const menuHeightEstimate = 200;
1145
+ const margin = 10;
1146
+ if (x + menuWidthEstimate > window.innerWidth - margin) {
1147
+ x = window.innerWidth - menuWidthEstimate - margin;
1094
1148
  }
1095
- this._store.rerender();
1096
- }
1097
- redo() {
1098
- const command = this.redoStack.pop();
1099
- if (command) {
1100
- command.execute();
1101
- if (this._store.state.debugInfo.logCommands)
1102
- console.info('redo', command);
1103
- this.undoStack.add(command);
1149
+ if (y + menuHeightEstimate > window.innerHeight - margin) {
1150
+ y = window.innerHeight - menuHeightEstimate - margin;
1104
1151
  }
1105
- this._store.rerender();
1152
+ x = Math.max(margin, x);
1153
+ y = Math.max(margin, y);
1154
+ this._core.store.setState('contextMenuX', x);
1155
+ this._core.store.setState('contextMenuY', y);
1156
+ this._core.store.setState('isContextMenuVisible', true);
1157
+ this._core.store.setState('isEnabled', false);
1158
+ this._core.rerender();
1106
1159
  }
1107
- addUpdateViewportCommand() {
1108
- const command = new UpdateViewportCommand(this._store, this, this.previousViewport);
1109
- command.execute();
1110
- this.undoStack.add(command);
1111
- if (this.redoStack.isEmpty() === false) {
1112
- this.redoStack.clear();
1113
- }
1114
- this._store.state.hasViewportChanged = false;
1115
- this.previousViewport = {
1116
- scale: this._store.state.scale,
1117
- scaleStep: this._store.state.scaleStep,
1118
- translateX: this._store.state.translateX,
1119
- translateY: this._store.state.translateY,
1120
- };
1160
+ }
1161
+
1162
+ class KritzelClassHelper {
1163
+ static isInstanceOf(object, className) {
1164
+ return !!object && object.__class__ === className;
1121
1165
  }
1122
1166
  }
1123
1167
 
@@ -1136,7 +1180,6 @@ const DEFAULT_ENGINE_STATE = {
1136
1180
  isEnabled: true,
1137
1181
  isScaling: false,
1138
1182
  isPanning: false,
1139
- isFocused: false,
1140
1183
  isSelecting: false,
1141
1184
  isResizing: false,
1142
1185
  isResizeHandleSelected: false,
@@ -1199,7 +1242,7 @@ class KritzelDatabase {
1199
1242
  return;
1200
1243
  }
1201
1244
  if (this.isLoggingEnabled) {
1202
- console.log(`[IndexedDB] Opening database: ${this.dbName}, version: ${this.dbVersion}`);
1245
+ console.info(`[IndexedDB] Opening database: ${this.dbName}, version: ${this.dbVersion}`);
1203
1246
  }
1204
1247
  const request = indexedDB.open(this.dbName, this.dbVersion);
1205
1248
  request.onerror = () => {
@@ -1209,25 +1252,25 @@ class KritzelDatabase {
1209
1252
  request.onsuccess = () => {
1210
1253
  this.db = request.result;
1211
1254
  if (this.isLoggingEnabled) {
1212
- console.log(`[IndexedDB] Database opened successfully.`);
1255
+ console.info(`[IndexedDB] Database opened successfully.`);
1213
1256
  }
1214
1257
  resolve();
1215
1258
  };
1216
1259
  request.onupgradeneeded = event => {
1217
1260
  if (this.isLoggingEnabled) {
1218
- console.log(`[IndexedDB] Upgrade needed for database: ${this.dbName}`);
1261
+ console.info(`[IndexedDB] Upgrade needed for database: ${this.dbName}`);
1219
1262
  }
1220
1263
  const db = event.target.result;
1221
1264
  stores.forEach(storeConfig => {
1222
1265
  if (!db.objectStoreNames.contains(storeConfig.name)) {
1223
1266
  if (this.isLoggingEnabled) {
1224
- console.log(`[IndexedDB] Creating store: ${storeConfig.name}`);
1267
+ console.info(`[IndexedDB] Creating store: ${storeConfig.name}`);
1225
1268
  }
1226
1269
  const store = db.createObjectStore(storeConfig.name, storeConfig.options);
1227
1270
  if (storeConfig.indices) {
1228
1271
  storeConfig.indices.forEach(index => {
1229
1272
  if (this.isLoggingEnabled) {
1230
- console.log(`[IndexedDB] Creating index: ${index.name} on store: ${storeConfig.name}`);
1273
+ console.info(`[IndexedDB] Creating index: ${index.name} on store: ${storeConfig.name}`);
1231
1274
  }
1232
1275
  store.createIndex(index.name, index.keyPath, index.options);
1233
1276
  });
@@ -1240,7 +1283,7 @@ class KritzelDatabase {
1240
1283
  close() {
1241
1284
  if (this.db) {
1242
1285
  if (this.isLoggingEnabled) {
1243
- console.log(`[IndexedDB] Closing database: ${this.dbName}`);
1286
+ console.info(`[IndexedDB] Closing database: ${this.dbName}`);
1244
1287
  }
1245
1288
  this.db.close();
1246
1289
  this.db = null;
@@ -1248,43 +1291,51 @@ class KritzelDatabase {
1248
1291
  }
1249
1292
  async add(storeName, item) {
1250
1293
  if (this.isLoggingEnabled) {
1251
- console.log('[IndexedDB] Add:', { storeName, item });
1294
+ console.info('[IndexedDB] Add:', { storeName, item });
1295
+ }
1296
+ if (item.serialize === undefined) {
1297
+ throw new Error('Item does not implement KritzelSerializable interface.');
1252
1298
  }
1253
- return this.executeTransaction(storeName, 'readwrite', store => store.add(item));
1299
+ const serializedItem = item.serialize();
1300
+ return this.executeTransaction(storeName, 'readwrite', store => store.add(serializedItem));
1254
1301
  }
1255
1302
  async get(storeName, key) {
1256
1303
  if (this.isLoggingEnabled) {
1257
- console.log('[IndexedDB] Get:', { storeName, key });
1304
+ console.info('[IndexedDB] Get:', { storeName, key });
1258
1305
  }
1259
1306
  return this.executeTransaction(storeName, 'readonly', store => store.get(key));
1260
1307
  }
1261
1308
  async getAll(storeName) {
1262
1309
  if (this.isLoggingEnabled) {
1263
- console.log('[IndexedDB] GetAll:', { storeName });
1310
+ console.info('[IndexedDB] GetAll:', { storeName });
1264
1311
  }
1265
1312
  return this.executeTransaction(storeName, 'readonly', store => store.getAll());
1266
1313
  }
1267
1314
  async update(storeName, item) {
1268
1315
  if (this.isLoggingEnabled) {
1269
- console.log('[IndexedDB] Update:', { storeName, item });
1316
+ console.info('[IndexedDB] Update:', { storeName, item });
1270
1317
  }
1271
- return this.executeTransaction(storeName, 'readwrite', store => store.put(item));
1318
+ if (item.serialize === undefined) {
1319
+ throw new Error('Item does not implement KritzelSerializable interface.');
1320
+ }
1321
+ const serializedItem = item.serialize();
1322
+ return this.executeTransaction(storeName, 'readwrite', store => store.put(serializedItem));
1272
1323
  }
1273
1324
  async delete(storeName, key) {
1274
1325
  if (this.isLoggingEnabled) {
1275
- console.log('[IndexedDB] Delete:', { storeName, key });
1326
+ console.info('[IndexedDB] Delete:', { storeName, key });
1276
1327
  }
1277
1328
  return this.executeTransaction(storeName, 'readwrite', store => store.delete(key));
1278
1329
  }
1279
1330
  async deleteByRange(storeName, range) {
1280
1331
  if (this.isLoggingEnabled) {
1281
- console.log('[IndexedDB] DeleteByRange:', { storeName, range });
1332
+ console.info('[IndexedDB] DeleteByRange:', { storeName, range });
1282
1333
  }
1283
1334
  return this.executeTransaction(storeName, 'readwrite', store => store.delete(range));
1284
1335
  }
1285
1336
  async getAllByRange(storeName, range) {
1286
1337
  if (this.isLoggingEnabled) {
1287
- console.log('[IndexedDB] GetAllByRange:', { storeName, range });
1338
+ console.info('[IndexedDB] GetAllByRange:', { storeName, range });
1288
1339
  }
1289
1340
  return this.executeTransaction(storeName, 'readonly', store => {
1290
1341
  return store.getAll(range);
@@ -1292,7 +1343,7 @@ class KritzelDatabase {
1292
1343
  }
1293
1344
  async getAllByIndex(storeName, indexName, query) {
1294
1345
  if (this.isLoggingEnabled) {
1295
- console.log('[IndexedDB] GetAllByIndex:', { storeName, indexName, query });
1346
+ console.info('[IndexedDB] GetAllByIndex:', { storeName, indexName, query });
1296
1347
  }
1297
1348
  return this.executeTransaction(storeName, 'readonly', store => {
1298
1349
  const index = store.index(indexName);
@@ -1328,7 +1379,7 @@ class KritzelDatabase {
1328
1379
  }
1329
1380
  const storeNames = await this.extractStoreNamesFromActions(actions);
1330
1381
  if (this.isLoggingEnabled) {
1331
- console.log('[IndexedDB] Starting batch transaction:', { storeNames });
1382
+ console.info('[IndexedDB] Starting batch transaction:', { storeNames });
1332
1383
  }
1333
1384
  return new Promise((resolve, reject) => {
1334
1385
  const transaction = this.db.transaction(storeNames, 'readwrite');
@@ -1346,13 +1397,13 @@ class KritzelDatabase {
1346
1397
  executeTransaction: (storeName, mode, action) => {
1347
1398
  return new Promise((resolveRequest, rejectRequest) => {
1348
1399
  if (this.isLoggingEnabled) {
1349
- console.log('[IndexedDB] Executing batch action:', { storeName, mode });
1400
+ console.info('[IndexedDB] Executing batch action:', { storeName, mode });
1350
1401
  }
1351
1402
  const store = transaction.objectStore(storeName);
1352
1403
  const request = action(store);
1353
1404
  request.onsuccess = () => {
1354
1405
  if (this.isLoggingEnabled) {
1355
- console.log('[IndexedDB] Batch action request successful:', { result: request.result });
1406
+ console.info('[IndexedDB] Batch action request successful:', { result: request.result });
1356
1407
  }
1357
1408
  resolveRequest(request.result);
1358
1409
  };
@@ -1365,7 +1416,7 @@ class KritzelDatabase {
1365
1416
  };
1366
1417
  transaction.oncomplete = () => {
1367
1418
  if (this.isLoggingEnabled) {
1368
- console.log('[IndexedDB] Batch transaction complete.');
1419
+ console.info('[IndexedDB] Batch transaction complete.');
1369
1420
  }
1370
1421
  Promise.all(promises).then(() => resolve(results));
1371
1422
  };
@@ -1410,6 +1461,164 @@ class KritzelDatabase {
1410
1461
  }
1411
1462
  }
1412
1463
 
1464
+ class UpdateViewportCommand extends index$1.KritzelBaseCommand {
1465
+ currentViewport;
1466
+ previousViewport;
1467
+ constructor(core, initiator, previousViewport, skipHistory = false) {
1468
+ super(core, initiator, skipHistory);
1469
+ this.previousViewport = previousViewport;
1470
+ this.currentViewport = {
1471
+ scale: this._core.store.state.scale,
1472
+ translateX: this._core.store.state.translateX,
1473
+ translateY: this._core.store.state.translateY,
1474
+ };
1475
+ }
1476
+ execute() {
1477
+ this._core.store.setState('scale', this.currentViewport.scale);
1478
+ this._core.store.setState('translateX', this.currentViewport.translateX);
1479
+ this._core.store.setState('translateY', this.currentViewport.translateY);
1480
+ }
1481
+ undo() {
1482
+ this._core.store.setState('scale', this.previousViewport.scale);
1483
+ this._core.store.setState('translateX', this.previousViewport.translateX);
1484
+ this._core.store.setState('translateY', this.previousViewport.translateY);
1485
+ }
1486
+ }
1487
+
1488
+ class KritzelCircularBuffer {
1489
+ buffer;
1490
+ capacity;
1491
+ head = 0;
1492
+ tail = 0;
1493
+ size = 0;
1494
+ constructor(capacity) {
1495
+ this.capacity = capacity;
1496
+ this.buffer = new Array(capacity).fill(null);
1497
+ }
1498
+ add(item) {
1499
+ this.buffer[this.head] = item;
1500
+ this.head = (this.head + 1) % this.capacity;
1501
+ if (this.size < this.capacity) {
1502
+ this.size++;
1503
+ }
1504
+ else {
1505
+ this.tail = (this.tail + 1) % this.capacity;
1506
+ }
1507
+ }
1508
+ pop() {
1509
+ if (this.size === 0) {
1510
+ return null;
1511
+ }
1512
+ this.head = (this.head - 1 + this.capacity) % this.capacity;
1513
+ const item = this.buffer[this.head];
1514
+ this.buffer[this.head] = null;
1515
+ this.size--;
1516
+ return item;
1517
+ }
1518
+ peek() {
1519
+ if (this.size === 0) {
1520
+ return null;
1521
+ }
1522
+ const lastIndex = (this.head - 1 + this.capacity) % this.capacity;
1523
+ return this.buffer[lastIndex];
1524
+ }
1525
+ isEmpty() {
1526
+ return this.size === 0;
1527
+ }
1528
+ clear() {
1529
+ this.buffer.fill(null);
1530
+ this.head = 0;
1531
+ this.tail = 0;
1532
+ this.size = 0;
1533
+ }
1534
+ }
1535
+
1536
+ class KritzelHistory {
1537
+ _core;
1538
+ undoStack;
1539
+ redoStack;
1540
+ previousViewport;
1541
+ constructor(core) {
1542
+ this._core = core;
1543
+ this.undoStack = new KritzelCircularBuffer(this._core.store.state.historyBufferSize);
1544
+ this.redoStack = new KritzelCircularBuffer(this._core.store.state.historyBufferSize);
1545
+ this.previousViewport = {
1546
+ scale: this._core.store.state.scale,
1547
+ scaleStep: this._core.store.state.scaleStep,
1548
+ translateX: this._core.store.state.translateX,
1549
+ translateY: this._core.store.state.translateY,
1550
+ };
1551
+ }
1552
+ reset() {
1553
+ this.undoStack.clear();
1554
+ this.redoStack.clear();
1555
+ this.previousViewport = {
1556
+ scale: this._core.store.state.scale,
1557
+ scaleStep: this._core.store.state.scaleStep,
1558
+ translateX: this._core.store.state.translateX,
1559
+ translateY: this._core.store.state.translateY
1560
+ };
1561
+ }
1562
+ executeCommand(command) {
1563
+ if (this._core.store.state.hasViewportChanged) {
1564
+ this.addUpdateViewportCommand();
1565
+ }
1566
+ command.execute();
1567
+ if (command.skipHistory === false) {
1568
+ if (this._core.store.state.debugInfo.logCommands) {
1569
+ console.info('add', command);
1570
+ }
1571
+ this.undoStack.add(command);
1572
+ if (this.redoStack.isEmpty() === false) {
1573
+ this.redoStack.clear();
1574
+ }
1575
+ }
1576
+ this._core.rerender();
1577
+ }
1578
+ undo() {
1579
+ if (this._core.store.state.hasViewportChanged) {
1580
+ const command = new UpdateViewportCommand(this._core, this, this.previousViewport);
1581
+ command.undo();
1582
+ this._core.store.setState('hasViewportChanged', false);
1583
+ this._core.rerender();
1584
+ return;
1585
+ }
1586
+ const command = this.undoStack.pop();
1587
+ if (command) {
1588
+ command.undo();
1589
+ if (this._core.store.state.debugInfo.logCommands)
1590
+ console.info('undo', command);
1591
+ this.redoStack.add(command);
1592
+ }
1593
+ this._core.rerender();
1594
+ }
1595
+ redo() {
1596
+ const command = this.redoStack.pop();
1597
+ if (command) {
1598
+ command.execute();
1599
+ if (this._core.store.state.debugInfo.logCommands)
1600
+ console.info('redo', command);
1601
+ this.undoStack.add(command);
1602
+ }
1603
+ this._core.rerender();
1604
+ }
1605
+ addUpdateViewportCommand() {
1606
+ const command = new UpdateViewportCommand(this._core, this, this.previousViewport);
1607
+ command.execute();
1608
+ this.undoStack.add(command);
1609
+ if (this.redoStack.isEmpty() === false) {
1610
+ this.redoStack.clear();
1611
+ }
1612
+ this._core.store.setState('hasViewportChanged', false);
1613
+ this.previousViewport = {
1614
+ scale: this._core.store.state.scale,
1615
+ scaleStep: this._core.store.state.scaleStep,
1616
+ translateX: this._core.store.state.translateX,
1617
+ translateY: this._core.store.state.translateY,
1618
+ };
1619
+ }
1620
+ }
1621
+
1413
1622
  class KritzelObjectMap {
1414
1623
  map;
1415
1624
  constructor() {
@@ -1454,18 +1663,8 @@ class KritzelObjectMap {
1454
1663
  }
1455
1664
 
1456
1665
  class KritzelStore {
1457
- _kritzelEngine;
1458
1666
  _state;
1459
- _history;
1460
- _database;
1461
1667
  _listeners = new Map();
1462
- objects = [];
1463
- get history() {
1464
- return this._history;
1465
- }
1466
- get database() {
1467
- return this._database;
1468
- }
1469
1668
  get state() {
1470
1669
  return this._state;
1471
1670
  }
@@ -1481,18 +1680,58 @@ class KritzelStore {
1481
1680
  get offsetX() {
1482
1681
  return this._state.host.getBoundingClientRect().left;
1483
1682
  }
1484
- get offsetY() {
1485
- return this._state.host.getBoundingClientRect().top;
1683
+ get offsetY() {
1684
+ return this._state.host.getBoundingClientRect().top;
1685
+ }
1686
+ get isDisabled() {
1687
+ return this._state.isEnabled === false || this._state.isReady === false || this._state.activeWorkspace === null;
1688
+ }
1689
+ constructor(state) {
1690
+ this._state = state;
1691
+ this._state.objectsMap = new KritzelObjectMap();
1692
+ }
1693
+ onStateChange(property, listener) {
1694
+ if (!this._listeners.has(property)) {
1695
+ this._listeners.set(property, new Set());
1696
+ }
1697
+ this._listeners.get(property).add(listener);
1698
+ }
1699
+ getState(property) {
1700
+ return this._state[property];
1701
+ }
1702
+ setState(property, value) {
1703
+ const oldValue = this._state[property];
1704
+ if (oldValue !== value) {
1705
+ this._state[property] = value;
1706
+ if (this._listeners.has(property)) {
1707
+ this._listeners.get(property).forEach(listener => listener(value, oldValue, String(property)));
1708
+ }
1709
+ }
1710
+ }
1711
+ }
1712
+
1713
+ class KritzelCore {
1714
+ _kritzelEngine;
1715
+ _store;
1716
+ _history;
1717
+ _database;
1718
+ get engine() {
1719
+ return this._kritzelEngine;
1720
+ }
1721
+ get history() {
1722
+ return this._history;
1723
+ }
1724
+ get database() {
1725
+ return this._database;
1486
1726
  }
1487
- get isDisabled() {
1488
- return this._state.isEnabled === false || this._state.isReady === false || this._state.activeWorkspace === null;
1727
+ get store() {
1728
+ return this._store;
1489
1729
  }
1490
1730
  constructor(kritzelEngine) {
1491
- this._state = DEFAULT_ENGINE_STATE;
1492
1731
  this._kritzelEngine = kritzelEngine;
1732
+ this._store = new KritzelStore(DEFAULT_ENGINE_STATE);
1493
1733
  this._history = new KritzelHistory(this);
1494
- this._database = new KritzelDatabase('kritzelDB', 1, this._state.debugInfo.logDatabase);
1495
- this._state.objectsMap = new KritzelObjectMap();
1734
+ this._database = new KritzelDatabase('kritzelDB', 1, this._store.state.debugInfo.logDatabase);
1496
1735
  }
1497
1736
  async initializeDatabase() {
1498
1737
  await this._database.open([
@@ -1508,52 +1747,50 @@ class KritzelStore {
1508
1747
  const workspaces = await this.getWorkspaces();
1509
1748
  const mostRecentWorkspace = [...workspaces].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime())[0];
1510
1749
  const fallbackWorkspace = new index$1.KritzelWorkspace(index$1.ObjectHelper.generateUUID(), 'New Workspace');
1511
- this._state.activeWorkspace = workspace ?? mostRecentWorkspace ?? fallbackWorkspace;
1512
- const isExistingWorkspace = await this.getWorkspace(this._state.activeWorkspace.id);
1750
+ this._store.setState('activeWorkspace', workspace ?? mostRecentWorkspace ?? fallbackWorkspace);
1751
+ const isExistingWorkspace = await this.getWorkspace(this._store.state.activeWorkspace.id);
1513
1752
  if (isExistingWorkspace) {
1514
- await this.updateWorkspace(this._state.activeWorkspace);
1753
+ await this.updateWorkspace(this._store.state.activeWorkspace);
1515
1754
  }
1516
1755
  else {
1517
- await this.createWorkspace(this._state.activeWorkspace);
1756
+ await this.createWorkspace(this._store.state.activeWorkspace);
1518
1757
  }
1519
- this._state.workspaces = await this.getWorkspaces();
1520
- this.state.translateX = this._state.activeWorkspace.viewport.translateX;
1521
- this.state.translateY = this._state.activeWorkspace.viewport.translateY;
1522
- this.state.scale = this._state.activeWorkspace.viewport.scale;
1523
- await this.initializeWorkspaceObjects(this._state.activeWorkspace.id);
1758
+ this._store.setState('workspaces', await this.getWorkspaces());
1759
+ this._store.setState('translateX', this._store.state.activeWorkspace.viewport.translateX);
1760
+ this._store.setState('translateY', this._store.state.activeWorkspace.viewport.translateY);
1761
+ this._store.setState('scale', this._store.state.activeWorkspace.viewport.scale);
1762
+ await this.initializeWorkspaceObjects(this._store.state.activeWorkspace.id);
1524
1763
  }
1525
1764
  async initializeWorkspaceObjects(workspaceId) {
1526
- this._state.objectsMap.reset();
1765
+ this._store.state.objectsMap.reset();
1527
1766
  this._history.reset();
1528
1767
  const objectsFromDb = await this._database.getAllByRange('objects', IDBKeyRange.bound([workspaceId], [workspaceId, '\uffff']));
1529
1768
  const reviver = new index$1.KritzelReviver(this);
1530
1769
  objectsFromDb.forEach(element => {
1531
1770
  const revivedObject = reviver.revive(element);
1532
- this._state.objectsMap.insert(revivedObject);
1771
+ this._store.state.objectsMap.insert(revivedObject);
1533
1772
  });
1534
1773
  this.rerender();
1535
1774
  }
1536
1775
  async updateWorkspaceViewport(translateX, translateY, scale) {
1537
- if (!this.state.activeWorkspace) {
1776
+ const activeWorkspace = this._store.state.activeWorkspace;
1777
+ if (!activeWorkspace) {
1538
1778
  throw new Error('Workspace not initialized');
1539
1779
  }
1540
- this.state.activeWorkspace.viewport = {
1541
- translateX,
1542
- translateY,
1543
- scale,
1544
- };
1545
- this.state.activeWorkspace.updatedAt = new Date();
1546
- await this._database.update('workspaces', this.state.activeWorkspace);
1780
+ activeWorkspace.viewport = { translateX, translateY, scale };
1781
+ activeWorkspace.updatedAt = new Date();
1782
+ await this._database.update('workspaces', activeWorkspace);
1547
1783
  }
1548
1784
  async addObjectToDatabase(object) {
1549
1785
  if (!this._database) {
1550
1786
  throw new Error('Database not initialized');
1551
1787
  }
1552
- if (!this.state.activeWorkspace) {
1788
+ const activeWorkspace = this._store.state.activeWorkspace;
1789
+ if (!activeWorkspace) {
1553
1790
  throw new Error('Workspace not initialized');
1554
1791
  }
1555
- this.state.activeWorkspace.updatedAt = new Date();
1556
- await this._database.batch([db => db.add('objects', object), db => db.update('workspaces', this.state.activeWorkspace)]).catch(err => {
1792
+ activeWorkspace.updatedAt = new Date();
1793
+ await this._database.batch([db => db.add('objects', object), db => db.update('workspaces', activeWorkspace)]).catch(err => {
1557
1794
  console.error('Error adding object to database:', err);
1558
1795
  });
1559
1796
  }
@@ -1561,11 +1798,12 @@ class KritzelStore {
1561
1798
  if (!this._database) {
1562
1799
  throw new Error('Database not initialized');
1563
1800
  }
1564
- if (!this.state.activeWorkspace) {
1801
+ const activeWorkspace = this._store.state.activeWorkspace;
1802
+ if (!activeWorkspace) {
1565
1803
  throw new Error('Workspace not initialized');
1566
1804
  }
1567
- this.state.activeWorkspace.updatedAt = new Date();
1568
- await this._database.batch([db => db.update('objects', object), db => db.update('workspaces', this.state.activeWorkspace)]).catch(err => {
1805
+ activeWorkspace.updatedAt = new Date();
1806
+ await this._database.batch([db => db.update('objects', object), db => db.update('workspaces', activeWorkspace)]).catch(err => {
1569
1807
  console.error('Error updating object in database:', err);
1570
1808
  });
1571
1809
  }
@@ -1573,25 +1811,28 @@ class KritzelStore {
1573
1811
  if (!this._database) {
1574
1812
  throw new Error('Database not initialized');
1575
1813
  }
1576
- if (!this.state.activeWorkspace) {
1814
+ const activeWorkspace = this._store.state.activeWorkspace;
1815
+ if (!activeWorkspace) {
1577
1816
  throw new Error('Workspace not initialized');
1578
1817
  }
1579
- this.state.activeWorkspace.updatedAt = new Date();
1580
- await this._database.batch([db => db.delete('objects', [this.state.activeWorkspace.id, objectId]), db => db.update('workspaces', this.state.activeWorkspace)]).catch(err => {
1818
+ activeWorkspace.updatedAt = new Date();
1819
+ await this._database.batch([db => db.delete('objects', [activeWorkspace.id, objectId]), db => db.update('workspaces', activeWorkspace)]).catch(err => {
1581
1820
  console.error('Error deleting object from database:', err);
1582
1821
  });
1583
1822
  }
1584
- getWorkspace(id) {
1823
+ async getWorkspace(id) {
1585
1824
  if (!this._database) {
1586
1825
  throw new Error('Database not initialized');
1587
1826
  }
1588
- return this._database.get('workspaces', id);
1827
+ const reviver = new index$1.KritzelReviver(this);
1828
+ return this._database.get('workspaces', id).then(rawWorkspace => (rawWorkspace ? reviver.revive(rawWorkspace) : null));
1589
1829
  }
1590
- getWorkspaces() {
1830
+ async getWorkspaces() {
1591
1831
  if (!this._database) {
1592
1832
  throw new Error('Database not initialized');
1593
1833
  }
1594
- return this._database.getAll('workspaces');
1834
+ const reviver = new index$1.KritzelReviver(this);
1835
+ return this._database.getAll('workspaces').then(rawWorkspaces => rawWorkspaces.map(ws => reviver.revive(ws)));
1595
1836
  }
1596
1837
  async createWorkspace(workspace) {
1597
1838
  if (!this._database) {
@@ -1600,7 +1841,7 @@ class KritzelStore {
1600
1841
  workspace.createdAt = new Date();
1601
1842
  workspace.updatedAt = new Date();
1602
1843
  await this._database.add('workspaces', workspace);
1603
- this.state.workspaces.push(workspace);
1844
+ this._store.state.workspaces.push(workspace);
1604
1845
  }
1605
1846
  async updateWorkspace(workspace) {
1606
1847
  if (!this._database) {
@@ -1608,9 +1849,11 @@ class KritzelStore {
1608
1849
  }
1609
1850
  workspace.updatedAt = new Date();
1610
1851
  await this._database.update('workspaces', workspace);
1611
- const index = this.state.workspaces.findIndex(w => w.id === workspace.id);
1852
+ const workspaces = this._store.state.workspaces;
1853
+ const index = workspaces.findIndex(w => w.id === workspace.id);
1612
1854
  if (index !== -1) {
1613
- this.state.workspaces[index] = workspace;
1855
+ workspaces[index] = workspace;
1856
+ this._store.setState('workspaces', workspaces);
1614
1857
  }
1615
1858
  }
1616
1859
  async deleteWorkspace(workspace) {
@@ -1620,7 +1863,7 @@ class KritzelStore {
1620
1863
  const objectRange = IDBKeyRange.bound([workspace.id], [workspace.id, '\uffff']);
1621
1864
  await this._database.deleteByRange('objects', objectRange);
1622
1865
  await this._database.delete('workspaces', workspace.id);
1623
- this.state.workspaces = this.state.workspaces.filter(ws => ws.id !== workspace.id);
1866
+ this._store.setState('workspaces', this._store.state.workspaces.filter(ws => ws.id !== workspace.id));
1624
1867
  }
1625
1868
  rerender() {
1626
1869
  if (this._kritzelEngine) {
@@ -1628,7 +1871,7 @@ class KritzelStore {
1628
1871
  }
1629
1872
  }
1630
1873
  findObjectById(id) {
1631
- for (const object of this.allObjects) {
1874
+ for (const object of this._store.allObjects) {
1632
1875
  if (object.id === id) {
1633
1876
  return object;
1634
1877
  }
@@ -1636,33 +1879,18 @@ class KritzelStore {
1636
1879
  return null;
1637
1880
  }
1638
1881
  deselectAllObjects() {
1639
- if (this._state.selectionGroup) {
1882
+ if (this._store.state.selectionGroup) {
1640
1883
  this._history.executeCommand(new index$1.RemoveSelectionGroupCommand(this, this));
1641
1884
  }
1642
1885
  }
1643
- onStateChange(property, listener) {
1644
- if (!this._listeners.has(property)) {
1645
- this._listeners.set(property, new Set());
1646
- }
1647
- this._listeners.get(property).add(listener);
1648
- }
1649
- setState(property, value) {
1650
- const oldValue = this._state[property];
1651
- if (oldValue !== value) {
1652
- this._state[property] = value;
1653
- if (this._listeners.has(property)) {
1654
- this._listeners.get(property).forEach(listener => listener(value, oldValue, String(property)));
1655
- }
1656
- }
1657
- }
1658
1886
  delete() {
1659
- if (!this.state.selectionGroup) {
1887
+ if (!this._store.state.selectionGroup) {
1660
1888
  return;
1661
1889
  }
1662
- const deleteSelectedObjectsCommand = this.state.selectionGroup.objects.map(obj => new index$1.RemoveObjectCommand(this, this.state.selectionGroup, obj));
1663
- const removeSelectionGroupCommand = new index$1.RemoveSelectionGroupCommand(this, this.state.selectionGroup);
1890
+ const deleteSelectedObjectsCommand = this._store.state.selectionGroup.objects.map(obj => new index$1.RemoveObjectCommand(this, this._store.state.selectionGroup, obj));
1891
+ const removeSelectionGroupCommand = new index$1.RemoveSelectionGroupCommand(this, this._store.state.selectionGroup);
1664
1892
  const commands = [...deleteSelectedObjectsCommand, removeSelectionGroupCommand];
1665
- this.history.executeCommand(new index$1.BatchCommand(this, this.state.selectionGroup, commands));
1893
+ this.history.executeCommand(new index$1.BatchCommand(this, this._store.state.selectionGroup, commands));
1666
1894
  }
1667
1895
  deleteObject(id, skipHistory = false) {
1668
1896
  const object = this.findObjectById(id);
@@ -1672,28 +1900,30 @@ class KritzelStore {
1672
1900
  }
1673
1901
  }
1674
1902
  copy() {
1675
- this.state.copiedObjects = this.state.selectionGroup.copy();
1903
+ this._store.setState('copiedObjects', this._store.state.selectionGroup.copy());
1676
1904
  }
1677
1905
  paste(x, y) {
1678
- this.state.copiedObjects.isSelected = true;
1679
- const adjustedX = x !== undefined ? x : this.state.copiedObjects.translateX + 25;
1680
- const adjustedY = y !== undefined ? y : this.state.copiedObjects.translateY + 25;
1681
- this.state.copiedObjects.updatePosition(adjustedX, adjustedY);
1906
+ const copiedObjects = this._store.state.copiedObjects;
1907
+ copiedObjects.isSelected = true;
1908
+ this._store.setState('copiedObjects', copiedObjects);
1909
+ const adjustedX = x !== undefined ? x : this._store.state.copiedObjects.translateX + 25 / this._store.state.scale;
1910
+ const adjustedY = y !== undefined ? y : this._store.state.copiedObjects.translateY + 25 / this._store.state.scale;
1911
+ this._store.state.copiedObjects.updatePosition(adjustedX, adjustedY);
1682
1912
  const commands = [];
1683
- if (this.state.selectionGroup !== null) {
1684
- commands.push(new index$1.RemoveSelectionGroupCommand(this, this.state.selectionGroup));
1913
+ if (this._store.state.selectionGroup !== null) {
1914
+ commands.push(new index$1.RemoveSelectionGroupCommand(this, this._store.state.selectionGroup));
1685
1915
  }
1686
- const addCopiedObjectsCommands = this.state.copiedObjects.objects.map(obj => new index$1.AddObjectCommand(this, this, obj));
1687
- const addCopiedObjectsAsSelectionGroupCommand = new index$1.AddSelectionGroupCommand(this, this, this.state.copiedObjects);
1916
+ const addCopiedObjectsCommands = this._store.state.copiedObjects.objects.map(obj => new index$1.AddObjectCommand(this, this, obj));
1917
+ const addCopiedObjectsAsSelectionGroupCommand = new index$1.AddSelectionGroupCommand(this, this, this._store.state.copiedObjects);
1688
1918
  commands.push(...addCopiedObjectsCommands, addCopiedObjectsAsSelectionGroupCommand);
1689
1919
  this.history.executeCommand(new index$1.BatchCommand(this, this, commands));
1690
- this.state.isSelecting = false;
1691
- this.state.copiedObjects = this.state.selectionGroup.copy();
1692
- this.setState('activeTool', index$1.KritzelToolRegistry.getTool('selection'));
1920
+ this._store.setState('isSelecting', false);
1921
+ this._store.setState('copiedObjects', this._store.state.selectionGroup.copy());
1922
+ this._store.setState('activeTool', index$1.KritzelToolRegistry.getTool('selection'));
1693
1923
  }
1694
1924
  bringForward(object) {
1695
- const max = this.allObjects.length + 1;
1696
- const objects = object ? [object] : this.state.selectionGroup.objects;
1925
+ const max = this._store.allObjects.length + 1;
1926
+ const objects = object ? [object] : this._store.state.selectionGroup.objects;
1697
1927
  const increaseZIndexCommands = objects.map(obj => {
1698
1928
  if (obj.zIndex === max) {
1699
1929
  return;
@@ -1704,7 +1934,7 @@ class KritzelStore {
1704
1934
  }
1705
1935
  sendBackward(object) {
1706
1936
  const min = 0;
1707
- const objects = object ? [object] : this.state.selectionGroup.objects;
1937
+ const objects = object ? [object] : this._store.state.selectionGroup.objects;
1708
1938
  const decreaseZIndexCommands = objects.map(obj => {
1709
1939
  if (obj.zIndex === min) {
1710
1940
  return;
@@ -1714,16 +1944,16 @@ class KritzelStore {
1714
1944
  this.history.executeCommand(new index$1.BatchCommand(this, this, decreaseZIndexCommands));
1715
1945
  }
1716
1946
  bringToFront(object) {
1717
- const max = Math.max(...this.allObjects.map(obj => obj.zIndex)) + 1;
1718
- const objects = object ? [object] : this.state.selectionGroup.objects;
1947
+ const max = Math.max(...this._store.allObjects.map(obj => obj.zIndex)) + 1;
1948
+ const objects = object ? [object] : this._store.state.selectionGroup.objects;
1719
1949
  const increaseZIndexCommands = objects.map(obj => {
1720
1950
  return new index$1.UpdateObjectCommand(this, this, obj, { zIndex: max });
1721
1951
  });
1722
1952
  this.history.executeCommand(new index$1.BatchCommand(this, this, increaseZIndexCommands));
1723
1953
  }
1724
1954
  sendToBack(object) {
1725
- const min = Math.min(...this.allObjects.map(obj => obj.zIndex)) - 1;
1726
- const objects = object ? [object] : this.state.selectionGroup.objects;
1955
+ const min = Math.min(...this._store.allObjects.map(obj => obj.zIndex)) - 1;
1956
+ const objects = object ? [object] : this._store.state.selectionGroup.objects;
1727
1957
  const decreaseZIndexCommands = objects.map(obj => {
1728
1958
  return new index$1.UpdateObjectCommand(this, this, obj, { zIndex: min });
1729
1959
  });
@@ -1739,14 +1969,14 @@ class KritzelStore {
1739
1969
  selectionGroup.addOrRemove(obj);
1740
1970
  });
1741
1971
  selectionGroup.isSelected = true;
1742
- this.state.selectionGroup = selectionGroup;
1972
+ this._store.setState('selectionGroup', selectionGroup);
1743
1973
  if (objects.length === 1) {
1744
1974
  selectionGroup.rotation = selectionGroup.objects[0].rotation;
1745
1975
  }
1746
1976
  this.history.executeCommand(new index$1.AddSelectionGroupCommand(this, this, selectionGroup));
1747
1977
  }
1748
1978
  selectAllObjectsInViewport() {
1749
- const objectsInViewport = this._state.objectsMap
1979
+ const objectsInViewport = this._store.state.objectsMap
1750
1980
  .filter(o => o.isInViewport())
1751
1981
  .filter(o => !(o instanceof index$1.KritzelSelectionGroup) && !(o instanceof index$1.KrtizelSelectionBox) && !(o instanceof KritzelContextMenu));
1752
1982
  if (objectsInViewport.length > 0) {
@@ -1756,31 +1986,31 @@ class KritzelStore {
1756
1986
  selectionGroup.addOrRemove(obj);
1757
1987
  });
1758
1988
  selectionGroup.isSelected = true;
1759
- this.state.isSelecting = false;
1989
+ this._store.setState('isSelecting', false);
1760
1990
  if (objectsInViewport.length === 1) {
1761
1991
  selectionGroup.rotation = selectionGroup.objects[0].rotation;
1762
1992
  }
1763
1993
  this.history.executeCommand(new index$1.AddSelectionGroupCommand(this, this, selectionGroup));
1764
- this.setState('activeTool', index$1.KritzelToolRegistry.getTool('selection'));
1994
+ this._store.setState('activeTool', index$1.KritzelToolRegistry.getTool('selection'));
1765
1995
  }
1766
1996
  }
1767
1997
  clearSelection() {
1768
- const command = new index$1.RemoveSelectionGroupCommand(this, this.state.selectionGroup);
1998
+ const command = new index$1.RemoveSelectionGroupCommand(this, this._store.state.selectionGroup);
1769
1999
  this.history.executeCommand(command);
1770
- this.state.selectionGroup = null;
1771
- this.state.selectionBox = null;
1772
- this.state.isSelecting = false;
1773
- this.state.isResizeHandleSelected = false;
1774
- this.state.isRotationHandleSelected = false;
2000
+ this._store.setState('selectionGroup', null);
2001
+ this._store.setState('selectionBox', null);
2002
+ this._store.setState('isSelecting', false);
2003
+ this._store.setState('isResizeHandleSelected', false);
2004
+ this._store.setState('isRotationHandleSelected', false);
1775
2005
  }
1776
2006
  resetActiveText() {
1777
- if (this.state.activeText && this.state.activeText.value === ' ') {
1778
- this.deleteObject(this.state.activeText.id, true);
2007
+ if (this._store.state.activeText && this._store.state.activeText.value === ' ') {
2008
+ this.deleteObject(this._store.state.activeText.id, true);
1779
2009
  }
1780
- this.state.activeText = null;
2010
+ this._store.setState('activeText', null);
1781
2011
  }
1782
2012
  getObjectFromPointerEvent(event, selector = '.object') {
1783
- const shadowRoot = this.state.host?.shadowRoot;
2013
+ const shadowRoot = this._store.state.host?.shadowRoot;
1784
2014
  if (!shadowRoot)
1785
2015
  return null;
1786
2016
  const clientX = event.clientX;
@@ -1790,12 +2020,14 @@ class KritzelStore {
1790
2020
  return null;
1791
2021
  const selectedObject = elementAtPoint.closest(selector);
1792
2022
  if (selectedObject) {
1793
- return this.allObjects.find(object => selectedObject.id === object.id);
2023
+ const foundObject = this._store.allObjects.find(object => selectedObject.id === object.id);
2024
+ const isHit = foundObject?.hitTest(clientX, clientY);
2025
+ return isHit ? foundObject : null;
1794
2026
  }
1795
2027
  return null;
1796
2028
  }
1797
2029
  getObjectsFromPointerEvent(event, selector = '.object') {
1798
- const shadowRoot = this.state.host?.shadowRoot;
2030
+ const shadowRoot = this._store.state.host?.shadowRoot;
1799
2031
  if (!shadowRoot)
1800
2032
  return [];
1801
2033
  const clientX = event.clientX;
@@ -1811,288 +2043,119 @@ class KritzelStore {
1811
2043
  }
1812
2044
  });
1813
2045
  if (objectIds.size > 0) {
1814
- return this.allObjects.filter(object => objectIds.has(object.id)).sort((a, b) => b.zIndex - a.zIndex);
2046
+ return this._store.allObjects.filter(object => objectIds.has(object.id)).sort((a, b) => b.zIndex - a.zIndex);
1815
2047
  }
1816
2048
  return [];
1817
2049
  }
1818
2050
  getCanvasPoint(event) {
1819
- if (!this.state.host) {
2051
+ if (!this._store.state.host) {
1820
2052
  return { x: 0, y: 0 };
1821
2053
  }
1822
- // Get the position of the kritzel-engine host element relative to the viewport
1823
- const hostRect = this.state.host.getBoundingClientRect();
1824
- // 1. Make the pointer coordinates relative to the host element
2054
+ const hostRect = this._store.state.host.getBoundingClientRect();
1825
2055
  const xRelativeToHost = event.clientX - hostRect.left;
1826
2056
  const yRelativeToHost = event.clientY - hostRect.top;
1827
- // 2. Reverse the translation applied to the #origin div
1828
- const xWithoutTranslate = xRelativeToHost - this.state.translateX;
1829
- const yWithoutTranslate = yRelativeToHost - this.state.translateY;
1830
- // 3. Reverse the scaling to get the final world coordinates
1831
- const worldX = xWithoutTranslate / this.state.scale;
1832
- const worldY = yWithoutTranslate / this.state.scale;
2057
+ const xWithoutTranslate = xRelativeToHost - this._store.state.translateX;
2058
+ const yWithoutTranslate = yRelativeToHost - this._store.state.translateY;
2059
+ const worldX = xWithoutTranslate / this._store.state.scale;
2060
+ const worldY = yWithoutTranslate / this._store.state.scale;
1833
2061
  return { x: worldX, y: worldY };
1834
2062
  }
1835
2063
  }
1836
2064
 
1837
- class KritzelKeyHandler extends index$1.KritzelBaseHandler {
1838
- constructor(store) {
1839
- super(store);
1840
- }
1841
- handleKeyDown(event) {
1842
- if (this._store.state.isFocused === false) {
1843
- return;
1844
- }
1845
- this._store.state.isCtrlKeyPressed = event.ctrlKey;
1846
- if (this._store.state.isCtrlKeyPressed) {
1847
- event.preventDefault();
1848
- }
1849
- if (event.key === 'Escape' && this._store.state.selectionGroup) {
1850
- this._store.clearSelection();
1851
- }
1852
- if (event.key === 'Delete' && this._store.state.selectionGroup) {
1853
- this._store.delete();
1854
- }
1855
- if (event.key === 'z' && event.ctrlKey) {
1856
- this._store.history.undo();
1857
- }
1858
- if (event.key === 'y' && event.ctrlKey) {
1859
- this._store.history.redo();
1860
- }
1861
- if (event.key === 's' && event.ctrlKey) {
1862
- this._store.setState('activeTool', index$1.KritzelToolRegistry.getTool('selection'));
1863
- this._store.deselectAllObjects();
1864
- }
1865
- if (event.key === 'b' && event.ctrlKey) {
1866
- this._store.setState('activeTool', index$1.KritzelToolRegistry.getTool('brush'));
1867
- this._store.deselectAllObjects();
1868
- }
1869
- if (event.key === 'e' && event.ctrlKey) {
1870
- this._store.setState('activeTool', index$1.KritzelToolRegistry.getTool('eraser'));
1871
- this._store.deselectAllObjects();
1872
- }
1873
- if (event.key === 'i' && event.ctrlKey) {
1874
- this._store.setState('activeTool', index$1.KritzelToolRegistry.getTool('image'));
1875
- this._store.deselectAllObjects();
1876
- }
1877
- if (event.key === 'x' && event.ctrlKey) {
1878
- this._store.setState('activeTool', index$1.KritzelToolRegistry.getTool('text'));
1879
- this._store.deselectAllObjects();
1880
- }
1881
- if (event.key === 'c' && event.ctrlKey && this._store.state.selectionGroup) {
1882
- this._store.copy();
1883
- this._store.rerender();
1884
- }
1885
- if (event.key === 'v' && event.ctrlKey && this._store.state.copiedObjects) {
1886
- this._store.paste();
1887
- }
1888
- if (event.key === '+' && event.ctrlKey && this._store.state.selectionGroup) {
1889
- this._store.bringForward();
1890
- }
1891
- if (event.key === '-' && event.ctrlKey && this._store.state.selectionGroup) {
1892
- this._store.sendBackward();
1893
- }
1894
- if (event.key === '*' && event.shiftKey && this._store.state.selectionGroup) {
1895
- this._store.bringToFront();
1896
- }
1897
- if (event.key === '_' && event.shiftKey && this._store.state.selectionGroup) {
1898
- this._store.sendToBack();
1899
- }
1900
- if (event.key === 'a' && event.ctrlKey && this._store.state.activeText) {
1901
- this._store.state.activeText.selectAll();
1902
- }
1903
- if (event.key === 'v' && event.ctrlKey && this._store.state.activeText) {
1904
- this._store.state.activeText.insertFromClipboard();
1905
- }
1906
- }
1907
- handleKeyUp(event) {
1908
- if (this._store.state.isFocused === false) {
1909
- return;
1910
- }
1911
- this._store.state.isCtrlKeyPressed = event.ctrlKey;
1912
- }
1913
- }
1914
-
1915
- class KritzelContextMenuHandler extends index$1.KritzelBaseHandler {
1916
- globalContextMenuItems = [];
1917
- objectContextMenuItems = [];
1918
- constructor(store, globalContextMenuItems, objectContextMenuItems) {
1919
- super(store);
1920
- this.globalContextMenuItems = globalContextMenuItems;
1921
- this.objectContextMenuItems = objectContextMenuItems;
1922
- }
1923
- handleContextMenu(event) {
1924
- if (this._store.state.skipContextMenu) {
1925
- this._store.state.skipContextMenu = false;
1926
- return;
1927
- }
1928
- const selectedObject = this._store.getObjectFromPointerEvent(event, '.object');
1929
- if (selectedObject && !(selectedObject instanceof index$1.KritzelSelectionGroup)) {
1930
- this._store.state.selectionGroup = index$1.KritzelSelectionGroup.create(this._store);
1931
- this._store.state.selectionGroup.addOrRemove(selectedObject);
1932
- this._store.state.selectionGroup.isSelected = true;
1933
- this._store.state.selectionGroup.rotation = selectedObject.rotation;
1934
- this._store.state.isSelecting = false;
1935
- this._store.history.executeCommand(new index$1.AddSelectionGroupCommand(this._store, this, this._store.state.selectionGroup));
1936
- }
1937
- this._store.state.contextMenuItems = this._store.state.selectionGroup ? this.objectContextMenuItems : this.globalContextMenuItems;
1938
- let x = event.clientX - this._store.offsetX;
1939
- let y = event.clientY - this._store.offsetY;
1940
- const menuWidthEstimate = 150;
1941
- const menuHeightEstimate = 200;
1942
- const margin = 10;
1943
- if (x + menuWidthEstimate > window.innerWidth - margin) {
1944
- x = window.innerWidth - menuWidthEstimate - margin;
1945
- }
1946
- if (y + menuHeightEstimate > window.innerHeight - margin) {
1947
- y = window.innerHeight - menuHeightEstimate - margin;
1948
- }
1949
- x = Math.max(margin, x);
1950
- y = Math.max(margin, y);
1951
- this._store.state.contextMenuX = x;
1952
- this._store.state.contextMenuY = y;
1953
- this._store.state.isContextMenuVisible = true;
1954
- this._store.state.isEnabled = false;
1955
- this._store.rerender();
1956
- }
1957
- }
1958
-
1959
- class KritzelClassHelper {
1960
- static isInstanceOf(object, className) {
1961
- return !!object && object.__class__ === className;
1962
- }
1963
- }
1964
-
1965
2065
  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}";
1966
2066
 
1967
2067
  const KritzelEngine = class {
2068
+ get host() { return index.getElement(this); }
1968
2069
  workspace;
2070
+ onWorkspaceChange(newWorkspace) {
2071
+ if (this.core.store.state.activeWorkspace !== newWorkspace) {
2072
+ this.core.initializeWorkspace(newWorkspace);
2073
+ }
2074
+ }
1969
2075
  activeTool;
1970
2076
  globalContextMenuItems;
1971
2077
  objectContextMenuItems;
1972
2078
  scaleMax = ABSOLUTE_SCALE_MAX;
1973
- scaleMin = ABSOLUTE_SCALE_MIN;
1974
- isEngineReady;
1975
- activeToolChange;
1976
- workspacesChange;
1977
- get host() { return index.getElement(this); }
1978
- forceUpdate = 0;
1979
- onWorkspaceChange(newWorkspace) {
1980
- if (newWorkspace) {
1981
- this.store.initializeWorkspace(newWorkspace);
1982
- }
1983
- }
1984
2079
  validateScaleMax(newValue) {
1985
2080
  if (newValue > ABSOLUTE_SCALE_MAX) {
1986
2081
  console.warn(`scaleMax cannot be greater than ${ABSOLUTE_SCALE_MAX}.`);
1987
2082
  this.scaleMax = ABSOLUTE_SCALE_MAX;
1988
- this.store.state.scaleMax = this.scaleMax;
2083
+ this.core.store.setState('scaleMax', this.scaleMax);
1989
2084
  }
1990
2085
  else {
1991
- this.store.state.scaleMax = newValue;
2086
+ this.core.store.setState('scaleMax', newValue);
1992
2087
  }
1993
2088
  }
2089
+ scaleMin = ABSOLUTE_SCALE_MIN;
1994
2090
  validateScaleMin(newValue) {
1995
2091
  if (newValue < ABSOLUTE_SCALE_MIN) {
1996
2092
  console.warn(`scaleMin cannot be less than ${ABSOLUTE_SCALE_MIN}.`);
1997
2093
  this.scaleMin = ABSOLUTE_SCALE_MIN;
1998
- this.store.state.scaleMin = this.scaleMin;
2094
+ this.core.store.setState('scaleMin', this.scaleMin);
1999
2095
  }
2000
2096
  else {
2001
- this.store.state.scaleMin = newValue;
2002
- }
2003
- }
2004
- store;
2005
- viewport;
2006
- contextMenuHandler;
2007
- keyHandler;
2008
- contextMenuElement = null;
2009
- get isSelecting() {
2010
- return this.store.state.activeTool instanceof index$1.KritzelSelectionTool && this.store.state.isSelecting;
2011
- }
2012
- get isSelectionActive() {
2013
- return this.store.state.activeTool instanceof index$1.KritzelSelectionTool && this.store.state.selectionGroup !== null;
2014
- }
2015
- constructor(hostRef) {
2016
- index.registerInstance(this, hostRef);
2017
- this.isEngineReady = index.createEvent(this, "isEngineReady");
2018
- this.activeToolChange = index.createEvent(this, "activeToolChange");
2019
- this.workspacesChange = index.createEvent(this, "workspacesChange");
2020
- this.store = new KritzelStore(this);
2021
- }
2022
- componentWillLoad() {
2023
- this.validateScaleMax(this.scaleMax);
2024
- this.validateScaleMin(this.scaleMin);
2025
- }
2026
- async componentDidLoad() {
2027
- this.contextMenuHandler = new KritzelContextMenuHandler(this.store, this.globalContextMenuItems, this.objectContextMenuItems);
2028
- this.keyHandler = new KritzelKeyHandler(this.store);
2029
- this.viewport = new KritzelViewport(this.store, this.host);
2030
- this._registerStateChangeListeners();
2031
- await this.store.initializeDatabase();
2032
- await this.store.initializeWorkspace(this.workspace);
2033
- if (this.store.state.isReady === false) {
2034
- this.store.state.isReady = true;
2035
- this.isEngineReady.emit(this.store.state);
2097
+ this.core.store.setState('scaleMin', newValue);
2036
2098
  }
2037
2099
  }
2100
+ isEngineReady;
2101
+ activeToolChange;
2102
+ workspacesChange;
2103
+ longpress;
2104
+ forceUpdate = 0;
2038
2105
  handleWheel(ev) {
2039
- if (this.store.isDisabled) {
2106
+ if (this.core.store.isDisabled) {
2040
2107
  return;
2041
2108
  }
2042
- if (this.store.state.isContextMenuVisible) {
2109
+ if (this.core.store.state.isContextMenuVisible) {
2043
2110
  this.hideContextMenu();
2044
2111
  }
2045
2112
  this.viewport.handleWheel(ev);
2046
- this.store.state?.activeTool?.handleWheel(ev);
2113
+ this.core.store.state?.activeTool?.handleWheel(ev);
2047
2114
  }
2048
2115
  handlePointerDown(ev) {
2049
- if (this.store.isDisabled) {
2116
+ if (this.core.store.isDisabled) {
2050
2117
  return;
2051
2118
  }
2052
- if (index$1.KritzelEventHelper.isPointerEventOnContextMenu(ev) === false && this.store.state.isContextMenuVisible) {
2053
- this.hideContextMenu();
2054
- return;
2119
+ if (KritzelDevicesHelper.isTouchDevice()) {
2120
+ index$1.KritzelEventHelper.onLongPress(ev, (event) => this.longpress.emit(event));
2055
2121
  }
2056
- index$1.KritzelEventHelper.onLongTouchPress(ev, (event) => {
2057
- if (!(this.store.state.activeTool instanceof index$1.KritzelSelectionTool)) {
2058
- return;
2059
- }
2060
- this.contextMenuHandler.handleContextMenu(event);
2061
- });
2062
2122
  this.host.setPointerCapture(ev.pointerId);
2063
- this.store.state.pointers.set(ev.pointerId, ev);
2123
+ this.core.store.state.pointers.set(ev.pointerId, ev);
2064
2124
  this.viewport.handlePointerDown(ev);
2065
- this.store.state?.activeTool?.handlePointerDown(ev);
2125
+ this.core.store.state?.activeTool?.handlePointerDown(ev);
2066
2126
  }
2067
2127
  handlePointerMove(ev) {
2068
- if (this.store.isDisabled) {
2128
+ if (this.core.store.isDisabled) {
2069
2129
  return;
2070
2130
  }
2071
- this.store.state.pointers.set(ev.pointerId, ev);
2131
+ this.core.store.state.pointers.set(ev.pointerId, ev);
2072
2132
  this.viewport.handlePointerMove(ev);
2073
- this.store.state?.activeTool?.handlePointerMove(ev);
2133
+ this.core.store.state?.activeTool?.handlePointerMove(ev);
2074
2134
  }
2075
2135
  handlePointerUp(ev) {
2076
- if (this.store.isDisabled) {
2136
+ if (this.core.store.isDisabled) {
2077
2137
  return;
2078
2138
  }
2079
- this.store.state.pointers.delete(ev.pointerId);
2139
+ this.core.store.state.pointers.delete(ev.pointerId);
2080
2140
  this.host.releasePointerCapture(ev.pointerId);
2081
2141
  this.viewport.handlePointerUp(ev);
2082
- this.store.state?.activeTool?.handlePointerUp(ev);
2142
+ this.core.store.state?.activeTool?.handlePointerUp(ev);
2083
2143
  }
2084
2144
  handlePointerCancel(ev) {
2085
- if (this.store.isDisabled) {
2145
+ if (this.core.store.isDisabled) {
2086
2146
  return;
2087
2147
  }
2088
2148
  this.host.releasePointerCapture(ev.pointerId);
2089
- this.store.state.pointers.delete(ev.pointerId);
2149
+ this.core.store.state.pointers.delete(ev.pointerId);
2090
2150
  this.viewport.handlePointerUp(ev);
2091
- this.store.state?.activeTool?.handlePointerUp(ev);
2151
+ this.core.store.state?.activeTool?.handlePointerUp(ev);
2152
+ }
2153
+ handleLongPress(ev) {
2154
+ this.contextMenuHandler.handleContextMenu(ev.detail);
2092
2155
  }
2093
2156
  handleContextMenu(ev) {
2094
2157
  ev.preventDefault();
2095
- if (this.store.isDisabled) {
2158
+ if (this.core.store.isDisabled) {
2096
2159
  return;
2097
2160
  }
2098
2161
  if (ev.pointerType === 'touch') {
@@ -2109,26 +2172,12 @@ const KritzelEngine = class {
2109
2172
  handleKeyUp(ev) {
2110
2173
  this.keyHandler.handleKeyUp(ev);
2111
2174
  }
2112
- updateFocus(ev) {
2113
- if (this.store.isDisabled) {
2114
- return;
2115
- }
2116
- const rect = this.store.state.host.getBoundingClientRect();
2117
- const isInside = ev.clientX >= rect.left && ev.clientX <= rect.right && ev.clientY >= rect.top && ev.clientY <= rect.bottom;
2118
- const path = ev.composedPath();
2119
- const kritzelEngineElement = this.host.closest('kritzel-engine');
2120
- const isInKritzelEngine = path.includes(kritzelEngineElement || this.host);
2121
- this.store.setState('isFocused', isInside && isInKritzelEngine);
2122
- }
2123
- handleClick() {
2124
- this.enable();
2125
- }
2126
2175
  async registerTool(toolName, toolClass, toolConfig) {
2127
2176
  if (typeof toolClass !== 'function' || !(toolClass.prototype instanceof index$1.KritzelBaseTool)) {
2128
2177
  console.error(`Failed to register tool "${toolName}": Tool class must be a constructor function`);
2129
2178
  return null;
2130
2179
  }
2131
- const registeredTool = index$1.KritzelToolRegistry.registerTool(toolName, toolClass, this.store);
2180
+ const registeredTool = index$1.KritzelToolRegistry.registerTool(toolName, toolClass, this.core);
2132
2181
  if (toolConfig) {
2133
2182
  Object.entries(toolConfig).forEach(([key, value]) => {
2134
2183
  registeredTool[key] = value;
@@ -2137,153 +2186,188 @@ const KritzelEngine = class {
2137
2186
  return Promise.resolve(registeredTool);
2138
2187
  }
2139
2188
  async changeActiveTool(tool) {
2140
- this.store.state.activeTool?.onDeactivate();
2141
- this.store.setState('activeTool', tool);
2142
- this.store.deselectAllObjects();
2189
+ this.core.store.state.activeTool?.onDeactivate();
2190
+ this.core.store.setState('activeTool', tool);
2191
+ this.core.deselectAllObjects();
2143
2192
  tool?.onActivate();
2144
2193
  }
2145
- async setFocus() {
2146
- this.host.focus();
2147
- this.store.state.isFocused = true;
2148
- }
2149
2194
  async disable() {
2150
- this.store.state.isEnabled = false;
2151
- this.forceUpdate++;
2195
+ this.core.store.setState('isEnabled', false);
2196
+ this.core.rerender();
2152
2197
  }
2153
2198
  async enable() {
2154
- this.store.state.isEnabled = true;
2155
- this.forceUpdate++;
2199
+ this.core.store.setState('isEnabled', true);
2200
+ this.core.rerender();
2156
2201
  }
2157
2202
  async delete() {
2158
- this.store.delete();
2203
+ this.core.delete();
2159
2204
  }
2160
2205
  async copy() {
2161
- this.store.copy();
2206
+ this.core.copy();
2162
2207
  }
2163
2208
  async paste(x, y) {
2164
- this.store.paste(x, y);
2209
+ this.core.paste(x, y);
2165
2210
  }
2166
2211
  async bringForward(object) {
2167
- this.store.bringForward(object);
2212
+ this.core.bringForward(object);
2168
2213
  }
2169
2214
  async sendBackward(object) {
2170
- this.store.sendBackward(object);
2215
+ this.core.sendBackward(object);
2171
2216
  }
2172
2217
  async bringToFront(object) {
2173
- this.store.bringToFront(object);
2218
+ this.core.bringToFront(object);
2174
2219
  }
2175
2220
  async sendToBack(object) {
2176
- this.store.sendToBack(object);
2221
+ this.core.sendToBack(object);
2177
2222
  }
2178
2223
  async undo() {
2179
- this.store.history.undo();
2224
+ this.core.history.undo();
2180
2225
  }
2181
2226
  async redo() {
2182
- this.store.history.redo();
2227
+ this.core.history.redo();
2183
2228
  }
2184
2229
  async hideContextMenu() {
2185
- this.store.state.pointers.clear();
2186
- this.store.state.isContextMenuVisible = false;
2187
- this.store.state.selectionBox = null;
2188
- this.store.state.isSelecting = false;
2230
+ this.core.store.state.pointers.clear();
2231
+ this.core.store.setState('isContextMenuVisible', false);
2232
+ this.core.store.setState('selectionBox', null);
2233
+ this.core.store.setState('isSelecting', false);
2234
+ this.core.store.setState('isEnabled', true);
2235
+ this.core.rerender();
2189
2236
  }
2190
2237
  async getObjectById(id) {
2191
- const object = this.store.objects.find(obj => obj.id === id);
2238
+ const object = this.core.store.allObjects.find(obj => obj.id === id);
2192
2239
  return object || null;
2193
2240
  }
2194
2241
  async addObject(object) {
2195
- this.store.deselectAllObjects();
2242
+ this.core.deselectAllObjects();
2196
2243
  object.id = object.generateId();
2197
- object._store = this.store;
2198
- object.scale = object.scale ? object.scale : this.store.state.scale;
2199
- object.zIndex = this.store.currentZIndex;
2200
- const command = new index$1.AddObjectCommand(this.store, this, object);
2201
- this.store.history.executeCommand(command);
2244
+ object._core = this.core;
2245
+ object.scale = object.scale ? object.scale : this.core.store.state.scale;
2246
+ object.zIndex = this.core.store.currentZIndex;
2247
+ const command = new index$1.AddObjectCommand(this.core, this, object);
2248
+ this.core.history.executeCommand(command);
2202
2249
  return object;
2203
2250
  }
2204
2251
  async updateObject(object, updatedProperties) {
2205
- this.store.deselectAllObjects();
2206
- const command = new index$1.UpdateObjectCommand(this.store, this, object, updatedProperties);
2207
- this.store.history.executeCommand(command);
2252
+ this.core.deselectAllObjects();
2253
+ const command = new index$1.UpdateObjectCommand(this.core, this, object, updatedProperties);
2254
+ this.core.history.executeCommand(command);
2208
2255
  return object;
2209
2256
  }
2210
2257
  async removeObject(object) {
2211
- this.store.deselectAllObjects();
2212
- const command = new index$1.RemoveObjectCommand(this.store, this, object);
2213
- this.store.history.executeCommand(command);
2258
+ this.core.deselectAllObjects();
2259
+ const command = new index$1.RemoveObjectCommand(this.core, this, object);
2260
+ this.core.history.executeCommand(command);
2214
2261
  return object;
2215
2262
  }
2216
2263
  async getSelectedObjects() {
2217
- return this.store.state.selectionGroup ? this.store.state.selectionGroup.objects : [];
2264
+ return this.core.store.state.selectionGroup ? this.core.store.state.selectionGroup.objects : [];
2218
2265
  }
2219
2266
  async selectObjects(objects) {
2220
- this.store.state.activeTool?.onDeactivate();
2221
- this.store.setState('activeTool', index$1.KritzelToolRegistry.getTool('selection'));
2222
- this.store.deselectAllObjects();
2223
- this.store.selectObjects(objects);
2267
+ this.core.store.state.activeTool?.onDeactivate();
2268
+ this.core.store.setState('activeTool', index$1.KritzelToolRegistry.getTool('selection'));
2269
+ this.core.deselectAllObjects();
2270
+ this.core.selectObjects(objects);
2224
2271
  }
2225
2272
  async selectAllObjectsInViewport() {
2226
- this.store.state.activeTool?.onDeactivate();
2227
- this.store.setState('activeTool', index$1.KritzelToolRegistry.getTool('selection'));
2228
- this.store.deselectAllObjects();
2229
- this.store.selectAllObjectsInViewport();
2273
+ this.core.store.state.activeTool?.onDeactivate();
2274
+ this.core.store.setState('activeTool', index$1.KritzelToolRegistry.getTool('selection'));
2275
+ this.core.deselectAllObjects();
2276
+ this.core.selectAllObjectsInViewport();
2230
2277
  }
2231
2278
  async clearSelection() {
2232
- this.store.clearSelection();
2279
+ this.core.clearSelection();
2233
2280
  }
2234
2281
  async centerObjectInViewport(object) {
2235
2282
  object.centerInViewport();
2236
- const command = new index$1.UpdateObjectCommand(this.store, this, object, object);
2237
- this.store.history.executeCommand(command);
2283
+ const command = new index$1.UpdateObjectCommand(this.core, this, object, object);
2284
+ this.core.history.executeCommand(command);
2238
2285
  return object;
2239
2286
  }
2240
2287
  async getCopiedObjects() {
2241
- return this.store.state.copiedObjects?.objects || [];
2288
+ return this.core.store.state.copiedObjects?.objects || [];
2242
2289
  }
2243
2290
  async createWorkspace(workspace) {
2244
- return this.store.createWorkspace(workspace).then(() => {
2245
- this.workspacesChange.emit(this.store.state.workspaces);
2246
- });
2291
+ workspace._core = this.core;
2292
+ await this.core.createWorkspace(workspace);
2293
+ this.workspacesChange.emit(this.core.store.state.workspaces);
2294
+ return workspace;
2247
2295
  }
2248
2296
  async updateWorkspace(workspace) {
2249
- return this.store.updateWorkspace(workspace).then(() => {
2250
- this.workspacesChange.emit(this.store.state.workspaces);
2251
- });
2297
+ await this.core.updateWorkspace(workspace);
2298
+ this.workspacesChange.emit(this.core.store.state.workspaces);
2252
2299
  }
2253
2300
  async deleteWorkspace(workspace) {
2254
- return this.store.deleteWorkspace(workspace).then(async () => {
2255
- this.workspacesChange.emit(this.store.state.workspaces);
2256
- });
2301
+ await this.core.deleteWorkspace(workspace);
2302
+ this.workspacesChange.emit(this.core.store.state.workspaces);
2257
2303
  }
2258
2304
  async getWorkspaces() {
2259
- return this.store.getWorkspaces();
2305
+ return this.core.getWorkspaces();
2306
+ }
2307
+ async getActiveWorkspace() {
2308
+ return this.core.store.state.activeWorkspace;
2309
+ }
2310
+ core;
2311
+ viewport;
2312
+ contextMenuHandler;
2313
+ keyHandler;
2314
+ contextMenuElement = null;
2315
+ get isSelecting() {
2316
+ return this.core.store.state.activeTool instanceof index$1.KritzelSelectionTool && this.core.store.state.isSelecting;
2317
+ }
2318
+ get isSelectionActive() {
2319
+ return this.core.store.state.activeTool instanceof index$1.KritzelSelectionTool && this.core.store.state.selectionGroup !== null;
2320
+ }
2321
+ constructor(hostRef) {
2322
+ index.registerInstance(this, hostRef);
2323
+ this.isEngineReady = index.createEvent(this, "isEngineReady");
2324
+ this.activeToolChange = index.createEvent(this, "activeToolChange");
2325
+ this.workspacesChange = index.createEvent(this, "workspacesChange");
2326
+ this.longpress = index.createEvent(this, "longpress");
2327
+ this.core = new KritzelCore(this);
2328
+ }
2329
+ componentWillLoad() {
2330
+ this.validateScaleMax(this.scaleMax);
2331
+ this.validateScaleMin(this.scaleMin);
2332
+ }
2333
+ async componentDidLoad() {
2334
+ this.contextMenuHandler = new KritzelContextMenuHandler(this.core, this.globalContextMenuItems, this.objectContextMenuItems);
2335
+ this.keyHandler = new KritzelKeyHandler(this.core);
2336
+ this.viewport = new KritzelViewport(this.core, this.host);
2337
+ await this.core.initializeDatabase();
2338
+ await this.core.initializeWorkspace(this.workspace);
2339
+ this._registerStateChangeListeners();
2340
+ if (this.core.store.state.isReady === false) {
2341
+ this.core.store.setState('isReady', true);
2342
+ this.isEngineReady.emit(this.core.store.state);
2343
+ }
2260
2344
  }
2261
2345
  _registerStateChangeListeners() {
2262
- this.store.onStateChange('activeTool', this._handleActiveToolChange.bind(this));
2263
- this.store.onStateChange('isFocused', this._handleIsFocusedChange.bind(this));
2346
+ this.core.store.onStateChange('activeTool', this._handleActiveToolChange.bind(this));
2264
2347
  }
2265
2348
  _handleActiveToolChange(activeTool) {
2266
2349
  if (!(activeTool instanceof index$1.KritzelSelectionTool)) {
2267
- this.store.clearSelection();
2350
+ this.core.clearSelection();
2268
2351
  }
2269
- this.store.state.skipContextMenu = false;
2352
+ this.core.store.setState('skipContextMenu', false);
2270
2353
  this.activeToolChange.emit(activeTool);
2271
2354
  index$1.KritzelKeyboardHelper.forceHideKeyboard();
2272
2355
  }
2273
- _handleIsFocusedChange(isFocused) {
2274
- if (!isFocused) {
2275
- this.store.resetActiveText();
2276
- }
2277
- }
2278
2356
  render() {
2279
2357
  const computedStyle = window.getComputedStyle(this.host);
2280
2358
  const baseHandleSizePx = computedStyle.getPropertyValue('--kritzel-selection-handle-size').trim() || '6px';
2281
2359
  const baseHandleSize = parseFloat(baseHandleSizePx);
2282
2360
  const baseHandleTouchSize = baseHandleSize * 2 < 14 ? 14 : baseHandleSize;
2283
- return (index.h(index.Host, { key: 'fd353ff17bcde1a9ab646b6f463d1c6ce00a3dff' }, index.h("div", { key: '45bc2af8f1a3a2bfa3aa76a478c7bf208027da0c', class: "debug-panel", style: { display: this.store.state.debugInfo.showViewportInfo ? 'block' : 'none' } }, index.h("div", { key: '50e932febc35c7dbe852ad99d96ca4f0e0b742fc' }, "ActiveWorkspaceId: ", this.store.state?.activeWorkspace?.id), index.h("div", { key: 'af94b5061f0803588fece6cccdf540f46f13ca05' }, "ActiveWorkspaceName: ", this.store.state?.activeWorkspace?.name), index.h("div", { key: '89c0d21ce94f4eda72153554fadbd6942e785edc' }, "TranslateX: ", this.store.state?.translateX), index.h("div", { key: '340b5165265241972a7a940268c7940063ba8c12' }, "TranslateY: ", this.store.state?.translateY), index.h("div", { key: '428054b3ea4a1c327f03d6b37bfe6331dea6c57b' }, "ViewportWidth: ", this.store.state?.viewportWidth), index.h("div", { key: 'd67420ef633627413066a28b8ef9ac43c520015d' }, "ViewportHeight: ", this.store.state?.viewportHeight), index.h("div", { key: 'dedf9eb89c79fa496f7b6d0df9c646898f66b3d4' }, "ObjectsInViewport. ", this.store.objects.length), index.h("div", { key: '59bb8416941fd84305f2892f24098f6f4a084401' }, "Scale: ", this.store.state?.scale), index.h("div", { key: '6705a4cec22e4e33f75e296e17bc2952a3d1cba7' }, "ActiveTool: ", this.store.state?.activeTool?.name), index.h("div", { key: 'ca22e0a377a11fdca851b38f1bf425648cd3b9dd' }, "HasViewportChanged: ", this.store.state?.hasViewportChanged ? 'true' : 'false'), index.h("div", { key: '57508b9ee24a5af631e6bb1eace404c39af14f82' }, "IsEnabled: ", this.store.state?.isEnabled ? 'true' : 'false'), index.h("div", { key: 'f6cea367b5007f767afb25a033215abda734de9d' }, "IsScaling: ", this.store.state?.isScaling ? 'true' : 'false'), index.h("div", { key: '4386ef749facd2e54da7f58aa2713b87ed76f2df' }, "IsPanning: ", this.store.state?.isPanning ? 'true' : 'false'), index.h("div", { key: '1713185b36a50dfe0f9efa0c92394222db80a377' }, "IsFocused: ", this.store.state.isFocused ? 'true' : 'false'), index.h("div", { key: '5104f428b808e7d843712302ad2e58b619876bee' }, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), index.h("div", { key: '2cb3b27a00627188e7082fa94169eb961a1ae6ed' }, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), index.h("div", { key: '7407656e61be665f27e706738faa6d318e2c1d04' }, "IsResizeHandleSelected: ", this.store.state.isResizeHandleSelected ? 'true' : 'false'), index.h("div", { key: '701bf05c25cb3d3728af6602f694e6064627ea59' }, "IsRotationHandleSelected: ", this.store.state.isRotationHandleSelected ? 'true' : 'false'), index.h("div", { key: '772c345ea9c64ef800fdbb26919f1a54ca889025' }, "IsDrawing: ", this.store.state.isDrawing ? 'true' : 'false'), index.h("div", { key: 'dc687c8ba24182b8b61979ad334b989d3be72ec6' }, "IsWriting: ", this.store.state.isWriting ? 'true' : 'false'), index.h("div", { key: '10cbc575a7905396a76eca4e7b56be719755aeb4' }, "PointerX: ", this.store.state?.pointerX), index.h("div", { key: '4f21199328ffadddcc58b7d6b102a89e5079f676' }, "PointerY: ", this.store.state?.pointerY), index.h("div", { key: 'ac705f38cb323b8dc8cbf95f875657c5dec5c9ae' }, "SelectedObjects: ", this.store.state.selectionGroup?.objects.length || 0)), index.h("div", { key: '2ca55c53246e64520af6720a3f87d2357295ca7f', id: "origin", class: "origin", style: {
2284
- transform: `matrix(${this.store.state?.scale}, 0, 0, ${this.store.state?.scale}, ${this.store.state?.translateX}, ${this.store.state?.translateY})`,
2285
- } }, this.store.state.objectsMap.allObjects()?.map(object => {
2286
- return (index.h("div", { key: object.id, style: { display: object.isInViewport() ? 'block' : 'none', transform: object?.transformationMatrix, transformOrigin: 'top left', zIndex: object.zIndex.toString(), position: 'absolute' } }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", id: object.id, class: "object", style: {
2361
+ return (index.h(index.Host, { key: 'da47553aad7abf8b5daab177c6933a9177b91089' }, index.h("div", { key: '4e64b43bfb85a61154d36ca8ecd3518d61445d50', class: "debug-panel", style: { display: this.core.store.state.debugInfo.showViewportInfo ? 'block' : 'none' } }, index.h("div", { key: '21742da9258a2b929b81c0ca6c8f37f41b228ad4' }, "ActiveWorkspaceId: ", this.core.store.state?.activeWorkspace?.id), index.h("div", { key: 'de31fcf57b0faf8fad2bb39336eeea35dbec35ca' }, "ActiveWorkspaceName: ", this.core.store.state?.activeWorkspace?.name), index.h("div", { key: 'a2cb298a867f92349b5e1fb556ee5f9c6110f1c7' }, "TranslateX: ", this.core.store.state?.translateX), index.h("div", { key: '28697bfcecf9f8b4b1972a90cd02855767433047' }, "TranslateY: ", this.core.store.state?.translateY), index.h("div", { key: '7fb25f6e9c9b8dea11832dbd311d2cc0b981cbeb' }, "ViewportWidth: ", this.core.store.state?.viewportWidth), index.h("div", { key: '92aeade312b3d28e4c9b0e1c7ca55f6932fd23d9' }, "ViewportHeight: ", this.core.store.state?.viewportHeight), index.h("div", { key: 'a4fd8090acaf094e44fdc2e72fcc388695b412c4' }, "Scale: ", this.core.store.state?.scale), index.h("div", { key: '6ff28100b64bafdffcb8fe9d49cd041a6a374817' }, "ActiveTool: ", this.core.store.state?.activeTool?.name), index.h("div", { key: '12a61ad3d070563eb721d0d4068143962914b2bc' }, "HasViewportChanged: ", this.core.store.state?.hasViewportChanged ? 'true' : 'false'), index.h("div", { key: '437309daa2af1a64c9b9d3548fe12e075dd4a8bd' }, "IsEnabled: ", this.core.store.state?.isEnabled ? 'true' : 'false'), index.h("div", { key: 'e6841095c220ebf081604c548729f085ec9d17bd' }, "IsScaling: ", this.core.store.state?.isScaling ? 'true' : 'false'), index.h("div", { key: 'b07316a528782f7560c2e42f7bd9edd473cc256c' }, "IsPanning: ", this.core.store.state?.isPanning ? 'true' : 'false'), index.h("div", { key: '7160a5aa21c4cdbf2b523f620c819ad541a2e466' }, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), index.h("div", { key: '9ad29a686bc76b47d4c5040121b468428ade437a' }, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), index.h("div", { key: '68f240aa7d7188996647afd0df73d63a253e18a1' }, "IsResizeHandleSelected: ", this.core.store.state.isResizeHandleSelected ? 'true' : 'false'), index.h("div", { key: '260010c089bdf0e8fd8c2406c39394ef79a85262' }, "IsRotationHandleSelected: ", this.core.store.state.isRotationHandleSelected ? 'true' : 'false'), index.h("div", { key: '6b07975c781801b0a7d7727d0666a6765aa9e889' }, "IsDrawing: ", this.core.store.state.isDrawing ? 'true' : 'false'), index.h("div", { key: '83c949c9ed26c3d445421ba1f965a742f5fc149f' }, "IsWriting: ", this.core.store.state.isWriting ? 'true' : 'false'), index.h("div", { key: '1687122785d3370da5d91a975dd56f11aebc81c1' }, "PointerX: ", this.core.store.state?.pointerX), index.h("div", { key: 'a28e152a0510c9e3eef5624de1b5512baf45b37c' }, "PointerY: ", this.core.store.state?.pointerY), index.h("div", { key: '09e5a0157002fe95a46415d32a3eb17be8d959a9' }, "SelectedObjects: ", this.core.store.state.selectionGroup?.objects.length || 0)), index.h("div", { key: '5228fbae773f30d91b129c257ef08adca10a6a70', id: "origin", class: "origin", style: {
2362
+ transform: `matrix(${this.core.store.state?.scale}, 0, 0, ${this.core.store.state?.scale}, ${this.core.store.state?.translateX}, ${this.core.store.state?.translateY})`,
2363
+ } }, this.core.store.state.objectsMap.allObjects()?.map(object => {
2364
+ return (index.h("div", { key: object.id, style: {
2365
+ display: object.isInViewport() ? 'block' : 'none',
2366
+ transform: object?.transformationMatrix,
2367
+ transformOrigin: 'top left',
2368
+ zIndex: object.zIndex.toString(),
2369
+ position: 'absolute',
2370
+ } }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", id: object.id, class: "object", style: {
2287
2371
  height: object?.totalHeight.toString(),
2288
2372
  width: object?.totalWidth.toString(),
2289
2373
  left: '0',
@@ -2340,69 +2424,71 @@ const KritzelEngine = class {
2340
2424
  } })), KritzelClassHelper.isInstanceOf(object, 'KrtizelSelectionBox') && (index.h("div", { ref: el => (el ? object.mount(el) : object.unmount()), style: {
2341
2425
  width: '100%',
2342
2426
  height: '100%',
2427
+ backgroundColor: KritzelDevicesHelper.isFirefox() ? object.backgroundColor : 'transparent',
2428
+ borderWidth: KritzelDevicesHelper.isFirefox() ? object.borderWidth + 'px' : '0',
2429
+ borderStyle: KritzelDevicesHelper.isFirefox() ? 'solid' : 'none',
2430
+ borderColor: KritzelDevicesHelper.isFirefox() ? object.borderColor : 'transparent',
2343
2431
  } }))), index.h("line", { x1: "0", y1: "0", x2: object.totalWidth, y2: "0", style: {
2344
2432
  stroke: 'var(--kritzel-selection-border-color, #007AFF)',
2345
- strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.store.state?.scale})`,
2433
+ strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.core.store.state?.scale})`,
2346
2434
  strokeLinecap: 'square',
2347
2435
  }, visibility: object.isSelected ? 'visible' : 'hidden' }), index.h("line", { x1: "0", y1: "0", x2: "0", y2: object.totalHeight, style: {
2348
2436
  stroke: 'var(--kritzel-selection-border-color, #007AFF)',
2349
- strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.store.state?.scale})`,
2437
+ strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.core.store.state?.scale})`,
2350
2438
  strokeLinecap: 'square',
2351
2439
  }, visibility: object.isSelected ? 'visible' : 'hidden' }), index.h("line", { x1: "0", y1: object.totalHeight, x2: object.totalWidth, y2: object.totalHeight, style: {
2352
2440
  stroke: 'var(--kritzel-selection-border-color, #007AFF)',
2353
- strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.store.state?.scale})`,
2441
+ strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.core.store.state?.scale})`,
2354
2442
  strokeLinecap: 'square',
2355
2443
  }, visibility: object.isSelected ? 'visible' : 'hidden' }), index.h("line", { x1: object.totalWidth, y1: "0", x2: object.totalWidth, y2: object.totalHeight, style: {
2356
2444
  stroke: 'var(--kritzel-selection-border-color, #007AFF)',
2357
- strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.store.state?.scale})`,
2445
+ strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.core.store.state?.scale})`,
2358
2446
  strokeLinecap: 'square',
2359
- }, visibility: object.isSelected ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle top-left", cx: "0", cy: "0", r: `${(baseHandleSize * object.scale) / this.store.state?.scale}`, style: {
2447
+ }, visibility: object.isSelected ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle top-left", cx: "0", cy: "0", r: `${(baseHandleSize * object.scale) / this.core.store.state?.scale}`, style: {
2360
2448
  fill: 'var(--kritzel-selection-handle-color, #000000)',
2361
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle-overlay top-left", cx: "0", cy: "0", r: `${(baseHandleTouchSize * object.scale) / this.store.state?.scale}`, style: {
2449
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle-overlay top-left", cx: "0", cy: "0", r: `${(baseHandleTouchSize * object.scale) / this.core.store.state?.scale}`, style: {
2362
2450
  fill: 'transparent',
2363
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle top-right", cx: object.totalWidth, cy: "0", r: `${(baseHandleSize * object.scale) / this.store.state?.scale}`, style: {
2451
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle top-right", cx: object.totalWidth, cy: "0", r: `${(baseHandleSize * object.scale) / this.core.store.state?.scale}`, style: {
2364
2452
  fill: 'var(--kritzel-selection-handle-color, #000000)',
2365
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle-overlay top-right", cx: object.totalWidth, cy: "0", r: `${(baseHandleTouchSize * object.scale) / this.store.state?.scale}`, style: {
2453
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle-overlay top-right", cx: object.totalWidth, cy: "0", r: `${(baseHandleTouchSize * object.scale) / this.core.store.state?.scale}`, style: {
2366
2454
  fill: 'transparent',
2367
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle bottom-left", cx: "0", cy: object.totalHeight, r: `${(baseHandleSize * object.scale) / this.store.state?.scale}`, style: {
2455
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle bottom-left", cx: "0", cy: object.totalHeight, r: `${(baseHandleSize * object.scale) / this.core.store.state?.scale}`, style: {
2368
2456
  fill: 'var(--kritzel-selection-handle-color, #000000)',
2369
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle-overlay bottom-left", cx: "0", cy: object.totalHeight, r: `${(baseHandleTouchSize * object.scale) / this.store.state?.scale}`, style: {
2457
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle-overlay bottom-left", cx: "0", cy: object.totalHeight, r: `${(baseHandleTouchSize * object.scale) / this.core.store.state?.scale}`, style: {
2370
2458
  fill: 'transparent',
2371
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle bottom-right", cx: object.totalWidth, cy: object.totalHeight, r: `${(baseHandleSize * object.scale) / this.store.state?.scale}`, style: {
2459
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle bottom-right", cx: object.totalWidth, cy: object.totalHeight, r: `${(baseHandleSize * object.scale) / this.core.store.state?.scale}`, style: {
2372
2460
  fill: 'var(--kritzel-selection-handle-color, #000000)',
2373
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle-overlay bottom-right", cx: object.totalWidth, cy: object.totalHeight, r: `${(baseHandleTouchSize * object.scale) / this.store.state?.scale}`, style: {
2461
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("circle", { class: "resize-handle-overlay bottom-right", cx: object.totalWidth, cy: object.totalHeight, r: `${(baseHandleTouchSize * object.scale) / this.core.store.state?.scale}`, style: {
2374
2462
  fill: 'transparent',
2375
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("line", { x1: object.totalWidth / 2, y1: "0", x2: object.totalWidth / 2, y2: -((15 * object.scale) / this.store.state?.scale), style: {
2463
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("line", { x1: object.totalWidth / 2, y1: "0", x2: object.totalWidth / 2, y2: -((15 * object.scale) / this.core.store.state?.scale), style: {
2376
2464
  stroke: 'var(--kritzel-selection-border-color, #007AFF)',
2377
- strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.store.state?.scale})`,
2378
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.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: {
2465
+ strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.core.store.state?.scale})`,
2466
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.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: {
2379
2467
  fill: 'var(--kritzel-selection-handle-color, #000000)',
2380
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.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: {
2468
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.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: {
2381
2469
  fill: 'transparent',
2382
2470
  cursor: 'grab',
2383
- }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("g", { style: { display: this.store.state.debugInfo.showObjectInfo ? 'block' : 'none', pointerEvents: 'none' } }, index.h("foreignObject", { x: object.totalWidth.toString(), y: "0", width: "400px", height: "160px", style: { minHeight: '0', minWidth: '0', display: object.isDebugInfoVisible ? 'block' : 'none' } }, index.h("div", { style: { width: '100%', height: '100%' } }, index.h("div", { style: { whiteSpace: 'nowrap' } }, "zIndex: ", object.zIndex), index.h("div", { style: { whiteSpace: 'nowrap' } }, "translateX: ", object.translateX), index.h("div", { style: { whiteSpace: 'nowrap' } }, "translateY: ", object.translateY), index.h("div", { style: { whiteSpace: 'nowrap' } }, "width: ", object.width), index.h("div", { style: { whiteSpace: 'nowrap' } }, "height: ", object.height), index.h("div", { style: { whiteSpace: 'nowrap' } }, "scale: ", object.scale), index.h("div", { style: { whiteSpace: 'nowrap' } }, "rotation: ", object.rotation), index.h("div", { style: { whiteSpace: 'nowrap' } }, "x: ", object.x), index.h("div", { style: { whiteSpace: 'nowrap' } }, "y: ", object.y)))))));
2384
- }), index.h("svg", { key: '0098f1b8233d45f49dc8bdcc13c08f20c04b65e1', class: "object", xmlns: "http://www.w3.org/2000/svg", style: {
2385
- height: this.store.state.currentPath?.height.toString(),
2386
- width: this.store.state.currentPath?.width.toString(),
2471
+ }, visibility: object.isSelected && !this.isSelecting ? 'visible' : 'hidden' }), index.h("g", { style: { display: this.core.store.state.debugInfo.showObjectInfo ? 'block' : 'none', pointerEvents: 'none' } }, index.h("foreignObject", { x: object.totalWidth.toString(), y: "0", width: "400px", height: "160px", style: { minHeight: '0', minWidth: '0', display: object.isDebugInfoVisible ? 'block' : 'none' } }, index.h("div", { style: { width: '100%', height: '100%' } }, index.h("div", { style: { whiteSpace: 'nowrap' } }, "zIndex: ", object.zIndex), index.h("div", { style: { whiteSpace: 'nowrap' } }, "translateX: ", object.translateX), index.h("div", { style: { whiteSpace: 'nowrap' } }, "translateY: ", object.translateY), index.h("div", { style: { whiteSpace: 'nowrap' } }, "width: ", object.width), index.h("div", { style: { whiteSpace: 'nowrap' } }, "height: ", object.height), index.h("div", { style: { whiteSpace: 'nowrap' } }, "scale: ", object.scale), index.h("div", { style: { whiteSpace: 'nowrap' } }, "rotation: ", object.rotation), index.h("div", { style: { whiteSpace: 'nowrap' } }, "x: ", object.x), index.h("div", { style: { whiteSpace: 'nowrap' } }, "y: ", object.y)))))));
2472
+ }), index.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: {
2387
2473
  left: '0',
2388
2474
  top: '0',
2389
- zIndex: this.store.state.currentPath?.zIndex.toString(),
2475
+ zIndex: this.core.store.state.currentPath?.zIndex.toString(),
2390
2476
  position: 'absolute',
2391
- transform: this.store.state.currentPath?.transformationMatrix,
2477
+ transform: this.core.store.state.currentPath?.transformationMatrix,
2392
2478
  transformOrigin: 'top left',
2393
2479
  overflow: 'visible',
2394
- }, viewBox: this.store.state.currentPath?.viewBox }, index.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 && (index.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: {
2480
+ }, viewBox: this.core.store.state.currentPath?.viewBox }, index.h("path", { key: '6dedb398968d275166e042660c4718635b57da84', 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 && (index.h("kritzel-context-menu", { key: '09ae0d7842918bcb4ae9fd16d416badc19942264', class: "context-menu", ref: el => (this.contextMenuElement = el), items: this.core.store.state.contextMenuItems, objects: this.core.store.state.selectionGroup?.objects || [], style: {
2395
2481
  position: 'fixed',
2396
- left: `${this.store.state.contextMenuX}px`,
2397
- top: `${this.store.state.contextMenuY}px`,
2482
+ left: `${this.core.store.state.contextMenuX}px`,
2483
+ top: `${this.core.store.state.contextMenuY}px`,
2398
2484
  zIndex: '10000',
2399
2485
  }, onActionSelected: event => {
2400
2486
  event.detail.action({
2401
- x: (-this.store.state.translateX + this.store.state.contextMenuX) / this.store.state.scale,
2402
- y: (-this.store.state.translateY + this.store.state.contextMenuY) / this.store.state.scale,
2403
- }, this.store.state.selectionGroup?.objects);
2487
+ x: (-this.core.store.state.translateX + this.core.store.state.contextMenuX) / this.core.store.state.scale,
2488
+ y: (-this.core.store.state.translateY + this.core.store.state.contextMenuY) / this.core.store.state.scale,
2489
+ }, this.core.store.state.selectionGroup?.objects);
2404
2490
  this.hideContextMenu();
2405
- } })), this.store.state?.activeTool instanceof index$1.KritzelEraserTool && !this.store.state.isScaling && index.h("kritzel-cursor-trail", { key: '7c10277160eb1bc51581e4dfbdd4d0cdf626ed8c', store: this.store })));
2491
+ }, onClose: () => this.hideContextMenu() })), this.core.store.state?.activeTool instanceof index$1.KritzelEraserTool && !this.core.store.state.isScaling && index.h("kritzel-cursor-trail", { key: 'e0863ccf8c52ebef822827d8eeac62d3619134ca', core: this.core })));
2406
2492
  }
2407
2493
  static get watchers() { return {
2408
2494
  "workspace": ["onWorkspaceChange"],
@@ -2422,7 +2508,7 @@ const KritzelFont = class {
2422
2508
  size = 24;
2423
2509
  color = '#000000';
2424
2510
  render() {
2425
- return (index.h(index.Host, { key: 'd318355704f1bf66468dd793e5e38da827076d3b' }, index.h("div", { key: '447b4fba97f5d1900060859943438733667aed08', class: "font-preview", style: {
2511
+ return (index.h(index.Host, { key: '0d0f0f75b64f579ca236950334fafde7f0ef2a38' }, index.h("div", { key: 'e71524879ded9727891bdd43f1a41ae5eef49175', class: "font-preview", style: {
2426
2512
  fontFamily: this.fontFamily,
2427
2513
  fontSize: `${this.size}px`,
2428
2514
  color: this.color
@@ -2469,7 +2555,7 @@ const KritzelFontFamily = class {
2469
2555
  label: option.label,
2470
2556
  style: { fontFamily: option.value },
2471
2557
  }));
2472
- return (index.h(index.Host, { key: '801b1dbc2b7da7d00fb00ed6a8d8ee7be3e9ef17' }, index.h("kritzel-dropdown", { key: '5f774c0b31ca16a1c8acda1c73ea3aacc2784649', options: dropdownOptions, value: this.selectedFontFamily, onValueChanged: this.handleDropdownValueChange, selectStyles: { fontFamily: this.selectedFontFamily } }, index.h("button", { key: '3c101155ff08854f665750f8988fb3691a77c04a', class: "font-style-button", slot: "suffix" }, "B"), index.h("button", { key: '48d2ead137a8a35f06fb8b5487431e2ce613c755', class: "font-style-button italic-text", slot: "suffix" }, "I"))));
2558
+ return (index.h(index.Host, { key: 'd05a099adf8623b8c67d68f3861c1cd401e86e2c' }, index.h("kritzel-dropdown", { key: 'b95af194feaaf5748bb0d584617d217e4b3b8180', options: dropdownOptions, value: this.selectedFontFamily, onValueChanged: this.handleDropdownValueChange, selectStyles: { fontFamily: this.selectedFontFamily } }, index.h("button", { key: '04a0a72f9297dc6c34a2a2019cae111d8725bcf4', class: "font-style-button", slot: "suffix" }, "B"), index.h("button", { key: 'f14b59f29bcce33f890b74c1fb8d1dad0ad6fd31', class: "font-style-button italic-text", slot: "suffix" }, "I"))));
2473
2559
  }
2474
2560
  };
2475
2561
  KritzelFontFamily.style = kritzelFontFamilyCss;
@@ -2490,7 +2576,7 @@ const KritzelFontSize = class {
2490
2576
  this.sizeChange.emit(size);
2491
2577
  }
2492
2578
  render() {
2493
- return (index.h(index.Host, { key: '08571feed86b37208956608b170ca1f782b7fb18' }, this.sizes.map(size => (index.h("div", { class: {
2579
+ return (index.h(index.Host, { key: '583659340d8f3bfb2ff6f64f2cd692ac07cb32d6' }, this.sizes.map(size => (index.h("div", { class: {
2494
2580
  'size-container': true,
2495
2581
  'selected': this.selectedSize === size,
2496
2582
  }, onClick: () => this.handleSizeClick(size) }, index.h("kritzel-font", { fontFamily: this.fontFamily, size: size }))))));
@@ -2498,7 +2584,7 @@ const KritzelFontSize = class {
2498
2584
  };
2499
2585
  KritzelFontSize.style = kritzelFontSizeCss;
2500
2586
 
2501
- const kritzelIconCss = ":host{display:inline-flex;justify-content:center;align-items:center;}span{display:flex;align-items:center;width:100%;height:100%;}span>svg{width:100%;height:100%}";
2587
+ const kritzelIconCss = ":host{display:inline-flex;justify-content:center;align-items:center;color:var(--kritzel-icon-color, inherited)}span{display:flex;align-items:center;width:100%;height:100%;}span>svg{width:100%;height:100%}";
2502
2588
 
2503
2589
  const KritzelIcon = class {
2504
2590
  constructor(hostRef) {
@@ -2522,7 +2608,7 @@ const KritzelIcon = class {
2522
2608
  };
2523
2609
  KritzelIcon.style = kritzelIconCss;
2524
2610
 
2525
- const kritzelMenuCss = ":host{position:relative;display:flex;flex-direction:column;background-color:var(--kritzel-menu-background-color, #ffffff);width:var(--kritzel-menu-width, 180px);padding:var(--kritzel-menu-padding, 8px);border-radius:var(--kritzel-menu-border-radius, 12px);box-shadow:var(--kritzel-menu-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-menu-border, 1px solid #ebebeb);z-index:2;gap:var(--kritzel-menu-gap, 4px);overflow-y:auto;scrollbar-color:#ebebeb transparent;scrollbar-width:thin;max-height:300px}.has-open-child-overlay{position:absolute;top:0;left:0;right:0;bottom:0;z-index:3}";
2611
+ const kritzelMenuCss = ":host{position:relative;display:flex;flex-direction:column;background-color:var(--kritzel-menu-background-color, #ffffff);width:var(--kritzel-menu-width, 200px);padding:var(--kritzel-menu-padding, 8px);border-radius:var(--kritzel-menu-border-radius, 12px);box-shadow:var(--kritzel-menu-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-menu-border, 1px solid #ebebeb);z-index:2;gap:var(--kritzel-menu-gap, 4px);overflow-y:auto;scrollbar-color:#ebebeb transparent;scrollbar-width:thin;max-height:300px}:host(:focus-visible){outline:var(--kritzel-menu-focus-outline, 2px solid #e3e3e3)}.has-open-child-overlay{position:absolute;top:0;left:0;right:0;bottom:0;z-index:3}";
2526
2612
 
2527
2613
  const KritzelMenu = class {
2528
2614
  constructor(hostRef) {
@@ -2545,7 +2631,7 @@ const KritzelMenu = class {
2545
2631
  close;
2546
2632
  selectedIndex = null;
2547
2633
  async setFocus() {
2548
- const firstItem = this.host.querySelector('kritzel-menu-item');
2634
+ const firstItem = this.host.shadowRoot.querySelector('kritzel-menu-item');
2549
2635
  if (firstItem) {
2550
2636
  firstItem.focus();
2551
2637
  }
@@ -2581,12 +2667,12 @@ const KritzelMenu = class {
2581
2667
  this.itemCloseChildMenu.emit(event.detail);
2582
2668
  };
2583
2669
  render() {
2584
- return (index.h(index.Host, { key: 'c82bde4dc70fdc79df7471bb10396394f6c3870a', onClick: e => e.stopPropagation() }, this.openChildMenuItem && index.h("div", { key: '5fe0323aaa0da44abe736c6ef5e0516113c7820d', class: "has-open-child-overlay", onClick: this.onOverlayClick }), this.items.map((item) => (index.h("kritzel-menu-item", { key: item.id, item: item, parent: this.parent, style: { pointerEvents: this.editingMenuItem && !item.isEditing ? 'none' : 'auto' }, onItemSelect: this.handleItemSelect, onItemSave: this.handleSave, onItemCancel: this.handleCancel, onItemToggleChildMenu: this.handleToggleChildMenu, onItemCloseChildMenu: this.handleCloseChildMenu })))));
2670
+ return (index.h(index.Host, { key: 'd971df2bd948b07f7bf2abc589c226d57891d05e', tabIndex: 0, onClick: e => e.stopPropagation() }, this.openChildMenuItem && index.h("div", { key: 'dfa6846429aac15a5912b87acd45610663200a3e', class: "has-open-child-overlay", onClick: this.onOverlayClick }), this.items.map((item) => (index.h("kritzel-menu-item", { key: item.id, item: item, parent: this.parent, style: { pointerEvents: this.editingMenuItem && !item.isEditing ? 'none' : 'auto' }, onItemSelect: this.handleItemSelect, onItemSave: this.handleSave, onItemCancel: this.handleCancel, onItemToggleChildMenu: this.handleToggleChildMenu, onItemCloseChildMenu: this.handleCloseChildMenu })))));
2585
2671
  }
2586
2672
  };
2587
2673
  KritzelMenu.style = kritzelMenuCss;
2588
2674
 
2589
- const kritzelMenuItemCss = ":host{position:relative;display:flex;align-items:center;justify-content:space-between;width:100%;padding:var(--kritzel-menu-item-padding, 8px);box-sizing:border-box;gap:16px;height:var(--kritzel-menu-item-height, 40px);min-height:var(--kritzel-menu-item-min-height, 40px);font-family:sans-serif;font-size:var(--kritzel-menu-item-font-size, 14px);border-radius:var(--kritzel-menu-item-border-radius, 12px);outline:none;cursor:default}:host(:hover) .menu-item-overlay,:host(:focus-within) .menu-item-overlay{background-color:var(--kritzel-menu-item-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}:host(.selected){background-color:var(--kritzel-menu-item-selected-bg, #007aff);color:var(--kritzel-menu-item-selected-color, #ffffff)}:host(.selected) .action-button{color:var(--kritzel-menu-item-selected-color, #ffffff)}:host(.selected.editing){background-color:var(--kritzel-menu-item-selected-bg, #007aff)}:host(.selected) .edit-input{color:var(--kritzel-menu-item-selected-color, #ffffff)}:host(.selected) .edit-input::selection{background-color:var(--kritzel-menu-item-input-selection-color, rgba(255, 255, 255, 0.16))}:host(.editing){background-color:var(--kritzel-menu-item-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}:host(.disabled){opacity:0.5;pointer-events:none}:host(.child-open){background-color:var(--kritzel-menu-item-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}:host(.child-open.selected){background-color:var(--kritzel-menu-item-selected-bg, #007aff)}.menu-item-overlay{position:absolute;inset:0;background-color:transparent;z-index:0;pointer-events:none;border-radius:var(--kritzel-menu-item-border-radius, 12px)}.menu-item-content{display:flex;align-items:center;gap:8px;position:relative;z-index:1;height:100%}.left{justify-content:flex-start;flex:1;min-width:0}.left>div{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.right{justify-content:flex-end}.edit-input{flex:1;height:var(--kritzel-menu-item-input-height, 24px);padding:0;background-color:transparent;border-radius:0;border:none;border-bottom:1px solid var(--kritzel-menu-item-input-border, #ccc);font-size:var(--kritzel-context-menu-item-font-size, 14px);width:100%;min-width:0;box-sizing:border-box;outline:none}.edit-input::selection{background-color:var(--kritzel-menu-item-input-selection-color, #007bff);color:var(--kritzel-menu-item-input-selection-text-color, #ffffff)}.action-button{padding:4px;border-radius:8px;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;background-color:transparent;background:transparent;outline:none;-webkit-tap-highlight-color:transparent}.action-button:hover,.action-button:focus{background-color:var(--kritzel-menu-item-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.action-button.disabled{pointer-events:none;opacity:0.5}";
2675
+ const kritzelMenuItemCss = ":host{position:relative;display:flex;align-items:center;justify-content:space-between;width:100%;padding:var(--kritzel-menu-item-padding, 8px);box-sizing:border-box;gap:16px;height:var(--kritzel-menu-item-height, 40px);min-height:var(--kritzel-menu-item-min-height, 40px);font-family:sans-serif;font-size:var(--kritzel-menu-item-font-size, 14px);color:var(--kritzel-menu-item-color, #333333);border-radius:var(--kritzel-menu-item-border-radius, 12px);outline:none;cursor:default}:host(:hover) .menu-item-overlay,:host(:focus-within) .menu-item-overlay{background-color:var(--kritzel-menu-item-overlay-background-color, hsl(0, 0%, 0%, 4.3%))}:host(.selected){background-color:var(--kritzel-menu-item-selected-bg, #007aff);color:var(--kritzel-menu-item-selected-color, #ffffff)}:host(.selected) .action-button{color:var(--kritzel-menu-item-selected-color, #ffffff)}:host(.selected.editing){background-color:var(--kritzel-menu-item-selected-bg, #007aff)}:host(.selected) .edit-input{color:var(--kritzel-menu-item-selected-color, #ffffff)}:host(.selected) .action-button kritzel-icon{--kritzel-icon-color:var(--kritzel-menu-item-selected-color, #ffffff)}kritzel-icon{--kritzel-icon-color:var(--kritzel-menu-item-color, #333333)}:host(.selected) .edit-input::selection{background-color:var(--kritzel-menu-item-input-selection-color, rgba(255, 255, 255, 0.16))}:host(.editing){background-color:var(--kritzel-menu-item-editing-background-color, hsl(0, 0%, 0%, 4.3%))}:host(.disabled){opacity:0.5;pointer-events:none !important}:host(.child-open){background-color:var(--kritzel-menu-item-child-open-background-color, hsl(0, 0%, 0%, 4.3%))}:host(.child-open.selected){background-color:var(--kritzel-menu-item-selected-bg, #007aff)}.menu-item-overlay{position:absolute;inset:0;background-color:transparent;z-index:0;pointer-events:none;border-radius:var(--kritzel-menu-item-border-radius, 12px)}.menu-item-content{display:flex;align-items:center;gap:8px;position:relative;z-index:1;height:100%}.left{justify-content:flex-start;flex:1;min-width:0}.left>div{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.right{justify-content:flex-end}.edit-input{flex:1;height:var(--kritzel-menu-item-input-height, 24px);padding:0;background-color:transparent;border-radius:0;border:none;border-bottom:1px solid var(--kritzel-menu-item-input-border, #ccc);font-size:var(--kritzel-context-menu-item-font-size, 14px);width:100%;min-width:0;box-sizing:border-box;outline:none}.edit-input::selection{background-color:var(--kritzel-menu-item-input-selection-color, #007bff);color:var(--kritzel-menu-item-input-selection-text-color, #ffffff)}.action-button{padding:4px;border-radius:8px;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;background-color:transparent;background:transparent;outline:none;-webkit-tap-highlight-color:transparent}.action-button:hover,.action-button:focus{background-color:var(--kritzel-menu-item-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.action-button.disabled{pointer-events:none;opacity:0.5}";
2590
2676
 
2591
2677
  const KritzelMenuItem = class {
2592
2678
  constructor(hostRef) {
@@ -2612,18 +2698,32 @@ const KritzelMenuItem = class {
2612
2698
  itemCloseChildMenu;
2613
2699
  isDirty = false;
2614
2700
  inputRef;
2615
- componentDidLoad() {
2701
+ focusInput() {
2616
2702
  if (this.item.isEditing && this.inputRef && !this.isDirty) {
2617
2703
  this.inputRef.focus();
2618
- this.inputRef.select();
2704
+ if (KritzelDevicesHelper.isIOS()) {
2705
+ const length = this.inputRef.value.length;
2706
+ this.inputRef.setSelectionRange(length, length);
2707
+ }
2708
+ else {
2709
+ this.inputRef.select();
2710
+ }
2619
2711
  }
2620
2712
  }
2713
+ componentDidLoad() {
2714
+ this.setDeviceSpecificStyles();
2715
+ this.focusInput();
2716
+ }
2621
2717
  componentDidUpdate() {
2622
- if (this.item.isEditing && this.inputRef && !this.isDirty) {
2623
- this.inputRef.focus();
2624
- this.inputRef.select();
2625
- }
2718
+ this.focusInput();
2626
2719
  }
2720
+ setDeviceSpecificStyles = () => {
2721
+ const isTouchDevice = KritzelDevicesHelper.isTouchDevice();
2722
+ if (isTouchDevice) {
2723
+ this.host.style.setProperty('--kritzel-menu-item-overlay-background-color', 'transparent');
2724
+ this.host.style.setProperty('--kritzel-menu-item-button-hover-background-color', 'transparent');
2725
+ }
2726
+ };
2627
2727
  handleItemSelect = (event) => {
2628
2728
  event.stopPropagation();
2629
2729
  this.itemSelect.emit({ item: this.item, parent: this.parent });
@@ -2664,16 +2764,16 @@ const KritzelMenuItem = class {
2664
2764
  renderEditMode() {
2665
2765
  return [
2666
2766
  index.h("div", { class: "menu-item-content left" }, index.h("input", { ref: el => (this.inputRef = el), type: "text", class: "edit-input", value: this.item.label, onInput: this.handleInputChange })),
2667
- index.h("div", { class: "menu-item-content right" }, index.h("div", { tabIndex: !this.isDirty && !this.item.isNewItem ? -1 : 0, class: { 'action-button': true, 'disabled': !this.isDirty && !this.item.isNewItem }, onClick: this.handleSave }, index.h("kritzel-icon", { name: "check", size: 16 })), index.h("div", { tabIndex: 0, class: "action-button", onClick: this.handleCancel }, index.h("kritzel-icon", { name: "x", size: 16 }))),
2767
+ index.h("div", { class: "menu-item-content right" }, index.h("div", { tabIndex: 0, class: "action-button", onClick: this.handleCancel }, index.h("kritzel-icon", { name: "x", size: 16 })), index.h("div", { tabIndex: !this.isDirty && !this.item.isNewItem ? -1 : 0, class: { 'action-button': true, 'disabled': !this.isDirty && !this.item.isNewItem }, onClick: this.handleSave }, index.h("kritzel-icon", { name: "check", size: 16 }))),
2668
2768
  ];
2669
2769
  }
2670
2770
  render() {
2671
- return (index.h(index.Host, { key: '5440ed43726d00ab65e7f423f065c1a3fa74e39e', tabIndex: 0, class: {
2771
+ return (index.h(index.Host, { key: 'a35e1e3427568f436a36b43ba87af3710a4e83c5', tabIndex: this.item.isDisabled ? -1 : 0, class: {
2672
2772
  'selected': this.item.isSelected,
2673
2773
  'editing': this.item.isEditing,
2674
2774
  'disabled': this.item.isDisabled,
2675
2775
  'child-open': this.item.isChildMenuOpen,
2676
- }, onClick: this.handleItemSelect }, index.h("div", { key: '69542710179216a1df47bde5d474a72e4a07aa5b', class: "menu-item-overlay" }), this.item.isEditing ? this.renderEditMode() : this.renderViewMode()));
2776
+ }, onClick: this.handleItemSelect }, index.h("div", { key: '42eef5a16b9b164839c1fe133e38ecb505c07632', class: "menu-item-overlay" }), this.item.isEditing ? this.renderEditMode() : this.renderViewMode()));
2677
2777
  }
2678
2778
  static get watchers() { return {
2679
2779
  "item": ["onItemChange"]
@@ -2681,6 +2781,70 @@ const KritzelMenuItem = class {
2681
2781
  };
2682
2782
  KritzelMenuItem.style = kritzelMenuItemCss;
2683
2783
 
2784
+ class KritzelHTMLHelper {
2785
+ static getNumericValueFromStyle(element, property) {
2786
+ const value = window.getComputedStyle(element).getPropertyValue(property);
2787
+ return parseFloat(value) || 0;
2788
+ }
2789
+ static getScrollableParent(element) {
2790
+ if (!element) {
2791
+ return window;
2792
+ }
2793
+ const parent = element.parentNode?.host ?? element.parentElement;
2794
+ if (!parent || parent.tagName === 'BODY') {
2795
+ return window;
2796
+ }
2797
+ const style = window.getComputedStyle(parent);
2798
+ if (style.overflow === 'auto' || style.overflowY === 'auto' || style.overflow === 'scroll' || style.overflowY === 'scroll') {
2799
+ return parent;
2800
+ }
2801
+ return this.getScrollableParent(parent);
2802
+ }
2803
+ static isElementInViewport(element) {
2804
+ if (!element) {
2805
+ return false;
2806
+ }
2807
+ const scrollableParent = this.getScrollableParent(element);
2808
+ const rect = element.getBoundingClientRect();
2809
+ if (scrollableParent === window) {
2810
+ const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
2811
+ const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
2812
+ return rect.top >= 0 && rect.left >= 0 && rect.bottom <= viewportHeight && rect.right <= viewportWidth;
2813
+ }
2814
+ const parentRect = scrollableParent.getBoundingClientRect();
2815
+ return rect.top >= parentRect.top && rect.left >= parentRect.left && rect.bottom <= parentRect.bottom && rect.right <= parentRect.right;
2816
+ }
2817
+ static getFocusableElements(root) {
2818
+ if (!root)
2819
+ return [];
2820
+ const focusableElements = [];
2821
+ const focusableSelector = 'a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details, [tabindex]:not([tabindex="-1"])';
2822
+ const isVisible = (el) => {
2823
+ return el.offsetParent !== null;
2824
+ };
2825
+ const find = (element) => {
2826
+ // Check if the element itself is focusable
2827
+ if (element instanceof HTMLElement && element.matches(focusableSelector) && !element.hasAttribute('disabled') && isVisible(element)) {
2828
+ focusableElements.push(element);
2829
+ }
2830
+ // Traverse shadow DOM
2831
+ if (element.shadowRoot) {
2832
+ Array.from(element.shadowRoot.children).forEach(find);
2833
+ }
2834
+ // Traverse slotted content
2835
+ if (element.tagName === 'SLOT') {
2836
+ element.assignedElements({ flatten: true }).forEach(find);
2837
+ }
2838
+ // Traverse light DOM children if there is no shadow root
2839
+ if (!element.shadowRoot) {
2840
+ Array.from(element.children).forEach(find);
2841
+ }
2842
+ };
2843
+ find(root);
2844
+ return focusableElements;
2845
+ }
2846
+ }
2847
+
2684
2848
  const KritzelPortal = class {
2685
2849
  constructor(hostRef) {
2686
2850
  index.registerInstance(this, hostRef);
@@ -2756,7 +2920,7 @@ const KritzelPortal = class {
2756
2920
  return activeEl;
2757
2921
  }
2758
2922
  trapFocus(event) {
2759
- const focusableElements = this.getFocusableElements(this.host);
2923
+ const focusableElements = KritzelHTMLHelper.getFocusableElements(this.host);
2760
2924
  if (focusableElements.length === 0)
2761
2925
  return;
2762
2926
  const firstFocusable = focusableElements[0];
@@ -2777,51 +2941,12 @@ const KritzelPortal = class {
2777
2941
  }
2778
2942
  }
2779
2943
  }
2780
- getFocusableElements(root) {
2781
- if (!root)
2782
- return [];
2783
- const focusableElements = [];
2784
- const focusableSelector = 'a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details, [tabindex]:not([tabindex="-1"])';
2785
- const isVisible = (el) => {
2786
- return el.offsetParent !== null;
2787
- };
2788
- // Check if the root element itself is focusable
2789
- if (root.matches(focusableSelector) && !root.hasAttribute('disabled') && isVisible(root)) {
2790
- focusableElements.push(root);
2791
- }
2792
- // Function to recursively find focusable elements
2793
- const findFocusable = (element) => {
2794
- // Search in shadow root
2795
- if (element.shadowRoot) {
2796
- Array.from(element.shadowRoot.querySelectorAll(focusableSelector)).forEach(el => {
2797
- if (isVisible(el)) {
2798
- focusableElements.push(el);
2799
- }
2800
- });
2801
- Array.from(element.shadowRoot.children).forEach(findFocusable);
2802
- }
2803
- // Search in light DOM
2804
- Array.from(element.querySelectorAll(focusableSelector)).forEach(el => {
2805
- if (!focusableElements.includes(el) && isVisible(el)) {
2806
- focusableElements.push(el);
2807
- }
2808
- });
2809
- // Handle slotted content
2810
- if (element.tagName === 'SLOT') {
2811
- element.assignedElements({ flatten: true }).forEach(el => findFocusable(el));
2812
- }
2813
- Array.from(element.children).forEach(findFocusable);
2814
- };
2815
- findFocusable(root);
2816
- // Return unique elements in document order
2817
- return [...new Set(focusableElements)];
2818
- }
2819
2944
  get firstFocusableElement() {
2820
2945
  const slotEl = this.host.shadowRoot?.querySelector('slot');
2821
2946
  const firstAssigned = slotEl?.assignedElements({ flatten: true })[0];
2822
2947
  if (!firstAssigned)
2823
2948
  return null;
2824
- const focusable = this.getFocusableElements(firstAssigned);
2949
+ const focusable = KritzelHTMLHelper.getFocusableElements(firstAssigned);
2825
2950
  return focusable[0] ?? firstAssigned;
2826
2951
  }
2827
2952
  get lastAddedPortal() {
@@ -2880,25 +3005,26 @@ const KritzelPortal = class {
2880
3005
  this.portal.style.left = `${left}px`;
2881
3006
  }
2882
3007
  render() {
2883
- return (index.h(index.Host, { key: '968f0360b9396da16f5b970293ba20f8a1dcc09a', style: { display: this.anchor ? 'block' : 'none' } }, index.h("slot", { key: '0fe1569bde60a834e9226d7c838d113a64151164' })));
3008
+ return (index.h(index.Host, { key: 'a994d8ab8c758bc92836693f35f8d9415913cfff', style: { display: this.anchor ? 'block' : 'none' } }, index.h("slot", { key: 'a9b9a71d82e9b57de24e5ecfa90197a27ed691c4' })));
2884
3009
  }
2885
3010
  static get watchers() { return {
2886
3011
  "anchor": ["anchorChanged"]
2887
3012
  }; }
2888
3013
  };
2889
3014
 
2890
- const kritzelSplitButtonCss = ":host{position:relative;display:flex;align-items:center;font-family:sans-serif;z-index:1;padding:var(--kritzel-split-button-padding, 4px);background-color:var(--kritzel-split-button-background-color, #ffffff);border-radius:var(--kritzel-split-button-border-radius, 12px);box-shadow:var(--kritzel-split-button-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-split-button-border, 1px solid #ebebeb);gap:var(--kritzel-split-button-gap, 4px)}:host(:focus){outline:none}:host(.mobile){--kritzel-split-button-hover-background-color:transparent}button{border:none;background-color:transparent;padding:0;margin:0;font-family:inherit;font-size:inherit;color:inherit;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;text-align:center;display:flex;align-items:center;justify-content:center;pointer-events:all;-webkit-tap-highlight-color:transparent}.split-main-button,.split-menu-button{height:auto;display:flex;align-items:center;padding:var(--kritzel-split-button-padding, 8px);background-color:var(--kritzel-split-button-background-color, #ffffff);border-radius:var(--kritzel-split-button-border-radius, 12px);font-size:var(--kritzel-split-button-font-size, 14px)}.split-main-button:hover,.split-menu-button:hover{background-color:var(--kritzel-split-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.split-main-button:focus,.split-menu-button:focus{outline:none;background-color:var(--kritzel-split-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.split-main-button{gap:var(--kritzel-split-button-gap, 4px)}.split-menu-button{border-left:none;justify-content:center}.split-divider{width:var(--kritzel-split-button-divider-width, 1px);height:24px;background-color:var(--kritzel-split-button-divider-background-color, hsl(0, 0%, 0%, 4.3%))}:disabled{pointer-events:none;opacity:0.5}";
3015
+ const kritzelSplitButtonCss = ":host{position:relative;display:flex;align-items:center;font-family:sans-serif;z-index:1;padding:var(--kritzel-split-button-padding, 4px);background-color:var(--kritzel-split-button-background-color, #ffffff);border-radius:var(--kritzel-split-button-border-radius, 12px);box-shadow:var(--kritzel-split-button-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-split-button-border, 1px solid #ebebeb);gap:var(--kritzel-split-button-gap, 4px)}:host(.mobile){--kritzel-split-button-hover-background-color:transparent}button{border:none;background-color:transparent;padding:0;margin:0;font-family:inherit;font-size:inherit;color:inherit;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;text-align:center;display:flex;align-items:center;justify-content:center;pointer-events:all;-webkit-tap-highlight-color:transparent}.split-main-button,.split-menu-button{height:auto;display:flex;align-items:center;padding:var(--kritzel-split-button-padding, 8px);background-color:var(--kritzel-split-button-background-color, #ffffff);border-radius:var(--kritzel-split-button-border-radius, 12px);font-size:var(--kritzel-split-button-font-size, 14px)}.split-main-button:hover,.split-menu-button:hover{background-color:var(--kritzel-split-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.split-main-button:focus,.split-menu-button:focus{outline:none;background-color:var(--kritzel-split-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.split-main-button{gap:var(--kritzel-split-button-gap, 4px)}.split-menu-button{border-left:none;justify-content:center}.split-divider{width:var(--kritzel-split-button-divider-width, 1px);height:24px;background-color:var(--kritzel-split-button-divider-background-color, hsl(0, 0%, 0%, 4.3%))}:disabled{pointer-events:none;opacity:0.5}";
2891
3016
 
2892
3017
  const KritzelSplitButton = class {
2893
3018
  constructor(hostRef) {
2894
3019
  index.registerInstance(this, hostRef);
2895
- this.buttonClick = index.createEvent(this, "buttonClick");
3020
+ this.mainButtonClick = index.createEvent(this, "mainButtonClick");
2896
3021
  this.itemSelect = index.createEvent(this, "itemSelect");
2897
3022
  this.itemSave = index.createEvent(this, "itemSave");
2898
3023
  this.itemCancel = index.createEvent(this, "itemCancel");
2899
3024
  this.itemToggleChildMenu = index.createEvent(this, "itemToggleChildMenu");
2900
3025
  this.itemCloseChildMenu = index.createEvent(this, "itemCloseChildMenu");
2901
- this.close = index.createEvent(this, "close");
3026
+ this.menuOpen = index.createEvent(this, "menuOpen");
3027
+ this.menuClose = index.createEvent(this, "menuClose");
2902
3028
  }
2903
3029
  get host() { return index.getElement(this); }
2904
3030
  buttonIcon = 'plus';
@@ -2906,13 +3032,14 @@ const KritzelSplitButton = class {
2906
3032
  items = [];
2907
3033
  mainButtonDisabled = false;
2908
3034
  menuButtonDisabled = false;
2909
- buttonClick;
3035
+ mainButtonClick;
2910
3036
  itemSelect;
2911
3037
  itemSave;
2912
3038
  itemCancel;
2913
3039
  itemToggleChildMenu;
2914
3040
  itemCloseChildMenu;
2915
- close;
3041
+ menuOpen;
3042
+ menuClose;
2916
3043
  isMenuOpen = false;
2917
3044
  isTouchDevice = KritzelDevicesHelper.isTouchDevice();
2918
3045
  anchorElement;
@@ -2921,11 +3048,18 @@ const KritzelSplitButton = class {
2921
3048
  async open() {
2922
3049
  if (this.isMenuOpen)
2923
3050
  return;
2924
- this.openMenu(new MouseEvent('click'));
3051
+ this.isMenuOpen = true;
3052
+ this.anchorElement = this.host;
3053
+ this.menuOpen.emit();
3054
+ }
3055
+ async focusMenu() {
3056
+ if (this.menuRef) {
3057
+ await this.menuRef.setFocus();
3058
+ }
2925
3059
  }
2926
3060
  handleButtonClick = (event) => {
2927
3061
  event.stopPropagation();
2928
- this.buttonClick.emit();
3062
+ this.mainButtonClick.emit();
2929
3063
  };
2930
3064
  toggleMenu = (event) => {
2931
3065
  event.stopPropagation();
@@ -2940,11 +3074,13 @@ const KritzelSplitButton = class {
2940
3074
  event.stopPropagation();
2941
3075
  this.isMenuOpen = true;
2942
3076
  this.anchorElement = this.host;
3077
+ this.menuOpen.emit();
2943
3078
  };
2944
3079
  closeMenu = () => {
2945
3080
  this.isMenuOpen = false;
2946
3081
  this.anchorElement = null;
2947
- this.close.emit();
3082
+ this.splitMenuButtonRef?.blur();
3083
+ this.menuClose.emit();
2948
3084
  };
2949
3085
  handleItemSelect = event => {
2950
3086
  this.itemSelect.emit(event.detail);
@@ -2962,12 +3098,12 @@ const KritzelSplitButton = class {
2962
3098
  this.itemCloseChildMenu.emit(event.detail);
2963
3099
  };
2964
3100
  render() {
2965
- return (index.h(index.Host, { key: 'be79d702d2c400d1feedeb89eca6fc78559f30f3', class: { mobile: this.isTouchDevice } }, index.h("button", { key: 'e4a74c56c122ea617f44f1d7e31672d1f913de46', class: "split-main-button", tabIndex: 0, onClick: this.handleButtonClick, disabled: this.mainButtonDisabled }, this.buttonIcon && index.h("kritzel-icon", { key: '44bd79270e7cc4a17b45133b5c513642013e5a66', name: this.buttonIcon })), index.h("div", { key: '2392e8c6f75510c529585a69c861b2fcafdef5ce', class: "split-divider" }), index.h("button", { key: 'bcdf61c2a195271771479de385db3b4982f6cad2', ref: el => (this.splitMenuButtonRef = el), class: "split-menu-button", tabIndex: 0, onClick: this.toggleMenu, disabled: this.menuButtonDisabled }, index.h("kritzel-icon", { key: '90383a8690111c97054fb8ac93b91cb6644de137', name: this.dropdownIcon })), index.h("kritzel-portal", { key: 'c6a4c32ab731fede13e1382bff9dbd68794b1103', anchor: this.anchorElement, offsetY: 4, onClose: this.closeMenu }, index.h("kritzel-menu", { key: '8b792c9a2d4af60ba464bb80551c5358e21bfa96', ref: el => (this.menuRef = el), items: this.items, onItemSelect: this.handleItemSelect, onItemSave: this.handleItemSave, onItemCancel: this.handleItemCancel, onItemToggleChildMenu: this.handleItemToggleChildMenu, onItemCloseChildMenu: this.handleItemCloseChildMenu, onClose: this.closeMenu }))));
3101
+ return (index.h(index.Host, { key: '2521559224e78ed1984446320a1601e77ccf2843', class: { mobile: this.isTouchDevice } }, index.h("button", { key: 'a924ad4590506cb5209ef9fa1babca5312ec0513', class: "split-main-button", tabIndex: 0, onClick: this.handleButtonClick, disabled: this.mainButtonDisabled }, this.buttonIcon && index.h("kritzel-icon", { key: '214565d158d4d3c06ad883559aa7bac2827a593f', name: this.buttonIcon })), index.h("div", { key: '2f7d189c46c08227c3006d226a0ee3065f241bf4', class: "split-divider" }), index.h("button", { key: '4d6e2e224e3719fe3685ee289af94680c120abf6', ref: el => (this.splitMenuButtonRef = el), class: "split-menu-button", tabIndex: 0, onClick: this.toggleMenu, disabled: this.menuButtonDisabled }, index.h("kritzel-icon", { key: 'bc8176681dfedde9d13b9af561d8bdff8613098f', name: this.dropdownIcon })), index.h("kritzel-portal", { key: 'afb44cd208f52350cbc82e050d6dee0ba734391d', anchor: this.anchorElement, offsetY: 4, onClose: this.closeMenu }, index.h("kritzel-menu", { key: 'b28f04138daa8777e6c9b2aa7fa3b5f2f62fd914', ref: el => (this.menuRef = el), items: this.items, onItemSelect: this.handleItemSelect, onItemSave: this.handleItemSave, onItemCancel: this.handleItemCancel, onItemToggleChildMenu: this.handleItemToggleChildMenu, onItemCloseChildMenu: this.handleItemCloseChildMenu, onClose: this.closeMenu }))));
2966
3102
  }
2967
3103
  };
2968
3104
  KritzelSplitButton.style = kritzelSplitButtonCss;
2969
3105
 
2970
- const kritzelStrokeSizeCss = ":host{display:flex;align-items:flex-start;gap:8px;padding:8px;box-sizing:border-box}.size-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:pointer;border:2px solid transparent;box-sizing:border-box}.size-container:hover{background-color:var(--kritzel-stroke-size-hover-background-color, #ebebeb)}.size-container.selected{border-color:var(--kritzel-selection-border-color, #007AFF);background-color:var(--kritzel-stroke-size-selected-background-color, #ebebeb)}";
3106
+ const kritzelStrokeSizeCss = ":host{display:flex;align-items:flex-start;gap:8px;padding:8px;box-sizing:border-box}.size-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:pointer;border:2px solid transparent;box-sizing:border-box}.size-container:focus-visible{outline:var(--kritzel-stroke-size-focus-outline, 2px auto #e3e3e3)}.size-container:hover{background-color:var(--kritzel-stroke-size-hover-background-color, #ebebeb)}.size-container.selected{border-color:var(--kritzel-selection-border-color, #007AFF);background-color:var(--kritzel-stroke-size-selected-background-color, #ebebeb)}";
2971
3107
 
2972
3108
  const KritzelStrokeSize = class {
2973
3109
  constructor(hostRef) {
@@ -2982,7 +3118,7 @@ const KritzelStrokeSize = class {
2982
3118
  this.sizeChange.emit(size);
2983
3119
  }
2984
3120
  render() {
2985
- return (index.h(index.Host, { key: 'f9f0fe49963655a2beeffe5c369ccbe018c8aa5e' }, this.sizes.map(size => (index.h("div", { class: {
3121
+ return (index.h(index.Host, { key: '001a0ef8408d19532b57a521929c0cba54e99c52' }, this.sizes.map(size => (index.h("div", { tabIndex: 0, class: {
2986
3122
  'size-container': true,
2987
3123
  'selected': this.selectedSize === size,
2988
3124
  }, onClick: () => this.handleSizeClick(size) }, index.h("kritzel-color", { value: '#000000', size: size }))))));
@@ -2996,19 +3132,38 @@ const MOBILE_BREAKPOINT = 768;
2996
3132
  const KritzelTooltip = class {
2997
3133
  constructor(hostRef) {
2998
3134
  index.registerInstance(this, hostRef);
3135
+ this.tooltipClosed = index.createEvent(this, "tooltipClosed");
2999
3136
  }
3137
+ get host() { return index.getElement(this); }
3000
3138
  isVisible = false;
3001
3139
  anchorElement;
3002
3140
  arrowSize = 8;
3003
3141
  offsetY = 24;
3004
- get el() { return index.getElement(this); }
3142
+ tooltipClosed;
3005
3143
  positionX = 0;
3006
3144
  arrowOffset = '0px';
3007
3145
  isMobileView = window.innerWidth < MOBILE_BREAKPOINT;
3146
+ handleOutsideClick(event) {
3147
+ if (!this.isVisible)
3148
+ return;
3149
+ const target = event.target;
3150
+ if (!this.host.contains(target)) {
3151
+ this.tooltipClosed.emit();
3152
+ }
3153
+ }
3008
3154
  handleWindowResize() {
3009
3155
  this.isMobileView = window.innerWidth < MOBILE_BREAKPOINT;
3010
3156
  this.calculateAdjustedPosition();
3011
3157
  }
3158
+ async focusContent() {
3159
+ const focusableElements = KritzelHTMLHelper.getFocusableElements(this.host);
3160
+ if (focusableElements.length > 0) {
3161
+ focusableElements[0].focus();
3162
+ }
3163
+ }
3164
+ componentDidLoad() {
3165
+ this.focusSlottedContent();
3166
+ }
3012
3167
  componentWillLoad() {
3013
3168
  this.isMobileView = window.innerWidth < MOBILE_BREAKPOINT;
3014
3169
  this.calculateAdjustedPosition();
@@ -3016,10 +3171,18 @@ const KritzelTooltip = class {
3016
3171
  componentWillUpdate() {
3017
3172
  this.calculateAdjustedPosition();
3018
3173
  }
3174
+ focusSlottedContent() {
3175
+ const slot = this.host.shadowRoot?.querySelector('slot');
3176
+ const assignedElements = slot?.assignedElements() || [];
3177
+ if (assignedElements.length > 0) {
3178
+ const firstElement = assignedElements[0];
3179
+ firstElement.focus();
3180
+ }
3181
+ }
3019
3182
  calculateAdjustedPosition() {
3020
3183
  if (this.isVisible && this.anchorElement) {
3021
3184
  const anchorRect = this.anchorElement.getBoundingClientRect();
3022
- const tooltipContent = this.el.shadowRoot?.querySelector('.tooltip-content');
3185
+ const tooltipContent = this.host.shadowRoot?.querySelector('.tooltip-content');
3023
3186
  if (!this.isMobileView) {
3024
3187
  this.positionX = anchorRect.left + anchorRect.width / 2;
3025
3188
  this.arrowOffset = `calc(${50}% - ${this.arrowSize}px)`;
@@ -3032,23 +3195,23 @@ const KritzelTooltip = class {
3032
3195
  }
3033
3196
  }
3034
3197
  render() {
3035
- return (index.h(index.Host, { key: '6eb67bcfd08234affe3724dff4d94ddf7907a1a7', style: {
3198
+ return (index.h(index.Host, { key: '8c3aeff60625f43f129afa70367cdb7a68a4b271', style: {
3036
3199
  position: 'fixed',
3037
3200
  zIndex: '9999',
3038
3201
  transition: 'opacity 0.3s ease-in-out, transform 0.3s ease-in-out',
3039
3202
  visibility: this.isVisible ? 'visible' : 'hidden',
3040
3203
  left: !this.isMobileView ? `${this.positionX}px` : '50%',
3041
3204
  marginBottom: `${this.offsetY + this.arrowSize}px`,
3042
- } }, index.h("div", { key: '9314b30b71200776e3728027b2ac7332cf4ab669', class: "tooltip-content", onClick: event => event.stopPropagation() }, index.h("slot", { key: '80cb8d0a8a91d9c816580cedc02fc9382fb07f8c' }), index.h("div", { key: '87fb2399463a0eb7beb1ca0f2c2867d8ff033f3a', class: "tooltip-arrow-wrapper", style: {
3205
+ } }, index.h("div", { key: 'b22b606c2a836c2c9bbe21c6b470754753ccb309', class: "tooltip-content", onClick: event => event.stopPropagation() }, index.h("slot", { key: '783403f4b5560012c9f6bd184a8c5eb26428e148' }), index.h("div", { key: 'bb98400edc5c6e05fd4ed2a476a5821f93964b8e', class: "tooltip-arrow-wrapper", style: {
3043
3206
  position: 'fixed',
3044
3207
  left: this.arrowOffset,
3045
3208
  bottom: `-${this.arrowSize * 2}px`,
3046
- } }, index.h("div", { key: 'fc3953ad9b6aa5a4b2228653573fc3a7e37c0487', class: "tooltip-arrow", style: {
3209
+ } }, index.h("div", { key: '850a058d635113a7870f25fa288a6447394c53ed', class: "tooltip-arrow", style: {
3047
3210
  borderLeft: `${this.arrowSize}px solid transparent`,
3048
3211
  borderRight: `${this.arrowSize}px solid transparent`,
3049
3212
  borderTop: `${this.arrowSize}px solid var(--kritzel-controls-tooltip-background-color, #ffffff)`,
3050
3213
  filter: 'drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2))',
3051
- } }), index.h("div", { key: '5b8e4e3eb90c4c47c47fa47dc96e4149794e1732', class: "tooltip-arrow-rect", style: {
3214
+ } }), index.h("div", { key: 'bbb3dc2673e2dfe4443ad80540dfc9e5a25c6c06', class: "tooltip-arrow-rect", style: {
3052
3215
  position: 'relative',
3053
3216
  width: `${this.arrowSize * 2}px`,
3054
3217
  height: `${this.arrowSize}px`,
@@ -3059,7 +3222,7 @@ const KritzelTooltip = class {
3059
3222
  };
3060
3223
  KritzelTooltip.style = kritzelTooltipCss;
3061
3224
 
3062
- const kritzelUtilityPanelCss = ":host{display:flex;flex-direction:row;align-items:center;padding:4px;gap:8px;border-top-left-radius:12px;border-top-right-radius:12px;background-color:rgb(226, 226, 226);width:fit-content;user-select:none}.utility-button{display:flex;justify-content:center;align-items:center;width:28px;height:28px;padding:8px 4px;border:none;outline:none;background:none;cursor:pointer;color:#333333;-webkit-tap-highlight-color:transparent}.utility-separator{width:1px;height:16px;background-color:hsl(0, 0%, 0%, 4.3%)}";
3225
+ const kritzelUtilityPanelCss = ":host{display:flex;flex-direction:row;align-items:center;padding:4px;gap:8px;border-top-left-radius:12px;border-top-right-radius:12px;background-color:rgb(226, 226, 226);width:fit-content;user-select:none}.utility-button{display:flex;justify-content:center;align-items:center;width:28px;height:28px;padding:8px 4px;border:none;outline:none;background:none;cursor:pointer;color:#333333;-webkit-tap-highlight-color:transparent;border-radius:var(--kritzel-utility-panel-button-border-radius, 8px)}.utility-button:focus{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.utility-separator{width:1px;height:16px;background-color:hsl(0, 0%, 0%, 4.3%)}";
3063
3226
 
3064
3227
  const KritzelUtilityPanel = class {
3065
3228
  constructor(hostRef) {
@@ -3084,7 +3247,7 @@ const KritzelUtilityPanel = class {
3084
3247
  this.redo.emit();
3085
3248
  }
3086
3249
  render() {
3087
- return (index.h(index.Host, { key: '134058928a840d11fdc39849b35f08b21840fc0c' }, index.h("button", { key: '8d80cb496983b0709c06bacb12ca6819789aa47d', class: "utility-button", onClick: event => this.handleUndo(event) }, index.h("kritzel-icon", { key: 'c6733ef61ab6a272f80a580243fdd15063b8bf0c', name: "undo" })), index.h("button", { key: 'dc6147152bccd43ea54b9af20d019d305e550987', class: "utility-button", onClick: event => this.handleRedo(event) }, index.h("kritzel-icon", { key: '3ab8bced0f398a8d5f053cb0f388199fd2148bfc', name: "redo" })), index.h("div", { key: 'ebbfd25fb69faf2b669de20dc74a3dcabc01f489', class: "utility-separator" }), index.h("button", { key: 'd86caf8a7f2c2bc899b09871f555973137693eb9', class: "utility-button" }, index.h("kritzel-icon", { key: 'e1b4e9eef3d3ab2a2ddd1688818d4bcd2d7226c1', name: "delete", onClick: () => this.delete.emit() }))));
3250
+ return (index.h(index.Host, { key: '8109ccff01374c046d057021dfbcabdc632d829f' }, index.h("button", { key: '0d51cfb401974edf1a2a8810d2244f8a977c347f', class: "utility-button", onClick: event => this.handleUndo(event) }, index.h("kritzel-icon", { key: '1d13ee6bbf060402e0b1349d41b728875314e2e5', name: "undo" })), index.h("button", { key: 'f2fe59e7c99cb1550052088b507313cfaed72f29', class: "utility-button", onClick: event => this.handleRedo(event) }, index.h("kritzel-icon", { key: '74bf8c20f61144ab4abc5804dcd8f39917d2c966', name: "redo" })), index.h("div", { key: '0c9a942e786425b32e984fefdc97b1abb5077997', class: "utility-separator" }), index.h("button", { key: '44ca9340c2f73212332e9b3ed93ed93b8f7c6944', class: "utility-button" }, index.h("kritzel-icon", { key: '7b4c3d9a105e0c25b5bbc11ff1bc1cbed9833e03', name: "delete", onClick: () => this.delete.emit() }))));
3088
3251
  }
3089
3252
  };
3090
3253
  KritzelUtilityPanel.style = kritzelUtilityPanelCss;
@@ -3133,9 +3296,9 @@ const KritzelWorkspaceManager = class {
3133
3296
  this.workspaceChange.emit(item.value);
3134
3297
  }
3135
3298
  async add() {
3299
+ await this.splitButtonRef.open();
3136
3300
  this.newWorkspace = new index$1.KritzelWorkspace(index$1.ObjectHelper.generateUUID(), 'New Workspace');
3137
3301
  this.editingItemId = this.newWorkspace.id;
3138
- await this.splitButtonRef.open();
3139
3302
  }
3140
3303
  edit(item) {
3141
3304
  this.openChildMenuItem = null;
@@ -3146,11 +3309,14 @@ const KritzelWorkspaceManager = class {
3146
3309
  }
3147
3310
  async save(item) {
3148
3311
  if (this.newWorkspace) {
3149
- await this.kritzelEngineRef.createWorkspace({ ...item.value, name: item.label });
3312
+ this.newWorkspace.name = item.label;
3313
+ await this.kritzelEngineRef.createWorkspace(this.newWorkspace);
3150
3314
  this.workspaceChange.emit(this.newWorkspace);
3151
3315
  }
3152
3316
  else {
3153
- await this.kritzelEngineRef.updateWorkspace({ ...item.value, name: item.label });
3317
+ const workspace = item.value;
3318
+ workspace.name = item.label;
3319
+ await this.kritzelEngineRef.updateWorkspace(workspace);
3154
3320
  }
3155
3321
  this.editingItemId = null;
3156
3322
  this.newWorkspace = null;
@@ -3163,6 +3329,11 @@ const KritzelWorkspaceManager = class {
3163
3329
  this.openChildMenuItem = null;
3164
3330
  this.childMenuAnchor = null;
3165
3331
  await this.kritzelEngineRef.deleteWorkspace(item.value);
3332
+ if (item.value.id === this.activeWorkspace?.id) {
3333
+ this.activeWorkspace = this.sortedWorkspaces.find(ws => ws.id !== item.value.id) || null;
3334
+ this.workspaceChange.emit(this.activeWorkspace);
3335
+ }
3336
+ await this.splitButtonRef.focusMenu();
3166
3337
  }
3167
3338
  toggleChildMenu(item, anchor) {
3168
3339
  this.openChildMenuItem = item;
@@ -3172,12 +3343,15 @@ const KritzelWorkspaceManager = class {
3172
3343
  this.openChildMenuItem = null;
3173
3344
  this.childMenuAnchor = null;
3174
3345
  }
3175
- closeMenu() {
3346
+ handleMenuOpen() {
3347
+ this.kritzelEngineRef.disable();
3348
+ }
3349
+ handleMenuClose() {
3176
3350
  this.cancel();
3177
3351
  this.closeChildMenu();
3352
+ this.kritzelEngineRef.enable();
3178
3353
  }
3179
3354
  render() {
3180
- console.log('render workspace manager');
3181
3355
  const menuItems = this.sortedWorkspaces
3182
3356
  .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())
3183
3357
  .filter(ws => ws !== null)
@@ -3202,19 +3376,17 @@ const KritzelWorkspaceManager = class {
3202
3376
  id: `${ws.id}-delete`,
3203
3377
  label: 'Delete',
3204
3378
  value: 'delete',
3379
+ isDisabled: this.sortedWorkspaces.length <= 1,
3205
3380
  action: (_item, parent) => this.delete(parent),
3206
3381
  },
3207
3382
  ],
3208
3383
  };
3209
3384
  });
3210
- return (index.h(index.Host, null, index.h("kritzel-split-button", { ref: el => (this.splitButtonRef = el), items: menuItems, mainButtonDisabled: this.editingItemId != null, onButtonClick: () => this.add(), onItemSelect: event => this.select(event.detail.item, event.detail.parent), onItemToggleChildMenu: event => this.toggleChildMenu(event.detail.item, event.detail.childMenuAnchor), onItemSave: event => this.save(event.detail), onItemCancel: () => this.cancel(), onItemCloseChildMenu: () => this.closeChildMenu(), onClose: () => {
3211
- this.closeMenu();
3212
- } })));
3385
+ return (index.h(index.Host, null, index.h("kritzel-split-button", { ref: el => (this.splitButtonRef = el), items: menuItems, mainButtonDisabled: this.editingItemId != null, onMainButtonClick: () => this.add(), onItemSelect: event => this.select(event.detail.item, event.detail.parent), onItemToggleChildMenu: event => this.toggleChildMenu(event.detail.item, event.detail.childMenuAnchor), onItemSave: event => this.save(event.detail), onItemCancel: () => this.cancel(), onItemCloseChildMenu: () => this.closeChildMenu(), onMenuOpen: () => this.handleMenuOpen(), onMenuClose: () => this.handleMenuClose() })));
3213
3386
  }
3214
3387
  };
3215
3388
  KritzelWorkspaceManager.style = kritzelWorkspaceManagerCss;
3216
3389
 
3217
- exports.kritzel_brush_style = KritzelBrushStyle;
3218
3390
  exports.kritzel_color = KritzelColor;
3219
3391
  exports.kritzel_color_palette = KritzelColorPalette;
3220
3392
  exports.kritzel_context_menu = KritzelContextMenu;
@@ -3237,4 +3409,4 @@ exports.kritzel_stroke_size = KritzelStrokeSize;
3237
3409
  exports.kritzel_tooltip = KritzelTooltip;
3238
3410
  exports.kritzel_utility_panel = KritzelUtilityPanel;
3239
3411
  exports.kritzel_workspace_manager = KritzelWorkspaceManager;
3240
- //# sourceMappingURL=kritzel-brush-style.kritzel-color.kritzel-color-palette.kritzel-context-menu.kritzel-control-brush-config.kritzel-control-text-config.kritzel-controls.kritzel-cursor-trail.kritzel-dropdown.kritzel-editor.kritzel-engine.kritzel-font.kritzel-font-family.kritzel-font-size.kritzel-icon.kritzel-menu.kritzel-menu-item.kritzel-portal.kritzel-split-button.kritzel-stroke-size.kritzel-tooltip.kritzel-utility-panel.kritzel-workspace-manager.entry.cjs.js.map
3412
+ //# sourceMappingURL=kritzel-color.kritzel-color-palette.kritzel-context-menu.kritzel-control-brush-config.kritzel-control-text-config.kritzel-controls.kritzel-cursor-trail.kritzel-dropdown.kritzel-editor.kritzel-engine.kritzel-font.kritzel-font-family.kritzel-font-size.kritzel-icon.kritzel-menu.kritzel-menu-item.kritzel-portal.kritzel-split-button.kritzel-stroke-size.kritzel-tooltip.kritzel-utility-panel.kritzel-workspace-manager.entry.cjs.js.map