@kritzel/engine 0.4.31 → 0.4.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +49 -49
- package/dist/cjs/{engine.constants-CakmdKMW.js → engine.constants-VyFrUl1W.js} +627 -129
- package/dist/cjs/{index-BbbWU2aN.js → index-BP5Iy6FQ.js} +27 -9
- package/dist/cjs/index.cjs.js +4 -2
- package/dist/cjs/kritzel-awareness-cursors_5.cjs.entry.js +257 -113
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/stencil.cjs.js +3 -3
- package/dist/collection/classes/core/core.class.js +40 -32
- package/dist/collection/classes/core/reviver.class.js +4 -0
- package/dist/collection/classes/core/store.class.js +10 -3
- package/dist/collection/classes/managers/cursor.manager.js +10 -5
- package/dist/collection/classes/objects/dynamic-object.class.js +18 -5
- package/dist/collection/classes/objects/iframe.class.js +447 -0
- package/dist/collection/classes/registries/icon-registry.class.js +100 -67
- package/dist/collection/classes/tools/selection-tool.class.js +3 -3
- package/dist/collection/collection-manifest.json +4 -2
- package/dist/collection/components/kritzel-awareness-cursors/kritzel-awareness-cursors.css +115 -115
- package/dist/collection/components/kritzel-awareness-cursors/kritzel-awareness-cursors.js +1 -1
- package/dist/collection/components/kritzel-cursor-trail/kritzel-cursor-trail.css +10 -10
- package/dist/collection/components/kritzel-cursor-trail/kritzel-cursor-trail.js +1 -1
- package/dist/collection/components/kritzel-engine/kritzel-engine.css +80 -80
- package/dist/collection/components/kritzel-engine/kritzel-engine.js +196 -44
- package/dist/collection/components/kritzel-icon/kritzel-icon.css +18 -18
- package/dist/collection/components/kritzel-icon/kritzel-icon.js +25 -4
- package/dist/collection/components/kritzel-watermark/kritzel-watermark.css +29 -29
- package/dist/collection/components/kritzel-watermark/kritzel-watermark.js +2 -2
- package/dist/collection/constants/version.js +1 -1
- package/dist/collection/helpers/cursor.helper.js +8 -8
- package/dist/collection/helpers/object.helper.js +13 -0
- package/dist/collection/helpers/svg-export.helper.js +55 -41
- package/dist/collection/helpers/wheel.helper.js +1 -7
- package/dist/collection/index.js +3 -0
- package/dist/collection/interfaces/embedded-object.interface.js +1 -0
- package/dist/collection/themes/dark-theme.js +1 -5
- package/dist/collection/themes/light-theme.js +1 -6
- package/dist/components/index.js +7 -7
- package/dist/components/kritzel-awareness-cursors.js +1 -1
- package/dist/components/kritzel-cursor-trail.js +1 -1
- package/dist/components/kritzel-engine.js +755 -161
- package/dist/components/kritzel-icon.js +1 -1
- package/dist/components/kritzel-watermark.js +1 -1
- package/dist/components/{p-B2Htv9ou.js → p-BHVbfJrf.js} +3 -3
- package/dist/components/{p-YP8wAcF4.js → p-BTU9qcSW.js} +2 -2
- package/dist/components/{p-CfSx6HU_.js → p-BWfRbEIq.js} +16 -4
- package/dist/components/p-NAEiq8CK.js +214 -0
- package/dist/components/{p-BvRGQvVI.js → p-k0LxV9Bg.js} +18 -14
- package/dist/esm/{engine.constants-Bl5-pbq-.js → engine.constants-BHTr2qPx.js} +626 -130
- package/dist/esm/{index-BU9Mv7y0.js → index-C8PnHbLt.js} +27 -10
- package/dist/esm/index.js +3 -3
- package/dist/esm/kritzel-awareness-cursors_5.entry.js +257 -113
- package/dist/esm/loader.js +3 -3
- package/dist/esm/stencil.js +4 -4
- package/dist/stencil/index.esm.js +3 -3
- package/dist/stencil/{p-f0a8b7af.entry.js → p-40097a38.entry.js} +257 -113
- package/dist/stencil/{p-Bl5-pbq-.js → p-BHTr2qPx.js} +626 -130
- package/dist/stencil/{p-BU9Mv7y0.js → p-C8PnHbLt.js} +27 -10
- package/dist/stencil/stencil.esm.js +4 -4
- package/dist/types/classes/core/store.class.d.ts +3 -2
- package/dist/types/classes/objects/dynamic-object.class.d.ts +4 -2
- package/dist/types/classes/objects/iframe.class.d.ts +76 -0
- package/dist/types/classes/registries/icon-registry.class.d.ts +75 -6
- package/dist/types/components/kritzel-engine/kritzel-engine.d.ts +14 -1
- package/dist/types/components/kritzel-icon/kritzel-icon.d.ts +5 -1
- package/dist/types/components.d.ts +26 -8
- package/dist/types/constants/version.d.ts +1 -1
- package/dist/types/helpers/cursor.helper.d.ts +2 -1
- package/dist/types/helpers/object.helper.d.ts +2 -0
- package/dist/types/helpers/svg-export.helper.d.ts +1 -0
- package/dist/types/helpers/wheel.helper.d.ts +2 -2
- package/dist/types/index.d.ts +3 -0
- package/dist/types/interfaces/context-menu-item.interface.d.ts +2 -1
- package/dist/types/interfaces/dynamic-object-renderer.interface.d.ts +7 -0
- package/dist/types/interfaces/embedded-object.interface.d.ts +9 -0
- package/dist/types/interfaces/engine-state.interface.d.ts +3 -2
- package/dist/types/interfaces/login-config.interface.d.ts +2 -1
- package/dist/types/interfaces/master-detail.interface.d.ts +2 -1
- package/dist/types/interfaces/menu-item.interface.d.ts +2 -1
- package/dist/types/interfaces/theme.interface.d.ts +6 -7
- package/dist/types/interfaces/tool.interface.d.ts +9 -0
- package/dist/types/interfaces/toolbar-item.interface.d.ts +3 -2
- package/dist/types/stencil-public-runtime.d.ts +61 -55
- package/package.json +3 -1
- package/readme.md +10 -10
- package/dist/components/p-fx6msYHJ.js +0 -167
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { r as registerInstance, h, H as Host, g as getElement, c as createEvent } from './p-
|
|
2
|
-
import { e as KritzelPath, g as KritzelLine,
|
|
1
|
+
import { r as registerInstance, h, H as Host, g as getElement, c as createEvent, f as forceUpdate } from './p-C8PnHbLt.js';
|
|
2
|
+
import { e as KritzelPath, g as KritzelLine, a7 as KritzelMouseButton, m as KritzelSelectionBox, a8 as KritzelBaseHandler, l as KritzelSelectionGroup, t as KritzelShapeTool, p as KritzelLineTool, s as KritzelTextTool, z as KritzelSelectionTool, r as KritzelImageTool, q as KritzelEraserTool, o as KritzelBrushTool, C as KritzelWorkspace, h as KritzelGroup, k as KritzelIframeObject, j as KritzelDynamicObject, f as KritzelImage, i as KritzelShape, d as KritzelText, Y as KritzelAlignment, P as DEFAULT_SYNC_CONFIG, Z as runMigrations, a1 as CURRENT_WORKSPACE_SCHEMA_VERSION, $ as WORKSPACE_MIGRATIONS, O as ObjectHelper, a0 as CURRENT_APP_STATE_SCHEMA_VERSION, _ as APP_STATE_MIGRATIONS, u as KritzelCursorHelper, w as KritzelDevicesHelper, a9 as KritzelClassHelper, aa as KritzelImageFileHelper, ab as imageCompression, E as KritzelAnchorManager, F as KritzelThemeManager, G as KritzelLocalizationManager, H as KritzelLicenseManager, B as KritzelAssetResolver, x as KritzelColorHelper, a4 as ABSOLUTE_SCALE_MAX, a5 as ABSOLUTE_SCALE_MIN, ac as KritzelEventHelper, W as WORKSPACE_EXPORT_VERSION, a3 as resolveTextToolAvailableFonts, n as KritzelBaseTool, v as KritzelKeyboardHelper, M as KritzelIconRegistry, a6 as KRITZEL_WEBSITE_URL } from './p-BHTr2qPx.js';
|
|
3
3
|
import * as Y from 'yjs';
|
|
4
4
|
|
|
5
5
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
6
6
|
|
|
7
|
-
const kritzelAwarenessCursorsCss = () => `:host{display:block;position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:1}.awareness-cursor{position:absolute;top:0;left:0;transition:transform var(--kritzel-awareness-cursor-transition-duration, 100ms) ease-out,
|
|
7
|
+
const kritzelAwarenessCursorsCss = () => `:host{display:block;position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:1}.awareness-cursor{position:absolute;top:0;left:0;transition:transform var(--kritzel-awareness-cursor-transition-duration, 100ms) ease-out, opacity 300ms ease;will-change:transform}.awareness-cursor.stale{opacity:0}.awareness-cursor.tracking-object{transition-duration:0ms}.cursor-arrow{filter:drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3))}.cursor-label{position:absolute;left:16px;top:16px;white-space:nowrap;font-family:var(--kritzel-awareness-font-family, var(--kritzel-global-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif));font-size:var(--kritzel-awareness-cursor-label-font-size, 12px);color:var(--kritzel-awareness-cursor-label-text-color, #ffffff);padding:2px 8px;border-radius:4px;line-height:1.4;font-weight:500;pointer-events:none;user-select:none}.edge-indicator{position:absolute;top:-12px;left:-12px;width:24px;height:24px;display:flex;align-items:center;justify-content:center;transition:transform var(--kritzel-awareness-cursor-transition-duration, 100ms) ease-out, opacity 300ms ease;will-change:transform;pointer-events:auto;user-select:none;cursor:pointer}.edge-indicator.stale{opacity:0}.edge-indicator.tracking-object{transition-duration:0ms}.edge-arrow{position:absolute;filter:drop-shadow(0 1px 3px rgba(0, 0, 0, 0.3));transition:opacity 300ms ease}.edge-arrow.stale{opacity:0}.edge-label{position:absolute;white-space:nowrap;font-family:var(--kritzel-awareness-font-family, var(--kritzel-global-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif));font-size:var(--kritzel-awareness-cursor-label-font-size, 12px);color:var(--kritzel-awareness-cursor-label-text-color, #ffffff);padding:2px 8px;border-radius:4px;line-height:1.4;font-weight:500;pointer-events:none;opacity:0;transform-origin:center;transition:opacity 150ms ease}.edge-indicator:hover .edge-label{opacity:1}.remote-selection-box{position:absolute;top:0;left:0;border-width:2px;border-style:solid;pointer-events:none;will-change:transform, width, height;transition:transform var(--kritzel-awareness-cursor-transition-duration, 100ms) ease-out, width var(--kritzel-awareness-cursor-transition-duration, 100ms) ease-out, height var(--kritzel-awareness-cursor-transition-duration, 100ms) ease-out}`;
|
|
8
8
|
|
|
9
9
|
const STALE_THRESHOLD_MS = 10_000;
|
|
10
10
|
const REMOVE_THRESHOLD_MS = 30_000;
|
|
@@ -209,7 +209,7 @@ const KritzelAwarenessCursors = class {
|
|
|
209
209
|
}
|
|
210
210
|
render() {
|
|
211
211
|
const cursors = Array.from(this.remoteCursors.values());
|
|
212
|
-
return (h(Host, { key: '
|
|
212
|
+
return (h(Host, { key: '2021875ea3e430c04da438dc5b7a2c22f119ea67' }, cursors.map(remoteCursor => {
|
|
213
213
|
if (!remoteCursor.cursor)
|
|
214
214
|
return null;
|
|
215
215
|
// When a remote user is actively drawing, derive cursor position from
|
|
@@ -361,7 +361,7 @@ const KritzelCursorTrail = class {
|
|
|
361
361
|
}
|
|
362
362
|
}
|
|
363
363
|
render() {
|
|
364
|
-
return (h(Host, { key: '
|
|
364
|
+
return (h(Host, { key: '39d026a0d4c444564f146a90ea1a51181d0652b7' }, this.cursorTrailPoints.length > 1 && (h("svg", { key: '927e52cd0828a548ba58e0e783b1d148a40c968c', class: "cursor-trail-svg", xmlns: "http://www.w3.org/2000/svg", style: {
|
|
365
365
|
position: 'absolute',
|
|
366
366
|
left: '0',
|
|
367
367
|
top: '0',
|
|
@@ -18829,6 +18829,9 @@ class KritzelReviver {
|
|
|
18829
18829
|
case 'KritzelDynamicObject':
|
|
18830
18830
|
revivedObj = KritzelDynamicObject.create(this._core).deserialize(obj);
|
|
18831
18831
|
break;
|
|
18832
|
+
case 'KritzelIframeObject':
|
|
18833
|
+
revivedObj = KritzelIframeObject.create(this._core).deserialize(obj);
|
|
18834
|
+
break;
|
|
18832
18835
|
case 'KritzelSelectionGroup':
|
|
18833
18836
|
revivedObj = KritzelSelectionGroup.create(this._core).deserialize(obj);
|
|
18834
18837
|
break;
|
|
@@ -20653,9 +20656,16 @@ class KritzelStore {
|
|
|
20653
20656
|
* Gets the currently selected dynamic object whose focused descendant is an input-like element.
|
|
20654
20657
|
* @returns The interactive dynamic object with focused input-like content, or null if none matches
|
|
20655
20658
|
*/
|
|
20659
|
+
get activeInteractiveEmbeddedObject() {
|
|
20660
|
+
for (const object of this.selectedObjects) {
|
|
20661
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object) && object.hasFocusedInputElement()) {
|
|
20662
|
+
return object;
|
|
20663
|
+
}
|
|
20664
|
+
}
|
|
20665
|
+
return null;
|
|
20666
|
+
}
|
|
20656
20667
|
get activeInteractiveDynamicObject() {
|
|
20657
|
-
|
|
20658
|
-
return interactiveDynamicObject ?? null;
|
|
20668
|
+
return this.activeInteractiveEmbeddedObject;
|
|
20659
20669
|
}
|
|
20660
20670
|
/**
|
|
20661
20671
|
* Gets the path currently being drawn (not yet completed).
|
|
@@ -21243,11 +21253,13 @@ class KritzelCursorManager {
|
|
|
21243
21253
|
// Reset cursor on old target
|
|
21244
21254
|
if (this._targetElement) {
|
|
21245
21255
|
this._targetElement.style.cursor = '';
|
|
21256
|
+
this._targetElement.style.removeProperty('--kritzel-global-default-cursor');
|
|
21246
21257
|
this._targetElement.style.removeProperty('--kritzel-global-pointer-cursor');
|
|
21247
21258
|
}
|
|
21248
21259
|
this._targetElement = element;
|
|
21249
21260
|
// Set the pointer cursor CSS variable for child components to use
|
|
21250
21261
|
if (this._targetElement) {
|
|
21262
|
+
this._targetElement.style.setProperty('--kritzel-global-default-cursor', KritzelCursorHelper.getCursor({ iconName: 'default' }));
|
|
21251
21263
|
this._targetElement.style.setProperty('--kritzel-global-pointer-cursor', KritzelCursorHelper.getPointerCursor());
|
|
21252
21264
|
}
|
|
21253
21265
|
}
|
|
@@ -21292,8 +21304,10 @@ class KritzelCursorManager {
|
|
|
21292
21304
|
if (!this._shadowRoot)
|
|
21293
21305
|
return;
|
|
21294
21306
|
const elementsAtPoint = this._shadowRoot.elementsFromPoint(ev.clientX, ev.clientY);
|
|
21295
|
-
if (!elementsAtPoint || elementsAtPoint.length === 0)
|
|
21307
|
+
if (!elementsAtPoint || elementsAtPoint.length === 0) {
|
|
21308
|
+
this.resetToDefault();
|
|
21296
21309
|
return;
|
|
21310
|
+
}
|
|
21297
21311
|
// Check for resize handle overlays (selection group)
|
|
21298
21312
|
const resizeHandleOverlay = elementsAtPoint.find(el => el.classList.contains('resize-handle-overlay'));
|
|
21299
21313
|
if (resizeHandleOverlay) {
|
|
@@ -21303,19 +21317,19 @@ class KritzelCursorManager {
|
|
|
21303
21317
|
const isTopLeft = resizeHandleOverlay.classList.contains('top-left');
|
|
21304
21318
|
const isBottomRight = resizeHandleOverlay.classList.contains('bottom-right');
|
|
21305
21319
|
const rotationOffset = (isTopLeft || isBottomRight) ? -45 : 45;
|
|
21306
|
-
this._core.store.state.cursor = { icon: '
|
|
21320
|
+
this._core.store.state.cursor = { icon: 'moveVertical', rotation: rotationDegrees + rotationOffset };
|
|
21307
21321
|
return;
|
|
21308
21322
|
}
|
|
21309
21323
|
// Check for rotation handle overlay
|
|
21310
21324
|
const rotationHandleOverlay = elementsAtPoint.find(el => el.classList.contains('rotation-handle-overlay'));
|
|
21311
21325
|
if (rotationHandleOverlay) {
|
|
21312
|
-
this._core.store.state.cursor = { icon: 'hand', iconActive: '
|
|
21326
|
+
this._core.store.state.cursor = { icon: 'hand', iconActive: 'handGrab' };
|
|
21313
21327
|
return;
|
|
21314
21328
|
}
|
|
21315
21329
|
// Check for line handle overlays (selection line)
|
|
21316
21330
|
const lineHandleOverlay = elementsAtPoint.find(el => el.classList.contains('selection-line-handle-overlay'));
|
|
21317
21331
|
if (lineHandleOverlay) {
|
|
21318
|
-
this._core.store.state.cursor = { icon: 'hand', iconActive: '
|
|
21332
|
+
this._core.store.state.cursor = { icon: 'hand', iconActive: 'handGrab' };
|
|
21319
21333
|
return;
|
|
21320
21334
|
}
|
|
21321
21335
|
// Reset cursor if not hovering any handle
|
|
@@ -21350,7 +21364,8 @@ class KritzelCursorManager {
|
|
|
21350
21364
|
cleanup() {
|
|
21351
21365
|
if (this._targetElement) {
|
|
21352
21366
|
this._targetElement.style.cursor = '';
|
|
21353
|
-
this._targetElement.style.removeProperty('--kritzel-
|
|
21367
|
+
this._targetElement.style.removeProperty('--kritzel-global-default-cursor');
|
|
21368
|
+
this._targetElement.style.removeProperty('--kritzel-global-pointer-cursor');
|
|
21354
21369
|
}
|
|
21355
21370
|
this._targetElement = null;
|
|
21356
21371
|
this._shadowRoot = null;
|
|
@@ -22275,7 +22290,7 @@ class KritzelCore {
|
|
|
22275
22290
|
this._store.state.translateY = viewportHeight / 2 - (viewport.centerWorldY ?? 0) * scale;
|
|
22276
22291
|
this._store.state.scale = scale;
|
|
22277
22292
|
await objectsMap.initialize(this, activeWorkspace.id, this._syncConfig);
|
|
22278
|
-
this.seedWorkspaceObjects(activeWorkspace, objectsMap);
|
|
22293
|
+
await this.seedWorkspaceObjects(activeWorkspace, objectsMap);
|
|
22279
22294
|
// Set local user in awareness after object map is initialized
|
|
22280
22295
|
if (this._user) {
|
|
22281
22296
|
objectsMap.setLocalUser(this._user);
|
|
@@ -22289,15 +22304,21 @@ class KritzelCore {
|
|
|
22289
22304
|
this.engine.emitObjectsChange();
|
|
22290
22305
|
this.rerender();
|
|
22291
22306
|
}
|
|
22292
|
-
seedWorkspaceObjects(workspace, objectsMap) {
|
|
22307
|
+
async seedWorkspaceObjects(workspace, objectsMap) {
|
|
22293
22308
|
if (!workspace.objects?.length) {
|
|
22294
22309
|
return;
|
|
22295
22310
|
}
|
|
22311
|
+
const pendingObjects = workspace.objects.filter(object => !objectsMap.findById(object.id));
|
|
22312
|
+
// Mirrors engine.addObject()/addObjects(): image asset upload is async and must
|
|
22313
|
+
// happen before the (synchronous) Yjs transaction that inserts the objects.
|
|
22314
|
+
for (const object of pendingObjects) {
|
|
22315
|
+
object._core = this;
|
|
22316
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
22317
|
+
await object.prepareForInsert();
|
|
22318
|
+
}
|
|
22319
|
+
}
|
|
22296
22320
|
objectsMap.transaction(() => {
|
|
22297
|
-
for (const object of
|
|
22298
|
-
if (objectsMap.findById(object.id)) {
|
|
22299
|
-
continue;
|
|
22300
|
-
}
|
|
22321
|
+
for (const object of pendingObjects) {
|
|
22301
22322
|
this.prepareObjectForWorkspace(object, workspace.id, this._store.currentZIndex, this._store.state.scale);
|
|
22302
22323
|
objectsMap.insert(object);
|
|
22303
22324
|
}
|
|
@@ -22336,16 +22357,30 @@ class KritzelCore {
|
|
|
22336
22357
|
* @param scaleFallback - Scale applied to objects that do not define one
|
|
22337
22358
|
* @returns The objects that were added, updated and removed
|
|
22338
22359
|
*/
|
|
22339
|
-
reconcileWorkspaceObjects(objectsMap, workspaceId, desiredObjects, nextZIndex, scaleFallback) {
|
|
22360
|
+
async reconcileWorkspaceObjects(objectsMap, workspaceId, desiredObjects, nextZIndex, scaleFallback) {
|
|
22340
22361
|
const existingObjects = objectsMap.allObjects().filter(o => !(o instanceof KritzelSelectionGroup) && !(o instanceof KritzelSelectionBox));
|
|
22341
22362
|
const existingById = new Map(existingObjects.map(object => [object.id, object]));
|
|
22342
22363
|
const desiredIds = new Set();
|
|
22343
22364
|
const diff = { added: [], updated: [], removed: [] };
|
|
22365
|
+
// Assign IDs up front so the insert-vs-update lookup below is stable, and so the
|
|
22366
|
+
// async image-prepare pass and the (synchronous) transaction agree on identity.
|
|
22367
|
+
for (const object of desiredObjects) {
|
|
22368
|
+
if (!object.id) {
|
|
22369
|
+
object.id = object.generateId();
|
|
22370
|
+
}
|
|
22371
|
+
}
|
|
22372
|
+
// Mirrors engine.addObject()/addObjects(): image asset upload is async and must
|
|
22373
|
+
// happen before the (synchronous) Yjs transaction that inserts the objects.
|
|
22374
|
+
for (const object of desiredObjects) {
|
|
22375
|
+
const existingObject = existingById.get(object.id);
|
|
22376
|
+
const isNewOrReplaced = !existingObject || existingObject !== object;
|
|
22377
|
+
if (isNewOrReplaced && KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
22378
|
+
object._core = this;
|
|
22379
|
+
await object.prepareForInsert();
|
|
22380
|
+
}
|
|
22381
|
+
}
|
|
22344
22382
|
objectsMap.transaction(() => {
|
|
22345
22383
|
for (const object of desiredObjects) {
|
|
22346
|
-
if (!object.id) {
|
|
22347
|
-
object.id = object.generateId();
|
|
22348
|
-
}
|
|
22349
22384
|
desiredIds.add(object.id);
|
|
22350
22385
|
const existingObject = existingById.get(object.id);
|
|
22351
22386
|
if (!existingObject) {
|
|
@@ -22383,7 +22418,7 @@ class KritzelCore {
|
|
|
22383
22418
|
* object set stays exactly what the caller declared.
|
|
22384
22419
|
*/
|
|
22385
22420
|
detachObject(object) {
|
|
22386
|
-
if (
|
|
22421
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
22387
22422
|
object.unmount();
|
|
22388
22423
|
}
|
|
22389
22424
|
object.isMounted = false;
|
|
@@ -22559,13 +22594,13 @@ class KritzelCore {
|
|
|
22559
22594
|
activeWorkspace.viewport = { centerWorldX, centerWorldY, scale };
|
|
22560
22595
|
}
|
|
22561
22596
|
}
|
|
22562
|
-
applyObjectsToActiveWorkspace(workspace, desiredObjects) {
|
|
22597
|
+
async applyObjectsToActiveWorkspace(workspace, desiredObjects) {
|
|
22563
22598
|
const objectsMap = this._store.objects;
|
|
22564
22599
|
if (!objectsMap) {
|
|
22565
22600
|
return null;
|
|
22566
22601
|
}
|
|
22567
22602
|
this.clearSelection();
|
|
22568
|
-
const diff = this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this._store.currentZIndex, this._store.state.scale);
|
|
22603
|
+
const diff = await this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this._store.currentZIndex, this._store.state.scale);
|
|
22569
22604
|
this._anchorManager.rebuildIndex();
|
|
22570
22605
|
this.rerender();
|
|
22571
22606
|
return diff;
|
|
@@ -22584,7 +22619,7 @@ class KritzelCore {
|
|
|
22584
22619
|
try {
|
|
22585
22620
|
await objectsMap.initialize(this, workspace.id, this._syncConfig, { headless: true, workspaceName: workspace.name });
|
|
22586
22621
|
await objectsMap.whenNetworkSynced();
|
|
22587
|
-
return this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this.nextZIndexOf(objectsMap), this._store.state.scale);
|
|
22622
|
+
return await this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this.nextZIndexOf(objectsMap), this._store.state.scale);
|
|
22588
22623
|
}
|
|
22589
22624
|
finally {
|
|
22590
22625
|
objectsMap.destroy();
|
|
@@ -22670,8 +22705,7 @@ class KritzelCore {
|
|
|
22670
22705
|
this.removeObject(child);
|
|
22671
22706
|
});
|
|
22672
22707
|
}
|
|
22673
|
-
|
|
22674
|
-
if (KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject')) {
|
|
22708
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
22675
22709
|
object.unmount();
|
|
22676
22710
|
}
|
|
22677
22711
|
// Handle anchor cleanup
|
|
@@ -22717,14 +22751,8 @@ class KritzelCore {
|
|
|
22717
22751
|
this.removeLocalSelectionGroups();
|
|
22718
22752
|
this.removeSelectionBox();
|
|
22719
22753
|
for (const object of selectionGroup.objects ?? []) {
|
|
22720
|
-
if (
|
|
22721
|
-
|
|
22722
|
-
if (typeof dynamicObject.setIsInteractive === 'function') {
|
|
22723
|
-
dynamicObject.setIsInteractive(true);
|
|
22724
|
-
}
|
|
22725
|
-
else {
|
|
22726
|
-
dynamicObject.isInteractive = true;
|
|
22727
|
-
}
|
|
22754
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
22755
|
+
object.setIsInteractive(true);
|
|
22728
22756
|
}
|
|
22729
22757
|
}
|
|
22730
22758
|
this._store.objects.insert(selectionGroup);
|
|
@@ -22745,14 +22773,8 @@ class KritzelCore {
|
|
|
22745
22773
|
teardownSelectionGroup(selectionGroup) {
|
|
22746
22774
|
selectionGroup.deselectAllChildren?.();
|
|
22747
22775
|
for (const object of selectionGroup.objects ?? []) {
|
|
22748
|
-
if (
|
|
22749
|
-
|
|
22750
|
-
if (typeof dynamicObject.setIsInteractive === 'function') {
|
|
22751
|
-
dynamicObject.setIsInteractive(false);
|
|
22752
|
-
}
|
|
22753
|
-
else {
|
|
22754
|
-
dynamicObject.isInteractive = false;
|
|
22755
|
-
}
|
|
22776
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
22777
|
+
object.setIsInteractive(false);
|
|
22756
22778
|
}
|
|
22757
22779
|
}
|
|
22758
22780
|
}
|
|
@@ -24198,13 +24220,7 @@ class KritzelWheelHelper {
|
|
|
24198
24220
|
return this.canElementConsumeWheel(scrollContainer, ev.deltaX, ev.deltaY);
|
|
24199
24221
|
}
|
|
24200
24222
|
static getScrollableContainerFromEventPath(path, dynamicObject) {
|
|
24201
|
-
const potentialRoots =
|
|
24202
|
-
if (dynamicObject.element instanceof HTMLElement) {
|
|
24203
|
-
potentialRoots.push(dynamicObject.element);
|
|
24204
|
-
}
|
|
24205
|
-
if (dynamicObject.elementRef instanceof HTMLElement) {
|
|
24206
|
-
potentialRoots.push(dynamicObject.elementRef);
|
|
24207
|
-
}
|
|
24223
|
+
const potentialRoots = dynamicObject.getEmbeddedContentRoots();
|
|
24208
24224
|
const legacyElementRef = dynamicObject.elmeentRef;
|
|
24209
24225
|
if (legacyElementRef instanceof HTMLElement) {
|
|
24210
24226
|
potentialRoots.push(legacyElementRef);
|
|
@@ -24362,8 +24378,8 @@ class KritzelSvgExportHelper {
|
|
|
24362
24378
|
.join('\n ');
|
|
24363
24379
|
const xmlDecl = includeXmlDeclaration ? '<?xml version="1.0" encoding="UTF-8"?>\n' : '';
|
|
24364
24380
|
const defsContent = defs.length > 0 ? `\n <defs>\n ${defs.join('\n ')}\n </defs>` : '';
|
|
24365
|
-
return `${xmlDecl}<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}" width="${viewBoxWidth}" height="${viewBoxHeight}">${defsContent}
|
|
24366
|
-
${elements}
|
|
24381
|
+
return `${xmlDecl}<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}" width="${viewBoxWidth}" height="${viewBoxHeight}">${defsContent}
|
|
24382
|
+
${elements}
|
|
24367
24383
|
</svg>`;
|
|
24368
24384
|
}
|
|
24369
24385
|
/**
|
|
@@ -24515,8 +24531,8 @@ class KritzelSvgExportHelper {
|
|
|
24515
24531
|
const orient = end === 'start' ? 'auto-start-reverse' : 'auto';
|
|
24516
24532
|
const refX = 0;
|
|
24517
24533
|
const refY = size / 2;
|
|
24518
|
-
return `<marker id="${markerId}" markerWidth="${size}" markerHeight="${size}" refX="${refX}" refY="${refY}" orient="${orient}" markerUnits="userSpaceOnUse">
|
|
24519
|
-
<path d="${path}" fill="${fill}" transform="scale(${size / 10})"/>
|
|
24534
|
+
return `<marker id="${markerId}" markerWidth="${size}" markerHeight="${size}" refX="${refX}" refY="${refY}" orient="${orient}" markerUnits="userSpaceOnUse">
|
|
24535
|
+
<path d="${path}" fill="${fill}" transform="scale(${size / 10})"/>
|
|
24520
24536
|
</marker>`;
|
|
24521
24537
|
}
|
|
24522
24538
|
/**
|
|
@@ -24545,6 +24561,9 @@ class KritzelSvgExportHelper {
|
|
|
24545
24561
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject')) {
|
|
24546
24562
|
return this.dynamicObjectToSvg(object, rasterSafeForCanvas);
|
|
24547
24563
|
}
|
|
24564
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelIframeObject')) {
|
|
24565
|
+
return this.iframeObjectToSvg(object);
|
|
24566
|
+
}
|
|
24548
24567
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
24549
24568
|
return this.groupToSvg(object, theme, imageDataUrls, rasterSafeForCanvas);
|
|
24550
24569
|
}
|
|
@@ -24563,10 +24582,10 @@ class KritzelSvgExportHelper {
|
|
|
24563
24582
|
const opacity = path.opacity !== 1 ? ` opacity="${path.opacity}"` : '';
|
|
24564
24583
|
const scale = this.getObjectScale(path);
|
|
24565
24584
|
// Path needs to be wrapped in a g with translation since path.d uses local coordinates
|
|
24566
|
-
return `<g transform="${transform}"${opacity}>
|
|
24567
|
-
<svg viewBox="${path.viewBox}" width="${path.totalWidth / scale}" height="${path.totalHeight / scale}" overflow="visible">
|
|
24568
|
-
<path d="${path.d}" fill="${fill || 'none'}" stroke="${stroke || 'none'}"${path.strokeWidth ? ` stroke-width="${path.strokeWidth}"` : ''}/>
|
|
24569
|
-
</svg>
|
|
24585
|
+
return `<g transform="${transform}"${opacity}>
|
|
24586
|
+
<svg viewBox="${path.viewBox}" width="${path.totalWidth / scale}" height="${path.totalHeight / scale}" overflow="visible">
|
|
24587
|
+
<path d="${path.d}" fill="${fill || 'none'}" stroke="${stroke || 'none'}"${path.strokeWidth ? ` stroke-width="${path.strokeWidth}"` : ''}/>
|
|
24588
|
+
</svg>
|
|
24570
24589
|
</g>`;
|
|
24571
24590
|
}
|
|
24572
24591
|
/**
|
|
@@ -24582,10 +24601,10 @@ class KritzelSvgExportHelper {
|
|
|
24582
24601
|
const scale = this.getObjectScale(line);
|
|
24583
24602
|
const markerStart = line.hasStartArrow ? ` marker-start="url(#${line.startMarkerId})"` : '';
|
|
24584
24603
|
const markerEnd = line.hasEndArrow ? ` marker-end="url(#${line.endMarkerId})"` : '';
|
|
24585
|
-
return `<g transform="${transform}"${opacity}>
|
|
24586
|
-
<svg viewBox="${line.viewBox}" width="${line.totalWidth / scale}" height="${line.totalHeight / scale}" overflow="visible">
|
|
24587
|
-
<path d="${line.d}" fill="none" stroke="${stroke}" stroke-width="${line.strokeWidth}" stroke-linecap="round"${markerStart}${markerEnd}/>
|
|
24588
|
-
</svg>
|
|
24604
|
+
return `<g transform="${transform}"${opacity}>
|
|
24605
|
+
<svg viewBox="${line.viewBox}" width="${line.totalWidth / scale}" height="${line.totalHeight / scale}" overflow="visible">
|
|
24606
|
+
<path d="${line.d}" fill="none" stroke="${stroke}" stroke-width="${line.strokeWidth}" stroke-linecap="round"${markerStart}${markerEnd}/>
|
|
24607
|
+
</svg>
|
|
24589
24608
|
</g>`;
|
|
24590
24609
|
}
|
|
24591
24610
|
/**
|
|
@@ -24609,18 +24628,18 @@ class KritzelSvgExportHelper {
|
|
|
24609
24628
|
const textHtml = this.prosemirrorToHtml(shape.content, shape, theme);
|
|
24610
24629
|
if (textHtml) {
|
|
24611
24630
|
const fontColor = KritzelColorHelper.resolveThemeColor(shape.fontColor, theme);
|
|
24612
|
-
textContent = `
|
|
24613
|
-
<foreignObject x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}">
|
|
24614
|
-
<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;">
|
|
24615
|
-
${textHtml}
|
|
24616
|
-
</div>
|
|
24631
|
+
textContent = `
|
|
24632
|
+
<foreignObject x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}">
|
|
24633
|
+
<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;">
|
|
24634
|
+
${textHtml}
|
|
24635
|
+
</div>
|
|
24617
24636
|
</foreignObject>`;
|
|
24618
24637
|
}
|
|
24619
24638
|
}
|
|
24620
|
-
return `<g transform="${transform}"${opacity}>
|
|
24621
|
-
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth / scale}" height="${shape.totalHeight / scale}" overflow="visible" preserveAspectRatio="none">
|
|
24622
|
-
<path d="${pathD}" fill="${fill || 'transparent'}" stroke="${stroke}" stroke-width="${shape.strokeWidth}"/>${textContent}
|
|
24623
|
-
</svg>
|
|
24639
|
+
return `<g transform="${transform}"${opacity}>
|
|
24640
|
+
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth / scale}" height="${shape.totalHeight / scale}" overflow="visible" preserveAspectRatio="none">
|
|
24641
|
+
<path d="${pathD}" fill="${fill || 'transparent'}" stroke="${stroke}" stroke-width="${shape.strokeWidth}"/>${textContent}
|
|
24642
|
+
</svg>
|
|
24624
24643
|
</g>`;
|
|
24625
24644
|
}
|
|
24626
24645
|
/**
|
|
@@ -24651,10 +24670,10 @@ class KritzelSvgExportHelper {
|
|
|
24651
24670
|
// adjusted font-size already accounts for it – keeping both would double-scale
|
|
24652
24671
|
// the content and overflow the foreignObject.
|
|
24653
24672
|
const svgFontSizePx = (text.fontSize * (4 / 3) * (text.scaleFactor || 1) / scale).toFixed(4);
|
|
24654
|
-
return `<g transform="${transform}"${opacity}>
|
|
24655
|
-
<foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
|
|
24656
|
-
<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>
|
|
24657
|
-
</foreignObject>
|
|
24673
|
+
return `<g transform="${transform}"${opacity}>
|
|
24674
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
|
|
24675
|
+
<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>
|
|
24676
|
+
</foreignObject>
|
|
24658
24677
|
</g>`;
|
|
24659
24678
|
}
|
|
24660
24679
|
/**
|
|
@@ -24688,9 +24707,9 @@ class KritzelSvgExportHelper {
|
|
|
24688
24707
|
return `<tspan x="0" y="${y}" xml:space="preserve">${this.escapeHtml(line)}</tspan>`;
|
|
24689
24708
|
})
|
|
24690
24709
|
.join('');
|
|
24691
|
-
return `<g transform="${transform}"${opacity}>
|
|
24692
|
-
${bgRect}
|
|
24693
|
-
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
24710
|
+
return `<g transform="${transform}"${opacity}>
|
|
24711
|
+
${bgRect}
|
|
24712
|
+
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
24694
24713
|
</g>`;
|
|
24695
24714
|
}
|
|
24696
24715
|
/**
|
|
@@ -24718,8 +24737,8 @@ class KritzelSvgExportHelper {
|
|
|
24718
24737
|
const width = image.totalWidth / scale;
|
|
24719
24738
|
const height = image.totalHeight / scale;
|
|
24720
24739
|
const href = imageDataUrls?.get(image.id) || image.resolvedSrc || image.src || '';
|
|
24721
|
-
return `<g transform="${transform}"${opacity}>
|
|
24722
|
-
<image href="${href}" x="0" y="0" width="${width}" height="${height}" preserveAspectRatio="xMidYMid meet"/>
|
|
24740
|
+
return `<g transform="${transform}"${opacity}>
|
|
24741
|
+
<image href="${href}" x="0" y="0" width="${width}" height="${height}" preserveAspectRatio="xMidYMid meet"/>
|
|
24723
24742
|
</g>`;
|
|
24724
24743
|
}
|
|
24725
24744
|
/**
|
|
@@ -24739,19 +24758,30 @@ class KritzelSvgExportHelper {
|
|
|
24739
24758
|
if (rasterSafeForCanvas) {
|
|
24740
24759
|
// PNG export: render placeholder rect (foreignObject doesn't rasterize to PNG well)
|
|
24741
24760
|
console.warn('[KritzelDynamicObject SVG Export] Dynamic objects do not serialize well to PNG. Use SVG export or screenshot instead.');
|
|
24742
|
-
return `<g transform="${transform}"${opacity}>
|
|
24743
|
-
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
24744
|
-
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Dynamic Object]</text>
|
|
24761
|
+
return `<g transform="${transform}"${opacity}>
|
|
24762
|
+
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
24763
|
+
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Dynamic Object]</text>
|
|
24745
24764
|
</g>`;
|
|
24746
24765
|
}
|
|
24747
24766
|
// SVG export: use foreignObject to embed HTML
|
|
24748
24767
|
const html = obj.element?.outerHTML || '<div style="border:1px dashed #ccc">Empty</div>';
|
|
24749
|
-
return `<g transform="${transform}"${opacity}>
|
|
24750
|
-
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
24751
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;overflow:hidden;">
|
|
24752
|
-
${html}
|
|
24753
|
-
</div>
|
|
24754
|
-
</foreignObject>
|
|
24768
|
+
return `<g transform="${transform}"${opacity}>
|
|
24769
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
24770
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;overflow:hidden;">
|
|
24771
|
+
${html}
|
|
24772
|
+
</div>
|
|
24773
|
+
</foreignObject>
|
|
24774
|
+
</g>`;
|
|
24775
|
+
}
|
|
24776
|
+
static iframeObjectToSvg(object) {
|
|
24777
|
+
const transform = this.buildTransform(object);
|
|
24778
|
+
const opacity = object.opacity !== 1 ? ` opacity="${object.opacity}"` : '';
|
|
24779
|
+
const scale = this.getObjectScale(object);
|
|
24780
|
+
const width = object.totalWidth / scale;
|
|
24781
|
+
const height = object.totalHeight / scale;
|
|
24782
|
+
return `<g transform="${transform}"${opacity}>
|
|
24783
|
+
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
24784
|
+
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Iframe]</text>
|
|
24755
24785
|
</g>`;
|
|
24756
24786
|
}
|
|
24757
24787
|
/**
|
|
@@ -24771,8 +24801,8 @@ class KritzelSvgExportHelper {
|
|
|
24771
24801
|
return '';
|
|
24772
24802
|
}
|
|
24773
24803
|
const opacity = group.opacity !== 1 ? ` opacity="${group.opacity}"` : '';
|
|
24774
|
-
return `<g${opacity}>
|
|
24775
|
-
${children}
|
|
24804
|
+
return `<g${opacity}>
|
|
24805
|
+
${children}
|
|
24776
24806
|
</g>`;
|
|
24777
24807
|
}
|
|
24778
24808
|
/**
|
|
@@ -24957,12 +24987,26 @@ const KritzelEngine = class {
|
|
|
24957
24987
|
/** Authoritative workspace catalog for this engine instance. When provided, provider-only workspaces are hidden but not deleted. */
|
|
24958
24988
|
workspaces;
|
|
24959
24989
|
async onWorkspacesPropChange() {
|
|
24960
|
-
|
|
24990
|
+
this._workspacesRevision++;
|
|
24991
|
+
if (!this._isYjsInitialized || this._syncInitPromise) {
|
|
24961
24992
|
return;
|
|
24962
24993
|
}
|
|
24963
|
-
|
|
24964
|
-
|
|
24965
|
-
|
|
24994
|
+
const previousReconciliation = this._workspacePropReconciliationPromise;
|
|
24995
|
+
const reconciliationPromise = (async () => {
|
|
24996
|
+
await previousReconciliation;
|
|
24997
|
+
await this.reconcileProvidedWorkspaces();
|
|
24998
|
+
await this.ensureActiveWorkspaceIsVisible();
|
|
24999
|
+
this.workspacesChange.emit(this.getVisibleWorkspaces());
|
|
25000
|
+
})();
|
|
25001
|
+
this._workspacePropReconciliationPromise = reconciliationPromise;
|
|
25002
|
+
try {
|
|
25003
|
+
await reconciliationPromise;
|
|
25004
|
+
}
|
|
25005
|
+
finally {
|
|
25006
|
+
if (this._workspacePropReconciliationPromise === reconciliationPromise) {
|
|
25007
|
+
this._workspacePropReconciliationPromise = null;
|
|
25008
|
+
}
|
|
25009
|
+
}
|
|
24966
25010
|
}
|
|
24967
25011
|
/** Optional unique identifier for namespacing storage keys across multiple editor instances. */
|
|
24968
25012
|
editorId;
|
|
@@ -25016,6 +25060,12 @@ const KritzelEngine = class {
|
|
|
25016
25060
|
onUserChange(newValue) {
|
|
25017
25061
|
this.core.setUser(newValue);
|
|
25018
25062
|
}
|
|
25063
|
+
/** Tool definitions to register with this engine instance. */
|
|
25064
|
+
tools = [];
|
|
25065
|
+
onToolsChange() {
|
|
25066
|
+
this._toolsRevision++;
|
|
25067
|
+
void this.registerConfiguredTools();
|
|
25068
|
+
}
|
|
25019
25069
|
/** Context menu items shown when right-clicking the canvas background. */
|
|
25020
25070
|
globalContextMenuItems;
|
|
25021
25071
|
onGlobalContextMenuItemsChange(newValue) {
|
|
@@ -25206,7 +25256,7 @@ const KritzelEngine = class {
|
|
|
25206
25256
|
}
|
|
25207
25257
|
const hoveredObject = this.core.getObjectFromPointerEvent(ev);
|
|
25208
25258
|
if (hoveredObject &&
|
|
25209
|
-
ObjectHelper.
|
|
25259
|
+
ObjectHelper.isKritzelEmbeddedObject(hoveredObject) &&
|
|
25210
25260
|
KritzelWheelHelper.shouldKeepWheelInDynamicObject(ev, hoveredObject)) {
|
|
25211
25261
|
return;
|
|
25212
25262
|
}
|
|
@@ -25308,7 +25358,7 @@ const KritzelEngine = class {
|
|
|
25308
25358
|
return false;
|
|
25309
25359
|
}
|
|
25310
25360
|
const object = this.core.store.objects.findById(objectElement.id);
|
|
25311
|
-
if (!object || !
|
|
25361
|
+
if (!object || !ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
25312
25362
|
return false;
|
|
25313
25363
|
}
|
|
25314
25364
|
const isSelected = !!this.core.store.selectionGroup?.objects?.some(selectedObject => selectedObject.id === object.id);
|
|
@@ -25318,13 +25368,7 @@ const KritzelEngine = class {
|
|
|
25318
25368
|
if (object.isInteractive !== true) {
|
|
25319
25369
|
return false;
|
|
25320
25370
|
}
|
|
25321
|
-
const potentialRoots =
|
|
25322
|
-
if (object.element instanceof HTMLElement) {
|
|
25323
|
-
potentialRoots.push(object.element);
|
|
25324
|
-
}
|
|
25325
|
-
if (object.elementRef instanceof HTMLElement) {
|
|
25326
|
-
potentialRoots.push(object.elementRef);
|
|
25327
|
-
}
|
|
25371
|
+
const potentialRoots = object.getEmbeddedContentRoots();
|
|
25328
25372
|
if (potentialRoots.length === 0) {
|
|
25329
25373
|
return false;
|
|
25330
25374
|
}
|
|
@@ -25498,7 +25542,7 @@ const KritzelEngine = class {
|
|
|
25498
25542
|
* Switches the active drawing tool by its registered name.
|
|
25499
25543
|
* @param toolName - The name the tool was registered with (e.g., 'brush', 'eraser').
|
|
25500
25544
|
*/
|
|
25501
|
-
async
|
|
25545
|
+
async setActiveTool(toolName) {
|
|
25502
25546
|
const tool = this.core.toolRegistry.getTool(toolName);
|
|
25503
25547
|
if (!tool) {
|
|
25504
25548
|
console.warn(`[KritzelEngine] No tool registered with name: ${toolName}`);
|
|
@@ -26804,9 +26848,13 @@ const KritzelEngine = class {
|
|
|
26804
26848
|
_stateChangeListenersRegistered = false;
|
|
26805
26849
|
_workspaceInitializationPromise = null;
|
|
26806
26850
|
_workspaceInitializationTargetKey = null;
|
|
26851
|
+
_workspacePropReconciliationPromise = null;
|
|
26807
26852
|
_syncInitPromise = null;
|
|
26853
|
+
_toolsInitPromise = null;
|
|
26854
|
+
_toolsRevision = 0;
|
|
26808
26855
|
_syncConfigRevision = 0;
|
|
26809
26856
|
_assetStorageConfigRevision = 0;
|
|
26857
|
+
_workspacesRevision = 0;
|
|
26810
26858
|
_hasLoggedUnlicensedWelcomeBanner = false;
|
|
26811
26859
|
_previousVisibleDynamicObjects = new Set();
|
|
26812
26860
|
_revealedImageKeys = new Set();
|
|
@@ -26819,6 +26867,37 @@ const KritzelEngine = class {
|
|
|
26819
26867
|
undoStackSize: 0,
|
|
26820
26868
|
redoStackSize: 0,
|
|
26821
26869
|
};
|
|
26870
|
+
/** Returns a tool registered in this engine instance. */
|
|
26871
|
+
async getTool(toolName) {
|
|
26872
|
+
await this.registerConfiguredTools();
|
|
26873
|
+
return this.core.toolRegistry.getTool(toolName);
|
|
26874
|
+
}
|
|
26875
|
+
async registerConfiguredTools() {
|
|
26876
|
+
if (this._toolsInitPromise) {
|
|
26877
|
+
return this._toolsInitPromise;
|
|
26878
|
+
}
|
|
26879
|
+
this._toolsInitPromise = (async () => {
|
|
26880
|
+
do {
|
|
26881
|
+
const revision = this._toolsRevision;
|
|
26882
|
+
for (const definition of this.tools) {
|
|
26883
|
+
let toolClass = definition.tool;
|
|
26884
|
+
if (typeof toolClass !== 'function') {
|
|
26885
|
+
toolClass = toolClass.constructor;
|
|
26886
|
+
}
|
|
26887
|
+
await this.registerTool(definition.name, toolClass, definition.config);
|
|
26888
|
+
}
|
|
26889
|
+
if (revision === this._toolsRevision) {
|
|
26890
|
+
break;
|
|
26891
|
+
}
|
|
26892
|
+
} while (true);
|
|
26893
|
+
})();
|
|
26894
|
+
try {
|
|
26895
|
+
await this._toolsInitPromise;
|
|
26896
|
+
}
|
|
26897
|
+
finally {
|
|
26898
|
+
this._toolsInitPromise = null;
|
|
26899
|
+
}
|
|
26900
|
+
}
|
|
26822
26901
|
setLoadingState(isLoading) {
|
|
26823
26902
|
if (this.core.store.state.isLoading === isLoading) {
|
|
26824
26903
|
return;
|
|
@@ -26946,6 +27025,8 @@ const KritzelEngine = class {
|
|
|
26946
27025
|
this.core.licenseManager.destroy();
|
|
26947
27026
|
}
|
|
26948
27027
|
componentWillLoad() {
|
|
27028
|
+
this._toolsRevision++;
|
|
27029
|
+
void this.registerConfiguredTools();
|
|
26949
27030
|
this.core.setEditorId(this.editorId);
|
|
26950
27031
|
if (this.themes && this.themes.length > 0) {
|
|
26951
27032
|
this.core.themeManager.registerThemes(this.themes);
|
|
@@ -26985,7 +27066,9 @@ const KritzelEngine = class {
|
|
|
26985
27066
|
const editorElement = this.host.closest('kritzel-editor');
|
|
26986
27067
|
this.core.themeManager.setTargetElement(editorElement || this.host);
|
|
26987
27068
|
// Initialize sync config and Yjs
|
|
27069
|
+
await this.registerConfiguredTools();
|
|
26988
27070
|
await this.initializeSyncAndWorkspace();
|
|
27071
|
+
await this.waitForWorkspaceAndSceneReady();
|
|
26989
27072
|
if (this.core.store.state.isReady === false) {
|
|
26990
27073
|
this.core.store.state.isReady = true;
|
|
26991
27074
|
this.logUnlicensedWelcomeBanner();
|
|
@@ -27007,6 +27090,20 @@ const KritzelEngine = class {
|
|
|
27007
27090
|
this._syncInitPromise = null;
|
|
27008
27091
|
}
|
|
27009
27092
|
}
|
|
27093
|
+
async waitForSceneRender() {
|
|
27094
|
+
await new Promise(resolve => {
|
|
27095
|
+
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
27096
|
+
});
|
|
27097
|
+
}
|
|
27098
|
+
async waitForWorkspaceAndSceneReady() {
|
|
27099
|
+
let observedRevision;
|
|
27100
|
+
do {
|
|
27101
|
+
observedRevision = this._workspacesRevision;
|
|
27102
|
+
await this._workspacePropReconciliationPromise;
|
|
27103
|
+
await this.waitForSceneRender();
|
|
27104
|
+
} while (observedRevision !== this._workspacesRevision ||
|
|
27105
|
+
this._workspacePropReconciliationPromise);
|
|
27106
|
+
}
|
|
27010
27107
|
/**
|
|
27011
27108
|
* Initializes the asset storage layer with the latest config. Mirrors
|
|
27012
27109
|
* the in-flight replay logic of {@link doInitializeSyncAndWorkspace} for
|
|
@@ -27389,7 +27486,7 @@ const KritzelEngine = class {
|
|
|
27389
27486
|
if (!KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup')) {
|
|
27390
27487
|
return 'auto';
|
|
27391
27488
|
}
|
|
27392
|
-
if (object.objects.length === 1 &&
|
|
27489
|
+
if (object.objects.length === 1 && ObjectHelper.isKritzelEmbeddedObject(object.objects[0])) {
|
|
27393
27490
|
return 'none';
|
|
27394
27491
|
}
|
|
27395
27492
|
return 'auto';
|
|
@@ -27397,7 +27494,7 @@ const KritzelEngine = class {
|
|
|
27397
27494
|
// Track visible dynamic objects and unmount culled ones
|
|
27398
27495
|
const currentVisibleDynamicObjects = new Set();
|
|
27399
27496
|
visibleObjects.forEach(object => {
|
|
27400
|
-
if (
|
|
27497
|
+
if (ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
27401
27498
|
currentVisibleDynamicObjects.add(object.id);
|
|
27402
27499
|
}
|
|
27403
27500
|
});
|
|
@@ -27405,7 +27502,7 @@ const KritzelEngine = class {
|
|
|
27405
27502
|
this._previousVisibleDynamicObjects.forEach(id => {
|
|
27406
27503
|
if (!currentVisibleDynamicObjects.has(id)) {
|
|
27407
27504
|
const object = this.core.store.objects.findById(id);
|
|
27408
|
-
if (object &&
|
|
27505
|
+
if (object && ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
27409
27506
|
object.unmount();
|
|
27410
27507
|
}
|
|
27411
27508
|
}
|
|
@@ -27498,7 +27595,7 @@ const KritzelEngine = class {
|
|
|
27498
27595
|
display: 'flex',
|
|
27499
27596
|
alignItems: 'center',
|
|
27500
27597
|
justifyContent: 'center',
|
|
27501
|
-
} }, h("kritzel-icon", { name: object.loadState === 'error' ? '
|
|
27598
|
+
} }, h("kritzel-icon", { name: object.loadState === 'error' ? 'imageOff' : 'image', size: Math.max(16, Math.min(object.totalWidth, object.totalHeight) * 0.3), style: {
|
|
27502
27599
|
color: KritzelColorHelper.resolveThemeColor({ light: '#9ca3af', dark: '#6b7280' }, currentTheme),
|
|
27503
27600
|
} }))), KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject') && (h("div", { ref: el => el && object.mount(el), style: {
|
|
27504
27601
|
position: 'absolute',
|
|
@@ -27517,7 +27614,37 @@ const KritzelEngine = class {
|
|
|
27517
27614
|
padding: object.padding + 'px',
|
|
27518
27615
|
overflow: 'visible',
|
|
27519
27616
|
display: 'block',
|
|
27520
|
-
} })), KritzelClassHelper.isInstanceOf(object, '
|
|
27617
|
+
} })), KritzelClassHelper.isInstanceOf(object, 'KritzelIframeObject') && (h("div", { style: {
|
|
27618
|
+
position: 'absolute',
|
|
27619
|
+
left: '0',
|
|
27620
|
+
top: '0',
|
|
27621
|
+
width: object.totalWidth + 'px',
|
|
27622
|
+
height: object.totalHeight + 'px',
|
|
27623
|
+
transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
|
|
27624
|
+
transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
|
|
27625
|
+
opacity: effectiveOpacityString,
|
|
27626
|
+
backgroundColor: KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
|
|
27627
|
+
borderColor: KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
|
|
27628
|
+
borderWidth: object.borderWidth + 'px',
|
|
27629
|
+
borderStyle: 'solid',
|
|
27630
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
27631
|
+
boxShadow: object.boxShadow,
|
|
27632
|
+
overflow: 'hidden',
|
|
27633
|
+
display: 'block',
|
|
27634
|
+
pointerEvents: object.markedForRemoval ? 'none' : 'auto',
|
|
27635
|
+
} }, h("iframe", { ref: element => element && object.mount(element), title: object.title, sandbox: object.sandboxAttribute, style: {
|
|
27636
|
+
display: 'block',
|
|
27637
|
+
width: '100%',
|
|
27638
|
+
height: '100%',
|
|
27639
|
+
border: '0',
|
|
27640
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
27641
|
+
pointerEvents: object.isInteractive ? 'auto' : 'none',
|
|
27642
|
+
} }), h("div", { style: {
|
|
27643
|
+
position: 'absolute',
|
|
27644
|
+
inset: '0',
|
|
27645
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
27646
|
+
pointerEvents: object.isInteractive ? 'none' : 'auto',
|
|
27647
|
+
} }))), KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') && !this.core.displaySelectionLineUI(object) && (h("div", { ref: el => el && object.mount(el), style: {
|
|
27521
27648
|
position: 'absolute',
|
|
27522
27649
|
left: '0',
|
|
27523
27650
|
top: '0',
|
|
@@ -27875,6 +28002,9 @@ const KritzelEngine = class {
|
|
|
27875
28002
|
"user": [{
|
|
27876
28003
|
"onUserChange": 0
|
|
27877
28004
|
}],
|
|
28005
|
+
"tools": [{
|
|
28006
|
+
"onToolsChange": 0
|
|
28007
|
+
}],
|
|
27878
28008
|
"globalContextMenuItems": [{
|
|
27879
28009
|
"onGlobalContextMenuItemsChange": 0
|
|
27880
28010
|
}],
|
|
@@ -27939,6 +28069,20 @@ const KritzelIcon = class {
|
|
|
27939
28069
|
name;
|
|
27940
28070
|
label;
|
|
27941
28071
|
size = 24;
|
|
28072
|
+
unsubscribe;
|
|
28073
|
+
connectedCallback() {
|
|
28074
|
+
this.unsubscribe?.();
|
|
28075
|
+
this.unsubscribe = KritzelIconRegistry.subscribe(name => {
|
|
28076
|
+
if (name === this.name) {
|
|
28077
|
+
forceUpdate(this);
|
|
28078
|
+
}
|
|
28079
|
+
});
|
|
28080
|
+
forceUpdate(this);
|
|
28081
|
+
}
|
|
28082
|
+
disconnectedCallback() {
|
|
28083
|
+
this.unsubscribe?.();
|
|
28084
|
+
this.unsubscribe = undefined;
|
|
28085
|
+
}
|
|
27942
28086
|
render() {
|
|
27943
28087
|
const svgContent = KritzelIconRegistry.get(this.name);
|
|
27944
28088
|
if (!svgContent) {
|
|
@@ -27954,7 +28098,7 @@ const KritzelIcon = class {
|
|
|
27954
28098
|
};
|
|
27955
28099
|
KritzelIcon.style = kritzelIconCss();
|
|
27956
28100
|
|
|
27957
|
-
const kritzelWatermarkCss = () => `:host{position:absolute;bottom:var(--kritzel-watermark-offset-bottom, 12px);right:var(--kritzel-watermark-offset-right, 12px);z-index:10000;pointer-events:none}.watermark-link{pointer-events:auto;display:inline-flex;align-items:center;padding:4px 8px;border-radius:var(--kritzel-watermark-border-radius, 6px);font-family:var(--kritzel-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);font-size:var(--kritzel-watermark-font-size, 11px);line-height:1;text-decoration:none;color:var(--kritzel-watermark-color, rgba(60, 60, 60, 0.75));background-color:var(--kritzel-watermark-background, rgba(255, 255, 255, 0.6));box-shadow:var(--kritzel-watermark-box-shadow, 0 1px 2px rgba(0, 0, 0, 0.12));opacity:var(--kritzel-watermark-opacity, 0.85);transition:opacity 150ms ease;user-select:none}.watermark-link:hover{opacity:1}`;
|
|
28101
|
+
const kritzelWatermarkCss = () => `:host{position:absolute;bottom:var(--kritzel-watermark-offset-bottom, 12px);right:var(--kritzel-watermark-offset-right, 12px);z-index:10000;pointer-events:none}.watermark-link{pointer-events:auto;display:inline-flex;align-items:center;padding:4px 8px;border-radius:var(--kritzel-watermark-border-radius, 6px);font-family:var(--kritzel-global-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);font-size:var(--kritzel-watermark-font-size, 11px);line-height:1;text-decoration:none;color:var(--kritzel-watermark-color, rgba(60, 60, 60, 0.75));background-color:var(--kritzel-watermark-background, rgba(255, 255, 255, 0.6));box-shadow:var(--kritzel-watermark-box-shadow, 0 1px 2px rgba(0, 0, 0, 0.12));opacity:var(--kritzel-watermark-opacity, 0.85);transition:opacity 150ms ease;user-select:none}.watermark-link:hover{opacity:1}`;
|
|
27958
28102
|
|
|
27959
28103
|
const KritzelWatermark = class {
|
|
27960
28104
|
constructor(hostRef) {
|
|
@@ -27970,7 +28114,7 @@ const KritzelWatermark = class {
|
|
|
27970
28114
|
label;
|
|
27971
28115
|
render() {
|
|
27972
28116
|
const label = this.label ?? this.core.localizationManager.translate('watermark.poweredBy');
|
|
27973
|
-
return (h(Host, { key: '
|
|
28117
|
+
return (h(Host, { key: '5bc76650ecd1f82f5ed283d4433b0e5fc8937cab' }, h("a", { key: 'b0828f36df618e461794772d2e8f55c0a8cb357e', class: "watermark-link", href: KRITZEL_WEBSITE_URL, target: "_blank", rel: "noopener noreferrer", part: "watermark", onPointerDown: (ev) => ev.stopPropagation(), onPointerUp: (ev) => ev.stopPropagation() }, label)));
|
|
27974
28118
|
}
|
|
27975
28119
|
};
|
|
27976
28120
|
KritzelWatermark.style = kritzelWatermarkCss();
|