kritzel-stencil 0.1.26 → 0.1.28

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.
Files changed (47) hide show
  1. package/dist/cjs/{default-line-tool.config-Dbu-DwOX.js → default-line-tool.config-B2cKxcY4.js} +96 -30
  2. package/dist/cjs/index.cjs.js +1 -1
  3. package/dist/cjs/kritzel-back-to-content_32.cjs.entry.js +206 -95
  4. package/dist/collection/classes/core/core.class.js +80 -67
  5. package/dist/collection/classes/core/store.class.js +55 -2
  6. package/dist/collection/classes/core/viewport.class.js +3 -2
  7. package/dist/collection/classes/handlers/context-menu.handler.js +1 -0
  8. package/dist/collection/classes/handlers/selection.handler.js +44 -9
  9. package/dist/collection/classes/objects/base-object.class.js +28 -17
  10. package/dist/collection/classes/objects/path.class.js +7 -0
  11. package/dist/collection/classes/structures/app-state-map.structure.js +17 -4
  12. package/dist/collection/classes/structures/object-map.structure.js +45 -6
  13. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +5 -2
  14. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +16 -13
  15. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js +1 -1
  16. package/dist/collection/constants/version.js +1 -1
  17. package/dist/components/index.js +1 -1
  18. package/dist/components/kritzel-controls.js +1 -1
  19. package/dist/components/kritzel-editor.js +1 -1
  20. package/dist/components/kritzel-engine.js +1 -1
  21. package/dist/components/kritzel-settings.js +1 -1
  22. package/dist/components/kritzel-tool-config.js +1 -1
  23. package/dist/components/kritzel-utility-panel.js +1 -1
  24. package/dist/components/p-Bi-kaLjA.js +1 -0
  25. package/dist/components/{p-BlBskbmV.js → p-D80DeXmM.js} +1 -1
  26. package/dist/components/p-DuaxKa_X.js +9 -0
  27. package/dist/components/{p-Bq-Qb0-N.js → p-OPLSOwSk.js} +1 -1
  28. package/dist/components/{p-SVmGNrsg.js → p-X69mguNG.js} +1 -1
  29. package/dist/components/{p-B37slzk_.js → p-YHPvHKjP.js} +1 -1
  30. package/dist/esm/{default-line-tool.config-C_yDm5gU.js → default-line-tool.config-C__0Hp7X.js} +97 -31
  31. package/dist/esm/index.js +2 -2
  32. package/dist/esm/kritzel-back-to-content_32.entry.js +206 -95
  33. package/dist/stencil/index.esm.js +1 -1
  34. package/dist/stencil/p-783e64a2.entry.js +9 -0
  35. package/dist/stencil/p-C__0Hp7X.js +1 -0
  36. package/dist/stencil/stencil.esm.js +1 -1
  37. package/dist/types/classes/core/store.class.d.ts +19 -0
  38. package/dist/types/classes/handlers/selection.handler.d.ts +1 -0
  39. package/dist/types/classes/objects/path.class.d.ts +1 -0
  40. package/dist/types/classes/structures/app-state-map.structure.d.ts +1 -0
  41. package/dist/types/classes/structures/object-map.structure.d.ts +3 -0
  42. package/dist/types/constants/version.d.ts +1 -1
  43. package/package.json +1 -1
  44. package/dist/components/p-DxWQQBfC.js +0 -9
  45. package/dist/components/p-kpem_jJ9.js +0 -1
  46. package/dist/stencil/p-C_yDm5gU.js +0 -1
  47. package/dist/stencil/p-c0fc7909.entry.js +0 -9
@@ -231,34 +231,45 @@ class KritzelBaseObject {
231
231
  };
232
232
  }
233
233
  get rotatedBoundingBox() {
234
+ const polygon = this.rotatedPolygon;
235
+ const xValues = [polygon.topLeft.x, polygon.topRight.x, polygon.bottomRight.x, polygon.bottomLeft.x];
236
+ const yValues = [polygon.topLeft.y, polygon.topRight.y, polygon.bottomRight.y, polygon.bottomLeft.y];
237
+ const minX = Math.min(...xValues);
238
+ const maxX = Math.max(...xValues);
239
+ const minY = Math.min(...yValues);
240
+ const maxY = Math.max(...yValues);
234
241
  return {
235
- x: this.minXRotated,
236
- y: this.minYRotated,
242
+ x: minX,
243
+ y: minY,
237
244
  z: this.scale,
238
- width: this.maxXRotated - this.minXRotated,
239
- height: this.maxYRotated - this.minYRotated,
245
+ width: maxX - minX,
246
+ height: maxY - minY,
240
247
  };
241
248
  }
242
249
  get rotatedPolygon() {
243
250
  const cx = this.translateX + this.totalWidth / 2 / this.scale;
244
251
  const cy = this.translateY + this.totalHeight / 2 / this.scale;
245
252
  const angle = this.rotation;
253
+ // Optimization: Precomputes cos/sin once
254
+ const cos = Math.cos(angle);
255
+ const sin = Math.sin(angle);
246
256
  const adjustedWidth = this.totalWidth / this.scale;
247
257
  const adjustedHeight = this.totalHeight / this.scale;
248
- const corners = {
249
- topLeft: { x: this.translateX, y: this.translateY },
250
- topRight: { x: this.translateX + adjustedWidth, y: this.translateY },
251
- bottomRight: { x: this.translateX + adjustedWidth, y: this.translateY + adjustedHeight },
252
- bottomLeft: { x: this.translateX, y: this.translateY + adjustedHeight },
258
+ const x1 = this.translateX;
259
+ const y1 = this.translateY;
260
+ const x2 = x1 + adjustedWidth;
261
+ const y2 = y1 + adjustedHeight;
262
+ // Helper to rotate a point around center
263
+ const rotate = (x, y) => ({
264
+ x: cos * (x - cx) - sin * (y - cy) + cx,
265
+ y: sin * (x - cx) + cos * (y - cy) + cy,
266
+ });
267
+ return {
268
+ topLeft: rotate(x1, y1),
269
+ topRight: rotate(x2, y1),
270
+ bottomRight: rotate(x2, y2),
271
+ bottomLeft: rotate(x1, y2),
253
272
  };
254
- const rotatedCorners = Object.keys(corners).reduce((acc, key) => {
255
- const corner = corners[key];
256
- const rotatedX = Math.cos(angle) * (corner.x - cx) - Math.sin(angle) * (corner.y - cy) + cx;
257
- const rotatedY = Math.sin(angle) * (corner.x - cx) + Math.cos(angle) * (corner.y - cy) + cy;
258
- acc[key] = { x: rotatedX, y: rotatedY };
259
- return acc;
260
- }, {});
261
- return rotatedCorners;
262
273
  }
263
274
  get minXRotated() {
264
275
  const corners = [this.rotatedPolygon.topLeft.x, this.rotatedPolygon.topRight.x, this.rotatedPolygon.bottomRight.x, this.rotatedPolygon.bottomLeft.x];
@@ -15151,6 +15162,13 @@ class KritzelPath extends KritzelBaseObject {
15151
15162
  object.updateDimensions();
15152
15163
  return object;
15153
15164
  }
15165
+ copy() {
15166
+ const copiedObject = super.copy();
15167
+ if (this.points) {
15168
+ copiedObject.points = this.points.map(p => [...p]);
15169
+ }
15170
+ return copiedObject;
15171
+ }
15154
15172
  resize(x, y, width, height) {
15155
15173
  if (width <= 1 || height <= 1) {
15156
15174
  return;
@@ -18357,6 +18375,8 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
18357
18375
  touchStartX = 0;
18358
18376
  touchStartY = 0;
18359
18377
  touchStartTimeout = null;
18378
+ // Track previously selected objects for efficient deselection (WeakRef to avoid memory leaks)
18379
+ _previouslySelectedObjects = new Set();
18360
18380
  get isSelectionClick() {
18361
18381
  const selectionBox = this._core.store.selectionBox;
18362
18382
  return selectionBox && selectionBox.width === 0 && selectionBox.height === 0;
@@ -18449,6 +18469,7 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
18449
18469
  removeSelectionBox() {
18450
18470
  this._core.store.state.isSelecting = false;
18451
18471
  this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox);
18472
+ this._core.store.setSelectionBox(null);
18452
18473
  }
18453
18474
  startMouseSelection(event) {
18454
18475
  let clientX, clientY;
@@ -18461,7 +18482,10 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
18461
18482
  selectionBox.translateY = this.startY;
18462
18483
  this._core.store.state.isSelecting = true;
18463
18484
  this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox || o instanceof KritzelSelectionGroup);
18485
+ this._core.store.setSelectionBox(null);
18486
+ this._core.store.setSelectionGroup(null);
18464
18487
  this._core.store.state.objects.insert(selectionBox);
18488
+ this._core.store.setSelectionBox(selectionBox);
18465
18489
  }
18466
18490
  startTouchSelection() {
18467
18491
  const activePointers = Array.from(this._core.store.state.pointers.values());
@@ -18481,7 +18505,10 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
18481
18505
  selectionBox.translateY = this.startY;
18482
18506
  this._core.store.state.isSelecting = true;
18483
18507
  this._core.store.state.objects.remove(o => o instanceof KritzelSelectionBox || o instanceof KritzelSelectionGroup);
18508
+ this._core.store.setSelectionBox(null);
18509
+ this._core.store.setSelectionGroup(null);
18484
18510
  this._core.store.state.objects.insert(selectionBox);
18511
+ this._core.store.setSelectionBox(selectionBox);
18485
18512
  }
18486
18513
  updateMouseSelection(event) {
18487
18514
  let clientX, clientY;
@@ -18538,19 +18565,43 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
18538
18565
  return;
18539
18566
  // Compute rotatedPolygon once per update (not per object)
18540
18567
  const selectionPolygon = selectionBox.rotatedPolygon;
18568
+ // Calculate bounding box from the polygon we already have to avoid recomputing it
18569
+ // calling selectionBox.rotatedBoundingBox would trigger another rotatedPolygon computation
18570
+ const xValues = [selectionPolygon.topLeft.x, selectionPolygon.topRight.x, selectionPolygon.bottomRight.x, selectionPolygon.bottomLeft.x];
18571
+ const yValues = [selectionPolygon.topLeft.y, selectionPolygon.topRight.y, selectionPolygon.bottomRight.y, selectionPolygon.bottomLeft.y];
18572
+ const minX = Math.min(...xValues);
18573
+ const maxX = Math.max(...xValues);
18574
+ const minY = Math.min(...yValues);
18575
+ const maxY = Math.max(...yValues);
18541
18576
  // Use quadtree spatial query to get only nearby candidates - O(log n + k) instead of O(n)
18542
- const selectionBounds = selectionBox.rotatedBoundingBox;
18577
+ const selectionBounds = {
18578
+ x: minX,
18579
+ y: minY,
18580
+ z: selectionBox.scale,
18581
+ width: maxX - minX,
18582
+ height: maxY - minY
18583
+ };
18543
18584
  const candidates = this._core.store.state.objects.query(selectionBounds);
18544
- // Clear selection on all non-selection objects first
18545
- this._core.store.allNonSelectionObjects.forEach(obj => {
18546
- obj.isSelected = false;
18547
- });
18585
+ // Track newly selected objects for efficient comparison
18586
+ const newlySelectedObjects = new Set();
18548
18587
  // Only test candidates that overlap the bounding box
18549
18588
  for (const object of candidates) {
18550
18589
  if (object instanceof KritzelSelectionBox)
18551
18590
  continue;
18552
- object.isSelected = object.hitTestPolygon(selectionPolygon);
18591
+ const isHit = object.hitTestPolygon(selectionPolygon);
18592
+ object.isSelected = isHit;
18593
+ if (isHit) {
18594
+ newlySelectedObjects.add(object);
18595
+ }
18553
18596
  }
18597
+ // Deselect only objects that were previously selected but aren't anymore
18598
+ // This is O(k) where k is the number of previously selected objects, not O(n)
18599
+ for (const prevObj of this._previouslySelectedObjects) {
18600
+ if (!newlySelectedObjects.has(prevObj)) {
18601
+ prevObj.isSelected = false;
18602
+ }
18603
+ }
18604
+ this._previouslySelectedObjects = newlySelectedObjects;
18554
18605
  }
18555
18606
  handleSelectionClick(event) {
18556
18607
  const selectedObject = this.getTopmostHitObject(event);
@@ -18572,9 +18623,11 @@ class KritzelSelectionHandler extends KritzelBaseHandler {
18572
18623
  return null;
18573
18624
  }
18574
18625
  clearSelectionPreview() {
18575
- this._core.store.allNonSelectionObjects.forEach(object => {
18576
- object.isSelected = false;
18577
- });
18626
+ // Only clear previously tracked selected objects - O(k) instead of O(n)
18627
+ for (const obj of this._previouslySelectedObjects) {
18628
+ obj.isSelected = false;
18629
+ }
18630
+ this._previouslySelectedObjects.clear();
18578
18631
  }
18579
18632
  addObjectToSelectionGroup(object) {
18580
18633
  if (!object) {
@@ -35986,6 +36039,7 @@ class KritzelAppStateMap {
35986
36039
  _core = null;
35987
36040
  _isReady = false;
35988
36041
  _onRemoteChangeCallback = null;
36042
+ _workspacesObserver = null;
35989
36043
  get isReady() {
35990
36044
  return this._isReady;
35991
36045
  }
@@ -36017,9 +36071,10 @@ class KritzelAppStateMap {
36017
36071
  this._providers.push(provider);
36018
36072
  }
36019
36073
  // Observe changes to workspaces and sync with application state
36020
- this._workspacesMap.observe(event => {
36074
+ this._workspacesObserver = event => {
36021
36075
  this.handleWorkspacesChange(event);
36022
- });
36076
+ };
36077
+ this._workspacesMap.observe(this._workspacesObserver);
36023
36078
  // Connect all providers in parallel
36024
36079
  await Promise.all(this._providers.map(p => p.connect()));
36025
36080
  this._isReady = true;
@@ -36149,8 +36204,16 @@ class KritzelAppStateMap {
36149
36204
  return this.map.has(id);
36150
36205
  }
36151
36206
  destroy() {
36152
- // Disconnect all providers
36153
- this._providers.forEach(p => p.disconnect());
36207
+ // Unobserve the workspaces map
36208
+ if (this._workspacesMap && this._workspacesObserver) {
36209
+ this._workspacesMap.unobserve(this._workspacesObserver);
36210
+ this._workspacesObserver = null;
36211
+ }
36212
+ // Disconnect and destroy all providers
36213
+ this._providers.forEach(p => {
36214
+ p.disconnect();
36215
+ p.destroy();
36216
+ });
36154
36217
  this._providers = [];
36155
36218
  // Clear maps
36156
36219
  this.map.clear();
@@ -36160,6 +36223,9 @@ class KritzelAppStateMap {
36160
36223
  this._ydoc.destroy();
36161
36224
  this._ydoc = null;
36162
36225
  }
36226
+ // Clear remaining references
36227
+ this._core = null;
36228
+ this._onRemoteChangeCallback = null;
36163
36229
  this._isReady = false;
36164
36230
  }
36165
36231
  }
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var defaultLineTool_config = require('./default-line-tool.config-Dbu-DwOX.js');
3
+ var defaultLineTool_config = require('./default-line-tool.config-B2cKxcY4.js');
4
4
 
5
5
  /**
6
6
  * BroadcastChannel sync provider for cross-tab synchronization