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.
- package/dist/cjs/index.cjs.js +70 -1
- package/dist/cjs/kritzel-active-users_42.cjs.entry.js +200 -41
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/stencil.cjs.js +1 -1
- package/dist/cjs/{workspace.migrations-D5sPPbQN.js → workspace.migrations-BlC8KRoQ.js} +12 -63
- package/dist/collection/classes/core/core.class.js +16 -5
- package/dist/collection/classes/core/store.class.js +8 -1
- package/dist/collection/classes/handlers/context-menu.handler.js +2 -2
- package/dist/collection/classes/handlers/key.handler.js +1 -2
- package/dist/collection/classes/objects/shape.class.js +2 -3
- package/dist/collection/classes/objects/text.class.js +2 -3
- package/dist/collection/classes/providers/sync/in-memory-sync-provider.class.js +68 -0
- package/dist/collection/classes/registries/tool.registry.js +29 -8
- package/dist/collection/classes/tools/image-tool.class.js +2 -3
- package/dist/collection/classes/tools/line-tool.class.js +1 -2
- package/dist/collection/classes/tools/shape-tool.class.js +3 -4
- package/dist/collection/classes/tools/text-tool.class.js +2 -3
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.css +0 -2
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +16 -7
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.css +2 -1
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +56 -32
- package/dist/collection/components/ui/kritzel-more-menu/kritzel-more-menu.css +1 -0
- package/dist/collection/components/ui/kritzel-tool-config/kritzel-tool-config.js +43 -9
- package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.css +1 -1
- package/dist/collection/constants/version.js +1 -1
- package/dist/collection/helpers/tool-config.helper.js +6 -5
- package/dist/collection/index.js +1 -0
- package/dist/components/index.js +1 -1
- package/dist/components/kritzel-controls.js +1 -1
- package/dist/components/kritzel-editor.js +1 -1
- package/dist/components/kritzel-engine.js +1 -1
- package/dist/components/kritzel-more-menu.js +1 -1
- package/dist/components/kritzel-settings.js +1 -1
- package/dist/components/kritzel-tool-config.js +1 -1
- package/dist/components/kritzel-utility-panel.js +1 -1
- package/dist/components/p-8b9zAWnS.js +1 -0
- package/dist/components/{p-Cx6YyDdF.js → p-BV3EJRtU.js} +1 -1
- package/dist/components/p-CSODtZrV.js +1 -0
- package/dist/components/p-CoJdbj3f.js +1 -0
- package/dist/components/p-Ctd1w9-z.js +1 -0
- package/dist/components/{p-C9jegh9w.js → p-D0ctIEh_.js} +1 -1
- package/dist/components/p-P0p4WBpa.js +9 -0
- package/dist/esm/index.js +71 -3
- package/dist/esm/kritzel-active-users_42.entry.js +200 -41
- package/dist/esm/loader.js +1 -1
- package/dist/esm/stencil.js +1 -1
- package/dist/esm/{workspace.migrations-BnTvdnKU.js → workspace.migrations-BLXBI--a.js} +13 -62
- package/dist/stencil/index.esm.js +1 -1
- package/dist/stencil/p-3058e485.entry.js +9 -0
- package/dist/stencil/p-BLXBI--a.js +1 -0
- package/dist/stencil/stencil.esm.js +1 -1
- package/dist/types/classes/core/core.class.d.ts +8 -0
- package/dist/types/classes/providers/sync/in-memory-sync-provider.class.d.ts +38 -0
- package/dist/types/classes/registries/tool.registry.d.ts +24 -7
- package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +5 -0
- package/dist/types/components/ui/kritzel-tool-config/kritzel-tool-config.d.ts +4 -0
- package/dist/types/components.d.ts +2 -0
- package/dist/types/constants/version.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
- package/dist/components/p-BWB2UGxj.js +0 -9
- package/dist/components/p-BWJGv9ZO.js +0 -1
- package/dist/components/p-BWRjTm0J.js +0 -1
- package/dist/components/p-Clo5Ydi1.js +0 -1
- package/dist/components/p-D9-C4GfD.js +0 -1
- package/dist/stencil/p-BnTvdnKU.js +0 -1
- package/dist/stencil/p-bfd1fca8.entry.js +0 -9
|
@@ -1,25 +1,46 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A
|
|
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
|
-
|
|
11
|
+
registry = {};
|
|
8
12
|
/**
|
|
9
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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',
|
|
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',
|
|
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',
|
|
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',
|
|
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',
|
|
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',
|
|
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',
|
|
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',
|
|
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'
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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: '
|
|
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:
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
194
|
-
this.activeControl
|
|
195
|
-
|
|
196
|
-
|
|
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.
|
|
200
|
-
const configControl = this.
|
|
201
|
-
return (h(Host, { key: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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
|
}
|
|
@@ -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
|
-
|
|
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
|
}
|
|
@@ -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
|
-
|
|
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',
|
package/dist/collection/index.js
CHANGED
|
@@ -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';
|