Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@drauu/core

Package Overview
Dependencies
Maintainers
0
Versions
33
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@drauu/core - npm Package Compare versions

Comparing version 0.4.1 to 0.4.2

56

dist/index.d.ts

@@ -179,29 +179,2 @@ interface Unsubscribe {

declare class StylusModel extends BaseModel<SVGPathElement> {
points: Point[];
onStart(point: Point): SVGPathElement;
onMove(point: Point): boolean;
onEnd(): boolean;
getSvgData(points: Point[]): string;
static getSvgData(points: Point[], brush: Brush): string;
}
declare class EllipseModel extends BaseModel<SVGEllipseElement> {
onStart(point: Point): SVGEllipseElement;
onMove(point: Point): boolean;
onEnd(): boolean;
}
declare class LineModel extends BaseModel<SVGLineElement> {
onStart(point: Point): SVGGElement;
onMove(point: Point): boolean;
onEnd(): boolean;
}
declare class RectModel extends BaseModel<SVGRectElement> {
onStart(point: Point): SVGRectElement;
onMove(point: Point): boolean;
onEnd(): boolean;
}
declare class DrawModel extends BaseModel<SVGPathElement> {

@@ -226,2 +199,8 @@ points: Point[];

declare class EllipseModel extends BaseModel<SVGEllipseElement> {
onStart(point: Point): SVGEllipseElement;
onMove(point: Point): boolean;
onEnd(): boolean;
}
interface EraserPathFragment {

@@ -250,2 +229,23 @@ x1: number;

declare class LineModel extends BaseModel<SVGLineElement> {
onStart(point: Point): SVGGElement;
onMove(point: Point): boolean;
onEnd(): boolean;
}
declare class RectModel extends BaseModel<SVGRectElement> {
onStart(point: Point): SVGRectElement;
onMove(point: Point): boolean;
onEnd(): boolean;
}
declare class StylusModel extends BaseModel<SVGPathElement> {
points: Point[];
onStart(point: Point): SVGPathElement;
onMove(point: Point): boolean;
onEnd(): boolean;
getSvgData(points: Point[]): string;
static getSvgData(points: Point[], brush: Brush): string;
}
declare class Drauu {

@@ -268,3 +268,3 @@ options: Options;

constructor(options?: Options);
get model(): StylusModel | EllipseModel | LineModel | RectModel | DrawModel | EraserModel;
get model(): DrawModel | EllipseModel | EraserModel | LineModel | RectModel | StylusModel;
get mounted(): boolean;

@@ -271,0 +271,0 @@ get mode(): DrawingMode;

@@ -20,6 +20,6 @@ "use strict";

// ../../node_modules/.pnpm/nanoevents@9.0.0/node_modules/nanoevents/index.js
// ../../node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js
var createNanoEvents = () => ({
emit(event, ...args) {
for (let i = 0, callbacks = this.events[event] || [], length = callbacks.length; i < length; i++) {
for (let callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) {
callbacks[i](...args);

@@ -40,150 +40,2 @@ }

// ../../node_modules/.pnpm/perfect-freehand@1.2.2/node_modules/perfect-freehand/dist/esm/index.mjs
function $(e, t, u, x = (h) => h) {
return e * x(0.5 - t * (0.5 - u));
}
function se(e) {
return [-e[0], -e[1]];
}
function l(e, t) {
return [e[0] + t[0], e[1] + t[1]];
}
function a(e, t) {
return [e[0] - t[0], e[1] - t[1]];
}
function b(e, t) {
return [e[0] * t, e[1] * t];
}
function he(e, t) {
return [e[0] / t, e[1] / t];
}
function R(e) {
return [e[1], -e[0]];
}
function B(e, t) {
return e[0] * t[0] + e[1] * t[1];
}
function ue(e, t) {
return e[0] === t[0] && e[1] === t[1];
}
function ge(e) {
return Math.hypot(e[0], e[1]);
}
function de(e) {
return e[0] * e[0] + e[1] * e[1];
}
function A(e, t) {
return de(a(e, t));
}
function G(e) {
return he(e, ge(e));
}
function ie(e, t) {
return Math.hypot(e[1] - t[1], e[0] - t[0]);
}
function L(e, t, u) {
let x = Math.sin(u), h = Math.cos(u), y = e[0] - t[0], n = e[1] - t[1], f = y * h - n * x, d = y * x + n * h;
return [f + t[0], d + t[1]];
}
function K(e, t, u) {
return l(e, b(a(t, e), u));
}
function ee(e, t, u) {
return l(e, b(t, u));
}
var { min: C, PI: xe } = Math;
var pe = 0.275;
var V = xe + 1e-4;
function ce(e, t = {}) {
let { size: u = 16, smoothing: x = 0.5, thinning: h = 0.5, simulatePressure: y = true, easing: n = (r) => r, start: f = {}, end: d = {}, last: D2 = false } = t, { cap: S = true, easing: j = (r) => r * (2 - r) } = f, { cap: q = true, easing: c = (r) => --r * r * r + 1 } = d;
if (e.length === 0 || u <= 0) return [];
let p = e[e.length - 1].runningLength, g = f.taper === false ? 0 : f.taper === true ? Math.max(u, p) : f.taper, T = d.taper === false ? 0 : d.taper === true ? Math.max(u, p) : d.taper, te = Math.pow(u * x, 2), _ = [], M = [], H = e.slice(0, 10).reduce((r, i) => {
let o = i.pressure;
if (y) {
let s = C(1, i.distance / u), W = C(1, 1 - s);
o = C(1, r + (W - r) * (s * pe));
}
return (r + o) / 2;
}, e[0].pressure), m = $(u, h, e[e.length - 1].pressure, n), U, X = e[0].vector, z = e[0].point, F = z, O = z, E = F, J = false;
for (let r = 0; r < e.length; r++) {
let { pressure: i } = e[r], { point: o, vector: s, distance: W, runningLength: I } = e[r];
if (r < e.length - 1 && p - I < 3) continue;
if (h) {
if (y) {
let v = C(1, W / u), Z = C(1, 1 - v);
i = C(1, H + (Z - H) * (v * pe));
}
m = $(u, h, i, n);
} else m = u / 2;
U === void 0 && (U = m);
let le = I < g ? j(I / g) : 1, fe = p - I < T ? c((p - I) / T) : 1;
m = Math.max(0.01, m * Math.min(le, fe));
let re = (r < e.length - 1 ? e[r + 1] : e[r]).vector, Y = r < e.length - 1 ? B(s, re) : 1, be = B(s, X) < 0 && !J, ne = Y !== null && Y < 0;
if (be || ne) {
let v = b(R(X), m);
for (let Z = 1 / 13, w = 0; w <= 1; w += Z) O = L(a(o, v), o, V * w), _.push(O), E = L(l(o, v), o, V * -w), M.push(E);
z = O, F = E, ne && (J = true);
continue;
}
if (J = false, r === e.length - 1) {
let v = b(R(s), m);
_.push(a(o, v)), M.push(l(o, v));
continue;
}
let oe = b(R(K(re, s, Y)), m);
O = a(o, oe), (r <= 1 || A(z, O) > te) && (_.push(O), z = O), E = l(o, oe), (r <= 1 || A(F, E) > te) && (M.push(E), F = E), H = i, X = s;
}
let P = e[0].point.slice(0, 2), k = e.length > 1 ? e[e.length - 1].point.slice(0, 2) : l(e[0].point, [1, 1]), Q = [], N = [];
if (e.length === 1) {
if (!(g || T) || D2) {
let r = ee(P, G(R(a(P, k))), -(U || m)), i = [];
for (let o = 1 / 13, s = o; s <= 1; s += o) i.push(L(r, P, V * 2 * s));
return i;
}
} else {
if (!(g || T && e.length === 1)) if (S) for (let i = 1 / 13, o = i; o <= 1; o += i) {
let s = L(M[0], P, V * o);
Q.push(s);
}
else {
let i = a(_[0], M[0]), o = b(i, 0.5), s = b(i, 0.51);
Q.push(a(P, o), a(P, s), l(P, s), l(P, o));
}
let r = R(se(e[e.length - 1].vector));
if (T || g && e.length === 1) N.push(k);
else if (q) {
let i = ee(k, r, m);
for (let o = 1 / 29, s = o; s < 1; s += o) N.push(L(i, k, V * 3 * s));
} else N.push(l(k, b(r, m)), l(k, b(r, m * 0.99)), a(k, b(r, m * 0.99)), a(k, b(r, m)));
}
return _.concat(N, M.reverse(), Q);
}
function me(e, t = {}) {
var q;
let { streamline: u = 0.5, size: x = 16, last: h = false } = t;
if (e.length === 0) return [];
let y = 0.15 + (1 - u) * 0.85, n = Array.isArray(e[0]) ? e : e.map(({ x: c, y: p, pressure: g = 0.5 }) => [c, p, g]);
if (n.length === 2) {
let c = n[1];
n = n.slice(0, -1);
for (let p = 1; p < 5; p++) n.push(K(n[0], c, p / 4));
}
n.length === 1 && (n = [...n, [...l(n[0], [1, 1]), ...n[0].slice(2)]]);
let f = [{ point: [n[0][0], n[0][1]], pressure: n[0][2] >= 0 ? n[0][2] : 0.25, vector: [1, 1], distance: 0, runningLength: 0 }], d = false, D2 = 0, S = f[0], j = n.length - 1;
for (let c = 1; c < n.length; c++) {
let p = h && c === j ? n[c].slice(0, 2) : K(S.point, n[c], y);
if (ue(S.point, p)) continue;
let g = ie(p, S.point);
if (D2 += g, c < j && !d) {
if (D2 < x) continue;
d = true;
}
S = { point: p, pressure: n[c][2] >= 0 ? n[c][2] : 0.5, vector: G(a(S.point, p)), distance: g, runningLength: D2 }, f.push(S);
}
return f[0].vector = ((q = f[1]) == null ? void 0 : q.vector) || [0, 0], f;
}
function ae(e, t = {}) {
return ce(me(e, t), t);
}
// src/utils/index.ts

@@ -208,2 +60,95 @@ function numSort(a2, b2) {

// src/utils/dom.ts
function createArrowHead(id, fill) {
const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
const marker = document.createElementNS("http://www.w3.org/2000/svg", "marker");
const head = document.createElementNS("http://www.w3.org/2000/svg", "path");
head.setAttribute("fill", fill);
marker.setAttribute("id", id);
marker.setAttribute("viewBox", "0 -5 10 10");
marker.setAttribute("refX", "5");
marker.setAttribute("refY", "0");
marker.setAttribute("markerWidth", "4");
marker.setAttribute("markerHeight", "4");
marker.setAttribute("orient", "auto");
head.setAttribute("d", "M0,-5L10,0L0,5");
marker.appendChild(head);
defs.appendChild(marker);
return defs;
}
// src/utils/simplify.ts
function getSqDist(p1, p2) {
const dx = p1.x - p2.x;
const dy = p1.y - p2.y;
return dx * dx + dy * dy;
}
function getSqSegDist(p, p1, p2) {
let x = p1.x;
let y = p1.y;
let dx = p2.x - x;
let dy = p2.y - y;
if (dx !== 0 || dy !== 0) {
const t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2.x;
y = p2.y;
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = p.x - x;
dy = p.y - y;
return dx * dx + dy * dy;
}
function simplifyRadialDist(points, sqTolerance) {
let prevPoint = points[0];
const newPoints = [prevPoint];
let point;
for (let i = 1, len = points.length; i < len; i++) {
point = points[i];
if (getSqDist(point, prevPoint) > sqTolerance) {
newPoints.push(point);
prevPoint = point;
}
}
if (prevPoint !== point && point)
newPoints.push(point);
return newPoints;
}
function simplifyDPStep(points, first, last, sqTolerance, simplified) {
let maxSqDist = sqTolerance;
let index = 0;
for (let i = first + 1; i < last; i++) {
const sqDist = getSqSegDist(points[i], points[first], points[last]);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
if (index - first > 1)
simplifyDPStep(points, first, index, sqTolerance, simplified);
simplified.push(points[index]);
if (last - index > 1)
simplifyDPStep(points, index, last, sqTolerance, simplified);
}
}
function simplifyDouglasPeucker(points, sqTolerance) {
const last = points.length - 1;
const simplified = [points[0]];
simplifyDPStep(points, 0, last, sqTolerance, simplified);
simplified.push(points[last]);
return simplified;
}
function simplify(points, tolerance, highestQuality = false) {
if (points.length <= 2)
return points;
const sqTolerance = tolerance !== void 0 ? tolerance * tolerance : 1;
points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
points = simplifyDouglasPeucker(points, sqTolerance);
return points;
}
// src/models/base.ts

@@ -310,13 +255,17 @@ var BaseModel = class {

// src/models/stylus.ts
var StylusModel = class _StylusModel extends BaseModel {
// src/models/draw.ts
var DrawModel = class _DrawModel extends BaseModel {
constructor() {
super(...arguments);
this.points = [];
this.count = 0;
}
onStart(point) {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el = this.createElement("path", { fill: "transparent" });
this.points = [point];
this.attr("fill", this.brush.color);
this.attr("d", this.getSvgData(this.points));
if (this.brush.arrowEnd) {
this.arrowId = guid();
const head = createArrowHead(this.arrowId, this.brush.color);
this.el.appendChild(head);
}
return this.el;

@@ -327,5 +276,11 @@ }

this.onStart(point);
if (this.points[this.points.length - 1] !== point)
if (this.points[this.points.length - 1] !== point) {
this.points.push(point);
this.attr("d", this.getSvgData(this.points));
this.count += 1;
}
if (this.count > 5) {
this.points = simplify(this.points, 1, true);
this.count = 0;
}
this.attr("d", _DrawModel.toSvgData(this.points));
return true;

@@ -338,31 +293,42 @@ }

return false;
path.setAttribute("d", _DrawModel.toSvgData(simplify(this.points, 1, true)));
if (!path.getTotalLength()) {
const { x, y } = this.points[0];
const r = this.brush.size / 2;
path.setAttribute("d", `M ${x - r} ${y} a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 ${-r * 2},0`);
path.setAttribute("fill", this.brush.color);
path.setAttribute("stroke-width", "0");
}
return true;
}
getSvgData(points) {
return _StylusModel.getSvgData(points, this.brush);
// https://francoisromain.medium.com/smooth-a-svg-path-with-cubic-bezier-curves-e37b49d46c74
static line(a2, b2) {
const lengthX = b2.x - a2.x;
const lengthY = b2.y - a2.y;
return {
length: Math.sqrt(lengthX ** 2 + lengthY ** 2),
angle: Math.atan2(lengthY, lengthX)
};
}
static getSvgData(points, brush) {
const stroke = ae(points, __spreadValues({
size: brush.size,
thinning: 0.9,
simulatePressure: false,
start: {
taper: 5
},
end: {
taper: 5
}
}, brush.stylusOptions));
if (!stroke.length)
return "";
const d = stroke.reduce(
(acc, [x0, y0], i, arr) => {
const [x1, y1] = arr[(i + 1) % arr.length];
acc.push(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2);
return acc;
},
["M", ...stroke[0], "Q"]
static controlPoint(current, previous, next, reverse) {
const p = previous || current;
const n = next || current;
const smoothing = 0.2;
const o = _DrawModel.line(p, n);
const angle = o.angle + (reverse ? Math.PI : 0);
const length = o.length * smoothing;
const x = current.x + Math.cos(angle) * length;
const y = current.y + Math.sin(angle) * length;
return { x, y };
}
static bezierCommand(point, i, points) {
const cps = _DrawModel.controlPoint(points[i - 1], points[i - 2], point);
const cpe = _DrawModel.controlPoint(point, points[i - 1], points[i + 1], true);
return `C ${cps.x.toFixed(D)},${cps.y.toFixed(D)} ${cpe.x.toFixed(D)},${cpe.y.toFixed(D)} ${point.x.toFixed(D)},${point.y.toFixed(D)}`;
}
static toSvgData(points) {
return points.reduce(
(acc, point, i, a2) => i === 0 ? `M ${point.x.toFixed(D)},${point.y.toFixed(D)}` : `${acc} ${_DrawModel.bezierCommand(point, i, a2)}`,
""
);
d.push("Z");
return d.map((i) => typeof i === "number" ? i.toFixed(2) : i).join(" ");
}

@@ -409,4 +375,8 @@ };

return false;
if (!path.getTotalLength())
try {
if (!path.getTotalLength())
return false;
} catch (e) {
return false;
}
return true;

@@ -416,20 +386,116 @@ }

// src/utils/dom.ts
function createArrowHead(id, fill) {
const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
const marker = document.createElementNS("http://www.w3.org/2000/svg", "marker");
const head = document.createElementNS("http://www.w3.org/2000/svg", "path");
head.setAttribute("fill", fill);
marker.setAttribute("id", id);
marker.setAttribute("viewBox", "0 -5 10 10");
marker.setAttribute("refX", "5");
marker.setAttribute("refY", "0");
marker.setAttribute("markerWidth", "4");
marker.setAttribute("markerHeight", "4");
marker.setAttribute("orient", "auto");
head.setAttribute("d", "M0,-5L10,0L0,5");
marker.appendChild(head);
defs.appendChild(marker);
return defs;
}
// src/models/eraser.ts
var EraserModel = class extends BaseModel {
constructor() {
super(...arguments);
this.pathSubFactor = 20;
this.pathFragments = [];
this._erased = [];
}
onSelected(el) {
const calculatePathFragments = (children, element) => {
if (children && children.length) {
for (let i = 0; i < children.length; i++) {
const ele = children[i];
if (ele.getTotalLength) {
const pathLength = ele.getTotalLength();
for (let j = 0; j < this.pathSubFactor; j++) {
const pos1 = ele.getPointAtLength(pathLength * j / this.pathSubFactor);
const pos2 = ele.getPointAtLength(pathLength * (j + 1) / this.pathSubFactor);
this.pathFragments.push({
x1: pos1.x,
x2: pos2.x,
y1: pos1.y,
y2: pos2.y,
segment: j,
element: element || ele
});
}
} else {
if (ele.children)
calculatePathFragments(ele.children, ele);
}
}
}
};
if (el)
calculatePathFragments(el.children);
}
onUnselected() {
this.pathFragments = [];
}
onStart(point) {
this.svgPointPrevious = this.svgElement.createSVGPoint();
this.svgPointPrevious.x = point.x;
this.svgPointPrevious.y = point.y;
return void 0;
}
onMove(point) {
this.svgPointCurrent = this.svgElement.createSVGPoint();
this.svgPointCurrent.x = point.x;
this.svgPointCurrent.y = point.y;
const erased = this.checkAndEraseElement();
this.svgPointPrevious = this.svgPointCurrent;
return erased;
}
onEnd() {
this.svgPointPrevious = void 0;
this.svgPointCurrent = void 0;
const erased = this._erased;
this._erased = [];
return {
undo: () => erased.forEach((v) => this.drauu._restoreNode(v)),
redo: () => erased.forEach((v) => this.drauu._removeNode(v))
};
}
checkAndEraseElement() {
if (this.pathFragments.length) {
for (let i = 0; i < this.pathFragments.length; i++) {
const segment = this.pathFragments[i];
if (this.svgPointPrevious && this.svgPointCurrent) {
const line = {
x1: this.svgPointPrevious.x,
x2: this.svgPointCurrent.x,
y1: this.svgPointPrevious.y,
y2: this.svgPointCurrent.y
};
if (this.lineLineIntersect(segment, line)) {
this.drauu._removeNode(segment.element);
this._erased.push(segment.element);
}
}
}
}
if (this._erased.length)
this.pathFragments = this.pathFragments.filter((v) => !this._erased.includes(v.element));
return this._erased.length > 0;
}
lineLineIntersect(line1, line2) {
const x1 = line1.x1;
const x2 = line1.x2;
const x3 = line2.x1;
const x4 = line2.x2;
const y1 = line1.y1;
const y2 = line1.y2;
const y3 = line2.y1;
const y4 = line2.y2;
const pt_denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
const pt_x_num = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4);
const pt_y_num = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4);
const btwn = (a2, b1, b2) => {
if (a2 >= b1 && a2 <= b2)
return true;
return a2 >= b2 && a2 <= b1;
};
if (pt_denom === 0) {
return false;
} else {
const pt = {
x: pt_x_num / pt_denom,
y: pt_y_num / pt_denom
};
return btwn(pt.x, x1, x2) && btwn(pt.y, y1, y2) && btwn(pt.x, x3, x4) && btwn(pt.y, y3, y4);
}
}
};

@@ -491,4 +557,8 @@ // src/models/line.ts

return false;
if (path.getTotalLength() < 5)
try {
if (path.getTotalLength() < 5)
return false;
} catch (e) {
return false;
}
return true;

@@ -540,4 +610,8 @@ }

return false;
if (!path.getTotalLength())
try {
if (!path.getTotalLength())
return false;
} catch (e) {
return false;
}
return true;

@@ -547,91 +621,161 @@ }

// src/utils/simplify.ts
function getSqDist(p1, p2) {
const dx = p1.x - p2.x;
const dy = p1.y - p2.y;
return dx * dx + dy * dy;
// ../../node_modules/.pnpm/perfect-freehand@1.2.2/node_modules/perfect-freehand/dist/esm/index.mjs
function $(e, t, u, x = (h) => h) {
return e * x(0.5 - t * (0.5 - u));
}
function getSqSegDist(p, p1, p2) {
let x = p1.x;
let y = p1.y;
let dx = p2.x - x;
let dy = p2.y - y;
if (dx !== 0 || dy !== 0) {
const t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2.x;
y = p2.y;
} else if (t > 0) {
x += dx * t;
y += dy * t;
function se(e) {
return [-e[0], -e[1]];
}
function l(e, t) {
return [e[0] + t[0], e[1] + t[1]];
}
function a(e, t) {
return [e[0] - t[0], e[1] - t[1]];
}
function b(e, t) {
return [e[0] * t, e[1] * t];
}
function he(e, t) {
return [e[0] / t, e[1] / t];
}
function R(e) {
return [e[1], -e[0]];
}
function B(e, t) {
return e[0] * t[0] + e[1] * t[1];
}
function ue(e, t) {
return e[0] === t[0] && e[1] === t[1];
}
function ge(e) {
return Math.hypot(e[0], e[1]);
}
function de(e) {
return e[0] * e[0] + e[1] * e[1];
}
function A(e, t) {
return de(a(e, t));
}
function G(e) {
return he(e, ge(e));
}
function ie(e, t) {
return Math.hypot(e[1] - t[1], e[0] - t[0]);
}
function L(e, t, u) {
let x = Math.sin(u), h = Math.cos(u), y = e[0] - t[0], n = e[1] - t[1], f = y * h - n * x, d = y * x + n * h;
return [f + t[0], d + t[1]];
}
function K(e, t, u) {
return l(e, b(a(t, e), u));
}
function ee(e, t, u) {
return l(e, b(t, u));
}
var { min: C, PI: xe } = Math;
var pe = 0.275;
var V = xe + 1e-4;
function ce(e, t = {}) {
let { size: u = 16, smoothing: x = 0.5, thinning: h = 0.5, simulatePressure: y = true, easing: n = (r) => r, start: f = {}, end: d = {}, last: D2 = false } = t, { cap: S = true, easing: j = (r) => r * (2 - r) } = f, { cap: q = true, easing: c = (r) => --r * r * r + 1 } = d;
if (e.length === 0 || u <= 0) return [];
let p = e[e.length - 1].runningLength, g = f.taper === false ? 0 : f.taper === true ? Math.max(u, p) : f.taper, T = d.taper === false ? 0 : d.taper === true ? Math.max(u, p) : d.taper, te = Math.pow(u * x, 2), _ = [], M = [], H = e.slice(0, 10).reduce((r, i) => {
let o = i.pressure;
if (y) {
let s = C(1, i.distance / u), W = C(1, 1 - s);
o = C(1, r + (W - r) * (s * pe));
}
return (r + o) / 2;
}, e[0].pressure), m = $(u, h, e[e.length - 1].pressure, n), U, X = e[0].vector, z = e[0].point, F = z, O = z, E = F, J = false;
for (let r = 0; r < e.length; r++) {
let { pressure: i } = e[r], { point: o, vector: s, distance: W, runningLength: I } = e[r];
if (r < e.length - 1 && p - I < 3) continue;
if (h) {
if (y) {
let v = C(1, W / u), Z = C(1, 1 - v);
i = C(1, H + (Z - H) * (v * pe));
}
m = $(u, h, i, n);
} else m = u / 2;
U === void 0 && (U = m);
let le = I < g ? j(I / g) : 1, fe = p - I < T ? c((p - I) / T) : 1;
m = Math.max(0.01, m * Math.min(le, fe));
let re = (r < e.length - 1 ? e[r + 1] : e[r]).vector, Y = r < e.length - 1 ? B(s, re) : 1, be = B(s, X) < 0 && !J, ne = Y !== null && Y < 0;
if (be || ne) {
let v = b(R(X), m);
for (let Z = 1 / 13, w = 0; w <= 1; w += Z) O = L(a(o, v), o, V * w), _.push(O), E = L(l(o, v), o, V * -w), M.push(E);
z = O, F = E, ne && (J = true);
continue;
}
if (J = false, r === e.length - 1) {
let v = b(R(s), m);
_.push(a(o, v)), M.push(l(o, v));
continue;
}
let oe = b(R(K(re, s, Y)), m);
O = a(o, oe), (r <= 1 || A(z, O) > te) && (_.push(O), z = O), E = l(o, oe), (r <= 1 || A(F, E) > te) && (M.push(E), F = E), H = i, X = s;
}
dx = p.x - x;
dy = p.y - y;
return dx * dx + dy * dy;
}
function simplifyRadialDist(points, sqTolerance) {
let prevPoint = points[0];
const newPoints = [prevPoint];
let point;
for (let i = 1, len = points.length; i < len; i++) {
point = points[i];
if (getSqDist(point, prevPoint) > sqTolerance) {
newPoints.push(point);
prevPoint = point;
let P = e[0].point.slice(0, 2), k = e.length > 1 ? e[e.length - 1].point.slice(0, 2) : l(e[0].point, [1, 1]), Q = [], N = [];
if (e.length === 1) {
if (!(g || T) || D2) {
let r = ee(P, G(R(a(P, k))), -(U || m)), i = [];
for (let o = 1 / 13, s = o; s <= 1; s += o) i.push(L(r, P, V * 2 * s));
return i;
}
} else {
if (!(g || T && e.length === 1)) if (S) for (let i = 1 / 13, o = i; o <= 1; o += i) {
let s = L(M[0], P, V * o);
Q.push(s);
}
else {
let i = a(_[0], M[0]), o = b(i, 0.5), s = b(i, 0.51);
Q.push(a(P, o), a(P, s), l(P, s), l(P, o));
}
let r = R(se(e[e.length - 1].vector));
if (T || g && e.length === 1) N.push(k);
else if (q) {
let i = ee(k, r, m);
for (let o = 1 / 29, s = o; s < 1; s += o) N.push(L(i, k, V * 3 * s));
} else N.push(l(k, b(r, m)), l(k, b(r, m * 0.99)), a(k, b(r, m * 0.99)), a(k, b(r, m)));
}
if (prevPoint !== point && point)
newPoints.push(point);
return newPoints;
return _.concat(N, M.reverse(), Q);
}
function simplifyDPStep(points, first, last, sqTolerance, simplified) {
let maxSqDist = sqTolerance;
let index = 0;
for (let i = first + 1; i < last; i++) {
const sqDist = getSqSegDist(points[i], points[first], points[last]);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
function me(e, t = {}) {
var q;
let { streamline: u = 0.5, size: x = 16, last: h = false } = t;
if (e.length === 0) return [];
let y = 0.15 + (1 - u) * 0.85, n = Array.isArray(e[0]) ? e : e.map(({ x: c, y: p, pressure: g = 0.5 }) => [c, p, g]);
if (n.length === 2) {
let c = n[1];
n = n.slice(0, -1);
for (let p = 1; p < 5; p++) n.push(K(n[0], c, p / 4));
}
n.length === 1 && (n = [...n, [...l(n[0], [1, 1]), ...n[0].slice(2)]]);
let f = [{ point: [n[0][0], n[0][1]], pressure: n[0][2] >= 0 ? n[0][2] : 0.25, vector: [1, 1], distance: 0, runningLength: 0 }], d = false, D2 = 0, S = f[0], j = n.length - 1;
for (let c = 1; c < n.length; c++) {
let p = h && c === j ? n[c].slice(0, 2) : K(S.point, n[c], y);
if (ue(S.point, p)) continue;
let g = ie(p, S.point);
if (D2 += g, c < j && !d) {
if (D2 < x) continue;
d = true;
}
S = { point: p, pressure: n[c][2] >= 0 ? n[c][2] : 0.5, vector: G(a(S.point, p)), distance: g, runningLength: D2 }, f.push(S);
}
if (maxSqDist > sqTolerance) {
if (index - first > 1)
simplifyDPStep(points, first, index, sqTolerance, simplified);
simplified.push(points[index]);
if (last - index > 1)
simplifyDPStep(points, index, last, sqTolerance, simplified);
}
return f[0].vector = ((q = f[1]) == null ? void 0 : q.vector) || [0, 0], f;
}
function simplifyDouglasPeucker(points, sqTolerance) {
const last = points.length - 1;
const simplified = [points[0]];
simplifyDPStep(points, 0, last, sqTolerance, simplified);
simplified.push(points[last]);
return simplified;
function ae(e, t = {}) {
return ce(me(e, t), t);
}
function simplify(points, tolerance, highestQuality = false) {
if (points.length <= 2)
return points;
const sqTolerance = tolerance !== void 0 ? tolerance * tolerance : 1;
points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
points = simplifyDouglasPeucker(points, sqTolerance);
return points;
}
// src/models/draw.ts
var DrawModel = class _DrawModel extends BaseModel {
// src/models/stylus.ts
var StylusModel = class _StylusModel extends BaseModel {
constructor() {
super(...arguments);
this.points = [];
this.count = 0;
}
onStart(point) {
this.el = this.createElement("path", { fill: "transparent" });
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.points = [point];
if (this.brush.arrowEnd) {
this.arrowId = guid();
const head = createArrowHead(this.arrowId, this.brush.color);
this.el.appendChild(head);
}
this.attr("fill", this.brush.color);
this.attr("d", this.getSvgData(this.points));
return this.el;

@@ -642,11 +786,5 @@ }

this.onStart(point);
if (this.points[this.points.length - 1] !== point) {
if (this.points[this.points.length - 1] !== point)
this.points.push(point);
this.count += 1;
}
if (this.count > 5) {
this.points = simplify(this.points, 1, true);
this.count = 0;
}
this.attr("d", _DrawModel.toSvgData(this.points));
this.attr("d", this.getSvgData(this.points));
return true;

@@ -659,158 +797,34 @@ }

return false;
path.setAttribute("d", _DrawModel.toSvgData(simplify(this.points, 1, true)));
if (!path.getTotalLength()) {
const { x, y } = this.points[0];
const r = this.brush.size / 2;
path.setAttribute("d", `M ${x - r} ${y} a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 ${-r * 2},0`);
path.setAttribute("fill", this.brush.color);
path.setAttribute("stroke-width", "0");
}
return true;
}
// https://francoisromain.medium.com/smooth-a-svg-path-with-cubic-bezier-curves-e37b49d46c74
static line(a2, b2) {
const lengthX = b2.x - a2.x;
const lengthY = b2.y - a2.y;
return {
length: Math.sqrt(lengthX ** 2 + lengthY ** 2),
angle: Math.atan2(lengthY, lengthX)
};
getSvgData(points) {
return _StylusModel.getSvgData(points, this.brush);
}
static controlPoint(current, previous, next, reverse) {
const p = previous || current;
const n = next || current;
const smoothing = 0.2;
const o = _DrawModel.line(p, n);
const angle = o.angle + (reverse ? Math.PI : 0);
const length = o.length * smoothing;
const x = current.x + Math.cos(angle) * length;
const y = current.y + Math.sin(angle) * length;
return { x, y };
}
static bezierCommand(point, i, points) {
const cps = _DrawModel.controlPoint(points[i - 1], points[i - 2], point);
const cpe = _DrawModel.controlPoint(point, points[i - 1], points[i + 1], true);
return `C ${cps.x.toFixed(D)},${cps.y.toFixed(D)} ${cpe.x.toFixed(D)},${cpe.y.toFixed(D)} ${point.x.toFixed(D)},${point.y.toFixed(D)}`;
}
static toSvgData(points) {
return points.reduce(
(acc, point, i, a2) => i === 0 ? `M ${point.x.toFixed(D)},${point.y.toFixed(D)}` : `${acc} ${_DrawModel.bezierCommand(point, i, a2)}`,
""
static getSvgData(points, brush) {
const stroke = ae(points, __spreadValues({
size: brush.size,
thinning: 0.9,
simulatePressure: false,
start: {
taper: 5
},
end: {
taper: 5
}
}, brush.stylusOptions));
if (!stroke.length)
return "";
const d = stroke.reduce(
(acc, [x0, y0], i, arr) => {
const [x1, y1] = arr[(i + 1) % arr.length];
acc.push(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2);
return acc;
},
["M", ...stroke[0], "Q"]
);
d.push("Z");
return d.map((i) => typeof i === "number" ? i.toFixed(2) : i).join(" ");
}
};
// src/models/eraser.ts
var EraserModel = class extends BaseModel {
constructor() {
super(...arguments);
this.pathSubFactor = 20;
this.pathFragments = [];
this._erased = [];
}
onSelected(el) {
const calculatePathFragments = (children, element) => {
if (children && children.length) {
for (let i = 0; i < children.length; i++) {
const ele = children[i];
if (ele.getTotalLength) {
const pathLength = ele.getTotalLength();
for (let j = 0; j < this.pathSubFactor; j++) {
const pos1 = ele.getPointAtLength(pathLength * j / this.pathSubFactor);
const pos2 = ele.getPointAtLength(pathLength * (j + 1) / this.pathSubFactor);
this.pathFragments.push({
x1: pos1.x,
x2: pos2.x,
y1: pos1.y,
y2: pos2.y,
segment: j,
element: element || ele
});
}
} else {
if (ele.children)
calculatePathFragments(ele.children, ele);
}
}
}
};
if (el)
calculatePathFragments(el.children);
}
onUnselected() {
this.pathFragments = [];
}
onStart(point) {
this.svgPointPrevious = this.svgElement.createSVGPoint();
this.svgPointPrevious.x = point.x;
this.svgPointPrevious.y = point.y;
return void 0;
}
onMove(point) {
this.svgPointCurrent = this.svgElement.createSVGPoint();
this.svgPointCurrent.x = point.x;
this.svgPointCurrent.y = point.y;
const erased = this.checkAndEraseElement();
this.svgPointPrevious = this.svgPointCurrent;
return erased;
}
onEnd() {
this.svgPointPrevious = void 0;
this.svgPointCurrent = void 0;
const erased = this._erased;
this._erased = [];
return {
undo: () => erased.forEach((v) => this.drauu._restoreNode(v)),
redo: () => erased.forEach((v) => this.drauu._removeNode(v))
};
}
checkAndEraseElement() {
if (this.pathFragments.length) {
for (let i = 0; i < this.pathFragments.length; i++) {
const segment = this.pathFragments[i];
const line = {
x1: this.svgPointPrevious.x,
x2: this.svgPointCurrent.x,
y1: this.svgPointPrevious.y,
y2: this.svgPointCurrent.y
};
if (this.lineLineIntersect(segment, line)) {
this.drauu._removeNode(segment.element);
this._erased.push(segment.element);
}
}
}
if (this._erased.length)
this.pathFragments = this.pathFragments.filter((v) => !this._erased.includes(v.element));
return this._erased.length > 0;
}
lineLineIntersect(line1, line2) {
const x1 = line1.x1;
const x2 = line1.x2;
const x3 = line2.x1;
const x4 = line2.x2;
const y1 = line1.y1;
const y2 = line1.y2;
const y3 = line2.y1;
const y4 = line2.y2;
const pt_denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
const pt_x_num = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4);
const pt_y_num = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4);
const btwn = (a2, b1, b2) => {
if (a2 >= b1 && a2 <= b2)
return true;
return a2 >= b2 && a2 <= b1;
};
if (pt_denom === 0) {
return false;
} else {
const pt = {
x: pt_x_num / pt_denom,
y: pt_y_num / pt_denom
};
return btwn(pt.x, x1, x2) && btwn(pt.y, y1, y2) && btwn(pt.x, x3, x4) && btwn(pt.y, y3, y4);
}
}
};
// src/models/index.ts

@@ -971,7 +985,9 @@ function createModels(drauu) {

const el = this._currentNode;
this._appendNode(el);
this.commit({
undo: () => this._removeNode(el),
redo: () => this._restoreNode(el)
});
if (el) {
this._appendNode(el);
this.commit({
undo: () => this._removeNode(el),
redo: () => this._restoreNode(el)
});
}
} else {

@@ -978,0 +994,0 @@ this.commit(result);

@@ -48,6 +48,6 @@ "use strict";

// ../../node_modules/.pnpm/nanoevents@9.0.0/node_modules/nanoevents/index.js
// ../../node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js
var createNanoEvents = () => ({
emit(event, ...args) {
for (let i = 0, callbacks = this.events[event] || [], length = callbacks.length; i < length; i++) {
for (let callbacks = this.events[event] || [], i = 0, length = callbacks.length; i < length; i++) {
callbacks[i](...args);

@@ -68,150 +68,2 @@ }

// ../../node_modules/.pnpm/perfect-freehand@1.2.2/node_modules/perfect-freehand/dist/esm/index.mjs
function $(e, t, u, x = (h) => h) {
return e * x(0.5 - t * (0.5 - u));
}
function se(e) {
return [-e[0], -e[1]];
}
function l(e, t) {
return [e[0] + t[0], e[1] + t[1]];
}
function a(e, t) {
return [e[0] - t[0], e[1] - t[1]];
}
function b(e, t) {
return [e[0] * t, e[1] * t];
}
function he(e, t) {
return [e[0] / t, e[1] / t];
}
function R(e) {
return [e[1], -e[0]];
}
function B(e, t) {
return e[0] * t[0] + e[1] * t[1];
}
function ue(e, t) {
return e[0] === t[0] && e[1] === t[1];
}
function ge(e) {
return Math.hypot(e[0], e[1]);
}
function de(e) {
return e[0] * e[0] + e[1] * e[1];
}
function A(e, t) {
return de(a(e, t));
}
function G(e) {
return he(e, ge(e));
}
function ie(e, t) {
return Math.hypot(e[1] - t[1], e[0] - t[0]);
}
function L(e, t, u) {
let x = Math.sin(u), h = Math.cos(u), y = e[0] - t[0], n = e[1] - t[1], f = y * h - n * x, d = y * x + n * h;
return [f + t[0], d + t[1]];
}
function K(e, t, u) {
return l(e, b(a(t, e), u));
}
function ee(e, t, u) {
return l(e, b(t, u));
}
var { min: C, PI: xe } = Math;
var pe = 0.275;
var V = xe + 1e-4;
function ce(e, t = {}) {
let { size: u = 16, smoothing: x = 0.5, thinning: h = 0.5, simulatePressure: y = true, easing: n = (r) => r, start: f = {}, end: d = {}, last: D2 = false } = t, { cap: S = true, easing: j = (r) => r * (2 - r) } = f, { cap: q = true, easing: c = (r) => --r * r * r + 1 } = d;
if (e.length === 0 || u <= 0) return [];
let p = e[e.length - 1].runningLength, g = f.taper === false ? 0 : f.taper === true ? Math.max(u, p) : f.taper, T = d.taper === false ? 0 : d.taper === true ? Math.max(u, p) : d.taper, te = Math.pow(u * x, 2), _ = [], M = [], H = e.slice(0, 10).reduce((r, i) => {
let o = i.pressure;
if (y) {
let s = C(1, i.distance / u), W = C(1, 1 - s);
o = C(1, r + (W - r) * (s * pe));
}
return (r + o) / 2;
}, e[0].pressure), m = $(u, h, e[e.length - 1].pressure, n), U, X = e[0].vector, z = e[0].point, F = z, O = z, E = F, J = false;
for (let r = 0; r < e.length; r++) {
let { pressure: i } = e[r], { point: o, vector: s, distance: W, runningLength: I } = e[r];
if (r < e.length - 1 && p - I < 3) continue;
if (h) {
if (y) {
let v = C(1, W / u), Z = C(1, 1 - v);
i = C(1, H + (Z - H) * (v * pe));
}
m = $(u, h, i, n);
} else m = u / 2;
U === void 0 && (U = m);
let le = I < g ? j(I / g) : 1, fe = p - I < T ? c((p - I) / T) : 1;
m = Math.max(0.01, m * Math.min(le, fe));
let re = (r < e.length - 1 ? e[r + 1] : e[r]).vector, Y = r < e.length - 1 ? B(s, re) : 1, be = B(s, X) < 0 && !J, ne = Y !== null && Y < 0;
if (be || ne) {
let v = b(R(X), m);
for (let Z = 1 / 13, w = 0; w <= 1; w += Z) O = L(a(o, v), o, V * w), _.push(O), E = L(l(o, v), o, V * -w), M.push(E);
z = O, F = E, ne && (J = true);
continue;
}
if (J = false, r === e.length - 1) {
let v = b(R(s), m);
_.push(a(o, v)), M.push(l(o, v));
continue;
}
let oe = b(R(K(re, s, Y)), m);
O = a(o, oe), (r <= 1 || A(z, O) > te) && (_.push(O), z = O), E = l(o, oe), (r <= 1 || A(F, E) > te) && (M.push(E), F = E), H = i, X = s;
}
let P = e[0].point.slice(0, 2), k = e.length > 1 ? e[e.length - 1].point.slice(0, 2) : l(e[0].point, [1, 1]), Q = [], N = [];
if (e.length === 1) {
if (!(g || T) || D2) {
let r = ee(P, G(R(a(P, k))), -(U || m)), i = [];
for (let o = 1 / 13, s = o; s <= 1; s += o) i.push(L(r, P, V * 2 * s));
return i;
}
} else {
if (!(g || T && e.length === 1)) if (S) for (let i = 1 / 13, o = i; o <= 1; o += i) {
let s = L(M[0], P, V * o);
Q.push(s);
}
else {
let i = a(_[0], M[0]), o = b(i, 0.5), s = b(i, 0.51);
Q.push(a(P, o), a(P, s), l(P, s), l(P, o));
}
let r = R(se(e[e.length - 1].vector));
if (T || g && e.length === 1) N.push(k);
else if (q) {
let i = ee(k, r, m);
for (let o = 1 / 29, s = o; s < 1; s += o) N.push(L(i, k, V * 3 * s));
} else N.push(l(k, b(r, m)), l(k, b(r, m * 0.99)), a(k, b(r, m * 0.99)), a(k, b(r, m)));
}
return _.concat(N, M.reverse(), Q);
}
function me(e, t = {}) {
var q;
let { streamline: u = 0.5, size: x = 16, last: h = false } = t;
if (e.length === 0) return [];
let y = 0.15 + (1 - u) * 0.85, n = Array.isArray(e[0]) ? e : e.map(({ x: c, y: p, pressure: g = 0.5 }) => [c, p, g]);
if (n.length === 2) {
let c = n[1];
n = n.slice(0, -1);
for (let p = 1; p < 5; p++) n.push(K(n[0], c, p / 4));
}
n.length === 1 && (n = [...n, [...l(n[0], [1, 1]), ...n[0].slice(2)]]);
let f = [{ point: [n[0][0], n[0][1]], pressure: n[0][2] >= 0 ? n[0][2] : 0.25, vector: [1, 1], distance: 0, runningLength: 0 }], d = false, D2 = 0, S = f[0], j = n.length - 1;
for (let c = 1; c < n.length; c++) {
let p = h && c === j ? n[c].slice(0, 2) : K(S.point, n[c], y);
if (ue(S.point, p)) continue;
let g = ie(p, S.point);
if (D2 += g, c < j && !d) {
if (D2 < x) continue;
d = true;
}
S = { point: p, pressure: n[c][2] >= 0 ? n[c][2] : 0.5, vector: G(a(S.point, p)), distance: g, runningLength: D2 }, f.push(S);
}
return f[0].vector = ((q = f[1]) == null ? void 0 : q.vector) || [0, 0], f;
}
function ae(e, t = {}) {
return ce(me(e, t), t);
}
// src/utils/index.ts

@@ -236,2 +88,95 @@ function numSort(a2, b2) {

// src/utils/dom.ts
function createArrowHead(id, fill) {
const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
const marker = document.createElementNS("http://www.w3.org/2000/svg", "marker");
const head = document.createElementNS("http://www.w3.org/2000/svg", "path");
head.setAttribute("fill", fill);
marker.setAttribute("id", id);
marker.setAttribute("viewBox", "0 -5 10 10");
marker.setAttribute("refX", "5");
marker.setAttribute("refY", "0");
marker.setAttribute("markerWidth", "4");
marker.setAttribute("markerHeight", "4");
marker.setAttribute("orient", "auto");
head.setAttribute("d", "M0,-5L10,0L0,5");
marker.appendChild(head);
defs.appendChild(marker);
return defs;
}
// src/utils/simplify.ts
function getSqDist(p1, p2) {
const dx = p1.x - p2.x;
const dy = p1.y - p2.y;
return dx * dx + dy * dy;
}
function getSqSegDist(p, p1, p2) {
let x = p1.x;
let y = p1.y;
let dx = p2.x - x;
let dy = p2.y - y;
if (dx !== 0 || dy !== 0) {
const t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2.x;
y = p2.y;
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = p.x - x;
dy = p.y - y;
return dx * dx + dy * dy;
}
function simplifyRadialDist(points, sqTolerance) {
let prevPoint = points[0];
const newPoints = [prevPoint];
let point;
for (let i = 1, len = points.length; i < len; i++) {
point = points[i];
if (getSqDist(point, prevPoint) > sqTolerance) {
newPoints.push(point);
prevPoint = point;
}
}
if (prevPoint !== point && point)
newPoints.push(point);
return newPoints;
}
function simplifyDPStep(points, first, last, sqTolerance, simplified) {
let maxSqDist = sqTolerance;
let index = 0;
for (let i = first + 1; i < last; i++) {
const sqDist = getSqSegDist(points[i], points[first], points[last]);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
}
}
if (maxSqDist > sqTolerance) {
if (index - first > 1)
simplifyDPStep(points, first, index, sqTolerance, simplified);
simplified.push(points[index]);
if (last - index > 1)
simplifyDPStep(points, index, last, sqTolerance, simplified);
}
}
function simplifyDouglasPeucker(points, sqTolerance) {
const last = points.length - 1;
const simplified = [points[0]];
simplifyDPStep(points, 0, last, sqTolerance, simplified);
simplified.push(points[last]);
return simplified;
}
function simplify(points, tolerance, highestQuality = false) {
if (points.length <= 2)
return points;
const sqTolerance = tolerance !== void 0 ? tolerance * tolerance : 1;
points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
points = simplifyDouglasPeucker(points, sqTolerance);
return points;
}
// src/models/base.ts

@@ -338,13 +283,17 @@ var BaseModel = class {

// src/models/stylus.ts
var StylusModel = class _StylusModel extends BaseModel {
// src/models/draw.ts
var DrawModel = class _DrawModel extends BaseModel {
constructor() {
super(...arguments);
this.points = [];
this.count = 0;
}
onStart(point) {
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.el = this.createElement("path", { fill: "transparent" });
this.points = [point];
this.attr("fill", this.brush.color);
this.attr("d", this.getSvgData(this.points));
if (this.brush.arrowEnd) {
this.arrowId = guid();
const head = createArrowHead(this.arrowId, this.brush.color);
this.el.appendChild(head);
}
return this.el;

@@ -355,5 +304,11 @@ }

this.onStart(point);
if (this.points[this.points.length - 1] !== point)
if (this.points[this.points.length - 1] !== point) {
this.points.push(point);
this.attr("d", this.getSvgData(this.points));
this.count += 1;
}
if (this.count > 5) {
this.points = simplify(this.points, 1, true);
this.count = 0;
}
this.attr("d", _DrawModel.toSvgData(this.points));
return true;

@@ -366,31 +321,42 @@ }

return false;
path.setAttribute("d", _DrawModel.toSvgData(simplify(this.points, 1, true)));
if (!path.getTotalLength()) {
const { x, y } = this.points[0];
const r = this.brush.size / 2;
path.setAttribute("d", `M ${x - r} ${y} a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 ${-r * 2},0`);
path.setAttribute("fill", this.brush.color);
path.setAttribute("stroke-width", "0");
}
return true;
}
getSvgData(points) {
return _StylusModel.getSvgData(points, this.brush);
// https://francoisromain.medium.com/smooth-a-svg-path-with-cubic-bezier-curves-e37b49d46c74
static line(a2, b2) {
const lengthX = b2.x - a2.x;
const lengthY = b2.y - a2.y;
return {
length: Math.sqrt(lengthX ** 2 + lengthY ** 2),
angle: Math.atan2(lengthY, lengthX)
};
}
static getSvgData(points, brush) {
const stroke = ae(points, __spreadValues({
size: brush.size,
thinning: 0.9,
simulatePressure: false,
start: {
taper: 5
},
end: {
taper: 5
}
}, brush.stylusOptions));
if (!stroke.length)
return "";
const d = stroke.reduce(
(acc, [x0, y0], i, arr) => {
const [x1, y1] = arr[(i + 1) % arr.length];
acc.push(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2);
return acc;
},
["M", ...stroke[0], "Q"]
static controlPoint(current, previous, next, reverse) {
const p = previous || current;
const n = next || current;
const smoothing = 0.2;
const o = _DrawModel.line(p, n);
const angle = o.angle + (reverse ? Math.PI : 0);
const length = o.length * smoothing;
const x = current.x + Math.cos(angle) * length;
const y = current.y + Math.sin(angle) * length;
return { x, y };
}
static bezierCommand(point, i, points) {
const cps = _DrawModel.controlPoint(points[i - 1], points[i - 2], point);
const cpe = _DrawModel.controlPoint(point, points[i - 1], points[i + 1], true);
return `C ${cps.x.toFixed(D)},${cps.y.toFixed(D)} ${cpe.x.toFixed(D)},${cpe.y.toFixed(D)} ${point.x.toFixed(D)},${point.y.toFixed(D)}`;
}
static toSvgData(points) {
return points.reduce(
(acc, point, i, a2) => i === 0 ? `M ${point.x.toFixed(D)},${point.y.toFixed(D)}` : `${acc} ${_DrawModel.bezierCommand(point, i, a2)}`,
""
);
d.push("Z");
return d.map((i) => typeof i === "number" ? i.toFixed(2) : i).join(" ");
}

@@ -437,4 +403,8 @@ };

return false;
if (!path.getTotalLength())
try {
if (!path.getTotalLength())
return false;
} catch (e) {
return false;
}
return true;

@@ -444,20 +414,116 @@ }

// src/utils/dom.ts
function createArrowHead(id, fill) {
const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
const marker = document.createElementNS("http://www.w3.org/2000/svg", "marker");
const head = document.createElementNS("http://www.w3.org/2000/svg", "path");
head.setAttribute("fill", fill);
marker.setAttribute("id", id);
marker.setAttribute("viewBox", "0 -5 10 10");
marker.setAttribute("refX", "5");
marker.setAttribute("refY", "0");
marker.setAttribute("markerWidth", "4");
marker.setAttribute("markerHeight", "4");
marker.setAttribute("orient", "auto");
head.setAttribute("d", "M0,-5L10,0L0,5");
marker.appendChild(head);
defs.appendChild(marker);
return defs;
}
// src/models/eraser.ts
var EraserModel = class extends BaseModel {
constructor() {
super(...arguments);
this.pathSubFactor = 20;
this.pathFragments = [];
this._erased = [];
}
onSelected(el) {
const calculatePathFragments = (children, element) => {
if (children && children.length) {
for (let i = 0; i < children.length; i++) {
const ele = children[i];
if (ele.getTotalLength) {
const pathLength = ele.getTotalLength();
for (let j = 0; j < this.pathSubFactor; j++) {
const pos1 = ele.getPointAtLength(pathLength * j / this.pathSubFactor);
const pos2 = ele.getPointAtLength(pathLength * (j + 1) / this.pathSubFactor);
this.pathFragments.push({
x1: pos1.x,
x2: pos2.x,
y1: pos1.y,
y2: pos2.y,
segment: j,
element: element || ele
});
}
} else {
if (ele.children)
calculatePathFragments(ele.children, ele);
}
}
}
};
if (el)
calculatePathFragments(el.children);
}
onUnselected() {
this.pathFragments = [];
}
onStart(point) {
this.svgPointPrevious = this.svgElement.createSVGPoint();
this.svgPointPrevious.x = point.x;
this.svgPointPrevious.y = point.y;
return void 0;
}
onMove(point) {
this.svgPointCurrent = this.svgElement.createSVGPoint();
this.svgPointCurrent.x = point.x;
this.svgPointCurrent.y = point.y;
const erased = this.checkAndEraseElement();
this.svgPointPrevious = this.svgPointCurrent;
return erased;
}
onEnd() {
this.svgPointPrevious = void 0;
this.svgPointCurrent = void 0;
const erased = this._erased;
this._erased = [];
return {
undo: () => erased.forEach((v) => this.drauu._restoreNode(v)),
redo: () => erased.forEach((v) => this.drauu._removeNode(v))
};
}
checkAndEraseElement() {
if (this.pathFragments.length) {
for (let i = 0; i < this.pathFragments.length; i++) {
const segment = this.pathFragments[i];
if (this.svgPointPrevious && this.svgPointCurrent) {
const line = {
x1: this.svgPointPrevious.x,
x2: this.svgPointCurrent.x,
y1: this.svgPointPrevious.y,
y2: this.svgPointCurrent.y
};
if (this.lineLineIntersect(segment, line)) {
this.drauu._removeNode(segment.element);
this._erased.push(segment.element);
}
}
}
}
if (this._erased.length)
this.pathFragments = this.pathFragments.filter((v) => !this._erased.includes(v.element));
return this._erased.length > 0;
}
lineLineIntersect(line1, line2) {
const x1 = line1.x1;
const x2 = line1.x2;
const x3 = line2.x1;
const x4 = line2.x2;
const y1 = line1.y1;
const y2 = line1.y2;
const y3 = line2.y1;
const y4 = line2.y2;
const pt_denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
const pt_x_num = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4);
const pt_y_num = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4);
const btwn = (a2, b1, b2) => {
if (a2 >= b1 && a2 <= b2)
return true;
return a2 >= b2 && a2 <= b1;
};
if (pt_denom === 0) {
return false;
} else {
const pt = {
x: pt_x_num / pt_denom,
y: pt_y_num / pt_denom
};
return btwn(pt.x, x1, x2) && btwn(pt.y, y1, y2) && btwn(pt.x, x3, x4) && btwn(pt.y, y3, y4);
}
}
};

@@ -519,4 +585,8 @@ // src/models/line.ts

return false;
if (path.getTotalLength() < 5)
try {
if (path.getTotalLength() < 5)
return false;
} catch (e) {
return false;
}
return true;

@@ -568,4 +638,8 @@ }

return false;
if (!path.getTotalLength())
try {
if (!path.getTotalLength())
return false;
} catch (e) {
return false;
}
return true;

@@ -575,91 +649,161 @@ }

// src/utils/simplify.ts
function getSqDist(p1, p2) {
const dx = p1.x - p2.x;
const dy = p1.y - p2.y;
return dx * dx + dy * dy;
// ../../node_modules/.pnpm/perfect-freehand@1.2.2/node_modules/perfect-freehand/dist/esm/index.mjs
function $(e, t, u, x = (h) => h) {
return e * x(0.5 - t * (0.5 - u));
}
function getSqSegDist(p, p1, p2) {
let x = p1.x;
let y = p1.y;
let dx = p2.x - x;
let dy = p2.y - y;
if (dx !== 0 || dy !== 0) {
const t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = p2.x;
y = p2.y;
} else if (t > 0) {
x += dx * t;
y += dy * t;
function se(e) {
return [-e[0], -e[1]];
}
function l(e, t) {
return [e[0] + t[0], e[1] + t[1]];
}
function a(e, t) {
return [e[0] - t[0], e[1] - t[1]];
}
function b(e, t) {
return [e[0] * t, e[1] * t];
}
function he(e, t) {
return [e[0] / t, e[1] / t];
}
function R(e) {
return [e[1], -e[0]];
}
function B(e, t) {
return e[0] * t[0] + e[1] * t[1];
}
function ue(e, t) {
return e[0] === t[0] && e[1] === t[1];
}
function ge(e) {
return Math.hypot(e[0], e[1]);
}
function de(e) {
return e[0] * e[0] + e[1] * e[1];
}
function A(e, t) {
return de(a(e, t));
}
function G(e) {
return he(e, ge(e));
}
function ie(e, t) {
return Math.hypot(e[1] - t[1], e[0] - t[0]);
}
function L(e, t, u) {
let x = Math.sin(u), h = Math.cos(u), y = e[0] - t[0], n = e[1] - t[1], f = y * h - n * x, d = y * x + n * h;
return [f + t[0], d + t[1]];
}
function K(e, t, u) {
return l(e, b(a(t, e), u));
}
function ee(e, t, u) {
return l(e, b(t, u));
}
var { min: C, PI: xe } = Math;
var pe = 0.275;
var V = xe + 1e-4;
function ce(e, t = {}) {
let { size: u = 16, smoothing: x = 0.5, thinning: h = 0.5, simulatePressure: y = true, easing: n = (r) => r, start: f = {}, end: d = {}, last: D2 = false } = t, { cap: S = true, easing: j = (r) => r * (2 - r) } = f, { cap: q = true, easing: c = (r) => --r * r * r + 1 } = d;
if (e.length === 0 || u <= 0) return [];
let p = e[e.length - 1].runningLength, g = f.taper === false ? 0 : f.taper === true ? Math.max(u, p) : f.taper, T = d.taper === false ? 0 : d.taper === true ? Math.max(u, p) : d.taper, te = Math.pow(u * x, 2), _ = [], M = [], H = e.slice(0, 10).reduce((r, i) => {
let o = i.pressure;
if (y) {
let s = C(1, i.distance / u), W = C(1, 1 - s);
o = C(1, r + (W - r) * (s * pe));
}
return (r + o) / 2;
}, e[0].pressure), m = $(u, h, e[e.length - 1].pressure, n), U, X = e[0].vector, z = e[0].point, F = z, O = z, E = F, J = false;
for (let r = 0; r < e.length; r++) {
let { pressure: i } = e[r], { point: o, vector: s, distance: W, runningLength: I } = e[r];
if (r < e.length - 1 && p - I < 3) continue;
if (h) {
if (y) {
let v = C(1, W / u), Z = C(1, 1 - v);
i = C(1, H + (Z - H) * (v * pe));
}
m = $(u, h, i, n);
} else m = u / 2;
U === void 0 && (U = m);
let le = I < g ? j(I / g) : 1, fe = p - I < T ? c((p - I) / T) : 1;
m = Math.max(0.01, m * Math.min(le, fe));
let re = (r < e.length - 1 ? e[r + 1] : e[r]).vector, Y = r < e.length - 1 ? B(s, re) : 1, be = B(s, X) < 0 && !J, ne = Y !== null && Y < 0;
if (be || ne) {
let v = b(R(X), m);
for (let Z = 1 / 13, w = 0; w <= 1; w += Z) O = L(a(o, v), o, V * w), _.push(O), E = L(l(o, v), o, V * -w), M.push(E);
z = O, F = E, ne && (J = true);
continue;
}
if (J = false, r === e.length - 1) {
let v = b(R(s), m);
_.push(a(o, v)), M.push(l(o, v));
continue;
}
let oe = b(R(K(re, s, Y)), m);
O = a(o, oe), (r <= 1 || A(z, O) > te) && (_.push(O), z = O), E = l(o, oe), (r <= 1 || A(F, E) > te) && (M.push(E), F = E), H = i, X = s;
}
dx = p.x - x;
dy = p.y - y;
return dx * dx + dy * dy;
}
function simplifyRadialDist(points, sqTolerance) {
let prevPoint = points[0];
const newPoints = [prevPoint];
let point;
for (let i = 1, len = points.length; i < len; i++) {
point = points[i];
if (getSqDist(point, prevPoint) > sqTolerance) {
newPoints.push(point);
prevPoint = point;
let P = e[0].point.slice(0, 2), k = e.length > 1 ? e[e.length - 1].point.slice(0, 2) : l(e[0].point, [1, 1]), Q = [], N = [];
if (e.length === 1) {
if (!(g || T) || D2) {
let r = ee(P, G(R(a(P, k))), -(U || m)), i = [];
for (let o = 1 / 13, s = o; s <= 1; s += o) i.push(L(r, P, V * 2 * s));
return i;
}
} else {
if (!(g || T && e.length === 1)) if (S) for (let i = 1 / 13, o = i; o <= 1; o += i) {
let s = L(M[0], P, V * o);
Q.push(s);
}
else {
let i = a(_[0], M[0]), o = b(i, 0.5), s = b(i, 0.51);
Q.push(a(P, o), a(P, s), l(P, s), l(P, o));
}
let r = R(se(e[e.length - 1].vector));
if (T || g && e.length === 1) N.push(k);
else if (q) {
let i = ee(k, r, m);
for (let o = 1 / 29, s = o; s < 1; s += o) N.push(L(i, k, V * 3 * s));
} else N.push(l(k, b(r, m)), l(k, b(r, m * 0.99)), a(k, b(r, m * 0.99)), a(k, b(r, m)));
}
if (prevPoint !== point && point)
newPoints.push(point);
return newPoints;
return _.concat(N, M.reverse(), Q);
}
function simplifyDPStep(points, first, last, sqTolerance, simplified) {
let maxSqDist = sqTolerance;
let index = 0;
for (let i = first + 1; i < last; i++) {
const sqDist = getSqSegDist(points[i], points[first], points[last]);
if (sqDist > maxSqDist) {
index = i;
maxSqDist = sqDist;
function me(e, t = {}) {
var q;
let { streamline: u = 0.5, size: x = 16, last: h = false } = t;
if (e.length === 0) return [];
let y = 0.15 + (1 - u) * 0.85, n = Array.isArray(e[0]) ? e : e.map(({ x: c, y: p, pressure: g = 0.5 }) => [c, p, g]);
if (n.length === 2) {
let c = n[1];
n = n.slice(0, -1);
for (let p = 1; p < 5; p++) n.push(K(n[0], c, p / 4));
}
n.length === 1 && (n = [...n, [...l(n[0], [1, 1]), ...n[0].slice(2)]]);
let f = [{ point: [n[0][0], n[0][1]], pressure: n[0][2] >= 0 ? n[0][2] : 0.25, vector: [1, 1], distance: 0, runningLength: 0 }], d = false, D2 = 0, S = f[0], j = n.length - 1;
for (let c = 1; c < n.length; c++) {
let p = h && c === j ? n[c].slice(0, 2) : K(S.point, n[c], y);
if (ue(S.point, p)) continue;
let g = ie(p, S.point);
if (D2 += g, c < j && !d) {
if (D2 < x) continue;
d = true;
}
S = { point: p, pressure: n[c][2] >= 0 ? n[c][2] : 0.5, vector: G(a(S.point, p)), distance: g, runningLength: D2 }, f.push(S);
}
if (maxSqDist > sqTolerance) {
if (index - first > 1)
simplifyDPStep(points, first, index, sqTolerance, simplified);
simplified.push(points[index]);
if (last - index > 1)
simplifyDPStep(points, index, last, sqTolerance, simplified);
}
return f[0].vector = ((q = f[1]) == null ? void 0 : q.vector) || [0, 0], f;
}
function simplifyDouglasPeucker(points, sqTolerance) {
const last = points.length - 1;
const simplified = [points[0]];
simplifyDPStep(points, 0, last, sqTolerance, simplified);
simplified.push(points[last]);
return simplified;
function ae(e, t = {}) {
return ce(me(e, t), t);
}
function simplify(points, tolerance, highestQuality = false) {
if (points.length <= 2)
return points;
const sqTolerance = tolerance !== void 0 ? tolerance * tolerance : 1;
points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
points = simplifyDouglasPeucker(points, sqTolerance);
return points;
}
// src/models/draw.ts
var DrawModel = class _DrawModel extends BaseModel {
// src/models/stylus.ts
var StylusModel = class _StylusModel extends BaseModel {
constructor() {
super(...arguments);
this.points = [];
this.count = 0;
}
onStart(point) {
this.el = this.createElement("path", { fill: "transparent" });
this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.points = [point];
if (this.brush.arrowEnd) {
this.arrowId = guid();
const head = createArrowHead(this.arrowId, this.brush.color);
this.el.appendChild(head);
}
this.attr("fill", this.brush.color);
this.attr("d", this.getSvgData(this.points));
return this.el;

@@ -670,11 +814,5 @@ }

this.onStart(point);
if (this.points[this.points.length - 1] !== point) {
if (this.points[this.points.length - 1] !== point)
this.points.push(point);
this.count += 1;
}
if (this.count > 5) {
this.points = simplify(this.points, 1, true);
this.count = 0;
}
this.attr("d", _DrawModel.toSvgData(this.points));
this.attr("d", this.getSvgData(this.points));
return true;

@@ -687,158 +825,34 @@ }

return false;
path.setAttribute("d", _DrawModel.toSvgData(simplify(this.points, 1, true)));
if (!path.getTotalLength()) {
const { x, y } = this.points[0];
const r = this.brush.size / 2;
path.setAttribute("d", `M ${x - r} ${y} a ${r},${r} 0 1,0 ${r * 2},0 a ${r},${r} 0 1,0 ${-r * 2},0`);
path.setAttribute("fill", this.brush.color);
path.setAttribute("stroke-width", "0");
}
return true;
}
// https://francoisromain.medium.com/smooth-a-svg-path-with-cubic-bezier-curves-e37b49d46c74
static line(a2, b2) {
const lengthX = b2.x - a2.x;
const lengthY = b2.y - a2.y;
return {
length: Math.sqrt(lengthX ** 2 + lengthY ** 2),
angle: Math.atan2(lengthY, lengthX)
};
getSvgData(points) {
return _StylusModel.getSvgData(points, this.brush);
}
static controlPoint(current, previous, next, reverse) {
const p = previous || current;
const n = next || current;
const smoothing = 0.2;
const o = _DrawModel.line(p, n);
const angle = o.angle + (reverse ? Math.PI : 0);
const length = o.length * smoothing;
const x = current.x + Math.cos(angle) * length;
const y = current.y + Math.sin(angle) * length;
return { x, y };
}
static bezierCommand(point, i, points) {
const cps = _DrawModel.controlPoint(points[i - 1], points[i - 2], point);
const cpe = _DrawModel.controlPoint(point, points[i - 1], points[i + 1], true);
return `C ${cps.x.toFixed(D)},${cps.y.toFixed(D)} ${cpe.x.toFixed(D)},${cpe.y.toFixed(D)} ${point.x.toFixed(D)},${point.y.toFixed(D)}`;
}
static toSvgData(points) {
return points.reduce(
(acc, point, i, a2) => i === 0 ? `M ${point.x.toFixed(D)},${point.y.toFixed(D)}` : `${acc} ${_DrawModel.bezierCommand(point, i, a2)}`,
""
static getSvgData(points, brush) {
const stroke = ae(points, __spreadValues({
size: brush.size,
thinning: 0.9,
simulatePressure: false,
start: {
taper: 5
},
end: {
taper: 5
}
}, brush.stylusOptions));
if (!stroke.length)
return "";
const d = stroke.reduce(
(acc, [x0, y0], i, arr) => {
const [x1, y1] = arr[(i + 1) % arr.length];
acc.push(x0, y0, (x0 + x1) / 2, (y0 + y1) / 2);
return acc;
},
["M", ...stroke[0], "Q"]
);
d.push("Z");
return d.map((i) => typeof i === "number" ? i.toFixed(2) : i).join(" ");
}
};
// src/models/eraser.ts
var EraserModel = class extends BaseModel {
constructor() {
super(...arguments);
this.pathSubFactor = 20;
this.pathFragments = [];
this._erased = [];
}
onSelected(el) {
const calculatePathFragments = (children, element) => {
if (children && children.length) {
for (let i = 0; i < children.length; i++) {
const ele = children[i];
if (ele.getTotalLength) {
const pathLength = ele.getTotalLength();
for (let j = 0; j < this.pathSubFactor; j++) {
const pos1 = ele.getPointAtLength(pathLength * j / this.pathSubFactor);
const pos2 = ele.getPointAtLength(pathLength * (j + 1) / this.pathSubFactor);
this.pathFragments.push({
x1: pos1.x,
x2: pos2.x,
y1: pos1.y,
y2: pos2.y,
segment: j,
element: element || ele
});
}
} else {
if (ele.children)
calculatePathFragments(ele.children, ele);
}
}
}
};
if (el)
calculatePathFragments(el.children);
}
onUnselected() {
this.pathFragments = [];
}
onStart(point) {
this.svgPointPrevious = this.svgElement.createSVGPoint();
this.svgPointPrevious.x = point.x;
this.svgPointPrevious.y = point.y;
return void 0;
}
onMove(point) {
this.svgPointCurrent = this.svgElement.createSVGPoint();
this.svgPointCurrent.x = point.x;
this.svgPointCurrent.y = point.y;
const erased = this.checkAndEraseElement();
this.svgPointPrevious = this.svgPointCurrent;
return erased;
}
onEnd() {
this.svgPointPrevious = void 0;
this.svgPointCurrent = void 0;
const erased = this._erased;
this._erased = [];
return {
undo: () => erased.forEach((v) => this.drauu._restoreNode(v)),
redo: () => erased.forEach((v) => this.drauu._removeNode(v))
};
}
checkAndEraseElement() {
if (this.pathFragments.length) {
for (let i = 0; i < this.pathFragments.length; i++) {
const segment = this.pathFragments[i];
const line = {
x1: this.svgPointPrevious.x,
x2: this.svgPointCurrent.x,
y1: this.svgPointPrevious.y,
y2: this.svgPointCurrent.y
};
if (this.lineLineIntersect(segment, line)) {
this.drauu._removeNode(segment.element);
this._erased.push(segment.element);
}
}
}
if (this._erased.length)
this.pathFragments = this.pathFragments.filter((v) => !this._erased.includes(v.element));
return this._erased.length > 0;
}
lineLineIntersect(line1, line2) {
const x1 = line1.x1;
const x2 = line1.x2;
const x3 = line2.x1;
const x4 = line2.x2;
const y1 = line1.y1;
const y2 = line1.y2;
const y3 = line2.y1;
const y4 = line2.y2;
const pt_denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
const pt_x_num = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4);
const pt_y_num = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4);
const btwn = (a2, b1, b2) => {
if (a2 >= b1 && a2 <= b2)
return true;
return a2 >= b2 && a2 <= b1;
};
if (pt_denom === 0) {
return false;
} else {
const pt = {
x: pt_x_num / pt_denom,
y: pt_y_num / pt_denom
};
return btwn(pt.x, x1, x2) && btwn(pt.y, y1, y2) && btwn(pt.x, x3, x4) && btwn(pt.y, y3, y4);
}
}
};
// src/models/index.ts

@@ -999,7 +1013,9 @@ function createModels(drauu) {

const el = this._currentNode;
this._appendNode(el);
this.commit({
undo: () => this._removeNode(el),
redo: () => this._restoreNode(el)
});
if (el) {
this._appendNode(el);
this.commit({
undo: () => this._removeNode(el),
redo: () => this._restoreNode(el)
});
}
} else {

@@ -1006,0 +1022,0 @@ this.commit(result);

{
"name": "@drauu/core",
"version": "0.4.1",
"version": "0.4.2",
"author": "Anthony Fu <anthonyfu117@hotmail.com>",

@@ -5,0 +5,0 @@ "license": "MIT",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc