kritzel-stencil 0.3.16 → 0.3.17

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 (227) hide show
  1. package/LICENSE.md +50 -0
  2. package/dist/cjs/index-Xav9JFHg.js +2 -2
  3. package/dist/cjs/index.cjs.js +7 -1
  4. package/dist/cjs/{kritzel-active-users_42.cjs.entry.js → kritzel-active-users_44.cjs.entry.js} +710 -145
  5. package/dist/cjs/loader.cjs.js +1 -1
  6. package/dist/cjs/{schema.constants-DJQTjcy7.js → schema.constants-DrHO_CYF.js} +1169 -171
  7. package/dist/cjs/stencil.cjs.js +1 -1
  8. package/dist/collection/classes/core/core.class.js +24 -0
  9. package/dist/collection/classes/handlers/context-menu.handler.js +24 -2
  10. package/dist/collection/classes/managers/license.manager.js +285 -0
  11. package/dist/collection/classes/managers/localization.manager.js +189 -0
  12. package/dist/collection/classes/objects/custom-element.class.js +2 -0
  13. package/dist/collection/classes/objects/group.class.js +7 -2
  14. package/dist/collection/classes/objects/image.class.js +10 -7
  15. package/dist/collection/classes/objects/line.class.js +3 -0
  16. package/dist/collection/classes/objects/path.class.js +13 -12
  17. package/dist/collection/classes/objects/selection-group.class.js +7 -2
  18. package/dist/collection/classes/objects/shape.class.js +3 -0
  19. package/dist/collection/classes/objects/text.class.js +4 -1
  20. package/dist/collection/classes/registries/icon-registry.class.js +1 -0
  21. package/dist/collection/classes/tools/brush-tool.class.js +1 -1
  22. package/dist/collection/collection-manifest.json +3 -1
  23. package/dist/collection/components/core/kritzel-editor/kritzel-editor.css +16 -0
  24. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +462 -60
  25. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +446 -16
  26. package/dist/collection/components/core/kritzel-watermark/kritzel-watermark.css +29 -0
  27. package/dist/collection/components/core/kritzel-watermark/kritzel-watermark.js +83 -0
  28. package/dist/collection/components/shared/kritzel-avatar/kritzel-avatar.js +3 -3
  29. package/dist/collection/components/shared/kritzel-button/kritzel-button.js +2 -2
  30. package/dist/collection/components/shared/kritzel-color/kritzel-color.js +2 -2
  31. package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.js +1 -1
  32. package/dist/collection/components/shared/kritzel-font/kritzel-font.js +1 -1
  33. package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.js +2 -1
  34. package/dist/collection/components/shared/kritzel-input/kritzel-input.js +1 -1
  35. package/dist/collection/components/shared/kritzel-master-detail/kritzel-master-detail.js +3 -3
  36. package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js +1 -1
  37. package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.js +2 -2
  38. package/dist/collection/components/shared/kritzel-numeric-input/kritzel-numeric-input.js +1 -1
  39. package/dist/collection/components/shared/kritzel-opacity-slider/kritzel-opacity-slider.js +1 -1
  40. package/dist/collection/components/shared/kritzel-portal/kritzel-portal.js +1 -1
  41. package/dist/collection/components/shared/kritzel-slide-toggle/kritzel-slide-toggle.js +1 -1
  42. package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js +1 -1
  43. package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.js +2 -1
  44. package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.js +2 -2
  45. package/dist/collection/components/ui/kritzel-back-to-content/kritzel-back-to-content.js +1 -1
  46. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +41 -6
  47. package/dist/collection/components/ui/kritzel-current-user/kritzel-current-user.js +36 -1
  48. package/dist/collection/components/ui/kritzel-current-user-dialog/kritzel-current-user-dialog.js +36 -1
  49. package/dist/collection/components/ui/kritzel-export/kritzel-export.js +44 -7
  50. package/dist/collection/components/ui/kritzel-login-dialog/kritzel-login-dialog.js +1 -1
  51. package/dist/collection/components/ui/kritzel-more-menu/kritzel-more-menu.js +36 -1
  52. package/dist/collection/components/ui/kritzel-settings/kritzel-settings.js +108 -14
  53. package/dist/collection/components/ui/kritzel-share-dialog/kritzel-share-dialog.js +38 -3
  54. package/dist/collection/components/ui/kritzel-tool-config/kritzel-tool-config.js +38 -3
  55. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js +36 -1
  56. package/dist/collection/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.js +38 -3
  57. package/dist/collection/components/ui/kritzel-zoom-panel/kritzel-zoom-panel.css +72 -0
  58. package/dist/collection/components/ui/kritzel-zoom-panel/kritzel-zoom-panel.js +173 -0
  59. package/dist/collection/constants/engine.constants.js +2 -0
  60. package/dist/collection/constants/license.constants.js +25 -0
  61. package/dist/collection/constants/version.js +1 -1
  62. package/dist/collection/helpers/localization.helper.js +25 -0
  63. package/dist/collection/helpers/math.helper.js +3 -0
  64. package/dist/collection/helpers/svg-export.helper.js +223 -26
  65. package/dist/collection/index.js +13 -0
  66. package/dist/collection/interfaces/localization.interface.js +1 -0
  67. package/dist/collection/locales/de-locale.js +119 -0
  68. package/dist/collection/locales/en-locale.js +120 -0
  69. package/dist/collection/locales/fr-locale.js +119 -0
  70. package/dist/collection/themes/dark-theme.js +18 -0
  71. package/dist/collection/themes/light-theme.js +18 -0
  72. package/dist/components/index.d.ts +4 -0
  73. package/dist/components/index.js +1 -1
  74. package/dist/components/kritzel-active-users.js +1 -1
  75. package/dist/components/kritzel-avatar.js +1 -1
  76. package/dist/components/kritzel-awareness-cursors.js +1 -1
  77. package/dist/components/kritzel-back-to-content.js +1 -1
  78. package/dist/components/kritzel-brush-style.js +1 -1
  79. package/dist/components/kritzel-button.js +1 -1
  80. package/dist/components/kritzel-color-palette.js +1 -1
  81. package/dist/components/kritzel-color.js +1 -1
  82. package/dist/components/kritzel-context-menu.js +1 -1
  83. package/dist/components/kritzel-controls.js +1 -1
  84. package/dist/components/kritzel-current-user-dialog.js +1 -1
  85. package/dist/components/kritzel-current-user.js +1 -1
  86. package/dist/components/kritzel-editor.js +1 -1
  87. package/dist/components/kritzel-engine.js +1 -1
  88. package/dist/components/kritzel-export.js +1 -1
  89. package/dist/components/kritzel-font-size.js +1 -1
  90. package/dist/components/kritzel-font.js +1 -1
  91. package/dist/components/kritzel-icon.js +1 -1
  92. package/dist/components/kritzel-input.js +1 -1
  93. package/dist/components/kritzel-login-dialog.js +1 -1
  94. package/dist/components/kritzel-master-detail.js +1 -1
  95. package/dist/components/kritzel-menu-item.js +1 -1
  96. package/dist/components/kritzel-menu.js +1 -1
  97. package/dist/components/kritzel-more-menu.js +1 -1
  98. package/dist/components/kritzel-numeric-input.js +1 -1
  99. package/dist/components/kritzel-opacity-slider.js +1 -1
  100. package/dist/components/kritzel-pill-tabs.js +1 -1
  101. package/dist/components/kritzel-portal.js +1 -1
  102. package/dist/components/kritzel-settings.js +1 -1
  103. package/dist/components/kritzel-share-dialog.js +1 -1
  104. package/dist/components/kritzel-slide-toggle.js +1 -1
  105. package/dist/components/kritzel-split-button.js +1 -1
  106. package/dist/components/kritzel-stroke-size.js +1 -1
  107. package/dist/components/kritzel-tool-config.js +1 -1
  108. package/dist/components/kritzel-tooltip.js +1 -1
  109. package/dist/components/kritzel-utility-panel.js +1 -1
  110. package/dist/components/kritzel-watermark.d.ts +11 -0
  111. package/dist/components/kritzel-watermark.js +1 -0
  112. package/dist/components/kritzel-workspace-manager.js +1 -1
  113. package/dist/components/kritzel-zoom-panel.d.ts +11 -0
  114. package/dist/components/kritzel-zoom-panel.js +1 -0
  115. package/dist/components/{p-B5xxfwKF.js → p-3HxnBrCM.js} +1 -1
  116. package/dist/components/p-6RjeGuvH.js +1 -0
  117. package/dist/components/p-7NsK0uHu.js +1 -0
  118. package/dist/components/{p-dcAernE1.js → p-BCNyR5Sw.js} +1 -1
  119. package/dist/components/{p-C2SX-XRr.js → p-BG6hOSrm.js} +1 -1
  120. package/dist/components/p-BKJSh8qQ.js +1 -0
  121. package/dist/components/{p-SptaSMno.js → p-BKvHg9cv.js} +1 -1
  122. package/dist/components/p-Bc55X65h.js +1 -0
  123. package/dist/components/p-BpnIvNvq.js +1 -0
  124. package/dist/components/p-BvRrA4hN.js +1 -0
  125. package/dist/components/{p-B2w8X7vn.js → p-BxpKq94F.js} +1 -1
  126. package/dist/components/{p-BFoK4W--.js → p-Bzv9Px8v.js} +1 -1
  127. package/dist/components/{p-COLHjboZ.js → p-C9HGoDHE.js} +1 -1
  128. package/dist/components/p-CEnEDaix.js +1 -0
  129. package/dist/components/p-CIcLzcfA.js +1 -0
  130. package/dist/components/p-CPtDfadX.js +1 -0
  131. package/dist/components/p-C_fKgKHu.js +9 -0
  132. package/dist/components/p-CdR76C4L.js +1 -0
  133. package/dist/components/p-Cu9KYyoq.js +1 -0
  134. package/dist/components/p-CyqRcqsO.js +1 -0
  135. package/dist/components/{p-UoPj5QjH.js → p-DDkmsPpV.js} +1 -1
  136. package/dist/components/{p-D-sRVAbQ.js → p-DI4vQRE3.js} +1 -1
  137. package/dist/components/{p-CJOhfMU5.js → p-DNdXJp8F.js} +1 -1
  138. package/dist/components/p-DX5K8xnh.js +1 -0
  139. package/dist/components/{p-DEy7zJCe.js → p-DZdgXCAx.js} +1 -1
  140. package/dist/components/p-DdH1cKED.js +1 -0
  141. package/dist/components/p-DdsSSqFY.js +1 -0
  142. package/dist/components/p-DgmtCdnL.js +1 -0
  143. package/dist/components/{p-BzYU3-MJ.js → p-DmWSRsjK.js} +1 -1
  144. package/dist/components/{p-Bj2laX89.js → p-Dz-Ti24X.js} +1 -1
  145. package/dist/components/{p-BiG1dxPS.js → p-F5_X4dZG.js} +1 -1
  146. package/dist/components/{p-x6doYeiI.js → p-IpoC5EEY.js} +1 -1
  147. package/dist/components/p-Jn6TNdfe.js +1 -0
  148. package/dist/components/{p-BfNHpqQ8.js → p-NuLP1xHe.js} +1 -1
  149. package/dist/components/{p-skWUIStn.js → p-SDZNC8GF.js} +1 -1
  150. package/dist/components/{p-BYmp9Ovv.js → p-U4oawa1x.js} +1 -1
  151. package/dist/components/{p-DM11KXUT.js → p-f8aW1ye7.js} +1 -1
  152. package/dist/components/p-v7dxxrL5.js +1 -0
  153. package/dist/components/p-vAeiXe6c.js +1 -0
  154. package/dist/esm/index-Dhio9uis.js +2 -2
  155. package/dist/esm/index.js +2 -2
  156. package/dist/esm/{kritzel-active-users_42.entry.js → kritzel-active-users_44.entry.js} +709 -146
  157. package/dist/esm/loader.js +1 -1
  158. package/dist/esm/{schema.constants-DiCnmIYK.js → schema.constants-DchTXG3V.js} +1163 -172
  159. package/dist/esm/stencil.js +1 -1
  160. package/dist/stencil/index.esm.js +1 -1
  161. package/dist/stencil/p-DchTXG3V.js +1 -0
  162. package/dist/stencil/p-c9a3807b.entry.js +9 -0
  163. package/dist/stencil/stencil.esm.js +1 -1
  164. package/dist/types/classes/core/core.class.d.ts +16 -0
  165. package/dist/types/classes/handlers/context-menu.handler.d.ts +13 -0
  166. package/dist/types/classes/managers/license.manager.d.ts +141 -0
  167. package/dist/types/classes/managers/localization.manager.d.ts +121 -0
  168. package/dist/types/classes/objects/custom-element.class.d.ts +2 -0
  169. package/dist/types/classes/objects/group.class.d.ts +6 -1
  170. package/dist/types/classes/objects/image.class.d.ts +1 -1
  171. package/dist/types/classes/objects/path.class.d.ts +3 -2
  172. package/dist/types/classes/objects/selection-group.class.d.ts +6 -1
  173. package/dist/types/classes/objects/shape.class.d.ts +2 -0
  174. package/dist/types/classes/objects/text.class.d.ts +2 -1
  175. package/dist/types/classes/tools/brush-tool.class.d.ts +1 -1
  176. package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +53 -1
  177. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +55 -3
  178. package/dist/types/components/core/kritzel-watermark/kritzel-watermark.d.ts +20 -0
  179. package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +3 -0
  180. package/dist/types/components/ui/kritzel-current-user/kritzel-current-user.d.ts +3 -0
  181. package/dist/types/components/ui/kritzel-current-user-dialog/kritzel-current-user-dialog.d.ts +3 -0
  182. package/dist/types/components/ui/kritzel-export/kritzel-export.d.ts +4 -1
  183. package/dist/types/components/ui/kritzel-more-menu/kritzel-more-menu.d.ts +3 -0
  184. package/dist/types/components/ui/kritzel-settings/kritzel-settings.d.ts +16 -0
  185. package/dist/types/components/ui/kritzel-share-dialog/kritzel-share-dialog.d.ts +3 -0
  186. package/dist/types/components/ui/kritzel-tool-config/kritzel-tool-config.d.ts +3 -0
  187. package/dist/types/components/ui/kritzel-utility-panel/kritzel-utility-panel.d.ts +3 -0
  188. package/dist/types/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.d.ts +3 -0
  189. package/dist/types/components/ui/kritzel-zoom-panel/kritzel-zoom-panel.d.ts +20 -0
  190. package/dist/types/components.d.ts +445 -26
  191. package/dist/types/constants/engine.constants.d.ts +2 -0
  192. package/dist/types/constants/license.constants.d.ts +25 -0
  193. package/dist/types/constants/version.d.ts +1 -1
  194. package/dist/types/helpers/localization.helper.d.ts +18 -0
  195. package/dist/types/helpers/math.helper.d.ts +1 -0
  196. package/dist/types/helpers/svg-export.helper.d.ts +81 -7
  197. package/dist/types/index.d.ts +13 -0
  198. package/dist/types/interfaces/context-menu-item.interface.d.ts +7 -1
  199. package/dist/types/interfaces/line-options.interface.d.ts +2 -0
  200. package/dist/types/interfaces/localization.interface.d.ts +143 -0
  201. package/dist/types/interfaces/path-options.interface.d.ts +2 -0
  202. package/dist/types/interfaces/settings.interface.d.ts +3 -0
  203. package/dist/types/interfaces/theme.interface.d.ts +27 -2
  204. package/dist/types/locales/de-locale.d.ts +5 -0
  205. package/dist/types/locales/en-locale.d.ts +6 -0
  206. package/dist/types/locales/fr-locale.d.ts +5 -0
  207. package/package.json +4 -7
  208. package/dist/components/p-2xYAGd0I.js +0 -1
  209. package/dist/components/p-B2Os1ya_.js +0 -1
  210. package/dist/components/p-BTEV1WwT.js +0 -1
  211. package/dist/components/p-BbactVA0.js +0 -1
  212. package/dist/components/p-BqwqGFQY.js +0 -1
  213. package/dist/components/p-C0TN5IAi.js +0 -1
  214. package/dist/components/p-CFgkUYoO.js +0 -1
  215. package/dist/components/p-COgo9OWy.js +0 -1
  216. package/dist/components/p-CUPYGT8c.js +0 -1
  217. package/dist/components/p-CcyIAi9S.js +0 -1
  218. package/dist/components/p-Cj78L1Kk.js +0 -1
  219. package/dist/components/p-CkAVEdDw.js +0 -9
  220. package/dist/components/p-CmuNn1Tc.js +0 -1
  221. package/dist/components/p-DDYoDSrm.js +0 -1
  222. package/dist/components/p-DbB730vO.js +0 -1
  223. package/dist/components/p-DlwYHzSj.js +0 -1
  224. package/dist/components/p-FK7b3BGt.js +0 -1
  225. package/dist/components/p-J9_SwObO.js +0 -1
  226. package/dist/stencil/p-67775031.entry.js +0 -9
  227. package/dist/stencil/p-DiCnmIYK.js +0 -1
@@ -149,6 +149,11 @@ export class KritzelEngine {
149
149
  onThemeChange(newValue) {
150
150
  this.core.themeManager.setTheme(newValue);
151
151
  }
152
+ /** License key that, when valid, removes the "Powered by Kritzel" watermark. */
153
+ licenseKey;
154
+ onLicenseKeyChange(newValue) {
155
+ this.core.licenseManager.validate(newValue);
156
+ }
152
157
  /** An array of available themes for the editor. */
153
158
  themes;
154
159
  onThemesChange(newValue) {
@@ -157,6 +162,25 @@ export class KritzelEngine {
157
162
  this.core.themeManager.applyTheme(this.core.themeManager.currentTheme);
158
163
  }
159
164
  }
165
+ /** The current locale (language) code to apply to the editor, e.g. 'en', 'de', 'fr'. */
166
+ locale = 'en';
167
+ onLocaleChange(newValue) {
168
+ this.core.localizationManager.setLocale(newValue);
169
+ }
170
+ /** An array of available locale definitions (with optional partial term overrides). */
171
+ locales;
172
+ onLocalesChange(newValue) {
173
+ if (newValue && newValue.length > 0) {
174
+ this.core.localizationManager.registerLocales(newValue);
175
+ this.core.localizationManager.setLocale(this.locale);
176
+ }
177
+ }
178
+ /** The locale used to resolve terms missing from the active locale. */
179
+ fallbackLocale = 'en';
180
+ onFallbackLocaleChange(newValue) {
181
+ this.core.localizationManager.setFallbackLocale(newValue);
182
+ this.core.rerender();
183
+ }
160
184
  /** Left boundary of the viewport in world coordinates. Objects beyond this X position cannot be panned to. */
161
185
  viewportBoundaryLeft = -Infinity;
162
186
  onViewportBoundaryLeftChange(newValue) {
@@ -184,8 +208,10 @@ export class KritzelEngine {
184
208
  this.core.store.state.debugInfo = newValue;
185
209
  }
186
210
  }
187
- /** When false, wheel events will not trigger viewport pan/zoom. The event still propagates to parent elements. */
188
- wheelEnabled = true;
211
+ /** When false, non-modified wheel events do not pan the viewport. */
212
+ isPanningEnabled = true;
213
+ /** When false, Ctrl+wheel events do not zoom the viewport. */
214
+ isZoomingEnabled = true;
189
215
  /** External loading state. Combined with internal workspace-loading state to drive the overlay. */
190
216
  isLoading = false;
191
217
  onIsLoadingChange() {
@@ -228,13 +254,19 @@ export class KritzelEngine {
228
254
  if (this.core.store.isDisabled) {
229
255
  return;
230
256
  }
231
- if (!this.wheelEnabled) {
232
- return;
233
- }
234
257
  if (this.core.store.state.isContextMenuVisible) {
235
258
  this.hideContextMenu();
236
259
  }
237
- this.viewport.handleWheel(ev);
260
+ if (ev.ctrlKey) {
261
+ if (this.isZoomingEnabled) {
262
+ this.viewport.handleWheel(ev);
263
+ }
264
+ }
265
+ else {
266
+ if (this.isPanningEnabled) {
267
+ this.viewport.handleWheel(ev);
268
+ }
269
+ }
238
270
  this.core.store.state?.activeTool?.handleWheel(ev);
239
271
  }
240
272
  handlePointerDown(ev) {
@@ -1070,7 +1102,7 @@ export class KritzelEngine {
1070
1102
  /**
1071
1103
  * Generates an SVG string from the currently selected objects.
1072
1104
  * Creates clean, standards-compliant SVG markup by directly serializing object properties.
1073
- * @param options - Optional export settings (theme, padding).
1105
+ * @param options - Optional export settings (theme, padding, raster-safe mode for canvas export).
1074
1106
  * @returns SVG markup string, or null if no objects are selected.
1075
1107
  */
1076
1108
  async getSelectedObjectsAsSvgString(options) {
@@ -1079,10 +1111,16 @@ export class KritzelEngine {
1079
1111
  return null;
1080
1112
  }
1081
1113
  const theme = options?.theme ?? this.core.themeManager.getStoredTheme();
1114
+ // Inline image bytes as data URLs so they survive both standalone SVG
1115
+ // files and rasterization to PNG (a `blob:` href is not loaded when an
1116
+ // SVG is drawn into a canvas, which otherwise yields a broken image).
1117
+ const imageDataUrls = await KritzelSvgExportHelper.resolveImageDataUrls(selectedObjects, this.core.assetResolver);
1082
1118
  return KritzelSvgExportHelper.generateSvg(selectedObjects, {
1083
1119
  theme,
1084
1120
  padding: options?.padding ?? 0,
1085
1121
  includeXmlDeclaration: true,
1122
+ rasterSafeForCanvas: options?.rasterSafeForCanvas ?? false,
1123
+ imageDataUrls,
1086
1124
  });
1087
1125
  }
1088
1126
  /**
@@ -1121,6 +1159,9 @@ export class KritzelEngine {
1121
1159
  const svgString = await this.getSelectedObjectsAsSvgString({
1122
1160
  theme: options?.theme,
1123
1161
  padding: options?.padding,
1162
+ // Avoid foreignObject-based text serialization, which taints the
1163
+ // canvas in SVG->PNG conversion paths.
1164
+ rasterSafeForCanvas: true,
1124
1165
  });
1125
1166
  if (!svgString) {
1126
1167
  return null;
@@ -1473,6 +1514,55 @@ export class KritzelEngine {
1473
1514
  return null;
1474
1515
  }
1475
1516
  }
1517
+ /**
1518
+ * Registers additional locale definitions (with optional partial term overrides).
1519
+ * @param locales - The locale definitions to register.
1520
+ */
1521
+ async registerLocales(locales) {
1522
+ this.core.localizationManager.registerLocales(locales);
1523
+ this.core.localizationManager.setLocale(this.core.localizationManager.currentLocale);
1524
+ }
1525
+ /**
1526
+ * Sets the active locale (language) and re-renders the UI.
1527
+ * @param code - The locale code to activate, e.g. 'de'.
1528
+ */
1529
+ async setLocale(code) {
1530
+ this.locale = code;
1531
+ this.core.localizationManager.setLocale(code);
1532
+ }
1533
+ /**
1534
+ * Gets the currently active locale code.
1535
+ */
1536
+ async getLocale() {
1537
+ return this.core.localizationManager.currentLocale;
1538
+ }
1539
+ /**
1540
+ * Gets the list of available locale codes (built-in and registered).
1541
+ */
1542
+ async getAvailableLocales() {
1543
+ return this.core.localizationManager.getAvailableLocales();
1544
+ }
1545
+ /**
1546
+ * Gets the list of available locales as `{ code, label }` options for a selector.
1547
+ */
1548
+ async getAvailableLocaleOptions() {
1549
+ return this.core.localizationManager.getAvailableLocaleOptions();
1550
+ }
1551
+ /**
1552
+ * Resolves a term key to its translated string for the active locale.
1553
+ * @param key - The term key to resolve.
1554
+ * @param vars - Optional values for `{placeholder}` interpolation.
1555
+ */
1556
+ async t(key, vars) {
1557
+ return this.core.localizationManager.translate(key, vars);
1558
+ }
1559
+ /**
1560
+ * Resolves every known term key for the active locale into a flat map.
1561
+ * Useful for UI layers that need to localize many strings at once.
1562
+ */
1563
+ async getResolvedTerms() {
1564
+ return this.core.localizationManager.getAllTerms();
1565
+ }
1476
1566
  core;
1477
1567
  viewport;
1478
1568
  contextMenuHandler;
@@ -1548,6 +1638,7 @@ export class KritzelEngine {
1548
1638
  // Clean up managers
1549
1639
  this.core.cursorManager.cleanup();
1550
1640
  this.core.themeManager.cleanup();
1641
+ this.core.licenseManager.destroy();
1551
1642
  }
1552
1643
  componentWillLoad() {
1553
1644
  this.core.setEditorId(this.editorId);
@@ -1556,6 +1647,13 @@ export class KritzelEngine {
1556
1647
  }
1557
1648
  const editorElement = this.host.closest('kritzel-editor');
1558
1649
  this.core.themeManager.injectThemeEarly(editorElement || this.host);
1650
+ if (this.locales && this.locales.length > 0) {
1651
+ this.core.localizationManager.registerLocales(this.locales);
1652
+ }
1653
+ this.core.localizationManager.setFallbackLocale(this.fallbackLocale);
1654
+ this.core.localizationManager.setLocale(this.locale);
1655
+ this.core.licenseManager.validate(this.licenseKey);
1656
+ this.core.licenseManager.startPeriodicValidation();
1559
1657
  this.core.setUser(this.user);
1560
1658
  this.validateScaleMax(this.scaleMax);
1561
1659
  this.validateScaleMin(this.scaleMin);
@@ -1860,7 +1958,7 @@ export class KritzelEngine {
1860
1958
  }
1861
1959
  render() {
1862
1960
  if (!this.viewport) {
1863
- return (h(Host, null, this.core.store.state.isLoading && (h("div", { class: "workspace-loading-overlay" }, h("span", { class: "workspace-loading-spinner" }), "Loading..."))));
1961
+ return (h(Host, null, this.core.store.state.isLoading && (h("div", { class: "workspace-loading-overlay" }, h("span", { class: "workspace-loading-spinner" }), this.core.localizationManager.translate('engine.loading')))));
1864
1962
  }
1865
1963
  const currentTheme = this.core.themeManager.getStoredTheme();
1866
1964
  const computedStyle = window.getComputedStyle(this.host);
@@ -2298,7 +2396,7 @@ export class KritzelEngine {
2298
2396
  }, this.core.store.selectionGroup?.objects || []);
2299
2397
  }
2300
2398
  this.hideContextMenu();
2301
- }, onClose: () => this.hideContextMenu() })), this.core.store.objects?.hasAwareness && h("kritzel-awareness-cursors", { core: this.core }), this.core.store.state?.activeTool instanceof KritzelEraserTool && !this.core.store.state.isScaling && h("kritzel-cursor-trail", { core: this.core })));
2399
+ }, onClose: () => this.hideContextMenu() })), this.core.store.objects?.hasAwareness && h("kritzel-awareness-cursors", { core: this.core }), this.core.store.state?.activeTool instanceof KritzelEraserTool && !this.core.store.state.isScaling && h("kritzel-cursor-trail", { core: this.core }), !this.core.licenseManager.isLicensed && (h("kritzel-watermark", { core: this.core, label: this.core.localizationManager.translate('watermark.poweredBy') }))));
2302
2400
  }
2303
2401
  static get is() { return "kritzel-engine"; }
2304
2402
  static get encapsulation() { return "shadow"; }
@@ -2625,6 +2723,25 @@ export class KritzelEngine {
2625
2723
  "attribute": "theme",
2626
2724
  "defaultValue": "'light'"
2627
2725
  },
2726
+ "licenseKey": {
2727
+ "type": "string",
2728
+ "mutable": false,
2729
+ "complexType": {
2730
+ "original": "string",
2731
+ "resolved": "string",
2732
+ "references": {}
2733
+ },
2734
+ "required": false,
2735
+ "optional": true,
2736
+ "docs": {
2737
+ "tags": [],
2738
+ "text": "License key that, when valid, removes the \"Powered by Kritzel\" watermark."
2739
+ },
2740
+ "getter": false,
2741
+ "setter": false,
2742
+ "reflect": false,
2743
+ "attribute": "license-key"
2744
+ },
2628
2745
  "themes": {
2629
2746
  "type": "unknown",
2630
2747
  "mutable": false,
@@ -2649,6 +2766,84 @@ export class KritzelEngine {
2649
2766
  "getter": false,
2650
2767
  "setter": false
2651
2768
  },
2769
+ "locale": {
2770
+ "type": "string",
2771
+ "mutable": false,
2772
+ "complexType": {
2773
+ "original": "LocaleCode",
2774
+ "resolved": "\"de\" | \"en\" | \"fr\" | string & {}",
2775
+ "references": {
2776
+ "LocaleCode": {
2777
+ "location": "import",
2778
+ "path": "../../../interfaces/localization.interface",
2779
+ "id": "src/interfaces/localization.interface.ts::LocaleCode",
2780
+ "referenceLocation": "LocaleCode"
2781
+ }
2782
+ }
2783
+ },
2784
+ "required": false,
2785
+ "optional": false,
2786
+ "docs": {
2787
+ "tags": [],
2788
+ "text": "The current locale (language) code to apply to the editor, e.g. 'en', 'de', 'fr'."
2789
+ },
2790
+ "getter": false,
2791
+ "setter": false,
2792
+ "reflect": false,
2793
+ "attribute": "locale",
2794
+ "defaultValue": "'en'"
2795
+ },
2796
+ "locales": {
2797
+ "type": "unknown",
2798
+ "mutable": false,
2799
+ "complexType": {
2800
+ "original": "KritzelLocale[]",
2801
+ "resolved": "KritzelLocale[]",
2802
+ "references": {
2803
+ "KritzelLocale": {
2804
+ "location": "import",
2805
+ "path": "../../../interfaces/localization.interface",
2806
+ "id": "src/interfaces/localization.interface.ts::KritzelLocale",
2807
+ "referenceLocation": "KritzelLocale"
2808
+ }
2809
+ }
2810
+ },
2811
+ "required": false,
2812
+ "optional": true,
2813
+ "docs": {
2814
+ "tags": [],
2815
+ "text": "An array of available locale definitions (with optional partial term overrides)."
2816
+ },
2817
+ "getter": false,
2818
+ "setter": false
2819
+ },
2820
+ "fallbackLocale": {
2821
+ "type": "string",
2822
+ "mutable": false,
2823
+ "complexType": {
2824
+ "original": "LocaleCode",
2825
+ "resolved": "\"de\" | \"en\" | \"fr\" | string & {}",
2826
+ "references": {
2827
+ "LocaleCode": {
2828
+ "location": "import",
2829
+ "path": "../../../interfaces/localization.interface",
2830
+ "id": "src/interfaces/localization.interface.ts::LocaleCode",
2831
+ "referenceLocation": "LocaleCode"
2832
+ }
2833
+ }
2834
+ },
2835
+ "required": false,
2836
+ "optional": false,
2837
+ "docs": {
2838
+ "tags": [],
2839
+ "text": "The locale used to resolve terms missing from the active locale."
2840
+ },
2841
+ "getter": false,
2842
+ "setter": false,
2843
+ "reflect": false,
2844
+ "attribute": "fallback-locale",
2845
+ "defaultValue": "'en'"
2846
+ },
2652
2847
  "viewportBoundaryLeft": {
2653
2848
  "type": "number",
2654
2849
  "mutable": false,
@@ -2753,7 +2948,27 @@ export class KritzelEngine {
2753
2948
  "getter": false,
2754
2949
  "setter": false
2755
2950
  },
2756
- "wheelEnabled": {
2951
+ "isPanningEnabled": {
2952
+ "type": "boolean",
2953
+ "mutable": false,
2954
+ "complexType": {
2955
+ "original": "boolean",
2956
+ "resolved": "boolean",
2957
+ "references": {}
2958
+ },
2959
+ "required": false,
2960
+ "optional": false,
2961
+ "docs": {
2962
+ "tags": [],
2963
+ "text": "When false, non-modified wheel events do not pan the viewport."
2964
+ },
2965
+ "getter": false,
2966
+ "setter": false,
2967
+ "reflect": false,
2968
+ "attribute": "is-panning-enabled",
2969
+ "defaultValue": "true"
2970
+ },
2971
+ "isZoomingEnabled": {
2757
2972
  "type": "boolean",
2758
2973
  "mutable": false,
2759
2974
  "complexType": {
@@ -2765,12 +2980,12 @@ export class KritzelEngine {
2765
2980
  "optional": false,
2766
2981
  "docs": {
2767
2982
  "tags": [],
2768
- "text": "When false, wheel events will not trigger viewport pan/zoom. The event still propagates to parent elements."
2983
+ "text": "When false, Ctrl+wheel events do not zoom the viewport."
2769
2984
  },
2770
2985
  "getter": false,
2771
2986
  "setter": false,
2772
2987
  "reflect": false,
2773
- "attribute": "wheel-enabled",
2988
+ "attribute": "is-zooming-enabled",
2774
2989
  "defaultValue": "true"
2775
2990
  },
2776
2991
  "isLoading": {
@@ -4698,11 +4913,11 @@ export class KritzelEngine {
4698
4913
  },
4699
4914
  "getSelectedObjectsAsSvgString": {
4700
4915
  "complexType": {
4701
- "signature": "(options?: { theme?: \"light\" | \"dark\"; padding?: number; }) => Promise<string | null>",
4916
+ "signature": "(options?: { theme?: \"light\" | \"dark\"; padding?: number; rasterSafeForCanvas?: boolean; }) => Promise<string | null>",
4702
4917
  "parameters": [{
4703
4918
  "name": "options",
4704
- "type": "{ theme?: \"light\" | \"dark\"; padding?: number; }",
4705
- "docs": "- Optional export settings (theme, padding)."
4919
+ "type": "{ theme?: \"light\" | \"dark\"; padding?: number; rasterSafeForCanvas?: boolean; }",
4920
+ "docs": "- Optional export settings (theme, padding, raster-safe mode for canvas export)."
4706
4921
  }],
4707
4922
  "references": {
4708
4923
  "Promise": {
@@ -4716,7 +4931,7 @@ export class KritzelEngine {
4716
4931
  "text": "Generates an SVG string from the currently selected objects.\nCreates clean, standards-compliant SVG markup by directly serializing object properties.",
4717
4932
  "tags": [{
4718
4933
  "name": "param",
4719
- "text": "options - Optional export settings (theme, padding)."
4934
+ "text": "options - Optional export settings (theme, padding, raster-safe mode for canvas export)."
4720
4935
  }, {
4721
4936
  "name": "returns",
4722
4937
  "text": "SVG markup string, or null if no objects are selected."
@@ -5200,6 +5415,209 @@ export class KritzelEngine {
5200
5415
  "text": "The stored settings, or null if nothing is stored or the value is invalid."
5201
5416
  }]
5202
5417
  }
5418
+ },
5419
+ "registerLocales": {
5420
+ "complexType": {
5421
+ "signature": "(locales: KritzelLocale[]) => Promise<void>",
5422
+ "parameters": [{
5423
+ "name": "locales",
5424
+ "type": "KritzelLocale[]",
5425
+ "docs": "- The locale definitions to register."
5426
+ }],
5427
+ "references": {
5428
+ "Promise": {
5429
+ "location": "global",
5430
+ "id": "global::Promise"
5431
+ },
5432
+ "KritzelLocale": {
5433
+ "location": "import",
5434
+ "path": "../../../interfaces/localization.interface",
5435
+ "id": "src/interfaces/localization.interface.ts::KritzelLocale",
5436
+ "referenceLocation": "KritzelLocale"
5437
+ }
5438
+ },
5439
+ "return": "Promise<void>"
5440
+ },
5441
+ "docs": {
5442
+ "text": "Registers additional locale definitions (with optional partial term overrides).",
5443
+ "tags": [{
5444
+ "name": "param",
5445
+ "text": "locales - The locale definitions to register."
5446
+ }]
5447
+ }
5448
+ },
5449
+ "setLocale": {
5450
+ "complexType": {
5451
+ "signature": "(code: LocaleCode) => Promise<void>",
5452
+ "parameters": [{
5453
+ "name": "code",
5454
+ "type": "(string & {}) | \"en\" | \"de\" | \"fr\"",
5455
+ "docs": "- The locale code to activate, e.g. 'de'."
5456
+ }],
5457
+ "references": {
5458
+ "Promise": {
5459
+ "location": "global",
5460
+ "id": "global::Promise"
5461
+ },
5462
+ "LocaleCode": {
5463
+ "location": "import",
5464
+ "path": "../../../interfaces/localization.interface",
5465
+ "id": "src/interfaces/localization.interface.ts::LocaleCode",
5466
+ "referenceLocation": "LocaleCode"
5467
+ }
5468
+ },
5469
+ "return": "Promise<void>"
5470
+ },
5471
+ "docs": {
5472
+ "text": "Sets the active locale (language) and re-renders the UI.",
5473
+ "tags": [{
5474
+ "name": "param",
5475
+ "text": "code - The locale code to activate, e.g. 'de'."
5476
+ }]
5477
+ }
5478
+ },
5479
+ "getLocale": {
5480
+ "complexType": {
5481
+ "signature": "() => Promise<LocaleCode>",
5482
+ "parameters": [],
5483
+ "references": {
5484
+ "Promise": {
5485
+ "location": "global",
5486
+ "id": "global::Promise"
5487
+ },
5488
+ "LocaleCode": {
5489
+ "location": "import",
5490
+ "path": "../../../interfaces/localization.interface",
5491
+ "id": "src/interfaces/localization.interface.ts::LocaleCode",
5492
+ "referenceLocation": "LocaleCode"
5493
+ }
5494
+ },
5495
+ "return": "Promise<LocaleCode>"
5496
+ },
5497
+ "docs": {
5498
+ "text": "Gets the currently active locale code.",
5499
+ "tags": []
5500
+ }
5501
+ },
5502
+ "getAvailableLocales": {
5503
+ "complexType": {
5504
+ "signature": "() => Promise<LocaleCode[]>",
5505
+ "parameters": [],
5506
+ "references": {
5507
+ "Promise": {
5508
+ "location": "global",
5509
+ "id": "global::Promise"
5510
+ },
5511
+ "LocaleCode": {
5512
+ "location": "import",
5513
+ "path": "../../../interfaces/localization.interface",
5514
+ "id": "src/interfaces/localization.interface.ts::LocaleCode",
5515
+ "referenceLocation": "LocaleCode"
5516
+ }
5517
+ },
5518
+ "return": "Promise<LocaleCode[]>"
5519
+ },
5520
+ "docs": {
5521
+ "text": "Gets the list of available locale codes (built-in and registered).",
5522
+ "tags": []
5523
+ }
5524
+ },
5525
+ "getAvailableLocaleOptions": {
5526
+ "complexType": {
5527
+ "signature": "() => Promise<{ code: LocaleCode; label: string; }[]>",
5528
+ "parameters": [],
5529
+ "references": {
5530
+ "Promise": {
5531
+ "location": "global",
5532
+ "id": "global::Promise"
5533
+ },
5534
+ "LocaleCode": {
5535
+ "location": "import",
5536
+ "path": "../../../interfaces/localization.interface",
5537
+ "id": "src/interfaces/localization.interface.ts::LocaleCode",
5538
+ "referenceLocation": "LocaleCode"
5539
+ }
5540
+ },
5541
+ "return": "Promise<{ code: LocaleCode; label: string; }[]>"
5542
+ },
5543
+ "docs": {
5544
+ "text": "Gets the list of available locales as `{ code, label }` options for a selector.",
5545
+ "tags": []
5546
+ }
5547
+ },
5548
+ "t": {
5549
+ "complexType": {
5550
+ "signature": "(key: KritzelTermKey, vars?: KritzelTermVars) => Promise<string>",
5551
+ "parameters": [{
5552
+ "name": "key",
5553
+ "type": "keyof KritzelTerms",
5554
+ "docs": "- The term key to resolve."
5555
+ }, {
5556
+ "name": "vars",
5557
+ "type": "{ [x: string]: string | number; }",
5558
+ "docs": "- Optional values for `{placeholder}` interpolation."
5559
+ }],
5560
+ "references": {
5561
+ "Promise": {
5562
+ "location": "global",
5563
+ "id": "global::Promise"
5564
+ },
5565
+ "KritzelTermKey": {
5566
+ "location": "import",
5567
+ "path": "../../../interfaces/localization.interface",
5568
+ "id": "src/interfaces/localization.interface.ts::KritzelTermKey",
5569
+ "referenceLocation": "KritzelTermKey"
5570
+ },
5571
+ "KritzelTermVars": {
5572
+ "location": "import",
5573
+ "path": "../../../interfaces/localization.interface",
5574
+ "id": "src/interfaces/localization.interface.ts::KritzelTermVars",
5575
+ "referenceLocation": "KritzelTermVars"
5576
+ }
5577
+ },
5578
+ "return": "Promise<string>"
5579
+ },
5580
+ "docs": {
5581
+ "text": "Resolves a term key to its translated string for the active locale.",
5582
+ "tags": [{
5583
+ "name": "param",
5584
+ "text": "key - The term key to resolve."
5585
+ }, {
5586
+ "name": "param",
5587
+ "text": "vars - Optional values for `{placeholder}` interpolation."
5588
+ }]
5589
+ }
5590
+ },
5591
+ "getResolvedTerms": {
5592
+ "complexType": {
5593
+ "signature": "() => Promise<Partial<Record<KritzelTermKey, string>>>",
5594
+ "parameters": [],
5595
+ "references": {
5596
+ "Promise": {
5597
+ "location": "global",
5598
+ "id": "global::Promise"
5599
+ },
5600
+ "Partial": {
5601
+ "location": "global",
5602
+ "id": "global::Partial"
5603
+ },
5604
+ "Record": {
5605
+ "location": "global",
5606
+ "id": "global::Record"
5607
+ },
5608
+ "KritzelTermKey": {
5609
+ "location": "import",
5610
+ "path": "../../../interfaces/localization.interface",
5611
+ "id": "src/interfaces/localization.interface.ts::KritzelTermKey",
5612
+ "referenceLocation": "KritzelTermKey"
5613
+ }
5614
+ },
5615
+ "return": "Promise<Partial<Record<keyof KritzelTerms, string>>>"
5616
+ },
5617
+ "docs": {
5618
+ "text": "Resolves every known term key for the active locale into a flat map.\nUseful for UI layers that need to localize many strings at once.",
5619
+ "tags": []
5620
+ }
5203
5621
  }
5204
5622
  };
5205
5623
  }
@@ -5244,9 +5662,21 @@ export class KritzelEngine {
5244
5662
  }, {
5245
5663
  "propName": "theme",
5246
5664
  "methodName": "onThemeChange"
5665
+ }, {
5666
+ "propName": "licenseKey",
5667
+ "methodName": "onLicenseKeyChange"
5247
5668
  }, {
5248
5669
  "propName": "themes",
5249
5670
  "methodName": "onThemesChange"
5671
+ }, {
5672
+ "propName": "locale",
5673
+ "methodName": "onLocaleChange"
5674
+ }, {
5675
+ "propName": "locales",
5676
+ "methodName": "onLocalesChange"
5677
+ }, {
5678
+ "propName": "fallbackLocale",
5679
+ "methodName": "onFallbackLocaleChange"
5250
5680
  }, {
5251
5681
  "propName": "viewportBoundaryLeft",
5252
5682
  "methodName": "onViewportBoundaryLeftChange"
@@ -0,0 +1,29 @@
1
+ :host {
2
+ position: absolute;
3
+ bottom: var(--kritzel-watermark-offset-bottom, 12px);
4
+ right: var(--kritzel-watermark-offset-right, 12px);
5
+ z-index: 10000;
6
+ pointer-events: none;
7
+ }
8
+
9
+ .watermark-link {
10
+ pointer-events: auto;
11
+ display: inline-flex;
12
+ align-items: center;
13
+ padding: 4px 8px;
14
+ border-radius: var(--kritzel-watermark-border-radius, 6px);
15
+ font-family: var(--kritzel-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
16
+ font-size: var(--kritzel-watermark-font-size, 11px);
17
+ line-height: 1;
18
+ text-decoration: none;
19
+ color: var(--kritzel-watermark-color, rgba(60, 60, 60, 0.75));
20
+ background-color: var(--kritzel-watermark-background, rgba(255, 255, 255, 0.6));
21
+ box-shadow: var(--kritzel-watermark-box-shadow, 0 1px 2px rgba(0, 0, 0, 0.12));
22
+ opacity: var(--kritzel-watermark-opacity, 0.85);
23
+ transition: opacity 150ms ease;
24
+ user-select: none;
25
+ }
26
+
27
+ .watermark-link:hover {
28
+ opacity: 1;
29
+ }