@tldraw/editor 3.15.0-next.f1dfcef63951 → 3.16.0-next.c30b1b5e551a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +159 -44
- package/dist-cjs/index.js +20 -16
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/components/SVGContainer.js +1 -1
- package/dist-cjs/lib/components/SVGContainer.js.map +2 -2
- package/dist-cjs/lib/components/Shape.js +4 -26
- package/dist-cjs/lib/components/Shape.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultBrush.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultBrush.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCursor.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCursor.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultGrid.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultGrid.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultHandles.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultHandles.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js +53 -0
- package/dist-cjs/lib/components/default-components/DefaultShapeWrapper.js.map +7 -0
- package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultSpinner.js +27 -15
- package/dist-cjs/lib/components/default-components/DefaultSpinner.js.map +3 -3
- package/dist-cjs/lib/config/TLUserPreferences.js +7 -1
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +88 -43
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +96 -101
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +7 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +20 -1
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/editor/types/misc-types.js.map +1 -1
- package/dist-cjs/lib/hooks/useEditorComponents.js +2 -0
- package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
- package/dist-cjs/lib/license/Watermark.js +2 -2
- package/dist-cjs/lib/license/Watermark.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Arc2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +3 -1
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/geometry-constants.js +2 -2
- package/dist-cjs/lib/primitives/geometry/geometry-constants.js.map +2 -2
- package/dist-cjs/lib/primitives/intersect.js +4 -4
- package/dist-cjs/lib/primitives/intersect.js.map +2 -2
- package/dist-cjs/lib/primitives/utils.js +4 -0
- package/dist-cjs/lib/primitives/utils.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +0 -1
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +159 -44
- package/dist-esm/index.mjs +47 -41
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/components/SVGContainer.mjs +1 -1
- package/dist-esm/lib/components/SVGContainer.mjs.map +2 -2
- package/dist-esm/lib/components/Shape.mjs +4 -26
- package/dist-esm/lib/components/Shape.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultBrush.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultBrush.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCursor.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCursor.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultGrid.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultGrid.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultHandles.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultHandles.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs +23 -0
- package/dist-esm/lib/components/default-components/DefaultShapeWrapper.mjs.map +7 -0
- package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultSpinner.mjs +17 -15
- package/dist-esm/lib/components/default-components/DefaultSpinner.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +7 -1
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +88 -43
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +96 -101
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +7 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +20 -1
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEditorComponents.mjs +4 -0
- package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
- package/dist-esm/lib/license/Watermark.mjs +2 -2
- package/dist-esm/lib/license/Watermark.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +3 -1
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/geometry-constants.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/geometry-constants.mjs.map +2 -2
- package/dist-esm/lib/primitives/intersect.mjs +5 -5
- package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
- package/dist-esm/lib/primitives/utils.mjs +4 -0
- package/dist-esm/lib/primitives/utils.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +0 -1
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +21 -27
- package/package.json +9 -8
- package/src/index.ts +68 -62
- package/src/lib/components/SVGContainer.tsx +1 -1
- package/src/lib/components/Shape.tsx +6 -21
- package/src/lib/components/default-components/DefaultBrush.tsx +1 -1
- package/src/lib/components/default-components/DefaultCanvas.tsx +1 -1
- package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
- package/src/lib/components/default-components/DefaultCursor.tsx +1 -1
- package/src/lib/components/default-components/DefaultGrid.tsx +1 -1
- package/src/lib/components/default-components/DefaultHandles.tsx +5 -1
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +1 -1
- package/src/lib/components/default-components/DefaultShapeWrapper.tsx +35 -0
- package/src/lib/components/default-components/DefaultSnapIndictor.tsx +1 -1
- package/src/lib/components/default-components/DefaultSpinner.tsx +12 -12
- package/src/lib/config/TLUserPreferences.ts +7 -0
- package/src/lib/editor/Editor.test.ts +407 -0
- package/src/lib/editor/Editor.ts +106 -44
- package/src/lib/editor/managers/TextManager/TextManager.ts +108 -128
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +21 -0
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +8 -0
- package/src/lib/editor/shapes/ShapeUtil.ts +57 -0
- package/src/lib/editor/tools/StateNode.test.ts +285 -0
- package/src/lib/editor/tools/StateNode.ts +27 -1
- package/src/lib/editor/types/misc-types.ts +19 -0
- package/src/lib/hooks/useEditorComponents.tsx +8 -2
- package/src/lib/license/LicenseManager.test.ts +1 -1
- package/src/lib/license/Watermark.tsx +2 -2
- package/src/lib/primitives/geometry/Arc2d.ts +2 -2
- package/src/lib/primitives/geometry/Circle2d.ts +2 -2
- package/src/lib/primitives/geometry/CubicBezier2d.ts +4 -1
- package/src/lib/primitives/geometry/Ellipse2d.ts +2 -2
- package/src/lib/primitives/geometry/geometry-constants.ts +2 -1
- package/src/lib/primitives/intersect.test.ts +946 -0
- package/src/lib/primitives/intersect.ts +12 -5
- package/src/lib/primitives/utils.ts +11 -0
- package/src/lib/utils/sync/TLLocalSyncClient.ts +0 -1
- package/src/version.ts +3 -3
- package/src/lib/test/currentToolIdMask.test.ts +0 -49
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/primitives/utils.ts"],
|
|
4
|
-
"sourcesContent": ["import { Vec, VecLike } from './Vec'\n\n/** @public */\nexport function precise(A: VecLike) {\n\treturn `${toDomPrecision(A.x)},${toDomPrecision(A.y)} `\n}\n\n/** @public */\nexport function average(A: VecLike, B: VecLike) {\n\treturn `${toDomPrecision((A.x + B.x) / 2)},${toDomPrecision((A.y + B.y) / 2)} `\n}\n\n/** @public */\nexport const PI = Math.PI\n/** @public */\nexport const HALF_PI = PI / 2\n/** @public */\nexport const PI2 = PI * 2\n/** @public */\nexport const SIN = Math.sin\n\n/**\n * Clamp a value into a range.\n *\n * @example\n *\n * ```ts\n * const A = clamp(0, 1) // 1\n * ```\n *\n * @param n - The number to clamp.\n * @param min - The minimum value.\n * @public\n */\nexport function clamp(n: number, min: number): number\n/**\n * Clamp a value into a range.\n *\n * @example\n *\n * ```ts\n * const A = clamp(0, 1, 10) // 1\n * const B = clamp(11, 1, 10) // 10\n * const C = clamp(5, 1, 10) // 5\n * ```\n *\n * @param n - The number to clamp.\n * @param min - The minimum value.\n * @param max - The maximum value.\n * @public\n */\nexport function clamp(n: number, min: number, max: number): number\nexport function clamp(n: number, min: number, max?: number): number {\n\treturn Math.max(min, typeof max !== 'undefined' ? Math.min(n, max) : n)\n}\n\n/**\n * Get a number to a precision.\n *\n * @param n - The number.\n * @param precision - The precision.\n * @public\n */\nexport function toPrecision(n: number, precision = 10000000000) {\n\tif (!n) return 0\n\treturn Math.round(n * precision) / precision\n}\n\n/**\n * Whether two numbers numbers a and b are approximately equal.\n *\n * @param a - The first point.\n * @param b - The second point.\n * @public\n */\nexport function approximately(a: number, b: number, precision = 0.000001) {\n\treturn Math.abs(a - b) <= precision\n}\n\n/**\n * Find the approximate perimeter of an ellipse.\n *\n * @param rx - The ellipse's x radius.\n * @param ry - The ellipse's y radius.\n * @public\n */\nexport function perimeterOfEllipse(rx: number, ry: number): number {\n\tconst h = Math.pow(rx - ry, 2) / Math.pow(rx + ry, 2)\n\treturn PI * (rx + ry) * (1 + (3 * h) / (10 + Math.sqrt(4 - 3 * h)))\n}\n\n/**\n * @param a - Any angle in radians\n * @returns A number between 0 and 2 * PI\n * @public\n */\nexport function canonicalizeRotation(a: number) {\n\ta = a % PI2\n\tif (a < 0) {\n\t\ta = a + PI2\n\t} else if (a === 0) {\n\t\t// prevent negative zero\n\t\ta = 0\n\t}\n\treturn a\n}\n\n/**\n * Get the clockwise angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function clockwiseAngleDist(a0: number, a1: number): number {\n\ta0 = canonicalizeRotation(a0)\n\ta1 = canonicalizeRotation(a1)\n\tif (a0 > a1) {\n\t\ta1 += PI2\n\t}\n\treturn a1 - a0\n}\n\n/**\n * Get the counter-clockwise angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function counterClockwiseAngleDist(a0: number, a1: number): number {\n\treturn PI2 - clockwiseAngleDist(a0, a1)\n}\n\n/**\n * Get the short angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function shortAngleDist(a0: number, a1: number): number {\n\tconst da = (a1 - a0) % PI2\n\treturn ((2 * da) % PI2) - da\n}\n\n/**\n * Clamp radians within 0 and 2PI\n *\n * @param r - The radian value.\n * @public\n */\nexport function clampRadians(r: number): number {\n\treturn (PI2 + r) % PI2\n}\n\n/**\n * Clamp rotation to even segments.\n *\n * @param r - The rotation in radians.\n * @param segments - The number of segments.\n * @public\n */\nexport function snapAngle(r: number, segments: number): number {\n\tconst seg = PI2 / segments\n\tlet ang = (Math.floor((clampRadians(r) + seg / 2) / seg) * seg) % PI2\n\tif (ang < PI) ang += PI2\n\tif (ang > PI) ang -= PI2\n\treturn ang\n}\n\n/**\n * Checks whether two angles are approximately at right-angles or parallel to each other\n *\n * @param a - Angle a (radians)\n * @param b - Angle b (radians)\n * @returns True iff the angles are approximately at right-angles or parallel to each other\n * @public\n */\nexport function areAnglesCompatible(a: number, b: number) {\n\treturn a === b || approximately((a % (Math.PI / 2)) - (b % (Math.PI / 2)), 0)\n}\n\n/**\n * Convert degrees to radians.\n *\n * @param d - The degree in degrees.\n * @public\n */\nexport function degreesToRadians(d: number): number {\n\treturn (d * PI) / 180\n}\n\n/**\n * Convert radians to degrees.\n *\n * @param r - The degree in radians.\n * @public\n */\nexport function radiansToDegrees(r: number): number {\n\treturn (r * 180) / PI\n}\n\n/**\n * Get a point on the perimeter of a circle.\n *\n * @param center - The center of the circle.\n * @param r - The radius of the circle.\n * @param a - The angle in radians.\n * @public\n */\nexport function getPointOnCircle(center: VecLike, r: number, a: number) {\n\treturn new Vec(center.x, center.y).add(Vec.FromAngle(a, r))\n}\n\n/** @public */\nexport function getPolygonVertices(width: number, height: number, sides: number) {\n\tconst cx = width / 2\n\tconst cy = height / 2\n\tconst pointsOnPerimeter: Vec[] = []\n\n\tlet minX = Infinity\n\tlet maxX = -Infinity\n\tlet minY = Infinity\n\tlet maxY = -Infinity\n\tfor (let i = 0; i < sides; i++) {\n\t\tconst step = PI2 / sides\n\t\tconst t = -HALF_PI + i * step\n\t\tconst x = cx + cx * Math.cos(t)\n\t\tconst y = cy + cy * Math.sin(t)\n\t\tif (x < minX) minX = x\n\t\tif (y < minY) minY = y\n\t\tif (x > maxX) maxX = x\n\t\tif (y > maxY) maxY = y\n\t\tpointsOnPerimeter.push(new Vec(x, y))\n\t}\n\n\t// Bounds of calculated points\n\tconst w = maxX - minX\n\tconst h = maxY - minY\n\n\t// Difference between input bounds and calculated bounds\n\tconst dx = width - w\n\tconst dy = height - h\n\n\t// If there's a difference, scale the points to the input bounds\n\tif (dx !== 0 || dy !== 0) {\n\t\tfor (let i = 0; i < pointsOnPerimeter.length; i++) {\n\t\t\tconst pt = pointsOnPerimeter[i]\n\t\t\tpt.x = ((pt.x - minX) / w) * width\n\t\t\tpt.y = ((pt.y - minY) / h) * height\n\t\t}\n\t}\n\n\treturn pointsOnPerimeter\n}\n\n/**\n * @param a0 - The start point in the A range\n * @param a1 - The end point in the A range\n * @param b0 - The start point in the B range\n * @param b1 - The end point in the B range\n * @returns True if the ranges overlap\n * @public\n */\nexport function rangesOverlap(a0: number, a1: number, b0: number, b1: number): boolean {\n\treturn a0 < b1 && b0 < a1\n}\n\n/**\n * Finds the intersection of two ranges.\n *\n * @param a0 - The start point in the A range\n * @param a1 - The end point in the A range\n * @param b0 - The start point in the B range\n * @param b1 - The end point in the B range\n * @returns The intersection of the ranges, or null if no intersection\n * @public\n */\nexport function rangeIntersection(\n\ta0: number,\n\ta1: number,\n\tb0: number,\n\tb1: number\n): [number, number] | null {\n\tconst min = Math.max(a0, b0)\n\tconst max = Math.min(a1, b1)\n\tif (min <= max) {\n\t\treturn [min, max]\n\t}\n\treturn null\n}\n\n/** Helper for point in polygon */\nfunction cross(x: VecLike, y: VecLike, z: VecLike): number {\n\treturn (y.x - x.x) * (z.y - x.y) - (z.x - x.x) * (y.y - x.y)\n}\n\n/**\n * Get whether a point is inside of a polygon.\n *\n * ```ts\n * const result = pointInPolygon(myPoint, myPoints)\n * ```\n *\n * @public\n */\nexport function pointInPolygon(A: VecLike, points: VecLike[]): boolean {\n\tlet windingNumber = 0\n\tlet a: VecLike\n\tlet b: VecLike\n\n\tfor (let i = 0; i < points.length; i++) {\n\t\ta = points[i]\n\t\t// Point is the same as one of the corners of the polygon\n\t\tif (a.x === A.x && a.y === A.y) return true\n\n\t\tb = points[(i + 1) % points.length]\n\n\t\t// Point is on the polygon edge\n\t\tif (Vec.Dist(A, a) + Vec.Dist(A, b) === Vec.Dist(a, b)) return true\n\n\t\tif (a.y <= A.y) {\n\t\t\tif (b.y > A.y && cross(a, b, A) > 0) {\n\t\t\t\twindingNumber += 1\n\t\t\t}\n\t\t} else if (b.y <= A.y && cross(a, b, A) < 0) {\n\t\t\twindingNumber -= 1\n\t\t}\n\t}\n\n\treturn windingNumber !== 0\n}\n\n/**\n * The DOM likes values to be fixed to 3 decimal places\n *\n * @public\n */\nexport function toDomPrecision(v: number) {\n\treturn Math.round(v * 1e4) / 1e4\n}\n\n/**\n * @public\n */\nexport function toFixed(v: number) {\n\treturn Math.round(v * 1e2) / 1e2\n}\n\n/**\n * Check if a float is safe to use. ie: Not too big or small.\n * @public\n */\nexport const isSafeFloat = (n: number) => {\n\treturn Math.abs(n) < Number.MAX_SAFE_INTEGER\n}\n\n/**\n * Get the angle of a point on an arc.\n * @param fromAngle - The angle from center to arc's start point (A) on the circle\n * @param toAngle - The angle from center to arc's end point (B) on the circle\n * @param direction - The direction of the arc (1 = counter-clockwise, -1 = clockwise)\n * @returns The distance in radians between the two angles according to the direction\n * @public\n */\nexport function angleDistance(fromAngle: number, toAngle: number, direction: number) {\n\tconst dist =\n\t\tdirection < 0\n\t\t\t? clockwiseAngleDist(fromAngle, toAngle)\n\t\t\t: counterClockwiseAngleDist(fromAngle, toAngle)\n\treturn dist\n}\n\n/**\n * Returns the t value of the point on the arc.\n *\n * @param mAB - The measure of the arc from A to B, negative if counter-clockwise\n * @param A - The angle from center to arc's start point (A) on the circle\n * @param B - The angle from center to arc's end point (B) on the circle\n * @param P - The angle on the circle (P) to find the t value for\n *\n * @returns The t value of the point on the arc, with 0 being the start and 1 being the end\n *\n * @public\n */\nexport function getPointInArcT(mAB: number, A: number, B: number, P: number): number {\n\tlet mAP: number\n\tif (Math.abs(mAB) > PI) {\n\t\tmAP = shortAngleDist(A, P)\n\t\tconst mPB = shortAngleDist(P, B)\n\t\tif (Math.abs(mAP) < Math.abs(mPB)) {\n\t\t\treturn mAP / mAB\n\t\t} else {\n\t\t\treturn (mAB - mPB) / mAB\n\t\t}\n\t} else {\n\t\tmAP = shortAngleDist(A, P)\n\t\tconst t = mAP / mAB\n\n\t\t// If the arc is something like -2.8 to 2.2, then we'll get a weird bug\n\t\t// where the measurement to the center is negative but measure to points\n\t\t// near the end are positive\n\t\tif (Math.sign(mAP) !== Math.sign(mAB)) {\n\t\t\treturn Math.abs(t) > 0.5 ? 1 : 0\n\t\t}\n\n\t\treturn t\n\t}\n}\n\n/**\n * Get the measure of an arc.\n *\n * @param A - The angle from center to arc's start point (A) on the circle\n * @param B - The angle from center to arc's end point (B) on the circle\n * @param sweepFlag - 1 if the arc is clockwise, 0 if counter-clockwise\n * @param largeArcFlag - 1 if the arc is greater than 180 degrees, 0 if less than 180 degrees\n *\n * @returns The measure of the arc, negative if counter-clockwise\n *\n * @public\n */\nexport function getArcMeasure(A: number, B: number, sweepFlag: number, largeArcFlag: number) {\n\tconst m = ((2 * ((B - A) % PI2)) % PI2) - ((B - A) % PI2)\n\tif (!largeArcFlag) return m\n\treturn (PI2 - Math.abs(m)) * (sweepFlag ? 1 : -1)\n}\n\n/**\n * Get the center of a circle from three points.\n *\n * @param a - The first point\n * @param b - The second point\n * @param c - The third point\n *\n * @returns The center of the circle or null if the points are collinear\n *\n * @public\n */\nexport function centerOfCircleFromThreePoints(a: VecLike, b: VecLike, c: VecLike) {\n\tconst u = -2 * (a.x * (b.y - c.y) - a.y * (b.x - c.x) + b.x * c.y - c.x * b.y)\n\tconst x =\n\t\t((a.x * a.x + a.y * a.y) * (c.y - b.y) +\n\t\t\t(b.x * b.x + b.y * b.y) * (a.y - c.y) +\n\t\t\t(c.x * c.x + c.y * c.y) * (b.y - a.y)) /\n\t\tu\n\tconst y =\n\t\t((a.x * a.x + a.y * a.y) * (b.x - c.x) +\n\t\t\t(b.x * b.x + b.y * b.y) * (c.x - a.x) +\n\t\t\t(c.x * c.x + c.y * c.y) * (a.x - b.x)) /\n\t\tu\n\tif (!Number.isFinite(x) || !Number.isFinite(y)) {\n\t\treturn null\n\t}\n\treturn new Vec(x, y)\n}\n\n/** @public */\nexport function getPointsOnArc(\n\tstartPoint: VecLike,\n\tendPoint: VecLike,\n\tcenter: VecLike | null,\n\tradius: number,\n\tnumPoints: number\n): Vec[] {\n\tif (center === null) {\n\t\treturn [Vec.From(startPoint), Vec.From(endPoint)]\n\t}\n\tconst results: Vec[] = []\n\tconst startAngle = Vec.Angle(center, startPoint)\n\tconst endAngle = Vec.Angle(center, endPoint)\n\tconst l = clockwiseAngleDist(startAngle, endAngle)\n\tfor (let i = 0; i < numPoints; i++) {\n\t\tconst t = i / (numPoints - 1)\n\t\tconst angle = startAngle + l * t\n\t\tconst point = getPointOnCircle(center, radius, angle)\n\t\tresults.push(point)\n\t}\n\treturn results\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { Vec, VecLike } from './Vec'\n\n/** @public */\nexport function precise(A: VecLike) {\n\treturn `${toDomPrecision(A.x)},${toDomPrecision(A.y)} `\n}\n\n/** @public */\nexport function average(A: VecLike, B: VecLike) {\n\treturn `${toDomPrecision((A.x + B.x) / 2)},${toDomPrecision((A.y + B.y) / 2)} `\n}\n\n/** @public */\nexport const PI = Math.PI\n/** @public */\nexport const HALF_PI = PI / 2\n/** @public */\nexport const PI2 = PI * 2\n/** @public */\nexport const SIN = Math.sin\n\n/**\n * Clamp a value into a range.\n *\n * @example\n *\n * ```ts\n * const A = clamp(0, 1) // 1\n * ```\n *\n * @param n - The number to clamp.\n * @param min - The minimum value.\n * @public\n */\nexport function clamp(n: number, min: number): number\n/**\n * Clamp a value into a range.\n *\n * @example\n *\n * ```ts\n * const A = clamp(0, 1, 10) // 1\n * const B = clamp(11, 1, 10) // 10\n * const C = clamp(5, 1, 10) // 5\n * ```\n *\n * @param n - The number to clamp.\n * @param min - The minimum value.\n * @param max - The maximum value.\n * @public\n */\nexport function clamp(n: number, min: number, max: number): number\nexport function clamp(n: number, min: number, max?: number): number {\n\treturn Math.max(min, typeof max !== 'undefined' ? Math.min(n, max) : n)\n}\n\n/**\n * Get a number to a precision.\n *\n * @param n - The number.\n * @param precision - The precision.\n * @public\n */\nexport function toPrecision(n: number, precision = 10000000000) {\n\tif (!n) return 0\n\treturn Math.round(n * precision) / precision\n}\n\n/**\n * Whether two numbers numbers a and b are approximately equal.\n *\n * @param a - The first point.\n * @param b - The second point.\n * @public\n */\nexport function approximately(a: number, b: number, precision = 0.000001) {\n\treturn Math.abs(a - b) <= precision\n}\n\n/**\n * Whether a number is approximately less than or equal to another number.\n *\n * @param a - The first number.\n * @param b - The second number.\n * @public\n */\nexport function approximatelyLte(a: number, b: number, precision = 0.000001) {\n\treturn a < b || approximately(a, b, precision)\n}\n\n/**\n * Find the approximate perimeter of an ellipse.\n *\n * @param rx - The ellipse's x radius.\n * @param ry - The ellipse's y radius.\n * @public\n */\nexport function perimeterOfEllipse(rx: number, ry: number): number {\n\tconst h = Math.pow(rx - ry, 2) / Math.pow(rx + ry, 2)\n\treturn PI * (rx + ry) * (1 + (3 * h) / (10 + Math.sqrt(4 - 3 * h)))\n}\n\n/**\n * @param a - Any angle in radians\n * @returns A number between 0 and 2 * PI\n * @public\n */\nexport function canonicalizeRotation(a: number) {\n\ta = a % PI2\n\tif (a < 0) {\n\t\ta = a + PI2\n\t} else if (a === 0) {\n\t\t// prevent negative zero\n\t\ta = 0\n\t}\n\treturn a\n}\n\n/**\n * Get the clockwise angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function clockwiseAngleDist(a0: number, a1: number): number {\n\ta0 = canonicalizeRotation(a0)\n\ta1 = canonicalizeRotation(a1)\n\tif (a0 > a1) {\n\t\ta1 += PI2\n\t}\n\treturn a1 - a0\n}\n\n/**\n * Get the counter-clockwise angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function counterClockwiseAngleDist(a0: number, a1: number): number {\n\treturn PI2 - clockwiseAngleDist(a0, a1)\n}\n\n/**\n * Get the short angle distance between two angles.\n *\n * @param a0 - The first angle.\n * @param a1 - The second angle.\n * @public\n */\nexport function shortAngleDist(a0: number, a1: number): number {\n\tconst da = (a1 - a0) % PI2\n\treturn ((2 * da) % PI2) - da\n}\n\n/**\n * Clamp radians within 0 and 2PI\n *\n * @param r - The radian value.\n * @public\n */\nexport function clampRadians(r: number): number {\n\treturn (PI2 + r) % PI2\n}\n\n/**\n * Clamp rotation to even segments.\n *\n * @param r - The rotation in radians.\n * @param segments - The number of segments.\n * @public\n */\nexport function snapAngle(r: number, segments: number): number {\n\tconst seg = PI2 / segments\n\tlet ang = (Math.floor((clampRadians(r) + seg / 2) / seg) * seg) % PI2\n\tif (ang < PI) ang += PI2\n\tif (ang > PI) ang -= PI2\n\treturn ang\n}\n\n/**\n * Checks whether two angles are approximately at right-angles or parallel to each other\n *\n * @param a - Angle a (radians)\n * @param b - Angle b (radians)\n * @returns True iff the angles are approximately at right-angles or parallel to each other\n * @public\n */\nexport function areAnglesCompatible(a: number, b: number) {\n\treturn a === b || approximately((a % (Math.PI / 2)) - (b % (Math.PI / 2)), 0)\n}\n\n/**\n * Convert degrees to radians.\n *\n * @param d - The degree in degrees.\n * @public\n */\nexport function degreesToRadians(d: number): number {\n\treturn (d * PI) / 180\n}\n\n/**\n * Convert radians to degrees.\n *\n * @param r - The degree in radians.\n * @public\n */\nexport function radiansToDegrees(r: number): number {\n\treturn (r * 180) / PI\n}\n\n/**\n * Get a point on the perimeter of a circle.\n *\n * @param center - The center of the circle.\n * @param r - The radius of the circle.\n * @param a - The angle in radians.\n * @public\n */\nexport function getPointOnCircle(center: VecLike, r: number, a: number) {\n\treturn new Vec(center.x, center.y).add(Vec.FromAngle(a, r))\n}\n\n/** @public */\nexport function getPolygonVertices(width: number, height: number, sides: number) {\n\tconst cx = width / 2\n\tconst cy = height / 2\n\tconst pointsOnPerimeter: Vec[] = []\n\n\tlet minX = Infinity\n\tlet maxX = -Infinity\n\tlet minY = Infinity\n\tlet maxY = -Infinity\n\tfor (let i = 0; i < sides; i++) {\n\t\tconst step = PI2 / sides\n\t\tconst t = -HALF_PI + i * step\n\t\tconst x = cx + cx * Math.cos(t)\n\t\tconst y = cy + cy * Math.sin(t)\n\t\tif (x < minX) minX = x\n\t\tif (y < minY) minY = y\n\t\tif (x > maxX) maxX = x\n\t\tif (y > maxY) maxY = y\n\t\tpointsOnPerimeter.push(new Vec(x, y))\n\t}\n\n\t// Bounds of calculated points\n\tconst w = maxX - minX\n\tconst h = maxY - minY\n\n\t// Difference between input bounds and calculated bounds\n\tconst dx = width - w\n\tconst dy = height - h\n\n\t// If there's a difference, scale the points to the input bounds\n\tif (dx !== 0 || dy !== 0) {\n\t\tfor (let i = 0; i < pointsOnPerimeter.length; i++) {\n\t\t\tconst pt = pointsOnPerimeter[i]\n\t\t\tpt.x = ((pt.x - minX) / w) * width\n\t\t\tpt.y = ((pt.y - minY) / h) * height\n\t\t}\n\t}\n\n\treturn pointsOnPerimeter\n}\n\n/**\n * @param a0 - The start point in the A range\n * @param a1 - The end point in the A range\n * @param b0 - The start point in the B range\n * @param b1 - The end point in the B range\n * @returns True if the ranges overlap\n * @public\n */\nexport function rangesOverlap(a0: number, a1: number, b0: number, b1: number): boolean {\n\treturn a0 < b1 && b0 < a1\n}\n\n/**\n * Finds the intersection of two ranges.\n *\n * @param a0 - The start point in the A range\n * @param a1 - The end point in the A range\n * @param b0 - The start point in the B range\n * @param b1 - The end point in the B range\n * @returns The intersection of the ranges, or null if no intersection\n * @public\n */\nexport function rangeIntersection(\n\ta0: number,\n\ta1: number,\n\tb0: number,\n\tb1: number\n): [number, number] | null {\n\tconst min = Math.max(a0, b0)\n\tconst max = Math.min(a1, b1)\n\tif (min <= max) {\n\t\treturn [min, max]\n\t}\n\treturn null\n}\n\n/** Helper for point in polygon */\nfunction cross(x: VecLike, y: VecLike, z: VecLike): number {\n\treturn (y.x - x.x) * (z.y - x.y) - (z.x - x.x) * (y.y - x.y)\n}\n\n/**\n * Get whether a point is inside of a polygon.\n *\n * ```ts\n * const result = pointInPolygon(myPoint, myPoints)\n * ```\n *\n * @public\n */\nexport function pointInPolygon(A: VecLike, points: VecLike[]): boolean {\n\tlet windingNumber = 0\n\tlet a: VecLike\n\tlet b: VecLike\n\n\tfor (let i = 0; i < points.length; i++) {\n\t\ta = points[i]\n\t\t// Point is the same as one of the corners of the polygon\n\t\tif (a.x === A.x && a.y === A.y) return true\n\n\t\tb = points[(i + 1) % points.length]\n\n\t\t// Point is on the polygon edge\n\t\tif (Vec.Dist(A, a) + Vec.Dist(A, b) === Vec.Dist(a, b)) return true\n\n\t\tif (a.y <= A.y) {\n\t\t\tif (b.y > A.y && cross(a, b, A) > 0) {\n\t\t\t\twindingNumber += 1\n\t\t\t}\n\t\t} else if (b.y <= A.y && cross(a, b, A) < 0) {\n\t\t\twindingNumber -= 1\n\t\t}\n\t}\n\n\treturn windingNumber !== 0\n}\n\n/**\n * The DOM likes values to be fixed to 3 decimal places\n *\n * @public\n */\nexport function toDomPrecision(v: number) {\n\treturn Math.round(v * 1e4) / 1e4\n}\n\n/**\n * @public\n */\nexport function toFixed(v: number) {\n\treturn Math.round(v * 1e2) / 1e2\n}\n\n/**\n * Check if a float is safe to use. ie: Not too big or small.\n * @public\n */\nexport const isSafeFloat = (n: number) => {\n\treturn Math.abs(n) < Number.MAX_SAFE_INTEGER\n}\n\n/**\n * Get the angle of a point on an arc.\n * @param fromAngle - The angle from center to arc's start point (A) on the circle\n * @param toAngle - The angle from center to arc's end point (B) on the circle\n * @param direction - The direction of the arc (1 = counter-clockwise, -1 = clockwise)\n * @returns The distance in radians between the two angles according to the direction\n * @public\n */\nexport function angleDistance(fromAngle: number, toAngle: number, direction: number) {\n\tconst dist =\n\t\tdirection < 0\n\t\t\t? clockwiseAngleDist(fromAngle, toAngle)\n\t\t\t: counterClockwiseAngleDist(fromAngle, toAngle)\n\treturn dist\n}\n\n/**\n * Returns the t value of the point on the arc.\n *\n * @param mAB - The measure of the arc from A to B, negative if counter-clockwise\n * @param A - The angle from center to arc's start point (A) on the circle\n * @param B - The angle from center to arc's end point (B) on the circle\n * @param P - The angle on the circle (P) to find the t value for\n *\n * @returns The t value of the point on the arc, with 0 being the start and 1 being the end\n *\n * @public\n */\nexport function getPointInArcT(mAB: number, A: number, B: number, P: number): number {\n\tlet mAP: number\n\tif (Math.abs(mAB) > PI) {\n\t\tmAP = shortAngleDist(A, P)\n\t\tconst mPB = shortAngleDist(P, B)\n\t\tif (Math.abs(mAP) < Math.abs(mPB)) {\n\t\t\treturn mAP / mAB\n\t\t} else {\n\t\t\treturn (mAB - mPB) / mAB\n\t\t}\n\t} else {\n\t\tmAP = shortAngleDist(A, P)\n\t\tconst t = mAP / mAB\n\n\t\t// If the arc is something like -2.8 to 2.2, then we'll get a weird bug\n\t\t// where the measurement to the center is negative but measure to points\n\t\t// near the end are positive\n\t\tif (Math.sign(mAP) !== Math.sign(mAB)) {\n\t\t\treturn Math.abs(t) > 0.5 ? 1 : 0\n\t\t}\n\n\t\treturn t\n\t}\n}\n\n/**\n * Get the measure of an arc.\n *\n * @param A - The angle from center to arc's start point (A) on the circle\n * @param B - The angle from center to arc's end point (B) on the circle\n * @param sweepFlag - 1 if the arc is clockwise, 0 if counter-clockwise\n * @param largeArcFlag - 1 if the arc is greater than 180 degrees, 0 if less than 180 degrees\n *\n * @returns The measure of the arc, negative if counter-clockwise\n *\n * @public\n */\nexport function getArcMeasure(A: number, B: number, sweepFlag: number, largeArcFlag: number) {\n\tconst m = ((2 * ((B - A) % PI2)) % PI2) - ((B - A) % PI2)\n\tif (!largeArcFlag) return m\n\treturn (PI2 - Math.abs(m)) * (sweepFlag ? 1 : -1)\n}\n\n/**\n * Get the center of a circle from three points.\n *\n * @param a - The first point\n * @param b - The second point\n * @param c - The third point\n *\n * @returns The center of the circle or null if the points are collinear\n *\n * @public\n */\nexport function centerOfCircleFromThreePoints(a: VecLike, b: VecLike, c: VecLike) {\n\tconst u = -2 * (a.x * (b.y - c.y) - a.y * (b.x - c.x) + b.x * c.y - c.x * b.y)\n\tconst x =\n\t\t((a.x * a.x + a.y * a.y) * (c.y - b.y) +\n\t\t\t(b.x * b.x + b.y * b.y) * (a.y - c.y) +\n\t\t\t(c.x * c.x + c.y * c.y) * (b.y - a.y)) /\n\t\tu\n\tconst y =\n\t\t((a.x * a.x + a.y * a.y) * (b.x - c.x) +\n\t\t\t(b.x * b.x + b.y * b.y) * (c.x - a.x) +\n\t\t\t(c.x * c.x + c.y * c.y) * (a.x - b.x)) /\n\t\tu\n\tif (!Number.isFinite(x) || !Number.isFinite(y)) {\n\t\treturn null\n\t}\n\treturn new Vec(x, y)\n}\n\n/** @public */\nexport function getPointsOnArc(\n\tstartPoint: VecLike,\n\tendPoint: VecLike,\n\tcenter: VecLike | null,\n\tradius: number,\n\tnumPoints: number\n): Vec[] {\n\tif (center === null) {\n\t\treturn [Vec.From(startPoint), Vec.From(endPoint)]\n\t}\n\tconst results: Vec[] = []\n\tconst startAngle = Vec.Angle(center, startPoint)\n\tconst endAngle = Vec.Angle(center, endPoint)\n\tconst l = clockwiseAngleDist(startAngle, endAngle)\n\tfor (let i = 0; i < numPoints; i++) {\n\t\tconst t = i / (numPoints - 1)\n\t\tconst angle = startAngle + l * t\n\t\tconst point = getPointOnCircle(center, radius, angle)\n\t\tresults.push(point)\n\t}\n\treturn results\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -185,7 +185,6 @@ class TLLocalSyncClient {
|
|
|
185
185
|
}
|
|
186
186
|
isPersisting = false;
|
|
187
187
|
didLastWriteError = false;
|
|
188
|
-
// eslint-disable-next-line no-restricted-globals
|
|
189
188
|
scheduledPersistTimeout = null;
|
|
190
189
|
/**
|
|
191
190
|
* Schedule a persist. Persists don't happen immediately: they are throttled to avoid writing too
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/utils/sync/TLLocalSyncClient.ts"],
|
|
4
|
-
"sourcesContent": ["import { Signal, transact } from '@tldraw/state'\nimport { RecordsDiff, SerializedSchema, UnknownRecord, squashRecordDiffs } from '@tldraw/store'\nimport { TLStore } from '@tldraw/tlschema'\nimport { assert } from '@tldraw/utils'\nimport {\n\tTAB_ID,\n\tTLSessionStateSnapshot,\n\tcreateSessionStateSnapshotSignal,\n\textractSessionStateFromLegacySnapshot,\n\tloadSessionStateSnapshotIntoStore,\n} from '../../config/TLSessionStateSnapshot'\nimport { LocalIndexedDb } from './LocalIndexedDb'\nimport { showCantReadFromIndexDbAlert, showCantWriteToIndexDbAlert } from './alerts'\n\n/** How should we debounce persists? */\nconst PERSIST_THROTTLE_MS = 350\n/** If we're in an error state, how long should we wait before retrying a write? */\nconst PERSIST_RETRY_THROTTLE_MS = 10_000\n\nconst UPDATE_INSTANCE_STATE = Symbol('UPDATE_INSTANCE_STATE')\n\n/**\n * IMPORTANT!!!\n *\n * This is just a quick-n-dirty temporary solution that will be replaced with the remote sync client\n * once it has the db integrated\n */\n\ninterface SyncMessage {\n\ttype: 'diff'\n\tstoreId: string\n\tchanges: RecordsDiff<UnknownRecord>\n\tschema: SerializedSchema\n}\n\n// Sent by new clients when they connect\n// If another client is on the channel with a newer schema version\n// It will\ninterface AnnounceMessage {\n\ttype: 'announce'\n\tschema: SerializedSchema\n}\n\ntype Message = SyncMessage | AnnounceMessage\n\ntype UnpackPromise<T> = T extends Promise<infer U> ? U : T\n\nconst msg = (msg: Message) => msg\n\n/** @internal */\nexport class BroadcastChannelMock {\n\tonmessage?: (e: MessageEvent) => void\n\tconstructor(_name: string) {\n\t\t// noop\n\t}\n\tpostMessage(_msg: Message) {\n\t\t// noop\n\t}\n\tclose() {\n\t\t// noop\n\t}\n}\n\nconst BC = typeof BroadcastChannel === 'undefined' ? BroadcastChannelMock : BroadcastChannel\n\n/** @internal */\nexport class TLLocalSyncClient {\n\tprivate disposables = new Set<() => void>()\n\tprivate diffQueue: Array<RecordsDiff<UnknownRecord> | typeof UPDATE_INSTANCE_STATE> = []\n\tprivate didDispose = false\n\tprivate shouldDoFullDBWrite = true\n\tprivate isReloading = false\n\treadonly persistenceKey: string\n\treadonly sessionId: string\n\treadonly serializedSchema: SerializedSchema\n\tprivate isDebugging = false\n\tprivate readonly documentTypes: ReadonlySet<string>\n\tprivate readonly $sessionStateSnapshot: Signal<TLSessionStateSnapshot | null>\n\t/** @internal */\n\treadonly db: LocalIndexedDb\n\n\tinitTime = Date.now()\n\tprivate debug(...args: any[]) {\n\t\tif (this.isDebugging) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.debug(...args)\n\t\t}\n\t}\n\tconstructor(\n\t\tpublic readonly store: TLStore,\n\t\t{\n\t\t\tpersistenceKey,\n\t\t\tsessionId = TAB_ID,\n\t\t\tonLoad,\n\t\t\tonLoadError,\n\t\t}: {\n\t\t\tpersistenceKey: string\n\t\t\tsessionId?: string\n\t\t\tonLoad(self: TLLocalSyncClient): void\n\t\t\tonLoadError(error: Error): void\n\t\t},\n\t\tpublic readonly channel = new BC(`tldraw-tab-sync-${persistenceKey}`)\n\t) {\n\t\tif (typeof window !== 'undefined') {\n\t\t\t;(window as any).tlsync = this\n\t\t}\n\t\tthis.persistenceKey = persistenceKey\n\t\tthis.sessionId = sessionId\n\t\tthis.db = new LocalIndexedDb(persistenceKey)\n\t\tthis.disposables.add(() => this.db.close())\n\n\t\tthis.serializedSchema = this.store.schema.serialize()\n\t\tthis.$sessionStateSnapshot = createSessionStateSnapshotSignal(this.store)\n\n\t\tthis.disposables.add(\n\t\t\t// Set up a subscription to changes from the store: When\n\t\t\t// the store changes (and if the change was made by the user)\n\t\t\t// then immediately send the diff to other tabs via postMessage\n\t\t\t// and schedule a persist.\n\t\t\tstore.listen(\n\t\t\t\t({ changes }) => {\n\t\t\t\t\tthis.diffQueue.push(changes)\n\t\t\t\t\tthis.channel.postMessage(\n\t\t\t\t\t\tmsg({\n\t\t\t\t\t\t\ttype: 'diff',\n\t\t\t\t\t\t\tstoreId: this.store.id,\n\t\t\t\t\t\t\tchanges,\n\t\t\t\t\t\t\tschema: this.serializedSchema,\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t\tthis.schedulePersist()\n\t\t\t\t},\n\t\t\t\t{ source: 'user', scope: 'document' }\n\t\t\t)\n\t\t)\n\t\tthis.disposables.add(\n\t\t\tstore.listen(\n\t\t\t\t() => {\n\t\t\t\t\tthis.diffQueue.push(UPDATE_INSTANCE_STATE)\n\t\t\t\t\tthis.schedulePersist()\n\t\t\t\t},\n\t\t\t\t{ scope: 'session' }\n\t\t\t)\n\t\t)\n\n\t\tthis.connect(onLoad, onLoadError)\n\n\t\tthis.documentTypes = new Set(\n\t\t\tObject.values(this.store.schema.types)\n\t\t\t\t.filter((t) => t.scope === 'document')\n\t\t\t\t.map((t) => t.typeName)\n\t\t)\n\t}\n\n\tprivate async connect(onLoad: (client: this) => void, onLoadError: (error: Error) => void) {\n\t\tthis.debug('connecting')\n\t\tlet data: UnpackPromise<ReturnType<LocalIndexedDb['load']>> | undefined\n\n\t\ttry {\n\t\t\tdata = await this.db.load({ sessionId: this.sessionId })\n\t\t} catch (error: any) {\n\t\t\tonLoadError(error)\n\t\t\tshowCantReadFromIndexDbAlert()\n\t\t\treturn\n\t\t}\n\n\t\tthis.debug('loaded data from store', data, 'didDispose', this.didDispose)\n\t\tif (this.didDispose) return\n\n\t\ttry {\n\t\t\tif (data) {\n\t\t\t\tconst documentSnapshot = Object.fromEntries(data.records.map((r) => [r.id, r]))\n\t\t\t\tconst sessionStateSnapshot =\n\t\t\t\t\tdata.sessionStateSnapshot ?? extractSessionStateFromLegacySnapshot(documentSnapshot)\n\t\t\t\tconst migrationResult = this.store.schema.migrateStoreSnapshot({\n\t\t\t\t\tstore: documentSnapshot,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t\tschema: data.schema ?? this.store.schema.serializeEarliestVersion(),\n\t\t\t\t})\n\n\t\t\t\tif (migrationResult.type === 'error') {\n\t\t\t\t\tconsole.error('failed to migrate store', migrationResult)\n\t\t\t\t\tonLoadError(new Error(`Failed to migrate store: ${migrationResult.reason}`))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst records = Object.values(migrationResult.value).filter((r) =>\n\t\t\t\t\tthis.documentTypes.has(r.typeName)\n\t\t\t\t)\n\t\t\t\tif (records.length > 0) {\n\t\t\t\t\t// 3. Merge the changes into the REAL STORE\n\t\t\t\t\tthis.store.mergeRemoteChanges(() => {\n\t\t\t\t\t\t// Calling put will validate the records!\n\t\t\t\t\t\tthis.store.put(records, 'initialize')\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tif (sessionStateSnapshot) {\n\t\t\t\t\tloadSessionStateSnapshotIntoStore(this.store, sessionStateSnapshot, {\n\t\t\t\t\t\tforceOverwrite: true,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.channel.onmessage = ({ data }) => {\n\t\t\t\tthis.debug('got message', data)\n\t\t\t\tconst msg = data as Message\n\t\t\t\t// if their schema is earlier than ours, we need to tell them so they can refresh\n\t\t\t\t// if their schema is later than ours, we need to refresh\n\t\t\t\tconst res = this.store.schema.getMigrationsSince(msg.schema)\n\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\t// we are older, refresh\n\t\t\t\t\t// but add a safety check to make sure we don't get in an infinite loop\n\t\t\t\t\tconst timeSinceInit = Date.now() - this.initTime\n\t\t\t\t\tif (timeSinceInit < 5000) {\n\t\t\t\t\t\t// This tab was just reloaded, but is out of date compared to other tabs.\n\t\t\t\t\t\t// Not expecting this to ever happen. It should only happen if we roll back a release that incremented\n\t\t\t\t\t\t// the schema version (which we should never do)\n\t\t\t\t\t\t// Or maybe during development if you have multiple local tabs open running the app on prod mode and you\n\t\t\t\t\t\t// check out an older commit. Dev server should be fine.\n\t\t\t\t\t\tonLoadError(new Error('Schema mismatch, please close other tabs and reload the page'))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tthis.debug('reloading')\n\t\t\t\t\tthis.isReloading = true\n\t\t\t\t\twindow?.location?.reload?.()\n\t\t\t\t\treturn\n\t\t\t\t} else if (res.value.length > 0) {\n\t\t\t\t\t// they are older, tell them to refresh and not write any more data\n\t\t\t\t\tthis.debug('telling them to reload')\n\t\t\t\t\tthis.channel.postMessage({ type: 'announce', schema: this.serializedSchema })\n\t\t\t\t\t// schedule a full db write in case they wrote data anyway\n\t\t\t\t\tthis.shouldDoFullDBWrite = true\n\t\t\t\t\tthis.persistIfNeeded()\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// otherwise, all good, same version :)\n\t\t\t\tif (msg.type === 'diff') {\n\t\t\t\t\tthis.debug('applying diff')\n\t\t\t\t\ttransact(() => {\n\t\t\t\t\t\tthis.store.mergeRemoteChanges(() => {\n\t\t\t\t\t\t\tthis.store.applyDiff(msg.changes as any)\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.channel.postMessage({ type: 'announce', schema: this.serializedSchema })\n\t\t\tthis.disposables.add(() => {\n\t\t\t\tthis.channel.close()\n\t\t\t})\n\t\t\tonLoad(this)\n\t\t} catch (e: any) {\n\t\t\tthis.debug('error loading data from store', e)\n\t\t\tif (this.didDispose) return\n\t\t\tonLoadError(e)\n\t\t\treturn\n\t\t}\n\t}\n\n\tclose() {\n\t\tthis.debug('closing')\n\t\tthis.didDispose = true\n\t\tthis.disposables.forEach((d) => d())\n\t}\n\n\tprivate isPersisting = false\n\tprivate didLastWriteError = false\n\t// eslint-disable-next-line no-restricted-globals\n\tprivate scheduledPersistTimeout: ReturnType<typeof setTimeout> | null = null\n\n\t/**\n\t * Schedule a persist. Persists don't happen immediately: they are throttled to avoid writing too\n\t * often, and will retry if failed.\n\t *\n\t * @internal\n\t */\n\tprivate schedulePersist() {\n\t\tthis.debug('schedulePersist', this.scheduledPersistTimeout)\n\t\tif (this.scheduledPersistTimeout) return\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.scheduledPersistTimeout = setTimeout(\n\t\t\t() => {\n\t\t\t\tthis.scheduledPersistTimeout = null\n\t\t\t\tthis.persistIfNeeded()\n\t\t\t},\n\t\t\tthis.didLastWriteError ? PERSIST_RETRY_THROTTLE_MS : PERSIST_THROTTLE_MS\n\t\t)\n\t}\n\n\t/**\n\t * Persist to IndexedDB only under certain circumstances:\n\t *\n\t * - If we're not already persisting\n\t * - If we're not reloading the page\n\t * - And we have something to persist (a full db write scheduled or changes in the diff queue)\n\t *\n\t * @internal\n\t */\n\tprivate persistIfNeeded() {\n\t\tthis.debug('persistIfNeeded', {\n\t\t\tisPersisting: this.isPersisting,\n\t\t\tisReloading: this.isReloading,\n\t\t\tshouldDoFullDBWrite: this.shouldDoFullDBWrite,\n\t\t\tdiffQueueLength: this.diffQueue.length,\n\t\t\tstoreIsPossiblyCorrupt: this.store.isPossiblyCorrupted(),\n\t\t})\n\n\t\t// if we've scheduled a persist for the future, that's no longer needed\n\t\tif (this.scheduledPersistTimeout) {\n\t\t\tclearTimeout(this.scheduledPersistTimeout)\n\t\t\tthis.scheduledPersistTimeout = null\n\t\t}\n\n\t\t// if a persist is already in progress, we don't need to do anything -\n\t\t// if there are still outstanding changes once it's finished, it'll\n\t\t// schedule another persist\n\t\tif (this.isPersisting) return\n\n\t\t// if we're reloading the page, it's because there's a newer client\n\t\t// present so lets not overwrite their changes\n\t\tif (this.isReloading) return\n\n\t\t// if the store is possibly corrupted, we don't want to persist\n\t\tif (this.store.isPossiblyCorrupted()) return\n\n\t\t// if we're scheduled for a full write or if we have changes outstanding, let's persist them!\n\t\tif (this.shouldDoFullDBWrite || this.diffQueue.length > 0) {\n\t\t\tthis.doPersist()\n\t\t}\n\t}\n\n\t/**\n\t * Actually persist to IndexedDB. If the write fails, then we'll retry with a full db write after\n\t * a short delay.\n\t */\n\tprivate async doPersist() {\n\t\tassert(!this.isPersisting, 'persist already in progress')\n\t\tif (this.didDispose) return\n\t\tthis.isPersisting = true\n\n\t\tthis.debug('doPersist start')\n\n\t\t// instantly empty the diff queue, but keep our own copy of it. this way\n\t\t// diffs that come in during the persist will still get tracked\n\t\tconst diffQueue = this.diffQueue\n\t\tthis.diffQueue = []\n\n\t\ttry {\n\t\t\tif (this.shouldDoFullDBWrite) {\n\t\t\t\tthis.shouldDoFullDBWrite = false\n\t\t\t\tawait this.db.storeSnapshot({\n\t\t\t\t\tschema: this.store.schema,\n\t\t\t\t\tsnapshot: this.store.serialize(),\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\tsessionStateSnapshot: this.$sessionStateSnapshot.get(),\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tconst diffs = squashRecordDiffs(\n\t\t\t\t\tdiffQueue.filter((d): d is RecordsDiff<UnknownRecord> => d !== UPDATE_INSTANCE_STATE)\n\t\t\t\t)\n\t\t\t\tawait this.db.storeChanges({\n\t\t\t\t\tchanges: diffs,\n\t\t\t\t\tschema: this.store.schema,\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\tsessionStateSnapshot: this.$sessionStateSnapshot.get(),\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.didLastWriteError = false\n\t\t} catch (e) {\n\t\t\t// set this.shouldDoFullDBWrite because we clear the diffQueue no matter what,\n\t\t\t// so if this is just a temporary error, we will still persist all changes\n\t\t\tthis.shouldDoFullDBWrite = true\n\t\t\tthis.didLastWriteError = true\n\t\t\tconsole.error('failed to store changes in indexed db', e)\n\n\t\t\tshowCantWriteToIndexDbAlert()\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\t// adios\n\t\t\t\twindow.location.reload()\n\t\t\t}\n\t\t}\n\n\t\tthis.isPersisting = false\n\t\tthis.debug('doPersist end')\n\n\t\t// changes might have come in between when we started the persist and\n\t\t// now. we request another persist so any new changes can get written\n\t\tthis.schedulePersist()\n\t}\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { Signal, transact } from '@tldraw/state'\nimport { RecordsDiff, SerializedSchema, UnknownRecord, squashRecordDiffs } from '@tldraw/store'\nimport { TLStore } from '@tldraw/tlschema'\nimport { assert } from '@tldraw/utils'\nimport {\n\tTAB_ID,\n\tTLSessionStateSnapshot,\n\tcreateSessionStateSnapshotSignal,\n\textractSessionStateFromLegacySnapshot,\n\tloadSessionStateSnapshotIntoStore,\n} from '../../config/TLSessionStateSnapshot'\nimport { LocalIndexedDb } from './LocalIndexedDb'\nimport { showCantReadFromIndexDbAlert, showCantWriteToIndexDbAlert } from './alerts'\n\n/** How should we debounce persists? */\nconst PERSIST_THROTTLE_MS = 350\n/** If we're in an error state, how long should we wait before retrying a write? */\nconst PERSIST_RETRY_THROTTLE_MS = 10_000\n\nconst UPDATE_INSTANCE_STATE = Symbol('UPDATE_INSTANCE_STATE')\n\n/**\n * IMPORTANT!!!\n *\n * This is just a quick-n-dirty temporary solution that will be replaced with the remote sync client\n * once it has the db integrated\n */\n\ninterface SyncMessage {\n\ttype: 'diff'\n\tstoreId: string\n\tchanges: RecordsDiff<UnknownRecord>\n\tschema: SerializedSchema\n}\n\n// Sent by new clients when they connect\n// If another client is on the channel with a newer schema version\n// It will\ninterface AnnounceMessage {\n\ttype: 'announce'\n\tschema: SerializedSchema\n}\n\ntype Message = SyncMessage | AnnounceMessage\n\ntype UnpackPromise<T> = T extends Promise<infer U> ? U : T\n\nconst msg = (msg: Message) => msg\n\n/** @internal */\nexport class BroadcastChannelMock {\n\tonmessage?: (e: MessageEvent) => void\n\tconstructor(_name: string) {\n\t\t// noop\n\t}\n\tpostMessage(_msg: Message) {\n\t\t// noop\n\t}\n\tclose() {\n\t\t// noop\n\t}\n}\n\nconst BC = typeof BroadcastChannel === 'undefined' ? BroadcastChannelMock : BroadcastChannel\n\n/** @internal */\nexport class TLLocalSyncClient {\n\tprivate disposables = new Set<() => void>()\n\tprivate diffQueue: Array<RecordsDiff<UnknownRecord> | typeof UPDATE_INSTANCE_STATE> = []\n\tprivate didDispose = false\n\tprivate shouldDoFullDBWrite = true\n\tprivate isReloading = false\n\treadonly persistenceKey: string\n\treadonly sessionId: string\n\treadonly serializedSchema: SerializedSchema\n\tprivate isDebugging = false\n\tprivate readonly documentTypes: ReadonlySet<string>\n\tprivate readonly $sessionStateSnapshot: Signal<TLSessionStateSnapshot | null>\n\t/** @internal */\n\treadonly db: LocalIndexedDb\n\n\tinitTime = Date.now()\n\tprivate debug(...args: any[]) {\n\t\tif (this.isDebugging) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.debug(...args)\n\t\t}\n\t}\n\tconstructor(\n\t\tpublic readonly store: TLStore,\n\t\t{\n\t\t\tpersistenceKey,\n\t\t\tsessionId = TAB_ID,\n\t\t\tonLoad,\n\t\t\tonLoadError,\n\t\t}: {\n\t\t\tpersistenceKey: string\n\t\t\tsessionId?: string\n\t\t\tonLoad(self: TLLocalSyncClient): void\n\t\t\tonLoadError(error: Error): void\n\t\t},\n\t\tpublic readonly channel = new BC(`tldraw-tab-sync-${persistenceKey}`)\n\t) {\n\t\tif (typeof window !== 'undefined') {\n\t\t\t;(window as any).tlsync = this\n\t\t}\n\t\tthis.persistenceKey = persistenceKey\n\t\tthis.sessionId = sessionId\n\t\tthis.db = new LocalIndexedDb(persistenceKey)\n\t\tthis.disposables.add(() => this.db.close())\n\n\t\tthis.serializedSchema = this.store.schema.serialize()\n\t\tthis.$sessionStateSnapshot = createSessionStateSnapshotSignal(this.store)\n\n\t\tthis.disposables.add(\n\t\t\t// Set up a subscription to changes from the store: When\n\t\t\t// the store changes (and if the change was made by the user)\n\t\t\t// then immediately send the diff to other tabs via postMessage\n\t\t\t// and schedule a persist.\n\t\t\tstore.listen(\n\t\t\t\t({ changes }) => {\n\t\t\t\t\tthis.diffQueue.push(changes)\n\t\t\t\t\tthis.channel.postMessage(\n\t\t\t\t\t\tmsg({\n\t\t\t\t\t\t\ttype: 'diff',\n\t\t\t\t\t\t\tstoreId: this.store.id,\n\t\t\t\t\t\t\tchanges,\n\t\t\t\t\t\t\tschema: this.serializedSchema,\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t\tthis.schedulePersist()\n\t\t\t\t},\n\t\t\t\t{ source: 'user', scope: 'document' }\n\t\t\t)\n\t\t)\n\t\tthis.disposables.add(\n\t\t\tstore.listen(\n\t\t\t\t() => {\n\t\t\t\t\tthis.diffQueue.push(UPDATE_INSTANCE_STATE)\n\t\t\t\t\tthis.schedulePersist()\n\t\t\t\t},\n\t\t\t\t{ scope: 'session' }\n\t\t\t)\n\t\t)\n\n\t\tthis.connect(onLoad, onLoadError)\n\n\t\tthis.documentTypes = new Set(\n\t\t\tObject.values(this.store.schema.types)\n\t\t\t\t.filter((t) => t.scope === 'document')\n\t\t\t\t.map((t) => t.typeName)\n\t\t)\n\t}\n\n\tprivate async connect(onLoad: (client: this) => void, onLoadError: (error: Error) => void) {\n\t\tthis.debug('connecting')\n\t\tlet data: UnpackPromise<ReturnType<LocalIndexedDb['load']>> | undefined\n\n\t\ttry {\n\t\t\tdata = await this.db.load({ sessionId: this.sessionId })\n\t\t} catch (error: any) {\n\t\t\tonLoadError(error)\n\t\t\tshowCantReadFromIndexDbAlert()\n\t\t\treturn\n\t\t}\n\n\t\tthis.debug('loaded data from store', data, 'didDispose', this.didDispose)\n\t\tif (this.didDispose) return\n\n\t\ttry {\n\t\t\tif (data) {\n\t\t\t\tconst documentSnapshot = Object.fromEntries(data.records.map((r) => [r.id, r]))\n\t\t\t\tconst sessionStateSnapshot =\n\t\t\t\t\tdata.sessionStateSnapshot ?? extractSessionStateFromLegacySnapshot(documentSnapshot)\n\t\t\t\tconst migrationResult = this.store.schema.migrateStoreSnapshot({\n\t\t\t\t\tstore: documentSnapshot,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t\tschema: data.schema ?? this.store.schema.serializeEarliestVersion(),\n\t\t\t\t})\n\n\t\t\t\tif (migrationResult.type === 'error') {\n\t\t\t\t\tconsole.error('failed to migrate store', migrationResult)\n\t\t\t\t\tonLoadError(new Error(`Failed to migrate store: ${migrationResult.reason}`))\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst records = Object.values(migrationResult.value).filter((r) =>\n\t\t\t\t\tthis.documentTypes.has(r.typeName)\n\t\t\t\t)\n\t\t\t\tif (records.length > 0) {\n\t\t\t\t\t// 3. Merge the changes into the REAL STORE\n\t\t\t\t\tthis.store.mergeRemoteChanges(() => {\n\t\t\t\t\t\t// Calling put will validate the records!\n\t\t\t\t\t\tthis.store.put(records, 'initialize')\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tif (sessionStateSnapshot) {\n\t\t\t\t\tloadSessionStateSnapshotIntoStore(this.store, sessionStateSnapshot, {\n\t\t\t\t\t\tforceOverwrite: true,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.channel.onmessage = ({ data }) => {\n\t\t\t\tthis.debug('got message', data)\n\t\t\t\tconst msg = data as Message\n\t\t\t\t// if their schema is earlier than ours, we need to tell them so they can refresh\n\t\t\t\t// if their schema is later than ours, we need to refresh\n\t\t\t\tconst res = this.store.schema.getMigrationsSince(msg.schema)\n\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\t// we are older, refresh\n\t\t\t\t\t// but add a safety check to make sure we don't get in an infinite loop\n\t\t\t\t\tconst timeSinceInit = Date.now() - this.initTime\n\t\t\t\t\tif (timeSinceInit < 5000) {\n\t\t\t\t\t\t// This tab was just reloaded, but is out of date compared to other tabs.\n\t\t\t\t\t\t// Not expecting this to ever happen. It should only happen if we roll back a release that incremented\n\t\t\t\t\t\t// the schema version (which we should never do)\n\t\t\t\t\t\t// Or maybe during development if you have multiple local tabs open running the app on prod mode and you\n\t\t\t\t\t\t// check out an older commit. Dev server should be fine.\n\t\t\t\t\t\tonLoadError(new Error('Schema mismatch, please close other tabs and reload the page'))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tthis.debug('reloading')\n\t\t\t\t\tthis.isReloading = true\n\t\t\t\t\twindow?.location?.reload?.()\n\t\t\t\t\treturn\n\t\t\t\t} else if (res.value.length > 0) {\n\t\t\t\t\t// they are older, tell them to refresh and not write any more data\n\t\t\t\t\tthis.debug('telling them to reload')\n\t\t\t\t\tthis.channel.postMessage({ type: 'announce', schema: this.serializedSchema })\n\t\t\t\t\t// schedule a full db write in case they wrote data anyway\n\t\t\t\t\tthis.shouldDoFullDBWrite = true\n\t\t\t\t\tthis.persistIfNeeded()\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// otherwise, all good, same version :)\n\t\t\t\tif (msg.type === 'diff') {\n\t\t\t\t\tthis.debug('applying diff')\n\t\t\t\t\ttransact(() => {\n\t\t\t\t\t\tthis.store.mergeRemoteChanges(() => {\n\t\t\t\t\t\t\tthis.store.applyDiff(msg.changes as any)\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.channel.postMessage({ type: 'announce', schema: this.serializedSchema })\n\t\t\tthis.disposables.add(() => {\n\t\t\t\tthis.channel.close()\n\t\t\t})\n\t\t\tonLoad(this)\n\t\t} catch (e: any) {\n\t\t\tthis.debug('error loading data from store', e)\n\t\t\tif (this.didDispose) return\n\t\t\tonLoadError(e)\n\t\t\treturn\n\t\t}\n\t}\n\n\tclose() {\n\t\tthis.debug('closing')\n\t\tthis.didDispose = true\n\t\tthis.disposables.forEach((d) => d())\n\t}\n\n\tprivate isPersisting = false\n\tprivate didLastWriteError = false\n\tprivate scheduledPersistTimeout: ReturnType<typeof setTimeout> | null = null\n\n\t/**\n\t * Schedule a persist. Persists don't happen immediately: they are throttled to avoid writing too\n\t * often, and will retry if failed.\n\t *\n\t * @internal\n\t */\n\tprivate schedulePersist() {\n\t\tthis.debug('schedulePersist', this.scheduledPersistTimeout)\n\t\tif (this.scheduledPersistTimeout) return\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.scheduledPersistTimeout = setTimeout(\n\t\t\t() => {\n\t\t\t\tthis.scheduledPersistTimeout = null\n\t\t\t\tthis.persistIfNeeded()\n\t\t\t},\n\t\t\tthis.didLastWriteError ? PERSIST_RETRY_THROTTLE_MS : PERSIST_THROTTLE_MS\n\t\t)\n\t}\n\n\t/**\n\t * Persist to IndexedDB only under certain circumstances:\n\t *\n\t * - If we're not already persisting\n\t * - If we're not reloading the page\n\t * - And we have something to persist (a full db write scheduled or changes in the diff queue)\n\t *\n\t * @internal\n\t */\n\tprivate persistIfNeeded() {\n\t\tthis.debug('persistIfNeeded', {\n\t\t\tisPersisting: this.isPersisting,\n\t\t\tisReloading: this.isReloading,\n\t\t\tshouldDoFullDBWrite: this.shouldDoFullDBWrite,\n\t\t\tdiffQueueLength: this.diffQueue.length,\n\t\t\tstoreIsPossiblyCorrupt: this.store.isPossiblyCorrupted(),\n\t\t})\n\n\t\t// if we've scheduled a persist for the future, that's no longer needed\n\t\tif (this.scheduledPersistTimeout) {\n\t\t\tclearTimeout(this.scheduledPersistTimeout)\n\t\t\tthis.scheduledPersistTimeout = null\n\t\t}\n\n\t\t// if a persist is already in progress, we don't need to do anything -\n\t\t// if there are still outstanding changes once it's finished, it'll\n\t\t// schedule another persist\n\t\tif (this.isPersisting) return\n\n\t\t// if we're reloading the page, it's because there's a newer client\n\t\t// present so lets not overwrite their changes\n\t\tif (this.isReloading) return\n\n\t\t// if the store is possibly corrupted, we don't want to persist\n\t\tif (this.store.isPossiblyCorrupted()) return\n\n\t\t// if we're scheduled for a full write or if we have changes outstanding, let's persist them!\n\t\tif (this.shouldDoFullDBWrite || this.diffQueue.length > 0) {\n\t\t\tthis.doPersist()\n\t\t}\n\t}\n\n\t/**\n\t * Actually persist to IndexedDB. If the write fails, then we'll retry with a full db write after\n\t * a short delay.\n\t */\n\tprivate async doPersist() {\n\t\tassert(!this.isPersisting, 'persist already in progress')\n\t\tif (this.didDispose) return\n\t\tthis.isPersisting = true\n\n\t\tthis.debug('doPersist start')\n\n\t\t// instantly empty the diff queue, but keep our own copy of it. this way\n\t\t// diffs that come in during the persist will still get tracked\n\t\tconst diffQueue = this.diffQueue\n\t\tthis.diffQueue = []\n\n\t\ttry {\n\t\t\tif (this.shouldDoFullDBWrite) {\n\t\t\t\tthis.shouldDoFullDBWrite = false\n\t\t\t\tawait this.db.storeSnapshot({\n\t\t\t\t\tschema: this.store.schema,\n\t\t\t\t\tsnapshot: this.store.serialize(),\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\tsessionStateSnapshot: this.$sessionStateSnapshot.get(),\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tconst diffs = squashRecordDiffs(\n\t\t\t\t\tdiffQueue.filter((d): d is RecordsDiff<UnknownRecord> => d !== UPDATE_INSTANCE_STATE)\n\t\t\t\t)\n\t\t\t\tawait this.db.storeChanges({\n\t\t\t\t\tchanges: diffs,\n\t\t\t\t\tschema: this.store.schema,\n\t\t\t\t\tsessionId: this.sessionId,\n\t\t\t\t\tsessionStateSnapshot: this.$sessionStateSnapshot.get(),\n\t\t\t\t})\n\t\t\t}\n\t\t\tthis.didLastWriteError = false\n\t\t} catch (e) {\n\t\t\t// set this.shouldDoFullDBWrite because we clear the diffQueue no matter what,\n\t\t\t// so if this is just a temporary error, we will still persist all changes\n\t\t\tthis.shouldDoFullDBWrite = true\n\t\t\tthis.didLastWriteError = true\n\t\t\tconsole.error('failed to store changes in indexed db', e)\n\n\t\t\tshowCantWriteToIndexDbAlert()\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\t// adios\n\t\t\t\twindow.location.reload()\n\t\t\t}\n\t\t}\n\n\t\tthis.isPersisting = false\n\t\tthis.debug('doPersist end')\n\n\t\t// changes might have come in between when we started the persist and\n\t\t// now. we request another persist so any new changes can get written\n\t\tthis.schedulePersist()\n\t}\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAiB,gBAAgB;AACjC,SAAuD,yBAAyB;AAEhF,SAAS,cAAc;AACvB;AAAA,EACC;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,sBAAsB;AAC/B,SAAS,8BAA8B,mCAAmC;AAG1E,MAAM,sBAAsB;AAE5B,MAAM,4BAA4B;AAElC,MAAM,wBAAwB,OAAO,uBAAuB;AA4B5D,MAAM,MAAM,CAACA,SAAiBA;AAGvB,MAAM,qBAAqB;AAAA,EACjC;AAAA,EACA,YAAY,OAAe;AAAA,EAE3B;AAAA,EACA,YAAY,MAAe;AAAA,EAE3B;AAAA,EACA,QAAQ;AAAA,EAER;AACD;AAEA,MAAM,KAAK,OAAO,qBAAqB,cAAc,uBAAuB;AAGrE,MAAM,kBAAkB;AAAA,EAsB9B,YACiB,OAChB;AAAA,IACC;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,EACD,GAMgB,UAAU,IAAI,GAAG,mBAAmB,cAAc,EAAE,GACnE;AAbe;AAYA;AAEhB,QAAI,OAAO,WAAW,aAAa;AAClC;AAAC,MAAC,OAAe,SAAS;AAAA,IAC3B;AACA,SAAK,iBAAiB;AACtB,SAAK,YAAY;AACjB,SAAK,KAAK,IAAI,eAAe,cAAc;AAC3C,SAAK,YAAY,IAAI,MAAM,KAAK,GAAG,MAAM,CAAC;AAE1C,SAAK,mBAAmB,KAAK,MAAM,OAAO,UAAU;AACpD,SAAK,wBAAwB,iCAAiC,KAAK,KAAK;AAExE,SAAK,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,MAKhB,MAAM;AAAA,QACL,CAAC,EAAE,QAAQ,MAAM;AAChB,eAAK,UAAU,KAAK,OAAO;AAC3B,eAAK,QAAQ;AAAA,YACZ,IAAI;AAAA,cACH,MAAM;AAAA,cACN,SAAS,KAAK,MAAM;AAAA,cACpB;AAAA,cACA,QAAQ,KAAK;AAAA,YACd,CAAC;AAAA,UACF;AACA,eAAK,gBAAgB;AAAA,QACtB;AAAA,QACA,EAAE,QAAQ,QAAQ,OAAO,WAAW;AAAA,MACrC;AAAA,IACD;AACA,SAAK,YAAY;AAAA,MAChB,MAAM;AAAA,QACL,MAAM;AACL,eAAK,UAAU,KAAK,qBAAqB;AACzC,eAAK,gBAAgB;AAAA,QACtB;AAAA,QACA,EAAE,OAAO,UAAU;AAAA,MACpB;AAAA,IACD;AAEA,SAAK,QAAQ,QAAQ,WAAW;AAEhC,SAAK,gBAAgB,IAAI;AAAA,MACxB,OAAO,OAAO,KAAK,MAAM,OAAO,KAAK,EACnC,OAAO,CAAC,MAAM,EAAE,UAAU,UAAU,EACpC,IAAI,CAAC,MAAM,EAAE,QAAQ;AAAA,IACxB;AAAA,EACD;AAAA,EArFQ,cAAc,oBAAI,IAAgB;AAAA,EAClC,YAA8E,CAAC;AAAA,EAC/E,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,cAAc;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACD,cAAc;AAAA,EACL;AAAA,EACA;AAAA;AAAA,EAER;AAAA,EAET,WAAW,KAAK,IAAI;AAAA,EACZ,SAAS,MAAa;AAC7B,QAAI,KAAK,aAAa;AAErB,cAAQ,MAAM,GAAG,IAAI;AAAA,IACtB;AAAA,EACD;AAAA,EAmEA,MAAc,QAAQ,QAAgC,aAAqC;AAC1F,SAAK,MAAM,YAAY;AACvB,QAAI;AAEJ,QAAI;AACH,aAAO,MAAM,KAAK,GAAG,KAAK,EAAE,WAAW,KAAK,UAAU,CAAC;AAAA,IACxD,SAAS,OAAY;AACpB,kBAAY,KAAK;AACjB,mCAA6B;AAC7B;AAAA,IACD;AAEA,SAAK,MAAM,0BAA0B,MAAM,cAAc,KAAK,UAAU;AACxE,QAAI,KAAK,WAAY;AAErB,QAAI;AACH,UAAI,MAAM;AACT,cAAM,mBAAmB,OAAO,YAAY,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAC9E,cAAM,uBACL,KAAK,wBAAwB,sCAAsC,gBAAgB;AACpF,cAAM,kBAAkB,KAAK,MAAM,OAAO,qBAAqB;AAAA,UAC9D,OAAO;AAAA;AAAA,UAEP,QAAQ,KAAK,UAAU,KAAK,MAAM,OAAO,yBAAyB;AAAA,QACnE,CAAC;AAED,YAAI,gBAAgB,SAAS,SAAS;AACrC,kBAAQ,MAAM,2BAA2B,eAAe;AACxD,sBAAY,IAAI,MAAM,4BAA4B,gBAAgB,MAAM,EAAE,CAAC;AAC3E;AAAA,QACD;AAEA,cAAM,UAAU,OAAO,OAAO,gBAAgB,KAAK,EAAE;AAAA,UAAO,CAAC,MAC5D,KAAK,cAAc,IAAI,EAAE,QAAQ;AAAA,QAClC;AACA,YAAI,QAAQ,SAAS,GAAG;AAEvB,eAAK,MAAM,mBAAmB,MAAM;AAEnC,iBAAK,MAAM,IAAI,SAAS,YAAY;AAAA,UACrC,CAAC;AAAA,QACF;AAEA,YAAI,sBAAsB;AACzB,4CAAkC,KAAK,OAAO,sBAAsB;AAAA,YACnE,gBAAgB;AAAA,UACjB,CAAC;AAAA,QACF;AAAA,MACD;AAEA,WAAK,QAAQ,YAAY,CAAC,EAAE,MAAAC,MAAK,MAAM;AACtC,aAAK,MAAM,eAAeA,KAAI;AAC9B,cAAMD,OAAMC;AAGZ,cAAM,MAAM,KAAK,MAAM,OAAO,mBAAmBD,KAAI,MAAM;AAE3D,YAAI,CAAC,IAAI,IAAI;AAGZ,gBAAM,gBAAgB,KAAK,IAAI,IAAI,KAAK;AACxC,cAAI,gBAAgB,KAAM;AAMzB,wBAAY,IAAI,MAAM,8DAA8D,CAAC;AACrF;AAAA,UACD;AACA,eAAK,MAAM,WAAW;AACtB,eAAK,cAAc;AACnB,kBAAQ,UAAU,SAAS;AAC3B;AAAA,QACD,WAAW,IAAI,MAAM,SAAS,GAAG;AAEhC,eAAK,MAAM,wBAAwB;AACnC,eAAK,QAAQ,YAAY,EAAE,MAAM,YAAY,QAAQ,KAAK,iBAAiB,CAAC;AAE5E,eAAK,sBAAsB;AAC3B,eAAK,gBAAgB;AACrB;AAAA,QACD;AAEA,YAAIA,KAAI,SAAS,QAAQ;AACxB,eAAK,MAAM,eAAe;AAC1B,mBAAS,MAAM;AACd,iBAAK,MAAM,mBAAmB,MAAM;AACnC,mBAAK,MAAM,UAAUA,KAAI,OAAc;AAAA,YACxC,CAAC;AAAA,UACF,CAAC;AAAA,QACF;AAAA,MACD;AACA,WAAK,QAAQ,YAAY,EAAE,MAAM,YAAY,QAAQ,KAAK,iBAAiB,CAAC;AAC5E,WAAK,YAAY,IAAI,MAAM;AAC1B,aAAK,QAAQ,MAAM;AAAA,MACpB,CAAC;AACD,aAAO,IAAI;AAAA,IACZ,SAAS,GAAQ;AAChB,WAAK,MAAM,iCAAiC,CAAC;AAC7C,UAAI,KAAK,WAAY;AACrB,kBAAY,CAAC;AACb;AAAA,IACD;AAAA,EACD;AAAA,EAEA,QAAQ;AACP,SAAK,MAAM,SAAS;AACpB,SAAK,aAAa;AAClB,SAAK,YAAY,QAAQ,CAAC,MAAM,EAAE,CAAC;AAAA,EACpC;AAAA,EAEQ,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,0BAAgE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQhE,kBAAkB;AACzB,SAAK,MAAM,mBAAmB,KAAK,uBAAuB;AAC1D,QAAI,KAAK,wBAAyB;AAElC,SAAK,0BAA0B;AAAA,MAC9B,MAAM;AACL,aAAK,0BAA0B;AAC/B,aAAK,gBAAgB;AAAA,MACtB;AAAA,MACA,KAAK,oBAAoB,4BAA4B;AAAA,IACtD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,kBAAkB;AACzB,SAAK,MAAM,mBAAmB;AAAA,MAC7B,cAAc,KAAK;AAAA,MACnB,aAAa,KAAK;AAAA,MAClB,qBAAqB,KAAK;AAAA,MAC1B,iBAAiB,KAAK,UAAU;AAAA,MAChC,wBAAwB,KAAK,MAAM,oBAAoB;AAAA,IACxD,CAAC;AAGD,QAAI,KAAK,yBAAyB;AACjC,mBAAa,KAAK,uBAAuB;AACzC,WAAK,0BAA0B;AAAA,IAChC;AAKA,QAAI,KAAK,aAAc;AAIvB,QAAI,KAAK,YAAa;AAGtB,QAAI,KAAK,MAAM,oBAAoB,EAAG;AAGtC,QAAI,KAAK,uBAAuB,KAAK,UAAU,SAAS,GAAG;AAC1D,WAAK,UAAU;AAAA,IAChB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,YAAY;AACzB,WAAO,CAAC,KAAK,cAAc,6BAA6B;AACxD,QAAI,KAAK,WAAY;AACrB,SAAK,eAAe;AAEpB,SAAK,MAAM,iBAAiB;AAI5B,UAAM,YAAY,KAAK;AACvB,SAAK,YAAY,CAAC;AAElB,QAAI;AACH,UAAI,KAAK,qBAAqB;AAC7B,aAAK,sBAAsB;AAC3B,cAAM,KAAK,GAAG,cAAc;AAAA,UAC3B,QAAQ,KAAK,MAAM;AAAA,UACnB,UAAU,KAAK,MAAM,UAAU;AAAA,UAC/B,WAAW,KAAK;AAAA,UAChB,sBAAsB,KAAK,sBAAsB,IAAI;AAAA,QACtD,CAAC;AAAA,MACF,OAAO;AACN,cAAM,QAAQ;AAAA,UACb,UAAU,OAAO,CAAC,MAAuC,MAAM,qBAAqB;AAAA,QACrF;AACA,cAAM,KAAK,GAAG,aAAa;AAAA,UAC1B,SAAS;AAAA,UACT,QAAQ,KAAK,MAAM;AAAA,UACnB,WAAW,KAAK;AAAA,UAChB,sBAAsB,KAAK,sBAAsB,IAAI;AAAA,QACtD,CAAC;AAAA,MACF;AACA,WAAK,oBAAoB;AAAA,IAC1B,SAAS,GAAG;AAGX,WAAK,sBAAsB;AAC3B,WAAK,oBAAoB;AACzB,cAAQ,MAAM,yCAAyC,CAAC;AAExD,kCAA4B;AAC5B,UAAI,OAAO,WAAW,aAAa;AAElC,eAAO,SAAS,OAAO;AAAA,MACxB;AAAA,IACD;AAEA,SAAK,eAAe;AACpB,SAAK,MAAM,eAAe;AAI1B,SAAK,gBAAgB;AAAA,EACtB;AACD;",
|
|
6
6
|
"names": ["msg", "data"]
|
|
7
7
|
}
|
package/dist-esm/version.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const version = "3.
|
|
1
|
+
const version = "3.16.0-next.c30b1b5e551a";
|
|
2
2
|
const publishDates = {
|
|
3
3
|
major: "2024-09-13T14:36:29.063Z",
|
|
4
|
-
minor: "2025-07-
|
|
5
|
-
patch: "2025-07-
|
|
4
|
+
minor: "2025-07-30T09:52:11.036Z",
|
|
5
|
+
patch: "2025-07-30T09:52:11.036Z"
|
|
6
6
|
};
|
|
7
7
|
export {
|
|
8
8
|
publishDates,
|
package/dist-esm/version.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/version.ts"],
|
|
4
|
-
"sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.
|
|
4
|
+
"sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-next.c30b1b5e551a'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-07-30T09:52:11.036Z',\n\tpatch: '2025-07-30T09:52:11.036Z',\n}\n"],
|
|
5
5
|
"mappings": "AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/editor.css
CHANGED
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
--color-text: hsl(0, 0%, 0%);
|
|
168
168
|
--color-text-0: hsl(0, 0%, 11%);
|
|
169
169
|
--color-text-1: hsl(0, 0%, 18%);
|
|
170
|
-
--color-text-3: hsl(
|
|
170
|
+
--color-text-3: hsl(204, 4%, 45%);
|
|
171
171
|
--color-text-shadow: hsl(0, 0%, 100%);
|
|
172
172
|
--color-text-highlight: hsl(52, 100%, 50%);
|
|
173
173
|
--color-text-highlight-p3: color(display-p3 0.972 0.8205 0.05);
|
|
@@ -222,7 +222,7 @@
|
|
|
222
222
|
--color-text: hsl(210, 17%, 98%);
|
|
223
223
|
--color-text-0: hsl(0, 9%, 94%);
|
|
224
224
|
--color-text-1: hsl(0, 0%, 85%);
|
|
225
|
-
--color-text-3: hsl(
|
|
225
|
+
--color-text-3: hsl(204, 4%, 75%);
|
|
226
226
|
--color-text-shadow: hsl(210, 13%, 18%);
|
|
227
227
|
--color-text-highlight: hsl(52, 100%, 41%);
|
|
228
228
|
--color-text-highlight-p3: color(display-p3 0.8078 0.6225 0.0312);
|
|
@@ -774,8 +774,7 @@ input,
|
|
|
774
774
|
position: static;
|
|
775
775
|
}
|
|
776
776
|
|
|
777
|
-
.tl-text-wrapper[data-isediting='false'] .tl-text-input
|
|
778
|
-
.tl-arrow-label[data-isediting='false'] .tl-text-input {
|
|
777
|
+
.tl-text-wrapper[data-isediting='false'] .tl-text-input {
|
|
779
778
|
opacity: 0;
|
|
780
779
|
cursor: var(--tl-cursor-default);
|
|
781
780
|
}
|
|
@@ -968,14 +967,14 @@ input,
|
|
|
968
967
|
font-size: 14px;
|
|
969
968
|
font-weight: 500;
|
|
970
969
|
opacity: 0;
|
|
971
|
-
animation: fade-in 0.2s ease-in-out forwards;
|
|
970
|
+
animation: tl-fade-in 0.2s ease-in-out forwards;
|
|
972
971
|
animation-delay: 0.2s;
|
|
973
972
|
position: absolute;
|
|
974
973
|
inset: 0px;
|
|
975
974
|
z-index: var(--layer-canvas-blocker);
|
|
976
975
|
}
|
|
977
976
|
|
|
978
|
-
@keyframes fade-in {
|
|
977
|
+
@keyframes tl-fade-in {
|
|
979
978
|
0% {
|
|
980
979
|
opacity: 0;
|
|
981
980
|
}
|
|
@@ -984,6 +983,19 @@ input,
|
|
|
984
983
|
}
|
|
985
984
|
}
|
|
986
985
|
|
|
986
|
+
.tl-spinner {
|
|
987
|
+
animation: tl-spin 1s linear infinite;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
@keyframes tl-spin {
|
|
991
|
+
0% {
|
|
992
|
+
transform: rotate(0deg);
|
|
993
|
+
}
|
|
994
|
+
100% {
|
|
995
|
+
transform: rotate(360deg);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
|
|
987
999
|
/* ---------------------- Brush --------------------- */
|
|
988
1000
|
|
|
989
1001
|
.tl-brush {
|
|
@@ -1175,7 +1187,7 @@ input,
|
|
|
1175
1187
|
|
|
1176
1188
|
/* --------------------- Arrow shape -------------------- */
|
|
1177
1189
|
|
|
1178
|
-
.tl-arrow-label {
|
|
1190
|
+
.tl-shape[data-shape-type='arrow'] .tl-text-label {
|
|
1179
1191
|
position: absolute;
|
|
1180
1192
|
top: -1px;
|
|
1181
1193
|
left: -1px;
|
|
@@ -1190,33 +1202,15 @@ input,
|
|
|
1190
1202
|
text-shadow: var(--tl-text-outline);
|
|
1191
1203
|
}
|
|
1192
1204
|
|
|
1193
|
-
.tl-
|
|
1194
|
-
opacity: 0;
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
.tl-arrow-label__inner {
|
|
1205
|
+
.tl-shape[data-shape-type='arrow'] .tl-text-label__inner {
|
|
1198
1206
|
border-radius: var(--radius-1);
|
|
1199
1207
|
box-sizing: content-box;
|
|
1200
|
-
position: relative;
|
|
1201
1208
|
height: max-content;
|
|
1202
1209
|
width: max-content;
|
|
1203
|
-
pointer-events: none;
|
|
1204
|
-
display: flex;
|
|
1205
|
-
justify-content: center;
|
|
1206
|
-
align-items: center;
|
|
1207
1210
|
}
|
|
1208
1211
|
|
|
1209
|
-
.tl-arrow
|
|
1210
|
-
position: relative;
|
|
1212
|
+
.tl-shape[data-shape-type='arrow'] .tl-text {
|
|
1211
1213
|
height: max-content;
|
|
1212
|
-
padding: inherit;
|
|
1213
|
-
overflow: visible;
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
.tl-arrow-label textarea {
|
|
1217
|
-
padding: inherit;
|
|
1218
|
-
/* Don't allow textarea to be zero width */
|
|
1219
|
-
min-width: 4px;
|
|
1220
1214
|
}
|
|
1221
1215
|
|
|
1222
1216
|
.tl-arrow-hint {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tldraw/editor",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "3.
|
|
3
|
+
"description": "tldraw infinite canvas SDK (editor).",
|
|
4
|
+
"version": "3.16.0-next.c30b1b5e551a",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tldraw Inc.",
|
|
7
7
|
"email": "hello@tldraw.com"
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"keywords": [
|
|
19
19
|
"tldraw",
|
|
20
|
+
"sdk",
|
|
20
21
|
"drawing",
|
|
21
22
|
"app",
|
|
22
23
|
"development",
|
|
@@ -48,12 +49,12 @@
|
|
|
48
49
|
"@tiptap/core": "^2.9.1",
|
|
49
50
|
"@tiptap/pm": "^2.9.1",
|
|
50
51
|
"@tiptap/react": "^2.9.1",
|
|
51
|
-
"@tldraw/state": "3.
|
|
52
|
-
"@tldraw/state-react": "3.
|
|
53
|
-
"@tldraw/store": "3.
|
|
54
|
-
"@tldraw/tlschema": "3.
|
|
55
|
-
"@tldraw/utils": "3.
|
|
56
|
-
"@tldraw/validate": "3.
|
|
52
|
+
"@tldraw/state": "3.16.0-next.c30b1b5e551a",
|
|
53
|
+
"@tldraw/state-react": "3.16.0-next.c30b1b5e551a",
|
|
54
|
+
"@tldraw/store": "3.16.0-next.c30b1b5e551a",
|
|
55
|
+
"@tldraw/tlschema": "3.16.0-next.c30b1b5e551a",
|
|
56
|
+
"@tldraw/utils": "3.16.0-next.c30b1b5e551a",
|
|
57
|
+
"@tldraw/validate": "3.16.0-next.c30b1b5e551a",
|
|
57
58
|
"@types/core-js": "^2.5.8",
|
|
58
59
|
"@use-gesture/react": "^10.3.1",
|
|
59
60
|
"classnames": "^2.5.1",
|
package/src/index.ts
CHANGED
|
@@ -18,27 +18,6 @@ export * from '@tldraw/utils'
|
|
|
18
18
|
// eslint-disable-next-line local/no-export-star
|
|
19
19
|
export * from '@tldraw/validate'
|
|
20
20
|
|
|
21
|
-
export {
|
|
22
|
-
ErrorScreen,
|
|
23
|
-
LoadingScreen,
|
|
24
|
-
TldrawEditor,
|
|
25
|
-
useOnMount,
|
|
26
|
-
type LoadingScreenProps,
|
|
27
|
-
type TLOnMountHandler,
|
|
28
|
-
type TldrawEditorBaseProps,
|
|
29
|
-
type TldrawEditorProps,
|
|
30
|
-
type TldrawEditorStoreProps,
|
|
31
|
-
type TldrawEditorWithStoreProps,
|
|
32
|
-
type TldrawEditorWithoutStoreProps,
|
|
33
|
-
} from './lib/TldrawEditor'
|
|
34
|
-
export {
|
|
35
|
-
ErrorBoundary,
|
|
36
|
-
OptionalErrorBoundary,
|
|
37
|
-
type TLErrorBoundaryProps,
|
|
38
|
-
} from './lib/components/ErrorBoundary'
|
|
39
|
-
export { HTMLContainer, type HTMLContainerProps } from './lib/components/HTMLContainer'
|
|
40
|
-
export { MenuClickCapture } from './lib/components/MenuClickCapture'
|
|
41
|
-
export { SVGContainer, type SVGContainerProps } from './lib/components/SVGContainer'
|
|
42
21
|
export { DefaultBackground } from './lib/components/default-components/DefaultBackground'
|
|
43
22
|
export { DefaultBrush, type TLBrushProps } from './lib/components/default-components/DefaultBrush'
|
|
44
23
|
export {
|
|
@@ -88,12 +67,36 @@ export {
|
|
|
88
67
|
DefaultShapeIndicators,
|
|
89
68
|
type TLShapeIndicatorsProps,
|
|
90
69
|
} from './lib/components/default-components/DefaultShapeIndicators'
|
|
70
|
+
export {
|
|
71
|
+
DefaultShapeWrapper,
|
|
72
|
+
type TLShapeWrapperProps,
|
|
73
|
+
} from './lib/components/default-components/DefaultShapeWrapper'
|
|
91
74
|
export {
|
|
92
75
|
DefaultSnapIndicator,
|
|
93
76
|
type TLSnapIndicatorProps,
|
|
94
77
|
} from './lib/components/default-components/DefaultSnapIndictor'
|
|
95
78
|
export { DefaultSpinner } from './lib/components/default-components/DefaultSpinner'
|
|
96
79
|
export { DefaultSvgDefs } from './lib/components/default-components/DefaultSvgDefs'
|
|
80
|
+
export {
|
|
81
|
+
ErrorBoundary,
|
|
82
|
+
OptionalErrorBoundary,
|
|
83
|
+
type TLErrorBoundaryProps,
|
|
84
|
+
} from './lib/components/ErrorBoundary'
|
|
85
|
+
export { HTMLContainer, type HTMLContainerProps } from './lib/components/HTMLContainer'
|
|
86
|
+
export { MenuClickCapture } from './lib/components/MenuClickCapture'
|
|
87
|
+
export { SVGContainer, type SVGContainerProps } from './lib/components/SVGContainer'
|
|
88
|
+
export {
|
|
89
|
+
createTLSchemaFromUtils,
|
|
90
|
+
createTLStore,
|
|
91
|
+
inlineBase64AssetStore,
|
|
92
|
+
type TLStoreBaseOptions,
|
|
93
|
+
type TLStoreEventInfo,
|
|
94
|
+
type TLStoreOptions,
|
|
95
|
+
type TLStoreSchemaOptions,
|
|
96
|
+
} from './lib/config/createTLStore'
|
|
97
|
+
export { createTLUser, useTldrawUser, type TLUser } from './lib/config/createTLUser'
|
|
98
|
+
export { type TLAnyBindingUtilConstructor } from './lib/config/defaultBindings'
|
|
99
|
+
export { coreShapes, type TLAnyShapeUtilConstructor } from './lib/config/defaultShapes'
|
|
97
100
|
export {
|
|
98
101
|
getSnapshot,
|
|
99
102
|
loadSnapshot,
|
|
@@ -101,42 +104,23 @@ export {
|
|
|
101
104
|
type TLLoadSnapshotOptions,
|
|
102
105
|
} from './lib/config/TLEditorSnapshot'
|
|
103
106
|
export {
|
|
104
|
-
TAB_ID,
|
|
105
107
|
createSessionStateSnapshotSignal,
|
|
106
108
|
extractSessionStateFromLegacySnapshot,
|
|
107
109
|
loadSessionStateSnapshotIntoStore,
|
|
110
|
+
TAB_ID,
|
|
108
111
|
type TLLoadSessionStateSnapshotOptions,
|
|
109
112
|
type TLSessionStateSnapshot,
|
|
110
113
|
} from './lib/config/TLSessionStateSnapshot'
|
|
111
114
|
export {
|
|
112
|
-
USER_COLORS,
|
|
113
115
|
defaultUserPreferences,
|
|
114
116
|
getFreshUserPreferences,
|
|
115
117
|
getUserPreferences,
|
|
116
118
|
setUserPreferences,
|
|
119
|
+
USER_COLORS,
|
|
117
120
|
userTypeValidator,
|
|
118
121
|
type TLUserPreferences,
|
|
119
122
|
} from './lib/config/TLUserPreferences'
|
|
120
|
-
export {
|
|
121
|
-
createTLSchemaFromUtils,
|
|
122
|
-
createTLStore,
|
|
123
|
-
inlineBase64AssetStore,
|
|
124
|
-
type TLStoreBaseOptions,
|
|
125
|
-
type TLStoreEventInfo,
|
|
126
|
-
type TLStoreOptions,
|
|
127
|
-
type TLStoreSchemaOptions,
|
|
128
|
-
} from './lib/config/createTLStore'
|
|
129
|
-
export { createTLUser, useTldrawUser, type TLUser } from './lib/config/createTLUser'
|
|
130
|
-
export { type TLAnyBindingUtilConstructor } from './lib/config/defaultBindings'
|
|
131
|
-
export { coreShapes, type TLAnyShapeUtilConstructor } from './lib/config/defaultShapes'
|
|
132
123
|
export { DEFAULT_ANIMATION_OPTIONS, DEFAULT_CAMERA_OPTIONS, SIDES } from './lib/constants'
|
|
133
|
-
export {
|
|
134
|
-
Editor,
|
|
135
|
-
type TLEditorOptions,
|
|
136
|
-
type TLEditorRunOptions,
|
|
137
|
-
type TLRenderingShape,
|
|
138
|
-
type TLResizeShapeOptions,
|
|
139
|
-
} from './lib/editor/Editor'
|
|
140
124
|
export {
|
|
141
125
|
BindingUtil,
|
|
142
126
|
type BindingOnChangeOptions,
|
|
@@ -147,6 +131,13 @@ export {
|
|
|
147
131
|
type BindingOnShapeIsolateOptions,
|
|
148
132
|
type TLBindingUtilConstructor,
|
|
149
133
|
} from './lib/editor/bindings/BindingUtil'
|
|
134
|
+
export {
|
|
135
|
+
Editor,
|
|
136
|
+
type TLEditorOptions,
|
|
137
|
+
type TLEditorRunOptions,
|
|
138
|
+
type TLRenderingShape,
|
|
139
|
+
type TLResizeShapeOptions,
|
|
140
|
+
} from './lib/editor/Editor'
|
|
150
141
|
export { ClickManager, type TLClickState } from './lib/editor/managers/ClickManager/ClickManager'
|
|
151
142
|
export { EdgeScrollManager } from './lib/editor/managers/EdgeScrollManager/EdgeScrollManager'
|
|
152
143
|
export {
|
|
@@ -179,6 +170,7 @@ export {
|
|
|
179
170
|
} from './lib/editor/managers/TextManager/TextManager'
|
|
180
171
|
export { UserPreferencesManager } from './lib/editor/managers/UserPreferencesManager/UserPreferencesManager'
|
|
181
172
|
export { BaseBoxShapeUtil, type TLBaseBoxShape } from './lib/editor/shapes/BaseBoxShapeUtil'
|
|
173
|
+
export { GroupShapeUtil } from './lib/editor/shapes/group/GroupShapeUtil'
|
|
182
174
|
export {
|
|
183
175
|
ShapeUtil,
|
|
184
176
|
type TLCropInfo,
|
|
@@ -195,7 +187,6 @@ export {
|
|
|
195
187
|
type TLShapeUtilCanvasSvgDef,
|
|
196
188
|
type TLShapeUtilConstructor,
|
|
197
189
|
} from './lib/editor/shapes/ShapeUtil'
|
|
198
|
-
export { GroupShapeUtil } from './lib/editor/shapes/group/GroupShapeUtil'
|
|
199
190
|
export {
|
|
200
191
|
getPerfectDashProps,
|
|
201
192
|
type PerfectDashTerminal,
|
|
@@ -205,22 +196,16 @@ export { resizeScaled } from './lib/editor/shapes/shared/resizeScaled'
|
|
|
205
196
|
export { BaseBoxShapeTool } from './lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool'
|
|
206
197
|
export { maybeSnapToGrid } from './lib/editor/tools/BaseBoxShapeTool/children/Pointing'
|
|
207
198
|
export { StateNode, type TLStateNodeConstructor } from './lib/editor/tools/StateNode'
|
|
208
|
-
export {
|
|
209
|
-
useDelaySvgExport,
|
|
210
|
-
useSvgExportContext,
|
|
211
|
-
type SvgExportContext,
|
|
212
|
-
type SvgExportDef,
|
|
213
|
-
} from './lib/editor/types/SvgExportContext'
|
|
214
199
|
export { type TLContent } from './lib/editor/types/clipboard-types'
|
|
215
200
|
export { type TLEventMap, type TLEventMapHandler } from './lib/editor/types/emit-types'
|
|
216
201
|
export {
|
|
217
202
|
EVENT_NAME_MAP,
|
|
218
203
|
type TLBaseEventInfo,
|
|
219
|
-
type TLCLickEventName,
|
|
220
204
|
type TLCancelEvent,
|
|
221
205
|
type TLCancelEventInfo,
|
|
222
206
|
type TLClickEvent,
|
|
223
207
|
type TLClickEventInfo,
|
|
208
|
+
type TLCLickEventName,
|
|
224
209
|
type TLCompleteEvent,
|
|
225
210
|
type TLCompleteEventInfo,
|
|
226
211
|
type TLEnterEventHandler,
|
|
@@ -283,12 +268,19 @@ export {
|
|
|
283
268
|
type TLImageExportOptions,
|
|
284
269
|
type TLSvgExportOptions,
|
|
285
270
|
type TLSvgOptions,
|
|
271
|
+
type TLUpdatePointerOptions,
|
|
286
272
|
} from './lib/editor/types/misc-types'
|
|
287
273
|
export {
|
|
288
274
|
type TLAdjacentDirection,
|
|
289
275
|
type TLResizeHandle,
|
|
290
276
|
type TLSelectionHandle,
|
|
291
277
|
} from './lib/editor/types/selection-types'
|
|
278
|
+
export {
|
|
279
|
+
useDelaySvgExport,
|
|
280
|
+
useSvgExportContext,
|
|
281
|
+
type SvgExportContext,
|
|
282
|
+
type SvgExportDef,
|
|
283
|
+
} from './lib/editor/types/SvgExportContext'
|
|
292
284
|
export { getSvgAsImage } from './lib/exports/getSvgAsImage'
|
|
293
285
|
export { tlenv } from './lib/globals/environment'
|
|
294
286
|
export { tlmenus } from './lib/globals/menus'
|
|
@@ -352,8 +344,6 @@ export {
|
|
|
352
344
|
type SelectionEdge,
|
|
353
345
|
type SelectionHandle,
|
|
354
346
|
} from './lib/primitives/Box'
|
|
355
|
-
export { Mat, type MatLike, type MatModel } from './lib/primitives/Mat'
|
|
356
|
-
export { Vec, type VecLike } from './lib/primitives/Vec'
|
|
357
347
|
export { EASINGS } from './lib/primitives/easings'
|
|
358
348
|
export { Arc2d } from './lib/primitives/geometry/Arc2d'
|
|
359
349
|
export { Circle2d } from './lib/primitives/geometry/Circle2d'
|
|
@@ -361,6 +351,7 @@ export { CubicBezier2d } from './lib/primitives/geometry/CubicBezier2d'
|
|
|
361
351
|
export { CubicSpline2d } from './lib/primitives/geometry/CubicSpline2d'
|
|
362
352
|
export { Edge2d } from './lib/primitives/geometry/Edge2d'
|
|
363
353
|
export { Ellipse2d } from './lib/primitives/geometry/Ellipse2d'
|
|
354
|
+
export { getVerticesCountForArcLength } from './lib/primitives/geometry/geometry-constants'
|
|
364
355
|
export {
|
|
365
356
|
Geometry2d,
|
|
366
357
|
Geometry2dFilters,
|
|
@@ -388,11 +379,8 @@ export {
|
|
|
388
379
|
polygonIntersectsPolyline,
|
|
389
380
|
polygonsIntersect,
|
|
390
381
|
} from './lib/primitives/intersect'
|
|
382
|
+
export { Mat, type MatLike, type MatModel } from './lib/primitives/Mat'
|
|
391
383
|
export {
|
|
392
|
-
HALF_PI,
|
|
393
|
-
PI,
|
|
394
|
-
PI2,
|
|
395
|
-
SIN,
|
|
396
384
|
angleDistance,
|
|
397
385
|
approximately,
|
|
398
386
|
areAnglesCompatible,
|
|
@@ -409,23 +397,36 @@ export {
|
|
|
409
397
|
getPointOnCircle,
|
|
410
398
|
getPointsOnArc,
|
|
411
399
|
getPolygonVertices,
|
|
400
|
+
HALF_PI,
|
|
412
401
|
isSafeFloat,
|
|
413
402
|
perimeterOfEllipse,
|
|
403
|
+
PI,
|
|
404
|
+
PI2,
|
|
414
405
|
pointInPolygon,
|
|
415
406
|
precise,
|
|
416
407
|
radiansToDegrees,
|
|
417
408
|
rangeIntersection,
|
|
418
409
|
shortAngleDist,
|
|
410
|
+
SIN,
|
|
419
411
|
snapAngle,
|
|
420
412
|
toDomPrecision,
|
|
421
413
|
toFixed,
|
|
422
414
|
toPrecision,
|
|
423
415
|
} from './lib/primitives/utils'
|
|
416
|
+
export { Vec, type VecLike } from './lib/primitives/Vec'
|
|
424
417
|
export {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
418
|
+
ErrorScreen,
|
|
419
|
+
LoadingScreen,
|
|
420
|
+
TldrawEditor,
|
|
421
|
+
useOnMount,
|
|
422
|
+
type LoadingScreenProps,
|
|
423
|
+
type TldrawEditorBaseProps,
|
|
424
|
+
type TldrawEditorProps,
|
|
425
|
+
type TldrawEditorStoreProps,
|
|
426
|
+
type TldrawEditorWithoutStoreProps,
|
|
427
|
+
type TldrawEditorWithStoreProps,
|
|
428
|
+
type TLOnMountHandler,
|
|
429
|
+
} from './lib/TldrawEditor'
|
|
429
430
|
export { dataUrlToFile, getDefaultCdnBaseUrl } from './lib/utils/assets'
|
|
430
431
|
export { clampToBrowserMaxCanvasSize, type CanvasMaxSize } from './lib/utils/browserCanvasMaxSize'
|
|
431
432
|
export {
|
|
@@ -461,9 +462,9 @@ export {
|
|
|
461
462
|
getFontsFromRichText,
|
|
462
463
|
type RichTextFontVisitor,
|
|
463
464
|
type RichTextFontVisitorState,
|
|
464
|
-
type TLTextOptions,
|
|
465
465
|
type TiptapEditor,
|
|
466
466
|
type TiptapNode,
|
|
467
|
+
type TLTextOptions,
|
|
467
468
|
} from './lib/utils/richText'
|
|
468
469
|
export {
|
|
469
470
|
applyRotationToSnapshotShapes,
|
|
@@ -471,9 +472,14 @@ export {
|
|
|
471
472
|
type TLRotationSnapshot,
|
|
472
473
|
} from './lib/utils/rotation'
|
|
473
474
|
export { runtime, setRuntimeOverrides } from './lib/utils/runtime'
|
|
475
|
+
export {
|
|
476
|
+
ReadonlySharedStyleMap,
|
|
477
|
+
SharedStyleMap,
|
|
478
|
+
type SharedStyle,
|
|
479
|
+
} from './lib/utils/SharedStylesMap'
|
|
480
|
+
export { hardReset } from './lib/utils/sync/hardReset'
|
|
474
481
|
export { LocalIndexedDb, Table, type StoreName } from './lib/utils/sync/LocalIndexedDb'
|
|
475
482
|
export { type TLStoreWithStatus } from './lib/utils/sync/StoreWithStatus'
|
|
476
|
-
export { hardReset } from './lib/utils/sync/hardReset'
|
|
477
483
|
export { uniq } from './lib/utils/uniq'
|
|
478
484
|
export { openWindow } from './lib/utils/window-open'
|
|
479
485
|
|