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
|
@@ -156,6 +156,7 @@ export class KritzelSelectionHandler extends KritzelBaseHandler {
|
|
|
156
156
|
this._core.store.state.isSelecting = false;
|
|
157
157
|
this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox);
|
|
158
158
|
this._core.store.setSelectionBox(null);
|
|
159
|
+
this._core.store.state.objects.clearLocalSelectionBox();
|
|
159
160
|
}
|
|
160
161
|
/**
|
|
161
162
|
* Initiates a mouse-based selection by creating a selection box at the click position.
|
|
@@ -174,7 +175,7 @@ export class KritzelSelectionHandler extends KritzelBaseHandler {
|
|
|
174
175
|
selectionBox.translateX = this.startX;
|
|
175
176
|
selectionBox.translateY = this.startY;
|
|
176
177
|
this._core.store.state.isSelecting = true;
|
|
177
|
-
this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox || (!isAdditive && o instanceof KritzelSelectionGroup));
|
|
178
|
+
this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox || (!isAdditive && o instanceof KritzelSelectionGroup && (o.userId == null || o.userId === this._core.user?.id)));
|
|
178
179
|
this._core.store.setSelectionBox(null);
|
|
179
180
|
if (!isAdditive) {
|
|
180
181
|
this._core.store.setSelectionGroup(null);
|
|
@@ -206,7 +207,7 @@ export class KritzelSelectionHandler extends KritzelBaseHandler {
|
|
|
206
207
|
selectionBox.translateX = this.startX;
|
|
207
208
|
selectionBox.translateY = this.startY;
|
|
208
209
|
this._core.store.state.isSelecting = true;
|
|
209
|
-
this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox || (!isAdditive && o instanceof KritzelSelectionGroup));
|
|
210
|
+
this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox || (!isAdditive && o instanceof KritzelSelectionGroup && (o.userId == null || o.userId === this._core.user?.id)));
|
|
210
211
|
this._core.store.setSelectionBox(null);
|
|
211
212
|
if (!isAdditive) {
|
|
212
213
|
this._core.store.setSelectionGroup(null);
|
|
@@ -234,6 +235,12 @@ export class KritzelSelectionHandler extends KritzelBaseHandler {
|
|
|
234
235
|
selectionBox.height = height;
|
|
235
236
|
selectionBox.translateX = Math.min(currentX, this.startX);
|
|
236
237
|
selectionBox.translateY = Math.min(currentY, this.startY);
|
|
238
|
+
this._core.store.state.objects.setLocalSelectionBox({
|
|
239
|
+
x: selectionBox.translateX,
|
|
240
|
+
y: selectionBox.translateY,
|
|
241
|
+
width: width / selectionBox.scale,
|
|
242
|
+
height: height / selectionBox.scale,
|
|
243
|
+
});
|
|
237
244
|
if (width > 0 || height > 0) {
|
|
238
245
|
this.updateSelectedObjects();
|
|
239
246
|
}
|
|
@@ -267,6 +274,12 @@ export class KritzelSelectionHandler extends KritzelBaseHandler {
|
|
|
267
274
|
selectionBox.height = height;
|
|
268
275
|
selectionBox.translateX = Math.min(currentX, this.startX);
|
|
269
276
|
selectionBox.translateY = Math.min(currentY, this.startY);
|
|
277
|
+
this._core.store.state.objects.setLocalSelectionBox({
|
|
278
|
+
x: selectionBox.translateX,
|
|
279
|
+
y: selectionBox.translateY,
|
|
280
|
+
width: width / selectionBox.scale,
|
|
281
|
+
height: height / selectionBox.scale,
|
|
282
|
+
});
|
|
270
283
|
if (width > 0 || height > 0) {
|
|
271
284
|
this.updateSelectedObjects();
|
|
272
285
|
}
|
|
@@ -286,16 +286,22 @@ export class KritzelAnchorManager {
|
|
|
286
286
|
if (!KritzelClassHelper.isInstanceOf(selectedObject, 'KritzelLine'))
|
|
287
287
|
return null;
|
|
288
288
|
const line = selectedObject;
|
|
289
|
-
const
|
|
290
|
-
const
|
|
289
|
+
const startAnchorVizRaw = this.computeAnchorVisualization(line, 'start');
|
|
290
|
+
const endAnchorVizRaw = this.computeAnchorVisualization(line, 'end');
|
|
291
|
+
const startAnchorViz = this.isFiniteAnchorVisualization(startAnchorVizRaw) ? startAnchorVizRaw : null;
|
|
292
|
+
const endAnchorViz = this.isFiniteAnchorVisualization(endAnchorVizRaw) ? endAnchorVizRaw : null;
|
|
291
293
|
if (!startAnchorViz && !endAnchorViz)
|
|
292
294
|
return null;
|
|
293
|
-
const scale = this._core.store.state.scale;
|
|
294
|
-
const
|
|
295
|
+
const scale = this.getSafeScale(this._core.store.state.scale);
|
|
296
|
+
const lineScale = this.getSafeScale(line.scale);
|
|
297
|
+
const lineStrokeWidth = line.strokeWidth / lineScale;
|
|
295
298
|
const indicatorStrokeWidth = `${2 / scale}`;
|
|
296
299
|
const dashLength = Math.max(lineStrokeWidth * 2, 4 / scale);
|
|
297
300
|
const dashArray = `${dashLength} ${dashLength}`;
|
|
298
301
|
const indicatorRadius = 8 / scale;
|
|
302
|
+
if (!this.areFiniteNumbers(lineStrokeWidth, dashLength, indicatorRadius)) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
299
305
|
return {
|
|
300
306
|
lineStrokeWidth,
|
|
301
307
|
indicatorStrokeWidth,
|
|
@@ -317,31 +323,39 @@ export class KritzelAnchorManager {
|
|
|
317
323
|
const snapCandidate = this.getSnapCandidate();
|
|
318
324
|
if (!snapCandidate)
|
|
319
325
|
return null;
|
|
320
|
-
|
|
326
|
+
if (!this.areFiniteNumbers(snapCandidate.centerX, snapCandidate.centerY, snapCandidate.lineEndpointX, snapCandidate.lineEndpointY)) {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
const scale = this.getSafeScale(this._core.store.state.scale);
|
|
321
330
|
const indicatorRadius = 8 / scale;
|
|
322
331
|
const indicatorStrokeWidth = `${2 / scale}`;
|
|
323
|
-
const
|
|
324
|
-
?
|
|
325
|
-
:
|
|
326
|
-
const
|
|
332
|
+
const lineStrokeWidthNum = this.areFiniteNumbers(snapCandidate.lineStrokeWidth) && snapCandidate.lineStrokeWidth > 0
|
|
333
|
+
? snapCandidate.lineStrokeWidth
|
|
334
|
+
: (4 / scale);
|
|
335
|
+
const lineStrokeWidth = `${lineStrokeWidthNum}`;
|
|
327
336
|
const dashLength = Math.max(lineStrokeWidthNum * 2, 4 / scale);
|
|
328
337
|
const dashArray = `${dashLength} ${dashLength}`;
|
|
329
338
|
const lineStroke = snapCandidate.lineStroke || '#000000';
|
|
330
|
-
let
|
|
331
|
-
let
|
|
339
|
+
let edgeX = this.areFiniteNumbers(snapCandidate.edgeX) ? snapCandidate.edgeX : undefined;
|
|
340
|
+
let edgeY = this.areFiniteNumbers(snapCandidate.edgeY) ? snapCandidate.edgeY : undefined;
|
|
341
|
+
let solidLineEndX = edgeX;
|
|
342
|
+
let solidLineEndY = edgeY;
|
|
332
343
|
let arrowPoints;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
344
|
+
const arrowOffset = this.areFiniteNumbers(snapCandidate.arrowOffset) && snapCandidate.arrowOffset > 0
|
|
345
|
+
? snapCandidate.arrowOffset
|
|
346
|
+
: undefined;
|
|
347
|
+
if (arrowOffset !== undefined && edgeX !== undefined && edgeY !== undefined) {
|
|
348
|
+
const dx = snapCandidate.lineEndpointX - edgeX;
|
|
349
|
+
const dy = snapCandidate.lineEndpointY - edgeY;
|
|
336
350
|
const length = Math.sqrt(dx * dx + dy * dy);
|
|
337
|
-
if (length >
|
|
338
|
-
solidLineEndX =
|
|
339
|
-
solidLineEndY =
|
|
351
|
+
if (length > arrowOffset) {
|
|
352
|
+
solidLineEndX = edgeX + (dx / length) * arrowOffset;
|
|
353
|
+
solidLineEndY = edgeY + (dy / length) * arrowOffset;
|
|
340
354
|
}
|
|
341
355
|
// Calculate arrow head points
|
|
342
356
|
// Direction from line endpoint to edge (arrow direction)
|
|
343
|
-
const arrowDx =
|
|
344
|
-
const arrowDy =
|
|
357
|
+
const arrowDx = edgeX - snapCandidate.lineEndpointX;
|
|
358
|
+
const arrowDy = edgeY - snapCandidate.lineEndpointY;
|
|
345
359
|
const arrowLengthTotal = Math.sqrt(arrowDx * arrowDx + arrowDy * arrowDy);
|
|
346
360
|
if (arrowLengthTotal > 0) {
|
|
347
361
|
const ux = arrowDx / arrowLengthTotal;
|
|
@@ -350,11 +364,11 @@ export class KritzelAnchorManager {
|
|
|
350
364
|
const px = -uy;
|
|
351
365
|
const py = ux;
|
|
352
366
|
// Arrow dimensions
|
|
353
|
-
const arrowLength =
|
|
367
|
+
const arrowLength = arrowOffset;
|
|
354
368
|
const arrowWidth = arrowLength; // 1:1 ratio
|
|
355
369
|
// Arrow tip at edge
|
|
356
|
-
const tipX =
|
|
357
|
-
const tipY =
|
|
370
|
+
const tipX = edgeX;
|
|
371
|
+
const tipY = edgeY;
|
|
358
372
|
// Arrow base
|
|
359
373
|
const baseX = tipX - ux * arrowLength;
|
|
360
374
|
const baseY = tipY - uy * arrowLength;
|
|
@@ -363,9 +377,31 @@ export class KritzelAnchorManager {
|
|
|
363
377
|
const leftY = baseY + py * arrowWidth / 2;
|
|
364
378
|
const rightX = baseX - px * arrowWidth / 2;
|
|
365
379
|
const rightY = baseY - py * arrowWidth / 2;
|
|
366
|
-
|
|
380
|
+
if (this.areFiniteNumbers(tipX, tipY, leftX, leftY, rightX, rightY)) {
|
|
381
|
+
arrowPoints = `${tipX},${tipY} ${leftX},${leftY} ${rightX},${rightY}`;
|
|
382
|
+
}
|
|
367
383
|
}
|
|
368
384
|
}
|
|
385
|
+
if (!this.areFiniteNumbers(indicatorRadius, lineStrokeWidthNum, dashLength)) {
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
const snapLinePath = (() => {
|
|
389
|
+
if (snapCandidate.controlX !== undefined &&
|
|
390
|
+
snapCandidate.controlY !== undefined &&
|
|
391
|
+
snapCandidate.t !== undefined &&
|
|
392
|
+
this.areFiniteNumbers(snapCandidate.controlX, snapCandidate.controlY, snapCandidate.t)) {
|
|
393
|
+
const startT = snapCandidate.endpoint === 'start' ? 1 - snapCandidate.t : snapCandidate.t;
|
|
394
|
+
// Ensure meaningful range
|
|
395
|
+
if (startT >= 1)
|
|
396
|
+
return undefined;
|
|
397
|
+
const segment = this.extractQuadraticSegment({ x: snapCandidate.lineEndpointX, y: snapCandidate.lineEndpointY }, { x: snapCandidate.controlX, y: snapCandidate.controlY }, { x: snapCandidate.centerX, y: snapCandidate.centerY }, startT, 1);
|
|
398
|
+
if (!this.areFiniteNumbers(segment.start.x, segment.start.y, segment.control.x, segment.control.y, segment.end.x, segment.end.y)) {
|
|
399
|
+
return undefined;
|
|
400
|
+
}
|
|
401
|
+
return `M ${segment.start.x} ${segment.start.y} Q ${segment.control.x} ${segment.control.y} ${segment.end.x} ${segment.end.y}`;
|
|
402
|
+
}
|
|
403
|
+
return undefined;
|
|
404
|
+
})();
|
|
369
405
|
return {
|
|
370
406
|
indicatorRadius,
|
|
371
407
|
indicatorStrokeWidth,
|
|
@@ -376,27 +412,15 @@ export class KritzelAnchorManager {
|
|
|
376
412
|
centerY: snapCandidate.centerY,
|
|
377
413
|
lineEndpointX: snapCandidate.lineEndpointX,
|
|
378
414
|
lineEndpointY: snapCandidate.lineEndpointY,
|
|
379
|
-
edgeX
|
|
380
|
-
edgeY
|
|
381
|
-
arrowOffset
|
|
415
|
+
edgeX,
|
|
416
|
+
edgeY,
|
|
417
|
+
arrowOffset,
|
|
382
418
|
arrowStyle: snapCandidate.arrowStyle,
|
|
383
419
|
arrowFill: snapCandidate.arrowFill,
|
|
384
420
|
solidLineEndX,
|
|
385
421
|
solidLineEndY,
|
|
386
422
|
arrowPoints,
|
|
387
|
-
snapLinePath
|
|
388
|
-
if (snapCandidate.controlX !== undefined &&
|
|
389
|
-
snapCandidate.controlY !== undefined &&
|
|
390
|
-
snapCandidate.t !== undefined) {
|
|
391
|
-
const startT = snapCandidate.endpoint === 'start' ? 1 - snapCandidate.t : snapCandidate.t;
|
|
392
|
-
// Ensure meaningful range
|
|
393
|
-
if (startT >= 1)
|
|
394
|
-
return undefined;
|
|
395
|
-
const segment = this.extractQuadraticSegment({ x: snapCandidate.lineEndpointX, y: snapCandidate.lineEndpointY }, { x: snapCandidate.controlX, y: snapCandidate.controlY }, { x: snapCandidate.centerX, y: snapCandidate.centerY }, startT, 1);
|
|
396
|
-
return `M ${segment.start.x} ${segment.start.y} Q ${segment.control.x} ${segment.control.y} ${segment.end.x} ${segment.end.y}`;
|
|
397
|
-
}
|
|
398
|
-
return undefined;
|
|
399
|
-
})(),
|
|
423
|
+
snapLinePath,
|
|
400
424
|
};
|
|
401
425
|
}
|
|
402
426
|
// ============================================
|
|
@@ -574,12 +598,19 @@ export class KritzelAnchorManager {
|
|
|
574
598
|
return null;
|
|
575
599
|
const centerX = targetObject.centerX;
|
|
576
600
|
const centerY = targetObject.centerY;
|
|
601
|
+
if (!this.areFiniteNumbers(clipInfo.worldX, clipInfo.worldY, centerX, centerY)) {
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
const pathD = this.buildAnchorPath(line, endpoint, clipInfo, targetObject) ?? undefined;
|
|
605
|
+
if (pathD && !this.isFinitePathData(pathD)) {
|
|
606
|
+
return null;
|
|
607
|
+
}
|
|
577
608
|
return {
|
|
578
609
|
edgeX: clipInfo.worldX,
|
|
579
610
|
edgeY: clipInfo.worldY,
|
|
580
611
|
centerX,
|
|
581
612
|
centerY,
|
|
582
|
-
pathD
|
|
613
|
+
pathD,
|
|
583
614
|
};
|
|
584
615
|
}
|
|
585
616
|
/**
|
|
@@ -1292,9 +1323,10 @@ export class KritzelAnchorManager {
|
|
|
1292
1323
|
const sin = Math.sin(line.rotation);
|
|
1293
1324
|
const rotatedX = (px - cx) * cos - (py - cy) * sin + cx;
|
|
1294
1325
|
const rotatedY = (px - cx) * sin + (py - cy) * cos + cy;
|
|
1326
|
+
const safeLineScale = this.getSafeScale(line.scale);
|
|
1295
1327
|
return {
|
|
1296
|
-
x: rotatedX /
|
|
1297
|
-
y: rotatedY /
|
|
1328
|
+
x: rotatedX / safeLineScale + line.translateX,
|
|
1329
|
+
y: rotatedY / safeLineScale + line.translateY,
|
|
1298
1330
|
};
|
|
1299
1331
|
}
|
|
1300
1332
|
/**
|
|
@@ -1308,8 +1340,9 @@ export class KritzelAnchorManager {
|
|
|
1308
1340
|
* @returns Object with x and y coordinates in the line's local SVG space.
|
|
1309
1341
|
*/
|
|
1310
1342
|
lineWorldToLocal(line, worldX, worldY) {
|
|
1311
|
-
const
|
|
1312
|
-
const
|
|
1343
|
+
const safeLineScale = this.getSafeScale(line.scale);
|
|
1344
|
+
const dx = (worldX - line.translateX) * safeLineScale;
|
|
1345
|
+
const dy = (worldY - line.translateY) * safeLineScale;
|
|
1313
1346
|
const cx = line.totalWidth / 2;
|
|
1314
1347
|
const cy = line.totalHeight / 2;
|
|
1315
1348
|
const cos = Math.cos(-line.rotation);
|
|
@@ -1321,6 +1354,30 @@ export class KritzelAnchorManager {
|
|
|
1321
1354
|
y: rotatedY + line.y,
|
|
1322
1355
|
};
|
|
1323
1356
|
}
|
|
1357
|
+
getSafeScale(scale) {
|
|
1358
|
+
if (Number.isFinite(scale) && Math.abs(scale) > 1e-6) {
|
|
1359
|
+
return scale;
|
|
1360
|
+
}
|
|
1361
|
+
return 1;
|
|
1362
|
+
}
|
|
1363
|
+
areFiniteNumbers(...values) {
|
|
1364
|
+
return values.every(value => value !== undefined && Number.isFinite(value));
|
|
1365
|
+
}
|
|
1366
|
+
isFiniteAnchorVisualization(visualization) {
|
|
1367
|
+
if (!visualization) {
|
|
1368
|
+
return false;
|
|
1369
|
+
}
|
|
1370
|
+
if (!this.areFiniteNumbers(visualization.edgeX, visualization.edgeY, visualization.centerX, visualization.centerY)) {
|
|
1371
|
+
return false;
|
|
1372
|
+
}
|
|
1373
|
+
if (visualization.pathD && !this.isFinitePathData(visualization.pathD)) {
|
|
1374
|
+
return false;
|
|
1375
|
+
}
|
|
1376
|
+
return true;
|
|
1377
|
+
}
|
|
1378
|
+
isFinitePathData(pathD) {
|
|
1379
|
+
return !pathD.includes('Infinity') && !pathD.includes('NaN');
|
|
1380
|
+
}
|
|
1324
1381
|
/**
|
|
1325
1382
|
* Checks if an object can be used as an anchor target.
|
|
1326
1383
|
* Excludes selection-related objects (SelectionBox, SelectionGroup) and
|
|
@@ -28,6 +28,7 @@ export class KritzelBaseObject {
|
|
|
28
28
|
rotation = 0;
|
|
29
29
|
markedForRemoval = false;
|
|
30
30
|
zIndex = 0;
|
|
31
|
+
userId;
|
|
31
32
|
/** Whether the object is currently visible on the canvas */
|
|
32
33
|
isVisible = true;
|
|
33
34
|
isSelected = false;
|
|
@@ -208,6 +209,7 @@ export class KritzelBaseObject {
|
|
|
208
209
|
object._core = core;
|
|
209
210
|
object.zIndex = core.store.currentZIndex;
|
|
210
211
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
212
|
+
object.userId = core.user?.id;
|
|
211
213
|
return object;
|
|
212
214
|
}
|
|
213
215
|
/**
|
|
@@ -70,6 +70,7 @@ export class KritzelGroup extends KritzelBaseObject {
|
|
|
70
70
|
group._core = core;
|
|
71
71
|
group.id = group.generateId();
|
|
72
72
|
group.workspaceId = core.store.state.activeWorkspace.id;
|
|
73
|
+
group.userId = core.user?.id;
|
|
73
74
|
group.scale = core.store.state.scale;
|
|
74
75
|
group.zIndex = core.store.currentZIndex;
|
|
75
76
|
return group;
|
|
@@ -40,6 +40,7 @@ export class KritzelImage extends KritzelBaseObject {
|
|
|
40
40
|
object._core = core;
|
|
41
41
|
object.id = object.generateId();
|
|
42
42
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
43
|
+
object.userId = core.user?.id;
|
|
43
44
|
object.x = 0;
|
|
44
45
|
object.y = 0;
|
|
45
46
|
object.translateX = 0;
|
|
@@ -80,6 +80,7 @@ export class KritzelLine extends KritzelBaseObject {
|
|
|
80
80
|
object._core = core;
|
|
81
81
|
object.id = object.generateId();
|
|
82
82
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
83
|
+
object.userId = core.user?.id;
|
|
83
84
|
object.options = options;
|
|
84
85
|
object.startX = options?.startX ?? 0;
|
|
85
86
|
object.startY = options?.startY ?? 0;
|
|
@@ -62,6 +62,7 @@ export class KritzelPath extends KritzelBaseObject {
|
|
|
62
62
|
object._core = core;
|
|
63
63
|
object.id = object.generateId();
|
|
64
64
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
65
|
+
object.userId = core.user?.id;
|
|
65
66
|
object.options = options;
|
|
66
67
|
object.points = options?.points ?? [];
|
|
67
68
|
object.translateX = options?.translateX ?? 0;
|
|
@@ -19,6 +19,7 @@ export class KritzelSelectionBox extends KritzelBaseObject {
|
|
|
19
19
|
object._core = core;
|
|
20
20
|
object.id = object.generateId();
|
|
21
21
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
22
|
+
object.userId = core.user?.id;
|
|
22
23
|
object.scale = core.store.state.scale;
|
|
23
24
|
object.zIndex = 99999;
|
|
24
25
|
object.backgroundColor = { light: 'rgba(0, 122, 255, 0.2)', dark: 'rgba(0, 122, 255, 0.2)' };
|
|
@@ -24,6 +24,10 @@ export class KritzelSelectionGroup extends KritzelBaseObject {
|
|
|
24
24
|
maxX;
|
|
25
25
|
minY;
|
|
26
26
|
maxY;
|
|
27
|
+
// Selection styling properties
|
|
28
|
+
handleColor;
|
|
29
|
+
handleStrokeColor;
|
|
30
|
+
handleSize = 6;
|
|
27
31
|
/**
|
|
28
32
|
* Gets the array of object IDs contained in this selection group.
|
|
29
33
|
* @returns Array of string IDs for the selected objects
|
|
@@ -78,6 +82,7 @@ export class KritzelSelectionGroup extends KritzelBaseObject {
|
|
|
78
82
|
/**
|
|
79
83
|
* Factory method to create a new KritzelSelectionGroup instance.
|
|
80
84
|
* Initializes the selection group with default properties and associates it with the core instance.
|
|
85
|
+
* Default styling uses values from the theme system (selection section).
|
|
81
86
|
* @param core - The KritzelCore instance to associate with this selection group
|
|
82
87
|
* @returns A new KritzelSelectionGroup instance configured with default settings
|
|
83
88
|
*/
|
|
@@ -86,8 +91,15 @@ export class KritzelSelectionGroup extends KritzelBaseObject {
|
|
|
86
91
|
object._core = core;
|
|
87
92
|
object.id = object.generateId();
|
|
88
93
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
94
|
+
object.userId = core.user?.id;
|
|
89
95
|
object.scale = core.store.state.scale;
|
|
90
96
|
object.zIndex = 99999;
|
|
97
|
+
// Initialize styling with theme-aware defaults
|
|
98
|
+
object.borderColor = { light: '#007AFF', dark: '#0A84FF' };
|
|
99
|
+
object.borderWidth = 2;
|
|
100
|
+
object.handleColor = { light: '#ffffff', dark: '#1a1a1a' };
|
|
101
|
+
object.handleStrokeColor = { light: '#007AFF', dark: '#0A84FF' };
|
|
102
|
+
object.handleSize = 6;
|
|
91
103
|
return object;
|
|
92
104
|
}
|
|
93
105
|
/**
|
|
@@ -253,7 +265,7 @@ export class KritzelSelectionGroup extends KritzelBaseObject {
|
|
|
253
265
|
* @returns A serializable object representation of the selection group
|
|
254
266
|
*/
|
|
255
267
|
serialize() {
|
|
256
|
-
const { _core, _elementRef, element, totalWidth, totalHeight, unchangedObjectSnapshots, _cachedObjects, _cachedObjectIdsHash, snapshotWidth, snapshotHeight, snapshotTranslateX, snapshotTranslateY, ...remainingProps } = this;
|
|
268
|
+
const { _core, _elementRef, element, totalWidth, totalHeight, unchangedObjectSnapshots, _cachedObjects, _cachedObjectIdsHash, snapshotWidth, snapshotHeight, snapshotTranslateX, snapshotTranslateY, snapshotRotation, ...remainingProps } = this;
|
|
257
269
|
const clonedProps = structuredClone(remainingProps);
|
|
258
270
|
// Ensure objectIds is serialized with the correct key name (getter returns _objectIds)
|
|
259
271
|
clonedProps.objectIds = this.objectIds;
|
|
@@ -100,6 +100,7 @@ export class KritzelShape extends KritzelBaseObject {
|
|
|
100
100
|
object._core = core;
|
|
101
101
|
object.id = object.generateId();
|
|
102
102
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
103
|
+
object.userId = core.user?.id;
|
|
103
104
|
object.x = config?.x ?? 0;
|
|
104
105
|
object.y = config?.y ?? 0;
|
|
105
106
|
object.translateX = config?.translateX ?? 0;
|
|
@@ -116,6 +116,7 @@ export class KritzelText extends KritzelBaseObject {
|
|
|
116
116
|
object._core = core;
|
|
117
117
|
object.id = object.generateId();
|
|
118
118
|
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
119
|
+
object.userId = core.user?.id;
|
|
119
120
|
object.fontSize = fontSize;
|
|
120
121
|
object.fontFamily = fontFamily;
|
|
121
122
|
object.translateX = 0;
|
|
@@ -6,6 +6,7 @@ import * as decoding from "lib0/decoding";
|
|
|
6
6
|
* This is a lightweight alternative to y-webrtc for browser-tab-only sync
|
|
7
7
|
*/
|
|
8
8
|
export class BroadcastSyncProvider {
|
|
9
|
+
type = 'local';
|
|
9
10
|
doc;
|
|
10
11
|
channel;
|
|
11
12
|
_synced = false;
|
|
@@ -87,6 +88,10 @@ export class BroadcastSyncProvider {
|
|
|
87
88
|
disconnect() {
|
|
88
89
|
// BroadcastChannel doesn't have explicit disconnect
|
|
89
90
|
}
|
|
91
|
+
async reconnect() {
|
|
92
|
+
this.disconnect();
|
|
93
|
+
return this.connect();
|
|
94
|
+
}
|
|
90
95
|
destroy() {
|
|
91
96
|
this.doc.off('update', this.handleDocUpdate);
|
|
92
97
|
this.channel.close();
|