kritzel-stencil 0.3.1 → 0.3.7

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 (67) hide show
  1. package/dist/cjs/index.cjs.js +70 -1
  2. package/dist/cjs/kritzel-active-users_42.cjs.entry.js +200 -41
  3. package/dist/cjs/loader.cjs.js +1 -1
  4. package/dist/cjs/stencil.cjs.js +1 -1
  5. package/dist/cjs/{workspace.migrations-D5sPPbQN.js → workspace.migrations-BlC8KRoQ.js} +12 -63
  6. package/dist/collection/classes/core/core.class.js +16 -5
  7. package/dist/collection/classes/core/store.class.js +8 -1
  8. package/dist/collection/classes/handlers/context-menu.handler.js +2 -2
  9. package/dist/collection/classes/handlers/key.handler.js +1 -2
  10. package/dist/collection/classes/objects/shape.class.js +2 -3
  11. package/dist/collection/classes/objects/text.class.js +2 -3
  12. package/dist/collection/classes/providers/sync/in-memory-sync-provider.class.js +68 -0
  13. package/dist/collection/classes/registries/tool.registry.js +29 -8
  14. package/dist/collection/classes/tools/image-tool.class.js +2 -3
  15. package/dist/collection/classes/tools/line-tool.class.js +1 -2
  16. package/dist/collection/classes/tools/shape-tool.class.js +3 -4
  17. package/dist/collection/classes/tools/text-tool.class.js +2 -3
  18. package/dist/collection/components/core/kritzel-editor/kritzel-editor.css +0 -2
  19. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +16 -7
  20. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.css +2 -1
  21. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +56 -32
  22. package/dist/collection/components/ui/kritzel-more-menu/kritzel-more-menu.css +1 -0
  23. package/dist/collection/components/ui/kritzel-tool-config/kritzel-tool-config.js +43 -9
  24. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.css +1 -1
  25. package/dist/collection/constants/version.js +1 -1
  26. package/dist/collection/helpers/tool-config.helper.js +6 -5
  27. package/dist/collection/index.js +1 -0
  28. package/dist/components/index.js +1 -1
  29. package/dist/components/kritzel-controls.js +1 -1
  30. package/dist/components/kritzel-editor.js +1 -1
  31. package/dist/components/kritzel-engine.js +1 -1
  32. package/dist/components/kritzel-more-menu.js +1 -1
  33. package/dist/components/kritzel-settings.js +1 -1
  34. package/dist/components/kritzel-tool-config.js +1 -1
  35. package/dist/components/kritzel-utility-panel.js +1 -1
  36. package/dist/components/p-8b9zAWnS.js +1 -0
  37. package/dist/components/{p-Cx6YyDdF.js → p-BV3EJRtU.js} +1 -1
  38. package/dist/components/p-CSODtZrV.js +1 -0
  39. package/dist/components/p-CoJdbj3f.js +1 -0
  40. package/dist/components/p-Ctd1w9-z.js +1 -0
  41. package/dist/components/{p-C9jegh9w.js → p-D0ctIEh_.js} +1 -1
  42. package/dist/components/p-P0p4WBpa.js +9 -0
  43. package/dist/esm/index.js +71 -3
  44. package/dist/esm/kritzel-active-users_42.entry.js +200 -41
  45. package/dist/esm/loader.js +1 -1
  46. package/dist/esm/stencil.js +1 -1
  47. package/dist/esm/{workspace.migrations-BnTvdnKU.js → workspace.migrations-BLXBI--a.js} +13 -62
  48. package/dist/stencil/index.esm.js +1 -1
  49. package/dist/stencil/p-3058e485.entry.js +9 -0
  50. package/dist/stencil/p-BLXBI--a.js +1 -0
  51. package/dist/stencil/stencil.esm.js +1 -1
  52. package/dist/types/classes/core/core.class.d.ts +8 -0
  53. package/dist/types/classes/providers/sync/in-memory-sync-provider.class.d.ts +38 -0
  54. package/dist/types/classes/registries/tool.registry.d.ts +24 -7
  55. package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +5 -0
  56. package/dist/types/components/ui/kritzel-tool-config/kritzel-tool-config.d.ts +4 -0
  57. package/dist/types/components.d.ts +2 -0
  58. package/dist/types/constants/version.d.ts +1 -1
  59. package/dist/types/index.d.ts +1 -0
  60. package/package.json +1 -1
  61. package/dist/components/p-BWB2UGxj.js +0 -9
  62. package/dist/components/p-BWJGv9ZO.js +0 -1
  63. package/dist/components/p-BWRjTm0J.js +0 -1
  64. package/dist/components/p-Clo5Ydi1.js +0 -1
  65. package/dist/components/p-D9-C4GfD.js +0 -1
  66. package/dist/stencil/p-BnTvdnKU.js +0 -1
  67. package/dist/stencil/p-bfd1fca8.entry.js +0 -9
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var index = require('./index-CFnj_FXt.js');
4
- var workspace_migrations = require('./workspace.migrations-D5sPPbQN.js');
4
+ var workspace_migrations = require('./workspace.migrations-BlC8KRoQ.js');
5
5
  var Y = require('yjs');
6
6
  require('y-indexeddb');
7
7
  require('y-websocket');
@@ -833,10 +833,11 @@ KritzelContextMenu.style = kritzelContextMenuCss();
833
833
 
834
834
  class KritzelToolConfigHelper {
835
835
  static getToolConfig(tool) {
836
- if (tool instanceof workspace_migrations.KritzelSelectionTool) {
836
+ const toolConstructorName = tool?.constructor?.name;
837
+ if (tool instanceof workspace_migrations.KritzelSelectionTool || toolConstructorName === 'KritzelSelectionTool') {
837
838
  return tool.getToolConfig();
838
839
  }
839
- if (tool instanceof workspace_migrations.KritzelBrushTool) {
840
+ if (tool instanceof workspace_migrations.KritzelBrushTool || toolConstructorName === 'KritzelBrushTool') {
840
841
  return {
841
842
  type: 'brush',
842
843
  colorProperty: 'color',
@@ -848,7 +849,7 @@ class KritzelToolConfigHelper {
848
849
  ],
849
850
  };
850
851
  }
851
- if (tool instanceof workspace_migrations.KritzelLineTool) {
852
+ if (tool instanceof workspace_migrations.KritzelLineTool || toolConstructorName === 'KritzelLineTool') {
852
853
  return {
853
854
  type: 'line',
854
855
  colorProperty: 'color',
@@ -861,7 +862,7 @@ class KritzelToolConfigHelper {
861
862
  ],
862
863
  };
863
864
  }
864
- if (tool instanceof workspace_migrations.KritzelShapeTool) {
865
+ if (tool instanceof workspace_migrations.KritzelShapeTool || toolConstructorName === 'KritzelShapeTool') {
865
866
  return {
866
867
  type: 'shape',
867
868
  colorProperty: 'strokeColor',
@@ -874,7 +875,7 @@ class KritzelToolConfigHelper {
874
875
  ],
875
876
  };
876
877
  }
877
- if (tool instanceof workspace_migrations.KritzelTextTool) {
878
+ if (tool instanceof workspace_migrations.KritzelTextTool || toolConstructorName === 'KritzelTextTool') {
878
879
  return {
879
880
  type: 'text',
880
881
  colorProperty: 'fontColor',
@@ -892,7 +893,7 @@ class KritzelToolConfigHelper {
892
893
  }
893
894
  }
894
895
 
895
- const kritzelControlsCss = () => `:host{display:flex;flex-direction:column;user-select:none;max-width:100%}:host(.mobile){--kritzel-controls-control-hover-background-color:transparent;--kritzel-controls-control-active-background-color:transparent}.kritzel-controls{display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:var(--kritzel-controls-gap, 8px);height:100%;padding:var(--kritzel-controls-padding, 8px);background-color:var(--kritzel-controls-background-color, #ffffff);border-radius:var(--kritzel-controls-border-radius, 16px);box-shadow:var(--kritzel-controls-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-controls-border, 1px solid #ebebeb);z-index:10000;position:relative;max-width:100%;overflow:hidden}.kritzel-tools-scroll{display:flex;flex-direction:row;align-items:center;gap:var(--kritzel-controls-gap, 8px);overflow-x:auto;overflow-y:hidden;flex:1 1 auto;min-width:0;padding:4px;margin:-4px;scrollbar-width:none;-ms-overflow-style:none}.kritzel-tools-scroll::-webkit-scrollbar{display:none}.scroll-indicator-left,.scroll-indicator-right{position:absolute;top:0;bottom:0;width:32px;pointer-events:none;opacity:0;transition:opacity 0.2s ease-out;z-index:1}.scroll-indicator-left{left:0;background:linear-gradient(to right, var(--kritzel-controls-background-color, #ffffff), transparent);border-radius:var(--kritzel-controls-border-radius, 16px) 0 0 var(--kritzel-controls-border-radius, 16px)}.scroll-indicator-right{right:0;background:linear-gradient(to left, var(--kritzel-controls-background-color, #ffffff), transparent);border-radius:0 var(--kritzel-controls-border-radius, 16px) var(--kritzel-controls-border-radius, 16px) 0}.scroll-indicator-left.visible,.scroll-indicator-right.visible{opacity:1}.kritzel-control{display:flex;justify-content:center;align-items:center;color:var(--kritzel-controls-control-color, #000000);border-radius:var(--kritzel-controls-control-border-radius, 12px);padding:var(--kritzel-controls-control-padding, 8px);border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);-webkit-tap-highlight-color:transparent;font-weight:bold}.kritzel-control:focus,.kritzel-control:hover{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-control:active{background-color:var(--kritzel-controls-control-active-background-color, hsl(0, 0%, 0%, 8.6%))}.kritzel-control.selected,.kritzel-control.selected:hover,.kritzel-control.selected:active{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF) !important;color:var(--kritzel-controls-control-selected-color, #ffffff) !important}.kritzel-control.selected:focus{background-color:var(--kritzel-controls-control-selected-background-color, #007bffe3) !important}.kritzel-control-separator{width:1px;height:24px;background-color:var(--kritzel-controls-border, #ebebeb);margin:0 4px}.kritzel-control-split{position:relative;display:flex;align-items:center;border-radius:var(--kritzel-controls-control-border-radius, 12px);color:var(--kritzel-controls-control-color, #000000)}.kritzel-control-split .kritzel-control-main{display:flex;justify-content:center;align-items:center;padding:var(--kritzel-controls-control-padding, 8px);border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);-webkit-tap-highlight-color:transparent;border-radius:var(--kritzel-controls-control-border-radius, 12px);color:inherit}.kritzel-control-split.selected .kritzel-control-main{border-radius:var(--kritzel-controls-control-border-radius, 12px) 0 0 var(--kritzel-controls-control-border-radius, 12px)}.kritzel-control-split .kritzel-control-dropdown{display:flex;justify-content:center;align-items:center;align-self:stretch;border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);-webkit-tap-highlight-color:transparent;border-radius:0 var(--kritzel-controls-control-border-radius, 12px) var(--kritzel-controls-control-border-radius, 12px) 0;color:inherit;width:0;padding:0;opacity:0;overflow:hidden;pointer-events:none;transition:width 0.15s ease-out, padding 0.15s ease-out, opacity 0.15s ease-out}.kritzel-control-split .kritzel-control-dropdown.visible{width:auto;padding:0 6px;opacity:1;pointer-events:auto}.kritzel-control-split .kritzel-control-main:focus,.kritzel-control-split .kritzel-control-main:hover,.kritzel-control-split .kritzel-control-dropdown:focus,.kritzel-control-split .kritzel-control-dropdown:hover{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-control-split .kritzel-control-main:active,.kritzel-control-split .kritzel-control-dropdown:active{background-color:var(--kritzel-controls-control-active-background-color, hsl(0, 0%, 0%, 8.6%))}.kritzel-control-split.selected{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF) !important;color:var(--kritzel-controls-control-selected-color, #ffffff) !important}.kritzel-control-split.selected .kritzel-control-main:hover,.kritzel-control-split.selected .kritzel-control-dropdown:hover{background-color:rgba(255, 255, 255, 0.15)}.kritzel-submenu-content{display:flex;flex-direction:column;gap:var(--kritzel-submenu-gap, 4px);min-width:140px}.kritzel-submenu-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);border-radius:8px;color:var(--kritzel-controls-control-color, #000000);font-size:14px;text-align:left;white-space:nowrap;-webkit-tap-highlight-color:transparent}.kritzel-submenu-item:hover{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-submenu-item.active{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF);color:var(--kritzel-controls-control-selected-color, #ffffff)}.kritzel-submenu-item.active:hover{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF)}.kritzel-config-container{position:relative;display:flex;justify-content:center;align-items:center;height:40px;box-sizing:border-box;-webkit-tap-highlight-color:transparent;flex-shrink:0;width:0;opacity:0;overflow:hidden;pointer-events:none;margin-left:calc(-1 * var(--kritzel-controls-gap, 8px));transition:width 0.2s ease-out, opacity 0.2s ease-out, margin-left 0.2s ease-out}.kritzel-config-container.visible{width:40px;opacity:1;pointer-events:auto;margin-left:0;overflow:visible}.config-gradient-left{position:absolute;top:0;bottom:0;left:-32px;width:32px;background:linear-gradient(to right, transparent, var(--kritzel-controls-background-color, #ffffff));pointer-events:none;z-index:1;opacity:0;transition:opacity 0.2s ease-out}.config-gradient-left.visible{opacity:1}.kritzel-config{display:flex;justify-content:center;align-items:center;cursor:var(--kritzel-global-pointer-cursor, pointer);border-radius:50%}.color-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:var(--kritzel-global-pointer-cursor, pointer);border:2px solid transparent;box-sizing:border-box;background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.font-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:var(--kritzel-global-pointer-cursor, pointer);border:2px solid transparent;box-sizing:border-box;background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.no-config{height:24px;width:24px;border-radius:50%;border:1px dashed gray}kritzel-tooltip{z-index:10001}`;
896
+ const kritzelControlsCss = () => `:host{display:flex;flex-direction:column;user-select:none;max-width:100%;z-index:1}:host(.mobile){--kritzel-controls-control-hover-background-color:transparent;--kritzel-controls-control-active-background-color:transparent}.kritzel-controls{display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:var(--kritzel-controls-gap, 8px);height:100%;padding:var(--kritzel-controls-padding, 8px);background-color:var(--kritzel-controls-background-color, #ffffff);border-radius:var(--kritzel-controls-border-radius, 16px);box-shadow:var(--kritzel-controls-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-controls-border, 1px solid #ebebeb);z-index:1;position:relative;max-width:100%;overflow:hidden}.kritzel-tools-scroll{display:flex;flex-direction:row;align-items:center;gap:var(--kritzel-controls-gap, 8px);overflow-x:auto;overflow-y:hidden;flex:1 1 auto;min-width:0;padding:4px;margin:-4px;scrollbar-width:none;-ms-overflow-style:none}.kritzel-tools-scroll::-webkit-scrollbar{display:none}.scroll-indicator-left,.scroll-indicator-right{position:absolute;top:0;bottom:0;width:32px;pointer-events:none;opacity:0;transition:opacity 0.2s ease-out;z-index:1}.scroll-indicator-left{left:0;background:linear-gradient(to right, var(--kritzel-controls-background-color, #ffffff), transparent);border-radius:var(--kritzel-controls-border-radius, 16px) 0 0 var(--kritzel-controls-border-radius, 16px)}.scroll-indicator-right{right:0;background:linear-gradient(to left, var(--kritzel-controls-background-color, #ffffff), transparent);border-radius:0 var(--kritzel-controls-border-radius, 16px) var(--kritzel-controls-border-radius, 16px) 0}.scroll-indicator-left.visible,.scroll-indicator-right.visible{opacity:1}.kritzel-control{display:flex;justify-content:center;align-items:center;color:var(--kritzel-controls-control-color, #000000);border-radius:var(--kritzel-controls-control-border-radius, 12px);padding:var(--kritzel-controls-control-padding, 8px);border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);-webkit-tap-highlight-color:transparent;font-weight:bold}.kritzel-control:focus,.kritzel-control:hover{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-control:active{background-color:var(--kritzel-controls-control-active-background-color, hsl(0, 0%, 0%, 8.6%))}.kritzel-control.selected,.kritzel-control.selected:hover,.kritzel-control.selected:active{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF) !important;color:var(--kritzel-controls-control-selected-color, #ffffff) !important}.kritzel-control.selected:focus{background-color:var(--kritzel-controls-control-selected-background-color, #007bffe3) !important}.kritzel-control-separator{width:1px;height:24px;background-color:var(--kritzel-controls-border, #ebebeb);margin:0 4px}.kritzel-control-split{position:relative;display:flex;align-items:center;border-radius:var(--kritzel-controls-control-border-radius, 12px);color:var(--kritzel-controls-control-color, #000000)}.kritzel-control-split .kritzel-control-main{display:flex;justify-content:center;align-items:center;padding:var(--kritzel-controls-control-padding, 8px);border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);-webkit-tap-highlight-color:transparent;border-radius:var(--kritzel-controls-control-border-radius, 12px);color:inherit}.kritzel-control-split.selected .kritzel-control-main{border-radius:var(--kritzel-controls-control-border-radius, 12px) 0 0 var(--kritzel-controls-control-border-radius, 12px)}.kritzel-control-split .kritzel-control-dropdown{display:flex;justify-content:center;align-items:center;align-self:stretch;border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);-webkit-tap-highlight-color:transparent;border-radius:0 var(--kritzel-controls-control-border-radius, 12px) var(--kritzel-controls-control-border-radius, 12px) 0;color:inherit;width:0;padding:0;opacity:0;overflow:hidden;pointer-events:none;transition:width 0.15s ease-out, padding 0.15s ease-out, opacity 0.15s ease-out}.kritzel-control-split .kritzel-control-dropdown.visible{width:auto;padding:0 6px;opacity:1;pointer-events:auto}.kritzel-control-split .kritzel-control-main:focus,.kritzel-control-split .kritzel-control-main:hover,.kritzel-control-split .kritzel-control-dropdown:focus,.kritzel-control-split .kritzel-control-dropdown:hover{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-control-split .kritzel-control-main:active,.kritzel-control-split .kritzel-control-dropdown:active{background-color:var(--kritzel-controls-control-active-background-color, hsl(0, 0%, 0%, 8.6%))}.kritzel-control-split.selected{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF) !important;color:var(--kritzel-controls-control-selected-color, #ffffff) !important}.kritzel-control-split.selected .kritzel-control-main:hover,.kritzel-control-split.selected .kritzel-control-dropdown:hover{background-color:rgba(255, 255, 255, 0.15)}.kritzel-submenu-content{display:flex;flex-direction:column;gap:var(--kritzel-submenu-gap, 4px);min-width:140px}.kritzel-submenu-item{display:flex;align-items:center;gap:10px;padding:10px 12px;border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);border-radius:8px;color:var(--kritzel-controls-control-color, #000000);font-size:14px;text-align:left;white-space:nowrap;-webkit-tap-highlight-color:transparent}.kritzel-submenu-item:hover{background-color:var(--kritzel-controls-control-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.kritzel-submenu-item.active{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF);color:var(--kritzel-controls-control-selected-color, #ffffff)}.kritzel-submenu-item.active:hover{background-color:var(--kritzel-controls-control-selected-background-color, #007AFF)}.kritzel-config-container{position:relative;display:flex;justify-content:center;align-items:center;height:40px;box-sizing:border-box;-webkit-tap-highlight-color:transparent;flex-shrink:0;width:0;opacity:0;overflow:hidden;pointer-events:none;margin-left:calc(-1 * var(--kritzel-controls-gap, 8px));transition:width 0.2s ease-out, opacity 0.2s ease-out, margin-left 0.2s ease-out}.kritzel-config-container.visible{width:40px;opacity:1;pointer-events:auto;margin-left:0;overflow:visible}.config-gradient-left{position:absolute;top:0;bottom:0;left:-32px;width:32px;background:linear-gradient(to right, transparent, var(--kritzel-controls-background-color, #ffffff));pointer-events:none;z-index:1;opacity:0;transition:opacity 0.2s ease-out}.config-gradient-left.visible{opacity:1}.kritzel-config{display:flex;justify-content:center;align-items:center;cursor:var(--kritzel-global-pointer-cursor, pointer);border-radius:50%}.color-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:var(--kritzel-global-pointer-cursor, pointer);border:2px solid transparent;box-sizing:border-box;background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.font-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:var(--kritzel-global-pointer-cursor, pointer);border:2px solid transparent;box-sizing:border-box;background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.no-config{height:24px;width:24px;border-radius:50%;border:1px dashed gray}kritzel-tooltip{z-index:10001}`;
896
897
 
897
898
  const KritzelControls = class {
898
899
  constructor(hostRef) {
@@ -913,6 +914,9 @@ const KritzelControls = class {
913
914
  canScrollRight = false;
914
915
  needsScrolling = false;
915
916
  displayValues = null;
917
+ internalControls = [];
918
+ handleActiveToolChangeBound = this.handleActiveToolChange.bind(this);
919
+ handleSelectionChangeBound = this.handleSelectionChange.bind(this);
916
920
  handleKeyDown(event) {
917
921
  if (event.key === 'Escape') {
918
922
  event.preventDefault();
@@ -921,7 +925,7 @@ const KritzelControls = class {
921
925
  }
922
926
  }
923
927
  async handleActiveToolChange(event) {
924
- this.activeControl = this.controls.find(control => control.tool === event.detail) || null;
928
+ this.activeControl = this.internalControls.find(control => control.tool === event.detail) || null;
925
929
  if (this.activeControl?.tool) {
926
930
  this.updateDisplayValues(this.activeControl.tool);
927
931
  }
@@ -932,6 +936,11 @@ const KritzelControls = class {
932
936
  this.updateDisplayValues(this.activeControl.tool);
933
937
  }
934
938
  }
939
+ async onControlsChange() {
940
+ if (this.kritzelEngine) {
941
+ await this.initializeTools();
942
+ }
943
+ }
935
944
  onThemeChange() {
936
945
  if (this.activeControl?.tool) {
937
946
  this.updateDisplayValues(this.activeControl.tool);
@@ -998,6 +1007,12 @@ const KritzelControls = class {
998
1007
  componentDidRender() {
999
1008
  this.updateScrollIndicators();
1000
1009
  }
1010
+ disconnectedCallback() {
1011
+ if (this.kritzelEngine) {
1012
+ this.kritzelEngine.removeEventListener('activeToolChange', this.handleActiveToolChangeBound);
1013
+ this.kritzelEngine.removeEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
1014
+ }
1015
+ }
1001
1016
  updateScrollIndicators() {
1002
1017
  if (!this.toolsScrollRef)
1003
1018
  return;
@@ -1022,16 +1037,28 @@ const KritzelControls = class {
1022
1037
  if (!this.kritzelEngine) {
1023
1038
  throw new Error('kritzel-engine not found in parent element.');
1024
1039
  }
1040
+ this.kritzelEngine.addEventListener('activeToolChange', this.handleActiveToolChangeBound);
1041
+ this.kritzelEngine.addEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
1025
1042
  }
1026
1043
  async initializeTools() {
1027
- for (const c of this.controls) {
1044
+ let hasDefault = false;
1045
+ const newControls = this.controls.map(c => ({ ...c }));
1046
+ for (const c of newControls) {
1028
1047
  if (c.type === 'tool' && c.tool) {
1029
- c.tool = await this.kritzelEngine.registerTool(c.name, c.tool, c.config);
1048
+ let toolConstructor = c.tool;
1049
+ if (typeof toolConstructor !== 'function') {
1050
+ toolConstructor = toolConstructor.constructor;
1051
+ }
1052
+ const registered = await this.kritzelEngine.registerTool(c.name, toolConstructor, c.config);
1053
+ if (registered) {
1054
+ c.tool = registered;
1055
+ }
1030
1056
  }
1031
1057
  if (c.type === 'tool' && c.isDefault && c.tool) {
1032
1058
  await this.kritzelEngine.changeActiveTool(c.tool);
1033
1059
  this.activeControl = c;
1034
1060
  this.updateDisplayValues(c.tool);
1061
+ hasDefault = true;
1035
1062
  }
1036
1063
  if (c.type === 'config') {
1037
1064
  if (this.firstConfig === null) {
@@ -1042,6 +1069,16 @@ const KritzelControls = class {
1042
1069
  }
1043
1070
  }
1044
1071
  }
1072
+ this.internalControls = newControls;
1073
+ // If no tool is marked as default, activate the first tool control
1074
+ if (!hasDefault) {
1075
+ const firstTool = this.internalControls.find(c => c.type === 'tool' && c.tool);
1076
+ if (firstTool) {
1077
+ await this.kritzelEngine.changeActiveTool(firstTool.tool);
1078
+ this.activeControl = firstTool;
1079
+ this.updateDisplayValues(firstTool.tool);
1080
+ }
1081
+ }
1045
1082
  }
1046
1083
  async handleControlClick(control) {
1047
1084
  this.activeControl = control;
@@ -1081,21 +1118,20 @@ const KritzelControls = class {
1081
1118
  await this.handleControlClick(control);
1082
1119
  }
1083
1120
  render() {
1084
- const hasConfigUI = this.activeControl?.tool instanceof workspace_migrations.KritzelBrushTool ||
1085
- this.activeControl?.tool instanceof workspace_migrations.KritzelTextTool ||
1086
- this.activeControl?.tool instanceof workspace_migrations.KritzelLineTool ||
1087
- this.activeControl?.tool instanceof workspace_migrations.KritzelShapeTool ||
1088
- (this.activeControl?.tool instanceof workspace_migrations.KritzelSelectionTool && this.activeControl.tool.hasSelection());
1121
+ const activeToolConfig = this.activeControl?.tool
1122
+ ? KritzelToolConfigHelper.getToolConfig(this.activeControl.tool)
1123
+ : null;
1124
+ const hasConfigUI = activeToolConfig !== null;
1089
1125
  // Separate tool controls from config control
1090
- const toolControls = this.controls.filter(c => c.type === 'tool' || c.type === 'separator');
1091
- const configControl = this.controls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
1092
- return (index.h(index.Host, { key: '93d08a3268edb67fc4cccb291b6e0aff6cf5a4bd', class: {
1126
+ const toolControls = this.internalControls.filter(c => c.type === 'tool' || c.type === 'separator');
1127
+ const configControl = this.internalControls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
1128
+ return (index.h(index.Host, { key: '7f2a5fed45ac89b34a86b87552ffaa1b94f44d8b', class: {
1093
1129
  mobile: this.isTouchDevice,
1094
- } }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '8862ea7e524b3e23d87ffea2929e04df7231bb0c', style: {
1130
+ } }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '2dcbbe498bce0b59fbd225d103f2e322d3b7ff85', style: {
1095
1131
  position: 'absolute',
1096
1132
  bottom: '56px',
1097
1133
  left: '12px',
1098
- }, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '2ea2a41ba4cda77f5abde9231d293da181a2a568', class: "kritzel-controls" }, index.h("div", { key: '6bd4f6d930a0a51d5549b6dbae1e7be14cbe7822', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), index.h("div", { key: 'c712ca502a4ebd244394158b39391a49839bc386', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
1134
+ }, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '6431079040502a78f021c612a7e953b1349f319a', class: "kritzel-controls" }, index.h("div", { key: '6e0d6dce107cf6b54fb904809fd525ce3b2ae4f0', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), index.h("div", { key: '2686304ad10deac2d022e1deba19195587659d64', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
1099
1135
  // Check if this control has sub-options (split-button)
1100
1136
  if (control.subOptions?.length) {
1101
1137
  const selectedSubOption = this.getSelectedSubOption(control);
@@ -1125,10 +1161,10 @@ const KritzelControls = class {
1125
1161
  'kritzel-control': true,
1126
1162
  'selected': this.activeControl?.name === control?.name,
1127
1163
  }, key: control.name, "data-testid": `tool-${control.name}`, onClick: _event => this.handleControlClick?.(control), "aria-label": control.name.charAt(0).toUpperCase() + control.name.slice(1) }, index.h("kritzel-icon", { name: control.icon })));
1128
- })), index.h("div", { key: '0d8ae76ea22cb0aea4f7971a17c787c722d1f476', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (index.h("div", { class: {
1164
+ })), index.h("div", { key: 'f4bcbc856f6e027cdb579356faf54288b43aa080', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (index.h("div", { class: {
1129
1165
  'kritzel-config-container': true,
1130
1166
  'visible': hasConfigUI,
1131
- }, key: configControl.name }, index.h("div", { key: 'd3da3913362d96109f618c86bd8370f6253a1b7c', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), index.h("kritzel-tooltip", { key: '26fed6901c67362ec0c18eacd23b48fff5a361ef', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, index.h("kritzel-tool-config", { key: '0371c038859c0bc3c413b8c72a836d611da01608', tool: this.activeControl.tool, theme: this.theme, onToolChange: event => this.handleToolChange?.(event), onDisplayValuesChange: this.handleDisplayValuesChange, style: { width: '100%', height: '100%' } })), index.h("div", { key: 'b9bb29fc19ee335103ea050155f5e240f2ad2cd9', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
1167
+ }, key: configControl.name }, index.h("div", { key: '0646c98b32047f51841f75dd5fb57813ebb153f5', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), index.h("kritzel-tooltip", { key: '0816b8d7ca55add3c6a81de788be3c61a8a814f2', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, index.h("kritzel-tool-config", { key: '8f299593454e7855d83ad5d79b528940b2dcb202', tool: this.activeControl.tool, theme: this.theme, engine: this.kritzelEngine, onToolChange: event => this.handleToolChange?.(event), onDisplayValuesChange: this.handleDisplayValuesChange, style: { width: '100%', height: '100%' } })), index.h("div", { key: '8b2dc1dcc61df93a92cea8ba2aeb776e57965ab3', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
1132
1168
  if (el)
1133
1169
  this.configTriggerRef = el;
1134
1170
  }, onKeyDown: event => {
@@ -1137,13 +1173,16 @@ const KritzelControls = class {
1137
1173
  }
1138
1174
  }, style: {
1139
1175
  cursor: 'pointer',
1140
- } }, this.displayValues && (index.h("div", { key: '5918f90d824c41700c5dac4fca13cb8b47759473', class: "color-container" }, index.h("kritzel-color", { key: '08b7847f1d9117cec216979016d10d7b25076ecc', value: this.displayValues.color, theme: this.theme, size: 18, style: {
1176
+ } }, this.displayValues && (index.h("div", { key: '1074fc05048aed92ec9d62e347822df0a57a80e4', class: "color-container" }, index.h("kritzel-color", { key: '222efa6883ccbc6c97d10360039a1315de7d6273', value: this.displayValues.color, theme: this.theme, size: 18, style: {
1141
1177
  borderRadius: '50%',
1142
1178
  border: 'none',
1143
1179
  } })))))))));
1144
1180
  }
1145
1181
  static get assetsDirs() { return ["../assets"]; }
1146
1182
  static get watchers() { return {
1183
+ "controls": [{
1184
+ "onControlsChange": 0
1185
+ }],
1147
1186
  "theme": [{
1148
1187
  "onThemeChange": 0
1149
1188
  }]
@@ -2091,7 +2130,7 @@ const DEFAULT_SYNC_CONFIG = {
2091
2130
  ],
2092
2131
  };
2093
2132
 
2094
- 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;z-index:10000}.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;z-index:10000}.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}`;
2133
+ 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}`;
2095
2134
 
2096
2135
  const KritzelEditor = class {
2097
2136
  constructor(hostRef) {
@@ -20962,7 +21001,7 @@ class KritzelKeyHandler extends workspace_migrations.KritzelBaseHandler {
20962
21001
  * @param index - The zero-based index of the tool to activate from the tool registry.
20963
21002
  */
20964
21003
  switchToolByIndex(index) {
20965
- const toolInstance = workspace_migrations.KritzelToolRegistry.getToolByIndex(index);
21004
+ const toolInstance = this._core.toolRegistry.getToolByIndex(index);
20966
21005
  if (toolInstance) {
20967
21006
  this._core.store.setState('activeTool', toolInstance);
20968
21007
  this._core.deselectAllObjects();
@@ -21093,8 +21132,8 @@ class KritzelContextMenuHandler extends workspace_migrations.KritzelBaseHandler
21093
21132
  let y = clickY;
21094
21133
  const menuWidthEstimate = 150;
21095
21134
  const margin = 10;
21096
- if (x + menuWidthEstimate > window.innerWidth - margin) {
21097
- x = window.innerWidth - menuWidthEstimate - margin;
21135
+ if (x + menuWidthEstimate > this._core.store.state.viewportWidth - margin) {
21136
+ x = this._core.store.state.viewportWidth - menuWidthEstimate - margin;
21098
21137
  }
21099
21138
  x = Math.max(margin, x);
21100
21139
  y = Math.max(margin, y);
@@ -21474,6 +21513,76 @@ class AlignmentHelper {
21474
21513
  }
21475
21514
  }
21476
21515
 
21516
+ /**
21517
+ * A per-engine registry for managing drawing tools in the Kritzel library.
21518
+ * Each `KritzelCore` owns its own `KritzelToolRegistry` instance so that
21519
+ * multiple editors on the same page do not share tool instances or configs.
21520
+ *
21521
+ * Tools are instantiated and stored by name, allowing retrieval by name or index.
21522
+ */
21523
+ class KritzelToolRegistry {
21524
+ core;
21525
+ /** Internal storage for registered tools, mapping tool names to their instances. */
21526
+ registry = {};
21527
+ /**
21528
+ * Creates a new tool registry bound to a specific `KritzelCore` instance.
21529
+ * The bound core is used as the constructor argument when registering new tools.
21530
+ *
21531
+ * @param core - The `KritzelCore` instance this registry is bound to.
21532
+ */
21533
+ constructor(core) {
21534
+ this.core = core;
21535
+ }
21536
+ /**
21537
+ * Registers a new tool by instantiating it with the registry's bound core.
21538
+ * The tool is stored in the registry under the specified name.
21539
+ *
21540
+ * @param toolName - The unique identifier for the tool.
21541
+ * @param constructor - The tool class constructor that extends `KritzelBaseTool`.
21542
+ * @returns The newly created and registered tool instance.
21543
+ */
21544
+ registerTool(toolName, constructor) {
21545
+ const toolInstance = new constructor(this.core);
21546
+ toolInstance.name = toolName;
21547
+ this.registry[toolName] = toolInstance;
21548
+ return toolInstance;
21549
+ }
21550
+ /**
21551
+ * Checks if a tool with the given name is registered.
21552
+ *
21553
+ * @param toolName - The unique identifier of the tool to check.
21554
+ * @returns `true` if the tool is registered, `false` otherwise.
21555
+ */
21556
+ hasTool(toolName) {
21557
+ return toolName in this.registry;
21558
+ }
21559
+ /**
21560
+ * Retrieves a registered tool by its name.
21561
+ * Logs a warning if the tool is not found.
21562
+ *
21563
+ * @param toolName - The unique identifier of the tool to retrieve.
21564
+ * @returns The tool instance if found, or `null` if not registered.
21565
+ */
21566
+ getTool(toolName) {
21567
+ const toolInstance = this.registry[toolName];
21568
+ if (!toolInstance) {
21569
+ console.warn(`Unknown tool: ${toolName}`);
21570
+ return null;
21571
+ }
21572
+ return toolInstance;
21573
+ }
21574
+ /**
21575
+ * Retrieves a registered tool by its index in the registry.
21576
+ * The index is based on the order tools were registered.
21577
+ *
21578
+ * @param index - The zero-based index of the tool in the registry.
21579
+ * @returns The tool instance at the specified index, or `null` if the index is out of bounds.
21580
+ */
21581
+ getToolByIndex(index) {
21582
+ return Object.values(this.registry)[index] ?? null;
21583
+ }
21584
+ }
21585
+
21477
21586
  /**
21478
21587
  * A quadtree data structure for efficient spatial indexing of objects.
21479
21588
  * Quadtrees recursively subdivide 2D space into four quadrants to enable
@@ -22982,7 +23091,14 @@ class KritzelStore {
22982
23091
  * @param state - The initial engine state configuration
22983
23092
  */
22984
23093
  constructor(state) {
22985
- this._state = state;
23094
+ this._state = {
23095
+ ...state,
23096
+ contextMenuItems: [...state.contextMenuItems],
23097
+ debugInfo: { ...state.debugInfo },
23098
+ pointers: new Map(state.pointers),
23099
+ workspaces: [...state.workspaces],
23100
+ cursor: { ...state.cursor },
23101
+ };
22986
23102
  this._state.objects = new KritzelObjectMap();
22987
23103
  }
22988
23104
  /**
@@ -23621,6 +23737,8 @@ class KritzelCore {
23621
23737
  _cursorManager;
23622
23738
  /** Manager for theme styling */
23623
23739
  _themeManager;
23740
+ /** Per-core registry of drawing tools (one instance per editor). */
23741
+ _toolRegistry;
23624
23742
  /** Optional unique identifier for namespacing storage keys across multiple editor instances */
23625
23743
  _editorId;
23626
23744
  /** Current user for awareness broadcasting */
@@ -23667,6 +23785,13 @@ class KritzelCore {
23667
23785
  get themeManager() {
23668
23786
  return this._themeManager;
23669
23787
  }
23788
+ /**
23789
+ * Gets the tool registry scoped to this core instance.
23790
+ * @returns The KritzelToolRegistry owned by this core
23791
+ */
23792
+ get toolRegistry() {
23793
+ return this._toolRegistry;
23794
+ }
23670
23795
  /**
23671
23796
  * Gets the editor ID used for namespacing storage keys.
23672
23797
  * @returns The editor ID or undefined if not set
@@ -23712,6 +23837,7 @@ class KritzelCore {
23712
23837
  this._anchorManager = new workspace_migrations.KritzelAnchorManager(this);
23713
23838
  this._cursorManager = new KritzelCursorManager(this);
23714
23839
  this._themeManager = new workspace_migrations.KritzelThemeManager(this);
23840
+ this._toolRegistry = new KritzelToolRegistry(this);
23715
23841
  this._assetResolver = new workspace_migrations.KritzelAssetResolver();
23716
23842
  }
23717
23843
  /**
@@ -23818,6 +23944,7 @@ class KritzelCore {
23818
23944
  async initializeWorkspace(workspace, options) {
23819
23945
  // Load all workspaces from app state map
23820
23946
  const workspaces = this.loadWorkspacesFromAppState();
23947
+ const shouldCreateEditorScopedFallback = !workspace && !!this._editorId;
23821
23948
  // Find newest created workspace (tie-break by most recently updated)
23822
23949
  const newestCreatedWorkspace = workspaces.length > 0
23823
23950
  ? [...workspaces].sort((a, b) => {
@@ -23843,7 +23970,7 @@ class KritzelCore {
23843
23970
  // Use last active workspace from localStorage
23844
23971
  activeWorkspace = lastActiveWorkspace;
23845
23972
  }
23846
- else if (newestCreatedWorkspace) {
23973
+ else if (newestCreatedWorkspace && !shouldCreateEditorScopedFallback) {
23847
23974
  // Use newest created workspace
23848
23975
  activeWorkspace = newestCreatedWorkspace;
23849
23976
  }
@@ -24408,7 +24535,7 @@ class KritzelCore {
24408
24535
  this._store.state.copiedObjectIdMapping = newIdMapping;
24409
24536
  }
24410
24537
  });
24411
- this._store.setState('activeTool', workspace_migrations.KritzelToolRegistry.getTool('selection'));
24538
+ this._store.setState('activeTool', this._toolRegistry.getTool('selection'));
24412
24539
  this.engine.emitObjectsChange();
24413
24540
  this.rerender();
24414
24541
  }
@@ -24597,7 +24724,7 @@ class KritzelCore {
24597
24724
  selectionGroup.rotation = selectionGroup.objects[0].rotation;
24598
24725
  }
24599
24726
  this.addSelectionGroup(selectionGroup);
24600
- this._store.setState('activeTool', workspace_migrations.KritzelToolRegistry.getTool('selection'));
24727
+ this._store.setState('activeTool', this._toolRegistry.getTool('selection'));
24601
24728
  this.rerender();
24602
24729
  }
24603
24730
  }
@@ -24631,7 +24758,7 @@ class KritzelCore {
24631
24758
  selectionGroup.rotation = selectionGroup.objects[0].rotation;
24632
24759
  }
24633
24760
  this.addSelectionGroup(selectionGroup);
24634
- this._store.setState('activeTool', workspace_migrations.KritzelToolRegistry.getTool('selection'));
24761
+ this._store.setState('activeTool', this._toolRegistry.getTool('selection'));
24635
24762
  this.rerender();
24636
24763
  }
24637
24764
  }
@@ -24787,7 +24914,7 @@ class KritzelCore {
24787
24914
  }
24788
24915
  this.resetActiveText();
24789
24916
  this.clearSelection();
24790
- this._store.setState('activeTool', workspace_migrations.KritzelToolRegistry.getTool('selection'));
24917
+ this._store.setState('activeTool', this._toolRegistry.getTool('selection'));
24791
24918
  }
24792
24919
  /**
24793
24920
  * Determines whether to display the selection group UI for an object.
@@ -26475,11 +26602,22 @@ const KritzelEngine = class {
26475
26602
  * @returns The registered tool instance, or `null` if registration failed.
26476
26603
  */
26477
26604
  async registerTool(toolName, toolClass, toolConfig) {
26478
- if (typeof toolClass !== 'function' || !(toolClass.prototype instanceof workspace_migrations.KritzelBaseTool)) {
26605
+ if (typeof toolClass !== 'function') {
26479
26606
  console.error(`Failed to register tool "${toolName}": Tool class must be a constructor function`);
26480
26607
  return null;
26481
26608
  }
26482
- const registeredTool = workspace_migrations.KritzelToolRegistry.registerTool(toolName, toolClass, this.core);
26609
+ // If a tool with this name is already registered, return the existing instance
26610
+ // This avoids dual-package issues when tool classes are passed from external bundles
26611
+ if (this.core.toolRegistry.hasTool(toolName)) {
26612
+ const existingTool = this.core.toolRegistry.getTool(toolName);
26613
+ if (toolConfig) {
26614
+ Object.entries(toolConfig).forEach(([key, value]) => {
26615
+ existingTool[key] = value;
26616
+ });
26617
+ }
26618
+ return existingTool;
26619
+ }
26620
+ const registeredTool = this.core.toolRegistry.registerTool(toolName, toolClass);
26483
26621
  if (toolConfig) {
26484
26622
  Object.entries(toolConfig).forEach(([key, value]) => {
26485
26623
  registeredTool[key] = value;
@@ -26757,7 +26895,7 @@ const KritzelEngine = class {
26757
26895
  * @param objects - The objects to select.
26758
26896
  */
26759
26897
  async selectObjects(objects) {
26760
- const selectionTool = workspace_migrations.KritzelToolRegistry.getTool('selection');
26898
+ const selectionTool = this.core.toolRegistry.getTool('selection');
26761
26899
  if (!selectionTool) {
26762
26900
  return;
26763
26901
  }
@@ -26768,7 +26906,7 @@ const KritzelEngine = class {
26768
26906
  }
26769
26907
  /** Selects all objects currently visible in the viewport. Switches to the selection tool automatically. */
26770
26908
  async selectAllObjectsInViewport() {
26771
- const selectionTool = workspace_migrations.KritzelToolRegistry.getTool('selection');
26909
+ const selectionTool = this.core.toolRegistry.getTool('selection');
26772
26910
  if (!selectionTool) {
26773
26911
  return;
26774
26912
  }
@@ -28127,7 +28265,7 @@ const KritzelEngine = class {
28127
28265
  strokeWidth: data.indicatorStrokeWidth,
28128
28266
  } }))));
28129
28267
  })()), this.core.store.state.isContextMenuVisible && (index.h("kritzel-context-menu", { class: "context-menu", ref: el => (this.contextMenuElement = el ?? null), items: this.core.store.state.contextMenuItems, objects: this.core.store.selectionGroup?.objects || [], style: {
28130
- position: 'fixed',
28268
+ position: 'absolute',
28131
28269
  left: `${this.core.store.state.contextMenuX}px`,
28132
28270
  top: `${this.core.store.state.contextMenuY}px`,
28133
28271
  zIndex: '10002',
@@ -28872,7 +29010,7 @@ const KritzelMenuItem = class {
28872
29010
  };
28873
29011
  KritzelMenuItem.style = kritzelMenuItemCss();
28874
29012
 
28875
- const kritzelMoreMenuCss = () => `:host{display:inline-flex}.more-menu-wrapper{display:inline-flex;padding:var(--kritzel-more-menu-padding, 4px);background-color:var(--kritzel-more-menu-background-color, #ffffff);border-radius:var(--kritzel-more-menu-border-radius, 12px);box-shadow:var(--kritzel-more-menu-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-more-menu-border, 1px solid #ebebeb);opacity:0;pointer-events:none;transition:opacity 0.2s ease-out}.more-menu-wrapper.visible{opacity:1;pointer-events:auto}:host(.mobile){--kritzel-more-menu-button-hover-background-color:transparent;--kritzel-more-menu-button-active-background-color:transparent}.more-menu-button{display:flex;align-items:center;justify-content:center;width:var(--kritzel-more-menu-button-width, 40px);height:var(--kritzel-more-menu-button-height, 40px);padding:0;border:none;border-radius:var(--kritzel-more-menu-inner-border-radius, 12px);background-color:transparent;cursor:var(--kritzel-global-pointer-cursor, pointer);box-shadow:none;transition:background-color 150ms ease;-webkit-tap-highlight-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none;color:var(--kritzel-more-menu-button-color, currentColor)}.more-menu-button:hover{background-color:var(--kritzel-more-menu-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.more-menu-button:focus-visible{background-color:var(--kritzel-more-menu-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.more-menu-button:active{background-color:var(--kritzel-more-menu-button-active-background-color, hsl(0, 0%, 0%, 4.3%))}`;
29013
+ const kritzelMoreMenuCss = () => `:host{display:inline-flex;z-index:1}.more-menu-wrapper{display:inline-flex;padding:var(--kritzel-more-menu-padding, 4px);background-color:var(--kritzel-more-menu-background-color, #ffffff);border-radius:var(--kritzel-more-menu-border-radius, 12px);box-shadow:var(--kritzel-more-menu-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-more-menu-border, 1px solid #ebebeb);opacity:0;pointer-events:none;transition:opacity 0.2s ease-out}.more-menu-wrapper.visible{opacity:1;pointer-events:auto}:host(.mobile){--kritzel-more-menu-button-hover-background-color:transparent;--kritzel-more-menu-button-active-background-color:transparent}.more-menu-button{display:flex;align-items:center;justify-content:center;width:var(--kritzel-more-menu-button-width, 40px);height:var(--kritzel-more-menu-button-height, 40px);padding:0;border:none;border-radius:var(--kritzel-more-menu-inner-border-radius, 12px);background-color:transparent;cursor:var(--kritzel-global-pointer-cursor, pointer);box-shadow:none;transition:background-color 150ms ease;-webkit-tap-highlight-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none;color:var(--kritzel-more-menu-button-color, currentColor)}.more-menu-button:hover{background-color:var(--kritzel-more-menu-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.more-menu-button:focus-visible{background-color:var(--kritzel-more-menu-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.more-menu-button:active{background-color:var(--kritzel-more-menu-button-active-background-color, hsl(0, 0%, 0%, 4.3%))}`;
28876
29014
 
28877
29015
  const KritzelMoreMenu = class {
28878
29016
  constructor(hostRef) {
@@ -29436,7 +29574,7 @@ const KritzelPortal = class {
29436
29574
  * This file is auto-generated by the version bump scripts.
29437
29575
  * Do not modify manually.
29438
29576
  */
29439
- const KRITZEL_VERSION = '0.3.1';
29577
+ const KRITZEL_VERSION = '0.3.7';
29440
29578
 
29441
29579
  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)}`;
29442
29580
 
@@ -29962,9 +30100,19 @@ const KritzelToolConfig = class {
29962
30100
  }
29963
30101
  isExpanded = false;
29964
30102
  theme;
30103
+ engine;
30104
+ handleSelectionChangeBound = this.handleSelectionChange.bind(this);
29965
30105
  onThemeChange() {
29966
30106
  this.emitDisplayValues();
29967
30107
  }
30108
+ handleEngineChange(newEngine, oldEngine) {
30109
+ if (oldEngine) {
30110
+ oldEngine.removeEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
30111
+ }
30112
+ if (newEngine) {
30113
+ newEngine.addEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
30114
+ }
30115
+ }
29968
30116
  toolChange;
29969
30117
  displayValuesChange;
29970
30118
  config;
@@ -29981,6 +30129,11 @@ const KritzelToolConfig = class {
29981
30129
  }
29982
30130
  }
29983
30131
  }
30132
+ disconnectedCallback() {
30133
+ if (this.engine) {
30134
+ this.engine.removeEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
30135
+ }
30136
+ }
29984
30137
  componentWillLoad() {
29985
30138
  this.config = KritzelToolConfigHelper.getToolConfig(this.tool);
29986
30139
  if (this.config) {
@@ -29988,6 +30141,9 @@ const KritzelToolConfig = class {
29988
30141
  this.currentOpacity = this.tool[this.config.opacityProperty] ?? 1;
29989
30142
  this.emitDisplayValues();
29990
30143
  }
30144
+ if (this.engine) {
30145
+ this.engine.addEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
30146
+ }
29991
30147
  }
29992
30148
  emitDisplayValues() {
29993
30149
  if (!this.config)
@@ -30119,6 +30275,9 @@ const KritzelToolConfig = class {
30119
30275
  }],
30120
30276
  "theme": [{
30121
30277
  "onThemeChange": 0
30278
+ }],
30279
+ "engine": [{
30280
+ "handleEngineChange": 0
30122
30281
  }]
30123
30282
  }; }
30124
30283
  };
@@ -30279,7 +30438,7 @@ const KritzelTooltip = class {
30279
30438
  };
30280
30439
  KritzelTooltip.style = kritzelTooltipCss();
30281
30440
 
30282
- const kritzelUtilityPanelCss = () => `:host{display:flex;flex-direction:row;align-items:center;padding:4px;gap:8px;border-top-left-radius:12px;border-top-right-radius:12px;background-color:var(--kritzel-utility-panel-background-color, #e2e2e2);width:fit-content;user-select:none;z-index:10000}.utility-button{display:flex;justify-content:center;align-items:center;width:28px;height:28px;padding:8px 4px;border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);color:var(--kritzel-utility-panel-button-color, #333333);--kritzel-icon-color:var(--kritzel-utility-panel-button-color, #333333);-webkit-tap-highlight-color:transparent;border-radius:var(--kritzel-utility-panel-button-border-radius, 8px)}.utility-button:hover,.utility-button:focus-visible{background-color:var(--kritzel-utility-panel-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.utility-button:disabled{opacity:0.4;cursor:not-allowed;pointer-events:none}.utility-separator{width:1px;height:16px;background-color:var(--kritzel-utility-panel-separator-color, hsl(0, 0%, 0%, 8%))}`;
30441
+ const kritzelUtilityPanelCss = () => `:host{display:flex;flex-direction:row;align-items:center;padding:4px;gap:8px;border-top-left-radius:12px;border-top-right-radius:12px;background-color:var(--kritzel-utility-panel-background-color, #e2e2e2);width:fit-content;user-select:none;z-index:1}.utility-button{display:flex;justify-content:center;align-items:center;width:28px;height:28px;padding:8px 4px;border:none;background:none;cursor:var(--kritzel-global-pointer-cursor, pointer);color:var(--kritzel-utility-panel-button-color, #333333);--kritzel-icon-color:var(--kritzel-utility-panel-button-color, #333333);-webkit-tap-highlight-color:transparent;border-radius:var(--kritzel-utility-panel-button-border-radius, 8px)}.utility-button:hover,.utility-button:focus-visible{background-color:var(--kritzel-utility-panel-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.utility-button:disabled{opacity:0.4;cursor:not-allowed;pointer-events:none}.utility-separator{width:1px;height:16px;background-color:var(--kritzel-utility-panel-separator-color, hsl(0, 0%, 0%, 8%))}`;
30283
30442
 
30284
30443
  const KritzelUtilityPanel = class {
30285
30444
  constructor(hostRef) {