@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,106 @@
1
+ import { resolveColor } from "../constants/color-palette.constants";
2
+ import { KritzelThemeManager } from "../classes/managers/theme.manager";
3
+ export class KritzelColorHelper {
4
+ /**
5
+ * Resolves a color value based on the current theme.
6
+ * Handles both simple string colors and theme-aware color objects.
7
+ * @param color - The color to resolve (string or ThemeAwareColor)
8
+ * @param theme - Optional theme to use. If not provided, uses current theme from ThemeManager
9
+ * @returns The resolved hex color string, or empty string if color is undefined
10
+ */
11
+ static resolveThemeColor(color, theme) {
12
+ if (!color) {
13
+ return '';
14
+ }
15
+ const currentTheme = theme ?? KritzelThemeManager.getStoredTheme();
16
+ return resolveColor(color, currentTheme);
17
+ }
18
+ /**
19
+ * Applies opacity to a theme-aware color and returns an rgba string.
20
+ * @param color - The theme-aware color object or a hex color string
21
+ * @param opacity - The opacity value between 0 and 1
22
+ * @param theme - Optional theme to use. If not provided, uses current theme from ThemeManager
23
+ * @returns The color as an rgba string, or the resolved hex if opacity is 1
24
+ */
25
+ static applyOpacity(color, opacity, theme) {
26
+ const hexColor = typeof color === 'string' ? color : this.resolveThemeColor(color, theme);
27
+ if (!hexColor || opacity >= 1)
28
+ return hexColor;
29
+ const sanitizedHex = hexColor.startsWith('#') ? hexColor.slice(1) : hexColor;
30
+ let r, g, b;
31
+ if (sanitizedHex.length === 3) {
32
+ r = parseInt(sanitizedHex[0] + sanitizedHex[0], 16);
33
+ g = parseInt(sanitizedHex[1] + sanitizedHex[1], 16);
34
+ b = parseInt(sanitizedHex[2] + sanitizedHex[2], 16);
35
+ }
36
+ else if (sanitizedHex.length === 6) {
37
+ r = parseInt(sanitizedHex.substring(0, 2), 16);
38
+ g = parseInt(sanitizedHex.substring(2, 4), 16);
39
+ b = parseInt(sanitizedHex.substring(4, 6), 16);
40
+ }
41
+ else {
42
+ return hexColor;
43
+ }
44
+ if (isNaN(r) || isNaN(g) || isNaN(b)) {
45
+ return hexColor;
46
+ }
47
+ return `rgba(${r}, ${g}, ${b}, ${opacity})`;
48
+ }
49
+ /**
50
+ * Determines the appropriate contrast color (black or white) based on the luminance of the given hex color.
51
+ * Uses the relative luminance formula: 0.299*R + 0.587*G + 0.114*B
52
+ * @param hexColor - The hex color string (with or without #)
53
+ * @returns '#000000' for light backgrounds, '#ffffff' for dark backgrounds
54
+ */
55
+ static getContrastColor(hexColor) {
56
+ const sanitizedHex = hexColor.startsWith('#') ? hexColor.slice(1) : hexColor;
57
+ let r, g, b;
58
+ if (sanitizedHex.length === 3) {
59
+ r = parseInt(sanitizedHex[0] + sanitizedHex[0], 16);
60
+ g = parseInt(sanitizedHex[1] + sanitizedHex[1], 16);
61
+ b = parseInt(sanitizedHex[2] + sanitizedHex[2], 16);
62
+ }
63
+ else if (sanitizedHex.length === 6) {
64
+ r = parseInt(sanitizedHex.substring(0, 2), 16);
65
+ g = parseInt(sanitizedHex.substring(2, 4), 16);
66
+ b = parseInt(sanitizedHex.substring(4, 6), 16);
67
+ }
68
+ else {
69
+ // Default to black for invalid colors
70
+ return '#000000';
71
+ }
72
+ if (isNaN(r) || isNaN(g) || isNaN(b)) {
73
+ return '#000000';
74
+ }
75
+ // Calculate relative luminance
76
+ const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
77
+ // Use threshold of 150 (midpoint) for balanced contrast
78
+ return luminance > 150 ? '#000000' : '#ffffff';
79
+ }
80
+ /**
81
+ * Determines the appropriate text color for both light and dark themes based on the fill color.
82
+ * Returns default theme-appropriate colors if the fill is transparent.
83
+ * @param fillColor - The theme-aware fill color
84
+ * @returns A theme-aware color object with appropriate text colors for both themes
85
+ */
86
+ static determineTextColor(fillColor) {
87
+ // Check if fillColor is transparent for both themes
88
+ const isTransparentLight = fillColor.light === 'transparent';
89
+ const isTransparentDark = fillColor.dark === 'transparent';
90
+ if (isTransparentLight && isTransparentDark) {
91
+ // Return default theme-appropriate colors for transparent fills
92
+ return { light: '#000000', dark: '#ffffff' };
93
+ }
94
+ // Determine text color for each theme based on fill brightness
95
+ const lightThemeTextColor = isTransparentLight
96
+ ? '#000000'
97
+ : this.getContrastColor(fillColor.light);
98
+ const darkThemeTextColor = isTransparentDark
99
+ ? '#ffffff'
100
+ : this.getContrastColor(fillColor.dark);
101
+ return {
102
+ light: lightThemeTextColor,
103
+ dark: darkThemeTextColor,
104
+ };
105
+ }
106
+ }
@@ -0,0 +1,57 @@
1
+ import { KritzelIconRegistry } from "../classes/registries/icon-registry.class";
2
+ export class KritzelCursorHelper {
3
+ static _pointerCursor = null;
4
+ /**
5
+ * Returns the custom pointer cursor CSS value.
6
+ * This can be used instead of `cursor: pointer` for consistent styling.
7
+ */
8
+ static getPointerCursor() {
9
+ if (!this._pointerCursor) {
10
+ this._pointerCursor = this.getCursor({ iconName: 'pointer' });
11
+ }
12
+ return this._pointerCursor;
13
+ }
14
+ /**
15
+ * Returns a custom cursor CSS value with support for rotation.
16
+ * The icon is retrieved from the KritzelIconRegistry.
17
+ */
18
+ static getCursor(options) {
19
+ const iconName = options.iconName === 'default' ? 'mouse-pointer' : options.iconName;
20
+ const iconSvg = KritzelIconRegistry.get(iconName);
21
+ if (!iconSvg) {
22
+ console.warn(`Icon "${iconName}" not found in registry.`);
23
+ return 'auto';
24
+ }
25
+ const size = options.size || 24;
26
+ const rotation = options.rotation || 0;
27
+ const color = options.color || 'black';
28
+ // Default cursor (mouse-pointer) has hotspot at (4, 4), others at center
29
+ const hotspot = options.hotspot || (options.iconName === 'default' ? { x: 4, y: 4 } : { x: size / 2, y: size / 2 });
30
+ // Modify the SVG string to set size and color
31
+ // We replace width and height to match the requested size
32
+ // We replace currentColor with the requested color
33
+ let content = iconSvg
34
+ .replace(/width="\d+"/, `width="${size}"`)
35
+ .replace(/height="\d+"/, `height="${size}"`)
36
+ .replace(/currentColor/g, color);
37
+ // Create the SVG string
38
+ // We rotate around the center of the SVG canvas
39
+ const center = size / 2;
40
+ // We use a group to apply the rotation
41
+ const svg = `
42
+ <svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
43
+ <g transform="rotate(${rotation} ${center} ${center})">
44
+ ${content}
45
+ </g>
46
+ </svg>
47
+ `;
48
+ // Encode the SVG for use in a data URI
49
+ // We need to be careful with encoding to ensure it works across browsers
50
+ const encodedSvg = encodeURIComponent(svg.replace(/\s+/g, ' ').trim())
51
+ .replace(/'/g, '%27')
52
+ .replace(/"/g, '%22');
53
+ const dataUri = `data:image/svg+xml;charset=utf-8,${encodedSvg}`;
54
+ // Return the cursor style string
55
+ return `url('${dataUri}') ${hotspot.x} ${hotspot.y}, auto`;
56
+ }
57
+ }
@@ -0,0 +1,28 @@
1
+ export class KritzelDevicesHelper {
2
+ static isTouchDevice() {
3
+ return window.matchMedia('(any-pointer: coarse)').matches;
4
+ }
5
+ static isAndroid() {
6
+ return /android/i.test(navigator.userAgent);
7
+ }
8
+ static isIOS() {
9
+ return /iPad|iPhone|iPod/.test(navigator.userAgent);
10
+ }
11
+ static detectOS() {
12
+ if (this.isIOS()) {
13
+ return 'iOS';
14
+ }
15
+ else if (this.isAndroid()) {
16
+ return 'Android';
17
+ }
18
+ else {
19
+ return 'Other';
20
+ }
21
+ }
22
+ static isMobile() {
23
+ return this.isIOS() || this.isAndroid();
24
+ }
25
+ static isFirefox() {
26
+ return /firefox/i.test(navigator.userAgent);
27
+ }
28
+ }
@@ -0,0 +1,58 @@
1
+ import { KritzelMouseButton } from "../enums/event-button.enum";
2
+ export class KritzelEventHelper {
3
+ static isRightClick(ev) {
4
+ return ev.button === KritzelMouseButton.Right;
5
+ }
6
+ static isLeftClick(ev) {
7
+ return ev.button === KritzelMouseButton.Left;
8
+ }
9
+ static isPointerEventOnContextMenu(event) {
10
+ const path = event.composedPath();
11
+ const contextMenu = path.find(element => element.classList && element.classList.contains('context-menu'));
12
+ return !!contextMenu;
13
+ }
14
+ static onLongPress(event, onSuccess, onCancel) {
15
+ if (event.pointerType !== 'touch') {
16
+ onCancel?.();
17
+ return () => { };
18
+ }
19
+ const startX = event.clientX;
20
+ const startY = event.clientY;
21
+ const target = event.target;
22
+ if (!target) {
23
+ onCancel?.();
24
+ return () => { };
25
+ }
26
+ const longPressTimeout = 400;
27
+ const moveThreshold = 10;
28
+ const timer = setTimeout(() => {
29
+ removeListeners();
30
+ onSuccess(event);
31
+ }, longPressTimeout);
32
+ const cancel = () => {
33
+ clearTimeout(timer);
34
+ removeListeners();
35
+ onCancel?.();
36
+ };
37
+ const onPointerMove = (e) => {
38
+ if (Math.abs(e.clientX - startX) > moveThreshold || Math.abs(e.clientY - startY) > moveThreshold) {
39
+ cancel();
40
+ }
41
+ };
42
+ const onPointerUp = () => {
43
+ cancel();
44
+ };
45
+ const onPointerCancel = () => {
46
+ cancel();
47
+ };
48
+ const removeListeners = () => {
49
+ target.removeEventListener('pointermove', onPointerMove);
50
+ target.removeEventListener('pointerup', onPointerUp);
51
+ target.removeEventListener('pointercancel', onPointerCancel);
52
+ };
53
+ target.addEventListener('pointermove', onPointerMove, { passive: true });
54
+ target.addEventListener('pointerup', onPointerUp, { once: true });
55
+ target.addEventListener('pointercancel', onPointerCancel, { once: true });
56
+ return cancel;
57
+ }
58
+ }
@@ -0,0 +1,149 @@
1
+ export class KritzelGeometryHelper {
2
+ static doPolygonsIntersect(polygon1, polygon2) {
3
+ // 1. Convert polygons to array of points for easier processing
4
+ const points1 = [polygon1.bottomLeft, polygon1.bottomRight, polygon1.topRight, polygon1.topLeft];
5
+ const points2 = [polygon2.bottomLeft, polygon2.bottomRight, polygon2.topRight, polygon2.topLeft];
6
+ // 2. Check if any point of polygon1 is inside polygon2
7
+ for (const point of points1) {
8
+ if (this.isPointInPolygon(point, points2)) {
9
+ return true;
10
+ }
11
+ }
12
+ // 3. Check if any point of polygon2 is inside polygon1
13
+ for (const point of points2) {
14
+ if (this.isPointInPolygon(point, points1)) {
15
+ return true;
16
+ }
17
+ }
18
+ // 4. Check for edge intersections (more complex)
19
+ for (let i = 0; i < points1.length; i++) {
20
+ const p1a = points1[i];
21
+ const p1b = points1[(i + 1) % points1.length]; // Wrap around to the first point
22
+ for (let j = 0; j < points2.length; j++) {
23
+ const p2a = points2[j];
24
+ const p2b = points2[(j + 1) % points2.length];
25
+ if (this.intersectLines(p1a, p1b, p2a, p2b)) {
26
+ return true;
27
+ }
28
+ }
29
+ }
30
+ return false; // No intersection found
31
+ }
32
+ static isPointInPolygon(point, polygon) {
33
+ let inside = false;
34
+ for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
35
+ const xi = polygon[i].x, yi = polygon[i].y;
36
+ const xj = polygon[j].x, yj = polygon[j].y;
37
+ const intersect = yi > point.y !== yj > point.y && point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;
38
+ if (intersect)
39
+ inside = !inside;
40
+ }
41
+ return inside;
42
+ }
43
+ static intersectLines(p1a, p1b, p2a, p2b) {
44
+ const det = (p1b.x - p1a.x) * (p2b.y - p2a.y) - (p1b.y - p1a.y) * (p2b.x - p2a.x);
45
+ if (det === 0) {
46
+ return false; // Lines are parallel
47
+ }
48
+ const t = ((p2a.x - p1a.x) * (p2b.y - p2a.y) - (p2a.y - p1a.y) * (p2b.x - p2a.x)) / det;
49
+ const u = -((p1a.x - p2a.x) * (p1b.y - p1a.y) - (p1a.y - p2a.y) * (p1b.x - p1a.x)) / det;
50
+ return t >= 0 && t <= 1 && u >= 0 && u <= 1;
51
+ }
52
+ /**
53
+ * Finds the intersection point between a line segment and a line segment.
54
+ * Returns the intersection point or null if no intersection.
55
+ */
56
+ static getLineIntersectionPoint(p1a, p1b, p2a, p2b) {
57
+ const det = (p1b.x - p1a.x) * (p2b.y - p2a.y) - (p1b.y - p1a.y) * (p2b.x - p2a.x);
58
+ if (det === 0) {
59
+ return null; // Lines are parallel
60
+ }
61
+ const t = ((p2a.x - p1a.x) * (p2b.y - p2a.y) - (p2a.y - p1a.y) * (p2b.x - p2a.x)) / det;
62
+ const u = -((p1a.x - p2a.x) * (p1b.y - p1a.y) - (p1a.y - p2a.y) * (p1b.x - p1a.x)) / det;
63
+ if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
64
+ return {
65
+ x: p1a.x + t * (p1b.x - p1a.x),
66
+ y: p1a.y + t * (p1b.y - p1a.y)
67
+ };
68
+ }
69
+ return null;
70
+ }
71
+ /**
72
+ * Finds the closest intersection point between a line segment (from lineStart to lineEnd)
73
+ * and a polygon. Returns the intersection point closest to lineStart, or null if no intersection.
74
+ */
75
+ static getLinePolygonIntersection(lineStart, lineEnd, polygon) {
76
+ const points = [polygon.topLeft, polygon.topRight, polygon.bottomRight, polygon.bottomLeft];
77
+ let closestIntersection = null;
78
+ let closestDistance = Infinity;
79
+ for (let i = 0; i < points.length; i++) {
80
+ const edgeStart = points[i];
81
+ const edgeEnd = points[(i + 1) % points.length];
82
+ const intersection = this.getLineIntersectionPoint(lineStart, lineEnd, edgeStart, edgeEnd);
83
+ if (intersection) {
84
+ const distance = Math.sqrt(Math.pow(intersection.x - lineStart.x, 2) +
85
+ Math.pow(intersection.y - lineStart.y, 2));
86
+ if (distance < closestDistance) {
87
+ closestDistance = distance;
88
+ closestIntersection = intersection;
89
+ }
90
+ }
91
+ }
92
+ return closestIntersection;
93
+ }
94
+ /**
95
+ * Generates a polygon approximation of an ellipse.
96
+ * @param centerX - X coordinate of ellipse center
97
+ * @param centerY - Y coordinate of ellipse center
98
+ * @param rx - Horizontal radius
99
+ * @param ry - Vertical radius
100
+ * @param segments - Number of segments (more = smoother approximation)
101
+ * @param rotation - Optional rotation angle in radians
102
+ */
103
+ static getEllipsePolygonApproximation(centerX, centerY, rx, ry, segments = 32, rotation = 0) {
104
+ const points = [];
105
+ const cos = Math.cos(rotation);
106
+ const sin = Math.sin(rotation);
107
+ for (let i = 0; i < segments; i++) {
108
+ const angle = (2 * Math.PI * i) / segments;
109
+ // Point on unrotated ellipse
110
+ const px = rx * Math.cos(angle);
111
+ const py = ry * Math.sin(angle);
112
+ // Apply rotation around center
113
+ const rotatedX = centerX + px * cos - py * sin;
114
+ const rotatedY = centerY + px * sin + py * cos;
115
+ points.push({ x: rotatedX, y: rotatedY });
116
+ }
117
+ return points;
118
+ }
119
+ /**
120
+ * Finds the closest intersection point between a line segment and a polygon
121
+ * defined as an array of points. Returns the intersection closest to lineStart,
122
+ * or null if no intersection.
123
+ */
124
+ static getLinePointsArrayIntersection(lineStart, lineEnd, polygonPoints) {
125
+ let closestIntersection = null;
126
+ let closestDistance = Infinity;
127
+ for (let i = 0; i < polygonPoints.length; i++) {
128
+ const edgeStart = polygonPoints[i];
129
+ const edgeEnd = polygonPoints[(i + 1) % polygonPoints.length];
130
+ const intersection = this.getLineIntersectionPoint(lineStart, lineEnd, edgeStart, edgeEnd);
131
+ if (intersection) {
132
+ const distance = Math.sqrt(Math.pow(intersection.x - lineStart.x, 2) +
133
+ Math.pow(intersection.y - lineStart.y, 2));
134
+ if (distance < closestDistance) {
135
+ closestDistance = distance;
136
+ closestIntersection = intersection;
137
+ }
138
+ }
139
+ }
140
+ return closestIntersection;
141
+ }
142
+ /**
143
+ * Checks if a point is inside a polygon defined as an array of points.
144
+ * This is a convenience wrapper that works with arbitrary polygon point arrays.
145
+ */
146
+ static isPointInPolygonPoints(point, polygonPoints) {
147
+ return this.isPointInPolygon(point, polygonPoints);
148
+ }
149
+ }
@@ -0,0 +1,116 @@
1
+ export class KritzelHTMLHelper {
2
+ static getNumericValueFromStyle(element, property) {
3
+ const value = window.getComputedStyle(element).getPropertyValue(property);
4
+ return parseFloat(value) || 0;
5
+ }
6
+ static isScrollableElement(element) {
7
+ if (!(element instanceof HTMLElement)) {
8
+ return false;
9
+ }
10
+ const style = window.getComputedStyle(element);
11
+ const overflowX = style.overflowX;
12
+ const overflowY = style.overflowY;
13
+ const overflow = style.overflow;
14
+ const canScrollX = (overflowX === 'auto' || overflowX === 'scroll' || overflowX === 'overlay') && element.scrollWidth > element.clientWidth;
15
+ const canScrollY = (overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay') && element.scrollHeight > element.clientHeight;
16
+ const canScroll = overflow === 'auto' || overflow === 'scroll' || overflow === 'overlay';
17
+ return canScrollX || canScrollY || (canScroll && (element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight));
18
+ }
19
+ static findScrollableElement(root) {
20
+ if (!root) {
21
+ return null;
22
+ }
23
+ const visited = new Set();
24
+ const walk = (element) => {
25
+ if (visited.has(element)) {
26
+ return null;
27
+ }
28
+ visited.add(element);
29
+ if (this.isScrollableElement(element)) {
30
+ return element;
31
+ }
32
+ if (element.shadowRoot) {
33
+ for (const child of Array.from(element.shadowRoot.children)) {
34
+ const scrollable = walk(child);
35
+ if (scrollable) {
36
+ return scrollable;
37
+ }
38
+ }
39
+ }
40
+ if (element.tagName === 'SLOT') {
41
+ for (const assignedElement of element.assignedElements({ flatten: true })) {
42
+ const scrollable = walk(assignedElement);
43
+ if (scrollable) {
44
+ return scrollable;
45
+ }
46
+ }
47
+ }
48
+ for (const child of Array.from(element.children)) {
49
+ const scrollable = walk(child);
50
+ if (scrollable) {
51
+ return scrollable;
52
+ }
53
+ }
54
+ return null;
55
+ };
56
+ return walk(root);
57
+ }
58
+ static getScrollableParent(element) {
59
+ if (!element) {
60
+ return window;
61
+ }
62
+ const parent = element.parentNode?.host ?? element.parentElement;
63
+ if (!parent || parent.tagName === 'BODY') {
64
+ return window;
65
+ }
66
+ const style = window.getComputedStyle(parent);
67
+ if (style.overflow === 'auto' || style.overflowY === 'auto' || style.overflow === 'scroll' || style.overflowY === 'scroll') {
68
+ return parent;
69
+ }
70
+ return this.getScrollableParent(parent);
71
+ }
72
+ static isElementInViewport(element) {
73
+ if (!element) {
74
+ return false;
75
+ }
76
+ const scrollableParent = this.getScrollableParent(element);
77
+ const rect = element.getBoundingClientRect();
78
+ if (scrollableParent === window) {
79
+ const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
80
+ const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
81
+ return rect.top >= 0 && rect.left >= 0 && rect.bottom <= viewportHeight && rect.right <= viewportWidth;
82
+ }
83
+ const parentRect = scrollableParent.getBoundingClientRect();
84
+ return rect.top >= parentRect.top && rect.left >= parentRect.left && rect.bottom <= parentRect.bottom && rect.right <= parentRect.right;
85
+ }
86
+ static getFocusableElements(root) {
87
+ if (!root)
88
+ return [];
89
+ const focusableElements = [];
90
+ const focusableSelector = 'a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details, [tabindex]:not([tabindex="-1"])';
91
+ const isVisible = (el) => {
92
+ const style = window.getComputedStyle(el);
93
+ return style.display !== 'none' && style.visibility !== 'hidden';
94
+ };
95
+ const find = (element) => {
96
+ // Check if the element itself is focusable
97
+ if (element instanceof HTMLElement && element.matches(focusableSelector) && !element.hasAttribute('disabled') && isVisible(element)) {
98
+ focusableElements.push(element);
99
+ }
100
+ // Traverse shadow DOM
101
+ if (element.shadowRoot) {
102
+ Array.from(element.shadowRoot.children).forEach(find);
103
+ }
104
+ // Traverse slotted content
105
+ if (element.tagName === 'SLOT') {
106
+ element.assignedElements({ flatten: true }).forEach(find);
107
+ }
108
+ // Traverse light DOM children if there is no shadow root
109
+ if (!element.shadowRoot) {
110
+ Array.from(element.children).forEach(find);
111
+ }
112
+ };
113
+ find(root);
114
+ return focusableElements;
115
+ }
116
+ }
@@ -0,0 +1,6 @@
1
+ export class KritzelImageFileHelper {
2
+ static isGifFile(file) {
3
+ const mimeType = file.type.trim().toLowerCase();
4
+ return mimeType === 'image/gif' || (mimeType === '' && file.name.toLowerCase().endsWith('.gif'));
5
+ }
6
+ }
@@ -0,0 +1,55 @@
1
+ import { KritzelDevicesHelper } from "./devices.helper";
2
+ export class KritzelKeyboardHelper {
3
+ static forceHideKeyboard() {
4
+ if (document.activeElement instanceof HTMLElement) {
5
+ document.activeElement.blur();
6
+ }
7
+ }
8
+ static enableInteractiveWidget() {
9
+ const meta = document.querySelector('meta[name="viewport"][content*="interactive-widget=resizes-content"]');
10
+ if (meta) {
11
+ let currentContent = meta.getAttribute('content');
12
+ if (!currentContent?.includes('interactive-widget=resizes-content')) {
13
+ currentContent += ', interactive-widget=resizes-content';
14
+ }
15
+ if (currentContent) {
16
+ meta.setAttribute('content', currentContent);
17
+ }
18
+ }
19
+ }
20
+ static disableInteractiveWidget() {
21
+ const meta = document.querySelector('meta[name="viewport"][content*="interactive-widget=resizes-content"]');
22
+ if (meta) {
23
+ let currentContent = meta.getAttribute('content');
24
+ let newContent = currentContent?.replace(/\s*interactive-widget=resizes-content\s*[,;]?/g, '');
25
+ if (newContent !== undefined) {
26
+ newContent = newContent
27
+ .replace(/,(\s*,)+/g, ',')
28
+ .replace(/^,/, '')
29
+ .replace(/,$/, '')
30
+ .trim();
31
+ meta.setAttribute('content', newContent);
32
+ }
33
+ }
34
+ }
35
+ static onKeyboardVisibleChanged(callback) {
36
+ if ('visualViewport' in window) {
37
+ const VIEWPORT_VS_CLIENT_HEIGHT_RATIO = 0.75;
38
+ const onResize = (event) => {
39
+ const target = event.target;
40
+ const isMobileDevice = KritzelDevicesHelper.isMobile();
41
+ const isViewportReduced = (target.height * target.scale) / window.screen.height < VIEWPORT_VS_CLIENT_HEIGHT_RATIO;
42
+ const isOpen = isMobileDevice && isViewportReduced;
43
+ callback(isOpen);
44
+ };
45
+ window.visualViewport?.addEventListener('resize', onResize);
46
+ return () => window.visualViewport?.removeEventListener('resize', onResize);
47
+ }
48
+ else {
49
+ // Fallback for older browsers does not provide a reliable event-based mechanism.
50
+ console.warn('Listening for keyboard visibility changes is not reliably supported in this browser.');
51
+ // Return a no-op cleanup function.
52
+ return () => { };
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Pure static utilities for localization term resolution.
3
+ */
4
+ export class LocalizationHelper {
5
+ /**
6
+ * Interpolates `{placeholder}` tokens in a term template with the provided
7
+ * variables. Tokens without a matching variable are left untouched.
8
+ *
9
+ * @param template - The raw term string, e.g. `'Expires {date}'`
10
+ * @param vars - Map of placeholder names to replacement values
11
+ * @returns The interpolated string
12
+ *
13
+ * @example
14
+ * LocalizationHelper.interpolate('Hello {name}', { name: 'Ada' }); // 'Hello Ada'
15
+ */
16
+ static interpolate(template, vars) {
17
+ if (!vars) {
18
+ return template;
19
+ }
20
+ return template.replace(/\{(\w+)\}/g, (match, key) => {
21
+ const value = vars[key];
22
+ return value === undefined || value === null ? match : String(value);
23
+ });
24
+ }
25
+ }
@@ -0,0 +1,8 @@
1
+ export class KritzelMathHelper {
2
+ static average(a, b) {
3
+ return (a + b) / 2;
4
+ }
5
+ static degreesToRadians(degrees) {
6
+ return degrees * (Math.PI / 180);
7
+ }
8
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Runs pending schema migrations on a Y.Doc.
3
+ *
4
+ * Reads the current `schemaVersion` from the metadata map (defaults to 0 for
5
+ * documents that predate the migration system), filters and sorts pending
6
+ * migrations, and executes them in a single `'migration'`-origin transaction.
7
+ *
8
+ * The `'migration'` origin is:
9
+ * - NOT tracked by the UndoManager (which only tracks `'local'` and `'temporary'`)
10
+ * - Distinguishable in observers so they can skip re-processing migration writes
11
+ *
12
+ * @param ydoc - The Y.Doc to migrate
13
+ * @param metadataMap - The metadata Y.Map that stores the schemaVersion
14
+ * @param maps - Named Y.Maps available for migration logic (e.g. `{ workspaces }` or `{ objects }`)
15
+ * @param migrations - The ordered array of migration definitions
16
+ * @param currentVersion - The target schema version defined in code
17
+ * @param options - Optional configuration (e.g. `{ quiet: true }` to suppress console logs)
18
+ * @returns A result object indicating whether migrations ran and the version range
19
+ */
20
+ export function runMigrations(ydoc, metadataMap, maps, migrations, currentVersion, options) {
21
+ const quiet = options?.quiet ?? true;
22
+ const docVersion = metadataMap.get('schemaVersion') ?? 0;
23
+ if (docVersion >= currentVersion) {
24
+ return { migrated: false, fromVersion: docVersion, toVersion: docVersion };
25
+ }
26
+ const pending = migrations
27
+ .filter(m => m.fromVersion >= docVersion && m.toVersion <= currentVersion)
28
+ .sort((a, b) => a.fromVersion - b.fromVersion);
29
+ if (!quiet) {
30
+ console.log(`[Kritzel] Running ${pending.length} migration(s) from v${docVersion} to v${currentVersion}`);
31
+ }
32
+ ydoc.transact(() => {
33
+ for (const migration of pending) {
34
+ if (!quiet) {
35
+ console.log(`[Kritzel] Migrating v${migration.fromVersion} → v${migration.toVersion}`);
36
+ }
37
+ migration.migrate(ydoc, maps);
38
+ }
39
+ metadataMap.set('schemaVersion', currentVersion);
40
+ }, 'migration');
41
+ if (!quiet) {
42
+ console.log(`[Kritzel] Migrations complete. Schema now at v${currentVersion}`);
43
+ }
44
+ return { migrated: true, fromVersion: docVersion, toVersion: currentVersion };
45
+ }