kritzel-stencil 0.3.12 → 0.3.14

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 (169) hide show
  1. package/dist/cjs/{index-CFnj_FXt.js → index-Xav9JFHg.js} +1 -1
  2. package/dist/cjs/index.cjs.js +41 -3
  3. package/dist/cjs/kritzel-active-users_42.cjs.entry.js +281 -113
  4. package/dist/cjs/kritzel-brush-style.cjs.entry.js +1 -1
  5. package/dist/cjs/loader.cjs.js +2 -2
  6. package/dist/cjs/{schema.constants-CzfoUWxF.js → schema.constants-DJQTjcy7.js} +84 -42
  7. package/dist/cjs/stencil.cjs.js +3 -3
  8. package/dist/collection/classes/core/viewport.class.js +97 -8
  9. package/dist/collection/classes/objects/image.class.js +62 -0
  10. package/dist/collection/classes/objects/shape.class.js +2 -1
  11. package/dist/collection/classes/tools/base-tool.class.js +2 -0
  12. package/dist/collection/classes/tools/brush-tool.class.js +1 -0
  13. package/dist/collection/classes/tools/eraser-tool.class.js +1 -0
  14. package/dist/collection/classes/tools/image-tool.class.js +1 -0
  15. package/dist/collection/classes/tools/line-tool.class.js +1 -0
  16. package/dist/collection/classes/tools/selection-tool.class.js +1 -0
  17. package/dist/collection/classes/tools/shape-tool.class.js +1 -0
  18. package/dist/collection/classes/tools/text-tool.class.js +1 -0
  19. package/dist/collection/collection-manifest.json +1 -1
  20. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +156 -33
  21. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +270 -19
  22. package/dist/collection/components/shared/kritzel-dropdown/kritzel-dropdown.css +3 -3
  23. package/dist/collection/components/shared/kritzel-input/kritzel-input.css +1 -1
  24. package/dist/collection/components/shared/kritzel-numeric-input/kritzel-numeric-input.css +2 -2
  25. package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.css +7 -0
  26. package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.js +7 -1
  27. package/dist/collection/components/ui/kritzel-export/kritzel-export.css +1 -1
  28. package/dist/collection/components/ui/kritzel-tool-config/kritzel-tool-config.js +2 -2
  29. package/dist/collection/configs/default-asset-storage.config.js +1 -2
  30. package/dist/collection/configs/default-sync.config.js +2 -5
  31. package/dist/collection/constants/version.js +1 -1
  32. package/dist/collection/helpers/tool-config.helper.js +58 -65
  33. package/dist/collection/interfaces/tool-type.interface.js +1 -0
  34. package/dist/collection/themes/dark-theme.js +5 -0
  35. package/dist/collection/themes/light-theme.js +5 -0
  36. package/dist/components/index.js +1 -1
  37. package/dist/components/kritzel-active-users.js +1 -1
  38. package/dist/components/kritzel-avatar.js +1 -1
  39. package/dist/components/kritzel-awareness-cursors.js +1 -1
  40. package/dist/components/kritzel-back-to-content.js +1 -1
  41. package/dist/components/kritzel-brush-style.js +1 -1
  42. package/dist/components/kritzel-button.js +1 -1
  43. package/dist/components/kritzel-color-palette.js +1 -1
  44. package/dist/components/kritzel-color.js +1 -1
  45. package/dist/components/kritzel-context-menu.js +1 -1
  46. package/dist/components/kritzel-controls.js +1 -1
  47. package/dist/components/kritzel-current-user-dialog.js +1 -1
  48. package/dist/components/kritzel-current-user.js +1 -1
  49. package/dist/components/kritzel-cursor-trail.js +1 -1
  50. package/dist/components/kritzel-dialog.js +1 -1
  51. package/dist/components/kritzel-dropdown.js +1 -1
  52. package/dist/components/kritzel-editor.js +1 -1
  53. package/dist/components/kritzel-engine.js +1 -1
  54. package/dist/components/kritzel-export.js +1 -1
  55. package/dist/components/kritzel-font-family.js +1 -1
  56. package/dist/components/kritzel-font-size.js +1 -1
  57. package/dist/components/kritzel-font.js +1 -1
  58. package/dist/components/kritzel-icon.js +1 -1
  59. package/dist/components/kritzel-input.js +1 -1
  60. package/dist/components/kritzel-line-endings.js +1 -1
  61. package/dist/components/kritzel-login-dialog.js +1 -1
  62. package/dist/components/kritzel-master-detail.js +1 -1
  63. package/dist/components/kritzel-menu-item.js +1 -1
  64. package/dist/components/kritzel-menu.js +1 -1
  65. package/dist/components/kritzel-more-menu.js +1 -1
  66. package/dist/components/kritzel-numeric-input.js +1 -1
  67. package/dist/components/kritzel-opacity-slider.js +1 -1
  68. package/dist/components/kritzel-pill-tabs.js +1 -1
  69. package/dist/components/kritzel-portal.js +1 -1
  70. package/dist/components/kritzel-settings.js +1 -1
  71. package/dist/components/kritzel-shape-fill.js +1 -1
  72. package/dist/components/kritzel-share-dialog.js +1 -1
  73. package/dist/components/kritzel-slide-toggle.js +1 -1
  74. package/dist/components/kritzel-split-button.js +1 -1
  75. package/dist/components/kritzel-stroke-size.js +1 -1
  76. package/dist/components/kritzel-tool-config.js +1 -1
  77. package/dist/components/kritzel-tooltip.js +1 -1
  78. package/dist/components/kritzel-utility-panel.js +1 -1
  79. package/dist/components/kritzel-workspace-manager.js +1 -1
  80. package/dist/components/p-2xYAGd0I.js +1 -0
  81. package/dist/components/{p-DdmJquQr.js → p-B2Os1ya_.js} +1 -1
  82. package/dist/components/p-B2w8X7vn.js +1 -0
  83. package/dist/components/{p-DRB3TZzI.js → p-B4b6TDxp.js} +1 -1
  84. package/dist/components/p-B5xxfwKF.js +1 -0
  85. package/dist/components/{p-D0aom7Yu.js → p-BFYtCsZu.js} +1 -1
  86. package/dist/components/{p-CARNM9pf.js → p-BFoK4W--.js} +1 -1
  87. package/dist/components/p-BTEV1WwT.js +1 -0
  88. package/dist/components/{p-x38RbGJA.js → p-BYmp9Ovv.js} +1 -1
  89. package/dist/components/{p-KVG5rztB.js → p-BbactVA0.js} +1 -1
  90. package/dist/components/{p-B_JH91jB.js → p-BfNHpqQ8.js} +1 -1
  91. package/dist/components/{p-DXgUuzXW.js → p-BiG1dxPS.js} +1 -1
  92. package/dist/components/{p-Dov3qOAR.js → p-Bj2laX89.js} +1 -1
  93. package/dist/components/{p-Cr7xOsIZ.js → p-BqwqGFQY.js} +1 -1
  94. package/dist/components/{p-DmTG0Y5h.js → p-BzYU3-MJ.js} +1 -1
  95. package/dist/components/p-C0TN5IAi.js +1 -0
  96. package/dist/components/{p-RnuCSIt-.js → p-C2SX-XRr.js} +1 -1
  97. package/dist/components/{p-guqEWGgV.js → p-CFgkUYoO.js} +1 -1
  98. package/dist/components/{p-BTSOqHMI.js → p-CHrSFOSI.js} +1 -1
  99. package/dist/components/p-CJOhfMU5.js +1 -0
  100. package/dist/components/p-CLLbE_z8.js +9 -0
  101. package/dist/components/{p-DJLJfKY2.js → p-COLHjboZ.js} +1 -1
  102. package/dist/components/{p-CKY7AvGR.js → p-COgo9OWy.js} +1 -1
  103. package/dist/components/p-CUPYGT8c.js +1 -0
  104. package/dist/components/{p-DhAM4qeQ.js → p-CXpv9Rxe.js} +1 -1
  105. package/dist/components/{p-Bp3kdH4l.js → p-CcyIAi9S.js} +1 -1
  106. package/dist/components/{p-COIxq81R.js → p-CmuNn1Tc.js} +1 -1
  107. package/dist/components/{p-DfH7YY2C.js → p-D-sRVAbQ.js} +1 -1
  108. package/dist/components/{p-ZgZqbJ58.js → p-DDYoDSrm.js} +1 -1
  109. package/dist/components/{p-u0b2RJAn.js → p-DEy7zJCe.js} +1 -1
  110. package/dist/components/{p-BPEn0_hr.js → p-DM11KXUT.js} +1 -1
  111. package/dist/components/{p-CJERvHdy.js → p-DbB730vO.js} +1 -1
  112. package/dist/components/{p-C8ggg-5h.js → p-Df3BwVGy.js} +1 -1
  113. package/dist/components/{p-EFyZdR89.js → p-DkaiWg1V.js} +1 -1
  114. package/dist/components/{p-Dx_xz_El.js → p-DlwYHzSj.js} +1 -1
  115. package/dist/components/{p-CJ2V42sz.js → p-FK7b3BGt.js} +1 -1
  116. package/dist/components/{p-Do4UlU4e.js → p-J9_SwObO.js} +1 -1
  117. package/dist/components/{p-CxtTuKCy.js → p-JhOYwUOj.js} +1 -1
  118. package/dist/components/{p-Dw9sKOsb.js → p-SptaSMno.js} +1 -1
  119. package/dist/components/{p-KjtNlFTl.js → p-UoPj5QjH.js} +1 -1
  120. package/dist/components/{p-CYR9wbJg.js → p-dcAernE1.js} +1 -1
  121. package/dist/components/{p-BI_UUiTr.js → p-skWUIStn.js} +1 -1
  122. package/dist/components/{p-DgtrNOWm.js → p-x6doYeiI.js} +1 -1
  123. package/dist/esm/{index-D9HaikfQ.js → index-Dhio9uis.js} +1 -1
  124. package/dist/esm/index.js +42 -4
  125. package/dist/esm/kritzel-active-users_42.entry.js +281 -113
  126. package/dist/esm/kritzel-brush-style.entry.js +1 -1
  127. package/dist/esm/loader.js +3 -3
  128. package/dist/esm/{schema.constants-BcT1vV4J.js → schema.constants-DiCnmIYK.js} +85 -42
  129. package/dist/esm/stencil.js +4 -4
  130. package/dist/stencil/index.esm.js +1 -1
  131. package/dist/stencil/p-DiCnmIYK.js +1 -0
  132. package/dist/stencil/p-ea76b21f.entry.js +9 -0
  133. package/dist/stencil/{p-69298b5f.entry.js → p-fb32cd8f.entry.js} +1 -1
  134. package/dist/stencil/stencil.esm.js +1 -1
  135. package/dist/types/classes/core/viewport.class.d.ts +38 -0
  136. package/dist/types/classes/objects/image.class.d.ts +15 -0
  137. package/dist/types/classes/tools/base-tool.class.d.ts +3 -0
  138. package/dist/types/classes/tools/brush-tool.class.d.ts +1 -0
  139. package/dist/types/classes/tools/eraser-tool.class.d.ts +1 -0
  140. package/dist/types/classes/tools/image-tool.class.d.ts +1 -0
  141. package/dist/types/classes/tools/line-tool.class.d.ts +1 -0
  142. package/dist/types/classes/tools/selection-tool.class.d.ts +1 -0
  143. package/dist/types/classes/tools/shape-tool.class.d.ts +1 -0
  144. package/dist/types/classes/tools/text-tool.class.d.ts +1 -0
  145. package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +13 -3
  146. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +49 -5
  147. package/dist/types/components/ui/kritzel-context-menu/kritzel-context-menu.d.ts +1 -0
  148. package/dist/types/components.d.ts +54 -20
  149. package/dist/types/configs/default-asset-storage.config.d.ts +1 -1
  150. package/dist/types/configs/default-sync.config.d.ts +1 -1
  151. package/dist/types/constants/version.d.ts +1 -1
  152. package/dist/types/interfaces/theme.interface.d.ts +8 -3
  153. package/dist/types/interfaces/tool-config.interface.d.ts +3 -6
  154. package/dist/types/interfaces/tool-type.interface.d.ts +1 -0
  155. package/dist/types/interfaces/tool.interface.d.ts +1 -0
  156. package/dist/types/stencil-public-runtime.d.ts +1 -0
  157. package/package.json +1 -1
  158. package/dist/components/p-C0wFAtT_.js +0 -1
  159. package/dist/components/p-CWgI1dA0.js +0 -1
  160. package/dist/components/p-DH-H7om7.js +0 -1
  161. package/dist/components/p-DIiGd0LS.js +0 -1
  162. package/dist/components/p-DLh8x1jK.js +0 -9
  163. package/dist/components/p-Dqjil3Hm.js +0 -1
  164. package/dist/components/p-IiG44Unz.js +0 -1
  165. package/dist/components/p-K7ySy791.js +0 -1
  166. package/dist/stencil/p-0c95e585.entry.js +0 -9
  167. package/dist/stencil/p-BcT1vV4J.js +0 -1
  168. /package/dist/components/{p-BWj1eE2b.js → p-B43upypT.js} +0 -0
  169. /package/dist/stencil/{p-D9HaikfQ.js → p-Dhio9uis.js} +0 -0
@@ -93,8 +93,18 @@ export class KritzelEngine {
93
93
  }
94
94
  /** Context menu items shown when right-clicking the canvas background. */
95
95
  globalContextMenuItems;
96
+ onGlobalContextMenuItemsChange(newValue) {
97
+ if (this.contextMenuHandler) {
98
+ this.contextMenuHandler.globalContextMenuItems = newValue ?? [];
99
+ }
100
+ }
96
101
  /** Context menu items shown when right-clicking a selected object. */
97
102
  objectContextMenuItems;
103
+ onObjectContextMenuItemsChange(newValue) {
104
+ if (this.contextMenuHandler) {
105
+ this.contextMenuHandler.objectContextMenuItems = newValue ?? [];
106
+ }
107
+ }
98
108
  /** Maximum zoom scale allowed. Clamped to the absolute maximum defined by the engine. */
99
109
  scaleMax = ABSOLUTE_SCALE_MAX;
100
110
  validateScaleMax(newValue) {
@@ -571,6 +581,9 @@ export class KritzelEngine {
571
581
  object.scale = object.scale ?? this.core.store.state.scale;
572
582
  object.zIndex = this.core.store.currentZIndex;
573
583
  object.workspaceId = this.core.store.state.activeWorkspace.id;
584
+ if (KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
585
+ await object.prepareForInsert();
586
+ }
574
587
  // Handle KritzelText: recreate the editor now that _core is available
575
588
  // The editor's dispatchTransaction callback needs _core for persisting changes
576
589
  if (KritzelClassHelper.isInstanceOf(object, 'KritzelText')) {
@@ -655,6 +668,12 @@ export class KritzelEngine {
655
668
  if (objects.length === 0) {
656
669
  return [];
657
670
  }
671
+ for (const object of objects) {
672
+ object._core = this.core;
673
+ if (KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
674
+ await object.prepareForInsert();
675
+ }
676
+ }
658
677
  this.core.store.objects.transaction(() => {
659
678
  for (const object of objects) {
660
679
  object.id = object.generateId();
@@ -819,6 +838,14 @@ export class KritzelEngine {
819
838
  this.core.rerender();
820
839
  return object;
821
840
  }
841
+ /**
842
+ * Pans the viewport to center on the given object without changing the zoom level.
843
+ * Unlike `centerObjectInViewport`, this moves the camera — not the object.
844
+ * @param object - The object whose center the viewport should pan to.
845
+ */
846
+ async panToObject(object) {
847
+ this.viewport.panTo(object.centerX, object.centerY);
848
+ }
822
849
  /**
823
850
  * Pans and zooms the viewport to fit the nearest content, with padding.
824
851
  * Useful when the user has panned away from all objects.
@@ -836,6 +863,16 @@ export class KritzelEngine {
836
863
  async centerAllObjects(animate = true) {
837
864
  return this.viewport.centerFitAllObjects(animate);
838
865
  }
866
+ /**
867
+ * Pans and zooms the viewport to fit the provided objects.
868
+ * Calculates the combined bounding box of the given objects and centers the viewport to show them.
869
+ * @param objects - The objects to center and fit in the viewport.
870
+ * @param animate - Whether to animate the viewport transition (default: true).
871
+ * @returns `true` if objects were provided and the viewport was adjusted, `false` otherwise.
872
+ */
873
+ async centerObjects(objects, animate = true) {
874
+ return this.viewport.centerFitObjects(objects, animate);
875
+ }
839
876
  /**
840
877
  * Sets the viewport to center on the given world coordinates at the specified scale.
841
878
  * @param x - X position in world coordinates to center on.
@@ -863,6 +900,22 @@ export class KritzelEngine {
863
900
  async zoomTo(scale, worldX, worldY) {
864
901
  this.viewport.zoomTo(scale, worldX, worldY);
865
902
  }
903
+ /**
904
+ * Zooms in by a fixed step, centered on the current viewport center, with a smooth animation.
905
+ * @param factor - Multiplicative zoom-in step.
906
+ * @param duration - Animation duration in milliseconds.
907
+ */
908
+ async zoomIn(factor, duration) {
909
+ this.viewport.zoomIn(factor, duration);
910
+ }
911
+ /**
912
+ * Zooms out by a fixed step, centered on the current viewport center, with a smooth animation.
913
+ * @param factor - Multiplicative zoom-out step.
914
+ * @param duration - Animation duration in milliseconds.
915
+ */
916
+ async zoomOut(factor, duration) {
917
+ this.viewport.zoomOut(factor, duration);
918
+ }
866
919
  /**
867
920
  * Returns the current viewport state including position, scale, and dimensions.
868
921
  * @returns The current viewport state.
@@ -899,11 +952,14 @@ export class KritzelEngine {
899
952
  /**
900
953
  * Captures a screenshot of the current viewport as a data URL.
901
954
  * @param format - The image format: `'png'` (default) or `'svg'`.
955
+ * @param options - Optional screenshot settings.
956
+ * @param options.includeBackground - Whether to include the canvas background in the export. Defaults to `true`. Set to `false` for a transparent background.
902
957
  * @returns A data URL string of the captured image.
903
958
  */
904
- async getScreenshot(format = 'png') {
959
+ async getScreenshot(format = 'png', options) {
905
960
  if (!this.host)
906
961
  return null;
962
+ const includeBackground = options?.includeBackground ?? true;
907
963
  // Save critical state before screenshot to restore after
908
964
  const savedState = {
909
965
  objects: this.core.store.objects,
@@ -915,7 +971,7 @@ export class KritzelEngine {
915
971
  translateY: this.core.store.state.translateY,
916
972
  scale: this.core.store.state.scale,
917
973
  };
918
- const options = {
974
+ const screenshotOptions = {
919
975
  filter: (node) => {
920
976
  // Exclude the context menu, debug panel, and awareness cursors from the screenshot
921
977
  if (node.tagName === 'KRITZEL-CONTEXT-MENU') {
@@ -930,13 +986,16 @@ export class KritzelEngine {
930
986
  return true;
931
987
  },
932
988
  };
989
+ if (!includeBackground) {
990
+ screenshotOptions.backgroundColor = 'transparent';
991
+ }
933
992
  let result;
934
993
  try {
935
994
  if (format === 'svg') {
936
- result = await toSvg(this.host, options);
995
+ result = await toSvg(this.host, screenshotOptions);
937
996
  }
938
997
  else {
939
- result = await toPng(this.host, options);
998
+ result = await toPng(this.host, screenshotOptions);
940
999
  }
941
1000
  }
942
1001
  finally {
@@ -953,14 +1012,18 @@ export class KritzelEngine {
953
1012
  }
954
1013
  return result;
955
1014
  }
956
- /** Exports the current viewport as a PNG file and triggers a browser download. */
957
- async exportViewportAsPng() {
1015
+ /**
1016
+ * Exports the current viewport as a PNG file and triggers a browser download.
1017
+ * @param options - Optional export settings.
1018
+ * @param options.includeBackground - Whether to include the canvas background. Defaults to `true`.
1019
+ */
1020
+ async exportViewportAsPng(options) {
958
1021
  try {
959
1022
  const activeWorkspaceName = this.core.store.state?.activeWorkspace?.name || 'workspace';
960
1023
  // timestamp format: YYYY-MM-DDTHH-mm-ss-sssZ, clearing colons/dots for safe filename
961
1024
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
962
1025
  const filename = `${activeWorkspaceName}-${timestamp}.png`;
963
- const dataUrl = await this.getScreenshot('png');
1026
+ const dataUrl = await this.getScreenshot('png', options);
964
1027
  if (!dataUrl) {
965
1028
  console.error('Failed to export viewport as PNG: screenshot could not be generated');
966
1029
  return;
@@ -974,14 +1037,18 @@ export class KritzelEngine {
974
1037
  console.error('Failed to export viewport as PNG:', error);
975
1038
  }
976
1039
  }
977
- /** Exports the current viewport as an SVG file and triggers a browser download. */
978
- async exportViewportAsSvg() {
1040
+ /**
1041
+ * Exports the current viewport as an SVG file and triggers a browser download.
1042
+ * @param options - Optional export settings.
1043
+ * @param options.includeBackground - Whether to include the canvas background. Defaults to `true`.
1044
+ */
1045
+ async exportViewportAsSvg(options) {
979
1046
  try {
980
1047
  const activeWorkspaceName = this.core.store.state?.activeWorkspace?.name || 'workspace';
981
1048
  // timestamp format: YYYY-MM-DDTHH-mm-ss-sssZ, clearing colons/dots for safe filename
982
1049
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
983
1050
  const filename = `${activeWorkspaceName}-${timestamp}.svg`;
984
- const dataUrl = await this.getScreenshot('svg');
1051
+ const dataUrl = await this.getScreenshot('svg', options);
985
1052
  if (!dataUrl) {
986
1053
  console.error('Failed to export viewport as SVG: screenshot could not be generated');
987
1054
  return;
@@ -2442,7 +2509,7 @@ export class KritzelEngine {
2442
2509
  "setter": false,
2443
2510
  "reflect": false,
2444
2511
  "attribute": "scale-max",
2445
- "defaultValue": "ABSOLUTE_SCALE_MAX"
2512
+ "defaultValue": "1000"
2446
2513
  },
2447
2514
  "scaleMin": {
2448
2515
  "type": "number",
@@ -2462,7 +2529,7 @@ export class KritzelEngine {
2462
2529
  "setter": false,
2463
2530
  "reflect": false,
2464
2531
  "attribute": "scale-min",
2465
- "defaultValue": "ABSOLUTE_SCALE_MIN"
2532
+ "defaultValue": "0.0001"
2466
2533
  },
2467
2534
  "cursorTarget": {
2468
2535
  "type": "unknown",
@@ -3713,6 +3780,12 @@ export class KritzelEngine {
3713
3780
  "id": "src/classes/objects/base-object.class.ts::KritzelBaseObject",
3714
3781
  "referenceLocation": "KritzelBaseObject"
3715
3782
  },
3783
+ "KritzelImage": {
3784
+ "location": "import",
3785
+ "path": "../../../classes/objects/image.class",
3786
+ "id": "src/classes/objects/image.class.ts::KritzelImage",
3787
+ "referenceLocation": "KritzelImage"
3788
+ },
3716
3789
  "KritzelText": {
3717
3790
  "location": "import",
3718
3791
  "path": "../../../classes/objects/text.class",
@@ -3768,6 +3841,12 @@ export class KritzelEngine {
3768
3841
  "id": "src/classes/objects/base-object.class.ts::KritzelBaseObject",
3769
3842
  "referenceLocation": "KritzelBaseObject"
3770
3843
  },
3844
+ "KritzelImage": {
3845
+ "location": "import",
3846
+ "path": "../../../classes/objects/image.class",
3847
+ "id": "src/classes/objects/image.class.ts::KritzelImage",
3848
+ "referenceLocation": "KritzelImage"
3849
+ },
3771
3850
  "KritzelText": {
3772
3851
  "location": "import",
3773
3852
  "path": "../../../classes/objects/text.class",
@@ -4077,6 +4156,36 @@ export class KritzelEngine {
4077
4156
  }]
4078
4157
  }
4079
4158
  },
4159
+ "panToObject": {
4160
+ "complexType": {
4161
+ "signature": "(object: KritzelBaseObject) => Promise<void>",
4162
+ "parameters": [{
4163
+ "name": "object",
4164
+ "type": "KritzelBaseObject<HTMLElement | SVGElement>",
4165
+ "docs": "- The object whose center the viewport should pan to."
4166
+ }],
4167
+ "references": {
4168
+ "Promise": {
4169
+ "location": "global",
4170
+ "id": "global::Promise"
4171
+ },
4172
+ "KritzelBaseObject": {
4173
+ "location": "import",
4174
+ "path": "../../../classes/objects/base-object.class",
4175
+ "id": "src/classes/objects/base-object.class.ts::KritzelBaseObject",
4176
+ "referenceLocation": "KritzelBaseObject"
4177
+ }
4178
+ },
4179
+ "return": "Promise<void>"
4180
+ },
4181
+ "docs": {
4182
+ "text": "Pans the viewport to center on the given object without changing the zoom level.\nUnlike `centerObjectInViewport`, this moves the camera \u2014 not the object.",
4183
+ "tags": [{
4184
+ "name": "param",
4185
+ "text": "object - The object whose center the viewport should pan to."
4186
+ }]
4187
+ }
4188
+ },
4080
4189
  "backToContent": {
4081
4190
  "complexType": {
4082
4191
  "signature": "() => Promise<boolean>",
@@ -4124,6 +4233,46 @@ export class KritzelEngine {
4124
4233
  }]
4125
4234
  }
4126
4235
  },
4236
+ "centerObjects": {
4237
+ "complexType": {
4238
+ "signature": "(objects: KritzelBaseObject[], animate?: boolean) => Promise<boolean>",
4239
+ "parameters": [{
4240
+ "name": "objects",
4241
+ "type": "KritzelBaseObject<HTMLElement | SVGElement>[]",
4242
+ "docs": "- The objects to center and fit in the viewport."
4243
+ }, {
4244
+ "name": "animate",
4245
+ "type": "boolean",
4246
+ "docs": "- Whether to animate the viewport transition (default: true)."
4247
+ }],
4248
+ "references": {
4249
+ "Promise": {
4250
+ "location": "global",
4251
+ "id": "global::Promise"
4252
+ },
4253
+ "KritzelBaseObject": {
4254
+ "location": "import",
4255
+ "path": "../../../classes/objects/base-object.class",
4256
+ "id": "src/classes/objects/base-object.class.ts::KritzelBaseObject",
4257
+ "referenceLocation": "KritzelBaseObject"
4258
+ }
4259
+ },
4260
+ "return": "Promise<boolean>"
4261
+ },
4262
+ "docs": {
4263
+ "text": "Pans and zooms the viewport to fit the provided objects.\nCalculates the combined bounding box of the given objects and centers the viewport to show them.",
4264
+ "tags": [{
4265
+ "name": "param",
4266
+ "text": "objects - The objects to center and fit in the viewport."
4267
+ }, {
4268
+ "name": "param",
4269
+ "text": "animate - Whether to animate the viewport transition (default: true)."
4270
+ }, {
4271
+ "name": "returns",
4272
+ "text": "`true` if objects were provided and the viewport was adjusted, `false` otherwise."
4273
+ }]
4274
+ }
4275
+ },
4127
4276
  "setViewport": {
4128
4277
  "complexType": {
4129
4278
  "signature": "(x: number, y: number, scale: number) => Promise<void>",
@@ -4231,6 +4380,68 @@ export class KritzelEngine {
4231
4380
  }]
4232
4381
  }
4233
4382
  },
4383
+ "zoomIn": {
4384
+ "complexType": {
4385
+ "signature": "(factor: number, duration: number) => Promise<void>",
4386
+ "parameters": [{
4387
+ "name": "factor",
4388
+ "type": "number",
4389
+ "docs": "- Multiplicative zoom-in step."
4390
+ }, {
4391
+ "name": "duration",
4392
+ "type": "number",
4393
+ "docs": "- Animation duration in milliseconds."
4394
+ }],
4395
+ "references": {
4396
+ "Promise": {
4397
+ "location": "global",
4398
+ "id": "global::Promise"
4399
+ }
4400
+ },
4401
+ "return": "Promise<void>"
4402
+ },
4403
+ "docs": {
4404
+ "text": "Zooms in by a fixed step, centered on the current viewport center, with a smooth animation.",
4405
+ "tags": [{
4406
+ "name": "param",
4407
+ "text": "factor - Multiplicative zoom-in step."
4408
+ }, {
4409
+ "name": "param",
4410
+ "text": "duration - Animation duration in milliseconds."
4411
+ }]
4412
+ }
4413
+ },
4414
+ "zoomOut": {
4415
+ "complexType": {
4416
+ "signature": "(factor: number, duration: number) => Promise<void>",
4417
+ "parameters": [{
4418
+ "name": "factor",
4419
+ "type": "number",
4420
+ "docs": "- Multiplicative zoom-out step."
4421
+ }, {
4422
+ "name": "duration",
4423
+ "type": "number",
4424
+ "docs": "- Animation duration in milliseconds."
4425
+ }],
4426
+ "references": {
4427
+ "Promise": {
4428
+ "location": "global",
4429
+ "id": "global::Promise"
4430
+ }
4431
+ },
4432
+ "return": "Promise<void>"
4433
+ },
4434
+ "docs": {
4435
+ "text": "Zooms out by a fixed step, centered on the current viewport center, with a smooth animation.",
4436
+ "tags": [{
4437
+ "name": "param",
4438
+ "text": "factor - Multiplicative zoom-out step."
4439
+ }, {
4440
+ "name": "param",
4441
+ "text": "duration - Animation duration in milliseconds."
4442
+ }]
4443
+ }
4444
+ },
4234
4445
  "getViewport": {
4235
4446
  "complexType": {
4236
4447
  "signature": "() => Promise<KritzelViewportState>",
@@ -4389,17 +4600,25 @@ export class KritzelEngine {
4389
4600
  },
4390
4601
  "getScreenshot": {
4391
4602
  "complexType": {
4392
- "signature": "(format?: \"png\" | \"svg\") => Promise<string | null>",
4603
+ "signature": "(format?: \"png\" | \"svg\", options?: { includeBackground?: boolean; }) => Promise<string | null>",
4393
4604
  "parameters": [{
4394
4605
  "name": "format",
4395
4606
  "type": "\"svg\" | \"png\"",
4396
4607
  "docs": "- The image format: `'png'` (default) or `'svg'`."
4608
+ }, {
4609
+ "name": "options",
4610
+ "type": "{ includeBackground?: boolean; }",
4611
+ "docs": "- Optional screenshot settings."
4397
4612
  }],
4398
4613
  "references": {
4399
4614
  "Promise": {
4400
4615
  "location": "global",
4401
4616
  "id": "global::Promise"
4402
4617
  },
4618
+ "Record": {
4619
+ "location": "global",
4620
+ "id": "global::Record"
4621
+ },
4403
4622
  "HTMLElement": {
4404
4623
  "location": "global",
4405
4624
  "id": "global::HTMLElement"
@@ -4412,6 +4631,12 @@ export class KritzelEngine {
4412
4631
  "tags": [{
4413
4632
  "name": "param",
4414
4633
  "text": "format - The image format: `'png'` (default) or `'svg'`."
4634
+ }, {
4635
+ "name": "param",
4636
+ "text": "options - Optional screenshot settings."
4637
+ }, {
4638
+ "name": "param",
4639
+ "text": "options.includeBackground - Whether to include the canvas background in the export. Defaults to `true`. Set to `false` for a transparent background."
4415
4640
  }, {
4416
4641
  "name": "returns",
4417
4642
  "text": "A data URL string of the captured image."
@@ -4420,8 +4645,12 @@ export class KritzelEngine {
4420
4645
  },
4421
4646
  "exportViewportAsPng": {
4422
4647
  "complexType": {
4423
- "signature": "() => Promise<void>",
4424
- "parameters": [],
4648
+ "signature": "(options?: { includeBackground?: boolean; }) => Promise<void>",
4649
+ "parameters": [{
4650
+ "name": "options",
4651
+ "type": "{ includeBackground?: boolean; }",
4652
+ "docs": "- Optional export settings."
4653
+ }],
4425
4654
  "references": {
4426
4655
  "Promise": {
4427
4656
  "location": "global",
@@ -4432,13 +4661,23 @@ export class KritzelEngine {
4432
4661
  },
4433
4662
  "docs": {
4434
4663
  "text": "Exports the current viewport as a PNG file and triggers a browser download.",
4435
- "tags": []
4664
+ "tags": [{
4665
+ "name": "param",
4666
+ "text": "options - Optional export settings."
4667
+ }, {
4668
+ "name": "param",
4669
+ "text": "options.includeBackground - Whether to include the canvas background. Defaults to `true`."
4670
+ }]
4436
4671
  }
4437
4672
  },
4438
4673
  "exportViewportAsSvg": {
4439
4674
  "complexType": {
4440
- "signature": "() => Promise<void>",
4441
- "parameters": [],
4675
+ "signature": "(options?: { includeBackground?: boolean; }) => Promise<void>",
4676
+ "parameters": [{
4677
+ "name": "options",
4678
+ "type": "{ includeBackground?: boolean; }",
4679
+ "docs": "- Optional export settings."
4680
+ }],
4442
4681
  "references": {
4443
4682
  "Promise": {
4444
4683
  "location": "global",
@@ -4449,7 +4688,13 @@ export class KritzelEngine {
4449
4688
  },
4450
4689
  "docs": {
4451
4690
  "text": "Exports the current viewport as an SVG file and triggers a browser download.",
4452
- "tags": []
4691
+ "tags": [{
4692
+ "name": "param",
4693
+ "text": "options - Optional export settings."
4694
+ }, {
4695
+ "name": "param",
4696
+ "text": "options.includeBackground - Whether to include the canvas background. Defaults to `true`."
4697
+ }]
4453
4698
  }
4454
4699
  },
4455
4700
  "getSelectedObjectsAsSvgString": {
@@ -4976,6 +5221,12 @@ export class KritzelEngine {
4976
5221
  }, {
4977
5222
  "propName": "user",
4978
5223
  "methodName": "onUserChange"
5224
+ }, {
5225
+ "propName": "globalContextMenuItems",
5226
+ "methodName": "onGlobalContextMenuItemsChange"
5227
+ }, {
5228
+ "propName": "objectContextMenuItems",
5229
+ "methodName": "onObjectContextMenuItemsChange"
4979
5230
  }, {
4980
5231
  "propName": "scaleMax",
4981
5232
  "methodName": "validateScaleMax"
@@ -9,7 +9,7 @@
9
9
  display: flex;
10
10
  align-items: center;
11
11
  border: 1px solid var(--kritzel-dropdown-border-color, #ebebeb);
12
- border-radius: 6px;
12
+ border-radius: var(--kritzel-dropdown-border-radius, 6px);
13
13
  overflow: visible;
14
14
  height: 38px;
15
15
  width: 100%;
@@ -35,7 +35,7 @@
35
35
  height: 100%;
36
36
  width: 100%;
37
37
  box-sizing: border-box;
38
- border-radius: 6px;
38
+ border-radius: var(--kritzel-dropdown-border-radius, 6px);
39
39
  border: none;
40
40
  background-color: var(--kritzel-dropdown-background, #ffffff);
41
41
  cursor: var(--kritzel-global-pointer-cursor, pointer);
@@ -103,7 +103,7 @@
103
103
  list-style: none;
104
104
  background-color: var(--kritzel-dropdown-background, #ffffff);
105
105
  border: 1px solid var(--kritzel-global-border-color, #ebebeb);
106
- border-radius: 6px;
106
+ border-radius: var(--kritzel-dropdown-menu-border-radius, var(--kritzel-dropdown-border-radius, 6px));
107
107
  box-shadow: var(--kritzel-controls-box-shadow, 0 4px 12px rgba(0, 0, 0, 0.15));
108
108
  z-index: 1000;
109
109
  max-height: 240px;
@@ -18,7 +18,7 @@
18
18
  display: flex;
19
19
  align-items: center;
20
20
  border: 1px solid var(--kritzel-text-input-border-color, #ebebeb);
21
- border-radius: 6px;
21
+ border-radius: var(--kritzel-text-input-border-radius, 6px);
22
22
  overflow: hidden;
23
23
  background: var(--kritzel-text-input-background, #ffffff);
24
24
  transition: border-color 150ms ease;
@@ -23,7 +23,7 @@
23
23
  flex: 1;
24
24
  padding: 8px 36px 8px 12px;
25
25
  border: 1px solid var(--kritzel-numeric-input-border-color, #ebebeb);
26
- border-radius: 6px;
26
+ border-radius: var(--kritzel-numeric-input-border-radius, 6px);
27
27
  font-size: 14px;
28
28
  color: var(--kritzel-numeric-input-text-color, #333333);
29
29
  background-color: var(--kritzel-numeric-input-input-background, #ffffff);
@@ -66,7 +66,7 @@
66
66
  display: flex;
67
67
  flex-direction: column;
68
68
  border-left: 1px solid var(--kritzel-numeric-input-border-color, #ebebeb);
69
- border-radius: 0 5px 5px 0;
69
+ border-radius: 0 var(--kritzel-numeric-input-spinner-border-radius, 5px) var(--kritzel-numeric-input-spinner-border-radius, 5px) 0;
70
70
  overflow: hidden;
71
71
  }
72
72
 
@@ -3,6 +3,8 @@
3
3
  }
4
4
 
5
5
  .menu-container {
6
+ position: relative;
7
+ z-index: 1;
6
8
  display: flex;
7
9
  flex-direction: column;
8
10
  gap: var(--kritzel-context-menu-item-spacing, 2px);
@@ -33,6 +35,7 @@
33
35
  white-space: nowrap;
34
36
  -webkit-tap-highlight-color: transparent;
35
37
  width: 100%;
38
+ min-width: 0;
36
39
  }
37
40
 
38
41
  .menu-item:not(.disabled):hover,
@@ -68,6 +71,9 @@
68
71
 
69
72
  .label {
70
73
  flex-grow: 1;
74
+ min-width: 0;
75
+ overflow: hidden;
76
+ text-overflow: ellipsis;
71
77
  }
72
78
 
73
79
  .submenu-arrow {
@@ -85,6 +91,7 @@
85
91
  position: absolute;
86
92
  top: 0;
87
93
  left: 100%;
94
+ z-index: 2;
88
95
  margin-left: 4px;
89
96
  display: flex;
90
97
  flex-direction: column;
@@ -113,6 +113,11 @@ export class KritzelContextMenu {
113
113
  const idx = path.lastIndexOf('.');
114
114
  return idx === -1 ? '' : path.substring(0, idx);
115
115
  }
116
+ getMenuDepth(path) {
117
+ if (!path)
118
+ return 0;
119
+ return path.split('.').length;
120
+ }
116
121
  pruneStaleRefs() {
117
122
  const openPaths = new Set(this.getOpenSubmenuPaths());
118
123
  for (const key of Array.from(this.submenuRefs.keys())) {
@@ -224,7 +229,8 @@ export class KritzelContextMenu {
224
229
  }
225
230
  renderSubmenu(processedChildren, path) {
226
231
  const position = this.submenuPositions[path] === 'left' ? 'left' : 'right';
227
- return (h("div", { class: { 'submenu-container': true, 'position-left': position === 'left' }, key: `submenu-${path}`, ref: el => el && this.submenuRefs.set(path, el), onMouseEnter: () => this.handleSubmenuMouseEnter(), onMouseLeave: () => this.handleSubmenuMouseLeave(path) }, this.renderItems(processedChildren, path)));
232
+ const zIndex = this.getMenuDepth(path) + 1;
233
+ return (h("div", { class: { 'submenu-container': true, 'position-left': position === 'left' }, key: `submenu-${path}`, style: { zIndex: String(zIndex) }, ref: el => el && this.submenuRefs.set(path, el), onMouseEnter: () => this.handleSubmenuMouseEnter(), onMouseLeave: () => this.handleSubmenuMouseLeave(path) }, this.renderItems(processedChildren, path)));
228
234
  }
229
235
  render() {
230
236
  if (!this.processedItems || this.processedItems.length === 0) {
@@ -41,7 +41,7 @@
41
41
  background-color: var(--kritzel-global-primary-color, #007AFF);
42
42
  color: var(--kritzel-global-primary-text-color, #fff);
43
43
  border: none;
44
- border-radius: 8px;
44
+ border-radius: var(--kritzel-button-border-radius, 8px);
45
45
  font-size: 14px;
46
46
  font-weight: 600;
47
47
  cursor: pointer;
@@ -237,7 +237,7 @@ export class KritzelToolConfig {
237
237
  "mutable": true,
238
238
  "complexType": {
239
239
  "original": "ConfigurableTool",
240
- "resolved": "KritzelBrushTool | KritzelLineTool | KritzelSelectionTool | KritzelShapeTool | KritzelTextTool",
240
+ "resolved": "KritzelBaseTool",
241
241
  "references": {
242
242
  "ConfigurableTool": {
243
243
  "location": "import",
@@ -348,7 +348,7 @@ export class KritzelToolConfig {
348
348
  },
349
349
  "complexType": {
350
350
  "original": "ConfigurableTool",
351
- "resolved": "KritzelBrushTool | KritzelLineTool | KritzelSelectionTool | KritzelShapeTool | KritzelTextTool",
351
+ "resolved": "KritzelBaseTool",
352
352
  "references": {
353
353
  "ConfigurableTool": {
354
354
  "location": "import",
@@ -1,4 +1,3 @@
1
- import { IndexedDBAssetProvider } from "../classes/providers/assets/indexeddb-asset-provider.class";
2
1
  /**
3
2
  * Default asset storage configuration. Stores bytes in IndexedDB only,
4
3
  * which provides offline-friendly behavior out of the box. Applications
@@ -6,5 +5,5 @@ import { IndexedDBAssetProvider } from "../classes/providers/assets/indexeddb-as
6
5
  * (e.g. HttpAssetProvider) so images are available across devices.
7
6
  */
8
7
  export const DEFAULT_ASSET_STORAGE_CONFIG = {
9
- providers: [IndexedDBAssetProvider],
8
+ providers: [],
10
9
  };
@@ -1,9 +1,6 @@
1
- import { IndexedDBSyncProvider } from "../classes/providers/sync/indexeddb-sync-provider.class";
2
1
  /**
3
- * Default sync configuration - IndexedDB
2
+ * Default sync configuration - None
4
3
  */
5
4
  export const DEFAULT_SYNC_CONFIG = {
6
- providers: [
7
- IndexedDBSyncProvider
8
- ],
5
+ providers: [],
9
6
  };
@@ -3,4 +3,4 @@
3
3
  * This file is auto-generated by the version bump scripts.
4
4
  * Do not modify manually.
5
5
  */
6
- export const KRITZEL_VERSION = '0.3.12';
6
+ export const KRITZEL_VERSION = '0.3.14';