kritzel-stencil 0.1.73 → 0.1.75
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/dist/cjs/index-Dc7LOVhs.js +2 -2
- package/dist/cjs/index.cjs.js +131 -86
- package/dist/cjs/{kritzel-active-users_41.cjs.entry.js → kritzel-active-users_42.cjs.entry.js} +593 -177
- package/dist/cjs/kritzel-brush-style.cjs.entry.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/stencil.cjs.js +1 -1
- package/dist/cjs/{workspace.migrations-DcwqsqPC.js → workspace.migrations-DkmVO6dE.js} +164 -49
- package/dist/collection/classes/core/core.class.js +9 -1
- package/dist/collection/classes/core/store.class.js +20 -6
- package/dist/collection/classes/core/viewport.class.js +9 -3
- package/dist/collection/classes/handlers/selection.handler.js +15 -2
- package/dist/collection/classes/managers/anchor.manager.js +101 -44
- package/dist/collection/classes/objects/base-object.class.js +2 -0
- package/dist/collection/classes/objects/custom-element.class.js +1 -0
- package/dist/collection/classes/objects/group.class.js +1 -0
- package/dist/collection/classes/objects/image.class.js +1 -0
- package/dist/collection/classes/objects/line.class.js +1 -0
- package/dist/collection/classes/objects/path.class.js +1 -0
- package/dist/collection/classes/objects/selection-box.class.js +1 -0
- package/dist/collection/classes/objects/selection-group.class.js +13 -1
- package/dist/collection/classes/objects/shape.class.js +1 -0
- package/dist/collection/classes/objects/text.class.js +1 -0
- package/dist/collection/classes/providers/broadcast-sync-provider.class.js +5 -0
- package/dist/collection/classes/providers/hocuspocus-sync-provider.class.js +120 -85
- package/dist/collection/classes/providers/indexeddb-sync-provider.class.js +5 -0
- package/dist/collection/classes/providers/websocket-sync-provider.class.js +5 -0
- package/dist/collection/classes/structures/app-state-map.structure.js +15 -4
- package/dist/collection/classes/structures/object-map.structure.js +85 -7
- package/dist/collection/classes/tools/brush-tool.class.js +4 -0
- package/dist/collection/classes/tools/line-tool.class.js +4 -0
- package/dist/collection/classes/tools/shape-tool.class.js +2 -0
- package/dist/collection/collection-manifest.json +3 -2
- package/dist/collection/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.css +110 -0
- package/dist/collection/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.js +347 -0
- package/dist/collection/components/core/kritzel-cursor-trail/kritzel-cursor-trail.js +1 -1
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +3 -3
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +150 -109
- package/dist/collection/components/shared/kritzel-avatar/kritzel-avatar.js +3 -3
- package/dist/collection/components/shared/kritzel-brush-style/kritzel-brush-style.js +1 -1
- package/dist/collection/components/shared/kritzel-button/kritzel-button.js +2 -2
- package/dist/collection/components/shared/kritzel-color/kritzel-color.js +2 -2
- package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.js +1 -1
- package/dist/collection/components/shared/kritzel-dropdown/kritzel-dropdown.js +1 -1
- package/dist/collection/components/shared/kritzel-font/kritzel-font.js +1 -1
- package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.js +1 -1
- package/dist/collection/components/shared/kritzel-input/kritzel-input.js +1 -1
- package/dist/collection/components/shared/kritzel-master-detail/kritzel-master-detail.js +3 -3
- package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js +1 -1
- package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.js +2 -2
- package/dist/collection/components/shared/kritzel-numeric-input/kritzel-numeric-input.js +1 -1
- package/dist/collection/components/shared/kritzel-opacity-slider/kritzel-opacity-slider.js +1 -1
- package/dist/collection/components/shared/kritzel-portal/kritzel-portal.js +1 -1
- package/dist/collection/components/shared/kritzel-slide-toggle/kritzel-slide-toggle.js +1 -1
- package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js +1 -1
- package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.js +1 -1
- package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.js +2 -2
- package/dist/collection/components/ui/kritzel-back-to-content/kritzel-back-to-content.js +1 -1
- package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.js +1 -1
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +5 -5
- package/dist/collection/components/ui/kritzel-current-user/kritzel-current-user.js +1 -1
- package/dist/collection/components/ui/kritzel-current-user-dialog/kritzel-current-user-dialog.js +1 -1
- package/dist/collection/components/ui/kritzel-export/kritzel-export.js +1 -1
- package/dist/collection/components/ui/kritzel-login-dialog/kritzel-login-dialog.js +1 -1
- package/dist/collection/components/ui/kritzel-more-menu/kritzel-more-menu.js +1 -1
- package/dist/collection/components/ui/kritzel-settings/kritzel-settings.js +1 -1
- package/dist/collection/components/ui/kritzel-share-dialog/kritzel-share-dialog.js +2 -2
- package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js +1 -1
- package/dist/collection/constants/schema.constants.js +1 -1
- package/dist/collection/constants/version.js +1 -1
- package/dist/collection/interfaces/remote-cursor.interface.js +1 -0
- package/dist/collection/migrations/workspace.migrations.js +10 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +1 -1
- package/dist/components/kritzel-active-users.js +1 -1
- package/dist/components/kritzel-avatar.js +1 -1
- package/dist/components/kritzel-awareness-cursors.d.ts +11 -0
- package/dist/components/kritzel-awareness-cursors.js +1 -0
- package/dist/components/kritzel-back-to-content.js +1 -1
- package/dist/components/kritzel-brush-style.js +1 -1
- package/dist/components/kritzel-button.js +1 -1
- package/dist/components/kritzel-color-palette.js +1 -1
- package/dist/components/kritzel-color.js +1 -1
- package/dist/components/kritzel-context-menu.js +1 -1
- package/dist/components/kritzel-controls.js +1 -1
- package/dist/components/kritzel-current-user-dialog.js +1 -1
- package/dist/components/kritzel-current-user.js +1 -1
- package/dist/components/kritzel-cursor-trail.js +1 -1
- package/dist/components/kritzel-dropdown.js +1 -1
- package/dist/components/kritzel-editor.js +1 -1
- package/dist/components/kritzel-engine.js +1 -1
- package/dist/components/kritzel-export.js +1 -1
- package/dist/components/kritzel-font-family.js +1 -1
- package/dist/components/kritzel-font-size.js +1 -1
- package/dist/components/kritzel-font.js +1 -1
- package/dist/components/kritzel-input.js +1 -1
- package/dist/components/kritzel-login-dialog.js +1 -1
- package/dist/components/kritzel-master-detail.js +1 -1
- package/dist/components/kritzel-menu-item.js +1 -1
- package/dist/components/kritzel-menu.js +1 -1
- package/dist/components/kritzel-more-menu.js +1 -1
- package/dist/components/kritzel-numeric-input.js +1 -1
- package/dist/components/kritzel-opacity-slider.js +1 -1
- package/dist/components/kritzel-portal.js +1 -1
- package/dist/components/kritzel-settings.js +1 -1
- package/dist/components/kritzel-share-dialog.js +1 -1
- package/dist/components/kritzel-slide-toggle.js +1 -1
- package/dist/components/kritzel-split-button.js +1 -1
- package/dist/components/kritzel-stroke-size.js +1 -1
- package/dist/components/kritzel-tool-config.js +1 -1
- package/dist/components/kritzel-tooltip.js +1 -1
- package/dist/components/kritzel-utility-panel.js +1 -1
- package/dist/components/kritzel-workspace-manager.js +1 -1
- package/dist/components/{p-Dp8idtVD.js → p-0kShCfeb.js} +1 -1
- package/dist/components/{p-B47JuZiD.js → p-2OYw6GJ7.js} +1 -1
- package/dist/components/p-7o2FWtFx.js +1 -0
- package/dist/components/{p-C5KuV1pK.js → p-BA0ayKqO.js} +1 -1
- package/dist/components/{p-NbNVTRk6.js → p-BEJQ2kP7.js} +1 -1
- package/dist/components/p-BSipRoFx.js +1 -0
- package/dist/components/{p-CDadAOMw.js → p-BeFUNGEI.js} +1 -1
- package/dist/components/{p-35nrk8s0.js → p-BiByyU2C.js} +1 -1
- package/dist/components/{p-CCAWSyDD.js → p-BiouZo1q.js} +1 -1
- package/dist/components/{p-CSExtYKI.js → p-ByR0VXeU.js} +1 -1
- package/dist/components/{p-1MGcXTLv.js → p-C1uR_ZNW.js} +1 -1
- package/dist/components/{p-x8PzaMuD.js → p-C69Stayh.js} +1 -1
- package/dist/components/{p-Ch0UlFwq.js → p-C7SBI_0T.js} +1 -1
- package/dist/components/{p-DEzfXrGX.js → p-CAIGuV2J.js} +1 -1
- package/dist/components/p-CJ2eHeoV.js +1 -0
- package/dist/components/p-CW-VyJgK.js +1 -0
- package/dist/components/{p-DW4ADV9w.js → p-CZhyKp-f.js} +1 -1
- package/dist/components/p-CsR4owzk.js +1 -0
- package/dist/components/{p-BG1IxseV.js → p-CsoDfhD5.js} +1 -1
- package/dist/components/{p-BgDhcDNw.js → p-D0MQFmqi.js} +1 -1
- package/dist/components/{p-DpFu5yAt.js → p-D1O7DxL4.js} +1 -1
- package/dist/components/{p-B5ouV8EQ.js → p-DRbG92F9.js} +1 -1
- package/dist/components/{p-C3eaM9TB.js → p-DS0xx1eT.js} +1 -1
- package/dist/components/{p-jx8VOz7S.js → p-DSzQ6H2j.js} +1 -1
- package/dist/components/{p-DsIlDGDO.js → p-DXjuuVq9.js} +1 -1
- package/dist/components/p-DXpYcAnT.js +1 -0
- package/dist/components/{p-DiFVw6IQ.js → p-Da46jw3N.js} +1 -1
- package/dist/components/{p-C6kZf91d.js → p-Dj_Qjga5.js} +1 -1
- package/dist/components/{p-Do0Q5-iC.js → p-DvIEvoZu.js} +1 -1
- package/dist/components/{p-CnVzLD5e.js → p-GYI7sDxr.js} +1 -1
- package/dist/components/{p-CcBM_ClD.js → p-HLbqRJGs.js} +1 -1
- package/dist/components/{p-VHyNcODZ.js → p-KQzWumjB.js} +1 -1
- package/dist/components/{p-VAkeZOZL.js → p-TyR-YTXm.js} +1 -1
- package/dist/components/p-WmxufeOo.js +9 -0
- package/dist/components/{p-CHtn5xr6.js → p-b4gyXoju.js} +1 -1
- package/dist/components/p-iRL0wQHQ.js +1 -0
- package/dist/components/{p-CqLaHE27.js → p-kj9wbLY8.js} +1 -1
- package/dist/components/{p-DaHq4iG1.js → p-xM-_OeRO.js} +1 -1
- package/dist/esm/index-MV-81ybv.js +2 -2
- package/dist/esm/index.js +132 -87
- package/dist/esm/{kritzel-active-users_41.entry.js → kritzel-active-users_42.entry.js} +593 -178
- package/dist/esm/kritzel-brush-style.entry.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/stencil.js +1 -1
- package/dist/esm/{workspace.migrations-BGixvB76.js → workspace.migrations-D48_Bqvh.js} +164 -49
- package/dist/stencil/index.esm.js +1 -1
- package/dist/stencil/p-0dbd9a2f.entry.js +9 -0
- package/dist/stencil/p-D48_Bqvh.js +1 -0
- package/dist/stencil/{p-016ad76a.entry.js → p-fc21e29c.entry.js} +1 -1
- package/dist/stencil/stencil.esm.js +1 -1
- package/dist/types/classes/core/store.class.d.ts +10 -2
- package/dist/types/classes/managers/anchor.manager.d.ts +4 -0
- package/dist/types/classes/objects/base-object.class.d.ts +1 -0
- package/dist/types/classes/objects/selection-group.class.d.ts +5 -0
- package/dist/types/classes/providers/broadcast-sync-provider.class.d.ts +2 -0
- package/dist/types/classes/providers/hocuspocus-sync-provider.class.d.ts +37 -1
- package/dist/types/classes/providers/indexeddb-sync-provider.class.d.ts +2 -0
- package/dist/types/classes/providers/websocket-sync-provider.class.d.ts +2 -0
- package/dist/types/classes/structures/object-map.structure.d.ts +38 -0
- package/dist/types/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.d.ts +26 -0
- package/dist/types/components.d.ts +39 -4
- package/dist/types/constants/schema.constants.d.ts +1 -1
- package/dist/types/constants/version.d.ts +1 -1
- package/dist/types/interfaces/object.interface.d.ts +1 -0
- package/dist/types/interfaces/remote-cursor.interface.d.ts +17 -0
- package/dist/types/interfaces/sync-provider.interface.d.ts +16 -0
- package/dist/types/interfaces/theme.interface.d.ts +7 -0
- package/package.json +1 -1
- package/dist/components/p-BvToKcu1.js +0 -1
- package/dist/components/p-By3NOY-k.js +0 -9
- package/dist/components/p-CNro30tB.js +0 -1
- package/dist/components/p-Duv3EM3w.js +0 -1
- package/dist/components/p-KFsLHwYm.js +0 -1
- package/dist/components/p-hCORwbZh.js +0 -1
- package/dist/stencil/p-67c79d75.entry.js +0 -9
- package/dist/stencil/p-BGixvB76.js +0 -1
|
@@ -266,6 +266,7 @@ class KritzelBaseObject {
|
|
|
266
266
|
rotation = 0;
|
|
267
267
|
markedForRemoval = false;
|
|
268
268
|
zIndex = 0;
|
|
269
|
+
userId;
|
|
269
270
|
/** Whether the object is currently visible on the canvas */
|
|
270
271
|
isVisible = true;
|
|
271
272
|
isSelected = false;
|
|
@@ -446,6 +447,7 @@ class KritzelBaseObject {
|
|
|
446
447
|
object._core = core;
|
|
447
448
|
object.zIndex = core.store.currentZIndex;
|
|
448
449
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
450
|
+
object.userId = core.user?.id;
|
|
449
451
|
return object;
|
|
450
452
|
}
|
|
451
453
|
/**
|
|
@@ -15296,6 +15298,7 @@ class KritzelText extends KritzelBaseObject {
|
|
|
15296
15298
|
object._core = core;
|
|
15297
15299
|
object.id = object.generateId();
|
|
15298
15300
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
15301
|
+
object.userId = core.user?.id;
|
|
15299
15302
|
object.fontSize = fontSize;
|
|
15300
15303
|
object.fontFamily = fontFamily;
|
|
15301
15304
|
object.translateX = 0;
|
|
@@ -15685,6 +15688,7 @@ class KritzelPath extends KritzelBaseObject {
|
|
|
15685
15688
|
object._core = core;
|
|
15686
15689
|
object.id = object.generateId();
|
|
15687
15690
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
15691
|
+
object.userId = core.user?.id;
|
|
15688
15692
|
object.options = options;
|
|
15689
15693
|
object.points = options?.points ?? [];
|
|
15690
15694
|
object.translateX = options?.translateX ?? 0;
|
|
@@ -16186,6 +16190,7 @@ class KritzelImage extends KritzelBaseObject {
|
|
|
16186
16190
|
object._core = core;
|
|
16187
16191
|
object.id = object.generateId();
|
|
16188
16192
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
16193
|
+
object.userId = core.user?.id;
|
|
16189
16194
|
object.x = 0;
|
|
16190
16195
|
object.y = 0;
|
|
16191
16196
|
object.translateX = 0;
|
|
@@ -16336,6 +16341,7 @@ class KritzelLine extends KritzelBaseObject {
|
|
|
16336
16341
|
object._core = core;
|
|
16337
16342
|
object.id = object.generateId();
|
|
16338
16343
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
16344
|
+
object.userId = core.user?.id;
|
|
16339
16345
|
object.options = options;
|
|
16340
16346
|
object.startX = options?.startX ?? 0;
|
|
16341
16347
|
object.startY = options?.startY ?? 0;
|
|
@@ -17095,6 +17101,7 @@ class KritzelGroup extends KritzelBaseObject {
|
|
|
17095
17101
|
group._core = core;
|
|
17096
17102
|
group.id = group.generateId();
|
|
17097
17103
|
group.workspaceId = core.store.state.activeWorkspace.id;
|
|
17104
|
+
group.userId = core.user?.id;
|
|
17098
17105
|
group.scale = core.store.state.scale;
|
|
17099
17106
|
group.zIndex = core.store.currentZIndex;
|
|
17100
17107
|
return group;
|
|
@@ -17646,6 +17653,7 @@ class KritzelShape extends KritzelBaseObject {
|
|
|
17646
17653
|
object._core = core;
|
|
17647
17654
|
object.id = object.generateId();
|
|
17648
17655
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
17656
|
+
object.userId = core.user?.id;
|
|
17649
17657
|
object.x = config?.x ?? 0;
|
|
17650
17658
|
object.y = config?.y ?? 0;
|
|
17651
17659
|
object.translateX = config?.translateX ?? 0;
|
|
@@ -18326,6 +18334,7 @@ class KritzelBrushTool extends KritzelBaseTool {
|
|
|
18326
18334
|
path.isCompleted = false;
|
|
18327
18335
|
this._currentPathId = path.id;
|
|
18328
18336
|
this._core.store.state.objects.insert(path);
|
|
18337
|
+
this._core.store.state.objects?.setActiveDrawingObject(path.id);
|
|
18329
18338
|
}
|
|
18330
18339
|
}
|
|
18331
18340
|
if (event.pointerType === 'touch' || event.pointerType === 'pen') {
|
|
@@ -18349,6 +18358,7 @@ class KritzelBrushTool extends KritzelBaseTool {
|
|
|
18349
18358
|
path.isCompleted = false;
|
|
18350
18359
|
this._currentPathId = path.id;
|
|
18351
18360
|
this._core.store.state.objects.insert(path);
|
|
18361
|
+
this._core.store.state.objects?.setActiveDrawingObject(path.id);
|
|
18352
18362
|
}
|
|
18353
18363
|
}
|
|
18354
18364
|
}
|
|
@@ -18439,6 +18449,7 @@ class KritzelBrushTool extends KritzelBaseTool {
|
|
|
18439
18449
|
this._core.engine.emitObjectsChange();
|
|
18440
18450
|
this._core.engine.emitObjectsAdded([currentPath]);
|
|
18441
18451
|
}
|
|
18452
|
+
this._core.store.state.objects?.setActiveDrawingObject(null);
|
|
18442
18453
|
this._currentPathId = null;
|
|
18443
18454
|
}
|
|
18444
18455
|
}
|
|
@@ -18454,6 +18465,7 @@ class KritzelBrushTool extends KritzelBaseTool {
|
|
|
18454
18465
|
this._core.engine.emitObjectsChange();
|
|
18455
18466
|
this._core.engine.emitObjectsAdded([currentPath]);
|
|
18456
18467
|
}
|
|
18468
|
+
this._core.store.state.objects?.setActiveDrawingObject(null);
|
|
18457
18469
|
this._currentPathId = null;
|
|
18458
18470
|
}
|
|
18459
18471
|
}
|
|
@@ -18484,6 +18496,10 @@ class KritzelSelectionGroup extends KritzelBaseObject {
|
|
|
18484
18496
|
maxX;
|
|
18485
18497
|
minY;
|
|
18486
18498
|
maxY;
|
|
18499
|
+
// Selection styling properties
|
|
18500
|
+
handleColor;
|
|
18501
|
+
handleStrokeColor;
|
|
18502
|
+
handleSize = 6;
|
|
18487
18503
|
/**
|
|
18488
18504
|
* Gets the array of object IDs contained in this selection group.
|
|
18489
18505
|
* @returns Array of string IDs for the selected objects
|
|
@@ -18538,6 +18554,7 @@ class KritzelSelectionGroup extends KritzelBaseObject {
|
|
|
18538
18554
|
/**
|
|
18539
18555
|
* Factory method to create a new KritzelSelectionGroup instance.
|
|
18540
18556
|
* Initializes the selection group with default properties and associates it with the core instance.
|
|
18557
|
+
* Default styling uses values from the theme system (selection section).
|
|
18541
18558
|
* @param core - The KritzelCore instance to associate with this selection group
|
|
18542
18559
|
* @returns A new KritzelSelectionGroup instance configured with default settings
|
|
18543
18560
|
*/
|
|
@@ -18546,8 +18563,15 @@ class KritzelSelectionGroup extends KritzelBaseObject {
|
|
|
18546
18563
|
object._core = core;
|
|
18547
18564
|
object.id = object.generateId();
|
|
18548
18565
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
18566
|
+
object.userId = core.user?.id;
|
|
18549
18567
|
object.scale = core.store.state.scale;
|
|
18550
18568
|
object.zIndex = 99999;
|
|
18569
|
+
// Initialize styling with theme-aware defaults
|
|
18570
|
+
object.borderColor = { light: '#007AFF', dark: '#0A84FF' };
|
|
18571
|
+
object.borderWidth = 2;
|
|
18572
|
+
object.handleColor = { light: '#ffffff', dark: '#1a1a1a' };
|
|
18573
|
+
object.handleStrokeColor = { light: '#007AFF', dark: '#0A84FF' };
|
|
18574
|
+
object.handleSize = 6;
|
|
18551
18575
|
return object;
|
|
18552
18576
|
}
|
|
18553
18577
|
/**
|
|
@@ -18713,7 +18737,7 @@ class KritzelSelectionGroup extends KritzelBaseObject {
|
|
|
18713
18737
|
* @returns A serializable object representation of the selection group
|
|
18714
18738
|
*/
|
|
18715
18739
|
serialize() {
|
|
18716
|
-
const { _core, _elementRef, element, totalWidth, totalHeight, unchangedObjectSnapshots, _cachedObjects, _cachedObjectIdsHash, snapshotWidth, snapshotHeight, snapshotTranslateX, snapshotTranslateY, ...remainingProps } = this;
|
|
18740
|
+
const { _core, _elementRef, element, totalWidth, totalHeight, unchangedObjectSnapshots, _cachedObjects, _cachedObjectIdsHash, snapshotWidth, snapshotHeight, snapshotTranslateX, snapshotTranslateY, snapshotRotation, ...remainingProps } = this;
|
|
18717
18741
|
const clonedProps = structuredClone(remainingProps);
|
|
18718
18742
|
// Ensure objectIds is serialized with the correct key name (getter returns _objectIds)
|
|
18719
18743
|
clonedProps.objectIds = this.objectIds;
|
|
@@ -19103,6 +19127,7 @@ class KritzelLineTool extends KritzelBaseTool {
|
|
|
19103
19127
|
line.isCompleted = false;
|
|
19104
19128
|
this._currentLineId = line.id;
|
|
19105
19129
|
this._core.store.state.objects.insert(line);
|
|
19130
|
+
this._core.store.state.objects?.setActiveDrawingObject(line.id);
|
|
19106
19131
|
}
|
|
19107
19132
|
}
|
|
19108
19133
|
if (event.pointerType === 'touch' || event.pointerType === 'pen') {
|
|
@@ -19132,6 +19157,7 @@ class KritzelLineTool extends KritzelBaseTool {
|
|
|
19132
19157
|
line.isCompleted = false;
|
|
19133
19158
|
this._currentLineId = line.id;
|
|
19134
19159
|
this._core.store.state.objects.insert(line);
|
|
19160
|
+
this._core.store.state.objects?.setActiveDrawingObject(line.id);
|
|
19135
19161
|
}
|
|
19136
19162
|
}
|
|
19137
19163
|
}
|
|
@@ -19230,6 +19256,7 @@ class KritzelLineTool extends KritzelBaseTool {
|
|
|
19230
19256
|
// Switch to selection tool and select the drawn line
|
|
19231
19257
|
this.selectLineAndSwitchTool(currentLine);
|
|
19232
19258
|
}
|
|
19259
|
+
this._core.store.state.objects?.setActiveDrawingObject(null);
|
|
19233
19260
|
this._currentLineId = null;
|
|
19234
19261
|
}
|
|
19235
19262
|
}
|
|
@@ -19247,6 +19274,7 @@ class KritzelLineTool extends KritzelBaseTool {
|
|
|
19247
19274
|
// Switch to selection tool and select the drawn line
|
|
19248
19275
|
this.selectLineAndSwitchTool(currentLine);
|
|
19249
19276
|
}
|
|
19277
|
+
this._core.store.state.objects?.setActiveDrawingObject(null);
|
|
19250
19278
|
this._currentLineId = null;
|
|
19251
19279
|
}
|
|
19252
19280
|
}
|
|
@@ -19828,6 +19856,7 @@ class KritzelShapeTool extends KritzelBaseTool {
|
|
|
19828
19856
|
scale: lockScale ? 1 : viewportScale,
|
|
19829
19857
|
});
|
|
19830
19858
|
this._core.store.state.objects.insert(this.currentShape);
|
|
19859
|
+
this._core.store.state.objects?.setActiveDrawingObject(this.currentShape.id);
|
|
19831
19860
|
this._core.rerender();
|
|
19832
19861
|
}
|
|
19833
19862
|
/**
|
|
@@ -19888,6 +19917,7 @@ class KritzelShapeTool extends KritzelBaseTool {
|
|
|
19888
19917
|
this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
|
|
19889
19918
|
}
|
|
19890
19919
|
this.isDrawing = false;
|
|
19920
|
+
this._core.store.state.objects?.setActiveDrawingObject(null);
|
|
19891
19921
|
this.currentShape = null;
|
|
19892
19922
|
this._core.rerender();
|
|
19893
19923
|
}
|
|
@@ -20838,6 +20868,7 @@ class KritzelSelectionBox extends KritzelBaseObject {
|
|
|
20838
20868
|
object._core = core;
|
|
20839
20869
|
object.id = object.generateId();
|
|
20840
20870
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
20871
|
+
object.userId = core.user?.id;
|
|
20841
20872
|
object.scale = core.store.state.scale;
|
|
20842
20873
|
object.zIndex = 99999;
|
|
20843
20874
|
object.backgroundColor = { light: 'rgba(0, 122, 255, 0.2)', dark: 'rgba(0, 122, 255, 0.2)' };
|
|
@@ -21002,6 +21033,7 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
|
|
|
21002
21033
|
this._core.store.state.isSelecting = false;
|
|
21003
21034
|
this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox);
|
|
21004
21035
|
this._core.store.setSelectionBox(null);
|
|
21036
|
+
this._core.store.state.objects.clearLocalSelectionBox();
|
|
21005
21037
|
}
|
|
21006
21038
|
/**
|
|
21007
21039
|
* Initiates a mouse-based selection by creating a selection box at the click position.
|
|
@@ -21020,7 +21052,7 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
|
|
|
21020
21052
|
selectionBox.translateX = this.startX;
|
|
21021
21053
|
selectionBox.translateY = this.startY;
|
|
21022
21054
|
this._core.store.state.isSelecting = true;
|
|
21023
|
-
this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox || (!isAdditive && o instanceof KritzelSelectionGroup));
|
|
21055
|
+
this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox || (!isAdditive && o instanceof KritzelSelectionGroup && (o.userId == null || o.userId === this._core.user?.id)));
|
|
21024
21056
|
this._core.store.setSelectionBox(null);
|
|
21025
21057
|
if (!isAdditive) {
|
|
21026
21058
|
this._core.store.setSelectionGroup(null);
|
|
@@ -21052,7 +21084,7 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
|
|
|
21052
21084
|
selectionBox.translateX = this.startX;
|
|
21053
21085
|
selectionBox.translateY = this.startY;
|
|
21054
21086
|
this._core.store.state.isSelecting = true;
|
|
21055
|
-
this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox || (!isAdditive && o instanceof KritzelSelectionGroup));
|
|
21087
|
+
this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox || (!isAdditive && o instanceof KritzelSelectionGroup && (o.userId == null || o.userId === this._core.user?.id)));
|
|
21056
21088
|
this._core.store.setSelectionBox(null);
|
|
21057
21089
|
if (!isAdditive) {
|
|
21058
21090
|
this._core.store.setSelectionGroup(null);
|
|
@@ -21080,6 +21112,12 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
|
|
|
21080
21112
|
selectionBox.height = height;
|
|
21081
21113
|
selectionBox.translateX = Math.min(currentX, this.startX);
|
|
21082
21114
|
selectionBox.translateY = Math.min(currentY, this.startY);
|
|
21115
|
+
this._core.store.state.objects.setLocalSelectionBox({
|
|
21116
|
+
x: selectionBox.translateX,
|
|
21117
|
+
y: selectionBox.translateY,
|
|
21118
|
+
width: width / selectionBox.scale,
|
|
21119
|
+
height: height / selectionBox.scale,
|
|
21120
|
+
});
|
|
21083
21121
|
if (width > 0 || height > 0) {
|
|
21084
21122
|
this.updateSelectedObjects();
|
|
21085
21123
|
}
|
|
@@ -21113,6 +21151,12 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
|
|
|
21113
21151
|
selectionBox.height = height;
|
|
21114
21152
|
selectionBox.translateX = Math.min(currentX, this.startX);
|
|
21115
21153
|
selectionBox.translateY = Math.min(currentY, this.startY);
|
|
21154
|
+
this._core.store.state.objects.setLocalSelectionBox({
|
|
21155
|
+
x: selectionBox.translateX,
|
|
21156
|
+
y: selectionBox.translateY,
|
|
21157
|
+
width: width / selectionBox.scale,
|
|
21158
|
+
height: height / selectionBox.scale,
|
|
21159
|
+
});
|
|
21116
21160
|
if (width > 0 || height > 0) {
|
|
21117
21161
|
this.updateSelectedObjects();
|
|
21118
21162
|
}
|
|
@@ -22342,6 +22386,7 @@ class KritzelSelectionTool extends KritzelBaseTool {
|
|
|
22342
22386
|
* IndexedDB sync provider for local persistence
|
|
22343
22387
|
*/
|
|
22344
22388
|
class IndexedDBSyncProvider {
|
|
22389
|
+
type = 'local';
|
|
22345
22390
|
provider;
|
|
22346
22391
|
isConnected = false;
|
|
22347
22392
|
constructor(docName, doc, options) {
|
|
@@ -22363,6 +22408,10 @@ class IndexedDBSyncProvider {
|
|
|
22363
22408
|
// IndexedDB doesn't need explicit disconnect
|
|
22364
22409
|
this.isConnected = false;
|
|
22365
22410
|
}
|
|
22411
|
+
async reconnect() {
|
|
22412
|
+
this.disconnect();
|
|
22413
|
+
return this.connect();
|
|
22414
|
+
}
|
|
22366
22415
|
destroy() {
|
|
22367
22416
|
if (this.provider) {
|
|
22368
22417
|
this.provider.destroy();
|
|
@@ -25558,16 +25607,22 @@ class KritzelAnchorManager {
|
|
|
25558
25607
|
if (!KritzelClassHelper.isInstanceOf(selectedObject, 'KritzelLine'))
|
|
25559
25608
|
return null;
|
|
25560
25609
|
const line = selectedObject;
|
|
25561
|
-
const
|
|
25562
|
-
const
|
|
25610
|
+
const startAnchorVizRaw = this.computeAnchorVisualization(line, 'start');
|
|
25611
|
+
const endAnchorVizRaw = this.computeAnchorVisualization(line, 'end');
|
|
25612
|
+
const startAnchorViz = this.isFiniteAnchorVisualization(startAnchorVizRaw) ? startAnchorVizRaw : null;
|
|
25613
|
+
const endAnchorViz = this.isFiniteAnchorVisualization(endAnchorVizRaw) ? endAnchorVizRaw : null;
|
|
25563
25614
|
if (!startAnchorViz && !endAnchorViz)
|
|
25564
25615
|
return null;
|
|
25565
|
-
const scale = this._core.store.state.scale;
|
|
25566
|
-
const
|
|
25616
|
+
const scale = this.getSafeScale(this._core.store.state.scale);
|
|
25617
|
+
const lineScale = this.getSafeScale(line.scale);
|
|
25618
|
+
const lineStrokeWidth = line.strokeWidth / lineScale;
|
|
25567
25619
|
const indicatorStrokeWidth = `${2 / scale}`;
|
|
25568
25620
|
const dashLength = Math.max(lineStrokeWidth * 2, 4 / scale);
|
|
25569
25621
|
const dashArray = `${dashLength} ${dashLength}`;
|
|
25570
25622
|
const indicatorRadius = 8 / scale;
|
|
25623
|
+
if (!this.areFiniteNumbers(lineStrokeWidth, dashLength, indicatorRadius)) {
|
|
25624
|
+
return null;
|
|
25625
|
+
}
|
|
25571
25626
|
return {
|
|
25572
25627
|
lineStrokeWidth,
|
|
25573
25628
|
indicatorStrokeWidth,
|
|
@@ -25589,31 +25644,39 @@ class KritzelAnchorManager {
|
|
|
25589
25644
|
const snapCandidate = this.getSnapCandidate();
|
|
25590
25645
|
if (!snapCandidate)
|
|
25591
25646
|
return null;
|
|
25592
|
-
|
|
25647
|
+
if (!this.areFiniteNumbers(snapCandidate.centerX, snapCandidate.centerY, snapCandidate.lineEndpointX, snapCandidate.lineEndpointY)) {
|
|
25648
|
+
return null;
|
|
25649
|
+
}
|
|
25650
|
+
const scale = this.getSafeScale(this._core.store.state.scale);
|
|
25593
25651
|
const indicatorRadius = 8 / scale;
|
|
25594
25652
|
const indicatorStrokeWidth = `${2 / scale}`;
|
|
25595
|
-
const
|
|
25596
|
-
?
|
|
25597
|
-
:
|
|
25598
|
-
const
|
|
25653
|
+
const lineStrokeWidthNum = this.areFiniteNumbers(snapCandidate.lineStrokeWidth) && snapCandidate.lineStrokeWidth > 0
|
|
25654
|
+
? snapCandidate.lineStrokeWidth
|
|
25655
|
+
: (4 / scale);
|
|
25656
|
+
const lineStrokeWidth = `${lineStrokeWidthNum}`;
|
|
25599
25657
|
const dashLength = Math.max(lineStrokeWidthNum * 2, 4 / scale);
|
|
25600
25658
|
const dashArray = `${dashLength} ${dashLength}`;
|
|
25601
25659
|
const lineStroke = snapCandidate.lineStroke || '#000000';
|
|
25602
|
-
let
|
|
25603
|
-
let
|
|
25660
|
+
let edgeX = this.areFiniteNumbers(snapCandidate.edgeX) ? snapCandidate.edgeX : undefined;
|
|
25661
|
+
let edgeY = this.areFiniteNumbers(snapCandidate.edgeY) ? snapCandidate.edgeY : undefined;
|
|
25662
|
+
let solidLineEndX = edgeX;
|
|
25663
|
+
let solidLineEndY = edgeY;
|
|
25604
25664
|
let arrowPoints;
|
|
25605
|
-
|
|
25606
|
-
|
|
25607
|
-
|
|
25665
|
+
const arrowOffset = this.areFiniteNumbers(snapCandidate.arrowOffset) && snapCandidate.arrowOffset > 0
|
|
25666
|
+
? snapCandidate.arrowOffset
|
|
25667
|
+
: undefined;
|
|
25668
|
+
if (arrowOffset !== undefined && edgeX !== undefined && edgeY !== undefined) {
|
|
25669
|
+
const dx = snapCandidate.lineEndpointX - edgeX;
|
|
25670
|
+
const dy = snapCandidate.lineEndpointY - edgeY;
|
|
25608
25671
|
const length = Math.sqrt(dx * dx + dy * dy);
|
|
25609
|
-
if (length >
|
|
25610
|
-
solidLineEndX =
|
|
25611
|
-
solidLineEndY =
|
|
25672
|
+
if (length > arrowOffset) {
|
|
25673
|
+
solidLineEndX = edgeX + (dx / length) * arrowOffset;
|
|
25674
|
+
solidLineEndY = edgeY + (dy / length) * arrowOffset;
|
|
25612
25675
|
}
|
|
25613
25676
|
// Calculate arrow head points
|
|
25614
25677
|
// Direction from line endpoint to edge (arrow direction)
|
|
25615
|
-
const arrowDx =
|
|
25616
|
-
const arrowDy =
|
|
25678
|
+
const arrowDx = edgeX - snapCandidate.lineEndpointX;
|
|
25679
|
+
const arrowDy = edgeY - snapCandidate.lineEndpointY;
|
|
25617
25680
|
const arrowLengthTotal = Math.sqrt(arrowDx * arrowDx + arrowDy * arrowDy);
|
|
25618
25681
|
if (arrowLengthTotal > 0) {
|
|
25619
25682
|
const ux = arrowDx / arrowLengthTotal;
|
|
@@ -25622,11 +25685,11 @@ class KritzelAnchorManager {
|
|
|
25622
25685
|
const px = -uy;
|
|
25623
25686
|
const py = ux;
|
|
25624
25687
|
// Arrow dimensions
|
|
25625
|
-
const arrowLength =
|
|
25688
|
+
const arrowLength = arrowOffset;
|
|
25626
25689
|
const arrowWidth = arrowLength; // 1:1 ratio
|
|
25627
25690
|
// Arrow tip at edge
|
|
25628
|
-
const tipX =
|
|
25629
|
-
const tipY =
|
|
25691
|
+
const tipX = edgeX;
|
|
25692
|
+
const tipY = edgeY;
|
|
25630
25693
|
// Arrow base
|
|
25631
25694
|
const baseX = tipX - ux * arrowLength;
|
|
25632
25695
|
const baseY = tipY - uy * arrowLength;
|
|
@@ -25635,9 +25698,31 @@ class KritzelAnchorManager {
|
|
|
25635
25698
|
const leftY = baseY + py * arrowWidth / 2;
|
|
25636
25699
|
const rightX = baseX - px * arrowWidth / 2;
|
|
25637
25700
|
const rightY = baseY - py * arrowWidth / 2;
|
|
25638
|
-
|
|
25701
|
+
if (this.areFiniteNumbers(tipX, tipY, leftX, leftY, rightX, rightY)) {
|
|
25702
|
+
arrowPoints = `${tipX},${tipY} ${leftX},${leftY} ${rightX},${rightY}`;
|
|
25703
|
+
}
|
|
25639
25704
|
}
|
|
25640
25705
|
}
|
|
25706
|
+
if (!this.areFiniteNumbers(indicatorRadius, lineStrokeWidthNum, dashLength)) {
|
|
25707
|
+
return null;
|
|
25708
|
+
}
|
|
25709
|
+
const snapLinePath = (() => {
|
|
25710
|
+
if (snapCandidate.controlX !== undefined &&
|
|
25711
|
+
snapCandidate.controlY !== undefined &&
|
|
25712
|
+
snapCandidate.t !== undefined &&
|
|
25713
|
+
this.areFiniteNumbers(snapCandidate.controlX, snapCandidate.controlY, snapCandidate.t)) {
|
|
25714
|
+
const startT = snapCandidate.endpoint === 'start' ? 1 - snapCandidate.t : snapCandidate.t;
|
|
25715
|
+
// Ensure meaningful range
|
|
25716
|
+
if (startT >= 1)
|
|
25717
|
+
return undefined;
|
|
25718
|
+
const segment = this.extractQuadraticSegment({ x: snapCandidate.lineEndpointX, y: snapCandidate.lineEndpointY }, { x: snapCandidate.controlX, y: snapCandidate.controlY }, { x: snapCandidate.centerX, y: snapCandidate.centerY }, startT, 1);
|
|
25719
|
+
if (!this.areFiniteNumbers(segment.start.x, segment.start.y, segment.control.x, segment.control.y, segment.end.x, segment.end.y)) {
|
|
25720
|
+
return undefined;
|
|
25721
|
+
}
|
|
25722
|
+
return `M ${segment.start.x} ${segment.start.y} Q ${segment.control.x} ${segment.control.y} ${segment.end.x} ${segment.end.y}`;
|
|
25723
|
+
}
|
|
25724
|
+
return undefined;
|
|
25725
|
+
})();
|
|
25641
25726
|
return {
|
|
25642
25727
|
indicatorRadius,
|
|
25643
25728
|
indicatorStrokeWidth,
|
|
@@ -25648,27 +25733,15 @@ class KritzelAnchorManager {
|
|
|
25648
25733
|
centerY: snapCandidate.centerY,
|
|
25649
25734
|
lineEndpointX: snapCandidate.lineEndpointX,
|
|
25650
25735
|
lineEndpointY: snapCandidate.lineEndpointY,
|
|
25651
|
-
edgeX
|
|
25652
|
-
edgeY
|
|
25653
|
-
arrowOffset
|
|
25736
|
+
edgeX,
|
|
25737
|
+
edgeY,
|
|
25738
|
+
arrowOffset,
|
|
25654
25739
|
arrowStyle: snapCandidate.arrowStyle,
|
|
25655
25740
|
arrowFill: snapCandidate.arrowFill,
|
|
25656
25741
|
solidLineEndX,
|
|
25657
25742
|
solidLineEndY,
|
|
25658
25743
|
arrowPoints,
|
|
25659
|
-
snapLinePath
|
|
25660
|
-
if (snapCandidate.controlX !== undefined &&
|
|
25661
|
-
snapCandidate.controlY !== undefined &&
|
|
25662
|
-
snapCandidate.t !== undefined) {
|
|
25663
|
-
const startT = snapCandidate.endpoint === 'start' ? 1 - snapCandidate.t : snapCandidate.t;
|
|
25664
|
-
// Ensure meaningful range
|
|
25665
|
-
if (startT >= 1)
|
|
25666
|
-
return undefined;
|
|
25667
|
-
const segment = this.extractQuadraticSegment({ x: snapCandidate.lineEndpointX, y: snapCandidate.lineEndpointY }, { x: snapCandidate.controlX, y: snapCandidate.controlY }, { x: snapCandidate.centerX, y: snapCandidate.centerY }, startT, 1);
|
|
25668
|
-
return `M ${segment.start.x} ${segment.start.y} Q ${segment.control.x} ${segment.control.y} ${segment.end.x} ${segment.end.y}`;
|
|
25669
|
-
}
|
|
25670
|
-
return undefined;
|
|
25671
|
-
})(),
|
|
25744
|
+
snapLinePath,
|
|
25672
25745
|
};
|
|
25673
25746
|
}
|
|
25674
25747
|
// ============================================
|
|
@@ -25846,12 +25919,19 @@ class KritzelAnchorManager {
|
|
|
25846
25919
|
return null;
|
|
25847
25920
|
const centerX = targetObject.centerX;
|
|
25848
25921
|
const centerY = targetObject.centerY;
|
|
25922
|
+
if (!this.areFiniteNumbers(clipInfo.worldX, clipInfo.worldY, centerX, centerY)) {
|
|
25923
|
+
return null;
|
|
25924
|
+
}
|
|
25925
|
+
const pathD = this.buildAnchorPath(line, endpoint, clipInfo, targetObject) ?? undefined;
|
|
25926
|
+
if (pathD && !this.isFinitePathData(pathD)) {
|
|
25927
|
+
return null;
|
|
25928
|
+
}
|
|
25849
25929
|
return {
|
|
25850
25930
|
edgeX: clipInfo.worldX,
|
|
25851
25931
|
edgeY: clipInfo.worldY,
|
|
25852
25932
|
centerX,
|
|
25853
25933
|
centerY,
|
|
25854
|
-
pathD
|
|
25934
|
+
pathD,
|
|
25855
25935
|
};
|
|
25856
25936
|
}
|
|
25857
25937
|
/**
|
|
@@ -26564,9 +26644,10 @@ class KritzelAnchorManager {
|
|
|
26564
26644
|
const sin = Math.sin(line.rotation);
|
|
26565
26645
|
const rotatedX = (px - cx) * cos - (py - cy) * sin + cx;
|
|
26566
26646
|
const rotatedY = (px - cx) * sin + (py - cy) * cos + cy;
|
|
26647
|
+
const safeLineScale = this.getSafeScale(line.scale);
|
|
26567
26648
|
return {
|
|
26568
|
-
x: rotatedX /
|
|
26569
|
-
y: rotatedY /
|
|
26649
|
+
x: rotatedX / safeLineScale + line.translateX,
|
|
26650
|
+
y: rotatedY / safeLineScale + line.translateY,
|
|
26570
26651
|
};
|
|
26571
26652
|
}
|
|
26572
26653
|
/**
|
|
@@ -26580,8 +26661,9 @@ class KritzelAnchorManager {
|
|
|
26580
26661
|
* @returns Object with x and y coordinates in the line's local SVG space.
|
|
26581
26662
|
*/
|
|
26582
26663
|
lineWorldToLocal(line, worldX, worldY) {
|
|
26583
|
-
const
|
|
26584
|
-
const
|
|
26664
|
+
const safeLineScale = this.getSafeScale(line.scale);
|
|
26665
|
+
const dx = (worldX - line.translateX) * safeLineScale;
|
|
26666
|
+
const dy = (worldY - line.translateY) * safeLineScale;
|
|
26585
26667
|
const cx = line.totalWidth / 2;
|
|
26586
26668
|
const cy = line.totalHeight / 2;
|
|
26587
26669
|
const cos = Math.cos(-line.rotation);
|
|
@@ -26593,6 +26675,30 @@ class KritzelAnchorManager {
|
|
|
26593
26675
|
y: rotatedY + line.y,
|
|
26594
26676
|
};
|
|
26595
26677
|
}
|
|
26678
|
+
getSafeScale(scale) {
|
|
26679
|
+
if (Number.isFinite(scale) && Math.abs(scale) > 1e-6) {
|
|
26680
|
+
return scale;
|
|
26681
|
+
}
|
|
26682
|
+
return 1;
|
|
26683
|
+
}
|
|
26684
|
+
areFiniteNumbers(...values) {
|
|
26685
|
+
return values.every(value => value !== undefined && Number.isFinite(value));
|
|
26686
|
+
}
|
|
26687
|
+
isFiniteAnchorVisualization(visualization) {
|
|
26688
|
+
if (!visualization) {
|
|
26689
|
+
return false;
|
|
26690
|
+
}
|
|
26691
|
+
if (!this.areFiniteNumbers(visualization.edgeX, visualization.edgeY, visualization.centerX, visualization.centerY)) {
|
|
26692
|
+
return false;
|
|
26693
|
+
}
|
|
26694
|
+
if (visualization.pathD && !this.isFinitePathData(visualization.pathD)) {
|
|
26695
|
+
return false;
|
|
26696
|
+
}
|
|
26697
|
+
return true;
|
|
26698
|
+
}
|
|
26699
|
+
isFinitePathData(pathD) {
|
|
26700
|
+
return !pathD.includes('Infinity') && !pathD.includes('NaN');
|
|
26701
|
+
}
|
|
26596
26702
|
/**
|
|
26597
26703
|
* Checks if an object can be used as an anchor target.
|
|
26598
26704
|
* Excludes selection-related objects (SelectionBox, SelectionGroup) and
|
|
@@ -26653,7 +26759,7 @@ exports.KritzelAlignment = void 0;
|
|
|
26653
26759
|
/** Current schema version for the app-state Y.Doc (workspace list & settings). */
|
|
26654
26760
|
const CURRENT_APP_STATE_SCHEMA_VERSION = 2;
|
|
26655
26761
|
/** Current schema version for workspace Y.Docs (drawable objects). */
|
|
26656
|
-
const CURRENT_WORKSPACE_SCHEMA_VERSION =
|
|
26762
|
+
const CURRENT_WORKSPACE_SCHEMA_VERSION = 2;
|
|
26657
26763
|
|
|
26658
26764
|
/**
|
|
26659
26765
|
* Runs pending schema migrations on a Y.Doc.
|
|
@@ -26758,7 +26864,16 @@ const APP_STATE_MIGRATIONS = [
|
|
|
26758
26864
|
* 2. Append a new entry with fromVersion = old version, toVersion = new version
|
|
26759
26865
|
* 3. Implement the migrate() function — it must be idempotent
|
|
26760
26866
|
*/
|
|
26761
|
-
const WORKSPACE_MIGRATIONS = [
|
|
26867
|
+
const WORKSPACE_MIGRATIONS = [
|
|
26868
|
+
{
|
|
26869
|
+
fromVersion: 1,
|
|
26870
|
+
toVersion: 2,
|
|
26871
|
+
migrate(_ydoc, _maps) {
|
|
26872
|
+
// No-op: adds optional userId property to objects.
|
|
26873
|
+
// Existing objects without userId are valid (field is optional).
|
|
26874
|
+
},
|
|
26875
|
+
},
|
|
26876
|
+
];
|
|
26762
26877
|
|
|
26763
26878
|
exports.APP_STATE_MIGRATIONS = APP_STATE_MIGRATIONS;
|
|
26764
26879
|
exports.CURRENT_APP_STATE_SCHEMA_VERSION = CURRENT_APP_STATE_SCHEMA_VERSION;
|
|
@@ -109,6 +109,7 @@ export class KritzelCore {
|
|
|
109
109
|
*/
|
|
110
110
|
setUser(user) {
|
|
111
111
|
this._user = user;
|
|
112
|
+
this._store.setLocalUserId(user?.id ?? null);
|
|
112
113
|
this._store.state.objects?.setLocalUser(user);
|
|
113
114
|
}
|
|
114
115
|
/**
|
|
@@ -508,6 +509,7 @@ export class KritzelCore {
|
|
|
508
509
|
if (selectionBox) {
|
|
509
510
|
this._store.state.objects.remove(object => object.id === selectionBox.id);
|
|
510
511
|
this._store.setSelectionBox(null);
|
|
512
|
+
this._store.state.objects.clearLocalSelectionBox();
|
|
511
513
|
}
|
|
512
514
|
}
|
|
513
515
|
/**
|
|
@@ -980,7 +982,9 @@ export class KritzelCore {
|
|
|
980
982
|
*/
|
|
981
983
|
clearSelection() {
|
|
982
984
|
this.removeSelectionGroup();
|
|
983
|
-
|
|
985
|
+
const localUserId = this._user?.id;
|
|
986
|
+
this._store.state.objects.remove(o => o instanceof KritzelSelectionBox ||
|
|
987
|
+
(o instanceof KritzelSelectionGroup && (localUserId == null || o.userId === localUserId || o.userId == null)));
|
|
984
988
|
this._store.setSelectionBox(null);
|
|
985
989
|
this._store.setSelectionGroup(null);
|
|
986
990
|
this._store.state.isSelecting = false;
|
|
@@ -1134,6 +1138,10 @@ export class KritzelCore {
|
|
|
1134
1138
|
if (!object.isSelected) {
|
|
1135
1139
|
return false;
|
|
1136
1140
|
}
|
|
1141
|
+
// Remote selection groups always show group UI (border only, no handles)
|
|
1142
|
+
if (object instanceof KritzelSelectionGroup && this._user?.id != null && object.userId != null && object.userId !== this._user.id) {
|
|
1143
|
+
return true;
|
|
1144
|
+
}
|
|
1137
1145
|
const selectionGroup = this._store.selectionGroup;
|
|
1138
1146
|
if (!selectionGroup) {
|
|
1139
1147
|
// During selection phase (no group yet), hide UI for KritzelLine objects
|
|
@@ -20,6 +20,7 @@ export class KritzelStore {
|
|
|
20
20
|
_cachedSelectionGroup = null;
|
|
21
21
|
_selectionBoxCacheValid = false;
|
|
22
22
|
_selectionGroupCacheValid = false;
|
|
23
|
+
_localUserId = null;
|
|
23
24
|
/**
|
|
24
25
|
* Gets the current engine state.
|
|
25
26
|
* @returns The mutable engine state object
|
|
@@ -97,9 +98,7 @@ export class KritzelStore {
|
|
|
97
98
|
height: this._state.viewportHeight / this._state.scale,
|
|
98
99
|
depth: 100,
|
|
99
100
|
};
|
|
100
|
-
return this._state.objects
|
|
101
|
-
.query(viewportBounds)
|
|
102
|
-
.sort((a, b) => a.zIndex - b.zIndex);
|
|
101
|
+
return this._state.objects.query(viewportBounds).sort((a, b) => a.zIndex - b.zIndex);
|
|
103
102
|
}
|
|
104
103
|
/**
|
|
105
104
|
* Gets all objects excluding selection-related objects (selection group and selection box).
|
|
@@ -130,16 +129,22 @@ export class KritzelStore {
|
|
|
130
129
|
return this._cachedSelectionBox;
|
|
131
130
|
}
|
|
132
131
|
/**
|
|
133
|
-
* Gets the current selection group if one exists.
|
|
132
|
+
* Gets the current local user's selection group if one exists.
|
|
133
|
+
* When a local user ID is set, returns only the selection group belonging to that user.
|
|
134
134
|
* Uses caching for O(1) access after initial lookup.
|
|
135
|
-
* @returns The selection group or null if none exists
|
|
135
|
+
* @returns The local user's selection group or null if none exists
|
|
136
136
|
*/
|
|
137
137
|
get selectionGroup() {
|
|
138
138
|
if (this._selectionGroupCacheValid) {
|
|
139
139
|
return this._cachedSelectionGroup;
|
|
140
140
|
}
|
|
141
141
|
const selectionGroups = this._state.objects.filter(o => o instanceof KritzelSelectionGroup);
|
|
142
|
-
this.
|
|
142
|
+
if (this._localUserId) {
|
|
143
|
+
this._cachedSelectionGroup = selectionGroups.find(sg => sg.userId === this._localUserId) ?? null;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
this._cachedSelectionGroup = selectionGroups.length > 0 ? selectionGroups[0] : null;
|
|
147
|
+
}
|
|
143
148
|
this._selectionGroupCacheValid = true;
|
|
144
149
|
return this._cachedSelectionGroup;
|
|
145
150
|
}
|
|
@@ -168,6 +173,15 @@ export class KritzelStore {
|
|
|
168
173
|
this._cachedSelectionGroup = group;
|
|
169
174
|
this._selectionGroupCacheValid = true;
|
|
170
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Sets the local user ID for scoping selection group lookups.
|
|
178
|
+
* When set, the selectionGroup getter returns only the group owned by this user.
|
|
179
|
+
* @param userId - The local user's ID, or null for non-collaborative mode
|
|
180
|
+
*/
|
|
181
|
+
setLocalUserId(userId) {
|
|
182
|
+
this._localUserId = userId;
|
|
183
|
+
this.invalidateSelectionCache();
|
|
184
|
+
}
|
|
171
185
|
/**
|
|
172
186
|
* Gets the currently active text object being edited.
|
|
173
187
|
* @returns The text object in editing mode, or null if none
|
|
@@ -149,6 +149,7 @@ export class KritzelViewport {
|
|
|
149
149
|
if (event.pointerType === 'touch' || event.pointerType === 'pen') {
|
|
150
150
|
const activePointers = Array.from(this._core.store.state.pointers.values());
|
|
151
151
|
if (activePointers.length === 2) {
|
|
152
|
+
this._core.store.state.objects?.clearCursorPosition();
|
|
152
153
|
const currentPath = this._core.store.currentPath;
|
|
153
154
|
if (currentPath) {
|
|
154
155
|
this._core.store.state.objects.remove(obj => obj.id === currentPath.id);
|
|
@@ -209,10 +210,15 @@ export class KritzelViewport {
|
|
|
209
210
|
const hostRect = this._core.store.state.host.getBoundingClientRect();
|
|
210
211
|
const xRelativeToHost = event.clientX - hostRect.left;
|
|
211
212
|
const yRelativeToHost = event.clientY - hostRect.top;
|
|
212
|
-
this._core.store.state.pointerX = (xRelativeToHost - this._core.store.state.translateX) / this._core.store.state.scale;
|
|
213
|
-
this._core.store.state.pointerY = (yRelativeToHost - this._core.store.state.translateY) / this._core.store.state.scale;
|
|
214
|
-
this._core.store.state.objects?.updateCursorPosition(this._core.store.state.pointerX, this._core.store.state.pointerY);
|
|
215
213
|
const activePointers = Array.from(this._core.store.state.pointers.values());
|
|
214
|
+
if (this._core.store.state.isScaling || activePointers.length > 1) {
|
|
215
|
+
this._core.store.state.objects?.clearCursorPosition();
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
this._core.store.state.pointerX = (xRelativeToHost - this._core.store.state.translateX) / this._core.store.state.scale;
|
|
219
|
+
this._core.store.state.pointerY = (yRelativeToHost - this._core.store.state.translateY) / this._core.store.state.scale;
|
|
220
|
+
this._core.store.state.objects?.updateCursorPosition(this._core.store.state.pointerX, this._core.store.state.pointerY);
|
|
221
|
+
}
|
|
216
222
|
if (activePointers.length === 2) {
|
|
217
223
|
const firstTouchX = activePointers[0].clientX - this._core.store.offsetX;
|
|
218
224
|
const firstTouchY = activePointers[0].clientY - this._core.store.offsetY;
|