kritzel-stencil 0.4.0 → 0.4.2

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 (86) hide show
  1. package/dist/cjs/index.cjs.js +2 -1
  2. package/dist/cjs/kritzel-active-users_47.cjs.entry.js +365 -80
  3. package/dist/cjs/loader.cjs.js +1 -1
  4. package/dist/cjs/{schema.constants-fuAsi56H.js → schema.constants-C8hqt--r.js} +274 -33
  5. package/dist/cjs/stencil.cjs.js +1 -1
  6. package/dist/collection/classes/core/workspace.class.js +1 -1
  7. package/dist/collection/classes/handlers/context-menu.handler.js +2 -3
  8. package/dist/collection/classes/managers/clipboard.manager.js +9 -3
  9. package/dist/collection/classes/objects/base-object.class.js +0 -1
  10. package/dist/collection/classes/objects/text.class.js +2 -1
  11. package/dist/collection/classes/registries/font-registry.class.js +161 -0
  12. package/dist/collection/classes/structures/object-map.structure.js +9 -0
  13. package/dist/collection/classes/tools/image-tool.class.js +19 -3
  14. package/dist/collection/classes/tools/text-tool.class.js +2 -0
  15. package/dist/collection/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.js +22 -7
  16. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +138 -9
  17. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +186 -25
  18. package/dist/collection/components/shared/kritzel-font-family/kritzel-font-family.js +31 -22
  19. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +10 -11
  20. package/dist/collection/components/ui/kritzel-tool-config/kritzel-tool-config.js +40 -5
  21. package/dist/collection/configs/default-text-tool.config.js +2 -0
  22. package/dist/collection/constants/text-tool-fonts.constants.js +18 -0
  23. package/dist/collection/constants/version.js +1 -1
  24. package/dist/collection/helpers/image-file.helper.js +6 -0
  25. package/dist/collection/index.js +2 -0
  26. package/dist/collection/interfaces/font.interface.js +1 -0
  27. package/dist/components/index.js +1 -1
  28. package/dist/components/kritzel-awareness-cursors.js +1 -1
  29. package/dist/components/kritzel-controls.js +1 -1
  30. package/dist/components/kritzel-cursor-trail.js +1 -1
  31. package/dist/components/kritzel-editor.js +1 -1
  32. package/dist/components/kritzel-engine.js +1 -1
  33. package/dist/components/kritzel-font-family.js +1 -1
  34. package/dist/components/kritzel-settings.js +1 -1
  35. package/dist/components/kritzel-tool-config.js +1 -1
  36. package/dist/components/kritzel-workspace-manager.js +1 -1
  37. package/dist/components/p--Oazz-BP.js +9 -0
  38. package/dist/components/p-C38P-Vd0.js +1 -0
  39. package/dist/components/{p-zhjb97WN.js → p-C3UQ-Zrg.js} +1 -1
  40. package/dist/components/{p-9692OaI_.js → p-ClFprFvz.js} +1 -1
  41. package/dist/components/p-Cm33td2O.js +1 -0
  42. package/dist/components/{p-DhMlShij.js → p-DAwPPDMS.js} +1 -1
  43. package/dist/components/p-DJkKlUyZ.js +1 -0
  44. package/dist/components/p-JYj3Facr.js +1 -0
  45. package/dist/components/p-Ka7OWbnk.js +1 -0
  46. package/dist/components/p-djJSnjAX.js +1 -0
  47. package/dist/esm/index.js +2 -2
  48. package/dist/esm/kritzel-active-users_47.entry.js +365 -80
  49. package/dist/esm/loader.js +1 -1
  50. package/dist/esm/{schema.constants-Cv5-yM39.js → schema.constants-uC7_X6yr.js} +272 -34
  51. package/dist/esm/stencil.js +1 -1
  52. package/dist/stencil/index.esm.js +1 -1
  53. package/dist/stencil/p-b64c3584.entry.js +9 -0
  54. package/dist/stencil/p-uC7_X6yr.js +1 -0
  55. package/dist/stencil/stencil.esm.js +1 -1
  56. package/dist/types/classes/core/workspace.class.d.ts +1 -1
  57. package/dist/types/classes/managers/clipboard.manager.d.ts +1 -0
  58. package/dist/types/classes/objects/base-object.class.d.ts +0 -1
  59. package/dist/types/classes/registries/font-registry.class.d.ts +19 -0
  60. package/dist/types/classes/structures/object-map.structure.d.ts +2 -2
  61. package/dist/types/classes/tools/image-tool.class.d.ts +9 -2
  62. package/dist/types/classes/tools/text-tool.class.d.ts +3 -0
  63. package/dist/types/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.d.ts +2 -0
  64. package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +22 -0
  65. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +17 -0
  66. package/dist/types/components/shared/kritzel-font-family/kritzel-font-family.d.ts +4 -0
  67. package/dist/types/components/ui/kritzel-tool-config/kritzel-tool-config.d.ts +1 -0
  68. package/dist/types/components.d.ts +20 -2
  69. package/dist/types/constants/text-tool-fonts.constants.d.ts +3 -0
  70. package/dist/types/constants/version.d.ts +1 -1
  71. package/dist/types/helpers/image-file.helper.d.ts +3 -0
  72. package/dist/types/index.d.ts +2 -0
  73. package/dist/types/interfaces/font.interface.d.ts +15 -0
  74. package/dist/types/interfaces/toolbar-control.interface.d.ts +2 -0
  75. package/package.json +1 -1
  76. package/dist/components/p-B4b6TDxp.js +0 -1
  77. package/dist/components/p-C2ocjA6D.js +0 -1
  78. package/dist/components/p-CwbZCXKh.js +0 -1
  79. package/dist/components/p-D2q_wTyG.js +0 -1
  80. package/dist/components/p-D8NvNMcU.js +0 -1
  81. package/dist/components/p-D8W6LE-c.js +0 -1
  82. package/dist/components/p-G9G9y5VE.js +0 -9
  83. package/dist/components/p-JhOYwUOj.js +0 -1
  84. package/dist/components/p-UEf2EN23.js +0 -1
  85. package/dist/stencil/p-2c489187.entry.js +0 -9
  86. package/dist/stencil/p-Cv5-yM39.js +0 -1
@@ -24,6 +24,8 @@ import { darkTheme } from "../../../themes/dark-theme";
24
24
  import { KritzelSelectionGroup } from "../../../classes/objects/selection-group.class";
25
25
  import { KritzelSelectionBox } from "../../../classes/objects/selection-box.class";
26
26
  import { ObjectHelper } from "../../../helpers/object.helper";
27
+ import { KritzelFontRegistry } from "../../../classes/registries/font-registry.class";
28
+ import { resolveTextToolAvailableFonts } from "../../../constants/text-tool-fonts.constants";
27
29
  export class KritzelEditor {
28
30
  host;
29
31
  scaleMax = ABSOLUTE_SCALE_MAX;
@@ -184,6 +186,11 @@ export class KritzelEditor {
184
186
  /** The locale used to resolve terms missing from the active locale. */
185
187
  fallbackLocale = 'en';
186
188
  customSvgIcons = {};
189
+ /**
190
+ * Registers fonts for runtime usage (for example custom object rendering).
191
+ * Text-tool config tooltip options are controlled via controls[].config.availableFonts.
192
+ */
193
+ customFonts = {};
187
194
  isPanningEnabled = true;
188
195
  isZoomingEnabled = true;
189
196
  isControlsVisible = true;
@@ -236,11 +243,14 @@ export class KritzelEditor {
236
243
  isEditorVisible = false;
237
244
  activeNotification;
238
245
  isNotificationDismissing = false;
246
+ normalizedControls = [];
239
247
  notificationDismissTimeout;
240
248
  notificationDismissAnimationTimeout;
241
249
  notificationDisplayDurationMs = 5000;
242
250
  notificationDismissAnimationDurationMs = 180;
243
251
  isNotificationHovered = false;
252
+ customFontsLoadVersion = 0;
253
+ customFontsReady = Promise.resolve();
244
254
  onIsEngineReady(newValue) {
245
255
  if (newValue && this.isControlsReady) {
246
256
  this.checkIsReady();
@@ -270,6 +280,12 @@ export class KritzelEditor {
270
280
  onActiveWorkspaceChange() {
271
281
  this.updateCurrentIsPublic();
272
282
  }
283
+ onCustomFontsChange(newValue) {
284
+ void this.registerCustomFonts(newValue);
285
+ }
286
+ onControlsChange(newValue) {
287
+ this.normalizedControls = this.normalizeControls(newValue);
288
+ }
273
289
  onActiveWorkspaceIdChange(newId) {
274
290
  // If no ID is provided, do nothing (allows other logic to control activeWorkspace)
275
291
  if (!newId) {
@@ -543,9 +559,27 @@ export class KritzelEditor {
543
559
  loginDialogRef;
544
560
  currentUserDialogRef;
545
561
  componentWillLoad() {
562
+ this.normalizedControls = this.normalizeControls(this.controls);
546
563
  this.loadSettingsFromStorage();
547
564
  this.applyTheme();
548
565
  }
566
+ isTextToolConfig(config) {
567
+ return !!config && 'fontFamily' in config && 'size' in config && 'color' in config;
568
+ }
569
+ normalizeControls(controls) {
570
+ return controls.map(control => {
571
+ if (!this.isTextToolConfig(control.config)) {
572
+ return control;
573
+ }
574
+ return {
575
+ ...control,
576
+ config: {
577
+ ...control.config,
578
+ availableFonts: resolveTextToolAvailableFonts(control.config.availableFonts),
579
+ },
580
+ };
581
+ });
582
+ }
549
583
  applyTheme() {
550
584
  const themeObj = this.resolveThemeObject();
551
585
  ThemeHelper.applyThemeToElement(this.host, themeObj);
@@ -556,6 +590,7 @@ export class KritzelEditor {
556
590
  }
557
591
  componentDidLoad() {
558
592
  this.registerCustomSvgIcons();
593
+ this.registerCustomFonts();
559
594
  this.listenForMobileKeyboard();
560
595
  this.setOsSpecificCssVariables();
561
596
  }
@@ -568,6 +603,7 @@ export class KritzelEditor {
568
603
  await customElements.whenDefined('kritzel-workspace-manager');
569
604
  await customElements.whenDefined('kritzel-controls');
570
605
  await customElements.whenDefined('kritzel-engine');
606
+ await this.waitForCustomFontsReady();
571
607
  if (!this.isEngineReady || !this.isControlsReady || !this.isWorkspaceManagerReady || !this.activeWorkspace) {
572
608
  return;
573
609
  }
@@ -831,6 +867,15 @@ export class KritzelEditor {
831
867
  async registerLocales(locales) {
832
868
  await this.engineRef?.registerLocales(locales);
833
869
  }
870
+ /**
871
+ * Registers custom fonts for the editor runtime.
872
+ * @param fonts - Mapping from font keys to family names or font definitions.
873
+ * @remarks This no longer controls the text-tool config tooltip font options.
874
+ * Configure tooltip fonts via controls[].config.availableFonts.
875
+ */
876
+ async registerFonts(fonts) {
877
+ await this.registerCustomFonts(fonts);
878
+ }
834
879
  /**
835
880
  * Resolves a term key to its translated string for the active locale.
836
881
  * @param key - The term key to resolve.
@@ -908,6 +953,25 @@ export class KritzelEditor {
908
953
  KritzelIconRegistry.register(name, svg);
909
954
  }
910
955
  }
956
+ async registerCustomFonts(fonts = this.customFonts) {
957
+ KritzelFontRegistry.registerFonts(fonts);
958
+ const currentVersion = ++this.customFontsLoadVersion;
959
+ const loadPromise = KritzelFontRegistry.waitForFonts(fonts);
960
+ this.customFontsReady = loadPromise;
961
+ await loadPromise;
962
+ if (currentVersion !== this.customFontsLoadVersion) {
963
+ await this.waitForCustomFontsReady();
964
+ }
965
+ }
966
+ async waitForCustomFontsReady() {
967
+ while (true) {
968
+ const version = this.customFontsLoadVersion;
969
+ await this.customFontsReady;
970
+ if (version === this.customFontsLoadVersion) {
971
+ return;
972
+ }
973
+ }
974
+ }
911
975
  listenForMobileKeyboard() {
912
976
  KritzelKeyboardHelper.onKeyboardVisibleChanged(isOpen => {
913
977
  this.isVirtualKeyboardOpen = isOpen;
@@ -946,36 +1010,36 @@ export class KritzelEditor {
946
1010
  const isLoggedIn = this.isLoggedIn;
947
1011
  const shouldShowCurrentUser = isLoggedIn;
948
1012
  const shouldShowLoginButton = this.isReady && !!this.loginConfig && !isLoggedIn;
949
- return (h(Host, { key: '3128b38a04cd636abc1f2466f1ac1aa3dcea2262' }, h("div", { key: 'b1fbb051cb1144fd84f28cfea4ad824f92189dbd', class: "editor-content", style: {
1013
+ return (h(Host, { key: '00d652c74feac7b4917772146368125da6deeb1c' }, h("div", { key: 'f8fb86b45b0cdabb5e3ad52de6d6ef31a71a09e4', class: "editor-content", style: {
950
1014
  opacity: this.isEditorVisible ? '1' : '0',
951
1015
  visibility: this.isEditorVisible ? 'visible' : 'hidden',
952
1016
  transition: 'opacity 0.2s ease-in-out, visibility 0.2s ease-in-out',
953
- } }, h("div", { key: '2b896fa8bd00a7c68b74df7a9846e8c3e0f6efc4', class: "top-left-buttons" }, h("kritzel-workspace-manager", { key: '13244251aa8999d78d275eefe5583d592f3506fc', visible: this.isWorkspaceManagerVisible, workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, terms: this.resolvedTerms, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), h("kritzel-back-to-content", { key: '7d3015918e4af7ee435aee8da37ddfa206cdfd66', visible: this.isBackToContentButtonVisible, text: this.resolvedTerms['backToContent.label'] ?? 'Back to content', onBackToContent: () => this.backToContent() })), this.activeNotification && (h("div", { key: '49f13f23698db9b804d139e0f35696be06569346', class: "top-center-notification-layer", role: "presentation" }, h("div", { key: '765aa6995398aca3c7738758bedb7d9a7c2f099a', class: { 'top-center-notification-container': true, 'is-dismissing': this.isNotificationDismissing }, role: "presentation" }, h("kritzel-notification-card", { key: 'fe0dfa30aa498a608f9167b01e0a2309dfa67162', notification: this.activeNotification, locale: this.locale, onDismiss: this.dismissNotification, onHoverChange: event => this.handleNotificationHoverChange(event) })))), h("kritzel-engine", { key: '5aeb7979faa8779653ff6a2930d288fd601cb0e9', ref: el => {
1017
+ } }, h("div", { key: '2378c776d8eecf2614567bed11c6e93fb338e302', class: "top-left-buttons" }, h("kritzel-workspace-manager", { key: 'ce41192540169694482d6f8cca60701bc4427438', visible: this.isWorkspaceManagerVisible, workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, terms: this.resolvedTerms, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), h("kritzel-back-to-content", { key: 'ec269d3e9f589362d8301370778f0c5e4252eead', visible: this.isBackToContentButtonVisible, text: this.resolvedTerms['backToContent.label'] ?? 'Back to content', onBackToContent: () => this.backToContent() })), this.activeNotification && (h("div", { key: '847ed8149d556c934090424ff54b17b6721ccc76', class: "top-center-notification-layer", role: "presentation" }, h("div", { key: '61d8b8e91cda100ffa6620db26ba6dfb2232946a', class: { 'top-center-notification-container': true, 'is-dismissing': this.isNotificationDismissing }, role: "presentation" }, h("kritzel-notification-card", { key: 'b7e132773225ace38e447756110dd39e4661f5fc', notification: this.activeNotification, locale: this.locale, onDismiss: this.dismissNotification, onHoverChange: event => this.handleNotificationHoverChange(event) })))), h("kritzel-engine", { key: '3e4a6d0dbc015ec675fb21a59990c87e9eaa805f', ref: el => {
954
1018
  if (el) {
955
1019
  this.engineRef = el;
956
1020
  }
957
- }, workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, assetStorageConfig: this.assetStorageConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, isObjectDistanceFadingActive: this.isObjectDistanceFadingActive, scaleMin: this.scaleMin, cursorTarget: this.cursorTarget, isLoading: this.isLoading, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom, isPanningEnabled: this.isPanningEnabled, isZoomingEnabled: this.isZoomingEnabled, theme: this.theme, themes: this.themes, licenseKey: this.licenseKey, locale: this.locale, locales: this.locales, fallbackLocale: this.fallbackLocale, debugInfo: this.debugInfo, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.handleWorkspacesChange(event), onActiveWorkspaceChange: event => this.handleActiveWorkspaceChange(event), onObjectsChange: event => this.handleObjectsChange(event), onObjectsAdded: event => this.handleObjectsAdded(event), onObjectsRemoved: event => this.handleObjectsRemoved(event), onObjectsUpdated: event => this.handleObjectsUpdated(event), onUndoStateChange: event => this.handleUndoStateChange(event), onObjectsInViewportChange: event => this.handleObjectsInViewportChange(event), onViewportChange: event => this.handleViewportChange(event), onAwarenessChange: event => this.handleAwarenessChange(event), onNotificationsChange: event => this.handleNotificationsChange(event) }), h("kritzel-controls", { key: 'eda4dc93fe663c8472638190216bea5bf64d7153', visible: this.isControlsVisible, class: { 'keyboard-open': this.isVirtualKeyboardOpen }, ref: el => {
1021
+ }, workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, assetStorageConfig: this.assetStorageConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, isObjectDistanceFadingActive: this.isObjectDistanceFadingActive, scaleMin: this.scaleMin, cursorTarget: this.cursorTarget, isLoading: this.isLoading, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom, isPanningEnabled: this.isPanningEnabled, isZoomingEnabled: this.isZoomingEnabled, theme: this.theme, themes: this.themes, licenseKey: this.licenseKey, locale: this.locale, locales: this.locales, fallbackLocale: this.fallbackLocale, debugInfo: this.debugInfo, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.handleWorkspacesChange(event), onActiveWorkspaceChange: event => this.handleActiveWorkspaceChange(event), onObjectsChange: event => this.handleObjectsChange(event), onObjectsAdded: event => this.handleObjectsAdded(event), onObjectsRemoved: event => this.handleObjectsRemoved(event), onObjectsUpdated: event => this.handleObjectsUpdated(event), onUndoStateChange: event => this.handleUndoStateChange(event), onObjectsInViewportChange: event => this.handleObjectsInViewportChange(event), onViewportChange: event => this.handleViewportChange(event), onAwarenessChange: event => this.handleAwarenessChange(event), onNotificationsChange: event => this.handleNotificationsChange(event) }), h("kritzel-controls", { key: 'f84607a0a4d0762c1249400f85b7b8454d672c1e', visible: this.isControlsVisible, class: { 'keyboard-open': this.isVirtualKeyboardOpen }, ref: el => {
958
1022
  if (el) {
959
1023
  this.controlsRef = el;
960
1024
  }
961
- }, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), h("div", { key: 'ffdb548da8aac3498b1b3e9bfdc9a41f8c448675', class: "bottom-left-buttons" }, h("kritzel-zoom-panel", { key: 'af6f6a86212195fd3ee13bc33c16574e0a5236a6', visible: this.isZoomPanelVisible, disabled: !this.isZoomingEnabled, zoomPercent: this.currentZoomPercent, terms: this.resolvedTerms, onZoomIn: () => this.zoomIn(), onZoomOut: () => this.zoomOut() })), h("div", { key: '0870c0e47838fc99b4041718a431535827e199cf', class: "top-right-buttons" }, h("kritzel-settings", { key: 'b95beb43dbe1a9c99454fc4ff74f0630aca7ad83', ref: el => {
1025
+ }, controls: this.normalizedControls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), h("div", { key: 'e2691e7c730195e197511cb1e4d0fe707677b5ff', class: "bottom-left-buttons" }, h("kritzel-zoom-panel", { key: 'd0ac6624eab49af78d4761c3ad91842834717aad', visible: this.isZoomPanelVisible, disabled: !this.isZoomingEnabled, zoomPercent: this.currentZoomPercent, terms: this.resolvedTerms, onZoomIn: () => this.zoomIn(), onZoomOut: () => this.zoomOut() })), h("div", { key: 'ad3d386ab7e8ad9fdfbb12754db005bc85fa28ce', class: "top-right-buttons" }, h("kritzel-settings", { key: '566024ac6f3d8f7f20238cc1f83882b39dbf698e', ref: el => {
962
1026
  if (el) {
963
1027
  this.settingsRef = el;
964
1028
  }
965
- }, shortcuts: this.shortcuts, availableThemes: this.themes && this.themes.length > 0 ? this.themes.map(t => t.name) : ['light', 'dark'], availableLocales: this.availableLocaleOptions, settings: this.currentSettingsConfig, terms: this.resolvedTerms, onSettingsChange: event => this.handleSettingsChange(event) }), h("kritzel-export", { key: 'ef6fea2715ff99226fde937185a693efc2a7dd75', ref: el => {
1029
+ }, shortcuts: this.shortcuts, availableThemes: this.themes && this.themes.length > 0 ? this.themes.map(t => t.name) : ['light', 'dark'], availableLocales: this.availableLocaleOptions, settings: this.currentSettingsConfig, terms: this.resolvedTerms, onSettingsChange: event => this.handleSettingsChange(event) }), h("kritzel-export", { key: '4a23ea0c6e070d424a90e9fc87de04e11cff7ade', ref: el => {
966
1030
  if (el) {
967
1031
  this.exportRef = el;
968
1032
  }
969
- }, workspaceName: this.activeWorkspace?.name || 'workspace', terms: this.resolvedTerms, onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), h("kritzel-active-users", { key: '872b7fa12d49410d1c370baed3386a34f89d3e2a', users: this.activeUsers }), shouldShowCurrentUser && h("kritzel-current-user", { key: 'da19825b4fba6a516803f8330cdfdfac6b6c9db1', user: this.user, terms: this.resolvedTerms, onClick: () => this.currentUserDialogRef?.open() }), shouldShowCurrentUser && (h("kritzel-current-user-dialog", { key: '9336ce611286d3ecf9318317ab4bedb8c3f79f05', ref: el => {
1033
+ }, workspaceName: this.activeWorkspace?.name || 'workspace', terms: this.resolvedTerms, onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), h("kritzel-active-users", { key: 'feef074b52e552fa2ef7e8258002571aca4c5abd', users: this.activeUsers }), shouldShowCurrentUser && h("kritzel-current-user", { key: '844c722545363eaf7eec69037a835eae943afeb9', user: this.user, terms: this.resolvedTerms, onClick: () => this.currentUserDialogRef?.open() }), shouldShowCurrentUser && (h("kritzel-current-user-dialog", { key: '8363c1d3230d111cf1ace0ccf805669e592bb533', ref: el => {
970
1034
  if (el) {
971
1035
  this.currentUserDialogRef = el;
972
1036
  this.currentUserDialogRef.addEventListener('logoutRequest', this.handleCurrentUserLogout);
973
1037
  }
974
- }, user: this.user, terms: this.resolvedTerms })), shouldShowLoginButton && (h("kritzel-button", { key: 'a9e38ad3e13c785f6a4223ebde95f60451c6515f', onButtonClick: () => this.loginDialogRef?.open() }, this.resolvedTerms['login.dialogTitle'] ?? 'Sign in')), h("kritzel-more-menu", { key: 'b8f63a63ae4e75a70d0069410170af902f2a362b', items: this.moreMenuItems, visible: this.isMoreMenuVisible, terms: this.resolvedTerms }), h("kritzel-share-dialog", { key: '7a923fd51e8d2bd1e2833e0941622efadd55f881', ref: el => {
1038
+ }, user: this.user, terms: this.resolvedTerms })), shouldShowLoginButton && (h("kritzel-button", { key: '68ddf8c3aabc7634b4c1d88f3d2d584fa1f1b150', onButtonClick: () => this.loginDialogRef?.open() }, this.resolvedTerms['login.dialogTitle'] ?? 'Sign in')), h("kritzel-more-menu", { key: '39b938f5792f7a36bbf21ed88a1a5c7717a785a6', items: this.moreMenuItems, visible: this.isMoreMenuVisible, terms: this.resolvedTerms }), h("kritzel-share-dialog", { key: '61ed918499760d874d5d2ec140d3cf59ce94520b', ref: el => {
975
1039
  if (el) {
976
1040
  this.shareDialogRef = el;
977
1041
  }
978
- }, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: 'ac54c699a94bb2657a6817c37d6220b75d931cd3', ref: el => {
1042
+ }, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: '5f6528a57884bd1494e45755609e710f69041a4d', ref: el => {
979
1043
  if (el) {
980
1044
  this.loginDialogRef = el;
981
1045
  }
@@ -1453,6 +1517,31 @@ export class KritzelEditor {
1453
1517
  "setter": false,
1454
1518
  "defaultValue": "{}"
1455
1519
  },
1520
+ "customFonts": {
1521
+ "type": "unknown",
1522
+ "mutable": false,
1523
+ "complexType": {
1524
+ "original": "KritzelFontMap",
1525
+ "resolved": "{ [x: string]: KritzelFontRegistration; }",
1526
+ "references": {
1527
+ "KritzelFontMap": {
1528
+ "location": "import",
1529
+ "path": "../../../interfaces/font.interface",
1530
+ "id": "src/interfaces/font.interface.ts::KritzelFontMap",
1531
+ "referenceLocation": "KritzelFontMap"
1532
+ }
1533
+ }
1534
+ },
1535
+ "required": false,
1536
+ "optional": false,
1537
+ "docs": {
1538
+ "tags": [],
1539
+ "text": "Registers fonts for runtime usage (for example custom object rendering).\nText-tool config tooltip options are controlled via controls[].config.availableFonts."
1540
+ },
1541
+ "getter": false,
1542
+ "setter": false,
1543
+ "defaultValue": "{}"
1544
+ },
1456
1545
  "isPanningEnabled": {
1457
1546
  "type": "boolean",
1458
1547
  "mutable": true,
@@ -1786,7 +1875,8 @@ export class KritzelEditor {
1786
1875
  "currentIsPublic": {},
1787
1876
  "isEditorVisible": {},
1788
1877
  "activeNotification": {},
1789
- "isNotificationDismissing": {}
1878
+ "isNotificationDismissing": {},
1879
+ "normalizedControls": {}
1790
1880
  };
1791
1881
  }
1792
1882
  static get events() {
@@ -3845,6 +3935,39 @@ export class KritzelEditor {
3845
3935
  }]
3846
3936
  }
3847
3937
  },
3938
+ "registerFonts": {
3939
+ "complexType": {
3940
+ "signature": "(fonts: KritzelFontMap) => Promise<void>",
3941
+ "parameters": [{
3942
+ "name": "fonts",
3943
+ "type": "{ [x: string]: KritzelFontRegistration; }",
3944
+ "docs": "- Mapping from font keys to family names or font definitions."
3945
+ }],
3946
+ "references": {
3947
+ "Promise": {
3948
+ "location": "global",
3949
+ "id": "global::Promise"
3950
+ },
3951
+ "KritzelFontMap": {
3952
+ "location": "import",
3953
+ "path": "../../../interfaces/font.interface",
3954
+ "id": "src/interfaces/font.interface.ts::KritzelFontMap",
3955
+ "referenceLocation": "KritzelFontMap"
3956
+ }
3957
+ },
3958
+ "return": "Promise<void>"
3959
+ },
3960
+ "docs": {
3961
+ "text": "Registers custom fonts for the editor runtime.",
3962
+ "tags": [{
3963
+ "name": "param",
3964
+ "text": "fonts - Mapping from font keys to family names or font definitions."
3965
+ }, {
3966
+ "name": "remarks",
3967
+ "text": "This no longer controls the text-tool config tooltip font options.\nConfigure tooltip fonts via controls[].config.availableFonts."
3968
+ }]
3969
+ }
3970
+ },
3848
3971
  "t": {
3849
3972
  "complexType": {
3850
3973
  "signature": "(key: KritzelTermKey, vars?: KritzelTermVars) => Promise<string>",
@@ -3904,6 +4027,12 @@ export class KritzelEditor {
3904
4027
  }, {
3905
4028
  "propName": "activeWorkspace",
3906
4029
  "methodName": "onActiveWorkspaceChange"
4030
+ }, {
4031
+ "propName": "customFonts",
4032
+ "methodName": "onCustomFontsChange"
4033
+ }, {
4034
+ "propName": "controls",
4035
+ "methodName": "onControlsChange"
3907
4036
  }, {
3908
4037
  "propName": "activeWorkspaceId",
3909
4038
  "methodName": "onActiveWorkspaceIdChange"
@@ -3,8 +3,12 @@ import { KritzelViewport } from "../../../classes/core/viewport.class";
3
3
  import { KritzelSelectionTool } from "../../../classes/tools/selection-tool.class";
4
4
  import { KritzelTextTool } from "../../../classes/tools/text-tool.class";
5
5
  import { KritzelShapeTool } from "../../../classes/tools/shape-tool.class";
6
+ import { KritzelBrushTool } from "../../../classes/tools/brush-tool.class";
7
+ import { KritzelLineTool } from "../../../classes/tools/line-tool.class";
8
+ import { KritzelImageTool } from "../../../classes/tools/image-tool.class";
6
9
  import { KritzelSelectionBox } from "../../../classes/objects/selection-box.class";
7
10
  import { KritzelKeyHandler } from "../../../classes/handlers/key.handler";
11
+ import { KritzelBaseTool } from "../../../classes/tools/base-tool.class";
8
12
  import { KritzelEraserTool } from "../../../classes/tools/eraser-tool.class";
9
13
  import { KritzelKeyboardHelper } from "../../../helpers/keyboard.helper";
10
14
  import { KritzelContextMenuHandler } from "../../../classes/handlers/context-menu.handler";
@@ -21,6 +25,7 @@ import { KritzelSvgExportHelper } from "../../../helpers/svg-export.helper";
21
25
  import { toPng, toSvg } from "html-to-image";
22
26
  import { ObjectHelper } from "../../../helpers/object.helper";
23
27
  import { KritzelWheelHelper } from "../../../helpers/wheel.helper";
28
+ import { resolveTextToolAvailableFonts } from "../../../constants/text-tool-fonts.constants";
24
29
  export class KritzelEngine {
25
30
  host;
26
31
  /** The workspace to load and display. Changing this prop switches the active workspace. */
@@ -539,7 +544,7 @@ export class KritzelEngine {
539
544
  }
540
545
  return existingTool;
541
546
  }
542
- const registeredTool = this.core.toolRegistry.registerTool(toolName, toolClass);
547
+ const registeredTool = this.core.toolRegistry.registerTool(toolName, this.resolveToolClass(toolClass));
543
548
  if (toolConfig) {
544
549
  this.applyToolConfig(registeredTool, toolConfig);
545
550
  }
@@ -1341,8 +1346,25 @@ export class KritzelEngine {
1341
1346
  if (!workspace) {
1342
1347
  throw new Error('Cannot export workspace: no active workspace is loaded');
1343
1348
  }
1349
+ await this.core.initializeAssetStorage();
1344
1350
  const serialized = workspace.serialize({ includeObjects: true });
1345
- return JSON.stringify(serialized, null, 2);
1351
+ const exportMode = this.getWorkspaceExportMode();
1352
+ const { objects, ...workspaceWithoutObjects } = serialized;
1353
+ const payload = {
1354
+ ...workspaceWithoutObjects,
1355
+ exportMode,
1356
+ ...(objects !== undefined ? { objects } : {}),
1357
+ };
1358
+ if (exportMode === 'portable') {
1359
+ const portableAssets = await this.collectPortableAssets(payload.objects);
1360
+ if (Object.keys(portableAssets).length > 0) {
1361
+ payload.assets = portableAssets;
1362
+ }
1363
+ }
1364
+ else {
1365
+ delete payload.assets;
1366
+ }
1367
+ return JSON.stringify(payload, null, 2);
1346
1368
  }
1347
1369
  /**
1348
1370
  * Imports a workspace from a JSON string into a new workspace.
@@ -1356,22 +1378,15 @@ export class KritzelEngine {
1356
1378
  if (!data.__class__ || data.__class__ !== 'KritzelWorkspace') {
1357
1379
  throw new Error('Invalid workspace data: missing or incorrect __class__ identifier');
1358
1380
  }
1381
+ await this.core.initializeAssetStorage();
1382
+ await this.restorePortableAssets(data);
1359
1383
  if (data.version && data.version !== WORKSPACE_EXPORT_VERSION) {
1360
1384
  console.warn(`Workspace version mismatch: expected ${WORKSPACE_EXPORT_VERSION}, got ${data.version}`);
1361
1385
  }
1362
1386
  // Create a new workspace with a fresh ID but use the imported name
1363
1387
  const newWorkspaceId = ObjectHelper.generateUUID();
1364
- const importedName = data.name || 'Imported Workspace';
1365
- let importedViewport = data.viewport || { centerWorldX: 0, centerWorldY: 0, scale: 1 };
1366
- // Backward compatibility: convert legacy translateX/translateY to centerWorldX/centerWorldY
1367
- if ('translateX' in importedViewport && !('centerWorldX' in importedViewport)) {
1368
- const scale = importedViewport.scale ?? 1;
1369
- importedViewport = {
1370
- centerWorldX: -(importedViewport.translateX ?? 0) / scale,
1371
- centerWorldY: -(importedViewport.translateY ?? 0) / scale,
1372
- scale,
1373
- };
1374
- }
1388
+ const importedName = this.getImportedWorkspaceName(data.name);
1389
+ const importedViewport = this.getImportedWorkspaceViewport(data.viewport);
1375
1390
  const newWorkspace = new KritzelWorkspace(newWorkspaceId, importedName, importedViewport);
1376
1391
  // Save the new workspace
1377
1392
  this.core.createWorkspace(newWorkspace);
@@ -1410,6 +1425,8 @@ export class KritzelEngine {
1410
1425
  if (!data.__class__ || data.__class__ !== 'KritzelWorkspace') {
1411
1426
  throw new Error('Invalid workspace data: missing or incorrect __class__ identifier');
1412
1427
  }
1428
+ await this.core.initializeAssetStorage();
1429
+ await this.restorePortableAssets(data);
1413
1430
  if (data.version && data.version !== WORKSPACE_EXPORT_VERSION) {
1414
1431
  console.warn(`Workspace version mismatch: expected ${WORKSPACE_EXPORT_VERSION}, got ${data.version}`);
1415
1432
  }
@@ -1436,6 +1453,98 @@ export class KritzelEngine {
1436
1453
  this.core.rerender();
1437
1454
  return loadedCount;
1438
1455
  }
1456
+ getWorkspaceExportMode() {
1457
+ return this.core.assetResolver.hasRemoteProvider ? 'lightweight' : 'portable';
1458
+ }
1459
+ async collectPortableAssets(serializedObjects) {
1460
+ if (!Array.isArray(serializedObjects) || serializedObjects.length === 0) {
1461
+ return {};
1462
+ }
1463
+ const assetIds = new Set();
1464
+ for (const serializedObject of serializedObjects) {
1465
+ if (!serializedObject || typeof serializedObject !== 'object') {
1466
+ continue;
1467
+ }
1468
+ const maybeImage = serializedObject;
1469
+ if (maybeImage.__class__ === 'KritzelImage' && typeof maybeImage.assetId === 'string' && maybeImage.assetId.length > 0) {
1470
+ assetIds.add(maybeImage.assetId);
1471
+ }
1472
+ }
1473
+ const assets = {};
1474
+ for (const assetId of assetIds) {
1475
+ try {
1476
+ const blob = await this.core.assetResolver.fetchBlob(assetId);
1477
+ assets[assetId] = await this.blobToDataUrl(blob);
1478
+ }
1479
+ catch (error) {
1480
+ console.warn(`[Kritzel] Failed to embed asset ${assetId} in portable workspace export:`, error);
1481
+ }
1482
+ }
1483
+ return assets;
1484
+ }
1485
+ async restorePortableAssets(data) {
1486
+ const assets = data.assets;
1487
+ if (!assets || typeof assets !== 'object') {
1488
+ return;
1489
+ }
1490
+ for (const [assetId, dataUrl] of Object.entries(assets)) {
1491
+ if (!assetId || typeof dataUrl !== 'string' || !dataUrl.startsWith('data:')) {
1492
+ continue;
1493
+ }
1494
+ try {
1495
+ const blob = await this.dataUrlToBlob(dataUrl);
1496
+ await this.core.assetResolver.put(blob, {
1497
+ id: assetId,
1498
+ mimeType: blob.type || 'application/octet-stream',
1499
+ kind: 'image',
1500
+ });
1501
+ }
1502
+ catch (error) {
1503
+ console.warn(`[Kritzel] Failed to restore embedded asset ${assetId} from portable workspace import:`, error);
1504
+ }
1505
+ }
1506
+ }
1507
+ blobToDataUrl(blob) {
1508
+ return new Promise((resolve, reject) => {
1509
+ const reader = new FileReader();
1510
+ reader.onload = () => resolve(reader.result);
1511
+ reader.onerror = () => reject(reader.error ?? new Error('Failed to read blob as data URL'));
1512
+ reader.readAsDataURL(blob);
1513
+ });
1514
+ }
1515
+ async dataUrlToBlob(dataUrl) {
1516
+ const response = await fetch(dataUrl);
1517
+ return response.blob();
1518
+ }
1519
+ getImportedWorkspaceName(rawName) {
1520
+ if (typeof rawName === 'string' && rawName.trim().length > 0) {
1521
+ return rawName;
1522
+ }
1523
+ return 'Imported Workspace';
1524
+ }
1525
+ getImportedWorkspaceViewport(rawViewport) {
1526
+ if (!rawViewport || typeof rawViewport !== 'object') {
1527
+ return { centerWorldX: 0, centerWorldY: 0, scale: 1 };
1528
+ }
1529
+ const viewport = rawViewport;
1530
+ if (typeof viewport.centerWorldX === 'number' && typeof viewport.centerWorldY === 'number') {
1531
+ const scale = typeof viewport.scale === 'number' && viewport.scale > 0 ? viewport.scale : 1;
1532
+ return {
1533
+ centerWorldX: viewport.centerWorldX,
1534
+ centerWorldY: viewport.centerWorldY,
1535
+ scale,
1536
+ };
1537
+ }
1538
+ if (typeof viewport.translateX === 'number' || typeof viewport.translateY === 'number') {
1539
+ const scale = typeof viewport.scale === 'number' && viewport.scale > 0 ? viewport.scale : 1;
1540
+ return {
1541
+ centerWorldX: -(typeof viewport.translateX === 'number' ? viewport.translateX : 0) / scale,
1542
+ centerWorldY: -(typeof viewport.translateY === 'number' ? viewport.translateY : 0) / scale,
1543
+ scale,
1544
+ };
1545
+ }
1546
+ return { centerWorldX: 0, centerWorldY: 0, scale: 1 };
1547
+ }
1439
1548
  /**
1440
1549
  * Exports the current workspace as a JSON file and triggers a browser download.
1441
1550
  * @param filename - Optional custom filename (without extension). Defaults to workspace name with timestamp.
@@ -1720,31 +1829,71 @@ export class KritzelEngine {
1720
1829
  this.syncingChange.emit(isSyncing);
1721
1830
  }
1722
1831
  applyToolConfig(tool, toolConfig) {
1723
- Object.entries(toolConfig).forEach(([key, value]) => {
1832
+ const normalizedToolConfig = this.normalizeToolConfig(toolConfig);
1833
+ Object.entries(normalizedToolConfig).forEach(([key, value]) => {
1724
1834
  tool[key] = value;
1725
1835
  });
1726
1836
  // Resolve palettes map into the flat palette array the UI reads
1727
- if ('palettes' in toolConfig && 'type' in toolConfig) {
1728
- const brushConfig = toolConfig;
1837
+ if ('palettes' in normalizedToolConfig && 'type' in normalizedToolConfig) {
1838
+ const brushConfig = normalizedToolConfig;
1729
1839
  const resolvedPalette = brushConfig.palettes[brushConfig.type];
1730
1840
  if (resolvedPalette) {
1731
1841
  tool['palette'] = resolvedPalette;
1732
1842
  }
1733
1843
  }
1734
1844
  // Resolve sizes map into the flat sizes array the UI reads (brush tool uses a map keyed by type)
1735
- if ('sizes' in toolConfig && toolConfig.sizes != null && 'type' in toolConfig) {
1736
- const brushConfig = toolConfig;
1845
+ if ('sizes' in normalizedToolConfig && normalizedToolConfig.sizes != null && 'type' in normalizedToolConfig) {
1846
+ const brushConfig = normalizedToolConfig;
1737
1847
  const resolvedSizes = brushConfig.sizes?.[brushConfig.type];
1738
1848
  if (resolvedSizes) {
1739
1849
  tool['sizes'] = resolvedSizes;
1740
1850
  }
1741
1851
  }
1742
1852
  }
1853
+ normalizeToolConfig(toolConfig) {
1854
+ if (!this.isTextToolConfig(toolConfig)) {
1855
+ return toolConfig;
1856
+ }
1857
+ return {
1858
+ ...toolConfig,
1859
+ availableFonts: resolveTextToolAvailableFonts(toolConfig.availableFonts),
1860
+ };
1861
+ }
1862
+ isTextToolConfig(toolConfig) {
1863
+ return 'fontFamily' in toolConfig && 'size' in toolConfig && 'color' in toolConfig;
1864
+ }
1865
+ /** Built-in tool classes of this bundle keyed by their tool type. */
1866
+ static BUILT_IN_TOOL_CLASSES = {
1867
+ selection: KritzelSelectionTool,
1868
+ brush: KritzelBrushTool,
1869
+ eraser: KritzelEraserTool,
1870
+ line: KritzelLineTool,
1871
+ shape: KritzelShapeTool,
1872
+ text: KritzelTextTool,
1873
+ image: KritzelImageTool,
1874
+ };
1875
+ /**
1876
+ * Resolves a tool class to the internal built-in class when a foreign copy is passed.
1877
+ * Classes from another compiled copy of the library (dual-package hazard, e.g. built-ins
1878
+ * re-exported by a framework wrapper) would otherwise break `instanceof` checks.
1879
+ */
1880
+ resolveToolClass(toolClass) {
1881
+ if (toolClass.prototype instanceof KritzelBaseTool) {
1882
+ return toolClass;
1883
+ }
1884
+ try {
1885
+ const probe = new toolClass(this.core);
1886
+ return KritzelEngine.BUILT_IN_TOOL_CLASSES[probe.toolType] ?? toolClass;
1887
+ }
1888
+ catch {
1889
+ return toolClass;
1890
+ }
1891
+ }
1743
1892
  get isSelecting() {
1744
- return this.core.store.state.activeTool instanceof KritzelSelectionTool && this.core.store.state.isSelecting;
1893
+ return this.core.store.state.activeTool?.toolType === 'selection' && this.core.store.state.isSelecting;
1745
1894
  }
1746
1895
  get isSelectionActive() {
1747
- return this.core.store.state.activeTool instanceof KritzelSelectionTool && this.core.store.selectionGroup !== null;
1896
+ return this.core.store.state.activeTool?.toolType === 'selection' && this.core.store.selectionGroup !== null;
1748
1897
  }
1749
1898
  constructor() {
1750
1899
  this.core = new KritzelCore(this);
@@ -2043,7 +2192,7 @@ export class KritzelEngine {
2043
2192
  this.core.store.onStateChange('activeTool', this._handleActiveToolChange.bind(this));
2044
2193
  }
2045
2194
  _handleActiveToolChange(activeTool) {
2046
- if (!(activeTool instanceof KritzelSelectionTool)) {
2195
+ if (activeTool?.toolType !== 'selection') {
2047
2196
  this.core.clearSelection();
2048
2197
  this.core.store.objects?.remove(o => o instanceof KritzelSelectionBox);
2049
2198
  this.core.store.setSelectionBox(null);
@@ -2052,10 +2201,10 @@ export class KritzelEngine {
2052
2201
  this.core.store.state.isResizeHandleSelected = false;
2053
2202
  this.core.store.state.isRotationHandleSelected = false;
2054
2203
  }
2055
- if (!(activeTool instanceof KritzelTextTool)) {
2204
+ if (activeTool?.toolType !== 'text') {
2056
2205
  this.core.resetActiveText();
2057
2206
  }
2058
- if (!(activeTool instanceof KritzelShapeTool)) {
2207
+ if (activeTool?.toolType !== 'shape') {
2059
2208
  this.core.resetActiveShape();
2060
2209
  }
2061
2210
  this.core.store.state.skipContextMenu = false;
@@ -2289,7 +2438,7 @@ export class KritzelEngine {
2289
2438
  borderWidth: object.borderWidth + 'px',
2290
2439
  borderStyle: 'solid',
2291
2440
  padding: object.padding + 'px',
2292
- overflow: 'hidden',
2441
+ overflow: 'visible',
2293
2442
  display: 'block',
2294
2443
  } })), KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') && !this.core.displaySelectionLineUI(object) && (h("div", { ref: el => el && object.mount(el), style: {
2295
2444
  position: 'absolute',
@@ -2639,7 +2788,7 @@ export class KritzelEngine {
2639
2788
  }, this.core.store.selectionGroup?.objects || []);
2640
2789
  }
2641
2790
  this.hideContextMenu();
2642
- }, 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') })));
2791
+ }, onClose: () => this.hideContextMenu() })), this.core.store.objects?.hasAwareness && h("kritzel-awareness-cursors", { core: this.core }), this.core.store.state?.activeTool?.toolType === 'eraser' && !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') })));
2643
2792
  }
2644
2793
  static get is() { return "kritzel-engine"; }
2645
2794
  static get encapsulation() { return "shadow"; }
@@ -5292,6 +5441,10 @@ export class KritzelEngine {
5292
5441
  "Promise": {
5293
5442
  "location": "global",
5294
5443
  "id": "global::Promise"
5444
+ },
5445
+ "WorkspaceJsonExportPayload": {
5446
+ "location": "global",
5447
+ "id": "global::WorkspaceJsonExportPayload"
5295
5448
  }
5296
5449
  },
5297
5450
  "return": "Promise<string>"
@@ -5317,6 +5470,10 @@ export class KritzelEngine {
5317
5470
  "location": "global",
5318
5471
  "id": "global::Promise"
5319
5472
  },
5473
+ "WorkspaceJsonExportPayload": {
5474
+ "location": "global",
5475
+ "id": "global::WorkspaceJsonExportPayload"
5476
+ },
5320
5477
  "KritzelBaseObject": {
5321
5478
  "location": "import",
5322
5479
  "path": "../../../classes/objects/base-object.class",
@@ -5350,6 +5507,10 @@ export class KritzelEngine {
5350
5507
  "location": "global",
5351
5508
  "id": "global::Promise"
5352
5509
  },
5510
+ "WorkspaceJsonExportPayload": {
5511
+ "location": "global",
5512
+ "id": "global::WorkspaceJsonExportPayload"
5513
+ },
5353
5514
  "KritzelBaseObject": {
5354
5515
  "location": "import",
5355
5516
  "path": "../../../classes/objects/base-object.class",