@kritzel/editor 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 +50 -50
- package/README.md +5 -5
- package/dist/cjs/{index-B92VHWr4.js → index-BAdxtEc7.js} +27 -9
- package/dist/cjs/kritzel-active-users_46.cjs.entry.js +1029 -366
- package/dist/cjs/kritzel-brush-style.cjs.entry.js +2 -2
- package/dist/cjs/kritzel-editor.cjs.js +3 -3
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/collection/collection-manifest.json +1 -1
- 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-CrIEmItB.js → p-2DAZSvN6.js} +5 -5
- package/dist/components/{p-CmjXRLdr.js → p-2gylYpXk.js} +7 -7
- package/dist/components/{p-BN8VWPlq.js → p-B-Divd0Q.js} +7 -7
- package/dist/components/{p-R1D8Sr0l.js → p-B-U13Ew1.js} +3 -3
- package/dist/components/{p-BZ_KnHdR.js → p-B1rmcPZr.js} +7 -7
- package/dist/components/{p-B_gT0lCn.js → p-B2-SxV8E.js} +3 -3
- package/dist/components/p-B6Z_VKKH.js +214 -0
- package/dist/components/{p-CVxGF4bJ.js → p-B8tHdknP.js} +5 -5
- package/dist/components/{p-CoNexfpB.js → p-BDsuJNT_.js} +3 -3
- package/dist/components/{p-BvG3JO85.js → p-BMi-i7sC.js} +3 -3
- package/dist/components/{p-Cy_cLtOP.js → p-BZ0ReYAA.js} +18 -14
- package/dist/components/{p-DZsSiMnA.js → p-BeCy6w6M.js} +770 -173
- package/dist/components/{p-4-qLegHb.js → p-Bipc1XvF.js} +4 -4
- package/dist/components/{p-CS3YZVYE.js → p-BmFJelgk.js} +2 -2
- package/dist/components/{p-DqOC_Yck.js → p-BpvSYxxN.js} +6 -6
- package/dist/components/{p-peZjvnkK.js → p-C0ns8IPO.js} +2 -2
- package/dist/components/{p-ClfOtiNp.js → p-C1_r9nJU.js} +3 -3
- package/dist/components/{p-GbCxpbQ6.js → p-C2ySiAXO.js} +3 -3
- package/dist/components/{p-B3Tqoyl9.js → p-C3KlONnT.js} +3 -3
- package/dist/components/{p-B5xYV1o3.js → p-C68YXjuL.js} +2 -2
- package/dist/components/{p-DJxgPPfs.js → p-CCuNN278.js} +3 -3
- package/dist/components/{p-Ds0uNtwQ.js → p-CNH7N3Aq.js} +4 -4
- package/dist/components/{p-DVv8ChhE.js → p-CO1cJlfg.js} +4 -4
- package/dist/components/{p-Cp4e4oTE.js → p-CqHKGLYE.js} +2 -2
- package/dist/components/{p-Blq9a1ni.js → p-CrEWqua9.js} +6 -6
- package/dist/components/{p-CvaxFYS0.js → p-Cv2nqOL8.js} +8 -8
- package/dist/components/{p-CzUeIini.js → p-D-1ixLxq.js} +13 -13
- package/dist/components/{p-BfMlwIcG.js → p-DF8p-DxR.js} +3 -3
- package/dist/components/{p-QEue33R5.js → p-DQ3VKzAS.js} +3 -3
- package/dist/components/{p-Ckqh1tqY.js → p-DRe-rTlX.js} +27 -31
- package/dist/components/{p-McY5wZ0h.js → p-DSyb29RF.js} +2 -2
- package/dist/components/{p-D0tPTPkR.js → p-DYDruZIw.js} +3 -3
- package/dist/components/{p-kOINnzaR.js → p-D_JxJxQ6.js} +7 -7
- package/dist/components/{p-BDjRSoAc.js → p-Dko_6jIh.js} +2 -2
- package/dist/components/{p-BjFrt1q0.js → p-DnHvqeyr.js} +3 -3
- package/dist/components/{p-BrGJIoGK.js → p-DqMikMrS.js} +3 -3
- package/dist/components/p-DsnHq8en.js +55 -0
- package/dist/components/{p-DXZBWJBt.js → p-DxFNLy9X.js} +4 -4
- package/dist/components/{p-5qkOM1RJ.js → p-Dzr6X2aj.js} +16 -4
- package/dist/components/{p-DXuf225S.js → p-HbHo7awi.js} +3 -3
- package/dist/components/{p-CwBxnzYu.js → p-Qbk7xE91.js} +3 -3
- package/dist/components/{p-h_uh_Njf.js → p-VYGV0cr3.js} +3 -3
- package/dist/components/{p-DyRJFg4w.js → p-YGBl60lb.js} +2 -2
- package/dist/components/{p-hQwVRh0t.js → p-clFfXKKn.js} +7 -7
- package/dist/components/{p-SLnqczCS.js → p-dUcCDLDF.js} +3 -3
- package/dist/components/{p-B6UJztrf.js → p-kXnNX65j.js} +4 -4
- package/dist/esm/{index-OjbYJz-P.js → index-YR-6hzAW.js} +27 -10
- package/dist/esm/kritzel-active-users_46.entry.js +1029 -366
- package/dist/esm/kritzel-brush-style.entry.js +2 -2
- package/dist/esm/kritzel-editor.js +4 -4
- package/dist/esm/loader.js +3 -3
- package/dist/kritzel-editor/kritzel-editor.esm.js +4 -4
- package/dist/kritzel-editor/{p-501047d8.entry.js → p-3a0f60b0.entry.js} +2 -2
- package/dist/kritzel-editor/{p-OjbYJz-P.js → p-YR-6hzAW.js} +27 -10
- package/dist/kritzel-editor/{p-60319edb.entry.js → p-adc45d46.entry.js} +1029 -366
- package/dist/types/components/kritzel-editor/kritzel-editor.d.ts +9 -2
- package/dist/types/components.d.ts +15 -15
- package/dist/types/stencil-public-runtime.d.ts +61 -55
- 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-Dzr6X2aj.js';
|
|
2
|
+
import { a as KritzelMouseButton, d as defineCustomElement$3 } from './p-CqHKGLYE.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-BZ0ReYAA.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-dUcCDLDF.js';
|
|
6
|
+
import { a as KritzelIconRegistry, d as defineCustomElement$2 } from './p-B6Z_VKKH.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Represents a visual selection box used for multi-object selection on the canvas.
|
|
@@ -22165,7 +22165,6 @@ class Mark {
|
|
|
22165
22165
|
if (!type)
|
|
22166
22166
|
throw new RangeError(`There is no mark type ${json.type} in this schema`);
|
|
22167
22167
|
let mark = type.create(json.attrs);
|
|
22168
|
-
type.checkAttrs(mark.attrs);
|
|
22169
22168
|
return mark;
|
|
22170
22169
|
}
|
|
22171
22170
|
/**
|
|
@@ -23145,11 +23144,11 @@ class Node {
|
|
|
23145
23144
|
*/
|
|
23146
23145
|
check() {
|
|
23147
23146
|
this.type.checkContent(this.content);
|
|
23148
|
-
this.type.
|
|
23147
|
+
checkAttrs(this.type.attrs, this.attrs, "node", this.type.name);
|
|
23149
23148
|
let copy = Mark.none;
|
|
23150
23149
|
for (let i = 0; i < this.marks.length; i++) {
|
|
23151
23150
|
let mark = this.marks[i];
|
|
23152
|
-
mark.type.
|
|
23151
|
+
checkAttrs(mark.type.attrs, mark.attrs, "mark", mark.type.name);
|
|
23153
23152
|
copy = mark.addToSet(copy);
|
|
23154
23153
|
}
|
|
23155
23154
|
if (!Mark.sameSet(copy, this.marks))
|
|
@@ -23190,7 +23189,6 @@ class Node {
|
|
|
23190
23189
|
}
|
|
23191
23190
|
let content = Fragment.fromJSON(schema, json.content);
|
|
23192
23191
|
let node = schema.nodeType(json.type).create(json.attrs, content, marks);
|
|
23193
|
-
node.type.checkAttrs(node.attrs);
|
|
23194
23192
|
return node;
|
|
23195
23193
|
}
|
|
23196
23194
|
}
|
|
@@ -23240,6 +23238,15 @@ function wrapMarks(marks, str) {
|
|
|
23240
23238
|
str = marks[i].type.name + "(" + str + ")";
|
|
23241
23239
|
return str;
|
|
23242
23240
|
}
|
|
23241
|
+
function checkAttrs(attrs, values, type, name) {
|
|
23242
|
+
for (let attr in values)
|
|
23243
|
+
if (!(attr in attrs))
|
|
23244
|
+
throw new RangeError(`Unsupported attribute ${attr} for ${type} of type ${name}`);
|
|
23245
|
+
for (let attr in attrs) {
|
|
23246
|
+
if (attrs[attr].validate)
|
|
23247
|
+
attrs[attr].validate(values[attr]);
|
|
23248
|
+
}
|
|
23249
|
+
}
|
|
23243
23250
|
|
|
23244
23251
|
/**
|
|
23245
23252
|
Instances of this class represent a match state of a node type's
|
|
@@ -23694,27 +23701,21 @@ function defaultAttrs(attrs) {
|
|
|
23694
23701
|
function computeAttrs(attrs, value) {
|
|
23695
23702
|
let built = Object.create(null);
|
|
23696
23703
|
for (let name in attrs) {
|
|
23704
|
+
let attr = attrs[name];
|
|
23697
23705
|
let given = value && value[name];
|
|
23698
23706
|
if (given === undefined) {
|
|
23699
|
-
let attr = attrs[name];
|
|
23700
23707
|
if (attr.hasDefault)
|
|
23701
23708
|
given = attr.default;
|
|
23702
23709
|
else
|
|
23703
23710
|
throw new RangeError("No value supplied for attribute " + name);
|
|
23704
23711
|
}
|
|
23712
|
+
else if (attr.validate) {
|
|
23713
|
+
attr.validate(given);
|
|
23714
|
+
}
|
|
23705
23715
|
built[name] = given;
|
|
23706
23716
|
}
|
|
23707
23717
|
return built;
|
|
23708
23718
|
}
|
|
23709
|
-
function checkAttrs(attrs, values, type, name) {
|
|
23710
|
-
for (let attr in values)
|
|
23711
|
-
if (!(attr in attrs))
|
|
23712
|
-
throw new RangeError(`Unsupported attribute ${attr} for ${type} of type ${name}`);
|
|
23713
|
-
for (let attr in attrs) {
|
|
23714
|
-
if (attrs[attr].validate)
|
|
23715
|
-
attrs[attr].validate(values[attr]);
|
|
23716
|
-
}
|
|
23717
|
-
}
|
|
23718
23719
|
function initAttrs(typeName, attrs) {
|
|
23719
23720
|
let result = Object.create(null);
|
|
23720
23721
|
if (attrs)
|
|
@@ -23886,11 +23887,9 @@ let NodeType$1 = class NodeType {
|
|
|
23886
23887
|
throw new RangeError(`Invalid content for node ${this.name}: ${content.toString().slice(0, 50)}`);
|
|
23887
23888
|
}
|
|
23888
23889
|
/**
|
|
23889
|
-
@internal
|
|
23890
|
+
@internal no longer useful, but called by old prosemirror-view versions
|
|
23890
23891
|
*/
|
|
23891
|
-
checkAttrs(attrs) {
|
|
23892
|
-
checkAttrs(this.attrs, attrs, "node", this.name);
|
|
23893
|
-
}
|
|
23892
|
+
checkAttrs(attrs) { }
|
|
23894
23893
|
/**
|
|
23895
23894
|
Check whether the given mark type is allowed in this node.
|
|
23896
23895
|
*/
|
|
@@ -24037,12 +24036,6 @@ class MarkType {
|
|
|
24037
24036
|
return set[i];
|
|
24038
24037
|
}
|
|
24039
24038
|
/**
|
|
24040
|
-
@internal
|
|
24041
|
-
*/
|
|
24042
|
-
checkAttrs(attrs) {
|
|
24043
|
-
checkAttrs(this.attrs, attrs, "mark", this.name);
|
|
24044
|
-
}
|
|
24045
|
-
/**
|
|
24046
24039
|
Queries whether a given mark type is
|
|
24047
24040
|
[excluded](https://prosemirror.net/docs/ref/#model.MarkSpec.excludes) by this one.
|
|
24048
24041
|
*/
|
|
@@ -30734,7 +30727,8 @@ function nodeLen(node) {
|
|
|
30734
30727
|
}
|
|
30735
30728
|
function isIgnorable(dom, dir) {
|
|
30736
30729
|
let desc = dom.pmViewDesc;
|
|
30737
|
-
return desc
|
|
30730
|
+
return desc ? desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR")
|
|
30731
|
+
: dom.nodeType == 1 && dom.contentEditable == "false";
|
|
30738
30732
|
}
|
|
30739
30733
|
function skipIgnoredNodes(view, dir) {
|
|
30740
30734
|
return dir < 0 ? skipIgnoredNodesBefore(view) : skipIgnoredNodesAfter(view);
|
|
@@ -31323,12 +31317,11 @@ function addContext(slice, context) {
|
|
|
31323
31317
|
if (!type || type.hasRequiredAttrs())
|
|
31324
31318
|
break;
|
|
31325
31319
|
try {
|
|
31326
|
-
type.
|
|
31320
|
+
content = Fragment.from(type.create(array[i + 1], content));
|
|
31327
31321
|
}
|
|
31328
31322
|
catch (e) {
|
|
31329
31323
|
break;
|
|
31330
31324
|
}
|
|
31331
|
-
content = Fragment.from(type.create(array[i + 1], content));
|
|
31332
31325
|
openStart++;
|
|
31333
31326
|
openEnd++;
|
|
31334
31327
|
}
|
|
@@ -31808,7 +31801,7 @@ editHandlers.compositionstart = editHandlers.compositionupdate = view => {
|
|
|
31808
31801
|
if (!view.composing) {
|
|
31809
31802
|
view.domObserver.flush();
|
|
31810
31803
|
let { state } = view, $pos = state.selection.$to;
|
|
31811
|
-
if (state.selection instanceof TextSelection &&
|
|
31804
|
+
if (state.selection instanceof TextSelection && state.selection.empty &&
|
|
31812
31805
|
(state.storedMarks ||
|
|
31813
31806
|
(!$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some(m => m.type.spec.inclusive === false)) ||
|
|
31814
31807
|
chrome && windows$1 && selectionBeforeUneditable(view))) { // Issue #1500
|
|
@@ -33445,9 +33438,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
33445
33438
|
// as being an iOS enter press), just dispatch an Enter key instead.
|
|
33446
33439
|
if (((ios && view.input.lastIOSEnter > Date.now() - 225 &&
|
|
33447
33440
|
(!inlineChange || addedNodes.some(n => n.nodeName == "DIV" || n.nodeName == "P"))) ||
|
|
33448
|
-
(!inlineChange && $from.pos
|
|
33449
|
-
(!$from.sameParent($to) || !$from.parent.inlineContent) &&
|
|
33450
|
-
$from.pos < $to.pos && !/\S/.test(parse.doc.textBetween($from.pos, $to.pos, "", "")))) &&
|
|
33441
|
+
(!inlineChange && looksLikeEnter(parse.doc, $from.pos, $to.pos))) &&
|
|
33451
33442
|
view.someProp("handleKeyDown", f => f(view, keyEvent(13, "Enter")))) {
|
|
33452
33443
|
view.input.lastIOSEnter = 0;
|
|
33453
33444
|
return;
|
|
@@ -33598,6 +33589,16 @@ function looksLikeBackspace(old, start, end, $newStart, $newEnd) {
|
|
|
33598
33589
|
// The fragments after the join point must match
|
|
33599
33590
|
return $newStart.parent.content.cut($newStart.parentOffset).eq($next.parent.content);
|
|
33600
33591
|
}
|
|
33592
|
+
function looksLikeEnter(content, from, to) {
|
|
33593
|
+
let newTextlines = 0, newLeaves = 0;
|
|
33594
|
+
content.nodesBetween(from, to, (node, pos) => {
|
|
33595
|
+
if (node.isTextblock && pos >= from && pos < to)
|
|
33596
|
+
newTextlines++;
|
|
33597
|
+
else if (node.isText ? /\S/.test(node.text.slice(Math.max(0, from - pos), Math.min(node.nodeSize, to - pos))) : node.isLeaf)
|
|
33598
|
+
newLeaves++;
|
|
33599
|
+
});
|
|
33600
|
+
return newLeaves == 0 && newTextlines == 1;
|
|
33601
|
+
}
|
|
33601
33602
|
function skipClosingAndOpening($pos, fromEnd, mayOpen) {
|
|
33602
33603
|
let depth = $pos.depth, end = fromEnd ? $pos.end() : $pos.pos;
|
|
33603
33604
|
while (depth > 0 && (fromEnd || $pos.indexAfter(depth) == $pos.node(depth).childCount)) {
|
|
@@ -38067,9 +38068,8 @@ class KritzelSelectionTool extends KritzelBaseTool {
|
|
|
38067
38068
|
}
|
|
38068
38069
|
if (selectedObject && selectedObject.isSelected === false && selectedObject?.objects.length === 1) {
|
|
38069
38070
|
const firstObj = selectedObject.objects[0];
|
|
38070
|
-
if (
|
|
38071
|
-
// Selected
|
|
38072
|
-
// embedded DOM content. Unselected dynamic objects remain selectable.
|
|
38071
|
+
if (ObjectHelper.isKritzelEmbeddedObject(firstObj)) {
|
|
38072
|
+
// Selected embedded objects hand pointer interaction to their content.
|
|
38073
38073
|
if (firstObj.isSelected && this._core.store.selectionGroup?.objects.length === 1)
|
|
38074
38074
|
return;
|
|
38075
38075
|
}
|
|
@@ -40238,7 +40238,7 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40238
40238
|
}
|
|
40239
40239
|
applyInteractiveState() {
|
|
40240
40240
|
const pointerEvents = this.isInteractive ? 'auto' : 'none';
|
|
40241
|
-
const contentCursor = this.isInteractive ? 'auto' : '';
|
|
40241
|
+
const contentCursor = this.isInteractive ? 'var(--kritzel-global-default-cursor, auto)' : '';
|
|
40242
40242
|
if (this.element) {
|
|
40243
40243
|
this.element.style.pointerEvents = pointerEvents;
|
|
40244
40244
|
this.element.style.cursor = contentCursor;
|
|
@@ -40274,7 +40274,7 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40274
40274
|
if (!this.isInteractive) {
|
|
40275
40275
|
return false;
|
|
40276
40276
|
}
|
|
40277
|
-
const focusHosts = this.
|
|
40277
|
+
const focusHosts = this.getEmbeddedContentRoots();
|
|
40278
40278
|
// Primary path: locate the focused input-like element by walking from each host through
|
|
40279
40279
|
// `:focus` (piercing open shadow roots). This works in real browsers even when the engine
|
|
40280
40280
|
// and editor are nested web components, because it never relies on the document-level
|
|
@@ -40291,7 +40291,7 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40291
40291
|
}
|
|
40292
40292
|
return false;
|
|
40293
40293
|
}
|
|
40294
|
-
|
|
40294
|
+
getEmbeddedContentRoots() {
|
|
40295
40295
|
const hosts = [];
|
|
40296
40296
|
if (this.element) {
|
|
40297
40297
|
hosts.push(this.element);
|
|
@@ -40504,11 +40504,11 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40504
40504
|
* @returns A serializable object with htmlString and dimension snapshots
|
|
40505
40505
|
*/
|
|
40506
40506
|
serialize() {
|
|
40507
|
-
const { _core, _elementRef, element, totalWidth, totalHeight, isSelected, isHovered, isMounted, isInteractive, resizing, markedForRemoval, isVisible, ...props } = this;
|
|
40507
|
+
const { _core, _elementRef, element, totalWidth, totalHeight, isSelected, isHovered, isMounted, isInteractive, resizing, markedForRemoval, isVisible, rendererData, ...props } = this;
|
|
40508
40508
|
const cloned = structuredClone(props);
|
|
40509
40509
|
// Include rendererKey and rendererData for lifecycle-driven rendering
|
|
40510
40510
|
cloned.rendererKey = this.rendererKey;
|
|
40511
|
-
cloned.rendererData = this.
|
|
40511
|
+
cloned.rendererData = this.serializeRendererData();
|
|
40512
40512
|
// Store HTML as string for fallback/compatibility when renderer is unavailable
|
|
40513
40513
|
cloned.htmlString = element ? element.outerHTML : '';
|
|
40514
40514
|
// Capture dimension snapshot at serialization time
|
|
@@ -40516,6 +40516,19 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40516
40516
|
cloned.serializedHeight = this.height;
|
|
40517
40517
|
return cloned;
|
|
40518
40518
|
}
|
|
40519
|
+
serializeRendererData() {
|
|
40520
|
+
if (this.rendererKey) {
|
|
40521
|
+
const renderer = KritzelDynamicObjectRendererRegistry.get(this.rendererKey);
|
|
40522
|
+
if (renderer?.onSerialize) {
|
|
40523
|
+
return structuredClone(renderer.onSerialize({
|
|
40524
|
+
object: this,
|
|
40525
|
+
container: this.isMounted && this.elementRef instanceof HTMLElement ? this.elementRef : null,
|
|
40526
|
+
data: this.rendererData,
|
|
40527
|
+
}));
|
|
40528
|
+
}
|
|
40529
|
+
}
|
|
40530
|
+
return structuredClone(this.rendererData);
|
|
40531
|
+
}
|
|
40519
40532
|
/**
|
|
40520
40533
|
* Deserializes the dynamic object from a plain object.
|
|
40521
40534
|
* Reconstructs the element from stored HTML string with fallback to placeholder.
|
|
@@ -40548,6 +40561,452 @@ class KritzelDynamicObject extends KritzelBaseObject {
|
|
|
40548
40561
|
}
|
|
40549
40562
|
}
|
|
40550
40563
|
|
|
40564
|
+
const IFRAME_STATE_MESSAGE = 'kritzel-iframe-state';
|
|
40565
|
+
const IFRAME_PARENT_STATE_MESSAGE = 'kritzel-iframe-parent-state';
|
|
40566
|
+
const IFRAME_POINTER_MESSAGE = 'kritzel-iframe-pointer';
|
|
40567
|
+
const IFRAME_CONTEXT_MENU_MESSAGE = 'kritzel-iframe-contextmenu';
|
|
40568
|
+
const SUPPORTED_SANDBOX_TOKENS = new Set([
|
|
40569
|
+
'allow-downloads',
|
|
40570
|
+
'allow-forms',
|
|
40571
|
+
'allow-modals',
|
|
40572
|
+
'allow-orientation-lock',
|
|
40573
|
+
'allow-pointer-lock',
|
|
40574
|
+
'allow-popups',
|
|
40575
|
+
'allow-popups-to-escape-sandbox',
|
|
40576
|
+
'allow-presentation',
|
|
40577
|
+
'allow-same-origin',
|
|
40578
|
+
'allow-scripts',
|
|
40579
|
+
'allow-top-navigation-by-user-activation',
|
|
40580
|
+
]);
|
|
40581
|
+
const iframePointerBridgeStarts = new WeakMap();
|
|
40582
|
+
class KritzelIframeObject extends KritzelBaseObject {
|
|
40583
|
+
__class__ = 'KritzelIframeObject';
|
|
40584
|
+
content = { html: '', css: '', script: '' };
|
|
40585
|
+
loadingContent;
|
|
40586
|
+
isLoading = false;
|
|
40587
|
+
state = {};
|
|
40588
|
+
title = 'Embedded content';
|
|
40589
|
+
sandbox = ['allow-scripts'];
|
|
40590
|
+
borderRadius;
|
|
40591
|
+
boxShadow;
|
|
40592
|
+
get html() { return this.content.html; }
|
|
40593
|
+
set html(value) { this.content = { ...this.content, html: value }; }
|
|
40594
|
+
get css() { return this.content.css; }
|
|
40595
|
+
set css(value) { this.content = { ...this.content, css: value }; }
|
|
40596
|
+
get script() { return this.content.script; }
|
|
40597
|
+
set script(value) { this.content = { ...this.content, script: value }; }
|
|
40598
|
+
messageListener = null;
|
|
40599
|
+
constructor(config) {
|
|
40600
|
+
super();
|
|
40601
|
+
this.content = {
|
|
40602
|
+
html: config?.content?.html ?? config?.html ?? '',
|
|
40603
|
+
css: config?.content?.css ?? config?.css ?? '',
|
|
40604
|
+
script: config?.content?.script ?? config?.script ?? '',
|
|
40605
|
+
};
|
|
40606
|
+
this.loadingContent = config?.loadingContent ? {
|
|
40607
|
+
html: config.loadingContent.html ?? '',
|
|
40608
|
+
css: config.loadingContent.css ?? '',
|
|
40609
|
+
script: config.loadingContent.script ?? '',
|
|
40610
|
+
} : undefined;
|
|
40611
|
+
this.isLoading = config?.isLoading ?? false;
|
|
40612
|
+
this.state = structuredClone(config?.state ?? {});
|
|
40613
|
+
this.title = config?.title ?? 'Embedded content';
|
|
40614
|
+
this.sandbox = this.normalizeSandbox(config?.sandbox);
|
|
40615
|
+
this.borderRadius = config?.borderRadius;
|
|
40616
|
+
this.boxShadow = config?.boxShadow;
|
|
40617
|
+
this.translateX = config?.translateX ?? 0;
|
|
40618
|
+
this.translateY = config?.translateY ?? 0;
|
|
40619
|
+
this.rotation = KritzelMathHelper.degreesToRadians(config?.rotation ?? 0);
|
|
40620
|
+
this.scale = config?.scale ?? 1;
|
|
40621
|
+
this.width = config?.width ?? 0;
|
|
40622
|
+
this.height = config?.height ?? 0;
|
|
40623
|
+
}
|
|
40624
|
+
static create(core, config) {
|
|
40625
|
+
const object = new KritzelIframeObject(config);
|
|
40626
|
+
object._core = core;
|
|
40627
|
+
object.id = object.generateId();
|
|
40628
|
+
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
40629
|
+
object.userId = core.user?.id;
|
|
40630
|
+
object.scale = config?.scale ?? core.store.state.scale;
|
|
40631
|
+
object.zIndex = core.store.currentZIndex;
|
|
40632
|
+
return object;
|
|
40633
|
+
}
|
|
40634
|
+
get sandboxAttribute() {
|
|
40635
|
+
return this.sandbox.join(' ');
|
|
40636
|
+
}
|
|
40637
|
+
mount(iframe) {
|
|
40638
|
+
if (this.isMounted && this.elementRef === iframe) {
|
|
40639
|
+
return;
|
|
40640
|
+
}
|
|
40641
|
+
if (this.isMounted) {
|
|
40642
|
+
this.unmount();
|
|
40643
|
+
}
|
|
40644
|
+
this.elementRef = iframe;
|
|
40645
|
+
this.isMounted = true;
|
|
40646
|
+
iframe.title = this.title;
|
|
40647
|
+
iframe.setAttribute('sandbox', this.sandboxAttribute);
|
|
40648
|
+
iframe.style.pointerEvents = this.isInteractive ? 'auto' : 'none';
|
|
40649
|
+
this.messageListener = event => this.handleMessage(event);
|
|
40650
|
+
window.addEventListener('message', this.messageListener);
|
|
40651
|
+
iframe.srcdoc = this.createSourceDocument();
|
|
40652
|
+
this.onMount(this.createLifecycleContext());
|
|
40653
|
+
}
|
|
40654
|
+
unmount() {
|
|
40655
|
+
if (!this.isMounted) {
|
|
40656
|
+
return;
|
|
40657
|
+
}
|
|
40658
|
+
const nextState = this.onUnmount(this.createLifecycleContext());
|
|
40659
|
+
if (nextState !== undefined) {
|
|
40660
|
+
this.state = structuredClone(nextState);
|
|
40661
|
+
}
|
|
40662
|
+
if (this.messageListener) {
|
|
40663
|
+
window.removeEventListener('message', this.messageListener);
|
|
40664
|
+
this.messageListener = null;
|
|
40665
|
+
}
|
|
40666
|
+
this.isMounted = false;
|
|
40667
|
+
this._elementRef = null;
|
|
40668
|
+
}
|
|
40669
|
+
setContent(content) {
|
|
40670
|
+
this.content = {
|
|
40671
|
+
html: content.html ?? this.content.html,
|
|
40672
|
+
css: content.css ?? this.content.css,
|
|
40673
|
+
script: content.script ?? this.content.script,
|
|
40674
|
+
};
|
|
40675
|
+
this.refreshDocument();
|
|
40676
|
+
this.persistUpdate();
|
|
40677
|
+
}
|
|
40678
|
+
setLoadingContent(content) {
|
|
40679
|
+
this.loadingContent = {
|
|
40680
|
+
html: content.html ?? this.loadingContent?.html ?? '',
|
|
40681
|
+
css: content.css ?? this.loadingContent?.css ?? '',
|
|
40682
|
+
script: content.script ?? this.loadingContent?.script ?? '',
|
|
40683
|
+
};
|
|
40684
|
+
this.refreshDocument();
|
|
40685
|
+
this.persistUpdate();
|
|
40686
|
+
}
|
|
40687
|
+
setLoading(isLoading) {
|
|
40688
|
+
this.isLoading = isLoading;
|
|
40689
|
+
this.refreshDocument();
|
|
40690
|
+
this.persistUpdate();
|
|
40691
|
+
}
|
|
40692
|
+
getActiveContent() {
|
|
40693
|
+
const activeLoadingContent = this.isLoading ? this.loadingContent : undefined;
|
|
40694
|
+
return {
|
|
40695
|
+
html: activeLoadingContent?.html ?? this.content.html,
|
|
40696
|
+
css: activeLoadingContent?.css ?? this.content.css,
|
|
40697
|
+
script: activeLoadingContent?.script ?? this.content.script,
|
|
40698
|
+
};
|
|
40699
|
+
}
|
|
40700
|
+
setState(state) {
|
|
40701
|
+
this.state = structuredClone(state);
|
|
40702
|
+
this.elementRef?.contentWindow?.postMessage({ type: IFRAME_PARENT_STATE_MESSAGE, state: this.state }, '*');
|
|
40703
|
+
this.persistUpdate();
|
|
40704
|
+
}
|
|
40705
|
+
setIsInteractive(isInteractive) {
|
|
40706
|
+
this.isInteractive = isInteractive;
|
|
40707
|
+
if (this.isMounted && this.elementRef) {
|
|
40708
|
+
this.elementRef.style.pointerEvents = isInteractive ? 'auto' : 'none';
|
|
40709
|
+
if (!isInteractive) {
|
|
40710
|
+
this.elementRef.blur();
|
|
40711
|
+
}
|
|
40712
|
+
}
|
|
40713
|
+
}
|
|
40714
|
+
hasFocusedInputElement() {
|
|
40715
|
+
return this.isInteractive && this.isMounted && document.activeElement === this.elementRef;
|
|
40716
|
+
}
|
|
40717
|
+
getEmbeddedContentRoots() {
|
|
40718
|
+
return this.isMounted && this.elementRef instanceof HTMLElement && this.elementRef.tagName === 'IFRAME' ? [this.elementRef] : [];
|
|
40719
|
+
}
|
|
40720
|
+
onMount(_context) { }
|
|
40721
|
+
onSerialize(context) {
|
|
40722
|
+
return context.state;
|
|
40723
|
+
}
|
|
40724
|
+
onUnmount(context) {
|
|
40725
|
+
return context.state;
|
|
40726
|
+
}
|
|
40727
|
+
serialize() {
|
|
40728
|
+
const nextState = this.onSerialize(this.createLifecycleContext());
|
|
40729
|
+
this.state = structuredClone(nextState);
|
|
40730
|
+
const messageListener = this.messageListener;
|
|
40731
|
+
this.messageListener = null;
|
|
40732
|
+
try {
|
|
40733
|
+
const serialized = super.serialize();
|
|
40734
|
+
delete serialized.messageListener;
|
|
40735
|
+
return serialized;
|
|
40736
|
+
}
|
|
40737
|
+
finally {
|
|
40738
|
+
this.messageListener = messageListener;
|
|
40739
|
+
}
|
|
40740
|
+
}
|
|
40741
|
+
deserialize(object) {
|
|
40742
|
+
super.deserialize(object);
|
|
40743
|
+
const nextContent = object.content && typeof object.content === 'object' ? object.content : {};
|
|
40744
|
+
const nextLoadingContent = object.loadingContent && typeof object.loadingContent === 'object' ? object.loadingContent : undefined;
|
|
40745
|
+
this.content = {
|
|
40746
|
+
html: typeof nextContent.html === 'string' ? nextContent.html : typeof object.html === 'string' ? object.html : '',
|
|
40747
|
+
css: typeof nextContent.css === 'string' ? nextContent.css : typeof object.css === 'string' ? object.css : '',
|
|
40748
|
+
script: typeof nextContent.script === 'string' ? nextContent.script : typeof object.script === 'string' ? object.script : '',
|
|
40749
|
+
};
|
|
40750
|
+
this.loadingContent = nextLoadingContent ? {
|
|
40751
|
+
html: typeof nextLoadingContent.html === 'string' ? nextLoadingContent.html : '',
|
|
40752
|
+
css: typeof nextLoadingContent.css === 'string' ? nextLoadingContent.css : '',
|
|
40753
|
+
script: typeof nextLoadingContent.script === 'string' ? nextLoadingContent.script : '',
|
|
40754
|
+
} : undefined;
|
|
40755
|
+
this.isLoading = typeof object.isLoading === 'boolean' ? object.isLoading : false;
|
|
40756
|
+
this.state = object.state && typeof object.state === 'object' ? structuredClone(object.state) : {};
|
|
40757
|
+
this.title = typeof object.title === 'string' ? object.title : 'Embedded content';
|
|
40758
|
+
this.sandbox = this.normalizeSandbox(Array.isArray(object.sandbox) ? object.sandbox.filter((token) => typeof token === 'string') : undefined);
|
|
40759
|
+
this.borderRadius = (typeof object.borderRadius === 'number' || typeof object.borderRadius === 'string') ? object.borderRadius : undefined;
|
|
40760
|
+
this.boxShadow = typeof object.boxShadow === 'string' ? object.boxShadow : undefined;
|
|
40761
|
+
this.messageListener = null;
|
|
40762
|
+
return this;
|
|
40763
|
+
}
|
|
40764
|
+
copy() {
|
|
40765
|
+
const copiedObject = super.copy();
|
|
40766
|
+
copiedObject.content = { ...this.content };
|
|
40767
|
+
copiedObject.loadingContent = this.loadingContent ? { ...this.loadingContent } : undefined;
|
|
40768
|
+
copiedObject.isLoading = this.isLoading;
|
|
40769
|
+
copiedObject.state = structuredClone(this.state);
|
|
40770
|
+
copiedObject.sandbox = [...this.sandbox];
|
|
40771
|
+
copiedObject.borderRadius = this.borderRadius;
|
|
40772
|
+
copiedObject.boxShadow = this.boxShadow;
|
|
40773
|
+
copiedObject.messageListener = null;
|
|
40774
|
+
copiedObject._elementRef = null;
|
|
40775
|
+
return copiedObject;
|
|
40776
|
+
}
|
|
40777
|
+
clone() {
|
|
40778
|
+
const clonedObject = super.clone();
|
|
40779
|
+
clonedObject.content = { ...this.content };
|
|
40780
|
+
clonedObject.loadingContent = this.loadingContent ? { ...this.loadingContent } : undefined;
|
|
40781
|
+
clonedObject.isLoading = this.isLoading;
|
|
40782
|
+
clonedObject.state = structuredClone(this.state);
|
|
40783
|
+
clonedObject.sandbox = [...this.sandbox];
|
|
40784
|
+
clonedObject.borderRadius = this.borderRadius;
|
|
40785
|
+
clonedObject.boxShadow = this.boxShadow;
|
|
40786
|
+
clonedObject.messageListener = null;
|
|
40787
|
+
clonedObject.isMounted = false;
|
|
40788
|
+
clonedObject._elementRef = null;
|
|
40789
|
+
return clonedObject;
|
|
40790
|
+
}
|
|
40791
|
+
adoptTransientStateFrom(previous) {
|
|
40792
|
+
if (!(previous instanceof KritzelIframeObject)) {
|
|
40793
|
+
return;
|
|
40794
|
+
}
|
|
40795
|
+
this.isInteractive = previous.isInteractive;
|
|
40796
|
+
this.isSelected = previous.isSelected;
|
|
40797
|
+
this.isHovered = previous.isHovered;
|
|
40798
|
+
if (!previous.isMounted || !(previous.elementRef instanceof HTMLElement) || previous.elementRef.tagName !== 'IFRAME') {
|
|
40799
|
+
return;
|
|
40800
|
+
}
|
|
40801
|
+
if (previous.messageListener) {
|
|
40802
|
+
window.removeEventListener('message', previous.messageListener);
|
|
40803
|
+
}
|
|
40804
|
+
this._elementRef = previous.elementRef;
|
|
40805
|
+
this.isMounted = true;
|
|
40806
|
+
this.messageListener = event => this.handleMessage(event);
|
|
40807
|
+
window.addEventListener('message', this.messageListener);
|
|
40808
|
+
this.elementRef.style.pointerEvents = this.isInteractive ? 'auto' : 'none';
|
|
40809
|
+
previous.messageListener = null;
|
|
40810
|
+
previous.isMounted = false;
|
|
40811
|
+
previous._elementRef = null;
|
|
40812
|
+
}
|
|
40813
|
+
createLifecycleContext() {
|
|
40814
|
+
return {
|
|
40815
|
+
object: this,
|
|
40816
|
+
iframe: this.isMounted ? this.elementRef : null,
|
|
40817
|
+
state: structuredClone(this.state),
|
|
40818
|
+
};
|
|
40819
|
+
}
|
|
40820
|
+
normalizeSandbox(tokens) {
|
|
40821
|
+
const requestedTokens = tokens ?? ['allow-scripts'];
|
|
40822
|
+
const normalized = requestedTokens.filter(token => SUPPORTED_SANDBOX_TOKENS.has(token));
|
|
40823
|
+
return [...new Set(normalized.length > 0 ? normalized : ['allow-scripts'])];
|
|
40824
|
+
}
|
|
40825
|
+
createSourceDocument() {
|
|
40826
|
+
const activeContent = this.getActiveContent();
|
|
40827
|
+
const state = JSON.stringify(this.state).replace(/</g, '\\u003c');
|
|
40828
|
+
const css = activeContent.css.replace(/<\/style/gi, '<\\/style');
|
|
40829
|
+
const script = activeContent.script.replace(/<\/script/gi, '<\\/script');
|
|
40830
|
+
const computedStyle = this.isMounted ? getComputedStyle(this.elementRef) : null;
|
|
40831
|
+
const defaultCursor = computedStyle?.getPropertyValue('--kritzel-global-default-cursor').trim() || 'auto';
|
|
40832
|
+
const pointerCursor = computedStyle?.getPropertyValue('--kritzel-global-pointer-cursor').trim() || defaultCursor;
|
|
40833
|
+
return `<!doctype html>
|
|
40834
|
+
<html>
|
|
40835
|
+
<head>
|
|
40836
|
+
<meta charset="utf-8">
|
|
40837
|
+
<style>
|
|
40838
|
+
:root {
|
|
40839
|
+
--kritzel-iframe-default-cursor: ${defaultCursor};
|
|
40840
|
+
--kritzel-iframe-pointer-cursor: ${pointerCursor};
|
|
40841
|
+
}
|
|
40842
|
+
html, body { width: 100%; height: 100%; margin: 0; overflow: hidden; cursor: var(--kritzel-iframe-default-cursor); }
|
|
40843
|
+
button, button *, a, a *, input, textarea, select { cursor: var(--kritzel-iframe-pointer-cursor) !important; }
|
|
40844
|
+
${css}
|
|
40845
|
+
</style>
|
|
40846
|
+
</head>
|
|
40847
|
+
<body>
|
|
40848
|
+
${activeContent.html}
|
|
40849
|
+
<script>
|
|
40850
|
+
const kritzel = globalThis.kritzel = {
|
|
40851
|
+
state: ${state},
|
|
40852
|
+
setState(nextState) {
|
|
40853
|
+
this.state = nextState;
|
|
40854
|
+
parent.postMessage({ type: '${IFRAME_STATE_MESSAGE}', state: nextState }, '*');
|
|
40855
|
+
},
|
|
40856
|
+
};
|
|
40857
|
+
globalThis.addEventListener('message', event => {
|
|
40858
|
+
if (event.data?.type === '${IFRAME_PARENT_STATE_MESSAGE}' && event.data.state && typeof event.data.state === 'object') {
|
|
40859
|
+
kritzel.state = event.data.state;
|
|
40860
|
+
globalThis.dispatchEvent(new CustomEvent('kritzelstatechange', { detail: kritzel.state }));
|
|
40861
|
+
}
|
|
40862
|
+
});
|
|
40863
|
+
let bridgedPointerId = null;
|
|
40864
|
+
const interactiveSelector = 'button, input, textarea, select, a[href], [contenteditable="true"], [contenteditable=""]';
|
|
40865
|
+
const bridgePointerEvent = event => parent.postMessage({
|
|
40866
|
+
type: '${IFRAME_POINTER_MESSAGE}',
|
|
40867
|
+
eventType: event.type,
|
|
40868
|
+
pointerId: event.pointerId,
|
|
40869
|
+
pointerType: event.pointerType,
|
|
40870
|
+
clientX: event.clientX,
|
|
40871
|
+
clientY: event.clientY,
|
|
40872
|
+
screenX: event.screenX,
|
|
40873
|
+
screenY: event.screenY,
|
|
40874
|
+
button: event.button,
|
|
40875
|
+
buttons: event.buttons,
|
|
40876
|
+
shiftKey: event.shiftKey,
|
|
40877
|
+
ctrlKey: event.ctrlKey,
|
|
40878
|
+
altKey: event.altKey,
|
|
40879
|
+
metaKey: event.metaKey,
|
|
40880
|
+
}, '*');
|
|
40881
|
+
document.addEventListener('pointerdown', event => {
|
|
40882
|
+
if (event.target instanceof Element && event.target.closest(interactiveSelector)) return;
|
|
40883
|
+
bridgedPointerId = event.pointerId;
|
|
40884
|
+
event.preventDefault();
|
|
40885
|
+
bridgePointerEvent(event);
|
|
40886
|
+
});
|
|
40887
|
+
document.addEventListener('pointermove', event => {
|
|
40888
|
+
if (event.pointerId !== bridgedPointerId) return;
|
|
40889
|
+
event.preventDefault();
|
|
40890
|
+
bridgePointerEvent(event);
|
|
40891
|
+
});
|
|
40892
|
+
const finishPointerBridge = event => {
|
|
40893
|
+
if (event.pointerId !== bridgedPointerId) return;
|
|
40894
|
+
event.preventDefault();
|
|
40895
|
+
bridgePointerEvent(event);
|
|
40896
|
+
bridgedPointerId = null;
|
|
40897
|
+
};
|
|
40898
|
+
document.addEventListener('pointerup', finishPointerBridge);
|
|
40899
|
+
document.addEventListener('pointercancel', finishPointerBridge);
|
|
40900
|
+
document.addEventListener('contextmenu', event => {
|
|
40901
|
+
event.preventDefault();
|
|
40902
|
+
parent.postMessage({
|
|
40903
|
+
type: '${IFRAME_CONTEXT_MENU_MESSAGE}',
|
|
40904
|
+
clientX: event.clientX,
|
|
40905
|
+
clientY: event.clientY,
|
|
40906
|
+
button: event.button,
|
|
40907
|
+
shiftKey: event.shiftKey,
|
|
40908
|
+
ctrlKey: event.ctrlKey,
|
|
40909
|
+
altKey: event.altKey,
|
|
40910
|
+
metaKey: event.metaKey,
|
|
40911
|
+
}, '*');
|
|
40912
|
+
});
|
|
40913
|
+
${script}
|
|
40914
|
+
<\/script>
|
|
40915
|
+
</body>
|
|
40916
|
+
</html>`;
|
|
40917
|
+
}
|
|
40918
|
+
handleMessage(event) {
|
|
40919
|
+
if (event.source !== this.elementRef?.contentWindow || !event.data || typeof event.data !== 'object') {
|
|
40920
|
+
return;
|
|
40921
|
+
}
|
|
40922
|
+
const message = event.data;
|
|
40923
|
+
if (message.type === IFRAME_POINTER_MESSAGE) {
|
|
40924
|
+
this.dispatchPointerMessage(event.data);
|
|
40925
|
+
return;
|
|
40926
|
+
}
|
|
40927
|
+
if (message.type === IFRAME_CONTEXT_MENU_MESSAGE) {
|
|
40928
|
+
this.dispatchContextMenuMessage(event.data);
|
|
40929
|
+
return;
|
|
40930
|
+
}
|
|
40931
|
+
if (message.type !== IFRAME_STATE_MESSAGE || !message.state || typeof message.state !== 'object') {
|
|
40932
|
+
return;
|
|
40933
|
+
}
|
|
40934
|
+
this.state = structuredClone(message.state);
|
|
40935
|
+
this.persistUpdate();
|
|
40936
|
+
}
|
|
40937
|
+
dispatchPointerMessage(message) {
|
|
40938
|
+
if (!this.isMounted || !this.elementRef || !['pointerdown', 'pointermove', 'pointerup', 'pointercancel'].includes(message.eventType)) {
|
|
40939
|
+
return;
|
|
40940
|
+
}
|
|
40941
|
+
const iframeRect = this.elementRef.getBoundingClientRect();
|
|
40942
|
+
if (message.eventType === 'pointerdown') {
|
|
40943
|
+
const scaleX = this.elementRef.offsetWidth > 0 ? iframeRect.width / this.elementRef.offsetWidth : 1;
|
|
40944
|
+
const scaleY = this.elementRef.offsetHeight > 0 ? iframeRect.height / this.elementRef.offsetHeight : 1;
|
|
40945
|
+
iframePointerBridgeStarts.set(this.elementRef, {
|
|
40946
|
+
pointerId: message.pointerId,
|
|
40947
|
+
clientX: iframeRect.left + message.clientX * scaleX,
|
|
40948
|
+
clientY: iframeRect.top + message.clientY * scaleY,
|
|
40949
|
+
screenX: message.screenX,
|
|
40950
|
+
screenY: message.screenY,
|
|
40951
|
+
});
|
|
40952
|
+
}
|
|
40953
|
+
const bridgeStart = iframePointerBridgeStarts.get(this.elementRef);
|
|
40954
|
+
const hasBridgeStart = bridgeStart?.pointerId === message.pointerId;
|
|
40955
|
+
const clientX = hasBridgeStart ? bridgeStart.clientX + message.screenX - bridgeStart.screenX : iframeRect.left + message.clientX;
|
|
40956
|
+
const clientY = hasBridgeStart ? bridgeStart.clientY + message.screenY - bridgeStart.screenY : iframeRect.top + message.clientY;
|
|
40957
|
+
this.elementRef.dispatchEvent(new PointerEvent(message.eventType, {
|
|
40958
|
+
bubbles: true,
|
|
40959
|
+
composed: true,
|
|
40960
|
+
cancelable: true,
|
|
40961
|
+
pointerId: message.pointerId,
|
|
40962
|
+
pointerType: message.pointerType,
|
|
40963
|
+
clientX,
|
|
40964
|
+
clientY,
|
|
40965
|
+
screenX: message.screenX,
|
|
40966
|
+
screenY: message.screenY,
|
|
40967
|
+
button: message.button,
|
|
40968
|
+
buttons: message.buttons,
|
|
40969
|
+
shiftKey: message.shiftKey,
|
|
40970
|
+
ctrlKey: message.ctrlKey,
|
|
40971
|
+
altKey: message.altKey,
|
|
40972
|
+
metaKey: message.metaKey,
|
|
40973
|
+
}));
|
|
40974
|
+
if (message.eventType === 'pointerup' || message.eventType === 'pointercancel') {
|
|
40975
|
+
iframePointerBridgeStarts.delete(this.elementRef);
|
|
40976
|
+
}
|
|
40977
|
+
}
|
|
40978
|
+
dispatchContextMenuMessage(message) {
|
|
40979
|
+
if (!this.isMounted || !this.elementRef) {
|
|
40980
|
+
return;
|
|
40981
|
+
}
|
|
40982
|
+
const iframeRect = this.elementRef.getBoundingClientRect();
|
|
40983
|
+
// Dispatched as a MouseEvent (not PointerEvent) to mirror how browsers
|
|
40984
|
+
// natively raise 'contextmenu' for both mouse right-click and touch long-press.
|
|
40985
|
+
this.elementRef.dispatchEvent(new MouseEvent('contextmenu', {
|
|
40986
|
+
bubbles: true,
|
|
40987
|
+
composed: true,
|
|
40988
|
+
cancelable: true,
|
|
40989
|
+
clientX: iframeRect.left + message.clientX,
|
|
40990
|
+
clientY: iframeRect.top + message.clientY,
|
|
40991
|
+
button: message.button,
|
|
40992
|
+
shiftKey: message.shiftKey,
|
|
40993
|
+
ctrlKey: message.ctrlKey,
|
|
40994
|
+
altKey: message.altKey,
|
|
40995
|
+
metaKey: message.metaKey,
|
|
40996
|
+
}));
|
|
40997
|
+
}
|
|
40998
|
+
refreshDocument() {
|
|
40999
|
+
if (this.isMounted && this.elementRef) {
|
|
41000
|
+
this.elementRef.srcdoc = this.createSourceDocument();
|
|
41001
|
+
}
|
|
41002
|
+
}
|
|
41003
|
+
persistUpdate() {
|
|
41004
|
+
if (this._core?.store?.objects) {
|
|
41005
|
+
this.update();
|
|
41006
|
+
}
|
|
41007
|
+
}
|
|
41008
|
+
}
|
|
41009
|
+
|
|
40551
41010
|
/**
|
|
40552
41011
|
* Handles deserialization/revival of Kritzel objects from plain JavaScript objects.
|
|
40553
41012
|
* This class uses a pattern similar to JSON.parse reviver to reconstruct class instances
|
|
@@ -40610,6 +41069,9 @@ class KritzelReviver {
|
|
|
40610
41069
|
case 'KritzelDynamicObject':
|
|
40611
41070
|
revivedObj = KritzelDynamicObject.create(this._core).deserialize(obj);
|
|
40612
41071
|
break;
|
|
41072
|
+
case 'KritzelIframeObject':
|
|
41073
|
+
revivedObj = KritzelIframeObject.create(this._core).deserialize(obj);
|
|
41074
|
+
break;
|
|
40613
41075
|
case 'KritzelSelectionGroup':
|
|
40614
41076
|
revivedObj = KritzelSelectionGroup.create(this._core).deserialize(obj);
|
|
40615
41077
|
break;
|
|
@@ -45534,20 +45996,22 @@ const cleanupTransactions = (transactionCleanups, i) => {
|
|
|
45534
45996
|
// We need to think about the possibility that the user transforms the
|
|
45535
45997
|
// Y.Doc in the event.
|
|
45536
45998
|
if (type._dEH.l.length > 0 && (type._item === null || !type._item.deleted)) {
|
|
45537
|
-
events = events
|
|
45538
|
-
.filter(event =>
|
|
45539
|
-
event.target._item === null || !event.target._item.deleted
|
|
45540
|
-
);
|
|
45541
|
-
events
|
|
45542
|
-
.forEach(event => {
|
|
45543
|
-
event.currentTarget = type;
|
|
45544
|
-
// path is relative to the current target
|
|
45545
|
-
event._path = null;
|
|
45546
|
-
});
|
|
45547
|
-
// sort events by path length so that top-level events are fired first.
|
|
45548
|
-
events
|
|
45549
|
-
.sort((event1, event2) => event1.path.length - event2.path.length);
|
|
45550
45999
|
fs.push(() => {
|
|
46000
|
+
// The same event instance is shared by all parent types. Hence, we must set
|
|
46001
|
+
// currentTarget right before calling the handlers (see #768).
|
|
46002
|
+
events = events
|
|
46003
|
+
.filter(event =>
|
|
46004
|
+
event.target._item === null || !event.target._item.deleted
|
|
46005
|
+
);
|
|
46006
|
+
events
|
|
46007
|
+
.forEach(event => {
|
|
46008
|
+
event.currentTarget = type;
|
|
46009
|
+
// path is relative to the current target
|
|
46010
|
+
event._path = null;
|
|
46011
|
+
});
|
|
46012
|
+
// sort events by path length so that top-level events are fired first.
|
|
46013
|
+
events
|
|
46014
|
+
.sort((event1, event2) => event1.path.length - event2.path.length);
|
|
45551
46015
|
// We don't need to check for events.length
|
|
45552
46016
|
// because we know it has at least one element
|
|
45553
46017
|
callEventHandlerListeners(type._dEH, events, transaction);
|
|
@@ -45561,6 +46025,7 @@ const cleanupTransactions = (transactionCleanups, i) => {
|
|
|
45561
46025
|
}
|
|
45562
46026
|
});
|
|
45563
46027
|
});
|
|
46028
|
+
// note the nested fs calls, must not modify fs at this point
|
|
45564
46029
|
callAll(fs, []);
|
|
45565
46030
|
} finally {
|
|
45566
46031
|
// Replace deleted items with ItemDeleted / GC.
|
|
@@ -52971,9 +53436,16 @@ class KritzelStore {
|
|
|
52971
53436
|
* Gets the currently selected dynamic object whose focused descendant is an input-like element.
|
|
52972
53437
|
* @returns The interactive dynamic object with focused input-like content, or null if none matches
|
|
52973
53438
|
*/
|
|
53439
|
+
get activeInteractiveEmbeddedObject() {
|
|
53440
|
+
for (const object of this.selectedObjects) {
|
|
53441
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object) && object.hasFocusedInputElement()) {
|
|
53442
|
+
return object;
|
|
53443
|
+
}
|
|
53444
|
+
}
|
|
53445
|
+
return null;
|
|
53446
|
+
}
|
|
52974
53447
|
get activeInteractiveDynamicObject() {
|
|
52975
|
-
|
|
52976
|
-
return interactiveDynamicObject ?? null;
|
|
53448
|
+
return this.activeInteractiveEmbeddedObject;
|
|
52977
53449
|
}
|
|
52978
53450
|
/**
|
|
52979
53451
|
* Gets the path currently being drawn (not yet completed).
|
|
@@ -55073,7 +55545,7 @@ class KritzelCursorHelper {
|
|
|
55073
55545
|
* The icon is retrieved from the KritzelIconRegistry.
|
|
55074
55546
|
*/
|
|
55075
55547
|
static getCursor(options) {
|
|
55076
|
-
const iconName = options.iconName === 'default' ? '
|
|
55548
|
+
const iconName = options.iconName === 'default' ? 'mousePointer' : options.iconName;
|
|
55077
55549
|
const iconSvg = KritzelIconRegistry.get(iconName);
|
|
55078
55550
|
if (!iconSvg) {
|
|
55079
55551
|
console.warn(`Icon "${iconName}" not found in registry.`);
|
|
@@ -55082,7 +55554,7 @@ class KritzelCursorHelper {
|
|
|
55082
55554
|
const size = options.size || 24;
|
|
55083
55555
|
const rotation = options.rotation || 0;
|
|
55084
55556
|
const color = options.color || 'black';
|
|
55085
|
-
// Default cursor (
|
|
55557
|
+
// Default cursor (mousePointer) has hotspot at (4, 4), others at center
|
|
55086
55558
|
const hotspot = options.hotspot || (options.iconName === 'default' ? { x: 4, y: 4 } : { x: size / 2, y: size / 2 });
|
|
55087
55559
|
// Modify the SVG string to set size and color
|
|
55088
55560
|
// We replace width and height to match the requested size
|
|
@@ -55095,12 +55567,12 @@ class KritzelCursorHelper {
|
|
|
55095
55567
|
// We rotate around the center of the SVG canvas
|
|
55096
55568
|
const center = size / 2;
|
|
55097
55569
|
// 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>
|
|
55570
|
+
const svg = `
|
|
55571
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
|
|
55572
|
+
<g transform="rotate(${rotation} ${center} ${center})">
|
|
55573
|
+
${content}
|
|
55574
|
+
</g>
|
|
55575
|
+
</svg>
|
|
55104
55576
|
`;
|
|
55105
55577
|
// Encode the SVG for use in a data URI
|
|
55106
55578
|
// We need to be careful with encoding to ensure it works across browsers
|
|
@@ -55138,11 +55610,13 @@ class KritzelCursorManager {
|
|
|
55138
55610
|
// Reset cursor on old target
|
|
55139
55611
|
if (this._targetElement) {
|
|
55140
55612
|
this._targetElement.style.cursor = '';
|
|
55613
|
+
this._targetElement.style.removeProperty('--kritzel-global-default-cursor');
|
|
55141
55614
|
this._targetElement.style.removeProperty('--kritzel-global-pointer-cursor');
|
|
55142
55615
|
}
|
|
55143
55616
|
this._targetElement = element;
|
|
55144
55617
|
// Set the pointer cursor CSS variable for child components to use
|
|
55145
55618
|
if (this._targetElement) {
|
|
55619
|
+
this._targetElement.style.setProperty('--kritzel-global-default-cursor', KritzelCursorHelper.getCursor({ iconName: 'default' }));
|
|
55146
55620
|
this._targetElement.style.setProperty('--kritzel-global-pointer-cursor', KritzelCursorHelper.getPointerCursor());
|
|
55147
55621
|
}
|
|
55148
55622
|
}
|
|
@@ -55187,8 +55661,10 @@ class KritzelCursorManager {
|
|
|
55187
55661
|
if (!this._shadowRoot)
|
|
55188
55662
|
return;
|
|
55189
55663
|
const elementsAtPoint = this._shadowRoot.elementsFromPoint(ev.clientX, ev.clientY);
|
|
55190
|
-
if (!elementsAtPoint || elementsAtPoint.length === 0)
|
|
55664
|
+
if (!elementsAtPoint || elementsAtPoint.length === 0) {
|
|
55665
|
+
this.resetToDefault();
|
|
55191
55666
|
return;
|
|
55667
|
+
}
|
|
55192
55668
|
// Check for resize handle overlays (selection group)
|
|
55193
55669
|
const resizeHandleOverlay = elementsAtPoint.find(el => el.classList.contains('resize-handle-overlay'));
|
|
55194
55670
|
if (resizeHandleOverlay) {
|
|
@@ -55198,19 +55674,19 @@ class KritzelCursorManager {
|
|
|
55198
55674
|
const isTopLeft = resizeHandleOverlay.classList.contains('top-left');
|
|
55199
55675
|
const isBottomRight = resizeHandleOverlay.classList.contains('bottom-right');
|
|
55200
55676
|
const rotationOffset = (isTopLeft || isBottomRight) ? -45 : 45;
|
|
55201
|
-
this._core.store.state.cursor = { icon: '
|
|
55677
|
+
this._core.store.state.cursor = { icon: 'moveVertical', rotation: rotationDegrees + rotationOffset };
|
|
55202
55678
|
return;
|
|
55203
55679
|
}
|
|
55204
55680
|
// Check for rotation handle overlay
|
|
55205
55681
|
const rotationHandleOverlay = elementsAtPoint.find(el => el.classList.contains('rotation-handle-overlay'));
|
|
55206
55682
|
if (rotationHandleOverlay) {
|
|
55207
|
-
this._core.store.state.cursor = { icon: 'hand', iconActive: '
|
|
55683
|
+
this._core.store.state.cursor = { icon: 'hand', iconActive: 'handGrab' };
|
|
55208
55684
|
return;
|
|
55209
55685
|
}
|
|
55210
55686
|
// Check for line handle overlays (selection line)
|
|
55211
55687
|
const lineHandleOverlay = elementsAtPoint.find(el => el.classList.contains('selection-line-handle-overlay'));
|
|
55212
55688
|
if (lineHandleOverlay) {
|
|
55213
|
-
this._core.store.state.cursor = { icon: 'hand', iconActive: '
|
|
55689
|
+
this._core.store.state.cursor = { icon: 'hand', iconActive: 'handGrab' };
|
|
55214
55690
|
return;
|
|
55215
55691
|
}
|
|
55216
55692
|
// Reset cursor if not hovering any handle
|
|
@@ -55245,7 +55721,8 @@ class KritzelCursorManager {
|
|
|
55245
55721
|
cleanup() {
|
|
55246
55722
|
if (this._targetElement) {
|
|
55247
55723
|
this._targetElement.style.cursor = '';
|
|
55248
|
-
this._targetElement.style.removeProperty('--kritzel-
|
|
55724
|
+
this._targetElement.style.removeProperty('--kritzel-global-default-cursor');
|
|
55725
|
+
this._targetElement.style.removeProperty('--kritzel-global-pointer-cursor');
|
|
55249
55726
|
}
|
|
55250
55727
|
this._targetElement = null;
|
|
55251
55728
|
this._shadowRoot = null;
|
|
@@ -57148,7 +57625,7 @@ class KritzelCore {
|
|
|
57148
57625
|
this._store.state.translateY = viewportHeight / 2 - (viewport.centerWorldY ?? 0) * scale;
|
|
57149
57626
|
this._store.state.scale = scale;
|
|
57150
57627
|
await objectsMap.initialize(this, activeWorkspace.id, this._syncConfig);
|
|
57151
|
-
this.seedWorkspaceObjects(activeWorkspace, objectsMap);
|
|
57628
|
+
await this.seedWorkspaceObjects(activeWorkspace, objectsMap);
|
|
57152
57629
|
// Set local user in awareness after object map is initialized
|
|
57153
57630
|
if (this._user) {
|
|
57154
57631
|
objectsMap.setLocalUser(this._user);
|
|
@@ -57162,15 +57639,21 @@ class KritzelCore {
|
|
|
57162
57639
|
this.engine.emitObjectsChange();
|
|
57163
57640
|
this.rerender();
|
|
57164
57641
|
}
|
|
57165
|
-
seedWorkspaceObjects(workspace, objectsMap) {
|
|
57642
|
+
async seedWorkspaceObjects(workspace, objectsMap) {
|
|
57166
57643
|
if (!workspace.objects?.length) {
|
|
57167
57644
|
return;
|
|
57168
57645
|
}
|
|
57646
|
+
const pendingObjects = workspace.objects.filter(object => !objectsMap.findById(object.id));
|
|
57647
|
+
// Mirrors engine.addObject()/addObjects(): image asset upload is async and must
|
|
57648
|
+
// happen before the (synchronous) Yjs transaction that inserts the objects.
|
|
57649
|
+
for (const object of pendingObjects) {
|
|
57650
|
+
object._core = this;
|
|
57651
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
57652
|
+
await object.prepareForInsert();
|
|
57653
|
+
}
|
|
57654
|
+
}
|
|
57169
57655
|
objectsMap.transaction(() => {
|
|
57170
|
-
for (const object of
|
|
57171
|
-
if (objectsMap.findById(object.id)) {
|
|
57172
|
-
continue;
|
|
57173
|
-
}
|
|
57656
|
+
for (const object of pendingObjects) {
|
|
57174
57657
|
this.prepareObjectForWorkspace(object, workspace.id, this._store.currentZIndex, this._store.state.scale);
|
|
57175
57658
|
objectsMap.insert(object);
|
|
57176
57659
|
}
|
|
@@ -57209,16 +57692,30 @@ class KritzelCore {
|
|
|
57209
57692
|
* @param scaleFallback - Scale applied to objects that do not define one
|
|
57210
57693
|
* @returns The objects that were added, updated and removed
|
|
57211
57694
|
*/
|
|
57212
|
-
reconcileWorkspaceObjects(objectsMap, workspaceId, desiredObjects, nextZIndex, scaleFallback) {
|
|
57695
|
+
async reconcileWorkspaceObjects(objectsMap, workspaceId, desiredObjects, nextZIndex, scaleFallback) {
|
|
57213
57696
|
const existingObjects = objectsMap.allObjects().filter(o => !(o instanceof KritzelSelectionGroup) && !(o instanceof KritzelSelectionBox));
|
|
57214
57697
|
const existingById = new Map(existingObjects.map(object => [object.id, object]));
|
|
57215
57698
|
const desiredIds = new Set();
|
|
57216
57699
|
const diff = { added: [], updated: [], removed: [] };
|
|
57700
|
+
// Assign IDs up front so the insert-vs-update lookup below is stable, and so the
|
|
57701
|
+
// async image-prepare pass and the (synchronous) transaction agree on identity.
|
|
57702
|
+
for (const object of desiredObjects) {
|
|
57703
|
+
if (!object.id) {
|
|
57704
|
+
object.id = object.generateId();
|
|
57705
|
+
}
|
|
57706
|
+
}
|
|
57707
|
+
// Mirrors engine.addObject()/addObjects(): image asset upload is async and must
|
|
57708
|
+
// happen before the (synchronous) Yjs transaction that inserts the objects.
|
|
57709
|
+
for (const object of desiredObjects) {
|
|
57710
|
+
const existingObject = existingById.get(object.id);
|
|
57711
|
+
const isNewOrReplaced = !existingObject || existingObject !== object;
|
|
57712
|
+
if (isNewOrReplaced && KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
57713
|
+
object._core = this;
|
|
57714
|
+
await object.prepareForInsert();
|
|
57715
|
+
}
|
|
57716
|
+
}
|
|
57217
57717
|
objectsMap.transaction(() => {
|
|
57218
57718
|
for (const object of desiredObjects) {
|
|
57219
|
-
if (!object.id) {
|
|
57220
|
-
object.id = object.generateId();
|
|
57221
|
-
}
|
|
57222
57719
|
desiredIds.add(object.id);
|
|
57223
57720
|
const existingObject = existingById.get(object.id);
|
|
57224
57721
|
if (!existingObject) {
|
|
@@ -57256,7 +57753,7 @@ class KritzelCore {
|
|
|
57256
57753
|
* object set stays exactly what the caller declared.
|
|
57257
57754
|
*/
|
|
57258
57755
|
detachObject(object) {
|
|
57259
|
-
if (
|
|
57756
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
57260
57757
|
object.unmount();
|
|
57261
57758
|
}
|
|
57262
57759
|
object.isMounted = false;
|
|
@@ -57432,13 +57929,13 @@ class KritzelCore {
|
|
|
57432
57929
|
activeWorkspace.viewport = { centerWorldX, centerWorldY, scale };
|
|
57433
57930
|
}
|
|
57434
57931
|
}
|
|
57435
|
-
applyObjectsToActiveWorkspace(workspace, desiredObjects) {
|
|
57932
|
+
async applyObjectsToActiveWorkspace(workspace, desiredObjects) {
|
|
57436
57933
|
const objectsMap = this._store.objects;
|
|
57437
57934
|
if (!objectsMap) {
|
|
57438
57935
|
return null;
|
|
57439
57936
|
}
|
|
57440
57937
|
this.clearSelection();
|
|
57441
|
-
const diff = this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this._store.currentZIndex, this._store.state.scale);
|
|
57938
|
+
const diff = await this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this._store.currentZIndex, this._store.state.scale);
|
|
57442
57939
|
this._anchorManager.rebuildIndex();
|
|
57443
57940
|
this.rerender();
|
|
57444
57941
|
return diff;
|
|
@@ -57457,7 +57954,7 @@ class KritzelCore {
|
|
|
57457
57954
|
try {
|
|
57458
57955
|
await objectsMap.initialize(this, workspace.id, this._syncConfig, { headless: true, workspaceName: workspace.name });
|
|
57459
57956
|
await objectsMap.whenNetworkSynced();
|
|
57460
|
-
return this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this.nextZIndexOf(objectsMap), this._store.state.scale);
|
|
57957
|
+
return await this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this.nextZIndexOf(objectsMap), this._store.state.scale);
|
|
57461
57958
|
}
|
|
57462
57959
|
finally {
|
|
57463
57960
|
objectsMap.destroy();
|
|
@@ -57543,8 +58040,7 @@ class KritzelCore {
|
|
|
57543
58040
|
this.removeObject(child);
|
|
57544
58041
|
});
|
|
57545
58042
|
}
|
|
57546
|
-
|
|
57547
|
-
if (KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject')) {
|
|
58043
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
57548
58044
|
object.unmount();
|
|
57549
58045
|
}
|
|
57550
58046
|
// Handle anchor cleanup
|
|
@@ -57590,14 +58086,8 @@ class KritzelCore {
|
|
|
57590
58086
|
this.removeLocalSelectionGroups();
|
|
57591
58087
|
this.removeSelectionBox();
|
|
57592
58088
|
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
|
-
}
|
|
58089
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
58090
|
+
object.setIsInteractive(true);
|
|
57601
58091
|
}
|
|
57602
58092
|
}
|
|
57603
58093
|
this._store.objects.insert(selectionGroup);
|
|
@@ -57618,14 +58108,8 @@ class KritzelCore {
|
|
|
57618
58108
|
teardownSelectionGroup(selectionGroup) {
|
|
57619
58109
|
selectionGroup.deselectAllChildren?.();
|
|
57620
58110
|
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
|
-
}
|
|
58111
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
58112
|
+
object.setIsInteractive(false);
|
|
57629
58113
|
}
|
|
57630
58114
|
}
|
|
57631
58115
|
}
|
|
@@ -59071,13 +59555,7 @@ class KritzelWheelHelper {
|
|
|
59071
59555
|
return this.canElementConsumeWheel(scrollContainer, ev.deltaX, ev.deltaY);
|
|
59072
59556
|
}
|
|
59073
59557
|
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
|
-
}
|
|
59558
|
+
const potentialRoots = dynamicObject.getEmbeddedContentRoots();
|
|
59081
59559
|
const legacyElementRef = dynamicObject.elmeentRef;
|
|
59082
59560
|
if (legacyElementRef instanceof HTMLElement) {
|
|
59083
59561
|
potentialRoots.push(legacyElementRef);
|
|
@@ -59254,8 +59732,8 @@ class KritzelSvgExportHelper {
|
|
|
59254
59732
|
.join('\n ');
|
|
59255
59733
|
const xmlDecl = includeXmlDeclaration ? '<?xml version="1.0" encoding="UTF-8"?>\n' : '';
|
|
59256
59734
|
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}
|
|
59735
|
+
return `${xmlDecl}<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}" width="${viewBoxWidth}" height="${viewBoxHeight}">${defsContent}
|
|
59736
|
+
${elements}
|
|
59259
59737
|
</svg>`;
|
|
59260
59738
|
}
|
|
59261
59739
|
/**
|
|
@@ -59407,8 +59885,8 @@ class KritzelSvgExportHelper {
|
|
|
59407
59885
|
const orient = end === 'start' ? 'auto-start-reverse' : 'auto';
|
|
59408
59886
|
const refX = 0;
|
|
59409
59887
|
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})"/>
|
|
59888
|
+
return `<marker id="${markerId}" markerWidth="${size}" markerHeight="${size}" refX="${refX}" refY="${refY}" orient="${orient}" markerUnits="userSpaceOnUse">
|
|
59889
|
+
<path d="${path}" fill="${fill}" transform="scale(${size / 10})"/>
|
|
59412
59890
|
</marker>`;
|
|
59413
59891
|
}
|
|
59414
59892
|
/**
|
|
@@ -59437,6 +59915,9 @@ class KritzelSvgExportHelper {
|
|
|
59437
59915
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject')) {
|
|
59438
59916
|
return this.dynamicObjectToSvg(object, rasterSafeForCanvas);
|
|
59439
59917
|
}
|
|
59918
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelIframeObject')) {
|
|
59919
|
+
return this.iframeObjectToSvg(object);
|
|
59920
|
+
}
|
|
59440
59921
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
59441
59922
|
return this.groupToSvg(object, theme, imageDataUrls, rasterSafeForCanvas);
|
|
59442
59923
|
}
|
|
@@ -59455,10 +59936,10 @@ class KritzelSvgExportHelper {
|
|
|
59455
59936
|
const opacity = path.opacity !== 1 ? ` opacity="${path.opacity}"` : '';
|
|
59456
59937
|
const scale = this.getObjectScale(path);
|
|
59457
59938
|
// 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>
|
|
59939
|
+
return `<g transform="${transform}"${opacity}>
|
|
59940
|
+
<svg viewBox="${path.viewBox}" width="${path.totalWidth / scale}" height="${path.totalHeight / scale}" overflow="visible">
|
|
59941
|
+
<path d="${path.d}" fill="${fill || 'none'}" stroke="${stroke || 'none'}"${path.strokeWidth ? ` stroke-width="${path.strokeWidth}"` : ''}/>
|
|
59942
|
+
</svg>
|
|
59462
59943
|
</g>`;
|
|
59463
59944
|
}
|
|
59464
59945
|
/**
|
|
@@ -59474,10 +59955,10 @@ class KritzelSvgExportHelper {
|
|
|
59474
59955
|
const scale = this.getObjectScale(line);
|
|
59475
59956
|
const markerStart = line.hasStartArrow ? ` marker-start="url(#${line.startMarkerId})"` : '';
|
|
59476
59957
|
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>
|
|
59958
|
+
return `<g transform="${transform}"${opacity}>
|
|
59959
|
+
<svg viewBox="${line.viewBox}" width="${line.totalWidth / scale}" height="${line.totalHeight / scale}" overflow="visible">
|
|
59960
|
+
<path d="${line.d}" fill="none" stroke="${stroke}" stroke-width="${line.strokeWidth}" stroke-linecap="round"${markerStart}${markerEnd}/>
|
|
59961
|
+
</svg>
|
|
59481
59962
|
</g>`;
|
|
59482
59963
|
}
|
|
59483
59964
|
/**
|
|
@@ -59501,18 +59982,18 @@ class KritzelSvgExportHelper {
|
|
|
59501
59982
|
const textHtml = this.prosemirrorToHtml(shape.content, shape, theme);
|
|
59502
59983
|
if (textHtml) {
|
|
59503
59984
|
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>
|
|
59985
|
+
textContent = `
|
|
59986
|
+
<foreignObject x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}">
|
|
59987
|
+
<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;">
|
|
59988
|
+
${textHtml}
|
|
59989
|
+
</div>
|
|
59509
59990
|
</foreignObject>`;
|
|
59510
59991
|
}
|
|
59511
59992
|
}
|
|
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>
|
|
59993
|
+
return `<g transform="${transform}"${opacity}>
|
|
59994
|
+
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth / scale}" height="${shape.totalHeight / scale}" overflow="visible" preserveAspectRatio="none">
|
|
59995
|
+
<path d="${pathD}" fill="${fill || 'transparent'}" stroke="${stroke}" stroke-width="${shape.strokeWidth}"/>${textContent}
|
|
59996
|
+
</svg>
|
|
59516
59997
|
</g>`;
|
|
59517
59998
|
}
|
|
59518
59999
|
/**
|
|
@@ -59543,10 +60024,10 @@ class KritzelSvgExportHelper {
|
|
|
59543
60024
|
// adjusted font-size already accounts for it – keeping both would double-scale
|
|
59544
60025
|
// the content and overflow the foreignObject.
|
|
59545
60026
|
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>
|
|
60027
|
+
return `<g transform="${transform}"${opacity}>
|
|
60028
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
|
|
60029
|
+
<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>
|
|
60030
|
+
</foreignObject>
|
|
59550
60031
|
</g>`;
|
|
59551
60032
|
}
|
|
59552
60033
|
/**
|
|
@@ -59580,9 +60061,9 @@ class KritzelSvgExportHelper {
|
|
|
59580
60061
|
return `<tspan x="0" y="${y}" xml:space="preserve">${this.escapeHtml(line)}</tspan>`;
|
|
59581
60062
|
})
|
|
59582
60063
|
.join('');
|
|
59583
|
-
return `<g transform="${transform}"${opacity}>
|
|
59584
|
-
${bgRect}
|
|
59585
|
-
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
60064
|
+
return `<g transform="${transform}"${opacity}>
|
|
60065
|
+
${bgRect}
|
|
60066
|
+
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
59586
60067
|
</g>`;
|
|
59587
60068
|
}
|
|
59588
60069
|
/**
|
|
@@ -59610,8 +60091,8 @@ class KritzelSvgExportHelper {
|
|
|
59610
60091
|
const width = image.totalWidth / scale;
|
|
59611
60092
|
const height = image.totalHeight / scale;
|
|
59612
60093
|
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"/>
|
|
60094
|
+
return `<g transform="${transform}"${opacity}>
|
|
60095
|
+
<image href="${href}" x="0" y="0" width="${width}" height="${height}" preserveAspectRatio="xMidYMid meet"/>
|
|
59615
60096
|
</g>`;
|
|
59616
60097
|
}
|
|
59617
60098
|
/**
|
|
@@ -59631,19 +60112,30 @@ class KritzelSvgExportHelper {
|
|
|
59631
60112
|
if (rasterSafeForCanvas) {
|
|
59632
60113
|
// PNG export: render placeholder rect (foreignObject doesn't rasterize to PNG well)
|
|
59633
60114
|
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>
|
|
60115
|
+
return `<g transform="${transform}"${opacity}>
|
|
60116
|
+
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
60117
|
+
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Dynamic Object]</text>
|
|
59637
60118
|
</g>`;
|
|
59638
60119
|
}
|
|
59639
60120
|
// SVG export: use foreignObject to embed HTML
|
|
59640
60121
|
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>
|
|
60122
|
+
return `<g transform="${transform}"${opacity}>
|
|
60123
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
60124
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;overflow:hidden;">
|
|
60125
|
+
${html}
|
|
60126
|
+
</div>
|
|
60127
|
+
</foreignObject>
|
|
60128
|
+
</g>`;
|
|
60129
|
+
}
|
|
60130
|
+
static iframeObjectToSvg(object) {
|
|
60131
|
+
const transform = this.buildTransform(object);
|
|
60132
|
+
const opacity = object.opacity !== 1 ? ` opacity="${object.opacity}"` : '';
|
|
60133
|
+
const scale = this.getObjectScale(object);
|
|
60134
|
+
const width = object.totalWidth / scale;
|
|
60135
|
+
const height = object.totalHeight / scale;
|
|
60136
|
+
return `<g transform="${transform}"${opacity}>
|
|
60137
|
+
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
60138
|
+
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Iframe]</text>
|
|
59647
60139
|
</g>`;
|
|
59648
60140
|
}
|
|
59649
60141
|
/**
|
|
@@ -59663,8 +60155,8 @@ class KritzelSvgExportHelper {
|
|
|
59663
60155
|
return '';
|
|
59664
60156
|
}
|
|
59665
60157
|
const opacity = group.opacity !== 1 ? ` opacity="${group.opacity}"` : '';
|
|
59666
|
-
return `<g${opacity}>
|
|
59667
|
-
${children}
|
|
60158
|
+
return `<g${opacity}>
|
|
60159
|
+
${children}
|
|
59668
60160
|
</g>`;
|
|
59669
60161
|
}
|
|
59670
60162
|
/**
|
|
@@ -59849,12 +60341,26 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
59849
60341
|
/** Authoritative workspace catalog for this engine instance. When provided, provider-only workspaces are hidden but not deleted. */
|
|
59850
60342
|
workspaces;
|
|
59851
60343
|
async onWorkspacesPropChange() {
|
|
59852
|
-
|
|
60344
|
+
this._workspacesRevision++;
|
|
60345
|
+
if (!this._isYjsInitialized || this._syncInitPromise) {
|
|
59853
60346
|
return;
|
|
59854
60347
|
}
|
|
59855
|
-
|
|
59856
|
-
|
|
59857
|
-
|
|
60348
|
+
const previousReconciliation = this._workspacePropReconciliationPromise;
|
|
60349
|
+
const reconciliationPromise = (async () => {
|
|
60350
|
+
await previousReconciliation;
|
|
60351
|
+
await this.reconcileProvidedWorkspaces();
|
|
60352
|
+
await this.ensureActiveWorkspaceIsVisible();
|
|
60353
|
+
this.workspacesChange.emit(this.getVisibleWorkspaces());
|
|
60354
|
+
})();
|
|
60355
|
+
this._workspacePropReconciliationPromise = reconciliationPromise;
|
|
60356
|
+
try {
|
|
60357
|
+
await reconciliationPromise;
|
|
60358
|
+
}
|
|
60359
|
+
finally {
|
|
60360
|
+
if (this._workspacePropReconciliationPromise === reconciliationPromise) {
|
|
60361
|
+
this._workspacePropReconciliationPromise = null;
|
|
60362
|
+
}
|
|
60363
|
+
}
|
|
59858
60364
|
}
|
|
59859
60365
|
/** Optional unique identifier for namespacing storage keys across multiple editor instances. */
|
|
59860
60366
|
editorId;
|
|
@@ -59908,6 +60414,12 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
59908
60414
|
onUserChange(newValue) {
|
|
59909
60415
|
this.core.setUser(newValue);
|
|
59910
60416
|
}
|
|
60417
|
+
/** Tool definitions to register with this engine instance. */
|
|
60418
|
+
tools = [];
|
|
60419
|
+
onToolsChange() {
|
|
60420
|
+
this._toolsRevision++;
|
|
60421
|
+
void this.registerConfiguredTools();
|
|
60422
|
+
}
|
|
59911
60423
|
/** Context menu items shown when right-clicking the canvas background. */
|
|
59912
60424
|
globalContextMenuItems;
|
|
59913
60425
|
onGlobalContextMenuItemsChange(newValue) {
|
|
@@ -60098,7 +60610,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
60098
60610
|
}
|
|
60099
60611
|
const hoveredObject = this.core.getObjectFromPointerEvent(ev);
|
|
60100
60612
|
if (hoveredObject &&
|
|
60101
|
-
ObjectHelper.
|
|
60613
|
+
ObjectHelper.isKritzelEmbeddedObject(hoveredObject) &&
|
|
60102
60614
|
KritzelWheelHelper.shouldKeepWheelInDynamicObject(ev, hoveredObject)) {
|
|
60103
60615
|
return;
|
|
60104
60616
|
}
|
|
@@ -60200,7 +60712,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
60200
60712
|
return false;
|
|
60201
60713
|
}
|
|
60202
60714
|
const object = this.core.store.objects.findById(objectElement.id);
|
|
60203
|
-
if (!object || !
|
|
60715
|
+
if (!object || !ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
60204
60716
|
return false;
|
|
60205
60717
|
}
|
|
60206
60718
|
const isSelected = !!this.core.store.selectionGroup?.objects?.some(selectedObject => selectedObject.id === object.id);
|
|
@@ -60210,13 +60722,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
60210
60722
|
if (object.isInteractive !== true) {
|
|
60211
60723
|
return false;
|
|
60212
60724
|
}
|
|
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
|
-
}
|
|
60725
|
+
const potentialRoots = object.getEmbeddedContentRoots();
|
|
60220
60726
|
if (potentialRoots.length === 0) {
|
|
60221
60727
|
return false;
|
|
60222
60728
|
}
|
|
@@ -60390,7 +60896,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
60390
60896
|
* Switches the active drawing tool by its registered name.
|
|
60391
60897
|
* @param toolName - The name the tool was registered with (e.g., 'brush', 'eraser').
|
|
60392
60898
|
*/
|
|
60393
|
-
async
|
|
60899
|
+
async setActiveTool(toolName) {
|
|
60394
60900
|
const tool = this.core.toolRegistry.getTool(toolName);
|
|
60395
60901
|
if (!tool) {
|
|
60396
60902
|
console.warn(`[KritzelEngine] No tool registered with name: ${toolName}`);
|
|
@@ -61696,9 +62202,13 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
61696
62202
|
_stateChangeListenersRegistered = false;
|
|
61697
62203
|
_workspaceInitializationPromise = null;
|
|
61698
62204
|
_workspaceInitializationTargetKey = null;
|
|
62205
|
+
_workspacePropReconciliationPromise = null;
|
|
61699
62206
|
_syncInitPromise = null;
|
|
62207
|
+
_toolsInitPromise = null;
|
|
62208
|
+
_toolsRevision = 0;
|
|
61700
62209
|
_syncConfigRevision = 0;
|
|
61701
62210
|
_assetStorageConfigRevision = 0;
|
|
62211
|
+
_workspacesRevision = 0;
|
|
61702
62212
|
_hasLoggedUnlicensedWelcomeBanner = false;
|
|
61703
62213
|
_previousVisibleDynamicObjects = new Set();
|
|
61704
62214
|
_revealedImageKeys = new Set();
|
|
@@ -61711,6 +62221,37 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
61711
62221
|
undoStackSize: 0,
|
|
61712
62222
|
redoStackSize: 0,
|
|
61713
62223
|
};
|
|
62224
|
+
/** Returns a tool registered in this engine instance. */
|
|
62225
|
+
async getTool(toolName) {
|
|
62226
|
+
await this.registerConfiguredTools();
|
|
62227
|
+
return this.core.toolRegistry.getTool(toolName);
|
|
62228
|
+
}
|
|
62229
|
+
async registerConfiguredTools() {
|
|
62230
|
+
if (this._toolsInitPromise) {
|
|
62231
|
+
return this._toolsInitPromise;
|
|
62232
|
+
}
|
|
62233
|
+
this._toolsInitPromise = (async () => {
|
|
62234
|
+
do {
|
|
62235
|
+
const revision = this._toolsRevision;
|
|
62236
|
+
for (const definition of this.tools) {
|
|
62237
|
+
let toolClass = definition.tool;
|
|
62238
|
+
if (typeof toolClass !== 'function') {
|
|
62239
|
+
toolClass = toolClass.constructor;
|
|
62240
|
+
}
|
|
62241
|
+
await this.registerTool(definition.name, toolClass, definition.config);
|
|
62242
|
+
}
|
|
62243
|
+
if (revision === this._toolsRevision) {
|
|
62244
|
+
break;
|
|
62245
|
+
}
|
|
62246
|
+
} while (true);
|
|
62247
|
+
})();
|
|
62248
|
+
try {
|
|
62249
|
+
await this._toolsInitPromise;
|
|
62250
|
+
}
|
|
62251
|
+
finally {
|
|
62252
|
+
this._toolsInitPromise = null;
|
|
62253
|
+
}
|
|
62254
|
+
}
|
|
61714
62255
|
setLoadingState(isLoading) {
|
|
61715
62256
|
if (this.core.store.state.isLoading === isLoading) {
|
|
61716
62257
|
return;
|
|
@@ -61842,6 +62383,8 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
61842
62383
|
this.core.licenseManager.destroy();
|
|
61843
62384
|
}
|
|
61844
62385
|
componentWillLoad() {
|
|
62386
|
+
this._toolsRevision++;
|
|
62387
|
+
void this.registerConfiguredTools();
|
|
61845
62388
|
this.core.setEditorId(this.editorId);
|
|
61846
62389
|
if (this.themes && this.themes.length > 0) {
|
|
61847
62390
|
this.core.themeManager.registerThemes(this.themes);
|
|
@@ -61881,7 +62424,9 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
61881
62424
|
const editorElement = this.host.closest('kritzel-editor');
|
|
61882
62425
|
this.core.themeManager.setTargetElement(editorElement || this.host);
|
|
61883
62426
|
// Initialize sync config and Yjs
|
|
62427
|
+
await this.registerConfiguredTools();
|
|
61884
62428
|
await this.initializeSyncAndWorkspace();
|
|
62429
|
+
await this.waitForWorkspaceAndSceneReady();
|
|
61885
62430
|
if (this.core.store.state.isReady === false) {
|
|
61886
62431
|
this.core.store.state.isReady = true;
|
|
61887
62432
|
this.logUnlicensedWelcomeBanner();
|
|
@@ -61903,6 +62448,20 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
61903
62448
|
this._syncInitPromise = null;
|
|
61904
62449
|
}
|
|
61905
62450
|
}
|
|
62451
|
+
async waitForSceneRender() {
|
|
62452
|
+
await new Promise(resolve => {
|
|
62453
|
+
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
62454
|
+
});
|
|
62455
|
+
}
|
|
62456
|
+
async waitForWorkspaceAndSceneReady() {
|
|
62457
|
+
let observedRevision;
|
|
62458
|
+
do {
|
|
62459
|
+
observedRevision = this._workspacesRevision;
|
|
62460
|
+
await this._workspacePropReconciliationPromise;
|
|
62461
|
+
await this.waitForSceneRender();
|
|
62462
|
+
} while (observedRevision !== this._workspacesRevision ||
|
|
62463
|
+
this._workspacePropReconciliationPromise);
|
|
62464
|
+
}
|
|
61906
62465
|
/**
|
|
61907
62466
|
* Initializes the asset storage layer with the latest config. Mirrors
|
|
61908
62467
|
* the in-flight replay logic of {@link doInitializeSyncAndWorkspace} for
|
|
@@ -62285,7 +62844,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62285
62844
|
if (!KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup')) {
|
|
62286
62845
|
return 'auto';
|
|
62287
62846
|
}
|
|
62288
|
-
if (object.objects.length === 1 &&
|
|
62847
|
+
if (object.objects.length === 1 && ObjectHelper.isKritzelEmbeddedObject(object.objects[0])) {
|
|
62289
62848
|
return 'none';
|
|
62290
62849
|
}
|
|
62291
62850
|
return 'auto';
|
|
@@ -62293,7 +62852,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62293
62852
|
// Track visible dynamic objects and unmount culled ones
|
|
62294
62853
|
const currentVisibleDynamicObjects = new Set();
|
|
62295
62854
|
visibleObjects.forEach(object => {
|
|
62296
|
-
if (
|
|
62855
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
62297
62856
|
currentVisibleDynamicObjects.add(object.id);
|
|
62298
62857
|
}
|
|
62299
62858
|
});
|
|
@@ -62301,7 +62860,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62301
62860
|
this._previousVisibleDynamicObjects.forEach(id => {
|
|
62302
62861
|
if (!currentVisibleDynamicObjects.has(id)) {
|
|
62303
62862
|
const object = this.core.store.objects.findById(id);
|
|
62304
|
-
if (object &&
|
|
62863
|
+
if (object && ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
62305
62864
|
object.unmount();
|
|
62306
62865
|
}
|
|
62307
62866
|
}
|
|
@@ -62394,7 +62953,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62394
62953
|
display: 'flex',
|
|
62395
62954
|
alignItems: 'center',
|
|
62396
62955
|
justifyContent: 'center',
|
|
62397
|
-
} }, h("kritzel-icon", { name: object.loadState === 'error' ? '
|
|
62956
|
+
} }, h("kritzel-icon", { name: object.loadState === 'error' ? 'imageOff' : 'image', size: Math.max(16, Math.min(object.totalWidth, object.totalHeight) * 0.3), style: {
|
|
62398
62957
|
color: KritzelColorHelper.resolveThemeColor({ light: '#9ca3af', dark: '#6b7280' }, currentTheme),
|
|
62399
62958
|
} }))), KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject') && (h("div", { ref: el => el && object.mount(el), style: {
|
|
62400
62959
|
position: 'absolute',
|
|
@@ -62413,7 +62972,37 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62413
62972
|
padding: object.padding + 'px',
|
|
62414
62973
|
overflow: 'visible',
|
|
62415
62974
|
display: 'block',
|
|
62416
|
-
} })), KritzelClassHelper.isInstanceOf(object, '
|
|
62975
|
+
} })), KritzelClassHelper.isInstanceOf(object, 'KritzelIframeObject') && (h("div", { style: {
|
|
62976
|
+
position: 'absolute',
|
|
62977
|
+
left: '0',
|
|
62978
|
+
top: '0',
|
|
62979
|
+
width: object.totalWidth + 'px',
|
|
62980
|
+
height: object.totalHeight + 'px',
|
|
62981
|
+
transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
|
|
62982
|
+
transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
|
|
62983
|
+
opacity: effectiveOpacityString,
|
|
62984
|
+
backgroundColor: KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
|
|
62985
|
+
borderColor: KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
|
|
62986
|
+
borderWidth: object.borderWidth + 'px',
|
|
62987
|
+
borderStyle: 'solid',
|
|
62988
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
62989
|
+
boxShadow: object.boxShadow,
|
|
62990
|
+
overflow: 'hidden',
|
|
62991
|
+
display: 'block',
|
|
62992
|
+
pointerEvents: object.markedForRemoval ? 'none' : 'auto',
|
|
62993
|
+
} }, h("iframe", { ref: element => element && object.mount(element), title: object.title, sandbox: object.sandboxAttribute, style: {
|
|
62994
|
+
display: 'block',
|
|
62995
|
+
width: '100%',
|
|
62996
|
+
height: '100%',
|
|
62997
|
+
border: '0',
|
|
62998
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
62999
|
+
pointerEvents: object.isInteractive ? 'auto' : 'none',
|
|
63000
|
+
} }), h("div", { style: {
|
|
63001
|
+
position: 'absolute',
|
|
63002
|
+
inset: '0',
|
|
63003
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
63004
|
+
pointerEvents: object.isInteractive ? 'none' : 'auto',
|
|
63005
|
+
} }))), KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') && !this.core.displaySelectionLineUI(object) && (h("div", { ref: el => el && object.mount(el), style: {
|
|
62417
63006
|
position: 'absolute',
|
|
62418
63007
|
left: '0',
|
|
62419
63008
|
top: '0',
|
|
@@ -62771,6 +63360,9 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62771
63360
|
"user": [{
|
|
62772
63361
|
"onUserChange": 0
|
|
62773
63362
|
}],
|
|
63363
|
+
"tools": [{
|
|
63364
|
+
"onToolsChange": 0
|
|
63365
|
+
}],
|
|
62774
63366
|
"globalContextMenuItems": [{
|
|
62775
63367
|
"onGlobalContextMenuItemsChange": 0
|
|
62776
63368
|
}],
|
|
@@ -62831,6 +63423,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62831
63423
|
"syncConfig": [16],
|
|
62832
63424
|
"assetStorageConfig": [16],
|
|
62833
63425
|
"user": [16],
|
|
63426
|
+
"tools": [16],
|
|
62834
63427
|
"globalContextMenuItems": [16],
|
|
62835
63428
|
"objectContextMenuItems": [16],
|
|
62836
63429
|
"scaleMax": [1026, "scale-max"],
|
|
@@ -62855,7 +63448,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62855
63448
|
"beginSceneBootstrap": [64],
|
|
62856
63449
|
"endSceneBootstrap": [64],
|
|
62857
63450
|
"registerTool": [64],
|
|
62858
|
-
"
|
|
63451
|
+
"setActiveTool": [64],
|
|
62859
63452
|
"disable": [64],
|
|
62860
63453
|
"enable": [64],
|
|
62861
63454
|
"delete": [64],
|
|
@@ -62931,7 +63524,8 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62931
63524
|
"getAvailableLocales": [64],
|
|
62932
63525
|
"getAvailableLocaleOptions": [64],
|
|
62933
63526
|
"t": [64],
|
|
62934
|
-
"getResolvedTerms": [64]
|
|
63527
|
+
"getResolvedTerms": [64],
|
|
63528
|
+
"getTool": [64]
|
|
62935
63529
|
}, [[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
63530
|
"workspaces": [{
|
|
62937
63531
|
"onWorkspacesPropChange": 0
|
|
@@ -62948,6 +63542,9 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
|
|
|
62948
63542
|
"user": [{
|
|
62949
63543
|
"onUserChange": 0
|
|
62950
63544
|
}],
|
|
63545
|
+
"tools": [{
|
|
63546
|
+
"onToolsChange": 0
|
|
63547
|
+
}],
|
|
62951
63548
|
"globalContextMenuItems": [{
|
|
62952
63549
|
"onGlobalContextMenuItemsChange": 0
|
|
62953
63550
|
}],
|