@kritzel/engine 0.4.31

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 (373) hide show
  1. package/LICENSE.md +50 -0
  2. package/dist/cjs/app-globals-V2Kpy_OQ.js +5 -0
  3. package/dist/cjs/engine.constants-CakmdKMW.js +28206 -0
  4. package/dist/cjs/index-BbbWU2aN.js +1742 -0
  5. package/dist/cjs/index.cjs.js +4232 -0
  6. package/dist/cjs/kritzel-awareness-cursors_5.cjs.entry.js +28004 -0
  7. package/dist/cjs/loader.cjs.js +13 -0
  8. package/dist/cjs/stencil.cjs.js +25 -0
  9. package/dist/collection/classes/core/core.class.js +1389 -0
  10. package/dist/collection/classes/core/reviver.class.js +124 -0
  11. package/dist/collection/classes/core/store.class.js +337 -0
  12. package/dist/collection/classes/core/viewport.class.js +794 -0
  13. package/dist/collection/classes/core/workspace.class.js +112 -0
  14. package/dist/collection/classes/handlers/base.handler.js +20 -0
  15. package/dist/collection/classes/handlers/context-menu.handler.js +170 -0
  16. package/dist/collection/classes/handlers/hover.handler.js +35 -0
  17. package/dist/collection/classes/handlers/key.handler.js +162 -0
  18. package/dist/collection/classes/handlers/line-handle.handler.js +475 -0
  19. package/dist/collection/classes/handlers/move.handler.js +295 -0
  20. package/dist/collection/classes/handlers/resize.handler.js +327 -0
  21. package/dist/collection/classes/handlers/rotation.handler.js +174 -0
  22. package/dist/collection/classes/handlers/selection.handler.js +526 -0
  23. package/dist/collection/classes/managers/anchor.manager.js +1476 -0
  24. package/dist/collection/classes/managers/browser-permission.manager.js +64 -0
  25. package/dist/collection/classes/managers/clipboard.manager.js +346 -0
  26. package/dist/collection/classes/managers/clipboard.types.js +1 -0
  27. package/dist/collection/classes/managers/cursor.manager.js +139 -0
  28. package/dist/collection/classes/managers/license.manager.js +341 -0
  29. package/dist/collection/classes/managers/localization.manager.js +227 -0
  30. package/dist/collection/classes/managers/theme.manager.js +206 -0
  31. package/dist/collection/classes/objects/base-object.class.js +462 -0
  32. package/dist/collection/classes/objects/dynamic-object.class.js +437 -0
  33. package/dist/collection/classes/objects/group.class.js +590 -0
  34. package/dist/collection/classes/objects/image.class.js +500 -0
  35. package/dist/collection/classes/objects/line.class.js +789 -0
  36. package/dist/collection/classes/objects/path.class.js +578 -0
  37. package/dist/collection/classes/objects/selection-box.class.js +32 -0
  38. package/dist/collection/classes/objects/selection-group.class.js +752 -0
  39. package/dist/collection/classes/objects/shape.class.js +628 -0
  40. package/dist/collection/classes/objects/text.class.js +461 -0
  41. package/dist/collection/classes/providers/assets/asset-resolver.class.js +536 -0
  42. package/dist/collection/classes/providers/assets/http-asset-provider.class.js +111 -0
  43. package/dist/collection/classes/providers/assets/indexeddb-asset-provider.class.js +241 -0
  44. package/dist/collection/classes/providers/assets/presigned-asset-provider.class.js +86 -0
  45. package/dist/collection/classes/providers/paste-intent/event-paste-intent.provider.js +48 -0
  46. package/dist/collection/classes/providers/paste-intent/ios-paste-intent.provider.js +16 -0
  47. package/dist/collection/classes/providers/paste-intent/navigator-paste-intent.provider.js +86 -0
  48. package/dist/collection/classes/providers/sync/broadcast-sync-provider.class.js +100 -0
  49. package/dist/collection/classes/providers/sync/hocuspocus-sync-provider.class.js +333 -0
  50. package/dist/collection/classes/providers/sync/in-memory-sync-provider.class.js +69 -0
  51. package/dist/collection/classes/providers/sync/indexeddb-sync-provider.class.js +39 -0
  52. package/dist/collection/classes/providers/sync/websocket-sync-provider.class.js +110 -0
  53. package/dist/collection/classes/registries/dynamic-object-renderer.registry.js +52 -0
  54. package/dist/collection/classes/registries/font-registry.class.js +161 -0
  55. package/dist/collection/classes/registries/icon-registry.class.js +118 -0
  56. package/dist/collection/classes/registries/paste-intent-provider.registry.js +26 -0
  57. package/dist/collection/classes/registries/tool.registry.js +69 -0
  58. package/dist/collection/classes/structures/app-state-map.structure.js +461 -0
  59. package/dist/collection/classes/structures/object-map.structure.js +1103 -0
  60. package/dist/collection/classes/structures/quadtree.structure.js +251 -0
  61. package/dist/collection/classes/tools/base-tool.class.js +88 -0
  62. package/dist/collection/classes/tools/brush-tool.class.js +236 -0
  63. package/dist/collection/classes/tools/eraser-tool.class.js +133 -0
  64. package/dist/collection/classes/tools/image-tool.class.js +152 -0
  65. package/dist/collection/classes/tools/line-tool.class.js +249 -0
  66. package/dist/collection/classes/tools/selection-tool.class.js +611 -0
  67. package/dist/collection/classes/tools/shape-tool.class.js +251 -0
  68. package/dist/collection/classes/tools/text-tool.class.js +179 -0
  69. package/dist/collection/collection-manifest.json +17 -0
  70. package/dist/collection/components/kritzel-awareness-cursors/kritzel-awareness-cursors.css +115 -0
  71. package/dist/collection/components/kritzel-awareness-cursors/kritzel-awareness-cursors.js +380 -0
  72. package/dist/collection/components/kritzel-cursor-trail/kritzel-cursor-trail.css +10 -0
  73. package/dist/collection/components/kritzel-cursor-trail/kritzel-cursor-trail.js +153 -0
  74. package/dist/collection/components/kritzel-engine/kritzel-engine.css +81 -0
  75. package/dist/collection/components/kritzel-engine/kritzel-engine.js +6345 -0
  76. package/dist/collection/components/kritzel-icon/kritzel-icon.css +18 -0
  77. package/dist/collection/components/kritzel-icon/kritzel-icon.js +93 -0
  78. package/dist/collection/components/kritzel-watermark/kritzel-watermark.css +29 -0
  79. package/dist/collection/components/kritzel-watermark/kritzel-watermark.js +83 -0
  80. package/dist/collection/configs/default-asset-storage.config.js +9 -0
  81. package/dist/collection/configs/default-brush-tool.config.js +9 -0
  82. package/dist/collection/configs/default-engine-config.js +73 -0
  83. package/dist/collection/configs/default-line-tool.config.js +12 -0
  84. package/dist/collection/configs/default-shape-tool.config.js +15 -0
  85. package/dist/collection/configs/default-sync.config.js +6 -0
  86. package/dist/collection/configs/default-text-tool.config.js +12 -0
  87. package/dist/collection/constants/color-palette.constants.js +40 -0
  88. package/dist/collection/constants/core.constants.js +1 -0
  89. package/dist/collection/constants/engine.constants.js +4 -0
  90. package/dist/collection/constants/license.constants.js +25 -0
  91. package/dist/collection/constants/schema.constants.js +4 -0
  92. package/dist/collection/constants/storage.constants.js +1 -0
  93. package/dist/collection/constants/stroke-size.constants.js +2 -0
  94. package/dist/collection/constants/text-tool-fonts.constants.js +18 -0
  95. package/dist/collection/constants/version.js +6 -0
  96. package/dist/collection/enums/alignment.enum.js +9 -0
  97. package/dist/collection/enums/event-button.enum.js +6 -0
  98. package/dist/collection/enums/handle-type.enum.js +7 -0
  99. package/dist/collection/enums/shape-type.enum.js +6 -0
  100. package/dist/collection/events/active-workspace-change.event.js +1 -0
  101. package/dist/collection/events/editor-is-ready.event.js +1 -0
  102. package/dist/collection/events/login.event.js +1 -0
  103. package/dist/collection/helpers/alignment.helper.js +73 -0
  104. package/dist/collection/helpers/class.helper.js +5 -0
  105. package/dist/collection/helpers/color.helper.js +106 -0
  106. package/dist/collection/helpers/cursor.helper.js +57 -0
  107. package/dist/collection/helpers/devices.helper.js +28 -0
  108. package/dist/collection/helpers/event.helper.js +58 -0
  109. package/dist/collection/helpers/geometry.helper.js +149 -0
  110. package/dist/collection/helpers/html.helper.js +116 -0
  111. package/dist/collection/helpers/image-file.helper.js +6 -0
  112. package/dist/collection/helpers/keyboard.helper.js +55 -0
  113. package/dist/collection/helpers/localization.helper.js +25 -0
  114. package/dist/collection/helpers/math.helper.js +8 -0
  115. package/dist/collection/helpers/migration.helper.js +45 -0
  116. package/dist/collection/helpers/object.helper.js +29 -0
  117. package/dist/collection/helpers/svg-export.helper.js +655 -0
  118. package/dist/collection/helpers/theme.helper.js +77 -0
  119. package/dist/collection/helpers/tool-config.helper.js +63 -0
  120. package/dist/collection/helpers/wheel.helper.js +113 -0
  121. package/dist/collection/index.js +107 -0
  122. package/dist/collection/interfaces/anchor.interface.js +1 -0
  123. package/dist/collection/interfaces/arrow-head.interface.js +1 -0
  124. package/dist/collection/interfaces/asset-provider.interface.js +1 -0
  125. package/dist/collection/interfaces/asset-storage-config.interface.js +1 -0
  126. package/dist/collection/interfaces/asset.interface.js +1 -0
  127. package/dist/collection/interfaces/bounding-box.interface.js +1 -0
  128. package/dist/collection/interfaces/clonable.interface.js +1 -0
  129. package/dist/collection/interfaces/context-menu-item.interface.js +1 -0
  130. package/dist/collection/interfaces/context-menu-state.interface.js +1 -0
  131. package/dist/collection/interfaces/debug-info.interface.js +1 -0
  132. package/dist/collection/interfaces/dialog.interface.js +1 -0
  133. package/dist/collection/interfaces/document-metadata.interface.js +1 -0
  134. package/dist/collection/interfaces/dynamic-object-renderer.interface.js +1 -0
  135. package/dist/collection/interfaces/engine-state.interface.js +1 -0
  136. package/dist/collection/interfaces/font.interface.js +1 -0
  137. package/dist/collection/interfaces/localization.interface.js +1 -0
  138. package/dist/collection/interfaces/login-config.interface.js +1 -0
  139. package/dist/collection/interfaces/master-detail.interface.js +1 -0
  140. package/dist/collection/interfaces/menu-item.interface.js +1 -0
  141. package/dist/collection/interfaces/migration.interface.js +1 -0
  142. package/dist/collection/interfaces/notification.interface.js +1 -0
  143. package/dist/collection/interfaces/object-change-event.interface.js +1 -0
  144. package/dist/collection/interfaces/object-export.interface.js +1 -0
  145. package/dist/collection/interfaces/object.interface.js +1 -0
  146. package/dist/collection/interfaces/paste-intent-provider.interface.js +1 -0
  147. package/dist/collection/interfaces/point.interface.js +1 -0
  148. package/dist/collection/interfaces/polygon.interface.js +1 -0
  149. package/dist/collection/interfaces/remote-cursor.interface.js +1 -0
  150. package/dist/collection/interfaces/selection-state.interface.js +1 -0
  151. package/dist/collection/interfaces/serializable.interface.js +1 -0
  152. package/dist/collection/interfaces/settings.interface.js +1 -0
  153. package/dist/collection/interfaces/share.interface.js +1 -0
  154. package/dist/collection/interfaces/shortcut.interface.js +1 -0
  155. package/dist/collection/interfaces/sync-config.interface.js +21 -0
  156. package/dist/collection/interfaces/sync-provider.interface.js +1 -0
  157. package/dist/collection/interfaces/theme.interface.js +1 -0
  158. package/dist/collection/interfaces/tool-config.interface.js +1 -0
  159. package/dist/collection/interfaces/tool-type.interface.js +1 -0
  160. package/dist/collection/interfaces/tool.interface.js +1 -0
  161. package/dist/collection/interfaces/toolbar-item.interface.js +1 -0
  162. package/dist/collection/interfaces/undo-state.interface.js +1 -0
  163. package/dist/collection/interfaces/user.interface.js +1 -0
  164. package/dist/collection/interfaces/viewport-state.interface.js +1 -0
  165. package/dist/collection/locales/de-locale.js +119 -0
  166. package/dist/collection/locales/en-locale.js +120 -0
  167. package/dist/collection/locales/fr-locale.js +119 -0
  168. package/dist/collection/migrations/app-state.migrations.js +47 -0
  169. package/dist/collection/migrations/workspace.migrations.js +67 -0
  170. package/dist/collection/themes/dark-theme.js +340 -0
  171. package/dist/collection/themes/light-theme.js +346 -0
  172. package/dist/collection/types/deep-readonly.type.js +1 -0
  173. package/dist/collection/types/state.types.js +1 -0
  174. package/dist/components/index.d.ts +47 -0
  175. package/dist/components/index.js +4143 -0
  176. package/dist/components/kritzel-awareness-cursors.d.ts +11 -0
  177. package/dist/components/kritzel-awareness-cursors.js +6 -0
  178. package/dist/components/kritzel-cursor-trail.d.ts +11 -0
  179. package/dist/components/kritzel-cursor-trail.js +6 -0
  180. package/dist/components/kritzel-engine.d.ts +11 -0
  181. package/dist/components/kritzel-engine.js +52641 -0
  182. package/dist/components/kritzel-icon.d.ts +11 -0
  183. package/dist/components/kritzel-icon.js +6 -0
  184. package/dist/components/kritzel-watermark.d.ts +11 -0
  185. package/dist/components/kritzel-watermark.js +6 -0
  186. package/dist/components/p-B2Htv9ou.js +49 -0
  187. package/dist/components/p-BvRGQvVI.js +3456 -0
  188. package/dist/components/p-CfSx6HU_.js +1469 -0
  189. package/dist/components/p-YP8wAcF4.js +122 -0
  190. package/dist/components/p-fx6msYHJ.js +167 -0
  191. package/dist/esm/app-globals-DQuL1Twl.js +3 -0
  192. package/dist/esm/engine.constants-Bl5-pbq-.js +28143 -0
  193. package/dist/esm/index-BU9Mv7y0.js +1715 -0
  194. package/dist/esm/index.js +4134 -0
  195. package/dist/esm/kritzel-awareness-cursors_5.entry.js +27978 -0
  196. package/dist/esm/loader.js +11 -0
  197. package/dist/esm/stencil.js +21 -0
  198. package/dist/index.cjs.js +1 -0
  199. package/dist/index.js +1 -0
  200. package/dist/stencil/index.esm.js +4134 -0
  201. package/dist/stencil/p-BU9Mv7y0.js +1702 -0
  202. package/dist/stencil/p-Bl5-pbq-.js +28143 -0
  203. package/dist/stencil/p-DQuL1Twl.js +3 -0
  204. package/dist/stencil/p-f0a8b7af.entry.js +27978 -0
  205. package/dist/stencil/stencil.esm.js +21 -0
  206. package/dist/types/classes/core/core.class.d.ts +532 -0
  207. package/dist/types/classes/core/reviver.class.d.ts +32 -0
  208. package/dist/types/classes/core/store.class.d.ts +198 -0
  209. package/dist/types/classes/core/viewport.class.d.ts +256 -0
  210. package/dist/types/classes/core/workspace.class.d.ts +95 -0
  211. package/dist/types/classes/handlers/base.handler.d.ts +18 -0
  212. package/dist/types/classes/handlers/context-menu.handler.d.ts +67 -0
  213. package/dist/types/classes/handlers/hover.handler.d.ts +23 -0
  214. package/dist/types/classes/handlers/key.handler.d.ts +44 -0
  215. package/dist/types/classes/handlers/line-handle.handler.d.ts +115 -0
  216. package/dist/types/classes/handlers/move.handler.d.ts +94 -0
  217. package/dist/types/classes/handlers/resize.handler.d.ts +95 -0
  218. package/dist/types/classes/handlers/rotation.handler.d.ts +50 -0
  219. package/dist/types/classes/handlers/selection.handler.d.ts +153 -0
  220. package/dist/types/classes/managers/anchor.manager.d.ts +513 -0
  221. package/dist/types/classes/managers/browser-permission.manager.d.ts +41 -0
  222. package/dist/types/classes/managers/clipboard.manager.d.ts +71 -0
  223. package/dist/types/classes/managers/clipboard.types.d.ts +23 -0
  224. package/dist/types/classes/managers/cursor.manager.d.ts +66 -0
  225. package/dist/types/classes/managers/license.manager.d.ts +147 -0
  226. package/dist/types/classes/managers/localization.manager.d.ts +145 -0
  227. package/dist/types/classes/managers/theme.manager.d.ts +112 -0
  228. package/dist/types/classes/objects/base-object.class.d.ts +266 -0
  229. package/dist/types/classes/objects/dynamic-object.class.d.ts +148 -0
  230. package/dist/types/classes/objects/group.class.d.ts +231 -0
  231. package/dist/types/classes/objects/image.class.d.ts +246 -0
  232. package/dist/types/classes/objects/line.class.d.ts +285 -0
  233. package/dist/types/classes/objects/path.class.d.ts +220 -0
  234. package/dist/types/classes/objects/selection-box.class.d.ts +19 -0
  235. package/dist/types/classes/objects/selection-group.class.d.ts +267 -0
  236. package/dist/types/classes/objects/shape.class.d.ts +322 -0
  237. package/dist/types/classes/objects/text.class.d.ts +197 -0
  238. package/dist/types/classes/providers/assets/asset-resolver.class.d.ts +141 -0
  239. package/dist/types/classes/providers/assets/http-asset-provider.class.d.ts +79 -0
  240. package/dist/types/classes/providers/assets/indexeddb-asset-provider.class.d.ts +69 -0
  241. package/dist/types/classes/providers/assets/presigned-asset-provider.class.d.ts +69 -0
  242. package/dist/types/classes/providers/paste-intent/event-paste-intent.provider.d.ts +8 -0
  243. package/dist/types/classes/providers/paste-intent/ios-paste-intent.provider.d.ts +6 -0
  244. package/dist/types/classes/providers/paste-intent/navigator-paste-intent.provider.d.ts +9 -0
  245. package/dist/types/classes/providers/sync/broadcast-sync-provider.class.d.ts +23 -0
  246. package/dist/types/classes/providers/sync/hocuspocus-sync-provider.class.d.ts +163 -0
  247. package/dist/types/classes/providers/sync/in-memory-sync-provider.class.d.ts +39 -0
  248. package/dist/types/classes/providers/sync/indexeddb-sync-provider.class.d.ts +25 -0
  249. package/dist/types/classes/providers/sync/websocket-sync-provider.class.d.ts +63 -0
  250. package/dist/types/classes/registries/dynamic-object-renderer.registry.d.ts +32 -0
  251. package/dist/types/classes/registries/font-registry.class.d.ts +19 -0
  252. package/dist/types/classes/registries/icon-registry.class.d.ts +39 -0
  253. package/dist/types/classes/registries/paste-intent-provider.registry.d.ts +10 -0
  254. package/dist/types/classes/registries/tool.registry.d.ts +53 -0
  255. package/dist/types/classes/structures/app-state-map.structure.d.ts +171 -0
  256. package/dist/types/classes/structures/object-map.structure.d.ts +403 -0
  257. package/dist/types/classes/structures/quadtree.structure.d.ts +128 -0
  258. package/dist/types/classes/tools/base-tool.class.d.ts +72 -0
  259. package/dist/types/classes/tools/brush-tool.class.d.ts +68 -0
  260. package/dist/types/classes/tools/eraser-tool.class.d.ts +38 -0
  261. package/dist/types/classes/tools/image-tool.class.d.ts +74 -0
  262. package/dist/types/classes/tools/line-tool.class.d.ts +63 -0
  263. package/dist/types/classes/tools/selection-tool.class.d.ts +188 -0
  264. package/dist/types/classes/tools/shape-tool.class.d.ts +90 -0
  265. package/dist/types/classes/tools/text-tool.class.d.ts +66 -0
  266. package/dist/types/components/kritzel-awareness-cursors/kritzel-awareness-cursors.d.ts +29 -0
  267. package/dist/types/components/kritzel-cursor-trail/kritzel-cursor-trail.d.ts +19 -0
  268. package/dist/types/components/kritzel-engine/kritzel-engine.d.ts +695 -0
  269. package/dist/types/components/kritzel-icon/kritzel-icon.d.ts +6 -0
  270. package/dist/types/components/kritzel-watermark/kritzel-watermark.d.ts +20 -0
  271. package/dist/types/components.d.ts +981 -0
  272. package/dist/types/configs/default-asset-storage.config.d.ts +8 -0
  273. package/dist/types/configs/default-brush-tool.config.d.ts +2 -0
  274. package/dist/types/configs/default-engine-config.d.ts +2 -0
  275. package/dist/types/configs/default-line-tool.config.d.ts +2 -0
  276. package/dist/types/configs/default-shape-tool.config.d.ts +2 -0
  277. package/dist/types/configs/default-sync.config.d.ts +5 -0
  278. package/dist/types/configs/default-text-tool.config.d.ts +2 -0
  279. package/dist/types/constants/color-palette.constants.d.ts +31 -0
  280. package/dist/types/constants/core.constants.d.ts +0 -0
  281. package/dist/types/constants/engine.constants.d.ts +4 -0
  282. package/dist/types/constants/license.constants.d.ts +25 -0
  283. package/dist/types/constants/schema.constants.d.ts +4 -0
  284. package/dist/types/constants/storage.constants.d.ts +1 -0
  285. package/dist/types/constants/stroke-size.constants.d.ts +2 -0
  286. package/dist/types/constants/text-tool-fonts.constants.d.ts +3 -0
  287. package/dist/types/constants/version.d.ts +6 -0
  288. package/dist/types/enums/alignment.enum.d.ts +8 -0
  289. package/dist/types/enums/event-button.enum.d.ts +5 -0
  290. package/dist/types/enums/handle-type.enum.d.ts +6 -0
  291. package/dist/types/enums/shape-type.enum.d.ts +5 -0
  292. package/dist/types/events/active-workspace-change.event.d.ts +7 -0
  293. package/dist/types/events/editor-is-ready.event.d.ts +18 -0
  294. package/dist/types/events/login.event.d.ts +3 -0
  295. package/dist/types/helpers/alignment.helper.d.ts +21 -0
  296. package/dist/types/helpers/class.helper.d.ts +3 -0
  297. package/dist/types/helpers/color.helper.d.ts +34 -0
  298. package/dist/types/helpers/cursor.helper.d.ts +22 -0
  299. package/dist/types/helpers/devices.helper.d.ts +8 -0
  300. package/dist/types/helpers/event.helper.d.ts +6 -0
  301. package/dist/types/helpers/geometry.helper.d.ts +38 -0
  302. package/dist/types/helpers/html.helper.d.ts +8 -0
  303. package/dist/types/helpers/image-file.helper.d.ts +3 -0
  304. package/dist/types/helpers/keyboard.helper.d.ts +6 -0
  305. package/dist/types/helpers/localization.helper.d.ts +18 -0
  306. package/dist/types/helpers/math.helper.d.ts +4 -0
  307. package/dist/types/helpers/migration.helper.d.ts +30 -0
  308. package/dist/types/helpers/object.helper.d.ts +9 -0
  309. package/dist/types/helpers/svg-export.helper.d.ts +231 -0
  310. package/dist/types/helpers/theme.helper.d.ts +42 -0
  311. package/dist/types/helpers/tool-config.helper.d.ts +4 -0
  312. package/dist/types/helpers/wheel.helper.d.ts +9 -0
  313. package/dist/types/index.d.ts +109 -0
  314. package/dist/types/interfaces/anchor.interface.d.ts +147 -0
  315. package/dist/types/interfaces/arrow-head.interface.d.ts +27 -0
  316. package/dist/types/interfaces/asset-provider.interface.d.ts +88 -0
  317. package/dist/types/interfaces/asset-storage-config.interface.d.ts +40 -0
  318. package/dist/types/interfaces/asset.interface.d.ts +43 -0
  319. package/dist/types/interfaces/bounding-box.interface.d.ts +8 -0
  320. package/dist/types/interfaces/clonable.interface.d.ts +3 -0
  321. package/dist/types/interfaces/context-menu-item.interface.d.ts +25 -0
  322. package/dist/types/interfaces/context-menu-state.interface.d.ts +16 -0
  323. package/dist/types/interfaces/debug-info.interface.d.ts +7 -0
  324. package/dist/types/interfaces/dialog.interface.d.ts +4 -0
  325. package/dist/types/interfaces/document-metadata.interface.d.ts +6 -0
  326. package/dist/types/interfaces/dynamic-object-renderer.interface.d.ts +40 -0
  327. package/dist/types/interfaces/engine-state.interface.d.ts +82 -0
  328. package/dist/types/interfaces/font.interface.d.ts +15 -0
  329. package/dist/types/interfaces/localization.interface.d.ts +143 -0
  330. package/dist/types/interfaces/login-config.interface.d.ts +24 -0
  331. package/dist/types/interfaces/master-detail.interface.d.ts +14 -0
  332. package/dist/types/interfaces/menu-item.interface.d.ts +27 -0
  333. package/dist/types/interfaces/migration.interface.d.ts +16 -0
  334. package/dist/types/interfaces/notification.interface.d.ts +10 -0
  335. package/dist/types/interfaces/object-change-event.interface.d.ts +31 -0
  336. package/dist/types/interfaces/object-export.interface.d.ts +20 -0
  337. package/dist/types/interfaces/object.interface.d.ts +53 -0
  338. package/dist/types/interfaces/paste-intent-provider.interface.d.ts +10 -0
  339. package/dist/types/interfaces/point.interface.d.ts +4 -0
  340. package/dist/types/interfaces/polygon.interface.d.ts +7 -0
  341. package/dist/types/interfaces/remote-cursor.interface.d.ts +18 -0
  342. package/dist/types/interfaces/selection-state.interface.d.ts +7 -0
  343. package/dist/types/interfaces/serializable.interface.d.ts +5 -0
  344. package/dist/types/interfaces/settings.interface.d.ts +25 -0
  345. package/dist/types/interfaces/share.interface.d.ts +9 -0
  346. package/dist/types/interfaces/shortcut.interface.d.ts +10 -0
  347. package/dist/types/interfaces/sync-config.interface.d.ts +41 -0
  348. package/dist/types/interfaces/sync-provider.interface.d.ts +66 -0
  349. package/dist/types/interfaces/theme.interface.d.ts +553 -0
  350. package/dist/types/interfaces/tool-config.interface.d.ts +24 -0
  351. package/dist/types/interfaces/tool-type.interface.d.ts +1 -0
  352. package/dist/types/interfaces/tool.interface.d.ts +8 -0
  353. package/dist/types/interfaces/toolbar-item.interface.d.ts +66 -0
  354. package/dist/types/interfaces/undo-state.interface.d.ts +6 -0
  355. package/dist/types/interfaces/user.interface.d.ts +22 -0
  356. package/dist/types/interfaces/viewport-state.interface.d.ts +7 -0
  357. package/dist/types/locales/de-locale.d.ts +5 -0
  358. package/dist/types/locales/en-locale.d.ts +6 -0
  359. package/dist/types/locales/fr-locale.d.ts +5 -0
  360. package/dist/types/migrations/app-state.migrations.d.ts +11 -0
  361. package/dist/types/migrations/workspace.migrations.d.ts +11 -0
  362. package/dist/types/stencil-public-runtime.d.ts +1873 -0
  363. package/dist/types/themes/dark-theme.d.ts +5 -0
  364. package/dist/types/themes/light-theme.d.ts +5 -0
  365. package/dist/types/types/deep-readonly.type.d.ts +7 -0
  366. package/dist/types/types/state.types.d.ts +3 -0
  367. package/loader/cdn.js +1 -0
  368. package/loader/index.cjs.js +1 -0
  369. package/loader/index.d.ts +24 -0
  370. package/loader/index.es2017.js +1 -0
  371. package/loader/index.js +2 -0
  372. package/package.json +101 -0
  373. package/readme.md +11 -0
@@ -0,0 +1,578 @@
1
+ import { getStroke } from "perfect-freehand";
2
+ import { KritzelMathHelper } from "../../helpers/math.helper";
3
+ import { KritzelBaseObject } from "./base-object.class";
4
+ import { KritzelGeometryHelper } from "../../helpers/geometry.helper";
5
+ export class KritzelPath extends KritzelBaseObject {
6
+ __class__ = 'KritzelPath';
7
+ points;
8
+ d;
9
+ stroke = { light: 'none', dark: 'none' };
10
+ strokeWidth;
11
+ lineSlack = 0.5;
12
+ fill;
13
+ x = 0;
14
+ y = 0;
15
+ height = 0;
16
+ width = 0;
17
+ scale = 1;
18
+ options;
19
+ isVisible = true;
20
+ isDebugInfoVisible = true;
21
+ isCompleted = false;
22
+ _adjustedPoints = null;
23
+ /**
24
+ * Gets the SVG viewBox string for local (object-relative) rendering.
25
+ *
26
+ * The path's `d` string is generated in local coordinates (offset so the
27
+ * object's top-left origin is at 0,0), so the viewBox always starts at 0,0.
28
+ * Keeping the SVG's internal coordinates small — independent of the object's
29
+ * world position — avoids float32 precision loss in the browser's SVG
30
+ * rasterizer (Skia), which otherwise fails to paint paths whose absolute
31
+ * world coordinates exceed ~2^24 (e.g. far from the origin at extreme zoom).
32
+ * @returns The viewBox attribute value in the format "0 0 width height"
33
+ */
34
+ get viewBox() {
35
+ return `0 0 ${this.width} ${this.height}`;
36
+ }
37
+ /**
38
+ * Creates a new KritzelPath instance.
39
+ * @param config - Optional configuration object for the path
40
+ * @param config.points - Array of [x, y] coordinate pairs defining the path
41
+ * @param config.translateX - Horizontal translation offset (default: 0)
42
+ * @param config.translateY - Vertical translation offset (default: 0)
43
+ * @param config.scale - Scale factor for the path (default: 1)
44
+ * @param config.strokeWidth - Width of the stroke in pixels (default: 8)
45
+ * @param config.fill - Theme-aware fill color with light and dark variants
46
+ * @param config.lineSlack - Additional padding for bounding box calculations (default: 0.5)
47
+ */
48
+ constructor(config) {
49
+ super();
50
+ this.options = config;
51
+ this.points = config?.points ?? [];
52
+ this.translateX = config?.translateX ?? 0;
53
+ this.translateY = config?.translateY ?? 0;
54
+ this.rotation = KritzelMathHelper.degreesToRadians(config?.rotation ?? 0);
55
+ this.scale = config?.scale ?? 1;
56
+ this.strokeWidth = config?.strokeWidth ?? 8;
57
+ this.fill = config?.fill ?? { light: '#000000', dark: '#ffffff' };
58
+ this.d = this.generateSvgPath();
59
+ this.updateDimensions();
60
+ }
61
+ /**
62
+ * Factory method to create a new KritzelPath instance with a core reference.
63
+ * This is the preferred way to create paths that will be managed by the canvas.
64
+ * @param core - The KritzelCore instance that will manage this path
65
+ * @param options - Optional configuration options for the path
66
+ * @returns A new KritzelPath instance configured with the provided options
67
+ */
68
+ static create(core, options) {
69
+ const object = new KritzelPath();
70
+ object._core = core;
71
+ object.id = object.generateId();
72
+ object.workspaceId = core.store.state.activeWorkspace.id;
73
+ object.userId = core.user?.id;
74
+ object.options = options;
75
+ object.points = options?.points ?? [];
76
+ object.translateX = options?.translateX ?? 0;
77
+ object.translateY = options?.translateY ?? 0;
78
+ object.rotation = KritzelMathHelper.degreesToRadians(options?.rotation ?? 0);
79
+ object.scale = options?.scale ?? 1;
80
+ object.strokeWidth = options?.strokeWidth ?? 8;
81
+ object.fill = options?.fill ?? { light: '#000000', dark: '#ffffff' };
82
+ object.opacity = options?.opacity ?? 1;
83
+ object.zIndex = core.store.currentZIndex;
84
+ object.d = object.generateSvgPath();
85
+ object.updateDimensions();
86
+ return object;
87
+ }
88
+ /**
89
+ * Creates a deep copy of this path object.
90
+ * The points array is cloned to ensure the copy is independent.
91
+ * @returns A new KritzelPath instance with copied properties
92
+ */
93
+ copy() {
94
+ const copiedObject = super.copy();
95
+ if (this.points) {
96
+ copiedObject.points = this.points.map(p => [...p]);
97
+ }
98
+ return copiedObject;
99
+ }
100
+ /**
101
+ * Restores the path from a serialized object, then regenerates the SVG `d`
102
+ * string from the restored points.
103
+ *
104
+ * Regeneration is required because the `d` string is now emitted in local
105
+ * (object-relative) coordinates paired with a "0 0 width height" viewBox.
106
+ * Older persisted paths stored `d` in absolute world coordinates, which
107
+ * would be inconsistent with the local-coordinate viewBox and fail to
108
+ * rasterize far from the origin at extreme zoom. Recomputing `d` here makes
109
+ * both freshly created and previously persisted paths render identically.
110
+ * @param object - The serialized path data to restore from
111
+ * @returns This instance cast to type T
112
+ */
113
+ deserialize(object) {
114
+ const result = super.deserialize(object);
115
+ this.d = this.generateSvgPath();
116
+ return result;
117
+ }
118
+ /**
119
+ * Resizes the path to fit within the specified dimensions.
120
+ * Scales all points proportionally and updates the SVG path.
121
+ * @param x - New X position for the path, or null to keep current
122
+ * @param y - New Y position for the path, or null to keep current
123
+ * @param width - New width for the path (must be > 1)
124
+ * @param height - New height for the path (must be > 1)
125
+ */
126
+ resize(x, y, width, height) {
127
+ if (width <= 1 || height <= 1) {
128
+ return;
129
+ }
130
+ const scaleX = width / this.width;
131
+ const scaleY = height / this.height;
132
+ this.width = width;
133
+ this.height = height;
134
+ if (this.points.length === 1) {
135
+ const p = this.points[0];
136
+ const spreadX = Math.max(0, width - this.strokeWidth) / scaleX;
137
+ const spreadY = Math.max(0, height - this.strokeWidth) / scaleY;
138
+ this.points.push([p[0] + spreadX, p[1] + spreadY]);
139
+ }
140
+ this.points = this.points.map(([x, y]) => [x * scaleX, y * scaleY]);
141
+ this.d = this.generateSvgPath();
142
+ this.width = Math.max(...this.points.map(p => p[0])) - Math.min(...this.points.map(p => p[0])) + this.strokeWidth;
143
+ this.height = Math.max(...this.points.map(p => p[1])) - Math.min(...this.points.map(p => p[1])) + this.strokeWidth;
144
+ this.x = Math.min(...this.points.map(p => p[0])) - this.strokeWidth / 2;
145
+ this.y = Math.min(...this.points.map(p => p[1])) - this.strokeWidth / 2;
146
+ if (x !== null) {
147
+ this.translateX = x;
148
+ }
149
+ if (y !== null) {
150
+ this.translateY = y;
151
+ }
152
+ this._adjustedPoints = null;
153
+ this._core.store.objects.update(this);
154
+ }
155
+ /**
156
+ * Rotates the path by the specified angle.
157
+ * Invalidates cached adjusted points to force recalculation.
158
+ * @param value - Rotation angle in radians
159
+ */
160
+ rotate(value) {
161
+ this.rotation = value;
162
+ this._adjustedPoints = null;
163
+ this._core.store.objects.update(this);
164
+ }
165
+ /**
166
+ * Moves the path by calculating the delta between start and end positions.
167
+ * The delta is adjusted for the current viewport scale.
168
+ * @param startX - Starting X coordinate in screen space
169
+ * @param startY - Starting Y coordinate in screen space
170
+ * @param endX - Ending X coordinate in screen space
171
+ * @param endY - Ending Y coordinate in screen space
172
+ */
173
+ move(startX, startY, endX, endY) {
174
+ const deltaX = (startX - endX) / this._core.store.state.scale;
175
+ const deltaY = (startY - endY) / this._core.store.state.scale;
176
+ this.translateX += deltaX;
177
+ this.translateY += deltaY;
178
+ this._adjustedPoints = null;
179
+ this._core.store.objects.update(this);
180
+ }
181
+ /**
182
+ * Tests whether a point intersects with the path's stroke.
183
+ * Uses distance-to-line-segment calculations for accurate hit detection.
184
+ * @param x - X coordinate to test in world space
185
+ * @param y - Y coordinate to test in world space
186
+ * @returns True if the point is within the stroke width of the path
187
+ */
188
+ hitTest(x, y) {
189
+ const halfStroke = this.strokeWidth / this.scale / 2;
190
+ if (this._adjustedPoints === null) {
191
+ this._adjustedPoints = this.computeAdjustedPoints();
192
+ }
193
+ if (this._adjustedPoints.length === 1) {
194
+ const p1 = this._adjustedPoints[0];
195
+ const distance = this.pointToLineSegmentDistance(x, y, p1[0], p1[1], p1[0], p1[1]);
196
+ return distance <= halfStroke;
197
+ }
198
+ for (let i = 0; i < this._adjustedPoints.length - 1; i++) {
199
+ const p1 = this._adjustedPoints[i];
200
+ const p2 = this._adjustedPoints[i + 1];
201
+ const distance = this.pointToLineSegmentDistance(x, y, p1[0], p1[1], p2[0], p2[1]);
202
+ if (distance <= halfStroke) {
203
+ return true;
204
+ }
205
+ }
206
+ return false;
207
+ }
208
+ /**
209
+ * Tests whether a polygon intersects with the path.
210
+ * Checks for point containment, edge intersections, and proximity to stroke.
211
+ * @param polygon - The polygon to test against, defined by its corner points
212
+ * @returns True if any part of the polygon overlaps with the path's stroke
213
+ */
214
+ hitTestPolygon(polygon) {
215
+ const halfStroke = this.strokeWidth / this.scale / 2;
216
+ if (this._adjustedPoints === null) {
217
+ this._adjustedPoints = this.computeAdjustedPoints();
218
+ }
219
+ const polyPoints = [
220
+ { x: polygon.bottomLeft.x, y: polygon.bottomLeft.y },
221
+ { x: polygon.bottomRight.x, y: polygon.bottomRight.y },
222
+ { x: polygon.topRight.x, y: polygon.topRight.y },
223
+ { x: polygon.topLeft.x, y: polygon.topLeft.y },
224
+ ];
225
+ for (const [px, py] of this._adjustedPoints) {
226
+ if (KritzelGeometryHelper.isPointInPolygon({ x: px, y: py }, polyPoints)) {
227
+ return true;
228
+ }
229
+ }
230
+ for (const pt of polyPoints) {
231
+ if (this.hitTest(pt.x, pt.y)) {
232
+ return true;
233
+ }
234
+ }
235
+ for (let i = 0; i < this._adjustedPoints.length - 1; i++) {
236
+ const p1 = { x: this._adjustedPoints[i][0], y: this._adjustedPoints[i][1] };
237
+ const p2 = { x: this._adjustedPoints[i + 1][0], y: this._adjustedPoints[i + 1][1] };
238
+ for (let j = 0; j < polyPoints.length; j++) {
239
+ const q1 = polyPoints[j];
240
+ const q2 = polyPoints[(j + 1) % polyPoints.length];
241
+ if (KritzelGeometryHelper.intersectLines(p1, p2, q1, q2)) {
242
+ return true;
243
+ }
244
+ }
245
+ }
246
+ for (let i = 0; i < this._adjustedPoints.length - 1; i++) {
247
+ const p1 = this._adjustedPoints[i];
248
+ const p2 = this._adjustedPoints[i + 1];
249
+ for (let j = 0; j < polyPoints.length; j++) {
250
+ const q1 = polyPoints[j];
251
+ const q2 = polyPoints[(j + 1) % polyPoints.length];
252
+ const d1 = this.pointToLineSegmentDistance(q1.x, q1.y, p1[0], p1[1], p2[0], p2[1]);
253
+ const d2 = this.pointToLineSegmentDistance(q2.x, q2.y, p1[0], p1[1], p2[0], p2[1]);
254
+ const d3 = this.pointToLineSegmentDistance(p1[0], p1[1], q1.x, q1.y, q2.x, q2.y);
255
+ const d4 = this.pointToLineSegmentDistance(p2[0], p2[1], q1.x, q1.y, q2.x, q2.y);
256
+ const minD = Math.min(d1, d2, d3, d4);
257
+ if (minD <= halfStroke) {
258
+ return true;
259
+ }
260
+ }
261
+ }
262
+ return false;
263
+ }
264
+ /**
265
+ * Updates the path's position to the specified coordinates.
266
+ * Invalidates cached adjusted points and triggers a store update.
267
+ * @param x - New X position in world space
268
+ * @param y - New Y position in world space
269
+ */
270
+ updatePosition(x, y) {
271
+ this.translateX = x;
272
+ this.translateY = y;
273
+ this._adjustedPoints = null;
274
+ this._core.store.objects.update(this);
275
+ }
276
+ /**
277
+ * Lifecycle hook called after properties have been updated.
278
+ * Regenerates the SVG path and bounding box when strokeWidth changes.
279
+ * @param changedProperties - Array of property names that were modified
280
+ */
281
+ onAfterUpdate(changedProperties) {
282
+ if (changedProperties.includes('strokeWidth')) {
283
+ this.d = this.generateSvgPath();
284
+ this.updateBoundingBox();
285
+ this._adjustedPoints = null;
286
+ }
287
+ }
288
+ /**
289
+ * Computes the world-space coordinates of all path points.
290
+ * Applies rotation around the path's center and adjusts for translation and scale.
291
+ * Results are cached in _adjustedPoints for performance.
292
+ * @returns Array of [x, y] coordinate pairs in world space
293
+ */
294
+ computeAdjustedPoints() {
295
+ if (!this.points?.length) {
296
+ return [];
297
+ }
298
+ const angle = this.rotation;
299
+ const cos = Math.cos(angle);
300
+ const sin = Math.sin(angle);
301
+ const xs = this.points.map(p => p[0]);
302
+ const ys = this.points.map(p => p[1]);
303
+ const pivot = {
304
+ x: (Math.min(...xs) + Math.max(...xs)) / 2,
305
+ y: (Math.min(...ys) + Math.max(...ys)) / 2,
306
+ };
307
+ const { x: cx, y: cy } = pivot;
308
+ const rotatedPoints = this.points.map(([x, y]) => {
309
+ const dx = x - cx;
310
+ const dy = y - cy;
311
+ return [cx + dx * cos - dy * sin, cy + dx * sin + dy * cos];
312
+ });
313
+ return rotatedPoints.map(([px, py]) => [Math.abs(px - this.x) / this.scale + this.translateX, Math.abs(py - this.y) / this.scale + this.translateY]);
314
+ }
315
+ /**
316
+ * Calculates the shortest distance from a point to a line segment.
317
+ * Uses projection to find the closest point on the segment.
318
+ * @param x - X coordinate of the test point
319
+ * @param y - Y coordinate of the test point
320
+ * @param x1 - X coordinate of the line segment start
321
+ * @param y1 - Y coordinate of the line segment start
322
+ * @param x2 - X coordinate of the line segment end
323
+ * @param y2 - Y coordinate of the line segment end
324
+ * @returns The shortest distance from the point to the line segment
325
+ */
326
+ pointToLineSegmentDistance(x, y, x1, y1, x2, y2) {
327
+ const A = x - x1;
328
+ const B = y - y1;
329
+ const C = x2 - x1;
330
+ const D = y2 - y1;
331
+ const dot = A * C + B * D;
332
+ const len_sq = C * C + D * D;
333
+ let param = -1;
334
+ if (len_sq !== 0) {
335
+ // in case of 0 length line
336
+ param = dot / len_sq;
337
+ }
338
+ let xx, yy;
339
+ if (param < 0) {
340
+ xx = x1;
341
+ yy = y1;
342
+ }
343
+ else if (param > 1) {
344
+ xx = x2;
345
+ yy = y2;
346
+ }
347
+ else {
348
+ xx = x1 + param * C;
349
+ yy = y1 + param * D;
350
+ }
351
+ const dx = x - xx;
352
+ const dy = y - yy;
353
+ return Math.sqrt(dx * dx + dy * dy);
354
+ }
355
+ /**
356
+ * Updates width, height, x, y, translateX, and translateY based on current points.
357
+ * Uses the unrotated local points and stroke width for base dimensions.
358
+ * Called during initial setup to establish the path's dimensions and position.
359
+ */
360
+ updateDimensions() {
361
+ const minX = Math.min(...this.points.map(p => p[0])) - this.strokeWidth / 2;
362
+ const minY = Math.min(...this.points.map(p => p[1])) - this.strokeWidth / 2;
363
+ const maxX = Math.max(...this.points.map(p => p[0])) + this.strokeWidth / 2;
364
+ const maxY = Math.max(...this.points.map(p => p[1])) + this.strokeWidth / 2;
365
+ this.width = maxX - minX + this.lineSlack;
366
+ this.height = maxY - minY + this.lineSlack;
367
+ this.x = minX;
368
+ this.y = minY;
369
+ this.translateX = (this.x + this.translateX) / this.scale;
370
+ this.translateY = (this.y + this.translateY) / this.scale;
371
+ }
372
+ /**
373
+ * Updates width, height, x, y based on current points and strokeWidth.
374
+ * Does NOT modify translateX/translateY (use updateDimensions for initial setup).
375
+ */
376
+ updateBoundingBox() {
377
+ const minX = Math.min(...this.points.map(p => p[0])) - this.strokeWidth / 2;
378
+ const minY = Math.min(...this.points.map(p => p[1])) - this.strokeWidth / 2;
379
+ const maxX = Math.max(...this.points.map(p => p[0])) + this.strokeWidth / 2;
380
+ const maxY = Math.max(...this.points.map(p => p[1])) + this.strokeWidth / 2;
381
+ this.width = maxX - minX + this.lineSlack;
382
+ this.height = maxY - minY + this.lineSlack;
383
+ this.x = minX;
384
+ this.y = minY;
385
+ }
386
+ /**
387
+ * Generates the SVG path data string from the current points.
388
+ * Uses perfect-freehand to create a smooth, pressure-sensitive stroke.
389
+ * @returns SVG path data string (d attribute value)
390
+ */
391
+ generateSvgPath() {
392
+ const stroke = this.getStrokeFromPoints(this.points, this.strokeWidth);
393
+ const offsetX = this.points.length ? Math.min(...this.points.map(p => p[0])) - this.strokeWidth / 2 : 0;
394
+ const offsetY = this.points.length ? Math.min(...this.points.map(p => p[1])) - this.strokeWidth / 2 : 0;
395
+ return this.getSvgPathFromStroke(stroke, offsetX, offsetY);
396
+ }
397
+ /**
398
+ * Converts raw input points into a smooth stroke outline using perfect-freehand.
399
+ * Applies pressure simulation and smoothing for a natural pen-like appearance.
400
+ * @param points - Array of [x, y] coordinate pairs representing the input path
401
+ * @param strokeWidth - The desired stroke width in pixels
402
+ * @returns Array of [x, y] coordinate pairs forming the stroke outline polygon
403
+ */
404
+ getStrokeFromPoints(points, strokeWidth) {
405
+ return getStroke(points, {
406
+ size: strokeWidth,
407
+ thinning: 0.5,
408
+ smoothing: 0.5,
409
+ streamline: 0.5,
410
+ easing: t => t,
411
+ simulatePressure: true,
412
+ last: true,
413
+ start: {
414
+ cap: true,
415
+ taper: 0,
416
+ easing: t => t,
417
+ },
418
+ end: {
419
+ cap: true,
420
+ taper: 0,
421
+ easing: t => t,
422
+ },
423
+ });
424
+ }
425
+ /**
426
+ * Converts stroke outline points into an SVG path data string.
427
+ * Uses quadratic bezier curves for smooth rendering.
428
+ * Coordinates are emitted relative to (offsetX, offsetY) so the resulting
429
+ * path lives in the object's local coordinate space (paired with a
430
+ * "0 0 width height" viewBox). This keeps SVG-internal coordinates small
431
+ * regardless of the object's world position, avoiding float32 rasterizer
432
+ * precision failures far from the origin.
433
+ * @param points - Array of [x, y] coordinate pairs forming the stroke outline
434
+ * @param offsetX - X origin to subtract from every coordinate (default 0)
435
+ * @param offsetY - Y origin to subtract from every coordinate (default 0)
436
+ * @param closed - Whether to close the path with 'Z' command (default: true)
437
+ * @returns SVG path data string with M, Q, and T commands
438
+ */
439
+ getSvgPathFromStroke(points, offsetX = 0, offsetY = 0, closed = true) {
440
+ const len = points.length;
441
+ if (len < 4) {
442
+ return ``;
443
+ }
444
+ const a = points[0];
445
+ const b = points[1];
446
+ const c = points[2];
447
+ const ax = a[0] - offsetX;
448
+ const ay = a[1] - offsetY;
449
+ const bx = b[0] - offsetX;
450
+ const by = b[1] - offsetY;
451
+ const cx = c[0] - offsetX;
452
+ const cy = c[1] - offsetY;
453
+ let result = `M${ax.toFixed(2)},${ay.toFixed(2)} Q${bx.toFixed(2)},${by.toFixed(2)} ${KritzelMathHelper.average(bx, cx).toFixed(2)},${KritzelMathHelper.average(by, cy).toFixed(2)} T`;
454
+ for (let i = 2, max = len - 1; i < max; i++) {
455
+ const p = points[i];
456
+ const q = points[i + 1];
457
+ const px = p[0] - offsetX;
458
+ const py = p[1] - offsetY;
459
+ const qx = q[0] - offsetX;
460
+ const qy = q[1] - offsetY;
461
+ result += `${KritzelMathHelper.average(px, qx).toFixed(2)},${KritzelMathHelper.average(py, qy).toFixed(2)} `;
462
+ }
463
+ if (closed) {
464
+ result += 'Z';
465
+ }
466
+ return result;
467
+ }
468
+ /**
469
+ * Determines if the path appears too small on screen for detailed rendering.
470
+ * Used for level-of-detail optimizations.
471
+ * @returns True if the path's screen area is less than 500 square pixels
472
+ */
473
+ isLowRes() {
474
+ if (!this._core) {
475
+ return false;
476
+ }
477
+ const viewportScale = this._core.store.state.scale;
478
+ const scaledWidth = this.boundingBox.width * viewportScale;
479
+ const scaledHeight = this.boundingBox.height * viewportScale;
480
+ return (scaledWidth * scaledHeight) < 500;
481
+ }
482
+ /**
483
+ * Finds the point where a line from outsidePoint to the path's center
484
+ * intersects the stroke edge. Used for arrow clipping at the actual stroke edge.
485
+ * Uses binary search refinement for accurate intersection detection.
486
+ * @param outsidePoint - A point outside the path to trace from
487
+ * @returns The intersection point on the stroke edge, or null if no intersection found
488
+ */
489
+ getClipPoint(outsidePoint) {
490
+ const centerX = this.centerX;
491
+ const centerY = this.centerY;
492
+ const halfStroke = this.strokeWidth / this.scale / 2;
493
+ // Ensure adjusted points are computed
494
+ if (this._adjustedPoints === null) {
495
+ this._adjustedPoints = this.computeAdjustedPoints();
496
+ }
497
+ if (this._adjustedPoints.length < 1) {
498
+ return null;
499
+ }
500
+ // Sample along the line from outsidePoint to center to find stroke edge
501
+ const steps = 32;
502
+ let prevOutside = true;
503
+ for (let i = 1; i <= steps; i++) {
504
+ const t = i / steps;
505
+ const sampleX = outsidePoint.x + (centerX - outsidePoint.x) * t;
506
+ const sampleY = outsidePoint.y + (centerY - outsidePoint.y) * t;
507
+ // Check distance to path stroke
508
+ let minDistance = Infinity;
509
+ if (this._adjustedPoints.length === 1) {
510
+ const p = this._adjustedPoints[0];
511
+ const dx = sampleX - p[0];
512
+ const dy = sampleY - p[1];
513
+ minDistance = Math.sqrt(dx * dx + dy * dy);
514
+ }
515
+ else {
516
+ for (let j = 0; j < this._adjustedPoints.length - 1; j++) {
517
+ const p1 = this._adjustedPoints[j];
518
+ const p2 = this._adjustedPoints[j + 1];
519
+ const dist = this.pointToLineSegmentDistance(sampleX, sampleY, p1[0], p1[1], p2[0], p2[1]);
520
+ if (dist < minDistance) {
521
+ minDistance = dist;
522
+ }
523
+ }
524
+ }
525
+ const isInside = minDistance <= halfStroke;
526
+ // Found the edge: transition from outside to inside
527
+ if (prevOutside && isInside) {
528
+ // Refine the intersection point using binary search
529
+ let tLow = (i - 1) / steps;
530
+ let tHigh = t;
531
+ for (let k = 0; k < 8; k++) {
532
+ const tMid = (tLow + tHigh) / 2;
533
+ const midX = outsidePoint.x + (centerX - outsidePoint.x) * tMid;
534
+ const midY = outsidePoint.y + (centerY - outsidePoint.y) * tMid;
535
+ let midDist = Infinity;
536
+ if (this._adjustedPoints.length === 1) {
537
+ const p = this._adjustedPoints[0];
538
+ const dx = midX - p[0];
539
+ const dy = midY - p[1];
540
+ midDist = Math.sqrt(dx * dx + dy * dy);
541
+ }
542
+ else {
543
+ for (let j = 0; j < this._adjustedPoints.length - 1; j++) {
544
+ const p1 = this._adjustedPoints[j];
545
+ const p2 = this._adjustedPoints[j + 1];
546
+ const dist = this.pointToLineSegmentDistance(midX, midY, p1[0], p1[1], p2[0], p2[1]);
547
+ if (dist < midDist) {
548
+ midDist = dist;
549
+ }
550
+ }
551
+ }
552
+ if (midDist <= halfStroke) {
553
+ tHigh = tMid;
554
+ }
555
+ else {
556
+ tLow = tMid;
557
+ }
558
+ }
559
+ const finalT = (tLow + tHigh) / 2;
560
+ return {
561
+ x: outsidePoint.x + (centerX - outsidePoint.x) * finalT,
562
+ y: outsidePoint.y + (centerY - outsidePoint.y) * finalT,
563
+ };
564
+ }
565
+ prevOutside = !isInside;
566
+ }
567
+ return null;
568
+ }
569
+ getSupportedExportFormats() {
570
+ return ['svg'];
571
+ }
572
+ async exportAs(format, context) {
573
+ if (format !== 'svg') {
574
+ return null;
575
+ }
576
+ return context.getObjectAsSvgDataUrl(this);
577
+ }
578
+ }
@@ -0,0 +1,32 @@
1
+ import { KritzelBaseObject } from "./base-object.class";
2
+ /**
3
+ * Represents a visual selection box used for multi-object selection on the canvas.
4
+ * The selection box is rendered as a semi-transparent rectangle with a border,
5
+ * typically shown when the user drags to select multiple objects.
6
+ */
7
+ export class KritzelSelectionBox extends KritzelBaseObject {
8
+ __class__ = 'KritzelSelectionBox';
9
+ /**
10
+ * Factory method to create a new KritzelSelectionBox instance with default styling.
11
+ * Initializes the selection box with a blue semi-transparent background and border,
12
+ * positioned at the highest z-index to ensure visibility above all other objects.
13
+ *
14
+ * @param core - The KritzelCore instance providing access to the store and workspace state.
15
+ * @returns A fully initialized KritzelSelectionBox instance with default dimensions of 0x0.
16
+ */
17
+ static create(core) {
18
+ const object = new KritzelSelectionBox();
19
+ object._core = core;
20
+ object.id = object.generateId();
21
+ object.workspaceId = core.store.state.activeWorkspace.id;
22
+ object.userId = core.user?.id;
23
+ object.scale = core.store.state.scale;
24
+ object.zIndex = 99999;
25
+ object.backgroundColor = { light: 'var(--kritzel-selection-box-background-color)', dark: 'var(--kritzel-selection-box-background-color)' };
26
+ object.borderColor = { light: 'var(--kritzel-selection-box-border-color)', dark: 'var(--kritzel-selection-box-border-color)' };
27
+ object.borderWidth = 2;
28
+ object.height = 0;
29
+ object.width = 0;
30
+ return object;
31
+ }
32
+ }