kritzel-stencil 0.0.162 → 0.0.164
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-D1Ns0NmM.js → default-line-tool.config-DJMYrkSu.js} +340 -9
- package/dist/cjs/default-line-tool.config-DJMYrkSu.js.map +1 -0
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/kritzel-color_22.cjs.entry.js +760 -27
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/stencil.cjs.js +1 -1
- package/dist/collection/classes/core/core.class.js +19 -3
- package/dist/collection/classes/core/core.class.js.map +1 -1
- package/dist/collection/classes/core/reviver.class.js +16 -0
- package/dist/collection/classes/core/reviver.class.js.map +1 -1
- package/dist/collection/classes/core/store.class.js +5 -0
- package/dist/collection/classes/core/store.class.js.map +1 -1
- package/dist/collection/classes/core/viewport.class.js +8 -0
- package/dist/collection/classes/core/viewport.class.js.map +1 -1
- package/dist/collection/classes/managers/anchor.manager.js +181 -3
- package/dist/collection/classes/managers/anchor.manager.js.map +1 -1
- package/dist/collection/classes/objects/path.class.js +85 -0
- package/dist/collection/classes/objects/path.class.js.map +1 -1
- package/dist/collection/classes/objects/shape.class.js +372 -0
- package/dist/collection/classes/objects/shape.class.js.map +1 -0
- package/dist/collection/classes/registries/icon-registry.class.js +4 -0
- package/dist/collection/classes/registries/icon-registry.class.js.map +1 -1
- package/dist/collection/classes/tools/brush-tool.class.js +2 -2
- package/dist/collection/classes/tools/brush-tool.class.js.map +1 -1
- package/dist/collection/classes/tools/line-tool.class.js +2 -2
- package/dist/collection/classes/tools/line-tool.class.js.map +1 -1
- package/dist/collection/classes/tools/shape-tool.class.js +204 -0
- package/dist/collection/classes/tools/shape-tool.class.js.map +1 -0
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +17 -6
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.js.map +1 -1
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +44 -8
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js.map +1 -1
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.css +143 -5
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +76 -12
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js.map +1 -1
- package/dist/collection/configs/default-shape-tool.config.js +26 -0
- package/dist/collection/configs/default-shape-tool.config.js.map +1 -0
- package/dist/collection/enums/shape-type.enum.js +7 -0
- package/dist/collection/enums/shape-type.enum.js.map +1 -0
- package/dist/collection/helpers/geometry.helper.js +55 -0
- package/dist/collection/helpers/geometry.helper.js.map +1 -1
- package/dist/collection/interfaces/toolbar-control.interface.js.map +1 -1
- package/dist/components/index.js +3 -3
- package/dist/components/kritzel-brush-style.js +1 -1
- package/dist/components/kritzel-context-menu.js +1 -1
- package/dist/components/kritzel-control-brush-config.js +1 -1
- package/dist/components/kritzel-control-text-config.js +1 -1
- package/dist/components/kritzel-controls.js +1 -1
- package/dist/components/kritzel-editor.js +49 -16
- package/dist/components/kritzel-editor.js.map +1 -1
- package/dist/components/kritzel-engine.js +1 -1
- package/dist/components/kritzel-icon.js +1 -1
- package/dist/components/kritzel-menu-item.js +1 -1
- package/dist/components/kritzel-menu.js +1 -1
- package/dist/components/kritzel-split-button.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-Cqr0Bah5.js → p-5OECjGHq.js} +3 -3
- package/dist/components/{p-Cqr0Bah5.js.map → p-5OECjGHq.js.map} +1 -1
- package/dist/components/{p-CvLFRlQU.js → p-BSBMBjhq.js} +3 -3
- package/dist/components/{p-CvLFRlQU.js.map → p-BSBMBjhq.js.map} +1 -1
- package/dist/components/{p-7_lwv0zQ.js → p-BuS7MM1j.js} +4 -4
- package/dist/components/{p-7_lwv0zQ.js.map → p-BuS7MM1j.js.map} +1 -1
- package/dist/components/{p-BixlbUD7.js → p-Cv4BGNPb.js} +6 -2
- package/dist/components/p-Cv4BGNPb.js.map +1 -0
- package/dist/components/{p-dMCB4tJA.js → p-D1YAsWrL.js} +3 -3
- package/dist/components/{p-dMCB4tJA.js.map → p-D1YAsWrL.js.map} +1 -1
- package/dist/components/{p-CDteBYm9.js → p-D8L0t-Ro.js} +3 -3
- package/dist/components/{p-CDteBYm9.js.map → p-D8L0t-Ro.js.map} +1 -1
- package/dist/components/{p-DZ7kxJUx.js → p-DguzZn_x.js} +3 -3
- package/dist/components/{p-DZ7kxJUx.js.map → p-DguzZn_x.js.map} +1 -1
- package/dist/components/{p-sokRZ7Vn.js → p-Dz2XHHqa.js} +145 -5
- package/dist/components/p-Dz2XHHqa.js.map +1 -0
- package/dist/components/{p-CuhOrcET.js → p-DzUUppVL.js} +837 -21
- package/dist/components/p-DzUUppVL.js.map +1 -0
- package/dist/components/{p-CkD1PQQX.js → p-I3iPEDpx.js} +5 -5
- package/dist/components/{p-CkD1PQQX.js.map → p-I3iPEDpx.js.map} +1 -1
- package/dist/components/{p-DKwJJuFb.js → p-tp96UZ0l.js} +83 -19
- package/dist/components/p-tp96UZ0l.js.map +1 -0
- package/dist/esm/{default-line-tool.config-C35m-d1Y.js → default-line-tool.config-C35P3XfD.js} +332 -10
- package/dist/esm/default-line-tool.config-C35P3XfD.js.map +1 -0
- package/dist/esm/index.js +2 -2
- package/dist/esm/kritzel-color_22.entry.js +760 -27
- package/dist/esm/loader.js +1 -1
- package/dist/esm/stencil.js +1 -1
- package/dist/stencil/index.esm.js +1 -1
- package/dist/stencil/p-3e2b5c42.entry.js +10 -0
- package/dist/stencil/p-3e2b5c42.entry.js.map +1 -0
- package/dist/stencil/p-C35P3XfD.js +2 -0
- package/dist/stencil/p-C35P3XfD.js.map +1 -0
- package/dist/stencil/stencil.esm.js +1 -1
- package/dist/types/classes/core/core.class.d.ts +1 -0
- package/dist/types/classes/core/store.class.d.ts +2 -0
- package/dist/types/classes/core/viewport.class.d.ts +6 -0
- package/dist/types/classes/managers/anchor.manager.d.ts +20 -0
- package/dist/types/classes/objects/path.class.d.ts +7 -0
- package/dist/types/classes/objects/shape.class.d.ts +116 -0
- package/dist/types/classes/tools/shape-tool.class.d.ts +37 -0
- package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +2 -2
- package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +16 -1
- package/dist/types/components.d.ts +5 -5
- package/dist/types/configs/default-shape-tool.config.d.ts +2 -0
- package/dist/types/enums/shape-type.enum.d.ts +5 -0
- package/dist/types/helpers/geometry.helper.d.ts +21 -0
- package/dist/types/interfaces/toolbar-control.interface.d.ts +21 -3
- package/package.json +1 -1
- package/dist/cjs/default-line-tool.config-D1Ns0NmM.js.map +0 -1
- package/dist/components/p-BixlbUD7.js.map +0 -1
- package/dist/components/p-CuhOrcET.js.map +0 -1
- package/dist/components/p-DKwJJuFb.js.map +0 -1
- package/dist/components/p-sokRZ7Vn.js.map +0 -1
- package/dist/esm/default-line-tool.config-C35m-d1Y.js.map +0 -1
- package/dist/stencil/p-C35m-d1Y.js +0 -2
- package/dist/stencil/p-C35m-d1Y.js.map +0 -1
- package/dist/stencil/p-d142ef46.entry.js +0 -10
- package/dist/stencil/p-d142ef46.entry.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var index = require('./index-Cj__YTlG.js');
|
|
4
|
-
var defaultLineTool_config = require('./default-line-tool.config-
|
|
4
|
+
var defaultLineTool_config = require('./default-line-tool.config-DJMYrkSu.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
|
|
|
@@ -249,7 +249,7 @@ const KritzelControlTextConfig = class {
|
|
|
249
249
|
};
|
|
250
250
|
KritzelControlTextConfig.style = kritzelControlTextConfigCss;
|
|
251
251
|
|
|
252
|
-
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-
|
|
252
|
+
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{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);display:flex;flex-direction:column;background:var(--kritzel-controls-background-color, #ffffff);border-radius:12px;padding:6px;box-shadow:0 4px 12px rgba(0, 0, 0, 0.15);border:1px solid #ebebeb;z-index:10001;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{position:fixed;bottom:56px;left:50%;transform:translateX(-50%);z-index:10001}";
|
|
253
253
|
|
|
254
254
|
const KritzelControls = class {
|
|
255
255
|
constructor(hostRef) {
|
|
@@ -265,17 +265,24 @@ const KritzelControls = class {
|
|
|
265
265
|
firstConfig = null;
|
|
266
266
|
isTooltipVisible = false;
|
|
267
267
|
isTouchDevice = defaultLineTool_config.KritzelDevicesHelper.isTouchDevice();
|
|
268
|
+
selectedSubOptions = new Map();
|
|
269
|
+
openSubMenuControl = null;
|
|
268
270
|
handleDocumentClick(event) {
|
|
269
271
|
const element = event.target;
|
|
270
272
|
if (!this.kritzelEngine || element.closest('.kritzel-tooltip')) {
|
|
271
273
|
return;
|
|
272
274
|
}
|
|
273
275
|
this.isTooltipVisible = false;
|
|
276
|
+
// Close submenu when clicking outside
|
|
277
|
+
if (!element.closest('.kritzel-control-split') && !element.closest('.kritzel-submenu')) {
|
|
278
|
+
this.openSubMenuControl = null;
|
|
279
|
+
}
|
|
274
280
|
}
|
|
275
281
|
handleKeyDown(event) {
|
|
276
282
|
if (event.key === 'Escape') {
|
|
277
283
|
event.preventDefault();
|
|
278
284
|
this.closeTooltip();
|
|
285
|
+
this.openSubMenuControl = null;
|
|
279
286
|
this.kritzelEngine?.enable();
|
|
280
287
|
}
|
|
281
288
|
}
|
|
@@ -351,36 +358,91 @@ const KritzelControls = class {
|
|
|
351
358
|
this.isTooltipVisible = false;
|
|
352
359
|
this.kritzelEngine?.enable();
|
|
353
360
|
}
|
|
361
|
+
/**
|
|
362
|
+
* Get the currently selected sub-option for a control.
|
|
363
|
+
* Returns the first sub-option as default if none is selected.
|
|
364
|
+
*/
|
|
365
|
+
getSelectedSubOption(control) {
|
|
366
|
+
if (!control.subOptions?.length)
|
|
367
|
+
return undefined;
|
|
368
|
+
return this.selectedSubOptions.get(control.name) || control.subOptions[0];
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Toggle the submenu for a split-button control
|
|
372
|
+
*/
|
|
373
|
+
toggleSubMenu(event, control) {
|
|
374
|
+
event.stopPropagation();
|
|
375
|
+
if (this.openSubMenuControl?.name === control.name) {
|
|
376
|
+
this.openSubMenuControl = null;
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
this.openSubMenuControl = control;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Select a sub-option and update the tool property
|
|
384
|
+
*/
|
|
385
|
+
async selectSubOption(control, option) {
|
|
386
|
+
// Update the selected sub-options map (create new Map for reactivity)
|
|
387
|
+
const newMap = new Map(this.selectedSubOptions);
|
|
388
|
+
newMap.set(control.name, option);
|
|
389
|
+
this.selectedSubOptions = newMap;
|
|
390
|
+
// Update the tool property if the tool is instantiated
|
|
391
|
+
if (control.tool && typeof control.tool !== 'function') {
|
|
392
|
+
control.tool[option.toolProperty] = option.value;
|
|
393
|
+
}
|
|
394
|
+
// Close the submenu
|
|
395
|
+
this.openSubMenuControl = null;
|
|
396
|
+
// Activate this control
|
|
397
|
+
await this.handleControlClick(control);
|
|
398
|
+
}
|
|
354
399
|
render() {
|
|
355
|
-
const
|
|
356
|
-
|
|
400
|
+
const hasConfigUI = this.activeControl?.tool instanceof defaultLineTool_config.KritzelBrushTool ||
|
|
401
|
+
this.activeControl?.tool instanceof defaultLineTool_config.KritzelTextTool;
|
|
402
|
+
return (index.h(index.Host, { key: '34a8a81224f1714a30a0d6e03fb81ed031fe36a0', class: {
|
|
357
403
|
mobile: this.isTouchDevice,
|
|
358
|
-
} }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '
|
|
404
|
+
} }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '8ddfe7b4872d59b08b0561dbd61c67b9c245dcc9', style: {
|
|
359
405
|
position: 'absolute',
|
|
360
406
|
bottom: '56px',
|
|
361
407
|
left: '12px',
|
|
362
|
-
}, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '
|
|
408
|
+
}, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '370229830b9a6c0ae5704d9fb0ce35d130fcf049', class: "kritzel-controls" }, this.controls.map(control => {
|
|
363
409
|
if (control.type === 'tool') {
|
|
410
|
+
// Check if this control has sub-options (split-button)
|
|
411
|
+
if (control.subOptions?.length) {
|
|
412
|
+
const selectedSubOption = this.getSelectedSubOption(control);
|
|
413
|
+
const isActive = this.activeControl?.name === control.name;
|
|
414
|
+
const isSubMenuOpen = this.openSubMenuControl?.name === control.name;
|
|
415
|
+
return (index.h("div", { class: {
|
|
416
|
+
'kritzel-control-split': true,
|
|
417
|
+
'selected': isActive,
|
|
418
|
+
}, key: control.name }, 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: {
|
|
419
|
+
'kritzel-control-dropdown': true,
|
|
420
|
+
'visible': isActive,
|
|
421
|
+
}, 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 })), isSubMenuOpen && (index.h("div", { class: "kritzel-submenu" }, control.subOptions.map(option => (index.h("button", { class: {
|
|
422
|
+
'kritzel-submenu-item': true,
|
|
423
|
+
'active': option.id === selectedSubOption?.id,
|
|
424
|
+
}, key: option.id, onClick: () => this.selectSubOption(control, option) }, index.h("kritzel-icon", { name: option.icon, size: 20 }), index.h("span", null, option.label))))))));
|
|
425
|
+
}
|
|
426
|
+
// Regular tool control (no sub-options)
|
|
364
427
|
return (index.h("button", { class: {
|
|
365
428
|
'kritzel-control': true,
|
|
366
429
|
'selected': this.activeControl?.name === control?.name,
|
|
367
430
|
}, key: control.name, onClick: _event => this.handleControlClick?.(control) }, index.h("kritzel-icon", { name: control.icon })));
|
|
368
431
|
}
|
|
369
|
-
if (control.type === 'divider') {
|
|
370
|
-
return index.h("div", { class: "kritzel-divider", key: control.name });
|
|
371
|
-
}
|
|
372
432
|
if (control.type === 'config' && control.name === this.firstConfig?.name && this.activeControl) {
|
|
373
|
-
return (index.h("div", { class:
|
|
433
|
+
return (index.h("div", { class: {
|
|
434
|
+
'kritzel-config-container': true,
|
|
435
|
+
'visible': hasConfigUI,
|
|
436
|
+
}, key: control.name }, index.h("kritzel-tooltip", { ref: el => (this.tooltipRef = el), isVisible: this.isTooltipVisible, anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), onTooltipClosed: () => this.handleTooltipClosed() }, index.h("div", { style: { width: '294px', height: '100%' } }, this.activeControl.name === 'brush' && (index.h("kritzel-control-brush-config", { tool: this.activeToolAsBrushTool, onToolChange: event => this.handleToolChange?.(event) })), this.activeControl.name === 'text' && (index.h("kritzel-control-text-config", { tool: this.activeToolAsTextTool, onToolChange: event => this.handleToolChange?.(event) })))), index.h("div", { tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", onClick: event => this.handleConfigClick?.(event), onKeyDown: event => {
|
|
374
437
|
if (event.key === 'Enter') {
|
|
375
438
|
this.handleConfigClick?.(event);
|
|
376
439
|
}
|
|
377
440
|
}, style: {
|
|
378
|
-
cursor:
|
|
379
|
-
pointerEvents: hasNoConfig ? 'none' : 'auto',
|
|
441
|
+
cursor: 'pointer',
|
|
380
442
|
} }, this.activeControl.tool instanceof defaultLineTool_config.KritzelBrushTool && (index.h("div", { class: "color-container" }, index.h("kritzel-color", { value: this.activeToolAsBrushTool?.color, size: this.activeToolAsBrushTool?.size, style: {
|
|
381
443
|
borderRadius: '50%',
|
|
382
444
|
border: 'none',
|
|
383
|
-
} }))), this.activeControl.tool instanceof defaultLineTool_config.KritzelTextTool && (index.h("div", { class: "font-container" }, index.h("kritzel-font", { fontFamily: this.activeToolAsTextTool?.fontFamily, size: this.activeToolAsTextTool?.fontSize, color: this.activeToolAsTextTool?.fontColor })))
|
|
445
|
+
} }))), this.activeControl.tool instanceof defaultLineTool_config.KritzelTextTool && (index.h("div", { class: "font-container" }, index.h("kritzel-font", { fontFamily: this.activeToolAsTextTool?.fontFamily, size: this.activeToolAsTextTool?.fontSize, color: this.activeToolAsTextTool?.fontColor }))))));
|
|
384
446
|
}
|
|
385
447
|
}))));
|
|
386
448
|
}
|
|
@@ -575,6 +637,596 @@ const KritzelDropdown = class {
|
|
|
575
637
|
};
|
|
576
638
|
KritzelDropdown.style = kritzelDropdownCss;
|
|
577
639
|
|
|
640
|
+
var ShapeType;
|
|
641
|
+
(function (ShapeType) {
|
|
642
|
+
ShapeType["Rectangle"] = "rectangle";
|
|
643
|
+
ShapeType["Ellipse"] = "ellipse";
|
|
644
|
+
ShapeType["Triangle"] = "triangle";
|
|
645
|
+
})(ShapeType || (ShapeType = {}));
|
|
646
|
+
|
|
647
|
+
class KritzelShape extends defaultLineTool_config.KritzelBaseObject {
|
|
648
|
+
__class__ = 'KritzelShape';
|
|
649
|
+
shapeType = ShapeType.Rectangle;
|
|
650
|
+
fillColor = 'transparent';
|
|
651
|
+
strokeColor = '#000000';
|
|
652
|
+
strokeWidth = 4;
|
|
653
|
+
fontFamily = 'Arial';
|
|
654
|
+
fontSize = 16;
|
|
655
|
+
fontColor = '#000000';
|
|
656
|
+
/** Screen-space x coordinate of the shape's top-left corner (like Path.x) */
|
|
657
|
+
x = 0;
|
|
658
|
+
/** Screen-space y coordinate of the shape's top-left corner (like Path.y) */
|
|
659
|
+
y = 0;
|
|
660
|
+
scale = 1;
|
|
661
|
+
scaleFactor = 1;
|
|
662
|
+
isDebugInfoVisible = true;
|
|
663
|
+
isEditable = true;
|
|
664
|
+
isEditing = false;
|
|
665
|
+
editor = null;
|
|
666
|
+
content = null;
|
|
667
|
+
_schema = new defaultLineTool_config.Schema({
|
|
668
|
+
nodes: defaultLineTool_config.addListNodes(defaultLineTool_config.schema.spec.nodes, 'paragraph block*', 'block'),
|
|
669
|
+
marks: defaultLineTool_config.schema.spec.marks,
|
|
670
|
+
});
|
|
671
|
+
uneditedObject = null;
|
|
672
|
+
/**
|
|
673
|
+
* Returns the viewBox for the shape's SVG, using screen-space coordinates.
|
|
674
|
+
* This follows the same pattern as KritzelPath.viewBox.
|
|
675
|
+
*/
|
|
676
|
+
get viewBox() {
|
|
677
|
+
return `${this.x} ${this.y} ${this.width} ${this.height}`;
|
|
678
|
+
}
|
|
679
|
+
constructor(config) {
|
|
680
|
+
super();
|
|
681
|
+
if (config) {
|
|
682
|
+
this.x = config.x ?? 0;
|
|
683
|
+
this.y = config.y ?? 0;
|
|
684
|
+
this.translateX = config.translateX ?? 0;
|
|
685
|
+
this.translateY = config.translateY ?? 0;
|
|
686
|
+
this.width = config.width ?? 100;
|
|
687
|
+
this.height = config.height ?? 100;
|
|
688
|
+
this.shapeType = config.shapeType ?? ShapeType.Rectangle;
|
|
689
|
+
this.fillColor = config.fillColor ?? 'transparent';
|
|
690
|
+
this.strokeColor = config.strokeColor ?? '#000000';
|
|
691
|
+
this.strokeWidth = config.strokeWidth ?? 4;
|
|
692
|
+
this.fontSize = config.fontSize ?? 16;
|
|
693
|
+
this.fontFamily = config.fontFamily ?? 'Arial';
|
|
694
|
+
this.fontColor = config.fontColor ?? '#000000';
|
|
695
|
+
this.scale = config.scale ?? 1;
|
|
696
|
+
this.scaleFactor = config.scaleX ?? 1;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Creates a new KritzelShape with screen-space coordinates.
|
|
701
|
+
* Following the same pattern as KritzelPath.create():
|
|
702
|
+
* - x, y are screen-space coordinates of the shape's top-left corner
|
|
703
|
+
* - translateX, translateY should be set to -viewportTranslateX, -viewportTranslateY
|
|
704
|
+
* - width, height are in screen-space
|
|
705
|
+
* - scale is the viewport scale at creation time
|
|
706
|
+
*/
|
|
707
|
+
static create(core, config) {
|
|
708
|
+
const object = new KritzelShape();
|
|
709
|
+
object._core = core;
|
|
710
|
+
object.id = object.generateId();
|
|
711
|
+
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
712
|
+
object.x = config?.x ?? 0;
|
|
713
|
+
object.y = config?.y ?? 0;
|
|
714
|
+
object.translateX = config?.translateX ?? 0;
|
|
715
|
+
object.translateY = config?.translateY ?? 0;
|
|
716
|
+
object.width = config?.width ?? 100;
|
|
717
|
+
object.height = config?.height ?? 100;
|
|
718
|
+
object.shapeType = config?.shapeType ?? ShapeType.Rectangle;
|
|
719
|
+
object.fillColor = config?.fillColor ?? 'transparent';
|
|
720
|
+
object.strokeColor = config?.strokeColor ?? '#000000';
|
|
721
|
+
object.strokeWidth = config?.strokeWidth ?? 4;
|
|
722
|
+
object.fontSize = config?.fontSize ?? 16;
|
|
723
|
+
object.fontFamily = config?.fontFamily ?? 'Arial';
|
|
724
|
+
object.fontColor = config?.fontColor ?? '#000000';
|
|
725
|
+
object.backgroundColor = 'transparent';
|
|
726
|
+
object.scaleFactor = 1;
|
|
727
|
+
object.scale = core.store.state.scale;
|
|
728
|
+
object.zIndex = core.store.currentZIndex;
|
|
729
|
+
object.editor = object.createEditor();
|
|
730
|
+
// Compute world-space translateX/Y from screen-space coordinates
|
|
731
|
+
// This follows the same pattern as KritzelPath.updateDimensions()
|
|
732
|
+
object.updateDimensions();
|
|
733
|
+
return object;
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Updates the translateX/Y to world coordinates based on screen-space x, y.
|
|
737
|
+
* This follows the same pattern as KritzelPath.updateDimensions().
|
|
738
|
+
*
|
|
739
|
+
* The formula: translateX = (x + initialTranslateX) / scale
|
|
740
|
+
* where initialTranslateX was -viewportTranslateX
|
|
741
|
+
*
|
|
742
|
+
* This converts screen-space position to world coordinates.
|
|
743
|
+
*/
|
|
744
|
+
updateDimensions() {
|
|
745
|
+
this.translateX = (this.x + this.translateX) / this.scale;
|
|
746
|
+
this.translateY = (this.y + this.translateY) / this.scale;
|
|
747
|
+
}
|
|
748
|
+
mount(element) {
|
|
749
|
+
if (element === null || this.isInViewport() === false) {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
this.elementRef = element;
|
|
756
|
+
this.isMounted = true;
|
|
757
|
+
}
|
|
758
|
+
mountTextEditor(element) {
|
|
759
|
+
if (element === null) {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
if (this.editor.dom.parentElement === element) {
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
element.style.fontFamily = this.fontFamily;
|
|
766
|
+
element.style.fontSize = `${this.fontSize}pt`;
|
|
767
|
+
element.style.color = this.fontColor;
|
|
768
|
+
element.style.whiteSpace = 'pre-wrap';
|
|
769
|
+
element.style.wordWrap = 'break-word';
|
|
770
|
+
element.innerHTML = '';
|
|
771
|
+
element.appendChild(this.editor.dom);
|
|
772
|
+
}
|
|
773
|
+
createEditor() {
|
|
774
|
+
const doc = this._schema.node('doc', null, [this._schema.node('paragraph')]);
|
|
775
|
+
return new defaultLineTool_config.EditorView(null, {
|
|
776
|
+
state: defaultLineTool_config.EditorState.create({
|
|
777
|
+
doc: doc,
|
|
778
|
+
plugins: [defaultLineTool_config.keymap(defaultLineTool_config.baseKeymap)],
|
|
779
|
+
}),
|
|
780
|
+
editable: () => false,
|
|
781
|
+
dispatchTransaction: transaction => {
|
|
782
|
+
const newState = this.editor.state.apply(transaction);
|
|
783
|
+
this.editor.updateState(newState);
|
|
784
|
+
if (transaction.docChanged) {
|
|
785
|
+
this.content = newState.doc.toJSON();
|
|
786
|
+
if (!transaction.getMeta('fromRemote')) {
|
|
787
|
+
this._core.store.state.objects.update(this, { temporary: true });
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
},
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
setContent(content) {
|
|
794
|
+
this.content = content;
|
|
795
|
+
if (this.editor && content) {
|
|
796
|
+
const newDoc = this.editor.state.schema.nodeFromJSON(content);
|
|
797
|
+
const tr = this.editor.state.tr.replaceWith(0, this.editor.state.doc.content.size, newDoc.content);
|
|
798
|
+
tr.setMeta('fromRemote', true);
|
|
799
|
+
this.editor.dispatch(tr);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
resize(x, y, width, height) {
|
|
803
|
+
if (width <= 1 || height <= 1) {
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
this.width = width;
|
|
807
|
+
this.height = height;
|
|
808
|
+
this.translateX = x;
|
|
809
|
+
this.translateY = y;
|
|
810
|
+
this._core.store.state.objects.update(this);
|
|
811
|
+
}
|
|
812
|
+
focus(coords) {
|
|
813
|
+
if (this.editor) {
|
|
814
|
+
const doc = this.editor.state.doc;
|
|
815
|
+
if (coords?.x && coords?.y) {
|
|
816
|
+
const pos = this.editor.posAtCoords({ left: coords.x, top: coords.y });
|
|
817
|
+
if (pos) {
|
|
818
|
+
this.editor.dispatch(this.editor.state.tr.setSelection(defaultLineTool_config.TextSelection.create(doc, pos.pos)));
|
|
819
|
+
this.editor.focus();
|
|
820
|
+
if (defaultLineTool_config.KritzelDevicesHelper.isIOS()) {
|
|
821
|
+
this.scrollIntoViewOnIOS();
|
|
822
|
+
}
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
const end = Math.max(1, doc.content.size - 1);
|
|
827
|
+
this.editor.dispatch(this.editor.state.tr.setSelection(defaultLineTool_config.TextSelection.create(doc, end)));
|
|
828
|
+
this.editor.focus();
|
|
829
|
+
if (defaultLineTool_config.KritzelDevicesHelper.isIOS()) {
|
|
830
|
+
this.scrollIntoViewOnIOS();
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
scrollIntoViewOnIOS() {
|
|
835
|
+
setTimeout(() => {
|
|
836
|
+
if (this.editor && this.editor.dom) {
|
|
837
|
+
this.editor.dom.scrollIntoView({
|
|
838
|
+
behavior: 'smooth',
|
|
839
|
+
block: 'center',
|
|
840
|
+
inline: 'nearest',
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
}, 300);
|
|
844
|
+
}
|
|
845
|
+
edit(event) {
|
|
846
|
+
defaultLineTool_config.KritzelKeyboardHelper.disableInteractiveWidget();
|
|
847
|
+
this.uneditedObject = this.clone();
|
|
848
|
+
this._core.store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('shape'));
|
|
849
|
+
this.editor.setProps({ editable: () => true });
|
|
850
|
+
this.isEditing = true;
|
|
851
|
+
this._core.rerender();
|
|
852
|
+
this.focus({ x: event?.clientX, y: event?.clientY });
|
|
853
|
+
defaultLineTool_config.KritzelKeyboardHelper.enableInteractiveWidget();
|
|
854
|
+
}
|
|
855
|
+
save() {
|
|
856
|
+
this.content = this.editor.state.doc.toJSON();
|
|
857
|
+
this.editor.setProps({ editable: () => false });
|
|
858
|
+
this.editor.dom.blur();
|
|
859
|
+
this.isEditing = false;
|
|
860
|
+
this._core.store.state.objects.consolidateTemporaryItems();
|
|
861
|
+
this._core.store.state.objects.update(this);
|
|
862
|
+
this._core.engine.emitObjectsChange();
|
|
863
|
+
}
|
|
864
|
+
handlePointerDown(event) {
|
|
865
|
+
if (!this.isEditing) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
event.stopPropagation();
|
|
869
|
+
}
|
|
870
|
+
handlePointerMove(event) {
|
|
871
|
+
if (!this.isEditing) {
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
event.stopPropagation();
|
|
875
|
+
}
|
|
876
|
+
handlePointerUp(event) {
|
|
877
|
+
if (!this.isEditing) {
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
event.stopPropagation();
|
|
881
|
+
}
|
|
882
|
+
copy() {
|
|
883
|
+
const copiedObject = super.copy();
|
|
884
|
+
copiedObject.editor = copiedObject.createEditor();
|
|
885
|
+
if (this.content) {
|
|
886
|
+
copiedObject.setContent(this.content);
|
|
887
|
+
}
|
|
888
|
+
return copiedObject;
|
|
889
|
+
}
|
|
890
|
+
serialize() {
|
|
891
|
+
const { _core, _elementRef, _schema, element, totalWidth, totalHeight, editor, uneditedObject, ...remainingProps } = this;
|
|
892
|
+
const clonedProps = structuredClone(remainingProps);
|
|
893
|
+
if (element && typeof element === 'object' && 'nodeType' in element && element.nodeType === 1) {
|
|
894
|
+
clonedProps.element = element.cloneNode(true);
|
|
895
|
+
}
|
|
896
|
+
return clonedProps;
|
|
897
|
+
}
|
|
898
|
+
deserialize(object) {
|
|
899
|
+
super.deserialize(object);
|
|
900
|
+
if (object.content) {
|
|
901
|
+
this.setContent(object.content);
|
|
902
|
+
}
|
|
903
|
+
return this;
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* Returns the clipping polygon for arrow intersection.
|
|
907
|
+
* For ellipse: returns a many-sided polygon approximation
|
|
908
|
+
* For triangle: returns the 3 corners
|
|
909
|
+
* For rectangle: returns null (uses default rotatedPolygon)
|
|
910
|
+
*
|
|
911
|
+
* Includes padding for half the stroke width so arrow heads don't overlap the stroke.
|
|
912
|
+
*/
|
|
913
|
+
getClipPolygon() {
|
|
914
|
+
// Calculate world-space center and dimensions
|
|
915
|
+
const worldWidth = this.totalWidth / this.scale;
|
|
916
|
+
const worldHeight = this.totalHeight / this.scale;
|
|
917
|
+
const centerX = this.translateX + worldWidth / 2;
|
|
918
|
+
const centerY = this.translateY + worldHeight / 2;
|
|
919
|
+
// Add padding for stroke width so arrows don't overlap the stroke
|
|
920
|
+
const strokePadding = (this.strokeWidth / this.scale) / 2;
|
|
921
|
+
switch (this.shapeType) {
|
|
922
|
+
case ShapeType.Ellipse:
|
|
923
|
+
// Return a 32-segment polygon approximation of the ellipse
|
|
924
|
+
// Add stroke padding to radii
|
|
925
|
+
return defaultLineTool_config.KritzelGeometryHelper.getEllipsePolygonApproximation(centerX, centerY, worldWidth / 2 + strokePadding, worldHeight / 2 + strokePadding, 32, this.rotation);
|
|
926
|
+
case ShapeType.Triangle:
|
|
927
|
+
// Return the 3 corners of the triangle in world coordinates
|
|
928
|
+
// Triangle: top-center, bottom-right, bottom-left
|
|
929
|
+
// Expand each vertex outward from center by strokePadding
|
|
930
|
+
const expandVertex = (vx, vy) => {
|
|
931
|
+
const dx = vx - centerX;
|
|
932
|
+
const dy = vy - centerY;
|
|
933
|
+
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
934
|
+
if (dist === 0)
|
|
935
|
+
return { x: vx, y: vy };
|
|
936
|
+
const scale = (dist + strokePadding) / dist;
|
|
937
|
+
return {
|
|
938
|
+
x: centerX + dx * scale,
|
|
939
|
+
y: centerY + dy * scale
|
|
940
|
+
};
|
|
941
|
+
};
|
|
942
|
+
const topX = this.translateX + worldWidth / 2;
|
|
943
|
+
const topY = this.translateY;
|
|
944
|
+
const bottomLeftX = this.translateX;
|
|
945
|
+
const bottomLeftY = this.translateY + worldHeight;
|
|
946
|
+
const bottomRightX = this.translateX + worldWidth;
|
|
947
|
+
const bottomRightY = this.translateY + worldHeight;
|
|
948
|
+
const expandedTop = expandVertex(topX, topY);
|
|
949
|
+
const expandedBottomRight = expandVertex(bottomRightX, bottomRightY);
|
|
950
|
+
const expandedBottomLeft = expandVertex(bottomLeftX, bottomLeftY);
|
|
951
|
+
// Apply rotation around center if rotated
|
|
952
|
+
if (this.rotation !== 0) {
|
|
953
|
+
const cos = Math.cos(this.rotation);
|
|
954
|
+
const sin = Math.sin(this.rotation);
|
|
955
|
+
const rotate = (p) => {
|
|
956
|
+
const dx = p.x - centerX;
|
|
957
|
+
const dy = p.y - centerY;
|
|
958
|
+
return {
|
|
959
|
+
x: centerX + dx * cos - dy * sin,
|
|
960
|
+
y: centerY + dx * sin + dy * cos
|
|
961
|
+
};
|
|
962
|
+
};
|
|
963
|
+
return [
|
|
964
|
+
rotate(expandedTop),
|
|
965
|
+
rotate(expandedBottomRight),
|
|
966
|
+
rotate(expandedBottomLeft)
|
|
967
|
+
];
|
|
968
|
+
}
|
|
969
|
+
return [expandedTop, expandedBottomRight, expandedBottomLeft];
|
|
970
|
+
case ShapeType.Rectangle:
|
|
971
|
+
default:
|
|
972
|
+
// For rectangles, return null to use the default rotatedPolygon
|
|
973
|
+
return null;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* Returns the SVG path for rendering the shape.
|
|
978
|
+
* The path uses screen-space coordinates relative to (x, y).
|
|
979
|
+
*/
|
|
980
|
+
getSvgPath() {
|
|
981
|
+
const w = this.width;
|
|
982
|
+
const h = this.height;
|
|
983
|
+
switch (this.shapeType) {
|
|
984
|
+
case ShapeType.Rectangle:
|
|
985
|
+
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`;
|
|
986
|
+
case ShapeType.Ellipse:
|
|
987
|
+
const cx = this.x + w / 2;
|
|
988
|
+
const cy = this.y + h / 2;
|
|
989
|
+
const rx = w / 2;
|
|
990
|
+
const ry = h / 2;
|
|
991
|
+
return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;
|
|
992
|
+
case ShapeType.Triangle:
|
|
993
|
+
const topX = this.x + w / 2;
|
|
994
|
+
const topY = this.y;
|
|
995
|
+
const bottomLeftX = this.x;
|
|
996
|
+
const bottomLeftY = this.y + h;
|
|
997
|
+
const bottomRightX = this.x + w;
|
|
998
|
+
const bottomRightY = this.y + h;
|
|
999
|
+
return `M ${topX} ${topY} L ${bottomRightX} ${bottomRightY} L ${bottomLeftX} ${bottomLeftY} Z`;
|
|
1000
|
+
default:
|
|
1001
|
+
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`;
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
class KritzelShapeTool extends defaultLineTool_config.KritzelBaseTool {
|
|
1007
|
+
shapeType = ShapeType.Rectangle;
|
|
1008
|
+
fillColor = 'transparent';
|
|
1009
|
+
strokeColor = '#000000';
|
|
1010
|
+
strokeWidth = 4;
|
|
1011
|
+
fontFamily = 'Arial';
|
|
1012
|
+
fontSize = 16;
|
|
1013
|
+
fontColor = '#000000';
|
|
1014
|
+
palette = [
|
|
1015
|
+
'#000000',
|
|
1016
|
+
'#FFFFFF',
|
|
1017
|
+
'#FF0000',
|
|
1018
|
+
'#00FF00',
|
|
1019
|
+
'#0000FF',
|
|
1020
|
+
'#FFFF00',
|
|
1021
|
+
'#FF00FF',
|
|
1022
|
+
'#00FFFF',
|
|
1023
|
+
'#808080',
|
|
1024
|
+
'#C0C0C0',
|
|
1025
|
+
'#800000',
|
|
1026
|
+
'#008000',
|
|
1027
|
+
'#000080',
|
|
1028
|
+
'#808000',
|
|
1029
|
+
'#800080',
|
|
1030
|
+
];
|
|
1031
|
+
startX = 0;
|
|
1032
|
+
startY = 0;
|
|
1033
|
+
isDrawing = false;
|
|
1034
|
+
currentShape = null;
|
|
1035
|
+
constructor(core) {
|
|
1036
|
+
super(core);
|
|
1037
|
+
}
|
|
1038
|
+
handlePointerDown(event) {
|
|
1039
|
+
if (event.cancelable) {
|
|
1040
|
+
event.preventDefault();
|
|
1041
|
+
}
|
|
1042
|
+
if (event.pointerType === 'mouse') {
|
|
1043
|
+
const path = event.composedPath().slice(1);
|
|
1044
|
+
const objectElement = path.find(element => element.classList && element.classList.contains('object'));
|
|
1045
|
+
const object = this._core.findObjectById(objectElement?.id);
|
|
1046
|
+
const activeShape = this._core.store.activeShape;
|
|
1047
|
+
if (activeShape === null && object instanceof KritzelShape) {
|
|
1048
|
+
object.edit(event);
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
if (activeShape !== null && object instanceof KritzelShape) {
|
|
1052
|
+
activeShape.save();
|
|
1053
|
+
object.edit(event);
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
if (activeShape !== null && object instanceof KritzelShape === false) {
|
|
1057
|
+
this._core.resetActiveShape();
|
|
1058
|
+
this._core.store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('selection'));
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
if (defaultLineTool_config.KritzelEventHelper.isLeftClick(event) === false) {
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1064
|
+
this.startDrawing(event.clientX, event.clientY);
|
|
1065
|
+
}
|
|
1066
|
+
if (event.pointerType === 'touch') {
|
|
1067
|
+
const activePointers = Array.from(this._core.store.state.pointers.values());
|
|
1068
|
+
const path = event.composedPath().slice(1);
|
|
1069
|
+
const objectElement = path.find(element => element.classList && element.classList.contains('object'));
|
|
1070
|
+
const object = this._core.findObjectById(objectElement?.id);
|
|
1071
|
+
const activeShape = this._core.store.activeShape;
|
|
1072
|
+
if (activeShape === null && object instanceof KritzelShape) {
|
|
1073
|
+
object.edit(event);
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
if (activeShape !== null && object instanceof KritzelShape) {
|
|
1077
|
+
activeShape.save();
|
|
1078
|
+
object.edit(event);
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
if (activeShape !== null && object instanceof KritzelShape === false) {
|
|
1082
|
+
this._core.resetActiveShape();
|
|
1083
|
+
this._core.store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('selection'));
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
if (activePointers.length > 1) {
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
const clientX = Math.round(activePointers[0].clientX);
|
|
1090
|
+
const clientY = Math.round(activePointers[0].clientY);
|
|
1091
|
+
this.startDrawing(clientX, clientY);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
handlePointerMove(event) {
|
|
1095
|
+
if (event.cancelable) {
|
|
1096
|
+
event.preventDefault();
|
|
1097
|
+
}
|
|
1098
|
+
if (!this.isDrawing || !this.currentShape) {
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
if (event.pointerType === 'mouse') {
|
|
1102
|
+
this.updateShapeSize(event.clientX, event.clientY);
|
|
1103
|
+
}
|
|
1104
|
+
if (event.pointerType === 'touch') {
|
|
1105
|
+
const activePointers = Array.from(this._core.store.state.pointers.values());
|
|
1106
|
+
if (activePointers.length === 1) {
|
|
1107
|
+
const clientX = Math.round(activePointers[0].clientX);
|
|
1108
|
+
const clientY = Math.round(activePointers[0].clientY);
|
|
1109
|
+
this.updateShapeSize(clientX, clientY);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
handlePointerUp(event) {
|
|
1114
|
+
if (event.cancelable) {
|
|
1115
|
+
event.preventDefault();
|
|
1116
|
+
}
|
|
1117
|
+
if (!this.isDrawing || !this.currentShape) {
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1120
|
+
this.finishDrawing();
|
|
1121
|
+
}
|
|
1122
|
+
/**
|
|
1123
|
+
* Start drawing a shape. Following the same pattern as LineTool/BrushTool:
|
|
1124
|
+
* - Store screen coordinates for startX, startY
|
|
1125
|
+
* - Set translateX/Y to -viewportTranslateX/Y (viewport offset)
|
|
1126
|
+
* - Set x, y to the actual screen position
|
|
1127
|
+
* - Let updateDimensions() convert to world coordinates
|
|
1128
|
+
*/
|
|
1129
|
+
startDrawing(clientX, clientY) {
|
|
1130
|
+
// Store screen coordinates (relative to host element)
|
|
1131
|
+
this.startX = clientX - this._core.store.offsetX;
|
|
1132
|
+
this.startY = clientY - this._core.store.offsetY;
|
|
1133
|
+
this.isDrawing = true;
|
|
1134
|
+
// Create shape using screen coordinates, following Path/Line pattern
|
|
1135
|
+
this.currentShape = KritzelShape.create(this._core, {
|
|
1136
|
+
x: this.startX,
|
|
1137
|
+
y: this.startY,
|
|
1138
|
+
translateX: -this._core.store.state.translateX,
|
|
1139
|
+
translateY: -this._core.store.state.translateY,
|
|
1140
|
+
width: 1,
|
|
1141
|
+
height: 1,
|
|
1142
|
+
shapeType: this.shapeType,
|
|
1143
|
+
fillColor: this.fillColor,
|
|
1144
|
+
strokeColor: this.strokeColor,
|
|
1145
|
+
strokeWidth: this.strokeWidth,
|
|
1146
|
+
fontSize: this.fontSize,
|
|
1147
|
+
fontFamily: this.fontFamily,
|
|
1148
|
+
fontColor: this.fontColor,
|
|
1149
|
+
});
|
|
1150
|
+
this._core.store.state.objects.insert(this.currentShape);
|
|
1151
|
+
this._core.rerender();
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Update shape size during drawing. Following the same pattern as LineTool:
|
|
1155
|
+
* - Use screen coordinates directly
|
|
1156
|
+
* - The shape's x, y, width, height are all in screen space
|
|
1157
|
+
* - updateDimensions() handles conversion to world coordinates
|
|
1158
|
+
*/
|
|
1159
|
+
updateShapeSize(clientX, clientY) {
|
|
1160
|
+
if (!this.currentShape) {
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
const currentX = clientX - this._core.store.offsetX;
|
|
1164
|
+
const currentY = clientY - this._core.store.offsetY;
|
|
1165
|
+
// Calculate bounding box in screen coordinates
|
|
1166
|
+
const minX = Math.min(this.startX, currentX);
|
|
1167
|
+
const minY = Math.min(this.startY, currentY);
|
|
1168
|
+
const width = Math.abs(currentX - this.startX);
|
|
1169
|
+
const height = Math.abs(currentY - this.startY);
|
|
1170
|
+
// Update shape with screen coordinates
|
|
1171
|
+
this.currentShape.x = minX;
|
|
1172
|
+
this.currentShape.y = minY;
|
|
1173
|
+
this.currentShape.width = Math.max(1, width);
|
|
1174
|
+
this.currentShape.height = Math.max(1, height);
|
|
1175
|
+
// Recalculate world-space translateX/Y
|
|
1176
|
+
// Reset translateX/Y to initial value before updateDimensions
|
|
1177
|
+
this.currentShape.translateX = -this._core.store.state.translateX;
|
|
1178
|
+
this.currentShape.translateY = -this._core.store.state.translateY;
|
|
1179
|
+
this.currentShape.updateDimensions();
|
|
1180
|
+
this._core.store.state.objects.update(this.currentShape);
|
|
1181
|
+
}
|
|
1182
|
+
finishDrawing() {
|
|
1183
|
+
if (!this.currentShape) {
|
|
1184
|
+
return;
|
|
1185
|
+
}
|
|
1186
|
+
// Remove shape if it's too small (likely an accidental click)
|
|
1187
|
+
// Compare in screen space
|
|
1188
|
+
if (this.currentShape.width < 10 && this.currentShape.height < 10) {
|
|
1189
|
+
const shapeId = this.currentShape.id;
|
|
1190
|
+
this._core.store.state.objects.remove(o => o.id === shapeId);
|
|
1191
|
+
}
|
|
1192
|
+
else {
|
|
1193
|
+
this.currentShape.zIndex = this._core.store.currentZIndex;
|
|
1194
|
+
this._core.store.state.objects.update(this.currentShape);
|
|
1195
|
+
this._core.engine.emitObjectsChange();
|
|
1196
|
+
this._core.selectObjects([this.currentShape]);
|
|
1197
|
+
this._core.store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('selection'));
|
|
1198
|
+
}
|
|
1199
|
+
this.isDrawing = false;
|
|
1200
|
+
this.currentShape = null;
|
|
1201
|
+
this._core.rerender();
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
const DEFAULT_SHAPE_CONFIG = {
|
|
1206
|
+
shapeType: ShapeType.Rectangle,
|
|
1207
|
+
fillColor: 'transparent',
|
|
1208
|
+
strokeColor: '#000000',
|
|
1209
|
+
strokeWidth: 4,
|
|
1210
|
+
fontColor: '#000000',
|
|
1211
|
+
fontSize: 16,
|
|
1212
|
+
fontFamily: 'Arial',
|
|
1213
|
+
palette: [
|
|
1214
|
+
'#000000',
|
|
1215
|
+
'#ff5252',
|
|
1216
|
+
'#ffbc00',
|
|
1217
|
+
'#00c853',
|
|
1218
|
+
'#0000FF',
|
|
1219
|
+
'#d500f9',
|
|
1220
|
+
'#fafafa',
|
|
1221
|
+
'#a52714',
|
|
1222
|
+
'#ee8100',
|
|
1223
|
+
'#558b2f',
|
|
1224
|
+
'#01579b',
|
|
1225
|
+
'#8e24aa',
|
|
1226
|
+
'#90a4ae',
|
|
1227
|
+
],
|
|
1228
|
+
};
|
|
1229
|
+
|
|
578
1230
|
const ABSOLUTE_SCALE_MAX = 1000;
|
|
579
1231
|
const ABSOLUTE_SCALE_MIN = 0.0001;
|
|
580
1232
|
|
|
@@ -625,16 +1277,24 @@ const KritzelEditor = class {
|
|
|
625
1277
|
icon: 'type',
|
|
626
1278
|
config: defaultLineTool_config.DEFAULT_TEXT_CONFIG,
|
|
627
1279
|
},
|
|
1280
|
+
{
|
|
1281
|
+
name: 'shape',
|
|
1282
|
+
type: 'tool',
|
|
1283
|
+
tool: KritzelShapeTool,
|
|
1284
|
+
icon: 'shape-rectangle',
|
|
1285
|
+
config: DEFAULT_SHAPE_CONFIG,
|
|
1286
|
+
subOptions: [
|
|
1287
|
+
{ id: 'rectangle', icon: 'shape-rectangle', label: 'Rectangle', value: ShapeType.Rectangle, toolProperty: 'shapeType' },
|
|
1288
|
+
{ id: 'ellipse', icon: 'shape-ellipse', label: 'Ellipse', value: ShapeType.Ellipse, toolProperty: 'shapeType' },
|
|
1289
|
+
{ id: 'triangle', icon: 'shape-triangle', label: 'Triangle', value: ShapeType.Triangle, toolProperty: 'shapeType' },
|
|
1290
|
+
],
|
|
1291
|
+
},
|
|
628
1292
|
{
|
|
629
1293
|
name: 'image',
|
|
630
1294
|
type: 'tool',
|
|
631
1295
|
tool: defaultLineTool_config.KritzelImageTool,
|
|
632
1296
|
icon: 'image',
|
|
633
1297
|
},
|
|
634
|
-
{
|
|
635
|
-
name: 'divider',
|
|
636
|
-
type: 'divider',
|
|
637
|
-
},
|
|
638
1298
|
{
|
|
639
1299
|
name: 'config',
|
|
640
1300
|
type: 'config',
|
|
@@ -811,7 +1471,7 @@ const KritzelEditor = class {
|
|
|
811
1471
|
}
|
|
812
1472
|
}
|
|
813
1473
|
render() {
|
|
814
|
-
return (index.h(index.Host, { key: '
|
|
1474
|
+
return (index.h(index.Host, { key: 'a39268fb2722bc9e1627a46a3430a574322dfdfb' }, index.h("kritzel-workspace-manager", { key: 'b0c08f2cab64347c0ee14a87ed0ab769a2e95733', workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), index.h("kritzel-engine", { key: 'c0efb9b0cdfdf3a9ba945e71e37c60ebfc45e981', 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: '5a275fb94e2f55a1f79d6d5b5f518305cd739f24', 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) })));
|
|
815
1475
|
}
|
|
816
1476
|
static get watchers() { return {
|
|
817
1477
|
"isEngineReady": ["onIsEngineReady"],
|
|
@@ -18056,6 +18716,14 @@ class KritzelViewport {
|
|
|
18056
18716
|
this._core.rerender();
|
|
18057
18717
|
}, 100);
|
|
18058
18718
|
}
|
|
18719
|
+
/**
|
|
18720
|
+
* Cancels any pending debounced viewport updates.
|
|
18721
|
+
* Should be called before switching workspaces to prevent the old workspace's
|
|
18722
|
+
* viewport state from being saved to the new workspace.
|
|
18723
|
+
*/
|
|
18724
|
+
cancelPendingUpdates() {
|
|
18725
|
+
this._debounceUpdate.cancel();
|
|
18726
|
+
}
|
|
18059
18727
|
handleResize() {
|
|
18060
18728
|
this._core.store.state.viewportWidth = this._core.store.state.host.clientWidth;
|
|
18061
18729
|
this._core.store.state.viewportHeight = this._core.store.state.host.clientHeight;
|
|
@@ -18477,6 +19145,17 @@ class KritzelReviver {
|
|
|
18477
19145
|
case 'KritzelText':
|
|
18478
19146
|
revivedObj = defaultLineTool_config.KritzelText.create(this._core, obj.fontSize, obj.fontFamily).deserialize(obj);
|
|
18479
19147
|
break;
|
|
19148
|
+
case 'KritzelShape':
|
|
19149
|
+
revivedObj = KritzelShape.create(this._core, {
|
|
19150
|
+
shapeType: obj.shapeType,
|
|
19151
|
+
fillColor: obj.fillColor,
|
|
19152
|
+
strokeColor: obj.strokeColor,
|
|
19153
|
+
strokeWidth: obj.strokeWidth,
|
|
19154
|
+
fontSize: obj.fontSize,
|
|
19155
|
+
fontFamily: obj.fontFamily,
|
|
19156
|
+
fontColor: obj.fontColor,
|
|
19157
|
+
}).deserialize(obj);
|
|
19158
|
+
break;
|
|
18480
19159
|
case 'KritzelImage':
|
|
18481
19160
|
revivedObj = defaultLineTool_config.KritzelImage.create(this._core).deserialize(obj);
|
|
18482
19161
|
break;
|
|
@@ -18507,6 +19186,9 @@ class KritzelReviver {
|
|
|
18507
19186
|
case 'KritzelLineTool':
|
|
18508
19187
|
revivedObj = new defaultLineTool_config.KritzelLineTool(this._core);
|
|
18509
19188
|
break;
|
|
19189
|
+
case 'KritzelShapeTool':
|
|
19190
|
+
revivedObj = new KritzelShapeTool(this._core);
|
|
19191
|
+
break;
|
|
18510
19192
|
default:
|
|
18511
19193
|
revivedObj = obj;
|
|
18512
19194
|
}
|
|
@@ -18982,6 +19664,10 @@ class KritzelStore {
|
|
|
18982
19664
|
const activeTexts = this._state.objects.filter(o => o instanceof defaultLineTool_config.KritzelText && o.isEditing);
|
|
18983
19665
|
return activeTexts.length > 0 ? activeTexts[0] : null;
|
|
18984
19666
|
}
|
|
19667
|
+
get activeShape() {
|
|
19668
|
+
const activeShapes = this._state.objects.filter(o => o instanceof KritzelShape && o.isEditing);
|
|
19669
|
+
return activeShapes.length > 0 ? activeShapes[0] : null;
|
|
19670
|
+
}
|
|
18985
19671
|
get currentPath() {
|
|
18986
19672
|
const drawingPaths = this._state.objects.filter(o => o instanceof defaultLineTool_config.KritzelPath && o.isCompleted === false);
|
|
18987
19673
|
return drawingPaths.length > 0 ? drawingPaths[0] : null;
|
|
@@ -19230,6 +19916,11 @@ class KritzelCore {
|
|
|
19230
19916
|
if (this._store.state.objects && this._store.state.objects.isReady) {
|
|
19231
19917
|
this._store.state.objects.destroy();
|
|
19232
19918
|
}
|
|
19919
|
+
// Create new ObjectMap with its own Y.Doc for this workspace
|
|
19920
|
+
const objectsMap = new KritzelObjectMap();
|
|
19921
|
+
// Assign immediately so the UI shows an empty state while loading,
|
|
19922
|
+
// instead of showing the old workspace's objects with the new workspace's viewport
|
|
19923
|
+
this._store.state.objects = objectsMap;
|
|
19233
19924
|
// Set active workspace
|
|
19234
19925
|
this._store.state.activeWorkspace = activeWorkspace;
|
|
19235
19926
|
this._store.state.workspaces = this.loadWorkspacesFromAppState();
|
|
@@ -19238,10 +19929,7 @@ class KritzelCore {
|
|
|
19238
19929
|
this._store.state.translateX = viewport.translateX ?? 0;
|
|
19239
19930
|
this._store.state.translateY = viewport.translateY ?? 0;
|
|
19240
19931
|
this._store.state.scale = viewport.scale ?? 1;
|
|
19241
|
-
// Create new ObjectMap with its own Y.Doc for this workspace
|
|
19242
|
-
const objectsMap = new KritzelObjectMap();
|
|
19243
19932
|
await objectsMap.initialize(this, activeWorkspace.id, this._syncConfig);
|
|
19244
|
-
this._store.state.objects = objectsMap;
|
|
19245
19933
|
// Rebuild anchor index after loading objects
|
|
19246
19934
|
this._anchorManager.rebuildIndex();
|
|
19247
19935
|
this.engine.emitObjectsChange();
|
|
@@ -19618,6 +20306,12 @@ class KritzelCore {
|
|
|
19618
20306
|
}
|
|
19619
20307
|
}
|
|
19620
20308
|
}
|
|
20309
|
+
resetActiveShape() {
|
|
20310
|
+
const activeShape = this._store.activeShape;
|
|
20311
|
+
if (activeShape) {
|
|
20312
|
+
activeShape.save();
|
|
20313
|
+
}
|
|
20314
|
+
}
|
|
19621
20315
|
getObjectFromPointerEvent(event, selector = '.object') {
|
|
19622
20316
|
const shadowRoot = this._store.state.host?.shadowRoot;
|
|
19623
20317
|
if (!shadowRoot)
|
|
@@ -19690,6 +20384,14 @@ class KritzelCore {
|
|
|
19690
20384
|
return { x: worldX, y: worldY };
|
|
19691
20385
|
}
|
|
19692
20386
|
beforeWorkspaceChange() {
|
|
20387
|
+
// Cancel any pending debounced viewport updates to prevent them from
|
|
20388
|
+
// saving the old workspace's viewport to the new workspace
|
|
20389
|
+
this._kritzelEngine.viewport?.cancelPendingUpdates();
|
|
20390
|
+
// Immediately save the current workspace's viewport before switching
|
|
20391
|
+
const currentWorkspace = this._store.state.activeWorkspace;
|
|
20392
|
+
if (currentWorkspace) {
|
|
20393
|
+
this.updateWorkspaceViewport(this._store.state.translateX, this._store.state.translateY, this._store.state.scale);
|
|
20394
|
+
}
|
|
19693
20395
|
this.resetActiveText();
|
|
19694
20396
|
this.clearSelection();
|
|
19695
20397
|
this._store.setState('activeTool', defaultLineTool_config.KritzelToolRegistry.getTool('selection'));
|
|
@@ -20115,9 +20817,9 @@ const KritzelEngine = class {
|
|
|
20115
20817
|
height: this.core.store.state.viewportHeight / this.core.store.state.scale,
|
|
20116
20818
|
depth: 100,
|
|
20117
20819
|
};
|
|
20118
|
-
const visibleObjects = this.core.store.state.objects.query(viewportBounds);
|
|
20820
|
+
const visibleObjects = this.core.store.state.objects.query(viewportBounds).sort((a, b) => a.zIndex - b.zIndex);
|
|
20119
20821
|
this.core.cursorManager.applyCursor();
|
|
20120
|
-
return (index.h(index.Host, { key: '
|
|
20822
|
+
return (index.h(index.Host, { key: '209ccf8414c635c9e04ca4807c95a29c629071ec' }, this.core.store.state.debugInfo.showViewportInfo && (index.h("div", { key: 'df6a03d1341887960bb91cbaa0a5dca6880a9293', class: "debug-panel" }, index.h("div", { key: '65157757ec6549ad2af311085a9618ab661f5ac0' }, "ActiveWorkspaceId: ", this.core.store.state?.activeWorkspace?.id), index.h("div", { key: '20137b6c651a9aa8df15bce66d5bfe870a7af139' }, "ActiveWorkspaceName: ", this.core.store.state?.activeWorkspace?.name), index.h("div", { key: '49dd30286641236ae428c731bb181cb06269852e' }, "TranslateX: ", this.core.store.state?.translateX), index.h("div", { key: 'd8ee431a10335e99aec40a596817765d7ee3f67b' }, "TranslateY: ", this.core.store.state?.translateY), index.h("div", { key: '34b1f31146080780433d6c1718d13bbfe397cb9b' }, "ViewportWidth: ", this.core.store.state?.viewportWidth), index.h("div", { key: '4c279a106101cf808c91a2be4987569b21ae52b3' }, "ViewportHeight: ", this.core.store.state?.viewportHeight), index.h("div", { key: '6ebd7ad3c803ef45d58a74180c52e8be8af8bca3' }, "PointerCount: ", this.core.store.state.pointers.size), index.h("div", { key: '345970c8b2b54f3a0d8fe1d9bb1b7b33023db386' }, "Scale: ", this.core.store.state?.scale), index.h("div", { key: 'fc265ae0e71cf22311cab3006dfc29b9d24397d2' }, "ActiveTool: ", this.core.store.state?.activeTool?.name), index.h("div", { key: '9f921032a58b55e60f82d11a76f269051357d3e1' }, "HasViewportChanged: ", this.core.store.state?.hasViewportChanged ? 'true' : 'false'), index.h("div", { key: '6d197e06cc362a9ecb8bfe00d272aecfec2b49e1' }, "IsEnabled: ", this.core.store.state?.isEnabled ? 'true' : 'false'), index.h("div", { key: '5313589ba2a509c95a5730dcf29c4003d9884cbf' }, "IsScaling: ", this.core.store.state?.isScaling ? 'true' : 'false'), index.h("div", { key: '8af9f9d6e33a2897c20962048bbf2a058f9d4a45' }, "IsPanning: ", this.core.store.state?.isPanning ? 'true' : 'false'), index.h("div", { key: '81aec0050d3e2122643b61fd725e71b25d97bc27' }, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), index.h("div", { key: 'c9956f05c01b74ee1666d9395a2715c3463fe401' }, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), index.h("div", { key: 'ae0a01c8f8aafc08326b136720c6a75b6aec6299' }, "IsResizeHandleSelected: ", this.core.store.state.isResizeHandleSelected ? 'true' : 'false'), index.h("div", { key: '7816d40d73248a55120440e6d721325e1894178e' }, "IsRotationHandleSelected: ", this.core.store.state.isRotationHandleSelected ? 'true' : 'false'), index.h("div", { key: 'c22383bacca0ada584f2e8a8577523c905d74ae2' }, "IsRotationHandleHovered: ", this.core.store.state.isRotationHandleHovered ? 'true' : 'false'), index.h("div", { key: '8185a7318c6cdfde558cc372b79582d58b706f9e' }, "IsDrawing: ", this.core.store.state.isDrawing ? 'true' : 'false'), index.h("div", { key: '2d56b05377693ef032ab2316fa753ecedf264b9c' }, "IsWriting: ", this.core.store.state.isWriting ? 'true' : 'false'), index.h("div", { key: '2e2bf9fd321ef04dc0ac6dc21539eb0117c9fb23' }, "IsPointerDown: ", this.core.store.isPointerDown ? 'true' : 'false'), index.h("div", { key: '3118ab970d5d37e01405c42308fc051d675d4bfa' }, "PointerX: ", this.core.store.state?.pointerX), index.h("div", { key: 'd8a31065843f89552f2d9c03dcbca960a716fa6c' }, "PointerY: ", this.core.store.state?.pointerY), index.h("div", { key: 'cb8d28b6ea63cbb6572f761011fccb847b748227' }, "SelectedObjects: ", this.core.store.selectionGroup?.objects.length || 0), index.h("div", { key: 'd112a7e833c265085246817423557bfdc5b30b74' }, "ViewportCenter: (", viewportCenterX.toFixed(2), ", ", viewportCenterY.toFixed(2), ")"))), index.h("div", { key: 'df4f302192a8fc9644b7f883618b0a0f8a600dc8', id: "origin", class: "origin", style: {
|
|
20121
20823
|
transform: `matrix(${this.core.store.state?.scale}, 0, 0, ${this.core.store.state?.scale}, ${this.core.store.state?.translateX}, ${this.core.store.state?.translateY})`,
|
|
20122
20824
|
} }, visibleObjects?.map(object => {
|
|
20123
20825
|
return (index.h("div", { key: object.id, style: {
|
|
@@ -20163,7 +20865,32 @@ const KritzelEngine = class {
|
|
|
20163
20865
|
backgroundColor: object.backgroundColor,
|
|
20164
20866
|
overflow: 'visible',
|
|
20165
20867
|
textRendering: this.core.store.state.isScaling || this.core.store.state.isPanning ? 'optimizeSpeed' : 'auto',
|
|
20166
|
-
} })), defaultLineTool_config.KritzelClassHelper.isInstanceOf(object, '
|
|
20868
|
+
} })), defaultLineTool_config.KritzelClassHelper.isInstanceOf(object, 'KritzelShape') && (index.h("div", { ref: el => object.mount(el), onPointerDown: e => object.handlePointerDown(e), onPointerMove: e => object.handlePointerMove(e), onPointerUp: e => object.handlePointerUp(e), style: {
|
|
20869
|
+
width: '100%',
|
|
20870
|
+
height: '100%',
|
|
20871
|
+
position: 'relative',
|
|
20872
|
+
overflow: 'visible',
|
|
20873
|
+
} }, index.h("svg", { xmlns: "http://www.w3.org/2000/svg", style: {
|
|
20874
|
+
position: 'absolute',
|
|
20875
|
+
top: '0',
|
|
20876
|
+
left: '0',
|
|
20877
|
+
width: '100%',
|
|
20878
|
+
height: '100%',
|
|
20879
|
+
overflow: 'visible',
|
|
20880
|
+
pointerEvents: 'none',
|
|
20881
|
+
}, viewBox: object.viewBox, preserveAspectRatio: "none" }, index.h("path", { d: object.getSvgPath(), fill: object.fillColor, stroke: object.strokeColor, "stroke-width": object.strokeWidth })), index.h("div", { ref: el => object.mountTextEditor(el), style: {
|
|
20882
|
+
position: 'absolute',
|
|
20883
|
+
top: '0',
|
|
20884
|
+
left: '0',
|
|
20885
|
+
width: '100%',
|
|
20886
|
+
height: '100%',
|
|
20887
|
+
display: 'flex',
|
|
20888
|
+
alignItems: 'center',
|
|
20889
|
+
justifyContent: 'center',
|
|
20890
|
+
textAlign: 'center',
|
|
20891
|
+
overflow: 'hidden',
|
|
20892
|
+
pointerEvents: object.isEditing ? 'auto' : 'none',
|
|
20893
|
+
} }))), defaultLineTool_config.KritzelClassHelper.isInstanceOf(object, 'KritzelCustomElement') && (index.h("div", { ref: el => object.mount(el), style: {
|
|
20167
20894
|
width: '100%',
|
|
20168
20895
|
height: '100%',
|
|
20169
20896
|
pointerEvents: 'auto',
|
|
@@ -20179,7 +20906,13 @@ const KritzelEngine = class {
|
|
|
20179
20906
|
borderWidth: defaultLineTool_config.KritzelDevicesHelper.isFirefox() ? object.borderWidth + 'px' : '0',
|
|
20180
20907
|
borderStyle: defaultLineTool_config.KritzelDevicesHelper.isFirefox() ? 'solid' : 'none',
|
|
20181
20908
|
borderColor: defaultLineTool_config.KritzelDevicesHelper.isFirefox() ? object.borderColor : 'transparent',
|
|
20182
|
-
} }))), this.core.store.state.debugInfo.showObjectInfo && object.isDebugInfoVisible && (index.h("
|
|
20909
|
+
} })))), this.core.store.state.debugInfo.showObjectInfo && object.isDebugInfoVisible && (index.h("div", { style: {
|
|
20910
|
+
pointerEvents: 'none',
|
|
20911
|
+
position: 'absolute',
|
|
20912
|
+
left: `${object.totalWidth}px`,
|
|
20913
|
+
top: '0',
|
|
20914
|
+
zIndex: (object.zIndex + 2).toString(),
|
|
20915
|
+
} }, index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "Id: ", object.id), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "width: ", object.width), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "height: ", object.height), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateX: ", object.translateX), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateY: ", object.translateY), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "rotationDegrees: ", object.rotationDegrees), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "zIndex: ", object.zIndex))), index.h("svg", { xmlns: "http://www.w3.org/2000/svg", style: {
|
|
20183
20916
|
zIndex: (object.zIndex + 1).toString(),
|
|
20184
20917
|
height: object?.totalHeight.toString(),
|
|
20185
20918
|
width: object?.totalWidth.toString(),
|
|
@@ -20335,7 +21068,7 @@ const KritzelEngine = class {
|
|
|
20335
21068
|
stroke: 'var(--kritzel-snap-indicator-stroke, #3b82f6)',
|
|
20336
21069
|
strokeWidth: data.indicatorStrokeWidth,
|
|
20337
21070
|
} }))));
|
|
20338
|
-
})()), this.core.store.state.isContextMenuVisible && (index.h("kritzel-context-menu", { key: '
|
|
21071
|
+
})()), this.core.store.state.isContextMenuVisible && (index.h("kritzel-context-menu", { key: '81b44614c23f4016a1daa914ef8ea73eda0869eb', class: "context-menu", ref: el => (this.contextMenuElement = el), items: this.core.store.state.contextMenuItems, objects: this.core.store.selectionGroup?.objects || [], style: {
|
|
20339
21072
|
position: 'fixed',
|
|
20340
21073
|
left: `${this.core.store.state.contextMenuX}px`,
|
|
20341
21074
|
top: `${this.core.store.state.contextMenuY}px`,
|
|
@@ -20346,7 +21079,7 @@ const KritzelEngine = class {
|
|
|
20346
21079
|
y: (-this.core.store.state.translateY + this.core.store.state.contextMenuY) / this.core.store.state.scale,
|
|
20347
21080
|
}, this.core.store.selectionGroup?.objects);
|
|
20348
21081
|
this.hideContextMenu();
|
|
20349
|
-
}, onClose: () => this.hideContextMenu() })), this.core.store.state?.activeTool instanceof defaultLineTool_config.KritzelEraserTool && !this.core.store.state.isScaling && index.h("kritzel-cursor-trail", { key: '
|
|
21082
|
+
}, onClose: () => this.hideContextMenu() })), this.core.store.state?.activeTool instanceof defaultLineTool_config.KritzelEraserTool && !this.core.store.state.isScaling && index.h("kritzel-cursor-trail", { key: 'f748cd15c916d9fcb5fbf445167c69c1cc8aea63', core: this.core })));
|
|
20350
21083
|
}
|
|
20351
21084
|
static get watchers() { return {
|
|
20352
21085
|
"workspace": ["onWorkspaceChange"],
|