moves svg utils into its own package
This commit is contained in:
parent
f8ede2eab2
commit
b94c97aafe
22 changed files with 311 additions and 597 deletions
|
@ -13,9 +13,10 @@
|
|||
"packages/core",
|
||||
"packages/tldraw",
|
||||
"packages/dev",
|
||||
"packages/www",
|
||||
"packages/vec",
|
||||
"packages/intersect"
|
||||
"packages/svg",
|
||||
"packages/intersect",
|
||||
"packages/www"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAE3B,eAAe,KAAK,CAAA"}
|
|
@ -1,5 +1,4 @@
|
|||
import { Utils } from './utils'
|
||||
export { Utils } from './utils'
|
||||
export { Svg } from './svg'
|
||||
|
||||
export default Utils
|
||||
|
|
1
packages/core/src/utils/polyfills.d.ts
vendored
1
packages/core/src/utils/polyfills.d.ts
vendored
|
@ -1 +0,0 @@
|
|||
//# sourceMappingURL=polyfills.d.ts.map
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"polyfills.d.ts","sourceRoot":"","sources":["polyfills.ts"],"names":[],"mappings":""}
|
15
packages/core/src/utils/svg.d.ts
vendored
15
packages/core/src/utils/svg.d.ts
vendored
|
@ -1,15 +0,0 @@
|
|||
export declare class Svg {
|
||||
static ellipse: (A: number[], r: number) => string;
|
||||
static moveTo: (v: number[]) => string;
|
||||
static lineTo: (v: number[]) => string;
|
||||
static line: (a: number[], ...pts: number[][]) => string;
|
||||
static hLineTo: (v: number[]) => string;
|
||||
static vLineTo: (v: number[]) => string;
|
||||
static bezierTo: (A: number[], B: number[], C: number[]) => string;
|
||||
static arcTo: (C: number[], r: number, A: number[], B: number[]) => string;
|
||||
static closePath: () => string;
|
||||
static rectTo: (A: number[]) => string;
|
||||
static getPointAtLength: (path: SVGPathElement, length: number) => number[];
|
||||
}
|
||||
export default Svg;
|
||||
//# sourceMappingURL=svg.d.ts.map
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"svg.d.ts","sourceRoot":"","sources":["svg.ts"],"names":[],"mappings":"AAIA,qBAAa,GAAG;IACd,MAAM,CAAC,OAAO,MAAO,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,CAIhD;IAED,MAAM,CAAC,MAAM,MAAO,MAAM,EAAE,KAAG,MAAM,CAEpC;IAED,MAAM,CAAC,MAAM,MAAO,MAAM,EAAE,KAAG,MAAM,CAEpC;IAED,MAAM,CAAC,IAAI,MAAO,MAAM,EAAE,UAAU,MAAM,EAAE,EAAE,KAAG,MAAM,CAEtD;IAED,MAAM,CAAC,OAAO,MAAO,MAAM,EAAE,KAAG,MAAM,CAErC;IAED,MAAM,CAAC,OAAO,MAAO,MAAM,EAAE,KAAG,MAAM,CAErC;IAED,MAAM,CAAC,QAAQ,MAAO,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,KAAG,MAAM,CAEhE;IAED,MAAM,CAAC,KAAK,MAAO,MAAM,EAAE,KAAK,MAAM,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,KAAG,MAAM,CAYxE;IAED,MAAM,CAAC,SAAS,QAAO,MAAM,CAE5B;IAED,MAAM,CAAC,MAAM,MAAO,MAAM,EAAE,KAAG,MAAM,CAEpC;IAED,MAAM,CAAC,gBAAgB,SAAU,cAAc,UAAU,MAAM,KAAG,MAAM,EAAE,CAGzE;CACF;AAED,eAAe,GAAG,CAAA"}
|
|
@ -1,64 +0,0 @@
|
|||
import { Utils } from './utils'
|
||||
|
||||
// General
|
||||
|
||||
export class Svg {
|
||||
static ellipse = (A: number[], r: number): string => {
|
||||
return `M ${A[0] - r},${A[1]}
|
||||
a ${r},${r} 0 1,0 ${r * 2},0
|
||||
a ${r},${r} 0 1,0 -${r * 2},0 `
|
||||
}
|
||||
|
||||
static moveTo = (v: number[]): string => {
|
||||
return `M ${v[0]},${v[1]} `
|
||||
}
|
||||
|
||||
static lineTo = (v: number[]): string => {
|
||||
return `L ${v[0]},${v[1]} `
|
||||
}
|
||||
|
||||
static line = (a: number[], ...pts: number[][]): string => {
|
||||
return Svg.moveTo(a) + pts.map((p): string => Svg.lineTo(p)).join()
|
||||
}
|
||||
|
||||
static hLineTo = (v: number[]): string => {
|
||||
return `H ${v[0]},${v[1]} `
|
||||
}
|
||||
|
||||
static vLineTo = (v: number[]): string => {
|
||||
return `V ${v[0]},${v[1]} `
|
||||
}
|
||||
|
||||
static bezierTo = (A: number[], B: number[], C: number[]): string => {
|
||||
return `C ${A[0]},${A[1]} ${B[0]},${B[1]} ${C[0]},${C[1]} `
|
||||
}
|
||||
|
||||
static arcTo = (C: number[], r: number, A: number[], B: number[]): string => {
|
||||
return [
|
||||
Svg.moveTo(A),
|
||||
'A',
|
||||
r,
|
||||
r,
|
||||
0,
|
||||
0,
|
||||
Utils.getArcLength(C, r, A, B) > 0 ? '1' : '0',
|
||||
B[0],
|
||||
B[1],
|
||||
].join(' ')
|
||||
}
|
||||
|
||||
static closePath = (): string => {
|
||||
return 'Z'
|
||||
}
|
||||
|
||||
static rectTo = (A: number[]): string => {
|
||||
return ['R', A[0], A[1]].join(' ')
|
||||
}
|
||||
|
||||
static getPointAtLength = (path: SVGPathElement, length: number): number[] => {
|
||||
const point = path.getPointAtLength(length)
|
||||
return [point.x, point.y]
|
||||
}
|
||||
}
|
||||
|
||||
export default Svg
|
497
packages/core/src/utils/utils.d.ts
vendored
497
packages/core/src/utils/utils.d.ts
vendored
|
@ -1,497 +0,0 @@
|
|||
import type React from 'react';
|
||||
import { TLBezierCurveSegment, TLBounds, TLBoundsCorner, TLBoundsEdge } from '../types';
|
||||
import './polyfills';
|
||||
import type { TLBoundsWithCenter } from '+index';
|
||||
export declare class Utils {
|
||||
static filterObject<T extends object>(obj: T, fn: (entry: Entry<T>, i?: number, arr?: Entry<T>[]) => boolean): Partial<T>;
|
||||
static deepMerge: <T>(target: T, patch: any) => T;
|
||||
/**
|
||||
* Linear interpolation betwen two numbers.
|
||||
* @param y1
|
||||
* @param y2
|
||||
* @param mu
|
||||
*/
|
||||
static lerp(y1: number, y2: number, mu: number): number;
|
||||
/**
|
||||
* Linear interpolation between two colors.
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
*```ts
|
||||
* lerpColor("#000000", "#0099FF", .25)
|
||||
*```
|
||||
*/
|
||||
static lerpColor(color1: string, color2: string, factor?: number): string;
|
||||
/**
|
||||
* Modulate a value between two ranges.
|
||||
* @param value
|
||||
* @param rangeA from [low, high]
|
||||
* @param rangeB to [low, high]
|
||||
* @param clamp
|
||||
*/
|
||||
static modulate(value: number, rangeA: number[], rangeB: number[], clamp?: boolean): number;
|
||||
/**
|
||||
* Clamp a value into a range.
|
||||
* @param n
|
||||
* @param min
|
||||
*/
|
||||
static clamp(n: number, min: number): number;
|
||||
static clamp(n: number, min: number, max: number): number;
|
||||
static compress(s: string): string;
|
||||
static decompress(s: string): string;
|
||||
/**
|
||||
* Recursively clone an object or array.
|
||||
* @param obj
|
||||
*/
|
||||
static deepClone<T extends unknown>(obj: T): T;
|
||||
/**
|
||||
* Seeded random number generator, using [xorshift](https://en.wikipedia.org/wiki/Xorshift).
|
||||
* The result will always be betweeen -1 and 1.
|
||||
*
|
||||
* Adapted from [seedrandom](https://github.com/davidbau/seedrandom).
|
||||
*/
|
||||
static rng(seed?: string): () => number;
|
||||
static getRectangleSides(point: number[], size: number[], rotation?: number): [string, number[][]][];
|
||||
static getBoundsSides(bounds: TLBounds): [string, number[][]][];
|
||||
static shallowEqual<T extends Record<string, unknown>>(objA: T, objB: T): boolean;
|
||||
/**
|
||||
* Get the outer of between a circle and a point.
|
||||
* @param C The circle's center.
|
||||
* @param r The circle's radius.
|
||||
* @param P The point.
|
||||
* @param side
|
||||
*/
|
||||
static getCircleTangentToPoint(C: number[], r: number, P: number[], side: number): number[] | null;
|
||||
/**
|
||||
* Get outer tangents of two circles.
|
||||
* @param x0
|
||||
* @param y0
|
||||
* @param r0
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param r1
|
||||
* @returns [lx0, ly0, lx1, ly1, rx0, ry0, rx1, ry1]
|
||||
*/
|
||||
static getOuterTangentsOfCircles(C0: number[], r0: number, C1: number[], r1: number): number[][] | null;
|
||||
/**
|
||||
* Get the closest point on the perimeter of a circle to a given point.
|
||||
* @param C The circle's center.
|
||||
* @param r The circle's radius.
|
||||
* @param P The point.
|
||||
*/
|
||||
static getClosestPointOnCircle(C: number[], r: number, P: number[]): number[];
|
||||
/**
|
||||
* Get a circle from three points.
|
||||
* @param A
|
||||
* @param B
|
||||
* @param C
|
||||
* @returns [x, y, r]
|
||||
*/
|
||||
static circleFromThreePoints(A: number[], B: number[], C: number[]): number[];
|
||||
/**
|
||||
* Find the approximate perimeter of an ellipse.
|
||||
* @param rx
|
||||
* @param ry
|
||||
*/
|
||||
static perimeterOfEllipse(rx: number, ry: number): number;
|
||||
/**
|
||||
* Get the short angle distance between two angles.
|
||||
* @param a0
|
||||
* @param a1
|
||||
*/
|
||||
static shortAngleDist(a0: number, a1: number): number;
|
||||
/**
|
||||
* Get the long angle distance between two angles.
|
||||
* @param a0
|
||||
* @param a1
|
||||
*/
|
||||
static longAngleDist(a0: number, a1: number): number;
|
||||
/**
|
||||
* Interpolate an angle between two angles.
|
||||
* @param a0
|
||||
* @param a1
|
||||
* @param t
|
||||
*/
|
||||
static lerpAngles(a0: number, a1: number, t: number): number;
|
||||
/**
|
||||
* Get the short distance between two angles.
|
||||
* @param a0
|
||||
* @param a1
|
||||
*/
|
||||
static angleDelta(a0: number, a1: number): number;
|
||||
/**
|
||||
* Get the "sweep" or short distance between two points on a circle's perimeter.
|
||||
* @param C
|
||||
* @param A
|
||||
* @param B
|
||||
*/
|
||||
static getSweep(C: number[], A: number[], B: number[]): number;
|
||||
/**
|
||||
* Rotate a point around a center.
|
||||
* @param x The x-axis coordinate of the point.
|
||||
* @param y The y-axis coordinate of the point.
|
||||
* @param cx The x-axis coordinate of the point to rotate round.
|
||||
* @param cy The y-axis coordinate of the point to rotate round.
|
||||
* @param angle The distance (in radians) to rotate.
|
||||
*/
|
||||
static rotatePoint(A: number[], B: number[], angle: number): number[];
|
||||
/**
|
||||
* Clamp radians within 0 and 2PI
|
||||
* @param r
|
||||
*/
|
||||
static clampRadians(r: number): number;
|
||||
/**
|
||||
* Clamp rotation to even segments.
|
||||
* @param r
|
||||
* @param segments
|
||||
*/
|
||||
static snapAngleToSegments(r: number, segments: number): number;
|
||||
/**
|
||||
* Is angle c between angles a and b?
|
||||
* @param a
|
||||
* @param b
|
||||
* @param c
|
||||
*/
|
||||
static isAngleBetween(a: number, b: number, c: number): boolean;
|
||||
/**
|
||||
* Convert degrees to radians.
|
||||
* @param d
|
||||
*/
|
||||
static degreesToRadians(d: number): number;
|
||||
/**
|
||||
* Convert radians to degrees.
|
||||
* @param r
|
||||
*/
|
||||
static radiansToDegrees(r: number): number;
|
||||
/**
|
||||
* Get the length of an arc between two points on a circle's perimeter.
|
||||
* @param C
|
||||
* @param r
|
||||
* @param A
|
||||
* @param B
|
||||
*/
|
||||
static getArcLength(C: number[], r: number, A: number[], B: number[]): number;
|
||||
/**
|
||||
* Get a dash offset for an arc, based on its length.
|
||||
* @param C
|
||||
* @param r
|
||||
* @param A
|
||||
* @param B
|
||||
* @param step
|
||||
*/
|
||||
static getArcDashOffset(C: number[], r: number, A: number[], B: number[], step: number): number;
|
||||
/**
|
||||
* Get a dash offset for an ellipse, based on its length.
|
||||
* @param A
|
||||
* @param step
|
||||
*/
|
||||
static getEllipseDashOffset(A: number[], step: number): number;
|
||||
/**
|
||||
* Get bezier curve segments that pass through an array of points.
|
||||
* @param points
|
||||
* @param tension
|
||||
*/
|
||||
static getTLBezierCurveSegments(points: number[][], tension?: number): TLBezierCurveSegment[];
|
||||
/**
|
||||
* Find a point along a curve segment, via pomax.
|
||||
* @param t
|
||||
* @param points [cpx1, cpy1, cpx2, cpy2, px, py][]
|
||||
*/
|
||||
static computePointOnCurve(t: number, points: number[][]): number[];
|
||||
/**
|
||||
* Evaluate a 2d cubic bezier at a point t on the x axis.
|
||||
* @param tx
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param x2
|
||||
* @param y2
|
||||
*/
|
||||
static cubicBezier(tx: number, x1: number, y1: number, x2: number, y2: number): number;
|
||||
/**
|
||||
* Get a bezier curve data for a spline that fits an array of points.
|
||||
* @param points An array of points formatted as [x, y]
|
||||
* @param k Tension
|
||||
*/
|
||||
static getSpline(pts: number[][], k?: number): {
|
||||
cp1x: number;
|
||||
cp1y: number;
|
||||
cp2x: number;
|
||||
cp2y: number;
|
||||
px: number;
|
||||
py: number;
|
||||
}[];
|
||||
/**
|
||||
* Get a bezier curve data for a spline that fits an array of points.
|
||||
* @param pts
|
||||
* @param tension
|
||||
* @param isClosed
|
||||
* @param numOfSegments
|
||||
*/
|
||||
static getCurvePoints(pts: number[][], tension?: number, isClosed?: boolean, numOfSegments?: number): number[][];
|
||||
/**
|
||||
* Simplify a line (using Ramer-Douglas-Peucker algorithm).
|
||||
* @param points An array of points as [x, y, ...][]
|
||||
* @param tolerance The minimum line distance (also called epsilon).
|
||||
* @returns Simplified array as [x, y, ...][]
|
||||
*/
|
||||
static simplify(points: number[][], tolerance?: number): number[][];
|
||||
/**
|
||||
* Get whether a point is inside of a circle.
|
||||
* @param A
|
||||
* @param b
|
||||
* @returns
|
||||
*/
|
||||
static pointInCircle(A: number[], C: number[], r: number): boolean;
|
||||
/**
|
||||
* Get whether a point is inside of an ellipse.
|
||||
* @param point
|
||||
* @param center
|
||||
* @param rx
|
||||
* @param ry
|
||||
* @param rotation
|
||||
* @returns
|
||||
*/
|
||||
static pointInEllipse(A: number[], C: number[], rx: number, ry: number, rotation?: number): boolean;
|
||||
/**
|
||||
* Get whether a point is inside of a rectangle.
|
||||
* @param point
|
||||
* @param size
|
||||
*/
|
||||
static pointInRect(point: number[], size: number[]): boolean;
|
||||
static pointInPolygon(p: number[], points: number[][]): boolean;
|
||||
/**
|
||||
* Expand a bounding box by a delta.
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
*```ts
|
||||
* expandBounds(myBounds, [100, 100])
|
||||
*```
|
||||
*/
|
||||
static expandBounds(bounds: TLBounds, delta: number): TLBounds;
|
||||
/**
|
||||
* Get whether a point is inside of a bounds.
|
||||
* @param A
|
||||
* @param b
|
||||
* @returns
|
||||
*/
|
||||
static pointInBounds(A: number[], b: TLBounds): boolean;
|
||||
/**
|
||||
* Get whether two bounds collide.
|
||||
* @param a Bounds
|
||||
* @param b Bounds
|
||||
* @returns
|
||||
*/
|
||||
static boundsCollide(a: TLBounds, b: TLBounds): boolean;
|
||||
/**
|
||||
* Get whether the bounds of A contain the bounds of B. A perfect match will return true.
|
||||
* @param a Bounds
|
||||
* @param b Bounds
|
||||
* @returns
|
||||
*/
|
||||
static boundsContain(a: TLBounds, b: TLBounds): boolean;
|
||||
/**
|
||||
* Get whether the bounds of A are contained by the bounds of B.
|
||||
* @param a Bounds
|
||||
* @param b Bounds
|
||||
* @returns
|
||||
*/
|
||||
static boundsContained(a: TLBounds, b: TLBounds): boolean;
|
||||
/**
|
||||
* Get whether two bounds are identical.
|
||||
* @param a Bounds
|
||||
* @param b Bounds
|
||||
* @returns
|
||||
*/
|
||||
static boundsAreEqual(a: TLBounds, b: TLBounds): boolean;
|
||||
/**
|
||||
* Find a bounding box from an array of points.
|
||||
* @param points
|
||||
* @param rotation (optional) The bounding box's rotation.
|
||||
*/
|
||||
static getBoundsFromPoints(points: number[][], rotation?: number): TLBounds;
|
||||
/**
|
||||
* Center a bounding box around a given point.
|
||||
* @param bounds
|
||||
* @param center
|
||||
*/
|
||||
static centerBounds(bounds: TLBounds, point: number[]): TLBounds;
|
||||
/**
|
||||
* Move a bounding box without recalculating it.
|
||||
* @param bounds
|
||||
* @param delta
|
||||
* @returns
|
||||
*/
|
||||
static translateBounds(bounds: TLBounds, delta: number[]): TLBounds;
|
||||
/**
|
||||
* Rotate a bounding box.
|
||||
* @param bounds
|
||||
* @param center
|
||||
* @param rotation
|
||||
*/
|
||||
static rotateBounds(bounds: TLBounds, center: number[], rotation: number): TLBounds;
|
||||
/**
|
||||
* Get the rotated bounds of an ellipse.
|
||||
* @param x
|
||||
* @param y
|
||||
* @param rx
|
||||
* @param ry
|
||||
* @param rotation
|
||||
*/
|
||||
static getRotatedEllipseBounds(x: number, y: number, rx: number, ry: number, rotation?: number): TLBounds;
|
||||
/**
|
||||
* Get a bounding box that includes two bounding boxes.
|
||||
* @param a Bounding box
|
||||
* @param b Bounding box
|
||||
* @returns
|
||||
*/
|
||||
static getExpandedBounds(a: TLBounds, b: TLBounds): TLBounds;
|
||||
/**
|
||||
* Get the common bounds of a group of bounds.
|
||||
* @returns
|
||||
*/
|
||||
static getCommonBounds(bounds: TLBounds[]): TLBounds;
|
||||
static getRotatedCorners(b: TLBounds, rotation?: number): number[][];
|
||||
static getTransformedBoundingBox(bounds: TLBounds, handle: TLBoundsCorner | TLBoundsEdge | 'center', delta: number[], rotation?: number, isAspectRatioLocked?: boolean): TLBounds & {
|
||||
scaleX: number;
|
||||
scaleY: number;
|
||||
};
|
||||
static getTransformAnchor(type: TLBoundsEdge | TLBoundsCorner, isFlippedX: boolean, isFlippedY: boolean): TLBoundsCorner | TLBoundsEdge;
|
||||
/**
|
||||
* Get the relative bounds (usually a child) within a transformed bounding box.
|
||||
* @param bounds
|
||||
* @param initialBounds
|
||||
* @param initialShapeBounds
|
||||
* @param isFlippedX
|
||||
* @param isFlippedY
|
||||
*/
|
||||
static getRelativeTransformedBoundingBox(bounds: TLBounds, initialBounds: TLBounds, initialShapeBounds: TLBounds, isFlippedX: boolean, isFlippedY: boolean): TLBounds;
|
||||
/**
|
||||
* Get the size of a rotated box.
|
||||
* @param size : ;
|
||||
* @param rotation
|
||||
*/
|
||||
static getRotatedSize(size: number[], rotation: number): number[];
|
||||
/**
|
||||
* Get the center of a bounding box.
|
||||
* @param bounds
|
||||
*/
|
||||
static getBoundsCenter(bounds: TLBounds): number[];
|
||||
/**
|
||||
* Get a bounding box with a midX and midY.
|
||||
* @param bounds
|
||||
*/
|
||||
static getBoundsWithCenter(bounds: TLBounds): TLBounds & {
|
||||
midX: number;
|
||||
midY: number;
|
||||
};
|
||||
static getSnapPoints: (bounds: any, others: TLBoundsWithCenter[], snapDistance: number) => {
|
||||
offset: number[];
|
||||
snapLines: number[][][];
|
||||
};
|
||||
/**
|
||||
*
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
*```ts
|
||||
* example
|
||||
*```
|
||||
*/
|
||||
static removeDuplicatePoints(points: number[][]): number[][];
|
||||
/**
|
||||
// points =
|
||||
|
||||
|
||||
/**
|
||||
* Get a value from a cache (a WeakMap), filling the value if it is not present.
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
*```ts
|
||||
* getFromCache(boundsCache, shape, (cache) => cache.set(shape, "value"))
|
||||
*```
|
||||
*/
|
||||
static getFromCache<V, I extends object>(cache: WeakMap<I, V>, item: I, getNext: () => V): V;
|
||||
/**
|
||||
* Get a unique string id.
|
||||
*/
|
||||
static uniqueId(a?: string): string;
|
||||
/**
|
||||
* Shuffle the contents of an array.
|
||||
* @param arr
|
||||
* @param offset
|
||||
*/
|
||||
static rotateArray<T>(arr: T[], offset: number): T[];
|
||||
/**
|
||||
* Deep compare two arrays.
|
||||
* @param a
|
||||
* @param b
|
||||
*/
|
||||
static deepCompareArrays<T>(a: T[], b: T[]): boolean;
|
||||
/**
|
||||
* Deep compare any values.
|
||||
* @param a
|
||||
* @param b
|
||||
*/
|
||||
static deepCompare<T>(a: T, b: T): boolean;
|
||||
/**
|
||||
* Find whether two arrays intersect.
|
||||
* @param a
|
||||
* @param b
|
||||
* @param fn An optional function to apply to the items of a; will check if b includes the result.
|
||||
*/
|
||||
static arrsIntersect<T, K>(a: T[], b: K[], fn?: (item: K) => T): boolean;
|
||||
static arrsIntersect<T>(a: T[], b: T[]): boolean;
|
||||
/**
|
||||
* Get the unique values from an array of strings or numbers.
|
||||
* @param items
|
||||
*/
|
||||
static uniqueArray<T extends string | number>(...items: T[]): T[];
|
||||
/**
|
||||
* Convert a set to an array.
|
||||
* @param set
|
||||
*/
|
||||
static setToArray<T>(set: Set<T>): T[];
|
||||
/**
|
||||
* Debounce a function.
|
||||
*/
|
||||
static debounce<T extends (...args: any[]) => void>(fn: T, ms?: number): (...args: Parameters<T>) => void;
|
||||
static TRIM_NUMBERS: RegExp;
|
||||
/**
|
||||
* Turn an array of points into a path of quadradic curves.
|
||||
* @param stroke ;
|
||||
*/
|
||||
static getSvgPathFromStroke(points: number[][], closed?: boolean): string;
|
||||
/**
|
||||
* Get balanced dash-strokearray and dash-strokeoffset properties for a path of a given length.
|
||||
* @param length The length of the path.
|
||||
* @param strokeWidth The shape's stroke-width property.
|
||||
* @param style The stroke's style: "dashed" or "dotted" (default "dashed").
|
||||
* @param snap An interval for dashes (e.g. 4 will produce arrays with 4, 8, 16, etc dashes).
|
||||
*/
|
||||
static getPerfectDashProps(length: number, strokeWidth: number, style: 'dashed' | 'dotted' | string, snap?: number, outset?: boolean): {
|
||||
strokeDasharray: string;
|
||||
strokeDashoffset: string;
|
||||
};
|
||||
static isMobileSize(): boolean;
|
||||
static isMobileSafari(): boolean;
|
||||
static throttle<T extends (...args: any) => any>(func: T, limit: number): (...args: Parameters<T>) => ReturnType<T>;
|
||||
/**
|
||||
* Find whether the current display is a touch display.
|
||||
*/
|
||||
/**
|
||||
* Find whether the current device is a Mac / iOS / iPadOS.
|
||||
*/
|
||||
static isDarwin(): boolean;
|
||||
/**
|
||||
* Get whether an event is command (mac) or control (pc).
|
||||
* @param e
|
||||
*/
|
||||
static metaKey(e: KeyboardEvent | React.KeyboardEvent): boolean;
|
||||
}
|
||||
export default Utils;
|
||||
declare type Entry<T> = {
|
||||
[K in keyof T]: [K, T[K]];
|
||||
}[keyof T];
|
||||
//# sourceMappingURL=utils.d.ts.map
|
File diff suppressed because one or more lines are too long
|
@ -40,4 +40,4 @@
|
|||
"typescript": "4.2.3"
|
||||
},
|
||||
"gitHead": "a7dac0f83ad998e205c2aab58182cb4ba4e099a6"
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
"name": "@tldraw/intersect",
|
||||
"version": "0.0.126",
|
||||
"private": false,
|
||||
"description": "A tiny little drawing app (intersect)",
|
||||
"description": "Intersection utilities for tldraw.",
|
||||
"author": "@steveruizok",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -21,7 +21,7 @@
|
|||
"typings": "./dist/types/index.d.ts",
|
||||
"scripts": {
|
||||
"start:pre": "node scripts/pre-dev && yarn types:pre",
|
||||
"start": "node scripts/dev & yarn types:dev",
|
||||
"start:utils": "node scripts/dev & yarn types:dev",
|
||||
"build": "node scripts/build && yarn types:build",
|
||||
"types:pre": "tsc",
|
||||
"types:dev": "tsc --watch",
|
||||
|
@ -33,8 +33,6 @@
|
|||
"docs:watch": "typedoc --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.15.5",
|
||||
"@babel/preset-env": "^7.15.4",
|
||||
"@types/jest": "^27.0.1",
|
||||
"@types/node": "^16.7.10",
|
||||
"@typescript-eslint/eslint-plugin": "^4.30.0",
|
||||
|
@ -42,7 +40,6 @@
|
|||
"esbuild": "^0.13.8",
|
||||
"eslint": "^7.32.0",
|
||||
"lerna": "^4.0.0",
|
||||
"ts-node": "^10.2.1",
|
||||
"tslib": "^2.3.1",
|
||||
"typedoc": "^0.22.3",
|
||||
"typescript": "^4.4.2"
|
||||
|
@ -51,4 +48,4 @@
|
|||
"@tldraw/vec": "^0.0.126"
|
||||
},
|
||||
"gitHead": "5cb031ddc264846ec6732d7179511cddea8ef034"
|
||||
}
|
||||
}
|
21
packages/svg/LICENSE
Normal file
21
packages/svg/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Stephen Ruiz Ltd
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
3
packages/svg/README.md
Normal file
3
packages/svg/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# @tldraw/svg
|
||||
|
||||
SVG utilities.
|
48
packages/svg/package.json
Normal file
48
packages/svg/package.json
Normal file
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
"name": "@tldraw/svg",
|
||||
"version": "0.0.126",
|
||||
"private": false,
|
||||
"description": "SVG utilities for tldraw.",
|
||||
"author": "@steveruizok",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/tldraw/tldraw.git",
|
||||
"directory": "packages/vec"
|
||||
},
|
||||
"license": "MIT",
|
||||
"keywords": [],
|
||||
"files": [
|
||||
"dist/**/*"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"main": "./dist/cjs/index.js",
|
||||
"module": "./dist/esm/index.js",
|
||||
"types": "./dist/types/index.d.ts",
|
||||
"typings": "./dist/types/index.d.ts",
|
||||
"scripts": {
|
||||
"start:pre": "node scripts/pre-dev && yarn types:pre",
|
||||
"start:utils": "node scripts/dev & yarn types:dev",
|
||||
"build": "node scripts/build && yarn types:build",
|
||||
"types:pre": "tsc",
|
||||
"types:dev": "tsc --watch",
|
||||
"types:build": "tsc --project tsconfig.build.json",
|
||||
"lint": "eslint src/ --ext .ts,.tsx",
|
||||
"clean": "rm -rf dist",
|
||||
"ts-node": "ts-node",
|
||||
"docs": "typedoc",
|
||||
"docs:watch": "typedoc --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.0.1",
|
||||
"@types/node": "^16.7.10",
|
||||
"@typescript-eslint/eslint-plugin": "^4.30.0",
|
||||
"@typescript-eslint/parser": "^4.30.0",
|
||||
"esbuild": "^0.13.8",
|
||||
"eslint": "^7.32.0",
|
||||
"lerna": "^4.0.0",
|
||||
"tslib": "^2.3.1",
|
||||
"typedoc": "^0.22.3",
|
||||
"typescript": "^4.4.2"
|
||||
},
|
||||
"gitHead": "5cb031ddc264846ec6732d7179511cddea8ef034"
|
||||
}
|
65
packages/svg/scripts/build.js
Normal file
65
packages/svg/scripts/build.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* eslint-disable */
|
||||
const fs = require('fs')
|
||||
const esbuild = require('esbuild')
|
||||
const { gzip } = require('zlib')
|
||||
|
||||
const name = process.env.npm_package_name || ''
|
||||
|
||||
async function main() {
|
||||
if (fs.existsSync('./dist')) {
|
||||
fs.rmSync('./dist', { recursive: true }, (e) => {
|
||||
if (e) {
|
||||
throw e
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
esbuild.buildSync({
|
||||
entryPoints: ['./src/index.ts'],
|
||||
outdir: 'dist/cjs',
|
||||
minify: true,
|
||||
bundle: true,
|
||||
format: 'cjs',
|
||||
target: 'es6',
|
||||
jsxFactory: 'React.createElement',
|
||||
jsxFragment: 'React.Fragment',
|
||||
tsconfig: './tsconfig.build.json',
|
||||
external: ['react', 'react-dom'],
|
||||
})
|
||||
|
||||
const esmResult = esbuild.buildSync({
|
||||
entryPoints: ['./src/index.ts'],
|
||||
outdir: 'dist/esm',
|
||||
minify: true,
|
||||
bundle: true,
|
||||
format: 'esm',
|
||||
target: 'es6',
|
||||
tsconfig: './tsconfig.build.json',
|
||||
jsxFactory: 'React.createElement',
|
||||
jsxFragment: 'React.Fragment',
|
||||
external: ['react', 'react-dom'],
|
||||
metafile: true,
|
||||
})
|
||||
|
||||
let esmSize = 0
|
||||
Object.values(esmResult.metafile.outputs).forEach((output) => {
|
||||
esmSize += output.bytes
|
||||
})
|
||||
|
||||
fs.readFile('./dist/esm/index.js', (_err, data) => {
|
||||
gzip(data, (_err, result) => {
|
||||
console.log(
|
||||
`✔ ${name}: Built package. ${(esmSize / 1000).toFixed(2)}kb (${(
|
||||
result.length / 1000
|
||||
).toFixed(2)}kb minified)`
|
||||
)
|
||||
})
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(`× ${name}: Build failed due to an error.`)
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
31
packages/svg/scripts/dev.js
Normal file
31
packages/svg/scripts/dev.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
/* eslint-disable */
|
||||
const esbuild = require('esbuild')
|
||||
|
||||
const name = process.env.npm_package_name || ''
|
||||
|
||||
async function main() {
|
||||
esbuild.build({
|
||||
entryPoints: ['./src/index.ts'],
|
||||
outdir: 'dist/cjs',
|
||||
minify: false,
|
||||
bundle: true,
|
||||
format: 'cjs',
|
||||
target: 'es6',
|
||||
jsxFactory: 'React.createElement',
|
||||
jsxFragment: 'React.Fragment',
|
||||
tsconfig: './tsconfig.json',
|
||||
external: ['react', 'react-dom'],
|
||||
incremental: true,
|
||||
watch: {
|
||||
onRebuild(error) {
|
||||
if (error) {
|
||||
console.log(`× ${name}: An error in prevented the rebuild.`)
|
||||
return
|
||||
}
|
||||
console.log(`✔ ${name}: Rebuilt.`)
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
main()
|
28
packages/svg/scripts/pre-dev.js
Normal file
28
packages/svg/scripts/pre-dev.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* eslint-disable */
|
||||
const fs = require('fs')
|
||||
const esbuild = require('esbuild')
|
||||
|
||||
async function main() {
|
||||
if (fs.existsSync('./dist')) {
|
||||
fs.rmSync('./dist', { recursive: true }, (e) => {
|
||||
if (e) {
|
||||
throw e
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
esbuild.build({
|
||||
entryPoints: ['./src/index.ts'],
|
||||
outdir: 'dist/cjs',
|
||||
minify: false,
|
||||
bundle: true,
|
||||
format: 'cjs',
|
||||
target: 'es6',
|
||||
jsxFactory: 'React.createElement',
|
||||
jsxFragment: 'React.Fragment',
|
||||
tsconfig: './tsconfig.json',
|
||||
external: ['react', 'react-dom'],
|
||||
})
|
||||
}
|
||||
|
||||
main()
|
63
packages/svg/src/index.ts
Normal file
63
packages/svg/src/index.ts
Normal file
|
@ -0,0 +1,63 @@
|
|||
// General
|
||||
function angle(A: number[], B: number[]): number {
|
||||
return Math.atan2(B[1] - A[1], B[0] - A[0])
|
||||
}
|
||||
|
||||
function shortAngleDist(A: number, B: number) {
|
||||
const max = Math.PI * 2
|
||||
const da = (B - A) % max
|
||||
return ((2 * da) % max) - da
|
||||
}
|
||||
|
||||
function getArcLength(C: number[], r: number, A: number[], B: number[]): number {
|
||||
return r * (2 * Math.PI) * (shortAngleDist(angle(C, A), angle(C, B)) / (2 * Math.PI))
|
||||
}
|
||||
|
||||
export const moveTo = (v: number[]): string => {
|
||||
return `M ${v} `
|
||||
}
|
||||
|
||||
export const lineTo = (...v: number[][]): string => {
|
||||
return `L ${v.join(' ')} `
|
||||
}
|
||||
|
||||
export const hLineTo = (v: number[]): string => {
|
||||
return `H ${v} `
|
||||
}
|
||||
|
||||
export const vLineTo = (v: number[]): string => {
|
||||
return `V ${v} `
|
||||
}
|
||||
|
||||
export const bezierTo = (A: number[], B: number[], C: number[]): string => {
|
||||
return `C ${A} ${B} ${C} `
|
||||
}
|
||||
|
||||
export const arcTo = (C: number[], r: number, A: number[], B: number[]): string => {
|
||||
return [moveTo(A), 'A', r, r, 0, 0, getArcLength(C, r, A, B) > 0 ? '1' : '0', B[0], B[1]].join(
|
||||
' '
|
||||
)
|
||||
}
|
||||
|
||||
export const rectTo = (A: number[]): string => {
|
||||
return `R ${A}`
|
||||
}
|
||||
|
||||
export const ellipse = (A: number[], r: number): string => {
|
||||
return `M ${A[0] - r},${A[1]}
|
||||
a ${r},${r} 0 1,0 ${r * 2},0
|
||||
a ${r},${r} 0 1,0 -${r * 2},0 `
|
||||
}
|
||||
|
||||
export const line = (a: number[], ...pts: number[][]): string => {
|
||||
return moveTo(a) + lineTo(...pts)
|
||||
}
|
||||
|
||||
export const closePath = (): string => {
|
||||
return 'Z'
|
||||
}
|
||||
|
||||
export const getPointAtLength = (path: SVGPathElement, length: number): number[] => {
|
||||
const point = path.getPointAtLength(length)
|
||||
return [point.x, point.y]
|
||||
}
|
24
packages/svg/tsconfig.build.json
Normal file
24
packages/svg/tsconfig.build.json
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"**/*.test.tsx",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.spec.ts",
|
||||
"src/test",
|
||||
"dist",
|
||||
"docs"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"composite": false,
|
||||
"incremental": false,
|
||||
"declarationMap": false,
|
||||
"sourceMap": false,
|
||||
"emitDeclarationOnly": true,
|
||||
"paths": {
|
||||
"@tldraw/vec": ["../vec"]
|
||||
}
|
||||
},
|
||||
"references": [{ "path": "../vec" }]
|
||||
}
|
18
packages/svg/tsconfig.json
Normal file
18
packages/svg/tsconfig.json
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist", "docs"],
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/types",
|
||||
"rootDir": "src",
|
||||
"baseUrl": "src",
|
||||
"paths": {
|
||||
"@tldraw/vec": ["../vec"]
|
||||
}
|
||||
},
|
||||
"references": [{ "path": "../vec" }],
|
||||
"typedocOptions": {
|
||||
"entryPoints": ["src/index.ts"],
|
||||
"out": "docs"
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
"name": "@tldraw/vec",
|
||||
"version": "0.0.126",
|
||||
"private": false,
|
||||
"description": "A tiny little drawing app (vec)",
|
||||
"description": "Vector utilities for tldraw.",
|
||||
"author": "@steveruizok",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -21,7 +21,7 @@
|
|||
"typings": "./dist/types/index.d.ts",
|
||||
"scripts": {
|
||||
"start:pre": "node scripts/pre-dev && yarn types:pre",
|
||||
"start": "node scripts/dev & yarn types:dev",
|
||||
"start:utils": "node scripts/dev & yarn types:dev",
|
||||
"build": "node scripts/build && yarn types:build",
|
||||
"types:pre": "tsc",
|
||||
"types:dev": "tsc --watch",
|
||||
|
@ -33,8 +33,6 @@
|
|||
"docs:watch": "typedoc --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.15.5",
|
||||
"@babel/preset-env": "^7.15.4",
|
||||
"@types/jest": "^27.0.1",
|
||||
"@types/node": "^16.7.10",
|
||||
"@typescript-eslint/eslint-plugin": "^4.30.0",
|
||||
|
@ -42,10 +40,9 @@
|
|||
"esbuild": "^0.13.8",
|
||||
"eslint": "^7.32.0",
|
||||
"lerna": "^4.0.0",
|
||||
"ts-node": "^10.2.1",
|
||||
"tslib": "^2.3.1",
|
||||
"typedoc": "^0.22.3",
|
||||
"typescript": "^4.4.2"
|
||||
},
|
||||
"gitHead": "5cb031ddc264846ec6732d7179511cddea8ef034"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue