@kritzel/editor 0.4.31 → 0.4.32
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/LICENSE.md +50 -50
- package/README.md +5 -5
- package/dist/cjs/{index-B92VHWr4.js → index-q_Tg9KUw.js} +12 -0
- package/dist/cjs/kritzel-active-users_46.cjs.entry.js +981 -322
- package/dist/cjs/kritzel-brush-style.cjs.entry.js +2 -2
- package/dist/cjs/kritzel-editor.cjs.js +2 -2
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/collection/components/kritzel-active-users/kritzel-active-users.css +65 -65
- package/dist/collection/components/kritzel-avatar/kritzel-avatar.css +58 -58
- package/dist/collection/components/kritzel-avatar/kritzel-avatar.js +3 -3
- package/dist/collection/components/kritzel-back-to-content/kritzel-back-to-content.css +42 -42
- package/dist/collection/components/kritzel-back-to-content/kritzel-back-to-content.js +1 -1
- package/dist/collection/components/kritzel-brush-style/kritzel-brush-style.css +42 -42
- package/dist/collection/components/kritzel-brush-style/kritzel-brush-style.js +3 -3
- package/dist/collection/components/kritzel-button/kritzel-button.css +73 -73
- package/dist/collection/components/kritzel-button/kritzel-button.js +2 -2
- package/dist/collection/components/kritzel-color/kritzel-color.css +24 -24
- package/dist/collection/components/kritzel-color/kritzel-color.js +2 -2
- package/dist/collection/components/kritzel-color-palette/kritzel-color-palette.css +46 -46
- package/dist/collection/components/kritzel-color-palette/kritzel-color-palette.js +1 -1
- package/dist/collection/components/kritzel-context-menu/kritzel-context-menu.css +113 -112
- package/dist/collection/components/kritzel-context-menu/kritzel-context-menu.js +1 -1
- package/dist/collection/components/kritzel-current-user/kritzel-current-user.css +11 -11
- package/dist/collection/components/kritzel-current-user/kritzel-current-user.js +1 -1
- package/dist/collection/components/kritzel-current-user-dialog/kritzel-current-user-dialog.css +39 -39
- package/dist/collection/components/kritzel-current-user-dialog/kritzel-current-user-dialog.js +1 -1
- package/dist/collection/components/kritzel-dialog/kritzel-dialog.css +209 -209
- package/dist/collection/components/kritzel-dropdown/kritzel-dropdown.css +190 -190
- package/dist/collection/components/kritzel-dropdown/kritzel-dropdown.js +2 -2
- package/dist/collection/components/kritzel-editor/kritzel-editor.css +160 -160
- package/dist/collection/components/kritzel-editor/kritzel-editor.js +72 -46
- package/dist/collection/components/kritzel-export/kritzel-export.css +89 -89
- package/dist/collection/components/kritzel-export/kritzel-export.js +1 -1
- package/dist/collection/components/kritzel-font/kritzel-font.css +10 -10
- package/dist/collection/components/kritzel-font/kritzel-font.js +1 -1
- package/dist/collection/components/kritzel-font-family/kritzel-font-family.css +48 -48
- package/dist/collection/components/kritzel-font-family/kritzel-font-family.js +2 -2
- package/dist/collection/components/kritzel-font-size/kritzel-font-size.css +30 -30
- package/dist/collection/components/kritzel-font-size/kritzel-font-size.js +1 -1
- package/dist/collection/components/kritzel-input/kritzel-input.css +69 -69
- package/dist/collection/components/kritzel-input/kritzel-input.js +1 -1
- package/dist/collection/components/kritzel-line-endings/kritzel-line-endings.css +60 -60
- package/dist/collection/components/kritzel-line-endings/kritzel-line-endings.js +3 -3
- package/dist/collection/components/kritzel-loading-overlay/kritzel-loading-overlay.css +54 -54
- package/dist/collection/components/kritzel-loading-overlay/kritzel-loading-overlay.js +1 -1
- package/dist/collection/components/kritzel-login-dialog/kritzel-login-dialog.css +98 -98
- package/dist/collection/components/kritzel-login-dialog/kritzel-login-dialog.js +1 -1
- package/dist/collection/components/kritzel-master-detail/kritzel-master-detail.css +190 -190
- package/dist/collection/components/kritzel-master-detail/kritzel-master-detail.js +3 -3
- package/dist/collection/components/kritzel-menu/kritzel-menu.css +35 -34
- package/dist/collection/components/kritzel-menu/kritzel-menu.js +1 -1
- package/dist/collection/components/kritzel-menu-item/kritzel-menu-item.css +166 -166
- package/dist/collection/components/kritzel-menu-item/kritzel-menu-item.js +3 -3
- package/dist/collection/components/kritzel-more-menu/kritzel-more-menu.css +58 -58
- package/dist/collection/components/kritzel-more-menu/kritzel-more-menu.js +4 -4
- package/dist/collection/components/kritzel-notification-card/kritzel-notification-card.css +101 -101
- package/dist/collection/components/kritzel-numeric-input/kritzel-numeric-input.css +102 -102
- package/dist/collection/components/kritzel-numeric-input/kritzel-numeric-input.js +1 -1
- package/dist/collection/components/kritzel-opacity-slider/kritzel-opacity-slider.css +85 -85
- package/dist/collection/components/kritzel-opacity-slider/kritzel-opacity-slider.js +1 -1
- package/dist/collection/components/kritzel-pill-tabs/kritzel-pill-tabs.css +68 -68
- package/dist/collection/components/kritzel-pill-tabs/kritzel-pill-tabs.js +2 -2
- package/dist/collection/components/kritzel-portal/kritzel-portal.js +1 -1
- package/dist/collection/components/kritzel-settings/kritzel-settings.css +137 -137
- package/dist/collection/components/kritzel-settings/kritzel-settings.js +1 -1
- package/dist/collection/components/kritzel-shape-fill/kritzel-shape-fill.css +47 -47
- package/dist/collection/components/kritzel-shape-fill/kritzel-shape-fill.js +4 -4
- package/dist/collection/components/kritzel-share-dialog/kritzel-share-dialog.css +150 -150
- package/dist/collection/components/kritzel-share-dialog/kritzel-share-dialog.js +2 -2
- package/dist/collection/components/kritzel-slide-toggle/kritzel-slide-toggle.css +48 -48
- package/dist/collection/components/kritzel-slide-toggle/kritzel-slide-toggle.js +1 -1
- package/dist/collection/components/kritzel-split-button/kritzel-split-button.css +78 -78
- package/dist/collection/components/kritzel-split-button/kritzel-split-button.js +3 -3
- package/dist/collection/components/kritzel-stroke-size/kritzel-stroke-size.css +37 -37
- package/dist/collection/components/kritzel-stroke-size/kritzel-stroke-size.js +1 -1
- package/dist/collection/components/kritzel-tool-config/kritzel-tool-config.css +38 -38
- package/dist/collection/components/kritzel-tool-config/kritzel-tool-config.js +1 -1
- package/dist/collection/components/kritzel-toolbar/kritzel-toolbar.css +347 -347
- package/dist/collection/components/kritzel-toolbar/kritzel-toolbar.js +12 -16
- package/dist/collection/components/kritzel-tooltip/kritzel-tooltip.css +18 -18
- package/dist/collection/components/kritzel-tooltip/kritzel-tooltip.js +2 -2
- package/dist/collection/components/kritzel-utility-panel/kritzel-utility-panel.css +45 -45
- package/dist/collection/components/kritzel-utility-panel/kritzel-utility-panel.js +1 -1
- package/dist/collection/components/kritzel-workspace-manager/kritzel-workspace-manager.css +16 -16
- package/dist/collection/components/kritzel-workspace-manager/kritzel-workspace-manager.js +1 -1
- package/dist/collection/components/kritzel-zoom-panel/kritzel-zoom-panel.css +72 -72
- package/dist/collection/components/kritzel-zoom-panel/kritzel-zoom-panel.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/kritzel-active-users.js +1 -1
- package/dist/components/kritzel-avatar.js +1 -1
- package/dist/components/kritzel-awareness-cursors.js +1 -1
- package/dist/components/kritzel-back-to-content.js +1 -1
- package/dist/components/kritzel-brush-style.js +4 -4
- package/dist/components/kritzel-button.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-current-user-dialog.js +1 -1
- package/dist/components/kritzel-current-user.js +1 -1
- package/dist/components/kritzel-cursor-trail.js +1 -1
- package/dist/components/kritzel-dialog.js +1 -1
- package/dist/components/kritzel-dropdown.js +1 -1
- package/dist/components/kritzel-editor.js +108 -81
- package/dist/components/kritzel-engine.js +1 -1
- package/dist/components/kritzel-export.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-input.js +1 -1
- package/dist/components/kritzel-line-endings.js +1 -1
- package/dist/components/kritzel-loading-overlay.js +1 -1
- package/dist/components/kritzel-login-dialog.js +1 -1
- package/dist/components/kritzel-master-detail.js +1 -1
- package/dist/components/kritzel-menu-item.js +1 -1
- package/dist/components/kritzel-menu.js +1 -1
- package/dist/components/kritzel-more-menu.js +1 -1
- package/dist/components/kritzel-notification-card.js +1 -1
- package/dist/components/kritzel-numeric-input.js +1 -1
- package/dist/components/kritzel-opacity-slider.js +1 -1
- package/dist/components/kritzel-pill-tabs.js +1 -1
- package/dist/components/kritzel-portal.js +1 -1
- package/dist/components/kritzel-settings.js +1 -1
- package/dist/components/kritzel-shape-fill.js +1 -1
- package/dist/components/kritzel-share-dialog.js +1 -1
- package/dist/components/kritzel-slide-toggle.js +1 -1
- package/dist/components/kritzel-split-button.js +1 -1
- package/dist/components/kritzel-stroke-size.js +1 -1
- package/dist/components/kritzel-tool-config.js +1 -1
- package/dist/components/kritzel-toolbar.js +1 -1
- package/dist/components/kritzel-tooltip.js +1 -1
- package/dist/components/kritzel-utility-panel.js +1 -1
- package/dist/components/kritzel-watermark.js +1 -1
- package/dist/components/kritzel-workspace-manager.js +1 -1
- package/dist/components/kritzel-zoom-panel.js +1 -1
- package/dist/components/{p-B_gT0lCn.js → p-5tEZmBli.js} +3 -3
- package/dist/components/{p-B6UJztrf.js → p-B6U2JNDq.js} +4 -4
- package/dist/components/{p-DXuf225S.js → p-BK5rE1rd.js} +3 -3
- package/dist/components/{p-BZ_KnHdR.js → p-BbXTqI4t.js} +7 -7
- package/dist/components/{p-McY5wZ0h.js → p-BhVCoiyK.js} +2 -2
- package/dist/components/{p-SLnqczCS.js → p-BowLPDbq.js} +3 -3
- package/dist/components/{p-hQwVRh0t.js → p-BuwiCK1I.js} +7 -7
- package/dist/components/{p-CoNexfpB.js → p-C01XOYLF.js} +3 -3
- package/dist/components/{p-ClfOtiNp.js → p-C5Hw8Wv3.js} +3 -3
- package/dist/components/{p-CmjXRLdr.js → p-C5fgp5y4.js} +7 -7
- package/dist/components/{p-BfMlwIcG.js → p-CHelQjUo.js} +3 -3
- package/dist/components/{p-B5xYV1o3.js → p-CIm1iROq.js} +2 -2
- package/dist/components/{p-BjFrt1q0.js → p-COGlcEiV.js} +3 -3
- package/dist/components/{p-4-qLegHb.js → p-COaLQ4Z-.js} +4 -4
- package/dist/components/{p-CVxGF4bJ.js → p-CPfTzGnn.js} +5 -5
- package/dist/components/p-CViWMGoM.js +55 -0
- package/dist/components/{p-Blq9a1ni.js → p-CY3fGZlt.js} +6 -6
- package/dist/components/{p-Cy_cLtOP.js → p-CdwD9F0m.js} +18 -14
- package/dist/components/{p-GbCxpbQ6.js → p-CgCVe3_P.js} +3 -3
- package/dist/components/{p-DZsSiMnA.js → p-CiSc7ASZ.js} +722 -129
- package/dist/components/{p-DVv8ChhE.js → p-D0lYLWkj.js} +4 -4
- package/dist/components/{p-QEue33R5.js → p-D1sxfQVN.js} +3 -3
- package/dist/components/{p-BvG3JO85.js → p-D53Q7EDf.js} +3 -3
- package/dist/components/{p-CzUeIini.js → p-D5OzFEtr.js} +13 -13
- package/dist/components/{p-B3Tqoyl9.js → p-DAr69onU.js} +3 -3
- package/dist/components/{p-h_uh_Njf.js → p-DE6S-FN0.js} +3 -3
- package/dist/components/p-DSi2HiZW.js +214 -0
- package/dist/components/{p-Ckqh1tqY.js → p-DX4FbgMi.js} +27 -31
- package/dist/components/{p-CwBxnzYu.js → p-DYNFqwX4.js} +3 -3
- package/dist/components/{p-Cp4e4oTE.js → p-DZ0S2l6Z.js} +2 -2
- package/dist/components/{p-BrGJIoGK.js → p-DZ4rAt6k.js} +3 -3
- package/dist/components/{p-BDjRSoAc.js → p-Ddk64LEI.js} +2 -2
- package/dist/components/{p-DJxgPPfs.js → p-DoNH4OhF.js} +3 -3
- package/dist/components/{p-D0tPTPkR.js → p-Dtm4CEHf.js} +3 -3
- package/dist/components/{p-BN8VWPlq.js → p-Dwg30A00.js} +7 -7
- package/dist/components/{p-DXZBWJBt.js → p-DxHrSwYy.js} +4 -4
- package/dist/components/{p-CvaxFYS0.js → p-EpqroVCx.js} +8 -8
- package/dist/components/{p-R1D8Sr0l.js → p-Fzi_dVqn.js} +3 -3
- package/dist/components/{p-CS3YZVYE.js → p-Qk844WR4.js} +2 -2
- package/dist/components/{p-peZjvnkK.js → p-g6VqjbL_.js} +2 -2
- package/dist/components/{p-DyRJFg4w.js → p-hKGrOeEa.js} +2 -2
- package/dist/components/{p-5qkOM1RJ.js → p-l1BZ4pYI.js} +12 -1
- package/dist/components/{p-CrIEmItB.js → p-p2H4pOpF.js} +5 -5
- package/dist/components/{p-DqOC_Yck.js → p-pWWRmEe8.js} +6 -6
- package/dist/components/{p-Ds0uNtwQ.js → p-piYX2tVg.js} +4 -4
- package/dist/components/{p-kOINnzaR.js → p-xPpMDzPX.js} +7 -7
- package/dist/esm/{index-OjbYJz-P.js → index-2x7dfLlM.js} +12 -1
- package/dist/esm/kritzel-active-users_46.entry.js +981 -322
- package/dist/esm/kritzel-brush-style.entry.js +2 -2
- package/dist/esm/kritzel-editor.js +3 -3
- package/dist/esm/loader.js +3 -3
- package/dist/kritzel-editor/kritzel-editor.esm.js +3 -3
- package/dist/kritzel-editor/{p-501047d8.entry.js → p-285cdc18.entry.js} +2 -2
- package/dist/kritzel-editor/{p-OjbYJz-P.js → p-2x7dfLlM.js} +12 -1
- package/dist/kritzel-editor/{p-60319edb.entry.js → p-d5439a4f.entry.js} +981 -322
- package/dist/types/components/kritzel-editor/kritzel-editor.d.ts +9 -2
- package/dist/types/components.d.ts +15 -15
- package/package.json +3 -3
- package/dist/components/p-BGmTmdLe.js +0 -167
- package/dist/components/p-DOJCDPVD.js +0 -55
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { p as proxyCustomElement, H, c as createEvent, h, d as Host, t as transformTag } from './p-
|
|
2
|
-
import { a as KritzelMouseButton, d as defineCustomElement$3 } from './p-
|
|
3
|
-
import { a as KritzelBaseObject, b as KritzelLine, c as KritzelMathHelper, e as KritzelGeometryHelper, f as KritzelColorHelper, D as DEFAULT_COLOR_PALETTE, g as KritzelPath, O as ObjectHelper, h as KritzelThemeManager, d as defineCustomElement$4 } from './p-
|
|
1
|
+
import { p as proxyCustomElement, H, c as createEvent, h, d as Host, t as transformTag } from './p-l1BZ4pYI.js';
|
|
2
|
+
import { a as KritzelMouseButton, d as defineCustomElement$3 } from './p-DZ0S2l6Z.js';
|
|
3
|
+
import { a as KritzelBaseObject, b as KritzelLine, c as KritzelMathHelper, e as KritzelGeometryHelper, f as KritzelColorHelper, D as DEFAULT_COLOR_PALETTE, g as KritzelPath, O as ObjectHelper, h as KritzelThemeManager, d as defineCustomElement$4 } from './p-CdwD9F0m.js';
|
|
4
4
|
import { c as commonjsGlobal } from './p-BFTU3MAI.js';
|
|
5
|
-
import { A as ABSOLUTE_SCALE_MAX, a as ABSOLUTE_SCALE_MIN, d as defineCustomElement$1 } from './p-
|
|
6
|
-
import { a as KritzelIconRegistry, d as defineCustomElement$2 } from './p-
|
|
5
|
+
import { A as ABSOLUTE_SCALE_MAX, a as ABSOLUTE_SCALE_MIN, d as defineCustomElement$1 } from './p-BowLPDbq.js';
|
|
6
|
+
import { a as KritzelIconRegistry, d as defineCustomElement$2 } from './p-DSi2HiZW.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Represents a visual selection box used for multi-object selection on the canvas.
|
|
@@ -38067,9 +38067,8 @@ class KritzelSelectionTool extends KritzelBaseTool {
|
|
|
38067
38067
|
}
|
|
38068
38068
|
if (selectedObject && selectedObject.isSelected === false && selectedObject?.objects.length === 1) {
|
|
38069
38069
|
const firstObj = selectedObject.objects[0];
|
|
38070
|
-
if (
|
|
38071
|
-
// Selected
|
|
38072
|
-
// embedded DOM content. Unselected dynamic objects remain selectable.
|
|
38070
|
+
if (ObjectHelper.isKritzelEmbeddedObject(firstObj)) {
|
|
38071
|
+
// Selected embedded objects hand pointer interaction to their content.
|
|
38073
38072
|
if (firstObj.isSelected && this._core.store.selectionGroup?.objects.length === 1)
|
|
38074
38073
|
return;
|
|
38075
38074
|
}
|
|
@@ -40238,7 +40237,7 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40238
40237
|
}
|
|
40239
40238
|
applyInteractiveState() {
|
|
40240
40239
|
const pointerEvents = this.isInteractive ? 'auto' : 'none';
|
|
40241
|
-
const contentCursor = this.isInteractive ? 'auto' : '';
|
|
40240
|
+
const contentCursor = this.isInteractive ? 'var(--kritzel-global-default-cursor, auto)' : '';
|
|
40242
40241
|
if (this.element) {
|
|
40243
40242
|
this.element.style.pointerEvents = pointerEvents;
|
|
40244
40243
|
this.element.style.cursor = contentCursor;
|
|
@@ -40274,7 +40273,7 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40274
40273
|
if (!this.isInteractive) {
|
|
40275
40274
|
return false;
|
|
40276
40275
|
}
|
|
40277
|
-
const focusHosts = this.
|
|
40276
|
+
const focusHosts = this.getEmbeddedContentRoots();
|
|
40278
40277
|
// Primary path: locate the focused input-like element by walking from each host through
|
|
40279
40278
|
// `:focus` (piercing open shadow roots). This works in real browsers even when the engine
|
|
40280
40279
|
// and editor are nested web components, because it never relies on the document-level
|
|
@@ -40291,7 +40290,7 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40291
40290
|
}
|
|
40292
40291
|
return false;
|
|
40293
40292
|
}
|
|
40294
|
-
|
|
40293
|
+
getEmbeddedContentRoots() {
|
|
40295
40294
|
const hosts = [];
|
|
40296
40295
|
if (this.element) {
|
|
40297
40296
|
hosts.push(this.element);
|
|
@@ -40504,11 +40503,11 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40504
40503
|
* @returns A serializable object with htmlString and dimension snapshots
|
|
40505
40504
|
*/
|
|
40506
40505
|
serialize() {
|
|
40507
|
-
const { _core, _elementRef, element, totalWidth, totalHeight, isSelected, isHovered, isMounted, isInteractive, resizing, markedForRemoval, isVisible, ...props } = this;
|
|
40506
|
+
const { _core, _elementRef, element, totalWidth, totalHeight, isSelected, isHovered, isMounted, isInteractive, resizing, markedForRemoval, isVisible, rendererData, ...props } = this;
|
|
40508
40507
|
const cloned = structuredClone(props);
|
|
40509
40508
|
// Include rendererKey and rendererData for lifecycle-driven rendering
|
|
40510
40509
|
cloned.rendererKey = this.rendererKey;
|
|
40511
|
-
cloned.rendererData = this.
|
|
40510
|
+
cloned.rendererData = this.serializeRendererData();
|
|
40512
40511
|
// Store HTML as string for fallback/compatibility when renderer is unavailable
|
|
40513
40512
|
cloned.htmlString = element ? element.outerHTML : '';
|
|
40514
40513
|
// Capture dimension snapshot at serialization time
|
|
@@ -40516,6 +40515,19 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40516
40515
|
cloned.serializedHeight = this.height;
|
|
40517
40516
|
return cloned;
|
|
40518
40517
|
}
|
|
40518
|
+
serializeRendererData() {
|
|
40519
|
+
if (this.rendererKey) {
|
|
40520
|
+
const renderer = KritzelDynamicObjectRendererRegistry.get(this.rendererKey);
|
|
40521
|
+
if (renderer?.onSerialize) {
|
|
40522
|
+
return structuredClone(renderer.onSerialize({
|
|
40523
|
+
object: this,
|
|
40524
|
+
container: this.isMounted && this.elementRef instanceof HTMLElement ? this.elementRef : null,
|
|
40525
|
+
data: this.rendererData,
|
|
40526
|
+
}));
|
|
40527
|
+
}
|
|
40528
|
+
}
|
|
40529
|
+
return structuredClone(this.rendererData);
|
|
40530
|
+
}
|
|
40519
40531
|
/**
|
|
40520
40532
|
* Deserializes the dynamic object from a plain object.
|
|
40521
40533
|
* Reconstructs the element from stored HTML string with fallback to placeholder.
|
|
@@ -40548,6 +40560,452 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40548
40560
|
}
|
|
40549
40561
|
}
|
|
40550
40562
|
|
|
40563
|
+
const IFRAME_STATE_MESSAGE = 'kritzel-iframe-state';
|
|
40564
|
+
const IFRAME_PARENT_STATE_MESSAGE = 'kritzel-iframe-parent-state';
|
|
40565
|
+
const IFRAME_POINTER_MESSAGE = 'kritzel-iframe-pointer';
|
|
40566
|
+
const IFRAME_CONTEXT_MENU_MESSAGE = 'kritzel-iframe-contextmenu';
|
|
40567
|
+
const SUPPORTED_SANDBOX_TOKENS = new Set([
|
|
40568
|
+
'allow-downloads',
|
|
40569
|
+
'allow-forms',
|
|
40570
|
+
'allow-modals',
|
|
40571
|
+
'allow-orientation-lock',
|
|
40572
|
+
'allow-pointer-lock',
|
|
40573
|
+
'allow-popups',
|
|
40574
|
+
'allow-popups-to-escape-sandbox',
|
|
40575
|
+
'allow-presentation',
|
|
40576
|
+
'allow-same-origin',
|
|
40577
|
+
'allow-scripts',
|
|
40578
|
+
'allow-top-navigation-by-user-activation',
|
|
40579
|
+
]);
|
|
40580
|
+
const iframePointerBridgeStarts = new WeakMap();
|
|
40581
|
+
class KritzelIframeObject extends KritzelBaseObject {
|
|
40582
|
+
__class__ = 'KritzelIframeObject';
|
|
40583
|
+
content = { html: '', css: '', script: '' };
|
|
40584
|
+
loadingContent;
|
|
40585
|
+
isLoading = false;
|
|
40586
|
+
state = {};
|
|
40587
|
+
title = 'Embedded content';
|
|
40588
|
+
sandbox = ['allow-scripts'];
|
|
40589
|
+
borderRadius;
|
|
40590
|
+
boxShadow;
|
|
40591
|
+
get html() { return this.content.html; }
|
|
40592
|
+
set html(value) { this.content = { ...this.content, html: value }; }
|
|
40593
|
+
get css() { return this.content.css; }
|
|
40594
|
+
set css(value) { this.content = { ...this.content, css: value }; }
|
|
40595
|
+
get script() { return this.content.script; }
|
|
40596
|
+
set script(value) { this.content = { ...this.content, script: value }; }
|
|
40597
|
+
messageListener = null;
|
|
40598
|
+
constructor(config) {
|
|
40599
|
+
super();
|
|
40600
|
+
this.content = {
|
|
40601
|
+
html: config?.content?.html ?? config?.html ?? '',
|
|
40602
|
+
css: config?.content?.css ?? config?.css ?? '',
|
|
40603
|
+
script: config?.content?.script ?? config?.script ?? '',
|
|
40604
|
+
};
|
|
40605
|
+
this.loadingContent = config?.loadingContent ? {
|
|
40606
|
+
html: config.loadingContent.html ?? '',
|
|
40607
|
+
css: config.loadingContent.css ?? '',
|
|
40608
|
+
script: config.loadingContent.script ?? '',
|
|
40609
|
+
} : undefined;
|
|
40610
|
+
this.isLoading = config?.isLoading ?? false;
|
|
40611
|
+
this.state = structuredClone(config?.state ?? {});
|
|
40612
|
+
this.title = config?.title ?? 'Embedded content';
|
|
40613
|
+
this.sandbox = this.normalizeSandbox(config?.sandbox);
|
|
40614
|
+
this.borderRadius = config?.borderRadius;
|
|
40615
|
+
this.boxShadow = config?.boxShadow;
|
|
40616
|
+
this.translateX = config?.translateX ?? 0;
|
|
40617
|
+
this.translateY = config?.translateY ?? 0;
|
|
40618
|
+
this.rotation = KritzelMathHelper.degreesToRadians(config?.rotation ?? 0);
|
|
40619
|
+
this.scale = config?.scale ?? 1;
|
|
40620
|
+
this.width = config?.width ?? 0;
|
|
40621
|
+
this.height = config?.height ?? 0;
|
|
40622
|
+
}
|
|
40623
|
+
static create(core, config) {
|
|
40624
|
+
const object = new KritzelIframeObject(config);
|
|
40625
|
+
object._core = core;
|
|
40626
|
+
object.id = object.generateId();
|
|
40627
|
+
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
40628
|
+
object.userId = core.user?.id;
|
|
40629
|
+
object.scale = config?.scale ?? core.store.state.scale;
|
|
40630
|
+
object.zIndex = core.store.currentZIndex;
|
|
40631
|
+
return object;
|
|
40632
|
+
}
|
|
40633
|
+
get sandboxAttribute() {
|
|
40634
|
+
return this.sandbox.join(' ');
|
|
40635
|
+
}
|
|
40636
|
+
mount(iframe) {
|
|
40637
|
+
if (this.isMounted && this.elementRef === iframe) {
|
|
40638
|
+
return;
|
|
40639
|
+
}
|
|
40640
|
+
if (this.isMounted) {
|
|
40641
|
+
this.unmount();
|
|
40642
|
+
}
|
|
40643
|
+
this.elementRef = iframe;
|
|
40644
|
+
this.isMounted = true;
|
|
40645
|
+
iframe.title = this.title;
|
|
40646
|
+
iframe.setAttribute('sandbox', this.sandboxAttribute);
|
|
40647
|
+
iframe.style.pointerEvents = this.isInteractive ? 'auto' : 'none';
|
|
40648
|
+
this.messageListener = event => this.handleMessage(event);
|
|
40649
|
+
window.addEventListener('message', this.messageListener);
|
|
40650
|
+
iframe.srcdoc = this.createSourceDocument();
|
|
40651
|
+
this.onMount(this.createLifecycleContext());
|
|
40652
|
+
}
|
|
40653
|
+
unmount() {
|
|
40654
|
+
if (!this.isMounted) {
|
|
40655
|
+
return;
|
|
40656
|
+
}
|
|
40657
|
+
const nextState = this.onUnmount(this.createLifecycleContext());
|
|
40658
|
+
if (nextState !== undefined) {
|
|
40659
|
+
this.state = structuredClone(nextState);
|
|
40660
|
+
}
|
|
40661
|
+
if (this.messageListener) {
|
|
40662
|
+
window.removeEventListener('message', this.messageListener);
|
|
40663
|
+
this.messageListener = null;
|
|
40664
|
+
}
|
|
40665
|
+
this.isMounted = false;
|
|
40666
|
+
this._elementRef = null;
|
|
40667
|
+
}
|
|
40668
|
+
setContent(content) {
|
|
40669
|
+
this.content = {
|
|
40670
|
+
html: content.html ?? this.content.html,
|
|
40671
|
+
css: content.css ?? this.content.css,
|
|
40672
|
+
script: content.script ?? this.content.script,
|
|
40673
|
+
};
|
|
40674
|
+
this.refreshDocument();
|
|
40675
|
+
this.persistUpdate();
|
|
40676
|
+
}
|
|
40677
|
+
setLoadingContent(content) {
|
|
40678
|
+
this.loadingContent = {
|
|
40679
|
+
html: content.html ?? this.loadingContent?.html ?? '',
|
|
40680
|
+
css: content.css ?? this.loadingContent?.css ?? '',
|
|
40681
|
+
script: content.script ?? this.loadingContent?.script ?? '',
|
|
40682
|
+
};
|
|
40683
|
+
this.refreshDocument();
|
|
40684
|
+
this.persistUpdate();
|
|
40685
|
+
}
|
|
40686
|
+
setLoading(isLoading) {
|
|
40687
|
+
this.isLoading = isLoading;
|
|
40688
|
+
this.refreshDocument();
|
|
40689
|
+
this.persistUpdate();
|
|
40690
|
+
}
|
|
40691
|
+
getActiveContent() {
|
|
40692
|
+
const activeLoadingContent = this.isLoading ? this.loadingContent : undefined;
|
|
40693
|
+
return {
|
|
40694
|
+
html: activeLoadingContent?.html ?? this.content.html,
|
|
40695
|
+
css: activeLoadingContent?.css ?? this.content.css,
|
|
40696
|
+
script: activeLoadingContent?.script ?? this.content.script,
|
|
40697
|
+
};
|
|
40698
|
+
}
|
|
40699
|
+
setState(state) {
|
|
40700
|
+
this.state = structuredClone(state);
|
|
40701
|
+
this.elementRef?.contentWindow?.postMessage({ type: IFRAME_PARENT_STATE_MESSAGE, state: this.state }, '*');
|
|
40702
|
+
this.persistUpdate();
|
|
40703
|
+
}
|
|
40704
|
+
setIsInteractive(isInteractive) {
|
|
40705
|
+
this.isInteractive = isInteractive;
|
|
40706
|
+
if (this.isMounted && this.elementRef) {
|
|
40707
|
+
this.elementRef.style.pointerEvents = isInteractive ? 'auto' : 'none';
|
|
40708
|
+
if (!isInteractive) {
|
|
40709
|
+
this.elementRef.blur();
|
|
40710
|
+
}
|
|
40711
|
+
}
|
|
40712
|
+
}
|
|
40713
|
+
hasFocusedInputElement() {
|
|
40714
|
+
return this.isInteractive && this.isMounted && document.activeElement === this.elementRef;
|
|
40715
|
+
}
|
|
40716
|
+
getEmbeddedContentRoots() {
|
|
40717
|
+
return this.isMounted && this.elementRef instanceof HTMLElement && this.elementRef.tagName === 'IFRAME' ? [this.elementRef] : [];
|
|
40718
|
+
}
|
|
40719
|
+
onMount(_context) { }
|
|
40720
|
+
onSerialize(context) {
|
|
40721
|
+
return context.state;
|
|
40722
|
+
}
|
|
40723
|
+
onUnmount(context) {
|
|
40724
|
+
return context.state;
|
|
40725
|
+
}
|
|
40726
|
+
serialize() {
|
|
40727
|
+
const nextState = this.onSerialize(this.createLifecycleContext());
|
|
40728
|
+
this.state = structuredClone(nextState);
|
|
40729
|
+
const messageListener = this.messageListener;
|
|
40730
|
+
this.messageListener = null;
|
|
40731
|
+
try {
|
|
40732
|
+
const serialized = super.serialize();
|
|
40733
|
+
delete serialized.messageListener;
|
|
40734
|
+
return serialized;
|
|
40735
|
+
}
|
|
40736
|
+
finally {
|
|
40737
|
+
this.messageListener = messageListener;
|
|
40738
|
+
}
|
|
40739
|
+
}
|
|
40740
|
+
deserialize(object) {
|
|
40741
|
+
super.deserialize(object);
|
|
40742
|
+
const nextContent = object.content && typeof object.content === 'object' ? object.content : {};
|
|
40743
|
+
const nextLoadingContent = object.loadingContent && typeof object.loadingContent === 'object' ? object.loadingContent : undefined;
|
|
40744
|
+
this.content = {
|
|
40745
|
+
html: typeof nextContent.html === 'string' ? nextContent.html : typeof object.html === 'string' ? object.html : '',
|
|
40746
|
+
css: typeof nextContent.css === 'string' ? nextContent.css : typeof object.css === 'string' ? object.css : '',
|
|
40747
|
+
script: typeof nextContent.script === 'string' ? nextContent.script : typeof object.script === 'string' ? object.script : '',
|
|
40748
|
+
};
|
|
40749
|
+
this.loadingContent = nextLoadingContent ? {
|
|
40750
|
+
html: typeof nextLoadingContent.html === 'string' ? nextLoadingContent.html : '',
|
|
40751
|
+
css: typeof nextLoadingContent.css === 'string' ? nextLoadingContent.css : '',
|
|
40752
|
+
script: typeof nextLoadingContent.script === 'string' ? nextLoadingContent.script : '',
|
|
40753
|
+
} : undefined;
|
|
40754
|
+
this.isLoading = typeof object.isLoading === 'boolean' ? object.isLoading : false;
|
|
40755
|
+
this.state = object.state && typeof object.state === 'object' ? structuredClone(object.state) : {};
|
|
40756
|
+
this.title = typeof object.title === 'string' ? object.title : 'Embedded content';
|
|
40757
|
+
this.sandbox = this.normalizeSandbox(Array.isArray(object.sandbox) ? object.sandbox.filter((token) => typeof token === 'string') : undefined);
|
|
40758
|
+
this.borderRadius = (typeof object.borderRadius === 'number' || typeof object.borderRadius === 'string') ? object.borderRadius : undefined;
|
|
40759
|
+
this.boxShadow = typeof object.boxShadow === 'string' ? object.boxShadow : undefined;
|
|
40760
|
+
this.messageListener = null;
|
|
40761
|
+
return this;
|
|
40762
|
+
}
|
|
40763
|
+
copy() {
|
|
40764
|
+
const copiedObject = super.copy();
|
|
40765
|
+
copiedObject.content = { ...this.content };
|
|
40766
|
+
copiedObject.loadingContent = this.loadingContent ? { ...this.loadingContent } : undefined;
|
|
40767
|
+
copiedObject.isLoading = this.isLoading;
|
|
40768
|
+
copiedObject.state = structuredClone(this.state);
|
|
40769
|
+
copiedObject.sandbox = [...this.sandbox];
|
|
40770
|
+
copiedObject.borderRadius = this.borderRadius;
|
|
40771
|
+
copiedObject.boxShadow = this.boxShadow;
|
|
40772
|
+
copiedObject.messageListener = null;
|
|
40773
|
+
copiedObject._elementRef = null;
|
|
40774
|
+
return copiedObject;
|
|
40775
|
+
}
|
|
40776
|
+
clone() {
|
|
40777
|
+
const clonedObject = super.clone();
|
|
40778
|
+
clonedObject.content = { ...this.content };
|
|
40779
|
+
clonedObject.loadingContent = this.loadingContent ? { ...this.loadingContent } : undefined;
|
|
40780
|
+
clonedObject.isLoading = this.isLoading;
|
|
40781
|
+
clonedObject.state = structuredClone(this.state);
|
|
40782
|
+
clonedObject.sandbox = [...this.sandbox];
|
|
40783
|
+
clonedObject.borderRadius = this.borderRadius;
|
|
40784
|
+
clonedObject.boxShadow = this.boxShadow;
|
|
40785
|
+
clonedObject.messageListener = null;
|
|
40786
|
+
clonedObject.isMounted = false;
|
|
40787
|
+
clonedObject._elementRef = null;
|
|
40788
|
+
return clonedObject;
|
|
40789
|
+
}
|
|
40790
|
+
adoptTransientStateFrom(previous) {
|
|
40791
|
+
if (!(previous instanceof KritzelIframeObject)) {
|
|
40792
|
+
return;
|
|
40793
|
+
}
|
|
40794
|
+
this.isInteractive = previous.isInteractive;
|
|
40795
|
+
this.isSelected = previous.isSelected;
|
|
40796
|
+
this.isHovered = previous.isHovered;
|
|
40797
|
+
if (!previous.isMounted || !(previous.elementRef instanceof HTMLElement) || previous.elementRef.tagName !== 'IFRAME') {
|
|
40798
|
+
return;
|
|
40799
|
+
}
|
|
40800
|
+
if (previous.messageListener) {
|
|
40801
|
+
window.removeEventListener('message', previous.messageListener);
|
|
40802
|
+
}
|
|
40803
|
+
this._elementRef = previous.elementRef;
|
|
40804
|
+
this.isMounted = true;
|
|
40805
|
+
this.messageListener = event => this.handleMessage(event);
|
|
40806
|
+
window.addEventListener('message', this.messageListener);
|
|
40807
|
+
this.elementRef.style.pointerEvents = this.isInteractive ? 'auto' : 'none';
|
|
40808
|
+
previous.messageListener = null;
|
|
40809
|
+
previous.isMounted = false;
|
|
40810
|
+
previous._elementRef = null;
|
|
40811
|
+
}
|
|
40812
|
+
createLifecycleContext() {
|
|
40813
|
+
return {
|
|
40814
|
+
object: this,
|
|
40815
|
+
iframe: this.isMounted ? this.elementRef : null,
|
|
40816
|
+
state: structuredClone(this.state),
|
|
40817
|
+
};
|
|
40818
|
+
}
|
|
40819
|
+
normalizeSandbox(tokens) {
|
|
40820
|
+
const requestedTokens = tokens ?? ['allow-scripts'];
|
|
40821
|
+
const normalized = requestedTokens.filter(token => SUPPORTED_SANDBOX_TOKENS.has(token));
|
|
40822
|
+
return [...new Set(normalized.length > 0 ? normalized : ['allow-scripts'])];
|
|
40823
|
+
}
|
|
40824
|
+
createSourceDocument() {
|
|
40825
|
+
const activeContent = this.getActiveContent();
|
|
40826
|
+
const state = JSON.stringify(this.state).replace(/</g, '\\u003c');
|
|
40827
|
+
const css = activeContent.css.replace(/<\/style/gi, '<\\/style');
|
|
40828
|
+
const script = activeContent.script.replace(/<\/script/gi, '<\\/script');
|
|
40829
|
+
const computedStyle = this.isMounted ? getComputedStyle(this.elementRef) : null;
|
|
40830
|
+
const defaultCursor = computedStyle?.getPropertyValue('--kritzel-global-default-cursor').trim() || 'auto';
|
|
40831
|
+
const pointerCursor = computedStyle?.getPropertyValue('--kritzel-global-pointer-cursor').trim() || defaultCursor;
|
|
40832
|
+
return `<!doctype html>
|
|
40833
|
+
<html>
|
|
40834
|
+
<head>
|
|
40835
|
+
<meta charset="utf-8">
|
|
40836
|
+
<style>
|
|
40837
|
+
:root {
|
|
40838
|
+
--kritzel-iframe-default-cursor: ${defaultCursor};
|
|
40839
|
+
--kritzel-iframe-pointer-cursor: ${pointerCursor};
|
|
40840
|
+
}
|
|
40841
|
+
html, body { width: 100%; height: 100%; margin: 0; overflow: hidden; cursor: var(--kritzel-iframe-default-cursor); }
|
|
40842
|
+
button, button *, a, a *, input, textarea, select { cursor: var(--kritzel-iframe-pointer-cursor) !important; }
|
|
40843
|
+
${css}
|
|
40844
|
+
</style>
|
|
40845
|
+
</head>
|
|
40846
|
+
<body>
|
|
40847
|
+
${activeContent.html}
|
|
40848
|
+
<script>
|
|
40849
|
+
const kritzel = globalThis.kritzel = {
|
|
40850
|
+
state: ${state},
|
|
40851
|
+
setState(nextState) {
|
|
40852
|
+
this.state = nextState;
|
|
40853
|
+
parent.postMessage({ type: '${IFRAME_STATE_MESSAGE}', state: nextState }, '*');
|
|
40854
|
+
},
|
|
40855
|
+
};
|
|
40856
|
+
globalThis.addEventListener('message', event => {
|
|
40857
|
+
if (event.data?.type === '${IFRAME_PARENT_STATE_MESSAGE}' && event.data.state && typeof event.data.state === 'object') {
|
|
40858
|
+
kritzel.state = event.data.state;
|
|
40859
|
+
globalThis.dispatchEvent(new CustomEvent('kritzelstatechange', { detail: kritzel.state }));
|
|
40860
|
+
}
|
|
40861
|
+
});
|
|
40862
|
+
let bridgedPointerId = null;
|
|
40863
|
+
const interactiveSelector = 'button, input, textarea, select, a[href], [contenteditable="true"], [contenteditable=""]';
|
|
40864
|
+
const bridgePointerEvent = event => parent.postMessage({
|
|
40865
|
+
type: '${IFRAME_POINTER_MESSAGE}',
|
|
40866
|
+
eventType: event.type,
|
|
40867
|
+
pointerId: event.pointerId,
|
|
40868
|
+
pointerType: event.pointerType,
|
|
40869
|
+
clientX: event.clientX,
|
|
40870
|
+
clientY: event.clientY,
|
|
40871
|
+
screenX: event.screenX,
|
|
40872
|
+
screenY: event.screenY,
|
|
40873
|
+
button: event.button,
|
|
40874
|
+
buttons: event.buttons,
|
|
40875
|
+
shiftKey: event.shiftKey,
|
|
40876
|
+
ctrlKey: event.ctrlKey,
|
|
40877
|
+
altKey: event.altKey,
|
|
40878
|
+
metaKey: event.metaKey,
|
|
40879
|
+
}, '*');
|
|
40880
|
+
document.addEventListener('pointerdown', event => {
|
|
40881
|
+
if (event.target instanceof Element && event.target.closest(interactiveSelector)) return;
|
|
40882
|
+
bridgedPointerId = event.pointerId;
|
|
40883
|
+
event.preventDefault();
|
|
40884
|
+
bridgePointerEvent(event);
|
|
40885
|
+
});
|
|
40886
|
+
document.addEventListener('pointermove', event => {
|
|
40887
|
+
if (event.pointerId !== bridgedPointerId) return;
|
|
40888
|
+
event.preventDefault();
|
|
40889
|
+
bridgePointerEvent(event);
|
|
40890
|
+
});
|
|
40891
|
+
const finishPointerBridge = event => {
|
|
40892
|
+
if (event.pointerId !== bridgedPointerId) return;
|
|
40893
|
+
event.preventDefault();
|
|
40894
|
+
bridgePointerEvent(event);
|
|
40895
|
+
bridgedPointerId = null;
|
|
40896
|
+
};
|
|
40897
|
+
document.addEventListener('pointerup', finishPointerBridge);
|
|
40898
|
+
document.addEventListener('pointercancel', finishPointerBridge);
|
|
40899
|
+
document.addEventListener('contextmenu', event => {
|
|
40900
|
+
event.preventDefault();
|
|
40901
|
+
parent.postMessage({
|
|
40902
|
+
type: '${IFRAME_CONTEXT_MENU_MESSAGE}',
|
|
40903
|
+
clientX: event.clientX,
|
|
40904
|
+
clientY: event.clientY,
|
|
40905
|
+
button: event.button,
|
|
40906
|
+
shiftKey: event.shiftKey,
|
|
40907
|
+
ctrlKey: event.ctrlKey,
|
|
40908
|
+
altKey: event.altKey,
|
|
40909
|
+
metaKey: event.metaKey,
|
|
40910
|
+
}, '*');
|
|
40911
|
+
});
|
|
40912
|
+
${script}
|
|
40913
|
+
<\/script>
|
|
40914
|
+
</body>
|
|
40915
|
+
</html>`;
|
|
40916
|
+
}
|
|
40917
|
+
handleMessage(event) {
|
|
40918
|
+
if (event.source !== this.elementRef?.contentWindow || !event.data || typeof event.data !== 'object') {
|
|
40919
|
+
return;
|
|
40920
|
+
}
|
|
40921
|
+
const message = event.data;
|
|
40922
|
+
if (message.type === IFRAME_POINTER_MESSAGE) {
|
|
40923
|
+
this.dispatchPointerMessage(event.data);
|
|
40924
|
+
return;
|
|
40925
|
+
}
|
|
40926
|
+
if (message.type === IFRAME_CONTEXT_MENU_MESSAGE) {
|
|
40927
|
+
this.dispatchContextMenuMessage(event.data);
|
|
40928
|
+
return;
|
|
40929
|
+
}
|
|
40930
|
+
if (message.type !== IFRAME_STATE_MESSAGE || !message.state || typeof message.state !== 'object') {
|
|
40931
|
+
return;
|
|
40932
|
+
}
|
|
40933
|
+
this.state = structuredClone(message.state);
|
|
40934
|
+
this.persistUpdate();
|
|
40935
|
+
}
|
|
40936
|
+
dispatchPointerMessage(message) {
|
|
40937
|
+
if (!this.isMounted || !this.elementRef || !['pointerdown', 'pointermove', 'pointerup', 'pointercancel'].includes(message.eventType)) {
|
|
40938
|
+
return;
|
|
40939
|
+
}
|
|
40940
|
+
const iframeRect = this.elementRef.getBoundingClientRect();
|
|
40941
|
+
if (message.eventType === 'pointerdown') {
|
|
40942
|
+
const scaleX = this.elementRef.offsetWidth > 0 ? iframeRect.width / this.elementRef.offsetWidth : 1;
|
|
40943
|
+
const scaleY = this.elementRef.offsetHeight > 0 ? iframeRect.height / this.elementRef.offsetHeight : 1;
|
|
40944
|
+
iframePointerBridgeStarts.set(this.elementRef, {
|
|
40945
|
+
pointerId: message.pointerId,
|
|
40946
|
+
clientX: iframeRect.left + message.clientX * scaleX,
|
|
40947
|
+
clientY: iframeRect.top + message.clientY * scaleY,
|
|
40948
|
+
screenX: message.screenX,
|
|
40949
|
+
screenY: message.screenY,
|
|
40950
|
+
});
|
|
40951
|
+
}
|
|
40952
|
+
const bridgeStart = iframePointerBridgeStarts.get(this.elementRef);
|
|
40953
|
+
const hasBridgeStart = bridgeStart?.pointerId === message.pointerId;
|
|
40954
|
+
const clientX = hasBridgeStart ? bridgeStart.clientX + message.screenX - bridgeStart.screenX : iframeRect.left + message.clientX;
|
|
40955
|
+
const clientY = hasBridgeStart ? bridgeStart.clientY + message.screenY - bridgeStart.screenY : iframeRect.top + message.clientY;
|
|
40956
|
+
this.elementRef.dispatchEvent(new PointerEvent(message.eventType, {
|
|
40957
|
+
bubbles: true,
|
|
40958
|
+
composed: true,
|
|
40959
|
+
cancelable: true,
|
|
40960
|
+
pointerId: message.pointerId,
|
|
40961
|
+
pointerType: message.pointerType,
|
|
40962
|
+
clientX,
|
|
40963
|
+
clientY,
|
|
40964
|
+
screenX: message.screenX,
|
|
40965
|
+
screenY: message.screenY,
|
|
40966
|
+
button: message.button,
|
|
40967
|
+
buttons: message.buttons,
|
|
40968
|
+
shiftKey: message.shiftKey,
|
|
40969
|
+
ctrlKey: message.ctrlKey,
|
|
40970
|
+
altKey: message.altKey,
|
|
40971
|
+
metaKey: message.metaKey,
|
|
40972
|
+
}));
|
|
40973
|
+
if (message.eventType === 'pointerup' || message.eventType === 'pointercancel') {
|
|
40974
|
+
iframePointerBridgeStarts.delete(this.elementRef);
|
|
40975
|
+
}
|
|
40976
|
+
}
|
|
40977
|
+
dispatchContextMenuMessage(message) {
|
|
40978
|
+
if (!this.isMounted || !this.elementRef) {
|
|
40979
|
+
return;
|
|
40980
|
+
}
|
|
40981
|
+
const iframeRect = this.elementRef.getBoundingClientRect();
|
|
40982
|
+
// Dispatched as a MouseEvent (not PointerEvent) to mirror how browsers
|
|
40983
|
+
// natively raise 'contextmenu' for both mouse right-click and touch long-press.
|
|
40984
|
+
this.elementRef.dispatchEvent(new MouseEvent('contextmenu', {
|
|
40985
|
+
bubbles: true,
|
|
40986
|
+
composed: true,
|
|
40987
|
+
cancelable: true,
|
|
40988
|
+
clientX: iframeRect.left + message.clientX,
|
|
40989
|
+
clientY: iframeRect.top + message.clientY,
|
|
40990
|
+
button: message.button,
|
|
40991
|
+
shiftKey: message.shiftKey,
|
|
40992
|
+
ctrlKey: message.ctrlKey,
|
|
40993
|
+
altKey: message.altKey,
|
|
40994
|
+
metaKey: message.metaKey,
|
|
40995
|
+
}));
|
|
40996
|
+
}
|
|
40997
|
+
refreshDocument() {
|
|
40998
|
+
if (this.isMounted && this.elementRef) {
|
|
40999
|
+
this.elementRef.srcdoc = this.createSourceDocument();
|
|
41000
|
+
}
|
|
41001
|
+
}
|
|
41002
|
+
persistUpdate() {
|
|
41003
|
+
if (this._core?.store?.objects) {
|
|
41004
|
+
this.update();
|
|
41005
|
+
}
|
|
41006
|
+
}
|
|
41007
|
+
}
|
|
41008
|
+
|
|
40551
41009
|
/**
|
|
40552
41010
|
* Handles deserialization/revival of Kritzel objects from plain JavaScript objects.
|
|
40553
41011
|
* This class uses a pattern similar to JSON.parse reviver to reconstruct class instances
|
|
@@ -40610,6 +41068,9 @@ class KritzelReviver {
|
|
|
40610
41068
|
case 'KritzelDynamicObject':
|
|
40611
41069
|
revivedObj = KritzelDynamicObject.create(this._core).deserialize(obj);
|
|
40612
41070
|
break;
|
|
41071
|
+
case 'KritzelIframeObject':
|
|
41072
|
+
revivedObj = KritzelIframeObject.create(this._core).deserialize(obj);
|
|
41073
|
+
break;
|
|
40613
41074
|
case 'KritzelSelectionGroup':
|
|
40614
41075
|
revivedObj = KritzelSelectionGroup.create(this._core).deserialize(obj);
|
|
40615
41076
|
break;
|
|
@@ -52971,9 +53432,16 @@ class KritzelStore {
|
|
|
52971
53432
|
* Gets the currently selected dynamic object whose focused descendant is an input-like element.
|
|
52972
53433
|
* @returns The interactive dynamic object with focused input-like content, or null if none matches
|
|
52973
53434
|
*/
|
|
53435
|
+
get activeInteractiveEmbeddedObject() {
|
|
53436
|
+
for (const object of this.selectedObjects) {
|
|
53437
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object) && object.hasFocusedInputElement()) {
|
|
53438
|
+
return object;
|
|
53439
|
+
}
|
|
53440
|
+
}
|
|
53441
|
+
return null;
|
|
53442
|
+
}
|
|
52974
53443
|
get activeInteractiveDynamicObject() {
|
|
52975
|
-
|
|
52976
|
-
return interactiveDynamicObject ?? null;
|
|
53444
|
+
return this.activeInteractiveEmbeddedObject;
|
|
52977
53445
|
}
|
|
52978
53446
|
/**
|
|
52979
53447
|
* Gets the path currently being drawn (not yet completed).
|
|
@@ -55073,7 +55541,7 @@ class KritzelCursorHelper {
|
|
|
55073
55541
|
* The icon is retrieved from the KritzelIconRegistry.
|
|
55074
55542
|
*/
|
|
55075
55543
|
static getCursor(options) {
|
|
55076
|
-
const iconName = options.iconName === 'default' ? '
|
|
55544
|
+
const iconName = options.iconName === 'default' ? 'mousePointer' : options.iconName;
|
|
55077
55545
|
const iconSvg = KritzelIconRegistry.get(iconName);
|
|
55078
55546
|
if (!iconSvg) {
|
|
55079
55547
|
console.warn(`Icon "${iconName}" not found in registry.`);
|
|
@@ -55082,7 +55550,7 @@ class KritzelCursorHelper {
|
|
|
55082
55550
|
const size = options.size || 24;
|
|
55083
55551
|
const rotation = options.rotation || 0;
|
|
55084
55552
|
const color = options.color || 'black';
|
|
55085
|
-
// Default cursor (
|
|
55553
|
+
// Default cursor (mousePointer) has hotspot at (4, 4), others at center
|
|
55086
55554
|
const hotspot = options.hotspot || (options.iconName === 'default' ? { x: 4, y: 4 } : { x: size / 2, y: size / 2 });
|
|
55087
55555
|
// Modify the SVG string to set size and color
|
|
55088
55556
|
// We replace width and height to match the requested size
|
|
@@ -55095,12 +55563,12 @@ class KritzelCursorHelper {
|
|
|
55095
55563
|
// We rotate around the center of the SVG canvas
|
|
55096
55564
|
const center = size / 2;
|
|
55097
55565
|
// We use a group to apply the rotation
|
|
55098
|
-
const svg = `
|
|
55099
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
|
|
55100
|
-
<g transform="rotate(${rotation} ${center} ${center})">
|
|
55101
|
-
${content}
|
|
55102
|
-
</g>
|
|
55103
|
-
</svg>
|
|
55566
|
+
const svg = `
|
|
55567
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
|
|
55568
|
+
<g transform="rotate(${rotation} ${center} ${center})">
|
|
55569
|
+
${content}
|
|
55570
|
+
</g>
|
|
55571
|
+
</svg>
|
|
55104
55572
|
`;
|
|
55105
55573
|
// Encode the SVG for use in a data URI
|
|
55106
55574
|
// We need to be careful with encoding to ensure it works across browsers
|
|
@@ -55138,11 +55606,13 @@ class KritzelCursorManager {
|
|
|
55138
55606
|
// Reset cursor on old target
|
|
55139
55607
|
if (this._targetElement) {
|
|
55140
55608
|
this._targetElement.style.cursor = '';
|
|
55609
|
+
this._targetElement.style.removeProperty('--kritzel-global-default-cursor');
|
|
55141
55610
|
this._targetElement.style.removeProperty('--kritzel-global-pointer-cursor');
|
|
55142
55611
|
}
|
|
55143
55612
|
this._targetElement = element;
|
|
55144
55613
|
// Set the pointer cursor CSS variable for child components to use
|
|
55145
55614
|
if (this._targetElement) {
|
|
55615
|
+
this._targetElement.style.setProperty('--kritzel-global-default-cursor', KritzelCursorHelper.getCursor({ iconName: 'default' }));
|
|
55146
55616
|
this._targetElement.style.setProperty('--kritzel-global-pointer-cursor', KritzelCursorHelper.getPointerCursor());
|
|
55147
55617
|
}
|
|
55148
55618
|
}
|
|
@@ -55187,8 +55657,10 @@ class KritzelCursorManager {
|
|
|
55187
55657
|
if (!this._shadowRoot)
|
|
55188
55658
|
return;
|
|
55189
55659
|
const elementsAtPoint = this._shadowRoot.elementsFromPoint(ev.clientX, ev.clientY);
|
|
55190
|
-
if (!elementsAtPoint || elementsAtPoint.length === 0)
|
|
55660
|
+
if (!elementsAtPoint || elementsAtPoint.length === 0) {
|
|
55661
|
+
this.resetToDefault();
|
|
55191
55662
|
return;
|
|
55663
|
+
}
|
|
55192
55664
|
// Check for resize handle overlays (selection group)
|
|
55193
55665
|
const resizeHandleOverlay = elementsAtPoint.find(el => el.classList.contains('resize-handle-overlay'));
|
|
55194
55666
|
if (resizeHandleOverlay) {
|
|
@@ -55198,19 +55670,19 @@ class KritzelCursorManager {
|
|
|
55198
55670
|
const isTopLeft = resizeHandleOverlay.classList.contains('top-left');
|
|
55199
55671
|
const isBottomRight = resizeHandleOverlay.classList.contains('bottom-right');
|
|
55200
55672
|
const rotationOffset = (isTopLeft || isBottomRight) ? -45 : 45;
|
|
55201
|
-
this._core.store.state.cursor = { icon: '
|
|
55673
|
+
this._core.store.state.cursor = { icon: 'moveVertical', rotation: rotationDegrees + rotationOffset };
|
|
55202
55674
|
return;
|
|
55203
55675
|
}
|
|
55204
55676
|
// Check for rotation handle overlay
|
|
55205
55677
|
const rotationHandleOverlay = elementsAtPoint.find(el => el.classList.contains('rotation-handle-overlay'));
|
|
55206
55678
|
if (rotationHandleOverlay) {
|
|
55207
|
-
this._core.store.state.cursor = { icon: 'hand', iconActive: '
|
|
55679
|
+
this._core.store.state.cursor = { icon: 'hand', iconActive: 'handGrab' };
|
|
55208
55680
|
return;
|
|
55209
55681
|
}
|
|
55210
55682
|
// Check for line handle overlays (selection line)
|
|
55211
55683
|
const lineHandleOverlay = elementsAtPoint.find(el => el.classList.contains('selection-line-handle-overlay'));
|
|
55212
55684
|
if (lineHandleOverlay) {
|
|
55213
|
-
this._core.store.state.cursor = { icon: 'hand', iconActive: '
|
|
55685
|
+
this._core.store.state.cursor = { icon: 'hand', iconActive: 'handGrab' };
|
|
55214
55686
|
return;
|
|
55215
55687
|
}
|
|
55216
55688
|
// Reset cursor if not hovering any handle
|
|
@@ -55245,7 +55717,8 @@ class KritzelCursorManager {
|
|
|
55245
55717
|
cleanup() {
|
|
55246
55718
|
if (this._targetElement) {
|
|
55247
55719
|
this._targetElement.style.cursor = '';
|
|
55248
|
-
this._targetElement.style.removeProperty('--kritzel-
|
|
55720
|
+
this._targetElement.style.removeProperty('--kritzel-global-default-cursor');
|
|
55721
|
+
this._targetElement.style.removeProperty('--kritzel-global-pointer-cursor');
|
|
55249
55722
|
}
|
|
55250
55723
|
this._targetElement = null;
|
|
55251
55724
|
this._shadowRoot = null;
|
|
@@ -57148,7 +57621,7 @@ class KritzelCore {
|
|
|
57148
57621
|
this._store.state.translateY = viewportHeight / 2 - (viewport.centerWorldY ?? 0) * scale;
|
|
57149
57622
|
this._store.state.scale = scale;
|
|
57150
57623
|
await objectsMap.initialize(this, activeWorkspace.id, this._syncConfig);
|
|
57151
|
-
this.seedWorkspaceObjects(activeWorkspace, objectsMap);
|
|
57624
|
+
await this.seedWorkspaceObjects(activeWorkspace, objectsMap);
|
|
57152
57625
|
// Set local user in awareness after object map is initialized
|
|
57153
57626
|
if (this._user) {
|
|
57154
57627
|
objectsMap.setLocalUser(this._user);
|
|
@@ -57162,15 +57635,21 @@ class KritzelCore {
|
|
|
57162
57635
|
this.engine.emitObjectsChange();
|
|
57163
57636
|
this.rerender();
|
|
57164
57637
|
}
|
|
57165
|
-
seedWorkspaceObjects(workspace, objectsMap) {
|
|
57638
|
+
async seedWorkspaceObjects(workspace, objectsMap) {
|
|
57166
57639
|
if (!workspace.objects?.length) {
|
|
57167
57640
|
return;
|
|
57168
57641
|
}
|
|
57642
|
+
const pendingObjects = workspace.objects.filter(object => !objectsMap.findById(object.id));
|
|
57643
|
+
// Mirrors engine.addObject()/addObjects(): image asset upload is async and must
|
|
57644
|
+
// happen before the (synchronous) Yjs transaction that inserts the objects.
|
|
57645
|
+
for (const object of pendingObjects) {
|
|
57646
|
+
object._core = this;
|
|
57647
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
57648
|
+
await object.prepareForInsert();
|
|
57649
|
+
}
|
|
57650
|
+
}
|
|
57169
57651
|
objectsMap.transaction(() => {
|
|
57170
|
-
for (const object of
|
|
57171
|
-
if (objectsMap.findById(object.id)) {
|
|
57172
|
-
continue;
|
|
57173
|
-
}
|
|
57652
|
+
for (const object of pendingObjects) {
|
|
57174
57653
|
this.prepareObjectForWorkspace(object, workspace.id, this._store.currentZIndex, this._store.state.scale);
|
|
57175
57654
|
objectsMap.insert(object);
|
|
57176
57655
|
}
|
|
@@ -57209,16 +57688,30 @@ class KritzelCore {
|
|
|
57209
57688
|
* @param scaleFallback - Scale applied to objects that do not define one
|
|
57210
57689
|
* @returns The objects that were added, updated and removed
|
|
57211
57690
|
*/
|
|
57212
|
-
reconcileWorkspaceObjects(objectsMap, workspaceId, desiredObjects, nextZIndex, scaleFallback) {
|
|
57691
|
+
async reconcileWorkspaceObjects(objectsMap, workspaceId, desiredObjects, nextZIndex, scaleFallback) {
|
|
57213
57692
|
const existingObjects = objectsMap.allObjects().filter(o => !(o instanceof KritzelSelectionGroup) && !(o instanceof KritzelSelectionBox));
|
|
57214
57693
|
const existingById = new Map(existingObjects.map(object => [object.id, object]));
|
|
57215
57694
|
const desiredIds = new Set();
|
|
57216
57695
|
const diff = { added: [], updated: [], removed: [] };
|
|
57696
|
+
// Assign IDs up front so the insert-vs-update lookup below is stable, and so the
|
|
57697
|
+
// async image-prepare pass and the (synchronous) transaction agree on identity.
|
|
57698
|
+
for (const object of desiredObjects) {
|
|
57699
|
+
if (!object.id) {
|
|
57700
|
+
object.id = object.generateId();
|
|
57701
|
+
}
|
|
57702
|
+
}
|
|
57703
|
+
// Mirrors engine.addObject()/addObjects(): image asset upload is async and must
|
|
57704
|
+
// happen before the (synchronous) Yjs transaction that inserts the objects.
|
|
57705
|
+
for (const object of desiredObjects) {
|
|
57706
|
+
const existingObject = existingById.get(object.id);
|
|
57707
|
+
const isNewOrReplaced = !existingObject || existingObject !== object;
|
|
57708
|
+
if (isNewOrReplaced && KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
57709
|
+
object._core = this;
|
|
57710
|
+
await object.prepareForInsert();
|
|
57711
|
+
}
|
|
57712
|
+
}
|
|
57217
57713
|
objectsMap.transaction(() => {
|
|
57218
57714
|
for (const object of desiredObjects) {
|
|
57219
|
-
if (!object.id) {
|
|
57220
|
-
object.id = object.generateId();
|
|
57221
|
-
}
|
|
57222
57715
|
desiredIds.add(object.id);
|
|
57223
57716
|
const existingObject = existingById.get(object.id);
|
|
57224
57717
|
if (!existingObject) {
|
|
@@ -57256,7 +57749,7 @@ class KritzelCore {
|
|
|
57256
57749
|
* object set stays exactly what the caller declared.
|
|
57257
57750
|
*/
|
|
57258
57751
|
detachObject(object) {
|
|
57259
|
-
if (
|
|
57752
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
57260
57753
|
object.unmount();
|
|
57261
57754
|
}
|
|
57262
57755
|
object.isMounted = false;
|
|
@@ -57432,13 +57925,13 @@ class KritzelCore {
|
|
|
57432
57925
|
activeWorkspace.viewport = { centerWorldX, centerWorldY, scale };
|
|
57433
57926
|
}
|
|
57434
57927
|
}
|
|
57435
|
-
applyObjectsToActiveWorkspace(workspace, desiredObjects) {
|
|
57928
|
+
async applyObjectsToActiveWorkspace(workspace, desiredObjects) {
|
|
57436
57929
|
const objectsMap = this._store.objects;
|
|
57437
57930
|
if (!objectsMap) {
|
|
57438
57931
|
return null;
|
|
57439
57932
|
}
|
|
57440
57933
|
this.clearSelection();
|
|
57441
|
-
const diff = this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this._store.currentZIndex, this._store.state.scale);
|
|
57934
|
+
const diff = await this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this._store.currentZIndex, this._store.state.scale);
|
|
57442
57935
|
this._anchorManager.rebuildIndex();
|
|
57443
57936
|
this.rerender();
|
|
57444
57937
|
return diff;
|
|
@@ -57457,7 +57950,7 @@ class KritzelCore {
|
|
|
57457
57950
|
try {
|
|
57458
57951
|
await objectsMap.initialize(this, workspace.id, this._syncConfig, { headless: true, workspaceName: workspace.name });
|
|
57459
57952
|
await objectsMap.whenNetworkSynced();
|
|
57460
|
-
return this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this.nextZIndexOf(objectsMap), this._store.state.scale);
|
|
57953
|
+
return await this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this.nextZIndexOf(objectsMap), this._store.state.scale);
|
|
57461
57954
|
}
|
|
57462
57955
|
finally {
|
|
57463
57956
|
objectsMap.destroy();
|
|
@@ -57543,8 +58036,7 @@ class KritzelCore {
|
|
|
57543
58036
|
this.removeObject(child);
|
|
57544
58037
|
});
|
|
57545
58038
|
}
|
|
57546
|
-
|
|
57547
|
-
if (KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject')) {
|
|
58039
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
57548
58040
|
object.unmount();
|
|
57549
58041
|
}
|
|
57550
58042
|
// Handle anchor cleanup
|
|
@@ -57590,14 +58082,8 @@ class KritzelCore {
|
|
|
57590
58082
|
this.removeLocalSelectionGroups();
|
|
57591
58083
|
this.removeSelectionBox();
|
|
57592
58084
|
for (const object of selectionGroup.objects ?? []) {
|
|
57593
|
-
if (
|
|
57594
|
-
|
|
57595
|
-
if (typeof dynamicObject.setIsInteractive === 'function') {
|
|
57596
|
-
dynamicObject.setIsInteractive(true);
|
|
57597
|
-
}
|
|
57598
|
-
else {
|
|
57599
|
-
dynamicObject.isInteractive = true;
|
|
57600
|
-
}
|
|
58085
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
58086
|
+
object.setIsInteractive(true);
|
|
57601
58087
|
}
|
|
57602
58088
|
}
|
|
57603
58089
|
this._store.objects.insert(selectionGroup);
|
|
@@ -57618,14 +58104,8 @@ class KritzelCore {
|
|
|
57618
58104
|
teardownSelectionGroup(selectionGroup) {
|
|
57619
58105
|
selectionGroup.deselectAllChildren?.();
|
|
57620
58106
|
for (const object of selectionGroup.objects ?? []) {
|
|
57621
|
-
if (
|
|
57622
|
-
|
|
57623
|
-
if (typeof dynamicObject.setIsInteractive === 'function') {
|
|
57624
|
-
dynamicObject.setIsInteractive(false);
|
|
57625
|
-
}
|
|
57626
|
-
else {
|
|
57627
|
-
dynamicObject.isInteractive = false;
|
|
57628
|
-
}
|
|
58107
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
58108
|
+
object.setIsInteractive(false);
|
|
57629
58109
|
}
|
|
57630
58110
|
}
|
|
57631
58111
|
}
|
|
@@ -59071,13 +59551,7 @@ class KritzelWheelHelper {
|
|
|
59071
59551
|
return this.canElementConsumeWheel(scrollContainer, ev.deltaX, ev.deltaY);
|
|
59072
59552
|
}
|
|
59073
59553
|
static getScrollableContainerFromEventPath(path, dynamicObject) {
|
|
59074
|
-
const potentialRoots =
|
|
59075
|
-
if (dynamicObject.element instanceof HTMLElement) {
|
|
59076
|
-
potentialRoots.push(dynamicObject.element);
|
|
59077
|
-
}
|
|
59078
|
-
if (dynamicObject.elementRef instanceof HTMLElement) {
|
|
59079
|
-
potentialRoots.push(dynamicObject.elementRef);
|
|
59080
|
-
}
|
|
59554
|
+
const potentialRoots = dynamicObject.getEmbeddedContentRoots();
|
|
59081
59555
|
const legacyElementRef = dynamicObject.elmeentRef;
|
|
59082
59556
|
if (legacyElementRef instanceof HTMLElement) {
|
|
59083
59557
|
potentialRoots.push(legacyElementRef);
|
|
@@ -59254,8 +59728,8 @@ class KritzelSvgExportHelper {
|
|
|
59254
59728
|
.join('\n ');
|
|
59255
59729
|
const xmlDecl = includeXmlDeclaration ? '<?xml version="1.0" encoding="UTF-8"?>\n' : '';
|
|
59256
59730
|
const defsContent = defs.length > 0 ? `\n <defs>\n ${defs.join('\n ')}\n </defs>` : '';
|
|
59257
|
-
return `${xmlDecl}<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}" width="${viewBoxWidth}" height="${viewBoxHeight}">${defsContent}
|
|
59258
|
-
${elements}
|
|
59731
|
+
return `${xmlDecl}<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}" width="${viewBoxWidth}" height="${viewBoxHeight}">${defsContent}
|
|
59732
|
+
${elements}
|
|
59259
59733
|
</svg>`;
|
|
59260
59734
|
}
|
|
59261
59735
|
/**
|
|
@@ -59407,8 +59881,8 @@ class KritzelSvgExportHelper {
|
|
|
59407
59881
|
const orient = end === 'start' ? 'auto-start-reverse' : 'auto';
|
|
59408
59882
|
const refX = 0;
|
|
59409
59883
|
const refY = size / 2;
|
|
59410
|
-
return `<marker id="${markerId}" markerWidth="${size}" markerHeight="${size}" refX="${refX}" refY="${refY}" orient="${orient}" markerUnits="userSpaceOnUse">
|
|
59411
|
-
<path d="${path}" fill="${fill}" transform="scale(${size / 10})"/>
|
|
59884
|
+
return `<marker id="${markerId}" markerWidth="${size}" markerHeight="${size}" refX="${refX}" refY="${refY}" orient="${orient}" markerUnits="userSpaceOnUse">
|
|
59885
|
+
<path d="${path}" fill="${fill}" transform="scale(${size / 10})"/>
|
|
59412
59886
|
</marker>`;
|
|
59413
59887
|
}
|
|
59414
59888
|
/**
|
|
@@ -59437,6 +59911,9 @@ class KritzelSvgExportHelper {
|
|
|
59437
59911
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject')) {
|
|
59438
59912
|
return this.dynamicObjectToSvg(object, rasterSafeForCanvas);
|
|
59439
59913
|
}
|
|
59914
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelIframeObject')) {
|
|
59915
|
+
return this.iframeObjectToSvg(object);
|
|
59916
|
+
}
|
|
59440
59917
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
59441
59918
|
return this.groupToSvg(object, theme, imageDataUrls, rasterSafeForCanvas);
|
|
59442
59919
|
}
|
|
@@ -59455,10 +59932,10 @@ class KritzelSvgExportHelper {
|
|
|
59455
59932
|
const opacity = path.opacity !== 1 ? ` opacity="${path.opacity}"` : '';
|
|
59456
59933
|
const scale = this.getObjectScale(path);
|
|
59457
59934
|
// Path needs to be wrapped in a g with translation since path.d uses local coordinates
|
|
59458
|
-
return `<g transform="${transform}"${opacity}>
|
|
59459
|
-
<svg viewBox="${path.viewBox}" width="${path.totalWidth / scale}" height="${path.totalHeight / scale}" overflow="visible">
|
|
59460
|
-
<path d="${path.d}" fill="${fill || 'none'}" stroke="${stroke || 'none'}"${path.strokeWidth ? ` stroke-width="${path.strokeWidth}"` : ''}/>
|
|
59461
|
-
</svg>
|
|
59935
|
+
return `<g transform="${transform}"${opacity}>
|
|
59936
|
+
<svg viewBox="${path.viewBox}" width="${path.totalWidth / scale}" height="${path.totalHeight / scale}" overflow="visible">
|
|
59937
|
+
<path d="${path.d}" fill="${fill || 'none'}" stroke="${stroke || 'none'}"${path.strokeWidth ? ` stroke-width="${path.strokeWidth}"` : ''}/>
|
|
59938
|
+
</svg>
|
|
59462
59939
|
</g>`;
|
|
59463
59940
|
}
|
|
59464
59941
|
/**
|
|
@@ -59474,10 +59951,10 @@ class KritzelSvgExportHelper {
|
|
|
59474
59951
|
const scale = this.getObjectScale(line);
|
|
59475
59952
|
const markerStart = line.hasStartArrow ? ` marker-start="url(#${line.startMarkerId})"` : '';
|
|
59476
59953
|
const markerEnd = line.hasEndArrow ? ` marker-end="url(#${line.endMarkerId})"` : '';
|
|
59477
|
-
return `<g transform="${transform}"${opacity}>
|
|
59478
|
-
<svg viewBox="${line.viewBox}" width="${line.totalWidth / scale}" height="${line.totalHeight / scale}" overflow="visible">
|
|
59479
|
-
<path d="${line.d}" fill="none" stroke="${stroke}" stroke-width="${line.strokeWidth}" stroke-linecap="round"${markerStart}${markerEnd}/>
|
|
59480
|
-
</svg>
|
|
59954
|
+
return `<g transform="${transform}"${opacity}>
|
|
59955
|
+
<svg viewBox="${line.viewBox}" width="${line.totalWidth / scale}" height="${line.totalHeight / scale}" overflow="visible">
|
|
59956
|
+
<path d="${line.d}" fill="none" stroke="${stroke}" stroke-width="${line.strokeWidth}" stroke-linecap="round"${markerStart}${markerEnd}/>
|
|
59957
|
+
</svg>
|
|
59481
59958
|
</g>`;
|
|
59482
59959
|
}
|
|
59483
59960
|
/**
|
|
@@ -59501,18 +59978,18 @@ class KritzelSvgExportHelper {
|
|
|
59501
59978
|
const textHtml = this.prosemirrorToHtml(shape.content, shape, theme);
|
|
59502
59979
|
if (textHtml) {
|
|
59503
59980
|
const fontColor = KritzelColorHelper.resolveThemeColor(shape.fontColor, theme);
|
|
59504
|
-
textContent = `
|
|
59505
|
-
<foreignObject x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}">
|
|
59506
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; text-align: center; font-family: ${shape.fontFamily}; font-size: ${shape.fontSize}px; color: ${fontColor}; overflow: hidden;">
|
|
59507
|
-
${textHtml}
|
|
59508
|
-
</div>
|
|
59981
|
+
textContent = `
|
|
59982
|
+
<foreignObject x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}">
|
|
59983
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; text-align: center; font-family: ${shape.fontFamily}; font-size: ${shape.fontSize}px; color: ${fontColor}; overflow: hidden;">
|
|
59984
|
+
${textHtml}
|
|
59985
|
+
</div>
|
|
59509
59986
|
</foreignObject>`;
|
|
59510
59987
|
}
|
|
59511
59988
|
}
|
|
59512
|
-
return `<g transform="${transform}"${opacity}>
|
|
59513
|
-
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth / scale}" height="${shape.totalHeight / scale}" overflow="visible" preserveAspectRatio="none">
|
|
59514
|
-
<path d="${pathD}" fill="${fill || 'transparent'}" stroke="${stroke}" stroke-width="${shape.strokeWidth}"/>${textContent}
|
|
59515
|
-
</svg>
|
|
59989
|
+
return `<g transform="${transform}"${opacity}>
|
|
59990
|
+
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth / scale}" height="${shape.totalHeight / scale}" overflow="visible" preserveAspectRatio="none">
|
|
59991
|
+
<path d="${pathD}" fill="${fill || 'transparent'}" stroke="${stroke}" stroke-width="${shape.strokeWidth}"/>${textContent}
|
|
59992
|
+
</svg>
|
|
59516
59993
|
</g>`;
|
|
59517
59994
|
}
|
|
59518
59995
|
/**
|
|
@@ -59543,10 +60020,10 @@ class KritzelSvgExportHelper {
|
|
|
59543
60020
|
// adjusted font-size already accounts for it – keeping both would double-scale
|
|
59544
60021
|
// the content and overflow the foreignObject.
|
|
59545
60022
|
const svgFontSizePx = (text.fontSize * (4 / 3) * (text.scaleFactor || 1) / scale).toFixed(4);
|
|
59546
|
-
return `<g transform="${transform}"${opacity}>
|
|
59547
|
-
<foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
|
|
59548
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: ${text.fontFamily}; font-size: ${svgFontSizePx}px; color: ${fontColor}; background-color: ${bgColor || 'transparent'}; white-space: pre-wrap; word-wrap: break-word; width: 100%; margin: 0; padding: 0; box-sizing: border-box;">${htmlContent.trim()}</div>
|
|
59549
|
-
</foreignObject>
|
|
60023
|
+
return `<g transform="${transform}"${opacity}>
|
|
60024
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
|
|
60025
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: ${text.fontFamily}; font-size: ${svgFontSizePx}px; color: ${fontColor}; background-color: ${bgColor || 'transparent'}; white-space: pre-wrap; word-wrap: break-word; width: 100%; margin: 0; padding: 0; box-sizing: border-box;">${htmlContent.trim()}</div>
|
|
60026
|
+
</foreignObject>
|
|
59550
60027
|
</g>`;
|
|
59551
60028
|
}
|
|
59552
60029
|
/**
|
|
@@ -59580,9 +60057,9 @@ class KritzelSvgExportHelper {
|
|
|
59580
60057
|
return `<tspan x="0" y="${y}" xml:space="preserve">${this.escapeHtml(line)}</tspan>`;
|
|
59581
60058
|
})
|
|
59582
60059
|
.join('');
|
|
59583
|
-
return `<g transform="${transform}"${opacity}>
|
|
59584
|
-
${bgRect}
|
|
59585
|
-
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
60060
|
+
return `<g transform="${transform}"${opacity}>
|
|
60061
|
+
${bgRect}
|
|
60062
|
+
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
59586
60063
|
</g>`;
|
|
59587
60064
|
}
|
|
59588
60065
|
/**
|
|
@@ -59610,8 +60087,8 @@ class KritzelSvgExportHelper {
|
|
|
59610
60087
|
const width = image.totalWidth / scale;
|
|
59611
60088
|
const height = image.totalHeight / scale;
|
|
59612
60089
|
const href = imageDataUrls?.get(image.id) || image.resolvedSrc || image.src || '';
|
|
59613
|
-
return `<g transform="${transform}"${opacity}>
|
|
59614
|
-
<image href="${href}" x="0" y="0" width="${width}" height="${height}" preserveAspectRatio="xMidYMid meet"/>
|
|
60090
|
+
return `<g transform="${transform}"${opacity}>
|
|
60091
|
+
<image href="${href}" x="0" y="0" width="${width}" height="${height}" preserveAspectRatio="xMidYMid meet"/>
|
|
59615
60092
|
</g>`;
|
|
59616
60093
|
}
|
|
59617
60094
|
/**
|
|
@@ -59631,19 +60108,30 @@ class KritzelSvgExportHelper {
|
|
|
59631
60108
|
if (rasterSafeForCanvas) {
|
|
59632
60109
|
// PNG export: render placeholder rect (foreignObject doesn't rasterize to PNG well)
|
|
59633
60110
|
console.warn('[KritzelDynamicObject SVG Export] Dynamic objects do not serialize well to PNG. Use SVG export or screenshot instead.');
|
|
59634
|
-
return `<g transform="${transform}"${opacity}>
|
|
59635
|
-
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
59636
|
-
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Dynamic Object]</text>
|
|
60111
|
+
return `<g transform="${transform}"${opacity}>
|
|
60112
|
+
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
60113
|
+
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Dynamic Object]</text>
|
|
59637
60114
|
</g>`;
|
|
59638
60115
|
}
|
|
59639
60116
|
// SVG export: use foreignObject to embed HTML
|
|
59640
60117
|
const html = obj.element?.outerHTML || '<div style="border:1px dashed #ccc">Empty</div>';
|
|
59641
|
-
return `<g transform="${transform}"${opacity}>
|
|
59642
|
-
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
59643
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;overflow:hidden;">
|
|
59644
|
-
${html}
|
|
59645
|
-
</div>
|
|
59646
|
-
</foreignObject>
|
|
60118
|
+
return `<g transform="${transform}"${opacity}>
|
|
60119
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
60120
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;overflow:hidden;">
|
|
60121
|
+
${html}
|
|
60122
|
+
</div>
|
|
60123
|
+
</foreignObject>
|
|
60124
|
+
</g>`;
|
|
60125
|
+
}
|
|
60126
|
+
static iframeObjectToSvg(object) {
|
|
60127
|
+
const transform = this.buildTransform(object);
|
|
60128
|
+
const opacity = object.opacity !== 1 ? ` opacity="${object.opacity}"` : '';
|
|
60129
|
+
const scale = this.getObjectScale(object);
|
|
60130
|
+
const width = object.totalWidth / scale;
|
|
60131
|
+
const height = object.totalHeight / scale;
|
|
60132
|
+
return `<g transform="${transform}"${opacity}>
|
|
60133
|
+
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
60134
|
+
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Iframe]</text>
|
|
59647
60135
|
</g>`;
|
|
59648
60136
|
}
|
|
59649
60137
|
/**
|
|
@@ -59663,8 +60151,8 @@ class KritzelSvgExportHelper {
|
|
|
59663
60151
|
return '';
|
|
59664
60152
|
}
|
|
59665
60153
|
const opacity = group.opacity !== 1 ? ` opacity="${group.opacity}"` : '';
|
|
59666
|
-
return `<g${opacity}>
|
|
59667
|
-
${children}
|
|
60154
|
+
return `<g${opacity}>
|
|
60155
|
+
${children}
|
|
59668
60156
|
</g>`;
|
|
59669
60157
|
}
|
|
59670
60158
|
/**
|
|
@@ -59849,12 +60337,26 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
59849
60337
|
/** Authoritative workspace catalog for this engine instance. When provided, provider-only workspaces are hidden but not deleted. */
|
|
59850
60338
|
workspaces;
|
|
59851
60339
|
async onWorkspacesPropChange() {
|
|
59852
|
-
|
|
60340
|
+
this._workspacesRevision++;
|
|
60341
|
+
if (!this._isYjsInitialized || this._syncInitPromise) {
|
|
59853
60342
|
return;
|
|
59854
60343
|
}
|
|
59855
|
-
|
|
59856
|
-
|
|
59857
|
-
|
|
60344
|
+
const previousReconciliation = this._workspacePropReconciliationPromise;
|
|
60345
|
+
const reconciliationPromise = (async () => {
|
|
60346
|
+
await previousReconciliation;
|
|
60347
|
+
await this.reconcileProvidedWorkspaces();
|
|
60348
|
+
await this.ensureActiveWorkspaceIsVisible();
|
|
60349
|
+
this.workspacesChange.emit(this.getVisibleWorkspaces());
|
|
60350
|
+
})();
|
|
60351
|
+
this._workspacePropReconciliationPromise = reconciliationPromise;
|
|
60352
|
+
try {
|
|
60353
|
+
await reconciliationPromise;
|
|
60354
|
+
}
|
|
60355
|
+
finally {
|
|
60356
|
+
if (this._workspacePropReconciliationPromise === reconciliationPromise) {
|
|
60357
|
+
this._workspacePropReconciliationPromise = null;
|
|
60358
|
+
}
|
|
60359
|
+
}
|
|
59858
60360
|
}
|
|
59859
60361
|
/** Optional unique identifier for namespacing storage keys across multiple editor instances. */
|
|
59860
60362
|
editorId;
|
|
@@ -59908,6 +60410,12 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
59908
60410
|
onUserChange(newValue) {
|
|
59909
60411
|
this.core.setUser(newValue);
|
|
59910
60412
|
}
|
|
60413
|
+
/** Tool definitions to register with this engine instance. */
|
|
60414
|
+
tools = [];
|
|
60415
|
+
onToolsChange() {
|
|
60416
|
+
this._toolsRevision++;
|
|
60417
|
+
void this.registerConfiguredTools();
|
|
60418
|
+
}
|
|
59911
60419
|
/** Context menu items shown when right-clicking the canvas background. */
|
|
59912
60420
|
globalContextMenuItems;
|
|
59913
60421
|
onGlobalContextMenuItemsChange(newValue) {
|
|
@@ -60098,7 +60606,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
60098
60606
|
}
|
|
60099
60607
|
const hoveredObject = this.core.getObjectFromPointerEvent(ev);
|
|
60100
60608
|
if (hoveredObject &&
|
|
60101
|
-
ObjectHelper.
|
|
60609
|
+
ObjectHelper.isKritzelEmbeddedObject(hoveredObject) &&
|
|
60102
60610
|
KritzelWheelHelper.shouldKeepWheelInDynamicObject(ev, hoveredObject)) {
|
|
60103
60611
|
return;
|
|
60104
60612
|
}
|
|
@@ -60200,7 +60708,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
60200
60708
|
return false;
|
|
60201
60709
|
}
|
|
60202
60710
|
const object = this.core.store.objects.findById(objectElement.id);
|
|
60203
|
-
if (!object || !
|
|
60711
|
+
if (!object || !ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
60204
60712
|
return false;
|
|
60205
60713
|
}
|
|
60206
60714
|
const isSelected = !!this.core.store.selectionGroup?.objects?.some(selectedObject => selectedObject.id === object.id);
|
|
@@ -60210,13 +60718,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
60210
60718
|
if (object.isInteractive !== true) {
|
|
60211
60719
|
return false;
|
|
60212
60720
|
}
|
|
60213
|
-
const potentialRoots =
|
|
60214
|
-
if (object.element instanceof H) {
|
|
60215
|
-
potentialRoots.push(object.element);
|
|
60216
|
-
}
|
|
60217
|
-
if (object.elementRef instanceof H) {
|
|
60218
|
-
potentialRoots.push(object.elementRef);
|
|
60219
|
-
}
|
|
60721
|
+
const potentialRoots = object.getEmbeddedContentRoots();
|
|
60220
60722
|
if (potentialRoots.length === 0) {
|
|
60221
60723
|
return false;
|
|
60222
60724
|
}
|
|
@@ -60390,7 +60892,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
60390
60892
|
* Switches the active drawing tool by its registered name.
|
|
60391
60893
|
* @param toolName - The name the tool was registered with (e.g., 'brush', 'eraser').
|
|
60392
60894
|
*/
|
|
60393
|
-
async
|
|
60895
|
+
async setActiveTool(toolName) {
|
|
60394
60896
|
const tool = this.core.toolRegistry.getTool(toolName);
|
|
60395
60897
|
if (!tool) {
|
|
60396
60898
|
console.warn(`[KritzelEngine] No tool registered with name: ${toolName}`);
|
|
@@ -61696,9 +62198,13 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
61696
62198
|
_stateChangeListenersRegistered = false;
|
|
61697
62199
|
_workspaceInitializationPromise = null;
|
|
61698
62200
|
_workspaceInitializationTargetKey = null;
|
|
62201
|
+
_workspacePropReconciliationPromise = null;
|
|
61699
62202
|
_syncInitPromise = null;
|
|
62203
|
+
_toolsInitPromise = null;
|
|
62204
|
+
_toolsRevision = 0;
|
|
61700
62205
|
_syncConfigRevision = 0;
|
|
61701
62206
|
_assetStorageConfigRevision = 0;
|
|
62207
|
+
_workspacesRevision = 0;
|
|
61702
62208
|
_hasLoggedUnlicensedWelcomeBanner = false;
|
|
61703
62209
|
_previousVisibleDynamicObjects = new Set();
|
|
61704
62210
|
_revealedImageKeys = new Set();
|
|
@@ -61711,6 +62217,37 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
61711
62217
|
undoStackSize: 0,
|
|
61712
62218
|
redoStackSize: 0,
|
|
61713
62219
|
};
|
|
62220
|
+
/** Returns a tool registered in this engine instance. */
|
|
62221
|
+
async getTool(toolName) {
|
|
62222
|
+
await this.registerConfiguredTools();
|
|
62223
|
+
return this.core.toolRegistry.getTool(toolName);
|
|
62224
|
+
}
|
|
62225
|
+
async registerConfiguredTools() {
|
|
62226
|
+
if (this._toolsInitPromise) {
|
|
62227
|
+
return this._toolsInitPromise;
|
|
62228
|
+
}
|
|
62229
|
+
this._toolsInitPromise = (async () => {
|
|
62230
|
+
do {
|
|
62231
|
+
const revision = this._toolsRevision;
|
|
62232
|
+
for (const definition of this.tools) {
|
|
62233
|
+
let toolClass = definition.tool;
|
|
62234
|
+
if (typeof toolClass !== 'function') {
|
|
62235
|
+
toolClass = toolClass.constructor;
|
|
62236
|
+
}
|
|
62237
|
+
await this.registerTool(definition.name, toolClass, definition.config);
|
|
62238
|
+
}
|
|
62239
|
+
if (revision === this._toolsRevision) {
|
|
62240
|
+
break;
|
|
62241
|
+
}
|
|
62242
|
+
} while (true);
|
|
62243
|
+
})();
|
|
62244
|
+
try {
|
|
62245
|
+
await this._toolsInitPromise;
|
|
62246
|
+
}
|
|
62247
|
+
finally {
|
|
62248
|
+
this._toolsInitPromise = null;
|
|
62249
|
+
}
|
|
62250
|
+
}
|
|
61714
62251
|
setLoadingState(isLoading) {
|
|
61715
62252
|
if (this.core.store.state.isLoading === isLoading) {
|
|
61716
62253
|
return;
|
|
@@ -61842,6 +62379,8 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
61842
62379
|
this.core.licenseManager.destroy();
|
|
61843
62380
|
}
|
|
61844
62381
|
componentWillLoad() {
|
|
62382
|
+
this._toolsRevision++;
|
|
62383
|
+
void this.registerConfiguredTools();
|
|
61845
62384
|
this.core.setEditorId(this.editorId);
|
|
61846
62385
|
if (this.themes && this.themes.length > 0) {
|
|
61847
62386
|
this.core.themeManager.registerThemes(this.themes);
|
|
@@ -61881,7 +62420,9 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
61881
62420
|
const editorElement = this.host.closest('kritzel-editor');
|
|
61882
62421
|
this.core.themeManager.setTargetElement(editorElement || this.host);
|
|
61883
62422
|
// Initialize sync config and Yjs
|
|
62423
|
+
await this.registerConfiguredTools();
|
|
61884
62424
|
await this.initializeSyncAndWorkspace();
|
|
62425
|
+
await this.waitForWorkspaceAndSceneReady();
|
|
61885
62426
|
if (this.core.store.state.isReady === false) {
|
|
61886
62427
|
this.core.store.state.isReady = true;
|
|
61887
62428
|
this.logUnlicensedWelcomeBanner();
|
|
@@ -61903,6 +62444,20 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
61903
62444
|
this._syncInitPromise = null;
|
|
61904
62445
|
}
|
|
61905
62446
|
}
|
|
62447
|
+
async waitForSceneRender() {
|
|
62448
|
+
await new Promise(resolve => {
|
|
62449
|
+
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
62450
|
+
});
|
|
62451
|
+
}
|
|
62452
|
+
async waitForWorkspaceAndSceneReady() {
|
|
62453
|
+
let observedRevision;
|
|
62454
|
+
do {
|
|
62455
|
+
observedRevision = this._workspacesRevision;
|
|
62456
|
+
await this._workspacePropReconciliationPromise;
|
|
62457
|
+
await this.waitForSceneRender();
|
|
62458
|
+
} while (observedRevision !== this._workspacesRevision ||
|
|
62459
|
+
this._workspacePropReconciliationPromise);
|
|
62460
|
+
}
|
|
61906
62461
|
/**
|
|
61907
62462
|
* Initializes the asset storage layer with the latest config. Mirrors
|
|
61908
62463
|
* the in-flight replay logic of {@link doInitializeSyncAndWorkspace} for
|
|
@@ -62285,7 +62840,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62285
62840
|
if (!KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup')) {
|
|
62286
62841
|
return 'auto';
|
|
62287
62842
|
}
|
|
62288
|
-
if (object.objects.length === 1 &&
|
|
62843
|
+
if (object.objects.length === 1 && ObjectHelper.isKritzelEmbeddedObject(object.objects[0])) {
|
|
62289
62844
|
return 'none';
|
|
62290
62845
|
}
|
|
62291
62846
|
return 'auto';
|
|
@@ -62293,7 +62848,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62293
62848
|
// Track visible dynamic objects and unmount culled ones
|
|
62294
62849
|
const currentVisibleDynamicObjects = new Set();
|
|
62295
62850
|
visibleObjects.forEach(object => {
|
|
62296
|
-
if (
|
|
62851
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
62297
62852
|
currentVisibleDynamicObjects.add(object.id);
|
|
62298
62853
|
}
|
|
62299
62854
|
});
|
|
@@ -62301,7 +62856,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62301
62856
|
this._previousVisibleDynamicObjects.forEach(id => {
|
|
62302
62857
|
if (!currentVisibleDynamicObjects.has(id)) {
|
|
62303
62858
|
const object = this.core.store.objects.findById(id);
|
|
62304
|
-
if (object &&
|
|
62859
|
+
if (object && ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
62305
62860
|
object.unmount();
|
|
62306
62861
|
}
|
|
62307
62862
|
}
|
|
@@ -62394,7 +62949,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62394
62949
|
display: 'flex',
|
|
62395
62950
|
alignItems: 'center',
|
|
62396
62951
|
justifyContent: 'center',
|
|
62397
|
-
} }, h("kritzel-icon", { name: object.loadState === 'error' ? '
|
|
62952
|
+
} }, h("kritzel-icon", { name: object.loadState === 'error' ? 'imageOff' : 'image', size: Math.max(16, Math.min(object.totalWidth, object.totalHeight) * 0.3), style: {
|
|
62398
62953
|
color: KritzelColorHelper.resolveThemeColor({ light: '#9ca3af', dark: '#6b7280' }, currentTheme),
|
|
62399
62954
|
} }))), KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject') && (h("div", { ref: el => el && object.mount(el), style: {
|
|
62400
62955
|
position: 'absolute',
|
|
@@ -62413,7 +62968,37 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62413
62968
|
padding: object.padding + 'px',
|
|
62414
62969
|
overflow: 'visible',
|
|
62415
62970
|
display: 'block',
|
|
62416
|
-
} })), KritzelClassHelper.isInstanceOf(object, '
|
|
62971
|
+
} })), KritzelClassHelper.isInstanceOf(object, 'KritzelIframeObject') && (h("div", { style: {
|
|
62972
|
+
position: 'absolute',
|
|
62973
|
+
left: '0',
|
|
62974
|
+
top: '0',
|
|
62975
|
+
width: object.totalWidth + 'px',
|
|
62976
|
+
height: object.totalHeight + 'px',
|
|
62977
|
+
transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
|
|
62978
|
+
transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
|
|
62979
|
+
opacity: effectiveOpacityString,
|
|
62980
|
+
backgroundColor: KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
|
|
62981
|
+
borderColor: KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
|
|
62982
|
+
borderWidth: object.borderWidth + 'px',
|
|
62983
|
+
borderStyle: 'solid',
|
|
62984
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
62985
|
+
boxShadow: object.boxShadow,
|
|
62986
|
+
overflow: 'hidden',
|
|
62987
|
+
display: 'block',
|
|
62988
|
+
pointerEvents: object.markedForRemoval ? 'none' : 'auto',
|
|
62989
|
+
} }, h("iframe", { ref: element => element && object.mount(element), title: object.title, sandbox: object.sandboxAttribute, style: {
|
|
62990
|
+
display: 'block',
|
|
62991
|
+
width: '100%',
|
|
62992
|
+
height: '100%',
|
|
62993
|
+
border: '0',
|
|
62994
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
62995
|
+
pointerEvents: object.isInteractive ? 'auto' : 'none',
|
|
62996
|
+
} }), h("div", { style: {
|
|
62997
|
+
position: 'absolute',
|
|
62998
|
+
inset: '0',
|
|
62999
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
63000
|
+
pointerEvents: object.isInteractive ? 'none' : 'auto',
|
|
63001
|
+
} }))), KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') && !this.core.displaySelectionLineUI(object) && (h("div", { ref: el => el && object.mount(el), style: {
|
|
62417
63002
|
position: 'absolute',
|
|
62418
63003
|
left: '0',
|
|
62419
63004
|
top: '0',
|
|
@@ -62771,6 +63356,9 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62771
63356
|
"user": [{
|
|
62772
63357
|
"onUserChange": 0
|
|
62773
63358
|
}],
|
|
63359
|
+
"tools": [{
|
|
63360
|
+
"onToolsChange": 0
|
|
63361
|
+
}],
|
|
62774
63362
|
"globalContextMenuItems": [{
|
|
62775
63363
|
"onGlobalContextMenuItemsChange": 0
|
|
62776
63364
|
}],
|
|
@@ -62831,6 +63419,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62831
63419
|
"syncConfig": [16],
|
|
62832
63420
|
"assetStorageConfig": [16],
|
|
62833
63421
|
"user": [16],
|
|
63422
|
+
"tools": [16],
|
|
62834
63423
|
"globalContextMenuItems": [16],
|
|
62835
63424
|
"objectContextMenuItems": [16],
|
|
62836
63425
|
"scaleMax": [1026, "scale-max"],
|
|
@@ -62855,7 +63444,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62855
63444
|
"beginSceneBootstrap": [64],
|
|
62856
63445
|
"endSceneBootstrap": [64],
|
|
62857
63446
|
"registerTool": [64],
|
|
62858
|
-
"
|
|
63447
|
+
"setActiveTool": [64],
|
|
62859
63448
|
"disable": [64],
|
|
62860
63449
|
"enable": [64],
|
|
62861
63450
|
"delete": [64],
|
|
@@ -62931,7 +63520,8 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62931
63520
|
"getAvailableLocales": [64],
|
|
62932
63521
|
"getAvailableLocaleOptions": [64],
|
|
62933
63522
|
"t": [64],
|
|
62934
|
-
"getResolvedTerms": [64]
|
|
63523
|
+
"getResolvedTerms": [64],
|
|
63524
|
+
"getTool": [64]
|
|
62935
63525
|
}, [[1, "wheel", "handleWheel"], [0, "pointerdown", "handlePointerDown"], [0, "pointermove", "handlePointerMove"], [0, "pointerup", "handlePointerUp"], [0, "pointercancel", "handlePointerCancel"], [1, "pointerleave", "handlePointerLeave"], [1, "longpress", "handleLongPress"], [0, "contextmenu", "handleContextMenu"], [9, "resize", "handleResize"], [8, "keydown", "handleKeyDown"], [8, "keyup", "handleKeyUp"], [8, "copy", "handleCopy"], [8, "cut", "handleCut"], [8, "paste", "handlePaste"], [4, "dblclick", "preventDoubleTapZoomOnTouchDevices"]], {
|
|
62936
63526
|
"workspaces": [{
|
|
62937
63527
|
"onWorkspacesPropChange": 0
|
|
@@ -62948,6 +63538,9 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62948
63538
|
"user": [{
|
|
62949
63539
|
"onUserChange": 0
|
|
62950
63540
|
}],
|
|
63541
|
+
"tools": [{
|
|
63542
|
+
"onToolsChange": 0
|
|
63543
|
+
}],
|
|
62951
63544
|
"globalContextMenuItems": [{
|
|
62952
63545
|
"onGlobalContextMenuItemsChange": 0
|
|
62953
63546
|
}],
|