kritzel-stencil 0.3.11 → 0.3.13

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 (178) 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 +344 -138
  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-BNMNpzvA.js → schema.constants-CMFOYyBj.js} +26 -43
  7. package/dist/cjs/stencil.cjs.js +3 -3
  8. package/dist/collection/classes/core/viewport.class.js +16 -8
  9. package/dist/collection/classes/objects/shape.class.js +3 -2
  10. package/dist/collection/classes/tools/base-tool.class.js +2 -0
  11. package/dist/collection/classes/tools/brush-tool.class.js +1 -0
  12. package/dist/collection/classes/tools/eraser-tool.class.js +1 -0
  13. package/dist/collection/classes/tools/image-tool.class.js +1 -0
  14. package/dist/collection/classes/tools/line-tool.class.js +1 -0
  15. package/dist/collection/classes/tools/selection-tool.class.js +1 -0
  16. package/dist/collection/classes/tools/shape-tool.class.js +1 -0
  17. package/dist/collection/classes/tools/text-tool.class.js +1 -0
  18. package/dist/collection/collection-manifest.json +1 -1
  19. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +166 -22
  20. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +408 -37
  21. package/dist/collection/components/shared/kritzel-dropdown/kritzel-dropdown.css +3 -3
  22. package/dist/collection/components/shared/kritzel-input/kritzel-input.css +1 -1
  23. package/dist/collection/components/shared/kritzel-numeric-input/kritzel-numeric-input.css +2 -2
  24. package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.css +7 -0
  25. package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.js +7 -1
  26. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +27 -6
  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-brush-tool.config.js +1 -0
  31. package/dist/collection/configs/default-line-tool.config.js +1 -0
  32. package/dist/collection/configs/default-shape-tool.config.js +1 -0
  33. package/dist/collection/configs/default-sync.config.js +2 -5
  34. package/dist/collection/configs/default-text-tool.config.js +1 -0
  35. package/dist/collection/constants/version.js +1 -1
  36. package/dist/collection/helpers/tool-config.helper.js +58 -65
  37. package/dist/collection/interfaces/tool-type.interface.js +1 -0
  38. package/dist/collection/themes/dark-theme.js +5 -0
  39. package/dist/collection/themes/light-theme.js +5 -0
  40. package/dist/components/index.js +1 -1
  41. package/dist/components/kritzel-active-users.js +1 -1
  42. package/dist/components/kritzel-avatar.js +1 -1
  43. package/dist/components/kritzel-awareness-cursors.js +1 -1
  44. package/dist/components/kritzel-back-to-content.js +1 -1
  45. package/dist/components/kritzel-brush-style.js +1 -1
  46. package/dist/components/kritzel-button.js +1 -1
  47. package/dist/components/kritzel-color-palette.js +1 -1
  48. package/dist/components/kritzel-color.js +1 -1
  49. package/dist/components/kritzel-context-menu.js +1 -1
  50. package/dist/components/kritzel-controls.js +1 -1
  51. package/dist/components/kritzel-current-user-dialog.js +1 -1
  52. package/dist/components/kritzel-current-user.js +1 -1
  53. package/dist/components/kritzel-cursor-trail.js +1 -1
  54. package/dist/components/kritzel-dialog.js +1 -1
  55. package/dist/components/kritzel-dropdown.js +1 -1
  56. package/dist/components/kritzel-editor.js +1 -1
  57. package/dist/components/kritzel-engine.js +1 -1
  58. package/dist/components/kritzel-export.js +1 -1
  59. package/dist/components/kritzel-font-family.js +1 -1
  60. package/dist/components/kritzel-font-size.js +1 -1
  61. package/dist/components/kritzel-font.js +1 -1
  62. package/dist/components/kritzel-icon.js +1 -1
  63. package/dist/components/kritzel-input.js +1 -1
  64. package/dist/components/kritzel-line-endings.js +1 -1
  65. package/dist/components/kritzel-login-dialog.js +1 -1
  66. package/dist/components/kritzel-master-detail.js +1 -1
  67. package/dist/components/kritzel-menu-item.js +1 -1
  68. package/dist/components/kritzel-menu.js +1 -1
  69. package/dist/components/kritzel-more-menu.js +1 -1
  70. package/dist/components/kritzel-numeric-input.js +1 -1
  71. package/dist/components/kritzel-opacity-slider.js +1 -1
  72. package/dist/components/kritzel-pill-tabs.js +1 -1
  73. package/dist/components/kritzel-portal.js +1 -1
  74. package/dist/components/kritzel-settings.js +1 -1
  75. package/dist/components/kritzel-shape-fill.js +1 -1
  76. package/dist/components/kritzel-share-dialog.js +1 -1
  77. package/dist/components/kritzel-slide-toggle.js +1 -1
  78. package/dist/components/kritzel-split-button.js +1 -1
  79. package/dist/components/kritzel-stroke-size.js +1 -1
  80. package/dist/components/kritzel-tool-config.js +1 -1
  81. package/dist/components/kritzel-tooltip.js +1 -1
  82. package/dist/components/kritzel-utility-panel.js +1 -1
  83. package/dist/components/kritzel-workspace-manager.js +1 -1
  84. package/dist/components/p-2xYAGd0I.js +1 -0
  85. package/dist/components/{p-DdmJquQr.js → p-B2Os1ya_.js} +1 -1
  86. package/dist/components/p-B2w8X7vn.js +1 -0
  87. package/dist/components/{p-DRB3TZzI.js → p-B4b6TDxp.js} +1 -1
  88. package/dist/components/p-B5xxfwKF.js +1 -0
  89. package/dist/components/p-B9hLySCl.js +1 -0
  90. package/dist/components/{p-D0aom7Yu.js → p-BFYtCsZu.js} +1 -1
  91. package/dist/components/{p-CARNM9pf.js → p-BFoK4W--.js} +1 -1
  92. package/dist/components/{p-x38RbGJA.js → p-BYmp9Ovv.js} +1 -1
  93. package/dist/components/{p-KVG5rztB.js → p-BbactVA0.js} +1 -1
  94. package/dist/components/{p-B_JH91jB.js → p-BfNHpqQ8.js} +1 -1
  95. package/dist/components/{p-DXgUuzXW.js → p-BiG1dxPS.js} +1 -1
  96. package/dist/components/{p-Dov3qOAR.js → p-Bj2laX89.js} +1 -1
  97. package/dist/components/{p-Cr7xOsIZ.js → p-BqwqGFQY.js} +1 -1
  98. package/dist/components/{p-DmTG0Y5h.js → p-BzYU3-MJ.js} +1 -1
  99. package/dist/components/p-C-aFOO5p.js +1 -0
  100. package/dist/components/p-C0TN5IAi.js +1 -0
  101. package/dist/components/{p-RnuCSIt-.js → p-C2SX-XRr.js} +1 -1
  102. package/dist/components/{p-guqEWGgV.js → p-CFgkUYoO.js} +1 -1
  103. package/dist/components/{p-BTSOqHMI.js → p-CHrSFOSI.js} +1 -1
  104. package/dist/components/p-CJOhfMU5.js +1 -0
  105. package/dist/components/{p-DJLJfKY2.js → p-COLHjboZ.js} +1 -1
  106. package/dist/components/{p-CKY7AvGR.js → p-COgo9OWy.js} +1 -1
  107. package/dist/components/p-CVzH1Oil.js +1 -0
  108. package/dist/components/{p-DhAM4qeQ.js → p-CXpv9Rxe.js} +1 -1
  109. package/dist/components/{p-Bp3kdH4l.js → p-CcyIAi9S.js} +1 -1
  110. package/dist/components/{p-COIxq81R.js → p-CmuNn1Tc.js} +1 -1
  111. package/dist/components/{p-DfH7YY2C.js → p-D-sRVAbQ.js} +1 -1
  112. package/dist/components/{p-ZgZqbJ58.js → p-DDYoDSrm.js} +1 -1
  113. package/dist/components/{p-u0b2RJAn.js → p-DEy7zJCe.js} +1 -1
  114. package/dist/components/{p-BPEn0_hr.js → p-DM11KXUT.js} +1 -1
  115. package/dist/components/{p-CJERvHdy.js → p-DbB730vO.js} +1 -1
  116. package/dist/components/{p-C8ggg-5h.js → p-Df3BwVGy.js} +1 -1
  117. package/dist/components/{p-Dx_xz_El.js → p-DlwYHzSj.js} +1 -1
  118. package/dist/components/p-DplAQ6jk.js +9 -0
  119. package/dist/components/{p-CJ2V42sz.js → p-FK7b3BGt.js} +1 -1
  120. package/dist/components/{p-CxtTuKCy.js → p-JhOYwUOj.js} +1 -1
  121. package/dist/components/{p-Dw9sKOsb.js → p-SptaSMno.js} +1 -1
  122. package/dist/components/{p-KjtNlFTl.js → p-UoPj5QjH.js} +1 -1
  123. package/dist/components/{p-CYR9wbJg.js → p-dcAernE1.js} +1 -1
  124. package/dist/components/{p-B0VnbmWu.js → p-ijIqLY9g.js} +1 -1
  125. package/dist/components/{p-BI_UUiTr.js → p-skWUIStn.js} +1 -1
  126. package/dist/components/{p-DgtrNOWm.js → p-x6doYeiI.js} +1 -1
  127. package/dist/esm/{index-D9HaikfQ.js → index-Dhio9uis.js} +1 -1
  128. package/dist/esm/index.js +42 -4
  129. package/dist/esm/kritzel-active-users_42.entry.js +344 -138
  130. package/dist/esm/kritzel-brush-style.entry.js +1 -1
  131. package/dist/esm/loader.js +3 -3
  132. package/dist/esm/{schema.constants-CqBoZbmA.js → schema.constants-NrtFvKER.js} +27 -43
  133. package/dist/esm/stencil.js +4 -4
  134. package/dist/stencil/index.esm.js +1 -1
  135. package/dist/stencil/p-9adee165.entry.js +9 -0
  136. package/dist/stencil/p-NrtFvKER.js +1 -0
  137. package/dist/stencil/{p-69298b5f.entry.js → p-fb32cd8f.entry.js} +1 -1
  138. package/dist/stencil/stencil.esm.js +1 -1
  139. package/dist/types/classes/core/viewport.class.d.ts +8 -0
  140. package/dist/types/classes/objects/base-object.class.d.ts +1 -1
  141. package/dist/types/classes/objects/shape.class.d.ts +1 -1
  142. package/dist/types/classes/tools/base-tool.class.d.ts +3 -0
  143. package/dist/types/classes/tools/brush-tool.class.d.ts +1 -0
  144. package/dist/types/classes/tools/eraser-tool.class.d.ts +1 -0
  145. package/dist/types/classes/tools/image-tool.class.d.ts +1 -0
  146. package/dist/types/classes/tools/line-tool.class.d.ts +1 -0
  147. package/dist/types/classes/tools/selection-tool.class.d.ts +1 -0
  148. package/dist/types/classes/tools/shape-tool.class.d.ts +1 -0
  149. package/dist/types/classes/tools/text-tool.class.d.ts +1 -0
  150. package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +5 -0
  151. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +48 -0
  152. package/dist/types/components/ui/kritzel-context-menu/kritzel-context-menu.d.ts +1 -0
  153. package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +1 -0
  154. package/dist/types/components.d.ts +69 -14
  155. package/dist/types/configs/default-asset-storage.config.d.ts +1 -1
  156. package/dist/types/configs/default-sync.config.d.ts +1 -1
  157. package/dist/types/constants/version.d.ts +1 -1
  158. package/dist/types/interfaces/object.interface.d.ts +1 -1
  159. package/dist/types/interfaces/theme.interface.d.ts +8 -3
  160. package/dist/types/interfaces/tool-config.interface.d.ts +3 -6
  161. package/dist/types/interfaces/tool-type.interface.d.ts +1 -0
  162. package/dist/types/interfaces/tool.interface.d.ts +1 -0
  163. package/dist/types/interfaces/toolbar-control.interface.d.ts +4 -0
  164. package/dist/types/stencil-public-runtime.d.ts +1 -0
  165. package/package.json +1 -1
  166. package/dist/components/p-BFgWBbpu.js +0 -1
  167. package/dist/components/p-C0wFAtT_.js +0 -1
  168. package/dist/components/p-CB7ynHtI.js +0 -1
  169. package/dist/components/p-CWgI1dA0.js +0 -1
  170. package/dist/components/p-D15NO5kE.js +0 -1
  171. package/dist/components/p-DH-H7om7.js +0 -1
  172. package/dist/components/p-DLlIaDNn.js +0 -9
  173. package/dist/components/p-IiG44Unz.js +0 -1
  174. package/dist/components/p-K7ySy791.js +0 -1
  175. package/dist/stencil/p-94992a11.entry.js +0 -9
  176. package/dist/stencil/p-CqBoZbmA.js +0 -1
  177. /package/dist/components/{p-BWj1eE2b.js → p-B43upypT.js} +0 -0
  178. /package/dist/stencil/{p-D9HaikfQ.js → p-Dhio9uis.js} +0 -0
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-CFnj_FXt.js');
4
- var schema_constants = require('./schema.constants-BNMNpzvA.js');
3
+ var index = require('./index-Xav9JFHg.js');
4
+ var schema_constants = require('./schema.constants-CMFOYyBj.js');
5
5
  var Y = require('yjs');
6
6
  require('y-indexeddb');
7
7
  require('y-websocket');
@@ -629,7 +629,7 @@ const KritzelColorPalette = class {
629
629
  };
630
630
  KritzelColorPalette.style = kritzelColorPaletteCss();
631
631
 
632
- const kritzelContextMenuCss = () => `:host{display:block}.menu-container{display:flex;flex-direction:column;gap:var(--kritzel-context-menu-item-spacing, 2px);background-color:var(--kritzel-context-menu-background-color, #ffffff);border-radius:var(--kritzel-context-menu-border-radius, 12px);box-shadow:var(--kritzel-context-menu-box-shadow, 0 1px 6px rgba(0, 0, 0, 0.12));border:var(--kritzel-context-menu-border, 1px solid #ebebeb);padding:var(--kritzel-context-menu-padding, 4px);min-width:var(--kritzel-context-menu-min-width, 140px)}.menu-item-wrapper{position:relative}.menu-item{display:flex;align-items:center;gap:var(--kritzel-context-menu-item-gap, 8px);background:none;border:none;text-align:left;padding:var(--kritzel-context-menu-item-padding, 8px);border-radius:var(--kritzel-context-menu-item-border-radius, 12px);cursor:var(--kritzel-global-pointer-cursor, pointer);font-size:var(--kritzel-context-menu-item-font-size, 14px);color:var(--kritzel-context-menu-item-color, #333333);white-space:nowrap;-webkit-tap-highlight-color:transparent;width:100%}.menu-item:not(.disabled):hover,.menu-item.submenu-open{background-color:var(--kritzel-context-menu-item-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.menu-item:not(.disabled):active{background-color:var(--kritzel-context-menu-item-active-background-color, hsl(0, 0%, 0%, 8.6%))}.menu-item.disabled{color:var(--kritzel-context-menu-item-disabled-color, #aaaaaa)}.menu-item.has-children.disabled{cursor:var(--kritzel-global-pointer-cursor, pointer);color:var(--kritzel-context-menu-item-color, #333333)}.menu-item kritzel-icon{opacity:0.8;flex-shrink:0}.menu-item.disabled kritzel-icon{opacity:0.4}.menu-item.has-children.disabled kritzel-icon{opacity:0.8}.label{flex-grow:1}.submenu-arrow{margin-left:auto;opacity:0.5}.menu-divider{height:1px;background-color:var(--kritzel-context-menu-divider-color, rgba(0, 0, 0, 0.1));margin:var(--kritzel-context-menu-divider-margin, 4px 8px)}.submenu-container{position:absolute;top:0;left:100%;margin-left:4px;display:flex;flex-direction:column;gap:var(--kritzel-context-menu-item-spacing, 2px);background-color:var(--kritzel-context-menu-background-color, #ffffff);border-radius:var(--kritzel-context-menu-border-radius, 12px);box-shadow:var(--kritzel-context-menu-box-shadow, 0 1px 6px rgba(0, 0, 0, 0.12));border:var(--kritzel-context-menu-border, 1px solid #ebebeb);padding:var(--kritzel-context-menu-padding, 4px);min-width:120px}.submenu-container.position-left{left:auto;right:100%;margin-left:0;margin-right:4px}`;
632
+ const kritzelContextMenuCss = () => `:host{display:block}.menu-container{position:relative;z-index:1;display:flex;flex-direction:column;gap:var(--kritzel-context-menu-item-spacing, 2px);background-color:var(--kritzel-context-menu-background-color, #ffffff);border-radius:var(--kritzel-context-menu-border-radius, 12px);box-shadow:var(--kritzel-context-menu-box-shadow, 0 1px 6px rgba(0, 0, 0, 0.12));border:var(--kritzel-context-menu-border, 1px solid #ebebeb);padding:var(--kritzel-context-menu-padding, 4px);min-width:var(--kritzel-context-menu-min-width, 140px)}.menu-item-wrapper{position:relative}.menu-item{display:flex;align-items:center;gap:var(--kritzel-context-menu-item-gap, 8px);background:none;border:none;text-align:left;padding:var(--kritzel-context-menu-item-padding, 8px);border-radius:var(--kritzel-context-menu-item-border-radius, 12px);cursor:var(--kritzel-global-pointer-cursor, pointer);font-size:var(--kritzel-context-menu-item-font-size, 14px);color:var(--kritzel-context-menu-item-color, #333333);white-space:nowrap;-webkit-tap-highlight-color:transparent;width:100%;min-width:0}.menu-item:not(.disabled):hover,.menu-item.submenu-open{background-color:var(--kritzel-context-menu-item-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.menu-item:not(.disabled):active{background-color:var(--kritzel-context-menu-item-active-background-color, hsl(0, 0%, 0%, 8.6%))}.menu-item.disabled{color:var(--kritzel-context-menu-item-disabled-color, #aaaaaa)}.menu-item.has-children.disabled{cursor:var(--kritzel-global-pointer-cursor, pointer);color:var(--kritzel-context-menu-item-color, #333333)}.menu-item kritzel-icon{opacity:0.8;flex-shrink:0}.menu-item.disabled kritzel-icon{opacity:0.4}.menu-item.has-children.disabled kritzel-icon{opacity:0.8}.label{flex-grow:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.submenu-arrow{margin-left:auto;opacity:0.5}.menu-divider{height:1px;background-color:var(--kritzel-context-menu-divider-color, rgba(0, 0, 0, 0.1));margin:var(--kritzel-context-menu-divider-margin, 4px 8px)}.submenu-container{position:absolute;top:0;left:100%;z-index:2;margin-left:4px;display:flex;flex-direction:column;gap:var(--kritzel-context-menu-item-spacing, 2px);background-color:var(--kritzel-context-menu-background-color, #ffffff);border-radius:var(--kritzel-context-menu-border-radius, 12px);box-shadow:var(--kritzel-context-menu-box-shadow, 0 1px 6px rgba(0, 0, 0, 0.12));border:var(--kritzel-context-menu-border, 1px solid #ebebeb);padding:var(--kritzel-context-menu-padding, 4px);min-width:120px}.submenu-container.position-left{left:auto;right:100%;margin-left:0;margin-right:4px}`;
633
633
 
634
634
  const VIEWPORT_PADDING = 8;
635
635
  const SUBMENU_DELAY = 150;
@@ -750,6 +750,11 @@ const KritzelContextMenu = class {
750
750
  const idx = path.lastIndexOf('.');
751
751
  return idx === -1 ? '' : path.substring(0, idx);
752
752
  }
753
+ getMenuDepth(path) {
754
+ if (!path)
755
+ return 0;
756
+ return path.split('.').length;
757
+ }
753
758
  pruneStaleRefs() {
754
759
  const openPaths = new Set(this.getOpenSubmenuPaths());
755
760
  for (const key of Array.from(this.submenuRefs.keys())) {
@@ -861,7 +866,8 @@ const KritzelContextMenu = class {
861
866
  }
862
867
  renderSubmenu(processedChildren, path) {
863
868
  const position = this.submenuPositions[path] === 'left' ? 'left' : 'right';
864
- return (index.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)));
869
+ const zIndex = this.getMenuDepth(path) + 1;
870
+ return (index.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)));
865
871
  }
866
872
  render() {
867
873
  if (!this.processedItems || this.processedItems.length === 0) {
@@ -879,67 +885,65 @@ KritzelContextMenu.style = kritzelContextMenuCss();
879
885
 
880
886
  class KritzelToolConfigHelper {
881
887
  static getToolConfig(tool) {
882
- const toolConstructorName = tool?.constructor?.name;
883
- if (tool instanceof schema_constants.KritzelSelectionTool || toolConstructorName === 'KritzelSelectionTool') {
884
- return tool.getToolConfig();
885
- }
886
- if (tool instanceof schema_constants.KritzelBrushTool || toolConstructorName === 'KritzelBrushTool') {
887
- return {
888
- type: 'brush',
889
- colorProperty: 'color',
890
- sizeProperty: 'size',
891
- opacityProperty: 'opacity',
892
- paletteSource: 'palette',
893
- sizesSource: 'sizes',
894
- controls: [
895
- { type: 'stroke-size', propertyName: 'size' },
896
- ],
897
- };
898
- }
899
- if (tool instanceof schema_constants.KritzelLineTool || toolConstructorName === 'KritzelLineTool') {
900
- return {
901
- type: 'line',
902
- colorProperty: 'color',
903
- sizeProperty: 'size',
904
- opacityProperty: 'opacity',
905
- paletteSource: 'palette',
906
- sizesSource: 'sizes',
907
- controls: [
908
- { type: 'stroke-size', propertyName: 'size' },
909
- { type: 'line-endings', propertyName: 'arrows', additionalProps: {} },
910
- ],
911
- };
912
- }
913
- if (tool instanceof schema_constants.KritzelShapeTool || toolConstructorName === 'KritzelShapeTool') {
914
- return {
915
- type: 'shape',
916
- colorProperty: 'strokeColor',
917
- sizeProperty: 'strokeWidth',
918
- opacityProperty: 'opacity',
919
- paletteSource: 'palette',
920
- sizesSource: 'sizes',
921
- controls: [
922
- { type: 'stroke-size', propertyName: 'strokeWidth' },
923
- { type: 'shape-fill', propertyName: 'fillColor', additionalProps: {} },
924
- ],
925
- };
926
- }
927
- if (tool instanceof schema_constants.KritzelTextTool || toolConstructorName === 'KritzelTextTool') {
928
- return {
929
- type: 'text',
930
- colorProperty: 'fontColor',
931
- sizeProperty: 'fontSize',
932
- opacityProperty: 'opacity',
933
- paletteSource: 'palette',
934
- sizesSource: 'sizes',
935
- controls: [
936
- { type: 'font-size', propertyName: 'fontSize', additionalProps: {} },
937
- { type: 'font-family', propertyName: 'fontFamily' },
938
- ],
939
- };
888
+ switch (tool?.toolType) {
889
+ case 'selection':
890
+ return 'getToolConfig' in tool && typeof tool.getToolConfig === 'function'
891
+ ? tool.getToolConfig()
892
+ : null;
893
+ case 'brush':
894
+ return {
895
+ type: 'brush',
896
+ colorProperty: 'color',
897
+ sizeProperty: 'size',
898
+ opacityProperty: 'opacity',
899
+ paletteSource: 'palette',
900
+ sizesSource: 'sizes',
901
+ controls: [
902
+ { type: 'stroke-size', propertyName: 'size' },
903
+ ],
904
+ };
905
+ case 'line':
906
+ return {
907
+ type: 'line',
908
+ colorProperty: 'color',
909
+ sizeProperty: 'size',
910
+ opacityProperty: 'opacity',
911
+ paletteSource: 'palette',
912
+ sizesSource: 'sizes',
913
+ controls: [
914
+ { type: 'stroke-size', propertyName: 'size' },
915
+ { type: 'line-endings', propertyName: 'arrows', additionalProps: {} },
916
+ ],
917
+ };
918
+ case 'shape':
919
+ return {
920
+ type: 'shape',
921
+ colorProperty: 'strokeColor',
922
+ sizeProperty: 'strokeWidth',
923
+ opacityProperty: 'opacity',
924
+ paletteSource: 'palette',
925
+ sizesSource: 'sizes',
926
+ controls: [
927
+ { type: 'stroke-size', propertyName: 'strokeWidth' },
928
+ { type: 'shape-fill', propertyName: 'fillColor', additionalProps: {} },
929
+ ],
930
+ };
931
+ case 'text':
932
+ return {
933
+ type: 'text',
934
+ colorProperty: 'fontColor',
935
+ sizeProperty: 'fontSize',
936
+ opacityProperty: 'opacity',
937
+ paletteSource: 'palette',
938
+ sizesSource: 'sizes',
939
+ controls: [
940
+ { type: 'font-size', propertyName: 'fontSize', additionalProps: {} },
941
+ { type: 'font-family', propertyName: 'fontFamily' },
942
+ ],
943
+ };
944
+ default:
945
+ return null;
940
946
  }
941
- // Tool is not configurable (e.g., selection, eraser, image)
942
- return null;
943
947
  }
944
948
  }
945
949
 
@@ -951,6 +955,7 @@ const KritzelControls = class {
951
955
  this.isControlsReady = index.createEvent(this, "isControlsReady");
952
956
  }
953
957
  get host() { return index.getElement(this); }
958
+ visible = true;
954
959
  controls = [];
955
960
  activeControl = null;
956
961
  isUtilityPanelVisible = true;
@@ -1175,13 +1180,13 @@ const KritzelControls = class {
1175
1180
  // Separate tool controls from config control
1176
1181
  const toolControls = this.internalControls.filter(c => c.type === 'tool' || c.type === 'separator');
1177
1182
  const configControl = this.internalControls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
1178
- return (index.h(index.Host, { key: 'b567aac7bca12cc5ffb0ee1eb9e6978636aa3c31', class: {
1183
+ return (index.h(index.Host, { key: '0f40a136a6a9556080d922d346318045794421a8', style: { display: this.visible ? '' : 'none' }, class: {
1179
1184
  mobile: this.isTouchDevice,
1180
- } }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '88e8ae9ae7429987724df70895b02a3f59216364', style: {
1185
+ } }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: 'd543e7575cb30e54d9362eddf7c7221fb8cce5f5', style: {
1181
1186
  position: 'absolute',
1182
1187
  bottom: '56px',
1183
1188
  left: '12px',
1184
- }, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '658e3d7b94e49a002d5057c1fb4fc199a371c48d', class: "kritzel-controls" }, index.h("div", { key: 'b54bb52a43e4a94ae1148cd4e75528bcaad681ef', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), index.h("div", { key: '36ce760357d3228141281a45c0ac7b0024b04795', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
1189
+ }, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '1083380152e9d1b51c35da335533c20ca2ca8fcc', class: "kritzel-controls" }, index.h("div", { key: '11ef0fb76c30ffda0e30f01d43229ca2142a5854', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), index.h("div", { key: '269924a8859aece37ff31202307d4feaecbbde86', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
1185
1190
  // Check if this control has sub-options (split-button)
1186
1191
  if (control.subOptions?.length) {
1187
1192
  const selectedSubOption = this.getSelectedSubOption(control);
@@ -1211,10 +1216,10 @@ const KritzelControls = class {
1211
1216
  'kritzel-control': true,
1212
1217
  'selected': this.activeControl?.name === control?.name,
1213
1218
  }, key: control.name, "data-testid": `tool-${control.name}`, onClick: _event => this.handleControlClick?.(control), "aria-label": control.name.charAt(0).toUpperCase() + control.name.slice(1) }, index.h("kritzel-icon", { name: control.icon })));
1214
- })), index.h("div", { key: 'f0b1e0f74fe197f4d39e307e7dd8dd4819c4b183', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (index.h("div", { class: {
1219
+ })), index.h("div", { key: '8b97a5bba3ac4992482e8f433d7ba6197918a914', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (index.h("div", { class: {
1215
1220
  'kritzel-config-container': true,
1216
1221
  'visible': hasConfigUI,
1217
- }, key: configControl.name }, index.h("div", { key: '51cc3ebf13092e710048441ff64856edd4f53dfc', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), index.h("kritzel-tooltip", { key: 'dcace186ae3ece1d7e943f51b48ed5094d847284', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, index.h("kritzel-tool-config", { key: '9b16ac90f335fec3c043545fa0c5b363ab99924e', tool: this.activeControl.tool, theme: this.theme, engine: this.kritzelEngine, onToolChange: event => this.handleToolChange?.(event), onDisplayValuesChange: this.handleDisplayValuesChange, style: { width: '100%', height: '100%' } })), index.h("div", { key: '2425507968e27a01b66c1d7be79a40ebe77cd27d', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
1222
+ }, key: configControl.name }, index.h("div", { key: 'd9adef8c2acc8d9b9d745174050ce78960b89b58', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), index.h("kritzel-tooltip", { key: '7605bbd2b6335c89c57aa68952293f26efad6b4b', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, index.h("kritzel-tool-config", { key: '27b0f41442215e78b692fa44bb665444a4993b89', tool: this.activeControl.tool, theme: this.theme, engine: this.kritzelEngine, onToolChange: event => this.handleToolChange?.(event), onDisplayValuesChange: this.handleDisplayValuesChange, style: { width: '100%', height: '100%' } })), index.h("div", { key: '1fb5979b1c531593acf5086861b22b7d78d03e8d', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
1218
1223
  if (el)
1219
1224
  this.configTriggerRef = el;
1220
1225
  }, onKeyDown: event => {
@@ -1223,7 +1228,7 @@ const KritzelControls = class {
1223
1228
  }
1224
1229
  }, style: {
1225
1230
  cursor: 'pointer',
1226
- } }, this.displayValues && (index.h("div", { key: 'd2499df3c0a90c101957f55664452739e0f1692b', class: "color-container" }, index.h("kritzel-color", { key: 'b7cfcd3a8579c63f508c2786eecace1223e88974', value: this.displayValues.color, theme: this.theme, size: 18, style: {
1231
+ } }, this.displayValues && (index.h("div", { key: '3713ef344630f6b4d88df2e83992018859ddb18c', class: "color-container" }, index.h("kritzel-color", { key: 'c2679f68efae77c6daeb98be9e03d5320d51a73a', value: this.displayValues.color, theme: this.theme, size: 18, style: {
1227
1232
  borderRadius: '50%',
1228
1233
  border: 'none',
1229
1234
  } })))))))));
@@ -1897,7 +1902,7 @@ const KritzelDialog = class {
1897
1902
  };
1898
1903
  KritzelDialog.style = kritzelDialogCss();
1899
1904
 
1900
- const kritzelDropdownCss = () => `:host{display:inline-flex;vertical-align:middle;width:100%;position:relative}.dropdown-wrapper{display:flex;align-items:center;border:1px solid var(--kritzel-dropdown-border-color, #ebebeb);border-radius:6px;overflow:visible;height:38px;width:100%;position:relative}.dropdown-wrapper:hover:not(:focus-within){border-color:var(--kritzel-dropdown-hover-border-color, #cccccc)}.dropdown-container{flex:1;height:100%;min-width:0}.dropdown-trigger{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:0 8px;height:100%;width:100%;box-sizing:border-box;border-radius:6px;border:none;background-color:var(--kritzel-dropdown-background, #ffffff);cursor:var(--kritzel-global-pointer-cursor, pointer);outline:none;font-size:inherit;font-family:inherit;color:var(--kritzel-dropdown-text-color, #333333);-webkit-tap-highlight-color:transparent;text-align:left}.dropdown-trigger:focus-visible{outline:revert}.dropdown-trigger.has-suffix-border{border-right:1px solid var(--kritzel-global-border-color, #ebebeb);border-top-right-radius:0;border-bottom-right-radius:0}.dropdown-trigger.has-prefix-border{border-left:1px solid var(--kritzel-global-border-color, #ebebeb);border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-trigger-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.dropdown-trigger-arrow{display:flex;align-items:center;justify-content:center;width:16px;height:16px;flex-shrink:0;transition:transform 0.2s ease}.dropdown-trigger-arrow svg{width:100%;height:100%}.dropdown-trigger.is-open .dropdown-trigger-arrow{transform:rotate(180deg)}.dropdown-trigger.is-open.open-up .dropdown-trigger-arrow{transform:rotate(0deg)}.dropdown-menu{position:absolute;left:0;right:0;margin:0;padding:4px 0;list-style:none;background-color:var(--kritzel-dropdown-background, #ffffff);border:1px solid var(--kritzel-global-border-color, #ebebeb);border-radius:6px;box-shadow:var(--kritzel-controls-box-shadow, 0 4px 12px rgba(0, 0, 0, 0.15));z-index:1000;max-height:240px;overflow-y:auto;opacity:0;visibility:hidden;transition:opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;outline:none}.dropdown-menu.open-down{top:calc(100% + 4px);bottom:auto;transform:translateY(-8px)}.dropdown-menu.open-up{bottom:calc(100% + 4px);top:auto;transform:translateY(8px)}.dropdown-menu.is-open{opacity:1;visibility:inherit;transform:translateY(0)}.dropdown-menu.open-up{box-shadow:var(--kritzel-controls-box-shadow, 0 -4px 12px rgba(0, 0, 0, 0.15))}.dropdown-option{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 12px;cursor:var(--kritzel-global-pointer-cursor, pointer);color:var(--kritzel-dropdown-text-color, #333333);transition:background-color 0.1s ease;-webkit-tap-highlight-color:transparent}.dropdown-option.is-focused{background-color:var(--kritzel-dropdown-hover-background-color, #f0f0f0)}.dropdown-option.is-selected{font-weight:600;background-color:var(--kritzel-dropdown-selected-background-color, #007bff1a)}.dropdown-option-check{display:flex;align-items:center;justify-content:center;width:16px;height:16px;flex-shrink:0;color:var(--kritzel-dropdown-accent-color, #007bff)}.dropdown-option-check svg{width:100%;height:100%}.dropdown-menu{scrollbar-color:var(--kritzel-global-scrollbar-thumb-color, #ebebeb) transparent;scrollbar-width:thin}::slotted(*){height:100%;box-sizing:border-box}`;
1905
+ const kritzelDropdownCss = () => `:host{display:inline-flex;vertical-align:middle;width:100%;position:relative}.dropdown-wrapper{display:flex;align-items:center;border:1px solid var(--kritzel-dropdown-border-color, #ebebeb);border-radius:var(--kritzel-dropdown-border-radius, 6px);overflow:visible;height:38px;width:100%;position:relative}.dropdown-wrapper:hover:not(:focus-within){border-color:var(--kritzel-dropdown-hover-border-color, #cccccc)}.dropdown-container{flex:1;height:100%;min-width:0}.dropdown-trigger{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:0 8px;height:100%;width:100%;box-sizing:border-box;border-radius:var(--kritzel-dropdown-border-radius, 6px);border:none;background-color:var(--kritzel-dropdown-background, #ffffff);cursor:var(--kritzel-global-pointer-cursor, pointer);outline:none;font-size:inherit;font-family:inherit;color:var(--kritzel-dropdown-text-color, #333333);-webkit-tap-highlight-color:transparent;text-align:left}.dropdown-trigger:focus-visible{outline:revert}.dropdown-trigger.has-suffix-border{border-right:1px solid var(--kritzel-global-border-color, #ebebeb);border-top-right-radius:0;border-bottom-right-radius:0}.dropdown-trigger.has-prefix-border{border-left:1px solid var(--kritzel-global-border-color, #ebebeb);border-top-left-radius:0;border-bottom-left-radius:0}.dropdown-trigger-label{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.dropdown-trigger-arrow{display:flex;align-items:center;justify-content:center;width:16px;height:16px;flex-shrink:0;transition:transform 0.2s ease}.dropdown-trigger-arrow svg{width:100%;height:100%}.dropdown-trigger.is-open .dropdown-trigger-arrow{transform:rotate(180deg)}.dropdown-trigger.is-open.open-up .dropdown-trigger-arrow{transform:rotate(0deg)}.dropdown-menu{position:absolute;left:0;right:0;margin:0;padding:4px 0;list-style:none;background-color:var(--kritzel-dropdown-background, #ffffff);border:1px solid var(--kritzel-global-border-color, #ebebeb);border-radius:var(--kritzel-dropdown-menu-border-radius, var(--kritzel-dropdown-border-radius, 6px));box-shadow:var(--kritzel-controls-box-shadow, 0 4px 12px rgba(0, 0, 0, 0.15));z-index:1000;max-height:240px;overflow-y:auto;opacity:0;visibility:hidden;transition:opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;outline:none}.dropdown-menu.open-down{top:calc(100% + 4px);bottom:auto;transform:translateY(-8px)}.dropdown-menu.open-up{bottom:calc(100% + 4px);top:auto;transform:translateY(8px)}.dropdown-menu.is-open{opacity:1;visibility:inherit;transform:translateY(0)}.dropdown-menu.open-up{box-shadow:var(--kritzel-controls-box-shadow, 0 -4px 12px rgba(0, 0, 0, 0.15))}.dropdown-option{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 12px;cursor:var(--kritzel-global-pointer-cursor, pointer);color:var(--kritzel-dropdown-text-color, #333333);transition:background-color 0.1s ease;-webkit-tap-highlight-color:transparent}.dropdown-option.is-focused{background-color:var(--kritzel-dropdown-hover-background-color, #f0f0f0)}.dropdown-option.is-selected{font-weight:600;background-color:var(--kritzel-dropdown-selected-background-color, #007bff1a)}.dropdown-option-check{display:flex;align-items:center;justify-content:center;width:16px;height:16px;flex-shrink:0;color:var(--kritzel-dropdown-accent-color, #007bff)}.dropdown-option-check svg{width:100%;height:100%}.dropdown-menu{scrollbar-color:var(--kritzel-global-scrollbar-thumb-color, #ebebeb) transparent;scrollbar-width:thin}::slotted(*){height:100%;box-sizing:border-box}`;
1901
1906
 
1902
1907
  const KritzelDropdown = class {
1903
1908
  constructor(hostRef) {
@@ -2162,6 +2167,7 @@ const DEFAULT_SHAPE_CONFIG = {
2162
2167
  fillColor: { light: 'transparent', dark: 'transparent' },
2163
2168
  strokeColor: schema_constants.DEFAULT_COLOR_PALETTE[0],
2164
2169
  strokeWidth: 4,
2170
+ opacity: 1,
2165
2171
  fontColor: schema_constants.DEFAULT_COLOR_PALETTE[0],
2166
2172
  fontSize: 16,
2167
2173
  fontFamily: 'Arial',
@@ -2173,12 +2179,10 @@ const ABSOLUTE_SCALE_MAX = 1000;
2173
2179
  const ABSOLUTE_SCALE_MIN = 0.0001;
2174
2180
 
2175
2181
  /**
2176
- * Default sync configuration - IndexedDB
2182
+ * Default sync configuration - None
2177
2183
  */
2178
2184
  const DEFAULT_SYNC_CONFIG = {
2179
- providers: [
2180
- schema_constants.IndexedDBSyncProvider
2181
- ],
2185
+ providers: [],
2182
2186
  };
2183
2187
 
2184
2188
  const kritzelEditorCss = () => `kritzel-editor{display:flex;margin:0;position:relative;overflow:hidden;width:100%;height:100%;align-items:center;justify-content:center;touch-action:manipulation;user-select:none;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:start;line-height:normal}kritzel-controls{position:absolute;left:0;right:0;margin-inline:auto;width:max-content;max-width:calc(100% - 16px);bottom:var(--kritzel-editor-controls-bottom, 14px);transition:transform var(--kritzel-editor-controls-transition-duration, 0.1s) var(--kritzel-editor-controls-transition, ease-in-out)}kritzel-controls.keyboard-open{transform:var(--kritzel-editor-controls-transform, translateY(300%))}.top-left-buttons{position:absolute;top:var(--kritzel-editor-top-left-buttons-top, 14px);left:var(--kritzel-editor-top-left-buttons-left, 14px);display:flex;align-items:flex-start;gap:8px}.top-right-buttons{position:absolute;top:var(--kritzel-editor-top-right-buttons-top, 14px);right:var(--kritzel-editor-top-right-buttons-right, 14px);display:flex;align-items:center;gap:8px}.top-right-button{display:flex;align-items:center;justify-content:center;width:50px;height:50px;padding:0;border:var(--kritzel-split-button-border, 1px solid #ebebeb);border-radius:var(--kritzel-split-button-border-radius, 12px);background-color:var(--kritzel-split-button-background-color, #ffffff);cursor:var(--kritzel-global-pointer-cursor, pointer);box-shadow:var(--kritzel-split-button-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));transition:background-color 150ms ease;-webkit-tap-highlight-color:transparent}.top-right-button:hover{background-color:#f5f5f5}.top-right-button:active{background-color:#ebebeb}`;
@@ -2364,20 +2368,13 @@ const KritzelEditor = class {
2364
2368
  isUtilityPanelVisible = true;
2365
2369
  isWorkspaceManagerVisible = true;
2366
2370
  isMoreMenuVisible = true;
2371
+ isObjectDistanceFadingActive = false;
2367
2372
  syncConfig = DEFAULT_SYNC_CONFIG;
2368
2373
  assetStorageConfig = schema_constants.DEFAULT_ASSET_STORAGE_CONFIG;
2369
2374
  /** The element to use as the target for the cursor. Defaults to the editor container if not set. */
2370
2375
  cursorTarget;
2371
2376
  /** Optional login configuration. When provided, a "Sign in" button is shown that opens a login dialog with the configured providers. */
2372
- loginConfig = {
2373
- providers: [
2374
- {
2375
- label: 'Sign in with Google',
2376
- icon: 'google',
2377
- name: 'Google',
2378
- },
2379
- ],
2380
- };
2377
+ loginConfig;
2381
2378
  /** Whether the editor is in a loading state. When true, a loading overlay is displayed. */
2382
2379
  isLoading = false;
2383
2380
  /** Optional unique identifier for namespacing storage keys across multiple editor instances. */
@@ -2479,12 +2476,18 @@ const KritzelEditor = class {
2479
2476
  async addObject(object) {
2480
2477
  return this.engineRef.addObject(object);
2481
2478
  }
2479
+ async addObjects(objects) {
2480
+ return this.engineRef.addObjects(objects);
2481
+ }
2482
2482
  async updateObject(object, updatedProperties) {
2483
2483
  return this.engineRef.updateObject(object, updatedProperties);
2484
2484
  }
2485
2485
  async removeObject(object) {
2486
2486
  return this.engineRef.removeObject(object);
2487
2487
  }
2488
+ async removeObjects(objects) {
2489
+ return this.engineRef.removeObjects(objects);
2490
+ }
2488
2491
  async getSelectedObjects() {
2489
2492
  return this.engineRef.getSelectedObjects();
2490
2493
  }
@@ -2500,12 +2503,18 @@ const KritzelEditor = class {
2500
2503
  async centerObjectInViewport(object) {
2501
2504
  return this.engineRef.centerObjectInViewport(object);
2502
2505
  }
2506
+ async panToObject(object) {
2507
+ return this.engineRef.panToObject(object);
2508
+ }
2503
2509
  async backToContent() {
2504
2510
  return this.engineRef.backToContent();
2505
2511
  }
2506
2512
  async centerAllObjects(animate = true) {
2507
2513
  return this.engineRef.centerAllObjects(animate);
2508
2514
  }
2515
+ async centerObjects(objects, animate = true) {
2516
+ return this.engineRef.centerObjects(objects, animate);
2517
+ }
2509
2518
  async setViewport(x, y, scale) {
2510
2519
  return this.engineRef.setViewport(x, y, scale);
2511
2520
  }
@@ -2959,31 +2968,31 @@ const KritzelEditor = class {
2959
2968
  const isLoggedIn = this.isLoggedIn;
2960
2969
  const shouldShowCurrentUser = isLoggedIn;
2961
2970
  const shouldShowLoginButton = this.isReady && !!this.loginConfig && !isLoggedIn;
2962
- return (index.h(index.Host, { key: '3606d2318e6811f2f4b647f1531ff8bda409a401', style: {
2971
+ return (index.h(index.Host, { key: '673bfb4d2d5224c3c3a11bada8afb1c3b90aa03d', style: {
2963
2972
  opacity: this.isEditorVisible ? '1' : '0',
2964
2973
  visibility: this.isEditorVisible ? 'visible' : 'hidden',
2965
2974
  transition: 'opacity 0.2s ease-in-out, visibility 0.2s ease-in-out',
2966
- } }, index.h("div", { key: '094e66c69a829a3d150cd672f66f3f092cf19623', class: "top-left-buttons" }, index.h("kritzel-workspace-manager", { key: 'b31a64b26f0f13a24bc07f2a5db8230ebc0377e2', visible: this.isWorkspaceManagerVisible, workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), index.h("kritzel-back-to-content", { key: '9768ead0daf60292c649a0ccdb4dcd92d8ce342a', visible: this.isBackToContentButtonVisible, onBackToContent: () => this.backToContent() })), index.h("kritzel-engine", { key: 'cf4cf487da19cd10352a31dab4e50db4aaabfd7a', ref: el => {
2975
+ } }, index.h("div", { key: 'cee9075de7a44953b3d017c334b19151ab7bb926', class: "top-left-buttons" }, index.h("kritzel-workspace-manager", { key: 'a7a6c246dabe3ddbab3d807a9f0c275bc621363f', visible: this.isWorkspaceManagerVisible, workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), index.h("kritzel-back-to-content", { key: 'b5452a22f7fd434b8816bdaa117d457b2f1879f3', visible: this.isBackToContentButtonVisible, onBackToContent: () => this.backToContent() })), index.h("kritzel-engine", { key: 'a08648ec91f678724171238735b1073ffb53ca73', ref: el => {
2967
2976
  if (el) {
2968
2977
  this.engineRef = el;
2969
2978
  }
2970
- }, workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, assetStorageConfig: this.assetStorageConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, scaleMin: this.scaleMin, cursorTarget: this.cursorTarget, isLoading: this.isLoading, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom, wheelEnabled: this.wheelEnabled, theme: this.theme, themes: this.themes, 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) }), index.h("kritzel-controls", { key: 'eb0839b834e688f15461ebd7391c87b331a5b328', class: { 'keyboard-open': this.isVirtualKeyboardOpen }, style: { display: this.isControlsVisible ? 'flex' : 'none' }, ref: el => {
2979
+ }, 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, wheelEnabled: this.wheelEnabled, theme: this.theme, themes: this.themes, 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) }), index.h("kritzel-controls", { key: 'a7b78a31bda3fe2fe1def6be339894b83ea3ee38', visible: this.isControlsVisible, class: { 'keyboard-open': this.isVirtualKeyboardOpen }, ref: el => {
2971
2980
  if (el) {
2972
2981
  this.controlsRef = el;
2973
2982
  }
2974
- }, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, onIsControlsReady: () => (this.isControlsReady = true) }), index.h("div", { key: 'e5c14a118d245ef0ec1c5863eb21022a5e5d7c77', class: "top-right-buttons" }, index.h("kritzel-settings", { key: 'bad9ebae5bc91efaf388e525375ba263f0344374', ref: el => {
2983
+ }, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, onIsControlsReady: () => (this.isControlsReady = true) }), index.h("div", { key: '0b3f4879c44864661a5bf5f126da3a869fa808f5', class: "top-right-buttons" }, index.h("kritzel-settings", { key: '7da7fb709f2e4a31a6df1f7382a91f4d78dc6e35', ref: el => {
2975
2984
  if (el) {
2976
2985
  this.settingsRef = el;
2977
2986
  }
2978
- }, shortcuts: this.shortcuts, availableThemes: this.themes && this.themes.length > 0 ? this.themes.map(t => t.name) : ['light', 'dark'], settings: this.currentSettingsConfig, onSettingsChange: event => this.handleSettingsChange(event) }), index.h("kritzel-export", { key: 'ca28cd1057181b347af75ea51950114272bf33ec', ref: el => {
2987
+ }, shortcuts: this.shortcuts, availableThemes: this.themes && this.themes.length > 0 ? this.themes.map(t => t.name) : ['light', 'dark'], settings: this.currentSettingsConfig, onSettingsChange: event => this.handleSettingsChange(event) }), index.h("kritzel-export", { key: 'f362b0181231da30efc927cbebd818a9a64991b0', ref: el => {
2979
2988
  if (el) {
2980
2989
  this.exportRef = el;
2981
2990
  }
2982
- }, workspaceName: this.activeWorkspace?.name || 'workspace', onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), index.h("kritzel-active-users", { key: '1b667e832c1f231ecdd9ea0cca0504c6f4a82ce1', users: this.activeUsers }), shouldShowCurrentUser && index.h("kritzel-current-user", { key: 'ec0a1827625f79435d20b8d53374eb29e7174f7e', user: this.user }), shouldShowLoginButton && (index.h("kritzel-button", { key: '0ddec61cc09b96797c33ae18c225ec967efed3e8', onButtonClick: () => this.loginDialogRef?.open() }, "Sign in")), index.h("kritzel-more-menu", { key: 'e9d41eff38bbd4e9420f8586559597f8ec9d6802', items: this.moreMenuItems, visible: this.isMoreMenuVisible }), index.h("kritzel-share-dialog", { key: 'f3fd8a06f5cf0ac89c02d535ee30dec05c9e536f', ref: el => {
2991
+ }, workspaceName: this.activeWorkspace?.name || 'workspace', onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), index.h("kritzel-active-users", { key: '1cf065fed9b27ffb19a3695425c797a3bc29fa51', users: this.activeUsers }), shouldShowCurrentUser && index.h("kritzel-current-user", { key: '7d6e8e227f36164daed7303645bdd490b362b4d0', user: this.user }), shouldShowLoginButton && (index.h("kritzel-button", { key: '1dcf1f5ae547f4c2c5b7ec88b34bcad0a2a4da28', onButtonClick: () => this.loginDialogRef?.open() }, "Sign in")), index.h("kritzel-more-menu", { key: 'cb80dea4bb9861b6d627399c9aad64075cb8944b', items: this.moreMenuItems, visible: this.isMoreMenuVisible }), index.h("kritzel-share-dialog", { key: 'd12bc96d7af23941e4e054dadfddcf6429de6208', ref: el => {
2983
2992
  if (el) {
2984
2993
  this.shareDialogRef = el;
2985
2994
  }
2986
- }, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: '49bd9f85d4cb7ee0f8dc7d2b7248169848c36b9f', ref: el => {
2995
+ }, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: '6c29a13069cd74972e94bbc245f26375fa95f4cc', ref: el => {
2987
2996
  if (el) {
2988
2997
  this.loginDialogRef = el;
2989
2998
  }
@@ -20926,22 +20935,21 @@ class KritzelViewport {
20926
20935
  return true;
20927
20936
  }
20928
20937
  /**
20929
- * Centers and fits ALL objects in the viewport, including objects not currently rendered.
20930
- * Calculates the combined bounding box of all objects and optionally animates the viewport to show them.
20938
+ * Centers and fits the provided objects in the viewport.
20939
+ * Calculates the combined bounding box of the provided objects and optionally animates the viewport to show them.
20940
+ * @param objects - Objects to include in the fit operation.
20931
20941
  * @param animate - Whether to animate the viewport transition (default: true)
20932
- * @returns true if objects were found and viewport was adjusted, false if no objects exist
20942
+ * @returns true if at least one object was provided and viewport was adjusted, false otherwise
20933
20943
  */
20934
- centerFitAllObjects(animate = true) {
20935
- const allObjects = this._core.store.allNonSelectionObjects;
20936
- if (allObjects.length === 0) {
20944
+ centerFitObjects(objects, animate = true) {
20945
+ if (objects.length === 0) {
20937
20946
  return false;
20938
20947
  }
20939
- // Calculate combined bounds of all objects
20940
20948
  let minX = Infinity;
20941
20949
  let minY = Infinity;
20942
20950
  let maxX = -Infinity;
20943
20951
  let maxY = -Infinity;
20944
- for (const obj of allObjects) {
20952
+ for (const obj of objects) {
20945
20953
  const bounds = obj.rotatedBoundingBox;
20946
20954
  minX = Math.min(minX, bounds.x);
20947
20955
  minY = Math.min(minY, bounds.y);
@@ -20964,6 +20972,15 @@ class KritzelViewport {
20964
20972
  this.animateViewportTo(targetTranslateX, targetTranslateY, clampedScale, animate ? 150 : 0);
20965
20973
  return true;
20966
20974
  }
20975
+ /**
20976
+ * Centers and fits ALL objects in the viewport, including objects not currently rendered.
20977
+ * Calculates the combined bounding box of all objects and optionally animates the viewport to show them.
20978
+ * @param animate - Whether to animate the viewport transition (default: true)
20979
+ * @returns true if objects were found and viewport was adjusted, false if no objects exist
20980
+ */
20981
+ centerFitAllObjects(animate = true) {
20982
+ return this.centerFitObjects(this._core.store.allNonSelectionObjects, animate);
20983
+ }
20967
20984
  }
20968
20985
 
20969
20986
  /** The amount of pixels to move an object when using arrow key nudging. */
@@ -26488,8 +26505,18 @@ const KritzelEngine = class {
26488
26505
  }
26489
26506
  /** Context menu items shown when right-clicking the canvas background. */
26490
26507
  globalContextMenuItems;
26508
+ onGlobalContextMenuItemsChange(newValue) {
26509
+ if (this.contextMenuHandler) {
26510
+ this.contextMenuHandler.globalContextMenuItems = newValue ?? [];
26511
+ }
26512
+ }
26491
26513
  /** Context menu items shown when right-clicking a selected object. */
26492
26514
  objectContextMenuItems;
26515
+ onObjectContextMenuItemsChange(newValue) {
26516
+ if (this.contextMenuHandler) {
26517
+ this.contextMenuHandler.objectContextMenuItems = newValue ?? [];
26518
+ }
26519
+ }
26493
26520
  /** Maximum zoom scale allowed. Clamped to the absolute maximum defined by the engine. */
26494
26521
  scaleMax = ABSOLUTE_SCALE_MAX;
26495
26522
  validateScaleMax(newValue) {
@@ -26524,6 +26551,11 @@ const KritzelEngine = class {
26524
26551
  onLockDrawingScaleChange(newValue) {
26525
26552
  this.core.store.state.lockDrawingScale = newValue;
26526
26553
  }
26554
+ /** When true, objects fade based on distance to the viewport center. */
26555
+ isObjectDistanceFadingActive = false;
26556
+ onIsObjectDistanceFadingActiveChange() {
26557
+ this.core.rerender();
26558
+ }
26527
26559
  /** The current theme to apply to the editor */
26528
26560
  theme = 'light';
26529
26561
  onThemeChange(newValue) {
@@ -26958,7 +26990,7 @@ const KritzelEngine = class {
26958
26990
  this.core.deselectAllObjects();
26959
26991
  object.id = object.generateId();
26960
26992
  object._core = this.core;
26961
- object.scale = this.core.store.state.scale;
26993
+ object.scale = object.scale ?? this.core.store.state.scale;
26962
26994
  object.zIndex = this.core.store.currentZIndex;
26963
26995
  object.workspaceId = this.core.store.state.activeWorkspace.id;
26964
26996
  // Handle KritzelText: recreate the editor now that _core is available
@@ -26987,7 +27019,7 @@ const KritzelEngine = class {
26987
27019
  const oldId = child.id;
26988
27020
  child.id = child.generateId();
26989
27021
  child._core = this.core;
26990
- child.scale = this.core.store.state.scale;
27022
+ child.scale = child.scale ?? this.core.store.state.scale;
26991
27023
  child.zIndex = this.core.store.currentZIndex;
26992
27024
  child.workspaceId = this.core.store.state.activeWorkspace.id;
26993
27025
  idRemapping.set(oldId, child.id);
@@ -27033,6 +27065,82 @@ const KritzelEngine = class {
27033
27065
  this.emitObjectsAdded([object]);
27034
27066
  return object;
27035
27067
  }
27068
+ /**
27069
+ * Adds multiple objects to the canvas in a single batch operation.
27070
+ * All objects are inserted within one Yjs transaction (single undo step),
27071
+ * triggering only one rerender cycle. Intended for programmatic streaming
27072
+ * scenarios where per-object overhead would cause stutter.
27073
+ * @param objects - The object instances to add.
27074
+ * @returns The added objects.
27075
+ */
27076
+ async addObjects(objects) {
27077
+ if (objects.length === 0) {
27078
+ return [];
27079
+ }
27080
+ this.core.store.objects.transaction(() => {
27081
+ for (const object of objects) {
27082
+ object.id = object.generateId();
27083
+ object._core = this.core;
27084
+ object.zIndex = this.core.store.currentZIndex;
27085
+ object.workspaceId = this.core.store.state.activeWorkspace.id;
27086
+ if (schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelText')) {
27087
+ const pendingContent = object.content;
27088
+ object.editor = object.createEditor();
27089
+ if (pendingContent) {
27090
+ object.setContent(pendingContent);
27091
+ }
27092
+ }
27093
+ if (schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup') && object._pendingChildren.length > 0) {
27094
+ const idRemapping = new Map();
27095
+ const allFlushedChildren = [];
27096
+ const flushGroup = (group) => {
27097
+ if (group._pendingChildren.length === 0) {
27098
+ return;
27099
+ }
27100
+ const pending = group._pendingChildren;
27101
+ group._pendingChildren = [];
27102
+ group.childIds = [];
27103
+ pending.forEach(child => {
27104
+ const oldId = child.id;
27105
+ child.id = child.generateId();
27106
+ child._core = this.core;
27107
+ child.zIndex = this.core.store.currentZIndex;
27108
+ child.workspaceId = this.core.store.state.activeWorkspace.id;
27109
+ idRemapping.set(oldId, child.id);
27110
+ group.childIds.push(child.id);
27111
+ allFlushedChildren.push(child);
27112
+ if (schema_constants.KritzelClassHelper.isInstanceOf(child, 'KritzelGroup')) {
27113
+ flushGroup(child);
27114
+ }
27115
+ });
27116
+ };
27117
+ flushGroup(object);
27118
+ allFlushedChildren.forEach(child => {
27119
+ if (schema_constants.KritzelClassHelper.isInstanceOf(child, 'KritzelLine')) {
27120
+ if (child.startAnchor && idRemapping.has(child.startAnchor.objectId)) {
27121
+ child.startAnchor = { objectId: idRemapping.get(child.startAnchor.objectId) };
27122
+ }
27123
+ if (child.endAnchor && idRemapping.has(child.endAnchor.objectId)) {
27124
+ child.endAnchor = { objectId: idRemapping.get(child.endAnchor.objectId) };
27125
+ }
27126
+ }
27127
+ });
27128
+ allFlushedChildren.forEach(child => {
27129
+ this.core.addObject(child);
27130
+ });
27131
+ object.finalize();
27132
+ this.core.anchorManager.rebuildIndex();
27133
+ }
27134
+ this.core.addObject(object);
27135
+ }
27136
+ });
27137
+ this.core.rerender();
27138
+ await new Promise(resolve => {
27139
+ requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
27140
+ });
27141
+ this.emitObjectsAdded(objects);
27142
+ return objects;
27143
+ }
27036
27144
  /**
27037
27145
  * Updates properties of an existing canvas object.
27038
27146
  * @param object - The object to update.
@@ -27062,6 +27170,28 @@ const KritzelEngine = class {
27062
27170
  this.emitObjectsRemoved([object]);
27063
27171
  return object;
27064
27172
  }
27173
+ /**
27174
+ * Removes multiple objects from the canvas in a single batch operation.
27175
+ * All removals happen within one Yjs transaction (single undo step),
27176
+ * triggering only one rerender cycle. Intended for programmatic streaming
27177
+ * scenarios where per-object overhead would cause stutter.
27178
+ * @param objects - The objects to remove.
27179
+ * @returns The removed objects.
27180
+ */
27181
+ async removeObjects(objects) {
27182
+ const objectsMap = this.core.store.objects;
27183
+ if (!objectsMap || objects.length === 0) {
27184
+ return [];
27185
+ }
27186
+ objectsMap.transaction(() => {
27187
+ for (const object of objects) {
27188
+ this.core.removeObject(object);
27189
+ }
27190
+ });
27191
+ this.core.rerender();
27192
+ this.emitObjectsRemoved(objects);
27193
+ return objects;
27194
+ }
27065
27195
  /** Returns the currently selected objects. Returns an empty array if nothing is selected. */
27066
27196
  async getSelectedObjects() {
27067
27197
  const selectionGroup = this.core.store.selectionGroup;
@@ -27111,6 +27241,14 @@ const KritzelEngine = class {
27111
27241
  this.core.rerender();
27112
27242
  return object;
27113
27243
  }
27244
+ /**
27245
+ * Pans the viewport to center on the given object without changing the zoom level.
27246
+ * Unlike `centerObjectInViewport`, this moves the camera — not the object.
27247
+ * @param object - The object whose center the viewport should pan to.
27248
+ */
27249
+ async panToObject(object) {
27250
+ this.viewport.panTo(object.centerX, object.centerY);
27251
+ }
27114
27252
  /**
27115
27253
  * Pans and zooms the viewport to fit the nearest content, with padding.
27116
27254
  * Useful when the user has panned away from all objects.
@@ -27128,6 +27266,16 @@ const KritzelEngine = class {
27128
27266
  async centerAllObjects(animate = true) {
27129
27267
  return this.viewport.centerFitAllObjects(animate);
27130
27268
  }
27269
+ /**
27270
+ * Pans and zooms the viewport to fit the provided objects.
27271
+ * Calculates the combined bounding box of the given objects and centers the viewport to show them.
27272
+ * @param objects - The objects to center and fit in the viewport.
27273
+ * @param animate - Whether to animate the viewport transition (default: true).
27274
+ * @returns `true` if objects were provided and the viewport was adjusted, `false` otherwise.
27275
+ */
27276
+ async centerObjects(objects, animate = true) {
27277
+ return this.viewport.centerFitObjects(objects, animate);
27278
+ }
27131
27279
  /**
27132
27280
  * Sets the viewport to center on the given world coordinates at the specified scale.
27133
27281
  * @param x - X position in world coordinates to center on.
@@ -27716,6 +27864,12 @@ const KritzelEngine = class {
27716
27864
  undoStackSize: 0,
27717
27865
  redoStackSize: 0,
27718
27866
  };
27867
+ _objectDistanceFadeNearScale = 1;
27868
+ _objectDistanceFadeFarScale = 0.15;
27869
+ _objectDistanceFadeMinOpacity = 0;
27870
+ _objectDistanceFadeCloseStartScale = 2;
27871
+ _objectDistanceFadeCloseMaxScale = 4;
27872
+ _objectDistanceFadeCloseMinOpacity = 0;
27719
27873
  syncLoadingState() {
27720
27874
  this.core.store.state.isLoading = this._isWorkspaceLoading || this.isLoading;
27721
27875
  }
@@ -28039,6 +28193,54 @@ const KritzelEngine = class {
28039
28193
  schema_constants.KritzelKeyboardHelper.forceHideKeyboard();
28040
28194
  this.core.rerender();
28041
28195
  }
28196
+ getObjectDistanceFadeMultiplier(objectScale, viewportScale) {
28197
+ if (!this.isObjectDistanceFadingActive) {
28198
+ return 1;
28199
+ }
28200
+ const safeViewportScale = Math.max(Number.isFinite(viewportScale) ? viewportScale : 1, Number.EPSILON);
28201
+ const safeObjectScale = Math.max(Number.isFinite(objectScale) ? objectScale : 1, Number.EPSILON);
28202
+ const normalizedScale = safeViewportScale / safeObjectScale;
28203
+ const farFadeMultiplier = this.getFarDistanceFadeMultiplier(normalizedScale);
28204
+ const closeFadeMultiplier = this.getCloseDistanceFadeMultiplier(normalizedScale);
28205
+ return Math.min(farFadeMultiplier, closeFadeMultiplier);
28206
+ }
28207
+ getFarDistanceFadeMultiplier(normalizedScale) {
28208
+ if (normalizedScale >= this._objectDistanceFadeNearScale) {
28209
+ return 1;
28210
+ }
28211
+ if (normalizedScale <= this._objectDistanceFadeFarScale) {
28212
+ return this._objectDistanceFadeMinOpacity;
28213
+ }
28214
+ const progress = (this._objectDistanceFadeNearScale - normalizedScale) /
28215
+ (this._objectDistanceFadeNearScale - this._objectDistanceFadeFarScale);
28216
+ const smooth = progress * progress * (3 - 2 * progress);
28217
+ return 1 - smooth * (1 - this._objectDistanceFadeMinOpacity);
28218
+ }
28219
+ getCloseDistanceFadeMultiplier(normalizedScale) {
28220
+ if (normalizedScale <= this._objectDistanceFadeCloseStartScale) {
28221
+ return 1;
28222
+ }
28223
+ if (normalizedScale >= this._objectDistanceFadeCloseMaxScale) {
28224
+ return this._objectDistanceFadeCloseMinOpacity;
28225
+ }
28226
+ const progress = (normalizedScale - this._objectDistanceFadeCloseStartScale) /
28227
+ (this._objectDistanceFadeCloseMaxScale - this._objectDistanceFadeCloseStartScale);
28228
+ const smooth = progress * progress * (3 - 2 * progress);
28229
+ return 1 - smooth * (1 - this._objectDistanceFadeCloseMinOpacity);
28230
+ }
28231
+ shouldApplyDistanceFade(object) {
28232
+ return (!schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') &&
28233
+ !schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionBox'));
28234
+ }
28235
+ getObjectEffectiveOpacity(object, viewportScale) {
28236
+ const safeObjectOpacity = Number.isFinite(object.opacity) ? object.opacity : 1;
28237
+ const distanceFadeMultiplier = this.shouldApplyDistanceFade(object)
28238
+ ? this.getObjectDistanceFadeMultiplier(object.scale, viewportScale)
28239
+ : 1;
28240
+ const multiplied = (object.markedForRemoval ? 0.5 : 1) * safeObjectOpacity * distanceFadeMultiplier;
28241
+ const overridden = ((object.markedForRemoval ? 0.5 : safeObjectOpacity) * distanceFadeMultiplier).toString();
28242
+ return { multiplied, overridden };
28243
+ }
28042
28244
  render() {
28043
28245
  if (!this.viewport) {
28044
28246
  return (index.h(index.Host, null, this.core.store.state.isLoading && (index.h("div", { class: "workspace-loading-overlay" }, index.h("span", { class: "workspace-loading-spinner" }), "Loading..."))));
@@ -28048,6 +28250,7 @@ const KritzelEngine = class {
28048
28250
  const baseHandleSizePx = computedStyle.getPropertyValue('--kritzel-selection-handle-size').trim() || '6px';
28049
28251
  const baseHandleSize = parseFloat(baseHandleSizePx);
28050
28252
  const baseHandleTouchSize = baseHandleSize * 2 < 14 ? 14 : baseHandleSize;
28253
+ const viewportScale = this.core.store.state.scale;
28051
28254
  const viewportCenterX = this.core.store.state.viewportWidth / 2 + this.core.store.state.translateX;
28052
28255
  const viewportCenterY = this.core.store.state.viewportHeight / 2 + this.core.store.state.translateY;
28053
28256
  const visibleObjects = this.core.store.objectsInViewport;
@@ -28061,39 +28264,34 @@ const KritzelEngine = class {
28061
28264
  return (index.h(index.Host, null, this.core.store.state.isLoading && (index.h("div", { class: "workspace-loading-overlay" }, index.h("span", { class: "workspace-loading-spinner" }), "Loading...")), this.core.store.state.debugInfo.showViewportInfo && (index.h("div", { class: "debug-panel" }, index.h("div", null, "ActiveWorkspaceId: ", this.core.store.state?.activeWorkspace?.id), index.h("div", null, "ActiveWorkspaceName: ", this.core.store.state?.activeWorkspace?.name), index.h("div", null, "TranslateX: ", this.core.store.state?.translateX), index.h("div", null, "TranslateY: ", this.core.store.state?.translateY), index.h("div", null, "ViewportWidth: ", this.core.store.state?.viewportWidth), index.h("div", null, "ViewportHeight: ", this.core.store.state?.viewportHeight), index.h("div", null, "PointerCount: ", this.core.store.state.pointers.size), index.h("div", null, "Scale: ", this.core.store.state?.scale), index.h("div", null, "ActiveTool: ", this.core.store.state?.activeTool?.name), index.h("div", null, "HasViewportChanged: ", this.core.store.state?.hasViewportChanged ? 'true' : 'false'), index.h("div", null, "IsEnabled: ", this.core.store.state?.isEnabled ? 'true' : 'false'), index.h("div", null, "IsScaling: ", this.core.store.state?.isScaling ? 'true' : 'false'), index.h("div", null, "IsPanning: ", this.core.store.state?.isPanning ? 'true' : 'false'), index.h("div", null, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), index.h("div", null, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), index.h("div", null, "IsResizeHandleSelected: ", this.core.store.state.isResizeHandleSelected ? 'true' : 'false'), index.h("div", null, "IsRotationHandleSelected: ", this.core.store.state.isRotationHandleSelected ? 'true' : 'false'), index.h("div", null, "IsRotationHandleHovered: ", this.core.store.state.isRotationHandleHovered ? 'true' : 'false'), index.h("div", null, "IsDrawing: ", this.core.store.state.isDrawing ? 'true' : 'false'), index.h("div", null, "IsWriting: ", this.core.store.state.isWriting ? 'true' : 'false'), index.h("div", null, "IsPointerDown: ", this.core.store.isPointerDown ? 'true' : 'false'), index.h("div", null, "PointerX: ", this.core.store.state?.pointerX), index.h("div", null, "PointerY: ", this.core.store.state?.pointerY), index.h("div", null, "TotalObjects: ", this.core.store.totalObjectCount), index.h("div", null, "ObjectsInViewport: ", this.core.store.objectsInViewport.length), index.h("div", null, "SelectedObjects: ", this.core.store.selectionGroup?.objects.length || 0), index.h("div", null, "ViewportCenter: (", viewportCenterX.toFixed(2), ", ", viewportCenterY.toFixed(2), ")"))), index.h("div", { id: "origin", class: "origin", style: {
28062
28265
  transform: `matrix(${this.core.store.state?.scale}, 0, 0, ${this.core.store.state?.scale}, ${this.core.store.state?.translateX}, ${this.core.store.state?.translateY})`,
28063
28266
  } }, visibleObjects?.map(object => {
28267
+ const { multiplied: effectiveOpacity, overridden: effectiveOpacityString } = this.getObjectEffectiveOpacity(object, viewportScale);
28064
28268
  return (index.h("div", { key: object.id, id: object.id, class: "object", style: {
28065
28269
  transform: object?.transformationMatrix,
28066
28270
  transformOrigin: 'top left',
28067
28271
  position: 'absolute',
28068
28272
  zIndex: object.zIndex.toString(),
28069
28273
  pointerEvents: this.core.store.state.isScaling ? 'none' : 'auto',
28070
- } }, schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelPath') && (() => {
28071
- const effectiveOpacity = (object.markedForRemoval ? 0.5 : 1) * object.opacity;
28072
- return (index.h("svg", { ref: el => el && object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
28073
- height: object?.totalHeight + 'px',
28074
- width: object?.totalWidth + 'px',
28075
- left: '0',
28076
- top: '0',
28077
- position: 'absolute',
28078
- transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28079
- transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28080
- pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28081
- overflow: 'visible',
28082
- }, viewBox: object?.viewBox }, index.h("path", { d: object?.d, fill: schema_constants.KritzelColorHelper.applyOpacity(object.fill, effectiveOpacity, currentTheme), stroke: schema_constants.KritzelColorHelper.applyOpacity(object?.stroke, effectiveOpacity, currentTheme), "shape-rendering": object.isLowRes() ? 'optimizeSpeed' : 'auto' })));
28083
- })(), schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelLine') && (() => {
28084
- const effectiveOpacity = (object.markedForRemoval ? 0.5 : 1) * object.opacity;
28085
- return (index.h("svg", { ref: el => el && object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
28086
- height: object?.totalHeight + 'px',
28087
- width: object?.totalWidth + 'px',
28088
- left: '0',
28089
- top: '0',
28090
- position: 'absolute',
28091
- transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28092
- transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28093
- pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28094
- overflow: 'visible',
28095
- }, viewBox: object?.viewBox }, (object.hasStartArrow || object.hasEndArrow) && (index.h("defs", null, object.hasStartArrow && (index.h("marker", { id: object.startMarkerId, markerWidth: object.getArrowSize('start'), markerHeight: object.getArrowSize('start'), refX: 0, refY: object.getArrowSize('start') / 2, orient: "auto-start-reverse", markerUnits: "userSpaceOnUse" }, index.h("path", { d: object.getArrowPath(object.arrows?.start?.style), fill: schema_constants.KritzelColorHelper.applyOpacity(object.getArrowFill('start'), effectiveOpacity), transform: `scale(${object.getArrowSize('start') / 10})` }))), object.hasEndArrow && (index.h("marker", { id: object.endMarkerId, markerWidth: object.getArrowSize('end'), markerHeight: object.getArrowSize('end'), refX: 0, refY: object.getArrowSize('end') / 2, orient: "auto", markerUnits: "userSpaceOnUse" }, index.h("path", { d: object.getArrowPath(object.arrows?.end?.style), fill: schema_constants.KritzelColorHelper.applyOpacity(object.getArrowFill('end'), effectiveOpacity), transform: `scale(${object.getArrowSize('end') / 10})` }))))), index.h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: "transparent", "stroke-width": Math.max(object?.strokeWidth || 0, 10), "stroke-linecap": "round" }), index.h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: schema_constants.KritzelColorHelper.applyOpacity(object?.stroke, effectiveOpacity, currentTheme), "stroke-width": object?.strokeWidth, "stroke-linecap": "round", "marker-start": object.hasStartArrow ? `url(#${object.startMarkerId})` : undefined, "marker-end": object.hasEndArrow ? `url(#${object.endMarkerId})` : undefined })));
28096
- })(), schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && object.loadState === 'ready' && (index.h("img", { ref: el => el && object.mount(el), src: object.resolvedSrc || object.src, style: {
28274
+ } }, schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelPath') && (index.h("svg", { ref: el => el && object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
28275
+ height: object?.totalHeight + 'px',
28276
+ width: object?.totalWidth + 'px',
28277
+ left: '0',
28278
+ top: '0',
28279
+ position: 'absolute',
28280
+ transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28281
+ transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28282
+ pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28283
+ overflow: 'visible',
28284
+ }, viewBox: object?.viewBox }, index.h("path", { d: object?.d, fill: schema_constants.KritzelColorHelper.applyOpacity(object.fill, effectiveOpacity, currentTheme), stroke: schema_constants.KritzelColorHelper.applyOpacity(object?.stroke, effectiveOpacity, currentTheme), "shape-rendering": object.isLowRes() ? 'optimizeSpeed' : 'auto' }))), schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelLine') && (index.h("svg", { ref: el => el && object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
28285
+ height: object?.totalHeight + 'px',
28286
+ width: object?.totalWidth + 'px',
28287
+ left: '0',
28288
+ top: '0',
28289
+ position: 'absolute',
28290
+ transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28291
+ transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28292
+ pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28293
+ overflow: 'visible',
28294
+ }, viewBox: object?.viewBox }, (object.hasStartArrow || object.hasEndArrow) && (index.h("defs", null, object.hasStartArrow && (index.h("marker", { id: object.startMarkerId, markerWidth: object.getArrowSize('start'), markerHeight: object.getArrowSize('start'), refX: 0, refY: object.getArrowSize('start') / 2, orient: "auto-start-reverse", markerUnits: "userSpaceOnUse" }, index.h("path", { d: object.getArrowPath(object.arrows?.start?.style), fill: schema_constants.KritzelColorHelper.applyOpacity(object.getArrowFill('start'), effectiveOpacity), transform: `scale(${object.getArrowSize('start') / 10})` }))), object.hasEndArrow && (index.h("marker", { id: object.endMarkerId, markerWidth: object.getArrowSize('end'), markerHeight: object.getArrowSize('end'), refX: 0, refY: object.getArrowSize('end') / 2, orient: "auto", markerUnits: "userSpaceOnUse" }, index.h("path", { d: object.getArrowPath(object.arrows?.end?.style), fill: schema_constants.KritzelColorHelper.applyOpacity(object.getArrowFill('end'), effectiveOpacity), transform: `scale(${object.getArrowSize('end') / 10})` }))))), index.h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: "transparent", "stroke-width": Math.max(object?.strokeWidth || 0, 10), "stroke-linecap": "round" }), index.h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: schema_constants.KritzelColorHelper.applyOpacity(object?.stroke, effectiveOpacity, currentTheme), "stroke-width": object?.strokeWidth, "stroke-linecap": "round", "marker-start": object.hasStartArrow ? `url(#${object.startMarkerId})` : undefined, "marker-end": object.hasEndArrow ? `url(#${object.endMarkerId})` : undefined }))), schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && object.loadState === 'ready' && (index.h("img", { ref: el => el && object.mount(el), src: object.resolvedSrc || object.src, style: {
28097
28295
  position: 'absolute',
28098
28296
  left: '0',
28099
28297
  top: '0',
@@ -28101,7 +28299,7 @@ const KritzelEngine = class {
28101
28299
  height: object.totalHeight + 'px',
28102
28300
  transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28103
28301
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28104
- opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
28302
+ opacity: effectiveOpacityString,
28105
28303
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28106
28304
  backgroundColor: schema_constants.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
28107
28305
  borderColor: schema_constants.KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
@@ -28119,7 +28317,7 @@ const KritzelEngine = class {
28119
28317
  height: object.totalHeight + 'px',
28120
28318
  transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28121
28319
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28122
- opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
28320
+ opacity: effectiveOpacityString,
28123
28321
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28124
28322
  backgroundColor: schema_constants.KritzelColorHelper.resolveThemeColor({ light: '#e5e7eb', dark: '#2a2a2a' }, currentTheme),
28125
28323
  borderColor: object.loadState === 'error'
@@ -28143,7 +28341,7 @@ const KritzelEngine = class {
28143
28341
  height: object.totalHeight + 'px',
28144
28342
  transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28145
28343
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28146
- opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
28344
+ opacity: effectiveOpacityString,
28147
28345
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28148
28346
  backgroundColor: schema_constants.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
28149
28347
  borderColor: schema_constants.KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
@@ -28184,7 +28382,7 @@ const KritzelEngine = class {
28184
28382
  height: object.totalHeight + 'px',
28185
28383
  transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28186
28384
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28187
- opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
28385
+ opacity: effectiveOpacityString,
28188
28386
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28189
28387
  } }, index.h("div", { id: "text-object", ref: el => el && object.mount(el), onPointerDown: e => object.handlePointerDown(e), onPointerMove: e => object.handlePointerMove(e), onPointerUp: e => object.handlePointerUp(e), style: {
28190
28388
  minWidth: object.initialWidth + 'px',
@@ -28197,7 +28395,6 @@ const KritzelEngine = class {
28197
28395
  backgroundColor: schema_constants.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
28198
28396
  overflow: 'visible',
28199
28397
  } }))), schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelShape') && (() => {
28200
- const effectiveOpacity = (object.markedForRemoval ? 0.5 : 1) * object.opacity;
28201
28398
  const fillResolved = schema_constants.KritzelColorHelper.resolveThemeColor(object.fillColor, currentTheme);
28202
28399
  const strokeResolved = schema_constants.KritzelColorHelper.resolveThemeColor(object.strokeColor, currentTheme);
28203
28400
  const isFilled = !!fillResolved && fillResolved !== 'transparent';
@@ -28239,7 +28436,7 @@ const KritzelEngine = class {
28239
28436
  left: `${object.totalWidth}px`,
28240
28437
  top: '0',
28241
28438
  zIndex: (object.zIndex + 2).toString(),
28242
- } }, index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "Id: ", object.id), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "userId: ", object.userId), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "width: ", object.width), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "height: ", object.height), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateX: ", object.translateX), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateY: ", object.translateY), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "rotationDegrees: ", object.rotationDegrees), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "zIndex: ", object.zIndex), schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && (index.h("div", null, index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "assetId: ", object.assetId), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "mimeType: ", object.mimeType))))), (this.core.displaySelectionGroupUI(object) || this.core.displaySelectionLineUI(object)) &&
28439
+ } }, index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "Id: ", object.id), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "userId: ", object.userId), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "width: ", object.width), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "height: ", object.height), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateX: ", object.translateX), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateY: ", object.translateY), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "scale: ", object.scale), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "rotationDegrees: ", object.rotationDegrees), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "zIndex: ", object.zIndex), schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && (index.h("div", null, index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "assetId: ", object.assetId), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "mimeType: ", object.mimeType))))), (this.core.displaySelectionGroupUI(object) || this.core.displaySelectionLineUI(object)) &&
28243
28440
  (() => {
28244
28441
  const isSelectionGroup = schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup');
28245
28442
  const localClientId = this.core.store.objects?.localClientId;
@@ -28502,6 +28699,12 @@ const KritzelEngine = class {
28502
28699
  "user": [{
28503
28700
  "onUserChange": 0
28504
28701
  }],
28702
+ "globalContextMenuItems": [{
28703
+ "onGlobalContextMenuItemsChange": 0
28704
+ }],
28705
+ "objectContextMenuItems": [{
28706
+ "onObjectContextMenuItemsChange": 0
28707
+ }],
28505
28708
  "scaleMax": [{
28506
28709
  "validateScaleMax": 0
28507
28710
  }],
@@ -28514,6 +28717,9 @@ const KritzelEngine = class {
28514
28717
  "lockDrawingScale": [{
28515
28718
  "onLockDrawingScaleChange": 0
28516
28719
  }],
28720
+ "isObjectDistanceFadingActive": [{
28721
+ "onIsObjectDistanceFadingActiveChange": 0
28722
+ }],
28517
28723
  "theme": [{
28518
28724
  "onThemeChange": 0
28519
28725
  }],
@@ -28542,7 +28748,7 @@ const KritzelEngine = class {
28542
28748
  };
28543
28749
  KritzelEngine.style = kritzelEngineCss();
28544
28750
 
28545
- const kritzelExportCss = () => `:host{display:flex;flex-direction:column;min-height:0}.export-content{display:flex;flex-direction:column;gap:16px;padding:0;flex:1}.export-content kritzel-pill-tabs{align-self:center}.export-tab-content{display:flex;flex-direction:column;gap:16px;min-height:330px}.format-selection{display:flex;flex-direction:column;gap:6px}.format-selection label{font-size:14px;font-weight:500;color:var(--kritzel-global-text-primary, #333)}.export-primary-button{width:100%;padding:12px 24px;background-color:var(--kritzel-global-primary-color, #007AFF);color:var(--kritzel-global-primary-text-color, #fff);border:none;border-radius:8px;font-size:14px;font-weight:600;cursor:pointer;transition:background-color 0.2s ease;-webkit-tap-highlight-color:transparent}.export-primary-button:hover{background-color:var(--kritzel-global-primary-hover-color, #0066d6)}.export-primary-button:focus-visible{outline:revert;outline-offset:revert}.preview-container{width:100%;display:flex;justify-content:center;align-items:center;box-sizing:border-box;margin-bottom:8px}.preview-container img{max-width:100%;max-height:250px;object-fit:contain;box-shadow:0 4px 8px rgba(0, 0, 0, 0.15);border-radius:4px;border:1px solid var(--kritzel-global-border-color, #dbdbdb)}.export-content p{margin:0;color:var(--kritzel-global-text-secondary, #666)}@media (max-width: 576px){.export-tab-content{flex:1;min-height:0}}`;
28751
+ const kritzelExportCss = () => `:host{display:flex;flex-direction:column;min-height:0}.export-content{display:flex;flex-direction:column;gap:16px;padding:0;flex:1}.export-content kritzel-pill-tabs{align-self:center}.export-tab-content{display:flex;flex-direction:column;gap:16px;min-height:330px}.format-selection{display:flex;flex-direction:column;gap:6px}.format-selection label{font-size:14px;font-weight:500;color:var(--kritzel-global-text-primary, #333)}.export-primary-button{width:100%;padding:12px 24px;background-color:var(--kritzel-global-primary-color, #007AFF);color:var(--kritzel-global-primary-text-color, #fff);border:none;border-radius:var(--kritzel-button-border-radius, 8px);font-size:14px;font-weight:600;cursor:pointer;transition:background-color 0.2s ease;-webkit-tap-highlight-color:transparent}.export-primary-button:hover{background-color:var(--kritzel-global-primary-hover-color, #0066d6)}.export-primary-button:focus-visible{outline:revert;outline-offset:revert}.preview-container{width:100%;display:flex;justify-content:center;align-items:center;box-sizing:border-box;margin-bottom:8px}.preview-container img{max-width:100%;max-height:250px;object-fit:contain;box-shadow:0 4px 8px rgba(0, 0, 0, 0.15);border-radius:4px;border:1px solid var(--kritzel-global-border-color, #dbdbdb)}.export-content p{margin:0;color:var(--kritzel-global-text-secondary, #666)}@media (max-width: 576px){.export-tab-content{flex:1;min-height:0}}`;
28546
28752
 
28547
28753
  const KritzelExport = class {
28548
28754
  constructor(hostRef) {
@@ -28738,7 +28944,7 @@ const KritzelIcon = class {
28738
28944
  };
28739
28945
  KritzelIcon.style = kritzelIconCss();
28740
28946
 
28741
- const kritzelInputCss = () => `:host{display:block}.input-container{display:flex;flex-direction:column;gap:6px}.input-label{font-size:14px;font-weight:500;color:var(--kritzel-text-input-label-color, #333333)}.input-wrapper{display:flex;align-items:center;border:1px solid var(--kritzel-text-input-border-color, #ebebeb);border-radius:6px;overflow:hidden;background:var(--kritzel-text-input-background, #ffffff);transition:border-color 150ms ease}.input-wrapper:hover:not(:focus-within){border-color:var(--kritzel-text-input-hover-border-color, #cccccc)}.input-wrapper:focus-within{border-color:var(--kritzel-text-input-focus-border-color, #007AFF);border-width:2px}.text-input{flex:1;padding:10px 12px;border:none;outline:none;font-size:14px;font-family:inherit;background:transparent;color:var(--kritzel-text-input-text-color, #333333);box-sizing:border-box}.text-input::placeholder{color:var(--kritzel-text-input-placeholder-color, #999999)}.text-input::selection{background-color:var(--kritzel-text-input-selection-background, #007AFF);color:var(--kritzel-text-input-selection-color, #ffffff)}.text-input:disabled{cursor:not-allowed;opacity:0.6}.input-suffix{padding:10px 12px;background:var(--kritzel-text-input-suffix-background, #f5f5f5);color:var(--kritzel-text-input-suffix-color, #666666);font-size:14px;border-left:1px solid var(--kritzel-text-input-border-color, #ebebeb);flex-shrink:0}`;
28947
+ const kritzelInputCss = () => `:host{display:block}.input-container{display:flex;flex-direction:column;gap:6px}.input-label{font-size:14px;font-weight:500;color:var(--kritzel-text-input-label-color, #333333)}.input-wrapper{display:flex;align-items:center;border:1px solid var(--kritzel-text-input-border-color, #ebebeb);border-radius:var(--kritzel-text-input-border-radius, 6px);overflow:hidden;background:var(--kritzel-text-input-background, #ffffff);transition:border-color 150ms ease}.input-wrapper:hover:not(:focus-within){border-color:var(--kritzel-text-input-hover-border-color, #cccccc)}.input-wrapper:focus-within{border-color:var(--kritzel-text-input-focus-border-color, #007AFF);border-width:2px}.text-input{flex:1;padding:10px 12px;border:none;outline:none;font-size:14px;font-family:inherit;background:transparent;color:var(--kritzel-text-input-text-color, #333333);box-sizing:border-box}.text-input::placeholder{color:var(--kritzel-text-input-placeholder-color, #999999)}.text-input::selection{background-color:var(--kritzel-text-input-selection-background, #007AFF);color:var(--kritzel-text-input-selection-color, #ffffff)}.text-input:disabled{cursor:not-allowed;opacity:0.6}.input-suffix{padding:10px 12px;background:var(--kritzel-text-input-suffix-background, #f5f5f5);color:var(--kritzel-text-input-suffix-color, #666666);font-size:14px;border-left:1px solid var(--kritzel-text-input-border-color, #ebebeb);flex-shrink:0}`;
28742
28948
 
28743
28949
  const KritzelInput = class {
28744
28950
  constructor(hostRef) {
@@ -29286,7 +29492,7 @@ const KritzelMoreMenu = class {
29286
29492
  };
29287
29493
  KritzelMoreMenu.style = kritzelMoreMenuCss();
29288
29494
 
29289
- const kritzelNumericInputCss = () => `:host{display:block}.input-container{display:flex;flex-direction:column;gap:6px}.input-label{font-size:14px;font-weight:500;color:var(--kritzel-numeric-input-label-color, #333333)}.input-wrapper{display:flex;position:relative}.numeric-input{flex:1;padding:8px 36px 8px 12px;border:1px solid var(--kritzel-numeric-input-border-color, #ebebeb);border-radius:6px;font-size:14px;color:var(--kritzel-numeric-input-text-color, #333333);background-color:var(--kritzel-numeric-input-input-background, #ffffff);outline:none;transition:border-color 150ms ease;box-sizing:border-box}.numeric-input::-webkit-outer-spin-button,.numeric-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.numeric-input[type='number']{-moz-appearance:textfield}.numeric-input::selection{background-color:var(--kritzel-numeric-input-selection-background, #007AFF);color:var(--kritzel-numeric-input-selection-color, #ffffff)}.numeric-input:hover{border-color:var(--kritzel-numeric-input-hover-border-color, #cccccc)}.numeric-input:focus{border-color:var(--kritzel-numeric-input-focus-border-color, #0066ff);border-width:2px;padding:7px 35px 7px 11px}.spinner-buttons{position:absolute;right:1px;top:1px;bottom:1px;display:flex;flex-direction:column;border-left:1px solid var(--kritzel-numeric-input-border-color, #ebebeb);border-radius:0 5px 5px 0;overflow:hidden}.spinner-button{flex:1;display:flex;align-items:center;justify-content:center;width:24px;padding:0;border:none;background-color:var(--kritzel-numeric-input-spinner-background, #f5f5f5);color:var(--kritzel-numeric-input-spinner-color, #666666);cursor:pointer;transition:background-color 150ms ease}.spinner-button:hover{background-color:var(--kritzel-numeric-input-spinner-hover-background, #ebebeb)}.spinner-button:active{background-color:var(--kritzel-numeric-input-spinner-active-background, #dddddd)}.spinner-up{border-bottom:1px solid var(--kritzel-numeric-input-border-color, #ebebeb)}.spinner-icon{width:10px;height:6px}`;
29495
+ const kritzelNumericInputCss = () => `:host{display:block}.input-container{display:flex;flex-direction:column;gap:6px}.input-label{font-size:14px;font-weight:500;color:var(--kritzel-numeric-input-label-color, #333333)}.input-wrapper{display:flex;position:relative}.numeric-input{flex:1;padding:8px 36px 8px 12px;border:1px solid var(--kritzel-numeric-input-border-color, #ebebeb);border-radius:var(--kritzel-numeric-input-border-radius, 6px);font-size:14px;color:var(--kritzel-numeric-input-text-color, #333333);background-color:var(--kritzel-numeric-input-input-background, #ffffff);outline:none;transition:border-color 150ms ease;box-sizing:border-box}.numeric-input::-webkit-outer-spin-button,.numeric-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.numeric-input[type='number']{-moz-appearance:textfield}.numeric-input::selection{background-color:var(--kritzel-numeric-input-selection-background, #007AFF);color:var(--kritzel-numeric-input-selection-color, #ffffff)}.numeric-input:hover{border-color:var(--kritzel-numeric-input-hover-border-color, #cccccc)}.numeric-input:focus{border-color:var(--kritzel-numeric-input-focus-border-color, #0066ff);border-width:2px;padding:7px 35px 7px 11px}.spinner-buttons{position:absolute;right:1px;top:1px;bottom:1px;display:flex;flex-direction:column;border-left:1px solid var(--kritzel-numeric-input-border-color, #ebebeb);border-radius:0 var(--kritzel-numeric-input-spinner-border-radius, 5px) var(--kritzel-numeric-input-spinner-border-radius, 5px) 0;overflow:hidden}.spinner-button{flex:1;display:flex;align-items:center;justify-content:center;width:24px;padding:0;border:none;background-color:var(--kritzel-numeric-input-spinner-background, #f5f5f5);color:var(--kritzel-numeric-input-spinner-color, #666666);cursor:pointer;transition:background-color 150ms ease}.spinner-button:hover{background-color:var(--kritzel-numeric-input-spinner-hover-background, #ebebeb)}.spinner-button:active{background-color:var(--kritzel-numeric-input-spinner-active-background, #dddddd)}.spinner-up{border-bottom:1px solid var(--kritzel-numeric-input-border-color, #ebebeb)}.spinner-icon{width:10px;height:6px}`;
29290
29496
 
29291
29497
  const KritzelNumericInput = class {
29292
29498
  constructor(hostRef) {
@@ -29785,7 +29991,7 @@ const KritzelPortal = class {
29785
29991
  * This file is auto-generated by the version bump scripts.
29786
29992
  * Do not modify manually.
29787
29993
  */
29788
- const KRITZEL_VERSION = '0.3.11';
29994
+ const KRITZEL_VERSION = '0.3.13';
29789
29995
 
29790
29996
  const kritzelSettingsCss = () => `:host{display:contents}kritzel-dialog{--kritzel-dialog-body-padding:0;--kritzel-dialog-width-large:800px;--kritzel-dialog-height-large:500px}.footer-button{padding:8px 16px;border-radius:6px;cursor:pointer;font-size:14px}.cancel-button{border:1px solid #ebebeb;background:#fff;color:inherit}.cancel-button:hover{background:#f5f5f5}.settings-content{padding:0}.settings-content h3{margin:0 0 16px 0;font-size:18px;font-weight:600;color:var(--kritzel-settings-content-heading-color, #333333)}.settings-content p{margin:0;font-size:14px;color:var(--kritzel-settings-content-text-color, #666666);line-height:1.5}.settings-group{display:flex;flex-direction:column;gap:24px}.settings-item{display:flex;flex-direction:column;gap:8px}.settings-row{display:flex;align-items:center;justify-content:space-between;gap:16px}.settings-label{font-size:14px;font-weight:600;color:var(--kritzel-settings-label-color, #333333);margin:0 0 4px 0}.settings-description{font-size:12px;color:var(--kritzel-settings-description-color, #888888);margin:0;line-height:1.4}.shortcuts-list{display:flex;flex-direction:column;gap:24px}.shortcuts-category{display:flex;flex-direction:column;gap:8px}.shortcuts-category-title{font-size:14px;font-weight:600;color:var(--kritzel-settings-label-color, #333333);margin:0 0 4px 0}.shortcuts-group{display:flex;flex-direction:column;gap:4px}.shortcut-item{display:flex;justify-content:space-between;align-items:center;padding:6px 8px;border-radius:4px;background:var(--kritzel-settings-shortcut-item-bg, rgba(0, 0, 0, 0.02))}.shortcut-label{font-size:14px;color:var(--kritzel-settings-content-text-color, #666666)}.shortcut-key{font-family:monospace;font-size:12px;padding:2px 8px;border-radius:4px;background:var(--kritzel-settings-shortcut-key-bg, #f0f0f0);color:var(--kritzel-settings-shortcut-key-color, #333333);border:1px solid var(--kritzel-settings-shortcut-key-border, #ddd)}`;
29791
29997