kritzel-stencil 0.0.162 → 0.0.163

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 (118) hide show
  1. package/dist/cjs/{default-line-tool.config-D1Ns0NmM.js → default-line-tool.config-DJMYrkSu.js} +340 -9
  2. package/dist/cjs/default-line-tool.config-DJMYrkSu.js.map +1 -0
  3. package/dist/cjs/index.cjs.js +1 -1
  4. package/dist/cjs/kritzel-color_22.cjs.entry.js +761 -28
  5. package/dist/cjs/loader.cjs.js +1 -1
  6. package/dist/cjs/stencil.cjs.js +1 -1
  7. package/dist/collection/classes/core/core.class.js +19 -3
  8. package/dist/collection/classes/core/core.class.js.map +1 -1
  9. package/dist/collection/classes/core/reviver.class.js +16 -0
  10. package/dist/collection/classes/core/reviver.class.js.map +1 -1
  11. package/dist/collection/classes/core/store.class.js +5 -0
  12. package/dist/collection/classes/core/store.class.js.map +1 -1
  13. package/dist/collection/classes/core/viewport.class.js +8 -0
  14. package/dist/collection/classes/core/viewport.class.js.map +1 -1
  15. package/dist/collection/classes/managers/anchor.manager.js +181 -3
  16. package/dist/collection/classes/managers/anchor.manager.js.map +1 -1
  17. package/dist/collection/classes/objects/path.class.js +85 -0
  18. package/dist/collection/classes/objects/path.class.js.map +1 -1
  19. package/dist/collection/classes/objects/shape.class.js +372 -0
  20. package/dist/collection/classes/objects/shape.class.js.map +1 -0
  21. package/dist/collection/classes/registries/icon-registry.class.js +4 -0
  22. package/dist/collection/classes/registries/icon-registry.class.js.map +1 -1
  23. package/dist/collection/classes/tools/brush-tool.class.js +2 -2
  24. package/dist/collection/classes/tools/brush-tool.class.js.map +1 -1
  25. package/dist/collection/classes/tools/line-tool.class.js +2 -2
  26. package/dist/collection/classes/tools/line-tool.class.js.map +1 -1
  27. package/dist/collection/classes/tools/shape-tool.class.js +204 -0
  28. package/dist/collection/classes/tools/shape-tool.class.js.map +1 -0
  29. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +17 -6
  30. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js.map +1 -1
  31. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +44 -8
  32. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js.map +1 -1
  33. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.css +143 -5
  34. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +76 -12
  35. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js.map +1 -1
  36. package/dist/collection/configs/default-engine-config.js +1 -1
  37. package/dist/collection/configs/default-engine-config.js.map +1 -1
  38. package/dist/collection/configs/default-shape-tool.config.js +26 -0
  39. package/dist/collection/configs/default-shape-tool.config.js.map +1 -0
  40. package/dist/collection/enums/shape-type.enum.js +7 -0
  41. package/dist/collection/enums/shape-type.enum.js.map +1 -0
  42. package/dist/collection/helpers/geometry.helper.js +55 -0
  43. package/dist/collection/helpers/geometry.helper.js.map +1 -1
  44. package/dist/collection/interfaces/toolbar-control.interface.js.map +1 -1
  45. package/dist/components/index.js +3 -3
  46. package/dist/components/kritzel-brush-style.js +1 -1
  47. package/dist/components/kritzel-context-menu.js +1 -1
  48. package/dist/components/kritzel-control-brush-config.js +1 -1
  49. package/dist/components/kritzel-control-text-config.js +1 -1
  50. package/dist/components/kritzel-controls.js +1 -1
  51. package/dist/components/kritzel-editor.js +49 -16
  52. package/dist/components/kritzel-editor.js.map +1 -1
  53. package/dist/components/kritzel-engine.js +1 -1
  54. package/dist/components/kritzel-icon.js +1 -1
  55. package/dist/components/kritzel-menu-item.js +1 -1
  56. package/dist/components/kritzel-menu.js +1 -1
  57. package/dist/components/kritzel-split-button.js +1 -1
  58. package/dist/components/kritzel-utility-panel.js +1 -1
  59. package/dist/components/kritzel-workspace-manager.js +1 -1
  60. package/dist/components/{p-Cqr0Bah5.js → p-5OECjGHq.js} +3 -3
  61. package/dist/components/{p-Cqr0Bah5.js.map → p-5OECjGHq.js.map} +1 -1
  62. package/dist/components/{p-CvLFRlQU.js → p-BSBMBjhq.js} +3 -3
  63. package/dist/components/{p-CvLFRlQU.js.map → p-BSBMBjhq.js.map} +1 -1
  64. package/dist/components/{p-7_lwv0zQ.js → p-BuS7MM1j.js} +4 -4
  65. package/dist/components/{p-7_lwv0zQ.js.map → p-BuS7MM1j.js.map} +1 -1
  66. package/dist/components/{p-CuhOrcET.js → p-CnRfQsIC.js} +838 -22
  67. package/dist/components/p-CnRfQsIC.js.map +1 -0
  68. package/dist/components/{p-BixlbUD7.js → p-Cv4BGNPb.js} +6 -2
  69. package/dist/components/p-Cv4BGNPb.js.map +1 -0
  70. package/dist/components/{p-dMCB4tJA.js → p-D1YAsWrL.js} +3 -3
  71. package/dist/components/{p-dMCB4tJA.js.map → p-D1YAsWrL.js.map} +1 -1
  72. package/dist/components/{p-CDteBYm9.js → p-D8L0t-Ro.js} +3 -3
  73. package/dist/components/{p-CDteBYm9.js.map → p-D8L0t-Ro.js.map} +1 -1
  74. package/dist/components/{p-DZ7kxJUx.js → p-DguzZn_x.js} +3 -3
  75. package/dist/components/{p-DZ7kxJUx.js.map → p-DguzZn_x.js.map} +1 -1
  76. package/dist/components/{p-sokRZ7Vn.js → p-Dz2XHHqa.js} +145 -5
  77. package/dist/components/p-Dz2XHHqa.js.map +1 -0
  78. package/dist/components/{p-CkD1PQQX.js → p-I3iPEDpx.js} +5 -5
  79. package/dist/components/{p-CkD1PQQX.js.map → p-I3iPEDpx.js.map} +1 -1
  80. package/dist/components/{p-DKwJJuFb.js → p-tp96UZ0l.js} +83 -19
  81. package/dist/components/p-tp96UZ0l.js.map +1 -0
  82. package/dist/esm/{default-line-tool.config-C35m-d1Y.js → default-line-tool.config-C35P3XfD.js} +332 -10
  83. package/dist/esm/default-line-tool.config-C35P3XfD.js.map +1 -0
  84. package/dist/esm/index.js +2 -2
  85. package/dist/esm/kritzel-color_22.entry.js +761 -28
  86. package/dist/esm/loader.js +1 -1
  87. package/dist/esm/stencil.js +1 -1
  88. package/dist/stencil/index.esm.js +1 -1
  89. package/dist/stencil/p-9d43b708.entry.js +10 -0
  90. package/dist/stencil/p-9d43b708.entry.js.map +1 -0
  91. package/dist/stencil/p-C35P3XfD.js +2 -0
  92. package/dist/stencil/p-C35P3XfD.js.map +1 -0
  93. package/dist/stencil/stencil.esm.js +1 -1
  94. package/dist/types/classes/core/core.class.d.ts +1 -0
  95. package/dist/types/classes/core/store.class.d.ts +2 -0
  96. package/dist/types/classes/core/viewport.class.d.ts +6 -0
  97. package/dist/types/classes/managers/anchor.manager.d.ts +20 -0
  98. package/dist/types/classes/objects/path.class.d.ts +7 -0
  99. package/dist/types/classes/objects/shape.class.d.ts +116 -0
  100. package/dist/types/classes/tools/shape-tool.class.d.ts +37 -0
  101. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +2 -2
  102. package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +16 -1
  103. package/dist/types/components.d.ts +5 -5
  104. package/dist/types/configs/default-shape-tool.config.d.ts +2 -0
  105. package/dist/types/enums/shape-type.enum.d.ts +5 -0
  106. package/dist/types/helpers/geometry.helper.d.ts +21 -0
  107. package/dist/types/interfaces/toolbar-control.interface.d.ts +21 -3
  108. package/package.json +1 -1
  109. package/dist/cjs/default-line-tool.config-D1Ns0NmM.js.map +0 -1
  110. package/dist/components/p-BixlbUD7.js.map +0 -1
  111. package/dist/components/p-CuhOrcET.js.map +0 -1
  112. package/dist/components/p-DKwJJuFb.js.map +0 -1
  113. package/dist/components/p-sokRZ7Vn.js.map +0 -1
  114. package/dist/esm/default-line-tool.config-C35m-d1Y.js.map +0 -1
  115. package/dist/stencil/p-C35m-d1Y.js +0 -2
  116. package/dist/stencil/p-C35m-d1Y.js.map +0 -1
  117. package/dist/stencil/p-d142ef46.entry.js +0 -10
  118. package/dist/stencil/p-d142ef46.entry.js.map +0 -1
@@ -1,11 +1,11 @@
1
1
  import { p as proxyCustomElement, H, c as createEvent, h, d as Host } from './p-CwkUrTy1.js';
2
2
  import { K as KritzelMouseButton } from './p-D8W6LE-c.js';
3
- import { e as KritzelBaseObject, f as KritzelGeometryHelper, g as KritzelBaseTool, h as KritzelEventHelper, i as KritzelToolRegistry, c as KritzelTextTool, b as KritzelBrushTool, K as KritzelText, a as KritzelPath, d as KritzelKeyboardHelper } from './p-sokRZ7Vn.js';
4
- import { K as KritzelContextMenu, d as defineCustomElement$3 } from './p-dMCB4tJA.js';
3
+ import { e as KritzelBaseObject, f as KritzelGeometryHelper, g as KritzelBaseTool, h as KritzelEventHelper, i as KritzelToolRegistry, S as Schema, s as schema, j as addListNodes, E as EditorView, k as EditorState, l as keymap, T as TextSelection, d as KritzelKeyboardHelper, m as baseKeymap, c as KritzelTextTool, b as KritzelBrushTool, K as KritzelText, a as KritzelPath } from './p-Dz2XHHqa.js';
4
+ import { K as KritzelContextMenu, d as defineCustomElement$3 } from './p-D1YAsWrL.js';
5
5
  import { O as ObjectHelper } from './p-B0kd2rUI.js';
6
- import { K as KritzelIconRegistry, d as defineCustomElement$1 } from './p-BixlbUD7.js';
7
- import { K as KritzelWorkspace } from './p-n789Y3S-.js';
8
6
  import { K as KritzelDevicesHelper } from './p-l10It7Nm.js';
7
+ import { K as KritzelIconRegistry, d as defineCustomElement$1 } from './p-Cv4BGNPb.js';
8
+ import { K as KritzelWorkspace } from './p-n789Y3S-.js';
9
9
  import { d as defineCustomElement$2 } from './p-B_3OZeom.js';
10
10
 
11
11
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
@@ -1018,6 +1018,7 @@ class KritzelLineTool extends KritzelBaseTool {
1018
1018
  });
1019
1019
  updatedLine.id = currentLine.id;
1020
1020
  updatedLine.workspaceId = currentLine.workspaceId;
1021
+ updatedLine.zIndex = currentLine.zIndex;
1021
1022
  updatedLine.isCompleted = false;
1022
1023
  this._core.store.state.objects.update(updatedLine);
1023
1024
  }
@@ -1044,6 +1045,7 @@ class KritzelLineTool extends KritzelBaseTool {
1044
1045
  });
1045
1046
  updatedLine.id = currentLine.id;
1046
1047
  updatedLine.workspaceId = currentLine.workspaceId;
1048
+ updatedLine.zIndex = currentLine.zIndex;
1047
1049
  updatedLine.isCompleted = false;
1048
1050
  this._core.store.state.objects.update(updatedLine);
1049
1051
  }
@@ -1060,7 +1062,6 @@ class KritzelLineTool extends KritzelBaseTool {
1060
1062
  const currentLine = this._core.store.currentLine;
1061
1063
  if (currentLine) {
1062
1064
  currentLine.isCompleted = true;
1063
- currentLine.zIndex = this._core.store.currentZIndex;
1064
1065
  this._core.store.state.objects.update(currentLine);
1065
1066
  this._core.engine.emitObjectsChange();
1066
1067
  // Switch to selection tool and select the drawn line
@@ -1074,7 +1075,6 @@ class KritzelLineTool extends KritzelBaseTool {
1074
1075
  const currentLine = this._core.store.currentLine;
1075
1076
  if (currentLine) {
1076
1077
  currentLine.isCompleted = true;
1077
- currentLine.zIndex = this._core.store.currentZIndex;
1078
1078
  this._core.store.state.objects.update(currentLine);
1079
1079
  this._core.engine.emitObjectsChange();
1080
1080
  // Switch to selection tool and select the drawn line
@@ -18281,7 +18281,34 @@ class KritzelAnchorManager {
18281
18281
  const reference = endpoint === 'start'
18282
18282
  ? this.lineLocalToWorld(line, line.endX, line.endY)
18283
18283
  : this.lineLocalToWorld(line, line.startX, line.startY);
18284
- const edgeIntersection = KritzelGeometryHelper.getLinePolygonIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, targetObject.rotatedPolygon);
18284
+ // Check for path object (uses stroke edge detection)
18285
+ const pathClipPoint = this.getPathClipPoint(targetObject, reference);
18286
+ if (pathClipPoint) {
18287
+ const localEdge = this.lineWorldToLocal(line, pathClipPoint.x, pathClipPoint.y);
18288
+ const totalLength = Math.sqrt(Math.pow(line.endX - line.startX, 2) +
18289
+ Math.pow(line.endY - line.startY, 2));
18290
+ const distanceFromStart = Math.sqrt(Math.pow(localEdge.x - line.startX, 2) +
18291
+ Math.pow(localEdge.y - line.startY, 2));
18292
+ const t = totalLength > 0 ? distanceFromStart / totalLength : endpoint === 'start' ? 0 : 1;
18293
+ return {
18294
+ localX: localEdge.x,
18295
+ localY: localEdge.y,
18296
+ worldX: pathClipPoint.x,
18297
+ worldY: pathClipPoint.y,
18298
+ t,
18299
+ };
18300
+ }
18301
+ // Check for custom clip polygon (ellipse, triangle shapes)
18302
+ const customClipPolygon = this.getClipPolygonForObject(targetObject);
18303
+ let edgeIntersection;
18304
+ if (customClipPolygon) {
18305
+ // Use custom polygon for non-rectangular shapes
18306
+ edgeIntersection = KritzelGeometryHelper.getLinePointsArrayIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, customClipPolygon);
18307
+ }
18308
+ else {
18309
+ // Fall back to bounding box for rectangles and other objects
18310
+ edgeIntersection = KritzelGeometryHelper.getLinePolygonIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, targetObject.rotatedPolygon);
18311
+ }
18285
18312
  if (!edgeIntersection) {
18286
18313
  return null;
18287
18314
  }
@@ -18300,7 +18327,15 @@ class KritzelAnchorManager {
18300
18327
  };
18301
18328
  }
18302
18329
  computeCurvedClipInfo(line, endpoint, targetObject) {
18303
- const polygonPoints = this.getPolygonPoints(targetObject.rotatedPolygon);
18330
+ // Check for path object (uses stroke edge detection via sampling)
18331
+ if (KritzelClassHelper.isInstanceOf(targetObject, 'KritzelPath')) {
18332
+ // For curved lines to paths, sample along the curve to find stroke edge
18333
+ const path = targetObject;
18334
+ return this.findCurveExitPointForPath(line, endpoint, path);
18335
+ }
18336
+ // Check for custom clip polygon (ellipse, triangle shapes)
18337
+ const customClipPolygon = this.getClipPolygonForObject(targetObject);
18338
+ const polygonPoints = customClipPolygon ?? this.getPolygonPoints(targetObject.rotatedPolygon);
18304
18339
  const exitPoint = this.findCurveExitPoint(line, endpoint, polygonPoints);
18305
18340
  if (exitPoint) {
18306
18341
  return exitPoint;
@@ -18308,7 +18343,13 @@ class KritzelAnchorManager {
18308
18343
  const reference = endpoint === 'start'
18309
18344
  ? this.lineLocalToWorld(line, line.endX, line.endY)
18310
18345
  : this.lineLocalToWorld(line, line.startX, line.startY);
18311
- const fallbackIntersection = KritzelGeometryHelper.getLinePolygonIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, targetObject.rotatedPolygon);
18346
+ let fallbackIntersection;
18347
+ if (customClipPolygon) {
18348
+ fallbackIntersection = KritzelGeometryHelper.getLinePointsArrayIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, customClipPolygon);
18349
+ }
18350
+ else {
18351
+ fallbackIntersection = KritzelGeometryHelper.getLinePolygonIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, targetObject.rotatedPolygon);
18352
+ }
18312
18353
  if (!fallbackIntersection) {
18313
18354
  return null;
18314
18355
  }
@@ -18348,6 +18389,119 @@ class KritzelAnchorManager {
18348
18389
  }
18349
18390
  return null;
18350
18391
  }
18392
+ /**
18393
+ * Finds the exit point for a curved line going to a Path object.
18394
+ * Uses distance-to-stroke sampling instead of polygon containment.
18395
+ */
18396
+ findCurveExitPointForPath(line, endpoint, path) {
18397
+ const steps = 64;
18398
+ const initialT = endpoint === 'start' ? 0 : 1;
18399
+ const halfStroke = path.strokeWidth / path.scale / 2;
18400
+ // Ensure path has computed points
18401
+ const pathPoints = this.getPathAdjustedPoints(path);
18402
+ if (pathPoints.length < 1) {
18403
+ return null;
18404
+ }
18405
+ // Check if starting point is inside the stroke
18406
+ const initialSample = this.evaluateLineAtT(line, initialT);
18407
+ let prevInside = this.isPointInPathStroke(initialSample.worldX, initialSample.worldY, pathPoints, halfStroke);
18408
+ let prevT = initialT;
18409
+ for (let i = 1; i <= steps; i++) {
18410
+ const t = endpoint === 'start' ? i / steps : 1 - i / steps;
18411
+ const sample = this.evaluateLineAtT(line, t);
18412
+ const inside = this.isPointInPathStroke(sample.worldX, sample.worldY, pathPoints, halfStroke);
18413
+ if (prevInside && !inside) {
18414
+ // Refine using binary search
18415
+ const refinedT = this.refineCurveExitParameterForPath(line, pathPoints, halfStroke, prevT, t);
18416
+ const refinedPoint = this.evaluateLineAtT(line, refinedT);
18417
+ return {
18418
+ localX: refinedPoint.localX,
18419
+ localY: refinedPoint.localY,
18420
+ worldX: refinedPoint.worldX,
18421
+ worldY: refinedPoint.worldY,
18422
+ t: refinedT,
18423
+ };
18424
+ }
18425
+ prevInside = inside;
18426
+ prevT = t;
18427
+ }
18428
+ return null;
18429
+ }
18430
+ refineCurveExitParameterForPath(line, pathPoints, halfStroke, insideT, outsideT) {
18431
+ let tInside = insideT;
18432
+ let tOutside = outsideT;
18433
+ for (let i = 0; i < 8; i++) {
18434
+ const mid = (tInside + tOutside) / 2;
18435
+ const sample = this.evaluateLineAtT(line, mid);
18436
+ const inside = this.isPointInPathStroke(sample.worldX, sample.worldY, pathPoints, halfStroke);
18437
+ if (inside) {
18438
+ tInside = mid;
18439
+ }
18440
+ else {
18441
+ tOutside = mid;
18442
+ }
18443
+ }
18444
+ return (tInside + tOutside) / 2;
18445
+ }
18446
+ getPathAdjustedPoints(path) {
18447
+ // Access the path's adjusted points through its internal computation
18448
+ // We'll need to manually compute them since they're private
18449
+ return this.computePathAdjustedPoints(path);
18450
+ }
18451
+ computePathAdjustedPoints(path) {
18452
+ if (!path.points?.length) {
18453
+ return [];
18454
+ }
18455
+ const angle = path.rotation;
18456
+ const cos = Math.cos(angle);
18457
+ const sin = Math.sin(angle);
18458
+ const xs = path.points.map(p => p[0]);
18459
+ const ys = path.points.map(p => p[1]);
18460
+ const pivot = {
18461
+ x: (Math.min(...xs) + Math.max(...xs)) / 2,
18462
+ y: (Math.min(...ys) + Math.max(...ys)) / 2,
18463
+ };
18464
+ const { x: cx, y: cy } = pivot;
18465
+ const rotatedPoints = path.points.map(([x, y]) => {
18466
+ const dx = x - cx;
18467
+ const dy = y - cy;
18468
+ return [cx + dx * cos - dy * sin, cy + dx * sin + dy * cos];
18469
+ });
18470
+ return rotatedPoints.map(([px, py]) => [
18471
+ Math.abs(px - path.x) / path.scale + path.translateX,
18472
+ Math.abs(py - path.y) / path.scale + path.translateY,
18473
+ ]);
18474
+ }
18475
+ isPointInPathStroke(x, y, pathPoints, halfStroke) {
18476
+ if (pathPoints.length === 1) {
18477
+ const p = pathPoints[0];
18478
+ const dx = x - p[0];
18479
+ const dy = y - p[1];
18480
+ return Math.sqrt(dx * dx + dy * dy) <= halfStroke;
18481
+ }
18482
+ for (let i = 0; i < pathPoints.length - 1; i++) {
18483
+ const p1 = pathPoints[i];
18484
+ const p2 = pathPoints[i + 1];
18485
+ const dist = this.pointToSegmentDistance(x, y, p1[0], p1[1], p2[0], p2[1]);
18486
+ if (dist <= halfStroke) {
18487
+ return true;
18488
+ }
18489
+ }
18490
+ return false;
18491
+ }
18492
+ pointToSegmentDistance(px, py, x1, y1, x2, y2) {
18493
+ const dx = x2 - x1;
18494
+ const dy = y2 - y1;
18495
+ const lengthSquared = dx * dx + dy * dy;
18496
+ if (lengthSquared === 0) {
18497
+ return Math.sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
18498
+ }
18499
+ let t = ((px - x1) * dx + (py - y1) * dy) / lengthSquared;
18500
+ t = Math.max(0, Math.min(1, t));
18501
+ const nearestX = x1 + t * dx;
18502
+ const nearestY = y1 + t * dy;
18503
+ return Math.sqrt((px - nearestX) * (px - nearestX) + (py - nearestY) * (py - nearestY));
18504
+ }
18351
18505
  refineCurveExitParameter(line, polygonPoints, insideT, outsideT) {
18352
18506
  let tInside = insideT;
18353
18507
  let tOutside = outsideT;
@@ -18481,6 +18635,30 @@ class KritzelAnchorManager {
18481
18635
  getPolygonPoints(polygon) {
18482
18636
  return [polygon.topLeft, polygon.topRight, polygon.bottomRight, polygon.bottomLeft];
18483
18637
  }
18638
+ /**
18639
+ * Gets the custom clip polygon for an object if it has one.
18640
+ * Returns null for objects that should use the default rotatedPolygon.
18641
+ */
18642
+ getClipPolygonForObject(object) {
18643
+ // Check if the object is a KritzelShape with a custom clip polygon
18644
+ if (KritzelClassHelper.isInstanceOf(object, 'KritzelShape')) {
18645
+ const shape = object;
18646
+ return shape.getClipPolygon();
18647
+ }
18648
+ // Path objects use getPathClipPoint instead of polygon
18649
+ return null;
18650
+ }
18651
+ /**
18652
+ * Gets the clip point for a Path object (stroke edge intersection).
18653
+ * Returns null if the object is not a Path or no intersection found.
18654
+ */
18655
+ getPathClipPoint(object, outsidePoint) {
18656
+ if (KritzelClassHelper.isInstanceOf(object, 'KritzelPath')) {
18657
+ const path = object;
18658
+ return path.getClipPoint(outsidePoint);
18659
+ }
18660
+ return null;
18661
+ }
18484
18662
  /**
18485
18663
  * Converts local line coordinates to world coordinates.
18486
18664
  */
@@ -18532,6 +18710,571 @@ class KritzelAnchorManager {
18532
18710
  }
18533
18711
  }
18534
18712
 
18713
+ var ShapeType;
18714
+ (function (ShapeType) {
18715
+ ShapeType["Rectangle"] = "rectangle";
18716
+ ShapeType["Ellipse"] = "ellipse";
18717
+ ShapeType["Triangle"] = "triangle";
18718
+ })(ShapeType || (ShapeType = {}));
18719
+
18720
+ class KritzelShape extends KritzelBaseObject {
18721
+ __class__ = 'KritzelShape';
18722
+ shapeType = ShapeType.Rectangle;
18723
+ fillColor = 'transparent';
18724
+ strokeColor = '#000000';
18725
+ strokeWidth = 4;
18726
+ fontFamily = 'Arial';
18727
+ fontSize = 16;
18728
+ fontColor = '#000000';
18729
+ /** Screen-space x coordinate of the shape's top-left corner (like Path.x) */
18730
+ x = 0;
18731
+ /** Screen-space y coordinate of the shape's top-left corner (like Path.y) */
18732
+ y = 0;
18733
+ scale = 1;
18734
+ scaleFactor = 1;
18735
+ isDebugInfoVisible = true;
18736
+ isEditable = true;
18737
+ isEditing = false;
18738
+ editor = null;
18739
+ content = null;
18740
+ _schema = new Schema({
18741
+ nodes: addListNodes(schema.spec.nodes, 'paragraph block*', 'block'),
18742
+ marks: schema.spec.marks,
18743
+ });
18744
+ uneditedObject = null;
18745
+ /**
18746
+ * Returns the viewBox for the shape's SVG, using screen-space coordinates.
18747
+ * This follows the same pattern as KritzelPath.viewBox.
18748
+ */
18749
+ get viewBox() {
18750
+ return `${this.x} ${this.y} ${this.width} ${this.height}`;
18751
+ }
18752
+ constructor(config) {
18753
+ super();
18754
+ if (config) {
18755
+ this.x = config.x ?? 0;
18756
+ this.y = config.y ?? 0;
18757
+ this.translateX = config.translateX ?? 0;
18758
+ this.translateY = config.translateY ?? 0;
18759
+ this.width = config.width ?? 100;
18760
+ this.height = config.height ?? 100;
18761
+ this.shapeType = config.shapeType ?? ShapeType.Rectangle;
18762
+ this.fillColor = config.fillColor ?? 'transparent';
18763
+ this.strokeColor = config.strokeColor ?? '#000000';
18764
+ this.strokeWidth = config.strokeWidth ?? 4;
18765
+ this.fontSize = config.fontSize ?? 16;
18766
+ this.fontFamily = config.fontFamily ?? 'Arial';
18767
+ this.fontColor = config.fontColor ?? '#000000';
18768
+ this.scale = config.scale ?? 1;
18769
+ this.scaleFactor = config.scaleX ?? 1;
18770
+ }
18771
+ }
18772
+ /**
18773
+ * Creates a new KritzelShape with screen-space coordinates.
18774
+ * Following the same pattern as KritzelPath.create():
18775
+ * - x, y are screen-space coordinates of the shape's top-left corner
18776
+ * - translateX, translateY should be set to -viewportTranslateX, -viewportTranslateY
18777
+ * - width, height are in screen-space
18778
+ * - scale is the viewport scale at creation time
18779
+ */
18780
+ static create(core, config) {
18781
+ const object = new KritzelShape();
18782
+ object._core = core;
18783
+ object.id = object.generateId();
18784
+ object.workspaceId = core.store.state.activeWorkspace.id;
18785
+ object.x = config?.x ?? 0;
18786
+ object.y = config?.y ?? 0;
18787
+ object.translateX = config?.translateX ?? 0;
18788
+ object.translateY = config?.translateY ?? 0;
18789
+ object.width = config?.width ?? 100;
18790
+ object.height = config?.height ?? 100;
18791
+ object.shapeType = config?.shapeType ?? ShapeType.Rectangle;
18792
+ object.fillColor = config?.fillColor ?? 'transparent';
18793
+ object.strokeColor = config?.strokeColor ?? '#000000';
18794
+ object.strokeWidth = config?.strokeWidth ?? 4;
18795
+ object.fontSize = config?.fontSize ?? 16;
18796
+ object.fontFamily = config?.fontFamily ?? 'Arial';
18797
+ object.fontColor = config?.fontColor ?? '#000000';
18798
+ object.backgroundColor = 'transparent';
18799
+ object.scaleFactor = 1;
18800
+ object.scale = core.store.state.scale;
18801
+ object.zIndex = core.store.currentZIndex;
18802
+ object.editor = object.createEditor();
18803
+ // Compute world-space translateX/Y from screen-space coordinates
18804
+ // This follows the same pattern as KritzelPath.updateDimensions()
18805
+ object.updateDimensions();
18806
+ return object;
18807
+ }
18808
+ /**
18809
+ * Updates the translateX/Y to world coordinates based on screen-space x, y.
18810
+ * This follows the same pattern as KritzelPath.updateDimensions().
18811
+ *
18812
+ * The formula: translateX = (x + initialTranslateX) / scale
18813
+ * where initialTranslateX was -viewportTranslateX
18814
+ *
18815
+ * This converts screen-space position to world coordinates.
18816
+ */
18817
+ updateDimensions() {
18818
+ this.translateX = (this.x + this.translateX) / this.scale;
18819
+ this.translateY = (this.y + this.translateY) / this.scale;
18820
+ }
18821
+ mount(element) {
18822
+ if (element === null || this.isInViewport() === false) {
18823
+ return;
18824
+ }
18825
+ if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
18826
+ return;
18827
+ }
18828
+ this.elementRef = element;
18829
+ this.isMounted = true;
18830
+ }
18831
+ mountTextEditor(element) {
18832
+ if (element === null) {
18833
+ return;
18834
+ }
18835
+ if (this.editor.dom.parentElement === element) {
18836
+ return;
18837
+ }
18838
+ element.style.fontFamily = this.fontFamily;
18839
+ element.style.fontSize = `${this.fontSize}pt`;
18840
+ element.style.color = this.fontColor;
18841
+ element.style.whiteSpace = 'pre-wrap';
18842
+ element.style.wordWrap = 'break-word';
18843
+ element.innerHTML = '';
18844
+ element.appendChild(this.editor.dom);
18845
+ }
18846
+ createEditor() {
18847
+ const doc = this._schema.node('doc', null, [this._schema.node('paragraph')]);
18848
+ return new EditorView(null, {
18849
+ state: EditorState.create({
18850
+ doc: doc,
18851
+ plugins: [keymap(baseKeymap)],
18852
+ }),
18853
+ editable: () => false,
18854
+ dispatchTransaction: transaction => {
18855
+ const newState = this.editor.state.apply(transaction);
18856
+ this.editor.updateState(newState);
18857
+ if (transaction.docChanged) {
18858
+ this.content = newState.doc.toJSON();
18859
+ if (!transaction.getMeta('fromRemote')) {
18860
+ this._core.store.state.objects.update(this, { temporary: true });
18861
+ }
18862
+ }
18863
+ },
18864
+ });
18865
+ }
18866
+ setContent(content) {
18867
+ this.content = content;
18868
+ if (this.editor && content) {
18869
+ const newDoc = this.editor.state.schema.nodeFromJSON(content);
18870
+ const tr = this.editor.state.tr.replaceWith(0, this.editor.state.doc.content.size, newDoc.content);
18871
+ tr.setMeta('fromRemote', true);
18872
+ this.editor.dispatch(tr);
18873
+ }
18874
+ }
18875
+ resize(x, y, width, height) {
18876
+ if (width <= 1 || height <= 1) {
18877
+ return;
18878
+ }
18879
+ this.width = width;
18880
+ this.height = height;
18881
+ this.translateX = x;
18882
+ this.translateY = y;
18883
+ this._core.store.state.objects.update(this);
18884
+ }
18885
+ focus(coords) {
18886
+ if (this.editor) {
18887
+ const doc = this.editor.state.doc;
18888
+ if (coords?.x && coords?.y) {
18889
+ const pos = this.editor.posAtCoords({ left: coords.x, top: coords.y });
18890
+ if (pos) {
18891
+ this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, pos.pos)));
18892
+ this.editor.focus();
18893
+ if (KritzelDevicesHelper.isIOS()) {
18894
+ this.scrollIntoViewOnIOS();
18895
+ }
18896
+ return;
18897
+ }
18898
+ }
18899
+ const end = Math.max(1, doc.content.size - 1);
18900
+ this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, end)));
18901
+ this.editor.focus();
18902
+ if (KritzelDevicesHelper.isIOS()) {
18903
+ this.scrollIntoViewOnIOS();
18904
+ }
18905
+ }
18906
+ }
18907
+ scrollIntoViewOnIOS() {
18908
+ setTimeout(() => {
18909
+ if (this.editor && this.editor.dom) {
18910
+ this.editor.dom.scrollIntoView({
18911
+ behavior: 'smooth',
18912
+ block: 'center',
18913
+ inline: 'nearest',
18914
+ });
18915
+ }
18916
+ }, 300);
18917
+ }
18918
+ edit(event) {
18919
+ KritzelKeyboardHelper.disableInteractiveWidget();
18920
+ this.uneditedObject = this.clone();
18921
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('shape'));
18922
+ this.editor.setProps({ editable: () => true });
18923
+ this.isEditing = true;
18924
+ this._core.rerender();
18925
+ this.focus({ x: event?.clientX, y: event?.clientY });
18926
+ KritzelKeyboardHelper.enableInteractiveWidget();
18927
+ }
18928
+ save() {
18929
+ this.content = this.editor.state.doc.toJSON();
18930
+ this.editor.setProps({ editable: () => false });
18931
+ this.editor.dom.blur();
18932
+ this.isEditing = false;
18933
+ this._core.store.state.objects.consolidateTemporaryItems();
18934
+ this._core.store.state.objects.update(this);
18935
+ this._core.engine.emitObjectsChange();
18936
+ }
18937
+ handlePointerDown(event) {
18938
+ if (!this.isEditing) {
18939
+ return;
18940
+ }
18941
+ event.stopPropagation();
18942
+ }
18943
+ handlePointerMove(event) {
18944
+ if (!this.isEditing) {
18945
+ return;
18946
+ }
18947
+ event.stopPropagation();
18948
+ }
18949
+ handlePointerUp(event) {
18950
+ if (!this.isEditing) {
18951
+ return;
18952
+ }
18953
+ event.stopPropagation();
18954
+ }
18955
+ copy() {
18956
+ const copiedObject = super.copy();
18957
+ copiedObject.editor = copiedObject.createEditor();
18958
+ if (this.content) {
18959
+ copiedObject.setContent(this.content);
18960
+ }
18961
+ return copiedObject;
18962
+ }
18963
+ serialize() {
18964
+ const { _core, _elementRef, _schema, element, totalWidth, totalHeight, editor, uneditedObject, ...remainingProps } = this;
18965
+ const clonedProps = structuredClone(remainingProps);
18966
+ if (element && typeof element === 'object' && 'nodeType' in element && element.nodeType === 1) {
18967
+ clonedProps.element = element.cloneNode(true);
18968
+ }
18969
+ return clonedProps;
18970
+ }
18971
+ deserialize(object) {
18972
+ super.deserialize(object);
18973
+ if (object.content) {
18974
+ this.setContent(object.content);
18975
+ }
18976
+ return this;
18977
+ }
18978
+ /**
18979
+ * Returns the clipping polygon for arrow intersection.
18980
+ * For ellipse: returns a many-sided polygon approximation
18981
+ * For triangle: returns the 3 corners
18982
+ * For rectangle: returns null (uses default rotatedPolygon)
18983
+ *
18984
+ * Includes padding for half the stroke width so arrow heads don't overlap the stroke.
18985
+ */
18986
+ getClipPolygon() {
18987
+ // Calculate world-space center and dimensions
18988
+ const worldWidth = this.totalWidth / this.scale;
18989
+ const worldHeight = this.totalHeight / this.scale;
18990
+ const centerX = this.translateX + worldWidth / 2;
18991
+ const centerY = this.translateY + worldHeight / 2;
18992
+ // Add padding for stroke width so arrows don't overlap the stroke
18993
+ const strokePadding = (this.strokeWidth / this.scale) / 2;
18994
+ switch (this.shapeType) {
18995
+ case ShapeType.Ellipse:
18996
+ // Return a 32-segment polygon approximation of the ellipse
18997
+ // Add stroke padding to radii
18998
+ return KritzelGeometryHelper.getEllipsePolygonApproximation(centerX, centerY, worldWidth / 2 + strokePadding, worldHeight / 2 + strokePadding, 32, this.rotation);
18999
+ case ShapeType.Triangle:
19000
+ // Return the 3 corners of the triangle in world coordinates
19001
+ // Triangle: top-center, bottom-right, bottom-left
19002
+ // Expand each vertex outward from center by strokePadding
19003
+ const expandVertex = (vx, vy) => {
19004
+ const dx = vx - centerX;
19005
+ const dy = vy - centerY;
19006
+ const dist = Math.sqrt(dx * dx + dy * dy);
19007
+ if (dist === 0)
19008
+ return { x: vx, y: vy };
19009
+ const scale = (dist + strokePadding) / dist;
19010
+ return {
19011
+ x: centerX + dx * scale,
19012
+ y: centerY + dy * scale
19013
+ };
19014
+ };
19015
+ const topX = this.translateX + worldWidth / 2;
19016
+ const topY = this.translateY;
19017
+ const bottomLeftX = this.translateX;
19018
+ const bottomLeftY = this.translateY + worldHeight;
19019
+ const bottomRightX = this.translateX + worldWidth;
19020
+ const bottomRightY = this.translateY + worldHeight;
19021
+ const expandedTop = expandVertex(topX, topY);
19022
+ const expandedBottomRight = expandVertex(bottomRightX, bottomRightY);
19023
+ const expandedBottomLeft = expandVertex(bottomLeftX, bottomLeftY);
19024
+ // Apply rotation around center if rotated
19025
+ if (this.rotation !== 0) {
19026
+ const cos = Math.cos(this.rotation);
19027
+ const sin = Math.sin(this.rotation);
19028
+ const rotate = (p) => {
19029
+ const dx = p.x - centerX;
19030
+ const dy = p.y - centerY;
19031
+ return {
19032
+ x: centerX + dx * cos - dy * sin,
19033
+ y: centerY + dx * sin + dy * cos
19034
+ };
19035
+ };
19036
+ return [
19037
+ rotate(expandedTop),
19038
+ rotate(expandedBottomRight),
19039
+ rotate(expandedBottomLeft)
19040
+ ];
19041
+ }
19042
+ return [expandedTop, expandedBottomRight, expandedBottomLeft];
19043
+ case ShapeType.Rectangle:
19044
+ default:
19045
+ // For rectangles, return null to use the default rotatedPolygon
19046
+ return null;
19047
+ }
19048
+ }
19049
+ /**
19050
+ * Returns the SVG path for rendering the shape.
19051
+ * The path uses screen-space coordinates relative to (x, y).
19052
+ */
19053
+ getSvgPath() {
19054
+ const w = this.width;
19055
+ const h = this.height;
19056
+ switch (this.shapeType) {
19057
+ case ShapeType.Rectangle:
19058
+ return `M ${this.x} ${this.y} L ${this.x + w} ${this.y} L ${this.x + w} ${this.y + h} L ${this.x} ${this.y + h} Z`;
19059
+ case ShapeType.Ellipse:
19060
+ const cx = this.x + w / 2;
19061
+ const cy = this.y + h / 2;
19062
+ const rx = w / 2;
19063
+ const ry = h / 2;
19064
+ return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;
19065
+ case ShapeType.Triangle:
19066
+ const topX = this.x + w / 2;
19067
+ const topY = this.y;
19068
+ const bottomLeftX = this.x;
19069
+ const bottomLeftY = this.y + h;
19070
+ const bottomRightX = this.x + w;
19071
+ const bottomRightY = this.y + h;
19072
+ return `M ${topX} ${topY} L ${bottomRightX} ${bottomRightY} L ${bottomLeftX} ${bottomLeftY} Z`;
19073
+ default:
19074
+ return `M ${this.x} ${this.y} L ${this.x + w} ${this.y} L ${this.x + w} ${this.y + h} L ${this.x} ${this.y + h} Z`;
19075
+ }
19076
+ }
19077
+ }
19078
+
19079
+ class KritzelShapeTool extends KritzelBaseTool {
19080
+ shapeType = ShapeType.Rectangle;
19081
+ fillColor = 'transparent';
19082
+ strokeColor = '#000000';
19083
+ strokeWidth = 4;
19084
+ fontFamily = 'Arial';
19085
+ fontSize = 16;
19086
+ fontColor = '#000000';
19087
+ palette = [
19088
+ '#000000',
19089
+ '#FFFFFF',
19090
+ '#FF0000',
19091
+ '#00FF00',
19092
+ '#0000FF',
19093
+ '#FFFF00',
19094
+ '#FF00FF',
19095
+ '#00FFFF',
19096
+ '#808080',
19097
+ '#C0C0C0',
19098
+ '#800000',
19099
+ '#008000',
19100
+ '#000080',
19101
+ '#808000',
19102
+ '#800080',
19103
+ ];
19104
+ startX = 0;
19105
+ startY = 0;
19106
+ isDrawing = false;
19107
+ currentShape = null;
19108
+ constructor(core) {
19109
+ super(core);
19110
+ }
19111
+ handlePointerDown(event) {
19112
+ if (event.cancelable) {
19113
+ event.preventDefault();
19114
+ }
19115
+ if (event.pointerType === 'mouse') {
19116
+ const path = event.composedPath().slice(1);
19117
+ const objectElement = path.find(element => element.classList && element.classList.contains('object'));
19118
+ const object = this._core.findObjectById(objectElement?.id);
19119
+ const activeShape = this._core.store.activeShape;
19120
+ if (activeShape === null && object instanceof KritzelShape) {
19121
+ object.edit(event);
19122
+ return;
19123
+ }
19124
+ if (activeShape !== null && object instanceof KritzelShape) {
19125
+ activeShape.save();
19126
+ object.edit(event);
19127
+ return;
19128
+ }
19129
+ if (activeShape !== null && object instanceof KritzelShape === false) {
19130
+ this._core.resetActiveShape();
19131
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
19132
+ return;
19133
+ }
19134
+ if (KritzelEventHelper.isLeftClick(event) === false) {
19135
+ return;
19136
+ }
19137
+ this.startDrawing(event.clientX, event.clientY);
19138
+ }
19139
+ if (event.pointerType === 'touch') {
19140
+ const activePointers = Array.from(this._core.store.state.pointers.values());
19141
+ const path = event.composedPath().slice(1);
19142
+ const objectElement = path.find(element => element.classList && element.classList.contains('object'));
19143
+ const object = this._core.findObjectById(objectElement?.id);
19144
+ const activeShape = this._core.store.activeShape;
19145
+ if (activeShape === null && object instanceof KritzelShape) {
19146
+ object.edit(event);
19147
+ return;
19148
+ }
19149
+ if (activeShape !== null && object instanceof KritzelShape) {
19150
+ activeShape.save();
19151
+ object.edit(event);
19152
+ return;
19153
+ }
19154
+ if (activeShape !== null && object instanceof KritzelShape === false) {
19155
+ this._core.resetActiveShape();
19156
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
19157
+ return;
19158
+ }
19159
+ if (activePointers.length > 1) {
19160
+ return;
19161
+ }
19162
+ const clientX = Math.round(activePointers[0].clientX);
19163
+ const clientY = Math.round(activePointers[0].clientY);
19164
+ this.startDrawing(clientX, clientY);
19165
+ }
19166
+ }
19167
+ handlePointerMove(event) {
19168
+ if (event.cancelable) {
19169
+ event.preventDefault();
19170
+ }
19171
+ if (!this.isDrawing || !this.currentShape) {
19172
+ return;
19173
+ }
19174
+ if (event.pointerType === 'mouse') {
19175
+ this.updateShapeSize(event.clientX, event.clientY);
19176
+ }
19177
+ if (event.pointerType === 'touch') {
19178
+ const activePointers = Array.from(this._core.store.state.pointers.values());
19179
+ if (activePointers.length === 1) {
19180
+ const clientX = Math.round(activePointers[0].clientX);
19181
+ const clientY = Math.round(activePointers[0].clientY);
19182
+ this.updateShapeSize(clientX, clientY);
19183
+ }
19184
+ }
19185
+ }
19186
+ handlePointerUp(event) {
19187
+ if (event.cancelable) {
19188
+ event.preventDefault();
19189
+ }
19190
+ if (!this.isDrawing || !this.currentShape) {
19191
+ return;
19192
+ }
19193
+ this.finishDrawing();
19194
+ }
19195
+ /**
19196
+ * Start drawing a shape. Following the same pattern as LineTool/BrushTool:
19197
+ * - Store screen coordinates for startX, startY
19198
+ * - Set translateX/Y to -viewportTranslateX/Y (viewport offset)
19199
+ * - Set x, y to the actual screen position
19200
+ * - Let updateDimensions() convert to world coordinates
19201
+ */
19202
+ startDrawing(clientX, clientY) {
19203
+ // Store screen coordinates (relative to host element)
19204
+ this.startX = clientX - this._core.store.offsetX;
19205
+ this.startY = clientY - this._core.store.offsetY;
19206
+ this.isDrawing = true;
19207
+ // Create shape using screen coordinates, following Path/Line pattern
19208
+ this.currentShape = KritzelShape.create(this._core, {
19209
+ x: this.startX,
19210
+ y: this.startY,
19211
+ translateX: -this._core.store.state.translateX,
19212
+ translateY: -this._core.store.state.translateY,
19213
+ width: 1,
19214
+ height: 1,
19215
+ shapeType: this.shapeType,
19216
+ fillColor: this.fillColor,
19217
+ strokeColor: this.strokeColor,
19218
+ strokeWidth: this.strokeWidth,
19219
+ fontSize: this.fontSize,
19220
+ fontFamily: this.fontFamily,
19221
+ fontColor: this.fontColor,
19222
+ });
19223
+ this._core.store.state.objects.insert(this.currentShape);
19224
+ this._core.rerender();
19225
+ }
19226
+ /**
19227
+ * Update shape size during drawing. Following the same pattern as LineTool:
19228
+ * - Use screen coordinates directly
19229
+ * - The shape's x, y, width, height are all in screen space
19230
+ * - updateDimensions() handles conversion to world coordinates
19231
+ */
19232
+ updateShapeSize(clientX, clientY) {
19233
+ if (!this.currentShape) {
19234
+ return;
19235
+ }
19236
+ const currentX = clientX - this._core.store.offsetX;
19237
+ const currentY = clientY - this._core.store.offsetY;
19238
+ // Calculate bounding box in screen coordinates
19239
+ const minX = Math.min(this.startX, currentX);
19240
+ const minY = Math.min(this.startY, currentY);
19241
+ const width = Math.abs(currentX - this.startX);
19242
+ const height = Math.abs(currentY - this.startY);
19243
+ // Update shape with screen coordinates
19244
+ this.currentShape.x = minX;
19245
+ this.currentShape.y = minY;
19246
+ this.currentShape.width = Math.max(1, width);
19247
+ this.currentShape.height = Math.max(1, height);
19248
+ // Recalculate world-space translateX/Y
19249
+ // Reset translateX/Y to initial value before updateDimensions
19250
+ this.currentShape.translateX = -this._core.store.state.translateX;
19251
+ this.currentShape.translateY = -this._core.store.state.translateY;
19252
+ this.currentShape.updateDimensions();
19253
+ this._core.store.state.objects.update(this.currentShape);
19254
+ }
19255
+ finishDrawing() {
19256
+ if (!this.currentShape) {
19257
+ return;
19258
+ }
19259
+ // Remove shape if it's too small (likely an accidental click)
19260
+ // Compare in screen space
19261
+ if (this.currentShape.width < 10 && this.currentShape.height < 10) {
19262
+ const shapeId = this.currentShape.id;
19263
+ this._core.store.state.objects.remove(o => o.id === shapeId);
19264
+ }
19265
+ else {
19266
+ this.currentShape.zIndex = this._core.store.currentZIndex;
19267
+ this._core.store.state.objects.update(this.currentShape);
19268
+ this._core.engine.emitObjectsChange();
19269
+ this._core.selectObjects([this.currentShape]);
19270
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
19271
+ }
19272
+ this.isDrawing = false;
19273
+ this.currentShape = null;
19274
+ this._core.rerender();
19275
+ }
19276
+ }
19277
+
18535
19278
  const ABSOLUTE_SCALE_MAX = 1000;
18536
19279
  const ABSOLUTE_SCALE_MIN = 0.0001;
18537
19280
 
@@ -35770,6 +36513,14 @@ class KritzelViewport {
35770
36513
  this._core.rerender();
35771
36514
  }, 100);
35772
36515
  }
36516
+ /**
36517
+ * Cancels any pending debounced viewport updates.
36518
+ * Should be called before switching workspaces to prevent the old workspace's
36519
+ * viewport state from being saved to the new workspace.
36520
+ */
36521
+ cancelPendingUpdates() {
36522
+ this._debounceUpdate.cancel();
36523
+ }
35773
36524
  handleResize() {
35774
36525
  this._core.store.state.viewportWidth = this._core.store.state.host.clientWidth;
35775
36526
  this._core.store.state.viewportHeight = this._core.store.state.host.clientHeight;
@@ -36082,7 +36833,7 @@ const DEFAULT_ENGINE_CONFIG = {
36082
36833
  contextMenuY: 0,
36083
36834
  skipContextMenu: false,
36084
36835
  debugInfo: {
36085
- showObjectInfo: false,
36836
+ showObjectInfo: true,
36086
36837
  showViewportInfo: false
36087
36838
  },
36088
36839
  host: null,
@@ -36191,6 +36942,17 @@ class KritzelReviver {
36191
36942
  case 'KritzelText':
36192
36943
  revivedObj = KritzelText.create(this._core, obj.fontSize, obj.fontFamily).deserialize(obj);
36193
36944
  break;
36945
+ case 'KritzelShape':
36946
+ revivedObj = KritzelShape.create(this._core, {
36947
+ shapeType: obj.shapeType,
36948
+ fillColor: obj.fillColor,
36949
+ strokeColor: obj.strokeColor,
36950
+ strokeWidth: obj.strokeWidth,
36951
+ fontSize: obj.fontSize,
36952
+ fontFamily: obj.fontFamily,
36953
+ fontColor: obj.fontColor,
36954
+ }).deserialize(obj);
36955
+ break;
36194
36956
  case 'KritzelImage':
36195
36957
  revivedObj = KritzelImage.create(this._core).deserialize(obj);
36196
36958
  break;
@@ -36221,6 +36983,9 @@ class KritzelReviver {
36221
36983
  case 'KritzelLineTool':
36222
36984
  revivedObj = new KritzelLineTool(this._core);
36223
36985
  break;
36986
+ case 'KritzelShapeTool':
36987
+ revivedObj = new KritzelShapeTool(this._core);
36988
+ break;
36224
36989
  default:
36225
36990
  revivedObj = obj;
36226
36991
  }
@@ -36696,6 +37461,10 @@ class KritzelStore {
36696
37461
  const activeTexts = this._state.objects.filter(o => o instanceof KritzelText && o.isEditing);
36697
37462
  return activeTexts.length > 0 ? activeTexts[0] : null;
36698
37463
  }
37464
+ get activeShape() {
37465
+ const activeShapes = this._state.objects.filter(o => o instanceof KritzelShape && o.isEditing);
37466
+ return activeShapes.length > 0 ? activeShapes[0] : null;
37467
+ }
36699
37468
  get currentPath() {
36700
37469
  const drawingPaths = this._state.objects.filter(o => o instanceof KritzelPath && o.isCompleted === false);
36701
37470
  return drawingPaths.length > 0 ? drawingPaths[0] : null;
@@ -36944,6 +37713,11 @@ class KritzelCore {
36944
37713
  if (this._store.state.objects && this._store.state.objects.isReady) {
36945
37714
  this._store.state.objects.destroy();
36946
37715
  }
37716
+ // Create new ObjectMap with its own Y.Doc for this workspace
37717
+ const objectsMap = new KritzelObjectMap();
37718
+ // Assign immediately so the UI shows an empty state while loading,
37719
+ // instead of showing the old workspace's objects with the new workspace's viewport
37720
+ this._store.state.objects = objectsMap;
36947
37721
  // Set active workspace
36948
37722
  this._store.state.activeWorkspace = activeWorkspace;
36949
37723
  this._store.state.workspaces = this.loadWorkspacesFromAppState();
@@ -36952,10 +37726,7 @@ class KritzelCore {
36952
37726
  this._store.state.translateX = viewport.translateX ?? 0;
36953
37727
  this._store.state.translateY = viewport.translateY ?? 0;
36954
37728
  this._store.state.scale = viewport.scale ?? 1;
36955
- // Create new ObjectMap with its own Y.Doc for this workspace
36956
- const objectsMap = new KritzelObjectMap();
36957
37729
  await objectsMap.initialize(this, activeWorkspace.id, this._syncConfig);
36958
- this._store.state.objects = objectsMap;
36959
37730
  // Rebuild anchor index after loading objects
36960
37731
  this._anchorManager.rebuildIndex();
36961
37732
  this.engine.emitObjectsChange();
@@ -37332,6 +38103,12 @@ class KritzelCore {
37332
38103
  }
37333
38104
  }
37334
38105
  }
38106
+ resetActiveShape() {
38107
+ const activeShape = this._store.activeShape;
38108
+ if (activeShape) {
38109
+ activeShape.save();
38110
+ }
38111
+ }
37335
38112
  getObjectFromPointerEvent(event, selector = '.object') {
37336
38113
  const shadowRoot = this._store.state.host?.shadowRoot;
37337
38114
  if (!shadowRoot)
@@ -37404,6 +38181,14 @@ class KritzelCore {
37404
38181
  return { x: worldX, y: worldY };
37405
38182
  }
37406
38183
  beforeWorkspaceChange() {
38184
+ // Cancel any pending debounced viewport updates to prevent them from
38185
+ // saving the old workspace's viewport to the new workspace
38186
+ this._kritzelEngine.viewport?.cancelPendingUpdates();
38187
+ // Immediately save the current workspace's viewport before switching
38188
+ const currentWorkspace = this._store.state.activeWorkspace;
38189
+ if (currentWorkspace) {
38190
+ this.updateWorkspaceViewport(this._store.state.translateX, this._store.state.translateY, this._store.state.scale);
38191
+ }
37407
38192
  this.resetActiveText();
37408
38193
  this.clearSelection();
37409
38194
  this._store.setState('activeTool', KritzelToolRegistry.getTool('selection'));
@@ -37833,9 +38618,9 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
37833
38618
  height: this.core.store.state.viewportHeight / this.core.store.state.scale,
37834
38619
  depth: 100,
37835
38620
  };
37836
- const visibleObjects = this.core.store.state.objects.query(viewportBounds);
38621
+ const visibleObjects = this.core.store.state.objects.query(viewportBounds).sort((a, b) => a.zIndex - b.zIndex);
37837
38622
  this.core.cursorManager.applyCursor();
37838
- return (h(Host, { key: '4a7e8c72ad1f80c3c31aa37eff33e78634cb37d1' }, this.core.store.state.debugInfo.showViewportInfo && (h("div", { key: '3c8981ce6cafbc49f4f04189d27809c511bf45c4', class: "debug-panel" }, h("div", { key: '428d483a87b98cde24446a0a26ba790ec2a6358b' }, "ActiveWorkspaceId: ", this.core.store.state?.activeWorkspace?.id), h("div", { key: '3ec597c219109c026f78e5018a885e88e51aa5c4' }, "ActiveWorkspaceName: ", this.core.store.state?.activeWorkspace?.name), h("div", { key: '803c0d009b19fdc7c465ef14f3b5f278a954a912' }, "TranslateX: ", this.core.store.state?.translateX), h("div", { key: '8b1aef0ae845cdf4b93afe59d8c78c84dd181a2d' }, "TranslateY: ", this.core.store.state?.translateY), h("div", { key: '137ead0c39a2fba55b4c4dde53fb09d0832439e1' }, "ViewportWidth: ", this.core.store.state?.viewportWidth), h("div", { key: 'b19f710385e4306620176551853eb2645b96ca7a' }, "ViewportHeight: ", this.core.store.state?.viewportHeight), h("div", { key: '943b55daada95aa37b759e45a15ffcfca76fba72' }, "PointerCount: ", this.core.store.state.pointers.size), h("div", { key: 'd001782dd4bc48c84c08477b26e5f3fce8df0b47' }, "Scale: ", this.core.store.state?.scale), h("div", { key: 'ed640d3905b39a995ba40a1cbf38f10a4aa1b400' }, "ActiveTool: ", this.core.store.state?.activeTool?.name), h("div", { key: '154888aabbb56365aaf4584b0b991be848629e3e' }, "HasViewportChanged: ", this.core.store.state?.hasViewportChanged ? 'true' : 'false'), h("div", { key: 'c0c39e988940baf20137de8a0eeda2c085da2810' }, "IsEnabled: ", this.core.store.state?.isEnabled ? 'true' : 'false'), h("div", { key: 'abd5a79b27bc75e898877d33097597c057dc3f2b' }, "IsScaling: ", this.core.store.state?.isScaling ? 'true' : 'false'), h("div", { key: '9c49bf3246525c9a755bb293bec8a143ade97158' }, "IsPanning: ", this.core.store.state?.isPanning ? 'true' : 'false'), h("div", { key: '88ff8ab48af31bf036719f72a5a3726780ab9720' }, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), h("div", { key: '9650075f855fcf91b7303d3ace14242075fc523d' }, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), h("div", { key: '911acb1f90f9812d30dc0aebceb207aecf9b4248' }, "IsResizeHandleSelected: ", this.core.store.state.isResizeHandleSelected ? 'true' : 'false'), h("div", { key: 'b65db638d3cefbd74e2d03b639ee5fe86a2a858b' }, "IsRotationHandleSelected: ", this.core.store.state.isRotationHandleSelected ? 'true' : 'false'), h("div", { key: 'c53ca259dadc656762733119b4086c1f82235a7e' }, "IsRotationHandleHovered: ", this.core.store.state.isRotationHandleHovered ? 'true' : 'false'), h("div", { key: 'ae2d7a8917af450eb3bfd8e171a87530f337c0c2' }, "IsDrawing: ", this.core.store.state.isDrawing ? 'true' : 'false'), h("div", { key: '5633cd9901ec028e4f5433c84b07321932beea66' }, "IsWriting: ", this.core.store.state.isWriting ? 'true' : 'false'), h("div", { key: '82232a8eec470562e5658dee9713c855e78ca6a3' }, "IsPointerDown: ", this.core.store.isPointerDown ? 'true' : 'false'), h("div", { key: '5b6b04b323a21ef37ddb144721ea01dccc7aec8b' }, "PointerX: ", this.core.store.state?.pointerX), h("div", { key: '3287f804515cfa31eaa755332e2043fce4feb7a9' }, "PointerY: ", this.core.store.state?.pointerY), h("div", { key: '3a59fd4db60f6f05d419de39149ea10e482875d4' }, "SelectedObjects: ", this.core.store.selectionGroup?.objects.length || 0), h("div", { key: 'f91a8ea9dfc50e5f1ae89d66c7609a103e3263a4' }, "ViewportCenter: (", viewportCenterX.toFixed(2), ", ", viewportCenterY.toFixed(2), ")"))), h("div", { key: '40ba8fb5530243c18e0b0c3ad68dadb2cbc615a1', id: "origin", class: "origin", style: {
38623
+ return (h(Host, { key: '209ccf8414c635c9e04ca4807c95a29c629071ec' }, this.core.store.state.debugInfo.showViewportInfo && (h("div", { key: 'df6a03d1341887960bb91cbaa0a5dca6880a9293', class: "debug-panel" }, h("div", { key: '65157757ec6549ad2af311085a9618ab661f5ac0' }, "ActiveWorkspaceId: ", this.core.store.state?.activeWorkspace?.id), h("div", { key: '20137b6c651a9aa8df15bce66d5bfe870a7af139' }, "ActiveWorkspaceName: ", this.core.store.state?.activeWorkspace?.name), h("div", { key: '49dd30286641236ae428c731bb181cb06269852e' }, "TranslateX: ", this.core.store.state?.translateX), h("div", { key: 'd8ee431a10335e99aec40a596817765d7ee3f67b' }, "TranslateY: ", this.core.store.state?.translateY), h("div", { key: '34b1f31146080780433d6c1718d13bbfe397cb9b' }, "ViewportWidth: ", this.core.store.state?.viewportWidth), h("div", { key: '4c279a106101cf808c91a2be4987569b21ae52b3' }, "ViewportHeight: ", this.core.store.state?.viewportHeight), h("div", { key: '6ebd7ad3c803ef45d58a74180c52e8be8af8bca3' }, "PointerCount: ", this.core.store.state.pointers.size), h("div", { key: '345970c8b2b54f3a0d8fe1d9bb1b7b33023db386' }, "Scale: ", this.core.store.state?.scale), h("div", { key: 'fc265ae0e71cf22311cab3006dfc29b9d24397d2' }, "ActiveTool: ", this.core.store.state?.activeTool?.name), h("div", { key: '9f921032a58b55e60f82d11a76f269051357d3e1' }, "HasViewportChanged: ", this.core.store.state?.hasViewportChanged ? 'true' : 'false'), h("div", { key: '6d197e06cc362a9ecb8bfe00d272aecfec2b49e1' }, "IsEnabled: ", this.core.store.state?.isEnabled ? 'true' : 'false'), h("div", { key: '5313589ba2a509c95a5730dcf29c4003d9884cbf' }, "IsScaling: ", this.core.store.state?.isScaling ? 'true' : 'false'), h("div", { key: '8af9f9d6e33a2897c20962048bbf2a058f9d4a45' }, "IsPanning: ", this.core.store.state?.isPanning ? 'true' : 'false'), h("div", { key: '81aec0050d3e2122643b61fd725e71b25d97bc27' }, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), h("div", { key: 'c9956f05c01b74ee1666d9395a2715c3463fe401' }, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), h("div", { key: 'ae0a01c8f8aafc08326b136720c6a75b6aec6299' }, "IsResizeHandleSelected: ", this.core.store.state.isResizeHandleSelected ? 'true' : 'false'), h("div", { key: '7816d40d73248a55120440e6d721325e1894178e' }, "IsRotationHandleSelected: ", this.core.store.state.isRotationHandleSelected ? 'true' : 'false'), h("div", { key: 'c22383bacca0ada584f2e8a8577523c905d74ae2' }, "IsRotationHandleHovered: ", this.core.store.state.isRotationHandleHovered ? 'true' : 'false'), h("div", { key: '8185a7318c6cdfde558cc372b79582d58b706f9e' }, "IsDrawing: ", this.core.store.state.isDrawing ? 'true' : 'false'), h("div", { key: '2d56b05377693ef032ab2316fa753ecedf264b9c' }, "IsWriting: ", this.core.store.state.isWriting ? 'true' : 'false'), h("div", { key: '2e2bf9fd321ef04dc0ac6dc21539eb0117c9fb23' }, "IsPointerDown: ", this.core.store.isPointerDown ? 'true' : 'false'), h("div", { key: '3118ab970d5d37e01405c42308fc051d675d4bfa' }, "PointerX: ", this.core.store.state?.pointerX), h("div", { key: 'd8a31065843f89552f2d9c03dcbca960a716fa6c' }, "PointerY: ", this.core.store.state?.pointerY), h("div", { key: 'cb8d28b6ea63cbb6572f761011fccb847b748227' }, "SelectedObjects: ", this.core.store.selectionGroup?.objects.length || 0), h("div", { key: 'd112a7e833c265085246817423557bfdc5b30b74' }, "ViewportCenter: (", viewportCenterX.toFixed(2), ", ", viewportCenterY.toFixed(2), ")"))), h("div", { key: 'df4f302192a8fc9644b7f883618b0a0f8a600dc8', id: "origin", class: "origin", style: {
37839
38624
  transform: `matrix(${this.core.store.state?.scale}, 0, 0, ${this.core.store.state?.scale}, ${this.core.store.state?.translateX}, ${this.core.store.state?.translateY})`,
37840
38625
  } }, visibleObjects?.map(object => {
37841
38626
  return (h("div", { key: object.id, style: {
@@ -37881,7 +38666,32 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
37881
38666
  backgroundColor: object.backgroundColor,
37882
38667
  overflow: 'visible',
37883
38668
  textRendering: this.core.store.state.isScaling || this.core.store.state.isPanning ? 'optimizeSpeed' : 'auto',
37884
- } })), KritzelClassHelper.isInstanceOf(object, 'KritzelCustomElement') && (h("div", { ref: el => object.mount(el), style: {
38669
+ } })), KritzelClassHelper.isInstanceOf(object, 'KritzelShape') && (h("div", { ref: el => object.mount(el), onPointerDown: e => object.handlePointerDown(e), onPointerMove: e => object.handlePointerMove(e), onPointerUp: e => object.handlePointerUp(e), style: {
38670
+ width: '100%',
38671
+ height: '100%',
38672
+ position: 'relative',
38673
+ overflow: 'visible',
38674
+ } }, h("svg", { xmlns: "http://www.w3.org/2000/svg", style: {
38675
+ position: 'absolute',
38676
+ top: '0',
38677
+ left: '0',
38678
+ width: '100%',
38679
+ height: '100%',
38680
+ overflow: 'visible',
38681
+ pointerEvents: 'none',
38682
+ }, viewBox: object.viewBox, preserveAspectRatio: "none" }, h("path", { d: object.getSvgPath(), fill: object.fillColor, stroke: object.strokeColor, "stroke-width": object.strokeWidth })), h("div", { ref: el => object.mountTextEditor(el), style: {
38683
+ position: 'absolute',
38684
+ top: '0',
38685
+ left: '0',
38686
+ width: '100%',
38687
+ height: '100%',
38688
+ display: 'flex',
38689
+ alignItems: 'center',
38690
+ justifyContent: 'center',
38691
+ textAlign: 'center',
38692
+ overflow: 'hidden',
38693
+ pointerEvents: object.isEditing ? 'auto' : 'none',
38694
+ } }))), KritzelClassHelper.isInstanceOf(object, 'KritzelCustomElement') && (h("div", { ref: el => object.mount(el), style: {
37885
38695
  width: '100%',
37886
38696
  height: '100%',
37887
38697
  pointerEvents: 'auto',
@@ -37897,7 +38707,13 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
37897
38707
  borderWidth: KritzelDevicesHelper.isFirefox() ? object.borderWidth + 'px' : '0',
37898
38708
  borderStyle: KritzelDevicesHelper.isFirefox() ? 'solid' : 'none',
37899
38709
  borderColor: KritzelDevicesHelper.isFirefox() ? object.borderColor : 'transparent',
37900
- } }))), this.core.store.state.debugInfo.showObjectInfo && object.isDebugInfoVisible && (h("g", { style: { pointerEvents: 'none' } }, h("foreignObject", { x: object.totalWidth.toString(), y: "0", width: "400px", height: "160px", style: { minHeight: '0', minWidth: '0' } }, h("div", { style: { width: '100%', height: '100%' } }, h("div", { style: { whiteSpace: 'nowrap' } }, "Id: ", object.id), h("div", { style: { whiteSpace: 'nowrap' } }, "width: ", object.width), h("div", { style: { whiteSpace: 'nowrap' } }, "height: ", object.height), h("div", { style: { whiteSpace: 'nowrap' } }, "translateX: ", object.translateX), h("div", { style: { whiteSpace: 'nowrap' } }, "translateY: ", object.translateY), h("div", { style: { whiteSpace: 'nowrap' } }, "rotationDegrees: ", object.rotationDegrees)))))), h("svg", { xmlns: "http://www.w3.org/2000/svg", style: {
38710
+ } })))), this.core.store.state.debugInfo.showObjectInfo && object.isDebugInfoVisible && (h("div", { style: {
38711
+ pointerEvents: 'none',
38712
+ position: 'absolute',
38713
+ left: `${object.totalWidth}px`,
38714
+ top: '0',
38715
+ zIndex: (object.zIndex + 2).toString(),
38716
+ } }, h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "Id: ", object.id), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "width: ", object.width), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "height: ", object.height), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateX: ", object.translateX), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateY: ", object.translateY), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "rotationDegrees: ", object.rotationDegrees), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "zIndex: ", object.zIndex))), h("svg", { xmlns: "http://www.w3.org/2000/svg", style: {
37901
38717
  zIndex: (object.zIndex + 1).toString(),
37902
38718
  height: object?.totalHeight.toString(),
37903
38719
  width: object?.totalWidth.toString(),
@@ -38053,7 +38869,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
38053
38869
  stroke: 'var(--kritzel-snap-indicator-stroke, #3b82f6)',
38054
38870
  strokeWidth: data.indicatorStrokeWidth,
38055
38871
  } }))));
38056
- })()), this.core.store.state.isContextMenuVisible && (h("kritzel-context-menu", { key: '7e350c48da76c54a223f23ead9dea8018b0bc36c', class: "context-menu", ref: el => (this.contextMenuElement = el), items: this.core.store.state.contextMenuItems, objects: this.core.store.selectionGroup?.objects || [], style: {
38872
+ })()), this.core.store.state.isContextMenuVisible && (h("kritzel-context-menu", { key: '81b44614c23f4016a1daa914ef8ea73eda0869eb', class: "context-menu", ref: el => (this.contextMenuElement = el), items: this.core.store.state.contextMenuItems, objects: this.core.store.selectionGroup?.objects || [], style: {
38057
38873
  position: 'fixed',
38058
38874
  left: `${this.core.store.state.contextMenuX}px`,
38059
38875
  top: `${this.core.store.state.contextMenuY}px`,
@@ -38064,7 +38880,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
38064
38880
  y: (-this.core.store.state.translateY + this.core.store.state.contextMenuY) / this.core.store.state.scale,
38065
38881
  }, this.core.store.selectionGroup?.objects);
38066
38882
  this.hideContextMenu();
38067
- }, onClose: () => this.hideContextMenu() })), this.core.store.state?.activeTool instanceof KritzelEraserTool && !this.core.store.state.isScaling && h("kritzel-cursor-trail", { key: '7923a3f6a92fa71911c971166171317b5bc421bf', core: this.core })));
38883
+ }, onClose: () => this.hideContextMenu() })), this.core.store.state?.activeTool instanceof KritzelEraserTool && !this.core.store.state.isScaling && h("kritzel-cursor-trail", { key: 'f748cd15c916d9fcb5fbf445167c69c1cc8aea63', core: this.core })));
38068
38884
  }
38069
38885
  static get watchers() { return {
38070
38886
  "workspace": ["onWorkspaceChange"],
@@ -38147,7 +38963,7 @@ function defineCustomElement() {
38147
38963
  } });
38148
38964
  }
38149
38965
 
38150
- export { isNode as A, min$2 as B, pow as C, HocuspocusProviderWebsocket as D, KritzelLine as E, KritzelLineTool as F, KritzelEraserTool as G, HocuspocusProvider as H, KritzelImageTool as I, KritzelCursorHelper as J, KritzelImage as K, KritzelSelectionTool as L, IndexedDBSyncProvider as M, KritzelAppStateMap as N, Observable$1 as O, KritzelAnchorManager as P, ABSOLUTE_SCALE_MAX as Q, ABSOLUTE_SCALE_MIN as R, defineCustomElement as S, KritzelEngine as T, writeVarUint8Array$2 as a, readVarUint8Array$2 as b, applyUpdate as c, encodeStateVector as d, encodeStateAsUpdate as e, createEncoder$1 as f, createDecoder$1 as g, create$8 as h, fromBase64 as i, toBase64 as j, createUint8ArrayFromArrayBuffer as k, offChange as l, readVarString$2 as m, floor$2 as n, onChange as o, getUnixTime$1 as p, equalityDeep$1 as q, readVarUint$2 as r, setIfUndefined$1 as s, toUint8Array$1 as t, writeVarString$2 as u, varStorage as v, writeVarUint$2 as w, map as x, ObservableV2 as y, length$3 as z };
38151
- //# sourceMappingURL=p-CuhOrcET.js.map
38966
+ export { isNode as A, min$2 as B, pow as C, HocuspocusProviderWebsocket as D, KritzelLine as E, KritzelLineTool as F, KritzelEraserTool as G, HocuspocusProvider as H, KritzelImageTool as I, KritzelCursorHelper as J, KritzelImage as K, KritzelSelectionTool as L, IndexedDBSyncProvider as M, KritzelAppStateMap as N, Observable$1 as O, KritzelAnchorManager as P, ABSOLUTE_SCALE_MAX as Q, ABSOLUTE_SCALE_MIN as R, ShapeType as S, KritzelShapeTool as T, defineCustomElement as U, KritzelEngine as V, writeVarUint8Array$2 as a, readVarUint8Array$2 as b, applyUpdate as c, encodeStateVector as d, encodeStateAsUpdate as e, createEncoder$1 as f, createDecoder$1 as g, create$8 as h, fromBase64 as i, toBase64 as j, createUint8ArrayFromArrayBuffer as k, offChange as l, readVarString$2 as m, floor$2 as n, onChange as o, getUnixTime$1 as p, equalityDeep$1 as q, readVarUint$2 as r, setIfUndefined$1 as s, toUint8Array$1 as t, writeVarString$2 as u, varStorage as v, writeVarUint$2 as w, map as x, ObservableV2 as y, length$3 as z };
38967
+ //# sourceMappingURL=p-CnRfQsIC.js.map
38152
38968
 
38153
- //# sourceMappingURL=p-CuhOrcET.js.map
38969
+ //# sourceMappingURL=p-CnRfQsIC.js.map