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.
- package/dist/cjs/{default-line-tool.config-D1Ns0NmM.js → default-line-tool.config-DJMYrkSu.js} +340 -9
- package/dist/cjs/default-line-tool.config-DJMYrkSu.js.map +1 -0
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/kritzel-color_22.cjs.entry.js +760 -27
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/stencil.cjs.js +1 -1
- package/dist/collection/classes/core/core.class.js +19 -3
- package/dist/collection/classes/core/core.class.js.map +1 -1
- package/dist/collection/classes/core/reviver.class.js +16 -0
- package/dist/collection/classes/core/reviver.class.js.map +1 -1
- package/dist/collection/classes/core/store.class.js +5 -0
- package/dist/collection/classes/core/store.class.js.map +1 -1
- package/dist/collection/classes/core/viewport.class.js +8 -0
- package/dist/collection/classes/core/viewport.class.js.map +1 -1
- package/dist/collection/classes/managers/anchor.manager.js +181 -3
- package/dist/collection/classes/managers/anchor.manager.js.map +1 -1
- package/dist/collection/classes/objects/path.class.js +85 -0
- package/dist/collection/classes/objects/path.class.js.map +1 -1
- package/dist/collection/classes/objects/shape.class.js +372 -0
- package/dist/collection/classes/objects/shape.class.js.map +1 -0
- package/dist/collection/classes/registries/icon-registry.class.js +4 -0
- package/dist/collection/classes/registries/icon-registry.class.js.map +1 -1
- package/dist/collection/classes/tools/brush-tool.class.js +2 -2
- package/dist/collection/classes/tools/brush-tool.class.js.map +1 -1
- package/dist/collection/classes/tools/line-tool.class.js +2 -2
- package/dist/collection/classes/tools/line-tool.class.js.map +1 -1
- package/dist/collection/classes/tools/shape-tool.class.js +204 -0
- package/dist/collection/classes/tools/shape-tool.class.js.map +1 -0
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +17 -6
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.js.map +1 -1
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +44 -8
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js.map +1 -1
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.css +143 -5
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +76 -12
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js.map +1 -1
- package/dist/collection/configs/default-shape-tool.config.js +26 -0
- package/dist/collection/configs/default-shape-tool.config.js.map +1 -0
- package/dist/collection/enums/shape-type.enum.js +7 -0
- package/dist/collection/enums/shape-type.enum.js.map +1 -0
- package/dist/collection/helpers/geometry.helper.js +55 -0
- package/dist/collection/helpers/geometry.helper.js.map +1 -1
- package/dist/collection/interfaces/toolbar-control.interface.js.map +1 -1
- package/dist/components/index.js +3 -3
- package/dist/components/kritzel-brush-style.js +1 -1
- package/dist/components/kritzel-context-menu.js +1 -1
- package/dist/components/kritzel-control-brush-config.js +1 -1
- package/dist/components/kritzel-control-text-config.js +1 -1
- package/dist/components/kritzel-controls.js +1 -1
- package/dist/components/kritzel-editor.js +49 -16
- package/dist/components/kritzel-editor.js.map +1 -1
- package/dist/components/kritzel-engine.js +1 -1
- package/dist/components/kritzel-icon.js +1 -1
- package/dist/components/kritzel-menu-item.js +1 -1
- package/dist/components/kritzel-menu.js +1 -1
- package/dist/components/kritzel-split-button.js +1 -1
- package/dist/components/kritzel-utility-panel.js +1 -1
- package/dist/components/kritzel-workspace-manager.js +1 -1
- package/dist/components/{p-Cqr0Bah5.js → p-5OECjGHq.js} +3 -3
- package/dist/components/{p-Cqr0Bah5.js.map → p-5OECjGHq.js.map} +1 -1
- package/dist/components/{p-CvLFRlQU.js → p-BSBMBjhq.js} +3 -3
- package/dist/components/{p-CvLFRlQU.js.map → p-BSBMBjhq.js.map} +1 -1
- package/dist/components/{p-7_lwv0zQ.js → p-BuS7MM1j.js} +4 -4
- package/dist/components/{p-7_lwv0zQ.js.map → p-BuS7MM1j.js.map} +1 -1
- package/dist/components/{p-BixlbUD7.js → p-Cv4BGNPb.js} +6 -2
- package/dist/components/p-Cv4BGNPb.js.map +1 -0
- package/dist/components/{p-dMCB4tJA.js → p-D1YAsWrL.js} +3 -3
- package/dist/components/{p-dMCB4tJA.js.map → p-D1YAsWrL.js.map} +1 -1
- package/dist/components/{p-CDteBYm9.js → p-D8L0t-Ro.js} +3 -3
- package/dist/components/{p-CDteBYm9.js.map → p-D8L0t-Ro.js.map} +1 -1
- package/dist/components/{p-DZ7kxJUx.js → p-DguzZn_x.js} +3 -3
- package/dist/components/{p-DZ7kxJUx.js.map → p-DguzZn_x.js.map} +1 -1
- package/dist/components/{p-sokRZ7Vn.js → p-Dz2XHHqa.js} +145 -5
- package/dist/components/p-Dz2XHHqa.js.map +1 -0
- package/dist/components/{p-CuhOrcET.js → p-DzUUppVL.js} +837 -21
- package/dist/components/p-DzUUppVL.js.map +1 -0
- package/dist/components/{p-CkD1PQQX.js → p-I3iPEDpx.js} +5 -5
- package/dist/components/{p-CkD1PQQX.js.map → p-I3iPEDpx.js.map} +1 -1
- package/dist/components/{p-DKwJJuFb.js → p-tp96UZ0l.js} +83 -19
- package/dist/components/p-tp96UZ0l.js.map +1 -0
- package/dist/esm/{default-line-tool.config-C35m-d1Y.js → default-line-tool.config-C35P3XfD.js} +332 -10
- package/dist/esm/default-line-tool.config-C35P3XfD.js.map +1 -0
- package/dist/esm/index.js +2 -2
- package/dist/esm/kritzel-color_22.entry.js +760 -27
- package/dist/esm/loader.js +1 -1
- package/dist/esm/stencil.js +1 -1
- package/dist/stencil/index.esm.js +1 -1
- package/dist/stencil/p-3e2b5c42.entry.js +10 -0
- package/dist/stencil/p-3e2b5c42.entry.js.map +1 -0
- package/dist/stencil/p-C35P3XfD.js +2 -0
- package/dist/stencil/p-C35P3XfD.js.map +1 -0
- package/dist/stencil/stencil.esm.js +1 -1
- package/dist/types/classes/core/core.class.d.ts +1 -0
- package/dist/types/classes/core/store.class.d.ts +2 -0
- package/dist/types/classes/core/viewport.class.d.ts +6 -0
- package/dist/types/classes/managers/anchor.manager.d.ts +20 -0
- package/dist/types/classes/objects/path.class.d.ts +7 -0
- package/dist/types/classes/objects/shape.class.d.ts +116 -0
- package/dist/types/classes/tools/shape-tool.class.d.ts +37 -0
- package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +2 -2
- package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +16 -1
- package/dist/types/components.d.ts +5 -5
- package/dist/types/configs/default-shape-tool.config.d.ts +2 -0
- package/dist/types/enums/shape-type.enum.d.ts +5 -0
- package/dist/types/helpers/geometry.helper.d.ts +21 -0
- package/dist/types/interfaces/toolbar-control.interface.d.ts +21 -3
- package/package.json +1 -1
- package/dist/cjs/default-line-tool.config-D1Ns0NmM.js.map +0 -1
- package/dist/components/p-BixlbUD7.js.map +0 -1
- package/dist/components/p-CuhOrcET.js.map +0 -1
- package/dist/components/p-DKwJJuFb.js.map +0 -1
- package/dist/components/p-sokRZ7Vn.js.map +0 -1
- package/dist/esm/default-line-tool.config-C35m-d1Y.js.map +0 -1
- package/dist/stencil/p-C35m-d1Y.js +0 -2
- package/dist/stencil/p-C35m-d1Y.js.map +0 -1
- package/dist/stencil/p-d142ef46.entry.js +0 -10
- package/dist/stencil/p-d142ef46.entry.js.map +0 -1
package/dist/esm/{default-line-tool.config-C35m-d1Y.js → default-line-tool.config-C35P3XfD.js}
RENAMED
|
@@ -121,6 +121,61 @@ class KritzelGeometryHelper {
|
|
|
121
121
|
}
|
|
122
122
|
return closestIntersection;
|
|
123
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Generates a polygon approximation of an ellipse.
|
|
126
|
+
* @param centerX - X coordinate of ellipse center
|
|
127
|
+
* @param centerY - Y coordinate of ellipse center
|
|
128
|
+
* @param rx - Horizontal radius
|
|
129
|
+
* @param ry - Vertical radius
|
|
130
|
+
* @param segments - Number of segments (more = smoother approximation)
|
|
131
|
+
* @param rotation - Optional rotation angle in radians
|
|
132
|
+
*/
|
|
133
|
+
static getEllipsePolygonApproximation(centerX, centerY, rx, ry, segments = 32, rotation = 0) {
|
|
134
|
+
const points = [];
|
|
135
|
+
const cos = Math.cos(rotation);
|
|
136
|
+
const sin = Math.sin(rotation);
|
|
137
|
+
for (let i = 0; i < segments; i++) {
|
|
138
|
+
const angle = (2 * Math.PI * i) / segments;
|
|
139
|
+
// Point on unrotated ellipse
|
|
140
|
+
const px = rx * Math.cos(angle);
|
|
141
|
+
const py = ry * Math.sin(angle);
|
|
142
|
+
// Apply rotation around center
|
|
143
|
+
const rotatedX = centerX + px * cos - py * sin;
|
|
144
|
+
const rotatedY = centerY + px * sin + py * cos;
|
|
145
|
+
points.push({ x: rotatedX, y: rotatedY });
|
|
146
|
+
}
|
|
147
|
+
return points;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Finds the closest intersection point between a line segment and a polygon
|
|
151
|
+
* defined as an array of points. Returns the intersection closest to lineStart,
|
|
152
|
+
* or null if no intersection.
|
|
153
|
+
*/
|
|
154
|
+
static getLinePointsArrayIntersection(lineStart, lineEnd, polygonPoints) {
|
|
155
|
+
let closestIntersection = null;
|
|
156
|
+
let closestDistance = Infinity;
|
|
157
|
+
for (let i = 0; i < polygonPoints.length; i++) {
|
|
158
|
+
const edgeStart = polygonPoints[i];
|
|
159
|
+
const edgeEnd = polygonPoints[(i + 1) % polygonPoints.length];
|
|
160
|
+
const intersection = this.getLineIntersectionPoint(lineStart, lineEnd, edgeStart, edgeEnd);
|
|
161
|
+
if (intersection) {
|
|
162
|
+
const distance = Math.sqrt(Math.pow(intersection.x - lineStart.x, 2) +
|
|
163
|
+
Math.pow(intersection.y - lineStart.y, 2));
|
|
164
|
+
if (distance < closestDistance) {
|
|
165
|
+
closestDistance = distance;
|
|
166
|
+
closestIntersection = intersection;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return closestIntersection;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Checks if a point is inside a polygon defined as an array of points.
|
|
174
|
+
* This is a convenience wrapper that works with arbitrary polygon point arrays.
|
|
175
|
+
*/
|
|
176
|
+
static isPointInPolygonPoints(point, polygonPoints) {
|
|
177
|
+
return this.isPointInPolygon(point, polygonPoints);
|
|
178
|
+
}
|
|
124
179
|
}
|
|
125
180
|
|
|
126
181
|
class KritzelBaseObject {
|
|
@@ -14439,6 +14494,91 @@ class KritzelPath extends KritzelBaseObject {
|
|
|
14439
14494
|
const scaledHeight = this.boundingBox.height * viewportScale;
|
|
14440
14495
|
return (scaledWidth * scaledHeight) < 500;
|
|
14441
14496
|
}
|
|
14497
|
+
/**
|
|
14498
|
+
* Finds the point where a line from outsidePoint to the path's center
|
|
14499
|
+
* intersects the stroke edge. Returns null if no intersection found.
|
|
14500
|
+
* This is used for arrow clipping at the actual stroke edge.
|
|
14501
|
+
*/
|
|
14502
|
+
getClipPoint(outsidePoint) {
|
|
14503
|
+
const centerX = this.centerX;
|
|
14504
|
+
const centerY = this.centerY;
|
|
14505
|
+
const halfStroke = this.strokeWidth / this.scale / 2;
|
|
14506
|
+
// Ensure adjusted points are computed
|
|
14507
|
+
if (this._adjustedPoints === null) {
|
|
14508
|
+
this._adjustedPoints = this.computeAdjustedPoints();
|
|
14509
|
+
}
|
|
14510
|
+
if (this._adjustedPoints.length < 1) {
|
|
14511
|
+
return null;
|
|
14512
|
+
}
|
|
14513
|
+
// Sample along the line from outsidePoint to center to find stroke edge
|
|
14514
|
+
const steps = 32;
|
|
14515
|
+
let prevOutside = true;
|
|
14516
|
+
for (let i = 1; i <= steps; i++) {
|
|
14517
|
+
const t = i / steps;
|
|
14518
|
+
const sampleX = outsidePoint.x + (centerX - outsidePoint.x) * t;
|
|
14519
|
+
const sampleY = outsidePoint.y + (centerY - outsidePoint.y) * t;
|
|
14520
|
+
// Check distance to path stroke
|
|
14521
|
+
let minDistance = Infinity;
|
|
14522
|
+
if (this._adjustedPoints.length === 1) {
|
|
14523
|
+
const p = this._adjustedPoints[0];
|
|
14524
|
+
const dx = sampleX - p[0];
|
|
14525
|
+
const dy = sampleY - p[1];
|
|
14526
|
+
minDistance = Math.sqrt(dx * dx + dy * dy);
|
|
14527
|
+
}
|
|
14528
|
+
else {
|
|
14529
|
+
for (let j = 0; j < this._adjustedPoints.length - 1; j++) {
|
|
14530
|
+
const p1 = this._adjustedPoints[j];
|
|
14531
|
+
const p2 = this._adjustedPoints[j + 1];
|
|
14532
|
+
const dist = this.pointToLineSegmentDistance(sampleX, sampleY, p1[0], p1[1], p2[0], p2[1]);
|
|
14533
|
+
if (dist < minDistance) {
|
|
14534
|
+
minDistance = dist;
|
|
14535
|
+
}
|
|
14536
|
+
}
|
|
14537
|
+
}
|
|
14538
|
+
const isInside = minDistance <= halfStroke;
|
|
14539
|
+
// Found the edge: transition from outside to inside
|
|
14540
|
+
if (prevOutside && isInside) {
|
|
14541
|
+
// Refine the intersection point using binary search
|
|
14542
|
+
let tLow = (i - 1) / steps;
|
|
14543
|
+
let tHigh = t;
|
|
14544
|
+
for (let k = 0; k < 8; k++) {
|
|
14545
|
+
const tMid = (tLow + tHigh) / 2;
|
|
14546
|
+
const midX = outsidePoint.x + (centerX - outsidePoint.x) * tMid;
|
|
14547
|
+
const midY = outsidePoint.y + (centerY - outsidePoint.y) * tMid;
|
|
14548
|
+
let midDist = Infinity;
|
|
14549
|
+
if (this._adjustedPoints.length === 1) {
|
|
14550
|
+
const p = this._adjustedPoints[0];
|
|
14551
|
+
const dx = midX - p[0];
|
|
14552
|
+
const dy = midY - p[1];
|
|
14553
|
+
midDist = Math.sqrt(dx * dx + dy * dy);
|
|
14554
|
+
}
|
|
14555
|
+
else {
|
|
14556
|
+
for (let j = 0; j < this._adjustedPoints.length - 1; j++) {
|
|
14557
|
+
const p1 = this._adjustedPoints[j];
|
|
14558
|
+
const p2 = this._adjustedPoints[j + 1];
|
|
14559
|
+
const dist = this.pointToLineSegmentDistance(midX, midY, p1[0], p1[1], p2[0], p2[1]);
|
|
14560
|
+
if (dist < midDist) {
|
|
14561
|
+
midDist = dist;
|
|
14562
|
+
}
|
|
14563
|
+
}
|
|
14564
|
+
}
|
|
14565
|
+
if (midDist <= halfStroke) {
|
|
14566
|
+
tHigh = tMid;
|
|
14567
|
+
}
|
|
14568
|
+
else {
|
|
14569
|
+
tLow = tMid;
|
|
14570
|
+
}
|
|
14571
|
+
}
|
|
14572
|
+
const finalT = (tLow + tHigh) / 2;
|
|
14573
|
+
return {
|
|
14574
|
+
x: outsidePoint.x + (centerX - outsidePoint.x) * finalT,
|
|
14575
|
+
y: outsidePoint.y + (centerY - outsidePoint.y) * finalT,
|
|
14576
|
+
};
|
|
14577
|
+
}
|
|
14578
|
+
prevOutside = !isInside;
|
|
14579
|
+
}
|
|
14580
|
+
return null;
|
|
14581
|
+
}
|
|
14442
14582
|
}
|
|
14443
14583
|
|
|
14444
14584
|
class KritzelImage extends KritzelBaseObject {
|
|
@@ -15223,6 +15363,7 @@ class KritzelBrushTool extends KritzelBaseTool {
|
|
|
15223
15363
|
});
|
|
15224
15364
|
updatedPath.id = currentPath.id;
|
|
15225
15365
|
updatedPath.workspaceId = currentPath.workspaceId;
|
|
15366
|
+
updatedPath.zIndex = currentPath.zIndex;
|
|
15226
15367
|
updatedPath.isCompleted = false;
|
|
15227
15368
|
this._core.store.state.objects.update(updatedPath);
|
|
15228
15369
|
}
|
|
@@ -15245,6 +15386,7 @@ class KritzelBrushTool extends KritzelBaseTool {
|
|
|
15245
15386
|
});
|
|
15246
15387
|
updatedPath.id = currentPath.id;
|
|
15247
15388
|
updatedPath.workspaceId = currentPath.workspaceId;
|
|
15389
|
+
updatedPath.zIndex = currentPath.zIndex;
|
|
15248
15390
|
updatedPath.isCompleted = false;
|
|
15249
15391
|
this._core.store.state.objects.update(updatedPath);
|
|
15250
15392
|
}
|
|
@@ -15261,7 +15403,6 @@ class KritzelBrushTool extends KritzelBaseTool {
|
|
|
15261
15403
|
const currentPath = this._core.store.currentPath;
|
|
15262
15404
|
if (currentPath) {
|
|
15263
15405
|
currentPath.isCompleted = true;
|
|
15264
|
-
currentPath.zIndex = this._core.store.currentZIndex;
|
|
15265
15406
|
this._core.store.state.objects.update(currentPath);
|
|
15266
15407
|
this._core.engine.emitObjectsChange();
|
|
15267
15408
|
}
|
|
@@ -15273,7 +15414,6 @@ class KritzelBrushTool extends KritzelBaseTool {
|
|
|
15273
15414
|
const currentPath = this._core.store.currentPath;
|
|
15274
15415
|
if (currentPath) {
|
|
15275
15416
|
currentPath.isCompleted = true;
|
|
15276
|
-
currentPath.zIndex = this._core.store.currentZIndex;
|
|
15277
15417
|
this._core.store.state.objects.update(currentPath);
|
|
15278
15418
|
this._core.engine.emitObjectsChange();
|
|
15279
15419
|
}
|
|
@@ -15673,6 +15813,7 @@ class KritzelLineTool extends KritzelBaseTool {
|
|
|
15673
15813
|
});
|
|
15674
15814
|
updatedLine.id = currentLine.id;
|
|
15675
15815
|
updatedLine.workspaceId = currentLine.workspaceId;
|
|
15816
|
+
updatedLine.zIndex = currentLine.zIndex;
|
|
15676
15817
|
updatedLine.isCompleted = false;
|
|
15677
15818
|
this._core.store.state.objects.update(updatedLine);
|
|
15678
15819
|
}
|
|
@@ -15699,6 +15840,7 @@ class KritzelLineTool extends KritzelBaseTool {
|
|
|
15699
15840
|
});
|
|
15700
15841
|
updatedLine.id = currentLine.id;
|
|
15701
15842
|
updatedLine.workspaceId = currentLine.workspaceId;
|
|
15843
|
+
updatedLine.zIndex = currentLine.zIndex;
|
|
15702
15844
|
updatedLine.isCompleted = false;
|
|
15703
15845
|
this._core.store.state.objects.update(updatedLine);
|
|
15704
15846
|
}
|
|
@@ -15715,7 +15857,6 @@ class KritzelLineTool extends KritzelBaseTool {
|
|
|
15715
15857
|
const currentLine = this._core.store.currentLine;
|
|
15716
15858
|
if (currentLine) {
|
|
15717
15859
|
currentLine.isCompleted = true;
|
|
15718
|
-
currentLine.zIndex = this._core.store.currentZIndex;
|
|
15719
15860
|
this._core.store.state.objects.update(currentLine);
|
|
15720
15861
|
this._core.engine.emitObjectsChange();
|
|
15721
15862
|
// Switch to selection tool and select the drawn line
|
|
@@ -15729,7 +15870,6 @@ class KritzelLineTool extends KritzelBaseTool {
|
|
|
15729
15870
|
const currentLine = this._core.store.currentLine;
|
|
15730
15871
|
if (currentLine) {
|
|
15731
15872
|
currentLine.isCompleted = true;
|
|
15732
|
-
currentLine.zIndex = this._core.store.currentZIndex;
|
|
15733
15873
|
this._core.store.state.objects.update(currentLine);
|
|
15734
15874
|
this._core.engine.emitObjectsChange();
|
|
15735
15875
|
// Switch to selection tool and select the drawn line
|
|
@@ -16057,6 +16197,10 @@ KritzelIconRegistry.registerIcons({
|
|
|
16057
16197
|
'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>',
|
|
16058
16198
|
'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>',
|
|
16059
16199
|
'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>',
|
|
16200
|
+
'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>',
|
|
16201
|
+
'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>',
|
|
16202
|
+
'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>',
|
|
16203
|
+
'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>',
|
|
16060
16204
|
'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>',
|
|
16061
16205
|
'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>',
|
|
16062
16206
|
'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>',
|
|
@@ -33134,7 +33278,34 @@ class KritzelAnchorManager {
|
|
|
33134
33278
|
const reference = endpoint === 'start'
|
|
33135
33279
|
? this.lineLocalToWorld(line, line.endX, line.endY)
|
|
33136
33280
|
: this.lineLocalToWorld(line, line.startX, line.startY);
|
|
33137
|
-
|
|
33281
|
+
// Check for path object (uses stroke edge detection)
|
|
33282
|
+
const pathClipPoint = this.getPathClipPoint(targetObject, reference);
|
|
33283
|
+
if (pathClipPoint) {
|
|
33284
|
+
const localEdge = this.lineWorldToLocal(line, pathClipPoint.x, pathClipPoint.y);
|
|
33285
|
+
const totalLength = Math.sqrt(Math.pow(line.endX - line.startX, 2) +
|
|
33286
|
+
Math.pow(line.endY - line.startY, 2));
|
|
33287
|
+
const distanceFromStart = Math.sqrt(Math.pow(localEdge.x - line.startX, 2) +
|
|
33288
|
+
Math.pow(localEdge.y - line.startY, 2));
|
|
33289
|
+
const t = totalLength > 0 ? distanceFromStart / totalLength : endpoint === 'start' ? 0 : 1;
|
|
33290
|
+
return {
|
|
33291
|
+
localX: localEdge.x,
|
|
33292
|
+
localY: localEdge.y,
|
|
33293
|
+
worldX: pathClipPoint.x,
|
|
33294
|
+
worldY: pathClipPoint.y,
|
|
33295
|
+
t,
|
|
33296
|
+
};
|
|
33297
|
+
}
|
|
33298
|
+
// Check for custom clip polygon (ellipse, triangle shapes)
|
|
33299
|
+
const customClipPolygon = this.getClipPolygonForObject(targetObject);
|
|
33300
|
+
let edgeIntersection;
|
|
33301
|
+
if (customClipPolygon) {
|
|
33302
|
+
// Use custom polygon for non-rectangular shapes
|
|
33303
|
+
edgeIntersection = KritzelGeometryHelper.getLinePointsArrayIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, customClipPolygon);
|
|
33304
|
+
}
|
|
33305
|
+
else {
|
|
33306
|
+
// Fall back to bounding box for rectangles and other objects
|
|
33307
|
+
edgeIntersection = KritzelGeometryHelper.getLinePolygonIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, targetObject.rotatedPolygon);
|
|
33308
|
+
}
|
|
33138
33309
|
if (!edgeIntersection) {
|
|
33139
33310
|
return null;
|
|
33140
33311
|
}
|
|
@@ -33153,7 +33324,15 @@ class KritzelAnchorManager {
|
|
|
33153
33324
|
};
|
|
33154
33325
|
}
|
|
33155
33326
|
computeCurvedClipInfo(line, endpoint, targetObject) {
|
|
33156
|
-
|
|
33327
|
+
// Check for path object (uses stroke edge detection via sampling)
|
|
33328
|
+
if (KritzelClassHelper.isInstanceOf(targetObject, 'KritzelPath')) {
|
|
33329
|
+
// For curved lines to paths, sample along the curve to find stroke edge
|
|
33330
|
+
const path = targetObject;
|
|
33331
|
+
return this.findCurveExitPointForPath(line, endpoint, path);
|
|
33332
|
+
}
|
|
33333
|
+
// Check for custom clip polygon (ellipse, triangle shapes)
|
|
33334
|
+
const customClipPolygon = this.getClipPolygonForObject(targetObject);
|
|
33335
|
+
const polygonPoints = customClipPolygon ?? this.getPolygonPoints(targetObject.rotatedPolygon);
|
|
33157
33336
|
const exitPoint = this.findCurveExitPoint(line, endpoint, polygonPoints);
|
|
33158
33337
|
if (exitPoint) {
|
|
33159
33338
|
return exitPoint;
|
|
@@ -33161,7 +33340,13 @@ class KritzelAnchorManager {
|
|
|
33161
33340
|
const reference = endpoint === 'start'
|
|
33162
33341
|
? this.lineLocalToWorld(line, line.endX, line.endY)
|
|
33163
33342
|
: this.lineLocalToWorld(line, line.startX, line.startY);
|
|
33164
|
-
|
|
33343
|
+
let fallbackIntersection;
|
|
33344
|
+
if (customClipPolygon) {
|
|
33345
|
+
fallbackIntersection = KritzelGeometryHelper.getLinePointsArrayIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, customClipPolygon);
|
|
33346
|
+
}
|
|
33347
|
+
else {
|
|
33348
|
+
fallbackIntersection = KritzelGeometryHelper.getLinePolygonIntersection(reference, { x: targetObject.centerX, y: targetObject.centerY }, targetObject.rotatedPolygon);
|
|
33349
|
+
}
|
|
33165
33350
|
if (!fallbackIntersection) {
|
|
33166
33351
|
return null;
|
|
33167
33352
|
}
|
|
@@ -33201,6 +33386,119 @@ class KritzelAnchorManager {
|
|
|
33201
33386
|
}
|
|
33202
33387
|
return null;
|
|
33203
33388
|
}
|
|
33389
|
+
/**
|
|
33390
|
+
* Finds the exit point for a curved line going to a Path object.
|
|
33391
|
+
* Uses distance-to-stroke sampling instead of polygon containment.
|
|
33392
|
+
*/
|
|
33393
|
+
findCurveExitPointForPath(line, endpoint, path) {
|
|
33394
|
+
const steps = 64;
|
|
33395
|
+
const initialT = endpoint === 'start' ? 0 : 1;
|
|
33396
|
+
const halfStroke = path.strokeWidth / path.scale / 2;
|
|
33397
|
+
// Ensure path has computed points
|
|
33398
|
+
const pathPoints = this.getPathAdjustedPoints(path);
|
|
33399
|
+
if (pathPoints.length < 1) {
|
|
33400
|
+
return null;
|
|
33401
|
+
}
|
|
33402
|
+
// Check if starting point is inside the stroke
|
|
33403
|
+
const initialSample = this.evaluateLineAtT(line, initialT);
|
|
33404
|
+
let prevInside = this.isPointInPathStroke(initialSample.worldX, initialSample.worldY, pathPoints, halfStroke);
|
|
33405
|
+
let prevT = initialT;
|
|
33406
|
+
for (let i = 1; i <= steps; i++) {
|
|
33407
|
+
const t = endpoint === 'start' ? i / steps : 1 - i / steps;
|
|
33408
|
+
const sample = this.evaluateLineAtT(line, t);
|
|
33409
|
+
const inside = this.isPointInPathStroke(sample.worldX, sample.worldY, pathPoints, halfStroke);
|
|
33410
|
+
if (prevInside && !inside) {
|
|
33411
|
+
// Refine using binary search
|
|
33412
|
+
const refinedT = this.refineCurveExitParameterForPath(line, pathPoints, halfStroke, prevT, t);
|
|
33413
|
+
const refinedPoint = this.evaluateLineAtT(line, refinedT);
|
|
33414
|
+
return {
|
|
33415
|
+
localX: refinedPoint.localX,
|
|
33416
|
+
localY: refinedPoint.localY,
|
|
33417
|
+
worldX: refinedPoint.worldX,
|
|
33418
|
+
worldY: refinedPoint.worldY,
|
|
33419
|
+
t: refinedT,
|
|
33420
|
+
};
|
|
33421
|
+
}
|
|
33422
|
+
prevInside = inside;
|
|
33423
|
+
prevT = t;
|
|
33424
|
+
}
|
|
33425
|
+
return null;
|
|
33426
|
+
}
|
|
33427
|
+
refineCurveExitParameterForPath(line, pathPoints, halfStroke, insideT, outsideT) {
|
|
33428
|
+
let tInside = insideT;
|
|
33429
|
+
let tOutside = outsideT;
|
|
33430
|
+
for (let i = 0; i < 8; i++) {
|
|
33431
|
+
const mid = (tInside + tOutside) / 2;
|
|
33432
|
+
const sample = this.evaluateLineAtT(line, mid);
|
|
33433
|
+
const inside = this.isPointInPathStroke(sample.worldX, sample.worldY, pathPoints, halfStroke);
|
|
33434
|
+
if (inside) {
|
|
33435
|
+
tInside = mid;
|
|
33436
|
+
}
|
|
33437
|
+
else {
|
|
33438
|
+
tOutside = mid;
|
|
33439
|
+
}
|
|
33440
|
+
}
|
|
33441
|
+
return (tInside + tOutside) / 2;
|
|
33442
|
+
}
|
|
33443
|
+
getPathAdjustedPoints(path) {
|
|
33444
|
+
// Access the path's adjusted points through its internal computation
|
|
33445
|
+
// We'll need to manually compute them since they're private
|
|
33446
|
+
return this.computePathAdjustedPoints(path);
|
|
33447
|
+
}
|
|
33448
|
+
computePathAdjustedPoints(path) {
|
|
33449
|
+
if (!path.points?.length) {
|
|
33450
|
+
return [];
|
|
33451
|
+
}
|
|
33452
|
+
const angle = path.rotation;
|
|
33453
|
+
const cos = Math.cos(angle);
|
|
33454
|
+
const sin = Math.sin(angle);
|
|
33455
|
+
const xs = path.points.map(p => p[0]);
|
|
33456
|
+
const ys = path.points.map(p => p[1]);
|
|
33457
|
+
const pivot = {
|
|
33458
|
+
x: (Math.min(...xs) + Math.max(...xs)) / 2,
|
|
33459
|
+
y: (Math.min(...ys) + Math.max(...ys)) / 2,
|
|
33460
|
+
};
|
|
33461
|
+
const { x: cx, y: cy } = pivot;
|
|
33462
|
+
const rotatedPoints = path.points.map(([x, y]) => {
|
|
33463
|
+
const dx = x - cx;
|
|
33464
|
+
const dy = y - cy;
|
|
33465
|
+
return [cx + dx * cos - dy * sin, cy + dx * sin + dy * cos];
|
|
33466
|
+
});
|
|
33467
|
+
return rotatedPoints.map(([px, py]) => [
|
|
33468
|
+
Math.abs(px - path.x) / path.scale + path.translateX,
|
|
33469
|
+
Math.abs(py - path.y) / path.scale + path.translateY,
|
|
33470
|
+
]);
|
|
33471
|
+
}
|
|
33472
|
+
isPointInPathStroke(x, y, pathPoints, halfStroke) {
|
|
33473
|
+
if (pathPoints.length === 1) {
|
|
33474
|
+
const p = pathPoints[0];
|
|
33475
|
+
const dx = x - p[0];
|
|
33476
|
+
const dy = y - p[1];
|
|
33477
|
+
return Math.sqrt(dx * dx + dy * dy) <= halfStroke;
|
|
33478
|
+
}
|
|
33479
|
+
for (let i = 0; i < pathPoints.length - 1; i++) {
|
|
33480
|
+
const p1 = pathPoints[i];
|
|
33481
|
+
const p2 = pathPoints[i + 1];
|
|
33482
|
+
const dist = this.pointToSegmentDistance(x, y, p1[0], p1[1], p2[0], p2[1]);
|
|
33483
|
+
if (dist <= halfStroke) {
|
|
33484
|
+
return true;
|
|
33485
|
+
}
|
|
33486
|
+
}
|
|
33487
|
+
return false;
|
|
33488
|
+
}
|
|
33489
|
+
pointToSegmentDistance(px, py, x1, y1, x2, y2) {
|
|
33490
|
+
const dx = x2 - x1;
|
|
33491
|
+
const dy = y2 - y1;
|
|
33492
|
+
const lengthSquared = dx * dx + dy * dy;
|
|
33493
|
+
if (lengthSquared === 0) {
|
|
33494
|
+
return Math.sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
|
|
33495
|
+
}
|
|
33496
|
+
let t = ((px - x1) * dx + (py - y1) * dy) / lengthSquared;
|
|
33497
|
+
t = Math.max(0, Math.min(1, t));
|
|
33498
|
+
const nearestX = x1 + t * dx;
|
|
33499
|
+
const nearestY = y1 + t * dy;
|
|
33500
|
+
return Math.sqrt((px - nearestX) * (px - nearestX) + (py - nearestY) * (py - nearestY));
|
|
33501
|
+
}
|
|
33204
33502
|
refineCurveExitParameter(line, polygonPoints, insideT, outsideT) {
|
|
33205
33503
|
let tInside = insideT;
|
|
33206
33504
|
let tOutside = outsideT;
|
|
@@ -33334,6 +33632,30 @@ class KritzelAnchorManager {
|
|
|
33334
33632
|
getPolygonPoints(polygon) {
|
|
33335
33633
|
return [polygon.topLeft, polygon.topRight, polygon.bottomRight, polygon.bottomLeft];
|
|
33336
33634
|
}
|
|
33635
|
+
/**
|
|
33636
|
+
* Gets the custom clip polygon for an object if it has one.
|
|
33637
|
+
* Returns null for objects that should use the default rotatedPolygon.
|
|
33638
|
+
*/
|
|
33639
|
+
getClipPolygonForObject(object) {
|
|
33640
|
+
// Check if the object is a KritzelShape with a custom clip polygon
|
|
33641
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelShape')) {
|
|
33642
|
+
const shape = object;
|
|
33643
|
+
return shape.getClipPolygon();
|
|
33644
|
+
}
|
|
33645
|
+
// Path objects use getPathClipPoint instead of polygon
|
|
33646
|
+
return null;
|
|
33647
|
+
}
|
|
33648
|
+
/**
|
|
33649
|
+
* Gets the clip point for a Path object (stroke edge intersection).
|
|
33650
|
+
* Returns null if the object is not a Path or no intersection found.
|
|
33651
|
+
*/
|
|
33652
|
+
getPathClipPoint(object, outsidePoint) {
|
|
33653
|
+
if (KritzelClassHelper.isInstanceOf(object, 'KritzelPath')) {
|
|
33654
|
+
const path = object;
|
|
33655
|
+
return path.getClipPoint(outsidePoint);
|
|
33656
|
+
}
|
|
33657
|
+
return null;
|
|
33658
|
+
}
|
|
33337
33659
|
/**
|
|
33338
33660
|
* Converts local line coordinates to world coordinates.
|
|
33339
33661
|
*/
|
|
@@ -33511,7 +33833,7 @@ const DEFAULT_LINE_TOOL_CONFIG = {
|
|
|
33511
33833
|
},
|
|
33512
33834
|
};
|
|
33513
33835
|
|
|
33514
|
-
export {
|
|
33515
|
-
//# sourceMappingURL=default-line-tool.config-
|
|
33836
|
+
export { Schema as $, isNode as A, min$2 as B, pow as C, HocuspocusProviderWebsocket as D, KritzelPath as E, KritzelImage as F, KritzelLine as G, HocuspocusProvider as H, KritzelBrushTool as I, KritzelLineTool as J, KritzelText as K, KritzelEraserTool as L, KritzelImageTool as M, KritzelTextTool as N, Observable$1 as O, KritzelCursorHelper as P, KritzelSelectionTool as Q, IndexedDBSyncProvider as R, KritzelAppStateMap as S, KritzelWorkspace as T, KritzelAnchorManager as U, DEFAULT_BRUSH_CONFIG as V, DEFAULT_TEXT_CONFIG as W, DEFAULT_LINE_TOOL_CONFIG as X, KritzelDevicesHelper as Y, KritzelMouseButton as Z, KritzelBaseObject as _, writeVarUint8Array$2 as a, schema as a0, addListNodes as a1, EditorView as a2, EditorState as a3, keymap as a4, TextSelection as a5, KritzelKeyboardHelper as a6, KritzelToolRegistry as a7, KritzelGeometryHelper as a8, baseKeymap as a9, KritzelBaseTool as aa, KritzelEventHelper as ab, KritzelIconRegistry as ac, KritzelBaseHandler as ad, KritzelSelectionBox as ae, KritzelSelectionGroup as af, Doc as ag, DEFAULT_SYNC_CONFIG as ah, UndoManager as ai, ObjectHelper as aj, KritzelClassHelper as ak, 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 };
|
|
33837
|
+
//# sourceMappingURL=default-line-tool.config-C35P3XfD.js.map
|
|
33516
33838
|
|
|
33517
|
-
//# sourceMappingURL=default-line-tool.config-
|
|
33839
|
+
//# sourceMappingURL=default-line-tool.config-C35P3XfD.js.map
|