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,5 +1,5 @@
1
- import { r as registerInstance, h, H as Host, c as createEvent, g as getElement } from './index-D9HaikfQ.js';
2
- import { c as KritzelPath, e as KritzelLine, J as KritzelColorHelper, o as KritzelSelectionTool, h as KritzelBrushTool, i as KritzelLineTool, m as KritzelShapeTool, l as KritzelTextTool, L as KritzelDevicesHelper, M as KritzelMouseButton, N as DEFAULT_STROKE_SIZES, O as DEFAULT_COLOR_PALETTE, S as ShapeType, I as IndexedDBSyncProvider, D as DEFAULT_BRUSH_CONFIG, j as KritzelEraserTool, v as DEFAULT_LINE_TOOL_CONFIG, u as DEFAULT_TEXT_CONFIG, k as KritzelImageTool, z as KritzelAlignment, w as DEFAULT_ASSET_STORAGE_CONFIG, T as ThemeHelper, y as darkTheme, x as lightTheme, P as KritzelSelectionGroup, Q as KritzelSelectionBox, R as KritzelIconRegistry, U as KritzelKeyboardHelper, V as KritzelBaseHandler, K as KritzelBaseObject, r as KritzelWorkspace, f as KritzelGroup, d as KritzelImage, g as KritzelShape, b as KritzelText, B as runMigrations, G as CURRENT_WORKSPACE_SCHEMA_VERSION, E as WORKSPACE_MIGRATIONS, F as CURRENT_APP_STATE_SCHEMA_VERSION, C as APP_STATE_MIGRATIONS, X as ObjectHelper, n as KritzelCursorHelper, s as KritzelAnchorManager, t as KritzelThemeManager, p as KritzelAssetResolver, Y as KritzelClassHelper, Z as KritzelEventHelper, W as WORKSPACE_EXPORT_VERSION } from './schema.constants-CqBoZbmA.js';
1
+ import { r as registerInstance, h, H as Host, c as createEvent, g as getElement } from './index-Dhio9uis.js';
2
+ import { c as KritzelPath, e as KritzelLine, G as KritzelColorHelper, J as KritzelDevicesHelper, o as KritzelSelectionTool, l as KritzelTextTool, L as KritzelMouseButton, M as DEFAULT_STROKE_SIZES, N as DEFAULT_COLOR_PALETTE, S as ShapeType, D as DEFAULT_BRUSH_CONFIG, h as KritzelBrushTool, j as KritzelEraserTool, u as DEFAULT_LINE_TOOL_CONFIG, i as KritzelLineTool, m as KritzelShapeTool, t as DEFAULT_TEXT_CONFIG, k as KritzelImageTool, y as KritzelAlignment, v as DEFAULT_ASSET_STORAGE_CONFIG, T as ThemeHelper, x as darkTheme, w as lightTheme, O as KritzelSelectionGroup, P as KritzelSelectionBox, Q as KritzelIconRegistry, R as KritzelKeyboardHelper, U as KritzelBaseHandler, K as KritzelBaseObject, q as KritzelWorkspace, f as KritzelGroup, d as KritzelImage, g as KritzelShape, b as KritzelText, z as runMigrations, F as CURRENT_WORKSPACE_SCHEMA_VERSION, C as WORKSPACE_MIGRATIONS, E as CURRENT_APP_STATE_SCHEMA_VERSION, B as APP_STATE_MIGRATIONS, V as ObjectHelper, n as KritzelCursorHelper, r as KritzelAnchorManager, s as KritzelThemeManager, p as KritzelAssetResolver, X as KritzelClassHelper, Y as KritzelEventHelper, W as WORKSPACE_EXPORT_VERSION } from './schema.constants-NrtFvKER.js';
3
3
  import * as Y from 'yjs';
4
4
  import 'y-indexeddb';
5
5
  import 'y-websocket';
@@ -607,7 +607,7 @@ const KritzelColorPalette = class {
607
607
  };
608
608
  KritzelColorPalette.style = kritzelColorPaletteCss();
609
609
 
610
- 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}`;
610
+ 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}`;
611
611
 
612
612
  const VIEWPORT_PADDING = 8;
613
613
  const SUBMENU_DELAY = 150;
@@ -728,6 +728,11 @@ const KritzelContextMenu = class {
728
728
  const idx = path.lastIndexOf('.');
729
729
  return idx === -1 ? '' : path.substring(0, idx);
730
730
  }
731
+ getMenuDepth(path) {
732
+ if (!path)
733
+ return 0;
734
+ return path.split('.').length;
735
+ }
731
736
  pruneStaleRefs() {
732
737
  const openPaths = new Set(this.getOpenSubmenuPaths());
733
738
  for (const key of Array.from(this.submenuRefs.keys())) {
@@ -839,7 +844,8 @@ const KritzelContextMenu = class {
839
844
  }
840
845
  renderSubmenu(processedChildren, path) {
841
846
  const position = this.submenuPositions[path] === 'left' ? 'left' : 'right';
842
- return (h("div", { class: { 'submenu-container': true, 'position-left': position === 'left' }, key: `submenu-${path}`, ref: el => el && this.submenuRefs.set(path, el), onMouseEnter: () => this.handleSubmenuMouseEnter(), onMouseLeave: () => this.handleSubmenuMouseLeave(path) }, this.renderItems(processedChildren, path)));
847
+ const zIndex = this.getMenuDepth(path) + 1;
848
+ return (h("div", { class: { 'submenu-container': true, 'position-left': position === 'left' }, key: `submenu-${path}`, style: { zIndex: String(zIndex) }, ref: el => el && this.submenuRefs.set(path, el), onMouseEnter: () => this.handleSubmenuMouseEnter(), onMouseLeave: () => this.handleSubmenuMouseLeave(path) }, this.renderItems(processedChildren, path)));
843
849
  }
844
850
  render() {
845
851
  if (!this.processedItems || this.processedItems.length === 0) {
@@ -857,67 +863,65 @@ KritzelContextMenu.style = kritzelContextMenuCss();
857
863
 
858
864
  class KritzelToolConfigHelper {
859
865
  static getToolConfig(tool) {
860
- const toolConstructorName = tool?.constructor?.name;
861
- if (tool instanceof KritzelSelectionTool || toolConstructorName === 'KritzelSelectionTool') {
862
- return tool.getToolConfig();
863
- }
864
- if (tool instanceof KritzelBrushTool || toolConstructorName === 'KritzelBrushTool') {
865
- return {
866
- type: 'brush',
867
- colorProperty: 'color',
868
- sizeProperty: 'size',
869
- opacityProperty: 'opacity',
870
- paletteSource: 'palette',
871
- sizesSource: 'sizes',
872
- controls: [
873
- { type: 'stroke-size', propertyName: 'size' },
874
- ],
875
- };
876
- }
877
- if (tool instanceof KritzelLineTool || toolConstructorName === 'KritzelLineTool') {
878
- return {
879
- type: 'line',
880
- colorProperty: 'color',
881
- sizeProperty: 'size',
882
- opacityProperty: 'opacity',
883
- paletteSource: 'palette',
884
- sizesSource: 'sizes',
885
- controls: [
886
- { type: 'stroke-size', propertyName: 'size' },
887
- { type: 'line-endings', propertyName: 'arrows', additionalProps: {} },
888
- ],
889
- };
890
- }
891
- if (tool instanceof KritzelShapeTool || toolConstructorName === 'KritzelShapeTool') {
892
- return {
893
- type: 'shape',
894
- colorProperty: 'strokeColor',
895
- sizeProperty: 'strokeWidth',
896
- opacityProperty: 'opacity',
897
- paletteSource: 'palette',
898
- sizesSource: 'sizes',
899
- controls: [
900
- { type: 'stroke-size', propertyName: 'strokeWidth' },
901
- { type: 'shape-fill', propertyName: 'fillColor', additionalProps: {} },
902
- ],
903
- };
904
- }
905
- if (tool instanceof KritzelTextTool || toolConstructorName === 'KritzelTextTool') {
906
- return {
907
- type: 'text',
908
- colorProperty: 'fontColor',
909
- sizeProperty: 'fontSize',
910
- opacityProperty: 'opacity',
911
- paletteSource: 'palette',
912
- sizesSource: 'sizes',
913
- controls: [
914
- { type: 'font-size', propertyName: 'fontSize', additionalProps: {} },
915
- { type: 'font-family', propertyName: 'fontFamily' },
916
- ],
917
- };
866
+ switch (tool?.toolType) {
867
+ case 'selection':
868
+ return 'getToolConfig' in tool && typeof tool.getToolConfig === 'function'
869
+ ? tool.getToolConfig()
870
+ : null;
871
+ case 'brush':
872
+ return {
873
+ type: 'brush',
874
+ colorProperty: 'color',
875
+ sizeProperty: 'size',
876
+ opacityProperty: 'opacity',
877
+ paletteSource: 'palette',
878
+ sizesSource: 'sizes',
879
+ controls: [
880
+ { type: 'stroke-size', propertyName: 'size' },
881
+ ],
882
+ };
883
+ case 'line':
884
+ return {
885
+ type: 'line',
886
+ colorProperty: 'color',
887
+ sizeProperty: 'size',
888
+ opacityProperty: 'opacity',
889
+ paletteSource: 'palette',
890
+ sizesSource: 'sizes',
891
+ controls: [
892
+ { type: 'stroke-size', propertyName: 'size' },
893
+ { type: 'line-endings', propertyName: 'arrows', additionalProps: {} },
894
+ ],
895
+ };
896
+ case 'shape':
897
+ return {
898
+ type: 'shape',
899
+ colorProperty: 'strokeColor',
900
+ sizeProperty: 'strokeWidth',
901
+ opacityProperty: 'opacity',
902
+ paletteSource: 'palette',
903
+ sizesSource: 'sizes',
904
+ controls: [
905
+ { type: 'stroke-size', propertyName: 'strokeWidth' },
906
+ { type: 'shape-fill', propertyName: 'fillColor', additionalProps: {} },
907
+ ],
908
+ };
909
+ case 'text':
910
+ return {
911
+ type: 'text',
912
+ colorProperty: 'fontColor',
913
+ sizeProperty: 'fontSize',
914
+ opacityProperty: 'opacity',
915
+ paletteSource: 'palette',
916
+ sizesSource: 'sizes',
917
+ controls: [
918
+ { type: 'font-size', propertyName: 'fontSize', additionalProps: {} },
919
+ { type: 'font-family', propertyName: 'fontFamily' },
920
+ ],
921
+ };
922
+ default:
923
+ return null;
918
924
  }
919
- // Tool is not configurable (e.g., selection, eraser, image)
920
- return null;
921
925
  }
922
926
  }
923
927
 
@@ -929,6 +933,7 @@ const KritzelControls = class {
929
933
  this.isControlsReady = createEvent(this, "isControlsReady");
930
934
  }
931
935
  get host() { return getElement(this); }
936
+ visible = true;
932
937
  controls = [];
933
938
  activeControl = null;
934
939
  isUtilityPanelVisible = true;
@@ -1153,13 +1158,13 @@ const KritzelControls = class {
1153
1158
  // Separate tool controls from config control
1154
1159
  const toolControls = this.internalControls.filter(c => c.type === 'tool' || c.type === 'separator');
1155
1160
  const configControl = this.internalControls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
1156
- return (h(Host, { key: 'b567aac7bca12cc5ffb0ee1eb9e6978636aa3c31', class: {
1161
+ return (h(Host, { key: '0f40a136a6a9556080d922d346318045794421a8', style: { display: this.visible ? '' : 'none' }, class: {
1157
1162
  mobile: this.isTouchDevice,
1158
- } }, this.isUtilityPanelVisible && (h("kritzel-utility-panel", { key: '88e8ae9ae7429987724df70895b02a3f59216364', style: {
1163
+ } }, this.isUtilityPanelVisible && (h("kritzel-utility-panel", { key: 'd543e7575cb30e54d9362eddf7c7221fb8cce5f5', style: {
1159
1164
  position: 'absolute',
1160
1165
  bottom: '56px',
1161
1166
  left: '12px',
1162
- }, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), h("div", { key: '658e3d7b94e49a002d5057c1fb4fc199a371c48d', class: "kritzel-controls" }, h("div", { key: 'b54bb52a43e4a94ae1148cd4e75528bcaad681ef', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), h("div", { key: '36ce760357d3228141281a45c0ac7b0024b04795', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
1167
+ }, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), h("div", { key: '1083380152e9d1b51c35da335533c20ca2ca8fcc', class: "kritzel-controls" }, h("div", { key: '11ef0fb76c30ffda0e30f01d43229ca2142a5854', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), h("div", { key: '269924a8859aece37ff31202307d4feaecbbde86', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
1163
1168
  // Check if this control has sub-options (split-button)
1164
1169
  if (control.subOptions?.length) {
1165
1170
  const selectedSubOption = this.getSelectedSubOption(control);
@@ -1189,10 +1194,10 @@ const KritzelControls = class {
1189
1194
  'kritzel-control': true,
1190
1195
  'selected': this.activeControl?.name === control?.name,
1191
1196
  }, key: control.name, "data-testid": `tool-${control.name}`, onClick: _event => this.handleControlClick?.(control), "aria-label": control.name.charAt(0).toUpperCase() + control.name.slice(1) }, h("kritzel-icon", { name: control.icon })));
1192
- })), h("div", { key: 'f0b1e0f74fe197f4d39e307e7dd8dd4819c4b183', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (h("div", { class: {
1197
+ })), h("div", { key: '8b97a5bba3ac4992482e8f433d7ba6197918a914', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (h("div", { class: {
1193
1198
  'kritzel-config-container': true,
1194
1199
  'visible': hasConfigUI,
1195
- }, key: configControl.name }, h("div", { key: '51cc3ebf13092e710048441ff64856edd4f53dfc', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), h("kritzel-tooltip", { key: 'dcace186ae3ece1d7e943f51b48ed5094d847284', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, 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%' } })), h("div", { key: '2425507968e27a01b66c1d7be79a40ebe77cd27d', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
1200
+ }, key: configControl.name }, h("div", { key: 'd9adef8c2acc8d9b9d745174050ce78960b89b58', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), h("kritzel-tooltip", { key: '7605bbd2b6335c89c57aa68952293f26efad6b4b', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, 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%' } })), h("div", { key: '1fb5979b1c531593acf5086861b22b7d78d03e8d', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
1196
1201
  if (el)
1197
1202
  this.configTriggerRef = el;
1198
1203
  }, onKeyDown: event => {
@@ -1201,7 +1206,7 @@ const KritzelControls = class {
1201
1206
  }
1202
1207
  }, style: {
1203
1208
  cursor: 'pointer',
1204
- } }, this.displayValues && (h("div", { key: 'd2499df3c0a90c101957f55664452739e0f1692b', class: "color-container" }, h("kritzel-color", { key: 'b7cfcd3a8579c63f508c2786eecace1223e88974', value: this.displayValues.color, theme: this.theme, size: 18, style: {
1209
+ } }, this.displayValues && (h("div", { key: '3713ef344630f6b4d88df2e83992018859ddb18c', class: "color-container" }, h("kritzel-color", { key: 'c2679f68efae77c6daeb98be9e03d5320d51a73a', value: this.displayValues.color, theme: this.theme, size: 18, style: {
1205
1210
  borderRadius: '50%',
1206
1211
  border: 'none',
1207
1212
  } })))))))));
@@ -1875,7 +1880,7 @@ const KritzelDialog = class {
1875
1880
  };
1876
1881
  KritzelDialog.style = kritzelDialogCss();
1877
1882
 
1878
- 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}`;
1883
+ 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}`;
1879
1884
 
1880
1885
  const KritzelDropdown = class {
1881
1886
  constructor(hostRef) {
@@ -2140,6 +2145,7 @@ const DEFAULT_SHAPE_CONFIG = {
2140
2145
  fillColor: { light: 'transparent', dark: 'transparent' },
2141
2146
  strokeColor: DEFAULT_COLOR_PALETTE[0],
2142
2147
  strokeWidth: 4,
2148
+ opacity: 1,
2143
2149
  fontColor: DEFAULT_COLOR_PALETTE[0],
2144
2150
  fontSize: 16,
2145
2151
  fontFamily: 'Arial',
@@ -2151,12 +2157,10 @@ const ABSOLUTE_SCALE_MAX = 1000;
2151
2157
  const ABSOLUTE_SCALE_MIN = 0.0001;
2152
2158
 
2153
2159
  /**
2154
- * Default sync configuration - IndexedDB
2160
+ * Default sync configuration - None
2155
2161
  */
2156
2162
  const DEFAULT_SYNC_CONFIG = {
2157
- providers: [
2158
- IndexedDBSyncProvider
2159
- ],
2163
+ providers: [],
2160
2164
  };
2161
2165
 
2162
2166
  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}`;
@@ -2342,20 +2346,13 @@ const KritzelEditor = class {
2342
2346
  isUtilityPanelVisible = true;
2343
2347
  isWorkspaceManagerVisible = true;
2344
2348
  isMoreMenuVisible = true;
2349
+ isObjectDistanceFadingActive = false;
2345
2350
  syncConfig = DEFAULT_SYNC_CONFIG;
2346
2351
  assetStorageConfig = DEFAULT_ASSET_STORAGE_CONFIG;
2347
2352
  /** The element to use as the target for the cursor. Defaults to the editor container if not set. */
2348
2353
  cursorTarget;
2349
2354
  /** Optional login configuration. When provided, a "Sign in" button is shown that opens a login dialog with the configured providers. */
2350
- loginConfig = {
2351
- providers: [
2352
- {
2353
- label: 'Sign in with Google',
2354
- icon: 'google',
2355
- name: 'Google',
2356
- },
2357
- ],
2358
- };
2355
+ loginConfig;
2359
2356
  /** Whether the editor is in a loading state. When true, a loading overlay is displayed. */
2360
2357
  isLoading = false;
2361
2358
  /** Optional unique identifier for namespacing storage keys across multiple editor instances. */
@@ -2457,12 +2454,18 @@ const KritzelEditor = class {
2457
2454
  async addObject(object) {
2458
2455
  return this.engineRef.addObject(object);
2459
2456
  }
2457
+ async addObjects(objects) {
2458
+ return this.engineRef.addObjects(objects);
2459
+ }
2460
2460
  async updateObject(object, updatedProperties) {
2461
2461
  return this.engineRef.updateObject(object, updatedProperties);
2462
2462
  }
2463
2463
  async removeObject(object) {
2464
2464
  return this.engineRef.removeObject(object);
2465
2465
  }
2466
+ async removeObjects(objects) {
2467
+ return this.engineRef.removeObjects(objects);
2468
+ }
2466
2469
  async getSelectedObjects() {
2467
2470
  return this.engineRef.getSelectedObjects();
2468
2471
  }
@@ -2478,12 +2481,18 @@ const KritzelEditor = class {
2478
2481
  async centerObjectInViewport(object) {
2479
2482
  return this.engineRef.centerObjectInViewport(object);
2480
2483
  }
2484
+ async panToObject(object) {
2485
+ return this.engineRef.panToObject(object);
2486
+ }
2481
2487
  async backToContent() {
2482
2488
  return this.engineRef.backToContent();
2483
2489
  }
2484
2490
  async centerAllObjects(animate = true) {
2485
2491
  return this.engineRef.centerAllObjects(animate);
2486
2492
  }
2493
+ async centerObjects(objects, animate = true) {
2494
+ return this.engineRef.centerObjects(objects, animate);
2495
+ }
2487
2496
  async setViewport(x, y, scale) {
2488
2497
  return this.engineRef.setViewport(x, y, scale);
2489
2498
  }
@@ -2937,31 +2946,31 @@ const KritzelEditor = class {
2937
2946
  const isLoggedIn = this.isLoggedIn;
2938
2947
  const shouldShowCurrentUser = isLoggedIn;
2939
2948
  const shouldShowLoginButton = this.isReady && !!this.loginConfig && !isLoggedIn;
2940
- return (h(Host, { key: '3606d2318e6811f2f4b647f1531ff8bda409a401', style: {
2949
+ return (h(Host, { key: '673bfb4d2d5224c3c3a11bada8afb1c3b90aa03d', style: {
2941
2950
  opacity: this.isEditorVisible ? '1' : '0',
2942
2951
  visibility: this.isEditorVisible ? 'visible' : 'hidden',
2943
2952
  transition: 'opacity 0.2s ease-in-out, visibility 0.2s ease-in-out',
2944
- } }, h("div", { key: '094e66c69a829a3d150cd672f66f3f092cf19623', class: "top-left-buttons" }, 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) }), h("kritzel-back-to-content", { key: '9768ead0daf60292c649a0ccdb4dcd92d8ce342a', visible: this.isBackToContentButtonVisible, onBackToContent: () => this.backToContent() })), h("kritzel-engine", { key: 'cf4cf487da19cd10352a31dab4e50db4aaabfd7a', ref: el => {
2953
+ } }, h("div", { key: 'cee9075de7a44953b3d017c334b19151ab7bb926', class: "top-left-buttons" }, 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) }), h("kritzel-back-to-content", { key: 'b5452a22f7fd434b8816bdaa117d457b2f1879f3', visible: this.isBackToContentButtonVisible, onBackToContent: () => this.backToContent() })), h("kritzel-engine", { key: 'a08648ec91f678724171238735b1073ffb53ca73', ref: el => {
2945
2954
  if (el) {
2946
2955
  this.engineRef = el;
2947
2956
  }
2948
- }, 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) }), h("kritzel-controls", { key: 'eb0839b834e688f15461ebd7391c87b331a5b328', class: { 'keyboard-open': this.isVirtualKeyboardOpen }, style: { display: this.isControlsVisible ? 'flex' : 'none' }, ref: el => {
2957
+ }, 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) }), h("kritzel-controls", { key: 'a7b78a31bda3fe2fe1def6be339894b83ea3ee38', visible: this.isControlsVisible, class: { 'keyboard-open': this.isVirtualKeyboardOpen }, ref: el => {
2949
2958
  if (el) {
2950
2959
  this.controlsRef = el;
2951
2960
  }
2952
- }, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, onIsControlsReady: () => (this.isControlsReady = true) }), h("div", { key: 'e5c14a118d245ef0ec1c5863eb21022a5e5d7c77', class: "top-right-buttons" }, h("kritzel-settings", { key: 'bad9ebae5bc91efaf388e525375ba263f0344374', ref: el => {
2961
+ }, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, onIsControlsReady: () => (this.isControlsReady = true) }), h("div", { key: '0b3f4879c44864661a5bf5f126da3a869fa808f5', class: "top-right-buttons" }, h("kritzel-settings", { key: '7da7fb709f2e4a31a6df1f7382a91f4d78dc6e35', ref: el => {
2953
2962
  if (el) {
2954
2963
  this.settingsRef = el;
2955
2964
  }
2956
- }, 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) }), h("kritzel-export", { key: 'ca28cd1057181b347af75ea51950114272bf33ec', ref: el => {
2965
+ }, 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) }), h("kritzel-export", { key: 'f362b0181231da30efc927cbebd818a9a64991b0', ref: el => {
2957
2966
  if (el) {
2958
2967
  this.exportRef = el;
2959
2968
  }
2960
- }, workspaceName: this.activeWorkspace?.name || 'workspace', onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), h("kritzel-active-users", { key: '1b667e832c1f231ecdd9ea0cca0504c6f4a82ce1', users: this.activeUsers }), shouldShowCurrentUser && h("kritzel-current-user", { key: 'ec0a1827625f79435d20b8d53374eb29e7174f7e', user: this.user }), shouldShowLoginButton && (h("kritzel-button", { key: '0ddec61cc09b96797c33ae18c225ec967efed3e8', onButtonClick: () => this.loginDialogRef?.open() }, "Sign in")), h("kritzel-more-menu", { key: 'e9d41eff38bbd4e9420f8586559597f8ec9d6802', items: this.moreMenuItems, visible: this.isMoreMenuVisible }), h("kritzel-share-dialog", { key: 'f3fd8a06f5cf0ac89c02d535ee30dec05c9e536f', ref: el => {
2969
+ }, workspaceName: this.activeWorkspace?.name || 'workspace', onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), h("kritzel-active-users", { key: '1cf065fed9b27ffb19a3695425c797a3bc29fa51', users: this.activeUsers }), shouldShowCurrentUser && h("kritzel-current-user", { key: '7d6e8e227f36164daed7303645bdd490b362b4d0', user: this.user }), shouldShowLoginButton && (h("kritzel-button", { key: '1dcf1f5ae547f4c2c5b7ec88b34bcad0a2a4da28', onButtonClick: () => this.loginDialogRef?.open() }, "Sign in")), h("kritzel-more-menu", { key: 'cb80dea4bb9861b6d627399c9aad64075cb8944b', items: this.moreMenuItems, visible: this.isMoreMenuVisible }), h("kritzel-share-dialog", { key: 'd12bc96d7af23941e4e054dadfddcf6429de6208', ref: el => {
2961
2970
  if (el) {
2962
2971
  this.shareDialogRef = el;
2963
2972
  }
2964
- }, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: '49bd9f85d4cb7ee0f8dc7d2b7248169848c36b9f', ref: el => {
2973
+ }, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: '6c29a13069cd74972e94bbc245f26375fa95f4cc', ref: el => {
2965
2974
  if (el) {
2966
2975
  this.loginDialogRef = el;
2967
2976
  }
@@ -20904,22 +20913,21 @@ class KritzelViewport {
20904
20913
  return true;
20905
20914
  }
20906
20915
  /**
20907
- * Centers and fits ALL objects in the viewport, including objects not currently rendered.
20908
- * Calculates the combined bounding box of all objects and optionally animates the viewport to show them.
20916
+ * Centers and fits the provided objects in the viewport.
20917
+ * Calculates the combined bounding box of the provided objects and optionally animates the viewport to show them.
20918
+ * @param objects - Objects to include in the fit operation.
20909
20919
  * @param animate - Whether to animate the viewport transition (default: true)
20910
- * @returns true if objects were found and viewport was adjusted, false if no objects exist
20920
+ * @returns true if at least one object was provided and viewport was adjusted, false otherwise
20911
20921
  */
20912
- centerFitAllObjects(animate = true) {
20913
- const allObjects = this._core.store.allNonSelectionObjects;
20914
- if (allObjects.length === 0) {
20922
+ centerFitObjects(objects, animate = true) {
20923
+ if (objects.length === 0) {
20915
20924
  return false;
20916
20925
  }
20917
- // Calculate combined bounds of all objects
20918
20926
  let minX = Infinity;
20919
20927
  let minY = Infinity;
20920
20928
  let maxX = -Infinity;
20921
20929
  let maxY = -Infinity;
20922
- for (const obj of allObjects) {
20930
+ for (const obj of objects) {
20923
20931
  const bounds = obj.rotatedBoundingBox;
20924
20932
  minX = Math.min(minX, bounds.x);
20925
20933
  minY = Math.min(minY, bounds.y);
@@ -20942,6 +20950,15 @@ class KritzelViewport {
20942
20950
  this.animateViewportTo(targetTranslateX, targetTranslateY, clampedScale, animate ? 150 : 0);
20943
20951
  return true;
20944
20952
  }
20953
+ /**
20954
+ * Centers and fits ALL objects in the viewport, including objects not currently rendered.
20955
+ * Calculates the combined bounding box of all objects and optionally animates the viewport to show them.
20956
+ * @param animate - Whether to animate the viewport transition (default: true)
20957
+ * @returns true if objects were found and viewport was adjusted, false if no objects exist
20958
+ */
20959
+ centerFitAllObjects(animate = true) {
20960
+ return this.centerFitObjects(this._core.store.allNonSelectionObjects, animate);
20961
+ }
20945
20962
  }
20946
20963
 
20947
20964
  /** The amount of pixels to move an object when using arrow key nudging. */
@@ -26466,8 +26483,18 @@ const KritzelEngine = class {
26466
26483
  }
26467
26484
  /** Context menu items shown when right-clicking the canvas background. */
26468
26485
  globalContextMenuItems;
26486
+ onGlobalContextMenuItemsChange(newValue) {
26487
+ if (this.contextMenuHandler) {
26488
+ this.contextMenuHandler.globalContextMenuItems = newValue ?? [];
26489
+ }
26490
+ }
26469
26491
  /** Context menu items shown when right-clicking a selected object. */
26470
26492
  objectContextMenuItems;
26493
+ onObjectContextMenuItemsChange(newValue) {
26494
+ if (this.contextMenuHandler) {
26495
+ this.contextMenuHandler.objectContextMenuItems = newValue ?? [];
26496
+ }
26497
+ }
26471
26498
  /** Maximum zoom scale allowed. Clamped to the absolute maximum defined by the engine. */
26472
26499
  scaleMax = ABSOLUTE_SCALE_MAX;
26473
26500
  validateScaleMax(newValue) {
@@ -26502,6 +26529,11 @@ const KritzelEngine = class {
26502
26529
  onLockDrawingScaleChange(newValue) {
26503
26530
  this.core.store.state.lockDrawingScale = newValue;
26504
26531
  }
26532
+ /** When true, objects fade based on distance to the viewport center. */
26533
+ isObjectDistanceFadingActive = false;
26534
+ onIsObjectDistanceFadingActiveChange() {
26535
+ this.core.rerender();
26536
+ }
26505
26537
  /** The current theme to apply to the editor */
26506
26538
  theme = 'light';
26507
26539
  onThemeChange(newValue) {
@@ -26936,7 +26968,7 @@ const KritzelEngine = class {
26936
26968
  this.core.deselectAllObjects();
26937
26969
  object.id = object.generateId();
26938
26970
  object._core = this.core;
26939
- object.scale = this.core.store.state.scale;
26971
+ object.scale = object.scale ?? this.core.store.state.scale;
26940
26972
  object.zIndex = this.core.store.currentZIndex;
26941
26973
  object.workspaceId = this.core.store.state.activeWorkspace.id;
26942
26974
  // Handle KritzelText: recreate the editor now that _core is available
@@ -26965,7 +26997,7 @@ const KritzelEngine = class {
26965
26997
  const oldId = child.id;
26966
26998
  child.id = child.generateId();
26967
26999
  child._core = this.core;
26968
- child.scale = this.core.store.state.scale;
27000
+ child.scale = child.scale ?? this.core.store.state.scale;
26969
27001
  child.zIndex = this.core.store.currentZIndex;
26970
27002
  child.workspaceId = this.core.store.state.activeWorkspace.id;
26971
27003
  idRemapping.set(oldId, child.id);
@@ -27011,6 +27043,82 @@ const KritzelEngine = class {
27011
27043
  this.emitObjectsAdded([object]);
27012
27044
  return object;
27013
27045
  }
27046
+ /**
27047
+ * Adds multiple objects to the canvas in a single batch operation.
27048
+ * All objects are inserted within one Yjs transaction (single undo step),
27049
+ * triggering only one rerender cycle. Intended for programmatic streaming
27050
+ * scenarios where per-object overhead would cause stutter.
27051
+ * @param objects - The object instances to add.
27052
+ * @returns The added objects.
27053
+ */
27054
+ async addObjects(objects) {
27055
+ if (objects.length === 0) {
27056
+ return [];
27057
+ }
27058
+ this.core.store.objects.transaction(() => {
27059
+ for (const object of objects) {
27060
+ object.id = object.generateId();
27061
+ object._core = this.core;
27062
+ object.zIndex = this.core.store.currentZIndex;
27063
+ object.workspaceId = this.core.store.state.activeWorkspace.id;
27064
+ if (KritzelClassHelper.isInstanceOf(object, 'KritzelText')) {
27065
+ const pendingContent = object.content;
27066
+ object.editor = object.createEditor();
27067
+ if (pendingContent) {
27068
+ object.setContent(pendingContent);
27069
+ }
27070
+ }
27071
+ if (KritzelClassHelper.isInstanceOf(object, 'KritzelGroup') && object._pendingChildren.length > 0) {
27072
+ const idRemapping = new Map();
27073
+ const allFlushedChildren = [];
27074
+ const flushGroup = (group) => {
27075
+ if (group._pendingChildren.length === 0) {
27076
+ return;
27077
+ }
27078
+ const pending = group._pendingChildren;
27079
+ group._pendingChildren = [];
27080
+ group.childIds = [];
27081
+ pending.forEach(child => {
27082
+ const oldId = child.id;
27083
+ child.id = child.generateId();
27084
+ child._core = this.core;
27085
+ child.zIndex = this.core.store.currentZIndex;
27086
+ child.workspaceId = this.core.store.state.activeWorkspace.id;
27087
+ idRemapping.set(oldId, child.id);
27088
+ group.childIds.push(child.id);
27089
+ allFlushedChildren.push(child);
27090
+ if (KritzelClassHelper.isInstanceOf(child, 'KritzelGroup')) {
27091
+ flushGroup(child);
27092
+ }
27093
+ });
27094
+ };
27095
+ flushGroup(object);
27096
+ allFlushedChildren.forEach(child => {
27097
+ if (KritzelClassHelper.isInstanceOf(child, 'KritzelLine')) {
27098
+ if (child.startAnchor && idRemapping.has(child.startAnchor.objectId)) {
27099
+ child.startAnchor = { objectId: idRemapping.get(child.startAnchor.objectId) };
27100
+ }
27101
+ if (child.endAnchor && idRemapping.has(child.endAnchor.objectId)) {
27102
+ child.endAnchor = { objectId: idRemapping.get(child.endAnchor.objectId) };
27103
+ }
27104
+ }
27105
+ });
27106
+ allFlushedChildren.forEach(child => {
27107
+ this.core.addObject(child);
27108
+ });
27109
+ object.finalize();
27110
+ this.core.anchorManager.rebuildIndex();
27111
+ }
27112
+ this.core.addObject(object);
27113
+ }
27114
+ });
27115
+ this.core.rerender();
27116
+ await new Promise(resolve => {
27117
+ requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
27118
+ });
27119
+ this.emitObjectsAdded(objects);
27120
+ return objects;
27121
+ }
27014
27122
  /**
27015
27123
  * Updates properties of an existing canvas object.
27016
27124
  * @param object - The object to update.
@@ -27040,6 +27148,28 @@ const KritzelEngine = class {
27040
27148
  this.emitObjectsRemoved([object]);
27041
27149
  return object;
27042
27150
  }
27151
+ /**
27152
+ * Removes multiple objects from the canvas in a single batch operation.
27153
+ * All removals happen within one Yjs transaction (single undo step),
27154
+ * triggering only one rerender cycle. Intended for programmatic streaming
27155
+ * scenarios where per-object overhead would cause stutter.
27156
+ * @param objects - The objects to remove.
27157
+ * @returns The removed objects.
27158
+ */
27159
+ async removeObjects(objects) {
27160
+ const objectsMap = this.core.store.objects;
27161
+ if (!objectsMap || objects.length === 0) {
27162
+ return [];
27163
+ }
27164
+ objectsMap.transaction(() => {
27165
+ for (const object of objects) {
27166
+ this.core.removeObject(object);
27167
+ }
27168
+ });
27169
+ this.core.rerender();
27170
+ this.emitObjectsRemoved(objects);
27171
+ return objects;
27172
+ }
27043
27173
  /** Returns the currently selected objects. Returns an empty array if nothing is selected. */
27044
27174
  async getSelectedObjects() {
27045
27175
  const selectionGroup = this.core.store.selectionGroup;
@@ -27089,6 +27219,14 @@ const KritzelEngine = class {
27089
27219
  this.core.rerender();
27090
27220
  return object;
27091
27221
  }
27222
+ /**
27223
+ * Pans the viewport to center on the given object without changing the zoom level.
27224
+ * Unlike `centerObjectInViewport`, this moves the camera — not the object.
27225
+ * @param object - The object whose center the viewport should pan to.
27226
+ */
27227
+ async panToObject(object) {
27228
+ this.viewport.panTo(object.centerX, object.centerY);
27229
+ }
27092
27230
  /**
27093
27231
  * Pans and zooms the viewport to fit the nearest content, with padding.
27094
27232
  * Useful when the user has panned away from all objects.
@@ -27106,6 +27244,16 @@ const KritzelEngine = class {
27106
27244
  async centerAllObjects(animate = true) {
27107
27245
  return this.viewport.centerFitAllObjects(animate);
27108
27246
  }
27247
+ /**
27248
+ * Pans and zooms the viewport to fit the provided objects.
27249
+ * Calculates the combined bounding box of the given objects and centers the viewport to show them.
27250
+ * @param objects - The objects to center and fit in the viewport.
27251
+ * @param animate - Whether to animate the viewport transition (default: true).
27252
+ * @returns `true` if objects were provided and the viewport was adjusted, `false` otherwise.
27253
+ */
27254
+ async centerObjects(objects, animate = true) {
27255
+ return this.viewport.centerFitObjects(objects, animate);
27256
+ }
27109
27257
  /**
27110
27258
  * Sets the viewport to center on the given world coordinates at the specified scale.
27111
27259
  * @param x - X position in world coordinates to center on.
@@ -27694,6 +27842,12 @@ const KritzelEngine = class {
27694
27842
  undoStackSize: 0,
27695
27843
  redoStackSize: 0,
27696
27844
  };
27845
+ _objectDistanceFadeNearScale = 1;
27846
+ _objectDistanceFadeFarScale = 0.15;
27847
+ _objectDistanceFadeMinOpacity = 0;
27848
+ _objectDistanceFadeCloseStartScale = 2;
27849
+ _objectDistanceFadeCloseMaxScale = 4;
27850
+ _objectDistanceFadeCloseMinOpacity = 0;
27697
27851
  syncLoadingState() {
27698
27852
  this.core.store.state.isLoading = this._isWorkspaceLoading || this.isLoading;
27699
27853
  }
@@ -28017,6 +28171,54 @@ const KritzelEngine = class {
28017
28171
  KritzelKeyboardHelper.forceHideKeyboard();
28018
28172
  this.core.rerender();
28019
28173
  }
28174
+ getObjectDistanceFadeMultiplier(objectScale, viewportScale) {
28175
+ if (!this.isObjectDistanceFadingActive) {
28176
+ return 1;
28177
+ }
28178
+ const safeViewportScale = Math.max(Number.isFinite(viewportScale) ? viewportScale : 1, Number.EPSILON);
28179
+ const safeObjectScale = Math.max(Number.isFinite(objectScale) ? objectScale : 1, Number.EPSILON);
28180
+ const normalizedScale = safeViewportScale / safeObjectScale;
28181
+ const farFadeMultiplier = this.getFarDistanceFadeMultiplier(normalizedScale);
28182
+ const closeFadeMultiplier = this.getCloseDistanceFadeMultiplier(normalizedScale);
28183
+ return Math.min(farFadeMultiplier, closeFadeMultiplier);
28184
+ }
28185
+ getFarDistanceFadeMultiplier(normalizedScale) {
28186
+ if (normalizedScale >= this._objectDistanceFadeNearScale) {
28187
+ return 1;
28188
+ }
28189
+ if (normalizedScale <= this._objectDistanceFadeFarScale) {
28190
+ return this._objectDistanceFadeMinOpacity;
28191
+ }
28192
+ const progress = (this._objectDistanceFadeNearScale - normalizedScale) /
28193
+ (this._objectDistanceFadeNearScale - this._objectDistanceFadeFarScale);
28194
+ const smooth = progress * progress * (3 - 2 * progress);
28195
+ return 1 - smooth * (1 - this._objectDistanceFadeMinOpacity);
28196
+ }
28197
+ getCloseDistanceFadeMultiplier(normalizedScale) {
28198
+ if (normalizedScale <= this._objectDistanceFadeCloseStartScale) {
28199
+ return 1;
28200
+ }
28201
+ if (normalizedScale >= this._objectDistanceFadeCloseMaxScale) {
28202
+ return this._objectDistanceFadeCloseMinOpacity;
28203
+ }
28204
+ const progress = (normalizedScale - this._objectDistanceFadeCloseStartScale) /
28205
+ (this._objectDistanceFadeCloseMaxScale - this._objectDistanceFadeCloseStartScale);
28206
+ const smooth = progress * progress * (3 - 2 * progress);
28207
+ return 1 - smooth * (1 - this._objectDistanceFadeCloseMinOpacity);
28208
+ }
28209
+ shouldApplyDistanceFade(object) {
28210
+ return (!KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') &&
28211
+ !KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionBox'));
28212
+ }
28213
+ getObjectEffectiveOpacity(object, viewportScale) {
28214
+ const safeObjectOpacity = Number.isFinite(object.opacity) ? object.opacity : 1;
28215
+ const distanceFadeMultiplier = this.shouldApplyDistanceFade(object)
28216
+ ? this.getObjectDistanceFadeMultiplier(object.scale, viewportScale)
28217
+ : 1;
28218
+ const multiplied = (object.markedForRemoval ? 0.5 : 1) * safeObjectOpacity * distanceFadeMultiplier;
28219
+ const overridden = ((object.markedForRemoval ? 0.5 : safeObjectOpacity) * distanceFadeMultiplier).toString();
28220
+ return { multiplied, overridden };
28221
+ }
28020
28222
  render() {
28021
28223
  if (!this.viewport) {
28022
28224
  return (h(Host, null, this.core.store.state.isLoading && (h("div", { class: "workspace-loading-overlay" }, h("span", { class: "workspace-loading-spinner" }), "Loading..."))));
@@ -28026,6 +28228,7 @@ const KritzelEngine = class {
28026
28228
  const baseHandleSizePx = computedStyle.getPropertyValue('--kritzel-selection-handle-size').trim() || '6px';
28027
28229
  const baseHandleSize = parseFloat(baseHandleSizePx);
28028
28230
  const baseHandleTouchSize = baseHandleSize * 2 < 14 ? 14 : baseHandleSize;
28231
+ const viewportScale = this.core.store.state.scale;
28029
28232
  const viewportCenterX = this.core.store.state.viewportWidth / 2 + this.core.store.state.translateX;
28030
28233
  const viewportCenterY = this.core.store.state.viewportHeight / 2 + this.core.store.state.translateY;
28031
28234
  const visibleObjects = this.core.store.objectsInViewport;
@@ -28039,39 +28242,34 @@ const KritzelEngine = class {
28039
28242
  return (h(Host, null, this.core.store.state.isLoading && (h("div", { class: "workspace-loading-overlay" }, h("span", { class: "workspace-loading-spinner" }), "Loading...")), this.core.store.state.debugInfo.showViewportInfo && (h("div", { class: "debug-panel" }, h("div", null, "ActiveWorkspaceId: ", this.core.store.state?.activeWorkspace?.id), h("div", null, "ActiveWorkspaceName: ", this.core.store.state?.activeWorkspace?.name), h("div", null, "TranslateX: ", this.core.store.state?.translateX), h("div", null, "TranslateY: ", this.core.store.state?.translateY), h("div", null, "ViewportWidth: ", this.core.store.state?.viewportWidth), h("div", null, "ViewportHeight: ", this.core.store.state?.viewportHeight), h("div", null, "PointerCount: ", this.core.store.state.pointers.size), h("div", null, "Scale: ", this.core.store.state?.scale), h("div", null, "ActiveTool: ", this.core.store.state?.activeTool?.name), h("div", null, "HasViewportChanged: ", this.core.store.state?.hasViewportChanged ? 'true' : 'false'), h("div", null, "IsEnabled: ", this.core.store.state?.isEnabled ? 'true' : 'false'), h("div", null, "IsScaling: ", this.core.store.state?.isScaling ? 'true' : 'false'), h("div", null, "IsPanning: ", this.core.store.state?.isPanning ? 'true' : 'false'), h("div", null, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), h("div", null, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), h("div", null, "IsResizeHandleSelected: ", this.core.store.state.isResizeHandleSelected ? 'true' : 'false'), h("div", null, "IsRotationHandleSelected: ", this.core.store.state.isRotationHandleSelected ? 'true' : 'false'), h("div", null, "IsRotationHandleHovered: ", this.core.store.state.isRotationHandleHovered ? 'true' : 'false'), h("div", null, "IsDrawing: ", this.core.store.state.isDrawing ? 'true' : 'false'), h("div", null, "IsWriting: ", this.core.store.state.isWriting ? 'true' : 'false'), h("div", null, "IsPointerDown: ", this.core.store.isPointerDown ? 'true' : 'false'), h("div", null, "PointerX: ", this.core.store.state?.pointerX), h("div", null, "PointerY: ", this.core.store.state?.pointerY), h("div", null, "TotalObjects: ", this.core.store.totalObjectCount), h("div", null, "ObjectsInViewport: ", this.core.store.objectsInViewport.length), h("div", null, "SelectedObjects: ", this.core.store.selectionGroup?.objects.length || 0), h("div", null, "ViewportCenter: (", viewportCenterX.toFixed(2), ", ", viewportCenterY.toFixed(2), ")"))), h("div", { id: "origin", class: "origin", style: {
28040
28243
  transform: `matrix(${this.core.store.state?.scale}, 0, 0, ${this.core.store.state?.scale}, ${this.core.store.state?.translateX}, ${this.core.store.state?.translateY})`,
28041
28244
  } }, visibleObjects?.map(object => {
28245
+ const { multiplied: effectiveOpacity, overridden: effectiveOpacityString } = this.getObjectEffectiveOpacity(object, viewportScale);
28042
28246
  return (h("div", { key: object.id, id: object.id, class: "object", style: {
28043
28247
  transform: object?.transformationMatrix,
28044
28248
  transformOrigin: 'top left',
28045
28249
  position: 'absolute',
28046
28250
  zIndex: object.zIndex.toString(),
28047
28251
  pointerEvents: this.core.store.state.isScaling ? 'none' : 'auto',
28048
- } }, KritzelClassHelper.isInstanceOf(object, 'KritzelPath') && (() => {
28049
- const effectiveOpacity = (object.markedForRemoval ? 0.5 : 1) * object.opacity;
28050
- return (h("svg", { ref: el => el && object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
28051
- height: object?.totalHeight + 'px',
28052
- width: object?.totalWidth + 'px',
28053
- left: '0',
28054
- top: '0',
28055
- position: 'absolute',
28056
- transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28057
- transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28058
- pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28059
- overflow: 'visible',
28060
- }, viewBox: object?.viewBox }, h("path", { d: object?.d, fill: KritzelColorHelper.applyOpacity(object.fill, effectiveOpacity, currentTheme), stroke: KritzelColorHelper.applyOpacity(object?.stroke, effectiveOpacity, currentTheme), "shape-rendering": object.isLowRes() ? 'optimizeSpeed' : 'auto' })));
28061
- })(), KritzelClassHelper.isInstanceOf(object, 'KritzelLine') && (() => {
28062
- const effectiveOpacity = (object.markedForRemoval ? 0.5 : 1) * object.opacity;
28063
- return (h("svg", { ref: el => el && object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
28064
- height: object?.totalHeight + 'px',
28065
- width: object?.totalWidth + 'px',
28066
- left: '0',
28067
- top: '0',
28068
- position: 'absolute',
28069
- transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28070
- transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28071
- pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28072
- overflow: 'visible',
28073
- }, viewBox: object?.viewBox }, (object.hasStartArrow || object.hasEndArrow) && (h("defs", null, object.hasStartArrow && (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" }, h("path", { d: object.getArrowPath(object.arrows?.start?.style), fill: KritzelColorHelper.applyOpacity(object.getArrowFill('start'), effectiveOpacity), transform: `scale(${object.getArrowSize('start') / 10})` }))), object.hasEndArrow && (h("marker", { id: object.endMarkerId, markerWidth: object.getArrowSize('end'), markerHeight: object.getArrowSize('end'), refX: 0, refY: object.getArrowSize('end') / 2, orient: "auto", markerUnits: "userSpaceOnUse" }, h("path", { d: object.getArrowPath(object.arrows?.end?.style), fill: KritzelColorHelper.applyOpacity(object.getArrowFill('end'), effectiveOpacity), transform: `scale(${object.getArrowSize('end') / 10})` }))))), h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: "transparent", "stroke-width": Math.max(object?.strokeWidth || 0, 10), "stroke-linecap": "round" }), h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: 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 })));
28074
- })(), KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && object.loadState === 'ready' && (h("img", { ref: el => el && object.mount(el), src: object.resolvedSrc || object.src, style: {
28252
+ } }, KritzelClassHelper.isInstanceOf(object, 'KritzelPath') && (h("svg", { ref: el => el && object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
28253
+ height: object?.totalHeight + 'px',
28254
+ width: object?.totalWidth + 'px',
28255
+ left: '0',
28256
+ top: '0',
28257
+ position: 'absolute',
28258
+ transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28259
+ transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28260
+ pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28261
+ overflow: 'visible',
28262
+ }, viewBox: object?.viewBox }, h("path", { d: object?.d, fill: KritzelColorHelper.applyOpacity(object.fill, effectiveOpacity, currentTheme), stroke: KritzelColorHelper.applyOpacity(object?.stroke, effectiveOpacity, currentTheme), "shape-rendering": object.isLowRes() ? 'optimizeSpeed' : 'auto' }))), KritzelClassHelper.isInstanceOf(object, 'KritzelLine') && (h("svg", { ref: el => el && object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
28263
+ height: object?.totalHeight + 'px',
28264
+ width: object?.totalWidth + 'px',
28265
+ left: '0',
28266
+ top: '0',
28267
+ position: 'absolute',
28268
+ transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28269
+ transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28270
+ pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28271
+ overflow: 'visible',
28272
+ }, viewBox: object?.viewBox }, (object.hasStartArrow || object.hasEndArrow) && (h("defs", null, object.hasStartArrow && (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" }, h("path", { d: object.getArrowPath(object.arrows?.start?.style), fill: KritzelColorHelper.applyOpacity(object.getArrowFill('start'), effectiveOpacity), transform: `scale(${object.getArrowSize('start') / 10})` }))), object.hasEndArrow && (h("marker", { id: object.endMarkerId, markerWidth: object.getArrowSize('end'), markerHeight: object.getArrowSize('end'), refX: 0, refY: object.getArrowSize('end') / 2, orient: "auto", markerUnits: "userSpaceOnUse" }, h("path", { d: object.getArrowPath(object.arrows?.end?.style), fill: KritzelColorHelper.applyOpacity(object.getArrowFill('end'), effectiveOpacity), transform: `scale(${object.getArrowSize('end') / 10})` }))))), h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: "transparent", "stroke-width": Math.max(object?.strokeWidth || 0, 10), "stroke-linecap": "round" }), h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: 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 }))), KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && object.loadState === 'ready' && (h("img", { ref: el => el && object.mount(el), src: object.resolvedSrc || object.src, style: {
28075
28273
  position: 'absolute',
28076
28274
  left: '0',
28077
28275
  top: '0',
@@ -28079,7 +28277,7 @@ const KritzelEngine = class {
28079
28277
  height: object.totalHeight + 'px',
28080
28278
  transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28081
28279
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28082
- opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
28280
+ opacity: effectiveOpacityString,
28083
28281
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28084
28282
  backgroundColor: KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
28085
28283
  borderColor: KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
@@ -28097,7 +28295,7 @@ const KritzelEngine = class {
28097
28295
  height: object.totalHeight + 'px',
28098
28296
  transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28099
28297
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28100
- opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
28298
+ opacity: effectiveOpacityString,
28101
28299
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28102
28300
  backgroundColor: KritzelColorHelper.resolveThemeColor({ light: '#e5e7eb', dark: '#2a2a2a' }, currentTheme),
28103
28301
  borderColor: object.loadState === 'error'
@@ -28121,7 +28319,7 @@ const KritzelEngine = class {
28121
28319
  height: object.totalHeight + 'px',
28122
28320
  transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28123
28321
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28124
- opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
28322
+ opacity: effectiveOpacityString,
28125
28323
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28126
28324
  backgroundColor: KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
28127
28325
  borderColor: KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
@@ -28162,7 +28360,7 @@ const KritzelEngine = class {
28162
28360
  height: object.totalHeight + 'px',
28163
28361
  transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
28164
28362
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
28165
- opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
28363
+ opacity: effectiveOpacityString,
28166
28364
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
28167
28365
  } }, 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: {
28168
28366
  minWidth: object.initialWidth + 'px',
@@ -28175,7 +28373,6 @@ const KritzelEngine = class {
28175
28373
  backgroundColor: KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
28176
28374
  overflow: 'visible',
28177
28375
  } }))), KritzelClassHelper.isInstanceOf(object, 'KritzelShape') && (() => {
28178
- const effectiveOpacity = (object.markedForRemoval ? 0.5 : 1) * object.opacity;
28179
28376
  const fillResolved = KritzelColorHelper.resolveThemeColor(object.fillColor, currentTheme);
28180
28377
  const strokeResolved = KritzelColorHelper.resolveThemeColor(object.strokeColor, currentTheme);
28181
28378
  const isFilled = !!fillResolved && fillResolved !== 'transparent';
@@ -28217,7 +28414,7 @@ const KritzelEngine = class {
28217
28414
  left: `${object.totalWidth}px`,
28218
28415
  top: '0',
28219
28416
  zIndex: (object.zIndex + 2).toString(),
28220
- } }, h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "Id: ", object.id), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "userId: ", object.userId), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "width: ", object.width), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "height: ", object.height), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateX: ", object.translateX), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateY: ", object.translateY), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "rotationDegrees: ", object.rotationDegrees), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "zIndex: ", object.zIndex), KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && (h("div", null, h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "assetId: ", object.assetId), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "mimeType: ", object.mimeType))))), (this.core.displaySelectionGroupUI(object) || this.core.displaySelectionLineUI(object)) &&
28417
+ } }, h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "Id: ", object.id), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "userId: ", object.userId), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "width: ", object.width), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "height: ", object.height), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateX: ", object.translateX), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateY: ", object.translateY), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "scale: ", object.scale), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "rotationDegrees: ", object.rotationDegrees), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "zIndex: ", object.zIndex), KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && (h("div", null, h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "assetId: ", object.assetId), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "mimeType: ", object.mimeType))))), (this.core.displaySelectionGroupUI(object) || this.core.displaySelectionLineUI(object)) &&
28221
28418
  (() => {
28222
28419
  const isSelectionGroup = KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup');
28223
28420
  const localClientId = this.core.store.objects?.localClientId;
@@ -28480,6 +28677,12 @@ const KritzelEngine = class {
28480
28677
  "user": [{
28481
28678
  "onUserChange": 0
28482
28679
  }],
28680
+ "globalContextMenuItems": [{
28681
+ "onGlobalContextMenuItemsChange": 0
28682
+ }],
28683
+ "objectContextMenuItems": [{
28684
+ "onObjectContextMenuItemsChange": 0
28685
+ }],
28483
28686
  "scaleMax": [{
28484
28687
  "validateScaleMax": 0
28485
28688
  }],
@@ -28492,6 +28695,9 @@ const KritzelEngine = class {
28492
28695
  "lockDrawingScale": [{
28493
28696
  "onLockDrawingScaleChange": 0
28494
28697
  }],
28698
+ "isObjectDistanceFadingActive": [{
28699
+ "onIsObjectDistanceFadingActiveChange": 0
28700
+ }],
28495
28701
  "theme": [{
28496
28702
  "onThemeChange": 0
28497
28703
  }],
@@ -28520,7 +28726,7 @@ const KritzelEngine = class {
28520
28726
  };
28521
28727
  KritzelEngine.style = kritzelEngineCss();
28522
28728
 
28523
- 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}}`;
28729
+ 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}}`;
28524
28730
 
28525
28731
  const KritzelExport = class {
28526
28732
  constructor(hostRef) {
@@ -28716,7 +28922,7 @@ const KritzelIcon = class {
28716
28922
  };
28717
28923
  KritzelIcon.style = kritzelIconCss();
28718
28924
 
28719
- 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}`;
28925
+ 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}`;
28720
28926
 
28721
28927
  const KritzelInput = class {
28722
28928
  constructor(hostRef) {
@@ -29264,7 +29470,7 @@ const KritzelMoreMenu = class {
29264
29470
  };
29265
29471
  KritzelMoreMenu.style = kritzelMoreMenuCss();
29266
29472
 
29267
- 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}`;
29473
+ 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}`;
29268
29474
 
29269
29475
  const KritzelNumericInput = class {
29270
29476
  constructor(hostRef) {
@@ -29763,7 +29969,7 @@ const KritzelPortal = class {
29763
29969
  * This file is auto-generated by the version bump scripts.
29764
29970
  * Do not modify manually.
29765
29971
  */
29766
- const KRITZEL_VERSION = '0.3.11';
29972
+ const KRITZEL_VERSION = '0.3.13';
29767
29973
 
29768
29974
  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)}`;
29769
29975