@kritzel/engine 0.4.31 → 0.4.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +49 -49
- package/dist/cjs/{engine.constants-CakmdKMW.js → engine.constants-cfbepvaI.js} +595 -98
- package/dist/cjs/{index-BbbWU2aN.js → index-BrjM5aN2.js} +12 -0
- 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 +2 -2
- 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 +3 -1
- 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 +723 -130
- package/dist/components/kritzel-icon.js +1 -1
- package/dist/components/kritzel-watermark.js +1 -1
- package/dist/components/{p-YP8wAcF4.js → p-9YjkpHyU.js} +2 -2
- package/dist/components/p-BIUT0gBe.js +214 -0
- package/dist/components/{p-B2Htv9ou.js → p-Bnuu1qip.js} +3 -3
- package/dist/components/{p-CfSx6HU_.js → p-CJ5B8cMK.js} +12 -1
- package/dist/components/{p-BvRGQvVI.js → p-DXnF4FeS.js} +18 -14
- package/dist/esm/{engine.constants-Bl5-pbq-.js → engine.constants-DPDQhv6S.js} +594 -99
- package/dist/esm/{index-BU9Mv7y0.js → index-Hqbtnnex.js} +12 -1
- 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 +3 -3
- package/dist/stencil/index.esm.js +3 -3
- package/dist/stencil/{p-Bl5-pbq-.js → p-DPDQhv6S.js} +594 -99
- package/dist/stencil/{p-BU9Mv7y0.js → p-Hqbtnnex.js} +12 -1
- package/dist/stencil/{p-f0a8b7af.entry.js → p-d678528e.entry.js} +257 -113
- package/dist/stencil/stencil.esm.js +3 -3
- 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/package.json +1 -1
- package/readme.md +10 -10
- package/dist/components/p-fx6msYHJ.js +0 -167
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
4
|
-
var engine_constants = require('./engine.constants-
|
|
3
|
+
var index = require('./index-BrjM5aN2.js');
|
|
4
|
+
var engine_constants = require('./engine.constants-cfbepvaI.js');
|
|
5
5
|
var Y = require('yjs');
|
|
6
6
|
|
|
7
7
|
function _interopNamespace(e) {
|
|
@@ -26,7 +26,7 @@ var Y__namespace = /*#__PURE__*/_interopNamespace(Y);
|
|
|
26
26
|
|
|
27
27
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
28
28
|
|
|
29
|
-
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,
|
|
29
|
+
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}`;
|
|
30
30
|
|
|
31
31
|
const STALE_THRESHOLD_MS = 10_000;
|
|
32
32
|
const REMOVE_THRESHOLD_MS = 30_000;
|
|
@@ -231,7 +231,7 @@ const KritzelAwarenessCursors = class {
|
|
|
231
231
|
}
|
|
232
232
|
render() {
|
|
233
233
|
const cursors = Array.from(this.remoteCursors.values());
|
|
234
|
-
return (index.h(index.Host, { key: '
|
|
234
|
+
return (index.h(index.Host, { key: '2021875ea3e430c04da438dc5b7a2c22f119ea67' }, cursors.map(remoteCursor => {
|
|
235
235
|
if (!remoteCursor.cursor)
|
|
236
236
|
return null;
|
|
237
237
|
// When a remote user is actively drawing, derive cursor position from
|
|
@@ -383,7 +383,7 @@ const KritzelCursorTrail = class {
|
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
385
|
render() {
|
|
386
|
-
return (index.h(index.Host, { key: '
|
|
386
|
+
return (index.h(index.Host, { key: '39d026a0d4c444564f146a90ea1a51181d0652b7' }, this.cursorTrailPoints.length > 1 && (index.h("svg", { key: '927e52cd0828a548ba58e0e783b1d148a40c968c', class: "cursor-trail-svg", xmlns: "http://www.w3.org/2000/svg", style: {
|
|
387
387
|
position: 'absolute',
|
|
388
388
|
left: '0',
|
|
389
389
|
top: '0',
|
|
@@ -18851,6 +18851,9 @@ class KritzelReviver {
|
|
|
18851
18851
|
case 'KritzelDynamicObject':
|
|
18852
18852
|
revivedObj = engine_constants.KritzelDynamicObject.create(this._core).deserialize(obj);
|
|
18853
18853
|
break;
|
|
18854
|
+
case 'KritzelIframeObject':
|
|
18855
|
+
revivedObj = engine_constants.KritzelIframeObject.create(this._core).deserialize(obj);
|
|
18856
|
+
break;
|
|
18854
18857
|
case 'KritzelSelectionGroup':
|
|
18855
18858
|
revivedObj = engine_constants.KritzelSelectionGroup.create(this._core).deserialize(obj);
|
|
18856
18859
|
break;
|
|
@@ -20675,9 +20678,16 @@ class KritzelStore {
|
|
|
20675
20678
|
* Gets the currently selected dynamic object whose focused descendant is an input-like element.
|
|
20676
20679
|
* @returns The interactive dynamic object with focused input-like content, or null if none matches
|
|
20677
20680
|
*/
|
|
20681
|
+
get activeInteractiveEmbeddedObject() {
|
|
20682
|
+
for (const object of this.selectedObjects) {
|
|
20683
|
+
if (engine_constants.ObjectHelper.isKritzelEmbeddedObject(object) && object.hasFocusedInputElement()) {
|
|
20684
|
+
return object;
|
|
20685
|
+
}
|
|
20686
|
+
}
|
|
20687
|
+
return null;
|
|
20688
|
+
}
|
|
20678
20689
|
get activeInteractiveDynamicObject() {
|
|
20679
|
-
|
|
20680
|
-
return interactiveDynamicObject ?? null;
|
|
20690
|
+
return this.activeInteractiveEmbeddedObject;
|
|
20681
20691
|
}
|
|
20682
20692
|
/**
|
|
20683
20693
|
* Gets the path currently being drawn (not yet completed).
|
|
@@ -21265,11 +21275,13 @@ class KritzelCursorManager {
|
|
|
21265
21275
|
// Reset cursor on old target
|
|
21266
21276
|
if (this._targetElement) {
|
|
21267
21277
|
this._targetElement.style.cursor = '';
|
|
21278
|
+
this._targetElement.style.removeProperty('--kritzel-global-default-cursor');
|
|
21268
21279
|
this._targetElement.style.removeProperty('--kritzel-global-pointer-cursor');
|
|
21269
21280
|
}
|
|
21270
21281
|
this._targetElement = element;
|
|
21271
21282
|
// Set the pointer cursor CSS variable for child components to use
|
|
21272
21283
|
if (this._targetElement) {
|
|
21284
|
+
this._targetElement.style.setProperty('--kritzel-global-default-cursor', engine_constants.KritzelCursorHelper.getCursor({ iconName: 'default' }));
|
|
21273
21285
|
this._targetElement.style.setProperty('--kritzel-global-pointer-cursor', engine_constants.KritzelCursorHelper.getPointerCursor());
|
|
21274
21286
|
}
|
|
21275
21287
|
}
|
|
@@ -21314,8 +21326,10 @@ class KritzelCursorManager {
|
|
|
21314
21326
|
if (!this._shadowRoot)
|
|
21315
21327
|
return;
|
|
21316
21328
|
const elementsAtPoint = this._shadowRoot.elementsFromPoint(ev.clientX, ev.clientY);
|
|
21317
|
-
if (!elementsAtPoint || elementsAtPoint.length === 0)
|
|
21329
|
+
if (!elementsAtPoint || elementsAtPoint.length === 0) {
|
|
21330
|
+
this.resetToDefault();
|
|
21318
21331
|
return;
|
|
21332
|
+
}
|
|
21319
21333
|
// Check for resize handle overlays (selection group)
|
|
21320
21334
|
const resizeHandleOverlay = elementsAtPoint.find(el => el.classList.contains('resize-handle-overlay'));
|
|
21321
21335
|
if (resizeHandleOverlay) {
|
|
@@ -21325,19 +21339,19 @@ class KritzelCursorManager {
|
|
|
21325
21339
|
const isTopLeft = resizeHandleOverlay.classList.contains('top-left');
|
|
21326
21340
|
const isBottomRight = resizeHandleOverlay.classList.contains('bottom-right');
|
|
21327
21341
|
const rotationOffset = (isTopLeft || isBottomRight) ? -45 : 45;
|
|
21328
|
-
this._core.store.state.cursor = { icon: '
|
|
21342
|
+
this._core.store.state.cursor = { icon: 'moveVertical', rotation: rotationDegrees + rotationOffset };
|
|
21329
21343
|
return;
|
|
21330
21344
|
}
|
|
21331
21345
|
// Check for rotation handle overlay
|
|
21332
21346
|
const rotationHandleOverlay = elementsAtPoint.find(el => el.classList.contains('rotation-handle-overlay'));
|
|
21333
21347
|
if (rotationHandleOverlay) {
|
|
21334
|
-
this._core.store.state.cursor = { icon: 'hand', iconActive: '
|
|
21348
|
+
this._core.store.state.cursor = { icon: 'hand', iconActive: 'handGrab' };
|
|
21335
21349
|
return;
|
|
21336
21350
|
}
|
|
21337
21351
|
// Check for line handle overlays (selection line)
|
|
21338
21352
|
const lineHandleOverlay = elementsAtPoint.find(el => el.classList.contains('selection-line-handle-overlay'));
|
|
21339
21353
|
if (lineHandleOverlay) {
|
|
21340
|
-
this._core.store.state.cursor = { icon: 'hand', iconActive: '
|
|
21354
|
+
this._core.store.state.cursor = { icon: 'hand', iconActive: 'handGrab' };
|
|
21341
21355
|
return;
|
|
21342
21356
|
}
|
|
21343
21357
|
// Reset cursor if not hovering any handle
|
|
@@ -21372,7 +21386,8 @@ class KritzelCursorManager {
|
|
|
21372
21386
|
cleanup() {
|
|
21373
21387
|
if (this._targetElement) {
|
|
21374
21388
|
this._targetElement.style.cursor = '';
|
|
21375
|
-
this._targetElement.style.removeProperty('--kritzel-
|
|
21389
|
+
this._targetElement.style.removeProperty('--kritzel-global-default-cursor');
|
|
21390
|
+
this._targetElement.style.removeProperty('--kritzel-global-pointer-cursor');
|
|
21376
21391
|
}
|
|
21377
21392
|
this._targetElement = null;
|
|
21378
21393
|
this._shadowRoot = null;
|
|
@@ -22297,7 +22312,7 @@ class KritzelCore {
|
|
|
22297
22312
|
this._store.state.translateY = viewportHeight / 2 - (viewport.centerWorldY ?? 0) * scale;
|
|
22298
22313
|
this._store.state.scale = scale;
|
|
22299
22314
|
await objectsMap.initialize(this, activeWorkspace.id, this._syncConfig);
|
|
22300
|
-
this.seedWorkspaceObjects(activeWorkspace, objectsMap);
|
|
22315
|
+
await this.seedWorkspaceObjects(activeWorkspace, objectsMap);
|
|
22301
22316
|
// Set local user in awareness after object map is initialized
|
|
22302
22317
|
if (this._user) {
|
|
22303
22318
|
objectsMap.setLocalUser(this._user);
|
|
@@ -22311,15 +22326,21 @@ class KritzelCore {
|
|
|
22311
22326
|
this.engine.emitObjectsChange();
|
|
22312
22327
|
this.rerender();
|
|
22313
22328
|
}
|
|
22314
|
-
seedWorkspaceObjects(workspace, objectsMap) {
|
|
22329
|
+
async seedWorkspaceObjects(workspace, objectsMap) {
|
|
22315
22330
|
if (!workspace.objects?.length) {
|
|
22316
22331
|
return;
|
|
22317
22332
|
}
|
|
22333
|
+
const pendingObjects = workspace.objects.filter(object => !objectsMap.findById(object.id));
|
|
22334
|
+
// Mirrors engine.addObject()/addObjects(): image asset upload is async and must
|
|
22335
|
+
// happen before the (synchronous) Yjs transaction that inserts the objects.
|
|
22336
|
+
for (const object of pendingObjects) {
|
|
22337
|
+
object._core = this;
|
|
22338
|
+
if (engine_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
22339
|
+
await object.prepareForInsert();
|
|
22340
|
+
}
|
|
22341
|
+
}
|
|
22318
22342
|
objectsMap.transaction(() => {
|
|
22319
|
-
for (const object of
|
|
22320
|
-
if (objectsMap.findById(object.id)) {
|
|
22321
|
-
continue;
|
|
22322
|
-
}
|
|
22343
|
+
for (const object of pendingObjects) {
|
|
22323
22344
|
this.prepareObjectForWorkspace(object, workspace.id, this._store.currentZIndex, this._store.state.scale);
|
|
22324
22345
|
objectsMap.insert(object);
|
|
22325
22346
|
}
|
|
@@ -22358,16 +22379,30 @@ class KritzelCore {
|
|
|
22358
22379
|
* @param scaleFallback - Scale applied to objects that do not define one
|
|
22359
22380
|
* @returns The objects that were added, updated and removed
|
|
22360
22381
|
*/
|
|
22361
|
-
reconcileWorkspaceObjects(objectsMap, workspaceId, desiredObjects, nextZIndex, scaleFallback) {
|
|
22382
|
+
async reconcileWorkspaceObjects(objectsMap, workspaceId, desiredObjects, nextZIndex, scaleFallback) {
|
|
22362
22383
|
const existingObjects = objectsMap.allObjects().filter(o => !(o instanceof engine_constants.KritzelSelectionGroup) && !(o instanceof engine_constants.KritzelSelectionBox));
|
|
22363
22384
|
const existingById = new Map(existingObjects.map(object => [object.id, object]));
|
|
22364
22385
|
const desiredIds = new Set();
|
|
22365
22386
|
const diff = { added: [], updated: [], removed: [] };
|
|
22387
|
+
// Assign IDs up front so the insert-vs-update lookup below is stable, and so the
|
|
22388
|
+
// async image-prepare pass and the (synchronous) transaction agree on identity.
|
|
22389
|
+
for (const object of desiredObjects) {
|
|
22390
|
+
if (!object.id) {
|
|
22391
|
+
object.id = object.generateId();
|
|
22392
|
+
}
|
|
22393
|
+
}
|
|
22394
|
+
// Mirrors engine.addObject()/addObjects(): image asset upload is async and must
|
|
22395
|
+
// happen before the (synchronous) Yjs transaction that inserts the objects.
|
|
22396
|
+
for (const object of desiredObjects) {
|
|
22397
|
+
const existingObject = existingById.get(object.id);
|
|
22398
|
+
const isNewOrReplaced = !existingObject || existingObject !== object;
|
|
22399
|
+
if (isNewOrReplaced && engine_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
22400
|
+
object._core = this;
|
|
22401
|
+
await object.prepareForInsert();
|
|
22402
|
+
}
|
|
22403
|
+
}
|
|
22366
22404
|
objectsMap.transaction(() => {
|
|
22367
22405
|
for (const object of desiredObjects) {
|
|
22368
|
-
if (!object.id) {
|
|
22369
|
-
object.id = object.generateId();
|
|
22370
|
-
}
|
|
22371
22406
|
desiredIds.add(object.id);
|
|
22372
22407
|
const existingObject = existingById.get(object.id);
|
|
22373
22408
|
if (!existingObject) {
|
|
@@ -22405,7 +22440,7 @@ class KritzelCore {
|
|
|
22405
22440
|
* object set stays exactly what the caller declared.
|
|
22406
22441
|
*/
|
|
22407
22442
|
detachObject(object) {
|
|
22408
|
-
if (engine_constants.
|
|
22443
|
+
if (engine_constants.ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
22409
22444
|
object.unmount();
|
|
22410
22445
|
}
|
|
22411
22446
|
object.isMounted = false;
|
|
@@ -22581,13 +22616,13 @@ class KritzelCore {
|
|
|
22581
22616
|
activeWorkspace.viewport = { centerWorldX, centerWorldY, scale };
|
|
22582
22617
|
}
|
|
22583
22618
|
}
|
|
22584
|
-
applyObjectsToActiveWorkspace(workspace, desiredObjects) {
|
|
22619
|
+
async applyObjectsToActiveWorkspace(workspace, desiredObjects) {
|
|
22585
22620
|
const objectsMap = this._store.objects;
|
|
22586
22621
|
if (!objectsMap) {
|
|
22587
22622
|
return null;
|
|
22588
22623
|
}
|
|
22589
22624
|
this.clearSelection();
|
|
22590
|
-
const diff = this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this._store.currentZIndex, this._store.state.scale);
|
|
22625
|
+
const diff = await this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this._store.currentZIndex, this._store.state.scale);
|
|
22591
22626
|
this._anchorManager.rebuildIndex();
|
|
22592
22627
|
this.rerender();
|
|
22593
22628
|
return diff;
|
|
@@ -22606,7 +22641,7 @@ class KritzelCore {
|
|
|
22606
22641
|
try {
|
|
22607
22642
|
await objectsMap.initialize(this, workspace.id, this._syncConfig, { headless: true, workspaceName: workspace.name });
|
|
22608
22643
|
await objectsMap.whenNetworkSynced();
|
|
22609
|
-
return this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this.nextZIndexOf(objectsMap), this._store.state.scale);
|
|
22644
|
+
return await this.reconcileWorkspaceObjects(objectsMap, workspace.id, desiredObjects, () => this.nextZIndexOf(objectsMap), this._store.state.scale);
|
|
22610
22645
|
}
|
|
22611
22646
|
finally {
|
|
22612
22647
|
objectsMap.destroy();
|
|
@@ -22692,8 +22727,7 @@ class KritzelCore {
|
|
|
22692
22727
|
this.removeObject(child);
|
|
22693
22728
|
});
|
|
22694
22729
|
}
|
|
22695
|
-
|
|
22696
|
-
if (engine_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject')) {
|
|
22730
|
+
if (engine_constants.ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
22697
22731
|
object.unmount();
|
|
22698
22732
|
}
|
|
22699
22733
|
// Handle anchor cleanup
|
|
@@ -22739,14 +22773,8 @@ class KritzelCore {
|
|
|
22739
22773
|
this.removeLocalSelectionGroups();
|
|
22740
22774
|
this.removeSelectionBox();
|
|
22741
22775
|
for (const object of selectionGroup.objects ?? []) {
|
|
22742
|
-
if (engine_constants.
|
|
22743
|
-
|
|
22744
|
-
if (typeof dynamicObject.setIsInteractive === 'function') {
|
|
22745
|
-
dynamicObject.setIsInteractive(true);
|
|
22746
|
-
}
|
|
22747
|
-
else {
|
|
22748
|
-
dynamicObject.isInteractive = true;
|
|
22749
|
-
}
|
|
22776
|
+
if (engine_constants.ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
22777
|
+
object.setIsInteractive(true);
|
|
22750
22778
|
}
|
|
22751
22779
|
}
|
|
22752
22780
|
this._store.objects.insert(selectionGroup);
|
|
@@ -22767,14 +22795,8 @@ class KritzelCore {
|
|
|
22767
22795
|
teardownSelectionGroup(selectionGroup) {
|
|
22768
22796
|
selectionGroup.deselectAllChildren?.();
|
|
22769
22797
|
for (const object of selectionGroup.objects ?? []) {
|
|
22770
|
-
if (engine_constants.
|
|
22771
|
-
|
|
22772
|
-
if (typeof dynamicObject.setIsInteractive === 'function') {
|
|
22773
|
-
dynamicObject.setIsInteractive(false);
|
|
22774
|
-
}
|
|
22775
|
-
else {
|
|
22776
|
-
dynamicObject.isInteractive = false;
|
|
22777
|
-
}
|
|
22798
|
+
if (engine_constants.ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
22799
|
+
object.setIsInteractive(false);
|
|
22778
22800
|
}
|
|
22779
22801
|
}
|
|
22780
22802
|
}
|
|
@@ -24220,13 +24242,7 @@ class KritzelWheelHelper {
|
|
|
24220
24242
|
return this.canElementConsumeWheel(scrollContainer, ev.deltaX, ev.deltaY);
|
|
24221
24243
|
}
|
|
24222
24244
|
static getScrollableContainerFromEventPath(path, dynamicObject) {
|
|
24223
|
-
const potentialRoots =
|
|
24224
|
-
if (dynamicObject.element instanceof HTMLElement) {
|
|
24225
|
-
potentialRoots.push(dynamicObject.element);
|
|
24226
|
-
}
|
|
24227
|
-
if (dynamicObject.elementRef instanceof HTMLElement) {
|
|
24228
|
-
potentialRoots.push(dynamicObject.elementRef);
|
|
24229
|
-
}
|
|
24245
|
+
const potentialRoots = dynamicObject.getEmbeddedContentRoots();
|
|
24230
24246
|
const legacyElementRef = dynamicObject.elmeentRef;
|
|
24231
24247
|
if (legacyElementRef instanceof HTMLElement) {
|
|
24232
24248
|
potentialRoots.push(legacyElementRef);
|
|
@@ -24384,8 +24400,8 @@ class KritzelSvgExportHelper {
|
|
|
24384
24400
|
.join('\n ');
|
|
24385
24401
|
const xmlDecl = includeXmlDeclaration ? '<?xml version="1.0" encoding="UTF-8"?>\n' : '';
|
|
24386
24402
|
const defsContent = defs.length > 0 ? `\n <defs>\n ${defs.join('\n ')}\n </defs>` : '';
|
|
24387
|
-
return `${xmlDecl}<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}" width="${viewBoxWidth}" height="${viewBoxHeight}">${defsContent}
|
|
24388
|
-
${elements}
|
|
24403
|
+
return `${xmlDecl}<svg xmlns="http://www.w3.org/2000/svg" viewBox="${viewBoxX} ${viewBoxY} ${viewBoxWidth} ${viewBoxHeight}" width="${viewBoxWidth}" height="${viewBoxHeight}">${defsContent}
|
|
24404
|
+
${elements}
|
|
24389
24405
|
</svg>`;
|
|
24390
24406
|
}
|
|
24391
24407
|
/**
|
|
@@ -24537,8 +24553,8 @@ class KritzelSvgExportHelper {
|
|
|
24537
24553
|
const orient = end === 'start' ? 'auto-start-reverse' : 'auto';
|
|
24538
24554
|
const refX = 0;
|
|
24539
24555
|
const refY = size / 2;
|
|
24540
|
-
return `<marker id="${markerId}" markerWidth="${size}" markerHeight="${size}" refX="${refX}" refY="${refY}" orient="${orient}" markerUnits="userSpaceOnUse">
|
|
24541
|
-
<path d="${path}" fill="${fill}" transform="scale(${size / 10})"/>
|
|
24556
|
+
return `<marker id="${markerId}" markerWidth="${size}" markerHeight="${size}" refX="${refX}" refY="${refY}" orient="${orient}" markerUnits="userSpaceOnUse">
|
|
24557
|
+
<path d="${path}" fill="${fill}" transform="scale(${size / 10})"/>
|
|
24542
24558
|
</marker>`;
|
|
24543
24559
|
}
|
|
24544
24560
|
/**
|
|
@@ -24567,6 +24583,9 @@ class KritzelSvgExportHelper {
|
|
|
24567
24583
|
if (engine_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject')) {
|
|
24568
24584
|
return this.dynamicObjectToSvg(object, rasterSafeForCanvas);
|
|
24569
24585
|
}
|
|
24586
|
+
if (engine_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelIframeObject')) {
|
|
24587
|
+
return this.iframeObjectToSvg(object);
|
|
24588
|
+
}
|
|
24570
24589
|
if (engine_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
24571
24590
|
return this.groupToSvg(object, theme, imageDataUrls, rasterSafeForCanvas);
|
|
24572
24591
|
}
|
|
@@ -24585,10 +24604,10 @@ class KritzelSvgExportHelper {
|
|
|
24585
24604
|
const opacity = path.opacity !== 1 ? ` opacity="${path.opacity}"` : '';
|
|
24586
24605
|
const scale = this.getObjectScale(path);
|
|
24587
24606
|
// Path needs to be wrapped in a g with translation since path.d uses local coordinates
|
|
24588
|
-
return `<g transform="${transform}"${opacity}>
|
|
24589
|
-
<svg viewBox="${path.viewBox}" width="${path.totalWidth / scale}" height="${path.totalHeight / scale}" overflow="visible">
|
|
24590
|
-
<path d="${path.d}" fill="${fill || 'none'}" stroke="${stroke || 'none'}"${path.strokeWidth ? ` stroke-width="${path.strokeWidth}"` : ''}/>
|
|
24591
|
-
</svg>
|
|
24607
|
+
return `<g transform="${transform}"${opacity}>
|
|
24608
|
+
<svg viewBox="${path.viewBox}" width="${path.totalWidth / scale}" height="${path.totalHeight / scale}" overflow="visible">
|
|
24609
|
+
<path d="${path.d}" fill="${fill || 'none'}" stroke="${stroke || 'none'}"${path.strokeWidth ? ` stroke-width="${path.strokeWidth}"` : ''}/>
|
|
24610
|
+
</svg>
|
|
24592
24611
|
</g>`;
|
|
24593
24612
|
}
|
|
24594
24613
|
/**
|
|
@@ -24604,10 +24623,10 @@ class KritzelSvgExportHelper {
|
|
|
24604
24623
|
const scale = this.getObjectScale(line);
|
|
24605
24624
|
const markerStart = line.hasStartArrow ? ` marker-start="url(#${line.startMarkerId})"` : '';
|
|
24606
24625
|
const markerEnd = line.hasEndArrow ? ` marker-end="url(#${line.endMarkerId})"` : '';
|
|
24607
|
-
return `<g transform="${transform}"${opacity}>
|
|
24608
|
-
<svg viewBox="${line.viewBox}" width="${line.totalWidth / scale}" height="${line.totalHeight / scale}" overflow="visible">
|
|
24609
|
-
<path d="${line.d}" fill="none" stroke="${stroke}" stroke-width="${line.strokeWidth}" stroke-linecap="round"${markerStart}${markerEnd}/>
|
|
24610
|
-
</svg>
|
|
24626
|
+
return `<g transform="${transform}"${opacity}>
|
|
24627
|
+
<svg viewBox="${line.viewBox}" width="${line.totalWidth / scale}" height="${line.totalHeight / scale}" overflow="visible">
|
|
24628
|
+
<path d="${line.d}" fill="none" stroke="${stroke}" stroke-width="${line.strokeWidth}" stroke-linecap="round"${markerStart}${markerEnd}/>
|
|
24629
|
+
</svg>
|
|
24611
24630
|
</g>`;
|
|
24612
24631
|
}
|
|
24613
24632
|
/**
|
|
@@ -24631,18 +24650,18 @@ class KritzelSvgExportHelper {
|
|
|
24631
24650
|
const textHtml = this.prosemirrorToHtml(shape.content, shape, theme);
|
|
24632
24651
|
if (textHtml) {
|
|
24633
24652
|
const fontColor = engine_constants.KritzelColorHelper.resolveThemeColor(shape.fontColor, theme);
|
|
24634
|
-
textContent = `
|
|
24635
|
-
<foreignObject x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}">
|
|
24636
|
-
<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;">
|
|
24637
|
-
${textHtml}
|
|
24638
|
-
</div>
|
|
24653
|
+
textContent = `
|
|
24654
|
+
<foreignObject x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}">
|
|
24655
|
+
<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;">
|
|
24656
|
+
${textHtml}
|
|
24657
|
+
</div>
|
|
24639
24658
|
</foreignObject>`;
|
|
24640
24659
|
}
|
|
24641
24660
|
}
|
|
24642
|
-
return `<g transform="${transform}"${opacity}>
|
|
24643
|
-
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth / scale}" height="${shape.totalHeight / scale}" overflow="visible" preserveAspectRatio="none">
|
|
24644
|
-
<path d="${pathD}" fill="${fill || 'transparent'}" stroke="${stroke}" stroke-width="${shape.strokeWidth}"/>${textContent}
|
|
24645
|
-
</svg>
|
|
24661
|
+
return `<g transform="${transform}"${opacity}>
|
|
24662
|
+
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth / scale}" height="${shape.totalHeight / scale}" overflow="visible" preserveAspectRatio="none">
|
|
24663
|
+
<path d="${pathD}" fill="${fill || 'transparent'}" stroke="${stroke}" stroke-width="${shape.strokeWidth}"/>${textContent}
|
|
24664
|
+
</svg>
|
|
24646
24665
|
</g>`;
|
|
24647
24666
|
}
|
|
24648
24667
|
/**
|
|
@@ -24673,10 +24692,10 @@ class KritzelSvgExportHelper {
|
|
|
24673
24692
|
// adjusted font-size already accounts for it – keeping both would double-scale
|
|
24674
24693
|
// the content and overflow the foreignObject.
|
|
24675
24694
|
const svgFontSizePx = (text.fontSize * (4 / 3) * (text.scaleFactor || 1) / scale).toFixed(4);
|
|
24676
|
-
return `<g transform="${transform}"${opacity}>
|
|
24677
|
-
<foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
|
|
24678
|
-
<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>
|
|
24679
|
-
</foreignObject>
|
|
24695
|
+
return `<g transform="${transform}"${opacity}>
|
|
24696
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
|
|
24697
|
+
<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>
|
|
24698
|
+
</foreignObject>
|
|
24680
24699
|
</g>`;
|
|
24681
24700
|
}
|
|
24682
24701
|
/**
|
|
@@ -24710,9 +24729,9 @@ class KritzelSvgExportHelper {
|
|
|
24710
24729
|
return `<tspan x="0" y="${y}" xml:space="preserve">${this.escapeHtml(line)}</tspan>`;
|
|
24711
24730
|
})
|
|
24712
24731
|
.join('');
|
|
24713
|
-
return `<g transform="${transform}"${opacity}>
|
|
24714
|
-
${bgRect}
|
|
24715
|
-
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
24732
|
+
return `<g transform="${transform}"${opacity}>
|
|
24733
|
+
${bgRect}
|
|
24734
|
+
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
24716
24735
|
</g>`;
|
|
24717
24736
|
}
|
|
24718
24737
|
/**
|
|
@@ -24740,8 +24759,8 @@ class KritzelSvgExportHelper {
|
|
|
24740
24759
|
const width = image.totalWidth / scale;
|
|
24741
24760
|
const height = image.totalHeight / scale;
|
|
24742
24761
|
const href = imageDataUrls?.get(image.id) || image.resolvedSrc || image.src || '';
|
|
24743
|
-
return `<g transform="${transform}"${opacity}>
|
|
24744
|
-
<image href="${href}" x="0" y="0" width="${width}" height="${height}" preserveAspectRatio="xMidYMid meet"/>
|
|
24762
|
+
return `<g transform="${transform}"${opacity}>
|
|
24763
|
+
<image href="${href}" x="0" y="0" width="${width}" height="${height}" preserveAspectRatio="xMidYMid meet"/>
|
|
24745
24764
|
</g>`;
|
|
24746
24765
|
}
|
|
24747
24766
|
/**
|
|
@@ -24761,19 +24780,30 @@ class KritzelSvgExportHelper {
|
|
|
24761
24780
|
if (rasterSafeForCanvas) {
|
|
24762
24781
|
// PNG export: render placeholder rect (foreignObject doesn't rasterize to PNG well)
|
|
24763
24782
|
console.warn('[KritzelDynamicObject SVG Export] Dynamic objects do not serialize well to PNG. Use SVG export or screenshot instead.');
|
|
24764
|
-
return `<g transform="${transform}"${opacity}>
|
|
24765
|
-
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
24766
|
-
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Dynamic Object]</text>
|
|
24783
|
+
return `<g transform="${transform}"${opacity}>
|
|
24784
|
+
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
24785
|
+
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Dynamic Object]</text>
|
|
24767
24786
|
</g>`;
|
|
24768
24787
|
}
|
|
24769
24788
|
// SVG export: use foreignObject to embed HTML
|
|
24770
24789
|
const html = obj.element?.outerHTML || '<div style="border:1px dashed #ccc">Empty</div>';
|
|
24771
|
-
return `<g transform="${transform}"${opacity}>
|
|
24772
|
-
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
24773
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;overflow:hidden;">
|
|
24774
|
-
${html}
|
|
24775
|
-
</div>
|
|
24776
|
-
</foreignObject>
|
|
24790
|
+
return `<g transform="${transform}"${opacity}>
|
|
24791
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
24792
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="width:100%;height:100%;overflow:hidden;">
|
|
24793
|
+
${html}
|
|
24794
|
+
</div>
|
|
24795
|
+
</foreignObject>
|
|
24796
|
+
</g>`;
|
|
24797
|
+
}
|
|
24798
|
+
static iframeObjectToSvg(object) {
|
|
24799
|
+
const transform = this.buildTransform(object);
|
|
24800
|
+
const opacity = object.opacity !== 1 ? ` opacity="${object.opacity}"` : '';
|
|
24801
|
+
const scale = this.getObjectScale(object);
|
|
24802
|
+
const width = object.totalWidth / scale;
|
|
24803
|
+
const height = object.totalHeight / scale;
|
|
24804
|
+
return `<g transform="${transform}"${opacity}>
|
|
24805
|
+
<rect x="0" y="0" width="${width}" height="${height}" fill="#f0f0f0" stroke="#999" stroke-width="1" />
|
|
24806
|
+
<text x="${width / 2}" y="${height / 2}" text-anchor="middle" dominant-baseline="middle" font-size="12" fill="#999">[Iframe]</text>
|
|
24777
24807
|
</g>`;
|
|
24778
24808
|
}
|
|
24779
24809
|
/**
|
|
@@ -24793,8 +24823,8 @@ class KritzelSvgExportHelper {
|
|
|
24793
24823
|
return '';
|
|
24794
24824
|
}
|
|
24795
24825
|
const opacity = group.opacity !== 1 ? ` opacity="${group.opacity}"` : '';
|
|
24796
|
-
return `<g${opacity}>
|
|
24797
|
-
${children}
|
|
24826
|
+
return `<g${opacity}>
|
|
24827
|
+
${children}
|
|
24798
24828
|
</g>`;
|
|
24799
24829
|
}
|
|
24800
24830
|
/**
|
|
@@ -24979,12 +25009,26 @@ const KritzelEngine = class {
|
|
|
24979
25009
|
/** Authoritative workspace catalog for this engine instance. When provided, provider-only workspaces are hidden but not deleted. */
|
|
24980
25010
|
workspaces;
|
|
24981
25011
|
async onWorkspacesPropChange() {
|
|
24982
|
-
|
|
25012
|
+
this._workspacesRevision++;
|
|
25013
|
+
if (!this._isYjsInitialized || this._syncInitPromise) {
|
|
24983
25014
|
return;
|
|
24984
25015
|
}
|
|
24985
|
-
|
|
24986
|
-
|
|
24987
|
-
|
|
25016
|
+
const previousReconciliation = this._workspacePropReconciliationPromise;
|
|
25017
|
+
const reconciliationPromise = (async () => {
|
|
25018
|
+
await previousReconciliation;
|
|
25019
|
+
await this.reconcileProvidedWorkspaces();
|
|
25020
|
+
await this.ensureActiveWorkspaceIsVisible();
|
|
25021
|
+
this.workspacesChange.emit(this.getVisibleWorkspaces());
|
|
25022
|
+
})();
|
|
25023
|
+
this._workspacePropReconciliationPromise = reconciliationPromise;
|
|
25024
|
+
try {
|
|
25025
|
+
await reconciliationPromise;
|
|
25026
|
+
}
|
|
25027
|
+
finally {
|
|
25028
|
+
if (this._workspacePropReconciliationPromise === reconciliationPromise) {
|
|
25029
|
+
this._workspacePropReconciliationPromise = null;
|
|
25030
|
+
}
|
|
25031
|
+
}
|
|
24988
25032
|
}
|
|
24989
25033
|
/** Optional unique identifier for namespacing storage keys across multiple editor instances. */
|
|
24990
25034
|
editorId;
|
|
@@ -25038,6 +25082,12 @@ const KritzelEngine = class {
|
|
|
25038
25082
|
onUserChange(newValue) {
|
|
25039
25083
|
this.core.setUser(newValue);
|
|
25040
25084
|
}
|
|
25085
|
+
/** Tool definitions to register with this engine instance. */
|
|
25086
|
+
tools = [];
|
|
25087
|
+
onToolsChange() {
|
|
25088
|
+
this._toolsRevision++;
|
|
25089
|
+
void this.registerConfiguredTools();
|
|
25090
|
+
}
|
|
25041
25091
|
/** Context menu items shown when right-clicking the canvas background. */
|
|
25042
25092
|
globalContextMenuItems;
|
|
25043
25093
|
onGlobalContextMenuItemsChange(newValue) {
|
|
@@ -25228,7 +25278,7 @@ const KritzelEngine = class {
|
|
|
25228
25278
|
}
|
|
25229
25279
|
const hoveredObject = this.core.getObjectFromPointerEvent(ev);
|
|
25230
25280
|
if (hoveredObject &&
|
|
25231
|
-
engine_constants.ObjectHelper.
|
|
25281
|
+
engine_constants.ObjectHelper.isKritzelEmbeddedObject(hoveredObject) &&
|
|
25232
25282
|
KritzelWheelHelper.shouldKeepWheelInDynamicObject(ev, hoveredObject)) {
|
|
25233
25283
|
return;
|
|
25234
25284
|
}
|
|
@@ -25330,7 +25380,7 @@ const KritzelEngine = class {
|
|
|
25330
25380
|
return false;
|
|
25331
25381
|
}
|
|
25332
25382
|
const object = this.core.store.objects.findById(objectElement.id);
|
|
25333
|
-
if (!object || !engine_constants.
|
|
25383
|
+
if (!object || !engine_constants.ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
25334
25384
|
return false;
|
|
25335
25385
|
}
|
|
25336
25386
|
const isSelected = !!this.core.store.selectionGroup?.objects?.some(selectedObject => selectedObject.id === object.id);
|
|
@@ -25340,13 +25390,7 @@ const KritzelEngine = class {
|
|
|
25340
25390
|
if (object.isInteractive !== true) {
|
|
25341
25391
|
return false;
|
|
25342
25392
|
}
|
|
25343
|
-
const potentialRoots =
|
|
25344
|
-
if (object.element instanceof HTMLElement) {
|
|
25345
|
-
potentialRoots.push(object.element);
|
|
25346
|
-
}
|
|
25347
|
-
if (object.elementRef instanceof HTMLElement) {
|
|
25348
|
-
potentialRoots.push(object.elementRef);
|
|
25349
|
-
}
|
|
25393
|
+
const potentialRoots = object.getEmbeddedContentRoots();
|
|
25350
25394
|
if (potentialRoots.length === 0) {
|
|
25351
25395
|
return false;
|
|
25352
25396
|
}
|
|
@@ -25520,7 +25564,7 @@ const KritzelEngine = class {
|
|
|
25520
25564
|
* Switches the active drawing tool by its registered name.
|
|
25521
25565
|
* @param toolName - The name the tool was registered with (e.g., 'brush', 'eraser').
|
|
25522
25566
|
*/
|
|
25523
|
-
async
|
|
25567
|
+
async setActiveTool(toolName) {
|
|
25524
25568
|
const tool = this.core.toolRegistry.getTool(toolName);
|
|
25525
25569
|
if (!tool) {
|
|
25526
25570
|
console.warn(`[KritzelEngine] No tool registered with name: ${toolName}`);
|
|
@@ -26826,9 +26870,13 @@ const KritzelEngine = class {
|
|
|
26826
26870
|
_stateChangeListenersRegistered = false;
|
|
26827
26871
|
_workspaceInitializationPromise = null;
|
|
26828
26872
|
_workspaceInitializationTargetKey = null;
|
|
26873
|
+
_workspacePropReconciliationPromise = null;
|
|
26829
26874
|
_syncInitPromise = null;
|
|
26875
|
+
_toolsInitPromise = null;
|
|
26876
|
+
_toolsRevision = 0;
|
|
26830
26877
|
_syncConfigRevision = 0;
|
|
26831
26878
|
_assetStorageConfigRevision = 0;
|
|
26879
|
+
_workspacesRevision = 0;
|
|
26832
26880
|
_hasLoggedUnlicensedWelcomeBanner = false;
|
|
26833
26881
|
_previousVisibleDynamicObjects = new Set();
|
|
26834
26882
|
_revealedImageKeys = new Set();
|
|
@@ -26841,6 +26889,37 @@ const KritzelEngine = class {
|
|
|
26841
26889
|
undoStackSize: 0,
|
|
26842
26890
|
redoStackSize: 0,
|
|
26843
26891
|
};
|
|
26892
|
+
/** Returns a tool registered in this engine instance. */
|
|
26893
|
+
async getTool(toolName) {
|
|
26894
|
+
await this.registerConfiguredTools();
|
|
26895
|
+
return this.core.toolRegistry.getTool(toolName);
|
|
26896
|
+
}
|
|
26897
|
+
async registerConfiguredTools() {
|
|
26898
|
+
if (this._toolsInitPromise) {
|
|
26899
|
+
return this._toolsInitPromise;
|
|
26900
|
+
}
|
|
26901
|
+
this._toolsInitPromise = (async () => {
|
|
26902
|
+
do {
|
|
26903
|
+
const revision = this._toolsRevision;
|
|
26904
|
+
for (const definition of this.tools) {
|
|
26905
|
+
let toolClass = definition.tool;
|
|
26906
|
+
if (typeof toolClass !== 'function') {
|
|
26907
|
+
toolClass = toolClass.constructor;
|
|
26908
|
+
}
|
|
26909
|
+
await this.registerTool(definition.name, toolClass, definition.config);
|
|
26910
|
+
}
|
|
26911
|
+
if (revision === this._toolsRevision) {
|
|
26912
|
+
break;
|
|
26913
|
+
}
|
|
26914
|
+
} while (true);
|
|
26915
|
+
})();
|
|
26916
|
+
try {
|
|
26917
|
+
await this._toolsInitPromise;
|
|
26918
|
+
}
|
|
26919
|
+
finally {
|
|
26920
|
+
this._toolsInitPromise = null;
|
|
26921
|
+
}
|
|
26922
|
+
}
|
|
26844
26923
|
setLoadingState(isLoading) {
|
|
26845
26924
|
if (this.core.store.state.isLoading === isLoading) {
|
|
26846
26925
|
return;
|
|
@@ -26968,6 +27047,8 @@ const KritzelEngine = class {
|
|
|
26968
27047
|
this.core.licenseManager.destroy();
|
|
26969
27048
|
}
|
|
26970
27049
|
componentWillLoad() {
|
|
27050
|
+
this._toolsRevision++;
|
|
27051
|
+
void this.registerConfiguredTools();
|
|
26971
27052
|
this.core.setEditorId(this.editorId);
|
|
26972
27053
|
if (this.themes && this.themes.length > 0) {
|
|
26973
27054
|
this.core.themeManager.registerThemes(this.themes);
|
|
@@ -27007,7 +27088,9 @@ const KritzelEngine = class {
|
|
|
27007
27088
|
const editorElement = this.host.closest('kritzel-editor');
|
|
27008
27089
|
this.core.themeManager.setTargetElement(editorElement || this.host);
|
|
27009
27090
|
// Initialize sync config and Yjs
|
|
27091
|
+
await this.registerConfiguredTools();
|
|
27010
27092
|
await this.initializeSyncAndWorkspace();
|
|
27093
|
+
await this.waitForWorkspaceAndSceneReady();
|
|
27011
27094
|
if (this.core.store.state.isReady === false) {
|
|
27012
27095
|
this.core.store.state.isReady = true;
|
|
27013
27096
|
this.logUnlicensedWelcomeBanner();
|
|
@@ -27029,6 +27112,20 @@ const KritzelEngine = class {
|
|
|
27029
27112
|
this._syncInitPromise = null;
|
|
27030
27113
|
}
|
|
27031
27114
|
}
|
|
27115
|
+
async waitForSceneRender() {
|
|
27116
|
+
await new Promise(resolve => {
|
|
27117
|
+
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
|
|
27118
|
+
});
|
|
27119
|
+
}
|
|
27120
|
+
async waitForWorkspaceAndSceneReady() {
|
|
27121
|
+
let observedRevision;
|
|
27122
|
+
do {
|
|
27123
|
+
observedRevision = this._workspacesRevision;
|
|
27124
|
+
await this._workspacePropReconciliationPromise;
|
|
27125
|
+
await this.waitForSceneRender();
|
|
27126
|
+
} while (observedRevision !== this._workspacesRevision ||
|
|
27127
|
+
this._workspacePropReconciliationPromise);
|
|
27128
|
+
}
|
|
27032
27129
|
/**
|
|
27033
27130
|
* Initializes the asset storage layer with the latest config. Mirrors
|
|
27034
27131
|
* the in-flight replay logic of {@link doInitializeSyncAndWorkspace} for
|
|
@@ -27411,7 +27508,7 @@ const KritzelEngine = class {
|
|
|
27411
27508
|
if (!engine_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup')) {
|
|
27412
27509
|
return 'auto';
|
|
27413
27510
|
}
|
|
27414
|
-
if (object.objects.length === 1 && engine_constants.
|
|
27511
|
+
if (object.objects.length === 1 && engine_constants.ObjectHelper.isKritzelEmbeddedObject(object.objects[0])) {
|
|
27415
27512
|
return 'none';
|
|
27416
27513
|
}
|
|
27417
27514
|
return 'auto';
|
|
@@ -27419,7 +27516,7 @@ const KritzelEngine = class {
|
|
|
27419
27516
|
// Track visible dynamic objects and unmount culled ones
|
|
27420
27517
|
const currentVisibleDynamicObjects = new Set();
|
|
27421
27518
|
visibleObjects.forEach(object => {
|
|
27422
|
-
if (engine_constants.
|
|
27519
|
+
if (engine_constants.ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
27423
27520
|
currentVisibleDynamicObjects.add(object.id);
|
|
27424
27521
|
}
|
|
27425
27522
|
});
|
|
@@ -27427,7 +27524,7 @@ const KritzelEngine = class {
|
|
|
27427
27524
|
this._previousVisibleDynamicObjects.forEach(id => {
|
|
27428
27525
|
if (!currentVisibleDynamicObjects.has(id)) {
|
|
27429
27526
|
const object = this.core.store.objects.findById(id);
|
|
27430
|
-
if (object && engine_constants.
|
|
27527
|
+
if (object && engine_constants.ObjectHelper.isKritzelEmbeddedObject(object)) {
|
|
27431
27528
|
object.unmount();
|
|
27432
27529
|
}
|
|
27433
27530
|
}
|
|
@@ -27520,7 +27617,7 @@ const KritzelEngine = class {
|
|
|
27520
27617
|
display: 'flex',
|
|
27521
27618
|
alignItems: 'center',
|
|
27522
27619
|
justifyContent: 'center',
|
|
27523
|
-
} }, index.h("kritzel-icon", { name: object.loadState === 'error' ? '
|
|
27620
|
+
} }, index.h("kritzel-icon", { name: object.loadState === 'error' ? 'imageOff' : 'image', size: Math.max(16, Math.min(object.totalWidth, object.totalHeight) * 0.3), style: {
|
|
27524
27621
|
color: engine_constants.KritzelColorHelper.resolveThemeColor({ light: '#9ca3af', dark: '#6b7280' }, currentTheme),
|
|
27525
27622
|
} }))), engine_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelDynamicObject') && (index.h("div", { ref: el => el && object.mount(el), style: {
|
|
27526
27623
|
position: 'absolute',
|
|
@@ -27539,7 +27636,37 @@ const KritzelEngine = class {
|
|
|
27539
27636
|
padding: object.padding + 'px',
|
|
27540
27637
|
overflow: 'visible',
|
|
27541
27638
|
display: 'block',
|
|
27542
|
-
} })), engine_constants.KritzelClassHelper.isInstanceOf(object, '
|
|
27639
|
+
} })), engine_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelIframeObject') && (index.h("div", { style: {
|
|
27640
|
+
position: 'absolute',
|
|
27641
|
+
left: '0',
|
|
27642
|
+
top: '0',
|
|
27643
|
+
width: object.totalWidth + 'px',
|
|
27644
|
+
height: object.totalHeight + 'px',
|
|
27645
|
+
transform: object.rotationDegrees !== 0 ? `rotate(${object.rotationDegrees}deg)` : undefined,
|
|
27646
|
+
transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
|
|
27647
|
+
opacity: effectiveOpacityString,
|
|
27648
|
+
backgroundColor: engine_constants.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
|
|
27649
|
+
borderColor: engine_constants.KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
|
|
27650
|
+
borderWidth: object.borderWidth + 'px',
|
|
27651
|
+
borderStyle: 'solid',
|
|
27652
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
27653
|
+
boxShadow: object.boxShadow,
|
|
27654
|
+
overflow: 'hidden',
|
|
27655
|
+
display: 'block',
|
|
27656
|
+
pointerEvents: object.markedForRemoval ? 'none' : 'auto',
|
|
27657
|
+
} }, index.h("iframe", { ref: element => element && object.mount(element), title: object.title, sandbox: object.sandboxAttribute, style: {
|
|
27658
|
+
display: 'block',
|
|
27659
|
+
width: '100%',
|
|
27660
|
+
height: '100%',
|
|
27661
|
+
border: '0',
|
|
27662
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
27663
|
+
pointerEvents: object.isInteractive ? 'auto' : 'none',
|
|
27664
|
+
} }), index.h("div", { style: {
|
|
27665
|
+
position: 'absolute',
|
|
27666
|
+
inset: '0',
|
|
27667
|
+
borderRadius: object.borderRadius !== undefined ? (typeof object.borderRadius === 'number' ? `${object.borderRadius}px` : object.borderRadius) : undefined,
|
|
27668
|
+
pointerEvents: object.isInteractive ? 'none' : 'auto',
|
|
27669
|
+
} }))), engine_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') && !this.core.displaySelectionLineUI(object) && (index.h("div", { ref: el => el && object.mount(el), style: {
|
|
27543
27670
|
position: 'absolute',
|
|
27544
27671
|
left: '0',
|
|
27545
27672
|
top: '0',
|
|
@@ -27897,6 +28024,9 @@ const KritzelEngine = class {
|
|
|
27897
28024
|
"user": [{
|
|
27898
28025
|
"onUserChange": 0
|
|
27899
28026
|
}],
|
|
28027
|
+
"tools": [{
|
|
28028
|
+
"onToolsChange": 0
|
|
28029
|
+
}],
|
|
27900
28030
|
"globalContextMenuItems": [{
|
|
27901
28031
|
"onGlobalContextMenuItemsChange": 0
|
|
27902
28032
|
}],
|
|
@@ -27961,6 +28091,20 @@ const KritzelIcon = class {
|
|
|
27961
28091
|
name;
|
|
27962
28092
|
label;
|
|
27963
28093
|
size = 24;
|
|
28094
|
+
unsubscribe;
|
|
28095
|
+
connectedCallback() {
|
|
28096
|
+
this.unsubscribe?.();
|
|
28097
|
+
this.unsubscribe = engine_constants.KritzelIconRegistry.subscribe(name => {
|
|
28098
|
+
if (name === this.name) {
|
|
28099
|
+
index.forceUpdate(this);
|
|
28100
|
+
}
|
|
28101
|
+
});
|
|
28102
|
+
index.forceUpdate(this);
|
|
28103
|
+
}
|
|
28104
|
+
disconnectedCallback() {
|
|
28105
|
+
this.unsubscribe?.();
|
|
28106
|
+
this.unsubscribe = undefined;
|
|
28107
|
+
}
|
|
27964
28108
|
render() {
|
|
27965
28109
|
const svgContent = engine_constants.KritzelIconRegistry.get(this.name);
|
|
27966
28110
|
if (!svgContent) {
|
|
@@ -27976,7 +28120,7 @@ const KritzelIcon = class {
|
|
|
27976
28120
|
};
|
|
27977
28121
|
KritzelIcon.style = kritzelIconCss();
|
|
27978
28122
|
|
|
27979
|
-
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}`;
|
|
28123
|
+
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}`;
|
|
27980
28124
|
|
|
27981
28125
|
const KritzelWatermark = class {
|
|
27982
28126
|
constructor(hostRef) {
|
|
@@ -27992,7 +28136,7 @@ const KritzelWatermark = class {
|
|
|
27992
28136
|
label;
|
|
27993
28137
|
render() {
|
|
27994
28138
|
const label = this.label ?? this.core.localizationManager.translate('watermark.poweredBy');
|
|
27995
|
-
return (index.h(index.Host, { key: '
|
|
28139
|
+
return (index.h(index.Host, { key: '5bc76650ecd1f82f5ed283d4433b0e5fc8937cab' }, index.h("a", { key: 'b0828f36df618e461794772d2e8f55c0a8cb357e', class: "watermark-link", href: engine_constants.KRITZEL_WEBSITE_URL, target: "_blank", rel: "noopener noreferrer", part: "watermark", onPointerDown: (ev) => ev.stopPropagation(), onPointerUp: (ev) => ev.stopPropagation() }, label)));
|
|
27996
28140
|
}
|
|
27997
28141
|
};
|
|
27998
28142
|
KritzelWatermark.style = kritzelWatermarkCss();
|