kritzel-stencil 0.0.162 → 0.0.164

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 (116) 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 +760 -27
  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-shape-tool.config.js +26 -0
  37. package/dist/collection/configs/default-shape-tool.config.js.map +1 -0
  38. package/dist/collection/enums/shape-type.enum.js +7 -0
  39. package/dist/collection/enums/shape-type.enum.js.map +1 -0
  40. package/dist/collection/helpers/geometry.helper.js +55 -0
  41. package/dist/collection/helpers/geometry.helper.js.map +1 -1
  42. package/dist/collection/interfaces/toolbar-control.interface.js.map +1 -1
  43. package/dist/components/index.js +3 -3
  44. package/dist/components/kritzel-brush-style.js +1 -1
  45. package/dist/components/kritzel-context-menu.js +1 -1
  46. package/dist/components/kritzel-control-brush-config.js +1 -1
  47. package/dist/components/kritzel-control-text-config.js +1 -1
  48. package/dist/components/kritzel-controls.js +1 -1
  49. package/dist/components/kritzel-editor.js +49 -16
  50. package/dist/components/kritzel-editor.js.map +1 -1
  51. package/dist/components/kritzel-engine.js +1 -1
  52. package/dist/components/kritzel-icon.js +1 -1
  53. package/dist/components/kritzel-menu-item.js +1 -1
  54. package/dist/components/kritzel-menu.js +1 -1
  55. package/dist/components/kritzel-split-button.js +1 -1
  56. package/dist/components/kritzel-utility-panel.js +1 -1
  57. package/dist/components/kritzel-workspace-manager.js +1 -1
  58. package/dist/components/{p-Cqr0Bah5.js → p-5OECjGHq.js} +3 -3
  59. package/dist/components/{p-Cqr0Bah5.js.map → p-5OECjGHq.js.map} +1 -1
  60. package/dist/components/{p-CvLFRlQU.js → p-BSBMBjhq.js} +3 -3
  61. package/dist/components/{p-CvLFRlQU.js.map → p-BSBMBjhq.js.map} +1 -1
  62. package/dist/components/{p-7_lwv0zQ.js → p-BuS7MM1j.js} +4 -4
  63. package/dist/components/{p-7_lwv0zQ.js.map → p-BuS7MM1j.js.map} +1 -1
  64. package/dist/components/{p-BixlbUD7.js → p-Cv4BGNPb.js} +6 -2
  65. package/dist/components/p-Cv4BGNPb.js.map +1 -0
  66. package/dist/components/{p-dMCB4tJA.js → p-D1YAsWrL.js} +3 -3
  67. package/dist/components/{p-dMCB4tJA.js.map → p-D1YAsWrL.js.map} +1 -1
  68. package/dist/components/{p-CDteBYm9.js → p-D8L0t-Ro.js} +3 -3
  69. package/dist/components/{p-CDteBYm9.js.map → p-D8L0t-Ro.js.map} +1 -1
  70. package/dist/components/{p-DZ7kxJUx.js → p-DguzZn_x.js} +3 -3
  71. package/dist/components/{p-DZ7kxJUx.js.map → p-DguzZn_x.js.map} +1 -1
  72. package/dist/components/{p-sokRZ7Vn.js → p-Dz2XHHqa.js} +145 -5
  73. package/dist/components/p-Dz2XHHqa.js.map +1 -0
  74. package/dist/components/{p-CuhOrcET.js → p-DzUUppVL.js} +837 -21
  75. package/dist/components/p-DzUUppVL.js.map +1 -0
  76. package/dist/components/{p-CkD1PQQX.js → p-I3iPEDpx.js} +5 -5
  77. package/dist/components/{p-CkD1PQQX.js.map → p-I3iPEDpx.js.map} +1 -1
  78. package/dist/components/{p-DKwJJuFb.js → p-tp96UZ0l.js} +83 -19
  79. package/dist/components/p-tp96UZ0l.js.map +1 -0
  80. package/dist/esm/{default-line-tool.config-C35m-d1Y.js → default-line-tool.config-C35P3XfD.js} +332 -10
  81. package/dist/esm/default-line-tool.config-C35P3XfD.js.map +1 -0
  82. package/dist/esm/index.js +2 -2
  83. package/dist/esm/kritzel-color_22.entry.js +760 -27
  84. package/dist/esm/loader.js +1 -1
  85. package/dist/esm/stencil.js +1 -1
  86. package/dist/stencil/index.esm.js +1 -1
  87. package/dist/stencil/p-3e2b5c42.entry.js +10 -0
  88. package/dist/stencil/p-3e2b5c42.entry.js.map +1 -0
  89. package/dist/stencil/p-C35P3XfD.js +2 -0
  90. package/dist/stencil/p-C35P3XfD.js.map +1 -0
  91. package/dist/stencil/stencil.esm.js +1 -1
  92. package/dist/types/classes/core/core.class.d.ts +1 -0
  93. package/dist/types/classes/core/store.class.d.ts +2 -0
  94. package/dist/types/classes/core/viewport.class.d.ts +6 -0
  95. package/dist/types/classes/managers/anchor.manager.d.ts +20 -0
  96. package/dist/types/classes/objects/path.class.d.ts +7 -0
  97. package/dist/types/classes/objects/shape.class.d.ts +116 -0
  98. package/dist/types/classes/tools/shape-tool.class.d.ts +37 -0
  99. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +2 -2
  100. package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +16 -1
  101. package/dist/types/components.d.ts +5 -5
  102. package/dist/types/configs/default-shape-tool.config.d.ts +2 -0
  103. package/dist/types/enums/shape-type.enum.d.ts +5 -0
  104. package/dist/types/helpers/geometry.helper.d.ts +21 -0
  105. package/dist/types/interfaces/toolbar-control.interface.d.ts +21 -3
  106. package/package.json +1 -1
  107. package/dist/cjs/default-line-tool.config-D1Ns0NmM.js.map +0 -1
  108. package/dist/components/p-BixlbUD7.js.map +0 -1
  109. package/dist/components/p-CuhOrcET.js.map +0 -1
  110. package/dist/components/p-DKwJJuFb.js.map +0 -1
  111. package/dist/components/p-sokRZ7Vn.js.map +0 -1
  112. package/dist/esm/default-line-tool.config-C35m-d1Y.js.map +0 -1
  113. package/dist/stencil/p-C35m-d1Y.js +0 -2
  114. package/dist/stencil/p-C35m-d1Y.js.map +0 -1
  115. package/dist/stencil/p-d142ef46.entry.js +0 -10
  116. package/dist/stencil/p-d142ef46.entry.js.map +0 -1
@@ -123,6 +123,61 @@ class KritzelGeometryHelper {
123
123
  }
124
124
  return closestIntersection;
125
125
  }
126
+ /**
127
+ * Generates a polygon approximation of an ellipse.
128
+ * @param centerX - X coordinate of ellipse center
129
+ * @param centerY - Y coordinate of ellipse center
130
+ * @param rx - Horizontal radius
131
+ * @param ry - Vertical radius
132
+ * @param segments - Number of segments (more = smoother approximation)
133
+ * @param rotation - Optional rotation angle in radians
134
+ */
135
+ static getEllipsePolygonApproximation(centerX, centerY, rx, ry, segments = 32, rotation = 0) {
136
+ const points = [];
137
+ const cos = Math.cos(rotation);
138
+ const sin = Math.sin(rotation);
139
+ for (let i = 0; i < segments; i++) {
140
+ const angle = (2 * Math.PI * i) / segments;
141
+ // Point on unrotated ellipse
142
+ const px = rx * Math.cos(angle);
143
+ const py = ry * Math.sin(angle);
144
+ // Apply rotation around center
145
+ const rotatedX = centerX + px * cos - py * sin;
146
+ const rotatedY = centerY + px * sin + py * cos;
147
+ points.push({ x: rotatedX, y: rotatedY });
148
+ }
149
+ return points;
150
+ }
151
+ /**
152
+ * Finds the closest intersection point between a line segment and a polygon
153
+ * defined as an array of points. Returns the intersection closest to lineStart,
154
+ * or null if no intersection.
155
+ */
156
+ static getLinePointsArrayIntersection(lineStart, lineEnd, polygonPoints) {
157
+ let closestIntersection = null;
158
+ let closestDistance = Infinity;
159
+ for (let i = 0; i < polygonPoints.length; i++) {
160
+ const edgeStart = polygonPoints[i];
161
+ const edgeEnd = polygonPoints[(i + 1) % polygonPoints.length];
162
+ const intersection = this.getLineIntersectionPoint(lineStart, lineEnd, edgeStart, edgeEnd);
163
+ if (intersection) {
164
+ const distance = Math.sqrt(Math.pow(intersection.x - lineStart.x, 2) +
165
+ Math.pow(intersection.y - lineStart.y, 2));
166
+ if (distance < closestDistance) {
167
+ closestDistance = distance;
168
+ closestIntersection = intersection;
169
+ }
170
+ }
171
+ }
172
+ return closestIntersection;
173
+ }
174
+ /**
175
+ * Checks if a point is inside a polygon defined as an array of points.
176
+ * This is a convenience wrapper that works with arbitrary polygon point arrays.
177
+ */
178
+ static isPointInPolygonPoints(point, polygonPoints) {
179
+ return this.isPointInPolygon(point, polygonPoints);
180
+ }
126
181
  }
127
182
 
128
183
  class KritzelBaseObject {
@@ -14441,6 +14496,91 @@ class KritzelPath extends KritzelBaseObject {
14441
14496
  const scaledHeight = this.boundingBox.height * viewportScale;
14442
14497
  return (scaledWidth * scaledHeight) < 500;
14443
14498
  }
14499
+ /**
14500
+ * Finds the point where a line from outsidePoint to the path's center
14501
+ * intersects the stroke edge. Returns null if no intersection found.
14502
+ * This is used for arrow clipping at the actual stroke edge.
14503
+ */
14504
+ getClipPoint(outsidePoint) {
14505
+ const centerX = this.centerX;
14506
+ const centerY = this.centerY;
14507
+ const halfStroke = this.strokeWidth / this.scale / 2;
14508
+ // Ensure adjusted points are computed
14509
+ if (this._adjustedPoints === null) {
14510
+ this._adjustedPoints = this.computeAdjustedPoints();
14511
+ }
14512
+ if (this._adjustedPoints.length < 1) {
14513
+ return null;
14514
+ }
14515
+ // Sample along the line from outsidePoint to center to find stroke edge
14516
+ const steps = 32;
14517
+ let prevOutside = true;
14518
+ for (let i = 1; i <= steps; i++) {
14519
+ const t = i / steps;
14520
+ const sampleX = outsidePoint.x + (centerX - outsidePoint.x) * t;
14521
+ const sampleY = outsidePoint.y + (centerY - outsidePoint.y) * t;
14522
+ // Check distance to path stroke
14523
+ let minDistance = Infinity;
14524
+ if (this._adjustedPoints.length === 1) {
14525
+ const p = this._adjustedPoints[0];
14526
+ const dx = sampleX - p[0];
14527
+ const dy = sampleY - p[1];
14528
+ minDistance = Math.sqrt(dx * dx + dy * dy);
14529
+ }
14530
+ else {
14531
+ for (let j = 0; j < this._adjustedPoints.length - 1; j++) {
14532
+ const p1 = this._adjustedPoints[j];
14533
+ const p2 = this._adjustedPoints[j + 1];
14534
+ const dist = this.pointToLineSegmentDistance(sampleX, sampleY, p1[0], p1[1], p2[0], p2[1]);
14535
+ if (dist < minDistance) {
14536
+ minDistance = dist;
14537
+ }
14538
+ }
14539
+ }
14540
+ const isInside = minDistance <= halfStroke;
14541
+ // Found the edge: transition from outside to inside
14542
+ if (prevOutside && isInside) {
14543
+ // Refine the intersection point using binary search
14544
+ let tLow = (i - 1) / steps;
14545
+ let tHigh = t;
14546
+ for (let k = 0; k < 8; k++) {
14547
+ const tMid = (tLow + tHigh) / 2;
14548
+ const midX = outsidePoint.x + (centerX - outsidePoint.x) * tMid;
14549
+ const midY = outsidePoint.y + (centerY - outsidePoint.y) * tMid;
14550
+ let midDist = Infinity;
14551
+ if (this._adjustedPoints.length === 1) {
14552
+ const p = this._adjustedPoints[0];
14553
+ const dx = midX - p[0];
14554
+ const dy = midY - p[1];
14555
+ midDist = Math.sqrt(dx * dx + dy * dy);
14556
+ }
14557
+ else {
14558
+ for (let j = 0; j < this._adjustedPoints.length - 1; j++) {
14559
+ const p1 = this._adjustedPoints[j];
14560
+ const p2 = this._adjustedPoints[j + 1];
14561
+ const dist = this.pointToLineSegmentDistance(midX, midY, p1[0], p1[1], p2[0], p2[1]);
14562
+ if (dist < midDist) {
14563
+ midDist = dist;
14564
+ }
14565
+ }
14566
+ }
14567
+ if (midDist <= halfStroke) {
14568
+ tHigh = tMid;
14569
+ }
14570
+ else {
14571
+ tLow = tMid;
14572
+ }
14573
+ }
14574
+ const finalT = (tLow + tHigh) / 2;
14575
+ return {
14576
+ x: outsidePoint.x + (centerX - outsidePoint.x) * finalT,
14577
+ y: outsidePoint.y + (centerY - outsidePoint.y) * finalT,
14578
+ };
14579
+ }
14580
+ prevOutside = !isInside;
14581
+ }
14582
+ return null;
14583
+ }
14444
14584
  }
14445
14585
 
14446
14586
  class KritzelImage extends KritzelBaseObject {
@@ -15225,6 +15365,7 @@ class KritzelBrushTool extends KritzelBaseTool {
15225
15365
  });
15226
15366
  updatedPath.id = currentPath.id;
15227
15367
  updatedPath.workspaceId = currentPath.workspaceId;
15368
+ updatedPath.zIndex = currentPath.zIndex;
15228
15369
  updatedPath.isCompleted = false;
15229
15370
  this._core.store.state.objects.update(updatedPath);
15230
15371
  }
@@ -15247,6 +15388,7 @@ class KritzelBrushTool extends KritzelBaseTool {
15247
15388
  });
15248
15389
  updatedPath.id = currentPath.id;
15249
15390
  updatedPath.workspaceId = currentPath.workspaceId;
15391
+ updatedPath.zIndex = currentPath.zIndex;
15250
15392
  updatedPath.isCompleted = false;
15251
15393
  this._core.store.state.objects.update(updatedPath);
15252
15394
  }
@@ -15263,7 +15405,6 @@ class KritzelBrushTool extends KritzelBaseTool {
15263
15405
  const currentPath = this._core.store.currentPath;
15264
15406
  if (currentPath) {
15265
15407
  currentPath.isCompleted = true;
15266
- currentPath.zIndex = this._core.store.currentZIndex;
15267
15408
  this._core.store.state.objects.update(currentPath);
15268
15409
  this._core.engine.emitObjectsChange();
15269
15410
  }
@@ -15275,7 +15416,6 @@ class KritzelBrushTool extends KritzelBaseTool {
15275
15416
  const currentPath = this._core.store.currentPath;
15276
15417
  if (currentPath) {
15277
15418
  currentPath.isCompleted = true;
15278
- currentPath.zIndex = this._core.store.currentZIndex;
15279
15419
  this._core.store.state.objects.update(currentPath);
15280
15420
  this._core.engine.emitObjectsChange();
15281
15421
  }
@@ -15675,6 +15815,7 @@ class KritzelLineTool extends KritzelBaseTool {
15675
15815
  });
15676
15816
  updatedLine.id = currentLine.id;
15677
15817
  updatedLine.workspaceId = currentLine.workspaceId;
15818
+ updatedLine.zIndex = currentLine.zIndex;
15678
15819
  updatedLine.isCompleted = false;
15679
15820
  this._core.store.state.objects.update(updatedLine);
15680
15821
  }
@@ -15701,6 +15842,7 @@ class KritzelLineTool extends KritzelBaseTool {
15701
15842
  });
15702
15843
  updatedLine.id = currentLine.id;
15703
15844
  updatedLine.workspaceId = currentLine.workspaceId;
15845
+ updatedLine.zIndex = currentLine.zIndex;
15704
15846
  updatedLine.isCompleted = false;
15705
15847
  this._core.store.state.objects.update(updatedLine);
15706
15848
  }
@@ -15717,7 +15859,6 @@ class KritzelLineTool extends KritzelBaseTool {
15717
15859
  const currentLine = this._core.store.currentLine;
15718
15860
  if (currentLine) {
15719
15861
  currentLine.isCompleted = true;
15720
- currentLine.zIndex = this._core.store.currentZIndex;
15721
15862
  this._core.store.state.objects.update(currentLine);
15722
15863
  this._core.engine.emitObjectsChange();
15723
15864
  // Switch to selection tool and select the drawn line
@@ -15731,7 +15872,6 @@ class KritzelLineTool extends KritzelBaseTool {
15731
15872
  const currentLine = this._core.store.currentLine;
15732
15873
  if (currentLine) {
15733
15874
  currentLine.isCompleted = true;
15734
- currentLine.zIndex = this._core.store.currentZIndex;
15735
15875
  this._core.store.state.objects.update(currentLine);
15736
15876
  this._core.engine.emitObjectsChange();
15737
15877
  // Switch to selection tool and select the drawn line
@@ -16059,6 +16199,10 @@ KritzelIconRegistry.registerIcons({
16059
16199
  'highlighter': '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-highlighter-icon lucide-highlighter"><path d="m9 11-6 6v3h9l3-3"/><path d="m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4"/></svg>',
16060
16200
  'eraser': '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21"/><path d="M22 21H7"/><path d="m5 11 9 9"/></svg>',
16061
16201
  'type': '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 7 4 4 20 4 20 7"/><line x1="9" x2="15" y1="20" y2="20"/><line x1="12" x2="12" y1="4" y2="20"/></svg>',
16202
+ 'shapes': '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8.3 10a.7.7 0 0 1-.626-1.079L11.4 3a.7.7 0 0 1 1.198-.043L16.3 8.9a.7.7 0 0 1-.572 1.1Z"/><rect x="3" y="14" width="7" height="7" rx="1"/><circle cx="17.5" cy="17.5" r="3.5"/></svg>',
16203
+ 'shape-rectangle': '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/></svg>',
16204
+ 'shape-ellipse': '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="12" rx="10" ry="8"/></svg>',
16205
+ 'shape-triangle': '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3L22 21H2L12 3Z"/></svg>',
16062
16206
  'image': '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><circle cx="9" cy="9" r="2"/><path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"/></svg>',
16063
16207
  'chevron-down': '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>',
16064
16208
  'chevron-up': '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>',
@@ -33136,7 +33280,34 @@ class KritzelAnchorManager {
33136
33280
  const reference = endpoint === 'start'
33137
33281
  ? this.lineLocalToWorld(line, line.endX, line.endY)
33138
33282
  : this.lineLocalToWorld(line, line.startX, line.startY);
33139
- const edgeIntersection = KritzelGeometryHelper.getLinePolygonIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, targetObject.rotatedPolygon);
33283
+ // Check for path object (uses stroke edge detection)
33284
+ const pathClipPoint = this.getPathClipPoint(targetObject, reference);
33285
+ if (pathClipPoint) {
33286
+ const localEdge = this.lineWorldToLocal(line, pathClipPoint.x, pathClipPoint.y);
33287
+ const totalLength = Math.sqrt(Math.pow(line.endX - line.startX, 2) +
33288
+ Math.pow(line.endY - line.startY, 2));
33289
+ const distanceFromStart = Math.sqrt(Math.pow(localEdge.x - line.startX, 2) +
33290
+ Math.pow(localEdge.y - line.startY, 2));
33291
+ const t = totalLength > 0 ? distanceFromStart / totalLength : endpoint === 'start' ? 0 : 1;
33292
+ return {
33293
+ localX: localEdge.x,
33294
+ localY: localEdge.y,
33295
+ worldX: pathClipPoint.x,
33296
+ worldY: pathClipPoint.y,
33297
+ t,
33298
+ };
33299
+ }
33300
+ // Check for custom clip polygon (ellipse, triangle shapes)
33301
+ const customClipPolygon = this.getClipPolygonForObject(targetObject);
33302
+ let edgeIntersection;
33303
+ if (customClipPolygon) {
33304
+ // Use custom polygon for non-rectangular shapes
33305
+ edgeIntersection = KritzelGeometryHelper.getLinePointsArrayIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, customClipPolygon);
33306
+ }
33307
+ else {
33308
+ // Fall back to bounding box for rectangles and other objects
33309
+ edgeIntersection = KritzelGeometryHelper.getLinePolygonIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, targetObject.rotatedPolygon);
33310
+ }
33140
33311
  if (!edgeIntersection) {
33141
33312
  return null;
33142
33313
  }
@@ -33155,7 +33326,15 @@ class KritzelAnchorManager {
33155
33326
  };
33156
33327
  }
33157
33328
  computeCurvedClipInfo(line, endpoint, targetObject) {
33158
- const polygonPoints = this.getPolygonPoints(targetObject.rotatedPolygon);
33329
+ // Check for path object (uses stroke edge detection via sampling)
33330
+ if (KritzelClassHelper.isInstanceOf(targetObject, 'KritzelPath')) {
33331
+ // For curved lines to paths, sample along the curve to find stroke edge
33332
+ const path = targetObject;
33333
+ return this.findCurveExitPointForPath(line, endpoint, path);
33334
+ }
33335
+ // Check for custom clip polygon (ellipse, triangle shapes)
33336
+ const customClipPolygon = this.getClipPolygonForObject(targetObject);
33337
+ const polygonPoints = customClipPolygon ?? this.getPolygonPoints(targetObject.rotatedPolygon);
33159
33338
  const exitPoint = this.findCurveExitPoint(line, endpoint, polygonPoints);
33160
33339
  if (exitPoint) {
33161
33340
  return exitPoint;
@@ -33163,7 +33342,13 @@ class KritzelAnchorManager {
33163
33342
  const reference = endpoint === 'start'
33164
33343
  ? this.lineLocalToWorld(line, line.endX, line.endY)
33165
33344
  : this.lineLocalToWorld(line, line.startX, line.startY);
33166
- const fallbackIntersection = KritzelGeometryHelper.getLinePolygonIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, targetObject.rotatedPolygon);
33345
+ let fallbackIntersection;
33346
+ if (customClipPolygon) {
33347
+ fallbackIntersection = KritzelGeometryHelper.getLinePointsArrayIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, customClipPolygon);
33348
+ }
33349
+ else {
33350
+ fallbackIntersection = KritzelGeometryHelper.getLinePolygonIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, targetObject.rotatedPolygon);
33351
+ }
33167
33352
  if (!fallbackIntersection) {
33168
33353
  return null;
33169
33354
  }
@@ -33203,6 +33388,119 @@ class KritzelAnchorManager {
33203
33388
  }
33204
33389
  return null;
33205
33390
  }
33391
+ /**
33392
+ * Finds the exit point for a curved line going to a Path object.
33393
+ * Uses distance-to-stroke sampling instead of polygon containment.
33394
+ */
33395
+ findCurveExitPointForPath(line, endpoint, path) {
33396
+ const steps = 64;
33397
+ const initialT = endpoint === 'start' ? 0 : 1;
33398
+ const halfStroke = path.strokeWidth / path.scale / 2;
33399
+ // Ensure path has computed points
33400
+ const pathPoints = this.getPathAdjustedPoints(path);
33401
+ if (pathPoints.length < 1) {
33402
+ return null;
33403
+ }
33404
+ // Check if starting point is inside the stroke
33405
+ const initialSample = this.evaluateLineAtT(line, initialT);
33406
+ let prevInside = this.isPointInPathStroke(initialSample.worldX, initialSample.worldY, pathPoints, halfStroke);
33407
+ let prevT = initialT;
33408
+ for (let i = 1; i <= steps; i++) {
33409
+ const t = endpoint === 'start' ? i / steps : 1 - i / steps;
33410
+ const sample = this.evaluateLineAtT(line, t);
33411
+ const inside = this.isPointInPathStroke(sample.worldX, sample.worldY, pathPoints, halfStroke);
33412
+ if (prevInside && !inside) {
33413
+ // Refine using binary search
33414
+ const refinedT = this.refineCurveExitParameterForPath(line, pathPoints, halfStroke, prevT, t);
33415
+ const refinedPoint = this.evaluateLineAtT(line, refinedT);
33416
+ return {
33417
+ localX: refinedPoint.localX,
33418
+ localY: refinedPoint.localY,
33419
+ worldX: refinedPoint.worldX,
33420
+ worldY: refinedPoint.worldY,
33421
+ t: refinedT,
33422
+ };
33423
+ }
33424
+ prevInside = inside;
33425
+ prevT = t;
33426
+ }
33427
+ return null;
33428
+ }
33429
+ refineCurveExitParameterForPath(line, pathPoints, halfStroke, insideT, outsideT) {
33430
+ let tInside = insideT;
33431
+ let tOutside = outsideT;
33432
+ for (let i = 0; i < 8; i++) {
33433
+ const mid = (tInside + tOutside) / 2;
33434
+ const sample = this.evaluateLineAtT(line, mid);
33435
+ const inside = this.isPointInPathStroke(sample.worldX, sample.worldY, pathPoints, halfStroke);
33436
+ if (inside) {
33437
+ tInside = mid;
33438
+ }
33439
+ else {
33440
+ tOutside = mid;
33441
+ }
33442
+ }
33443
+ return (tInside + tOutside) / 2;
33444
+ }
33445
+ getPathAdjustedPoints(path) {
33446
+ // Access the path's adjusted points through its internal computation
33447
+ // We'll need to manually compute them since they're private
33448
+ return this.computePathAdjustedPoints(path);
33449
+ }
33450
+ computePathAdjustedPoints(path) {
33451
+ if (!path.points?.length) {
33452
+ return [];
33453
+ }
33454
+ const angle = path.rotation;
33455
+ const cos = Math.cos(angle);
33456
+ const sin = Math.sin(angle);
33457
+ const xs = path.points.map(p => p[0]);
33458
+ const ys = path.points.map(p => p[1]);
33459
+ const pivot = {
33460
+ x: (Math.min(...xs) + Math.max(...xs)) / 2,
33461
+ y: (Math.min(...ys) + Math.max(...ys)) / 2,
33462
+ };
33463
+ const { x: cx, y: cy } = pivot;
33464
+ const rotatedPoints = path.points.map(([x, y]) => {
33465
+ const dx = x - cx;
33466
+ const dy = y - cy;
33467
+ return [cx + dx * cos - dy * sin, cy + dx * sin + dy * cos];
33468
+ });
33469
+ return rotatedPoints.map(([px, py]) => [
33470
+ Math.abs(px - path.x) / path.scale + path.translateX,
33471
+ Math.abs(py - path.y) / path.scale + path.translateY,
33472
+ ]);
33473
+ }
33474
+ isPointInPathStroke(x, y, pathPoints, halfStroke) {
33475
+ if (pathPoints.length === 1) {
33476
+ const p = pathPoints[0];
33477
+ const dx = x - p[0];
33478
+ const dy = y - p[1];
33479
+ return Math.sqrt(dx * dx + dy * dy) <= halfStroke;
33480
+ }
33481
+ for (let i = 0; i < pathPoints.length - 1; i++) {
33482
+ const p1 = pathPoints[i];
33483
+ const p2 = pathPoints[i + 1];
33484
+ const dist = this.pointToSegmentDistance(x, y, p1[0], p1[1], p2[0], p2[1]);
33485
+ if (dist <= halfStroke) {
33486
+ return true;
33487
+ }
33488
+ }
33489
+ return false;
33490
+ }
33491
+ pointToSegmentDistance(px, py, x1, y1, x2, y2) {
33492
+ const dx = x2 - x1;
33493
+ const dy = y2 - y1;
33494
+ const lengthSquared = dx * dx + dy * dy;
33495
+ if (lengthSquared === 0) {
33496
+ return Math.sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
33497
+ }
33498
+ let t = ((px - x1) * dx + (py - y1) * dy) / lengthSquared;
33499
+ t = Math.max(0, Math.min(1, t));
33500
+ const nearestX = x1 + t * dx;
33501
+ const nearestY = y1 + t * dy;
33502
+ return Math.sqrt((px - nearestX) * (px - nearestX) + (py - nearestY) * (py - nearestY));
33503
+ }
33206
33504
  refineCurveExitParameter(line, polygonPoints, insideT, outsideT) {
33207
33505
  let tInside = insideT;
33208
33506
  let tOutside = outsideT;
@@ -33336,6 +33634,30 @@ class KritzelAnchorManager {
33336
33634
  getPolygonPoints(polygon) {
33337
33635
  return [polygon.topLeft, polygon.topRight, polygon.bottomRight, polygon.bottomLeft];
33338
33636
  }
33637
+ /**
33638
+ * Gets the custom clip polygon for an object if it has one.
33639
+ * Returns null for objects that should use the default rotatedPolygon.
33640
+ */
33641
+ getClipPolygonForObject(object) {
33642
+ // Check if the object is a KritzelShape with a custom clip polygon
33643
+ if (KritzelClassHelper.isInstanceOf(object, 'KritzelShape')) {
33644
+ const shape = object;
33645
+ return shape.getClipPolygon();
33646
+ }
33647
+ // Path objects use getPathClipPoint instead of polygon
33648
+ return null;
33649
+ }
33650
+ /**
33651
+ * Gets the clip point for a Path object (stroke edge intersection).
33652
+ * Returns null if the object is not a Path or no intersection found.
33653
+ */
33654
+ getPathClipPoint(object, outsidePoint) {
33655
+ if (KritzelClassHelper.isInstanceOf(object, 'KritzelPath')) {
33656
+ const path = object;
33657
+ return path.getClipPoint(outsidePoint);
33658
+ }
33659
+ return null;
33660
+ }
33339
33661
  /**
33340
33662
  * Converts local line coordinates to world coordinates.
33341
33663
  */
@@ -33518,6 +33840,8 @@ exports.DEFAULT_LINE_TOOL_CONFIG = DEFAULT_LINE_TOOL_CONFIG;
33518
33840
  exports.DEFAULT_SYNC_CONFIG = DEFAULT_SYNC_CONFIG;
33519
33841
  exports.DEFAULT_TEXT_CONFIG = DEFAULT_TEXT_CONFIG;
33520
33842
  exports.Doc = Doc;
33843
+ exports.EditorState = EditorState;
33844
+ exports.EditorView = EditorView;
33521
33845
  exports.HocuspocusProvider = HocuspocusProvider;
33522
33846
  exports.HocuspocusProviderWebsocket = HocuspocusProviderWebsocket;
33523
33847
  exports.IndexedDBSyncProvider = IndexedDBSyncProvider;
@@ -33532,6 +33856,7 @@ exports.KritzelCursorHelper = KritzelCursorHelper;
33532
33856
  exports.KritzelDevicesHelper = KritzelDevicesHelper;
33533
33857
  exports.KritzelEraserTool = KritzelEraserTool;
33534
33858
  exports.KritzelEventHelper = KritzelEventHelper;
33859
+ exports.KritzelGeometryHelper = KritzelGeometryHelper;
33535
33860
  exports.KritzelIconRegistry = KritzelIconRegistry;
33536
33861
  exports.KritzelImage = KritzelImage;
33537
33862
  exports.KritzelImageTool = KritzelImageTool;
@@ -33549,8 +33874,12 @@ exports.KritzelWorkspace = KritzelWorkspace;
33549
33874
  exports.ObjectHelper = ObjectHelper;
33550
33875
  exports.Observable = Observable$1;
33551
33876
  exports.ObservableV2 = ObservableV2;
33877
+ exports.Schema = Schema;
33878
+ exports.TextSelection = TextSelection;
33552
33879
  exports.UndoManager = UndoManager;
33880
+ exports.addListNodes = addListNodes;
33553
33881
  exports.applyUpdate = applyUpdate;
33882
+ exports.baseKeymap = baseKeymap;
33554
33883
  exports.create = create$8;
33555
33884
  exports.createDecoder = createDecoder$1;
33556
33885
  exports.createEncoder = createEncoder$1;
@@ -33562,6 +33891,7 @@ exports.floor = floor$2;
33562
33891
  exports.fromBase64 = fromBase64;
33563
33892
  exports.getUnixTime = getUnixTime$1;
33564
33893
  exports.isNode = isNode;
33894
+ exports.keymap = keymap;
33565
33895
  exports.length = length$3;
33566
33896
  exports.map = map;
33567
33897
  exports.min = min$2;
@@ -33571,6 +33901,7 @@ exports.pow = pow;
33571
33901
  exports.readVarString = readVarString$2;
33572
33902
  exports.readVarUint = readVarUint$2;
33573
33903
  exports.readVarUint8Array = readVarUint8Array$2;
33904
+ exports.schema = schema;
33574
33905
  exports.setIfUndefined = setIfUndefined$1;
33575
33906
  exports.toBase64 = toBase64;
33576
33907
  exports.toUint8Array = toUint8Array$1;
@@ -33578,6 +33909,6 @@ exports.varStorage = varStorage;
33578
33909
  exports.writeVarString = writeVarString$2;
33579
33910
  exports.writeVarUint = writeVarUint$2;
33580
33911
  exports.writeVarUint8Array = writeVarUint8Array$2;
33581
- //# sourceMappingURL=default-line-tool.config-D1Ns0NmM.js.map
33912
+ //# sourceMappingURL=default-line-tool.config-DJMYrkSu.js.map
33582
33913
 
33583
- //# sourceMappingURL=default-line-tool.config-D1Ns0NmM.js.map
33914
+ //# sourceMappingURL=default-line-tool.config-DJMYrkSu.js.map