@kritzel/engine 0.4.31 → 0.4.33
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 +49 -49
- package/dist/cjs/{engine.constants-CakmdKMW.js → engine.constants-VyFrUl1W.js} +627 -129
- package/dist/cjs/{index-BbbWU2aN.js → index-BP5Iy6FQ.js} +27 -9
- package/dist/cjs/index.cjs.js +4 -2
- package/dist/cjs/kritzel-awareness-cursors_5.cjs.entry.js +257 -113
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/stencil.cjs.js +3 -3
- package/dist/collection/classes/core/core.class.js +40 -32
- package/dist/collection/classes/core/reviver.class.js +4 -0
- package/dist/collection/classes/core/store.class.js +10 -3
- package/dist/collection/classes/managers/cursor.manager.js +10 -5
- package/dist/collection/classes/objects/dynamic-object.class.js +18 -5
- package/dist/collection/classes/objects/iframe.class.js +447 -0
- package/dist/collection/classes/registries/icon-registry.class.js +100 -67
- package/dist/collection/classes/tools/selection-tool.class.js +3 -3
- package/dist/collection/collection-manifest.json +4 -2
- package/dist/collection/components/kritzel-awareness-cursors/kritzel-awareness-cursors.css +115 -115
- package/dist/collection/components/kritzel-awareness-cursors/kritzel-awareness-cursors.js +1 -1
- package/dist/collection/components/kritzel-cursor-trail/kritzel-cursor-trail.css +10 -10
- package/dist/collection/components/kritzel-cursor-trail/kritzel-cursor-trail.js +1 -1
- package/dist/collection/components/kritzel-engine/kritzel-engine.css +80 -80
- package/dist/collection/components/kritzel-engine/kritzel-engine.js +196 -44
- package/dist/collection/components/kritzel-icon/kritzel-icon.css +18 -18
- package/dist/collection/components/kritzel-icon/kritzel-icon.js +25 -4
- package/dist/collection/components/kritzel-watermark/kritzel-watermark.css +29 -29
- package/dist/collection/components/kritzel-watermark/kritzel-watermark.js +2 -2
- package/dist/collection/constants/version.js +1 -1
- package/dist/collection/helpers/cursor.helper.js +8 -8
- package/dist/collection/helpers/object.helper.js +13 -0
- package/dist/collection/helpers/svg-export.helper.js +55 -41
- package/dist/collection/helpers/wheel.helper.js +1 -7
- package/dist/collection/index.js +3 -0
- package/dist/collection/interfaces/embedded-object.interface.js +1 -0
- package/dist/collection/themes/dark-theme.js +1 -5
- package/dist/collection/themes/light-theme.js +1 -6
- package/dist/components/index.js +7 -7
- package/dist/components/kritzel-awareness-cursors.js +1 -1
- package/dist/components/kritzel-cursor-trail.js +1 -1
- package/dist/components/kritzel-engine.js +755 -161
- package/dist/components/kritzel-icon.js +1 -1
- package/dist/components/kritzel-watermark.js +1 -1
- package/dist/components/{p-B2Htv9ou.js → p-BHVbfJrf.js} +3 -3
- package/dist/components/{p-YP8wAcF4.js → p-BTU9qcSW.js} +2 -2
- package/dist/components/{p-CfSx6HU_.js → p-BWfRbEIq.js} +16 -4
- package/dist/components/p-NAEiq8CK.js +214 -0
- package/dist/components/{p-BvRGQvVI.js → p-k0LxV9Bg.js} +18 -14
- package/dist/esm/{engine.constants-Bl5-pbq-.js → engine.constants-BHTr2qPx.js} +626 -130
- package/dist/esm/{index-BU9Mv7y0.js → index-C8PnHbLt.js} +27 -10
- package/dist/esm/index.js +3 -3
- package/dist/esm/kritzel-awareness-cursors_5.entry.js +257 -113
- package/dist/esm/loader.js +3 -3
- package/dist/esm/stencil.js +4 -4
- package/dist/stencil/index.esm.js +3 -3
- package/dist/stencil/{p-f0a8b7af.entry.js → p-40097a38.entry.js} +257 -113
- package/dist/stencil/{p-Bl5-pbq-.js → p-BHTr2qPx.js} +626 -130
- package/dist/stencil/{p-BU9Mv7y0.js → p-C8PnHbLt.js} +27 -10
- package/dist/stencil/stencil.esm.js +4 -4
- package/dist/types/classes/core/store.class.d.ts +3 -2
- package/dist/types/classes/objects/dynamic-object.class.d.ts +4 -2
- package/dist/types/classes/objects/iframe.class.d.ts +76 -0
- package/dist/types/classes/registries/icon-registry.class.d.ts +75 -6
- package/dist/types/components/kritzel-engine/kritzel-engine.d.ts +14 -1
- package/dist/types/components/kritzel-icon/kritzel-icon.d.ts +5 -1
- package/dist/types/components.d.ts +26 -8
- package/dist/types/constants/version.d.ts +1 -1
- package/dist/types/helpers/cursor.helper.d.ts +2 -1
- package/dist/types/helpers/object.helper.d.ts +2 -0
- package/dist/types/helpers/svg-export.helper.d.ts +1 -0
- package/dist/types/helpers/wheel.helper.d.ts +2 -2
- package/dist/types/index.d.ts +3 -0
- package/dist/types/interfaces/context-menu-item.interface.d.ts +2 -1
- package/dist/types/interfaces/dynamic-object-renderer.interface.d.ts +7 -0
- package/dist/types/interfaces/embedded-object.interface.d.ts +9 -0
- package/dist/types/interfaces/engine-state.interface.d.ts +3 -2
- package/dist/types/interfaces/login-config.interface.d.ts +2 -1
- package/dist/types/interfaces/master-detail.interface.d.ts +2 -1
- package/dist/types/interfaces/menu-item.interface.d.ts +2 -1
- package/dist/types/interfaces/theme.interface.d.ts +6 -7
- package/dist/types/interfaces/tool.interface.d.ts +9 -0
- package/dist/types/interfaces/toolbar-item.interface.d.ts +3 -2
- package/dist/types/stencil-public-runtime.d.ts +61 -55
- package/package.json +3 -1
- package/readme.md +10 -10
- package/dist/components/p-fx6msYHJ.js +0 -167
|
@@ -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$4 } from './p-
|
|
3
|
-
import { K as KritzelBaseObject, h as KritzelMathHelper, c as KritzelColorHelper, i as KritzelGeometryHelper, D as DEFAULT_COLOR_PALETTE, a as KritzelPath, b as KritzelLine, O as ObjectHelper, d as KritzelThemeManager, g as defineCustomElement$5 } from './p-
|
|
4
|
-
import { A as ABSOLUTE_SCALE_MAX, a as ABSOLUTE_SCALE_MIN, d as defineCustomElement$2 } from './p-
|
|
1
|
+
import { p as proxyCustomElement, H, c as createEvent, h, d as Host, t as transformTag } from './p-BWfRbEIq.js';
|
|
2
|
+
import { a as KritzelMouseButton, d as defineCustomElement$4 } from './p-BTU9qcSW.js';
|
|
3
|
+
import { K as KritzelBaseObject, h as KritzelMathHelper, c as KritzelColorHelper, i as KritzelGeometryHelper, D as DEFAULT_COLOR_PALETTE, a as KritzelPath, b as KritzelLine, O as ObjectHelper, d as KritzelThemeManager, g as defineCustomElement$5 } from './p-k0LxV9Bg.js';
|
|
4
|
+
import { A as ABSOLUTE_SCALE_MAX, a as ABSOLUTE_SCALE_MIN, d as defineCustomElement$2 } from './p-BHVbfJrf.js';
|
|
5
5
|
import * as Y from 'yjs';
|
|
6
|
-
import { K as KritzelIconRegistry,
|
|
6
|
+
import { K as KritzelIconRegistry, a as defineCustomElement$3 } from './p-NAEiq8CK.js';
|
|
7
7
|
|
|
8
8
|
class KritzelDevicesHelper {
|
|
9
9
|
static isTouchDevice() {
|
|
@@ -739,7 +739,6 @@ class Mark {
|
|
|
739
739
|
if (!type)
|
|
740
740
|
throw new RangeError(`There is no mark type ${json.type} in this schema`);
|
|
741
741
|
let mark = type.create(json.attrs);
|
|
742
|
-
type.checkAttrs(mark.attrs);
|
|
743
742
|
return mark;
|
|
744
743
|
}
|
|
745
744
|
/**
|
|
@@ -1719,11 +1718,11 @@ class Node {
|
|
|
1719
1718
|
*/
|
|
1720
1719
|
check() {
|
|
1721
1720
|
this.type.checkContent(this.content);
|
|
1722
|
-
this.type.
|
|
1721
|
+
checkAttrs(this.type.attrs, this.attrs, "node", this.type.name);
|
|
1723
1722
|
let copy = Mark.none;
|
|
1724
1723
|
for (let i = 0; i < this.marks.length; i++) {
|
|
1725
1724
|
let mark = this.marks[i];
|
|
1726
|
-
mark.type.
|
|
1725
|
+
checkAttrs(mark.type.attrs, mark.attrs, "mark", mark.type.name);
|
|
1727
1726
|
copy = mark.addToSet(copy);
|
|
1728
1727
|
}
|
|
1729
1728
|
if (!Mark.sameSet(copy, this.marks))
|
|
@@ -1764,7 +1763,6 @@ class Node {
|
|
|
1764
1763
|
}
|
|
1765
1764
|
let content = Fragment.fromJSON(schema, json.content);
|
|
1766
1765
|
let node = schema.nodeType(json.type).create(json.attrs, content, marks);
|
|
1767
|
-
node.type.checkAttrs(node.attrs);
|
|
1768
1766
|
return node;
|
|
1769
1767
|
}
|
|
1770
1768
|
}
|
|
@@ -1814,6 +1812,15 @@ function wrapMarks(marks, str) {
|
|
|
1814
1812
|
str = marks[i].type.name + "(" + str + ")";
|
|
1815
1813
|
return str;
|
|
1816
1814
|
}
|
|
1815
|
+
function checkAttrs(attrs, values, type, name) {
|
|
1816
|
+
for (let attr in values)
|
|
1817
|
+
if (!(attr in attrs))
|
|
1818
|
+
throw new RangeError(`Unsupported attribute ${attr} for ${type} of type ${name}`);
|
|
1819
|
+
for (let attr in attrs) {
|
|
1820
|
+
if (attrs[attr].validate)
|
|
1821
|
+
attrs[attr].validate(values[attr]);
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1817
1824
|
|
|
1818
1825
|
/**
|
|
1819
1826
|
Instances of this class represent a match state of a node type's
|
|
@@ -2268,27 +2275,21 @@ function defaultAttrs(attrs) {
|
|
|
2268
2275
|
function computeAttrs(attrs, value) {
|
|
2269
2276
|
let built = Object.create(null);
|
|
2270
2277
|
for (let name in attrs) {
|
|
2278
|
+
let attr = attrs[name];
|
|
2271
2279
|
let given = value && value[name];
|
|
2272
2280
|
if (given === undefined) {
|
|
2273
|
-
let attr = attrs[name];
|
|
2274
2281
|
if (attr.hasDefault)
|
|
2275
2282
|
given = attr.default;
|
|
2276
2283
|
else
|
|
2277
2284
|
throw new RangeError("No value supplied for attribute " + name);
|
|
2278
2285
|
}
|
|
2286
|
+
else if (attr.validate) {
|
|
2287
|
+
attr.validate(given);
|
|
2288
|
+
}
|
|
2279
2289
|
built[name] = given;
|
|
2280
2290
|
}
|
|
2281
2291
|
return built;
|
|
2282
2292
|
}
|
|
2283
|
-
function checkAttrs(attrs, values, type, name) {
|
|
2284
|
-
for (let attr in values)
|
|
2285
|
-
if (!(attr in attrs))
|
|
2286
|
-
throw new RangeError(`Unsupported attribute ${attr} for ${type} of type ${name}`);
|
|
2287
|
-
for (let attr in attrs) {
|
|
2288
|
-
if (attrs[attr].validate)
|
|
2289
|
-
attrs[attr].validate(values[attr]);
|
|
2290
|
-
}
|
|
2291
|
-
}
|
|
2292
2293
|
function initAttrs(typeName, attrs) {
|
|
2293
2294
|
let result = Object.create(null);
|
|
2294
2295
|
if (attrs)
|
|
@@ -2460,11 +2461,9 @@ let NodeType$1 = class NodeType {
|
|
|
2460
2461
|
throw new RangeError(`Invalid content for node ${this.name}: ${content.toString().slice(0, 50)}`);
|
|
2461
2462
|
}
|
|
2462
2463
|
/**
|
|
2463
|
-
@internal
|
|
2464
|
+
@internal no longer useful, but called by old prosemirror-view versions
|
|
2464
2465
|
*/
|
|
2465
|
-
checkAttrs(attrs) {
|
|
2466
|
-
checkAttrs(this.attrs, attrs, "node", this.name);
|
|
2467
|
-
}
|
|
2466
|
+
checkAttrs(attrs) { }
|
|
2468
2467
|
/**
|
|
2469
2468
|
Check whether the given mark type is allowed in this node.
|
|
2470
2469
|
*/
|
|
@@ -2611,12 +2610,6 @@ class MarkType {
|
|
|
2611
2610
|
return set[i];
|
|
2612
2611
|
}
|
|
2613
2612
|
/**
|
|
2614
|
-
@internal
|
|
2615
|
-
*/
|
|
2616
|
-
checkAttrs(attrs) {
|
|
2617
|
-
checkAttrs(this.attrs, attrs, "mark", this.name);
|
|
2618
|
-
}
|
|
2619
|
-
/**
|
|
2620
2613
|
Queries whether a given mark type is
|
|
2621
2614
|
[excluded](https://prosemirror.net/docs/ref/#model.MarkSpec.excludes) by this one.
|
|
2622
2615
|
*/
|
|
@@ -9308,7 +9301,8 @@ function nodeLen(node) {
|
|
|
9308
9301
|
}
|
|
9309
9302
|
function isIgnorable(dom, dir) {
|
|
9310
9303
|
let desc = dom.pmViewDesc;
|
|
9311
|
-
return desc
|
|
9304
|
+
return desc ? desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR")
|
|
9305
|
+
: dom.nodeType == 1 && dom.contentEditable == "false";
|
|
9312
9306
|
}
|
|
9313
9307
|
function skipIgnoredNodes(view, dir) {
|
|
9314
9308
|
return dir < 0 ? skipIgnoredNodesBefore(view) : skipIgnoredNodesAfter(view);
|
|
@@ -9897,12 +9891,11 @@ function addContext(slice, context) {
|
|
|
9897
9891
|
if (!type || type.hasRequiredAttrs())
|
|
9898
9892
|
break;
|
|
9899
9893
|
try {
|
|
9900
|
-
type.
|
|
9894
|
+
content = Fragment.from(type.create(array[i + 1], content));
|
|
9901
9895
|
}
|
|
9902
9896
|
catch (e) {
|
|
9903
9897
|
break;
|
|
9904
9898
|
}
|
|
9905
|
-
content = Fragment.from(type.create(array[i + 1], content));
|
|
9906
9899
|
openStart++;
|
|
9907
9900
|
openEnd++;
|
|
9908
9901
|
}
|
|
@@ -10382,7 +10375,7 @@ editHandlers.compositionstart = editHandlers.compositionupdate = view => {
|
|
|
10382
10375
|
if (!view.composing) {
|
|
10383
10376
|
view.domObserver.flush();
|
|
10384
10377
|
let { state } = view, $pos = state.selection.$to;
|
|
10385
|
-
if (state.selection instanceof TextSelection &&
|
|
10378
|
+
if (state.selection instanceof TextSelection && state.selection.empty &&
|
|
10386
10379
|
(state.storedMarks ||
|
|
10387
10380
|
(!$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some(m => m.type.spec.inclusive === false)) ||
|
|
10388
10381
|
chrome && windows$1 && selectionBeforeUneditable(view))) { // Issue #1500
|
|
@@ -12019,9 +12012,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
12019
12012
|
// as being an iOS enter press), just dispatch an Enter key instead.
|
|
12020
12013
|
if (((ios && view.input.lastIOSEnter > Date.now() - 225 &&
|
|
12021
12014
|
(!inlineChange || addedNodes.some(n => n.nodeName == "DIV" || n.nodeName == "P"))) ||
|
|
12022
|
-
(!inlineChange && $from.pos
|
|
12023
|
-
(!$from.sameParent($to) || !$from.parent.inlineContent) &&
|
|
12024
|
-
$from.pos < $to.pos && !/\S/.test(parse.doc.textBetween($from.pos, $to.pos, "", "")))) &&
|
|
12015
|
+
(!inlineChange && looksLikeEnter(parse.doc, $from.pos, $to.pos))) &&
|
|
12025
12016
|
view.someProp("handleKeyDown", f => f(view, keyEvent(13, "Enter")))) {
|
|
12026
12017
|
view.input.lastIOSEnter = 0;
|
|
12027
12018
|
return;
|
|
@@ -12172,6 +12163,16 @@ function looksLikeBackspace(old, start, end, $newStart, $newEnd) {
|
|
|
12172
12163
|
// The fragments after the join point must match
|
|
12173
12164
|
return $newStart.parent.content.cut($newStart.parentOffset).eq($next.parent.content);
|
|
12174
12165
|
}
|
|
12166
|
+
function looksLikeEnter(content, from, to) {
|
|
12167
|
+
let newTextlines = 0, newLeaves = 0;
|
|
12168
|
+
content.nodesBetween(from, to, (node, pos) => {
|
|
12169
|
+
if (node.isTextblock && pos >= from && pos < to)
|
|
12170
|
+
newTextlines++;
|
|
12171
|
+
else if (node.isText ? /\S/.test(node.text.slice(Math.max(0, from - pos), Math.min(node.nodeSize, to - pos))) : node.isLeaf)
|
|
12172
|
+
newLeaves++;
|
|
12173
|
+
});
|
|
12174
|
+
return newLeaves == 0 && newTextlines == 1;
|
|
12175
|
+
}
|
|
12175
12176
|
function skipClosingAndOpening($pos, fromEnd, mayOpen) {
|
|
12176
12177
|
let depth = $pos.depth, end = fromEnd ? $pos.end() : $pos.pos;
|
|
12177
12178
|
while (depth > 0 && (fromEnd || $pos.indexAfter(depth) == $pos.node(depth).childCount)) {
|
|
@@ -17181,7 +17182,7 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
17181
17182
|
}
|
|
17182
17183
|
applyInteractiveState() {
|
|
17183
17184
|
const pointerEvents = this.isInteractive ? 'auto' : 'none';
|
|
17184
|
-
const contentCursor = this.isInteractive ? 'auto' : '';
|
|
17185
|
+
const contentCursor = this.isInteractive ? 'var(--kritzel-global-default-cursor, auto)' : '';
|
|
17185
17186
|
if (this.element) {
|
|
17186
17187
|
this.element.style.pointerEvents = pointerEvents;
|
|
17187
17188
|
this.element.style.cursor = contentCursor;
|
|
@@ -17217,7 +17218,7 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
17217
17218
|
if (!this.isInteractive) {
|
|
17218
17219
|
return false;
|
|
17219
17220
|
}
|
|
17220
|
-
const focusHosts = this.
|
|
17221
|
+
const focusHosts = this.getEmbeddedContentRoots();
|
|
17221
17222
|
// Primary path: locate the focused input-like element by walking from each host through
|
|
17222
17223
|
// `:focus` (piercing open shadow roots). This works in real browsers even when the engine
|
|
17223
17224
|
// and editor are nested web components, because it never relies on the document-level
|
|
@@ -17234,7 +17235,7 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
17234
17235
|
}
|
|
17235
17236
|
return false;
|
|
17236
17237
|
}
|
|
17237
|
-
|
|
17238
|
+
getEmbeddedContentRoots() {
|
|
17238
17239
|
const hosts = [];
|
|
17239
17240
|
if (this.element) {
|
|
17240
17241
|
hosts.push(this.element);
|
|
@@ -17447,11 +17448,11 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
17447
17448
|
* @returns A serializable object with htmlString and dimension snapshots
|
|
17448
17449
|
*/
|
|
17449
17450
|
serialize() {
|
|
17450
|
-
const { _core, _elementRef, element, totalWidth, totalHeight, isSelected, isHovered, isMounted, isInteractive, resizing, markedForRemoval, isVisible, ...props } = this;
|
|
17451
|
+
const { _core, _elementRef, element, totalWidth, totalHeight, isSelected, isHovered, isMounted, isInteractive, resizing, markedForRemoval, isVisible, rendererData, ...props } = this;
|
|
17451
17452
|
const cloned = structuredClone(props);
|
|
17452
17453
|
// Include rendererKey and rendererData for lifecycle-driven rendering
|
|
17453
17454
|
cloned.rendererKey = this.rendererKey;
|
|
17454
|
-
cloned.rendererData = this.
|
|
17455
|
+
cloned.rendererData = this.serializeRendererData();
|
|
17455
17456
|
// Store HTML as string for fallback/compatibility when renderer is unavailable
|
|
17456
17457
|
cloned.htmlString = element ? element.outerHTML : '';
|
|
17457
17458
|
// Capture dimension snapshot at serialization time
|
|
@@ -17459,6 +17460,19 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
17459
17460
|
cloned.serializedHeight = this.height;
|
|
17460
17461
|
return cloned;
|
|
17461
17462
|
}
|
|
17463
|
+
serializeRendererData() {
|
|
17464
|
+
if (this.rendererKey) {
|
|
17465
|
+
const renderer = KritzelDynamicObjectRendererRegistry.get(this.rendererKey);
|
|
17466
|
+
if (renderer?.onSerialize) {
|
|
17467
|
+
return structuredClone(renderer.onSerialize({
|
|
17468
|
+
object: this,
|
|
17469
|
+
container: this.isMounted && this.elementRef instanceof HTMLElement ? this.elementRef : null,
|
|
17470
|
+
data: this.rendererData,
|
|
17471
|
+
}));
|
|
17472
|
+
}
|
|
17473
|
+
}
|
|
17474
|
+
return structuredClone(this.rendererData);
|
|
17475
|
+
}
|
|
17462
17476
|
/**
|
|
17463
17477
|
* Deserializes the dynamic object from a plain object.
|
|
17464
17478
|
* Reconstructs the element from stored HTML string with fallback to placeholder.
|
|
@@ -17491,6 +17505,452 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
17491
17505
|
}
|
|
17492
17506
|
}
|
|
17493
17507
|
|
|
17508
|
+
const IFRAME_STATE_MESSAGE = 'kritzel-iframe-state';
|
|
17509
|
+
const IFRAME_PARENT_STATE_MESSAGE = 'kritzel-iframe-parent-state';
|
|
17510
|
+
const IFRAME_POINTER_MESSAGE = 'kritzel-iframe-pointer';
|
|
17511
|
+
const IFRAME_CONTEXT_MENU_MESSAGE = 'kritzel-iframe-contextmenu';
|
|
17512
|
+
const SUPPORTED_SANDBOX_TOKENS = new Set([
|
|
17513
|
+
'allow-downloads',
|
|
17514
|
+
'allow-forms',
|
|
17515
|
+
'allow-modals',
|
|
17516
|
+
'allow-orientation-lock',
|
|
17517
|
+
'allow-pointer-lock',
|
|
17518
|
+
'allow-popups',
|
|
17519
|
+
'allow-popups-to-escape-sandbox',
|
|
17520
|
+
'allow-presentation',
|
|
17521
|
+
'allow-same-origin',
|
|
17522
|
+
'allow-scripts',
|
|
17523
|
+
'allow-top-navigation-by-user-activation',
|
|
17524
|
+
]);
|
|
17525
|
+
const iframePointerBridgeStarts = new WeakMap();
|
|
17526
|
+
class KritzelIframeObject extends KritzelBaseObject {
|
|
17527
|
+
__class__ = 'KritzelIframeObject';
|
|
17528
|
+
content = { html: '', css: '', script: '' };
|
|
17529
|
+
loadingContent;
|
|
17530
|
+
isLoading = false;
|
|
17531
|
+
state = {};
|
|
17532
|
+
title = 'Embedded content';
|
|
17533
|
+
sandbox = ['allow-scripts'];
|
|
17534
|
+
borderRadius;
|
|
17535
|
+
boxShadow;
|
|
17536
|
+
get html() { return this.content.html; }
|
|
17537
|
+
set html(value) { this.content = { ...this.content, html: value }; }
|
|
17538
|
+
get css() { return this.content.css; }
|
|
17539
|
+
set css(value) { this.content = { ...this.content, css: value }; }
|
|
17540
|
+
get script() { return this.content.script; }
|
|
17541
|
+
set script(value) { this.content = { ...this.content, script: value }; }
|
|
17542
|
+
messageListener = null;
|
|
17543
|
+
constructor(config) {
|
|
17544
|
+
super();
|
|
17545
|
+
this.content = {
|
|
17546
|
+
html: config?.content?.html ?? config?.html ?? '',
|
|
17547
|
+
css: config?.content?.css ?? config?.css ?? '',
|
|
17548
|
+
script: config?.content?.script ?? config?.script ?? '',
|
|
17549
|
+
};
|
|
17550
|
+
this.loadingContent = config?.loadingContent ? {
|
|
17551
|
+
html: config.loadingContent.html ?? '',
|
|
17552
|
+
css: config.loadingContent.css ?? '',
|
|
17553
|
+
script: config.loadingContent.script ?? '',
|
|
17554
|
+
} : undefined;
|
|
17555
|
+
this.isLoading = config?.isLoading ?? false;
|
|
17556
|
+
this.state = structuredClone(config?.state ?? {});
|
|
17557
|
+
this.title = config?.title ?? 'Embedded content';
|
|
17558
|
+
this.sandbox = this.normalizeSandbox(config?.sandbox);
|
|
17559
|
+
this.borderRadius = config?.borderRadius;
|
|
17560
|
+
this.boxShadow = config?.boxShadow;
|
|
17561
|
+
this.translateX = config?.translateX ?? 0;
|
|
17562
|
+
this.translateY = config?.translateY ?? 0;
|
|
17563
|
+
this.rotation = KritzelMathHelper.degreesToRadians(config?.rotation ?? 0);
|
|
17564
|
+
this.scale = config?.scale ?? 1;
|
|
17565
|
+
this.width = config?.width ?? 0;
|
|
17566
|
+
this.height = config?.height ?? 0;
|
|
17567
|
+
}
|
|
17568
|
+
static create(core, config) {
|
|
17569
|
+
const object = new KritzelIframeObject(config);
|
|
17570
|
+
object._core = core;
|
|
17571
|
+
object.id = object.generateId();
|
|
17572
|
+
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
17573
|
+
object.userId = core.user?.id;
|
|
17574
|
+
object.scale = config?.scale ?? core.store.state.scale;
|
|
17575
|
+
object.zIndex = core.store.currentZIndex;
|
|
17576
|
+
return object;
|
|
17577
|
+
}
|
|
17578
|
+
get sandboxAttribute() {
|
|
17579
|
+
return this.sandbox.join(' ');
|
|
17580
|
+
}
|
|
17581
|
+
mount(iframe) {
|
|
17582
|
+
if (this.isMounted && this.elementRef === iframe) {
|
|
17583
|
+
return;
|
|
17584
|
+
}
|
|
17585
|
+
if (this.isMounted) {
|
|
17586
|
+
this.unmount();
|
|
17587
|
+
}
|
|
17588
|
+
this.elementRef = iframe;
|
|
17589
|
+
this.isMounted = true;
|
|
17590
|
+
iframe.title = this.title;
|
|
17591
|
+
iframe.setAttribute('sandbox', this.sandboxAttribute);
|
|
17592
|
+
iframe.style.pointerEvents = this.isInteractive ? 'auto' : 'none';
|
|
17593
|
+
this.messageListener = event => this.handleMessage(event);
|
|
17594
|
+
window.addEventListener('message', this.messageListener);
|
|
17595
|
+
iframe.srcdoc = this.createSourceDocument();
|
|
17596
|
+
this.onMount(this.createLifecycleContext());
|
|
17597
|
+
}
|
|
17598
|
+
unmount() {
|
|
17599
|
+
if (!this.isMounted) {
|
|
17600
|
+
return;
|
|
17601
|
+
}
|
|
17602
|
+
const nextState = this.onUnmount(this.createLifecycleContext());
|
|
17603
|
+
if (nextState !== undefined) {
|
|
17604
|
+
this.state = structuredClone(nextState);
|
|
17605
|
+
}
|
|
17606
|
+
if (this.messageListener) {
|
|
17607
|
+
window.removeEventListener('message', this.messageListener);
|
|
17608
|
+
this.messageListener = null;
|
|
17609
|
+
}
|
|
17610
|
+
this.isMounted = false;
|
|
17611
|
+
this._elementRef = null;
|
|
17612
|
+
}
|
|
17613
|
+
setContent(content) {
|
|
17614
|
+
this.content = {
|
|
17615
|
+
html: content.html ?? this.content.html,
|
|
17616
|
+
css: content.css ?? this.content.css,
|
|
17617
|
+
script: content.script ?? this.content.script,
|
|
17618
|
+
};
|
|
17619
|
+
this.refreshDocument();
|
|
17620
|
+
this.persistUpdate();
|
|
17621
|
+
}
|
|
17622
|
+
setLoadingContent(content) {
|
|
17623
|
+
this.loadingContent = {
|
|
17624
|
+
html: content.html ?? this.loadingContent?.html ?? '',
|
|
17625
|
+
css: content.css ?? this.loadingContent?.css ?? '',
|
|
17626
|
+
script: content.script ?? this.loadingContent?.script ?? '',
|
|
17627
|
+
};
|
|
17628
|
+
this.refreshDocument();
|
|
17629
|
+
this.persistUpdate();
|
|
17630
|
+
}
|
|
17631
|
+
setLoading(isLoading) {
|
|
17632
|
+
this.isLoading = isLoading;
|
|
17633
|
+
this.refreshDocument();
|
|
17634
|
+
this.persistUpdate();
|
|
17635
|
+
}
|
|
17636
|
+
getActiveContent() {
|
|
17637
|
+
const activeLoadingContent = this.isLoading ? this.loadingContent : undefined;
|
|
17638
|
+
return {
|
|
17639
|
+
html: activeLoadingContent?.html ?? this.content.html,
|
|
17640
|
+
css: activeLoadingContent?.css ?? this.content.css,
|
|
17641
|
+
script: activeLoadingContent?.script ?? this.content.script,
|
|
17642
|
+
};
|
|
17643
|
+
}
|
|
17644
|
+
setState(state) {
|
|
17645
|
+
this.state = structuredClone(state);
|
|
17646
|
+
this.elementRef?.contentWindow?.postMessage({ type: IFRAME_PARENT_STATE_MESSAGE, state: this.state }, '*');
|
|
17647
|
+
this.persistUpdate();
|
|
17648
|
+
}
|
|
17649
|
+
setIsInteractive(isInteractive) {
|
|
17650
|
+
this.isInteractive = isInteractive;
|
|
17651
|
+
if (this.isMounted && this.elementRef) {
|
|
17652
|
+
this.elementRef.style.pointerEvents = isInteractive ? 'auto' : 'none';
|
|
17653
|
+
if (!isInteractive) {
|
|
17654
|
+
this.elementRef.blur();
|
|
17655
|
+
}
|
|
17656
|
+
}
|
|
17657
|
+
}
|
|
17658
|
+
hasFocusedInputElement() {
|
|
17659
|
+
return this.isInteractive && this.isMounted && document.activeElement === this.elementRef;
|
|
17660
|
+
}
|
|
17661
|
+
getEmbeddedContentRoots() {
|
|
17662
|
+
return this.isMounted && this.elementRef instanceof HTMLElement && this.elementRef.tagName === 'IFRAME' ? [this.elementRef] : [];
|
|
17663
|
+
}
|
|
17664
|
+
onMount(_context) { }
|
|
17665
|
+
onSerialize(context) {
|
|
17666
|
+
return context.state;
|
|
17667
|
+
}
|
|
17668
|
+
onUnmount(context) {
|
|
17669
|
+
return context.state;
|
|
17670
|
+
}
|
|
17671
|
+
serialize() {
|
|
17672
|
+
const nextState = this.onSerialize(this.createLifecycleContext());
|
|
17673
|
+
this.state = structuredClone(nextState);
|
|
17674
|
+
const messageListener = this.messageListener;
|
|
17675
|
+
this.messageListener = null;
|
|
17676
|
+
try {
|
|
17677
|
+
const serialized = super.serialize();
|
|
17678
|
+
delete serialized.messageListener;
|
|
17679
|
+
return serialized;
|
|
17680
|
+
}
|
|
17681
|
+
finally {
|
|
17682
|
+
this.messageListener = messageListener;
|
|
17683
|
+
}
|
|
17684
|
+
}
|
|
17685
|
+
deserialize(object) {
|
|
17686
|
+
super.deserialize(object);
|
|
17687
|
+
const nextContent = object.content && typeof object.content === 'object' ? object.content : {};
|
|
17688
|
+
const nextLoadingContent = object.loadingContent && typeof object.loadingContent === 'object' ? object.loadingContent : undefined;
|
|
17689
|
+
this.content = {
|
|
17690
|
+
html: typeof nextContent.html === 'string' ? nextContent.html : typeof object.html === 'string' ? object.html : '',
|
|
17691
|
+
css: typeof nextContent.css === 'string' ? nextContent.css : typeof object.css === 'string' ? object.css : '',
|
|
17692
|
+
script: typeof nextContent.script === 'string' ? nextContent.script : typeof object.script === 'string' ? object.script : '',
|
|
17693
|
+
};
|
|
17694
|
+
this.loadingContent = nextLoadingContent ? {
|
|
17695
|
+
html: typeof nextLoadingContent.html === 'string' ? nextLoadingContent.html : '',
|
|
17696
|
+
css: typeof nextLoadingContent.css === 'string' ? nextLoadingContent.css : '',
|
|
17697
|
+
script: typeof nextLoadingContent.script === 'string' ? nextLoadingContent.script : '',
|
|
17698
|
+
} : undefined;
|
|
17699
|
+
this.isLoading = typeof object.isLoading === 'boolean' ? object.isLoading : false;
|
|
17700
|
+
this.state = object.state && typeof object.state === 'object' ? structuredClone(object.state) : {};
|
|
17701
|
+
this.title = typeof object.title === 'string' ? object.title : 'Embedded content';
|
|
17702
|
+
this.sandbox = this.normalizeSandbox(Array.isArray(object.sandbox) ? object.sandbox.filter((token) => typeof token === 'string') : undefined);
|
|
17703
|
+
this.borderRadius = (typeof object.borderRadius === 'number' || typeof object.borderRadius === 'string') ? object.borderRadius : undefined;
|
|
17704
|
+
this.boxShadow = typeof object.boxShadow === 'string' ? object.boxShadow : undefined;
|
|
17705
|
+
this.messageListener = null;
|
|
17706
|
+
return this;
|
|
17707
|
+
}
|
|
17708
|
+
copy() {
|
|
17709
|
+
const copiedObject = super.copy();
|
|
17710
|
+
copiedObject.content = { ...this.content };
|
|
17711
|
+
copiedObject.loadingContent = this.loadingContent ? { ...this.loadingContent } : undefined;
|
|
17712
|
+
copiedObject.isLoading = this.isLoading;
|
|
17713
|
+
copiedObject.state = structuredClone(this.state);
|
|
17714
|
+
copiedObject.sandbox = [...this.sandbox];
|
|
17715
|
+
copiedObject.borderRadius = this.borderRadius;
|
|
17716
|
+
copiedObject.boxShadow = this.boxShadow;
|
|
17717
|
+
copiedObject.messageListener = null;
|
|
17718
|
+
copiedObject._elementRef = null;
|
|
17719
|
+
return copiedObject;
|
|
17720
|
+
}
|
|
17721
|
+
clone() {
|
|
17722
|
+
const clonedObject = super.clone();
|
|
17723
|
+
clonedObject.content = { ...this.content };
|
|
17724
|
+
clonedObject.loadingContent = this.loadingContent ? { ...this.loadingContent } : undefined;
|
|
17725
|
+
clonedObject.isLoading = this.isLoading;
|
|
17726
|
+
clonedObject.state = structuredClone(this.state);
|
|
17727
|
+
clonedObject.sandbox = [...this.sandbox];
|
|
17728
|
+
clonedObject.borderRadius = this.borderRadius;
|
|
17729
|
+
clonedObject.boxShadow = this.boxShadow;
|
|
17730
|
+
clonedObject.messageListener = null;
|
|
17731
|
+
clonedObject.isMounted = false;
|
|
17732
|
+
clonedObject._elementRef = null;
|
|
17733
|
+
return clonedObject;
|
|
17734
|
+
}
|
|
17735
|
+
adoptTransientStateFrom(previous) {
|
|
17736
|
+
if (!(previous instanceof KritzelIframeObject)) {
|
|
17737
|
+
return;
|
|
17738
|
+
}
|
|
17739
|
+
this.isInteractive = previous.isInteractive;
|
|
17740
|
+
this.isSelected = previous.isSelected;
|
|
17741
|
+
this.isHovered = previous.isHovered;
|
|
17742
|
+
if (!previous.isMounted || !(previous.elementRef instanceof HTMLElement) || previous.elementRef.tagName !== 'IFRAME') {
|
|
17743
|
+
return;
|
|
17744
|
+
}
|
|
17745
|
+
if (previous.messageListener) {
|
|
17746
|
+
window.removeEventListener('message', previous.messageListener);
|
|
17747
|
+
}
|
|
17748
|
+
this._elementRef = previous.elementRef;
|
|
17749
|
+
this.isMounted = true;
|
|
17750
|
+
this.messageListener = event => this.handleMessage(event);
|
|
17751
|
+
window.addEventListener('message', this.messageListener);
|
|
17752
|
+
this.elementRef.style.pointerEvents = this.isInteractive ? 'auto' : 'none';
|
|
17753
|
+
previous.messageListener = null;
|
|
17754
|
+
previous.isMounted = false;
|
|
17755
|
+
previous._elementRef = null;
|
|
17756
|
+
}
|
|
17757
|
+
createLifecycleContext() {
|
|
17758
|
+
return {
|
|
17759
|
+
object: this,
|
|
17760
|
+
iframe: this.isMounted ? this.elementRef : null,
|
|
17761
|
+
state: structuredClone(this.state),
|
|
17762
|
+
};
|
|
17763
|
+
}
|
|
17764
|
+
normalizeSandbox(tokens) {
|
|
17765
|
+
const requestedTokens = tokens ?? ['allow-scripts'];
|
|
17766
|
+
const normalized = requestedTokens.filter(token => SUPPORTED_SANDBOX_TOKENS.has(token));
|
|
17767
|
+
return [...new Set(normalized.length > 0 ? normalized : ['allow-scripts'])];
|
|
17768
|
+
}
|
|
17769
|
+
createSourceDocument() {
|
|
17770
|
+
const activeContent = this.getActiveContent();
|
|
17771
|
+
const state = JSON.stringify(this.state).replace(/</g, '\\u003c');
|
|
17772
|
+
const css = activeContent.css.replace(/<\/style/gi, '<\\/style');
|
|
17773
|
+
const script = activeContent.script.replace(/<\/script/gi, '<\\/script');
|
|
17774
|
+
const computedStyle = this.isMounted ? getComputedStyle(this.elementRef) : null;
|
|
17775
|
+
const defaultCursor = computedStyle?.getPropertyValue('--kritzel-global-default-cursor').trim() || 'auto';
|
|
17776
|
+
const pointerCursor = computedStyle?.getPropertyValue('--kritzel-global-pointer-cursor').trim() || defaultCursor;
|
|
17777
|
+
return `<!doctype html>
|
|
17778
|
+
<html>
|
|
17779
|
+
<head>
|
|
17780
|
+
<meta charset="utf-8">
|
|
17781
|
+
<style>
|
|
17782
|
+
:root {
|
|
17783
|
+
--kritzel-iframe-default-cursor: ${defaultCursor};
|
|
17784
|
+
--kritzel-iframe-pointer-cursor: ${pointerCursor};
|
|
17785
|
+
}
|
|
17786
|
+
html, body { width: 100%; height: 100%; margin: 0; overflow: hidden; cursor: var(--kritzel-iframe-default-cursor); }
|
|
17787
|
+
button, button *, a, a *, input, textarea, select { cursor: var(--kritzel-iframe-pointer-cursor) !important; }
|
|
17788
|
+
${css}
|
|
17789
|
+
</style>
|
|
17790
|
+
</head>
|
|
17791
|
+
<body>
|
|
17792
|
+
${activeContent.html}
|
|
17793
|
+
<script>
|
|
17794
|
+
const kritzel = globalThis.kritzel = {
|
|
17795
|
+
state: ${state},
|
|
17796
|
+
setState(nextState) {
|
|
17797
|
+
this.state = nextState;
|
|
17798
|
+
parent.postMessage({ type: '${IFRAME_STATE_MESSAGE}', state: nextState }, '*');
|
|
17799
|
+
},
|
|
17800
|
+
};
|
|
17801
|
+
globalThis.addEventListener('message', event => {
|
|
17802
|
+
if (event.data?.type === '${IFRAME_PARENT_STATE_MESSAGE}' && event.data.state && typeof event.data.state === 'object') {
|
|
17803
|
+
kritzel.state = event.data.state;
|
|
17804
|
+
globalThis.dispatchEvent(new CustomEvent('kritzelstatechange', { detail: kritzel.state }));
|
|
17805
|
+
}
|
|
17806
|
+
});
|
|
17807
|
+
let bridgedPointerId = null;
|
|
17808
|
+
const interactiveSelector = 'button, input, textarea, select, a[href], [contenteditable="true"], [contenteditable=""]';
|
|
17809
|
+
const bridgePointerEvent = event => parent.postMessage({
|
|
17810
|
+
type: '${IFRAME_POINTER_MESSAGE}',
|
|
17811
|
+
eventType: event.type,
|
|
17812
|
+
pointerId: event.pointerId,
|
|
17813
|
+
pointerType: event.pointerType,
|
|
17814
|
+
clientX: event.clientX,
|
|
17815
|
+
clientY: event.clientY,
|
|
17816
|
+
screenX: event.screenX,
|
|
17817
|
+
screenY: event.screenY,
|
|
17818
|
+
button: event.button,
|
|
17819
|
+
buttons: event.buttons,
|
|
17820
|
+
shiftKey: event.shiftKey,
|
|
17821
|
+
ctrlKey: event.ctrlKey,
|
|
17822
|
+
altKey: event.altKey,
|
|
17823
|
+
metaKey: event.metaKey,
|
|
17824
|
+
}, '*');
|
|
17825
|
+
document.addEventListener('pointerdown', event => {
|
|
17826
|
+
if (event.target instanceof Element && event.target.closest(interactiveSelector)) return;
|
|
17827
|
+
bridgedPointerId = event.pointerId;
|
|
17828
|
+
event.preventDefault();
|
|
17829
|
+
bridgePointerEvent(event);
|
|
17830
|
+
});
|
|
17831
|
+
document.addEventListener('pointermove', event => {
|
|
17832
|
+
if (event.pointerId !== bridgedPointerId) return;
|
|
17833
|
+
event.preventDefault();
|
|
17834
|
+
bridgePointerEvent(event);
|
|
17835
|
+
});
|
|
17836
|
+
const finishPointerBridge = event => {
|
|
17837
|
+
if (event.pointerId !== bridgedPointerId) return;
|
|
17838
|
+
event.preventDefault();
|
|
17839
|
+
bridgePointerEvent(event);
|
|
17840
|
+
bridgedPointerId = null;
|
|
17841
|
+
};
|
|
17842
|
+
document.addEventListener('pointerup', finishPointerBridge);
|
|
17843
|
+
document.addEventListener('pointercancel', finishPointerBridge);
|
|
17844
|
+
document.addEventListener('contextmenu', event => {
|
|
17845
|
+
event.preventDefault();
|
|
17846
|
+
parent.postMessage({
|
|
17847
|
+
type: '${IFRAME_CONTEXT_MENU_MESSAGE}',
|
|
17848
|
+
clientX: event.clientX,
|
|
17849
|
+
clientY: event.clientY,
|
|
17850
|
+
button: event.button,
|
|
17851
|
+
shiftKey: event.shiftKey,
|
|
17852
|
+
ctrlKey: event.ctrlKey,
|
|
17853
|
+
altKey: event.altKey,
|
|
17854
|
+
metaKey: event.metaKey,
|
|
17855
|
+
}, '*');
|
|
17856
|
+
});
|
|
17857
|
+
${script}
|
|
17858
|
+
<\/script>
|
|
17859
|
+
</body>
|
|
17860
|
+
</html>`;
|
|
17861
|
+
}
|
|
17862
|
+
handleMessage(event) {
|
|
17863
|
+
if (event.source !== this.elementRef?.contentWindow || !event.data || typeof event.data !== 'object') {
|
|
17864
|
+
return;
|
|
17865
|
+
}
|
|
17866
|
+
const message = event.data;
|
|
17867
|
+
if (message.type === IFRAME_POINTER_MESSAGE) {
|
|
17868
|
+
this.dispatchPointerMessage(event.data);
|
|
17869
|
+
return;
|
|
17870
|
+
}
|
|
17871
|
+
if (message.type === IFRAME_CONTEXT_MENU_MESSAGE) {
|
|
17872
|
+
this.dispatchContextMenuMessage(event.data);
|
|
17873
|
+
return;
|
|
17874
|
+
}
|
|
17875
|
+
if (message.type !== IFRAME_STATE_MESSAGE || !message.state || typeof message.state !== 'object') {
|
|
17876
|
+
return;
|
|
17877
|
+
}
|
|
17878
|
+
this.state = structuredClone(message.state);
|
|
17879
|
+
this.persistUpdate();
|
|
17880
|
+
}
|
|
17881
|
+
dispatchPointerMessage(message) {
|
|
17882
|
+
if (!this.isMounted || !this.elementRef || !['pointerdown', 'pointermove', 'pointerup', 'pointercancel'].includes(message.eventType)) {
|
|
17883
|
+
return;
|
|
17884
|
+
}
|
|
17885
|
+
const iframeRect = this.elementRef.getBoundingClientRect();
|
|
17886
|
+
if (message.eventType === 'pointerdown') {
|
|
17887
|
+
const scaleX = this.elementRef.offsetWidth > 0 ? iframeRect.width / this.elementRef.offsetWidth : 1;
|
|
17888
|
+
const scaleY = this.elementRef.offsetHeight > 0 ? iframeRect.height / this.elementRef.offsetHeight : 1;
|
|
17889
|
+
iframePointerBridgeStarts.set(this.elementRef, {
|
|
17890
|
+
pointerId: message.pointerId,
|
|
17891
|
+
clientX: iframeRect.left + message.clientX * scaleX,
|
|
17892
|
+
clientY: iframeRect.top + message.clientY * scaleY,
|
|
17893
|
+
screenX: message.screenX,
|
|
17894
|
+
screenY: message.screenY,
|
|
17895
|
+
});
|
|
17896
|
+
}
|
|
17897
|
+
const bridgeStart = iframePointerBridgeStarts.get(this.elementRef);
|
|
17898
|
+
const hasBridgeStart = bridgeStart?.pointerId === message.pointerId;
|
|
17899
|
+
const clientX = hasBridgeStart ? bridgeStart.clientX + message.screenX - bridgeStart.screenX : iframeRect.left + message.clientX;
|
|
17900
|
+
const clientY = hasBridgeStart ? bridgeStart.clientY + message.screenY - bridgeStart.screenY : iframeRect.top + message.clientY;
|
|
17901
|
+
this.elementRef.dispatchEvent(new PointerEvent(message.eventType, {
|
|
17902
|
+
bubbles: true,
|
|
17903
|
+
composed: true,
|
|
17904
|
+
cancelable: true,
|
|
17905
|
+
pointerId: message.pointerId,
|
|
17906
|
+
pointerType: message.pointerType,
|
|
17907
|
+
clientX,
|
|
17908
|
+
clientY,
|
|
17909
|
+
screenX: message.screenX,
|
|
17910
|
+
screenY: message.screenY,
|
|
17911
|
+
button: message.button,
|
|
17912
|
+
buttons: message.buttons,
|
|
17913
|
+
shiftKey: message.shiftKey,
|
|
17914
|
+
ctrlKey: message.ctrlKey,
|
|
17915
|
+
altKey: message.altKey,
|
|
17916
|
+
metaKey: message.metaKey,
|
|
17917
|
+
}));
|
|
17918
|
+
if (message.eventType === 'pointerup' || message.eventType === 'pointercancel') {
|
|
17919
|
+
iframePointerBridgeStarts.delete(this.elementRef);
|
|
17920
|
+
}
|
|
17921
|
+
}
|
|
17922
|
+
dispatchContextMenuMessage(message) {
|
|
17923
|
+
if (!this.isMounted || !this.elementRef) {
|
|
17924
|
+
return;
|
|
17925
|
+
}
|
|
17926
|
+
const iframeRect = this.elementRef.getBoundingClientRect();
|
|
17927
|
+
// Dispatched as a MouseEvent (not PointerEvent) to mirror how browsers
|
|
17928
|
+
// natively raise 'contextmenu' for both mouse right-click and touch long-press.
|
|
17929
|
+
this.elementRef.dispatchEvent(new MouseEvent('contextmenu', {
|
|
17930
|
+
bubbles: true,
|
|
17931
|
+
composed: true,
|
|
17932
|
+
cancelable: true,
|
|
17933
|
+
clientX: iframeRect.left + message.clientX,
|
|
17934
|
+
clientY: iframeRect.top + message.clientY,
|
|
17935
|
+
button: message.button,
|
|
17936
|
+
shiftKey: message.shiftKey,
|
|
17937
|
+
ctrlKey: message.ctrlKey,
|
|
17938
|
+
altKey: message.altKey,
|
|
17939
|
+
metaKey: message.metaKey,
|
|
17940
|
+
}));
|
|
17941
|
+
}
|
|
17942
|
+
refreshDocument() {
|
|
17943
|
+
if (this.isMounted && this.elementRef) {
|
|
17944
|
+
this.elementRef.srcdoc = this.createSourceDocument();
|
|
17945
|
+
}
|
|
17946
|
+
}
|
|
17947
|
+
persistUpdate() {
|
|
17948
|
+
if (this._core?.store?.objects) {
|
|
17949
|
+
this.update();
|
|
17950
|
+
}
|
|
17951
|
+
}
|
|
17952
|
+
}
|
|
17953
|
+
|
|
17494
17954
|
/**
|
|
17495
17955
|
* Represents a selection group that manages multiple selected objects on the canvas.
|
|
17496
17956
|
* The selection group allows batch operations like move, resize, and rotate on multiple objects simultaneously.
|
|
@@ -19631,7 +20091,7 @@ class KritzelCursorHelper {
|
|
|
19631
20091
|
* The icon is retrieved from the KritzelIconRegistry.
|
|
19632
20092
|
*/
|
|
19633
20093
|
static getCursor(options) {
|
|
19634
|
-
const iconName = options.iconName === 'default' ? '
|
|
20094
|
+
const iconName = options.iconName === 'default' ? 'mousePointer' : options.iconName;
|
|
19635
20095
|
const iconSvg = KritzelIconRegistry.get(iconName);
|
|
19636
20096
|
if (!iconSvg) {
|
|
19637
20097
|
console.warn(`Icon "${iconName}" not found in registry.`);
|
|
@@ -19640,7 +20100,7 @@ class KritzelCursorHelper {
|
|
|
19640
20100
|
const size = options.size || 24;
|
|
19641
20101
|
const rotation = options.rotation || 0;
|
|
19642
20102
|
const color = options.color || 'black';
|
|
19643
|
-
// Default cursor (
|
|
20103
|
+
// Default cursor (mousePointer) has hotspot at (4, 4), others at center
|
|
19644
20104
|
const hotspot = options.hotspot || (options.iconName === 'default' ? { x: 4, y: 4 } : { x: size / 2, y: size / 2 });
|
|
19645
20105
|
// Modify the SVG string to set size and color
|
|
19646
20106
|
// We replace width and height to match the requested size
|
|
@@ -19653,12 +20113,12 @@ class KritzelCursorHelper {
|
|
|
19653
20113
|
// We rotate around the center of the SVG canvas
|
|
19654
20114
|
const center = size / 2;
|
|
19655
20115
|
// We use a group to apply the rotation
|
|
19656
|
-
const svg = `
|
|
19657
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
|
|
19658
|
-
<g transform="rotate(${rotation} ${center} ${center})">
|
|
19659
|
-
${content}
|
|
19660
|
-
</g>
|
|
19661
|
-
</svg>
|
|
20116
|
+
const svg = `
|
|
20117
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
|
|
20118
|
+
<g transform="rotate(${rotation} ${center} ${center})">
|
|
20119
|
+
${content}
|
|
20120
|
+
</g>
|
|
20121
|
+
</svg>
|
|
19662
20122
|
`;
|
|
19663
20123
|
// Encode the SVG for use in a data URI
|
|
19664
20124
|
// We need to be careful with encoding to ensure it works across browsers
|
|
@@ -21874,9 +22334,8 @@ class KritzelSelectionTool extends KritzelBaseTool {
|
|
|
21874
22334
|
}
|
|
21875
22335
|
if (selectedObject && selectedObject.isSelected === false && selectedObject?.objects.length === 1) {
|
|
21876
22336
|
const firstObj = selectedObject.objects[0];
|
|
21877
|
-
if (
|
|
21878
|
-
// Selected
|
|
21879
|
-
// embedded DOM content. Unselected dynamic objects remain selectable.
|
|
22337
|
+
if (ObjectHelper.isKritzelEmbeddedObject(firstObj)) {
|
|
22338
|
+
// Selected embedded objects hand pointer interaction to their content.
|
|
21880
22339
|
if (firstObj.isSelected && this._core.store.selectionGroup?.objects.length === 1)
|
|
21881
22340
|
return;
|
|
21882
22341
|
}
|
|
@@ -43322,6 +43781,9 @@ class KritzelReviver {
|
|
|
43322
43781
|
case 'KritzelDynamicObject':
|
|
43323
43782
|
revivedObj = KritzelDynamicObject.create(this._core).deserialize(obj);
|
|
43324
43783
|
break;
|
|
43784
|
+
case 'KritzelIframeObject':
|
|
43785
|
+
revivedObj = KritzelIframeObject.create(this._core).deserialize(obj);
|
|
43786
|
+
break;
|
|
43325
43787
|
case 'KritzelSelectionGroup':
|
|
43326
43788
|
revivedObj = KritzelSelectionGroup.create(this._core).deserialize(obj);
|
|
43327
43789
|
break;
|
|
@@ -45146,9 +45608,16 @@ class KritzelStore {
|
|
|
45146
45608
|
* Gets the currently selected dynamic object whose focused descendant is an input-like element.
|
|
45147
45609
|
* @returns The interactive dynamic object with focused input-like content, or null if none matches
|
|
45148
45610
|
*/
|
|
45611
|
+
get activeInteractiveEmbeddedObject() {
|
|
45612
|
+
for (const object of this.selectedObjects) {
|
|
45613
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object) && object.hasFocusedInputElement()) {
|
|
45614
|
+
return object;
|
|
45615
|
+
}
|
|
45616
|
+
}
|
|
45617
|
+
return null;
|
|
45618
|
+
}
|
|
45149
45619
|
get activeInteractiveDynamicObject() {
|
|
45150
|
-
|
|
45151
|
-
return interactiveDynamicObject ?? null;
|
|
45620
|
+
return this.activeInteractiveEmbeddedObject;
|
|
45152
45621
|
}
|
|
45153
45622
|
/**
|
|
45154
45623
|
* Gets the path currently being drawn (not yet completed).
|
|
@@ -45736,11 +46205,13 @@ class KritzelCursorManager {
|
|
|
45736
46205
|
// Reset cursor on old target
|
|
45737
46206
|
if (this._targetElement) {
|
|
45738
46207
|
this._targetElement.style.cursor = '';
|
|
46208
|
+
this._targetElement.style.removeProperty('--kritzel-global-default-cursor');
|
|
45739
46209
|
this._targetElement.style.removeProperty('--kritzel-global-pointer-cursor');
|
|
45740
46210
|
}
|
|
45741
46211
|
this._targetElement = element;
|
|
45742
46212
|
// Set the pointer cursor CSS variable for child components to use
|
|
45743
46213
|
if (this._targetElement) {
|
|
46214
|
+
this._targetElement.style.setProperty('--kritzel-global-default-cursor', KritzelCursorHelper.getCursor({ iconName: 'default' }));
|
|
45744
46215
|
this._targetElement.style.setProperty('--kritzel-global-pointer-cursor', KritzelCursorHelper.getPointerCursor());
|
|
45745
46216
|
}
|
|
45746
46217
|
}
|
|
@@ -45785,8 +46256,10 @@ class KritzelCursorManager {
|
|
|
45785
46256
|
if (!this._shadowRoot)
|
|
45786
46257
|
return;
|
|
45787
46258
|
const elementsAtPoint = this._shadowRoot.elementsFromPoint(ev.clientX, ev.clientY);
|
|
45788
|
-
if (!elementsAtPoint || elementsAtPoint.length === 0)
|
|
46259
|
+
if (!elementsAtPoint || elementsAtPoint.length === 0) {
|
|
46260
|
+
this.resetToDefault();
|
|
45789
46261
|
return;
|
|
46262
|
+
}
|
|
45790
46263
|
// Check for resize handle overlays (selection group)
|
|
45791
46264
|
const resizeHandleOverlay = elementsAtPoint.find(el => el.classList.contains('resize-handle-overlay'));
|
|
45792
46265
|
if (resizeHandleOverlay) {
|
|
@@ -45796,19 +46269,19 @@ class KritzelCursorManager {
|
|
|
45796
46269
|
const isTopLeft = resizeHandleOverlay.classList.contains('top-left');
|
|
45797
46270
|
const isBottomRight = resizeHandleOverlay.classList.contains('bottom-right');
|
|
45798
46271
|
const rotationOffset = (isTopLeft || isBottomRight) ? -45 : 45;
|
|
45799
|
-
this._core.store.state.cursor = { icon: '
|
|
46272
|
+
this._core.store.state.cursor = { icon: 'moveVertical', rotation: rotationDegrees + rotationOffset };
|
|
45800
46273
|
return;
|
|
45801
46274
|
}
|
|
45802
46275
|
// Check for rotation handle overlay
|
|
45803
46276
|
const rotationHandleOverlay = elementsAtPoint.find(el => el.classList.contains('rotation-handle-overlay'));
|
|
45804
46277
|
if (rotationHandleOverlay) {
|
|
45805
|
-
this._core.store.state.cursor = { icon: 'hand', iconActive: '
|
|
46278
|
+
this._core.store.state.cursor = { icon: 'hand', iconActive: 'handGrab' };
|
|
45806
46279
|
return;
|
|
45807
46280
|
}
|
|
45808
46281
|
// Check for line handle overlays (selection line)
|
|
45809
46282
|
const lineHandleOverlay = elementsAtPoint.find(el => el.classList.contains('selection-line-handle-overlay'));
|
|
45810
46283
|
if (lineHandleOverlay) {
|
|
45811
|
-
this._core.store.state.cursor = { icon: 'hand', iconActive: '
|
|
46284
|
+
this._core.store.state.cursor = { icon: 'hand', iconActive: 'handGrab' };
|
|
45812
46285
|
return;
|
|
45813
46286
|
}
|
|
45814
46287
|
// Reset cursor if not hovering any handle
|
|
@@ -45843,7 +46316,8 @@ class KritzelCursorManager {
|
|
|
45843
46316
|
cleanup() {
|
|
45844
46317
|
if (this._targetElement) {
|
|
45845
46318
|
this._targetElement.style.cursor = '';
|
|
45846
|
-
this._targetElement.style.removeProperty('--kritzel-
|
|
46319
|
+
this._targetElement.style.removeProperty('--kritzel-global-default-cursor');
|
|
46320
|
+
this._targetElement.style.removeProperty('--kritzel-global-pointer-cursor');
|
|
45847
46321
|
}
|
|
45848
46322
|
this._targetElement = null;
|
|
45849
46323
|
this._shadowRoot = null;
|
|
@@ -46768,7 +47242,7 @@ class KritzelCore {
|
|
|
46768
47242
|
this._store.state.translateY = viewportHeight / 2 - (viewport.centerWorldY ?? 0) * scale;
|
|
46769
47243
|
this._store.state.scale = scale;
|
|
46770
47244
|
await objectsMap.initialize(this, activeWorkspace.id, this._syncConfig);
|
|
46771
|
-
this.seedWorkspaceObjects(activeWorkspace, objectsMap);
|
|
47245
|
+
await this.seedWorkspaceObjects(activeWorkspace, objectsMap);
|
|
46772
47246
|
// Set local user in awareness after object map is initialized
|
|
46773
47247
|
if (this._user) {
|
|
46774
47248
|
objectsMap.setLocalUser(this._user);
|
|
@@ -46782,15 +47256,21 @@ class KritzelCore {
|
|
|
46782
47256
|
this.engine.emitObjectsChange();
|
|
46783
47257
|
this.rerender();
|
|
46784
47258
|
}
|
|
46785
|
-
seedWorkspaceObjects(workspace, objectsMap) {
|
|
47259
|
+
async seedWorkspaceObjects(workspace, objectsMap) {
|
|
46786
47260
|
if (!workspace.objects?.length) {
|
|
46787
47261
|
return;
|
|
46788
47262
|
}
|
|
47263
|
+
const pendingObjects = workspace.objects.filter(object => !objectsMap.findById(object.id));
|
|
47264
|
+
// Mirrors engine.addObject()/addObjects(): image asset upload is async and must
|
|
47265
|
+
// happen before the (synchronous) Yjs transaction that inserts the objects.
|
|
47266
|
+
for (const object of pendingObjects) {
|
|
47267
|
+
object._core = this;
|
|
47268
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
47269
|
+
await object.prepareForInsert();
|
|
47270
|
+
}
|
|
47271
|
+
}
|
|
46789
47272
|
objectsMap.transaction(() => {
|
|
46790
|
-
for (const object of
|
|
46791
|
-
if (objectsMap.findById(object.id)) {
|
|
46792
|
-
continue;
|
|
46793
|
-
}
|
|
47273
|
+
for (const object of pendingObjects) {
|
|
46794
47274
|
this.prepareObjectForWorkspace(object, workspace.id, this._store.currentZIndex, this._store.state.scale);
|
|
46795
47275
|
objectsMap.insert(object);
|
|
46796
47276
|
}
|
|
@@ -46829,16 +47309,30 @@ class KritzelCore {
|
|
|
46829
47309
|
* @param scaleFallback - Scale applied to objects that do not define one
|
|
46830
47310
|
* @returns The objects that were added, updated and removed
|
|
46831
47311
|
*/
|
|
46832
|
-
reconcileWorkspaceObjects(objectsMap, workspaceId, desiredObjects, nextZIndex, scaleFallback) {
|
|
47312
|
+
async reconcileWorkspaceObjects(objectsMap, workspaceId, desiredObjects, nextZIndex, scaleFallback) {
|
|
46833
47313
|
const existingObjects = objectsMap.allObjects().filter(o => !(o instanceof KritzelSelectionGroup) && !(o instanceof KritzelSelectionBox));
|
|
46834
47314
|
const existingById = new Map(existingObjects.map(object => [object.id, object]));
|
|
46835
47315
|
const desiredIds = new Set();
|
|
46836
47316
|
const diff = { added: [], updated: [], removed: [] };
|
|
47317
|
+
// Assign IDs up front so the insert-vs-update lookup below is stable, and so the
|
|
47318
|
+
// async image-prepare pass and the (synchronous) transaction agree on identity.
|
|
47319
|
+
for (const object of desiredObjects) {
|
|
47320
|
+
if (!object.id) {
|
|
47321
|
+
object.id = object.generateId();
|
|
47322
|
+
}
|
|
47323
|
+
}
|
|
47324
|
+
// Mirrors engine.addObject()/addObjects(): image asset upload is async and must
|
|
47325
|
+
// happen before the (synchronous) Yjs transaction that inserts the objects.
|
|
47326
|
+
for (const object of desiredObjects) {
|
|
47327
|
+
const existingObject = existingById.get(object.id);
|
|
47328
|
+
const isNewOrReplaced = !existingObject || existingObject !== object;
|
|
47329
|
+
if (isNewOrReplaced && KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
47330
|
+
object._core = this;
|
|
47331
|
+
await object.prepareForInsert();
|
|
47332
|
+
}
|
|
47333
|
+
}
|
|
46837
47334
|
objectsMap.transaction(() => {
|
|
46838
47335
|
for (const object of desiredObjects) {
|
|
46839
|
-
if (!object.id) {
|
|
46840
|
-
object.id = object.generateId();
|
|
46841
|
-
}
|
|
46842
47336
|
desiredIds.add(object.id);
|
|
46843
47337
|
const existingObject = existingById.get(object.id);
|
|
46844
47338
|
if (!existingObject) {
|
|
@@ -46876,7 +47370,7 @@ class KritzelCore {
|
|
|
46876
47370
|
* object set stays exactly what the caller declared.
|
|
46877
47371
|
*/
|
|
46878
47372
|
detachObject(object) {
|
|
46879
|
-
if (
|
|
47373
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
46880
47374
|
object.unmount();
|
|
46881
47375
|
}
|
|
46882
47376
|
object.isMounted = false;
|
|
@@ -47052,13 +47546,13 @@ class KritzelCore {
|
|
|
47052
47546
|
activeWorkspace.viewport = { centerWorldX, centerWorldY, scale };
|
|
47053
47547
|
}
|
|
47054
47548
|
}
|
|
47055
|
-
applyObjectsToActiveWorkspace(workspace, desiredObjects) {
|
|
47549
|
+
async applyObjectsToActiveWorkspace(workspace, desiredObjects) {
|
|
47056
47550
|
const objectsMap = this._store.objects;
|
|
47057
47551
|
if (!objectsMap) {
|
|
47058
47552
|
return null;
|
|
47059
47553
|
}
|
|
47060
47554
|
this.clearSelection();
|
|
47061
|
-
const diff = this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this._store.currentZIndex, this._store.state.scale);
|
|
47555
|
+
const diff = await this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this._store.currentZIndex, this._store.state.scale);
|
|
47062
47556
|
this._anchorManager.rebuildIndex();
|
|
47063
47557
|
this.rerender();
|
|
47064
47558
|
return diff;
|
|
@@ -47077,7 +47571,7 @@ class KritzelCore {
|
|
|
47077
47571
|
try {
|
|
47078
47572
|
await objectsMap.initialize(this, workspace.id, this._syncConfig, { headless: true, workspaceName: workspace.name });
|
|
47079
47573
|
await objectsMap.whenNetworkSynced();
|
|
47080
|
-
return this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this.nextZIndexOf(objectsMap), this._store.state.scale);
|
|
47574
|
+
return await this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this.nextZIndexOf(objectsMap), this._store.state.scale);
|
|
47081
47575
|
}
|
|
47082
47576
|
finally {
|
|
47083
47577
|
objectsMap.destroy();
|
|
@@ -47163,8 +47657,7 @@ class KritzelCore {
|
|
|
47163
47657
|
this.removeObject(child);
|
|
47164
47658
|
});
|
|
47165
47659
|
}
|
|
47166
|
-
|
|
47167
|
-
if (KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject')) {
|
|
47660
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
47168
47661
|
object.unmount();
|
|
47169
47662
|
}
|
|
47170
47663
|
// Handle anchor cleanup
|
|
@@ -47210,14 +47703,8 @@ class KritzelCore {
|
|
|
47210
47703
|
this.removeLocalSelectionGroups();
|
|
47211
47704
|
this.removeSelectionBox();
|
|
47212
47705
|
for (const object of selectionGroup.objects ?? []) {
|
|
47213
|
-
if (
|
|
47214
|
-
|
|
47215
|
-
if (typeof dynamicObject.setIsInteractive === 'function') {
|
|
47216
|
-
dynamicObject.setIsInteractive(true);
|
|
47217
|
-
}
|
|
47218
|
-
else {
|
|
47219
|
-
dynamicObject.isInteractive = true;
|
|
47220
|
-
}
|
|
47706
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
47707
|
+
object.setIsInteractive(true);
|
|
47221
47708
|
}
|
|
47222
47709
|
}
|
|
47223
47710
|
this._store.objects.insert(selectionGroup);
|
|
@@ -47238,14 +47725,8 @@ class KritzelCore {
|
|
|
47238
47725
|
teardownSelectionGroup(selectionGroup) {
|
|
47239
47726
|
selectionGroup.deselectAllChildren?.();
|
|
47240
47727
|
for (const object of selectionGroup.objects ?? []) {
|
|
47241
|
-
if (
|
|
47242
|
-
|
|
47243
|
-
if (typeof dynamicObject.setIsInteractive === 'function') {
|
|
47244
|
-
dynamicObject.setIsInteractive(false);
|
|
47245
|
-
}
|
|
47246
|
-
else {
|
|
47247
|
-
dynamicObject.isInteractive = false;
|
|
47248
|
-
}
|
|
47728
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
47729
|
+
object.setIsInteractive(false);
|
|
47249
47730
|
}
|
|
47250
47731
|
}
|
|
47251
47732
|
}
|
|
@@ -48691,13 +49172,7 @@ class KritzelWheelHelper {
|
|
|
48691
49172
|
return this.canElementConsumeWheel(scrollContainer, ev.deltaX, ev.deltaY);
|
|
48692
49173
|
}
|
|
48693
49174
|
static getScrollableContainerFromEventPath(path, dynamicObject) {
|
|
48694
|
-
const potentialRoots =
|
|
48695
|
-
if (dynamicObject.element instanceof HTMLElement) {
|
|
48696
|
-
potentialRoots.push(dynamicObject.element);
|
|
48697
|
-
}
|
|
48698
|
-
if (dynamicObject.elementRef instanceof HTMLElement) {
|
|
48699
|
-
potentialRoots.push(dynamicObject.elementRef);
|
|
48700
|
-
}
|
|
49175
|
+
const potentialRoots = dynamicObject.getEmbeddedContentRoots();
|
|
48701
49176
|
const legacyElementRef = dynamicObject.elmeentRef;
|
|
48702
49177
|
if (legacyElementRef instanceof HTMLElement) {
|
|
48703
49178
|
potentialRoots.push(legacyElementRef);
|
|
@@ -48855,8 +49330,8 @@ class KritzelSvgExportHelper {
|
|
|
48855
49330
|
.join('\n ');
|
|
48856
49331
|
const xmlDecl = includeXmlDeclaration ? '<?xml version="1.0" encoding="UTF-8"?>\n' : '';
|
|
48857
49332
|
const defsContent = defs.length > 0 ? `\n <defs>\n ${defs.join('\n ')}\n </defs>` : '';
|
|
48858
|
-
return `${xmlDecl}<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}" width="${viewBoxWidth}" height="${viewBoxHeight}">${defsContent}
|
|
48859
|
-
${elements}
|
|
49333
|
+
return `${xmlDecl}<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}" width="${viewBoxWidth}" height="${viewBoxHeight}">${defsContent}
|
|
49334
|
+
${elements}
|
|
48860
49335
|
</svg>`;
|
|
48861
49336
|
}
|
|
48862
49337
|
/**
|
|
@@ -49008,8 +49483,8 @@ class KritzelSvgExportHelper {
|
|
|
49008
49483
|
const orient = end === 'start' ? 'auto-start-reverse' : 'auto';
|
|
49009
49484
|
const refX = 0;
|
|
49010
49485
|
const refY = size / 2;
|
|
49011
|
-
return `<marker id="${markerId}" markerWidth="${size}" markerHeight="${size}" refX="${refX}" refY="${refY}" orient="${orient}" markerUnits="userSpaceOnUse">
|
|
49012
|
-
<path d="${path}" fill="${fill}" transform="scale(${size / 10})"/>
|
|
49486
|
+
return `<marker id="${markerId}" markerWidth="${size}" markerHeight="${size}" refX="${refX}" refY="${refY}" orient="${orient}" markerUnits="userSpaceOnUse">
|
|
49487
|
+
<path d="${path}" fill="${fill}" transform="scale(${size / 10})"/>
|
|
49013
49488
|
</marker>`;
|
|
49014
49489
|
}
|
|
49015
49490
|
/**
|
|
@@ -49038,6 +49513,9 @@ class KritzelSvgExportHelper {
|
|
|
49038
49513
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject')) {
|
|
49039
49514
|
return this.dynamicObjectToSvg(object, rasterSafeForCanvas);
|
|
49040
49515
|
}
|
|
49516
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelIframeObject')) {
|
|
49517
|
+
return this.iframeObjectToSvg(object);
|
|
49518
|
+
}
|
|
49041
49519
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
49042
49520
|
return this.groupToSvg(object, theme, imageDataUrls, rasterSafeForCanvas);
|
|
49043
49521
|
}
|
|
@@ -49056,10 +49534,10 @@ class KritzelSvgExportHelper {
|
|
|
49056
49534
|
const opacity = path.opacity !== 1 ? ` opacity="${path.opacity}"` : '';
|
|
49057
49535
|
const scale = this.getObjectScale(path);
|
|
49058
49536
|
// Path needs to be wrapped in a g with translation since path.d uses local coordinates
|
|
49059
|
-
return `<g transform="${transform}"${opacity}>
|
|
49060
|
-
<svg viewBox="${path.viewBox}" width="${path.totalWidth / scale}" height="${path.totalHeight / scale}" overflow="visible">
|
|
49061
|
-
<path d="${path.d}" fill="${fill || 'none'}" stroke="${stroke || 'none'}"${path.strokeWidth ? ` stroke-width="${path.strokeWidth}"` : ''}/>
|
|
49062
|
-
</svg>
|
|
49537
|
+
return `<g transform="${transform}"${opacity}>
|
|
49538
|
+
<svg viewBox="${path.viewBox}" width="${path.totalWidth / scale}" height="${path.totalHeight / scale}" overflow="visible">
|
|
49539
|
+
<path d="${path.d}" fill="${fill || 'none'}" stroke="${stroke || 'none'}"${path.strokeWidth ? ` stroke-width="${path.strokeWidth}"` : ''}/>
|
|
49540
|
+
</svg>
|
|
49063
49541
|
</g>`;
|
|
49064
49542
|
}
|
|
49065
49543
|
/**
|
|
@@ -49075,10 +49553,10 @@ class KritzelSvgExportHelper {
|
|
|
49075
49553
|
const scale = this.getObjectScale(line);
|
|
49076
49554
|
const markerStart = line.hasStartArrow ? ` marker-start="url(#${line.startMarkerId})"` : '';
|
|
49077
49555
|
const markerEnd = line.hasEndArrow ? ` marker-end="url(#${line.endMarkerId})"` : '';
|
|
49078
|
-
return `<g transform="${transform}"${opacity}>
|
|
49079
|
-
<svg viewBox="${line.viewBox}" width="${line.totalWidth / scale}" height="${line.totalHeight / scale}" overflow="visible">
|
|
49080
|
-
<path d="${line.d}" fill="none" stroke="${stroke}" stroke-width="${line.strokeWidth}" stroke-linecap="round"${markerStart}${markerEnd}/>
|
|
49081
|
-
</svg>
|
|
49556
|
+
return `<g transform="${transform}"${opacity}>
|
|
49557
|
+
<svg viewBox="${line.viewBox}" width="${line.totalWidth / scale}" height="${line.totalHeight / scale}" overflow="visible">
|
|
49558
|
+
<path d="${line.d}" fill="none" stroke="${stroke}" stroke-width="${line.strokeWidth}" stroke-linecap="round"${markerStart}${markerEnd}/>
|
|
49559
|
+
</svg>
|
|
49082
49560
|
</g>`;
|
|
49083
49561
|
}
|
|
49084
49562
|
/**
|
|
@@ -49102,18 +49580,18 @@ class KritzelSvgExportHelper {
|
|
|
49102
49580
|
const textHtml = this.prosemirrorToHtml(shape.content, shape, theme);
|
|
49103
49581
|
if (textHtml) {
|
|
49104
49582
|
const fontColor = KritzelColorHelper.resolveThemeColor(shape.fontColor, theme);
|
|
49105
|
-
textContent = `
|
|
49106
|
-
<foreignObject x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}">
|
|
49107
|
-
<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;">
|
|
49108
|
-
${textHtml}
|
|
49109
|
-
</div>
|
|
49583
|
+
textContent = `
|
|
49584
|
+
<foreignObject x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}">
|
|
49585
|
+
<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;">
|
|
49586
|
+
${textHtml}
|
|
49587
|
+
</div>
|
|
49110
49588
|
</foreignObject>`;
|
|
49111
49589
|
}
|
|
49112
49590
|
}
|
|
49113
|
-
return `<g transform="${transform}"${opacity}>
|
|
49114
|
-
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth / scale}" height="${shape.totalHeight / scale}" overflow="visible" preserveAspectRatio="none">
|
|
49115
|
-
<path d="${pathD}" fill="${fill || 'transparent'}" stroke="${stroke}" stroke-width="${shape.strokeWidth}"/>${textContent}
|
|
49116
|
-
</svg>
|
|
49591
|
+
return `<g transform="${transform}"${opacity}>
|
|
49592
|
+
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth / scale}" height="${shape.totalHeight / scale}" overflow="visible" preserveAspectRatio="none">
|
|
49593
|
+
<path d="${pathD}" fill="${fill || 'transparent'}" stroke="${stroke}" stroke-width="${shape.strokeWidth}"/>${textContent}
|
|
49594
|
+
</svg>
|
|
49117
49595
|
</g>`;
|
|
49118
49596
|
}
|
|
49119
49597
|
/**
|
|
@@ -49144,10 +49622,10 @@ class KritzelSvgExportHelper {
|
|
|
49144
49622
|
// adjusted font-size already accounts for it – keeping both would double-scale
|
|
49145
49623
|
// the content and overflow the foreignObject.
|
|
49146
49624
|
const svgFontSizePx = (text.fontSize * (4 / 3) * (text.scaleFactor || 1) / scale).toFixed(4);
|
|
49147
|
-
return `<g transform="${transform}"${opacity}>
|
|
49148
|
-
<foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
|
|
49149
|
-
<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>
|
|
49150
|
-
</foreignObject>
|
|
49625
|
+
return `<g transform="${transform}"${opacity}>
|
|
49626
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
|
|
49627
|
+
<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>
|
|
49628
|
+
</foreignObject>
|
|
49151
49629
|
</g>`;
|
|
49152
49630
|
}
|
|
49153
49631
|
/**
|
|
@@ -49181,9 +49659,9 @@ class KritzelSvgExportHelper {
|
|
|
49181
49659
|
return `<tspan x="0" y="${y}" xml:space="preserve">${this.escapeHtml(line)}</tspan>`;
|
|
49182
49660
|
})
|
|
49183
49661
|
.join('');
|
|
49184
|
-
return `<g transform="${transform}"${opacity}>
|
|
49185
|
-
${bgRect}
|
|
49186
|
-
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
49662
|
+
return `<g transform="${transform}"${opacity}>
|
|
49663
|
+
${bgRect}
|
|
49664
|
+
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
49187
49665
|
</g>`;
|
|
49188
49666
|
}
|
|
49189
49667
|
/**
|
|
@@ -49211,8 +49689,8 @@ class KritzelSvgExportHelper {
|
|
|
49211
49689
|
const width = image.totalWidth / scale;
|
|
49212
49690
|
const height = image.totalHeight / scale;
|
|
49213
49691
|
const href = imageDataUrls?.get(image.id) || image.resolvedSrc || image.src || '';
|
|
49214
|
-
return `<g transform="${transform}"${opacity}>
|
|
49215
|
-
<image href="${href}" x="0" y="0" width="${width}" height="${height}" preserveAspectRatio="xMidYMid meet"/>
|
|
49692
|
+
return `<g transform="${transform}"${opacity}>
|
|
49693
|
+
<image href="${href}" x="0" y="0" width="${width}" height="${height}" preserveAspectRatio="xMidYMid meet"/>
|
|
49216
49694
|
</g>`;
|
|
49217
49695
|
}
|
|
49218
49696
|
/**
|
|
@@ -49232,19 +49710,30 @@ class KritzelSvgExportHelper {
|
|
|
49232
49710
|
if (rasterSafeForCanvas) {
|
|
49233
49711
|
// PNG export: render placeholder rect (foreignObject doesn't rasterize to PNG well)
|
|
49234
49712
|
console.warn('[KritzelDynamicObject SVG Export] Dynamic objects do not serialize well to PNG. Use SVG export or screenshot instead.');
|
|
49235
|
-
return `<g transform="${transform}"${opacity}>
|
|
49236
|
-
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
49237
|
-
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Dynamic Object]</text>
|
|
49713
|
+
return `<g transform="${transform}"${opacity}>
|
|
49714
|
+
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
49715
|
+
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Dynamic Object]</text>
|
|
49238
49716
|
</g>`;
|
|
49239
49717
|
}
|
|
49240
49718
|
// SVG export: use foreignObject to embed HTML
|
|
49241
49719
|
const html = obj.element?.outerHTML || '<div style="border:1px dashed #ccc">Empty</div>';
|
|
49242
|
-
return `<g transform="${transform}"${opacity}>
|
|
49243
|
-
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
49244
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;overflow:hidden;">
|
|
49245
|
-
${html}
|
|
49246
|
-
</div>
|
|
49247
|
-
</foreignObject>
|
|
49720
|
+
return `<g transform="${transform}"${opacity}>
|
|
49721
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
49722
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;overflow:hidden;">
|
|
49723
|
+
${html}
|
|
49724
|
+
</div>
|
|
49725
|
+
</foreignObject>
|
|
49726
|
+
</g>`;
|
|
49727
|
+
}
|
|
49728
|
+
static iframeObjectToSvg(object) {
|
|
49729
|
+
const transform = this.buildTransform(object);
|
|
49730
|
+
const opacity = object.opacity !== 1 ? ` opacity="${object.opacity}"` : '';
|
|
49731
|
+
const scale = this.getObjectScale(object);
|
|
49732
|
+
const width = object.totalWidth / scale;
|
|
49733
|
+
const height = object.totalHeight / scale;
|
|
49734
|
+
return `<g transform="${transform}"${opacity}>
|
|
49735
|
+
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
49736
|
+
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Iframe]</text>
|
|
49248
49737
|
</g>`;
|
|
49249
49738
|
}
|
|
49250
49739
|
/**
|
|
@@ -49264,8 +49753,8 @@ class KritzelSvgExportHelper {
|
|
|
49264
49753
|
return '';
|
|
49265
49754
|
}
|
|
49266
49755
|
const opacity = group.opacity !== 1 ? ` opacity="${group.opacity}"` : '';
|
|
49267
|
-
return `<g${opacity}>
|
|
49268
|
-
${children}
|
|
49756
|
+
return `<g${opacity}>
|
|
49757
|
+
${children}
|
|
49269
49758
|
</g>`;
|
|
49270
49759
|
}
|
|
49271
49760
|
/**
|
|
@@ -49450,12 +49939,26 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
49450
49939
|
/** Authoritative workspace catalog for this engine instance. When provided, provider-only workspaces are hidden but not deleted. */
|
|
49451
49940
|
workspaces;
|
|
49452
49941
|
async onWorkspacesPropChange() {
|
|
49453
|
-
|
|
49942
|
+
this._workspacesRevision++;
|
|
49943
|
+
if (!this._isYjsInitialized || this._syncInitPromise) {
|
|
49454
49944
|
return;
|
|
49455
49945
|
}
|
|
49456
|
-
|
|
49457
|
-
|
|
49458
|
-
|
|
49946
|
+
const previousReconciliation = this._workspacePropReconciliationPromise;
|
|
49947
|
+
const reconciliationPromise = (async () => {
|
|
49948
|
+
await previousReconciliation;
|
|
49949
|
+
await this.reconcileProvidedWorkspaces();
|
|
49950
|
+
await this.ensureActiveWorkspaceIsVisible();
|
|
49951
|
+
this.workspacesChange.emit(this.getVisibleWorkspaces());
|
|
49952
|
+
})();
|
|
49953
|
+
this._workspacePropReconciliationPromise = reconciliationPromise;
|
|
49954
|
+
try {
|
|
49955
|
+
await reconciliationPromise;
|
|
49956
|
+
}
|
|
49957
|
+
finally {
|
|
49958
|
+
if (this._workspacePropReconciliationPromise === reconciliationPromise) {
|
|
49959
|
+
this._workspacePropReconciliationPromise = null;
|
|
49960
|
+
}
|
|
49961
|
+
}
|
|
49459
49962
|
}
|
|
49460
49963
|
/** Optional unique identifier for namespacing storage keys across multiple editor instances. */
|
|
49461
49964
|
editorId;
|
|
@@ -49509,6 +50012,12 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
49509
50012
|
onUserChange(newValue) {
|
|
49510
50013
|
this.core.setUser(newValue);
|
|
49511
50014
|
}
|
|
50015
|
+
/** Tool definitions to register with this engine instance. */
|
|
50016
|
+
tools = [];
|
|
50017
|
+
onToolsChange() {
|
|
50018
|
+
this._toolsRevision++;
|
|
50019
|
+
void this.registerConfiguredTools();
|
|
50020
|
+
}
|
|
49512
50021
|
/** Context menu items shown when right-clicking the canvas background. */
|
|
49513
50022
|
globalContextMenuItems;
|
|
49514
50023
|
onGlobalContextMenuItemsChange(newValue) {
|
|
@@ -49699,7 +50208,7 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
49699
50208
|
}
|
|
49700
50209
|
const hoveredObject = this.core.getObjectFromPointerEvent(ev);
|
|
49701
50210
|
if (hoveredObject &&
|
|
49702
|
-
ObjectHelper.
|
|
50211
|
+
ObjectHelper.isKritzelEmbeddedObject(hoveredObject) &&
|
|
49703
50212
|
KritzelWheelHelper.shouldKeepWheelInDynamicObject(ev, hoveredObject)) {
|
|
49704
50213
|
return;
|
|
49705
50214
|
}
|
|
@@ -49801,7 +50310,7 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
49801
50310
|
return false;
|
|
49802
50311
|
}
|
|
49803
50312
|
const object = this.core.store.objects.findById(objectElement.id);
|
|
49804
|
-
if (!object || !
|
|
50313
|
+
if (!object || !ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
49805
50314
|
return false;
|
|
49806
50315
|
}
|
|
49807
50316
|
const isSelected = !!this.core.store.selectionGroup?.objects?.some(selectedObject => selectedObject.id === object.id);
|
|
@@ -49811,13 +50320,7 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
49811
50320
|
if (object.isInteractive !== true) {
|
|
49812
50321
|
return false;
|
|
49813
50322
|
}
|
|
49814
|
-
const potentialRoots =
|
|
49815
|
-
if (object.element instanceof H) {
|
|
49816
|
-
potentialRoots.push(object.element);
|
|
49817
|
-
}
|
|
49818
|
-
if (object.elementRef instanceof H) {
|
|
49819
|
-
potentialRoots.push(object.elementRef);
|
|
49820
|
-
}
|
|
50323
|
+
const potentialRoots = object.getEmbeddedContentRoots();
|
|
49821
50324
|
if (potentialRoots.length === 0) {
|
|
49822
50325
|
return false;
|
|
49823
50326
|
}
|
|
@@ -49991,7 +50494,7 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
49991
50494
|
* Switches the active drawing tool by its registered name.
|
|
49992
50495
|
* @param toolName - The name the tool was registered with (e.g., 'brush', 'eraser').
|
|
49993
50496
|
*/
|
|
49994
|
-
async
|
|
50497
|
+
async setActiveTool(toolName) {
|
|
49995
50498
|
const tool = this.core.toolRegistry.getTool(toolName);
|
|
49996
50499
|
if (!tool) {
|
|
49997
50500
|
console.warn(`[KritzelEngine] No tool registered with name: ${toolName}`);
|
|
@@ -51297,9 +51800,13 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
51297
51800
|
_stateChangeListenersRegistered = false;
|
|
51298
51801
|
_workspaceInitializationPromise = null;
|
|
51299
51802
|
_workspaceInitializationTargetKey = null;
|
|
51803
|
+
_workspacePropReconciliationPromise = null;
|
|
51300
51804
|
_syncInitPromise = null;
|
|
51805
|
+
_toolsInitPromise = null;
|
|
51806
|
+
_toolsRevision = 0;
|
|
51301
51807
|
_syncConfigRevision = 0;
|
|
51302
51808
|
_assetStorageConfigRevision = 0;
|
|
51809
|
+
_workspacesRevision = 0;
|
|
51303
51810
|
_hasLoggedUnlicensedWelcomeBanner = false;
|
|
51304
51811
|
_previousVisibleDynamicObjects = new Set();
|
|
51305
51812
|
_revealedImageKeys = new Set();
|
|
@@ -51312,6 +51819,37 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
51312
51819
|
undoStackSize: 0,
|
|
51313
51820
|
redoStackSize: 0,
|
|
51314
51821
|
};
|
|
51822
|
+
/** Returns a tool registered in this engine instance. */
|
|
51823
|
+
async getTool(toolName) {
|
|
51824
|
+
await this.registerConfiguredTools();
|
|
51825
|
+
return this.core.toolRegistry.getTool(toolName);
|
|
51826
|
+
}
|
|
51827
|
+
async registerConfiguredTools() {
|
|
51828
|
+
if (this._toolsInitPromise) {
|
|
51829
|
+
return this._toolsInitPromise;
|
|
51830
|
+
}
|
|
51831
|
+
this._toolsInitPromise = (async () => {
|
|
51832
|
+
do {
|
|
51833
|
+
const revision = this._toolsRevision;
|
|
51834
|
+
for (const definition of this.tools) {
|
|
51835
|
+
let toolClass = definition.tool;
|
|
51836
|
+
if (typeof toolClass !== 'function') {
|
|
51837
|
+
toolClass = toolClass.constructor;
|
|
51838
|
+
}
|
|
51839
|
+
await this.registerTool(definition.name, toolClass, definition.config);
|
|
51840
|
+
}
|
|
51841
|
+
if (revision === this._toolsRevision) {
|
|
51842
|
+
break;
|
|
51843
|
+
}
|
|
51844
|
+
} while (true);
|
|
51845
|
+
})();
|
|
51846
|
+
try {
|
|
51847
|
+
await this._toolsInitPromise;
|
|
51848
|
+
}
|
|
51849
|
+
finally {
|
|
51850
|
+
this._toolsInitPromise = null;
|
|
51851
|
+
}
|
|
51852
|
+
}
|
|
51315
51853
|
setLoadingState(isLoading) {
|
|
51316
51854
|
if (this.core.store.state.isLoading === isLoading) {
|
|
51317
51855
|
return;
|
|
@@ -51443,6 +51981,8 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
51443
51981
|
this.core.licenseManager.destroy();
|
|
51444
51982
|
}
|
|
51445
51983
|
componentWillLoad() {
|
|
51984
|
+
this._toolsRevision++;
|
|
51985
|
+
void this.registerConfiguredTools();
|
|
51446
51986
|
this.core.setEditorId(this.editorId);
|
|
51447
51987
|
if (this.themes && this.themes.length > 0) {
|
|
51448
51988
|
this.core.themeManager.registerThemes(this.themes);
|
|
@@ -51482,7 +52022,9 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
51482
52022
|
const editorElement = this.host.closest('kritzel-editor');
|
|
51483
52023
|
this.core.themeManager.setTargetElement(editorElement || this.host);
|
|
51484
52024
|
// Initialize sync config and Yjs
|
|
52025
|
+
await this.registerConfiguredTools();
|
|
51485
52026
|
await this.initializeSyncAndWorkspace();
|
|
52027
|
+
await this.waitForWorkspaceAndSceneReady();
|
|
51486
52028
|
if (this.core.store.state.isReady === false) {
|
|
51487
52029
|
this.core.store.state.isReady = true;
|
|
51488
52030
|
this.logUnlicensedWelcomeBanner();
|
|
@@ -51504,6 +52046,20 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
51504
52046
|
this._syncInitPromise = null;
|
|
51505
52047
|
}
|
|
51506
52048
|
}
|
|
52049
|
+
async waitForSceneRender() {
|
|
52050
|
+
await new Promise(resolve => {
|
|
52051
|
+
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
52052
|
+
});
|
|
52053
|
+
}
|
|
52054
|
+
async waitForWorkspaceAndSceneReady() {
|
|
52055
|
+
let observedRevision;
|
|
52056
|
+
do {
|
|
52057
|
+
observedRevision = this._workspacesRevision;
|
|
52058
|
+
await this._workspacePropReconciliationPromise;
|
|
52059
|
+
await this.waitForSceneRender();
|
|
52060
|
+
} while (observedRevision !== this._workspacesRevision ||
|
|
52061
|
+
this._workspacePropReconciliationPromise);
|
|
52062
|
+
}
|
|
51507
52063
|
/**
|
|
51508
52064
|
* Initializes the asset storage layer with the latest config. Mirrors
|
|
51509
52065
|
* the in-flight replay logic of {@link doInitializeSyncAndWorkspace} for
|
|
@@ -51886,7 +52442,7 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
51886
52442
|
if (!KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup')) {
|
|
51887
52443
|
return 'auto';
|
|
51888
52444
|
}
|
|
51889
|
-
if (object.objects.length === 1 &&
|
|
52445
|
+
if (object.objects.length === 1 && ObjectHelper.isKritzelEmbeddedObject(object.objects[0])) {
|
|
51890
52446
|
return 'none';
|
|
51891
52447
|
}
|
|
51892
52448
|
return 'auto';
|
|
@@ -51894,7 +52450,7 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
51894
52450
|
// Track visible dynamic objects and unmount culled ones
|
|
51895
52451
|
const currentVisibleDynamicObjects = new Set();
|
|
51896
52452
|
visibleObjects.forEach(object => {
|
|
51897
|
-
if (
|
|
52453
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
51898
52454
|
currentVisibleDynamicObjects.add(object.id);
|
|
51899
52455
|
}
|
|
51900
52456
|
});
|
|
@@ -51902,7 +52458,7 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
51902
52458
|
this._previousVisibleDynamicObjects.forEach(id => {
|
|
51903
52459
|
if (!currentVisibleDynamicObjects.has(id)) {
|
|
51904
52460
|
const object = this.core.store.objects.findById(id);
|
|
51905
|
-
if (object &&
|
|
52461
|
+
if (object && ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
51906
52462
|
object.unmount();
|
|
51907
52463
|
}
|
|
51908
52464
|
}
|
|
@@ -51995,7 +52551,7 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
51995
52551
|
display: 'flex',
|
|
51996
52552
|
alignItems: 'center',
|
|
51997
52553
|
justifyContent: 'center',
|
|
51998
|
-
} }, h("kritzel-icon", { name: object.loadState === 'error' ? '
|
|
52554
|
+
} }, h("kritzel-icon", { name: object.loadState === 'error' ? 'imageOff' : 'image', size: Math.max(16, Math.min(object.totalWidth, object.totalHeight) * 0.3), style: {
|
|
51999
52555
|
color: KritzelColorHelper.resolveThemeColor({ light: '#9ca3af', dark: '#6b7280' }, currentTheme),
|
|
52000
52556
|
} }))), KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject') && (h("div", { ref: el => el && object.mount(el), style: {
|
|
52001
52557
|
position: 'absolute',
|
|
@@ -52014,7 +52570,37 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
52014
52570
|
padding: object.padding + 'px',
|
|
52015
52571
|
overflow: 'visible',
|
|
52016
52572
|
display: 'block',
|
|
52017
|
-
} })), KritzelClassHelper.isInstanceOf(object, '
|
|
52573
|
+
} })), KritzelClassHelper.isInstanceOf(object, 'KritzelIframeObject') && (h("div", { style: {
|
|
52574
|
+
position: 'absolute',
|
|
52575
|
+
left: '0',
|
|
52576
|
+
top: '0',
|
|
52577
|
+
width: object.totalWidth + 'px',
|
|
52578
|
+
height: object.totalHeight + 'px',
|
|
52579
|
+
transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
|
|
52580
|
+
transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
|
|
52581
|
+
opacity: effectiveOpacityString,
|
|
52582
|
+
backgroundColor: KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
|
|
52583
|
+
borderColor: KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
|
|
52584
|
+
borderWidth: object.borderWidth + 'px',
|
|
52585
|
+
borderStyle: 'solid',
|
|
52586
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
52587
|
+
boxShadow: object.boxShadow,
|
|
52588
|
+
overflow: 'hidden',
|
|
52589
|
+
display: 'block',
|
|
52590
|
+
pointerEvents: object.markedForRemoval ? 'none' : 'auto',
|
|
52591
|
+
} }, h("iframe", { ref: element => element && object.mount(element), title: object.title, sandbox: object.sandboxAttribute, style: {
|
|
52592
|
+
display: 'block',
|
|
52593
|
+
width: '100%',
|
|
52594
|
+
height: '100%',
|
|
52595
|
+
border: '0',
|
|
52596
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
52597
|
+
pointerEvents: object.isInteractive ? 'auto' : 'none',
|
|
52598
|
+
} }), h("div", { style: {
|
|
52599
|
+
position: 'absolute',
|
|
52600
|
+
inset: '0',
|
|
52601
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
52602
|
+
pointerEvents: object.isInteractive ? 'none' : 'auto',
|
|
52603
|
+
} }))), KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') && !this.core.displaySelectionLineUI(object) && (h("div", { ref: el => el && object.mount(el), style: {
|
|
52018
52604
|
position: 'absolute',
|
|
52019
52605
|
left: '0',
|
|
52020
52606
|
top: '0',
|
|
@@ -52372,6 +52958,9 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
52372
52958
|
"user": [{
|
|
52373
52959
|
"onUserChange": 0
|
|
52374
52960
|
}],
|
|
52961
|
+
"tools": [{
|
|
52962
|
+
"onToolsChange": 0
|
|
52963
|
+
}],
|
|
52375
52964
|
"globalContextMenuItems": [{
|
|
52376
52965
|
"onGlobalContextMenuItemsChange": 0
|
|
52377
52966
|
}],
|
|
@@ -52432,6 +53021,7 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
52432
53021
|
"syncConfig": [16],
|
|
52433
53022
|
"assetStorageConfig": [16],
|
|
52434
53023
|
"user": [16],
|
|
53024
|
+
"tools": [16],
|
|
52435
53025
|
"globalContextMenuItems": [16],
|
|
52436
53026
|
"objectContextMenuItems": [16],
|
|
52437
53027
|
"scaleMax": [1026, "scale-max"],
|
|
@@ -52456,7 +53046,7 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
52456
53046
|
"beginSceneBootstrap": [64],
|
|
52457
53047
|
"endSceneBootstrap": [64],
|
|
52458
53048
|
"registerTool": [64],
|
|
52459
|
-
"
|
|
53049
|
+
"setActiveTool": [64],
|
|
52460
53050
|
"disable": [64],
|
|
52461
53051
|
"enable": [64],
|
|
52462
53052
|
"delete": [64],
|
|
@@ -52532,7 +53122,8 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
52532
53122
|
"getAvailableLocales": [64],
|
|
52533
53123
|
"getAvailableLocaleOptions": [64],
|
|
52534
53124
|
"t": [64],
|
|
52535
|
-
"getResolvedTerms": [64]
|
|
53125
|
+
"getResolvedTerms": [64],
|
|
53126
|
+
"getTool": [64]
|
|
52536
53127
|
}, [[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"]], {
|
|
52537
53128
|
"workspaces": [{
|
|
52538
53129
|
"onWorkspacesPropChange": 0
|
|
@@ -52549,6 +53140,9 @@ const KritzelEngine$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEngine ext
|
|
|
52549
53140
|
"user": [{
|
|
52550
53141
|
"onUserChange": 0
|
|
52551
53142
|
}],
|
|
53143
|
+
"tools": [{
|
|
53144
|
+
"onToolsChange": 0
|
|
53145
|
+
}],
|
|
52552
53146
|
"globalContextMenuItems": [{
|
|
52553
53147
|
"onGlobalContextMenuItemsChange": 0
|
|
52554
53148
|
}],
|
|
@@ -52638,4 +53232,4 @@ function defineCustomElement$1() {
|
|
|
52638
53232
|
const KritzelEngine = KritzelEngine$1;
|
|
52639
53233
|
const defineCustomElement = defineCustomElement$1;
|
|
52640
53234
|
|
|
52641
|
-
export { AssetNotFoundError as A,
|
|
53235
|
+
export { AssetNotFoundError as A, KritzelDynamicObjectRendererRegistry as B, KritzelFontRegistry as C, DEFAULT_STROKE_SIZES as D, DEFAULT_SYNC_CONFIG as E, EN_LOCALE as F, DE_LOCALE as G, FR_LOCALE as H, IndexedDBAssetProvider as I, KritzelAlignment as J, KritzelText as K, KritzelEngine, runMigrations as L, APP_STATE_MIGRATIONS as M, WORKSPACE_MIGRATIONS as N, CURRENT_APP_STATE_SCHEMA_VERSION as O, CURRENT_WORKSPACE_SCHEMA_VERSION as P, resolveTextToolAvailableFonts as Q, ShapeType as S, WORKSPACE_EXPORT_VERSION as W, DEFAULT_FONT_SIZES as a, DEFAULT_TEXT_TOOL_AVAILABLE_FONTS as b, KritzelImage as c, KritzelGroup as d, defineCustomElement, KritzelShape as e, KritzelDynamicObject as f, KritzelIframeObject as g, KritzelSelectionGroup as h, KritzelSelectionBox as i, KritzelBaseTool as j, KritzelBrushTool as k, KritzelLineTool as l, KritzelEraserTool as m, KritzelImageTool as n, KritzelTextTool as o, KritzelShapeTool as p, KritzelCursorHelper as q, KritzelKeyboardHelper as r, KritzelDevicesHelper as s, KritzelHTMLHelper as t, KritzelSelectionTool as u, KritzelAssetResolver as v, KritzelWorkspace as w, KritzelAnchorManager as x, KritzelLocalizationManager as y, KritzelLicenseManager as z };
|