kritzel-stencil 0.1.0 → 0.1.2
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/{default-line-tool.config-7eJND6Jb.js → default-line-tool.config-MA02HCrH.js} +703 -133
- package/dist/cjs/{index-BeKMS-Zt.js → index-Bj0n7fQQ.js} +84 -7
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/kritzel-brush-style.cjs.entry.js +1 -1
- package/dist/cjs/{kritzel-color_22.cjs.entry.js → kritzel-color_24.cjs.entry.js} +1018 -897
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/stencil.cjs.js +3 -3
- package/dist/collection/classes/core/core.class.js +2 -0
- package/dist/collection/classes/core/viewport.class.js +43 -3
- package/dist/collection/classes/handlers/move.handler.js +6 -0
- package/dist/collection/classes/objects/line.class.js +63 -15
- package/dist/collection/classes/objects/path.class.js +1 -0
- package/dist/collection/classes/objects/shape.class.js +1 -0
- package/dist/collection/classes/objects/text.class.js +4 -3
- package/dist/collection/classes/providers/indexeddb-sync-provider.class.js +0 -1
- package/dist/collection/classes/tools/brush-tool.class.js +5 -0
- package/dist/collection/classes/tools/line-tool.class.js +31 -1
- package/dist/collection/classes/tools/selection-tool.class.js +193 -0
- package/dist/collection/classes/tools/shape-tool.class.js +2 -0
- package/dist/collection/classes/tools/text-tool.class.js +3 -0
- package/dist/collection/collection-manifest.json +5 -3
- package/dist/collection/components/core/kritzel-cursor-trail/kritzel-cursor-trail.js +3 -2
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +37 -19
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +108 -36
- package/dist/collection/components/shared/kritzel-color/kritzel-color.js +2 -2
- package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.css +1 -1
- package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.js +24 -2
- package/dist/collection/components/shared/kritzel-font/kritzel-font.js +1 -1
- package/dist/collection/components/shared/kritzel-font-family/kritzel-font-family.css +1 -1
- package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.css +1 -1
- package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.js +1 -1
- package/dist/collection/components/shared/kritzel-line-endings/kritzel-line-endings.css +60 -0
- package/dist/collection/components/shared/kritzel-line-endings/kritzel-line-endings.js +187 -0
- package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js +15 -8
- package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.js +16 -9
- package/dist/collection/components/shared/kritzel-opacity-slider/kritzel-opacity-slider.css +85 -0
- package/dist/collection/components/shared/kritzel-opacity-slider/kritzel-opacity-slider.js +163 -0
- package/dist/collection/components/shared/kritzel-portal/kritzel-portal.js +1 -1
- package/dist/collection/components/shared/kritzel-shape-fill/kritzel-shape-fill.css +47 -0
- package/dist/collection/components/shared/kritzel-shape-fill/kritzel-shape-fill.js +93 -0
- package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js +13 -7
- package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.css +11 -2
- package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.js +2 -2
- package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.css +1 -1
- package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.js +6 -4
- package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.js +6 -3
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.css +66 -0
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +153 -50
- package/dist/collection/components/ui/kritzel-tool-config/kritzel-tool-config.css +38 -0
- package/dist/collection/components/ui/kritzel-tool-config/kritzel-tool-config.js +321 -0
- package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js +3 -2
- package/dist/collection/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.js +6 -3
- package/dist/collection/configs/default-brush-tool.config.js +2 -52
- package/dist/collection/configs/default-line-tool.config.js +2 -26
- package/dist/collection/configs/default-shape-tool.config.js +2 -15
- package/dist/collection/configs/default-text-tool.config.js +2 -26
- package/dist/collection/constants/color-palette.constants.js +30 -0
- package/dist/collection/helpers/color.helper.js +31 -0
- package/dist/collection/helpers/tool-config.helper.js +65 -0
- package/dist/collection/interfaces/tool-config.interface.js +1 -0
- package/dist/components/index.d.ts +8 -4
- package/dist/components/index.js +1 -1
- package/dist/components/kritzel-brush-style.js +1 -1
- package/dist/components/kritzel-color-palette.js +1 -1
- package/dist/components/kritzel-color.js +1 -1
- package/dist/components/kritzel-context-menu.js +1 -1
- package/dist/components/kritzel-controls.js +1 -1
- package/dist/components/kritzel-cursor-trail.js +1 -1
- package/dist/components/kritzel-dropdown.js +1 -1
- package/dist/components/kritzel-editor.js +1 -1
- package/dist/components/kritzel-engine.js +1 -1
- package/dist/components/kritzel-font-family.js +1 -1
- package/dist/components/kritzel-font-size.js +1 -1
- package/dist/components/kritzel-font.js +1 -1
- package/dist/components/kritzel-icon.js +1 -1
- package/dist/components/kritzel-line-endings.d.ts +11 -0
- package/dist/components/kritzel-line-endings.js +1 -0
- package/dist/components/kritzel-menu-item.js +1 -1
- package/dist/components/kritzel-menu.js +1 -1
- package/dist/components/kritzel-opacity-slider.d.ts +11 -0
- package/dist/components/kritzel-opacity-slider.js +1 -0
- package/dist/components/kritzel-portal.js +1 -1
- package/dist/components/kritzel-shape-fill.d.ts +11 -0
- package/dist/components/kritzel-shape-fill.js +1 -0
- package/dist/components/kritzel-split-button.js +1 -1
- package/dist/components/kritzel-stroke-size.js +1 -1
- package/dist/components/kritzel-tool-config.d.ts +11 -0
- package/dist/components/kritzel-tool-config.js +1 -0
- package/dist/components/kritzel-tooltip.js +1 -1
- package/dist/components/kritzel-utility-panel.js +1 -1
- package/dist/components/kritzel-workspace-manager.js +1 -1
- package/dist/components/p-83YX0-FS.js +1 -0
- package/dist/components/p-8iEiCuEN.js +1 -0
- package/dist/components/p-9XZbc_qK.js +1 -0
- package/dist/components/p-B3P64-gH.js +9 -0
- package/dist/components/p-B8QjTqOY.js +1 -0
- package/dist/components/p-BF6MdW17.js +1 -0
- package/dist/components/p-BVIY50lR.js +1 -0
- package/dist/components/p-BbqT9o1F.js +1 -0
- package/dist/components/{p-CXzfYQ_u.js → p-BnidlyU0.js} +1 -1
- package/dist/components/{p-Bj_Og27M.js → p-BxS4Pdpz.js} +1 -1
- package/dist/components/{p-g0N9j_uT.js → p-CCj8nmQH.js} +1 -1
- package/dist/components/{p-1z-ds26_.js → p-CLOnpu42.js} +1 -1
- package/dist/components/{p-D1tfzpy8.js → p-CSGeDE4f.js} +1 -1
- package/dist/components/p-CbuHMNa9.js +1 -0
- package/dist/components/p-ClMFs3KI.js +1 -0
- package/dist/components/{p-IAqZFssU.js → p-Cnpk2hfo.js} +1 -1
- package/dist/components/{p-Cy77SpWt.js → p-Ctv4NAxk.js} +1 -1
- package/dist/components/p-CyHZWbkS.js +1 -0
- package/dist/components/{p-C4krHoUl.js → p-D8GeJNUv.js} +1 -1
- package/dist/components/{p-DB5s1NY4.js → p-DKgqzi2Y.js} +1 -1
- package/dist/components/p-DOF5fWDU.js +1 -0
- package/dist/components/{p-4FEa4ADy.js → p-DV_h5Jo2.js} +1 -1
- package/dist/components/{p-DTezr6w9.js → p-DgCGSL2Q.js} +1 -1
- package/dist/components/{p-D5ZsALCP.js → p-wRXL928z.js} +1 -1
- package/dist/esm/{default-line-tool.config-CD5sTKH-.js → default-line-tool.config-DLpNl6R9.js} +702 -125
- package/dist/esm/{index-BqhmuUH2.js → index-OLdaFN6W.js} +84 -7
- package/dist/esm/index.js +2 -2
- package/dist/esm/kritzel-brush-style.entry.js +1 -1
- package/dist/esm/{kritzel-color_22.entry.js → kritzel-color_24.entry.js} +1009 -890
- package/dist/esm/loader.js +3 -3
- package/dist/esm/stencil.js +4 -4
- package/dist/stencil/index.esm.js +1 -1
- package/dist/stencil/{p-09295079.entry.js → p-802bc7cf.entry.js} +1 -1
- package/dist/stencil/p-DLpNl6R9.js +1 -0
- package/dist/stencil/p-OLdaFN6W.js +2 -0
- package/dist/stencil/p-caf30edb.entry.js +9 -0
- package/dist/stencil/stencil.esm.js +1 -1
- package/dist/types/classes/core/viewport.class.d.ts +6 -0
- package/dist/types/classes/managers/anchor.manager.d.ts +1 -1
- package/dist/types/classes/objects/line.class.d.ts +2 -0
- package/dist/types/classes/objects/shape.class.d.ts +1 -0
- package/dist/types/classes/tools/brush-tool.class.d.ts +1 -0
- package/dist/types/classes/tools/line-tool.class.d.ts +2 -1
- package/dist/types/classes/tools/selection-tool.class.d.ts +22 -0
- package/dist/types/classes/tools/shape-tool.class.d.ts +1 -0
- package/dist/types/classes/tools/text-tool.class.d.ts +1 -0
- package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +2 -0
- package/dist/types/components/shared/kritzel-color-palette/kritzel-color-palette.d.ts +1 -0
- package/dist/types/components/shared/kritzel-line-endings/kritzel-line-endings.d.ts +23 -0
- package/dist/types/components/shared/kritzel-opacity-slider/kritzel-opacity-slider.d.ts +17 -0
- package/dist/types/components/shared/kritzel-shape-fill/kritzel-shape-fill.d.ts +10 -0
- package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +15 -0
- package/dist/types/components/ui/kritzel-tool-config/kritzel-tool-config.d.ts +25 -0
- package/dist/types/components.d.ts +235 -82
- package/dist/types/constants/color-palette.constants.d.ts +5 -0
- package/dist/types/helpers/color.helper.d.ts +9 -0
- package/dist/types/helpers/tool-config.helper.d.ts +4 -0
- package/dist/types/interfaces/line-options.interface.d.ts +1 -0
- package/dist/types/interfaces/path-options.interface.d.ts +1 -0
- package/dist/types/interfaces/tool-config.interface.d.ts +26 -0
- package/dist/types/stencil-public-runtime.d.ts +29 -0
- package/package.json +5 -3
- package/dist/collection/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.css +0 -19
- package/dist/collection/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.js +0 -134
- package/dist/collection/components/ui/kritzel-control-text-config/kritzel-control-text-config.css +0 -19
- package/dist/collection/components/ui/kritzel-control-text-config/kritzel-control-text-config.js +0 -114
- package/dist/components/kritzel-control-brush-config.d.ts +0 -11
- package/dist/components/kritzel-control-brush-config.js +0 -1
- package/dist/components/kritzel-control-text-config.d.ts +0 -11
- package/dist/components/kritzel-control-text-config.js +0 -1
- package/dist/components/p-B7Fdo5QJ.js +0 -1
- package/dist/components/p-BXaWhpO2.js +0 -1
- package/dist/components/p-BtuXeItZ.js +0 -1
- package/dist/components/p-C-d2IH4v.js +0 -1
- package/dist/components/p-C3UriJh7.js +0 -1
- package/dist/components/p-CF5L2Gdl.js +0 -1
- package/dist/components/p-CeKT_dTd.js +0 -1
- package/dist/components/p-Cp15toXH.js +0 -1
- package/dist/components/p-D3LRBk2t.js +0 -9
- package/dist/components/p-Du1vxHy8.js +0 -1
- package/dist/stencil/p-381c0e9c.entry.js +0 -9
- package/dist/stencil/p-BqhmuUH2.js +0 -2
- package/dist/stencil/p-CD5sTKH-.js +0 -1
- package/dist/types/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.d.ts +0 -15
- package/dist/types/components/ui/kritzel-control-text-config/kritzel-control-text-config.d.ts +0 -12
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
4
|
-
var defaultLineTool_config = require('./default-line-tool.config-
|
|
3
|
+
var index = require('./index-Bj0n7fQQ.js');
|
|
4
|
+
var defaultLineTool_config = require('./default-line-tool.config-MA02HCrH.js');
|
|
5
5
|
|
|
6
6
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
7
7
|
|
|
@@ -39,13 +39,13 @@ const KritzelColor = class {
|
|
|
39
39
|
}
|
|
40
40
|
render() {
|
|
41
41
|
const isColorVeryLight = this.isLightColor(this.value);
|
|
42
|
-
return (index.h(index.Host, { key: '
|
|
42
|
+
return (index.h(index.Host, { key: '5d9fa3dd0fa30dd8e6589459efafd63a71c317bb' }, index.h("div", { key: 'fe35227ea4636234de62b7eec42f11a58ca788bb', class: "checkerboard-bg", style: {
|
|
43
43
|
width: `${this.size}px`,
|
|
44
44
|
height: `${this.size}px`,
|
|
45
45
|
borderRadius: '50%',
|
|
46
46
|
display: 'inline-block',
|
|
47
47
|
position: 'relative',
|
|
48
|
-
} }, index.h("div", { key: '
|
|
48
|
+
} }, index.h("div", { key: '37f99d30a6f238e9e1f9976d2419364d2f83bbd8', class: {
|
|
49
49
|
'color-circle': true,
|
|
50
50
|
'white': isColorVeryLight,
|
|
51
51
|
}, style: {
|
|
@@ -62,7 +62,39 @@ const KritzelColor = class {
|
|
|
62
62
|
};
|
|
63
63
|
KritzelColor.style = kritzelColorCss();
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
class KritzelColorHelper {
|
|
66
|
+
/**
|
|
67
|
+
* Applies opacity to a hex color and returns an rgba string.
|
|
68
|
+
* @param hexColor - The hex color string (e.g., '#ff0000' or '#f00')
|
|
69
|
+
* @param opacity - The opacity value between 0 and 1
|
|
70
|
+
* @returns The color as an rgba string, or the original hex if opacity is 1
|
|
71
|
+
*/
|
|
72
|
+
static applyOpacity(hexColor, opacity) {
|
|
73
|
+
if (opacity >= 1)
|
|
74
|
+
return hexColor;
|
|
75
|
+
const sanitizedHex = hexColor.startsWith('#') ? hexColor.slice(1) : hexColor;
|
|
76
|
+
let r, g, b;
|
|
77
|
+
if (sanitizedHex.length === 3) {
|
|
78
|
+
r = parseInt(sanitizedHex[0] + sanitizedHex[0], 16);
|
|
79
|
+
g = parseInt(sanitizedHex[1] + sanitizedHex[1], 16);
|
|
80
|
+
b = parseInt(sanitizedHex[2] + sanitizedHex[2], 16);
|
|
81
|
+
}
|
|
82
|
+
else if (sanitizedHex.length === 6) {
|
|
83
|
+
r = parseInt(sanitizedHex.substring(0, 2), 16);
|
|
84
|
+
g = parseInt(sanitizedHex.substring(2, 4), 16);
|
|
85
|
+
b = parseInt(sanitizedHex.substring(4, 6), 16);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
return hexColor;
|
|
89
|
+
}
|
|
90
|
+
if (isNaN(r) || isNaN(g) || isNaN(b)) {
|
|
91
|
+
return hexColor;
|
|
92
|
+
}
|
|
93
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const kritzelColorPaletteCss = () => `:host{display:flex;align-items:flex-start;gap:8px;padding:0;width:100%;box-sizing:border-box}.color-grid{width:100%;display:grid;grid-template-columns:repeat(6, 32px);gap:8px;justify-items:center;overflow:hidden;height:40px;transition:height 0.1s ease-in-out}.color-grid.expanded{height:500px}.color-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:var(--kritzel-pointer-cursor, pointer);border:2px solid transparent;box-sizing:border-box}.color-container:hover{background-color:var(--kritzel-color-palette-hover-background-color, #ebebeb)}.color-container.selected{border-color:var(--kritzel-selection-border-color, #007AFF);background-color:var(--kritzel-color-palette-selected-background-color)}`;
|
|
66
98
|
|
|
67
99
|
const KritzelColorPalette = class {
|
|
68
100
|
constructor(hostRef) {
|
|
@@ -73,6 +105,7 @@ const KritzelColorPalette = class {
|
|
|
73
105
|
selectedColor = null;
|
|
74
106
|
isExpanded = false;
|
|
75
107
|
isOpaque = false;
|
|
108
|
+
opacity = 1;
|
|
76
109
|
colorChange;
|
|
77
110
|
handleColorClick(color) {
|
|
78
111
|
this.selectedColor = color;
|
|
@@ -94,7 +127,7 @@ const KritzelColorPalette = class {
|
|
|
94
127
|
render() {
|
|
95
128
|
const displayedColors = this.isExpanded ? this.colors : this.colors.slice(0, 6);
|
|
96
129
|
const expandedHeight = this.isExpanded ? this.calculateHeight() : '32px';
|
|
97
|
-
return (index.h(index.Host, { key: '
|
|
130
|
+
return (index.h(index.Host, { key: '5d7861ab8510af002d4f0f4171a38bf4624d70cb' }, index.h("div", { key: 'd8b65ecf9aa36e0a158170e12aec27d112f5e0de', class: {
|
|
98
131
|
'color-grid': true,
|
|
99
132
|
'expanded': this.isExpanded,
|
|
100
133
|
}, style: {
|
|
@@ -102,7 +135,7 @@ const KritzelColorPalette = class {
|
|
|
102
135
|
} }, displayedColors.map(color => (index.h("div", { tabIndex: 0, class: {
|
|
103
136
|
'color-container': true,
|
|
104
137
|
'selected': this.selectedColor === color,
|
|
105
|
-
}, onClick: () => this.handleColorClick(color), onKeyDown: event => this.handleKeyDown(event, color) }, index.h("kritzel-color", { value: color })))))));
|
|
138
|
+
}, onClick: () => this.handleColorClick(color), onKeyDown: event => this.handleKeyDown(event, color) }, index.h("kritzel-color", { value: KritzelColorHelper.applyOpacity(color, this.opacity) })))))));
|
|
106
139
|
}
|
|
107
140
|
};
|
|
108
141
|
KritzelColorPalette.style = kritzelColorPaletteCss();
|
|
@@ -206,198 +239,450 @@ const KritzelContextMenu = class {
|
|
|
206
239
|
};
|
|
207
240
|
KritzelContextMenu.style = kritzelContextMenuCss();
|
|
208
241
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
this.toolChange.emit(this.tool);
|
|
242
|
-
}
|
|
243
|
-
render() {
|
|
244
|
-
return (index.h(index.Host, { key: 'ce2ac77db22f52239a45b62f690d54009f2c6954' }, index.h("div", { key: '5f6c50853e876c3612bb5c270bccc468c2c9a726', style: {
|
|
245
|
-
display: 'flex',
|
|
246
|
-
flexDirection: 'row',
|
|
247
|
-
alignItems: this.isExpanded ? 'flex-start' : 'center',
|
|
248
|
-
justifyContent: 'flex-start',
|
|
249
|
-
width: '100%',
|
|
250
|
-
gap: '8px',
|
|
251
|
-
} }, index.h("kritzel-color-palette", { key: 'bfa24bb8683027c37f200ad65e4e6787d7224c56', colors: this.palette, selectedColor: this.tool.color, isExpanded: this.isExpanded, isOpaque: true, onColorChange: color => this.handleColorChange(color) }), index.h("button", { key: '8e2c55c6d16ca3911c5f068c354bdce5a4f7e844', class: "expand-toggle", onClick: () => this.handleToggleExpand(), title: this.isExpanded ? 'Collapse' : 'Expand', style: this.palette.length > 6 ? { visibillity: 'visible' } : { visibility: 'hidden' } }, index.h("kritzel-icon", { key: '33610ada109fe5d1d9cb2da4c70a60d672e3d6cb', name: this.isExpanded ? 'chevron-up' : 'chevron-down' }))), index.h("kritzel-stroke-size", { key: '9b095dd9436e46dd88a3485ceb2dafa5d06d1bc4', selectedSize: this.tool.size, onSizeChange: event => this.handleSizeChange(event) })));
|
|
252
|
-
}
|
|
253
|
-
static get watchers() { return {
|
|
254
|
-
"tool": [{
|
|
255
|
-
"handleToolChange": 0
|
|
256
|
-
}]
|
|
257
|
-
}; }
|
|
258
|
-
};
|
|
259
|
-
KritzelControlBrushConfig.style = kritzelControlBrushConfigCss();
|
|
260
|
-
|
|
261
|
-
const kritzelControlTextConfigCss = () => `:host{display:block;flex-direction:column;width:100%}.expand-toggle{background:none;border:none;cursor:var(--kritzel-pointer-cursor, pointer);font-size:14px;line-height:1;padding:8px;color:var(--kritzel-color-palette-expand-toggle-color, #666666)}.expand-toggle:hover{color:var(--kritzel-color-palette-expand-toggle-hover-color, #333333)}`;
|
|
262
|
-
|
|
263
|
-
const KritzelControlTextConfig = class {
|
|
264
|
-
constructor(hostRef) {
|
|
265
|
-
index.registerInstance(this, hostRef);
|
|
266
|
-
this.toolChange = index.createEvent(this, "toolChange");
|
|
267
|
-
}
|
|
268
|
-
tool;
|
|
269
|
-
isExpanded = false;
|
|
270
|
-
toolChange;
|
|
271
|
-
handleToggleExpand() {
|
|
272
|
-
this.isExpanded = !this.isExpanded;
|
|
273
|
-
}
|
|
274
|
-
handleFamilyChange(event) {
|
|
275
|
-
this.tool.fontFamily = event.detail;
|
|
276
|
-
this.toolChange.emit(this.tool);
|
|
277
|
-
}
|
|
278
|
-
handleColorChange(event) {
|
|
279
|
-
this.tool.fontColor = event.detail;
|
|
280
|
-
this.toolChange.emit(this.tool);
|
|
281
|
-
}
|
|
282
|
-
handleSizeChange(event) {
|
|
283
|
-
this.tool.fontSize = event.detail;
|
|
284
|
-
this.toolChange.emit(this.tool);
|
|
285
|
-
}
|
|
286
|
-
render() {
|
|
287
|
-
return (index.h(index.Host, { key: '4a0027969b183fef77c374eb114d9d30104e5ad7' }, index.h("div", { key: '9f49eb3a95080447b938fdfeb256fafbe5ff9ddc', style: {
|
|
288
|
-
display: 'flex',
|
|
289
|
-
flexDirection: 'row',
|
|
290
|
-
alignItems: 'center',
|
|
291
|
-
justifyContent: 'flex-start',
|
|
292
|
-
width: '100%',
|
|
293
|
-
gap: '8px',
|
|
294
|
-
} }, index.h("kritzel-font-family", { key: '4e75cda048f8b8c04e6cb5568e7cdcde91e28112', selectedFontFamily: this.tool.fontFamily, onFontFamilyChange: event => this.handleFamilyChange(event) }), index.h("button", { key: '05c6ce98bd700e9e9d2e676cbcf191b943a2980e', class: "expand-toggle", onClick: () => this.handleToggleExpand(), title: this.isExpanded ? 'Collapse' : 'Expand', tabindex: "0" }, index.h("kritzel-icon", { key: 'ce30d48dd5ce5eefeee7702dff81ca8f96e0872d', name: this.isExpanded ? 'chevron-up' : 'chevron-down' }))), index.h("kritzel-color-palette", { key: 'a3d313bf01dafc15c8cf39a129d8c0c35741a3ca', colors: this.tool.palette, selectedColor: this.tool.fontColor, isExpanded: this.isExpanded, onColorChange: event => this.handleColorChange(event) }), index.h("kritzel-font-size", { key: '954db891b80fb244083de24dc87255b1239ff913', selectedSize: this.tool.fontSize, fontFamily: this.tool.fontFamily, onSizeChange: event => this.handleSizeChange(event) })));
|
|
295
|
-
}
|
|
296
|
-
};
|
|
297
|
-
KritzelControlTextConfig.style = kritzelControlTextConfigCss();
|
|
298
|
-
|
|
299
|
-
const kritzelControlsCss = () => `:host{display:flex;flex-direction:column;user-select:none}: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}.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-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-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-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-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-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;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}.kritzel-config{display:flex;justify-content:center;align-items:center;cursor:var(--kritzel-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-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-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}`;
|
|
300
|
-
|
|
301
|
-
const KritzelControls = class {
|
|
302
|
-
constructor(hostRef) {
|
|
303
|
-
index.registerInstance(this, hostRef);
|
|
304
|
-
this.isControlsReady = index.createEvent(this, "isControlsReady");
|
|
305
|
-
}
|
|
306
|
-
get host() { return index.getElement(this); }
|
|
307
|
-
controls = [];
|
|
308
|
-
activeControl = null;
|
|
309
|
-
isUtilityPanelVisible = true;
|
|
310
|
-
undoState = null;
|
|
311
|
-
isControlsReady;
|
|
312
|
-
firstConfig = null;
|
|
313
|
-
isTooltipVisible = false;
|
|
314
|
-
isTouchDevice = defaultLineTool_config.KritzelDevicesHelper.isTouchDevice();
|
|
315
|
-
selectedSubOptions = new Map();
|
|
316
|
-
openSubMenuControl = null;
|
|
317
|
-
handleDocumentClick(event) {
|
|
318
|
-
const element = event.target;
|
|
319
|
-
if (!this.kritzelEngine || element.closest('.kritzel-tooltip')) {
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
this.isTooltipVisible = false;
|
|
242
|
+
class KritzelShapeTool extends defaultLineTool_config.KritzelBaseTool {
|
|
243
|
+
shapeType = defaultLineTool_config.ShapeType.Rectangle;
|
|
244
|
+
fillColor = 'transparent';
|
|
245
|
+
strokeColor = '#000000';
|
|
246
|
+
strokeWidth = 4;
|
|
247
|
+
opacity = 1;
|
|
248
|
+
fontFamily = 'Arial';
|
|
249
|
+
fontSize = 16;
|
|
250
|
+
fontColor = '#000000';
|
|
251
|
+
palette = [
|
|
252
|
+
'#000000',
|
|
253
|
+
'#FFFFFF',
|
|
254
|
+
'#FF0000',
|
|
255
|
+
'#00FF00',
|
|
256
|
+
'#0000FF',
|
|
257
|
+
'#FFFF00',
|
|
258
|
+
'#FF00FF',
|
|
259
|
+
'#00FFFF',
|
|
260
|
+
'#808080',
|
|
261
|
+
'#C0C0C0',
|
|
262
|
+
'#800000',
|
|
263
|
+
'#008000',
|
|
264
|
+
'#000080',
|
|
265
|
+
'#808000',
|
|
266
|
+
'#800080',
|
|
267
|
+
];
|
|
268
|
+
startX = 0;
|
|
269
|
+
startY = 0;
|
|
270
|
+
isDrawing = false;
|
|
271
|
+
currentShape = null;
|
|
272
|
+
constructor(core) {
|
|
273
|
+
super(core);
|
|
323
274
|
}
|
|
324
|
-
|
|
325
|
-
if (event.
|
|
275
|
+
handlePointerDown(event) {
|
|
276
|
+
if (event.cancelable) {
|
|
326
277
|
event.preventDefault();
|
|
327
|
-
this.closeTooltip();
|
|
328
|
-
this.openSubMenuControl = null;
|
|
329
|
-
this.kritzelEngine?.enable();
|
|
330
278
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
if (!this.kritzelEngine) {
|
|
355
|
-
throw new Error('kritzel-engine not found in parent element.');
|
|
279
|
+
if (event.pointerType === 'mouse') {
|
|
280
|
+
const path = event.composedPath().slice(1);
|
|
281
|
+
const objectElement = path.find(element => element.classList && element.classList.contains('object'));
|
|
282
|
+
const object = this._core.findObjectById(objectElement?.id);
|
|
283
|
+
const activeShape = this._core.store.activeShape;
|
|
284
|
+
if (activeShape === null && object instanceof defaultLineTool_config.KritzelShape) {
|
|
285
|
+
object.edit(event);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (activeShape !== null && object instanceof defaultLineTool_config.KritzelShape) {
|
|
289
|
+
activeShape.save();
|
|
290
|
+
object.edit(event);
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (activeShape !== null && object instanceof defaultLineTool_config.KritzelShape === false) {
|
|
294
|
+
this._core.resetActiveShape();
|
|
295
|
+
this._core.store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('selection'));
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
if (defaultLineTool_config.KritzelEventHelper.isLeftClick(event) === false) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
this.startDrawing(event.clientX, event.clientY);
|
|
356
302
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
303
|
+
if (event.pointerType === 'touch') {
|
|
304
|
+
const activePointers = Array.from(this._core.store.state.pointers.values());
|
|
305
|
+
const path = event.composedPath().slice(1);
|
|
306
|
+
const objectElement = path.find(element => element.classList && element.classList.contains('object'));
|
|
307
|
+
const object = this._core.findObjectById(objectElement?.id);
|
|
308
|
+
const activeShape = this._core.store.activeShape;
|
|
309
|
+
if (activeShape === null && object instanceof defaultLineTool_config.KritzelShape) {
|
|
310
|
+
object.edit(event);
|
|
311
|
+
return;
|
|
362
312
|
}
|
|
363
|
-
if (
|
|
364
|
-
|
|
365
|
-
|
|
313
|
+
if (activeShape !== null && object instanceof defaultLineTool_config.KritzelShape) {
|
|
314
|
+
activeShape.save();
|
|
315
|
+
object.edit(event);
|
|
316
|
+
return;
|
|
366
317
|
}
|
|
367
|
-
if (
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
else {
|
|
372
|
-
console.warn('Only one config control is allowed. The first one will be used.');
|
|
373
|
-
}
|
|
318
|
+
if (activeShape !== null && object instanceof defaultLineTool_config.KritzelShape === false) {
|
|
319
|
+
this._core.resetActiveShape();
|
|
320
|
+
this._core.store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('selection'));
|
|
321
|
+
return;
|
|
374
322
|
}
|
|
323
|
+
if (activePointers.length > 1) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const clientX = Math.round(activePointers[0].clientX);
|
|
327
|
+
const clientY = Math.round(activePointers[0].clientY);
|
|
328
|
+
this.startDrawing(clientX, clientY);
|
|
375
329
|
}
|
|
376
330
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
await this.kritzelEngine.changeActiveTool(this.activeControl.tool);
|
|
331
|
+
handlePointerMove(event) {
|
|
332
|
+
if (event.cancelable) {
|
|
333
|
+
event.preventDefault();
|
|
381
334
|
}
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
event.stopPropagation();
|
|
385
|
-
this.isTooltipVisible = !this.isTooltipVisible;
|
|
386
|
-
if (this.isTooltipVisible) {
|
|
387
|
-
this.kritzelEngine?.disable();
|
|
335
|
+
if (!this.isDrawing || !this.currentShape) {
|
|
336
|
+
return;
|
|
388
337
|
}
|
|
389
|
-
|
|
390
|
-
this.
|
|
338
|
+
if (event.pointerType === 'mouse') {
|
|
339
|
+
this.updateShapeSize(event.clientX, event.clientY);
|
|
340
|
+
}
|
|
341
|
+
if (event.pointerType === 'touch') {
|
|
342
|
+
const activePointers = Array.from(this._core.store.state.pointers.values());
|
|
343
|
+
if (activePointers.length === 1) {
|
|
344
|
+
const clientX = Math.round(activePointers[0].clientX);
|
|
345
|
+
const clientY = Math.round(activePointers[0].clientY);
|
|
346
|
+
this.updateShapeSize(clientX, clientY);
|
|
347
|
+
}
|
|
391
348
|
}
|
|
392
|
-
setTimeout(() => {
|
|
393
|
-
this.tooltipRef?.focusContent();
|
|
394
|
-
}, 100);
|
|
395
349
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
350
|
+
handlePointerUp(event) {
|
|
351
|
+
if (event.cancelable) {
|
|
352
|
+
event.preventDefault();
|
|
353
|
+
}
|
|
354
|
+
if (!this.isDrawing || !this.currentShape) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
this.finishDrawing();
|
|
399
358
|
}
|
|
400
|
-
|
|
359
|
+
/**
|
|
360
|
+
* Start drawing a shape. Following the same pattern as LineTool/BrushTool:
|
|
361
|
+
* - Store screen coordinates for startX, startY
|
|
362
|
+
* - Set translateX/Y to -viewportTranslateX/Y (viewport offset)
|
|
363
|
+
* - Set x, y to the actual screen position
|
|
364
|
+
* - Let updateDimensions() convert to world coordinates
|
|
365
|
+
*/
|
|
366
|
+
startDrawing(clientX, clientY) {
|
|
367
|
+
// Store screen coordinates (relative to host element)
|
|
368
|
+
this.startX = clientX - this._core.store.offsetX;
|
|
369
|
+
this.startY = clientY - this._core.store.offsetY;
|
|
370
|
+
this.isDrawing = true;
|
|
371
|
+
// Create shape using screen coordinates, following Path/Line pattern
|
|
372
|
+
this.currentShape = defaultLineTool_config.KritzelShape.create(this._core, {
|
|
373
|
+
x: this.startX,
|
|
374
|
+
y: this.startY,
|
|
375
|
+
translateX: -this._core.store.state.translateX,
|
|
376
|
+
translateY: -this._core.store.state.translateY,
|
|
377
|
+
width: 1,
|
|
378
|
+
height: 1,
|
|
379
|
+
shapeType: this.shapeType,
|
|
380
|
+
fillColor: this.fillColor,
|
|
381
|
+
strokeColor: this.strokeColor,
|
|
382
|
+
strokeWidth: this.strokeWidth,
|
|
383
|
+
opacity: this.opacity,
|
|
384
|
+
fontSize: this.fontSize,
|
|
385
|
+
fontFamily: this.fontFamily,
|
|
386
|
+
fontColor: this.fontColor,
|
|
387
|
+
});
|
|
388
|
+
this._core.store.state.objects.insert(this.currentShape);
|
|
389
|
+
this._core.rerender();
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Update shape size during drawing. Following the same pattern as LineTool:
|
|
393
|
+
* - Use screen coordinates directly
|
|
394
|
+
* - The shape's x, y, width, height are all in screen space
|
|
395
|
+
* - updateDimensions() handles conversion to world coordinates
|
|
396
|
+
*/
|
|
397
|
+
updateShapeSize(clientX, clientY) {
|
|
398
|
+
if (!this.currentShape) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
const currentX = clientX - this._core.store.offsetX;
|
|
402
|
+
const currentY = clientY - this._core.store.offsetY;
|
|
403
|
+
// Calculate bounding box in screen coordinates
|
|
404
|
+
const minX = Math.min(this.startX, currentX);
|
|
405
|
+
const minY = Math.min(this.startY, currentY);
|
|
406
|
+
const width = Math.abs(currentX - this.startX);
|
|
407
|
+
const height = Math.abs(currentY - this.startY);
|
|
408
|
+
// Update shape with screen coordinates
|
|
409
|
+
this.currentShape.x = minX;
|
|
410
|
+
this.currentShape.y = minY;
|
|
411
|
+
this.currentShape.width = Math.max(1, width);
|
|
412
|
+
this.currentShape.height = Math.max(1, height);
|
|
413
|
+
// Recalculate world-space translateX/Y
|
|
414
|
+
// Reset translateX/Y to initial value before updateDimensions
|
|
415
|
+
this.currentShape.translateX = -this._core.store.state.translateX;
|
|
416
|
+
this.currentShape.translateY = -this._core.store.state.translateY;
|
|
417
|
+
this.currentShape.updateDimensions();
|
|
418
|
+
this._core.store.state.objects.update(this.currentShape);
|
|
419
|
+
}
|
|
420
|
+
finishDrawing() {
|
|
421
|
+
if (!this.currentShape) {
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
// Remove shape if it's too small (likely an accidental click)
|
|
425
|
+
// Compare in screen space
|
|
426
|
+
if (this.currentShape.width < 10 && this.currentShape.height < 10) {
|
|
427
|
+
const shapeId = this.currentShape.id;
|
|
428
|
+
this._core.store.state.objects.remove(o => o.id === shapeId);
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
this.currentShape.zIndex = this._core.store.currentZIndex;
|
|
432
|
+
this._core.store.state.objects.update(this.currentShape);
|
|
433
|
+
this._core.engine.emitObjectsChange();
|
|
434
|
+
this._core.selectObjects([this.currentShape]);
|
|
435
|
+
this._core.store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('selection'));
|
|
436
|
+
}
|
|
437
|
+
this.isDrawing = false;
|
|
438
|
+
this.currentShape = null;
|
|
439
|
+
this._core.rerender();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
class KritzelToolConfigHelper {
|
|
444
|
+
static getToolConfig(tool) {
|
|
445
|
+
if (tool instanceof defaultLineTool_config.KritzelSelectionTool) {
|
|
446
|
+
return tool.getToolConfig();
|
|
447
|
+
}
|
|
448
|
+
if (tool instanceof defaultLineTool_config.KritzelBrushTool) {
|
|
449
|
+
return {
|
|
450
|
+
type: 'brush',
|
|
451
|
+
colorProperty: 'color',
|
|
452
|
+
sizeProperty: 'size',
|
|
453
|
+
opacityProperty: 'opacity',
|
|
454
|
+
paletteSource: 'palettes',
|
|
455
|
+
controls: [
|
|
456
|
+
{ type: 'stroke-size', propertyName: 'size' },
|
|
457
|
+
],
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
if (tool instanceof defaultLineTool_config.KritzelLineTool) {
|
|
461
|
+
return {
|
|
462
|
+
type: 'line',
|
|
463
|
+
colorProperty: 'color',
|
|
464
|
+
sizeProperty: 'size',
|
|
465
|
+
opacityProperty: 'opacity',
|
|
466
|
+
paletteSource: 'palette',
|
|
467
|
+
controls: [
|
|
468
|
+
{ type: 'stroke-size', propertyName: 'size' },
|
|
469
|
+
{ type: 'line-endings', propertyName: 'arrows', additionalProps: {} },
|
|
470
|
+
],
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
if (tool instanceof KritzelShapeTool) {
|
|
474
|
+
return {
|
|
475
|
+
type: 'shape',
|
|
476
|
+
colorProperty: 'strokeColor',
|
|
477
|
+
sizeProperty: 'strokeWidth',
|
|
478
|
+
opacityProperty: 'opacity',
|
|
479
|
+
paletteSource: 'palette',
|
|
480
|
+
controls: [
|
|
481
|
+
{ type: 'stroke-size', propertyName: 'strokeWidth' },
|
|
482
|
+
{ type: 'shape-fill', propertyName: 'fillColor', additionalProps: {} },
|
|
483
|
+
],
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
if (tool instanceof defaultLineTool_config.KritzelTextTool) {
|
|
487
|
+
return {
|
|
488
|
+
type: 'text',
|
|
489
|
+
colorProperty: 'fontColor',
|
|
490
|
+
sizeProperty: 'fontSize',
|
|
491
|
+
opacityProperty: 'opacity',
|
|
492
|
+
paletteSource: 'palette',
|
|
493
|
+
controls: [
|
|
494
|
+
{ type: 'font-size', propertyName: 'fontSize', additionalProps: {} },
|
|
495
|
+
{ type: 'font-family', propertyName: 'fontFamily' },
|
|
496
|
+
],
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
// Tool is not configurable (e.g., selection, eraser, image)
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const kritzelControlsCss = () => `:host{display:flex;flex-direction:column;user-select:none;max-width:calc(100vw - 28px)}: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;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:24px;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-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-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-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-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-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:-16px;width:16px;background:linear-gradient(to right, transparent, var(--kritzel-controls-background-color, #ffffff));pointer-events:none;z-index:1}.kritzel-config{display:flex;justify-content:center;align-items:center;cursor:var(--kritzel-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-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-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}`;
|
|
505
|
+
|
|
506
|
+
const KritzelControls = class {
|
|
507
|
+
constructor(hostRef) {
|
|
508
|
+
index.registerInstance(this, hostRef);
|
|
509
|
+
this.isControlsReady = index.createEvent(this, "isControlsReady");
|
|
510
|
+
}
|
|
511
|
+
get host() { return index.getElement(this); }
|
|
512
|
+
controls = [];
|
|
513
|
+
activeControl = null;
|
|
514
|
+
isUtilityPanelVisible = true;
|
|
515
|
+
undoState = null;
|
|
516
|
+
isControlsReady;
|
|
517
|
+
firstConfig = null;
|
|
518
|
+
isTooltipVisible = false;
|
|
519
|
+
isTouchDevice = defaultLineTool_config.KritzelDevicesHelper.isTouchDevice();
|
|
520
|
+
selectedSubOptions = new Map();
|
|
521
|
+
openSubMenuControl = null;
|
|
522
|
+
canScrollLeft = false;
|
|
523
|
+
canScrollRight = false;
|
|
524
|
+
displayValues = null;
|
|
525
|
+
handleDocumentClick(event) {
|
|
526
|
+
if (!this.kritzelEngine) {
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
// Use composedPath to check if click is inside tooltip (works across shadow DOM boundaries)
|
|
530
|
+
const path = event.composedPath();
|
|
531
|
+
const isInsideTooltip = path.some(el => {
|
|
532
|
+
const element = el;
|
|
533
|
+
if (element.tagName) {
|
|
534
|
+
return element.tagName.toLowerCase() === 'kritzel-tooltip' || element.classList?.contains('kritzel-tooltip');
|
|
535
|
+
}
|
|
536
|
+
return false;
|
|
537
|
+
});
|
|
538
|
+
if (isInsideTooltip) {
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
this.isTooltipVisible = false;
|
|
542
|
+
}
|
|
543
|
+
handleKeyDown(event) {
|
|
544
|
+
if (event.key === 'Escape') {
|
|
545
|
+
event.preventDefault();
|
|
546
|
+
this.closeTooltip();
|
|
547
|
+
this.openSubMenuControl = null;
|
|
548
|
+
this.kritzelEngine?.enable();
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
async handleActiveToolChange(event) {
|
|
552
|
+
this.activeControl = this.controls.find(control => control.tool === event.detail) || null;
|
|
553
|
+
if (this.activeControl?.tool) {
|
|
554
|
+
this.updateDisplayValues(this.activeControl.tool);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
handleSelectionChange() {
|
|
558
|
+
if (this.activeControl?.tool instanceof defaultLineTool_config.KritzelSelectionTool) {
|
|
559
|
+
this.updateDisplayValues(this.activeControl.tool);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
async closeTooltip() {
|
|
563
|
+
this.isTooltipVisible = false;
|
|
564
|
+
}
|
|
565
|
+
kritzelEngine = null;
|
|
566
|
+
tooltipRef = null;
|
|
567
|
+
toolsScrollRef = null;
|
|
568
|
+
get activeToolAsTextTool() {
|
|
569
|
+
return this.activeControl?.tool;
|
|
570
|
+
}
|
|
571
|
+
get activeToolAsBrushTool() {
|
|
572
|
+
return this.activeControl?.tool;
|
|
573
|
+
}
|
|
574
|
+
get activeToolAsLineTool() {
|
|
575
|
+
return this.activeControl?.tool;
|
|
576
|
+
}
|
|
577
|
+
get activeToolAsShapeTool() {
|
|
578
|
+
return this.activeControl?.tool;
|
|
579
|
+
}
|
|
580
|
+
handleDisplayValuesChange = (event) => {
|
|
581
|
+
const newVal = event.detail;
|
|
582
|
+
if (this.displayValues &&
|
|
583
|
+
this.displayValues.color === newVal.color &&
|
|
584
|
+
this.displayValues.size === newVal.size &&
|
|
585
|
+
this.displayValues.fontFamily === newVal.fontFamily) {
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
this.displayValues = newVal;
|
|
589
|
+
};
|
|
590
|
+
updateDisplayValues(tool) {
|
|
591
|
+
const config = KritzelToolConfigHelper.getToolConfig(tool);
|
|
592
|
+
if (!config) {
|
|
593
|
+
this.displayValues = null;
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
const color = tool[config.colorProperty];
|
|
597
|
+
const opacity = tool[config.opacityProperty] ?? 1;
|
|
598
|
+
const size = tool[config.sizeProperty];
|
|
599
|
+
const displayValues = {
|
|
600
|
+
color: KritzelColorHelper.applyOpacity(color, opacity),
|
|
601
|
+
size,
|
|
602
|
+
};
|
|
603
|
+
if (tool instanceof defaultLineTool_config.KritzelTextTool) {
|
|
604
|
+
displayValues.fontFamily = tool.fontFamily;
|
|
605
|
+
}
|
|
606
|
+
// Check for equality implementation to prevent unnecessary re-renders
|
|
607
|
+
if (this.displayValues &&
|
|
608
|
+
this.displayValues.color === displayValues.color &&
|
|
609
|
+
this.displayValues.size === displayValues.size &&
|
|
610
|
+
this.displayValues.fontFamily === displayValues.fontFamily) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
this.displayValues = displayValues;
|
|
614
|
+
}
|
|
615
|
+
async componentWillLoad() {
|
|
616
|
+
await this.initializeEngine();
|
|
617
|
+
await this.initializeTools();
|
|
618
|
+
this.isControlsReady.emit();
|
|
619
|
+
}
|
|
620
|
+
componentDidLoad() {
|
|
621
|
+
this.updateScrollIndicators();
|
|
622
|
+
}
|
|
623
|
+
updateScrollIndicators() {
|
|
624
|
+
if (!this.toolsScrollRef)
|
|
625
|
+
return;
|
|
626
|
+
const { scrollLeft, scrollWidth, clientWidth } = this.toolsScrollRef;
|
|
627
|
+
const threshold = 2; // Small threshold to account for rounding
|
|
628
|
+
this.canScrollLeft = scrollLeft > threshold;
|
|
629
|
+
this.canScrollRight = scrollLeft + clientWidth < scrollWidth - threshold;
|
|
630
|
+
}
|
|
631
|
+
handleToolsScroll = () => {
|
|
632
|
+
this.updateScrollIndicators();
|
|
633
|
+
};
|
|
634
|
+
async initializeEngine() {
|
|
635
|
+
await customElements.whenDefined('kritzel-engine');
|
|
636
|
+
this.kritzelEngine = this.host.parentElement.querySelector('kritzel-engine');
|
|
637
|
+
if (!this.kritzelEngine) {
|
|
638
|
+
throw new Error('kritzel-engine not found in parent element.');
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
async initializeTools() {
|
|
642
|
+
for (const c of this.controls) {
|
|
643
|
+
if (c.type === 'tool' && c.tool) {
|
|
644
|
+
c.tool = await this.kritzelEngine.registerTool(c.name, c.tool, c.config);
|
|
645
|
+
}
|
|
646
|
+
if (c.type === 'tool' && c.isDefault && c.tool) {
|
|
647
|
+
await this.kritzelEngine.changeActiveTool(c.tool);
|
|
648
|
+
this.activeControl = c;
|
|
649
|
+
this.updateDisplayValues(c.tool);
|
|
650
|
+
}
|
|
651
|
+
if (c.type === 'config') {
|
|
652
|
+
if (this.firstConfig === null) {
|
|
653
|
+
this.firstConfig = c;
|
|
654
|
+
}
|
|
655
|
+
else {
|
|
656
|
+
console.warn('Only one config control is allowed. The first one will be used.');
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
async handleControlClick(control) {
|
|
662
|
+
this.activeControl = control;
|
|
663
|
+
if (this.activeControl.type === 'tool') {
|
|
664
|
+
this.updateDisplayValues(this.activeControl.tool);
|
|
665
|
+
await this.kritzelEngine.changeActiveTool(this.activeControl.tool);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
handleConfigClick(event) {
|
|
669
|
+
event.stopPropagation();
|
|
670
|
+
this.isTooltipVisible = !this.isTooltipVisible;
|
|
671
|
+
if (this.isTooltipVisible) {
|
|
672
|
+
this.kritzelEngine?.disable();
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
this.kritzelEngine?.enable();
|
|
676
|
+
}
|
|
677
|
+
setTimeout(() => {
|
|
678
|
+
this.tooltipRef?.focusContent();
|
|
679
|
+
}, 100);
|
|
680
|
+
}
|
|
681
|
+
async handleToolChange(event) {
|
|
682
|
+
this.activeControl = { ...this.activeControl, tool: event.detail };
|
|
683
|
+
await this.kritzelEngine.changeActiveTool(this.activeControl.tool);
|
|
684
|
+
}
|
|
685
|
+
handleTooltipClosed() {
|
|
401
686
|
this.isTooltipVisible = false;
|
|
402
687
|
this.kritzelEngine?.enable();
|
|
403
688
|
}
|
|
@@ -441,56 +726,62 @@ const KritzelControls = class {
|
|
|
441
726
|
}
|
|
442
727
|
render() {
|
|
443
728
|
const hasConfigUI = this.activeControl?.tool instanceof defaultLineTool_config.KritzelBrushTool ||
|
|
444
|
-
this.activeControl?.tool instanceof defaultLineTool_config.KritzelTextTool
|
|
445
|
-
|
|
729
|
+
this.activeControl?.tool instanceof defaultLineTool_config.KritzelTextTool ||
|
|
730
|
+
this.activeControl?.tool instanceof defaultLineTool_config.KritzelLineTool ||
|
|
731
|
+
this.activeControl?.tool instanceof KritzelShapeTool ||
|
|
732
|
+
(this.activeControl?.tool instanceof defaultLineTool_config.KritzelSelectionTool && this.activeControl.tool.hasSelection());
|
|
733
|
+
// Separate tool controls from config control
|
|
734
|
+
const toolControls = this.controls.filter(c => c.type === 'tool');
|
|
735
|
+
const configControl = this.controls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
|
|
736
|
+
return (index.h(index.Host, { key: 'db2a043a2a32d10d7f27c01123da63115781941c', class: {
|
|
446
737
|
mobile: this.isTouchDevice,
|
|
447
|
-
} }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '
|
|
738
|
+
} }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '09104351c9f178b8d0dbc0636cf9cc230b2bca53', style: {
|
|
448
739
|
position: 'absolute',
|
|
449
740
|
bottom: '56px',
|
|
450
741
|
left: '12px',
|
|
451
|
-
}, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '
|
|
452
|
-
|
|
453
|
-
//
|
|
454
|
-
if (
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
if (el)
|
|
463
|
-
control._anchorRef = el;
|
|
464
|
-
} }, index.h("button", { class: "kritzel-control-main", onClick: () => this.handleControlClick(control), title: selectedSubOption?.label }, index.h("kritzel-icon", { name: selectedSubOption?.icon || control.icon })), index.h("button", { class: {
|
|
465
|
-
'kritzel-control-dropdown': true,
|
|
466
|
-
'visible': isActive,
|
|
467
|
-
}, onClick: (e) => this.toggleSubMenu(e, control), "aria-label": "Select shape type", "aria-expanded": isSubMenuOpen ? 'true' : 'false', tabIndex: isActive ? 0 : -1 }, index.h("kritzel-icon", { name: "chevron-down", size: 12 })), index.h("kritzel-tooltip", { isVisible: isSubMenuOpen, anchorElement: control._anchorRef, onTooltipClosed: () => { this.openSubMenuControl = null; } }, index.h("div", { class: "kritzel-submenu-content" }, control.subOptions.map(option => (index.h("button", { class: {
|
|
468
|
-
'kritzel-submenu-item': true,
|
|
469
|
-
'active': option.id === selectedSubOption?.id,
|
|
470
|
-
}, key: option.id, onClick: () => this.selectSubOption(control, option) }, index.h("kritzel-icon", { name: option.icon, size: 20 }), index.h("span", null, option.label))))))));
|
|
471
|
-
}
|
|
472
|
-
// Regular tool control (no sub-options)
|
|
473
|
-
return (index.h("button", { class: {
|
|
474
|
-
'kritzel-control': true,
|
|
475
|
-
'selected': this.activeControl?.name === control?.name,
|
|
476
|
-
}, key: control.name, onClick: _event => this.handleControlClick?.(control) }, index.h("kritzel-icon", { name: control.icon })));
|
|
477
|
-
}
|
|
478
|
-
if (control.type === 'config' && control.name === this.firstConfig?.name && this.activeControl) {
|
|
742
|
+
}, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '22f95249dddcf05a75425f96ab5381fe8a4824d4', class: "kritzel-controls" }, index.h("div", { key: 'fcca99e2a56f401b28205b8806497c46b7f9a94b', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), index.h("div", { key: '145802334aa83b0190a70dd2a3aca4389cb8b88c', class: "kritzel-tools-scroll", ref: el => {
|
|
743
|
+
this.toolsScrollRef = el;
|
|
744
|
+
// Update indicators when ref is set
|
|
745
|
+
if (el)
|
|
746
|
+
this.updateScrollIndicators();
|
|
747
|
+
}, onScroll: this.handleToolsScroll }, toolControls.map(control => {
|
|
748
|
+
// Check if this control has sub-options (split-button)
|
|
749
|
+
if (control.subOptions?.length) {
|
|
750
|
+
const selectedSubOption = this.getSelectedSubOption(control);
|
|
751
|
+
const isActive = this.activeControl?.name === control.name;
|
|
752
|
+
const isSubMenuOpen = this.openSubMenuControl?.name === control.name;
|
|
479
753
|
return (index.h("div", { class: {
|
|
480
|
-
'kritzel-
|
|
481
|
-
'
|
|
482
|
-
}, key: control.name
|
|
483
|
-
if (
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
}
|
|
754
|
+
'kritzel-control-split': true,
|
|
755
|
+
'selected': isActive,
|
|
756
|
+
}, key: control.name, ref: el => {
|
|
757
|
+
if (el)
|
|
758
|
+
control._anchorRef = el;
|
|
759
|
+
} }, index.h("button", { class: "kritzel-control-main", onClick: () => this.handleControlClick(control), title: selectedSubOption?.label }, index.h("kritzel-icon", { name: selectedSubOption?.icon || control.icon })), index.h("button", { class: {
|
|
760
|
+
'kritzel-control-dropdown': true,
|
|
761
|
+
'visible': isActive,
|
|
762
|
+
}, onClick: (e) => this.toggleSubMenu(e, control), "aria-label": "Select shape type", "aria-expanded": isSubMenuOpen ? 'true' : 'false', tabIndex: isActive ? 0 : -1 }, index.h("kritzel-icon", { name: "chevron-down", size: 12 })), index.h("kritzel-tooltip", { isVisible: isSubMenuOpen, anchorElement: control._anchorRef, onTooltipClosed: () => { this.openSubMenuControl = null; } }, index.h("div", { class: "kritzel-submenu-content" }, control.subOptions.map(option => (index.h("button", { class: {
|
|
763
|
+
'kritzel-submenu-item': true,
|
|
764
|
+
'active': option.id === selectedSubOption?.id,
|
|
765
|
+
}, key: option.id, onClick: () => this.selectSubOption(control, option) }, index.h("kritzel-icon", { name: option.icon, size: 20 }), index.h("span", null, option.label))))))));
|
|
492
766
|
}
|
|
493
|
-
|
|
767
|
+
// Regular tool control (no sub-options)
|
|
768
|
+
return (index.h("button", { class: {
|
|
769
|
+
'kritzel-control': true,
|
|
770
|
+
'selected': this.activeControl?.name === control?.name,
|
|
771
|
+
}, key: control.name, onClick: _event => this.handleControlClick?.(control) }, index.h("kritzel-icon", { name: control.icon })));
|
|
772
|
+
})), index.h("div", { key: '43e7811998855f57097b743998363fd6866bfb29', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight } }), configControl && this.activeControl && (index.h("div", { class: {
|
|
773
|
+
'kritzel-config-container': true,
|
|
774
|
+
'visible': hasConfigUI,
|
|
775
|
+
}, key: configControl.name }, index.h("div", { key: 'c1ff98f16c41d45666915b96931f23e0cf12ed6f', class: "config-gradient-left" }), index.h("kritzel-tooltip", { key: 'eac68125daa371d751b65ac561e33848cad3bd69', ref: el => (this.tooltipRef = el), isVisible: this.isTooltipVisible, anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), onTooltipClosed: () => this.handleTooltipClosed() }, index.h("kritzel-tool-config", { key: '83ed025386d9d1b3ec8b52e99930645c4c35b20a', tool: this.activeControl.tool, onToolChange: event => this.handleToolChange?.(event), onDisplayValuesChange: this.handleDisplayValuesChange, style: { width: '100%', height: '100%' } })), index.h("div", { key: 'cf18abb832c10826685fb41794a42b8b6a6a7486', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", onClick: event => this.handleConfigClick?.(event), onKeyDown: event => {
|
|
776
|
+
if (event.key === 'Enter') {
|
|
777
|
+
this.handleConfigClick?.(event);
|
|
778
|
+
}
|
|
779
|
+
}, style: {
|
|
780
|
+
cursor: 'pointer',
|
|
781
|
+
} }, this.activeControl.tool instanceof defaultLineTool_config.KritzelTextTool && this.displayValues ? (index.h("div", { class: "font-container" }, index.h("kritzel-font", { fontFamily: this.displayValues.fontFamily, size: this.displayValues.size, color: this.displayValues.color }))) : this.displayValues && (index.h("div", { class: "color-container" }, index.h("kritzel-color", { value: this.displayValues.color, size: this.displayValues.size, style: {
|
|
782
|
+
borderRadius: '50%',
|
|
783
|
+
border: 'none',
|
|
784
|
+
} })))))))));
|
|
494
785
|
}
|
|
495
786
|
static get assetsDirs() { return ["../assets"]; }
|
|
496
787
|
};
|
|
@@ -564,7 +855,7 @@ const KritzelCursorTrail = class {
|
|
|
564
855
|
}
|
|
565
856
|
}
|
|
566
857
|
render() {
|
|
567
|
-
return (index.h(index.Host, { key: '
|
|
858
|
+
return (index.h(index.Host, { key: '65563f09091c0014046b65d424b4cecf89d4a407' }, this.cursorTrailPoints.length > 1 && (index.h("svg", { key: '9634426566a9cd69cbc63f419726af16826e45f9', class: "cursor-trail-svg", xmlns: "http://www.w3.org/2000/svg", style: {
|
|
568
859
|
position: 'absolute',
|
|
569
860
|
left: '0',
|
|
570
861
|
top: '0',
|
|
@@ -773,656 +1064,77 @@ const KritzelDropdown = class {
|
|
|
773
1064
|
if (this.suffixSlotElement) {
|
|
774
1065
|
const newHasContent = this.suffixSlotElement.assignedNodes({ flatten: true }).length > 0;
|
|
775
1066
|
if (this.hasSuffixContent !== newHasContent) {
|
|
776
|
-
this.hasSuffixContent = newHasContent;
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
else if (this.hasSuffixContent !== false) {
|
|
780
|
-
this.hasSuffixContent = false;
|
|
781
|
-
}
|
|
782
|
-
};
|
|
783
|
-
evaluatePrefixContent = () => {
|
|
784
|
-
if (this.prefixSlotElement) {
|
|
785
|
-
const newHasContent = this.prefixSlotElement.assignedNodes({ flatten: true }).length > 0;
|
|
786
|
-
if (this.hasPrefixContent !== newHasContent) {
|
|
787
|
-
this.hasPrefixContent = newHasContent;
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
else if (this.hasPrefixContent !== false) {
|
|
791
|
-
this.hasPrefixContent = false;
|
|
792
|
-
}
|
|
793
|
-
};
|
|
794
|
-
getSelectedLabel() {
|
|
795
|
-
const selectedOption = this.options.find(opt => opt.value === this.internalValue);
|
|
796
|
-
return selectedOption?.label ?? '';
|
|
797
|
-
}
|
|
798
|
-
getSelectedStyle() {
|
|
799
|
-
const selectedOption = this.options.find(opt => opt.value === this.internalValue);
|
|
800
|
-
return selectedOption?.style;
|
|
801
|
-
}
|
|
802
|
-
render() {
|
|
803
|
-
const triggerClasses = {
|
|
804
|
-
'dropdown-trigger': true,
|
|
805
|
-
'has-suffix-border': this.hasSuffixContent,
|
|
806
|
-
'has-prefix-border': this.hasPrefixContent,
|
|
807
|
-
'is-open': this.isOpen,
|
|
808
|
-
'open-up': this.openDirection === 'up',
|
|
809
|
-
};
|
|
810
|
-
const menuClasses = {
|
|
811
|
-
'dropdown-menu': true,
|
|
812
|
-
'is-open': this.isOpen,
|
|
813
|
-
'open-up': this.openDirection === 'up',
|
|
814
|
-
'open-down': this.openDirection === 'down',
|
|
815
|
-
};
|
|
816
|
-
return (index.h(index.Host, { key: '29d076eb2ef76527c0930ab82ace0d05c896ab6c' }, index.h("div", { key: '1afac5cc0b7f408849670b8cb62fe0bd0f3b27f1', class: "dropdown-wrapper", ref: el => (this.wrapperElement = el) }, index.h("slot", { key: '3cfcf787c3b3eedbd6bf30c7506a0a4912429672', name: "prefix", ref: el => (this.prefixSlotElement = el), onSlotchange: this.evaluatePrefixContent }), index.h("div", { key: 'b88120ed3e44871220e6ba61e8bef457651a2086', class: "dropdown-container", style: { width: this.width } }, index.h("button", { key: '79082189066f3d0b4f5797420ec222847792fe52', type: "button", class: triggerClasses, style: { ...this.selectStyles, ...this.getSelectedStyle() }, onClick: this.toggleMenu, onKeyDown: this.handleTriggerKeyDown, "aria-haspopup": "listbox", "aria-expanded": this.isOpen ? 'true' : 'false', ref: el => (this.triggerElement = el) }, index.h("span", { key: 'a490bb6689ec1820144fe82f6833bee82e6ead0e', class: "dropdown-trigger-label" }, this.getSelectedLabel()), index.h("span", { key: '8bd7768f6fdd3c507bbca54d7d135adabe04901f', class: "dropdown-trigger-arrow", "aria-hidden": "true" }, index.h("svg", { key: 'e1b854d2c93e3067181108f8d782e1393ddb615c', xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("polyline", { key: '3622cbf8964f4e50aa55be5209240dfd252f1d84', points: "6 9 12 15 18 9" }))))), index.h("slot", { key: 'b91317736904cbeee0f87058b822bd77c6b163ca', name: "suffix", ref: el => (this.suffixSlotElement = el), onSlotchange: this.evaluateSuffixContent }), index.h("ul", { key: '0ca8690345974e9b7ad184f4c7ab7cf5367b183c', class: menuClasses, role: "listbox", tabindex: "-1", onKeyDown: this.handleMenuKeyDown, ref: el => (this.menuElement = el) }, this.options.map((option, index$1) => {
|
|
817
|
-
const isSelected = option.value === this.internalValue;
|
|
818
|
-
const isFocused = index$1 === this.focusedIndex;
|
|
819
|
-
const optionClasses = {
|
|
820
|
-
'dropdown-option': true,
|
|
821
|
-
'is-selected': isSelected,
|
|
822
|
-
'is-focused': isFocused,
|
|
823
|
-
};
|
|
824
|
-
return (index.h("li", { class: optionClasses, role: "option", "aria-selected": isSelected ? 'true' : 'false', style: option.style, onClick: () => this.selectOption(option), onMouseEnter: () => this.handleOptionMouseEnter(index$1) }, option.label, isSelected && (index.h("span", { class: "dropdown-option-check", "aria-hidden": "true" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("polyline", { points: "20 6 9 17 4 12" }))))));
|
|
825
|
-
})))));
|
|
826
|
-
}
|
|
827
|
-
static get watchers() { return {
|
|
828
|
-
"options": [{
|
|
829
|
-
"optionsChanged": 0
|
|
830
|
-
}],
|
|
831
|
-
"value": [{
|
|
832
|
-
"externalValueChanged": 0
|
|
833
|
-
}]
|
|
834
|
-
}; }
|
|
835
|
-
};
|
|
836
|
-
KritzelDropdown.style = kritzelDropdownCss();
|
|
837
|
-
|
|
838
|
-
var ShapeType;
|
|
839
|
-
(function (ShapeType) {
|
|
840
|
-
ShapeType["Rectangle"] = "rectangle";
|
|
841
|
-
ShapeType["Ellipse"] = "ellipse";
|
|
842
|
-
ShapeType["Triangle"] = "triangle";
|
|
843
|
-
})(ShapeType || (ShapeType = {}));
|
|
844
|
-
|
|
845
|
-
class KritzelShape extends defaultLineTool_config.KritzelBaseObject {
|
|
846
|
-
__class__ = 'KritzelShape';
|
|
847
|
-
shapeType = ShapeType.Rectangle;
|
|
848
|
-
fillColor = 'transparent';
|
|
849
|
-
strokeColor = '#000000';
|
|
850
|
-
strokeWidth = 4;
|
|
851
|
-
fontFamily = 'Arial';
|
|
852
|
-
fontSize = 16;
|
|
853
|
-
fontColor = '#000000';
|
|
854
|
-
/** Screen-space x coordinate of the shape's top-left corner (like Path.x) */
|
|
855
|
-
x = 0;
|
|
856
|
-
/** Screen-space y coordinate of the shape's top-left corner (like Path.y) */
|
|
857
|
-
y = 0;
|
|
858
|
-
scale = 1;
|
|
859
|
-
scaleFactor = 1;
|
|
860
|
-
isDebugInfoVisible = true;
|
|
861
|
-
isEditable = true;
|
|
862
|
-
isEditing = false;
|
|
863
|
-
editor = null;
|
|
864
|
-
content = null;
|
|
865
|
-
_schema = new defaultLineTool_config.Schema({
|
|
866
|
-
nodes: defaultLineTool_config.addListNodes(defaultLineTool_config.schema.spec.nodes, 'paragraph block*', 'block'),
|
|
867
|
-
marks: defaultLineTool_config.schema.spec.marks,
|
|
868
|
-
});
|
|
869
|
-
uneditedObject = null;
|
|
870
|
-
/**
|
|
871
|
-
* Returns the viewBox for the shape's SVG, using screen-space coordinates.
|
|
872
|
-
* This follows the same pattern as KritzelPath.viewBox.
|
|
873
|
-
*/
|
|
874
|
-
get viewBox() {
|
|
875
|
-
return `${this.x} ${this.y} ${this.width} ${this.height}`;
|
|
876
|
-
}
|
|
877
|
-
constructor(config) {
|
|
878
|
-
super();
|
|
879
|
-
if (config) {
|
|
880
|
-
this.x = config.x ?? 0;
|
|
881
|
-
this.y = config.y ?? 0;
|
|
882
|
-
this.translateX = config.translateX ?? 0;
|
|
883
|
-
this.translateY = config.translateY ?? 0;
|
|
884
|
-
this.width = config.width ?? 100;
|
|
885
|
-
this.height = config.height ?? 100;
|
|
886
|
-
this.shapeType = config.shapeType ?? ShapeType.Rectangle;
|
|
887
|
-
this.fillColor = config.fillColor ?? 'transparent';
|
|
888
|
-
this.strokeColor = config.strokeColor ?? '#000000';
|
|
889
|
-
this.strokeWidth = config.strokeWidth ?? 4;
|
|
890
|
-
this.fontSize = config.fontSize ?? 16;
|
|
891
|
-
this.fontFamily = config.fontFamily ?? 'Arial';
|
|
892
|
-
this.fontColor = config.fontColor ?? '#000000';
|
|
893
|
-
this.scale = config.scale ?? 1;
|
|
894
|
-
this.scaleFactor = config.scaleX ?? 1;
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
/**
|
|
898
|
-
* Creates a new KritzelShape with screen-space coordinates.
|
|
899
|
-
* Following the same pattern as KritzelPath.create():
|
|
900
|
-
* - x, y are screen-space coordinates of the shape's top-left corner
|
|
901
|
-
* - translateX, translateY should be set to -viewportTranslateX, -viewportTranslateY
|
|
902
|
-
* - width, height are in screen-space
|
|
903
|
-
* - scale is the viewport scale at creation time
|
|
904
|
-
*/
|
|
905
|
-
static create(core, config) {
|
|
906
|
-
const object = new KritzelShape();
|
|
907
|
-
object._core = core;
|
|
908
|
-
object.id = object.generateId();
|
|
909
|
-
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
910
|
-
object.x = config?.x ?? 0;
|
|
911
|
-
object.y = config?.y ?? 0;
|
|
912
|
-
object.translateX = config?.translateX ?? 0;
|
|
913
|
-
object.translateY = config?.translateY ?? 0;
|
|
914
|
-
object.width = config?.width ?? 100;
|
|
915
|
-
object.height = config?.height ?? 100;
|
|
916
|
-
object.shapeType = config?.shapeType ?? ShapeType.Rectangle;
|
|
917
|
-
object.fillColor = config?.fillColor ?? 'transparent';
|
|
918
|
-
object.strokeColor = config?.strokeColor ?? '#000000';
|
|
919
|
-
object.strokeWidth = config?.strokeWidth ?? 4;
|
|
920
|
-
object.fontSize = config?.fontSize ?? 16;
|
|
921
|
-
object.fontFamily = config?.fontFamily ?? 'Arial';
|
|
922
|
-
object.fontColor = config?.fontColor ?? '#000000';
|
|
923
|
-
object.backgroundColor = 'transparent';
|
|
924
|
-
object.scaleFactor = 1;
|
|
925
|
-
object.scale = core.store.state.scale;
|
|
926
|
-
object.zIndex = core.store.currentZIndex;
|
|
927
|
-
object.editor = object.createEditor();
|
|
928
|
-
// Compute world-space translateX/Y from screen-space coordinates
|
|
929
|
-
// This follows the same pattern as KritzelPath.updateDimensions()
|
|
930
|
-
object.updateDimensions();
|
|
931
|
-
return object;
|
|
932
|
-
}
|
|
933
|
-
/**
|
|
934
|
-
* Updates the translateX/Y to world coordinates based on screen-space x, y.
|
|
935
|
-
* This follows the same pattern as KritzelPath.updateDimensions().
|
|
936
|
-
*
|
|
937
|
-
* The formula: translateX = (x + initialTranslateX) / scale
|
|
938
|
-
* where initialTranslateX was -viewportTranslateX
|
|
939
|
-
*
|
|
940
|
-
* This converts screen-space position to world coordinates.
|
|
941
|
-
*/
|
|
942
|
-
updateDimensions() {
|
|
943
|
-
this.translateX = (this.x + this.translateX) / this.scale;
|
|
944
|
-
this.translateY = (this.y + this.translateY) / this.scale;
|
|
945
|
-
}
|
|
946
|
-
mount(element) {
|
|
947
|
-
if (element === null || this.isInViewport() === false) {
|
|
948
|
-
return;
|
|
949
|
-
}
|
|
950
|
-
if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
953
|
-
this.elementRef = element;
|
|
954
|
-
this.isMounted = true;
|
|
955
|
-
}
|
|
956
|
-
mountTextEditor(element) {
|
|
957
|
-
if (element === null) {
|
|
958
|
-
return;
|
|
959
|
-
}
|
|
960
|
-
if (this.editor.dom.parentElement === element) {
|
|
961
|
-
return;
|
|
962
|
-
}
|
|
963
|
-
element.style.fontFamily = this.fontFamily;
|
|
964
|
-
element.style.fontSize = `${this.fontSize}pt`;
|
|
965
|
-
element.style.color = this.fontColor;
|
|
966
|
-
element.style.whiteSpace = 'pre-wrap';
|
|
967
|
-
element.style.wordWrap = 'break-word';
|
|
968
|
-
element.innerHTML = '';
|
|
969
|
-
element.appendChild(this.editor.dom);
|
|
970
|
-
}
|
|
971
|
-
createEditor() {
|
|
972
|
-
const doc = this._schema.node('doc', null, [this._schema.node('paragraph')]);
|
|
973
|
-
return new defaultLineTool_config.EditorView(null, {
|
|
974
|
-
state: defaultLineTool_config.EditorState.create({
|
|
975
|
-
doc: doc,
|
|
976
|
-
plugins: [defaultLineTool_config.keymap(defaultLineTool_config.baseKeymap)],
|
|
977
|
-
}),
|
|
978
|
-
editable: () => false,
|
|
979
|
-
dispatchTransaction: transaction => {
|
|
980
|
-
const newState = this.editor.state.apply(transaction);
|
|
981
|
-
this.editor.updateState(newState);
|
|
982
|
-
if (transaction.docChanged) {
|
|
983
|
-
this.content = newState.doc.toJSON();
|
|
984
|
-
if (!transaction.getMeta('fromRemote')) {
|
|
985
|
-
this._core.store.state.objects.update(this, { temporary: true });
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
},
|
|
989
|
-
});
|
|
990
|
-
}
|
|
991
|
-
setContent(content) {
|
|
992
|
-
this.content = content;
|
|
993
|
-
if (this.editor && content) {
|
|
994
|
-
const newDoc = this.editor.state.schema.nodeFromJSON(content);
|
|
995
|
-
const tr = this.editor.state.tr.replaceWith(0, this.editor.state.doc.content.size, newDoc.content);
|
|
996
|
-
tr.setMeta('fromRemote', true);
|
|
997
|
-
this.editor.dispatch(tr);
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
resize(x, y, width, height) {
|
|
1001
|
-
if (width <= 1 || height <= 1) {
|
|
1002
|
-
return;
|
|
1003
|
-
}
|
|
1004
|
-
this.width = width;
|
|
1005
|
-
this.height = height;
|
|
1006
|
-
this.translateX = x;
|
|
1007
|
-
this.translateY = y;
|
|
1008
|
-
this._core.store.state.objects.update(this);
|
|
1009
|
-
}
|
|
1010
|
-
focus(coords) {
|
|
1011
|
-
if (this.editor) {
|
|
1012
|
-
const doc = this.editor.state.doc;
|
|
1013
|
-
if (coords?.x && coords?.y) {
|
|
1014
|
-
const pos = this.editor.posAtCoords({ left: coords.x, top: coords.y });
|
|
1015
|
-
if (pos) {
|
|
1016
|
-
this.editor.dispatch(this.editor.state.tr.setSelection(defaultLineTool_config.TextSelection.create(doc, pos.pos)));
|
|
1017
|
-
this.editor.focus();
|
|
1018
|
-
if (defaultLineTool_config.KritzelDevicesHelper.isIOS()) {
|
|
1019
|
-
this.scrollIntoViewOnIOS();
|
|
1020
|
-
}
|
|
1021
|
-
return;
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
const end = Math.max(1, doc.content.size - 1);
|
|
1025
|
-
this.editor.dispatch(this.editor.state.tr.setSelection(defaultLineTool_config.TextSelection.create(doc, end)));
|
|
1026
|
-
this.editor.focus();
|
|
1027
|
-
if (defaultLineTool_config.KritzelDevicesHelper.isIOS()) {
|
|
1028
|
-
this.scrollIntoViewOnIOS();
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
scrollIntoViewOnIOS() {
|
|
1033
|
-
setTimeout(() => {
|
|
1034
|
-
if (this.editor && this.editor.dom) {
|
|
1035
|
-
this.editor.dom.scrollIntoView({
|
|
1036
|
-
behavior: 'smooth',
|
|
1037
|
-
block: 'center',
|
|
1038
|
-
inline: 'nearest',
|
|
1039
|
-
});
|
|
1040
|
-
}
|
|
1041
|
-
}, 300);
|
|
1042
|
-
}
|
|
1043
|
-
edit(event) {
|
|
1044
|
-
defaultLineTool_config.KritzelKeyboardHelper.disableInteractiveWidget();
|
|
1045
|
-
this.uneditedObject = this.clone();
|
|
1046
|
-
this._core.store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('shape'));
|
|
1047
|
-
this.editor.setProps({ editable: () => true });
|
|
1048
|
-
this.isEditing = true;
|
|
1049
|
-
this._core.rerender();
|
|
1050
|
-
this.focus({ x: event?.clientX, y: event?.clientY });
|
|
1051
|
-
defaultLineTool_config.KritzelKeyboardHelper.enableInteractiveWidget();
|
|
1052
|
-
}
|
|
1053
|
-
save() {
|
|
1054
|
-
this.content = this.editor.state.doc.toJSON();
|
|
1055
|
-
this.editor.setProps({ editable: () => false });
|
|
1056
|
-
this.editor.dom.blur();
|
|
1057
|
-
this.isEditing = false;
|
|
1058
|
-
this._core.store.state.objects.consolidateTemporaryItems();
|
|
1059
|
-
this._core.store.state.objects.update(this);
|
|
1060
|
-
this._core.engine.emitObjectsChange();
|
|
1061
|
-
}
|
|
1062
|
-
handlePointerDown(event) {
|
|
1063
|
-
if (!this.isEditing) {
|
|
1064
|
-
return;
|
|
1065
|
-
}
|
|
1066
|
-
event.stopPropagation();
|
|
1067
|
-
}
|
|
1068
|
-
handlePointerMove(event) {
|
|
1069
|
-
if (!this.isEditing) {
|
|
1070
|
-
return;
|
|
1071
|
-
}
|
|
1072
|
-
event.stopPropagation();
|
|
1073
|
-
}
|
|
1074
|
-
handlePointerUp(event) {
|
|
1075
|
-
if (!this.isEditing) {
|
|
1076
|
-
return;
|
|
1077
|
-
}
|
|
1078
|
-
event.stopPropagation();
|
|
1079
|
-
}
|
|
1080
|
-
copy() {
|
|
1081
|
-
const copiedObject = super.copy();
|
|
1082
|
-
copiedObject.editor = copiedObject.createEditor();
|
|
1083
|
-
if (this.content) {
|
|
1084
|
-
copiedObject.setContent(this.content);
|
|
1085
|
-
}
|
|
1086
|
-
return copiedObject;
|
|
1087
|
-
}
|
|
1088
|
-
serialize() {
|
|
1089
|
-
const { _core, _elementRef, _schema, element, totalWidth, totalHeight, editor, uneditedObject, ...remainingProps } = this;
|
|
1090
|
-
const clonedProps = structuredClone(remainingProps);
|
|
1091
|
-
if (element && typeof element === 'object' && 'nodeType' in element && element.nodeType === 1) {
|
|
1092
|
-
clonedProps.element = element.cloneNode(true);
|
|
1093
|
-
}
|
|
1094
|
-
return clonedProps;
|
|
1095
|
-
}
|
|
1096
|
-
deserialize(object) {
|
|
1097
|
-
super.deserialize(object);
|
|
1098
|
-
if (object.content) {
|
|
1099
|
-
this.setContent(object.content);
|
|
1100
|
-
}
|
|
1101
|
-
return this;
|
|
1102
|
-
}
|
|
1103
|
-
/**
|
|
1104
|
-
* Returns the clipping polygon for arrow intersection.
|
|
1105
|
-
* For ellipse: returns a many-sided polygon approximation
|
|
1106
|
-
* For triangle: returns the 3 corners
|
|
1107
|
-
* For rectangle: returns null (uses default rotatedPolygon)
|
|
1108
|
-
*
|
|
1109
|
-
* Includes padding for half the stroke width so arrow heads don't overlap the stroke.
|
|
1110
|
-
*/
|
|
1111
|
-
getClipPolygon() {
|
|
1112
|
-
// Calculate world-space center and dimensions
|
|
1113
|
-
const worldWidth = this.totalWidth / this.scale;
|
|
1114
|
-
const worldHeight = this.totalHeight / this.scale;
|
|
1115
|
-
const centerX = this.translateX + worldWidth / 2;
|
|
1116
|
-
const centerY = this.translateY + worldHeight / 2;
|
|
1117
|
-
// Add padding for stroke width so arrows don't overlap the stroke
|
|
1118
|
-
const strokePadding = (this.strokeWidth / this.scale) / 2;
|
|
1119
|
-
switch (this.shapeType) {
|
|
1120
|
-
case ShapeType.Ellipse:
|
|
1121
|
-
// Return a 32-segment polygon approximation of the ellipse
|
|
1122
|
-
// Add stroke padding to radii
|
|
1123
|
-
return defaultLineTool_config.KritzelGeometryHelper.getEllipsePolygonApproximation(centerX, centerY, worldWidth / 2 + strokePadding, worldHeight / 2 + strokePadding, 32, this.rotation);
|
|
1124
|
-
case ShapeType.Triangle:
|
|
1125
|
-
// Return the 3 corners of the triangle in world coordinates
|
|
1126
|
-
// Triangle: top-center, bottom-right, bottom-left
|
|
1127
|
-
// Expand each vertex outward from center by strokePadding
|
|
1128
|
-
const expandVertex = (vx, vy) => {
|
|
1129
|
-
const dx = vx - centerX;
|
|
1130
|
-
const dy = vy - centerY;
|
|
1131
|
-
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
1132
|
-
if (dist === 0)
|
|
1133
|
-
return { x: vx, y: vy };
|
|
1134
|
-
const scale = (dist + strokePadding) / dist;
|
|
1135
|
-
return {
|
|
1136
|
-
x: centerX + dx * scale,
|
|
1137
|
-
y: centerY + dy * scale
|
|
1138
|
-
};
|
|
1139
|
-
};
|
|
1140
|
-
const topX = this.translateX + worldWidth / 2;
|
|
1141
|
-
const topY = this.translateY;
|
|
1142
|
-
const bottomLeftX = this.translateX;
|
|
1143
|
-
const bottomLeftY = this.translateY + worldHeight;
|
|
1144
|
-
const bottomRightX = this.translateX + worldWidth;
|
|
1145
|
-
const bottomRightY = this.translateY + worldHeight;
|
|
1146
|
-
const expandedTop = expandVertex(topX, topY);
|
|
1147
|
-
const expandedBottomRight = expandVertex(bottomRightX, bottomRightY);
|
|
1148
|
-
const expandedBottomLeft = expandVertex(bottomLeftX, bottomLeftY);
|
|
1149
|
-
// Apply rotation around center if rotated
|
|
1150
|
-
if (this.rotation !== 0) {
|
|
1151
|
-
const cos = Math.cos(this.rotation);
|
|
1152
|
-
const sin = Math.sin(this.rotation);
|
|
1153
|
-
const rotate = (p) => {
|
|
1154
|
-
const dx = p.x - centerX;
|
|
1155
|
-
const dy = p.y - centerY;
|
|
1156
|
-
return {
|
|
1157
|
-
x: centerX + dx * cos - dy * sin,
|
|
1158
|
-
y: centerY + dx * sin + dy * cos
|
|
1159
|
-
};
|
|
1160
|
-
};
|
|
1161
|
-
return [
|
|
1162
|
-
rotate(expandedTop),
|
|
1163
|
-
rotate(expandedBottomRight),
|
|
1164
|
-
rotate(expandedBottomLeft)
|
|
1165
|
-
];
|
|
1166
|
-
}
|
|
1167
|
-
return [expandedTop, expandedBottomRight, expandedBottomLeft];
|
|
1168
|
-
case ShapeType.Rectangle:
|
|
1169
|
-
default:
|
|
1170
|
-
// For rectangles, return null to use the default rotatedPolygon
|
|
1171
|
-
return null;
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
/**
|
|
1175
|
-
* Returns the SVG path for rendering the shape.
|
|
1176
|
-
* The path uses screen-space coordinates relative to (x, y).
|
|
1177
|
-
*/
|
|
1178
|
-
getSvgPath() {
|
|
1179
|
-
const w = this.width;
|
|
1180
|
-
const h = this.height;
|
|
1181
|
-
switch (this.shapeType) {
|
|
1182
|
-
case ShapeType.Rectangle:
|
|
1183
|
-
return `M ${this.x} ${this.y} L ${this.x + w} ${this.y} L ${this.x + w} ${this.y + h} L ${this.x} ${this.y + h} Z`;
|
|
1184
|
-
case ShapeType.Ellipse:
|
|
1185
|
-
const cx = this.x + w / 2;
|
|
1186
|
-
const cy = this.y + h / 2;
|
|
1187
|
-
const rx = w / 2;
|
|
1188
|
-
const ry = h / 2;
|
|
1189
|
-
return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;
|
|
1190
|
-
case ShapeType.Triangle:
|
|
1191
|
-
const topX = this.x + w / 2;
|
|
1192
|
-
const topY = this.y;
|
|
1193
|
-
const bottomLeftX = this.x;
|
|
1194
|
-
const bottomLeftY = this.y + h;
|
|
1195
|
-
const bottomRightX = this.x + w;
|
|
1196
|
-
const bottomRightY = this.y + h;
|
|
1197
|
-
return `M ${topX} ${topY} L ${bottomRightX} ${bottomRightY} L ${bottomLeftX} ${bottomLeftY} Z`;
|
|
1198
|
-
default:
|
|
1199
|
-
return `M ${this.x} ${this.y} L ${this.x + w} ${this.y} L ${this.x + w} ${this.y + h} L ${this.x} ${this.y + h} Z`;
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
|
|
1204
|
-
class KritzelShapeTool extends defaultLineTool_config.KritzelBaseTool {
|
|
1205
|
-
shapeType = ShapeType.Rectangle;
|
|
1206
|
-
fillColor = 'transparent';
|
|
1207
|
-
strokeColor = '#000000';
|
|
1208
|
-
strokeWidth = 4;
|
|
1209
|
-
fontFamily = 'Arial';
|
|
1210
|
-
fontSize = 16;
|
|
1211
|
-
fontColor = '#000000';
|
|
1212
|
-
palette = [
|
|
1213
|
-
'#000000',
|
|
1214
|
-
'#FFFFFF',
|
|
1215
|
-
'#FF0000',
|
|
1216
|
-
'#00FF00',
|
|
1217
|
-
'#0000FF',
|
|
1218
|
-
'#FFFF00',
|
|
1219
|
-
'#FF00FF',
|
|
1220
|
-
'#00FFFF',
|
|
1221
|
-
'#808080',
|
|
1222
|
-
'#C0C0C0',
|
|
1223
|
-
'#800000',
|
|
1224
|
-
'#008000',
|
|
1225
|
-
'#000080',
|
|
1226
|
-
'#808000',
|
|
1227
|
-
'#800080',
|
|
1228
|
-
];
|
|
1229
|
-
startX = 0;
|
|
1230
|
-
startY = 0;
|
|
1231
|
-
isDrawing = false;
|
|
1232
|
-
currentShape = null;
|
|
1233
|
-
constructor(core) {
|
|
1234
|
-
super(core);
|
|
1235
|
-
}
|
|
1236
|
-
handlePointerDown(event) {
|
|
1237
|
-
if (event.cancelable) {
|
|
1238
|
-
event.preventDefault();
|
|
1239
|
-
}
|
|
1240
|
-
if (event.pointerType === 'mouse') {
|
|
1241
|
-
const path = event.composedPath().slice(1);
|
|
1242
|
-
const objectElement = path.find(element => element.classList && element.classList.contains('object'));
|
|
1243
|
-
const object = this._core.findObjectById(objectElement?.id);
|
|
1244
|
-
const activeShape = this._core.store.activeShape;
|
|
1245
|
-
if (activeShape === null && object instanceof KritzelShape) {
|
|
1246
|
-
object.edit(event);
|
|
1247
|
-
return;
|
|
1248
|
-
}
|
|
1249
|
-
if (activeShape !== null && object instanceof KritzelShape) {
|
|
1250
|
-
activeShape.save();
|
|
1251
|
-
object.edit(event);
|
|
1252
|
-
return;
|
|
1253
|
-
}
|
|
1254
|
-
if (activeShape !== null && object instanceof KritzelShape === false) {
|
|
1255
|
-
this._core.resetActiveShape();
|
|
1256
|
-
this._core.store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('selection'));
|
|
1257
|
-
return;
|
|
1258
|
-
}
|
|
1259
|
-
if (defaultLineTool_config.KritzelEventHelper.isLeftClick(event) === false) {
|
|
1260
|
-
return;
|
|
1261
|
-
}
|
|
1262
|
-
this.startDrawing(event.clientX, event.clientY);
|
|
1263
|
-
}
|
|
1264
|
-
if (event.pointerType === 'touch') {
|
|
1265
|
-
const activePointers = Array.from(this._core.store.state.pointers.values());
|
|
1266
|
-
const path = event.composedPath().slice(1);
|
|
1267
|
-
const objectElement = path.find(element => element.classList && element.classList.contains('object'));
|
|
1268
|
-
const object = this._core.findObjectById(objectElement?.id);
|
|
1269
|
-
const activeShape = this._core.store.activeShape;
|
|
1270
|
-
if (activeShape === null && object instanceof KritzelShape) {
|
|
1271
|
-
object.edit(event);
|
|
1272
|
-
return;
|
|
1273
|
-
}
|
|
1274
|
-
if (activeShape !== null && object instanceof KritzelShape) {
|
|
1275
|
-
activeShape.save();
|
|
1276
|
-
object.edit(event);
|
|
1277
|
-
return;
|
|
1278
|
-
}
|
|
1279
|
-
if (activeShape !== null && object instanceof KritzelShape === false) {
|
|
1280
|
-
this._core.resetActiveShape();
|
|
1281
|
-
this._core.store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('selection'));
|
|
1282
|
-
return;
|
|
1283
|
-
}
|
|
1284
|
-
if (activePointers.length > 1) {
|
|
1285
|
-
return;
|
|
1286
|
-
}
|
|
1287
|
-
const clientX = Math.round(activePointers[0].clientX);
|
|
1288
|
-
const clientY = Math.round(activePointers[0].clientY);
|
|
1289
|
-
this.startDrawing(clientX, clientY);
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
handlePointerMove(event) {
|
|
1293
|
-
if (event.cancelable) {
|
|
1294
|
-
event.preventDefault();
|
|
1295
|
-
}
|
|
1296
|
-
if (!this.isDrawing || !this.currentShape) {
|
|
1297
|
-
return;
|
|
1298
|
-
}
|
|
1299
|
-
if (event.pointerType === 'mouse') {
|
|
1300
|
-
this.updateShapeSize(event.clientX, event.clientY);
|
|
1301
|
-
}
|
|
1302
|
-
if (event.pointerType === 'touch') {
|
|
1303
|
-
const activePointers = Array.from(this._core.store.state.pointers.values());
|
|
1304
|
-
if (activePointers.length === 1) {
|
|
1305
|
-
const clientX = Math.round(activePointers[0].clientX);
|
|
1306
|
-
const clientY = Math.round(activePointers[0].clientY);
|
|
1307
|
-
this.updateShapeSize(clientX, clientY);
|
|
1067
|
+
this.hasSuffixContent = newHasContent;
|
|
1308
1068
|
}
|
|
1309
1069
|
}
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
if (event.cancelable) {
|
|
1313
|
-
event.preventDefault();
|
|
1070
|
+
else if (this.hasSuffixContent !== false) {
|
|
1071
|
+
this.hasSuffixContent = false;
|
|
1314
1072
|
}
|
|
1315
|
-
|
|
1316
|
-
|
|
1073
|
+
};
|
|
1074
|
+
evaluatePrefixContent = () => {
|
|
1075
|
+
if (this.prefixSlotElement) {
|
|
1076
|
+
const newHasContent = this.prefixSlotElement.assignedNodes({ flatten: true }).length > 0;
|
|
1077
|
+
if (this.hasPrefixContent !== newHasContent) {
|
|
1078
|
+
this.hasPrefixContent = newHasContent;
|
|
1079
|
+
}
|
|
1317
1080
|
}
|
|
1318
|
-
this.
|
|
1319
|
-
|
|
1320
|
-
/**
|
|
1321
|
-
* Start drawing a shape. Following the same pattern as LineTool/BrushTool:
|
|
1322
|
-
* - Store screen coordinates for startX, startY
|
|
1323
|
-
* - Set translateX/Y to -viewportTranslateX/Y (viewport offset)
|
|
1324
|
-
* - Set x, y to the actual screen position
|
|
1325
|
-
* - Let updateDimensions() convert to world coordinates
|
|
1326
|
-
*/
|
|
1327
|
-
startDrawing(clientX, clientY) {
|
|
1328
|
-
// Store screen coordinates (relative to host element)
|
|
1329
|
-
this.startX = clientX - this._core.store.offsetX;
|
|
1330
|
-
this.startY = clientY - this._core.store.offsetY;
|
|
1331
|
-
this.isDrawing = true;
|
|
1332
|
-
// Create shape using screen coordinates, following Path/Line pattern
|
|
1333
|
-
this.currentShape = KritzelShape.create(this._core, {
|
|
1334
|
-
x: this.startX,
|
|
1335
|
-
y: this.startY,
|
|
1336
|
-
translateX: -this._core.store.state.translateX,
|
|
1337
|
-
translateY: -this._core.store.state.translateY,
|
|
1338
|
-
width: 1,
|
|
1339
|
-
height: 1,
|
|
1340
|
-
shapeType: this.shapeType,
|
|
1341
|
-
fillColor: this.fillColor,
|
|
1342
|
-
strokeColor: this.strokeColor,
|
|
1343
|
-
strokeWidth: this.strokeWidth,
|
|
1344
|
-
fontSize: this.fontSize,
|
|
1345
|
-
fontFamily: this.fontFamily,
|
|
1346
|
-
fontColor: this.fontColor,
|
|
1347
|
-
});
|
|
1348
|
-
this._core.store.state.objects.insert(this.currentShape);
|
|
1349
|
-
this._core.rerender();
|
|
1350
|
-
}
|
|
1351
|
-
/**
|
|
1352
|
-
* Update shape size during drawing. Following the same pattern as LineTool:
|
|
1353
|
-
* - Use screen coordinates directly
|
|
1354
|
-
* - The shape's x, y, width, height are all in screen space
|
|
1355
|
-
* - updateDimensions() handles conversion to world coordinates
|
|
1356
|
-
*/
|
|
1357
|
-
updateShapeSize(clientX, clientY) {
|
|
1358
|
-
if (!this.currentShape) {
|
|
1359
|
-
return;
|
|
1081
|
+
else if (this.hasPrefixContent !== false) {
|
|
1082
|
+
this.hasPrefixContent = false;
|
|
1360
1083
|
}
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
const minY = Math.min(this.startY, currentY);
|
|
1366
|
-
const width = Math.abs(currentX - this.startX);
|
|
1367
|
-
const height = Math.abs(currentY - this.startY);
|
|
1368
|
-
// Update shape with screen coordinates
|
|
1369
|
-
this.currentShape.x = minX;
|
|
1370
|
-
this.currentShape.y = minY;
|
|
1371
|
-
this.currentShape.width = Math.max(1, width);
|
|
1372
|
-
this.currentShape.height = Math.max(1, height);
|
|
1373
|
-
// Recalculate world-space translateX/Y
|
|
1374
|
-
// Reset translateX/Y to initial value before updateDimensions
|
|
1375
|
-
this.currentShape.translateX = -this._core.store.state.translateX;
|
|
1376
|
-
this.currentShape.translateY = -this._core.store.state.translateY;
|
|
1377
|
-
this.currentShape.updateDimensions();
|
|
1378
|
-
this._core.store.state.objects.update(this.currentShape);
|
|
1084
|
+
};
|
|
1085
|
+
getSelectedLabel() {
|
|
1086
|
+
const selectedOption = this.options.find(opt => opt.value === this.internalValue);
|
|
1087
|
+
return selectedOption?.label ?? '';
|
|
1379
1088
|
}
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
}
|
|
1384
|
-
// Remove shape if it's too small (likely an accidental click)
|
|
1385
|
-
// Compare in screen space
|
|
1386
|
-
if (this.currentShape.width < 10 && this.currentShape.height < 10) {
|
|
1387
|
-
const shapeId = this.currentShape.id;
|
|
1388
|
-
this._core.store.state.objects.remove(o => o.id === shapeId);
|
|
1389
|
-
}
|
|
1390
|
-
else {
|
|
1391
|
-
this.currentShape.zIndex = this._core.store.currentZIndex;
|
|
1392
|
-
this._core.store.state.objects.update(this.currentShape);
|
|
1393
|
-
this._core.engine.emitObjectsChange();
|
|
1394
|
-
this._core.selectObjects([this.currentShape]);
|
|
1395
|
-
this._core.store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('selection'));
|
|
1396
|
-
}
|
|
1397
|
-
this.isDrawing = false;
|
|
1398
|
-
this.currentShape = null;
|
|
1399
|
-
this._core.rerender();
|
|
1089
|
+
getSelectedStyle() {
|
|
1090
|
+
const selectedOption = this.options.find(opt => opt.value === this.internalValue);
|
|
1091
|
+
return selectedOption?.style;
|
|
1400
1092
|
}
|
|
1401
|
-
|
|
1093
|
+
render() {
|
|
1094
|
+
const triggerClasses = {
|
|
1095
|
+
'dropdown-trigger': true,
|
|
1096
|
+
'has-suffix-border': this.hasSuffixContent,
|
|
1097
|
+
'has-prefix-border': this.hasPrefixContent,
|
|
1098
|
+
'is-open': this.isOpen,
|
|
1099
|
+
'open-up': this.openDirection === 'up',
|
|
1100
|
+
};
|
|
1101
|
+
const menuClasses = {
|
|
1102
|
+
'dropdown-menu': true,
|
|
1103
|
+
'is-open': this.isOpen,
|
|
1104
|
+
'open-up': this.openDirection === 'up',
|
|
1105
|
+
'open-down': this.openDirection === 'down',
|
|
1106
|
+
};
|
|
1107
|
+
return (index.h(index.Host, { key: '29d076eb2ef76527c0930ab82ace0d05c896ab6c' }, index.h("div", { key: '1afac5cc0b7f408849670b8cb62fe0bd0f3b27f1', class: "dropdown-wrapper", ref: el => (this.wrapperElement = el) }, index.h("slot", { key: '3cfcf787c3b3eedbd6bf30c7506a0a4912429672', name: "prefix", ref: el => (this.prefixSlotElement = el), onSlotchange: this.evaluatePrefixContent }), index.h("div", { key: 'b88120ed3e44871220e6ba61e8bef457651a2086', class: "dropdown-container", style: { width: this.width } }, index.h("button", { key: '79082189066f3d0b4f5797420ec222847792fe52', type: "button", class: triggerClasses, style: { ...this.selectStyles, ...this.getSelectedStyle() }, onClick: this.toggleMenu, onKeyDown: this.handleTriggerKeyDown, "aria-haspopup": "listbox", "aria-expanded": this.isOpen ? 'true' : 'false', ref: el => (this.triggerElement = el) }, index.h("span", { key: 'a490bb6689ec1820144fe82f6833bee82e6ead0e', class: "dropdown-trigger-label" }, this.getSelectedLabel()), index.h("span", { key: '8bd7768f6fdd3c507bbca54d7d135adabe04901f', class: "dropdown-trigger-arrow", "aria-hidden": "true" }, index.h("svg", { key: 'e1b854d2c93e3067181108f8d782e1393ddb615c', xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("polyline", { key: '3622cbf8964f4e50aa55be5209240dfd252f1d84', points: "6 9 12 15 18 9" }))))), index.h("slot", { key: 'b91317736904cbeee0f87058b822bd77c6b163ca', name: "suffix", ref: el => (this.suffixSlotElement = el), onSlotchange: this.evaluateSuffixContent }), index.h("ul", { key: '0ca8690345974e9b7ad184f4c7ab7cf5367b183c', class: menuClasses, role: "listbox", tabindex: "-1", onKeyDown: this.handleMenuKeyDown, ref: el => (this.menuElement = el) }, this.options.map((option, index$1) => {
|
|
1108
|
+
const isSelected = option.value === this.internalValue;
|
|
1109
|
+
const isFocused = index$1 === this.focusedIndex;
|
|
1110
|
+
const optionClasses = {
|
|
1111
|
+
'dropdown-option': true,
|
|
1112
|
+
'is-selected': isSelected,
|
|
1113
|
+
'is-focused': isFocused,
|
|
1114
|
+
};
|
|
1115
|
+
return (index.h("li", { class: optionClasses, role: "option", "aria-selected": isSelected ? 'true' : 'false', style: option.style, onClick: () => this.selectOption(option), onMouseEnter: () => this.handleOptionMouseEnter(index$1) }, option.label, isSelected && (index.h("span", { class: "dropdown-option-check", "aria-hidden": "true" }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("polyline", { points: "20 6 9 17 4 12" }))))));
|
|
1116
|
+
})))));
|
|
1117
|
+
}
|
|
1118
|
+
static get watchers() { return {
|
|
1119
|
+
"options": [{
|
|
1120
|
+
"optionsChanged": 0
|
|
1121
|
+
}],
|
|
1122
|
+
"value": [{
|
|
1123
|
+
"externalValueChanged": 0
|
|
1124
|
+
}]
|
|
1125
|
+
}; }
|
|
1126
|
+
};
|
|
1127
|
+
KritzelDropdown.style = kritzelDropdownCss();
|
|
1402
1128
|
|
|
1403
1129
|
const DEFAULT_SHAPE_CONFIG = {
|
|
1404
|
-
shapeType: ShapeType.Rectangle,
|
|
1130
|
+
shapeType: defaultLineTool_config.ShapeType.Rectangle,
|
|
1405
1131
|
fillColor: 'transparent',
|
|
1406
1132
|
strokeColor: '#000000',
|
|
1407
1133
|
strokeWidth: 4,
|
|
1408
1134
|
fontColor: '#000000',
|
|
1409
1135
|
fontSize: 16,
|
|
1410
1136
|
fontFamily: 'Arial',
|
|
1411
|
-
palette: [
|
|
1412
|
-
'#000000',
|
|
1413
|
-
'#ff5252',
|
|
1414
|
-
'#ffbc00',
|
|
1415
|
-
'#00c853',
|
|
1416
|
-
'#0000FF',
|
|
1417
|
-
'#d500f9',
|
|
1418
|
-
'#fafafa',
|
|
1419
|
-
'#a52714',
|
|
1420
|
-
'#ee8100',
|
|
1421
|
-
'#558b2f',
|
|
1422
|
-
'#01579b',
|
|
1423
|
-
'#8e24aa',
|
|
1424
|
-
'#90a4ae',
|
|
1425
|
-
],
|
|
1137
|
+
palette: [...defaultLineTool_config.DEFAULT_COLOR_PALETTE],
|
|
1426
1138
|
};
|
|
1427
1139
|
|
|
1428
1140
|
const ABSOLUTE_SCALE_MAX = 1000;
|
|
@@ -1482,9 +1194,9 @@ const KritzelEditor = class {
|
|
|
1482
1194
|
icon: 'shape-rectangle',
|
|
1483
1195
|
config: DEFAULT_SHAPE_CONFIG,
|
|
1484
1196
|
subOptions: [
|
|
1485
|
-
{ id: 'rectangle', icon: 'shape-rectangle', label: 'Rectangle', value: ShapeType.Rectangle, toolProperty: 'shapeType' },
|
|
1486
|
-
{ id: 'ellipse', icon: 'shape-ellipse', label: 'Ellipse', value: ShapeType.Ellipse, toolProperty: 'shapeType' },
|
|
1487
|
-
{ id: 'triangle', icon: 'shape-triangle', label: 'Triangle', value: ShapeType.Triangle, toolProperty: 'shapeType' },
|
|
1197
|
+
{ id: 'rectangle', icon: 'shape-rectangle', label: 'Rectangle', value: defaultLineTool_config.ShapeType.Rectangle, toolProperty: 'shapeType' },
|
|
1198
|
+
{ id: 'ellipse', icon: 'shape-ellipse', label: 'Ellipse', value: defaultLineTool_config.ShapeType.Ellipse, toolProperty: 'shapeType' },
|
|
1199
|
+
{ id: 'triangle', icon: 'shape-triangle', label: 'Triangle', value: defaultLineTool_config.ShapeType.Triangle, toolProperty: 'shapeType' },
|
|
1488
1200
|
],
|
|
1489
1201
|
},
|
|
1490
1202
|
{
|
|
@@ -1684,7 +1396,7 @@ const KritzelEditor = class {
|
|
|
1684
1396
|
}
|
|
1685
1397
|
}
|
|
1686
1398
|
render() {
|
|
1687
|
-
return (index.h(index.Host, { key: '
|
|
1399
|
+
return (index.h(index.Host, { key: '46500c70e4c5321532eddc7f6aa96210c0fe73c8' }, index.h("kritzel-workspace-manager", { key: '70f780b4d42281c6c37b3fd16acab1541cc84ee1', workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), index.h("kritzel-engine", { key: 'a4906f8ac2d42126a4e55ad7c16697aca25763fb', ref: el => (this.engineRef = el), workspace: this.activeWorkspace, syncConfig: this.syncConfig, scaleMax: this.scaleMax, scaleMin: this.scaleMin, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.handleWorkspacesChange(event), onObjectsChange: event => this.handleObjectsChange(event), onUndoStateChange: event => this.handleUndoStateChange(event) }), index.h("kritzel-controls", { key: '4d08c06fa2c6e4f5c3c75c5e5a60bddb61083b98', class: { 'keyboard-open': this.isVirtualKeyboardOpen }, style: { display: this.isControlsVisible ? 'flex' : 'none' }, ref: el => (this.controlsRef = el), controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState, onIsControlsReady: () => (this.isControlsReady = true) })));
|
|
1688
1400
|
}
|
|
1689
1401
|
static get watchers() { return {
|
|
1690
1402
|
"isEngineReady": [{
|
|
@@ -18915,6 +18627,11 @@ class KritzelViewport {
|
|
|
18915
18627
|
_core;
|
|
18916
18628
|
_debounceUpdate;
|
|
18917
18629
|
_debounceEndScaling;
|
|
18630
|
+
_velocityX = 0;
|
|
18631
|
+
_velocityY = 0;
|
|
18632
|
+
_panRafId = null;
|
|
18633
|
+
_friction = 0.92;
|
|
18634
|
+
_minVelocity = 0.5;
|
|
18918
18635
|
initialTouchDistance = 0;
|
|
18919
18636
|
startX = 0;
|
|
18920
18637
|
startY = 0;
|
|
@@ -19098,12 +18815,47 @@ class KritzelViewport {
|
|
|
19098
18815
|
this._debounceEndScaling();
|
|
19099
18816
|
}
|
|
19100
18817
|
handlePan(event) {
|
|
18818
|
+
// Normalize delta for trackpad vs mouse wheel
|
|
18819
|
+
// WheelEvent.deltaMode: 0=pixels, 1=lines, 2=pages
|
|
18820
|
+
let deltaX = event.deltaX;
|
|
18821
|
+
let deltaY = event.deltaY;
|
|
18822
|
+
if (event.deltaMode === 1) {
|
|
18823
|
+
deltaX *= 16;
|
|
18824
|
+
deltaY *= 16;
|
|
18825
|
+
}
|
|
18826
|
+
else if (event.deltaMode === 2) {
|
|
18827
|
+
deltaX *= window.innerWidth;
|
|
18828
|
+
deltaY *= window.innerHeight;
|
|
18829
|
+
}
|
|
19101
18830
|
const panSpeed = 0.8;
|
|
19102
|
-
|
|
19103
|
-
this.
|
|
18831
|
+
// Add to velocity for momentum effect
|
|
18832
|
+
this._velocityX = -deltaX * panSpeed;
|
|
18833
|
+
this._velocityY = -deltaY * panSpeed;
|
|
18834
|
+
// Start animation loop if not already running
|
|
18835
|
+
if (this._panRafId === null) {
|
|
18836
|
+
this._animatePan();
|
|
18837
|
+
}
|
|
18838
|
+
}
|
|
18839
|
+
_animatePan() {
|
|
18840
|
+
// Apply current velocity
|
|
18841
|
+
this._core.store.state.translateX += this._velocityX;
|
|
18842
|
+
this._core.store.state.translateY += this._velocityY;
|
|
19104
18843
|
this._core.store.state.hasViewportChanged = true;
|
|
19105
18844
|
this._core.rerender();
|
|
19106
|
-
|
|
18845
|
+
// Apply friction to slow down
|
|
18846
|
+
this._velocityX *= this._friction;
|
|
18847
|
+
this._velocityY *= this._friction;
|
|
18848
|
+
// Continue animation if velocity is still significant
|
|
18849
|
+
if (Math.abs(this._velocityX) > this._minVelocity || Math.abs(this._velocityY) > this._minVelocity) {
|
|
18850
|
+
this._panRafId = requestAnimationFrame(() => this._animatePan());
|
|
18851
|
+
}
|
|
18852
|
+
else {
|
|
18853
|
+
// Stop animation and finalize
|
|
18854
|
+
this._velocityX = 0;
|
|
18855
|
+
this._velocityY = 0;
|
|
18856
|
+
this._panRafId = null;
|
|
18857
|
+
this._debounceUpdate();
|
|
18858
|
+
}
|
|
19107
18859
|
}
|
|
19108
18860
|
}
|
|
19109
18861
|
|
|
@@ -19368,7 +19120,7 @@ class KritzelReviver {
|
|
|
19368
19120
|
revivedObj = defaultLineTool_config.KritzelText.create(this._core, obj.fontSize, obj.fontFamily).deserialize(obj);
|
|
19369
19121
|
break;
|
|
19370
19122
|
case 'KritzelShape':
|
|
19371
|
-
revivedObj = KritzelShape.create(this._core, {
|
|
19123
|
+
revivedObj = defaultLineTool_config.KritzelShape.create(this._core, {
|
|
19372
19124
|
shapeType: obj.shapeType,
|
|
19373
19125
|
fillColor: obj.fillColor,
|
|
19374
19126
|
strokeColor: obj.strokeColor,
|
|
@@ -19890,7 +19642,7 @@ class KritzelStore {
|
|
|
19890
19642
|
return activeTexts.length > 0 ? activeTexts[0] : null;
|
|
19891
19643
|
}
|
|
19892
19644
|
get activeShape() {
|
|
19893
|
-
const activeShapes = this._state.objects.filter(o => o instanceof KritzelShape && o.isEditing);
|
|
19645
|
+
const activeShapes = this._state.objects.filter(o => o instanceof defaultLineTool_config.KritzelShape && o.isEditing);
|
|
19894
19646
|
return activeShapes.length > 0 ? activeShapes[0] : null;
|
|
19895
19647
|
}
|
|
19896
19648
|
get currentPath() {
|
|
@@ -20258,11 +20010,13 @@ class KritzelCore {
|
|
|
20258
20010
|
this.removeSelectionGroup();
|
|
20259
20011
|
this.removeSelectionBox();
|
|
20260
20012
|
this._store.state.objects.insert(selectionGroup);
|
|
20013
|
+
this._kritzelEngine.triggerSelectionChange();
|
|
20261
20014
|
}
|
|
20262
20015
|
removeSelectionGroup() {
|
|
20263
20016
|
const selectionGroup = this._store.selectionGroup;
|
|
20264
20017
|
if (selectionGroup) {
|
|
20265
20018
|
this._store.state.objects.remove(object => object.id === selectionGroup.id);
|
|
20019
|
+
this._kritzelEngine.triggerSelectionChange();
|
|
20266
20020
|
}
|
|
20267
20021
|
}
|
|
20268
20022
|
removeSelectionBox() {
|
|
@@ -20804,11 +20558,15 @@ const KritzelEngine = class {
|
|
|
20804
20558
|
}
|
|
20805
20559
|
isEngineReady;
|
|
20806
20560
|
activeToolChange;
|
|
20561
|
+
objectsSelectionChange;
|
|
20807
20562
|
workspacesChange;
|
|
20808
20563
|
longpress;
|
|
20809
20564
|
objectsChange;
|
|
20810
20565
|
undoStateChange;
|
|
20811
20566
|
forceUpdate = 0;
|
|
20567
|
+
async triggerSelectionChange() {
|
|
20568
|
+
this.objectsSelectionChange.emit();
|
|
20569
|
+
}
|
|
20812
20570
|
throttledWheel = lodashExports.throttle((ev) => {
|
|
20813
20571
|
this.viewport.handleWheel(ev);
|
|
20814
20572
|
this.core.store.state?.activeTool?.handleWheel(ev);
|
|
@@ -20924,6 +20682,9 @@ const KritzelEngine = class {
|
|
|
20924
20682
|
return Promise.resolve(registeredTool);
|
|
20925
20683
|
}
|
|
20926
20684
|
async changeActiveTool(tool) {
|
|
20685
|
+
if (this.core.store.state.activeTool === tool) {
|
|
20686
|
+
return;
|
|
20687
|
+
}
|
|
20927
20688
|
this.core.store.state.activeTool?.onDeactivate();
|
|
20928
20689
|
this.core.store.setState('activeTool', tool);
|
|
20929
20690
|
this.core.deselectAllObjects();
|
|
@@ -21066,6 +20827,7 @@ const KritzelEngine = class {
|
|
|
21066
20827
|
index.registerInstance(this, hostRef);
|
|
21067
20828
|
this.isEngineReady = index.createEvent(this, "isEngineReady");
|
|
21068
20829
|
this.activeToolChange = index.createEvent(this, "activeToolChange");
|
|
20830
|
+
this.objectsSelectionChange = index.createEvent(this, "objectsSelectionChange");
|
|
21069
20831
|
this.workspacesChange = index.createEvent(this, "workspacesChange");
|
|
21070
20832
|
this.longpress = index.createEvent(this, "longpress");
|
|
21071
20833
|
this.objectsChange = index.createEvent(this, "objectsChange");
|
|
@@ -21146,7 +20908,7 @@ const KritzelEngine = class {
|
|
|
21146
20908
|
};
|
|
21147
20909
|
const visibleObjects = this.core.store.state.objects.query(viewportBounds).sort((a, b) => a.zIndex - b.zIndex);
|
|
21148
20910
|
this.core.cursorManager.applyCursor();
|
|
21149
|
-
return (index.h(index.Host, { key: '
|
|
20911
|
+
return (index.h(index.Host, { key: '49fbba9ba7044acb82cb23627bf08435f8683b80' }, this.core.store.state.debugInfo.showViewportInfo && (index.h("div", { key: '7e18e66bdbae71ec35a6ea14bfdcd735e537a37b', class: "debug-panel" }, index.h("div", { key: '562ff35d3803b80f3c02c075741f1c4b81ba0739' }, "ActiveWorkspaceId: ", this.core.store.state?.activeWorkspace?.id), index.h("div", { key: '82d08ac0527017c9f3674e1d551a071b0002477e' }, "ActiveWorkspaceName: ", this.core.store.state?.activeWorkspace?.name), index.h("div", { key: 'e4e3b8c6f18714dbf141a900768b2fb78ef8ec3a' }, "TranslateX: ", this.core.store.state?.translateX), index.h("div", { key: '68823a22db98800c7ec7b18770f38f03dd53f826' }, "TranslateY: ", this.core.store.state?.translateY), index.h("div", { key: '4683676eca0796b927ac8c10fe9ea48770366ee5' }, "ViewportWidth: ", this.core.store.state?.viewportWidth), index.h("div", { key: 'fcbd728c4483f06cffe1e9d581399a9619b3c172' }, "ViewportHeight: ", this.core.store.state?.viewportHeight), index.h("div", { key: 'f713005a414bd05b187327b5ffa021c51f227d97' }, "PointerCount: ", this.core.store.state.pointers.size), index.h("div", { key: 'fdb4892c0b5df0a599d4e457d656ca8e71086033' }, "Scale: ", this.core.store.state?.scale), index.h("div", { key: '7c1ceb6398ceccb891d5854a731467771d88e688' }, "ActiveTool: ", this.core.store.state?.activeTool?.name), index.h("div", { key: 'fddfb8b396ab095dd99158b32bf4c9a06745c65f' }, "HasViewportChanged: ", this.core.store.state?.hasViewportChanged ? 'true' : 'false'), index.h("div", { key: '8b807879e83bada98ff44a9124dddc7e7f8d8516' }, "IsEnabled: ", this.core.store.state?.isEnabled ? 'true' : 'false'), index.h("div", { key: '93827fa7bf4c27db8b3165a1d2be5d0cde5a65b6' }, "IsScaling: ", this.core.store.state?.isScaling ? 'true' : 'false'), index.h("div", { key: '923455fb261bc9aa8d6cd22c74894e41dc6a2f93' }, "IsPanning: ", this.core.store.state?.isPanning ? 'true' : 'false'), index.h("div", { key: '33579a767be0a80bed4a177da9577e6304d4900c' }, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), index.h("div", { key: '950c340bf725d7c8c92a51c61066c1aa7d09aa41' }, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), index.h("div", { key: '2a8ce1e6d68ea030f42521b25615bf60a1a8267e' }, "IsResizeHandleSelected: ", this.core.store.state.isResizeHandleSelected ? 'true' : 'false'), index.h("div", { key: '9fd5a4b1a842c9aa178dc98dc9a210cf7d947615' }, "IsRotationHandleSelected: ", this.core.store.state.isRotationHandleSelected ? 'true' : 'false'), index.h("div", { key: '81f9c6f9f5c38b48db1faaa8da08476cd747e906' }, "IsRotationHandleHovered: ", this.core.store.state.isRotationHandleHovered ? 'true' : 'false'), index.h("div", { key: 'bbea182105ab1f1856d8ffe7ee6dae2c96cefbae' }, "IsDrawing: ", this.core.store.state.isDrawing ? 'true' : 'false'), index.h("div", { key: '0e57b3b517fc6f4780a6bf8b13a18e7d595e2e91' }, "IsWriting: ", this.core.store.state.isWriting ? 'true' : 'false'), index.h("div", { key: '5be12fd92b4ccb6890680e725aea0f29fa16eda4' }, "IsPointerDown: ", this.core.store.isPointerDown ? 'true' : 'false'), index.h("div", { key: '51402f4730b8e482ee534bb83944c50462d895af' }, "PointerX: ", this.core.store.state?.pointerX), index.h("div", { key: 'dddf5bed76a1755aec71ae7f30eab8dd0c39fdb0' }, "PointerY: ", this.core.store.state?.pointerY), index.h("div", { key: '367166d068f34090eb895116d8ac1ddd3ab5aaad' }, "SelectedObjects: ", this.core.store.selectionGroup?.objects.length || 0), index.h("div", { key: 'e88d10e302e4ff3e8cb877a509a883e2cffcc067' }, "ViewportCenter: (", viewportCenterX.toFixed(2), ", ", viewportCenterY.toFixed(2), ")"))), index.h("div", { key: '12bf294a8640947230611690f71b8c8116e861f4', id: "origin", class: "origin", style: {
|
|
21150
20912
|
transform: `matrix(${this.core.store.state?.scale}, 0, 0, ${this.core.store.state?.scale}, ${this.core.store.state?.translateX}, ${this.core.store.state?.translateY})`,
|
|
21151
20913
|
} }, visibleObjects?.map(object => {
|
|
21152
20914
|
return (index.h("div", { key: object.id, style: {
|
|
@@ -21395,7 +21157,7 @@ const KritzelEngine = class {
|
|
|
21395
21157
|
stroke: 'var(--kritzel-snap-indicator-stroke, #007bff)',
|
|
21396
21158
|
strokeWidth: data.indicatorStrokeWidth,
|
|
21397
21159
|
} }))));
|
|
21398
|
-
})()), this.core.store.state.isContextMenuVisible && (index.h("kritzel-context-menu", { key: '
|
|
21160
|
+
})()), this.core.store.state.isContextMenuVisible && (index.h("kritzel-context-menu", { key: '9d17520994c59b7eca2940d1a05f4f150b790767', class: "context-menu", ref: el => (this.contextMenuElement = el), items: this.core.store.state.contextMenuItems, objects: this.core.store.selectionGroup?.objects || [], style: {
|
|
21399
21161
|
position: 'fixed',
|
|
21400
21162
|
left: `${this.core.store.state.contextMenuX}px`,
|
|
21401
21163
|
top: `${this.core.store.state.contextMenuY}px`,
|
|
@@ -21406,7 +21168,7 @@ const KritzelEngine = class {
|
|
|
21406
21168
|
y: (-this.core.store.state.translateY + this.core.store.state.contextMenuY) / this.core.store.state.scale,
|
|
21407
21169
|
}, this.core.store.selectionGroup?.objects);
|
|
21408
21170
|
this.hideContextMenu();
|
|
21409
|
-
}, onClose: () => this.hideContextMenu() })), this.core.store.state?.activeTool instanceof defaultLineTool_config.KritzelEraserTool && !this.core.store.state.isScaling && index.h("kritzel-cursor-trail", { key: '
|
|
21171
|
+
}, onClose: () => this.hideContextMenu() })), this.core.store.state?.activeTool instanceof defaultLineTool_config.KritzelEraserTool && !this.core.store.state.isScaling && index.h("kritzel-cursor-trail", { key: 'b86989f2a710324e420994f74bd8c4990cc52060', core: this.core })));
|
|
21410
21172
|
}
|
|
21411
21173
|
static get watchers() { return {
|
|
21412
21174
|
"workspace": [{
|
|
@@ -21435,7 +21197,7 @@ const KritzelFont = class {
|
|
|
21435
21197
|
size = 24;
|
|
21436
21198
|
color = '#000000';
|
|
21437
21199
|
render() {
|
|
21438
|
-
return (index.h(index.Host, { key: '
|
|
21200
|
+
return (index.h(index.Host, { key: '47e1580b093d5c9039a5bc1a7764e345afb7700b' }, index.h("div", { key: '1d6d36e895ab4e1fd76383b0847f81918e14dbb0', class: "font-preview", style: {
|
|
21439
21201
|
fontFamily: this.fontFamily,
|
|
21440
21202
|
fontSize: `${this.size}px`,
|
|
21441
21203
|
color: this.color
|
|
@@ -21444,7 +21206,7 @@ const KritzelFont = class {
|
|
|
21444
21206
|
};
|
|
21445
21207
|
KritzelFont.style = kritzelFontCss();
|
|
21446
21208
|
|
|
21447
|
-
const kritzelFontFamilyCss = () => `:host{display:flex;align-items:flex-start;gap:8px;padding:
|
|
21209
|
+
const kritzelFontFamilyCss = () => `:host{display:flex;align-items:flex-start;gap:8px;padding:0;box-sizing:border-box;width:100%}.font-style-button{display:flex;justify-content:center;align-items:center;width:42px;height:32px;padding:0;border:none;outline:none;background:none;cursor:var(--kritzel-pointer-cursor, pointer);border-radius:0;color:var(--control-text-color);font-weight:bold;-webkit-tap-highlight-color:transparent}.font-style-button:not(:last-child){border-right:1px solid #333333}.font-style-button:hover{background-color:var(--control-hover-bg)}.font-style-button:active{background-color:var(--control-active-bg)}.font-style-button.selected,.font-style-button.selected:hover,.font-style-button.selected:active{background-color:var(--control-selected-bg);color:var(--control-selected-color)}.font-style-button.italic-text{font-style:italic}`;
|
|
21448
21210
|
|
|
21449
21211
|
const KritzelFontFamily = class {
|
|
21450
21212
|
constructor(hostRef) {
|
|
@@ -21487,7 +21249,7 @@ const KritzelFontFamily = class {
|
|
|
21487
21249
|
};
|
|
21488
21250
|
KritzelFontFamily.style = kritzelFontFamilyCss();
|
|
21489
21251
|
|
|
21490
|
-
const kritzelFontSizeCss = () => `:host{display:flex;align-items:flex-start;gap:8px;padding:
|
|
21252
|
+
const kritzelFontSizeCss = () => `:host{display:flex;align-items:flex-start;gap:8px;padding:0;box-sizing:border-box}.size-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:4px;cursor:var(--kritzel-pointer-cursor, pointer);border:2px solid transparent;box-sizing:border-box;border-radius:50%}.size-container:hover{background-color:var(--kritzel-font-size-hover-background-color, #ebebeb)}.size-container.selected{border-color:var(--kritzel-selection-border-color, #007AFF);background-color:var(--kritzel-font-size-selected-background-color, #e0e0e0)}`;
|
|
21491
21253
|
|
|
21492
21254
|
const KritzelFontSize = class {
|
|
21493
21255
|
constructor(hostRef) {
|
|
@@ -21509,7 +21271,7 @@ const KritzelFontSize = class {
|
|
|
21509
21271
|
}
|
|
21510
21272
|
}
|
|
21511
21273
|
render() {
|
|
21512
|
-
return (index.h(index.Host, { key: '
|
|
21274
|
+
return (index.h(index.Host, { key: 'ea8461f3b921c6adec6360ffcca69832a30e5808' }, this.sizes.map(size => (index.h("div", { tabIndex: 0, class: {
|
|
21513
21275
|
'size-container': true,
|
|
21514
21276
|
'selected': this.selectedSize === size,
|
|
21515
21277
|
}, onClick: () => this.handleSizeClick(size), onKeyDown: event => this.handleKeyDown(event, size) }, index.h("kritzel-font", { fontFamily: this.fontFamily, size: size }))))));
|
|
@@ -21541,6 +21303,91 @@ const KritzelIcon = class {
|
|
|
21541
21303
|
};
|
|
21542
21304
|
KritzelIcon.style = kritzelIconCss();
|
|
21543
21305
|
|
|
21306
|
+
const kritzelLineEndingsCss = () => `:host{display:flex;flex-direction:column;gap:12px;padding:0;box-sizing:border-box}.endings-section{display:flex;flex-direction:column;gap:6px}.section-label{font-size:12px;font-weight:500;color:var(--kritzel-line-endings-label-color, #666666);padding-left:4px}.endings-row{display:flex;align-items:center;gap:4px}.ending-option{display:flex;justify-content:center;align-items:center;width:48px;height:32px;border-radius:6px;cursor:var(--kritzel-pointer-cursor, pointer);border:2px solid transparent;box-sizing:border-box;background:var(--kritzel-line-endings-option-background, #ffffff);padding:4px;transition:background-color 0.15s ease, border-color 0.15s ease}.ending-option:hover{background-color:var(--kritzel-line-endings-hover-background-color, #ebebeb)}.ending-option.selected{border-color:var(--kritzel-selection-border-color, #007AFF);background-color:var(--kritzel-line-endings-selected-background-color, #ebebeb)}.ending-option:focus{outline:none;box-shadow:0 0 0 2px var(--kritzel-focus-ring-color, rgba(0, 122, 255, 0.3))}.ending-icon{width:100%;height:100%}`;
|
|
21307
|
+
|
|
21308
|
+
const KritzelLineEndings = class {
|
|
21309
|
+
constructor(hostRef) {
|
|
21310
|
+
index.registerInstance(this, hostRef);
|
|
21311
|
+
this.valueChange = index.createEvent(this, "valueChange");
|
|
21312
|
+
}
|
|
21313
|
+
/** Available ending styles */
|
|
21314
|
+
styles = ['none', 'triangle'];
|
|
21315
|
+
/** Current line arrow configuration */
|
|
21316
|
+
value;
|
|
21317
|
+
/** Stroke color used for rendering the preview */
|
|
21318
|
+
strokeColor = '#000000';
|
|
21319
|
+
valueChange;
|
|
21320
|
+
getStartEnding() {
|
|
21321
|
+
if (!this.value?.start?.enabled)
|
|
21322
|
+
return 'none';
|
|
21323
|
+
return this.value.start.style ?? 'triangle';
|
|
21324
|
+
}
|
|
21325
|
+
getEndEnding() {
|
|
21326
|
+
if (!this.value?.end?.enabled)
|
|
21327
|
+
return 'none';
|
|
21328
|
+
return this.value.end.style ?? 'triangle';
|
|
21329
|
+
}
|
|
21330
|
+
handleStartChange(type) {
|
|
21331
|
+
const newValue = {
|
|
21332
|
+
...this.value,
|
|
21333
|
+
start: type === 'none'
|
|
21334
|
+
? { enabled: false }
|
|
21335
|
+
: { enabled: true, style: type },
|
|
21336
|
+
};
|
|
21337
|
+
this.value = newValue;
|
|
21338
|
+
this.valueChange.emit(newValue);
|
|
21339
|
+
}
|
|
21340
|
+
handleEndChange(type) {
|
|
21341
|
+
const newValue = {
|
|
21342
|
+
...this.value,
|
|
21343
|
+
end: type === 'none'
|
|
21344
|
+
? { enabled: false }
|
|
21345
|
+
: { enabled: true, style: type },
|
|
21346
|
+
};
|
|
21347
|
+
this.value = newValue;
|
|
21348
|
+
this.valueChange.emit(newValue);
|
|
21349
|
+
}
|
|
21350
|
+
getEndingPath(type) {
|
|
21351
|
+
switch (type) {
|
|
21352
|
+
case 'triangle':
|
|
21353
|
+
return 'M 0 0 L 10 5 L 0 10 Z';
|
|
21354
|
+
case 'open':
|
|
21355
|
+
return 'M 0 0 L 10 5 L 0 10';
|
|
21356
|
+
case 'diamond':
|
|
21357
|
+
return 'M 0 5 L 5 0 L 10 5 L 5 10 Z';
|
|
21358
|
+
case 'circle':
|
|
21359
|
+
return 'M 10 5 A 5 5 0 1 1 0 5 A 5 5 0 1 1 10 5 Z';
|
|
21360
|
+
default:
|
|
21361
|
+
return '';
|
|
21362
|
+
}
|
|
21363
|
+
}
|
|
21364
|
+
renderEndingIcon(type, isStart) {
|
|
21365
|
+
const color = '#000000';
|
|
21366
|
+
if (type === 'none') {
|
|
21367
|
+
return (index.h("svg", { viewBox: "0 0 24 12", class: "ending-icon" }, index.h("line", { x1: isStart ? 4 : 2, y1: "6", x2: isStart ? 22 : 20, y2: "6", stroke: color, "stroke-width": "2", "stroke-linecap": "round" })));
|
|
21368
|
+
}
|
|
21369
|
+
const path = this.getEndingPath(type);
|
|
21370
|
+
const isOpenStyle = type === 'open';
|
|
21371
|
+
return (index.h("svg", { viewBox: "0 0 24 12", class: "ending-icon" }, isStart ? (
|
|
21372
|
+
// Start arrow points left
|
|
21373
|
+
index.h("g", null, index.h("line", { x1: "12", y1: "6", x2: "22", y2: "6", stroke: color, "stroke-width": "2", "stroke-linecap": "round" }), index.h("g", { transform: "translate(2, 1) scale(1, 1)" }, index.h("path", { d: path, fill: isOpenStyle ? 'none' : color, stroke: color, "stroke-width": isOpenStyle ? 2 : 0, "stroke-linecap": "round", "stroke-linejoin": "round", transform: "scale(-1, 1) translate(-10, 0)" })))) : (
|
|
21374
|
+
// End arrow points right
|
|
21375
|
+
index.h("g", null, index.h("line", { x1: "2", y1: "6", x2: "12", y2: "6", stroke: color, "stroke-width": "2", "stroke-linecap": "round" }), index.h("g", { transform: "translate(12, 1)" }, index.h("path", { d: path, fill: isOpenStyle ? 'none' : color, stroke: color, "stroke-width": isOpenStyle ? 2 : 0, "stroke-linecap": "round", "stroke-linejoin": "round" }))))));
|
|
21376
|
+
}
|
|
21377
|
+
render() {
|
|
21378
|
+
const startEnding = this.getStartEnding();
|
|
21379
|
+
const endEnding = this.getEndEnding();
|
|
21380
|
+
return (index.h(index.Host, { key: '395c2c7e54986d9edffe7b1329361d9e0727d086' }, index.h("div", { key: '9f29cb35182b74d73fe82a89f91be42da3e43d3f', class: "endings-section" }, index.h("div", { key: '61f3e2bc9e3c2739e241213e68af71dd1091774e', class: "endings-row" }, this.styles.map(type => (index.h("button", { class: {
|
|
21381
|
+
'ending-option': true,
|
|
21382
|
+
'selected': startEnding === type,
|
|
21383
|
+
}, onClick: () => this.handleStartChange(type), title: type === 'none' ? 'No start arrow' : `${type} start arrow` }, this.renderEndingIcon(type, true)))))), index.h("div", { key: '1e39f687277ebdd0786f56b9be40101df42495d2', class: "endings-section" }, index.h("div", { key: 'fbe2ea8393cbf82b7c7aff7d6d8ca16abab1020a', class: "endings-row" }, this.styles.map(type => (index.h("button", { class: {
|
|
21384
|
+
'ending-option': true,
|
|
21385
|
+
'selected': endEnding === type,
|
|
21386
|
+
}, onClick: () => this.handleEndChange(type), title: type === 'none' ? 'No end arrow' : `${type} end arrow` }, this.renderEndingIcon(type, false))))))));
|
|
21387
|
+
}
|
|
21388
|
+
};
|
|
21389
|
+
KritzelLineEndings.style = kritzelLineEndingsCss();
|
|
21390
|
+
|
|
21544
21391
|
const kritzelMenuCss = () => `:host{position:relative;display:flex;flex-direction:column;background-color:var(--kritzel-menu-background-color, #ffffff);width:var(--kritzel-menu-width, 200px);padding:var(--kritzel-menu-padding, 8px);border-radius:var(--kritzel-menu-border-radius, 12px);box-shadow:var(--kritzel-menu-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-menu-border, 1px solid #ebebeb);z-index:2;gap:var(--kritzel-menu-gap, 4px);overflow-y:auto;scrollbar-color:#ebebeb transparent;scrollbar-width:thin;max-height:var(--kritzel-portal-max-height, 300px);box-sizing:border-box}.has-open-child-overlay{position:absolute;top:0;left:0;right:0;bottom:0;z-index:3}`;
|
|
21545
21392
|
|
|
21546
21393
|
const KritzelMenu = class {
|
|
@@ -21604,7 +21451,7 @@ const KritzelMenu = class {
|
|
|
21604
21451
|
this.itemCloseChildMenu.emit(event.detail);
|
|
21605
21452
|
};
|
|
21606
21453
|
render() {
|
|
21607
|
-
return (index.h(index.Host, { key: '
|
|
21454
|
+
return (index.h(index.Host, { key: '7143a116ad361651851491bce048901d6c0a02a0', tabIndex: 0, onClick: e => e.stopPropagation() }, this.openChildMenuItem && index.h("div", { key: '8a5524ca7516955e1be34d10b8495c7b40ac05dd', class: "has-open-child-overlay", onClick: this.onOverlayClick }), this.items.map(item => (index.h("kritzel-menu-item", { key: item.id, item: item, parent: this.parent, style: { pointerEvents: this.editingMenuItem && !item.isEditing ? 'none' : 'auto' }, onItemSelect: this.handleItemSelect, onItemSave: this.handleSave, onItemCancel: this.handleCancel, onItemToggleChildMenu: this.handleToggleChildMenu, onItemCloseChildMenu: this.handleCloseChildMenu })))));
|
|
21608
21455
|
}
|
|
21609
21456
|
};
|
|
21610
21457
|
KritzelMenu.style = kritzelMenuCss();
|
|
@@ -21705,12 +21552,12 @@ const KritzelMenuItem = class {
|
|
|
21705
21552
|
];
|
|
21706
21553
|
}
|
|
21707
21554
|
render() {
|
|
21708
|
-
return (index.h(index.Host, { key: '
|
|
21555
|
+
return (index.h(index.Host, { key: '59a53dc472dd624f78dd773eb20a8722720ed465', tabIndex: this.item.isDisabled ? -1 : 0, class: {
|
|
21709
21556
|
'selected': this.item.isSelected,
|
|
21710
21557
|
'editing': this.item.isEditing,
|
|
21711
21558
|
'disabled': this.item.isDisabled,
|
|
21712
21559
|
'child-open': this.item.isChildMenuOpen,
|
|
21713
|
-
}, onClick: this.handleItemSelect }, index.h("div", { key: '
|
|
21560
|
+
}, onClick: this.handleItemSelect }, index.h("div", { key: '22665fedfa83e2483d97480a9c9e45da9d296319', class: "menu-item-overlay" }), this.item.isEditing ? this.renderEditMode() : this.renderViewMode()));
|
|
21714
21561
|
}
|
|
21715
21562
|
static get watchers() { return {
|
|
21716
21563
|
"item": [{
|
|
@@ -21720,6 +21567,42 @@ const KritzelMenuItem = class {
|
|
|
21720
21567
|
};
|
|
21721
21568
|
KritzelMenuItem.style = kritzelMenuItemCss();
|
|
21722
21569
|
|
|
21570
|
+
const kritzelOpacitySliderCss = () => `:host{display:flex;flex-direction:column;padding:0;box-sizing:border-box}.opacity-container{display:flex;align-items:center;width:232px}.slider-wrapper{flex:1;display:flex;align-items:center}.opacity-slider{-webkit-appearance:none;appearance:none;width:100%;height:6px;border-radius:3px;background:linear-gradient( to right, var(--kritzel-opacity-slider-active-color, #007AFF) 0%, var(--kritzel-opacity-slider-active-color, #007AFF) var(--slider-progress, 100%), var(--kritzel-opacity-slider-track-color, #e0e0e0) var(--slider-progress, 100%), var(--kritzel-opacity-slider-track-color, #e0e0e0) 100% );outline:none;cursor:var(--kritzel-pointer-cursor, pointer)}.opacity-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:16px;height:16px;border-radius:50%;background:var(--kritzel-opacity-slider-thumb-color, #ffffff);border:2px solid var(--kritzel-opacity-slider-thumb-border-color, #007AFF);cursor:var(--kritzel-pointer-cursor, pointer);box-shadow:0 1px 3px rgba(0, 0, 0, 0.2);transition:transform 0.1s ease}.opacity-slider::-webkit-slider-thumb:hover{transform:scale(1.1)}.opacity-slider::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:var(--kritzel-opacity-slider-thumb-color, #ffffff);border:2px solid var(--kritzel-opacity-slider-thumb-border-color, #007AFF);cursor:var(--kritzel-pointer-cursor, pointer);box-shadow:0 1px 3px rgba(0, 0, 0, 0.2);transition:transform 0.1s ease}.opacity-slider::-moz-range-thumb:hover{transform:scale(1.1)}.opacity-slider::-moz-range-track{height:6px;border-radius:3px;background:transparent}.opacity-slider:focus{outline:none}.opacity-slider:focus::-webkit-slider-thumb{box-shadow:0 0 0 3px var(--kritzel-focus-ring-color, rgba(0, 122, 255, 0.3))}.opacity-slider:focus::-moz-range-thumb{box-shadow:0 0 0 3px var(--kritzel-focus-ring-color, rgba(0, 122, 255, 0.3))}`;
|
|
21571
|
+
|
|
21572
|
+
const KritzelOpacitySlider = class {
|
|
21573
|
+
constructor(hostRef) {
|
|
21574
|
+
index.registerInstance(this, hostRef);
|
|
21575
|
+
this.valueChange = index.createEvent(this, "valueChange");
|
|
21576
|
+
}
|
|
21577
|
+
/** Current opacity value (0 to 1) */
|
|
21578
|
+
value = 1;
|
|
21579
|
+
/** Minimum opacity value */
|
|
21580
|
+
min = 0;
|
|
21581
|
+
/** Maximum opacity value */
|
|
21582
|
+
max = 1;
|
|
21583
|
+
/** Step increment */
|
|
21584
|
+
step = 0.01;
|
|
21585
|
+
/** Color to display in the preview (optional) */
|
|
21586
|
+
previewColor = '#000000';
|
|
21587
|
+
valueChange;
|
|
21588
|
+
handleInput(event) {
|
|
21589
|
+
const input = event.target;
|
|
21590
|
+
const newValue = parseFloat(input.value);
|
|
21591
|
+
this.value = newValue;
|
|
21592
|
+
this.valueChange.emit(newValue);
|
|
21593
|
+
}
|
|
21594
|
+
getPercentage() {
|
|
21595
|
+
return Math.round(this.value * 100);
|
|
21596
|
+
}
|
|
21597
|
+
render() {
|
|
21598
|
+
const percentage = this.getPercentage();
|
|
21599
|
+
return (index.h(index.Host, { key: 'e1409175b038e78d2659356452c48ccc7d79b8de' }, index.h("div", { key: '1de138f56f699fc54623ed8d7b8b5c6d3eda3c67', class: "opacity-container" }, index.h("div", { key: '1dd5d0d36c8d025ba46a0623a20f040990cc749a', class: "slider-wrapper" }, index.h("input", { key: '7b555aa0a4a9abfdcdadc86bffa5878c9336d1e4', type: "range", class: "opacity-slider", min: this.min, max: this.max, step: this.step, value: this.value, onInput: (e) => this.handleInput(e), style: {
|
|
21600
|
+
'--slider-progress': `${percentage}%`,
|
|
21601
|
+
} })))));
|
|
21602
|
+
}
|
|
21603
|
+
};
|
|
21604
|
+
KritzelOpacitySlider.style = kritzelOpacitySliderCss();
|
|
21605
|
+
|
|
21723
21606
|
class KritzelHTMLHelper {
|
|
21724
21607
|
static getNumericValueFromStyle(element, property) {
|
|
21725
21608
|
const value = window.getComputedStyle(element).getPropertyValue(property);
|
|
@@ -21976,7 +21859,7 @@ const KritzelPortal = class {
|
|
|
21976
21859
|
this.portal.style.left = `${left}px`;
|
|
21977
21860
|
}
|
|
21978
21861
|
render() {
|
|
21979
|
-
return (index.h(index.Host, { key: '
|
|
21862
|
+
return (index.h(index.Host, { key: 'c70a1f7c4b2801346fc7a711b44e951337f42f77', style: { display: this.anchor ? 'block' : 'none' } }, index.h("slot", { key: '654bd6dd3ec83d77984a500d505ed1f3c04a0c26' })));
|
|
21980
21863
|
}
|
|
21981
21864
|
static get watchers() { return {
|
|
21982
21865
|
"anchor": [{
|
|
@@ -21985,6 +21868,40 @@ const KritzelPortal = class {
|
|
|
21985
21868
|
}; }
|
|
21986
21869
|
};
|
|
21987
21870
|
|
|
21871
|
+
const kritzelShapeFillCss = () => `:host{display:flex;flex-direction:column;gap:12px;padding:0;box-sizing:border-box}.fill-row{display:flex;align-items:center;gap:4px}.fill-option{display:flex;justify-content:center;align-items:center;width:48px;height:32px;border-radius:6px;cursor:var(--kritzel-pointer-cursor, pointer);border:2px solid transparent;box-sizing:border-box;background:var(--kritzel-shape-fill-option-background, #ffffff);padding:4px;transition:background-color 0.15s ease, border-color 0.15s ease}.fill-option:hover{background-color:var(--kritzel-shape-fill-hover-background-color, #ebebeb)}.fill-option.selected{border-color:var(--kritzel-selection-border-color, #007AFF);background-color:var(--kritzel-shape-fill-selected-background-color, #ebebeb)}.fill-option:focus{outline:none;box-shadow:0 0 0 2px var(--kritzel-focus-ring-color, rgba(0, 122, 255, 0.3))}.fill-icon{width:100%;height:100%}`;
|
|
21872
|
+
|
|
21873
|
+
const KritzelShapeFill = class {
|
|
21874
|
+
constructor(hostRef) {
|
|
21875
|
+
index.registerInstance(this, hostRef);
|
|
21876
|
+
this.valueChange = index.createEvent(this, "valueChange");
|
|
21877
|
+
}
|
|
21878
|
+
/** Current fill type */
|
|
21879
|
+
value = 'transparent';
|
|
21880
|
+
valueChange;
|
|
21881
|
+
handleFillChange(type) {
|
|
21882
|
+
this.value = type;
|
|
21883
|
+
this.valueChange.emit(type);
|
|
21884
|
+
}
|
|
21885
|
+
renderFillIcon(type) {
|
|
21886
|
+
const strokeColor = '#000000';
|
|
21887
|
+
if (type === 'transparent') {
|
|
21888
|
+
return (index.h("svg", { viewBox: "0 0 24 24", class: "fill-icon" }, index.h("rect", { x: "4", y: "4", width: "16", height: "16", rx: "2", fill: "none", stroke: strokeColor, "stroke-width": "2" })));
|
|
21889
|
+
}
|
|
21890
|
+
// Filled
|
|
21891
|
+
return (index.h("svg", { viewBox: "0 0 24 24", class: "fill-icon" }, index.h("rect", { x: "4", y: "4", width: "16", height: "16", rx: "2", fill: strokeColor, stroke: strokeColor, "stroke-width": "2" })));
|
|
21892
|
+
}
|
|
21893
|
+
render() {
|
|
21894
|
+
return (index.h(index.Host, { key: '7935296eb495557672cc96ab838ff4996953b220' }, index.h("div", { key: '69011629ff2dbdd38c7fb03b873fe5411b712de3', class: "fill-row" }, index.h("button", { key: '8a16a43b1ed8f316bc698a304d76667397a83015', class: {
|
|
21895
|
+
'fill-option': true,
|
|
21896
|
+
'selected': this.value === 'transparent',
|
|
21897
|
+
}, onClick: () => this.handleFillChange('transparent'), title: "Transparent background" }, this.renderFillIcon('transparent')), index.h("button", { key: 'f51854da5ece9f18242b4b91ac9645e13efc41b3', class: {
|
|
21898
|
+
'fill-option': true,
|
|
21899
|
+
'selected': this.value === 'filled',
|
|
21900
|
+
}, onClick: () => this.handleFillChange('filled'), title: "Filled background" }, this.renderFillIcon('filled')))));
|
|
21901
|
+
}
|
|
21902
|
+
};
|
|
21903
|
+
KritzelShapeFill.style = kritzelShapeFillCss();
|
|
21904
|
+
|
|
21988
21905
|
const kritzelSplitButtonCss = () => `:host{position:relative;display:flex;align-items:center;font-family:sans-serif;z-index:1;padding:var(--kritzel-split-button-padding, 4px);background-color:var(--kritzel-split-button-background-color, #ffffff);border-radius:var(--kritzel-split-button-border-radius, 12px);box-shadow:var(--kritzel-split-button-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-split-button-border, 1px solid #ebebeb);gap:var(--kritzel-split-button-gap, 4px)}:host(.mobile){--kritzel-split-button-hover-background-color:transparent}button{border:none;background-color:transparent;padding:0;margin:0;font-family:inherit;font-size:inherit;color:inherit;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:var(--kritzel-pointer-cursor, pointer);text-align:center;display:flex;align-items:center;justify-content:center;pointer-events:all;-webkit-tap-highlight-color:transparent}.split-main-button,.split-menu-button{height:auto;display:flex;align-items:center;padding:var(--kritzel-split-button-padding, 8px);background-color:var(--kritzel-split-button-background-color, #ffffff);border-radius:var(--kritzel-split-button-border-radius, 12px);font-size:var(--kritzel-split-button-font-size, 14px)}.split-main-button:hover,.split-menu-button:hover{background-color:var(--kritzel-split-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.split-main-button:focus,.split-menu-button:focus{background-color:var(--kritzel-split-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.split-main-button{gap:var(--kritzel-split-button-gap, 4px)}.split-menu-button{border-left:none;justify-content:center}.split-divider{width:var(--kritzel-split-button-divider-width, 1px);height:24px;background-color:var(--kritzel-split-button-divider-background-color, hsl(0, 0%, 0%, 4.3%))}:disabled{pointer-events:none;opacity:0.5}`;
|
|
21989
21906
|
|
|
21990
21907
|
const KritzelSplitButton = class {
|
|
@@ -22078,12 +21995,12 @@ const KritzelSplitButton = class {
|
|
|
22078
21995
|
this.menuScrollTop = event.target.scrollTop;
|
|
22079
21996
|
};
|
|
22080
21997
|
render() {
|
|
22081
|
-
return (index.h(index.Host, { key: '
|
|
21998
|
+
return (index.h(index.Host, { key: 'cdfb795efe513061f464c76650aa226cd7d5ac81', class: { mobile: this.isTouchDevice } }, index.h("button", { key: '5c38c82b57f35c2e39b0dbba71b3ccfd99ebcc5c', class: "split-main-button", tabIndex: 0, onClick: this.handleButtonClick, disabled: this.mainButtonDisabled }, this.buttonIcon && index.h("kritzel-icon", { key: '862d96cca7ec5aef55284ac6a65ce16b07a03dda', name: this.buttonIcon })), index.h("div", { key: '41849e36e756af257d10baf82d2cb0c9cd1e441f', class: "split-divider" }), index.h("button", { key: '0c54c40c84dcf5cf1b94b024353334e4be0e3404', ref: el => (this.splitMenuButtonRef = el), class: "split-menu-button", tabIndex: 0, onClick: this.toggleMenu, disabled: this.menuButtonDisabled }, index.h("kritzel-icon", { key: '15b0d07c9afa584105180fb5f0701c15974f11aa', name: this.dropdownIcon })), index.h("kritzel-portal", { key: '23014ad95c3ee688b9348f480cc33cdb1c970244', anchor: this.anchorElement, offsetY: 4, onClose: this.closeMenu }, index.h("kritzel-menu", { key: '90f4f29429a80f5700d16b1e99f3dd6315464bbb', ref: el => (this.menuRef = el), items: this.items, onItemSelect: this.handleItemSelect, onItemSave: this.handleItemSave, onItemCancel: this.handleItemCancel, onItemToggleChildMenu: this.handleItemToggleChildMenu, onItemCloseChildMenu: this.handleItemCloseChildMenu, onClose: this.closeMenu, onScroll: this.handleScroll }))));
|
|
22082
21999
|
}
|
|
22083
22000
|
};
|
|
22084
22001
|
KritzelSplitButton.style = kritzelSplitButtonCss();
|
|
22085
22002
|
|
|
22086
|
-
const kritzelStrokeSizeCss = () => `:host{display:flex;align-items:flex-start;gap:
|
|
22003
|
+
const kritzelStrokeSizeCss = () => `:host{display:flex;align-items:flex-start;gap:0;padding:0;width:100%;box-sizing:border-box}.size-grid{width:100%;display:grid;grid-template-columns:repeat(6, 32px);gap:8px;justify-items:center}.size-container{display:flex;justify-content:center;align-items:center;width:32px;height:32px;border-radius:50%;cursor:var(--kritzel-pointer-cursor, pointer);border:2px solid transparent;box-sizing:border-box}.size-container:hover{background-color:var(--kritzel-stroke-size-hover-background-color, #ebebeb)}.size-container.selected{border-color:var(--kritzel-selection-border-color, #007AFF);background-color:var(--kritzel-stroke-size-selected-background-color, #ebebeb)}`;
|
|
22087
22004
|
|
|
22088
22005
|
const KritzelStrokeSize = class {
|
|
22089
22006
|
constructor(hostRef) {
|
|
@@ -22098,15 +22015,215 @@ const KritzelStrokeSize = class {
|
|
|
22098
22015
|
this.sizeChange.emit(size);
|
|
22099
22016
|
}
|
|
22100
22017
|
render() {
|
|
22101
|
-
return (index.h(index.Host, { key: '
|
|
22018
|
+
return (index.h(index.Host, { key: '891f899a41844bba03305e3dd7cbf428d4471ff9' }, index.h("div", { key: '773a756d54d0632c9ea6b3aebb743abad2274244', class: "size-grid" }, this.sizes.map(size => (index.h("div", { tabIndex: 0, class: {
|
|
22102
22019
|
'size-container': true,
|
|
22103
22020
|
'selected': this.selectedSize === size,
|
|
22104
|
-
}, onClick: () => this.handleSizeClick(size) }, index.h("kritzel-color", { value: '#000000', size: size }))))));
|
|
22021
|
+
}, onClick: () => this.handleSizeClick(size) }, index.h("kritzel-color", { value: '#000000', size: size })))))));
|
|
22105
22022
|
}
|
|
22106
22023
|
};
|
|
22107
22024
|
KritzelStrokeSize.style = kritzelStrokeSizeCss();
|
|
22108
22025
|
|
|
22109
|
-
const
|
|
22026
|
+
const kritzelToolConfigCss = () => `.expand-toggle{background:none;border:none;cursor:pointer;padding:0;margin:0;display:flex;align-items:center;justify-content:center;width:32px;height:32px;color:var(--kritzel-icon-color, currentColor);transition:transform 0.2s ease}.expand-toggle:hover{opacity:0.7}.expand-toggle:focus{outline:none}.expand-toggle:focus-visible{outline:2px solid var(--kritzel-focus-color, #007acc);outline-offset:2px}.expand-toggle:active{transform:scale(0.95)}.divider{height:1px;background-color:var(--kritzel-divider-color, #e0e0e0);margin:4px 0;width:100%}`;
|
|
22027
|
+
|
|
22028
|
+
const KritzelToolConfig = class {
|
|
22029
|
+
constructor(hostRef) {
|
|
22030
|
+
index.registerInstance(this, hostRef);
|
|
22031
|
+
this.toolChange = index.createEvent(this, "toolChange");
|
|
22032
|
+
this.displayValuesChange = index.createEvent(this, "displayValuesChange");
|
|
22033
|
+
}
|
|
22034
|
+
tool;
|
|
22035
|
+
handleToolChange(newTool, oldTool) {
|
|
22036
|
+
const newConfig = KritzelToolConfigHelper.getToolConfig(newTool);
|
|
22037
|
+
// Maintain settings when switching between shape tools
|
|
22038
|
+
if (oldTool && newTool && newConfig?.type === 'shape') {
|
|
22039
|
+
const oldConfig = KritzelToolConfigHelper.getToolConfig(oldTool);
|
|
22040
|
+
if (oldConfig?.type === 'shape') {
|
|
22041
|
+
// Copy properties that should persist
|
|
22042
|
+
const propsToCopy = [
|
|
22043
|
+
newConfig.colorProperty, // strokeColor
|
|
22044
|
+
newConfig.sizeProperty, // strokeWidth
|
|
22045
|
+
newConfig.opacityProperty, // opacity
|
|
22046
|
+
'fillColor' // shape specific
|
|
22047
|
+
];
|
|
22048
|
+
propsToCopy.forEach(prop => {
|
|
22049
|
+
if (prop && oldTool[prop] !== undefined) {
|
|
22050
|
+
newTool[prop] = oldTool[prop];
|
|
22051
|
+
}
|
|
22052
|
+
});
|
|
22053
|
+
}
|
|
22054
|
+
}
|
|
22055
|
+
this.config = newConfig;
|
|
22056
|
+
if (this.config) {
|
|
22057
|
+
this.updatePalette();
|
|
22058
|
+
this.currentOpacity = newTool[this.config.opacityProperty] ?? 1;
|
|
22059
|
+
// Emit the values since they might have been updated from the old tool
|
|
22060
|
+
this.emitDisplayValues();
|
|
22061
|
+
}
|
|
22062
|
+
}
|
|
22063
|
+
isExpanded = false;
|
|
22064
|
+
toolChange;
|
|
22065
|
+
displayValuesChange;
|
|
22066
|
+
config;
|
|
22067
|
+
palette = [];
|
|
22068
|
+
currentOpacity = 1;
|
|
22069
|
+
updateTrigger = 0;
|
|
22070
|
+
handleSelectionChange() {
|
|
22071
|
+
if (this.tool instanceof defaultLineTool_config.KritzelSelectionTool) {
|
|
22072
|
+
this.config = KritzelToolConfigHelper.getToolConfig(this.tool);
|
|
22073
|
+
if (this.config) {
|
|
22074
|
+
this.updatePalette();
|
|
22075
|
+
this.currentOpacity = this.tool[this.config.opacityProperty] ?? 1;
|
|
22076
|
+
this.emitDisplayValues();
|
|
22077
|
+
}
|
|
22078
|
+
}
|
|
22079
|
+
}
|
|
22080
|
+
componentWillLoad() {
|
|
22081
|
+
this.config = KritzelToolConfigHelper.getToolConfig(this.tool);
|
|
22082
|
+
if (this.config) {
|
|
22083
|
+
this.updatePalette();
|
|
22084
|
+
this.currentOpacity = this.tool[this.config.opacityProperty] ?? 1;
|
|
22085
|
+
this.emitDisplayValues();
|
|
22086
|
+
}
|
|
22087
|
+
}
|
|
22088
|
+
emitDisplayValues() {
|
|
22089
|
+
if (!this.config)
|
|
22090
|
+
return;
|
|
22091
|
+
const color = this.tool[this.config.colorProperty];
|
|
22092
|
+
const opacity = this.currentOpacity;
|
|
22093
|
+
const size = this.tool[this.config.sizeProperty];
|
|
22094
|
+
const displayValues = {
|
|
22095
|
+
color: KritzelColorHelper.applyOpacity(color, opacity),
|
|
22096
|
+
size,
|
|
22097
|
+
};
|
|
22098
|
+
if (this.tool instanceof defaultLineTool_config.KritzelTextTool) {
|
|
22099
|
+
displayValues.fontFamily = this.tool.fontFamily;
|
|
22100
|
+
}
|
|
22101
|
+
this.displayValuesChange.emit(displayValues);
|
|
22102
|
+
}
|
|
22103
|
+
updatePalette() {
|
|
22104
|
+
if (!this.config)
|
|
22105
|
+
return;
|
|
22106
|
+
if (this.config.paletteSource === 'palettes') {
|
|
22107
|
+
// Brush tool has palettes[type]
|
|
22108
|
+
const brushTool = this.tool;
|
|
22109
|
+
this.palette = brushTool.palettes[brushTool.type] || [];
|
|
22110
|
+
}
|
|
22111
|
+
else if (this.config.paletteSource === 'palette') {
|
|
22112
|
+
// Line, Shape, Text tools have palette
|
|
22113
|
+
this.palette = this.tool.palette || [];
|
|
22114
|
+
}
|
|
22115
|
+
}
|
|
22116
|
+
handleToggleExpand = () => {
|
|
22117
|
+
this.isExpanded = !this.isExpanded;
|
|
22118
|
+
};
|
|
22119
|
+
handleColorChange = (event) => {
|
|
22120
|
+
this.tool[this.config.colorProperty] = event.detail;
|
|
22121
|
+
// Special handling for shape fill: when color (stroke) changes, update fill color if it's currently filled
|
|
22122
|
+
if (this.config.type === 'shape' || this.config.type === 'selection') {
|
|
22123
|
+
const tool = this.tool;
|
|
22124
|
+
if (tool.fillColor !== 'transparent') {
|
|
22125
|
+
tool.fillColor = event.detail;
|
|
22126
|
+
}
|
|
22127
|
+
}
|
|
22128
|
+
this.emitDisplayValues();
|
|
22129
|
+
this.toolChange.emit(this.tool);
|
|
22130
|
+
this.updateTrigger++;
|
|
22131
|
+
};
|
|
22132
|
+
handleSizeChange = (event) => {
|
|
22133
|
+
this.tool[this.config.sizeProperty] = event.detail;
|
|
22134
|
+
this.emitDisplayValues();
|
|
22135
|
+
this.toolChange.emit(this.tool);
|
|
22136
|
+
this.updateTrigger++;
|
|
22137
|
+
};
|
|
22138
|
+
handleOpacityChange = (event) => {
|
|
22139
|
+
this.tool[this.config.opacityProperty] = event.detail;
|
|
22140
|
+
this.currentOpacity = event.detail;
|
|
22141
|
+
this.emitDisplayValues();
|
|
22142
|
+
this.toolChange.emit(this.tool);
|
|
22143
|
+
};
|
|
22144
|
+
handlePropertyChange = (propertyName, value) => {
|
|
22145
|
+
// Special handling for shape fill
|
|
22146
|
+
if ((this.config.type === 'shape' || this.config.type === 'selection') && propertyName === 'fillColor') {
|
|
22147
|
+
const newFillColor = value === 'filled' ? this.tool[this.config.colorProperty] : 'transparent';
|
|
22148
|
+
this.tool.fillColor = newFillColor;
|
|
22149
|
+
// When switching to fill mode, also update stroke color to match
|
|
22150
|
+
if (value === 'filled') {
|
|
22151
|
+
this.tool[this.config.colorProperty] = newFillColor;
|
|
22152
|
+
}
|
|
22153
|
+
}
|
|
22154
|
+
// Special handling for brush type change
|
|
22155
|
+
else if (this.config.type === 'brush' && propertyName === 'type') {
|
|
22156
|
+
const brushTool = this.tool;
|
|
22157
|
+
brushTool.type = value;
|
|
22158
|
+
this.palette = brushTool.palettes[value];
|
|
22159
|
+
brushTool.color = this.palette[0];
|
|
22160
|
+
this.emitDisplayValues();
|
|
22161
|
+
}
|
|
22162
|
+
else {
|
|
22163
|
+
this.tool[propertyName] = value;
|
|
22164
|
+
// Emit display values for font family changes
|
|
22165
|
+
if (propertyName === 'fontFamily') {
|
|
22166
|
+
this.emitDisplayValues();
|
|
22167
|
+
}
|
|
22168
|
+
}
|
|
22169
|
+
this.toolChange.emit(this.tool);
|
|
22170
|
+
this.updateTrigger++;
|
|
22171
|
+
};
|
|
22172
|
+
getShapeFillValue() {
|
|
22173
|
+
const fillColor = this.tool.fillColor;
|
|
22174
|
+
return fillColor === 'transparent' ? 'transparent' : 'filled';
|
|
22175
|
+
}
|
|
22176
|
+
renderControl(control) {
|
|
22177
|
+
const value = this.tool[control.propertyName];
|
|
22178
|
+
switch (control.type) {
|
|
22179
|
+
case 'stroke-size':
|
|
22180
|
+
return (index.h("kritzel-stroke-size", { key: control.type, selectedSize: value, onSizeChange: this.handleSizeChange }));
|
|
22181
|
+
case 'font-size':
|
|
22182
|
+
return (index.h("kritzel-font-size", { key: control.type, selectedSize: value, fontFamily: this.tool.fontFamily, onSizeChange: this.handleSizeChange }));
|
|
22183
|
+
case 'line-endings':
|
|
22184
|
+
return (index.h("kritzel-line-endings", { key: control.type, value: value, strokeColor: this.tool[this.config.colorProperty], onValueChange: (event) => this.handlePropertyChange(control.propertyName, event.detail) }));
|
|
22185
|
+
case 'shape-fill':
|
|
22186
|
+
return (index.h("kritzel-shape-fill", { key: control.type, value: this.getShapeFillValue(), onValueChange: (event) => this.handlePropertyChange(control.propertyName, event.detail) }));
|
|
22187
|
+
case 'font-family':
|
|
22188
|
+
return (index.h("kritzel-font-family", { key: control.type, selectedFontFamily: value, onFontFamilyChange: (event) => this.handlePropertyChange(control.propertyName, event.detail) }));
|
|
22189
|
+
default:
|
|
22190
|
+
return null;
|
|
22191
|
+
}
|
|
22192
|
+
}
|
|
22193
|
+
render() {
|
|
22194
|
+
if (!this.config)
|
|
22195
|
+
return null;
|
|
22196
|
+
const shouldShowExpandButton = this.palette.length > 6 || this.config.type === 'text';
|
|
22197
|
+
// Separate size control from other controls
|
|
22198
|
+
const sizeControl = this.config.controls.find(c => c.type === 'stroke-size' || c.type === 'font-size');
|
|
22199
|
+
const otherControls = this.config.controls.filter(c => c.type !== 'stroke-size' && c.type !== 'font-size');
|
|
22200
|
+
return (index.h(index.Host, null, index.h("div", { style: {
|
|
22201
|
+
display: 'flex',
|
|
22202
|
+
flexDirection: 'row',
|
|
22203
|
+
gap: '8px',
|
|
22204
|
+
width: '100%',
|
|
22205
|
+
} }, index.h("div", { style: {
|
|
22206
|
+
display: 'flex',
|
|
22207
|
+
flexDirection: 'column',
|
|
22208
|
+
gap: '12px',
|
|
22209
|
+
flex: '1',
|
|
22210
|
+
} }, index.h("kritzel-color-palette", { colors: this.palette, selectedColor: this.tool[this.config.colorProperty], isExpanded: this.isExpanded, isOpaque: true, opacity: this.currentOpacity, onColorChange: this.handleColorChange }), sizeControl && this.renderControl(sizeControl), index.h("kritzel-opacity-slider", { value: this.tool[this.config.opacityProperty], previewColor: this.tool[this.config.colorProperty], onValueChange: this.handleOpacityChange }), otherControls.map((control) => [
|
|
22211
|
+
index.h("div", { class: "divider" }),
|
|
22212
|
+
this.renderControl(control),
|
|
22213
|
+
])), shouldShowExpandButton && (index.h("div", { style: {
|
|
22214
|
+
display: 'flex',
|
|
22215
|
+
alignItems: 'flex-start',
|
|
22216
|
+
} }, index.h("button", { class: "expand-toggle", onClick: this.handleToggleExpand, title: this.isExpanded ? 'Collapse' : 'Expand' }, index.h("kritzel-icon", { name: this.isExpanded ? 'chevron-up' : 'chevron-down' })))))));
|
|
22217
|
+
}
|
|
22218
|
+
static get watchers() { return {
|
|
22219
|
+
"tool": [{
|
|
22220
|
+
"handleToolChange": 0
|
|
22221
|
+
}]
|
|
22222
|
+
}; }
|
|
22223
|
+
};
|
|
22224
|
+
KritzelToolConfig.style = kritzelToolConfigCss();
|
|
22225
|
+
|
|
22226
|
+
const kritzelTooltipCss = () => `:host{width:auto}.tooltip-content{position:relative;padding:8px 12px;border-radius:4px;width:fit-content;background-color:var(--kritzel-controls-tooltip-background-color, #ffffff);color:var(--kritzel-controls-tooltip-color, #000000);padding:var(--kritzel-controls-tooltip-padding, 12px);border-radius:var(--kritzel-controls-tooltip-border-radius, 16px);white-space:nowrap;box-shadow:var(--kritzel-controls-tooltip-box-shadow, 0 1px 6px rgba(0, 0, 0, 0.12))}`;
|
|
22110
22227
|
|
|
22111
22228
|
const KritzelTooltip = class {
|
|
22112
22229
|
constructor(hostRef) {
|
|
@@ -22123,8 +22240,10 @@ const KritzelTooltip = class {
|
|
|
22123
22240
|
handleOutsideClick(event) {
|
|
22124
22241
|
if (!this.isVisible)
|
|
22125
22242
|
return;
|
|
22126
|
-
|
|
22127
|
-
|
|
22243
|
+
// Check if click is inside the tooltip host or any of its shadow DOM content
|
|
22244
|
+
const path = event.composedPath();
|
|
22245
|
+
const isInsideTooltip = path.some(el => el === this.host);
|
|
22246
|
+
if (!isInsideTooltip) {
|
|
22128
22247
|
this.tooltipClosed.emit();
|
|
22129
22248
|
}
|
|
22130
22249
|
}
|
|
@@ -22174,14 +22293,14 @@ const KritzelTooltip = class {
|
|
|
22174
22293
|
}
|
|
22175
22294
|
}
|
|
22176
22295
|
render() {
|
|
22177
|
-
return (index.h(index.Host, { key: '
|
|
22296
|
+
return (index.h(index.Host, { key: '104ad4a160e4f47454955696e5f0e7a28873c3f5', style: {
|
|
22178
22297
|
position: 'fixed',
|
|
22179
22298
|
zIndex: '9999',
|
|
22180
22299
|
transition: 'opacity 0.3s ease-in-out, transform 0.3s ease-in-out',
|
|
22181
22300
|
visibility: this.isVisible ? 'visible' : 'hidden',
|
|
22182
22301
|
left: `${this.positionX}px`,
|
|
22183
22302
|
bottom: `${this.positionY}px`,
|
|
22184
|
-
} }, index.h("div", { key: '
|
|
22303
|
+
} }, index.h("div", { key: '283eec8d84ea29caefdb1f0c4f129c57d30bc133', class: "tooltip-content", onClick: event => event.stopPropagation(), onPointerDown: event => event.stopPropagation(), onMouseDown: event => event.stopPropagation() }, index.h("slot", { key: '1c6e2d9bcb69f8deec08b6c10384b4c7593babd3' }))));
|
|
22185
22304
|
}
|
|
22186
22305
|
};
|
|
22187
22306
|
KritzelTooltip.style = kritzelTooltipCss();
|
|
@@ -22212,7 +22331,7 @@ const KritzelUtilityPanel = class {
|
|
|
22212
22331
|
this.redo.emit();
|
|
22213
22332
|
}
|
|
22214
22333
|
render() {
|
|
22215
|
-
return (index.h(index.Host, { key: '
|
|
22334
|
+
return (index.h(index.Host, { key: 'b0994bdfd10e1bfbad18d7df2810575b19a9e67d' }, index.h("button", { key: '4bcb8106f6977ff1472477b6a689942e7eedd8b7', class: "utility-button", disabled: !this.undoState?.canUndo, onClick: event => this.handleUndo(event) }, index.h("kritzel-icon", { key: '05c9a0b6a926eeb236cda9bf8c333dd6a0b563cb', name: "undo" })), index.h("button", { key: '88b008c4c37de9440da414617a0b2e144e47e830', class: "utility-button", disabled: !this.undoState?.canRedo, onClick: event => this.handleRedo(event) }, index.h("kritzel-icon", { key: 'ec921af2eca35fd1d1aad88d88d5f0a0804e4c44', name: "redo" })), index.h("div", { key: '94b7eec2edee8a41296726ab79d61bccba1940d8', class: "utility-separator" }), index.h("button", { key: '50be446ae7510d5133b7767e0dd382b7e1c87c3f', class: "utility-button" }, index.h("kritzel-icon", { key: 'd11d988dafc42c250b7361f5bba532fa9f81d97e', name: "delete", onClick: () => this.delete.emit() }))));
|
|
22216
22335
|
}
|
|
22217
22336
|
};
|
|
22218
22337
|
KritzelUtilityPanel.style = kritzelUtilityPanelCss();
|
|
@@ -22360,8 +22479,6 @@ KritzelWorkspaceManager.style = kritzelWorkspaceManagerCss();
|
|
|
22360
22479
|
exports.kritzel_color = KritzelColor;
|
|
22361
22480
|
exports.kritzel_color_palette = KritzelColorPalette;
|
|
22362
22481
|
exports.kritzel_context_menu = KritzelContextMenu;
|
|
22363
|
-
exports.kritzel_control_brush_config = KritzelControlBrushConfig;
|
|
22364
|
-
exports.kritzel_control_text_config = KritzelControlTextConfig;
|
|
22365
22482
|
exports.kritzel_controls = KritzelControls;
|
|
22366
22483
|
exports.kritzel_cursor_trail = KritzelCursorTrail;
|
|
22367
22484
|
exports.kritzel_dropdown = KritzelDropdown;
|
|
@@ -22371,11 +22488,15 @@ exports.kritzel_font = KritzelFont;
|
|
|
22371
22488
|
exports.kritzel_font_family = KritzelFontFamily;
|
|
22372
22489
|
exports.kritzel_font_size = KritzelFontSize;
|
|
22373
22490
|
exports.kritzel_icon = KritzelIcon;
|
|
22491
|
+
exports.kritzel_line_endings = KritzelLineEndings;
|
|
22374
22492
|
exports.kritzel_menu = KritzelMenu;
|
|
22375
22493
|
exports.kritzel_menu_item = KritzelMenuItem;
|
|
22494
|
+
exports.kritzel_opacity_slider = KritzelOpacitySlider;
|
|
22376
22495
|
exports.kritzel_portal = KritzelPortal;
|
|
22496
|
+
exports.kritzel_shape_fill = KritzelShapeFill;
|
|
22377
22497
|
exports.kritzel_split_button = KritzelSplitButton;
|
|
22378
22498
|
exports.kritzel_stroke_size = KritzelStrokeSize;
|
|
22499
|
+
exports.kritzel_tool_config = KritzelToolConfig;
|
|
22379
22500
|
exports.kritzel_tooltip = KritzelTooltip;
|
|
22380
22501
|
exports.kritzel_utility_panel = KritzelUtilityPanel;
|
|
22381
22502
|
exports.kritzel_workspace_manager = KritzelWorkspaceManager;
|