@tldraw/editor 4.4.0-next.f181afb0ab39 → 4.4.0
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 +102 -19
- package/dist-cjs/index.js +1 -6
- package/dist-cjs/index.js.map +3 -3
- package/dist-cjs/lib/TldrawEditor.js +20 -8
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/Shape.js +12 -17
- package/dist-cjs/lib/components/Shape.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +26 -1
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +16 -1
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/config/createTLStore.js.map +1 -1
- package/dist-cjs/lib/editor/Editor.js +35 -17
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +32 -13
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +2 -2
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +2 -3
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +13 -38
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +3 -3
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/tools/RootState.js +0 -13
- package/dist-cjs/lib/editor/tools/RootState.js.map +2 -2
- package/dist-cjs/lib/hooks/usePeerIds.js +8 -2
- package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
- package/dist-cjs/lib/hooks/useShapeCulling.js +75 -0
- package/dist-cjs/lib/hooks/useShapeCulling.js.map +7 -0
- package/dist-cjs/lib/license/LicenseManager.js +6 -6
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/options.js +6 -1
- package/dist-cjs/lib/options.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 +102 -19
- package/dist-esm/index.mjs +1 -6
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +20 -8
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/Shape.mjs +12 -17
- package/dist-esm/lib/components/Shape.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +27 -2
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +16 -1
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/config/createTLStore.mjs.map +1 -1
- package/dist-esm/lib/editor/Editor.mjs +35 -17
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +32 -13
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +2 -3
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +14 -39
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/RootState.mjs +0 -13
- package/dist-esm/lib/editor/tools/RootState.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs +8 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
- package/dist-esm/lib/hooks/useShapeCulling.mjs +55 -0
- package/dist-esm/lib/hooks/useShapeCulling.mjs.map +7 -0
- package/dist-esm/lib/license/LicenseManager.mjs +6 -6
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +6 -1
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +22 -11
- package/package.json +10 -13
- package/src/index.ts +0 -5
- package/src/lib/TldrawEditor.tsx +35 -13
- package/src/lib/components/Shape.tsx +15 -16
- package/src/lib/components/default-components/CanvasShapeIndicators.tsx +46 -2
- package/src/lib/components/default-components/DefaultCanvas.tsx +24 -2
- package/src/lib/config/createTLStore.ts +1 -1
- package/src/lib/editor/Editor.ts +62 -19
- package/src/lib/editor/derivations/notVisibleShapes.ts +39 -17
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +0 -35
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +4 -8
- package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +19 -47
- package/src/lib/editor/shapes/ShapeUtil.ts +19 -5
- package/src/lib/editor/tools/RootState.ts +0 -16
- package/src/lib/hooks/usePeerIds.ts +9 -2
- package/src/lib/hooks/useShapeCulling.tsx +98 -0
- package/src/lib/license/LicenseManager.ts +6 -6
- package/src/lib/options.ts +41 -2
- package/src/version.ts +3 -3
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var useShapeCulling_exports = {};
|
|
20
|
+
__export(useShapeCulling_exports, {
|
|
21
|
+
ShapeCullingProvider: () => ShapeCullingProvider,
|
|
22
|
+
useShapeCulling: () => useShapeCulling
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(useShapeCulling_exports);
|
|
25
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
26
|
+
var import_react = require("react");
|
|
27
|
+
var import_dom = require("../utils/dom");
|
|
28
|
+
const ShapeCullingContext = (0, import_react.createContext)(null);
|
|
29
|
+
function ShapeCullingProvider({ children }) {
|
|
30
|
+
const containersRef = (0, import_react.useRef)(/* @__PURE__ */ new Map());
|
|
31
|
+
const register = (0, import_react.useCallback)(
|
|
32
|
+
(id, container, bgContainer, isCulled) => {
|
|
33
|
+
const display = isCulled ? "none" : "block";
|
|
34
|
+
(0, import_dom.setStyleProperty)(container, "display", display);
|
|
35
|
+
(0, import_dom.setStyleProperty)(bgContainer, "display", display);
|
|
36
|
+
containersRef.current.set(id, {
|
|
37
|
+
container,
|
|
38
|
+
bgContainer,
|
|
39
|
+
isCulled
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
[]
|
|
43
|
+
);
|
|
44
|
+
const unregister = (0, import_react.useCallback)((id) => {
|
|
45
|
+
containersRef.current.delete(id);
|
|
46
|
+
}, []);
|
|
47
|
+
const updateCulling = (0, import_react.useCallback)((culledShapes) => {
|
|
48
|
+
for (const [id, entry] of containersRef.current) {
|
|
49
|
+
const shouldBeCulled = culledShapes.has(id);
|
|
50
|
+
if (shouldBeCulled !== entry.isCulled) {
|
|
51
|
+
const display = shouldBeCulled ? "none" : "block";
|
|
52
|
+
(0, import_dom.setStyleProperty)(entry.container, "display", display);
|
|
53
|
+
(0, import_dom.setStyleProperty)(entry.bgContainer, "display", display);
|
|
54
|
+
entry.isCulled = shouldBeCulled;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}, []);
|
|
58
|
+
const value = (0, import_react.useMemo)(
|
|
59
|
+
() => ({
|
|
60
|
+
register,
|
|
61
|
+
unregister,
|
|
62
|
+
updateCulling
|
|
63
|
+
}),
|
|
64
|
+
[register, unregister, updateCulling]
|
|
65
|
+
);
|
|
66
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ShapeCullingContext.Provider, { value, children });
|
|
67
|
+
}
|
|
68
|
+
function useShapeCulling() {
|
|
69
|
+
const context = (0, import_react.useContext)(ShapeCullingContext);
|
|
70
|
+
if (!context) {
|
|
71
|
+
throw new Error("useShapeCulling must be used within ShapeCullingProvider");
|
|
72
|
+
}
|
|
73
|
+
return context;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=useShapeCulling.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/hooks/useShapeCulling.tsx"],
|
|
4
|
+
"sourcesContent": ["import { TLShapeId } from '@tldraw/tlschema'\nimport { createContext, useCallback, useContext, useMemo, useRef } from 'react'\nimport { setStyleProperty } from '../utils/dom'\n\ninterface ShapeContainerEntry {\n\tcontainer: HTMLDivElement\n\tbgContainer: HTMLDivElement | null\n\tisCulled: boolean\n}\n\ninterface ShapeCullingContextValue {\n\tregister(\n\t\tid: TLShapeId,\n\t\tcontainer: HTMLDivElement,\n\t\tbgContainer: HTMLDivElement | null,\n\t\tisCulled: boolean\n\t): void\n\tunregister(id: TLShapeId): void\n\tupdateCulling(culledShapes: Set<TLShapeId>): void\n}\n\nconst ShapeCullingContext = createContext<ShapeCullingContextValue | null>(null)\n\n/** @internal */\nexport interface ShapeCullingProviderProps {\n\tchildren: React.ReactNode\n}\n\n/**\n * Provides centralized culling management for shape containers.\n * This allows a single reactor to update all shape display states\n * instead of each shape having its own subscription.\n *\n * @internal\n */\nexport function ShapeCullingProvider({ children }: ShapeCullingProviderProps) {\n\tconst containersRef = useRef(new Map<TLShapeId, ShapeContainerEntry>())\n\n\tconst register = useCallback(\n\t\t(\n\t\t\tid: TLShapeId,\n\t\t\tcontainer: HTMLDivElement,\n\t\t\tbgContainer: HTMLDivElement | null,\n\t\t\tisCulled: boolean\n\t\t) => {\n\t\t\tconst display = isCulled ? 'none' : 'block'\n\t\t\tsetStyleProperty(container, 'display', display)\n\t\t\tsetStyleProperty(bgContainer, 'display', display)\n\n\t\t\tcontainersRef.current.set(id, {\n\t\t\t\tcontainer,\n\t\t\t\tbgContainer,\n\t\t\t\tisCulled,\n\t\t\t})\n\t\t},\n\t\t[]\n\t)\n\n\tconst unregister = useCallback((id: TLShapeId) => {\n\t\tcontainersRef.current.delete(id)\n\t}, [])\n\n\tconst updateCulling = useCallback((culledShapes: Set<TLShapeId>) => {\n\t\tfor (const [id, entry] of containersRef.current) {\n\t\t\tconst shouldBeCulled = culledShapes.has(id)\n\t\t\tif (shouldBeCulled !== entry.isCulled) {\n\t\t\t\tconst display = shouldBeCulled ? 'none' : 'block'\n\t\t\t\tsetStyleProperty(entry.container, 'display', display)\n\t\t\t\tsetStyleProperty(entry.bgContainer, 'display', display)\n\t\t\t\tentry.isCulled = shouldBeCulled\n\t\t\t}\n\t\t}\n\t}, [])\n\n\tconst value = useMemo(\n\t\t() => ({\n\t\t\tregister,\n\t\t\tunregister,\n\t\t\tupdateCulling,\n\t\t}),\n\t\t[register, unregister, updateCulling]\n\t)\n\n\treturn <ShapeCullingContext.Provider value={value}>{children}</ShapeCullingContext.Provider>\n}\n\n/**\n * Hook to access the shape culling context for container registration.\n *\n * @internal\n */\nexport function useShapeCulling(): ShapeCullingContextValue {\n\tconst context = useContext(ShapeCullingContext)\n\tif (!context) {\n\t\tthrow new Error('useShapeCulling must be used within ShapeCullingProvider')\n\t}\n\treturn context\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmFQ;AAlFR,mBAAwE;AACxE,iBAAiC;AAmBjC,MAAM,0BAAsB,4BAA+C,IAAI;AAcxE,SAAS,qBAAqB,EAAE,SAAS,GAA8B;AAC7E,QAAM,oBAAgB,qBAAO,oBAAI,IAAoC,CAAC;AAEtE,QAAM,eAAW;AAAA,IAChB,CACC,IACA,WACA,aACA,aACI;AACJ,YAAM,UAAU,WAAW,SAAS;AACpC,uCAAiB,WAAW,WAAW,OAAO;AAC9C,uCAAiB,aAAa,WAAW,OAAO;AAEhD,oBAAc,QAAQ,IAAI,IAAI;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF;AAAA,IACA,CAAC;AAAA,EACF;AAEA,QAAM,iBAAa,0BAAY,CAAC,OAAkB;AACjD,kBAAc,QAAQ,OAAO,EAAE;AAAA,EAChC,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAgB,0BAAY,CAAC,iBAAiC;AACnE,eAAW,CAAC,IAAI,KAAK,KAAK,cAAc,SAAS;AAChD,YAAM,iBAAiB,aAAa,IAAI,EAAE;AAC1C,UAAI,mBAAmB,MAAM,UAAU;AACtC,cAAM,UAAU,iBAAiB,SAAS;AAC1C,yCAAiB,MAAM,WAAW,WAAW,OAAO;AACpD,yCAAiB,MAAM,aAAa,WAAW,OAAO;AACtD,cAAM,WAAW;AAAA,MAClB;AAAA,IACD;AAAA,EACD,GAAG,CAAC,CAAC;AAEL,QAAM,YAAQ;AAAA,IACb,OAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,IACA,CAAC,UAAU,YAAY,aAAa;AAAA,EACrC;AAEA,SAAO,4CAAC,oBAAoB,UAApB,EAA6B,OAAe,UAAS;AAC9D;AAOO,SAAS,kBAA4C;AAC3D,QAAM,cAAU,yBAAW,mBAAmB;AAC9C,MAAI,CAAC,SAAS;AACb,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC3E;AACA,SAAO;AACR;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -301,22 +301,22 @@ class LicenseManager {
|
|
|
301
301
|
outputMessages(messages, type = "error") {
|
|
302
302
|
if (this.isTest) return;
|
|
303
303
|
if (this.verbose) {
|
|
304
|
-
this.outputDelimiter();
|
|
304
|
+
this.outputDelimiter(type);
|
|
305
305
|
for (const message of messages) {
|
|
306
|
-
const color = type === "warning" ? "orange" : "crimson";
|
|
307
306
|
const bgColor = type === "warning" ? "orange" : "crimson";
|
|
308
307
|
console.log(
|
|
309
308
|
`%c${message}`,
|
|
310
|
-
`color:
|
|
309
|
+
`color: white; background: ${bgColor}; padding: 2px; border-radius: 3px;`
|
|
311
310
|
);
|
|
312
311
|
}
|
|
313
|
-
this.outputDelimiter();
|
|
312
|
+
this.outputDelimiter(type);
|
|
314
313
|
}
|
|
315
314
|
}
|
|
316
|
-
outputDelimiter() {
|
|
315
|
+
outputDelimiter(type = "error") {
|
|
316
|
+
const bgColor = type === "warning" ? "orange" : "crimson";
|
|
317
317
|
console.log(
|
|
318
318
|
"%c-------------------------------------------------------------------",
|
|
319
|
-
`color: white; background:
|
|
319
|
+
`color: white; background: ${bgColor}; padding: 2px; border-radius: 3px;`
|
|
320
320
|
);
|
|
321
321
|
}
|
|
322
322
|
static className = "tl-watermark_SEE-LICENSE";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/license/LicenseManager.ts"],
|
|
4
|
-
"sourcesContent": ["import { atom } from '@tldraw/state'\nimport { publishDates, version } from '../../version'\nimport { getDefaultCdnBaseUrl } from '../utils/assets'\nimport { importPublicKey, str2ab } from '../utils/licensing'\n\nconst GRACE_PERIOD_DAYS = 30\n\nexport const FLAGS = {\n\t// -- MUTUALLY EXCLUSIVE FLAGS --\n\t// Annual means the license expires after a time period, usually 1 year.\n\tANNUAL_LICENSE: 1,\n\t// Perpetual means the license never expires up to the max supported version.\n\tPERPETUAL_LICENSE: 1 << 1,\n\n\t// -- ADDITIVE FLAGS --\n\t// Internal means the license is for internal use only.\n\tINTERNAL_LICENSE: 1 << 2,\n\t// Watermark means the product is watermarked.\n\tWITH_WATERMARK: 1 << 3,\n\t// Evaluation means the license is for evaluation purposes only.\n\tEVALUATION_LICENSE: 1 << 4,\n\t// Native means the license is for native apps which switches\n\t// on special-case logic.\n\tNATIVE_LICENSE: 1 << 5,\n}\nconst HIGHEST_FLAG = Math.max(...Object.values(FLAGS))\n\nexport const PROPERTIES = {\n\tID: 0,\n\tHOSTS: 1,\n\tFLAGS: 2,\n\tEXPIRY_DATE: 3,\n}\nconst NUMBER_OF_KNOWN_PROPERTIES = Object.keys(PROPERTIES).length\n\nconst LICENSE_EMAIL = 'sales@tldraw.com'\n\nconst WATERMARK_TRACK_SRC = `${getDefaultCdnBaseUrl()}/watermarks/watermark-track.svg`\n\n/** @internal */\nexport interface LicenseInfo {\n\tid: string\n\thosts: string[]\n\tflags: number\n\texpiryDate: string\n}\n\n/** @internal */\nexport type LicenseState =\n\t| 'pending' // License validation is in progress\n\t| 'licensed' // License is valid and active (no restrictions)\n\t| 'licensed-with-watermark' // License is valid but shows watermark (evaluation licenses, WITH_WATERMARK licenses)\n\t| 'unlicensed' // No valid license found or license is invalid (development)\n\t| 'unlicensed-production' // No valid license in production deployment (missing, invalid, or wrong domain)\n\t| 'expired' // License has been expired (30 days past expiration for regular licenses, immediately for evaluation licenses)\n/** @internal */\nexport type InvalidLicenseReason =\n\t| 'invalid-license-key'\n\t| 'no-key-provided'\n\t| 'has-key-development-mode'\n\n/** @internal */\nexport type LicenseFromKeyResult = InvalidLicenseKeyResult | ValidLicenseKeyResult\n\n/** @internal */\nexport interface InvalidLicenseKeyResult {\n\tisLicenseParseable: false\n\treason: InvalidLicenseReason\n}\n\n/** @internal */\nexport interface ValidLicenseKeyResult {\n\tisLicenseParseable: true\n\tlicense: LicenseInfo\n\tisDevelopment: boolean\n\tisDomainValid: boolean\n\texpiryDate: Date\n\tisAnnualLicense: boolean\n\tisAnnualLicenseExpired: boolean\n\tisPerpetualLicense: boolean\n\tisPerpetualLicenseExpired: boolean\n\tisInternalLicense: boolean\n\tisNativeLicense: boolean\n\tisLicensedWithWatermark: boolean\n\tisEvaluationLicense: boolean\n\tisEvaluationLicenseExpired: boolean\n\tdaysSinceExpiry: number\n}\n\n/** @internal */\nexport type TrackType = 'unlicensed' | 'with_watermark' | 'evaluation' | null\n\n/** @internal */\nexport class LicenseManager {\n\tprivate publicKey =\n\t\t'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHJh0uUfxHtCGyerXmmatE368Hd9rI6LH9oPDQihnaCryRFWEVeOvf9U/SPbyxX74LFyJs5tYeAHq5Nc0Ax25LQ'\n\tpublic isDevelopment: boolean\n\tpublic isTest: boolean\n\tpublic isCryptoAvailable: boolean\n\tstate = atom<LicenseState>('license state', 'pending')\n\tpublic verbose = true\n\n\tconstructor(licenseKey: string | undefined, testPublicKey?: string) {\n\t\tthis.isTest = process.env.NODE_ENV === 'test'\n\t\tthis.isDevelopment = this.getIsDevelopment()\n\t\tthis.publicKey = testPublicKey || this.publicKey\n\t\tthis.isCryptoAvailable = !!crypto.subtle\n\n\t\tthis.getLicenseFromKey(licenseKey)\n\t\t\t.then((result) => {\n\t\t\t\tconst licenseState = getLicenseState(\n\t\t\t\t\tresult,\n\t\t\t\t\t(messages: string[]) => this.outputMessages(messages),\n\t\t\t\t\tthis.isDevelopment\n\t\t\t\t)\n\n\t\t\t\tthis.maybeTrack(result, licenseState)\n\n\t\t\t\tthis.state.set(licenseState)\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tconsole.error('License validation failed:', error)\n\t\t\t\tthis.state.set('unlicensed')\n\t\t\t})\n\t}\n\n\tprivate getIsDevelopment() {\n\t\t// If we are using https on a non-localhost domain we assume it's a production env and a development one otherwise\n\t\treturn (\n\t\t\t!['https:', 'vscode-webview:'].includes(window.location.protocol) ||\n\t\t\twindow.location.hostname === 'localhost' ||\n\t\t\tprocess.env.NODE_ENV !== 'production'\n\t\t)\n\t}\n\n\tprivate getTrackType(result: LicenseFromKeyResult, licenseState: LicenseState): TrackType {\n\t\t// Track watermark for unlicensed production deployments\n\t\tif (licenseState === 'unlicensed-production') {\n\t\t\treturn 'unlicensed'\n\t\t}\n\n\t\tif (this.isDevelopment) {\n\t\t\treturn null\n\t\t}\n\n\t\tif (!result.isLicenseParseable) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Track evaluation licenses (for analytics, even though no watermark is shown)\n\t\tif (result.isEvaluationLicense) {\n\t\t\treturn 'evaluation'\n\t\t}\n\n\t\t// Track licenses that show watermarks\n\t\tif (licenseState === 'licensed-with-watermark') {\n\t\t\treturn 'with_watermark'\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate maybeTrack(result: LicenseFromKeyResult, licenseState: LicenseState): void {\n\t\tconst trackType = this.getTrackType(result, licenseState)\n\t\tif (!trackType) {\n\t\t\treturn\n\t\t}\n\n\t\tconst url = new URL(WATERMARK_TRACK_SRC)\n\t\turl.searchParams.set('version', version)\n\t\turl.searchParams.set('license_type', trackType)\n\t\tif ('license' in result) {\n\t\t\turl.searchParams.set('license_id', result.license.id)\n\t\t\tconst sku = this.isFlagEnabled(result.license.flags, FLAGS.EVALUATION_LICENSE)\n\t\t\t\t? 'evaluation'\n\t\t\t\t: this.isFlagEnabled(result.license.flags, FLAGS.ANNUAL_LICENSE)\n\t\t\t\t\t? 'annual'\n\t\t\t\t\t: this.isFlagEnabled(result.license.flags, FLAGS.PERPETUAL_LICENSE)\n\t\t\t\t\t\t? 'perpetual'\n\t\t\t\t\t\t: 'unknown'\n\t\t\turl.searchParams.set('sku', sku)\n\t\t}\n\t\turl.searchParams.set('url', window.location.href)\n\t\tif (process.env.NODE_ENV) {\n\t\t\turl.searchParams.set('environment', process.env.NODE_ENV)\n\t\t}\n\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tfetch(url.toString())\n\t}\n\n\tprivate async extractLicenseKey(licenseKey: string): Promise<LicenseInfo> {\n\t\tconst [data, signature] = licenseKey.split('.')\n\t\tconst [prefix, encodedData] = data.split('/')\n\n\t\tif (!prefix.startsWith('tldraw-')) {\n\t\t\tthrow new Error(`Unsupported prefix '${prefix}'`)\n\t\t}\n\n\t\tconst publicCryptoKey = await importPublicKey(this.publicKey)\n\n\t\tlet isVerified\n\t\ttry {\n\t\t\tisVerified = await crypto.subtle.verify(\n\t\t\t\t{\n\t\t\t\t\tname: 'ECDSA',\n\t\t\t\t\thash: { name: 'SHA-256' },\n\t\t\t\t},\n\t\t\t\tpublicCryptoKey,\n\t\t\t\tnew Uint8Array(str2ab(atob(signature))),\n\t\t\t\tnew Uint8Array(str2ab(atob(encodedData)))\n\t\t\t)\n\t\t} catch (e) {\n\t\t\tconsole.error(e)\n\t\t\tthrow new Error('Could not perform signature validation')\n\t\t}\n\n\t\tif (!isVerified) {\n\t\t\tthrow new Error('Invalid signature')\n\t\t}\n\n\t\tlet decodedData: any\n\t\ttry {\n\t\t\tdecodedData = JSON.parse(atob(encodedData))\n\t\t} catch {\n\t\t\tthrow new Error('Could not parse object')\n\t\t}\n\t\tif (decodedData.length > NUMBER_OF_KNOWN_PROPERTIES) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'License key contains some unknown properties.',\n\t\t\t\t'You may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t])\n\t\t}\n\n\t\treturn {\n\t\t\tid: decodedData[PROPERTIES.ID],\n\t\t\thosts: decodedData[PROPERTIES.HOSTS],\n\t\t\tflags: decodedData[PROPERTIES.FLAGS],\n\t\t\texpiryDate: decodedData[PROPERTIES.EXPIRY_DATE],\n\t\t}\n\t}\n\n\tasync getLicenseFromKey(licenseKey?: string): Promise<LicenseFromKeyResult> {\n\t\tif (!licenseKey) {\n\t\t\tif (!this.isDevelopment) {\n\t\t\t\tthis.outputNoLicenseKeyProvided()\n\t\t\t}\n\n\t\t\treturn { isLicenseParseable: false, reason: 'no-key-provided' }\n\t\t}\n\n\t\tif (this.isDevelopment && !this.isCryptoAvailable) {\n\t\t\tif (this.verbose) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t'tldraw: you seem to be in a development environment that does not support crypto. License not verified.'\n\t\t\t\t)\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log('You should check that this works in production separately.')\n\t\t\t}\n\t\t\t// We can't parse the license if we are in development mode since crypto\n\t\t\t// is not available on http\n\t\t\treturn { isLicenseParseable: false, reason: 'has-key-development-mode' }\n\t\t}\n\n\t\t// Borrowed idea from AG Grid:\n\t\t// Copying from various sources (like PDFs) can include zero-width characters.\n\t\t// This helps makes sure the key validation doesn't fail.\n\t\tlet cleanedLicenseKey = licenseKey.replace(/[\\u200B-\\u200D\\uFEFF]/g, '')\n\t\tcleanedLicenseKey = cleanedLicenseKey.replace(/\\r?\\n|\\r/g, '')\n\n\t\ttry {\n\t\t\tconst licenseInfo = await this.extractLicenseKey(cleanedLicenseKey)\n\t\t\tconst expiryDate = new Date(licenseInfo.expiryDate)\n\t\t\tconst isAnnualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.ANNUAL_LICENSE)\n\t\t\tconst isPerpetualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.PERPETUAL_LICENSE)\n\n\t\t\tconst isEvaluationLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.EVALUATION_LICENSE)\n\t\t\tconst daysSinceExpiry = this.getDaysSinceExpiry(expiryDate)\n\n\t\t\tconst result: ValidLicenseKeyResult = {\n\t\t\t\tlicense: licenseInfo,\n\t\t\t\tisLicenseParseable: true,\n\t\t\t\tisDevelopment: this.isDevelopment,\n\t\t\t\tisDomainValid: this.isDomainValid(licenseInfo),\n\t\t\t\texpiryDate,\n\t\t\t\tisAnnualLicense,\n\t\t\t\tisAnnualLicenseExpired: isAnnualLicense && this.isAnnualLicenseExpired(expiryDate),\n\t\t\t\tisPerpetualLicense,\n\t\t\t\tisPerpetualLicenseExpired: isPerpetualLicense && this.isPerpetualLicenseExpired(expiryDate),\n\t\t\t\tisInternalLicense: this.isFlagEnabled(licenseInfo.flags, FLAGS.INTERNAL_LICENSE),\n\t\t\t\tisNativeLicense: this.isNativeLicense(licenseInfo),\n\t\t\t\tisLicensedWithWatermark: this.isFlagEnabled(licenseInfo.flags, FLAGS.WITH_WATERMARK),\n\t\t\t\tisEvaluationLicense,\n\t\t\t\tisEvaluationLicenseExpired:\n\t\t\t\t\tisEvaluationLicense && this.isEvaluationLicenseExpired(expiryDate),\n\t\t\t\tdaysSinceExpiry,\n\t\t\t}\n\t\t\tthis.outputLicenseInfoIfNeeded(result)\n\n\t\t\treturn result\n\t\t} catch (e: any) {\n\t\t\tthis.outputInvalidLicenseKey(e.message)\n\t\t\t// If the license can't be parsed, it's invalid\n\t\t\treturn { isLicenseParseable: false, reason: 'invalid-license-key' }\n\t\t}\n\t}\n\n\tprivate isDomainValid(licenseInfo: LicenseInfo) {\n\t\tconst currentHostname = window.location.hostname.toLowerCase()\n\n\t\treturn licenseInfo.hosts.some((host) => {\n\t\t\tconst normalizedHostOrUrlRegex = host.toLowerCase().trim()\n\n\t\t\t// Allow the domain if listed and www variations, 'example.com' allows 'example.com' and 'www.example.com'\n\t\t\tif (\n\t\t\t\tnormalizedHostOrUrlRegex === currentHostname ||\n\t\t\t\t`www.${normalizedHostOrUrlRegex}` === currentHostname ||\n\t\t\t\tnormalizedHostOrUrlRegex === `www.${currentHostname}`\n\t\t\t) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// If host is '*', we allow all domains.\n\t\t\tif (host === '*') {\n\t\t\t\t// All domains allowed.\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Native license support\n\t\t\t// In this case, `normalizedHost` is actually a protocol, e.g. `app-bundle:`\n\t\t\tif (this.isNativeLicense(licenseInfo)) {\n\t\t\t\treturn new RegExp(normalizedHostOrUrlRegex).test(window.location.href)\n\t\t\t}\n\n\t\t\t// Glob testing, we only support '*.somedomain.com' right now.\n\t\t\tif (host.includes('*')) {\n\t\t\t\tconst globToRegex = new RegExp(host.replace(/\\*/g, '.*?'))\n\t\t\t\treturn globToRegex.test(currentHostname) || globToRegex.test(`www.${currentHostname}`)\n\t\t\t}\n\n\t\t\t// VSCode support\n\t\t\tif (window.location.protocol === 'vscode-webview:') {\n\t\t\t\tconst currentUrl = new URL(window.location.href)\n\t\t\t\tconst extensionId = currentUrl.searchParams.get('extensionId')\n\t\t\t\tif (normalizedHostOrUrlRegex === extensionId) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false\n\t\t})\n\t}\n\n\tprivate isNativeLicense(licenseInfo: LicenseInfo) {\n\t\treturn this.isFlagEnabled(licenseInfo.flags, FLAGS.NATIVE_LICENSE)\n\t}\n\n\tprivate getExpirationDateWithoutGracePeriod(expiryDate: Date) {\n\t\treturn new Date(expiryDate.getFullYear(), expiryDate.getMonth(), expiryDate.getDate())\n\t}\n\n\tprivate getExpirationDateWithGracePeriod(expiryDate: Date) {\n\t\treturn new Date(\n\t\t\texpiryDate.getFullYear(),\n\t\t\texpiryDate.getMonth(),\n\t\t\texpiryDate.getDate() + GRACE_PERIOD_DAYS + 1 // Add 1 day to include the expiration day\n\t\t)\n\t}\n\n\tprivate isAnnualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\treturn new Date() >= expiration\n\t}\n\n\tprivate isPerpetualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\tconst dates = {\n\t\t\tmajor: new Date(publishDates.major),\n\t\t\tminor: new Date(publishDates.minor),\n\t\t}\n\t\t// We allow patch releases, but the major and minor releases should be within the expiration date\n\t\treturn dates.major >= expiration || dates.minor >= expiration\n\t}\n\n\tprivate getDaysSinceExpiry(expiryDate: Date): number {\n\t\tconst now = new Date()\n\t\tconst expiration = this.getExpirationDateWithoutGracePeriod(expiryDate)\n\t\tconst diffTime = now.getTime() - expiration.getTime()\n\t\tconst diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24))\n\t\treturn Math.max(0, diffDays)\n\t}\n\n\tprivate isEvaluationLicenseExpired(expiryDate: Date): boolean {\n\t\t// Evaluation licenses have no grace period - they expire immediately\n\t\tconst now = new Date()\n\t\tconst expiration = this.getExpirationDateWithoutGracePeriod(expiryDate)\n\t\treturn now >= expiration\n\t}\n\n\tprivate isFlagEnabled(flags: number, flag: number) {\n\t\treturn (flags & flag) === flag\n\t}\n\n\tprivate outputNoLicenseKeyProvided() {\n\t\t// Noop, we don't need to show this message.\n\t\t// this.outputMessages([\n\t\t// \t'No tldraw license key provided!',\n\t\t// \t`Please reach out to ${LICENSE_EMAIL} if you would like to license tldraw or if you'd like a trial.`,\n\t\t// ])\n\t}\n\n\tprivate outputInvalidLicenseKey(msg: string) {\n\t\tthis.outputMessages(['Invalid tldraw license key', `Reason: ${msg}`])\n\t}\n\n\tprivate outputLicenseInfoIfNeeded(result: ValidLicenseKeyResult) {\n\t\t// If we added a new flag it will be twice the value of the currently highest flag.\n\t\t// And if all the current flags are on we would get the `HIGHEST_FLAG * 2 - 1`, so anything higher than that means there are new flags.\n\t\tif (result.license.flags >= HIGHEST_FLAG * 2) {\n\t\t\tthis.outputMessages(\n\t\t\t\t[\n\t\t\t\t\t'Warning: This tldraw license contains some unknown flags.',\n\t\t\t\t\t'This will still work, however, you may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t\t],\n\t\t\t\t'warning'\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate outputMessages(messages: string[], type: 'warning' | 'error' = 'error') {\n\t\tif (this.isTest) return\n\t\tif (this.verbose) {\n\t\t\tthis.outputDelimiter()\n\t\t\tfor (const message of messages) {\n\t\t\t\tconst color = type === 'warning' ? 'orange' : 'crimson'\n\t\t\t\tconst bgColor = type === 'warning' ? 'orange' : 'crimson'\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t`%c${message}`,\n\t\t\t\t\t`color: ${color}; background: ${bgColor}; padding: 2px; border-radius: 3px;`\n\t\t\t\t)\n\t\t\t}\n\t\t\tthis.outputDelimiter()\n\t\t}\n\t}\n\n\tprivate outputDelimiter() {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(\n\t\t\t'%c-------------------------------------------------------------------',\n\t\t\t`color: white; background: crimson; padding: 2px; border-radius: 3px;`\n\t\t)\n\t}\n\n\tstatic className = 'tl-watermark_SEE-LICENSE'\n}\n\nexport function getLicenseState(\n\tresult: LicenseFromKeyResult,\n\toutputMessages: (messages: string[]) => void,\n\tisDevelopment: boolean\n): LicenseState {\n\tif (!result.isLicenseParseable) {\n\t\tif (isDevelopment) {\n\t\t\treturn 'unlicensed'\n\t\t}\n\n\t\t// All unlicensed scenarios should not work in production\n\t\tif (result.reason === 'no-key-provided') {\n\t\t\toutputMessages([\n\t\t\t\t'No tldraw license key provided!',\n\t\t\t\t'A license is required for production deployments.',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t\t])\n\t\t} else {\n\t\t\toutputMessages([\n\t\t\t\t'Invalid license key. tldraw requires a valid license for production use.',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t\t])\n\t\t}\n\t\treturn 'unlicensed-production'\n\t}\n\n\tif (!result.isDomainValid && !result.isDevelopment) {\n\t\toutputMessages([\n\t\t\t'License key is not valid for this domain.',\n\t\t\t'A license is required for production deployments.',\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t])\n\t\treturn 'unlicensed-production'\n\t}\n\n\t// Handle evaluation licenses - they expire immediately with no grace period\n\tif (result.isEvaluationLicense) {\n\t\tif (result.isEvaluationLicenseExpired) {\n\t\t\toutputMessages([\n\t\t\t\t'Your tldraw evaluation license has expired!',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a full license.`,\n\t\t\t])\n\t\t\treturn 'expired'\n\t\t} else {\n\t\t\t// Valid evaluation license - tracked but no watermark shown\n\t\t\treturn 'licensed'\n\t\t}\n\t}\n\n\t// Handle expired regular licenses (both annual and perpetual)\n\tif (result.isPerpetualLicenseExpired || result.isAnnualLicenseExpired) {\n\t\toutputMessages([\n\t\t\t'Your tldraw license has been expired for more than 30 days!',\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to renew your license.`,\n\t\t])\n\t\treturn 'expired'\n\t}\n\n\t// Check if license is past expiry date but within grace period\n\tconst daysSinceExpiry = result.daysSinceExpiry\n\tif (daysSinceExpiry > 0 && !result.isEvaluationLicense) {\n\t\toutputMessages([\n\t\t\t'Your tldraw license has expired.',\n\t\t\t`License expired ${daysSinceExpiry} days ago.`,\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to renew your license.`,\n\t\t])\n\t\t// Within 30-day grace period: still licensed (no watermark)\n\t\treturn 'licensed'\n\t}\n\n\t// License is valid, determine if it has watermark\n\tif (result.isLicensedWithWatermark) {\n\t\treturn 'licensed-with-watermark'\n\t}\n\n\treturn 'licensed'\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { atom } from '@tldraw/state'\nimport { publishDates, version } from '../../version'\nimport { getDefaultCdnBaseUrl } from '../utils/assets'\nimport { importPublicKey, str2ab } from '../utils/licensing'\n\nconst GRACE_PERIOD_DAYS = 30\n\nexport const FLAGS = {\n\t// -- MUTUALLY EXCLUSIVE FLAGS --\n\t// Annual means the license expires after a time period, usually 1 year.\n\tANNUAL_LICENSE: 1,\n\t// Perpetual means the license never expires up to the max supported version.\n\tPERPETUAL_LICENSE: 1 << 1,\n\n\t// -- ADDITIVE FLAGS --\n\t// Internal means the license is for internal use only.\n\tINTERNAL_LICENSE: 1 << 2,\n\t// Watermark means the product is watermarked.\n\tWITH_WATERMARK: 1 << 3,\n\t// Evaluation means the license is for evaluation purposes only.\n\tEVALUATION_LICENSE: 1 << 4,\n\t// Native means the license is for native apps which switches\n\t// on special-case logic.\n\tNATIVE_LICENSE: 1 << 5,\n}\nconst HIGHEST_FLAG = Math.max(...Object.values(FLAGS))\n\nexport const PROPERTIES = {\n\tID: 0,\n\tHOSTS: 1,\n\tFLAGS: 2,\n\tEXPIRY_DATE: 3,\n}\nconst NUMBER_OF_KNOWN_PROPERTIES = Object.keys(PROPERTIES).length\n\nconst LICENSE_EMAIL = 'sales@tldraw.com'\n\nconst WATERMARK_TRACK_SRC = `${getDefaultCdnBaseUrl()}/watermarks/watermark-track.svg`\n\n/** @internal */\nexport interface LicenseInfo {\n\tid: string\n\thosts: string[]\n\tflags: number\n\texpiryDate: string\n}\n\n/** @internal */\nexport type LicenseState =\n\t| 'pending' // License validation is in progress\n\t| 'licensed' // License is valid and active (no restrictions)\n\t| 'licensed-with-watermark' // License is valid but shows watermark (evaluation licenses, WITH_WATERMARK licenses)\n\t| 'unlicensed' // No valid license found or license is invalid (development)\n\t| 'unlicensed-production' // No valid license in production deployment (missing, invalid, or wrong domain)\n\t| 'expired' // License has been expired (30 days past expiration for regular licenses, immediately for evaluation licenses)\n/** @internal */\nexport type InvalidLicenseReason =\n\t| 'invalid-license-key'\n\t| 'no-key-provided'\n\t| 'has-key-development-mode'\n\n/** @internal */\nexport type LicenseFromKeyResult = InvalidLicenseKeyResult | ValidLicenseKeyResult\n\n/** @internal */\nexport interface InvalidLicenseKeyResult {\n\tisLicenseParseable: false\n\treason: InvalidLicenseReason\n}\n\n/** @internal */\nexport interface ValidLicenseKeyResult {\n\tisLicenseParseable: true\n\tlicense: LicenseInfo\n\tisDevelopment: boolean\n\tisDomainValid: boolean\n\texpiryDate: Date\n\tisAnnualLicense: boolean\n\tisAnnualLicenseExpired: boolean\n\tisPerpetualLicense: boolean\n\tisPerpetualLicenseExpired: boolean\n\tisInternalLicense: boolean\n\tisNativeLicense: boolean\n\tisLicensedWithWatermark: boolean\n\tisEvaluationLicense: boolean\n\tisEvaluationLicenseExpired: boolean\n\tdaysSinceExpiry: number\n}\n\n/** @internal */\nexport type TrackType = 'unlicensed' | 'with_watermark' | 'evaluation' | null\n\n/** @internal */\nexport class LicenseManager {\n\tprivate publicKey =\n\t\t'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHJh0uUfxHtCGyerXmmatE368Hd9rI6LH9oPDQihnaCryRFWEVeOvf9U/SPbyxX74LFyJs5tYeAHq5Nc0Ax25LQ'\n\tpublic isDevelopment: boolean\n\tpublic isTest: boolean\n\tpublic isCryptoAvailable: boolean\n\tstate = atom<LicenseState>('license state', 'pending')\n\tpublic verbose = true\n\n\tconstructor(licenseKey: string | undefined, testPublicKey?: string) {\n\t\tthis.isTest = process.env.NODE_ENV === 'test'\n\t\tthis.isDevelopment = this.getIsDevelopment()\n\t\tthis.publicKey = testPublicKey || this.publicKey\n\t\tthis.isCryptoAvailable = !!crypto.subtle\n\n\t\tthis.getLicenseFromKey(licenseKey)\n\t\t\t.then((result) => {\n\t\t\t\tconst licenseState = getLicenseState(\n\t\t\t\t\tresult,\n\t\t\t\t\t(messages: string[]) => this.outputMessages(messages),\n\t\t\t\t\tthis.isDevelopment\n\t\t\t\t)\n\n\t\t\t\tthis.maybeTrack(result, licenseState)\n\n\t\t\t\tthis.state.set(licenseState)\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tconsole.error('License validation failed:', error)\n\t\t\t\tthis.state.set('unlicensed')\n\t\t\t})\n\t}\n\n\tprivate getIsDevelopment() {\n\t\t// If we are using https on a non-localhost domain we assume it's a production env and a development one otherwise\n\t\treturn (\n\t\t\t!['https:', 'vscode-webview:'].includes(window.location.protocol) ||\n\t\t\twindow.location.hostname === 'localhost' ||\n\t\t\tprocess.env.NODE_ENV !== 'production'\n\t\t)\n\t}\n\n\tprivate getTrackType(result: LicenseFromKeyResult, licenseState: LicenseState): TrackType {\n\t\t// Track watermark for unlicensed production deployments\n\t\tif (licenseState === 'unlicensed-production') {\n\t\t\treturn 'unlicensed'\n\t\t}\n\n\t\tif (this.isDevelopment) {\n\t\t\treturn null\n\t\t}\n\n\t\tif (!result.isLicenseParseable) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Track evaluation licenses (for analytics, even though no watermark is shown)\n\t\tif (result.isEvaluationLicense) {\n\t\t\treturn 'evaluation'\n\t\t}\n\n\t\t// Track licenses that show watermarks\n\t\tif (licenseState === 'licensed-with-watermark') {\n\t\t\treturn 'with_watermark'\n\t\t}\n\n\t\treturn null\n\t}\n\n\tprivate maybeTrack(result: LicenseFromKeyResult, licenseState: LicenseState): void {\n\t\tconst trackType = this.getTrackType(result, licenseState)\n\t\tif (!trackType) {\n\t\t\treturn\n\t\t}\n\n\t\tconst url = new URL(WATERMARK_TRACK_SRC)\n\t\turl.searchParams.set('version', version)\n\t\turl.searchParams.set('license_type', trackType)\n\t\tif ('license' in result) {\n\t\t\turl.searchParams.set('license_id', result.license.id)\n\t\t\tconst sku = this.isFlagEnabled(result.license.flags, FLAGS.EVALUATION_LICENSE)\n\t\t\t\t? 'evaluation'\n\t\t\t\t: this.isFlagEnabled(result.license.flags, FLAGS.ANNUAL_LICENSE)\n\t\t\t\t\t? 'annual'\n\t\t\t\t\t: this.isFlagEnabled(result.license.flags, FLAGS.PERPETUAL_LICENSE)\n\t\t\t\t\t\t? 'perpetual'\n\t\t\t\t\t\t: 'unknown'\n\t\t\turl.searchParams.set('sku', sku)\n\t\t}\n\t\turl.searchParams.set('url', window.location.href)\n\t\tif (process.env.NODE_ENV) {\n\t\t\turl.searchParams.set('environment', process.env.NODE_ENV)\n\t\t}\n\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tfetch(url.toString())\n\t}\n\n\tprivate async extractLicenseKey(licenseKey: string): Promise<LicenseInfo> {\n\t\tconst [data, signature] = licenseKey.split('.')\n\t\tconst [prefix, encodedData] = data.split('/')\n\n\t\tif (!prefix.startsWith('tldraw-')) {\n\t\t\tthrow new Error(`Unsupported prefix '${prefix}'`)\n\t\t}\n\n\t\tconst publicCryptoKey = await importPublicKey(this.publicKey)\n\n\t\tlet isVerified\n\t\ttry {\n\t\t\tisVerified = await crypto.subtle.verify(\n\t\t\t\t{\n\t\t\t\t\tname: 'ECDSA',\n\t\t\t\t\thash: { name: 'SHA-256' },\n\t\t\t\t},\n\t\t\t\tpublicCryptoKey,\n\t\t\t\tnew Uint8Array(str2ab(atob(signature))),\n\t\t\t\tnew Uint8Array(str2ab(atob(encodedData)))\n\t\t\t)\n\t\t} catch (e) {\n\t\t\tconsole.error(e)\n\t\t\tthrow new Error('Could not perform signature validation')\n\t\t}\n\n\t\tif (!isVerified) {\n\t\t\tthrow new Error('Invalid signature')\n\t\t}\n\n\t\tlet decodedData: any\n\t\ttry {\n\t\t\tdecodedData = JSON.parse(atob(encodedData))\n\t\t} catch {\n\t\t\tthrow new Error('Could not parse object')\n\t\t}\n\t\tif (decodedData.length > NUMBER_OF_KNOWN_PROPERTIES) {\n\t\t\tthis.outputMessages([\n\t\t\t\t'License key contains some unknown properties.',\n\t\t\t\t'You may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t])\n\t\t}\n\n\t\treturn {\n\t\t\tid: decodedData[PROPERTIES.ID],\n\t\t\thosts: decodedData[PROPERTIES.HOSTS],\n\t\t\tflags: decodedData[PROPERTIES.FLAGS],\n\t\t\texpiryDate: decodedData[PROPERTIES.EXPIRY_DATE],\n\t\t}\n\t}\n\n\tasync getLicenseFromKey(licenseKey?: string): Promise<LicenseFromKeyResult> {\n\t\tif (!licenseKey) {\n\t\t\tif (!this.isDevelopment) {\n\t\t\t\tthis.outputNoLicenseKeyProvided()\n\t\t\t}\n\n\t\t\treturn { isLicenseParseable: false, reason: 'no-key-provided' }\n\t\t}\n\n\t\tif (this.isDevelopment && !this.isCryptoAvailable) {\n\t\t\tif (this.verbose) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t'tldraw: you seem to be in a development environment that does not support crypto. License not verified.'\n\t\t\t\t)\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log('You should check that this works in production separately.')\n\t\t\t}\n\t\t\t// We can't parse the license if we are in development mode since crypto\n\t\t\t// is not available on http\n\t\t\treturn { isLicenseParseable: false, reason: 'has-key-development-mode' }\n\t\t}\n\n\t\t// Borrowed idea from AG Grid:\n\t\t// Copying from various sources (like PDFs) can include zero-width characters.\n\t\t// This helps makes sure the key validation doesn't fail.\n\t\tlet cleanedLicenseKey = licenseKey.replace(/[\\u200B-\\u200D\\uFEFF]/g, '')\n\t\tcleanedLicenseKey = cleanedLicenseKey.replace(/\\r?\\n|\\r/g, '')\n\n\t\ttry {\n\t\t\tconst licenseInfo = await this.extractLicenseKey(cleanedLicenseKey)\n\t\t\tconst expiryDate = new Date(licenseInfo.expiryDate)\n\t\t\tconst isAnnualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.ANNUAL_LICENSE)\n\t\t\tconst isPerpetualLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.PERPETUAL_LICENSE)\n\n\t\t\tconst isEvaluationLicense = this.isFlagEnabled(licenseInfo.flags, FLAGS.EVALUATION_LICENSE)\n\t\t\tconst daysSinceExpiry = this.getDaysSinceExpiry(expiryDate)\n\n\t\t\tconst result: ValidLicenseKeyResult = {\n\t\t\t\tlicense: licenseInfo,\n\t\t\t\tisLicenseParseable: true,\n\t\t\t\tisDevelopment: this.isDevelopment,\n\t\t\t\tisDomainValid: this.isDomainValid(licenseInfo),\n\t\t\t\texpiryDate,\n\t\t\t\tisAnnualLicense,\n\t\t\t\tisAnnualLicenseExpired: isAnnualLicense && this.isAnnualLicenseExpired(expiryDate),\n\t\t\t\tisPerpetualLicense,\n\t\t\t\tisPerpetualLicenseExpired: isPerpetualLicense && this.isPerpetualLicenseExpired(expiryDate),\n\t\t\t\tisInternalLicense: this.isFlagEnabled(licenseInfo.flags, FLAGS.INTERNAL_LICENSE),\n\t\t\t\tisNativeLicense: this.isNativeLicense(licenseInfo),\n\t\t\t\tisLicensedWithWatermark: this.isFlagEnabled(licenseInfo.flags, FLAGS.WITH_WATERMARK),\n\t\t\t\tisEvaluationLicense,\n\t\t\t\tisEvaluationLicenseExpired:\n\t\t\t\t\tisEvaluationLicense && this.isEvaluationLicenseExpired(expiryDate),\n\t\t\t\tdaysSinceExpiry,\n\t\t\t}\n\t\t\tthis.outputLicenseInfoIfNeeded(result)\n\n\t\t\treturn result\n\t\t} catch (e: any) {\n\t\t\tthis.outputInvalidLicenseKey(e.message)\n\t\t\t// If the license can't be parsed, it's invalid\n\t\t\treturn { isLicenseParseable: false, reason: 'invalid-license-key' }\n\t\t}\n\t}\n\n\tprivate isDomainValid(licenseInfo: LicenseInfo) {\n\t\tconst currentHostname = window.location.hostname.toLowerCase()\n\n\t\treturn licenseInfo.hosts.some((host) => {\n\t\t\tconst normalizedHostOrUrlRegex = host.toLowerCase().trim()\n\n\t\t\t// Allow the domain if listed and www variations, 'example.com' allows 'example.com' and 'www.example.com'\n\t\t\tif (\n\t\t\t\tnormalizedHostOrUrlRegex === currentHostname ||\n\t\t\t\t`www.${normalizedHostOrUrlRegex}` === currentHostname ||\n\t\t\t\tnormalizedHostOrUrlRegex === `www.${currentHostname}`\n\t\t\t) {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// If host is '*', we allow all domains.\n\t\t\tif (host === '*') {\n\t\t\t\t// All domains allowed.\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Native license support\n\t\t\t// In this case, `normalizedHost` is actually a protocol, e.g. `app-bundle:`\n\t\t\tif (this.isNativeLicense(licenseInfo)) {\n\t\t\t\treturn new RegExp(normalizedHostOrUrlRegex).test(window.location.href)\n\t\t\t}\n\n\t\t\t// Glob testing, we only support '*.somedomain.com' right now.\n\t\t\tif (host.includes('*')) {\n\t\t\t\tconst globToRegex = new RegExp(host.replace(/\\*/g, '.*?'))\n\t\t\t\treturn globToRegex.test(currentHostname) || globToRegex.test(`www.${currentHostname}`)\n\t\t\t}\n\n\t\t\t// VSCode support\n\t\t\tif (window.location.protocol === 'vscode-webview:') {\n\t\t\t\tconst currentUrl = new URL(window.location.href)\n\t\t\t\tconst extensionId = currentUrl.searchParams.get('extensionId')\n\t\t\t\tif (normalizedHostOrUrlRegex === extensionId) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn false\n\t\t})\n\t}\n\n\tprivate isNativeLicense(licenseInfo: LicenseInfo) {\n\t\treturn this.isFlagEnabled(licenseInfo.flags, FLAGS.NATIVE_LICENSE)\n\t}\n\n\tprivate getExpirationDateWithoutGracePeriod(expiryDate: Date) {\n\t\treturn new Date(expiryDate.getFullYear(), expiryDate.getMonth(), expiryDate.getDate())\n\t}\n\n\tprivate getExpirationDateWithGracePeriod(expiryDate: Date) {\n\t\treturn new Date(\n\t\t\texpiryDate.getFullYear(),\n\t\t\texpiryDate.getMonth(),\n\t\t\texpiryDate.getDate() + GRACE_PERIOD_DAYS + 1 // Add 1 day to include the expiration day\n\t\t)\n\t}\n\n\tprivate isAnnualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\treturn new Date() >= expiration\n\t}\n\n\tprivate isPerpetualLicenseExpired(expiryDate: Date) {\n\t\tconst expiration = this.getExpirationDateWithGracePeriod(expiryDate)\n\t\tconst dates = {\n\t\t\tmajor: new Date(publishDates.major),\n\t\t\tminor: new Date(publishDates.minor),\n\t\t}\n\t\t// We allow patch releases, but the major and minor releases should be within the expiration date\n\t\treturn dates.major >= expiration || dates.minor >= expiration\n\t}\n\n\tprivate getDaysSinceExpiry(expiryDate: Date): number {\n\t\tconst now = new Date()\n\t\tconst expiration = this.getExpirationDateWithoutGracePeriod(expiryDate)\n\t\tconst diffTime = now.getTime() - expiration.getTime()\n\t\tconst diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24))\n\t\treturn Math.max(0, diffDays)\n\t}\n\n\tprivate isEvaluationLicenseExpired(expiryDate: Date): boolean {\n\t\t// Evaluation licenses have no grace period - they expire immediately\n\t\tconst now = new Date()\n\t\tconst expiration = this.getExpirationDateWithoutGracePeriod(expiryDate)\n\t\treturn now >= expiration\n\t}\n\n\tprivate isFlagEnabled(flags: number, flag: number) {\n\t\treturn (flags & flag) === flag\n\t}\n\n\tprivate outputNoLicenseKeyProvided() {\n\t\t// Noop, we don't need to show this message.\n\t\t// this.outputMessages([\n\t\t// \t'No tldraw license key provided!',\n\t\t// \t`Please reach out to ${LICENSE_EMAIL} if you would like to license tldraw or if you'd like a trial.`,\n\t\t// ])\n\t}\n\n\tprivate outputInvalidLicenseKey(msg: string) {\n\t\tthis.outputMessages(['Invalid tldraw license key', `Reason: ${msg}`])\n\t}\n\n\tprivate outputLicenseInfoIfNeeded(result: ValidLicenseKeyResult) {\n\t\t// If we added a new flag it will be twice the value of the currently highest flag.\n\t\t// And if all the current flags are on we would get the `HIGHEST_FLAG * 2 - 1`, so anything higher than that means there are new flags.\n\t\tif (result.license.flags >= HIGHEST_FLAG * 2) {\n\t\t\tthis.outputMessages(\n\t\t\t\t[\n\t\t\t\t\t'Warning: This tldraw license contains some unknown flags.',\n\t\t\t\t\t'This will still work, however, you may want to update tldraw packages to a newer version to get access to new functionality.',\n\t\t\t\t],\n\t\t\t\t'warning'\n\t\t\t)\n\t\t}\n\t}\n\n\tprivate outputMessages(messages: string[], type: 'warning' | 'error' = 'error') {\n\t\tif (this.isTest) return\n\t\tif (this.verbose) {\n\t\t\tthis.outputDelimiter(type)\n\t\t\tfor (const message of messages) {\n\t\t\t\tconst bgColor = type === 'warning' ? 'orange' : 'crimson'\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(\n\t\t\t\t\t`%c${message}`,\n\t\t\t\t\t`color: white; background: ${bgColor}; padding: 2px; border-radius: 3px;`\n\t\t\t\t)\n\t\t\t}\n\t\t\tthis.outputDelimiter(type)\n\t\t}\n\t}\n\n\tprivate outputDelimiter(type: 'warning' | 'error' = 'error') {\n\t\tconst bgColor = type === 'warning' ? 'orange' : 'crimson'\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(\n\t\t\t'%c-------------------------------------------------------------------',\n\t\t\t`color: white; background: ${bgColor}; padding: 2px; border-radius: 3px;`\n\t\t)\n\t}\n\n\tstatic className = 'tl-watermark_SEE-LICENSE'\n}\n\nexport function getLicenseState(\n\tresult: LicenseFromKeyResult,\n\toutputMessages: (messages: string[]) => void,\n\tisDevelopment: boolean\n): LicenseState {\n\tif (!result.isLicenseParseable) {\n\t\tif (isDevelopment) {\n\t\t\treturn 'unlicensed'\n\t\t}\n\n\t\t// All unlicensed scenarios should not work in production\n\t\tif (result.reason === 'no-key-provided') {\n\t\t\toutputMessages([\n\t\t\t\t'No tldraw license key provided!',\n\t\t\t\t'A license is required for production deployments.',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t\t])\n\t\t} else {\n\t\t\toutputMessages([\n\t\t\t\t'Invalid license key. tldraw requires a valid license for production use.',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t\t])\n\t\t}\n\t\treturn 'unlicensed-production'\n\t}\n\n\tif (!result.isDomainValid && !result.isDevelopment) {\n\t\toutputMessages([\n\t\t\t'License key is not valid for this domain.',\n\t\t\t'A license is required for production deployments.',\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a license.`,\n\t\t])\n\t\treturn 'unlicensed-production'\n\t}\n\n\t// Handle evaluation licenses - they expire immediately with no grace period\n\tif (result.isEvaluationLicense) {\n\t\tif (result.isEvaluationLicenseExpired) {\n\t\t\toutputMessages([\n\t\t\t\t'Your tldraw evaluation license has expired!',\n\t\t\t\t`Please reach out to ${LICENSE_EMAIL} to purchase a full license.`,\n\t\t\t])\n\t\t\treturn 'expired'\n\t\t} else {\n\t\t\t// Valid evaluation license - tracked but no watermark shown\n\t\t\treturn 'licensed'\n\t\t}\n\t}\n\n\t// Handle expired regular licenses (both annual and perpetual)\n\tif (result.isPerpetualLicenseExpired || result.isAnnualLicenseExpired) {\n\t\toutputMessages([\n\t\t\t'Your tldraw license has been expired for more than 30 days!',\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to renew your license.`,\n\t\t])\n\t\treturn 'expired'\n\t}\n\n\t// Check if license is past expiry date but within grace period\n\tconst daysSinceExpiry = result.daysSinceExpiry\n\tif (daysSinceExpiry > 0 && !result.isEvaluationLicense) {\n\t\toutputMessages([\n\t\t\t'Your tldraw license has expired.',\n\t\t\t`License expired ${daysSinceExpiry} days ago.`,\n\t\t\t`Please reach out to ${LICENSE_EMAIL} to renew your license.`,\n\t\t])\n\t\t// Within 30-day grace period: still licensed (no watermark)\n\t\treturn 'licensed'\n\t}\n\n\t// License is valid, determine if it has watermark\n\tif (result.isLicensedWithWatermark) {\n\t\treturn 'licensed-with-watermark'\n\t}\n\n\treturn 'licensed'\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-cjs/lib/options.js
CHANGED
|
@@ -22,6 +22,7 @@ __export(options_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(options_exports);
|
|
24
24
|
var import_react = require("react");
|
|
25
|
+
var import_constants = require("./constants");
|
|
25
26
|
const defaultTldrawOptions = {
|
|
26
27
|
maxShapesPerPage: 4e3,
|
|
27
28
|
maxFilesAtOnce: 100,
|
|
@@ -80,6 +81,10 @@ const defaultTldrawOptions = {
|
|
|
80
81
|
debouncedZoomThreshold: 500,
|
|
81
82
|
spacebarPanning: true,
|
|
82
83
|
zoomToFitPadding: 128,
|
|
83
|
-
snapThreshold: 8
|
|
84
|
+
snapThreshold: 8,
|
|
85
|
+
camera: import_constants.DEFAULT_CAMERA_OPTIONS,
|
|
86
|
+
text: {},
|
|
87
|
+
deepLinks: void 0,
|
|
88
|
+
quickZoomPreservesScreenBounds: true
|
|
84
89
|
};
|
|
85
90
|
//# sourceMappingURL=options.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/options.ts"],
|
|
4
|
-
"sourcesContent": ["import { ComponentType, Fragment } from 'react'\n\n/**\n * Options for configuring tldraw. For defaults, see {@link defaultTldrawOptions}.\n *\n * @example\n * ```tsx\n * const options: Partial<TldrawOptions> = {\n * maxPages: 3,\n * maxShapesPerPage: 1000,\n * }\n *\n * function MyTldrawComponent() {\n * return <Tldraw options={options} />\n * }\n * ```\n *\n * @public\n */\nexport interface TldrawOptions {\n\treadonly maxShapesPerPage: number\n\treadonly maxFilesAtOnce: number\n\treadonly maxPages: number\n\treadonly animationMediumMs: number\n\treadonly followChaseViewportSnap: number\n\treadonly doubleClickDurationMs: number\n\treadonly multiClickDurationMs: number\n\treadonly coarseDragDistanceSquared: number\n\treadonly dragDistanceSquared: number\n\treadonly uiDragDistanceSquared: number\n\treadonly uiCoarseDragDistanceSquared: number\n\treadonly defaultSvgPadding: number\n\treadonly cameraSlideFriction: number\n\treadonly gridSteps: readonly {\n\t\treadonly min: number\n\t\treadonly mid: number\n\t\treadonly step: number\n\t}[]\n\treadonly collaboratorInactiveTimeoutMs: number\n\treadonly collaboratorIdleTimeoutMs: number\n\treadonly collaboratorCheckIntervalMs: number\n\treadonly cameraMovingTimeoutMs: number\n\treadonly hitTestMargin: number\n\treadonly edgeScrollDelay: number\n\treadonly edgeScrollEaseDuration: number\n\treadonly edgeScrollSpeed: number\n\treadonly edgeScrollDistance: number\n\treadonly coarsePointerWidth: number\n\treadonly coarseHandleRadius: number\n\treadonly handleRadius: number\n\treadonly longPressDurationMs: number\n\treadonly textShadowLod: number\n\treadonly adjacentShapeMargin: number\n\treadonly flattenImageBoundsExpand: number\n\treadonly flattenImageBoundsPadding: number\n\treadonly laserDelayMs: number\n\t/**\n\t * How long (in milliseconds) to fade all laser scribbles after the session ends.\n\t * The total points across all scribbles will be removed proportionally over this duration.\n\t * Defaults to 500ms (0.5 seconds).\n\t */\n\treadonly laserFadeoutMs: number\n\treadonly maxExportDelayMs: number\n\treadonly tooltipDelayMs: number\n\t/**\n\t * How long should previews created by {@link Editor.createTemporaryAssetPreview} last before\n\t * they expire? Defaults to 3 minutes.\n\t */\n\treadonly temporaryAssetPreviewLifetimeMs: number\n\treadonly actionShortcutsLocation: 'menu' | 'toolbar' | 'swap'\n\treadonly createTextOnCanvasDoubleClick: boolean\n\t/**\n\t * The react provider to use when exporting an image. This is useful if your shapes depend on\n\t * external context providers. By default, this is `React.Fragment`.\n\t */\n\treadonly exportProvider: ComponentType<{ children: React.ReactNode }>\n\t/**\n\t * By default, the toolbar items are accessible via number shortcuts according to their order. To disable this, set this option to false.\n\t */\n\treadonly enableToolbarKeyboardShortcuts: boolean\n\t/**\n\t * The maximum number of fonts that will be loaded while blocking the main rendering of the\n\t * canvas. If there are more than this number of fonts needed, we'll just show the canvas right\n\t * away and let the fonts load in in the background.\n\t */\n\treadonly maxFontsToLoadBeforeRender: number\n\t/**\n\t * If you have a CSP policy that blocks inline styles, you can use this prop to provide a\n\t * nonce to use in the editor's styles.\n\t */\n\treadonly nonce: string | undefined\n\t/**\n\t * Branding name of the app, currently only used for adding aria-label for the application.\n\t */\n\treadonly branding?: string\n\t/**\n\t * Whether to use debounced zoom level for certain rendering optimizations. When true,\n\t * `editor.
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAwC;
|
|
4
|
+
"sourcesContent": ["import { ComponentType, Fragment } from 'react'\nimport { DEFAULT_CAMERA_OPTIONS } from './constants'\nimport { TLCameraOptions } from './editor/types/misc-types'\nimport { TLDeepLinkOptions } from './utils/deepLinks'\nimport { TLTextOptions } from './utils/richText'\n\n/**\n * Options for configuring tldraw. For defaults, see {@link defaultTldrawOptions}.\n *\n * @example\n * ```tsx\n * const options: Partial<TldrawOptions> = {\n * maxPages: 3,\n * maxShapesPerPage: 1000,\n * }\n *\n * function MyTldrawComponent() {\n * return <Tldraw options={options} />\n * }\n * ```\n *\n * @public\n */\nexport interface TldrawOptions {\n\treadonly maxShapesPerPage: number\n\treadonly maxFilesAtOnce: number\n\treadonly maxPages: number\n\treadonly animationMediumMs: number\n\treadonly followChaseViewportSnap: number\n\treadonly doubleClickDurationMs: number\n\treadonly multiClickDurationMs: number\n\treadonly coarseDragDistanceSquared: number\n\treadonly dragDistanceSquared: number\n\treadonly uiDragDistanceSquared: number\n\treadonly uiCoarseDragDistanceSquared: number\n\treadonly defaultSvgPadding: number\n\treadonly cameraSlideFriction: number\n\treadonly gridSteps: readonly {\n\t\treadonly min: number\n\t\treadonly mid: number\n\t\treadonly step: number\n\t}[]\n\treadonly collaboratorInactiveTimeoutMs: number\n\treadonly collaboratorIdleTimeoutMs: number\n\treadonly collaboratorCheckIntervalMs: number\n\treadonly cameraMovingTimeoutMs: number\n\treadonly hitTestMargin: number\n\treadonly edgeScrollDelay: number\n\treadonly edgeScrollEaseDuration: number\n\treadonly edgeScrollSpeed: number\n\treadonly edgeScrollDistance: number\n\treadonly coarsePointerWidth: number\n\treadonly coarseHandleRadius: number\n\treadonly handleRadius: number\n\treadonly longPressDurationMs: number\n\treadonly textShadowLod: number\n\treadonly adjacentShapeMargin: number\n\treadonly flattenImageBoundsExpand: number\n\treadonly flattenImageBoundsPadding: number\n\treadonly laserDelayMs: number\n\t/**\n\t * How long (in milliseconds) to fade all laser scribbles after the session ends.\n\t * The total points across all scribbles will be removed proportionally over this duration.\n\t * Defaults to 500ms (0.5 seconds).\n\t */\n\treadonly laserFadeoutMs: number\n\treadonly maxExportDelayMs: number\n\treadonly tooltipDelayMs: number\n\t/**\n\t * How long should previews created by {@link Editor.createTemporaryAssetPreview} last before\n\t * they expire? Defaults to 3 minutes.\n\t */\n\treadonly temporaryAssetPreviewLifetimeMs: number\n\treadonly actionShortcutsLocation: 'menu' | 'toolbar' | 'swap'\n\treadonly createTextOnCanvasDoubleClick: boolean\n\t/**\n\t * The react provider to use when exporting an image. This is useful if your shapes depend on\n\t * external context providers. By default, this is `React.Fragment`.\n\t */\n\treadonly exportProvider: ComponentType<{ children: React.ReactNode }>\n\t/**\n\t * By default, the toolbar items are accessible via number shortcuts according to their order. To disable this, set this option to false.\n\t */\n\treadonly enableToolbarKeyboardShortcuts: boolean\n\t/**\n\t * The maximum number of fonts that will be loaded while blocking the main rendering of the\n\t * canvas. If there are more than this number of fonts needed, we'll just show the canvas right\n\t * away and let the fonts load in in the background.\n\t */\n\treadonly maxFontsToLoadBeforeRender: number\n\t/**\n\t * If you have a CSP policy that blocks inline styles, you can use this prop to provide a\n\t * nonce to use in the editor's styles.\n\t */\n\treadonly nonce: string | undefined\n\t/**\n\t * Branding name of the app, currently only used for adding aria-label for the application.\n\t */\n\treadonly branding?: string\n\t/**\n\t * Whether to use debounced zoom level for certain rendering optimizations. When true,\n\t * `editor.getEfficientZoomLevel()` returns a cached zoom value while the camera is moving,\n\t * reducing re-renders. When false, it always returns the current zoom level.\n\t */\n\treadonly debouncedZoom: boolean\n\t/**\n\t * The number of shapes that must be on the page for the debounced zoom level to be used.\n\t * Defaults to 500 shapes.\n\t */\n\treadonly debouncedZoomThreshold: number\n\t/**\n\t * Whether to allow spacebar panning. When true, the spacebar will pan the camera when held down.\n\t * When false, the spacebar will not pan the camera.\n\t */\n\treadonly spacebarPanning: boolean\n\t/**\n\t * The default padding (in pixels) used when zooming to fit content in the viewport.\n\t * This affects methods like `zoomToFit()`, `zoomToSelection()`, and `zoomToBounds()`.\n\t * The actual padding used is the minimum of this value and 28% of the viewport width.\n\t * Defaults to 128 pixels.\n\t */\n\treadonly zoomToFitPadding: number\n\t/**\n\t * The distance (in screen pixels) at which shapes snap to guides and other shapes.\n\t */\n\treadonly snapThreshold: number\n\t/**\n\t * Options for the editor's camera. These are the initial camera options.\n\t * Use {@link Editor.setCameraOptions} to update camera options at runtime.\n\t */\n\treadonly camera: Partial<TLCameraOptions>\n\t/**\n\t * Options for the editor's text rendering. These include TipTap configuration and\n\t * font handling. These are the initial text options and cannot be changed at runtime.\n\t */\n\treadonly text: TLTextOptions\n\t/**\n\t * Options for syncing the editor's camera state with the URL. Set to `true` to enable\n\t * with default options, or pass an options object to customize behavior.\n\t *\n\t * @example\n\t * ```tsx\n\t * // Enable with defaults\n\t * <Tldraw options={{ deepLinks: true }} />\n\t *\n\t * // Enable with custom options\n\t * <Tldraw options={{ deepLinks: { param: 'd', debounceMs: 500 } }} />\n\t * ```\n\t */\n\treadonly deepLinks: true | TLDeepLinkOptions | undefined\n\t/**\n\t * Whether the quick-zoom brush preserves its screen-pixel size when the user\n\t * zooms the overview. When true, zooming in shrinks the target viewport (higher\n\t * return zoom); zooming out expands it. When false, the brush keeps the original\n\t * viewport's page dimensions regardless of overview zoom changes.\n\t */\n\treadonly quickZoomPreservesScreenBounds: boolean\n}\n\n/** @public */\nexport const defaultTldrawOptions = {\n\tmaxShapesPerPage: 4000,\n\tmaxFilesAtOnce: 100,\n\tmaxPages: 40,\n\tanimationMediumMs: 320,\n\tfollowChaseViewportSnap: 2,\n\tdoubleClickDurationMs: 450,\n\tmultiClickDurationMs: 200,\n\tcoarseDragDistanceSquared: 36, // 6 squared\n\tdragDistanceSquared: 16, // 4 squared\n\tuiDragDistanceSquared: 16, // 4 squared\n\t// it's really easy to accidentally drag from the toolbar on mobile, so we use a much larger\n\t// threshold than usual here to try and prevent accidental drags.\n\tuiCoarseDragDistanceSquared: 625, // 25 squared\n\tdefaultSvgPadding: 32,\n\tcameraSlideFriction: 0.09,\n\tgridSteps: [\n\t\t{ min: -1, mid: 0.15, step: 64 },\n\t\t{ min: 0.05, mid: 0.375, step: 16 },\n\t\t{ min: 0.15, mid: 1, step: 4 },\n\t\t{ min: 0.7, mid: 2.5, step: 1 },\n\t],\n\tcollaboratorInactiveTimeoutMs: 60000,\n\tcollaboratorIdleTimeoutMs: 3000,\n\tcollaboratorCheckIntervalMs: 1200,\n\tcameraMovingTimeoutMs: 64,\n\thitTestMargin: 8,\n\tedgeScrollDelay: 200,\n\tedgeScrollEaseDuration: 200,\n\tedgeScrollSpeed: 25,\n\tedgeScrollDistance: 8,\n\tcoarsePointerWidth: 12,\n\tcoarseHandleRadius: 20,\n\thandleRadius: 12,\n\tlongPressDurationMs: 500,\n\ttextShadowLod: 0.35,\n\tadjacentShapeMargin: 10,\n\tflattenImageBoundsExpand: 64,\n\tflattenImageBoundsPadding: 16,\n\tlaserDelayMs: 1200,\n\tlaserFadeoutMs: 500,\n\tmaxExportDelayMs: 5000,\n\ttooltipDelayMs: 700,\n\ttemporaryAssetPreviewLifetimeMs: 180000,\n\tactionShortcutsLocation: 'swap',\n\tcreateTextOnCanvasDoubleClick: true,\n\texportProvider: Fragment,\n\tenableToolbarKeyboardShortcuts: true,\n\tmaxFontsToLoadBeforeRender: Infinity,\n\tnonce: undefined,\n\tdebouncedZoom: true,\n\tdebouncedZoomThreshold: 500,\n\tspacebarPanning: true,\n\tzoomToFitPadding: 128,\n\tsnapThreshold: 8,\n\tcamera: DEFAULT_CAMERA_OPTIONS,\n\ttext: {},\n\tdeepLinks: undefined,\n\tquickZoomPreservesScreenBounds: true,\n} as const satisfies TldrawOptions\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAwC;AACxC,uBAAuC;AA+JhC,MAAM,uBAAuB;AAAA,EACnC,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,mBAAmB;AAAA,EACnB,yBAAyB;AAAA,EACzB,uBAAuB;AAAA,EACvB,sBAAsB;AAAA,EACtB,2BAA2B;AAAA;AAAA,EAC3B,qBAAqB;AAAA;AAAA,EACrB,uBAAuB;AAAA;AAAA;AAAA;AAAA,EAGvB,6BAA6B;AAAA;AAAA,EAC7B,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,WAAW;AAAA,IACV,EAAE,KAAK,IAAI,KAAK,MAAM,MAAM,GAAG;AAAA,IAC/B,EAAE,KAAK,MAAM,KAAK,OAAO,MAAM,GAAG;AAAA,IAClC,EAAE,KAAK,MAAM,KAAK,GAAG,MAAM,EAAE;AAAA,IAC7B,EAAE,KAAK,KAAK,KAAK,KAAK,MAAM,EAAE;AAAA,EAC/B;AAAA,EACA,+BAA+B;AAAA,EAC/B,2BAA2B;AAAA,EAC3B,6BAA6B;AAAA,EAC7B,uBAAuB;AAAA,EACvB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,wBAAwB;AAAA,EACxB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,qBAAqB;AAAA,EACrB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,0BAA0B;AAAA,EAC1B,2BAA2B;AAAA,EAC3B,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,iCAAiC;AAAA,EACjC,yBAAyB;AAAA,EACzB,+BAA+B;AAAA,EAC/B,gBAAgB;AAAA,EAChB,gCAAgC;AAAA,EAChC,4BAA4B;AAAA,EAC5B,OAAO;AAAA,EACP,eAAe;AAAA,EACf,wBAAwB;AAAA,EACxB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,QAAQ;AAAA,EACR,MAAM,CAAC;AAAA,EACP,WAAW;AAAA,EACX,gCAAgC;AACjC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-cjs/version.js
CHANGED
|
@@ -22,10 +22,10 @@ __export(version_exports, {
|
|
|
22
22
|
version: () => version
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(version_exports);
|
|
25
|
-
const version = "4.4.0
|
|
25
|
+
const version = "4.4.0";
|
|
26
26
|
const publishDates = {
|
|
27
27
|
major: "2025-09-18T14:39:22.803Z",
|
|
28
|
-
minor: "2026-
|
|
29
|
-
patch: "2026-
|
|
28
|
+
minor: "2026-02-18T12:03:50.380Z",
|
|
29
|
+
patch: "2026-02-18T12:03:50.380Z"
|
|
30
30
|
};
|
|
31
31
|
//# sourceMappingURL=version.js.map
|
package/dist-cjs/version.js.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 = '4.4.0
|
|
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 = '4.4.0'\nexport const publishDates = {\n\tmajor: '2025-09-18T14:39:22.803Z',\n\tminor: '2026-02-18T12:03:50.380Z',\n\tpatch: '2026-02-18T12:03:50.380Z',\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-esm/index.d.mts
CHANGED
|
@@ -857,6 +857,7 @@ export declare const defaultTldrawOptions: {
|
|
|
857
857
|
readonly actionShortcutsLocation: "swap";
|
|
858
858
|
readonly adjacentShapeMargin: 10;
|
|
859
859
|
readonly animationMediumMs: 320;
|
|
860
|
+
readonly camera: TLCameraOptions;
|
|
860
861
|
readonly cameraMovingTimeoutMs: 64;
|
|
861
862
|
readonly cameraSlideFriction: 0.09;
|
|
862
863
|
readonly coarseDragDistanceSquared: 36;
|
|
@@ -868,6 +869,7 @@ export declare const defaultTldrawOptions: {
|
|
|
868
869
|
readonly createTextOnCanvasDoubleClick: true;
|
|
869
870
|
readonly debouncedZoom: true;
|
|
870
871
|
readonly debouncedZoomThreshold: 500;
|
|
872
|
+
readonly deepLinks: undefined;
|
|
871
873
|
readonly defaultSvgPadding: 32;
|
|
872
874
|
readonly doubleClickDurationMs: 450;
|
|
873
875
|
readonly dragDistanceSquared: 16;
|
|
@@ -909,9 +911,11 @@ export declare const defaultTldrawOptions: {
|
|
|
909
911
|
readonly maxShapesPerPage: 4000;
|
|
910
912
|
readonly multiClickDurationMs: 200;
|
|
911
913
|
readonly nonce: undefined;
|
|
914
|
+
readonly quickZoomPreservesScreenBounds: true;
|
|
912
915
|
readonly snapThreshold: 8;
|
|
913
916
|
readonly spacebarPanning: true;
|
|
914
917
|
readonly temporaryAssetPreviewLifetimeMs: 180000;
|
|
918
|
+
readonly text: {};
|
|
915
919
|
readonly textShadowLod: 0.35;
|
|
916
920
|
readonly tooltipDelayMs: 700;
|
|
917
921
|
readonly uiCoarseDragDistanceSquared: 625;
|
|
@@ -1011,7 +1015,7 @@ export declare class EdgeScrollManager {
|
|
|
1011
1015
|
/** @public */
|
|
1012
1016
|
export declare class Editor extends EventEmitter<TLEventMap> {
|
|
1013
1017
|
readonly id: string;
|
|
1014
|
-
constructor({ store, user, shapeUtils, bindingUtils, tools, getContainer, cameraOptions,
|
|
1018
|
+
constructor({ store, user, shapeUtils, bindingUtils, tools, getContainer, cameraOptions, initialState, autoFocus, inferDarkMode, options: _options, textOptions: _textOptions, getShapeVisibility, fontAssetUrls, }: TLEditorOptions);
|
|
1015
1019
|
private readonly _getShapeVisibility?;
|
|
1016
1020
|
private getIsShapeHiddenCache;
|
|
1017
1021
|
isShapeHidden(shapeOrId: TLShape | TLShapeId): boolean;
|
|
@@ -1906,7 +1910,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
1906
1910
|
getDebouncedZoomLevel(): number;
|
|
1907
1911
|
private _getAboveDebouncedZoomThreshold;
|
|
1908
1912
|
/**
|
|
1909
|
-
* Get the efficient zoom level. This returns the current zoom level if there are less than
|
|
1913
|
+
* Get the efficient zoom level. This returns the current zoom level if there are less than a certain number of shapes on the page,
|
|
1910
1914
|
* otherwise it returns the debounced zoom level. This can be used to avoid expensive re-renders during camera movements.
|
|
1911
1915
|
*
|
|
1912
1916
|
* @public
|
|
@@ -2259,10 +2263,10 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2259
2263
|
*/
|
|
2260
2264
|
stopFollowingUser(): this;
|
|
2261
2265
|
/* Excluded from this release type: getUnorderedRenderingShapes */
|
|
2262
|
-
private _cameraState;
|
|
2263
2266
|
private _cameraStateTimeoutRemaining;
|
|
2264
2267
|
private _decayCameraStateTimeout;
|
|
2265
2268
|
private _tickCameraState;
|
|
2269
|
+
private _setCameraState;
|
|
2266
2270
|
/**
|
|
2267
2271
|
* Whether the camera is moving or idle.
|
|
2268
2272
|
*
|
|
@@ -2761,7 +2765,24 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
2761
2765
|
hitInside?: boolean;
|
|
2762
2766
|
margin?: number;
|
|
2763
2767
|
}): TLShape[];
|
|
2764
|
-
|
|
2768
|
+
/**
|
|
2769
|
+
* Get shape IDs within the given bounds.
|
|
2770
|
+
*
|
|
2771
|
+
* Note: Uses shape page bounds only. Frames with labels outside their bounds
|
|
2772
|
+
* may not be included even if the label is within the search bounds.
|
|
2773
|
+
*
|
|
2774
|
+
* Note: Results are unordered. If you need z-order, combine with sorted shapes:
|
|
2775
|
+
* ```ts
|
|
2776
|
+
* const candidates = editor.getShapeIdsInsideBounds(bounds)
|
|
2777
|
+
* const sorted = editor.getCurrentPageShapesSorted().filter(s => candidates.has(s.id))
|
|
2778
|
+
* ```
|
|
2779
|
+
*
|
|
2780
|
+
* @param bounds - The bounds to search within.
|
|
2781
|
+
* @returns Unordered set of shape IDs within the given bounds.
|
|
2782
|
+
*
|
|
2783
|
+
* @public
|
|
2784
|
+
*/
|
|
2785
|
+
getShapeIdsInsideBounds(bounds: Box): Set<TLShapeId>;
|
|
2765
2786
|
/**
|
|
2766
2787
|
* Test whether a point (in the current page space) will will a shape. This method takes into account masks,
|
|
2767
2788
|
* such as when a shape is the child of a frame and is partially clipped by the frame.
|
|
@@ -3903,7 +3924,7 @@ export declare class Editor extends EventEmitter<TLEventMap> {
|
|
|
3903
3924
|
/**
|
|
3904
3925
|
* Handles navigating to the content specified by the query param in the given URL.
|
|
3905
3926
|
*
|
|
3906
|
-
* Use {@link Editor
|
|
3927
|
+
* Use {@link Editor.createDeepLink} to create a URL with a deep link query param.
|
|
3907
3928
|
*
|
|
3908
3929
|
* If no URL is provided, it will look for the param in the current `window.location.href`.
|
|
3909
3930
|
*
|
|
@@ -6827,29 +6848,35 @@ export declare interface TldrawEditorBaseProps {
|
|
|
6827
6848
|
inferDarkMode?: boolean;
|
|
6828
6849
|
/**
|
|
6829
6850
|
* Camera options for the editor.
|
|
6851
|
+
*
|
|
6852
|
+
* @deprecated Use `options.cameraOptions` instead. This will be removed in a future release.
|
|
6830
6853
|
*/
|
|
6831
6854
|
cameraOptions?: Partial<TLCameraOptions>;
|
|
6832
|
-
/**
|
|
6833
|
-
* Text options for the editor.
|
|
6834
|
-
*/
|
|
6835
|
-
textOptions?: TLTextOptions;
|
|
6836
6855
|
/**
|
|
6837
6856
|
* Options for the editor.
|
|
6838
6857
|
*/
|
|
6839
6858
|
options?: Partial<TldrawOptions>;
|
|
6859
|
+
/**
|
|
6860
|
+
* Text options for the editor.
|
|
6861
|
+
*
|
|
6862
|
+
* @deprecated Use `options.text` instead. This prop will be removed in a future release.
|
|
6863
|
+
*/
|
|
6864
|
+
textOptions?: TLTextOptions;
|
|
6840
6865
|
/**
|
|
6841
6866
|
* The license key.
|
|
6842
6867
|
*/
|
|
6843
6868
|
licenseKey?: string;
|
|
6844
6869
|
/**
|
|
6845
6870
|
* Options for syncing the editor's camera state with the URL.
|
|
6871
|
+
*
|
|
6872
|
+
* @deprecated Use `options.deepLinks` instead. This prop will be removed in a future release.
|
|
6846
6873
|
*/
|
|
6847
6874
|
deepLinks?: TLDeepLinkOptions | true;
|
|
6848
6875
|
/**
|
|
6849
6876
|
* Provides a way to hide shapes.
|
|
6850
6877
|
*
|
|
6851
6878
|
* Hidden shapes will not render in the editor, and they will not be eligible for hit test via
|
|
6852
|
-
* {@link Editor
|
|
6879
|
+
* {@link @tldraw/editor#Editor.getShapeAtPoint} and {@link @tldraw/editor#Editor.getShapesAtPoint}. But otherwise they will
|
|
6853
6880
|
* remain in the store and participate in all other operations.
|
|
6854
6881
|
*
|
|
6855
6882
|
* @example
|
|
@@ -7022,13 +7049,13 @@ export declare interface TldrawOptions {
|
|
|
7022
7049
|
readonly branding?: string;
|
|
7023
7050
|
/**
|
|
7024
7051
|
* Whether to use debounced zoom level for certain rendering optimizations. When true,
|
|
7025
|
-
* `editor.
|
|
7052
|
+
* `editor.getEfficientZoomLevel()` returns a cached zoom value while the camera is moving,
|
|
7026
7053
|
* reducing re-renders. When false, it always returns the current zoom level.
|
|
7027
7054
|
*/
|
|
7028
7055
|
readonly debouncedZoom: boolean;
|
|
7029
7056
|
/**
|
|
7030
7057
|
* The number of shapes that must be on the page for the debounced zoom level to be used.
|
|
7031
|
-
* Defaults to
|
|
7058
|
+
* Defaults to 500 shapes.
|
|
7032
7059
|
*/
|
|
7033
7060
|
readonly debouncedZoomThreshold: number;
|
|
7034
7061
|
/**
|
|
@@ -7047,6 +7074,37 @@ export declare interface TldrawOptions {
|
|
|
7047
7074
|
* The distance (in screen pixels) at which shapes snap to guides and other shapes.
|
|
7048
7075
|
*/
|
|
7049
7076
|
readonly snapThreshold: number;
|
|
7077
|
+
/**
|
|
7078
|
+
* Options for the editor's camera. These are the initial camera options.
|
|
7079
|
+
* Use {@link Editor.setCameraOptions} to update camera options at runtime.
|
|
7080
|
+
*/
|
|
7081
|
+
readonly camera: Partial<TLCameraOptions>;
|
|
7082
|
+
/**
|
|
7083
|
+
* Options for the editor's text rendering. These include TipTap configuration and
|
|
7084
|
+
* font handling. These are the initial text options and cannot be changed at runtime.
|
|
7085
|
+
*/
|
|
7086
|
+
readonly text: TLTextOptions;
|
|
7087
|
+
/**
|
|
7088
|
+
* Options for syncing the editor's camera state with the URL. Set to `true` to enable
|
|
7089
|
+
* with default options, or pass an options object to customize behavior.
|
|
7090
|
+
*
|
|
7091
|
+
* @example
|
|
7092
|
+
* ```tsx
|
|
7093
|
+
* // Enable with defaults
|
|
7094
|
+
* <Tldraw options={{ deepLinks: true }} />
|
|
7095
|
+
*
|
|
7096
|
+
* // Enable with custom options
|
|
7097
|
+
* <Tldraw options={{ deepLinks: { param: 'd', debounceMs: 500 } }} />
|
|
7098
|
+
* ```
|
|
7099
|
+
*/
|
|
7100
|
+
readonly deepLinks: TLDeepLinkOptions | true | undefined;
|
|
7101
|
+
/**
|
|
7102
|
+
* Whether the quick-zoom brush preserves its screen-pixel size when the user
|
|
7103
|
+
* zooms the overview. When true, zooming in shrinks the target viewport (higher
|
|
7104
|
+
* return zoom); zooming out expands it. When false, the brush keeps the original
|
|
7105
|
+
* viewport's page dimensions regardless of overview zoom changes.
|
|
7106
|
+
*/
|
|
7107
|
+
readonly quickZoomPreservesScreenBounds: boolean;
|
|
7050
7108
|
}
|
|
7051
7109
|
|
|
7052
7110
|
/** @public */
|
|
@@ -7131,10 +7189,17 @@ export declare interface TLEditorOptions {
|
|
|
7131
7189
|
inferDarkMode?: boolean;
|
|
7132
7190
|
/**
|
|
7133
7191
|
* Options for the editor's camera.
|
|
7192
|
+
*
|
|
7193
|
+
* @deprecated Use `options.cameraOptions` instead. This will be removed in a future release.
|
|
7134
7194
|
*/
|
|
7135
7195
|
cameraOptions?: Partial<TLCameraOptions>;
|
|
7136
|
-
textOptions?: TLTextOptions;
|
|
7137
7196
|
options?: Partial<TldrawOptions>;
|
|
7197
|
+
/**
|
|
7198
|
+
* Text options for the editor.
|
|
7199
|
+
*
|
|
7200
|
+
* @deprecated Use `options.text` instead. This prop will be removed in a future release.
|
|
7201
|
+
*/
|
|
7202
|
+
textOptions?: TLTextOptions;
|
|
7138
7203
|
licenseKey?: string;
|
|
7139
7204
|
fontAssetUrls?: {
|
|
7140
7205
|
[key: string]: string | undefined;
|
|
@@ -8002,17 +8067,35 @@ export declare interface TLShapeUtilCanBeLaidOutOpts {
|
|
|
8002
8067
|
|
|
8003
8068
|
/**
|
|
8004
8069
|
* Options passed to {@link ShapeUtil.canBind}. A binding that could be made. At least one of
|
|
8005
|
-
* `
|
|
8070
|
+
* `fromShape` or `toShape` will belong to this shape util.
|
|
8071
|
+
*
|
|
8072
|
+
* The shapes may be full {@link @tldraw/tlschema#TLShape} objects when available, or just
|
|
8073
|
+
* `{ type }` stubs when the shape hasn't been created yet (e.g. during arrow creation). Use
|
|
8074
|
+
* `'id' in shape` to check whether the full shape is available.
|
|
8006
8075
|
*
|
|
8007
8076
|
* @public
|
|
8008
8077
|
*/
|
|
8009
8078
|
export declare interface TLShapeUtilCanBindOpts<Shape extends TLShape = TLShape> {
|
|
8010
|
-
/** The
|
|
8011
|
-
|
|
8012
|
-
|
|
8013
|
-
|
|
8079
|
+
/** The shape referenced by the `fromId` of the binding, or a `{ type }` stub if unavailable. */
|
|
8080
|
+
fromShape: {
|
|
8081
|
+
type: TLShape['type'];
|
|
8082
|
+
} | TLShape;
|
|
8083
|
+
/** The shape referenced by the `toId` of the binding, or a `{ type }` stub if unavailable. */
|
|
8084
|
+
toShape: {
|
|
8085
|
+
type: TLShape['type'];
|
|
8086
|
+
} | TLShape;
|
|
8014
8087
|
/** The type of binding. */
|
|
8015
8088
|
bindingType: string;
|
|
8089
|
+
/**
|
|
8090
|
+
* The type of shape referenced by the `fromId` of the binding.
|
|
8091
|
+
* @deprecated Use `fromShape.type` instead.
|
|
8092
|
+
*/
|
|
8093
|
+
fromShapeType: TLShape['type'];
|
|
8094
|
+
/**
|
|
8095
|
+
* The type of shape referenced by the `toId` of the binding.
|
|
8096
|
+
* @deprecated Use `toShape.type` instead.
|
|
8097
|
+
*/
|
|
8098
|
+
toShapeType: TLShape['type'];
|
|
8016
8099
|
}
|
|
8017
8100
|
|
|
8018
8101
|
/** @public */
|
|
@@ -8066,7 +8149,7 @@ export declare interface TLStoreBaseOptions {
|
|
|
8066
8149
|
defaultName?: string;
|
|
8067
8150
|
/** How should this store upload & resolve assets? */
|
|
8068
8151
|
assets?: TLAssetStore;
|
|
8069
|
-
/** Called when the store is connected to an {@link Editor}. */
|
|
8152
|
+
/** Called when the store is connected to an {@link @tldraw/editor#Editor}. */
|
|
8070
8153
|
onMount?(editor: Editor): (() => void) | void;
|
|
8071
8154
|
}
|
|
8072
8155
|
|
package/dist-esm/index.mjs
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
import { registerTldrawLibraryVersion } from "@tldraw/utils";
|
|
2
|
-
import "core-js/stable/array/at.js";
|
|
3
|
-
import "core-js/stable/array/flat-map.js";
|
|
4
|
-
import "core-js/stable/array/flat.js";
|
|
5
|
-
import "core-js/stable/string/at.js";
|
|
6
|
-
import "core-js/stable/string/replace-all.js";
|
|
7
2
|
export * from "@tldraw/state";
|
|
8
3
|
export * from "@tldraw/state-react";
|
|
9
4
|
export * from "@tldraw/store";
|
|
@@ -305,7 +300,7 @@ import { uniq } from "./lib/utils/uniq.mjs";
|
|
|
305
300
|
import { openWindow } from "./lib/utils/window-open.mjs";
|
|
306
301
|
registerTldrawLibraryVersion(
|
|
307
302
|
"@tldraw/editor",
|
|
308
|
-
"4.4.0
|
|
303
|
+
"4.4.0",
|
|
309
304
|
"esm"
|
|
310
305
|
);
|
|
311
306
|
export {
|