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,25 +1,46 @@
1
1
  /**
2
- * A static registry for managing drawing tools in the Kritzel library.
2
+ * A per-engine registry for managing drawing tools in the Kritzel library.
3
+ * Each `KritzelCore` owns its own `KritzelToolRegistry` instance so that
4
+ * multiple editors on the same page do not share tool instances or configs.
5
+ *
3
6
  * Tools are instantiated and stored by name, allowing retrieval by name or index.
4
7
  */
5
8
  export class KritzelToolRegistry {
9
+ core;
6
10
  /** Internal storage for registered tools, mapping tool names to their instances. */
7
- static registry = {};
11
+ registry = {};
8
12
  /**
9
- * Registers a new tool by instantiating it with the provided constructor and core instance.
13
+ * Creates a new tool registry bound to a specific `KritzelCore` instance.
14
+ * The bound core is used as the constructor argument when registering new tools.
15
+ *
16
+ * @param core - The `KritzelCore` instance this registry is bound to.
17
+ */
18
+ constructor(core) {
19
+ this.core = core;
20
+ }
21
+ /**
22
+ * Registers a new tool by instantiating it with the registry's bound core.
10
23
  * The tool is stored in the registry under the specified name.
11
24
  *
12
25
  * @param toolName - The unique identifier for the tool.
13
26
  * @param constructor - The tool class constructor that extends `KritzelBaseTool`.
14
- * @param core - The `KritzelCore` instance to pass to the tool constructor.
15
27
  * @returns The newly created and registered tool instance.
16
28
  */
17
- static registerTool(toolName, constructor, core) {
18
- const toolInstance = new constructor(core);
29
+ registerTool(toolName, constructor) {
30
+ const toolInstance = new constructor(this.core);
19
31
  toolInstance.name = toolName;
20
32
  this.registry[toolName] = toolInstance;
21
33
  return toolInstance;
22
34
  }
35
+ /**
36
+ * Checks if a tool with the given name is registered.
37
+ *
38
+ * @param toolName - The unique identifier of the tool to check.
39
+ * @returns `true` if the tool is registered, `false` otherwise.
40
+ */
41
+ hasTool(toolName) {
42
+ return toolName in this.registry;
43
+ }
23
44
  /**
24
45
  * Retrieves a registered tool by its name.
25
46
  * Logs a warning if the tool is not found.
@@ -27,7 +48,7 @@ export class KritzelToolRegistry {
27
48
  * @param toolName - The unique identifier of the tool to retrieve.
28
49
  * @returns The tool instance if found, or `null` if not registered.
29
50
  */
30
- static getTool(toolName) {
51
+ getTool(toolName) {
31
52
  const toolInstance = this.registry[toolName];
32
53
  if (!toolInstance) {
33
54
  console.warn(`Unknown tool: ${toolName}`);
@@ -42,7 +63,7 @@ export class KritzelToolRegistry {
42
63
  * @param index - The zero-based index of the tool in the registry.
43
64
  * @returns The tool instance at the specified index, or `null` if the index is out of bounds.
44
65
  */
45
- static getToolByIndex(index) {
66
+ getToolByIndex(index) {
46
67
  return Object.values(this.registry)[index] ?? null;
47
68
  }
48
69
  }
@@ -1,7 +1,6 @@
1
1
  import { KritzelImage } from "../objects/image.class";
2
2
  import { KritzelBaseTool } from "./base-tool.class";
3
3
  import imageCompression from "browser-image-compression";
4
- import { KritzelToolRegistry } from "../registries/tool.registry";
5
4
  /**
6
5
  * Image tool for importing and placing images on the canvas.
7
6
  *
@@ -179,7 +178,7 @@ export class KritzelImageTool extends KritzelBaseTool {
179
178
  }
180
179
  this._core.addObject(image);
181
180
  });
182
- this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
181
+ this._core.store.setState('activeTool', this._core.toolRegistry.getTool('selection'));
183
182
  this._core.selectObjects(images);
184
183
  this._core.engine.emitObjectsChange();
185
184
  this._core.engine.emitObjectsAdded(images);
@@ -189,6 +188,6 @@ export class KritzelImageTool extends KritzelBaseTool {
189
188
  * Switches back to the selection tool without adding any image.
190
189
  */
191
190
  handleCancel() {
192
- this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
191
+ this._core.store.setState('activeTool', this._core.toolRegistry.getTool('selection'));
193
192
  }
194
193
  }
@@ -1,7 +1,6 @@
1
1
  import { KritzelEventHelper } from "../../helpers/event.helper";
2
2
  import { KritzelLine } from "../objects/line.class";
3
3
  import { KritzelBaseTool } from "./base-tool.class";
4
- import { KritzelToolRegistry } from "../registries/tool.registry";
5
4
  import { KritzelSelectionGroup } from "../objects/selection-group.class";
6
5
  import { DEFAULT_COLOR_PALETTE } from "../../constants/color-palette.constants";
7
6
  /**
@@ -239,7 +238,7 @@ export class KritzelLineTool extends KritzelBaseTool {
239
238
  // Add the selection group
240
239
  this._core.addSelectionGroup(selectionGroup);
241
240
  // Switch to selection tool
242
- this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
241
+ this._core.store.setState('activeTool', this._core.toolRegistry.getTool('selection'));
243
242
  // Rerender
244
243
  this._core.rerender();
245
244
  }
@@ -1,7 +1,6 @@
1
1
  import { KritzelShape } from "../objects/shape.class";
2
2
  import { KritzelBaseTool } from "./base-tool.class";
3
3
  import { KritzelEventHelper } from "../../helpers/event.helper";
4
- import { KritzelToolRegistry } from "../registries/tool.registry";
5
4
  import { ShapeType } from "../../enums/shape-type.enum";
6
5
  import { DEFAULT_COLOR_PALETTE } from "../../constants/color-palette.constants";
7
6
  /**
@@ -70,7 +69,7 @@ export class KritzelShapeTool extends KritzelBaseTool {
70
69
  }
71
70
  if (activeShape !== null && object instanceof KritzelShape === false) {
72
71
  this._core.resetActiveShape();
73
- this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
72
+ this._core.store.setState('activeTool', this._core.toolRegistry.getTool('selection'));
74
73
  return;
75
74
  }
76
75
  if (KritzelEventHelper.isLeftClick(event) === false) {
@@ -95,7 +94,7 @@ export class KritzelShapeTool extends KritzelBaseTool {
95
94
  }
96
95
  if (activeShape !== null && object instanceof KritzelShape === false) {
97
96
  this._core.resetActiveShape();
98
- this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
97
+ this._core.store.setState('activeTool', this._core.toolRegistry.getTool('selection'));
99
98
  return;
100
99
  }
101
100
  if (activePointers.length > 1) {
@@ -237,7 +236,7 @@ export class KritzelShapeTool extends KritzelBaseTool {
237
236
  this._core.engine.emitObjectsChange();
238
237
  this._core.engine.emitObjectsAdded([this.currentShape]);
239
238
  this._core.selectObjects([this.currentShape]);
240
- this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
239
+ this._core.store.setState('activeTool', this._core.toolRegistry.getTool('selection'));
241
240
  }
242
241
  this.isDrawing = false;
243
242
  this._core.store.objects?.setActiveDrawingObject(null);
@@ -1,7 +1,6 @@
1
1
  import { KritzelText } from "../objects/text.class";
2
2
  import { KritzelBaseTool } from "./base-tool.class";
3
3
  import { KritzelEventHelper } from "../../helpers/event.helper";
4
- import { KritzelToolRegistry } from "../registries/tool.registry";
5
4
  import { DEFAULT_COLOR_PALETTE } from "../../constants/color-palette.constants";
6
5
  /**
7
6
  * Text tool for creating and editing text objects on the canvas.
@@ -99,7 +98,7 @@ export class KritzelTextTool extends KritzelBaseTool {
99
98
  }
100
99
  if (activeText !== null && object instanceof KritzelText === false) {
101
100
  this._core.resetActiveText();
102
- this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
101
+ this._core.store.setState('activeTool', this._core.toolRegistry.getTool('selection'));
103
102
  return;
104
103
  }
105
104
  if (KritzelEventHelper.isLeftClick(event) === false) {
@@ -136,7 +135,7 @@ export class KritzelTextTool extends KritzelBaseTool {
136
135
  }
137
136
  if (activeText !== null && object instanceof KritzelText === false) {
138
137
  this._core.resetActiveText();
139
- this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
138
+ this._core.store.setState('activeTool', this._core.toolRegistry.getTool('selection'));
140
139
  return;
141
140
  }
142
141
  if (activePointers.length > 1) {
@@ -41,7 +41,6 @@ kritzel-controls.keyboard-open {
41
41
  display: flex;
42
42
  align-items: flex-start;
43
43
  gap: 8px;
44
- z-index: 10000;
45
44
  }
46
45
 
47
46
  .top-right-buttons {
@@ -51,7 +50,6 @@ kritzel-controls.keyboard-open {
51
50
  display: flex;
52
51
  align-items: center;
53
52
  gap: 8px;
54
- z-index: 10000;
55
53
  }
56
54
 
57
55
  .top-right-button {
@@ -5,11 +5,9 @@ import { KritzelTextTool } from "../../../classes/tools/text-tool.class";
5
5
  import { KritzelShapeTool } from "../../../classes/tools/shape-tool.class";
6
6
  import { KritzelSelectionBox } from "../../../classes/objects/selection-box.class";
7
7
  import { KritzelKeyHandler } from "../../../classes/handlers/key.handler";
8
- import { KritzelBaseTool } from "../../../classes/tools/base-tool.class";
9
8
  import { KritzelEraserTool } from "../../../classes/tools/eraser-tool.class";
10
9
  import { KritzelKeyboardHelper } from "../../../helpers/keyboard.helper";
11
10
  import { KritzelContextMenuHandler } from "../../../classes/handlers/context-menu.handler";
12
- import { KritzelToolRegistry } from "../../../classes/registries/tool.registry";
13
11
  import { KritzelEventHelper } from "../../../helpers/event.helper";
14
12
  import { KritzelClassHelper } from "../../../helpers/class.helper";
15
13
  import { ABSOLUTE_SCALE_MAX, ABSOLUTE_SCALE_MIN } from "../../../constants/engine.constants";
@@ -362,11 +360,22 @@ export class KritzelEngine {
362
360
  * @returns The registered tool instance, or `null` if registration failed.
363
361
  */
364
362
  async registerTool(toolName, toolClass, toolConfig) {
365
- if (typeof toolClass !== 'function' || !(toolClass.prototype instanceof KritzelBaseTool)) {
363
+ if (typeof toolClass !== 'function') {
366
364
  console.error(`Failed to register tool "${toolName}": Tool class must be a constructor function`);
367
365
  return null;
368
366
  }
369
- const registeredTool = KritzelToolRegistry.registerTool(toolName, toolClass, this.core);
367
+ // If a tool with this name is already registered, return the existing instance
368
+ // This avoids dual-package issues when tool classes are passed from external bundles
369
+ if (this.core.toolRegistry.hasTool(toolName)) {
370
+ const existingTool = this.core.toolRegistry.getTool(toolName);
371
+ if (toolConfig) {
372
+ Object.entries(toolConfig).forEach(([key, value]) => {
373
+ existingTool[key] = value;
374
+ });
375
+ }
376
+ return existingTool;
377
+ }
378
+ const registeredTool = this.core.toolRegistry.registerTool(toolName, toolClass);
370
379
  if (toolConfig) {
371
380
  Object.entries(toolConfig).forEach(([key, value]) => {
372
381
  registeredTool[key] = value;
@@ -644,7 +653,7 @@ export class KritzelEngine {
644
653
  * @param objects - The objects to select.
645
654
  */
646
655
  async selectObjects(objects) {
647
- const selectionTool = KritzelToolRegistry.getTool('selection');
656
+ const selectionTool = this.core.toolRegistry.getTool('selection');
648
657
  if (!selectionTool) {
649
658
  return;
650
659
  }
@@ -655,7 +664,7 @@ export class KritzelEngine {
655
664
  }
656
665
  /** Selects all objects currently visible in the viewport. Switches to the selection tool automatically. */
657
666
  async selectAllObjectsInViewport() {
658
- const selectionTool = KritzelToolRegistry.getTool('selection');
667
+ const selectionTool = this.core.toolRegistry.getTool('selection');
659
668
  if (!selectionTool) {
660
669
  return;
661
670
  }
@@ -1999,7 +2008,7 @@ export class KritzelEngine {
1999
2008
  strokeWidth: data.indicatorStrokeWidth,
2000
2009
  } }))));
2001
2010
  })()), this.core.store.state.isContextMenuVisible && (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: {
2002
- position: 'fixed',
2011
+ position: 'absolute',
2003
2012
  left: `${this.core.store.state.contextMenuX}px`,
2004
2013
  top: `${this.core.store.state.contextMenuY}px`,
2005
2014
  zIndex: '10002',
@@ -3,6 +3,7 @@
3
3
  flex-direction: column;
4
4
  user-select: none;
5
5
  max-width: 100%;
6
+ z-index: 1;
6
7
  }
7
8
 
8
9
  :host(.mobile) {
@@ -22,7 +23,7 @@
22
23
  border-radius: var(--kritzel-controls-border-radius, 16px);
23
24
  box-shadow: var(--kritzel-controls-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));
24
25
  border: var(--kritzel-controls-border, 1px solid #ebebeb);
25
- z-index: 10000;
26
+ z-index: 1;
26
27
  position: relative;
27
28
  max-width: 100%;
28
29
  overflow: hidden;
@@ -1,7 +1,4 @@
1
1
  import { h, Host } from "@stencil/core";
2
- import { KritzelBrushTool } from "../../../classes/tools/brush-tool.class";
3
- import { KritzelLineTool } from "../../../classes/tools/line-tool.class";
4
- import { KritzelShapeTool } from "../../../classes/tools/shape-tool.class";
5
2
  import { KritzelTextTool } from "../../../classes/tools/text-tool.class";
6
3
  import { KritzelSelectionTool } from "../../../classes/tools/selection-tool.class";
7
4
  import { KritzelDevicesHelper } from "../../../helpers/devices.helper";
@@ -22,6 +19,9 @@ export class KritzelControls {
22
19
  canScrollRight = false;
23
20
  needsScrolling = false;
24
21
  displayValues = null;
22
+ internalControls = [];
23
+ handleActiveToolChangeBound = this.handleActiveToolChange.bind(this);
24
+ handleSelectionChangeBound = this.handleSelectionChange.bind(this);
25
25
  handleKeyDown(event) {
26
26
  if (event.key === 'Escape') {
27
27
  event.preventDefault();
@@ -30,7 +30,7 @@ export class KritzelControls {
30
30
  }
31
31
  }
32
32
  async handleActiveToolChange(event) {
33
- this.activeControl = this.controls.find(control => control.tool === event.detail) || null;
33
+ this.activeControl = this.internalControls.find(control => control.tool === event.detail) || null;
34
34
  if (this.activeControl?.tool) {
35
35
  this.updateDisplayValues(this.activeControl.tool);
36
36
  }
@@ -41,6 +41,11 @@ export class KritzelControls {
41
41
  this.updateDisplayValues(this.activeControl.tool);
42
42
  }
43
43
  }
44
+ async onControlsChange() {
45
+ if (this.kritzelEngine) {
46
+ await this.initializeTools();
47
+ }
48
+ }
44
49
  onThemeChange() {
45
50
  if (this.activeControl?.tool) {
46
51
  this.updateDisplayValues(this.activeControl.tool);
@@ -107,6 +112,12 @@ export class KritzelControls {
107
112
  componentDidRender() {
108
113
  this.updateScrollIndicators();
109
114
  }
115
+ disconnectedCallback() {
116
+ if (this.kritzelEngine) {
117
+ this.kritzelEngine.removeEventListener('activeToolChange', this.handleActiveToolChangeBound);
118
+ this.kritzelEngine.removeEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
119
+ }
120
+ }
110
121
  updateScrollIndicators() {
111
122
  if (!this.toolsScrollRef)
112
123
  return;
@@ -131,16 +142,28 @@ export class KritzelControls {
131
142
  if (!this.kritzelEngine) {
132
143
  throw new Error('kritzel-engine not found in parent element.');
133
144
  }
145
+ this.kritzelEngine.addEventListener('activeToolChange', this.handleActiveToolChangeBound);
146
+ this.kritzelEngine.addEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
134
147
  }
135
148
  async initializeTools() {
136
- for (const c of this.controls) {
149
+ let hasDefault = false;
150
+ const newControls = this.controls.map(c => ({ ...c }));
151
+ for (const c of newControls) {
137
152
  if (c.type === 'tool' && c.tool) {
138
- c.tool = await this.kritzelEngine.registerTool(c.name, c.tool, c.config);
153
+ let toolConstructor = c.tool;
154
+ if (typeof toolConstructor !== 'function') {
155
+ toolConstructor = toolConstructor.constructor;
156
+ }
157
+ const registered = await this.kritzelEngine.registerTool(c.name, toolConstructor, c.config);
158
+ if (registered) {
159
+ c.tool = registered;
160
+ }
139
161
  }
140
162
  if (c.type === 'tool' && c.isDefault && c.tool) {
141
163
  await this.kritzelEngine.changeActiveTool(c.tool);
142
164
  this.activeControl = c;
143
165
  this.updateDisplayValues(c.tool);
166
+ hasDefault = true;
144
167
  }
145
168
  if (c.type === 'config') {
146
169
  if (this.firstConfig === null) {
@@ -151,6 +174,16 @@ export class KritzelControls {
151
174
  }
152
175
  }
153
176
  }
177
+ this.internalControls = newControls;
178
+ // If no tool is marked as default, activate the first tool control
179
+ if (!hasDefault) {
180
+ const firstTool = this.internalControls.find(c => c.type === 'tool' && c.tool);
181
+ if (firstTool) {
182
+ await this.kritzelEngine.changeActiveTool(firstTool.tool);
183
+ this.activeControl = firstTool;
184
+ this.updateDisplayValues(firstTool.tool);
185
+ }
186
+ }
154
187
  }
155
188
  async handleControlClick(control) {
156
189
  this.activeControl = control;
@@ -190,21 +223,20 @@ export class KritzelControls {
190
223
  await this.handleControlClick(control);
191
224
  }
192
225
  render() {
193
- const hasConfigUI = this.activeControl?.tool instanceof KritzelBrushTool ||
194
- this.activeControl?.tool instanceof KritzelTextTool ||
195
- this.activeControl?.tool instanceof KritzelLineTool ||
196
- this.activeControl?.tool instanceof KritzelShapeTool ||
197
- (this.activeControl?.tool instanceof KritzelSelectionTool && this.activeControl.tool.hasSelection());
226
+ const activeToolConfig = this.activeControl?.tool
227
+ ? KritzelToolConfigHelper.getToolConfig(this.activeControl.tool)
228
+ : null;
229
+ const hasConfigUI = activeToolConfig !== null;
198
230
  // Separate tool controls from config control
199
- const toolControls = this.controls.filter(c => c.type === 'tool' || c.type === 'separator');
200
- const configControl = this.controls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
201
- return (h(Host, { key: '93d08a3268edb67fc4cccb291b6e0aff6cf5a4bd', class: {
231
+ const toolControls = this.internalControls.filter(c => c.type === 'tool' || c.type === 'separator');
232
+ const configControl = this.internalControls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
233
+ return (h(Host, { key: '7f2a5fed45ac89b34a86b87552ffaa1b94f44d8b', class: {
202
234
  mobile: this.isTouchDevice,
203
- } }, this.isUtilityPanelVisible && (h("kritzel-utility-panel", { key: '8862ea7e524b3e23d87ffea2929e04df7231bb0c', style: {
235
+ } }, this.isUtilityPanelVisible && (h("kritzel-utility-panel", { key: '2dcbbe498bce0b59fbd225d103f2e322d3b7ff85', style: {
204
236
  position: 'absolute',
205
237
  bottom: '56px',
206
238
  left: '12px',
207
- }, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), h("div", { key: '2ea2a41ba4cda77f5abde9231d293da181a2a568', class: "kritzel-controls" }, h("div", { key: '6bd4f6d930a0a51d5549b6dbae1e7be14cbe7822', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), h("div", { key: 'c712ca502a4ebd244394158b39391a49839bc386', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
239
+ }, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), h("div", { key: '6431079040502a78f021c612a7e953b1349f319a', class: "kritzel-controls" }, h("div", { key: '6e0d6dce107cf6b54fb904809fd525ce3b2ae4f0', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), h("div", { key: '2686304ad10deac2d022e1deba19195587659d64', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
208
240
  // Check if this control has sub-options (split-button)
209
241
  if (control.subOptions?.length) {
210
242
  const selectedSubOption = this.getSelectedSubOption(control);
@@ -234,10 +266,10 @@ export class KritzelControls {
234
266
  'kritzel-control': true,
235
267
  'selected': this.activeControl?.name === control?.name,
236
268
  }, 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 })));
237
- })), h("div", { key: '0d8ae76ea22cb0aea4f7971a17c787c722d1f476', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (h("div", { class: {
269
+ })), h("div", { key: 'f4bcbc856f6e027cdb579356faf54288b43aa080', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (h("div", { class: {
238
270
  'kritzel-config-container': true,
239
271
  'visible': hasConfigUI,
240
- }, key: configControl.name }, h("div", { key: 'd3da3913362d96109f618c86bd8370f6253a1b7c', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), h("kritzel-tooltip", { key: '26fed6901c67362ec0c18eacd23b48fff5a361ef', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, 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%' } })), h("div", { key: 'b9bb29fc19ee335103ea050155f5e240f2ad2cd9', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
272
+ }, key: configControl.name }, h("div", { key: '0646c98b32047f51841f75dd5fb57813ebb153f5', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), h("kritzel-tooltip", { key: '0816b8d7ca55add3c6a81de788be3c61a8a814f2', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, 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%' } })), h("div", { key: '8b2dc1dcc61df93a92cea8ba2aeb776e57965ab3', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
241
273
  if (el)
242
274
  this.configTriggerRef = el;
243
275
  }, onKeyDown: event => {
@@ -246,7 +278,7 @@ export class KritzelControls {
246
278
  }
247
279
  }, style: {
248
280
  cursor: 'pointer',
249
- } }, this.displayValues && (h("div", { key: '5918f90d824c41700c5dac4fca13cb8b47759473', class: "color-container" }, h("kritzel-color", { key: '08b7847f1d9117cec216979016d10d7b25076ecc', value: this.displayValues.color, theme: this.theme, size: 18, style: {
281
+ } }, this.displayValues && (h("div", { key: '1074fc05048aed92ec9d62e347822df0a57a80e4', class: "color-container" }, h("kritzel-color", { key: '222efa6883ccbc6c97d10360039a1315de7d6273', value: this.displayValues.color, theme: this.theme, size: 18, style: {
250
282
  borderRadius: '50%',
251
283
  border: 'none',
252
284
  } })))))))));
@@ -397,7 +429,8 @@ export class KritzelControls {
397
429
  "canScrollLeft": {},
398
430
  "canScrollRight": {},
399
431
  "needsScrolling": {},
400
- "displayValues": {}
432
+ "displayValues": {},
433
+ "internalControls": {}
401
434
  };
402
435
  }
403
436
  static get events() {
@@ -442,6 +475,9 @@ export class KritzelControls {
442
475
  static get elementRef() { return "host"; }
443
476
  static get watchers() {
444
477
  return [{
478
+ "propName": "controls",
479
+ "methodName": "onControlsChange"
480
+ }, {
445
481
  "propName": "theme",
446
482
  "methodName": "onThemeChange"
447
483
  }];
@@ -453,18 +489,6 @@ export class KritzelControls {
453
489
  "target": "window",
454
490
  "capture": false,
455
491
  "passive": false
456
- }, {
457
- "name": "activeToolChange",
458
- "method": "handleActiveToolChange",
459
- "target": "document",
460
- "capture": false,
461
- "passive": false
462
- }, {
463
- "name": "objectsSelectionChange",
464
- "method": "handleSelectionChange",
465
- "target": "document",
466
- "capture": false,
467
- "passive": false
468
492
  }];
469
493
  }
470
494
  }
@@ -1,5 +1,6 @@
1
1
  :host {
2
2
  display: inline-flex;
3
+ z-index: 1;
3
4
  }
4
5
 
5
6
  .more-menu-wrapper {
@@ -35,9 +35,19 @@ export class KritzelToolConfig {
35
35
  }
36
36
  isExpanded = false;
37
37
  theme;
38
+ engine;
39
+ handleSelectionChangeBound = this.handleSelectionChange.bind(this);
38
40
  onThemeChange() {
39
41
  this.emitDisplayValues();
40
42
  }
43
+ handleEngineChange(newEngine, oldEngine) {
44
+ if (oldEngine) {
45
+ oldEngine.removeEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
46
+ }
47
+ if (newEngine) {
48
+ newEngine.addEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
49
+ }
50
+ }
41
51
  toolChange;
42
52
  displayValuesChange;
43
53
  config;
@@ -54,6 +64,11 @@ export class KritzelToolConfig {
54
64
  }
55
65
  }
56
66
  }
67
+ disconnectedCallback() {
68
+ if (this.engine) {
69
+ this.engine.removeEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
70
+ }
71
+ }
57
72
  componentWillLoad() {
58
73
  this.config = KritzelToolConfigHelper.getToolConfig(this.tool);
59
74
  if (this.config) {
@@ -61,6 +76,9 @@ export class KritzelToolConfig {
61
76
  this.currentOpacity = this.tool[this.config.opacityProperty] ?? 1;
62
77
  this.emitDisplayValues();
63
78
  }
79
+ if (this.engine) {
80
+ this.engine.addEventListener('objectsSelectionChange', this.handleSelectionChangeBound);
81
+ }
64
82
  }
65
83
  emitDisplayValues() {
66
84
  if (!this.config)
@@ -269,6 +287,28 @@ export class KritzelToolConfig {
269
287
  "setter": false,
270
288
  "reflect": false,
271
289
  "attribute": "theme"
290
+ },
291
+ "engine": {
292
+ "type": "unknown",
293
+ "mutable": false,
294
+ "complexType": {
295
+ "original": "HTMLElement",
296
+ "resolved": "HTMLElement",
297
+ "references": {
298
+ "HTMLElement": {
299
+ "location": "global",
300
+ "id": "global::HTMLElement"
301
+ }
302
+ }
303
+ },
304
+ "required": false,
305
+ "optional": false,
306
+ "docs": {
307
+ "tags": [],
308
+ "text": ""
309
+ },
310
+ "getter": false,
311
+ "setter": false
272
312
  }
273
313
  };
274
314
  }
@@ -334,15 +374,9 @@ export class KritzelToolConfig {
334
374
  }, {
335
375
  "propName": "theme",
336
376
  "methodName": "onThemeChange"
337
- }];
338
- }
339
- static get listeners() {
340
- return [{
341
- "name": "objectsSelectionChange",
342
- "method": "handleSelectionChange",
343
- "target": "document",
344
- "capture": false,
345
- "passive": false
377
+ }, {
378
+ "propName": "engine",
379
+ "methodName": "handleEngineChange"
346
380
  }];
347
381
  }
348
382
  }
@@ -9,7 +9,7 @@
9
9
  background-color: var(--kritzel-utility-panel-background-color, #e2e2e2);
10
10
  width: fit-content;
11
11
  user-select: none;
12
- z-index: 10000;
12
+ z-index: 1;
13
13
  }
14
14
 
15
15
  .utility-button {
@@ -3,4 +3,4 @@
3
3
  * This file is auto-generated by the version bump scripts.
4
4
  * Do not modify manually.
5
5
  */
6
- export const KRITZEL_VERSION = '0.3.1';
6
+ export const KRITZEL_VERSION = '0.3.7';
@@ -5,10 +5,11 @@ import { KritzelTextTool } from "../classes/tools/text-tool.class";
5
5
  import { KritzelSelectionTool } from "../classes/tools/selection-tool.class";
6
6
  export class KritzelToolConfigHelper {
7
7
  static getToolConfig(tool) {
8
- if (tool instanceof KritzelSelectionTool) {
8
+ const toolConstructorName = tool?.constructor?.name;
9
+ if (tool instanceof KritzelSelectionTool || toolConstructorName === 'KritzelSelectionTool') {
9
10
  return tool.getToolConfig();
10
11
  }
11
- if (tool instanceof KritzelBrushTool) {
12
+ if (tool instanceof KritzelBrushTool || toolConstructorName === 'KritzelBrushTool') {
12
13
  return {
13
14
  type: 'brush',
14
15
  colorProperty: 'color',
@@ -20,7 +21,7 @@ export class KritzelToolConfigHelper {
20
21
  ],
21
22
  };
22
23
  }
23
- if (tool instanceof KritzelLineTool) {
24
+ if (tool instanceof KritzelLineTool || toolConstructorName === 'KritzelLineTool') {
24
25
  return {
25
26
  type: 'line',
26
27
  colorProperty: 'color',
@@ -33,7 +34,7 @@ export class KritzelToolConfigHelper {
33
34
  ],
34
35
  };
35
36
  }
36
- if (tool instanceof KritzelShapeTool) {
37
+ if (tool instanceof KritzelShapeTool || toolConstructorName === 'KritzelShapeTool') {
37
38
  return {
38
39
  type: 'shape',
39
40
  colorProperty: 'strokeColor',
@@ -46,7 +47,7 @@ export class KritzelToolConfigHelper {
46
47
  ],
47
48
  };
48
49
  }
49
- if (tool instanceof KritzelTextTool) {
50
+ if (tool instanceof KritzelTextTool || toolConstructorName === 'KritzelTextTool') {
50
51
  return {
51
52
  type: 'text',
52
53
  colorProperty: 'fontColor',
@@ -22,6 +22,7 @@ export * from './classes/tools/shape-tool.class';
22
22
  export * from './helpers/cursor.helper';
23
23
  export * from './classes/tools/selection-tool.class';
24
24
  export * from './classes/providers/sync/broadcast-sync-provider.class';
25
+ export * from './classes/providers/sync/in-memory-sync-provider.class';
25
26
  export * from './classes/providers/sync/indexeddb-sync-provider.class';
26
27
  export * from './classes/providers/sync/websocket-sync-provider.class';
27
28
  export * from './classes/providers/sync/hocuspocus-sync-provider.class';