@tldraw/utils 4.6.0-next.5a871ec02ff3 → 4.6.0-next.d15997ff5a4b
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 +9 -1
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/PerformanceTracker.js +1 -1
- package/dist-cjs/lib/PerformanceTracker.js.map +1 -1
- package/dist-cjs/lib/bind.js.map +1 -1
- package/dist-cjs/lib/debounce.js.map +2 -2
- package/dist-cjs/lib/network.js.map +1 -1
- package/dist-cjs/lib/retry.js.map +2 -2
- package/dist-cjs/lib/storage.js.map +1 -1
- package/dist-cjs/lib/timers.js.map +1 -1
- package/dist-cjs/lib/types.js.map +1 -1
- package/dist-cjs/lib/version.js.map +1 -1
- package/dist-esm/index.d.mts +9 -1
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/PerformanceTracker.mjs +1 -1
- package/dist-esm/lib/PerformanceTracker.mjs.map +1 -1
- package/dist-esm/lib/bind.mjs.map +1 -1
- package/dist-esm/lib/debounce.mjs.map +2 -2
- package/dist-esm/lib/network.mjs.map +1 -1
- package/dist-esm/lib/retry.mjs.map +2 -2
- package/dist-esm/lib/storage.mjs.map +1 -1
- package/dist-esm/lib/timers.mjs.map +1 -1
- package/dist-esm/lib/version.mjs.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/lib/ExecutionQueue.test.ts +1 -1
- package/src/lib/PerformanceTracker.test.ts +1 -1
- package/src/lib/PerformanceTracker.ts +1 -1
- package/src/lib/bind.ts +1 -1
- package/src/lib/debounce.ts +4 -1
- package/src/lib/network.ts +2 -2
- package/src/lib/retry.ts +1 -0
- package/src/lib/storage.test.ts +2 -0
- package/src/lib/storage.tsx +1 -1
- package/src/lib/timers.ts +1 -1
- package/src/lib/types.ts +8 -0
- package/src/lib/version.ts +1 -1
package/dist-cjs/index.d.ts
CHANGED
|
@@ -13,6 +13,14 @@ import { default as uniq } from 'lodash.uniq';
|
|
|
13
13
|
|
|
14
14
|
/* Excluded from this release type: assertExists */
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* A value that may be returned synchronously or as a `Promise` / `PromiseLike`.
|
|
18
|
+
* Use with `await` or `Promise.resolve(...)` to normalize to a single `Promise`.
|
|
19
|
+
*
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export declare type Awaitable<T> = PromiseLike<T> | T;
|
|
23
|
+
|
|
16
24
|
/**
|
|
17
25
|
* Decorator that binds a method to its class instance (legacy stage-2 TypeScript decorators).
|
|
18
26
|
* When applied to a class method, ensures `this` always refers to the class instance,
|
|
@@ -109,7 +117,7 @@ export declare function bind<This extends object, T extends (...args: any[]) =>
|
|
|
109
117
|
* @public
|
|
110
118
|
* @see source - https://gist.github.com/ca0v/73a31f57b397606c9813472f7493a940
|
|
111
119
|
*/
|
|
112
|
-
export declare function debounce<T extends unknown[], U>(callback: (...args: T) =>
|
|
120
|
+
export declare function debounce<T extends unknown[], U>(callback: (...args: T) => Awaitable<U>, wait: number): {
|
|
113
121
|
(...args: T): Promise<U>;
|
|
114
122
|
cancel: () => void;
|
|
115
123
|
};
|
package/dist-cjs/index.js
CHANGED
|
@@ -169,7 +169,7 @@ var import_version2 = require("./lib/version");
|
|
|
169
169
|
var import_warn = require("./lib/warn");
|
|
170
170
|
(0, import_version.registerTldrawLibraryVersion)(
|
|
171
171
|
"@tldraw/utils",
|
|
172
|
-
"4.6.0-next.
|
|
172
|
+
"4.6.0-next.d15997ff5a4b",
|
|
173
173
|
"cjs"
|
|
174
174
|
);
|
|
175
175
|
//# sourceMappingURL=index.js.map
|
package/dist-cjs/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { registerTldrawLibraryVersion } from './lib/version'\n\nexport { default as isEqual } from 'lodash.isequal'\nexport { default as isEqualWith } from 'lodash.isequalwith'\nexport { default as throttle } from 'lodash.throttle'\nexport { default as uniq } from 'lodash.uniq'\nexport {\n\tareArraysShallowEqual,\n\tcompact,\n\tdedupe,\n\tlast,\n\tmaxBy,\n\tmergeArraysAndReplaceDefaults,\n\tminBy,\n\tpartition,\n\trotateArray,\n} from './lib/array'\nexport { bind } from './lib/bind'\nexport { WeakCache } from './lib/cache'\nexport {\n\tassert,\n\tassertExists,\n\texhaustiveSwitchError,\n\tpromiseWithResolve,\n\tResult,\n\tsleep,\n\ttype ErrorResult,\n\ttype OkResult,\n} from './lib/control'\nexport { debounce } from './lib/debounce'\nexport { annotateError, getErrorAnnotations, type ErrorAnnotations } from './lib/error'\nexport { ExecutionQueue } from './lib/ExecutionQueue'\nexport { FileHelpers } from './lib/file'\nexport { noop, omitFromStackTrace } from './lib/function'\nexport { getHashForBuffer, getHashForObject, getHashForString, lns } from './lib/hash'\nexport { mockUniqueId, restoreUniqueId, uniqueId } from './lib/id'\nexport { getFirstFromIterable } from './lib/iterable'\nexport type { JsonArray, JsonObject, JsonPrimitive, JsonValue } from './lib/json-value'\nexport {\n\tDEFAULT_SUPPORT_VIDEO_TYPES,\n\tDEFAULT_SUPPORTED_IMAGE_TYPES,\n\tDEFAULT_SUPPORTED_MEDIA_TYPE_LIST,\n\tDEFAULT_SUPPORTED_MEDIA_TYPES,\n\tMediaHelpers,\n} from './lib/media/media'\nexport { PngHelpers } from './lib/media/png'\nexport { fetch, Image } from './lib/network'\nexport { invLerp, lerp, modulate, rng } from './lib/number'\nexport {\n\tareObjectsShallowEqual,\n\tfilterEntries,\n\tgetChangedKeys,\n\tgetOwnProperty,\n\tgroupBy,\n\thasOwnProperty,\n\tisEqualAllowingForFloatingPointErrors,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n\tobjectMapEntriesIterable,\n\tobjectMapFromEntries,\n\tobjectMapKeys,\n\tobjectMapValues,\n\tomit,\n} from './lib/object'\nexport { measureAverageDuration, measureCbDuration, measureDuration } from './lib/perf'\nexport { PerformanceTracker } from './lib/PerformanceTracker'\nexport {\n\tgetIndexAbove,\n\tgetIndexBelow,\n\tgetIndexBetween,\n\tgetIndices,\n\tgetIndicesAbove,\n\tgetIndicesBelow,\n\tgetIndicesBetween,\n\tsortByIndex,\n\tsortByMaybeIndex,\n\tvalidateIndexKey,\n\tZERO_INDEX_KEY,\n\ttype IndexKey,\n} from './lib/reordering'\nexport { retry } from './lib/retry'\nexport { sortById } from './lib/sort'\nexport {\n\tclearLocalStorage,\n\tclearSessionStorage,\n\tdeleteFromLocalStorage,\n\tdeleteFromSessionStorage,\n\tgetFromLocalStorage,\n\tgetFromSessionStorage,\n\tsetInLocalStorage,\n\tsetInSessionStorage,\n} from './lib/storage'\nexport { stringEnum } from './lib/stringEnum'\nexport { FpsScheduler, fpsThrottle, throttleToNextFrame } from './lib/throttle'\nexport { Timers } from './lib/timers'\nexport {\n\ttype Expand,\n\ttype MakeUndefinedOptional,\n\ttype RecursivePartial,\n\ttype Required,\n} from './lib/types'\nexport { safeParseUrl } from './lib/url'\nexport {\n\tisDefined,\n\tisNativeStructuredClone,\n\tisNonNull,\n\tisNonNullish,\n\tSTRUCTURED_CLONE_OBJECT_PROTOTYPE,\n\tstructuredClone,\n} from './lib/value'\nexport { registerTldrawLibraryVersion } from './lib/version'\nexport { warnDeprecatedGetter, warnOnce } from './lib/warn'\n\nregisterTldrawLibraryVersion(\n\t(globalThis as any).TLDRAW_LIBRARY_NAME,\n\t(globalThis as any).TLDRAW_LIBRARY_VERSION,\n\t(globalThis as any).TLDRAW_LIBRARY_MODULES\n)\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA6C;AAE7C,oBAAmC;AACnC,IAAAA,iBAAuC;AACvC,IAAAA,iBAAoC;AACpC,IAAAA,iBAAgC;AAChC,mBAUO;AACP,kBAAqB;AACrB,mBAA0B;AAC1B,qBASO;AACP,sBAAyB;AACzB,mBAA0E;AAC1E,4BAA+B;AAC/B,kBAA4B;AAC5B,sBAAyC;AACzC,kBAA0E;AAC1E,gBAAwD;AACxD,sBAAqC;AAErC,mBAMO;AACP,iBAA2B;AAC3B,qBAA6B;AAC7B,oBAA6C;AAC7C,oBAeO;AACP,kBAA2E;AAC3E,gCAAmC;AACnC,wBAaO;AACP,mBAAsB;AACtB,kBAAyB;AACzB,qBASO;AACP,wBAA2B;AAC3B,sBAA+D;AAC/D,oBAAuB;
|
|
4
|
+
"sourcesContent": ["import { registerTldrawLibraryVersion } from './lib/version'\n\nexport { default as isEqual } from 'lodash.isequal'\nexport { default as isEqualWith } from 'lodash.isequalwith'\nexport { default as throttle } from 'lodash.throttle'\nexport { default as uniq } from 'lodash.uniq'\nexport {\n\tareArraysShallowEqual,\n\tcompact,\n\tdedupe,\n\tlast,\n\tmaxBy,\n\tmergeArraysAndReplaceDefaults,\n\tminBy,\n\tpartition,\n\trotateArray,\n} from './lib/array'\nexport { bind } from './lib/bind'\nexport { WeakCache } from './lib/cache'\nexport {\n\tassert,\n\tassertExists,\n\texhaustiveSwitchError,\n\tpromiseWithResolve,\n\tResult,\n\tsleep,\n\ttype ErrorResult,\n\ttype OkResult,\n} from './lib/control'\nexport { debounce } from './lib/debounce'\nexport { annotateError, getErrorAnnotations, type ErrorAnnotations } from './lib/error'\nexport { ExecutionQueue } from './lib/ExecutionQueue'\nexport { FileHelpers } from './lib/file'\nexport { noop, omitFromStackTrace } from './lib/function'\nexport { getHashForBuffer, getHashForObject, getHashForString, lns } from './lib/hash'\nexport { mockUniqueId, restoreUniqueId, uniqueId } from './lib/id'\nexport { getFirstFromIterable } from './lib/iterable'\nexport type { JsonArray, JsonObject, JsonPrimitive, JsonValue } from './lib/json-value'\nexport {\n\tDEFAULT_SUPPORT_VIDEO_TYPES,\n\tDEFAULT_SUPPORTED_IMAGE_TYPES,\n\tDEFAULT_SUPPORTED_MEDIA_TYPE_LIST,\n\tDEFAULT_SUPPORTED_MEDIA_TYPES,\n\tMediaHelpers,\n} from './lib/media/media'\nexport { PngHelpers } from './lib/media/png'\nexport { fetch, Image } from './lib/network'\nexport { invLerp, lerp, modulate, rng } from './lib/number'\nexport {\n\tareObjectsShallowEqual,\n\tfilterEntries,\n\tgetChangedKeys,\n\tgetOwnProperty,\n\tgroupBy,\n\thasOwnProperty,\n\tisEqualAllowingForFloatingPointErrors,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n\tobjectMapEntriesIterable,\n\tobjectMapFromEntries,\n\tobjectMapKeys,\n\tobjectMapValues,\n\tomit,\n} from './lib/object'\nexport { measureAverageDuration, measureCbDuration, measureDuration } from './lib/perf'\nexport { PerformanceTracker } from './lib/PerformanceTracker'\nexport {\n\tgetIndexAbove,\n\tgetIndexBelow,\n\tgetIndexBetween,\n\tgetIndices,\n\tgetIndicesAbove,\n\tgetIndicesBelow,\n\tgetIndicesBetween,\n\tsortByIndex,\n\tsortByMaybeIndex,\n\tvalidateIndexKey,\n\tZERO_INDEX_KEY,\n\ttype IndexKey,\n} from './lib/reordering'\nexport { retry } from './lib/retry'\nexport { sortById } from './lib/sort'\nexport {\n\tclearLocalStorage,\n\tclearSessionStorage,\n\tdeleteFromLocalStorage,\n\tdeleteFromSessionStorage,\n\tgetFromLocalStorage,\n\tgetFromSessionStorage,\n\tsetInLocalStorage,\n\tsetInSessionStorage,\n} from './lib/storage'\nexport { stringEnum } from './lib/stringEnum'\nexport { FpsScheduler, fpsThrottle, throttleToNextFrame } from './lib/throttle'\nexport { Timers } from './lib/timers'\nexport {\n\ttype Awaitable,\n\ttype Expand,\n\ttype MakeUndefinedOptional,\n\ttype RecursivePartial,\n\ttype Required,\n} from './lib/types'\nexport { safeParseUrl } from './lib/url'\nexport {\n\tisDefined,\n\tisNativeStructuredClone,\n\tisNonNull,\n\tisNonNullish,\n\tSTRUCTURED_CLONE_OBJECT_PROTOTYPE,\n\tstructuredClone,\n} from './lib/value'\nexport { registerTldrawLibraryVersion } from './lib/version'\nexport { warnDeprecatedGetter, warnOnce } from './lib/warn'\n\nregisterTldrawLibraryVersion(\n\t(globalThis as any).TLDRAW_LIBRARY_NAME,\n\t(globalThis as any).TLDRAW_LIBRARY_VERSION,\n\t(globalThis as any).TLDRAW_LIBRARY_MODULES\n)\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAA6C;AAE7C,oBAAmC;AACnC,IAAAA,iBAAuC;AACvC,IAAAA,iBAAoC;AACpC,IAAAA,iBAAgC;AAChC,mBAUO;AACP,kBAAqB;AACrB,mBAA0B;AAC1B,qBASO;AACP,sBAAyB;AACzB,mBAA0E;AAC1E,4BAA+B;AAC/B,kBAA4B;AAC5B,sBAAyC;AACzC,kBAA0E;AAC1E,gBAAwD;AACxD,sBAAqC;AAErC,mBAMO;AACP,iBAA2B;AAC3B,qBAA6B;AAC7B,oBAA6C;AAC7C,oBAeO;AACP,kBAA2E;AAC3E,gCAAmC;AACnC,wBAaO;AACP,mBAAsB;AACtB,kBAAyB;AACzB,qBASO;AACP,wBAA2B;AAC3B,sBAA+D;AAC/D,oBAAuB;AAQvB,iBAA6B;AAC7B,mBAOO;AACP,IAAAC,kBAA6C;AAC7C,kBAA+C;AAAA,IAE/C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;",
|
|
6
6
|
"names": ["import_lodash", "import_version"]
|
|
7
7
|
}
|
|
@@ -32,7 +32,7 @@ class PerformanceTracker {
|
|
|
32
32
|
* Records animation frames to calculate frame rate.
|
|
33
33
|
* Called automatically during performance tracking.
|
|
34
34
|
*/
|
|
35
|
-
// eslint-disable-next-line
|
|
35
|
+
// eslint-disable-next-line tldraw/prefer-class-methods
|
|
36
36
|
recordFrame = () => {
|
|
37
37
|
this.frames++;
|
|
38
38
|
if (!this.started) return;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/PerformanceTracker.ts"],
|
|
4
|
-
"sourcesContent": ["import { PERFORMANCE_COLORS, PERFORMANCE_PREFIX_COLOR } from './perf'\n\n/**\n * A utility class for measuring and tracking frame rate performance during operations.\n * Provides visual feedback in the browser console with color-coded FPS indicators.\n *\n * @example\n * ```ts\n * const tracker = new PerformanceTracker()\n *\n * tracker.start('render')\n * renderShapes()\n * tracker.stop() // Logs performance info to console\n *\n * // Check if tracking is active\n * if (tracker.isStarted()) {\n * console.log('Still tracking performance')\n * }\n * ```\n *\n * @public\n */\nexport class PerformanceTracker {\n\tprivate startTime = 0\n\tprivate name = ''\n\tprivate frames = 0\n\tprivate started = false\n\tprivate frame: number | null = null\n\n\t/**\n\t * Records animation frames to calculate frame rate.\n\t * Called automatically during performance tracking.\n\t */\n\t// eslint-disable-next-line
|
|
4
|
+
"sourcesContent": ["import { PERFORMANCE_COLORS, PERFORMANCE_PREFIX_COLOR } from './perf'\n\n/**\n * A utility class for measuring and tracking frame rate performance during operations.\n * Provides visual feedback in the browser console with color-coded FPS indicators.\n *\n * @example\n * ```ts\n * const tracker = new PerformanceTracker()\n *\n * tracker.start('render')\n * renderShapes()\n * tracker.stop() // Logs performance info to console\n *\n * // Check if tracking is active\n * if (tracker.isStarted()) {\n * console.log('Still tracking performance')\n * }\n * ```\n *\n * @public\n */\nexport class PerformanceTracker {\n\tprivate startTime = 0\n\tprivate name = ''\n\tprivate frames = 0\n\tprivate started = false\n\tprivate frame: number | null = null\n\n\t/**\n\t * Records animation frames to calculate frame rate.\n\t * Called automatically during performance tracking.\n\t */\n\t// eslint-disable-next-line tldraw/prefer-class-methods\n\trecordFrame = () => {\n\t\tthis.frames++\n\t\tif (!this.started) return\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.frame = requestAnimationFrame(this.recordFrame)\n\t}\n\n\t/**\n\t * Starts performance tracking for a named operation.\n\t *\n\t * @param name - A descriptive name for the operation being tracked\n\t *\n\t * @example\n\t * ```ts\n\t * tracker.start('canvas-render')\n\t * // ... perform rendering operations\n\t * tracker.stop()\n\t * ```\n\t */\n\tstart(name: string) {\n\t\tthis.name = name\n\t\tthis.frames = 0\n\t\tthis.started = true\n\t\tif (this.frame !== null) cancelAnimationFrame(this.frame)\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.frame = requestAnimationFrame(this.recordFrame)\n\t\tthis.startTime = performance.now()\n\t}\n\n\t/**\n\t * Stops performance tracking and logs results to the console.\n\t *\n\t * Displays the operation name, frame rate, and uses color coding:\n\t * - Green background: \\> 55 FPS (good performance)\n\t * - Yellow background: 30-55 FPS (moderate performance)\n\t * - Red background: \\< 30 FPS (poor performance)\n\t *\n\t * @example\n\t * ```ts\n\t * tracker.start('interaction')\n\t * handleUserInteraction()\n\t * tracker.stop() // Logs: \"Perf Interaction 60 fps\"\n\t * ```\n\t */\n\tstop() {\n\t\tthis.started = false\n\t\tif (this.frame !== null) cancelAnimationFrame(this.frame)\n\t\tconst duration = (performance.now() - this.startTime) / 1000\n\t\tconst fps = duration === 0 ? 0 : Math.floor(this.frames / duration)\n\t\tconst background =\n\t\t\tfps > 55\n\t\t\t\t? PERFORMANCE_COLORS.Good\n\t\t\t\t: fps > 30\n\t\t\t\t\t? PERFORMANCE_COLORS.Mid\n\t\t\t\t\t: PERFORMANCE_COLORS.Poor\n\t\tconst color = background === PERFORMANCE_COLORS.Mid ? 'black' : 'white'\n\t\tconst capitalized = this.name[0].toUpperCase() + this.name.slice(1)\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.debug(\n\t\t\t`%cPerf%c ${capitalized} %c${fps}%c fps`,\n\t\t\t`color: white; background: ${PERFORMANCE_PREFIX_COLOR};padding: 2px;border-radius: 3px;`,\n\t\t\t'font-weight: normal',\n\t\t\t`font-weight: bold; padding: 2px; background: ${background};color: ${color};`,\n\t\t\t'font-weight: normal'\n\t\t)\n\t}\n\n\t/**\n\t * Checks whether performance tracking is currently active.\n\t *\n\t * @returns True if tracking is in progress, false otherwise\n\t *\n\t * @example\n\t * ```ts\n\t * if (!tracker.isStarted()) {\n\t * tracker.start('new-operation')\n\t * }\n\t * ```\n\t */\n\tisStarted() {\n\t\treturn this.started\n\t}\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAA6D;AAsBtD,MAAM,mBAAmB;AAAA,EACvB,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO/B,cAAc,MAAM;AACnB,SAAK;AACL,QAAI,CAAC,KAAK,QAAS;AAEnB,SAAK,QAAQ,sBAAsB,KAAK,WAAW;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,MAAc;AACnB,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,UAAU;AACf,QAAI,KAAK,UAAU,KAAM,sBAAqB,KAAK,KAAK;AAExD,SAAK,QAAQ,sBAAsB,KAAK,WAAW;AACnD,SAAK,YAAY,YAAY,IAAI;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,OAAO;AACN,SAAK,UAAU;AACf,QAAI,KAAK,UAAU,KAAM,sBAAqB,KAAK,KAAK;AACxD,UAAM,YAAY,YAAY,IAAI,IAAI,KAAK,aAAa;AACxD,UAAM,MAAM,aAAa,IAAI,IAAI,KAAK,MAAM,KAAK,SAAS,QAAQ;AAClE,UAAM,aACL,MAAM,KACH,+BAAmB,OACnB,MAAM,KACL,+BAAmB,MACnB,+BAAmB;AACxB,UAAM,QAAQ,eAAe,+BAAmB,MAAM,UAAU;AAChE,UAAM,cAAc,KAAK,KAAK,CAAC,EAAE,YAAY,IAAI,KAAK,KAAK,MAAM,CAAC;AAElE,YAAQ;AAAA,MACP,YAAY,WAAW,MAAM,GAAG;AAAA,MAChC,6BAA6B,oCAAwB;AAAA,MACrD;AAAA,MACA,gDAAgD,UAAU,WAAW,KAAK;AAAA,MAC1E;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,YAAY;AACX,WAAO,KAAK;AAAA,EACb;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-cjs/lib/bind.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/bind.ts"],
|
|
4
|
-
"sourcesContent": ["/*!\n * MIT License: https://github.com/NoHomey/bind-decorator/blob/master/License\n * Copyright (c) 2016 Ivo Stratev\n */\n\nimport { assert } from './control'\n\n/**\n * Decorator that binds a method to its class instance (legacy stage-2 TypeScript decorators).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param target - The prototype of the class being decorated\n * @param propertyKey - The name of the method being decorated\n * @param descriptor - The property descriptor for the method being decorated\n * @returns The modified property descriptor with bound method access\n * @example\n * ```typescript\n * class MyClass {\n * name = 'example';\n *\n * @bind\n * getName() {\n * return this.name;\n * }\n * }\n *\n * const instance = new MyClass();\n * const callback = instance.getName;\n * console.log(callback()); // 'example' (this is properly bound)\n * ```\n * @public\n */\nexport function bind<T extends (...args: any[]) => any>(\n\ttarget: object,\n\tpropertyKey: string,\n\tdescriptor: TypedPropertyDescriptor<T>\n): TypedPropertyDescriptor<T>\n\n/**\n * Decorator that binds a method to its class instance (TC39 decorators standard).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param originalMethod - The original method being decorated\n * @param context - The decorator context containing metadata about the method\n * @example\n * ```typescript\n * class EventHandler {\n * message = 'Hello World';\n *\n * @bind\n * handleClick() {\n * console.log(this.message);\n * }\n * }\n *\n * const handler = new EventHandler();\n * document.addEventListener('click', handler.handleClick); // 'this' is properly bound\n * ```\n * @public\n */\nexport function bind<This extends object, T extends (...args: any[]) => any>(\n\toriginalMethod: T,\n\tcontext: ClassMethodDecoratorContext<This, T>\n): void\n\n/**\n * Universal decorator implementation that handles both legacy stage-2 and TC39 decorator formats.\n * Automatically detects the decorator format based on the number of arguments and binds the\n * decorated method to the class instance, preventing common `this` context issues.\n *\n * @param args - Either legacy decorator arguments (target, propertyKey, descriptor) or TC39 decorator arguments (originalMethod, context)\n * @returns Property descriptor for legacy decorators, or void for TC39 decorators\n * @example\n * ```typescript\n * // Works with both decorator formats\n * class Calculator {\n * multiplier = 2;\n *\n * @bind\n * multiply(value: number) {\n * return value * this.multiplier;\n * }\n * }\n *\n * const calc = new Calculator();\n * const multiplyFn = calc.multiply;\n * console.log(multiplyFn(5)); // 10 (this.multiplier is accessible)\n *\n * // Useful for event handlers and callbacks\n * setTimeout(calc.multiply, 100, 3); // 6\n * ```\n * @public\n */\nexport function bind(\n\t...args: // legacy stage-2 typescript decorators\n\t| [_target: object, propertyKey: string, descriptor: PropertyDescriptor]\n\t\t// TC39 decorators\n\t\t| [originalMethod: (...args: any[]) => any, context: ClassMemberDecoratorContext]\n): PropertyDescriptor | void {\n\tif (args.length === 2) {\n\t\tconst [originalMethod, context] = args\n\t\tcontext.addInitializer(function initializeMethod(this: any) {\n\t\t\tassert(Reflect.isExtensible(this), 'Cannot bind to a non-extensible class.')\n\t\t\tconst value = originalMethod.bind(this)\n\t\t\tconst ok = Reflect.defineProperty(this, context.name, {\n\t\t\t\tvalue,\n\t\t\t\twritable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t})\n\t\t\tassert(ok, 'Cannot bind a non-configurable class method.')\n\t\t})\n\t} else {\n\t\tconst [_target, propertyKey, descriptor] = args\n\t\tif (!descriptor || typeof descriptor.value !== 'function') {\n\t\t\tthrow new TypeError(\n\t\t\t\t`Only methods can be decorated with @bind. <${propertyKey}> is not a method!`\n\t\t\t)\n\t\t}\n\n\t\treturn {\n\t\t\tconfigurable: true,\n\t\t\tget(this: any): any {\n\t\t\t\tconst bound = descriptor.value!.bind(this)\n\t\t\t\t// Credits to https://github.com/andreypopp/autobind-decorator for memoizing the result of bind against a symbol on the instance.\n\t\t\t\tObject.defineProperty(this, propertyKey, {\n\t\t\t\t\tvalue: bound,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t})\n\t\t\t\treturn bound\n\t\t\t},\n\t\t}\n\t}\n}\n"],
|
|
4
|
+
"sourcesContent": ["/*!\n * MIT License: https://github.com/NoHomey/bind-decorator/blob/master/License\n * Copyright (c) 2016 Ivo Stratev\n */\n\nimport { assert } from './control'\n\n/**\n * Decorator that binds a method to its class instance (legacy stage-2 TypeScript decorators).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param target - The prototype of the class being decorated\n * @param propertyKey - The name of the method being decorated\n * @param descriptor - The property descriptor for the method being decorated\n * @returns The modified property descriptor with bound method access\n * @example\n * ```typescript\n * class MyClass {\n * name = 'example';\n *\n * @bind\n * getName() {\n * return this.name;\n * }\n * }\n *\n * const instance = new MyClass();\n * const callback = instance.getName;\n * console.log(callback()); // 'example' (this is properly bound)\n * ```\n * @public\n */\nexport function bind<T extends (...args: any[]) => any>(\n\ttarget: object,\n\tpropertyKey: string,\n\tdescriptor: TypedPropertyDescriptor<T>\n): TypedPropertyDescriptor<T>\n\n/**\n * Decorator that binds a method to its class instance (TC39 decorators standard).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param originalMethod - The original method being decorated\n * @param context - The decorator context containing metadata about the method\n * @example\n * ```typescript\n * class EventHandler {\n * message = 'Hello World';\n *\n * @bind\n * handleClick() {\n * console.log(this.message);\n * }\n * }\n *\n * const handler = new EventHandler();\n * document.addEventListener('click', handler.handleClick); // 'this' is properly bound\n * ```\n * @public\n */\nexport function bind<This extends object, T extends (...args: any[]) => any>(\n\toriginalMethod: T,\n\tcontext: ClassMethodDecoratorContext<This, T>\n): void\n\n/**\n * Universal decorator implementation that handles both legacy stage-2 and TC39 decorator formats.\n * Automatically detects the decorator format based on the number of arguments and binds the\n * decorated method to the class instance, preventing common `this` context issues.\n *\n * @param args - Either legacy decorator arguments (target, propertyKey, descriptor) or TC39 decorator arguments (originalMethod, context)\n * @returns Property descriptor for legacy decorators, or void for TC39 decorators\n * @example\n * ```typescript\n * // Works with both decorator formats\n * class Calculator {\n * multiplier = 2;\n *\n * @bind\n * multiply(value: number) {\n * return value * this.multiplier;\n * }\n * }\n *\n * const calc = new Calculator();\n * const multiplyFn = calc.multiply;\n * console.log(multiplyFn(5)); // 10 (this.multiplier is accessible)\n *\n * // Useful for event handlers and callbacks\n * setTimeout(calc.multiply, 100, 3); // 6\n * ```\n * @public\n */\nexport function bind(\n\t...args: // legacy stage-2 typescript decorators\n\t\t| [_target: object, propertyKey: string, descriptor: PropertyDescriptor]\n\t\t// TC39 decorators\n\t\t| [originalMethod: (...args: any[]) => any, context: ClassMemberDecoratorContext]\n): PropertyDescriptor | void {\n\tif (args.length === 2) {\n\t\tconst [originalMethod, context] = args\n\t\tcontext.addInitializer(function initializeMethod(this: any) {\n\t\t\tassert(Reflect.isExtensible(this), 'Cannot bind to a non-extensible class.')\n\t\t\tconst value = originalMethod.bind(this)\n\t\t\tconst ok = Reflect.defineProperty(this, context.name, {\n\t\t\t\tvalue,\n\t\t\t\twritable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t})\n\t\t\tassert(ok, 'Cannot bind a non-configurable class method.')\n\t\t})\n\t} else {\n\t\tconst [_target, propertyKey, descriptor] = args\n\t\tif (!descriptor || typeof descriptor.value !== 'function') {\n\t\t\tthrow new TypeError(\n\t\t\t\t`Only methods can be decorated with @bind. <${propertyKey}> is not a method!`\n\t\t\t)\n\t\t}\n\n\t\treturn {\n\t\t\tconfigurable: true,\n\t\t\tget(this: any): any {\n\t\t\t\tconst bound = descriptor.value!.bind(this)\n\t\t\t\t// Credits to https://github.com/andreypopp/autobind-decorator for memoizing the result of bind against a symbol on the instance.\n\t\t\t\tObject.defineProperty(this, propertyKey, {\n\t\t\t\t\tvalue: bound,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t})\n\t\t\t\treturn bound\n\t\t\t},\n\t\t}\n\t}\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,qBAAuB;AALvB;AAAA;AAAA;AAAA;AA+FO,SAAS,QACZ,MAIyB;AAC5B,MAAI,KAAK,WAAW,GAAG;AACtB,UAAM,CAAC,gBAAgB,OAAO,IAAI;AAClC,YAAQ,eAAe,SAAS,mBAA4B;AAC3D,iCAAO,QAAQ,aAAa,IAAI,GAAG,wCAAwC;AAC3E,YAAM,QAAQ,eAAe,KAAK,IAAI;AACtC,YAAM,KAAK,QAAQ,eAAe,MAAM,QAAQ,MAAM;AAAA,QACrD;AAAA,QACA,UAAU;AAAA,QACV,cAAc;AAAA,MACf,CAAC;AACD,iCAAO,IAAI,8CAA8C;AAAA,IAC1D,CAAC;AAAA,EACF,OAAO;AACN,UAAM,CAAC,SAAS,aAAa,UAAU,IAAI;AAC3C,QAAI,CAAC,cAAc,OAAO,WAAW,UAAU,YAAY;AAC1D,YAAM,IAAI;AAAA,QACT,8CAA8C,WAAW;AAAA,MAC1D;AAAA,IACD;AAEA,WAAO;AAAA,MACN,cAAc;AAAA,MACd,MAAoB;AACnB,cAAM,QAAQ,WAAW,MAAO,KAAK,IAAI;AAEzC,eAAO,eAAe,MAAM,aAAa;AAAA,UACxC,OAAO;AAAA,UACP,cAAc;AAAA,UACd,UAAU;AAAA,QACX,CAAC;AACD,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/debounce.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Create a debounced version of a function that delays execution until after a specified wait time.\n *\n * Debouncing ensures that a function is only executed once after a specified delay,\n * even if called multiple times in rapid succession. Each new call resets the timer. The debounced\n * function returns a Promise that resolves with the result of the original function. Includes a\n * cancel method to prevent execution if needed.\n *\n * @param callback - The function to debounce (can be sync or async)\n * @param wait - The delay in milliseconds before executing the function\n * @returns A debounced function that returns a Promise and includes a cancel method\n *\n * @example\n * ```ts\n * // Debounce a search function\n * const searchAPI = (query: string) => fetch(`/search?q=${query}`)\n * const debouncedSearch = debounce(searchAPI, 300)\n *\n * // Multiple rapid calls will only execute the last one after 300ms\n * debouncedSearch('react').then(result => console.log(result))\n * debouncedSearch('react hooks') // This cancels the previous call\n * debouncedSearch('react typescript') // Only this will execute\n *\n * // Cancel pending execution\n * debouncedSearch.cancel()\n *\n * // With async/await\n * const saveData = debounce(async (data: any) => {\n * return await api.save(data)\n * }, 1000)\n *\n * const result = await saveData({name: 'John'})\n * ```\n *\n * @public\n * @see source - https://gist.github.com/ca0v/73a31f57b397606c9813472f7493a940\n */\nexport function debounce<T extends unknown[], U>(\n\tcallback: (...args: T) =>
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import type { Awaitable } from './types'\n\n/**\n * Create a debounced version of a function that delays execution until after a specified wait time.\n *\n * Debouncing ensures that a function is only executed once after a specified delay,\n * even if called multiple times in rapid succession. Each new call resets the timer. The debounced\n * function returns a Promise that resolves with the result of the original function. Includes a\n * cancel method to prevent execution if needed.\n *\n * @param callback - The function to debounce (can be sync or async)\n * @param wait - The delay in milliseconds before executing the function\n * @returns A debounced function that returns a Promise and includes a cancel method\n *\n * @example\n * ```ts\n * // Debounce a search function\n * const searchAPI = (query: string) => fetch(`/search?q=${query}`)\n * const debouncedSearch = debounce(searchAPI, 300)\n *\n * // Multiple rapid calls will only execute the last one after 300ms\n * debouncedSearch('react').then(result => console.log(result))\n * debouncedSearch('react hooks') // This cancels the previous call\n * debouncedSearch('react typescript') // Only this will execute\n *\n * // Cancel pending execution\n * debouncedSearch.cancel()\n *\n * // With async/await\n * const saveData = debounce(async (data: any) => {\n * return await api.save(data)\n * }, 1000)\n *\n * const result = await saveData({name: 'John'})\n * ```\n *\n * @public\n * @see source - https://gist.github.com/ca0v/73a31f57b397606c9813472f7493a940\n */\nexport function debounce<T extends unknown[], U>(\n\tcallback: (...args: T) => Awaitable<U>,\n\twait: number\n) {\n\tlet state:\n\t\t| undefined\n\t\t| {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\ttimeout: ReturnType<typeof setTimeout>\n\t\t\t\tpromise: Promise<U>\n\t\t\t\tresolve(value: U | PromiseLike<U>): void\n\t\t\t\treject(value: any): void\n\t\t\t\tlatestArgs: T\n\t\t } = undefined\n\n\tconst fn = (...args: T): Promise<U> => {\n\t\tif (!state) {\n\t\t\tstate = {} as any\n\t\t\tstate!.promise = new Promise((resolve, reject) => {\n\t\t\t\tstate!.resolve = resolve\n\t\t\t\tstate!.reject = reject\n\t\t\t})\n\t\t}\n\t\tclearTimeout(state!.timeout)\n\t\tstate!.latestArgs = args\n\t\t// It's up to the consumer of debounce to call `cancel`\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tstate!.timeout = setTimeout(() => {\n\t\t\tconst s = state!\n\t\t\tstate = undefined\n\t\t\ttry {\n\t\t\t\ts.resolve(callback(...s.latestArgs))\n\t\t\t} catch (e) {\n\t\t\t\ts.reject(e)\n\t\t\t}\n\t\t}, wait)\n\n\t\treturn state!.promise\n\t}\n\tfn.cancel = () => {\n\t\tif (!state) return\n\t\tclearTimeout(state.timeout)\n\t}\n\treturn fn\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAuCO,SAAS,SACf,UACA,MACC;AACD,MAAI,QASG;AAEP,QAAM,KAAK,IAAI,SAAwB;AACtC,QAAI,CAAC,OAAO;AACX,cAAQ,CAAC;AACT,YAAO,UAAU,IAAI,QAAQ,CAAC,SAAS,WAAW;AACjD,cAAO,UAAU;AACjB,cAAO,SAAS;AAAA,MACjB,CAAC;AAAA,IACF;AACA,iBAAa,MAAO,OAAO;AAC3B,UAAO,aAAa;AAGpB,UAAO,UAAU,WAAW,MAAM;AACjC,YAAM,IAAI;AACV,cAAQ;AACR,UAAI;AACH,UAAE,QAAQ,SAAS,GAAG,EAAE,UAAU,CAAC;AAAA,MACpC,SAAS,GAAG;AACX,UAAE,OAAO,CAAC;AAAA,MACX;AAAA,IACD,GAAG,IAAI;AAEP,WAAO,MAAO;AAAA,EACf;AACA,KAAG,SAAS,MAAM;AACjB,QAAI,CAAC,MAAO;AACZ,iBAAa,MAAM,OAAO;AAAA,EAC3B;AACA,SAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/network.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Just a wrapper around `window.fetch` that sets the `referrerPolicy` to `strict-origin-when-cross-origin`.\n *\n * @param input - A Request object or string containing the URL to fetch\n * @param init - Optional request initialization options\n * @returns Promise that resolves to the Response object\n * @internal\n */\nexport async function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n\t// eslint-disable-next-line no-restricted-properties\n\treturn window.fetch(input, {\n\t\t// We want to make sure that the referrer is not sent to other domains.\n\t\treferrerPolicy: 'strict-origin-when-cross-origin',\n\t\t...init,\n\t})\n}\n\n/**\n * Just a wrapper around `new Image`, and yeah, it's a bit strange that it's in the network.ts file\n * but the main concern here is the referrerPolicy and setting it correctly.\n *\n * @param width - Optional width for the image element\n * @param height - Optional height for the image element\n * @returns HTMLImageElement with referrerPolicy set to 'strict-origin-when-cross-origin'\n * @internal\n */\nexport const Image = (width?: number, height?: number) => {\n\t// eslint-disable-next-line no-restricted-properties\n\tconst img = new window.Image(width, height)\n\timg.referrerPolicy = 'strict-origin-when-cross-origin'\n\treturn img\n}\n"],
|
|
4
|
+
"sourcesContent": ["/**\n * Just a wrapper around `window.fetch` that sets the `referrerPolicy` to `strict-origin-when-cross-origin`.\n *\n * @param input - A Request object or string containing the URL to fetch\n * @param init - Optional request initialization options\n * @returns Promise that resolves to the Response object\n * @internal\n */\nexport async function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n\t// eslint-disable-next-line tldraw/no-restricted-properties\n\treturn window.fetch(input, {\n\t\t// We want to make sure that the referrer is not sent to other domains.\n\t\treferrerPolicy: 'strict-origin-when-cross-origin',\n\t\t...init,\n\t})\n}\n\n/**\n * Just a wrapper around `new Image`, and yeah, it's a bit strange that it's in the network.ts file\n * but the main concern here is the referrerPolicy and setting it correctly.\n *\n * @param width - Optional width for the image element\n * @param height - Optional height for the image element\n * @returns HTMLImageElement with referrerPolicy set to 'strict-origin-when-cross-origin'\n * @internal\n */\nexport const Image = (width?: number, height?: number) => {\n\t// eslint-disable-next-line tldraw/no-restricted-properties\n\tconst img = new window.Image(width, height)\n\timg.referrerPolicy = 'strict-origin-when-cross-origin'\n\treturn img\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,eAAsB,MAAM,OAA0B,MAAuC;AAE5F,SAAO,OAAO,MAAM,OAAO;AAAA;AAAA,IAE1B,gBAAgB;AAAA,IAChB,GAAG;AAAA,EACJ,CAAC;AACF;AAWO,MAAM,QAAQ,CAAC,OAAgB,WAAoB;AAEzD,QAAM,MAAM,IAAI,OAAO,MAAM,OAAO,MAAM;AAC1C,MAAI,iBAAiB;AACrB,SAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/retry.ts"],
|
|
4
|
-
"sourcesContent": ["import { sleep } from './control'\n\n/**\n * Retries an async operation with configurable attempt count, wait duration, and error filtering.\n * Executes the provided async function repeatedly until it succeeds or the maximum number of attempts is reached.\n * Includes support for abort signals and custom error matching to determine which errors should trigger retries.\n *\n * @param fn - The async function to retry on failure\n * @param options - Configuration options for retry behavior:\n * - `attempts`: Maximum number of retry attempts (default: 3)\n * - `waitDuration`: Milliseconds to wait between retry attempts (default: 1000)\n * - `abortSignal`: Optional AbortSignal to cancel the retry operation\n * - `matchError`: Optional function to determine if an error should trigger a retry\n * @returns Promise that resolves with the function's return value on success\n *\n * @example\n * ```ts\n * // Basic retry with default settings (3 attempts, 1 second wait)\n * const data = await retry(async () => {\n * const response = await fetch('/api/data')\n * if (!response.ok) throw new Error('Network error')\n * return response.json()\n * })\n *\n * // Custom retry configuration\n * const result = await retry(\n * async () => unreliableApiCall(),\n * {\n * attempts: 5,\n * waitDuration: 2000,\n * matchError: (error) => error instanceof NetworkError\n * }\n * )\n *\n * // With abort signal for cancellation\n * const controller = new AbortController()\n * setTimeout(() => controller.abort(), 10000) // Cancel after 10 seconds\n *\n * const data = await retry(\n * async () => fetchData(),\n * {\n * attempts: 10,\n * abortSignal: controller.signal\n * }\n * )\n * ```\n *\n * @internal\n */\nexport async function retry<T>(\n\tfn: (args: { attempt: number; remaining: number; total: number }) => Promise<T>,\n\t{\n\t\tattempts = 3,\n\t\twaitDuration = 1000,\n\t\tabortSignal,\n\t\tmatchError,\n\t}: {\n\t\tattempts?: number\n\t\twaitDuration?: number\n\t\tabortSignal?: AbortSignal\n\t\tmatchError?(error: unknown): boolean\n\t} = {}\n): Promise<T> {\n\tlet error: unknown = null\n\tfor (let i = 0; i < attempts; i++) {\n\t\tif (abortSignal?.aborted) throw new Error('aborted')\n\t\ttry {\n\t\t\treturn await fn({ attempt: i, remaining: attempts - i, total: attempts })\n\t\t} catch (e) {\n\t\t\tif (matchError && !matchError(e)) throw e\n\t\t\terror = e\n\t\t\tawait sleep(waitDuration)\n\t\t}\n\t}\n\tthrow error\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAsB;AAiDtB,eAAsB,MACrB,IACA;AAAA,EACC,WAAW;AAAA,EACX,eAAe;AAAA,EACf;AAAA,EACA;AACD,IAKI,CAAC,GACQ;AACb,MAAI,QAAiB;AACrB,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAClC,QAAI,aAAa,QAAS,OAAM,IAAI,MAAM,SAAS;AACnD,QAAI;AACH,aAAO,MAAM,GAAG,EAAE,SAAS,GAAG,WAAW,WAAW,GAAG,OAAO,SAAS,CAAC;AAAA,IACzE,SAAS,GAAG;AACX,UAAI,cAAc,CAAC,WAAW,CAAC,EAAG,OAAM;AACxC,cAAQ;AACR,gBAAM,sBAAM,YAAY;AAAA,IACzB;AAAA,EACD;
|
|
4
|
+
"sourcesContent": ["import { sleep } from './control'\n\n/**\n * Retries an async operation with configurable attempt count, wait duration, and error filtering.\n * Executes the provided async function repeatedly until it succeeds or the maximum number of attempts is reached.\n * Includes support for abort signals and custom error matching to determine which errors should trigger retries.\n *\n * @param fn - The async function to retry on failure\n * @param options - Configuration options for retry behavior:\n * - `attempts`: Maximum number of retry attempts (default: 3)\n * - `waitDuration`: Milliseconds to wait between retry attempts (default: 1000)\n * - `abortSignal`: Optional AbortSignal to cancel the retry operation\n * - `matchError`: Optional function to determine if an error should trigger a retry\n * @returns Promise that resolves with the function's return value on success\n *\n * @example\n * ```ts\n * // Basic retry with default settings (3 attempts, 1 second wait)\n * const data = await retry(async () => {\n * const response = await fetch('/api/data')\n * if (!response.ok) throw new Error('Network error')\n * return response.json()\n * })\n *\n * // Custom retry configuration\n * const result = await retry(\n * async () => unreliableApiCall(),\n * {\n * attempts: 5,\n * waitDuration: 2000,\n * matchError: (error) => error instanceof NetworkError\n * }\n * )\n *\n * // With abort signal for cancellation\n * const controller = new AbortController()\n * setTimeout(() => controller.abort(), 10000) // Cancel after 10 seconds\n *\n * const data = await retry(\n * async () => fetchData(),\n * {\n * attempts: 10,\n * abortSignal: controller.signal\n * }\n * )\n * ```\n *\n * @internal\n */\nexport async function retry<T>(\n\tfn: (args: { attempt: number; remaining: number; total: number }) => Promise<T>,\n\t{\n\t\tattempts = 3,\n\t\twaitDuration = 1000,\n\t\tabortSignal,\n\t\tmatchError,\n\t}: {\n\t\tattempts?: number\n\t\twaitDuration?: number\n\t\tabortSignal?: AbortSignal\n\t\tmatchError?(error: unknown): boolean\n\t} = {}\n): Promise<T> {\n\tlet error: unknown = null\n\tfor (let i = 0; i < attempts; i++) {\n\t\tif (abortSignal?.aborted) throw new Error('aborted')\n\t\ttry {\n\t\t\treturn await fn({ attempt: i, remaining: attempts - i, total: attempts })\n\t\t} catch (e) {\n\t\t\tif (matchError && !matchError(e)) throw e\n\t\t\terror = e\n\t\t\tawait sleep(waitDuration)\n\t\t}\n\t}\n\t// eslint-disable-next-line no-throw-literal\n\tthrow error\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAsB;AAiDtB,eAAsB,MACrB,IACA;AAAA,EACC,WAAW;AAAA,EACX,eAAe;AAAA,EACf;AAAA,EACA;AACD,IAKI,CAAC,GACQ;AACb,MAAI,QAAiB;AACrB,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAClC,QAAI,aAAa,QAAS,OAAM,IAAI,MAAM,SAAS;AACnD,QAAI;AACH,aAAO,MAAM,GAAG,EAAE,SAAS,GAAG,WAAW,WAAW,GAAG,OAAO,SAAS,CAAC;AAAA,IACzE,SAAS,GAAG;AACX,UAAI,cAAc,CAAC,WAAW,CAAC,EAAG,OAAM;AACxC,cAAQ;AACR,gBAAM,sBAAM,YAAY;AAAA,IACzB;AAAA,EACD;AAEA,QAAM;AACP;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/storage.tsx"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable no-
|
|
4
|
+
"sourcesContent": ["/* eslint-disable tldraw/no-direct-storage */\n\n/**\n * Get a value from local storage.\n *\n * @param key - The key to get.\n * @returns The stored value as a string, or null if not found or storage is unavailable.\n * @example\n * ```ts\n * const userTheme = getFromLocalStorage('user-theme')\n * if (userTheme) {\n * console.log('Stored theme:', userTheme)\n * }\n * ```\n * @internal\n */\nexport function getFromLocalStorage(key: string) {\n\ttry {\n\t\treturn localStorage.getItem(key)\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Set a value in local storage. Will not throw an error if localStorage is not available.\n *\n * @param key - The key to set.\n * @param value - The value to set.\n * @returns void\n * @example\n * ```ts\n * const preferences = { theme: 'dark', language: 'en' }\n * setInLocalStorage('user-preferences', JSON.stringify(preferences))\n * ```\n * @internal\n */\nexport function setInLocalStorage(key: string, value: string) {\n\ttry {\n\t\tlocalStorage.setItem(key, value)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Remove a value from local storage. Will not throw an error if localStorage is not available.\n *\n * @param key - The key to remove.\n * @returns void\n * @example\n * ```ts\n * deleteFromLocalStorage('user-preferences')\n * // Value is now removed from localStorage\n * ```\n * @internal\n */\nexport function deleteFromLocalStorage(key: string) {\n\ttry {\n\t\tlocalStorage.removeItem(key)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Clear all values from local storage. Will not throw an error if localStorage is not available.\n *\n * @returns void\n * @example\n * ```ts\n * clearLocalStorage()\n * // All localStorage data is now cleared\n * ```\n * @internal\n */\nexport function clearLocalStorage() {\n\ttry {\n\t\tlocalStorage.clear()\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Get a value from session storage.\n *\n * @param key - The key to get.\n * @returns The stored value as a string, or null if not found or storage is unavailable.\n * @example\n * ```ts\n * const currentTool = getFromSessionStorage('current-tool')\n * if (currentTool) {\n * console.log('Active tool:', currentTool)\n * }\n * ```\n * @internal\n */\nexport function getFromSessionStorage(key: string) {\n\ttry {\n\t\treturn sessionStorage.getItem(key)\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Set a value in session storage. Will not throw an error if sessionStorage is not available.\n *\n * @param key - The key to set.\n * @param value - The value to set.\n * @returns void\n * @example\n * ```ts\n * setInSessionStorage('current-tool', 'select')\n * setInSessionStorage('temp-data', JSON.stringify({ x: 100, y: 200 }))\n * ```\n * @internal\n */\nexport function setInSessionStorage(key: string, value: string) {\n\ttry {\n\t\tsessionStorage.setItem(key, value)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Remove a value from session storage. Will not throw an error if sessionStorage is not available.\n *\n * @param key - The key to remove.\n * @returns void\n * @example\n * ```ts\n * deleteFromSessionStorage('temp-data')\n * // Value is now removed from sessionStorage\n * ```\n * @internal\n */\nexport function deleteFromSessionStorage(key: string) {\n\ttry {\n\t\tsessionStorage.removeItem(key)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Clear all values from session storage. Will not throw an error if sessionStorage is not available.\n *\n * @returns void\n * @example\n * ```ts\n * clearSessionStorage()\n * // All sessionStorage data is now cleared\n * ```\n * @internal\n */\nexport function clearSessionStorage() {\n\ttry {\n\t\tsessionStorage.clear()\n\t} catch {\n\t\t// noop\n\t}\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBO,SAAS,oBAAoB,KAAa;AAChD,MAAI;AACH,WAAO,aAAa,QAAQ,GAAG;AAAA,EAChC,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAeO,SAAS,kBAAkB,KAAa,OAAe;AAC7D,MAAI;AACH,iBAAa,QAAQ,KAAK,KAAK;AAAA,EAChC,QAAQ;AAAA,EAER;AACD;AAcO,SAAS,uBAAuB,KAAa;AACnD,MAAI;AACH,iBAAa,WAAW,GAAG;AAAA,EAC5B,QAAQ;AAAA,EAER;AACD;AAaO,SAAS,oBAAoB;AACnC,MAAI;AACH,iBAAa,MAAM;AAAA,EACpB,QAAQ;AAAA,EAER;AACD;AAgBO,SAAS,sBAAsB,KAAa;AAClD,MAAI;AACH,WAAO,eAAe,QAAQ,GAAG;AAAA,EAClC,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAeO,SAAS,oBAAoB,KAAa,OAAe;AAC/D,MAAI;AACH,mBAAe,QAAQ,KAAK,KAAK;AAAA,EAClC,QAAQ;AAAA,EAER;AACD;AAcO,SAAS,yBAAyB,KAAa;AACrD,MAAI;AACH,mBAAe,WAAW,GAAG;AAAA,EAC9B,QAAQ;AAAA,EAER;AACD;AAaO,SAAS,sBAAsB;AACrC,MAAI;AACH,mBAAe,MAAM;AAAA,EACtB,QAAQ;AAAA,EAER;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/timers.ts"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable no-restricted-properties */\n\n/**\n * A utility class for managing timeouts, intervals, and animation frames with context-based organization and automatic cleanup.\n * Helps prevent memory leaks by organizing timers into named contexts that can be cleared together.\n * @example\n * ```ts\n * const timers = new Timers()\n *\n * // Set timers with context organization\n * timers.setTimeout('ui', () => console.log('Auto save'), 5000)\n * timers.setInterval('ui', () => console.log('Refresh'), 1000)\n * timers.requestAnimationFrame('ui', () => console.log('Render'))\n *\n * // Clear all timers for a context\n * timers.dispose('ui')\n *\n * // Or get context-bound functions\n * const uiTimers = timers.forContext('ui')\n * uiTimers.setTimeout(() => console.log('Contextual timeout'), 1000)\n * ```\n * @public\n */\nexport class Timers {\n\tprivate timeouts = new Map<string, number[]>()\n\tprivate intervals = new Map<string, number[]>()\n\tprivate rafs = new Map<string, number[]>()\n\n\t/**\n\t * Creates a new Timers instance with bound methods for safe callback usage.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * // Methods are pre-bound, safe to use as callbacks\n\t * element.addEventListener('click', timers.dispose)\n\t * ```\n\t */\n\tconstructor() {\n\t\tthis.setTimeout = this.setTimeout.bind(this)\n\t\tthis.setInterval = this.setInterval.bind(this)\n\t\tthis.requestAnimationFrame = this.requestAnimationFrame.bind(this)\n\t\tthis.dispose = this.dispose.bind(this)\n\t}\n\n\t/**\n\t * Creates a timeout that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute when the timeout expires.\n\t * @param timeout - The delay in milliseconds (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The timer ID that can be used with clearTimeout.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setTimeout('autosave', () => save(), 5000)\n\t * // Timer will be automatically cleared when 'autosave' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetTimeout(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setTimeout(handler, timeout, args)\n\t\tconst current = this.timeouts.get(contextId) ?? []\n\t\tthis.timeouts.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Creates an interval that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute repeatedly.\n\t * @param timeout - The delay in milliseconds between executions (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The interval ID that can be used with clearInterval.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setInterval('refresh', () => updateData(), 1000)\n\t * // Interval will be automatically cleared when 'refresh' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetInterval(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setInterval(handler, timeout, args)\n\t\tconst current = this.intervals.get(contextId) ?? []\n\t\tthis.intervals.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Requests an animation frame that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this animation frame under.\n\t * @param callback - The function to execute on the next animation frame.\n\t * @returns The request ID that can be used with cancelAnimationFrame.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.requestAnimationFrame('render', () => draw())\n\t * // Animation frame will be automatically cancelled when 'render' context is disposed\n\t * ```\n\t * @public\n\t */\n\trequestAnimationFrame(contextId: string, callback: FrameRequestCallback): number {\n\t\tconst id = window.requestAnimationFrame(callback)\n\t\tconst current = this.rafs.get(contextId) ?? []\n\t\tthis.rafs.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Disposes of all timers associated with the specified context.\n\t * Clears all timeouts, intervals, and animation frames for the given context ID.\n\t * @param contextId - The context identifier whose timers should be cleared.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('timeout'), 1000)\n\t * timers.setInterval('ui', () => console.log('interval'), 500)\n\t *\n\t * // Clear all 'ui' context timers\n\t * timers.dispose('ui')\n\t * ```\n\t * @public\n\t */\n\tdispose(contextId: string) {\n\t\tthis.timeouts.get(contextId)?.forEach((id) => clearTimeout(id))\n\t\tthis.intervals.get(contextId)?.forEach((id) => clearInterval(id))\n\t\tthis.rafs.get(contextId)?.forEach((id) => cancelAnimationFrame(id))\n\n\t\tthis.timeouts.delete(contextId)\n\t\tthis.intervals.delete(contextId)\n\t\tthis.rafs.delete(contextId)\n\t}\n\n\t/**\n\t * Disposes of all timers across all contexts.\n\t * Clears every timeout, interval, and animation frame managed by this instance.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('ui'), 1000)\n\t * timers.setTimeout('background', () => console.log('bg'), 2000)\n\t *\n\t * // Clear everything\n\t * timers.disposeAll()\n\t * ```\n\t * @public\n\t */\n\tdisposeAll() {\n\t\tfor (const contextId of this.timeouts.keys()) {\n\t\t\tthis.dispose(contextId)\n\t\t}\n\t}\n\n\t/**\n\t * Returns an object with timer methods bound to a specific context.\n\t * Convenient for getting context-specific timer functions without repeatedly passing the contextId.\n\t * @param contextId - The context identifier to bind the returned methods to.\n\t * @returns An object with setTimeout, setInterval, requestAnimationFrame, and dispose methods bound to the context.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const uiTimers = timers.forContext('ui')\n\t *\n\t * // These are equivalent to calling timers.setTimeout('ui', ...)\n\t * uiTimers.setTimeout(() => console.log('timeout'), 1000)\n\t * uiTimers.setInterval(() => console.log('interval'), 500)\n\t * uiTimers.requestAnimationFrame(() => console.log('frame'))\n\t *\n\t * // Dispose only this context\n\t * uiTimers.dispose()\n\t * ```\n\t * @public\n\t */\n\tforContext(contextId: string) {\n\t\treturn {\n\t\t\tsetTimeout: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setTimeout(contextId, handler, timeout, args),\n\t\t\tsetInterval: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setInterval(contextId, handler, timeout, args),\n\t\t\trequestAnimationFrame: (callback: FrameRequestCallback) =>\n\t\t\t\tthis.requestAnimationFrame(contextId, callback),\n\t\t\tdispose: () => this.dispose(contextId),\n\t\t}\n\t}\n}\n"],
|
|
4
|
+
"sourcesContent": ["/* eslint-disable tldraw/no-restricted-properties */\n\n/**\n * A utility class for managing timeouts, intervals, and animation frames with context-based organization and automatic cleanup.\n * Helps prevent memory leaks by organizing timers into named contexts that can be cleared together.\n * @example\n * ```ts\n * const timers = new Timers()\n *\n * // Set timers with context organization\n * timers.setTimeout('ui', () => console.log('Auto save'), 5000)\n * timers.setInterval('ui', () => console.log('Refresh'), 1000)\n * timers.requestAnimationFrame('ui', () => console.log('Render'))\n *\n * // Clear all timers for a context\n * timers.dispose('ui')\n *\n * // Or get context-bound functions\n * const uiTimers = timers.forContext('ui')\n * uiTimers.setTimeout(() => console.log('Contextual timeout'), 1000)\n * ```\n * @public\n */\nexport class Timers {\n\tprivate timeouts = new Map<string, number[]>()\n\tprivate intervals = new Map<string, number[]>()\n\tprivate rafs = new Map<string, number[]>()\n\n\t/**\n\t * Creates a new Timers instance with bound methods for safe callback usage.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * // Methods are pre-bound, safe to use as callbacks\n\t * element.addEventListener('click', timers.dispose)\n\t * ```\n\t */\n\tconstructor() {\n\t\tthis.setTimeout = this.setTimeout.bind(this)\n\t\tthis.setInterval = this.setInterval.bind(this)\n\t\tthis.requestAnimationFrame = this.requestAnimationFrame.bind(this)\n\t\tthis.dispose = this.dispose.bind(this)\n\t}\n\n\t/**\n\t * Creates a timeout that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute when the timeout expires.\n\t * @param timeout - The delay in milliseconds (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The timer ID that can be used with clearTimeout.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setTimeout('autosave', () => save(), 5000)\n\t * // Timer will be automatically cleared when 'autosave' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetTimeout(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setTimeout(handler, timeout, args)\n\t\tconst current = this.timeouts.get(contextId) ?? []\n\t\tthis.timeouts.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Creates an interval that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute repeatedly.\n\t * @param timeout - The delay in milliseconds between executions (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The interval ID that can be used with clearInterval.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setInterval('refresh', () => updateData(), 1000)\n\t * // Interval will be automatically cleared when 'refresh' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetInterval(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setInterval(handler, timeout, args)\n\t\tconst current = this.intervals.get(contextId) ?? []\n\t\tthis.intervals.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Requests an animation frame that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this animation frame under.\n\t * @param callback - The function to execute on the next animation frame.\n\t * @returns The request ID that can be used with cancelAnimationFrame.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.requestAnimationFrame('render', () => draw())\n\t * // Animation frame will be automatically cancelled when 'render' context is disposed\n\t * ```\n\t * @public\n\t */\n\trequestAnimationFrame(contextId: string, callback: FrameRequestCallback): number {\n\t\tconst id = window.requestAnimationFrame(callback)\n\t\tconst current = this.rafs.get(contextId) ?? []\n\t\tthis.rafs.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Disposes of all timers associated with the specified context.\n\t * Clears all timeouts, intervals, and animation frames for the given context ID.\n\t * @param contextId - The context identifier whose timers should be cleared.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('timeout'), 1000)\n\t * timers.setInterval('ui', () => console.log('interval'), 500)\n\t *\n\t * // Clear all 'ui' context timers\n\t * timers.dispose('ui')\n\t * ```\n\t * @public\n\t */\n\tdispose(contextId: string) {\n\t\tthis.timeouts.get(contextId)?.forEach((id) => clearTimeout(id))\n\t\tthis.intervals.get(contextId)?.forEach((id) => clearInterval(id))\n\t\tthis.rafs.get(contextId)?.forEach((id) => cancelAnimationFrame(id))\n\n\t\tthis.timeouts.delete(contextId)\n\t\tthis.intervals.delete(contextId)\n\t\tthis.rafs.delete(contextId)\n\t}\n\n\t/**\n\t * Disposes of all timers across all contexts.\n\t * Clears every timeout, interval, and animation frame managed by this instance.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('ui'), 1000)\n\t * timers.setTimeout('background', () => console.log('bg'), 2000)\n\t *\n\t * // Clear everything\n\t * timers.disposeAll()\n\t * ```\n\t * @public\n\t */\n\tdisposeAll() {\n\t\tfor (const contextId of this.timeouts.keys()) {\n\t\t\tthis.dispose(contextId)\n\t\t}\n\t}\n\n\t/**\n\t * Returns an object with timer methods bound to a specific context.\n\t * Convenient for getting context-specific timer functions without repeatedly passing the contextId.\n\t * @param contextId - The context identifier to bind the returned methods to.\n\t * @returns An object with setTimeout, setInterval, requestAnimationFrame, and dispose methods bound to the context.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const uiTimers = timers.forContext('ui')\n\t *\n\t * // These are equivalent to calling timers.setTimeout('ui', ...)\n\t * uiTimers.setTimeout(() => console.log('timeout'), 1000)\n\t * uiTimers.setInterval(() => console.log('interval'), 500)\n\t * uiTimers.requestAnimationFrame(() => console.log('frame'))\n\t *\n\t * // Dispose only this context\n\t * uiTimers.dispose()\n\t * ```\n\t * @public\n\t */\n\tforContext(contextId: string) {\n\t\treturn {\n\t\t\tsetTimeout: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setTimeout(contextId, handler, timeout, args),\n\t\t\tsetInterval: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setInterval(contextId, handler, timeout, args),\n\t\t\trequestAnimationFrame: (callback: FrameRequestCallback) =>\n\t\t\t\tthis.requestAnimationFrame(contextId, callback),\n\t\t\tdispose: () => this.dispose(contextId),\n\t\t}\n\t}\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/types.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Makes all properties in a type and all nested properties optional recursively.\n * This is useful for creating partial update objects where you only want to specify\n * some deeply nested properties while leaving others unchanged.\n *\n * @example\n * ```ts\n * interface User {\n * name: string\n * settings: {\n * theme: string\n * notifications: {\n * email: boolean\n * push: boolean\n * }\n * }\n * }\n *\n * type PartialUser = RecursivePartial<User>\n * // Result: {\n * // name?: string\n * // settings?: {\n * // theme?: string\n * // notifications?: {\n * // email?: boolean\n * // push?: boolean\n * // }\n * // }\n * // }\n *\n * const update: PartialUser = {\n * settings: {\n * notifications: {\n * email: false\n * }\n * }\n * }\n * ```\n *\n * @public\n */\nexport type RecursivePartial<T> = {\n\t[P in keyof T]?: RecursivePartial<T[P]>\n}\n\n/**\n * Expands a type definition to show its full structure in IDE tooltips and error messages.\n * This utility type forces TypeScript to resolve and display the complete type structure\n * instead of showing complex conditional types or intersections as-is.\n *\n * @example\n * ```ts\n * type User = { name: string }\n * type WithId = { id: string }\n * type UserWithId = User & WithId\n *\n * // Without Expand, IDE shows: User & WithId\n * // With Expand, IDE shows: { name: string; id: string }\n * type ExpandedUserWithId = Expand<UserWithId>\n *\n * // Useful for complex intersections\n * type ComplexType = Expand<BaseType & Mixin1 & Mixin2>\n * ```\n *\n * @public\n */\nexport type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never\n\n/**\n * Makes specified keys in a type required while keeping all other properties as-is.\n * This is useful when you need to ensure certain optional properties are provided\n * in specific contexts without affecting the entire type structure.\n *\n * @example\n * ```ts\n * interface Shape {\n * id: string\n * x?: number\n * y?: number\n * visible?: boolean\n * }\n *\n * // Make position properties required\n * type PositionedShape = Required<Shape, 'x' | 'y'>\n * // Result: {\n * // id: string\n * // x: number // now required\n * // y: number // now required\n * // visible?: boolean\n * // }\n *\n * const shape: PositionedShape = {\n * id: 'rect1',\n * x: 10, // must provide\n * y: 20, // must provide\n * // visible is still optional\n * }\n * ```\n *\n * @internal\n */\nexport type Required<T, K extends keyof T> = Expand<Omit<T, K> & { [P in K]-?: T[P] }>\n\n/**\n * Automatically makes properties optional if their type includes `undefined`.\n * This transforms properties like `prop: string | undefined` to `prop?: string | undefined`,\n * making the API more ergonomic by not requiring explicit undefined assignments.\n *\n * @example\n * ```ts\n * interface RawConfig {\n * name: string\n * theme: string | undefined\n * debug: boolean | undefined\n * version: number\n * }\n *\n * type Config = MakeUndefinedOptional<RawConfig>\n * // Result: {\n * // name: string\n * // theme?: string | undefined // now optional\n * // debug?: boolean | undefined // now optional\n * // version: number\n * // }\n *\n * const config: Config = {\n * name: 'MyApp',\n * version: 1\n * // theme and debug can be omitted instead of explicitly set to undefined\n * }\n * ```\n *\n * @public\n */\nexport type MakeUndefinedOptional<T extends object> = Expand<\n\t{\n\t\t[P in { [K in keyof T]: undefined extends T[K] ? never : K }[keyof T]]: T[P]\n\t} & {\n\t\t[P in { [K in keyof T]: undefined extends T[K] ? K : never }[keyof T]]?: T[P]\n\t}\n>\n"],
|
|
4
|
+
"sourcesContent": ["/**\n * Makes all properties in a type and all nested properties optional recursively.\n * This is useful for creating partial update objects where you only want to specify\n * some deeply nested properties while leaving others unchanged.\n *\n * @example\n * ```ts\n * interface User {\n * name: string\n * settings: {\n * theme: string\n * notifications: {\n * email: boolean\n * push: boolean\n * }\n * }\n * }\n *\n * type PartialUser = RecursivePartial<User>\n * // Result: {\n * // name?: string\n * // settings?: {\n * // theme?: string\n * // notifications?: {\n * // email?: boolean\n * // push?: boolean\n * // }\n * // }\n * // }\n *\n * const update: PartialUser = {\n * settings: {\n * notifications: {\n * email: false\n * }\n * }\n * }\n * ```\n *\n * @public\n */\nexport type RecursivePartial<T> = {\n\t[P in keyof T]?: RecursivePartial<T[P]>\n}\n\n/**\n * Expands a type definition to show its full structure in IDE tooltips and error messages.\n * This utility type forces TypeScript to resolve and display the complete type structure\n * instead of showing complex conditional types or intersections as-is.\n *\n * @example\n * ```ts\n * type User = { name: string }\n * type WithId = { id: string }\n * type UserWithId = User & WithId\n *\n * // Without Expand, IDE shows: User & WithId\n * // With Expand, IDE shows: { name: string; id: string }\n * type ExpandedUserWithId = Expand<UserWithId>\n *\n * // Useful for complex intersections\n * type ComplexType = Expand<BaseType & Mixin1 & Mixin2>\n * ```\n *\n * @public\n */\nexport type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never\n\n/**\n * A value that may be returned synchronously or as a `Promise` / `PromiseLike`.\n * Use with `await` or `Promise.resolve(...)` to normalize to a single `Promise`.\n *\n * @public\n */\nexport type Awaitable<T> = T | PromiseLike<T>\n\n/**\n * Makes specified keys in a type required while keeping all other properties as-is.\n * This is useful when you need to ensure certain optional properties are provided\n * in specific contexts without affecting the entire type structure.\n *\n * @example\n * ```ts\n * interface Shape {\n * id: string\n * x?: number\n * y?: number\n * visible?: boolean\n * }\n *\n * // Make position properties required\n * type PositionedShape = Required<Shape, 'x' | 'y'>\n * // Result: {\n * // id: string\n * // x: number // now required\n * // y: number // now required\n * // visible?: boolean\n * // }\n *\n * const shape: PositionedShape = {\n * id: 'rect1',\n * x: 10, // must provide\n * y: 20, // must provide\n * // visible is still optional\n * }\n * ```\n *\n * @internal\n */\nexport type Required<T, K extends keyof T> = Expand<Omit<T, K> & { [P in K]-?: T[P] }>\n\n/**\n * Automatically makes properties optional if their type includes `undefined`.\n * This transforms properties like `prop: string | undefined` to `prop?: string | undefined`,\n * making the API more ergonomic by not requiring explicit undefined assignments.\n *\n * @example\n * ```ts\n * interface RawConfig {\n * name: string\n * theme: string | undefined\n * debug: boolean | undefined\n * version: number\n * }\n *\n * type Config = MakeUndefinedOptional<RawConfig>\n * // Result: {\n * // name: string\n * // theme?: string | undefined // now optional\n * // debug?: boolean | undefined // now optional\n * // version: number\n * // }\n *\n * const config: Config = {\n * name: 'MyApp',\n * version: 1\n * // theme and debug can be omitted instead of explicitly set to undefined\n * }\n * ```\n *\n * @public\n */\nexport type MakeUndefinedOptional<T extends object> = Expand<\n\t{\n\t\t[P in { [K in keyof T]: undefined extends T[K] ? never : K }[keyof T]]: T[P]\n\t} & {\n\t\t[P in { [K in keyof T]: undefined extends T[K] ? K : never }[keyof T]]?: T[P]\n\t}\n>\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/version.ts"],
|
|
4
|
-
"sourcesContent": ["interface TldrawLibraryVersion {\n\tname: string\n\tversion: string\n\tmodules: string\n}\n\ninterface TldrawLibraryVersionInfo {\n\tversions: TldrawLibraryVersion[]\n\tdidWarn: boolean\n\tscheduledNotice: number | NodeJS.Timeout | null\n}\n\nconst TLDRAW_LIBRARY_VERSION_KEY = '__TLDRAW_LIBRARY_VERSIONS__' as const\n\n// eslint-disable-next-line @typescript-eslint/prefer-namespace-keyword, @typescript-eslint/no-namespace\ndeclare module globalThis {\n\texport const __TLDRAW_LIBRARY_VERSIONS__: TldrawLibraryVersionInfo\n}\n\nfunction getLibraryVersions(): TldrawLibraryVersionInfo {\n\tif (globalThis[TLDRAW_LIBRARY_VERSION_KEY]) {\n\t\treturn globalThis[TLDRAW_LIBRARY_VERSION_KEY]\n\t}\n\n\tconst info: TldrawLibraryVersionInfo = {\n\t\tversions: [],\n\t\tdidWarn: false,\n\t\tscheduledNotice: null,\n\t}\n\n\tObject.defineProperty(globalThis, TLDRAW_LIBRARY_VERSION_KEY, {\n\t\tvalue: info,\n\t\twritable: false,\n\t\tconfigurable: false,\n\t\tenumerable: false,\n\t})\n\n\treturn info\n}\n\n/**\n * Clears all registered library versions and resets warning state.\n * This function is intended for testing purposes only to reset the global version tracking state.\n * @returns void\n * @example\n * ```ts\n * // In a test setup\n * beforeEach(() => {\n * clearRegisteredVersionsForTests()\n * })\n *\n * // Now version tracking starts fresh for each test\n * registerTldrawLibraryVersion('@tldraw/editor', '2.0.0', 'esm')\n * ```\n * @internal\n */\nexport function clearRegisteredVersionsForTests() {\n\tconst info = getLibraryVersions()\n\tinfo.versions = []\n\tinfo.didWarn = false\n\tif (info.scheduledNotice) {\n\t\tclearTimeout(info.scheduledNotice)\n\t\tinfo.scheduledNotice = null\n\t}\n}\n\n/**\n * Registers a tldraw library version for conflict detection.\n * This function tracks different tldraw library versions to warn about potential conflicts\n * when multiple versions are loaded simultaneously.\n * @param name - The name of the tldraw library package (e.g., '\\@tldraw/editor').\n * @param version - The semantic version string (e.g., '2.0.0').\n * @param modules - The module system being used ('esm' or 'cjs').\n * @returns void\n * @example\n * ```ts\n * // Register a library version during package initialization\n * registerTldrawLibraryVersion('@tldraw/editor', '2.0.0', 'esm')\n * registerTldrawLibraryVersion('@tldraw/tldraw', '2.0.0', 'esm')\n *\n * // If conflicting versions are detected, warnings will be logged:\n * registerTldrawLibraryVersion('@tldraw/editor', '1.9.0', 'cjs')\n * // Console warning about version mismatch will appear\n * ```\n * @internal\n */\nexport function registerTldrawLibraryVersion(name?: string, version?: string, modules?: string) {\n\tif (!name || !version || !modules) {\n\t\tif ((globalThis as any).TLDRAW_LIBRARY_IS_BUILD) {\n\t\t\tthrow new Error('Missing name/version/module system in built version of tldraw library')\n\t\t}\n\t\treturn\n\t}\n\n\tconst info = getLibraryVersions()\n\n\t// In Next.js dev mode, Fast Refresh re-executes module-level code which causes\n\t// the same library to register multiple times, producing a false positive warning.\n\t// We skip exact duplicates only in Next.js dev to avoid hiding genuine issues.\n\tif (isNextjsDev()) {\n\t\tconst isDuplicate = info.versions.some(\n\t\t\t(v) => v.name === name && v.version === version && v.modules === modules\n\t\t)\n\t\tif (isDuplicate) return\n\t}\n\n\tinfo.versions.push({ name, version, modules })\n\n\tif (!info.scheduledNotice) {\n\t\ttry {\n\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\tinfo.scheduledNotice = setTimeout(() => {\n\t\t\t\tinfo.scheduledNotice = null\n\t\t\t\tcheckLibraryVersions(info)\n\t\t\t}, 100)\n\t\t} catch {\n\t\t\t// some environments (e.g. cloudflare workers) don't support setTimeout immediately, only in a handler.\n\t\t\t// in this case, we'll just check immediately.\n\t\t\tcheckLibraryVersions(info)\n\t\t}\n\t}\n}\n\nfunction checkLibraryVersions(info: TldrawLibraryVersionInfo) {\n\tif (!info.versions.length) return\n\tif (info.didWarn) return\n\n\tconst sorted = info.versions.sort((a, b) => compareVersions(a.version, b.version))\n\tconst latestVersion = sorted[sorted.length - 1].version\n\n\tconst matchingVersions = new Set<string>()\n\tconst nonMatchingVersions = new Map<string, Set<string>>()\n\tfor (const lib of sorted) {\n\t\tif (nonMatchingVersions.has(lib.name)) {\n\t\t\tmatchingVersions.delete(lib.name)\n\t\t\tentry(nonMatchingVersions, lib.name, new Set()).add(lib.version)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (lib.version === latestVersion) {\n\t\t\tmatchingVersions.add(lib.name)\n\t\t} else {\n\t\t\tmatchingVersions.delete(lib.name)\n\t\t\tentry(nonMatchingVersions, lib.name, new Set()).add(lib.version)\n\t\t}\n\t}\n\n\tif (nonMatchingVersions.size > 0) {\n\t\tconst message = [\n\t\t\t`${format('[tldraw]', ['bold', 'bgRed', 'textWhite'])} ${format('You have multiple versions of tldraw libraries installed. This can lead to bugs and unexpected behavior.', ['textRed', 'bold'])}`,\n\t\t\t'',\n\t\t\t`The latest version you have installed is ${format(`v${latestVersion}`, ['bold', 'textBlue'])}. The following libraries are on the latest version:`,\n\t\t\t...Array.from(matchingVersions, (name) => ` \u2022 \u2705 ${format(name, ['bold'])}`),\n\t\t\t'',\n\t\t\t`The following libraries are not on the latest version, or have multiple versions installed:`,\n\t\t\t...Array.from(nonMatchingVersions, ([name, versions]) => {\n\t\t\t\tconst sortedVersions = Array.from(versions)\n\t\t\t\t\t.sort(compareVersions)\n\t\t\t\t\t.map((v) => format(`v${v}`, v === latestVersion ? ['textGreen'] : ['textRed']))\n\t\t\t\treturn ` \u2022 \u274C ${format(name, ['bold'])} (${sortedVersions.join(', ')})`\n\t\t\t}),\n\t\t]\n\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(message.join('\\n'))\n\t\tinfo.didWarn = true\n\t\treturn\n\t}\n\n\t// at this point, we know that everything has the same version. there may still be duplicates though!\n\tconst potentialDuplicates = new Map<string, { version: string; modules: string[] }>()\n\tfor (const lib of sorted) {\n\t\tentry(potentialDuplicates, lib.name, { version: lib.version, modules: [] }).modules.push(\n\t\t\tlib.modules\n\t\t)\n\t}\n\n\tconst duplicates = new Map<string, { version: string; modules: string[] }>()\n\tfor (const [name, lib] of potentialDuplicates) {\n\t\tif (lib.modules.length > 1) duplicates.set(name, lib)\n\t}\n\n\tif (duplicates.size > 0) {\n\t\tconst message = [\n\t\t\t`${format('[tldraw]', ['bold', 'bgRed', 'textWhite'])} ${format('You have multiple instances of some tldraw libraries active. This can lead to bugs and unexpected behavior. ', ['textRed', 'bold'])}`,\n\t\t\t'',\n\t\t\t'This usually means that your bundler is misconfigured, and is importing the same library multiple times - usually once as an ES Module, and once as a CommonJS module.',\n\t\t\t'',\n\t\t\t'The following libraries have been imported multiple times:',\n\t\t\t...Array.from(duplicates, ([name, lib]) => {\n\t\t\t\tconst modules = lib.modules\n\t\t\t\t\t.map((m, i) => (m === 'esm' ? ` ${i + 1}. ES Modules` : ` ${i + 1}. CommonJS`))\n\t\t\t\t\t.join('\\n')\n\t\t\t\treturn ` \u2022 \u274C ${format(name, ['bold'])} v${lib.version}: \\n${modules}`\n\t\t\t}),\n\t\t\t'',\n\t\t\t'You should configure your bundler to only import one version of each library.',\n\t\t]\n\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(message.join('\\n'))\n\t\tinfo.didWarn = true\n\t\treturn\n\t}\n}\n\nfunction compareVersions(a: string, b: string) {\n\tconst aMatch = a.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(\\w+))?$/)\n\tconst bMatch = b.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(\\w+))?$/)\n\n\tif (!aMatch || !bMatch) return a.localeCompare(b)\n\tif (aMatch[1] !== bMatch[1]) return Number(aMatch[1]) - Number(bMatch[1])\n\tif (aMatch[2] !== bMatch[2]) return Number(aMatch[2]) - Number(bMatch[2])\n\tif (aMatch[3] !== bMatch[3]) return Number(aMatch[3]) - Number(bMatch[3])\n\tif (aMatch[4] && bMatch[4]) return aMatch[4].localeCompare(bMatch[4])\n\tif (aMatch[4]) return 1\n\tif (bMatch[4]) return -1\n\treturn 0\n}\n\nconst formats = {\n\tbold: '1',\n\ttextBlue: '94',\n\ttextRed: '31',\n\ttextGreen: '32',\n\tbgRed: '41',\n\ttextWhite: '97',\n} as const\nfunction format(value: string, formatters: (keyof typeof formats)[] = []) {\n\treturn `\\x1B[${formatters.map((f) => formats[f]).join(';')}m${value}\\x1B[m`\n}\n\nfunction isNextjsDev(): boolean {\n\ttry {\n\t\treturn process.env.NODE_ENV === 'development' && '__NEXT_DATA__' in globalThis\n\t} catch {\n\t\treturn false\n\t}\n}\n\nfunction entry<K, V>(map: Map<K, V>, key: K, defaultValue: V): V {\n\tif (map.has(key)) {\n\t\treturn map.get(key)!\n\t}\n\tmap.set(key, defaultValue)\n\treturn defaultValue\n}\n"],
|
|
4
|
+
"sourcesContent": ["interface TldrawLibraryVersion {\n\tname: string\n\tversion: string\n\tmodules: string\n}\n\ninterface TldrawLibraryVersionInfo {\n\tversions: TldrawLibraryVersion[]\n\tdidWarn: boolean\n\tscheduledNotice: number | NodeJS.Timeout | null\n}\n\nconst TLDRAW_LIBRARY_VERSION_KEY = '__TLDRAW_LIBRARY_VERSIONS__' as const\n\n// eslint-disable-next-line @typescript-eslint/prefer-namespace-keyword, @typescript-eslint/no-namespace, no-shadow-restricted-names\ndeclare module globalThis {\n\texport const __TLDRAW_LIBRARY_VERSIONS__: TldrawLibraryVersionInfo\n}\n\nfunction getLibraryVersions(): TldrawLibraryVersionInfo {\n\tif (globalThis[TLDRAW_LIBRARY_VERSION_KEY]) {\n\t\treturn globalThis[TLDRAW_LIBRARY_VERSION_KEY]\n\t}\n\n\tconst info: TldrawLibraryVersionInfo = {\n\t\tversions: [],\n\t\tdidWarn: false,\n\t\tscheduledNotice: null,\n\t}\n\n\tObject.defineProperty(globalThis, TLDRAW_LIBRARY_VERSION_KEY, {\n\t\tvalue: info,\n\t\twritable: false,\n\t\tconfigurable: false,\n\t\tenumerable: false,\n\t})\n\n\treturn info\n}\n\n/**\n * Clears all registered library versions and resets warning state.\n * This function is intended for testing purposes only to reset the global version tracking state.\n * @returns void\n * @example\n * ```ts\n * // In a test setup\n * beforeEach(() => {\n * clearRegisteredVersionsForTests()\n * })\n *\n * // Now version tracking starts fresh for each test\n * registerTldrawLibraryVersion('@tldraw/editor', '2.0.0', 'esm')\n * ```\n * @internal\n */\nexport function clearRegisteredVersionsForTests() {\n\tconst info = getLibraryVersions()\n\tinfo.versions = []\n\tinfo.didWarn = false\n\tif (info.scheduledNotice) {\n\t\tclearTimeout(info.scheduledNotice)\n\t\tinfo.scheduledNotice = null\n\t}\n}\n\n/**\n * Registers a tldraw library version for conflict detection.\n * This function tracks different tldraw library versions to warn about potential conflicts\n * when multiple versions are loaded simultaneously.\n * @param name - The name of the tldraw library package (e.g., '\\@tldraw/editor').\n * @param version - The semantic version string (e.g., '2.0.0').\n * @param modules - The module system being used ('esm' or 'cjs').\n * @returns void\n * @example\n * ```ts\n * // Register a library version during package initialization\n * registerTldrawLibraryVersion('@tldraw/editor', '2.0.0', 'esm')\n * registerTldrawLibraryVersion('@tldraw/tldraw', '2.0.0', 'esm')\n *\n * // If conflicting versions are detected, warnings will be logged:\n * registerTldrawLibraryVersion('@tldraw/editor', '1.9.0', 'cjs')\n * // Console warning about version mismatch will appear\n * ```\n * @internal\n */\nexport function registerTldrawLibraryVersion(name?: string, version?: string, modules?: string) {\n\tif (!name || !version || !modules) {\n\t\tif ((globalThis as any).TLDRAW_LIBRARY_IS_BUILD) {\n\t\t\tthrow new Error('Missing name/version/module system in built version of tldraw library')\n\t\t}\n\t\treturn\n\t}\n\n\tconst info = getLibraryVersions()\n\n\t// In Next.js dev mode, Fast Refresh re-executes module-level code which causes\n\t// the same library to register multiple times, producing a false positive warning.\n\t// We skip exact duplicates only in Next.js dev to avoid hiding genuine issues.\n\tif (isNextjsDev()) {\n\t\tconst isDuplicate = info.versions.some(\n\t\t\t(v) => v.name === name && v.version === version && v.modules === modules\n\t\t)\n\t\tif (isDuplicate) return\n\t}\n\n\tinfo.versions.push({ name, version, modules })\n\n\tif (!info.scheduledNotice) {\n\t\ttry {\n\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\tinfo.scheduledNotice = setTimeout(() => {\n\t\t\t\tinfo.scheduledNotice = null\n\t\t\t\tcheckLibraryVersions(info)\n\t\t\t}, 100)\n\t\t} catch {\n\t\t\t// some environments (e.g. cloudflare workers) don't support setTimeout immediately, only in a handler.\n\t\t\t// in this case, we'll just check immediately.\n\t\t\tcheckLibraryVersions(info)\n\t\t}\n\t}\n}\n\nfunction checkLibraryVersions(info: TldrawLibraryVersionInfo) {\n\tif (!info.versions.length) return\n\tif (info.didWarn) return\n\n\tconst sorted = info.versions.sort((a, b) => compareVersions(a.version, b.version))\n\tconst latestVersion = sorted[sorted.length - 1].version\n\n\tconst matchingVersions = new Set<string>()\n\tconst nonMatchingVersions = new Map<string, Set<string>>()\n\tfor (const lib of sorted) {\n\t\tif (nonMatchingVersions.has(lib.name)) {\n\t\t\tmatchingVersions.delete(lib.name)\n\t\t\tentry(nonMatchingVersions, lib.name, new Set()).add(lib.version)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (lib.version === latestVersion) {\n\t\t\tmatchingVersions.add(lib.name)\n\t\t} else {\n\t\t\tmatchingVersions.delete(lib.name)\n\t\t\tentry(nonMatchingVersions, lib.name, new Set()).add(lib.version)\n\t\t}\n\t}\n\n\tif (nonMatchingVersions.size > 0) {\n\t\tconst message = [\n\t\t\t`${format('[tldraw]', ['bold', 'bgRed', 'textWhite'])} ${format('You have multiple versions of tldraw libraries installed. This can lead to bugs and unexpected behavior.', ['textRed', 'bold'])}`,\n\t\t\t'',\n\t\t\t`The latest version you have installed is ${format(`v${latestVersion}`, ['bold', 'textBlue'])}. The following libraries are on the latest version:`,\n\t\t\t...Array.from(matchingVersions, (name) => ` \u2022 \u2705 ${format(name, ['bold'])}`),\n\t\t\t'',\n\t\t\t`The following libraries are not on the latest version, or have multiple versions installed:`,\n\t\t\t...Array.from(nonMatchingVersions, ([name, versions]) => {\n\t\t\t\tconst sortedVersions = Array.from(versions)\n\t\t\t\t\t.sort(compareVersions)\n\t\t\t\t\t.map((v) => format(`v${v}`, v === latestVersion ? ['textGreen'] : ['textRed']))\n\t\t\t\treturn ` \u2022 \u274C ${format(name, ['bold'])} (${sortedVersions.join(', ')})`\n\t\t\t}),\n\t\t]\n\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(message.join('\\n'))\n\t\tinfo.didWarn = true\n\t\treturn\n\t}\n\n\t// at this point, we know that everything has the same version. there may still be duplicates though!\n\tconst potentialDuplicates = new Map<string, { version: string; modules: string[] }>()\n\tfor (const lib of sorted) {\n\t\tentry(potentialDuplicates, lib.name, { version: lib.version, modules: [] }).modules.push(\n\t\t\tlib.modules\n\t\t)\n\t}\n\n\tconst duplicates = new Map<string, { version: string; modules: string[] }>()\n\tfor (const [name, lib] of potentialDuplicates) {\n\t\tif (lib.modules.length > 1) duplicates.set(name, lib)\n\t}\n\n\tif (duplicates.size > 0) {\n\t\tconst message = [\n\t\t\t`${format('[tldraw]', ['bold', 'bgRed', 'textWhite'])} ${format('You have multiple instances of some tldraw libraries active. This can lead to bugs and unexpected behavior. ', ['textRed', 'bold'])}`,\n\t\t\t'',\n\t\t\t'This usually means that your bundler is misconfigured, and is importing the same library multiple times - usually once as an ES Module, and once as a CommonJS module.',\n\t\t\t'',\n\t\t\t'The following libraries have been imported multiple times:',\n\t\t\t...Array.from(duplicates, ([name, lib]) => {\n\t\t\t\tconst modules = lib.modules\n\t\t\t\t\t.map((m, i) => (m === 'esm' ? ` ${i + 1}. ES Modules` : ` ${i + 1}. CommonJS`))\n\t\t\t\t\t.join('\\n')\n\t\t\t\treturn ` \u2022 \u274C ${format(name, ['bold'])} v${lib.version}: \\n${modules}`\n\t\t\t}),\n\t\t\t'',\n\t\t\t'You should configure your bundler to only import one version of each library.',\n\t\t]\n\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(message.join('\\n'))\n\t\tinfo.didWarn = true\n\t\treturn\n\t}\n}\n\nfunction compareVersions(a: string, b: string) {\n\tconst aMatch = a.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(\\w+))?$/)\n\tconst bMatch = b.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(\\w+))?$/)\n\n\tif (!aMatch || !bMatch) return a.localeCompare(b)\n\tif (aMatch[1] !== bMatch[1]) return Number(aMatch[1]) - Number(bMatch[1])\n\tif (aMatch[2] !== bMatch[2]) return Number(aMatch[2]) - Number(bMatch[2])\n\tif (aMatch[3] !== bMatch[3]) return Number(aMatch[3]) - Number(bMatch[3])\n\tif (aMatch[4] && bMatch[4]) return aMatch[4].localeCompare(bMatch[4])\n\tif (aMatch[4]) return 1\n\tif (bMatch[4]) return -1\n\treturn 0\n}\n\nconst formats = {\n\tbold: '1',\n\ttextBlue: '94',\n\ttextRed: '31',\n\ttextGreen: '32',\n\tbgRed: '41',\n\ttextWhite: '97',\n} as const\nfunction format(value: string, formatters: (keyof typeof formats)[] = []) {\n\treturn `\\x1B[${formatters.map((f) => formats[f]).join(';')}m${value}\\x1B[m`\n}\n\nfunction isNextjsDev(): boolean {\n\ttry {\n\t\treturn process.env.NODE_ENV === 'development' && '__NEXT_DATA__' in globalThis\n\t} catch {\n\t\treturn false\n\t}\n}\n\nfunction entry<K, V>(map: Map<K, V>, key: K, defaultValue: V): V {\n\tif (map.has(key)) {\n\t\treturn map.get(key)!\n\t}\n\tmap.set(key, defaultValue)\n\treturn defaultValue\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-esm/index.d.mts
CHANGED
|
@@ -13,6 +13,14 @@ import { default as uniq } from 'lodash.uniq';
|
|
|
13
13
|
|
|
14
14
|
/* Excluded from this release type: assertExists */
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* A value that may be returned synchronously or as a `Promise` / `PromiseLike`.
|
|
18
|
+
* Use with `await` or `Promise.resolve(...)` to normalize to a single `Promise`.
|
|
19
|
+
*
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export declare type Awaitable<T> = PromiseLike<T> | T;
|
|
23
|
+
|
|
16
24
|
/**
|
|
17
25
|
* Decorator that binds a method to its class instance (legacy stage-2 TypeScript decorators).
|
|
18
26
|
* When applied to a class method, ensures `this` always refers to the class instance,
|
|
@@ -109,7 +117,7 @@ export declare function bind<This extends object, T extends (...args: any[]) =>
|
|
|
109
117
|
* @public
|
|
110
118
|
* @see source - https://gist.github.com/ca0v/73a31f57b397606c9813472f7493a940
|
|
111
119
|
*/
|
|
112
|
-
export declare function debounce<T extends unknown[], U>(callback: (...args: T) =>
|
|
120
|
+
export declare function debounce<T extends unknown[], U>(callback: (...args: T) => Awaitable<U>, wait: number): {
|
|
113
121
|
(...args: T): Promise<U>;
|
|
114
122
|
cancel: () => void;
|
|
115
123
|
};
|
package/dist-esm/index.mjs
CHANGED
|
@@ -101,7 +101,7 @@ import { registerTldrawLibraryVersion as registerTldrawLibraryVersion2 } from ".
|
|
|
101
101
|
import { warnDeprecatedGetter, warnOnce } from "./lib/warn.mjs";
|
|
102
102
|
registerTldrawLibraryVersion(
|
|
103
103
|
"@tldraw/utils",
|
|
104
|
-
"4.6.0-next.
|
|
104
|
+
"4.6.0-next.d15997ff5a4b",
|
|
105
105
|
"esm"
|
|
106
106
|
);
|
|
107
107
|
export {
|
package/dist-esm/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { registerTldrawLibraryVersion } from './lib/version'\n\nexport { default as isEqual } from 'lodash.isequal'\nexport { default as isEqualWith } from 'lodash.isequalwith'\nexport { default as throttle } from 'lodash.throttle'\nexport { default as uniq } from 'lodash.uniq'\nexport {\n\tareArraysShallowEqual,\n\tcompact,\n\tdedupe,\n\tlast,\n\tmaxBy,\n\tmergeArraysAndReplaceDefaults,\n\tminBy,\n\tpartition,\n\trotateArray,\n} from './lib/array'\nexport { bind } from './lib/bind'\nexport { WeakCache } from './lib/cache'\nexport {\n\tassert,\n\tassertExists,\n\texhaustiveSwitchError,\n\tpromiseWithResolve,\n\tResult,\n\tsleep,\n\ttype ErrorResult,\n\ttype OkResult,\n} from './lib/control'\nexport { debounce } from './lib/debounce'\nexport { annotateError, getErrorAnnotations, type ErrorAnnotations } from './lib/error'\nexport { ExecutionQueue } from './lib/ExecutionQueue'\nexport { FileHelpers } from './lib/file'\nexport { noop, omitFromStackTrace } from './lib/function'\nexport { getHashForBuffer, getHashForObject, getHashForString, lns } from './lib/hash'\nexport { mockUniqueId, restoreUniqueId, uniqueId } from './lib/id'\nexport { getFirstFromIterable } from './lib/iterable'\nexport type { JsonArray, JsonObject, JsonPrimitive, JsonValue } from './lib/json-value'\nexport {\n\tDEFAULT_SUPPORT_VIDEO_TYPES,\n\tDEFAULT_SUPPORTED_IMAGE_TYPES,\n\tDEFAULT_SUPPORTED_MEDIA_TYPE_LIST,\n\tDEFAULT_SUPPORTED_MEDIA_TYPES,\n\tMediaHelpers,\n} from './lib/media/media'\nexport { PngHelpers } from './lib/media/png'\nexport { fetch, Image } from './lib/network'\nexport { invLerp, lerp, modulate, rng } from './lib/number'\nexport {\n\tareObjectsShallowEqual,\n\tfilterEntries,\n\tgetChangedKeys,\n\tgetOwnProperty,\n\tgroupBy,\n\thasOwnProperty,\n\tisEqualAllowingForFloatingPointErrors,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n\tobjectMapEntriesIterable,\n\tobjectMapFromEntries,\n\tobjectMapKeys,\n\tobjectMapValues,\n\tomit,\n} from './lib/object'\nexport { measureAverageDuration, measureCbDuration, measureDuration } from './lib/perf'\nexport { PerformanceTracker } from './lib/PerformanceTracker'\nexport {\n\tgetIndexAbove,\n\tgetIndexBelow,\n\tgetIndexBetween,\n\tgetIndices,\n\tgetIndicesAbove,\n\tgetIndicesBelow,\n\tgetIndicesBetween,\n\tsortByIndex,\n\tsortByMaybeIndex,\n\tvalidateIndexKey,\n\tZERO_INDEX_KEY,\n\ttype IndexKey,\n} from './lib/reordering'\nexport { retry } from './lib/retry'\nexport { sortById } from './lib/sort'\nexport {\n\tclearLocalStorage,\n\tclearSessionStorage,\n\tdeleteFromLocalStorage,\n\tdeleteFromSessionStorage,\n\tgetFromLocalStorage,\n\tgetFromSessionStorage,\n\tsetInLocalStorage,\n\tsetInSessionStorage,\n} from './lib/storage'\nexport { stringEnum } from './lib/stringEnum'\nexport { FpsScheduler, fpsThrottle, throttleToNextFrame } from './lib/throttle'\nexport { Timers } from './lib/timers'\nexport {\n\ttype Expand,\n\ttype MakeUndefinedOptional,\n\ttype RecursivePartial,\n\ttype Required,\n} from './lib/types'\nexport { safeParseUrl } from './lib/url'\nexport {\n\tisDefined,\n\tisNativeStructuredClone,\n\tisNonNull,\n\tisNonNullish,\n\tSTRUCTURED_CLONE_OBJECT_PROTOTYPE,\n\tstructuredClone,\n} from './lib/value'\nexport { registerTldrawLibraryVersion } from './lib/version'\nexport { warnDeprecatedGetter, warnOnce } from './lib/warn'\n\nregisterTldrawLibraryVersion(\n\t(globalThis as any).TLDRAW_LIBRARY_NAME,\n\t(globalThis as any).TLDRAW_LIBRARY_VERSION,\n\t(globalThis as any).TLDRAW_LIBRARY_MODULES\n)\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,oCAAoC;AAE7C,SAAoB,WAAXA,gBAA0B;AACnC,SAAoB,WAAXA,gBAA8B;AACvC,SAAoB,WAAXA,gBAA2B;AACpC,SAAoB,WAAXA,gBAAuB;AAChC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAC1B;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGM;AACP,SAAS,gBAAgB;AACzB,SAAS,eAAe,2BAAkD;AAC1E,SAAS,sBAAsB;AAC/B,SAAS,mBAAmB;AAC5B,SAAS,MAAM,0BAA0B;AACzC,SAAS,kBAAkB,kBAAkB,kBAAkB,WAAW;AAC1E,SAAS,cAAc,iBAAiB,gBAAgB;AACxD,SAAS,4BAA4B;AAErC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,kBAAkB;AAC3B,SAAS,OAAO,aAAa;AAC7B,SAAS,SAAS,MAAM,UAAU,WAAW;AAC7C;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,wBAAwB,mBAAmB,uBAAuB;AAC3E,SAAS,0BAA0B;AACnC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEM;AACP,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,kBAAkB;AAC3B,SAAS,cAAc,aAAa,2BAA2B;AAC/D,SAAS,cAAc;
|
|
4
|
+
"sourcesContent": ["import { registerTldrawLibraryVersion } from './lib/version'\n\nexport { default as isEqual } from 'lodash.isequal'\nexport { default as isEqualWith } from 'lodash.isequalwith'\nexport { default as throttle } from 'lodash.throttle'\nexport { default as uniq } from 'lodash.uniq'\nexport {\n\tareArraysShallowEqual,\n\tcompact,\n\tdedupe,\n\tlast,\n\tmaxBy,\n\tmergeArraysAndReplaceDefaults,\n\tminBy,\n\tpartition,\n\trotateArray,\n} from './lib/array'\nexport { bind } from './lib/bind'\nexport { WeakCache } from './lib/cache'\nexport {\n\tassert,\n\tassertExists,\n\texhaustiveSwitchError,\n\tpromiseWithResolve,\n\tResult,\n\tsleep,\n\ttype ErrorResult,\n\ttype OkResult,\n} from './lib/control'\nexport { debounce } from './lib/debounce'\nexport { annotateError, getErrorAnnotations, type ErrorAnnotations } from './lib/error'\nexport { ExecutionQueue } from './lib/ExecutionQueue'\nexport { FileHelpers } from './lib/file'\nexport { noop, omitFromStackTrace } from './lib/function'\nexport { getHashForBuffer, getHashForObject, getHashForString, lns } from './lib/hash'\nexport { mockUniqueId, restoreUniqueId, uniqueId } from './lib/id'\nexport { getFirstFromIterable } from './lib/iterable'\nexport type { JsonArray, JsonObject, JsonPrimitive, JsonValue } from './lib/json-value'\nexport {\n\tDEFAULT_SUPPORT_VIDEO_TYPES,\n\tDEFAULT_SUPPORTED_IMAGE_TYPES,\n\tDEFAULT_SUPPORTED_MEDIA_TYPE_LIST,\n\tDEFAULT_SUPPORTED_MEDIA_TYPES,\n\tMediaHelpers,\n} from './lib/media/media'\nexport { PngHelpers } from './lib/media/png'\nexport { fetch, Image } from './lib/network'\nexport { invLerp, lerp, modulate, rng } from './lib/number'\nexport {\n\tareObjectsShallowEqual,\n\tfilterEntries,\n\tgetChangedKeys,\n\tgetOwnProperty,\n\tgroupBy,\n\thasOwnProperty,\n\tisEqualAllowingForFloatingPointErrors,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n\tobjectMapEntriesIterable,\n\tobjectMapFromEntries,\n\tobjectMapKeys,\n\tobjectMapValues,\n\tomit,\n} from './lib/object'\nexport { measureAverageDuration, measureCbDuration, measureDuration } from './lib/perf'\nexport { PerformanceTracker } from './lib/PerformanceTracker'\nexport {\n\tgetIndexAbove,\n\tgetIndexBelow,\n\tgetIndexBetween,\n\tgetIndices,\n\tgetIndicesAbove,\n\tgetIndicesBelow,\n\tgetIndicesBetween,\n\tsortByIndex,\n\tsortByMaybeIndex,\n\tvalidateIndexKey,\n\tZERO_INDEX_KEY,\n\ttype IndexKey,\n} from './lib/reordering'\nexport { retry } from './lib/retry'\nexport { sortById } from './lib/sort'\nexport {\n\tclearLocalStorage,\n\tclearSessionStorage,\n\tdeleteFromLocalStorage,\n\tdeleteFromSessionStorage,\n\tgetFromLocalStorage,\n\tgetFromSessionStorage,\n\tsetInLocalStorage,\n\tsetInSessionStorage,\n} from './lib/storage'\nexport { stringEnum } from './lib/stringEnum'\nexport { FpsScheduler, fpsThrottle, throttleToNextFrame } from './lib/throttle'\nexport { Timers } from './lib/timers'\nexport {\n\ttype Awaitable,\n\ttype Expand,\n\ttype MakeUndefinedOptional,\n\ttype RecursivePartial,\n\ttype Required,\n} from './lib/types'\nexport { safeParseUrl } from './lib/url'\nexport {\n\tisDefined,\n\tisNativeStructuredClone,\n\tisNonNull,\n\tisNonNullish,\n\tSTRUCTURED_CLONE_OBJECT_PROTOTYPE,\n\tstructuredClone,\n} from './lib/value'\nexport { registerTldrawLibraryVersion } from './lib/version'\nexport { warnDeprecatedGetter, warnOnce } from './lib/warn'\n\nregisterTldrawLibraryVersion(\n\t(globalThis as any).TLDRAW_LIBRARY_NAME,\n\t(globalThis as any).TLDRAW_LIBRARY_VERSION,\n\t(globalThis as any).TLDRAW_LIBRARY_MODULES\n)\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oCAAoC;AAE7C,SAAoB,WAAXA,gBAA0B;AACnC,SAAoB,WAAXA,gBAA8B;AACvC,SAAoB,WAAXA,gBAA2B;AACpC,SAAoB,WAAXA,gBAAuB;AAChC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAC1B;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGM;AACP,SAAS,gBAAgB;AACzB,SAAS,eAAe,2BAAkD;AAC1E,SAAS,sBAAsB;AAC/B,SAAS,mBAAmB;AAC5B,SAAS,MAAM,0BAA0B;AACzC,SAAS,kBAAkB,kBAAkB,kBAAkB,WAAW;AAC1E,SAAS,cAAc,iBAAiB,gBAAgB;AACxD,SAAS,4BAA4B;AAErC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,kBAAkB;AAC3B,SAAS,OAAO,aAAa;AAC7B,SAAS,SAAS,MAAM,UAAU,WAAW;AAC7C;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,wBAAwB,mBAAmB,uBAAuB;AAC3E,SAAS,0BAA0B;AACnC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEM;AACP,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,kBAAkB;AAC3B,SAAS,cAAc,aAAa,2BAA2B;AAC/D,SAAS,cAAc;AAQvB,SAAS,oBAAoB;AAC7B;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,gCAAAC,qCAAoC;AAC7C,SAAS,sBAAsB,gBAAgB;AAE/C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;",
|
|
6
6
|
"names": ["default", "registerTldrawLibraryVersion"]
|
|
7
7
|
}
|
|
@@ -9,7 +9,7 @@ class PerformanceTracker {
|
|
|
9
9
|
* Records animation frames to calculate frame rate.
|
|
10
10
|
* Called automatically during performance tracking.
|
|
11
11
|
*/
|
|
12
|
-
// eslint-disable-next-line
|
|
12
|
+
// eslint-disable-next-line tldraw/prefer-class-methods
|
|
13
13
|
recordFrame = () => {
|
|
14
14
|
this.frames++;
|
|
15
15
|
if (!this.started) return;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/PerformanceTracker.ts"],
|
|
4
|
-
"sourcesContent": ["import { PERFORMANCE_COLORS, PERFORMANCE_PREFIX_COLOR } from './perf'\n\n/**\n * A utility class for measuring and tracking frame rate performance during operations.\n * Provides visual feedback in the browser console with color-coded FPS indicators.\n *\n * @example\n * ```ts\n * const tracker = new PerformanceTracker()\n *\n * tracker.start('render')\n * renderShapes()\n * tracker.stop() // Logs performance info to console\n *\n * // Check if tracking is active\n * if (tracker.isStarted()) {\n * console.log('Still tracking performance')\n * }\n * ```\n *\n * @public\n */\nexport class PerformanceTracker {\n\tprivate startTime = 0\n\tprivate name = ''\n\tprivate frames = 0\n\tprivate started = false\n\tprivate frame: number | null = null\n\n\t/**\n\t * Records animation frames to calculate frame rate.\n\t * Called automatically during performance tracking.\n\t */\n\t// eslint-disable-next-line
|
|
4
|
+
"sourcesContent": ["import { PERFORMANCE_COLORS, PERFORMANCE_PREFIX_COLOR } from './perf'\n\n/**\n * A utility class for measuring and tracking frame rate performance during operations.\n * Provides visual feedback in the browser console with color-coded FPS indicators.\n *\n * @example\n * ```ts\n * const tracker = new PerformanceTracker()\n *\n * tracker.start('render')\n * renderShapes()\n * tracker.stop() // Logs performance info to console\n *\n * // Check if tracking is active\n * if (tracker.isStarted()) {\n * console.log('Still tracking performance')\n * }\n * ```\n *\n * @public\n */\nexport class PerformanceTracker {\n\tprivate startTime = 0\n\tprivate name = ''\n\tprivate frames = 0\n\tprivate started = false\n\tprivate frame: number | null = null\n\n\t/**\n\t * Records animation frames to calculate frame rate.\n\t * Called automatically during performance tracking.\n\t */\n\t// eslint-disable-next-line tldraw/prefer-class-methods\n\trecordFrame = () => {\n\t\tthis.frames++\n\t\tif (!this.started) return\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.frame = requestAnimationFrame(this.recordFrame)\n\t}\n\n\t/**\n\t * Starts performance tracking for a named operation.\n\t *\n\t * @param name - A descriptive name for the operation being tracked\n\t *\n\t * @example\n\t * ```ts\n\t * tracker.start('canvas-render')\n\t * // ... perform rendering operations\n\t * tracker.stop()\n\t * ```\n\t */\n\tstart(name: string) {\n\t\tthis.name = name\n\t\tthis.frames = 0\n\t\tthis.started = true\n\t\tif (this.frame !== null) cancelAnimationFrame(this.frame)\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tthis.frame = requestAnimationFrame(this.recordFrame)\n\t\tthis.startTime = performance.now()\n\t}\n\n\t/**\n\t * Stops performance tracking and logs results to the console.\n\t *\n\t * Displays the operation name, frame rate, and uses color coding:\n\t * - Green background: \\> 55 FPS (good performance)\n\t * - Yellow background: 30-55 FPS (moderate performance)\n\t * - Red background: \\< 30 FPS (poor performance)\n\t *\n\t * @example\n\t * ```ts\n\t * tracker.start('interaction')\n\t * handleUserInteraction()\n\t * tracker.stop() // Logs: \"Perf Interaction 60 fps\"\n\t * ```\n\t */\n\tstop() {\n\t\tthis.started = false\n\t\tif (this.frame !== null) cancelAnimationFrame(this.frame)\n\t\tconst duration = (performance.now() - this.startTime) / 1000\n\t\tconst fps = duration === 0 ? 0 : Math.floor(this.frames / duration)\n\t\tconst background =\n\t\t\tfps > 55\n\t\t\t\t? PERFORMANCE_COLORS.Good\n\t\t\t\t: fps > 30\n\t\t\t\t\t? PERFORMANCE_COLORS.Mid\n\t\t\t\t\t: PERFORMANCE_COLORS.Poor\n\t\tconst color = background === PERFORMANCE_COLORS.Mid ? 'black' : 'white'\n\t\tconst capitalized = this.name[0].toUpperCase() + this.name.slice(1)\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.debug(\n\t\t\t`%cPerf%c ${capitalized} %c${fps}%c fps`,\n\t\t\t`color: white; background: ${PERFORMANCE_PREFIX_COLOR};padding: 2px;border-radius: 3px;`,\n\t\t\t'font-weight: normal',\n\t\t\t`font-weight: bold; padding: 2px; background: ${background};color: ${color};`,\n\t\t\t'font-weight: normal'\n\t\t)\n\t}\n\n\t/**\n\t * Checks whether performance tracking is currently active.\n\t *\n\t * @returns True if tracking is in progress, false otherwise\n\t *\n\t * @example\n\t * ```ts\n\t * if (!tracker.isStarted()) {\n\t * tracker.start('new-operation')\n\t * }\n\t * ```\n\t */\n\tisStarted() {\n\t\treturn this.started\n\t}\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,oBAAoB,gCAAgC;AAsBtD,MAAM,mBAAmB;AAAA,EACvB,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO/B,cAAc,MAAM;AACnB,SAAK;AACL,QAAI,CAAC,KAAK,QAAS;AAEnB,SAAK,QAAQ,sBAAsB,KAAK,WAAW;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,MAAc;AACnB,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,UAAU;AACf,QAAI,KAAK,UAAU,KAAM,sBAAqB,KAAK,KAAK;AAExD,SAAK,QAAQ,sBAAsB,KAAK,WAAW;AACnD,SAAK,YAAY,YAAY,IAAI;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,OAAO;AACN,SAAK,UAAU;AACf,QAAI,KAAK,UAAU,KAAM,sBAAqB,KAAK,KAAK;AACxD,UAAM,YAAY,YAAY,IAAI,IAAI,KAAK,aAAa;AACxD,UAAM,MAAM,aAAa,IAAI,IAAI,KAAK,MAAM,KAAK,SAAS,QAAQ;AAClE,UAAM,aACL,MAAM,KACH,mBAAmB,OACnB,MAAM,KACL,mBAAmB,MACnB,mBAAmB;AACxB,UAAM,QAAQ,eAAe,mBAAmB,MAAM,UAAU;AAChE,UAAM,cAAc,KAAK,KAAK,CAAC,EAAE,YAAY,IAAI,KAAK,KAAK,MAAM,CAAC;AAElE,YAAQ;AAAA,MACP,YAAY,WAAW,MAAM,GAAG;AAAA,MAChC,6BAA6B,wBAAwB;AAAA,MACrD;AAAA,MACA,gDAAgD,UAAU,WAAW,KAAK;AAAA,MAC1E;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,YAAY;AACX,WAAO,KAAK;AAAA,EACb;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/bind.ts"],
|
|
4
|
-
"sourcesContent": ["/*!\n * MIT License: https://github.com/NoHomey/bind-decorator/blob/master/License\n * Copyright (c) 2016 Ivo Stratev\n */\n\nimport { assert } from './control'\n\n/**\n * Decorator that binds a method to its class instance (legacy stage-2 TypeScript decorators).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param target - The prototype of the class being decorated\n * @param propertyKey - The name of the method being decorated\n * @param descriptor - The property descriptor for the method being decorated\n * @returns The modified property descriptor with bound method access\n * @example\n * ```typescript\n * class MyClass {\n * name = 'example';\n *\n * @bind\n * getName() {\n * return this.name;\n * }\n * }\n *\n * const instance = new MyClass();\n * const callback = instance.getName;\n * console.log(callback()); // 'example' (this is properly bound)\n * ```\n * @public\n */\nexport function bind<T extends (...args: any[]) => any>(\n\ttarget: object,\n\tpropertyKey: string,\n\tdescriptor: TypedPropertyDescriptor<T>\n): TypedPropertyDescriptor<T>\n\n/**\n * Decorator that binds a method to its class instance (TC39 decorators standard).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param originalMethod - The original method being decorated\n * @param context - The decorator context containing metadata about the method\n * @example\n * ```typescript\n * class EventHandler {\n * message = 'Hello World';\n *\n * @bind\n * handleClick() {\n * console.log(this.message);\n * }\n * }\n *\n * const handler = new EventHandler();\n * document.addEventListener('click', handler.handleClick); // 'this' is properly bound\n * ```\n * @public\n */\nexport function bind<This extends object, T extends (...args: any[]) => any>(\n\toriginalMethod: T,\n\tcontext: ClassMethodDecoratorContext<This, T>\n): void\n\n/**\n * Universal decorator implementation that handles both legacy stage-2 and TC39 decorator formats.\n * Automatically detects the decorator format based on the number of arguments and binds the\n * decorated method to the class instance, preventing common `this` context issues.\n *\n * @param args - Either legacy decorator arguments (target, propertyKey, descriptor) or TC39 decorator arguments (originalMethod, context)\n * @returns Property descriptor for legacy decorators, or void for TC39 decorators\n * @example\n * ```typescript\n * // Works with both decorator formats\n * class Calculator {\n * multiplier = 2;\n *\n * @bind\n * multiply(value: number) {\n * return value * this.multiplier;\n * }\n * }\n *\n * const calc = new Calculator();\n * const multiplyFn = calc.multiply;\n * console.log(multiplyFn(5)); // 10 (this.multiplier is accessible)\n *\n * // Useful for event handlers and callbacks\n * setTimeout(calc.multiply, 100, 3); // 6\n * ```\n * @public\n */\nexport function bind(\n\t...args: // legacy stage-2 typescript decorators\n\t| [_target: object, propertyKey: string, descriptor: PropertyDescriptor]\n\t\t// TC39 decorators\n\t\t| [originalMethod: (...args: any[]) => any, context: ClassMemberDecoratorContext]\n): PropertyDescriptor | void {\n\tif (args.length === 2) {\n\t\tconst [originalMethod, context] = args\n\t\tcontext.addInitializer(function initializeMethod(this: any) {\n\t\t\tassert(Reflect.isExtensible(this), 'Cannot bind to a non-extensible class.')\n\t\t\tconst value = originalMethod.bind(this)\n\t\t\tconst ok = Reflect.defineProperty(this, context.name, {\n\t\t\t\tvalue,\n\t\t\t\twritable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t})\n\t\t\tassert(ok, 'Cannot bind a non-configurable class method.')\n\t\t})\n\t} else {\n\t\tconst [_target, propertyKey, descriptor] = args\n\t\tif (!descriptor || typeof descriptor.value !== 'function') {\n\t\t\tthrow new TypeError(\n\t\t\t\t`Only methods can be decorated with @bind. <${propertyKey}> is not a method!`\n\t\t\t)\n\t\t}\n\n\t\treturn {\n\t\t\tconfigurable: true,\n\t\t\tget(this: any): any {\n\t\t\t\tconst bound = descriptor.value!.bind(this)\n\t\t\t\t// Credits to https://github.com/andreypopp/autobind-decorator for memoizing the result of bind against a symbol on the instance.\n\t\t\t\tObject.defineProperty(this, propertyKey, {\n\t\t\t\t\tvalue: bound,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t})\n\t\t\t\treturn bound\n\t\t\t},\n\t\t}\n\t}\n}\n"],
|
|
4
|
+
"sourcesContent": ["/*!\n * MIT License: https://github.com/NoHomey/bind-decorator/blob/master/License\n * Copyright (c) 2016 Ivo Stratev\n */\n\nimport { assert } from './control'\n\n/**\n * Decorator that binds a method to its class instance (legacy stage-2 TypeScript decorators).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param target - The prototype of the class being decorated\n * @param propertyKey - The name of the method being decorated\n * @param descriptor - The property descriptor for the method being decorated\n * @returns The modified property descriptor with bound method access\n * @example\n * ```typescript\n * class MyClass {\n * name = 'example';\n *\n * @bind\n * getName() {\n * return this.name;\n * }\n * }\n *\n * const instance = new MyClass();\n * const callback = instance.getName;\n * console.log(callback()); // 'example' (this is properly bound)\n * ```\n * @public\n */\nexport function bind<T extends (...args: any[]) => any>(\n\ttarget: object,\n\tpropertyKey: string,\n\tdescriptor: TypedPropertyDescriptor<T>\n): TypedPropertyDescriptor<T>\n\n/**\n * Decorator that binds a method to its class instance (TC39 decorators standard).\n * When applied to a class method, ensures `this` always refers to the class instance,\n * even when the method is called as a callback or event handler.\n *\n * @param originalMethod - The original method being decorated\n * @param context - The decorator context containing metadata about the method\n * @example\n * ```typescript\n * class EventHandler {\n * message = 'Hello World';\n *\n * @bind\n * handleClick() {\n * console.log(this.message);\n * }\n * }\n *\n * const handler = new EventHandler();\n * document.addEventListener('click', handler.handleClick); // 'this' is properly bound\n * ```\n * @public\n */\nexport function bind<This extends object, T extends (...args: any[]) => any>(\n\toriginalMethod: T,\n\tcontext: ClassMethodDecoratorContext<This, T>\n): void\n\n/**\n * Universal decorator implementation that handles both legacy stage-2 and TC39 decorator formats.\n * Automatically detects the decorator format based on the number of arguments and binds the\n * decorated method to the class instance, preventing common `this` context issues.\n *\n * @param args - Either legacy decorator arguments (target, propertyKey, descriptor) or TC39 decorator arguments (originalMethod, context)\n * @returns Property descriptor for legacy decorators, or void for TC39 decorators\n * @example\n * ```typescript\n * // Works with both decorator formats\n * class Calculator {\n * multiplier = 2;\n *\n * @bind\n * multiply(value: number) {\n * return value * this.multiplier;\n * }\n * }\n *\n * const calc = new Calculator();\n * const multiplyFn = calc.multiply;\n * console.log(multiplyFn(5)); // 10 (this.multiplier is accessible)\n *\n * // Useful for event handlers and callbacks\n * setTimeout(calc.multiply, 100, 3); // 6\n * ```\n * @public\n */\nexport function bind(\n\t...args: // legacy stage-2 typescript decorators\n\t\t| [_target: object, propertyKey: string, descriptor: PropertyDescriptor]\n\t\t// TC39 decorators\n\t\t| [originalMethod: (...args: any[]) => any, context: ClassMemberDecoratorContext]\n): PropertyDescriptor | void {\n\tif (args.length === 2) {\n\t\tconst [originalMethod, context] = args\n\t\tcontext.addInitializer(function initializeMethod(this: any) {\n\t\t\tassert(Reflect.isExtensible(this), 'Cannot bind to a non-extensible class.')\n\t\t\tconst value = originalMethod.bind(this)\n\t\t\tconst ok = Reflect.defineProperty(this, context.name, {\n\t\t\t\tvalue,\n\t\t\t\twritable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t})\n\t\t\tassert(ok, 'Cannot bind a non-configurable class method.')\n\t\t})\n\t} else {\n\t\tconst [_target, propertyKey, descriptor] = args\n\t\tif (!descriptor || typeof descriptor.value !== 'function') {\n\t\t\tthrow new TypeError(\n\t\t\t\t`Only methods can be decorated with @bind. <${propertyKey}> is not a method!`\n\t\t\t)\n\t\t}\n\n\t\treturn {\n\t\t\tconfigurable: true,\n\t\t\tget(this: any): any {\n\t\t\t\tconst bound = descriptor.value!.bind(this)\n\t\t\t\t// Credits to https://github.com/andreypopp/autobind-decorator for memoizing the result of bind against a symbol on the instance.\n\t\t\t\tObject.defineProperty(this, propertyKey, {\n\t\t\t\t\tvalue: bound,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t})\n\t\t\t\treturn bound\n\t\t\t},\n\t\t}\n\t}\n}\n"],
|
|
5
5
|
"mappings": "AAAA;AAAA;AAAA;AAAA;AAKA,SAAS,cAAc;AA0FhB,SAAS,QACZ,MAIyB;AAC5B,MAAI,KAAK,WAAW,GAAG;AACtB,UAAM,CAAC,gBAAgB,OAAO,IAAI;AAClC,YAAQ,eAAe,SAAS,mBAA4B;AAC3D,aAAO,QAAQ,aAAa,IAAI,GAAG,wCAAwC;AAC3E,YAAM,QAAQ,eAAe,KAAK,IAAI;AACtC,YAAM,KAAK,QAAQ,eAAe,MAAM,QAAQ,MAAM;AAAA,QACrD;AAAA,QACA,UAAU;AAAA,QACV,cAAc;AAAA,MACf,CAAC;AACD,aAAO,IAAI,8CAA8C;AAAA,IAC1D,CAAC;AAAA,EACF,OAAO;AACN,UAAM,CAAC,SAAS,aAAa,UAAU,IAAI;AAC3C,QAAI,CAAC,cAAc,OAAO,WAAW,UAAU,YAAY;AAC1D,YAAM,IAAI;AAAA,QACT,8CAA8C,WAAW;AAAA,MAC1D;AAAA,IACD;AAEA,WAAO;AAAA,MACN,cAAc;AAAA,MACd,MAAoB;AACnB,cAAM,QAAQ,WAAW,MAAO,KAAK,IAAI;AAEzC,eAAO,eAAe,MAAM,aAAa;AAAA,UACxC,OAAO;AAAA,UACP,cAAc;AAAA,UACd,UAAU;AAAA,QACX,CAAC;AACD,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/debounce.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Create a debounced version of a function that delays execution until after a specified wait time.\n *\n * Debouncing ensures that a function is only executed once after a specified delay,\n * even if called multiple times in rapid succession. Each new call resets the timer. The debounced\n * function returns a Promise that resolves with the result of the original function. Includes a\n * cancel method to prevent execution if needed.\n *\n * @param callback - The function to debounce (can be sync or async)\n * @param wait - The delay in milliseconds before executing the function\n * @returns A debounced function that returns a Promise and includes a cancel method\n *\n * @example\n * ```ts\n * // Debounce a search function\n * const searchAPI = (query: string) => fetch(`/search?q=${query}`)\n * const debouncedSearch = debounce(searchAPI, 300)\n *\n * // Multiple rapid calls will only execute the last one after 300ms\n * debouncedSearch('react').then(result => console.log(result))\n * debouncedSearch('react hooks') // This cancels the previous call\n * debouncedSearch('react typescript') // Only this will execute\n *\n * // Cancel pending execution\n * debouncedSearch.cancel()\n *\n * // With async/await\n * const saveData = debounce(async (data: any) => {\n * return await api.save(data)\n * }, 1000)\n *\n * const result = await saveData({name: 'John'})\n * ```\n *\n * @public\n * @see source - https://gist.github.com/ca0v/73a31f57b397606c9813472f7493a940\n */\nexport function debounce<T extends unknown[], U>(\n\tcallback: (...args: T) =>
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import type { Awaitable } from './types'\n\n/**\n * Create a debounced version of a function that delays execution until after a specified wait time.\n *\n * Debouncing ensures that a function is only executed once after a specified delay,\n * even if called multiple times in rapid succession. Each new call resets the timer. The debounced\n * function returns a Promise that resolves with the result of the original function. Includes a\n * cancel method to prevent execution if needed.\n *\n * @param callback - The function to debounce (can be sync or async)\n * @param wait - The delay in milliseconds before executing the function\n * @returns A debounced function that returns a Promise and includes a cancel method\n *\n * @example\n * ```ts\n * // Debounce a search function\n * const searchAPI = (query: string) => fetch(`/search?q=${query}`)\n * const debouncedSearch = debounce(searchAPI, 300)\n *\n * // Multiple rapid calls will only execute the last one after 300ms\n * debouncedSearch('react').then(result => console.log(result))\n * debouncedSearch('react hooks') // This cancels the previous call\n * debouncedSearch('react typescript') // Only this will execute\n *\n * // Cancel pending execution\n * debouncedSearch.cancel()\n *\n * // With async/await\n * const saveData = debounce(async (data: any) => {\n * return await api.save(data)\n * }, 1000)\n *\n * const result = await saveData({name: 'John'})\n * ```\n *\n * @public\n * @see source - https://gist.github.com/ca0v/73a31f57b397606c9813472f7493a940\n */\nexport function debounce<T extends unknown[], U>(\n\tcallback: (...args: T) => Awaitable<U>,\n\twait: number\n) {\n\tlet state:\n\t\t| undefined\n\t\t| {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\ttimeout: ReturnType<typeof setTimeout>\n\t\t\t\tpromise: Promise<U>\n\t\t\t\tresolve(value: U | PromiseLike<U>): void\n\t\t\t\treject(value: any): void\n\t\t\t\tlatestArgs: T\n\t\t } = undefined\n\n\tconst fn = (...args: T): Promise<U> => {\n\t\tif (!state) {\n\t\t\tstate = {} as any\n\t\t\tstate!.promise = new Promise((resolve, reject) => {\n\t\t\t\tstate!.resolve = resolve\n\t\t\t\tstate!.reject = reject\n\t\t\t})\n\t\t}\n\t\tclearTimeout(state!.timeout)\n\t\tstate!.latestArgs = args\n\t\t// It's up to the consumer of debounce to call `cancel`\n\t\t// eslint-disable-next-line no-restricted-globals\n\t\tstate!.timeout = setTimeout(() => {\n\t\t\tconst s = state!\n\t\t\tstate = undefined\n\t\t\ttry {\n\t\t\t\ts.resolve(callback(...s.latestArgs))\n\t\t\t} catch (e) {\n\t\t\t\ts.reject(e)\n\t\t\t}\n\t\t}, wait)\n\n\t\treturn state!.promise\n\t}\n\tfn.cancel = () => {\n\t\tif (!state) return\n\t\tclearTimeout(state.timeout)\n\t}\n\treturn fn\n}\n"],
|
|
5
|
+
"mappings": "AAuCO,SAAS,SACf,UACA,MACC;AACD,MAAI,QASG;AAEP,QAAM,KAAK,IAAI,SAAwB;AACtC,QAAI,CAAC,OAAO;AACX,cAAQ,CAAC;AACT,YAAO,UAAU,IAAI,QAAQ,CAAC,SAAS,WAAW;AACjD,cAAO,UAAU;AACjB,cAAO,SAAS;AAAA,MACjB,CAAC;AAAA,IACF;AACA,iBAAa,MAAO,OAAO;AAC3B,UAAO,aAAa;AAGpB,UAAO,UAAU,WAAW,MAAM;AACjC,YAAM,IAAI;AACV,cAAQ;AACR,UAAI;AACH,UAAE,QAAQ,SAAS,GAAG,EAAE,UAAU,CAAC;AAAA,MACpC,SAAS,GAAG;AACX,UAAE,OAAO,CAAC;AAAA,MACX;AAAA,IACD,GAAG,IAAI;AAEP,WAAO,MAAO;AAAA,EACf;AACA,KAAG,SAAS,MAAM;AACjB,QAAI,CAAC,MAAO;AACZ,iBAAa,MAAM,OAAO;AAAA,EAC3B;AACA,SAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/network.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Just a wrapper around `window.fetch` that sets the `referrerPolicy` to `strict-origin-when-cross-origin`.\n *\n * @param input - A Request object or string containing the URL to fetch\n * @param init - Optional request initialization options\n * @returns Promise that resolves to the Response object\n * @internal\n */\nexport async function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n\t// eslint-disable-next-line no-restricted-properties\n\treturn window.fetch(input, {\n\t\t// We want to make sure that the referrer is not sent to other domains.\n\t\treferrerPolicy: 'strict-origin-when-cross-origin',\n\t\t...init,\n\t})\n}\n\n/**\n * Just a wrapper around `new Image`, and yeah, it's a bit strange that it's in the network.ts file\n * but the main concern here is the referrerPolicy and setting it correctly.\n *\n * @param width - Optional width for the image element\n * @param height - Optional height for the image element\n * @returns HTMLImageElement with referrerPolicy set to 'strict-origin-when-cross-origin'\n * @internal\n */\nexport const Image = (width?: number, height?: number) => {\n\t// eslint-disable-next-line no-restricted-properties\n\tconst img = new window.Image(width, height)\n\timg.referrerPolicy = 'strict-origin-when-cross-origin'\n\treturn img\n}\n"],
|
|
4
|
+
"sourcesContent": ["/**\n * Just a wrapper around `window.fetch` that sets the `referrerPolicy` to `strict-origin-when-cross-origin`.\n *\n * @param input - A Request object or string containing the URL to fetch\n * @param init - Optional request initialization options\n * @returns Promise that resolves to the Response object\n * @internal\n */\nexport async function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n\t// eslint-disable-next-line tldraw/no-restricted-properties\n\treturn window.fetch(input, {\n\t\t// We want to make sure that the referrer is not sent to other domains.\n\t\treferrerPolicy: 'strict-origin-when-cross-origin',\n\t\t...init,\n\t})\n}\n\n/**\n * Just a wrapper around `new Image`, and yeah, it's a bit strange that it's in the network.ts file\n * but the main concern here is the referrerPolicy and setting it correctly.\n *\n * @param width - Optional width for the image element\n * @param height - Optional height for the image element\n * @returns HTMLImageElement with referrerPolicy set to 'strict-origin-when-cross-origin'\n * @internal\n */\nexport const Image = (width?: number, height?: number) => {\n\t// eslint-disable-next-line tldraw/no-restricted-properties\n\tconst img = new window.Image(width, height)\n\timg.referrerPolicy = 'strict-origin-when-cross-origin'\n\treturn img\n}\n"],
|
|
5
5
|
"mappings": "AAQA,eAAsB,MAAM,OAA0B,MAAuC;AAE5F,SAAO,OAAO,MAAM,OAAO;AAAA;AAAA,IAE1B,gBAAgB;AAAA,IAChB,GAAG;AAAA,EACJ,CAAC;AACF;AAWO,MAAM,QAAQ,CAAC,OAAgB,WAAoB;AAEzD,QAAM,MAAM,IAAI,OAAO,MAAM,OAAO,MAAM;AAC1C,MAAI,iBAAiB;AACrB,SAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/retry.ts"],
|
|
4
|
-
"sourcesContent": ["import { sleep } from './control'\n\n/**\n * Retries an async operation with configurable attempt count, wait duration, and error filtering.\n * Executes the provided async function repeatedly until it succeeds or the maximum number of attempts is reached.\n * Includes support for abort signals and custom error matching to determine which errors should trigger retries.\n *\n * @param fn - The async function to retry on failure\n * @param options - Configuration options for retry behavior:\n * - `attempts`: Maximum number of retry attempts (default: 3)\n * - `waitDuration`: Milliseconds to wait between retry attempts (default: 1000)\n * - `abortSignal`: Optional AbortSignal to cancel the retry operation\n * - `matchError`: Optional function to determine if an error should trigger a retry\n * @returns Promise that resolves with the function's return value on success\n *\n * @example\n * ```ts\n * // Basic retry with default settings (3 attempts, 1 second wait)\n * const data = await retry(async () => {\n * const response = await fetch('/api/data')\n * if (!response.ok) throw new Error('Network error')\n * return response.json()\n * })\n *\n * // Custom retry configuration\n * const result = await retry(\n * async () => unreliableApiCall(),\n * {\n * attempts: 5,\n * waitDuration: 2000,\n * matchError: (error) => error instanceof NetworkError\n * }\n * )\n *\n * // With abort signal for cancellation\n * const controller = new AbortController()\n * setTimeout(() => controller.abort(), 10000) // Cancel after 10 seconds\n *\n * const data = await retry(\n * async () => fetchData(),\n * {\n * attempts: 10,\n * abortSignal: controller.signal\n * }\n * )\n * ```\n *\n * @internal\n */\nexport async function retry<T>(\n\tfn: (args: { attempt: number; remaining: number; total: number }) => Promise<T>,\n\t{\n\t\tattempts = 3,\n\t\twaitDuration = 1000,\n\t\tabortSignal,\n\t\tmatchError,\n\t}: {\n\t\tattempts?: number\n\t\twaitDuration?: number\n\t\tabortSignal?: AbortSignal\n\t\tmatchError?(error: unknown): boolean\n\t} = {}\n): Promise<T> {\n\tlet error: unknown = null\n\tfor (let i = 0; i < attempts; i++) {\n\t\tif (abortSignal?.aborted) throw new Error('aborted')\n\t\ttry {\n\t\t\treturn await fn({ attempt: i, remaining: attempts - i, total: attempts })\n\t\t} catch (e) {\n\t\t\tif (matchError && !matchError(e)) throw e\n\t\t\terror = e\n\t\t\tawait sleep(waitDuration)\n\t\t}\n\t}\n\tthrow error\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,aAAa;AAiDtB,eAAsB,MACrB,IACA;AAAA,EACC,WAAW;AAAA,EACX,eAAe;AAAA,EACf;AAAA,EACA;AACD,IAKI,CAAC,GACQ;AACb,MAAI,QAAiB;AACrB,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAClC,QAAI,aAAa,QAAS,OAAM,IAAI,MAAM,SAAS;AACnD,QAAI;AACH,aAAO,MAAM,GAAG,EAAE,SAAS,GAAG,WAAW,WAAW,GAAG,OAAO,SAAS,CAAC;AAAA,IACzE,SAAS,GAAG;AACX,UAAI,cAAc,CAAC,WAAW,CAAC,EAAG,OAAM;AACxC,cAAQ;AACR,YAAM,MAAM,YAAY;AAAA,IACzB;AAAA,EACD;
|
|
4
|
+
"sourcesContent": ["import { sleep } from './control'\n\n/**\n * Retries an async operation with configurable attempt count, wait duration, and error filtering.\n * Executes the provided async function repeatedly until it succeeds or the maximum number of attempts is reached.\n * Includes support for abort signals and custom error matching to determine which errors should trigger retries.\n *\n * @param fn - The async function to retry on failure\n * @param options - Configuration options for retry behavior:\n * - `attempts`: Maximum number of retry attempts (default: 3)\n * - `waitDuration`: Milliseconds to wait between retry attempts (default: 1000)\n * - `abortSignal`: Optional AbortSignal to cancel the retry operation\n * - `matchError`: Optional function to determine if an error should trigger a retry\n * @returns Promise that resolves with the function's return value on success\n *\n * @example\n * ```ts\n * // Basic retry with default settings (3 attempts, 1 second wait)\n * const data = await retry(async () => {\n * const response = await fetch('/api/data')\n * if (!response.ok) throw new Error('Network error')\n * return response.json()\n * })\n *\n * // Custom retry configuration\n * const result = await retry(\n * async () => unreliableApiCall(),\n * {\n * attempts: 5,\n * waitDuration: 2000,\n * matchError: (error) => error instanceof NetworkError\n * }\n * )\n *\n * // With abort signal for cancellation\n * const controller = new AbortController()\n * setTimeout(() => controller.abort(), 10000) // Cancel after 10 seconds\n *\n * const data = await retry(\n * async () => fetchData(),\n * {\n * attempts: 10,\n * abortSignal: controller.signal\n * }\n * )\n * ```\n *\n * @internal\n */\nexport async function retry<T>(\n\tfn: (args: { attempt: number; remaining: number; total: number }) => Promise<T>,\n\t{\n\t\tattempts = 3,\n\t\twaitDuration = 1000,\n\t\tabortSignal,\n\t\tmatchError,\n\t}: {\n\t\tattempts?: number\n\t\twaitDuration?: number\n\t\tabortSignal?: AbortSignal\n\t\tmatchError?(error: unknown): boolean\n\t} = {}\n): Promise<T> {\n\tlet error: unknown = null\n\tfor (let i = 0; i < attempts; i++) {\n\t\tif (abortSignal?.aborted) throw new Error('aborted')\n\t\ttry {\n\t\t\treturn await fn({ attempt: i, remaining: attempts - i, total: attempts })\n\t\t} catch (e) {\n\t\t\tif (matchError && !matchError(e)) throw e\n\t\t\terror = e\n\t\t\tawait sleep(waitDuration)\n\t\t}\n\t}\n\t// eslint-disable-next-line no-throw-literal\n\tthrow error\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,aAAa;AAiDtB,eAAsB,MACrB,IACA;AAAA,EACC,WAAW;AAAA,EACX,eAAe;AAAA,EACf;AAAA,EACA;AACD,IAKI,CAAC,GACQ;AACb,MAAI,QAAiB;AACrB,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAClC,QAAI,aAAa,QAAS,OAAM,IAAI,MAAM,SAAS;AACnD,QAAI;AACH,aAAO,MAAM,GAAG,EAAE,SAAS,GAAG,WAAW,WAAW,GAAG,OAAO,SAAS,CAAC;AAAA,IACzE,SAAS,GAAG;AACX,UAAI,cAAc,CAAC,WAAW,CAAC,EAAG,OAAM;AACxC,cAAQ;AACR,YAAM,MAAM,YAAY;AAAA,IACzB;AAAA,EACD;AAEA,QAAM;AACP;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/storage.tsx"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable no-
|
|
4
|
+
"sourcesContent": ["/* eslint-disable tldraw/no-direct-storage */\n\n/**\n * Get a value from local storage.\n *\n * @param key - The key to get.\n * @returns The stored value as a string, or null if not found or storage is unavailable.\n * @example\n * ```ts\n * const userTheme = getFromLocalStorage('user-theme')\n * if (userTheme) {\n * console.log('Stored theme:', userTheme)\n * }\n * ```\n * @internal\n */\nexport function getFromLocalStorage(key: string) {\n\ttry {\n\t\treturn localStorage.getItem(key)\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Set a value in local storage. Will not throw an error if localStorage is not available.\n *\n * @param key - The key to set.\n * @param value - The value to set.\n * @returns void\n * @example\n * ```ts\n * const preferences = { theme: 'dark', language: 'en' }\n * setInLocalStorage('user-preferences', JSON.stringify(preferences))\n * ```\n * @internal\n */\nexport function setInLocalStorage(key: string, value: string) {\n\ttry {\n\t\tlocalStorage.setItem(key, value)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Remove a value from local storage. Will not throw an error if localStorage is not available.\n *\n * @param key - The key to remove.\n * @returns void\n * @example\n * ```ts\n * deleteFromLocalStorage('user-preferences')\n * // Value is now removed from localStorage\n * ```\n * @internal\n */\nexport function deleteFromLocalStorage(key: string) {\n\ttry {\n\t\tlocalStorage.removeItem(key)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Clear all values from local storage. Will not throw an error if localStorage is not available.\n *\n * @returns void\n * @example\n * ```ts\n * clearLocalStorage()\n * // All localStorage data is now cleared\n * ```\n * @internal\n */\nexport function clearLocalStorage() {\n\ttry {\n\t\tlocalStorage.clear()\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Get a value from session storage.\n *\n * @param key - The key to get.\n * @returns The stored value as a string, or null if not found or storage is unavailable.\n * @example\n * ```ts\n * const currentTool = getFromSessionStorage('current-tool')\n * if (currentTool) {\n * console.log('Active tool:', currentTool)\n * }\n * ```\n * @internal\n */\nexport function getFromSessionStorage(key: string) {\n\ttry {\n\t\treturn sessionStorage.getItem(key)\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Set a value in session storage. Will not throw an error if sessionStorage is not available.\n *\n * @param key - The key to set.\n * @param value - The value to set.\n * @returns void\n * @example\n * ```ts\n * setInSessionStorage('current-tool', 'select')\n * setInSessionStorage('temp-data', JSON.stringify({ x: 100, y: 200 }))\n * ```\n * @internal\n */\nexport function setInSessionStorage(key: string, value: string) {\n\ttry {\n\t\tsessionStorage.setItem(key, value)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Remove a value from session storage. Will not throw an error if sessionStorage is not available.\n *\n * @param key - The key to remove.\n * @returns void\n * @example\n * ```ts\n * deleteFromSessionStorage('temp-data')\n * // Value is now removed from sessionStorage\n * ```\n * @internal\n */\nexport function deleteFromSessionStorage(key: string) {\n\ttry {\n\t\tsessionStorage.removeItem(key)\n\t} catch {\n\t\t// noop\n\t}\n}\n\n/**\n * Clear all values from session storage. Will not throw an error if sessionStorage is not available.\n *\n * @returns void\n * @example\n * ```ts\n * clearSessionStorage()\n * // All sessionStorage data is now cleared\n * ```\n * @internal\n */\nexport function clearSessionStorage() {\n\ttry {\n\t\tsessionStorage.clear()\n\t} catch {\n\t\t// noop\n\t}\n}\n"],
|
|
5
5
|
"mappings": "AAgBO,SAAS,oBAAoB,KAAa;AAChD,MAAI;AACH,WAAO,aAAa,QAAQ,GAAG;AAAA,EAChC,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAeO,SAAS,kBAAkB,KAAa,OAAe;AAC7D,MAAI;AACH,iBAAa,QAAQ,KAAK,KAAK;AAAA,EAChC,QAAQ;AAAA,EAER;AACD;AAcO,SAAS,uBAAuB,KAAa;AACnD,MAAI;AACH,iBAAa,WAAW,GAAG;AAAA,EAC5B,QAAQ;AAAA,EAER;AACD;AAaO,SAAS,oBAAoB;AACnC,MAAI;AACH,iBAAa,MAAM;AAAA,EACpB,QAAQ;AAAA,EAER;AACD;AAgBO,SAAS,sBAAsB,KAAa;AAClD,MAAI;AACH,WAAO,eAAe,QAAQ,GAAG;AAAA,EAClC,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAeO,SAAS,oBAAoB,KAAa,OAAe;AAC/D,MAAI;AACH,mBAAe,QAAQ,KAAK,KAAK;AAAA,EAClC,QAAQ;AAAA,EAER;AACD;AAcO,SAAS,yBAAyB,KAAa;AACrD,MAAI;AACH,mBAAe,WAAW,GAAG;AAAA,EAC9B,QAAQ;AAAA,EAER;AACD;AAaO,SAAS,sBAAsB;AACrC,MAAI;AACH,mBAAe,MAAM;AAAA,EACtB,QAAQ;AAAA,EAER;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/timers.ts"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable no-restricted-properties */\n\n/**\n * A utility class for managing timeouts, intervals, and animation frames with context-based organization and automatic cleanup.\n * Helps prevent memory leaks by organizing timers into named contexts that can be cleared together.\n * @example\n * ```ts\n * const timers = new Timers()\n *\n * // Set timers with context organization\n * timers.setTimeout('ui', () => console.log('Auto save'), 5000)\n * timers.setInterval('ui', () => console.log('Refresh'), 1000)\n * timers.requestAnimationFrame('ui', () => console.log('Render'))\n *\n * // Clear all timers for a context\n * timers.dispose('ui')\n *\n * // Or get context-bound functions\n * const uiTimers = timers.forContext('ui')\n * uiTimers.setTimeout(() => console.log('Contextual timeout'), 1000)\n * ```\n * @public\n */\nexport class Timers {\n\tprivate timeouts = new Map<string, number[]>()\n\tprivate intervals = new Map<string, number[]>()\n\tprivate rafs = new Map<string, number[]>()\n\n\t/**\n\t * Creates a new Timers instance with bound methods for safe callback usage.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * // Methods are pre-bound, safe to use as callbacks\n\t * element.addEventListener('click', timers.dispose)\n\t * ```\n\t */\n\tconstructor() {\n\t\tthis.setTimeout = this.setTimeout.bind(this)\n\t\tthis.setInterval = this.setInterval.bind(this)\n\t\tthis.requestAnimationFrame = this.requestAnimationFrame.bind(this)\n\t\tthis.dispose = this.dispose.bind(this)\n\t}\n\n\t/**\n\t * Creates a timeout that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute when the timeout expires.\n\t * @param timeout - The delay in milliseconds (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The timer ID that can be used with clearTimeout.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setTimeout('autosave', () => save(), 5000)\n\t * // Timer will be automatically cleared when 'autosave' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetTimeout(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setTimeout(handler, timeout, args)\n\t\tconst current = this.timeouts.get(contextId) ?? []\n\t\tthis.timeouts.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Creates an interval that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute repeatedly.\n\t * @param timeout - The delay in milliseconds between executions (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The interval ID that can be used with clearInterval.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setInterval('refresh', () => updateData(), 1000)\n\t * // Interval will be automatically cleared when 'refresh' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetInterval(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setInterval(handler, timeout, args)\n\t\tconst current = this.intervals.get(contextId) ?? []\n\t\tthis.intervals.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Requests an animation frame that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this animation frame under.\n\t * @param callback - The function to execute on the next animation frame.\n\t * @returns The request ID that can be used with cancelAnimationFrame.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.requestAnimationFrame('render', () => draw())\n\t * // Animation frame will be automatically cancelled when 'render' context is disposed\n\t * ```\n\t * @public\n\t */\n\trequestAnimationFrame(contextId: string, callback: FrameRequestCallback): number {\n\t\tconst id = window.requestAnimationFrame(callback)\n\t\tconst current = this.rafs.get(contextId) ?? []\n\t\tthis.rafs.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Disposes of all timers associated with the specified context.\n\t * Clears all timeouts, intervals, and animation frames for the given context ID.\n\t * @param contextId - The context identifier whose timers should be cleared.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('timeout'), 1000)\n\t * timers.setInterval('ui', () => console.log('interval'), 500)\n\t *\n\t * // Clear all 'ui' context timers\n\t * timers.dispose('ui')\n\t * ```\n\t * @public\n\t */\n\tdispose(contextId: string) {\n\t\tthis.timeouts.get(contextId)?.forEach((id) => clearTimeout(id))\n\t\tthis.intervals.get(contextId)?.forEach((id) => clearInterval(id))\n\t\tthis.rafs.get(contextId)?.forEach((id) => cancelAnimationFrame(id))\n\n\t\tthis.timeouts.delete(contextId)\n\t\tthis.intervals.delete(contextId)\n\t\tthis.rafs.delete(contextId)\n\t}\n\n\t/**\n\t * Disposes of all timers across all contexts.\n\t * Clears every timeout, interval, and animation frame managed by this instance.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('ui'), 1000)\n\t * timers.setTimeout('background', () => console.log('bg'), 2000)\n\t *\n\t * // Clear everything\n\t * timers.disposeAll()\n\t * ```\n\t * @public\n\t */\n\tdisposeAll() {\n\t\tfor (const contextId of this.timeouts.keys()) {\n\t\t\tthis.dispose(contextId)\n\t\t}\n\t}\n\n\t/**\n\t * Returns an object with timer methods bound to a specific context.\n\t * Convenient for getting context-specific timer functions without repeatedly passing the contextId.\n\t * @param contextId - The context identifier to bind the returned methods to.\n\t * @returns An object with setTimeout, setInterval, requestAnimationFrame, and dispose methods bound to the context.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const uiTimers = timers.forContext('ui')\n\t *\n\t * // These are equivalent to calling timers.setTimeout('ui', ...)\n\t * uiTimers.setTimeout(() => console.log('timeout'), 1000)\n\t * uiTimers.setInterval(() => console.log('interval'), 500)\n\t * uiTimers.requestAnimationFrame(() => console.log('frame'))\n\t *\n\t * // Dispose only this context\n\t * uiTimers.dispose()\n\t * ```\n\t * @public\n\t */\n\tforContext(contextId: string) {\n\t\treturn {\n\t\t\tsetTimeout: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setTimeout(contextId, handler, timeout, args),\n\t\t\tsetInterval: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setInterval(contextId, handler, timeout, args),\n\t\t\trequestAnimationFrame: (callback: FrameRequestCallback) =>\n\t\t\t\tthis.requestAnimationFrame(contextId, callback),\n\t\t\tdispose: () => this.dispose(contextId),\n\t\t}\n\t}\n}\n"],
|
|
4
|
+
"sourcesContent": ["/* eslint-disable tldraw/no-restricted-properties */\n\n/**\n * A utility class for managing timeouts, intervals, and animation frames with context-based organization and automatic cleanup.\n * Helps prevent memory leaks by organizing timers into named contexts that can be cleared together.\n * @example\n * ```ts\n * const timers = new Timers()\n *\n * // Set timers with context organization\n * timers.setTimeout('ui', () => console.log('Auto save'), 5000)\n * timers.setInterval('ui', () => console.log('Refresh'), 1000)\n * timers.requestAnimationFrame('ui', () => console.log('Render'))\n *\n * // Clear all timers for a context\n * timers.dispose('ui')\n *\n * // Or get context-bound functions\n * const uiTimers = timers.forContext('ui')\n * uiTimers.setTimeout(() => console.log('Contextual timeout'), 1000)\n * ```\n * @public\n */\nexport class Timers {\n\tprivate timeouts = new Map<string, number[]>()\n\tprivate intervals = new Map<string, number[]>()\n\tprivate rafs = new Map<string, number[]>()\n\n\t/**\n\t * Creates a new Timers instance with bound methods for safe callback usage.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * // Methods are pre-bound, safe to use as callbacks\n\t * element.addEventListener('click', timers.dispose)\n\t * ```\n\t */\n\tconstructor() {\n\t\tthis.setTimeout = this.setTimeout.bind(this)\n\t\tthis.setInterval = this.setInterval.bind(this)\n\t\tthis.requestAnimationFrame = this.requestAnimationFrame.bind(this)\n\t\tthis.dispose = this.dispose.bind(this)\n\t}\n\n\t/**\n\t * Creates a timeout that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute when the timeout expires.\n\t * @param timeout - The delay in milliseconds (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The timer ID that can be used with clearTimeout.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setTimeout('autosave', () => save(), 5000)\n\t * // Timer will be automatically cleared when 'autosave' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetTimeout(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setTimeout(handler, timeout, args)\n\t\tconst current = this.timeouts.get(contextId) ?? []\n\t\tthis.timeouts.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Creates an interval that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this timer under.\n\t * @param handler - The function to execute repeatedly.\n\t * @param timeout - The delay in milliseconds between executions (default: 0).\n\t * @param args - Additional arguments to pass to the handler.\n\t * @returns The interval ID that can be used with clearInterval.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.setInterval('refresh', () => updateData(), 1000)\n\t * // Interval will be automatically cleared when 'refresh' context is disposed\n\t * ```\n\t * @public\n\t */\n\tsetInterval(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number {\n\t\tconst id = window.setInterval(handler, timeout, args)\n\t\tconst current = this.intervals.get(contextId) ?? []\n\t\tthis.intervals.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Requests an animation frame that will be tracked under the specified context.\n\t * @param contextId - The context identifier to group this animation frame under.\n\t * @param callback - The function to execute on the next animation frame.\n\t * @returns The request ID that can be used with cancelAnimationFrame.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const id = timers.requestAnimationFrame('render', () => draw())\n\t * // Animation frame will be automatically cancelled when 'render' context is disposed\n\t * ```\n\t * @public\n\t */\n\trequestAnimationFrame(contextId: string, callback: FrameRequestCallback): number {\n\t\tconst id = window.requestAnimationFrame(callback)\n\t\tconst current = this.rafs.get(contextId) ?? []\n\t\tthis.rafs.set(contextId, [...current, id])\n\t\treturn id\n\t}\n\n\t/**\n\t * Disposes of all timers associated with the specified context.\n\t * Clears all timeouts, intervals, and animation frames for the given context ID.\n\t * @param contextId - The context identifier whose timers should be cleared.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('timeout'), 1000)\n\t * timers.setInterval('ui', () => console.log('interval'), 500)\n\t *\n\t * // Clear all 'ui' context timers\n\t * timers.dispose('ui')\n\t * ```\n\t * @public\n\t */\n\tdispose(contextId: string) {\n\t\tthis.timeouts.get(contextId)?.forEach((id) => clearTimeout(id))\n\t\tthis.intervals.get(contextId)?.forEach((id) => clearInterval(id))\n\t\tthis.rafs.get(contextId)?.forEach((id) => cancelAnimationFrame(id))\n\n\t\tthis.timeouts.delete(contextId)\n\t\tthis.intervals.delete(contextId)\n\t\tthis.rafs.delete(contextId)\n\t}\n\n\t/**\n\t * Disposes of all timers across all contexts.\n\t * Clears every timeout, interval, and animation frame managed by this instance.\n\t * @returns void\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * timers.setTimeout('ui', () => console.log('ui'), 1000)\n\t * timers.setTimeout('background', () => console.log('bg'), 2000)\n\t *\n\t * // Clear everything\n\t * timers.disposeAll()\n\t * ```\n\t * @public\n\t */\n\tdisposeAll() {\n\t\tfor (const contextId of this.timeouts.keys()) {\n\t\t\tthis.dispose(contextId)\n\t\t}\n\t}\n\n\t/**\n\t * Returns an object with timer methods bound to a specific context.\n\t * Convenient for getting context-specific timer functions without repeatedly passing the contextId.\n\t * @param contextId - The context identifier to bind the returned methods to.\n\t * @returns An object with setTimeout, setInterval, requestAnimationFrame, and dispose methods bound to the context.\n\t * @example\n\t * ```ts\n\t * const timers = new Timers()\n\t * const uiTimers = timers.forContext('ui')\n\t *\n\t * // These are equivalent to calling timers.setTimeout('ui', ...)\n\t * uiTimers.setTimeout(() => console.log('timeout'), 1000)\n\t * uiTimers.setInterval(() => console.log('interval'), 500)\n\t * uiTimers.requestAnimationFrame(() => console.log('frame'))\n\t *\n\t * // Dispose only this context\n\t * uiTimers.dispose()\n\t * ```\n\t * @public\n\t */\n\tforContext(contextId: string) {\n\t\treturn {\n\t\t\tsetTimeout: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setTimeout(contextId, handler, timeout, args),\n\t\t\tsetInterval: (handler: TimerHandler, timeout?: number, ...args: any[]) =>\n\t\t\t\tthis.setInterval(contextId, handler, timeout, args),\n\t\t\trequestAnimationFrame: (callback: FrameRequestCallback) =>\n\t\t\t\tthis.requestAnimationFrame(contextId, callback),\n\t\t\tdispose: () => this.dispose(contextId),\n\t\t}\n\t}\n}\n"],
|
|
5
5
|
"mappings": "AAuBO,MAAM,OAAO;AAAA,EACX,WAAW,oBAAI,IAAsB;AAAA,EACrC,YAAY,oBAAI,IAAsB;AAAA,EACtC,OAAO,oBAAI,IAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWzC,cAAc;AACb,SAAK,aAAa,KAAK,WAAW,KAAK,IAAI;AAC3C,SAAK,cAAc,KAAK,YAAY,KAAK,IAAI;AAC7C,SAAK,wBAAwB,KAAK,sBAAsB,KAAK,IAAI;AACjE,SAAK,UAAU,KAAK,QAAQ,KAAK,IAAI;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,WAAW,WAAmB,SAAuB,YAAqB,MAAqB;AAC9F,UAAM,KAAK,OAAO,WAAW,SAAS,SAAS,IAAI;AACnD,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS,KAAK,CAAC;AACjD,SAAK,SAAS,IAAI,WAAW,CAAC,GAAG,SAAS,EAAE,CAAC;AAC7C,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,YAAY,WAAmB,SAAuB,YAAqB,MAAqB;AAC/F,UAAM,KAAK,OAAO,YAAY,SAAS,SAAS,IAAI;AACpD,UAAM,UAAU,KAAK,UAAU,IAAI,SAAS,KAAK,CAAC;AAClD,SAAK,UAAU,IAAI,WAAW,CAAC,GAAG,SAAS,EAAE,CAAC;AAC9C,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,sBAAsB,WAAmB,UAAwC;AAChF,UAAM,KAAK,OAAO,sBAAsB,QAAQ;AAChD,UAAM,UAAU,KAAK,KAAK,IAAI,SAAS,KAAK,CAAC;AAC7C,SAAK,KAAK,IAAI,WAAW,CAAC,GAAG,SAAS,EAAE,CAAC;AACzC,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,QAAQ,WAAmB;AAC1B,SAAK,SAAS,IAAI,SAAS,GAAG,QAAQ,CAAC,OAAO,aAAa,EAAE,CAAC;AAC9D,SAAK,UAAU,IAAI,SAAS,GAAG,QAAQ,CAAC,OAAO,cAAc,EAAE,CAAC;AAChE,SAAK,KAAK,IAAI,SAAS,GAAG,QAAQ,CAAC,OAAO,qBAAqB,EAAE,CAAC;AAElE,SAAK,SAAS,OAAO,SAAS;AAC9B,SAAK,UAAU,OAAO,SAAS;AAC/B,SAAK,KAAK,OAAO,SAAS;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,aAAa;AACZ,eAAW,aAAa,KAAK,SAAS,KAAK,GAAG;AAC7C,WAAK,QAAQ,SAAS;AAAA,IACvB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,WAAW,WAAmB;AAC7B,WAAO;AAAA,MACN,YAAY,CAAC,SAAuB,YAAqB,SACxD,KAAK,WAAW,WAAW,SAAS,SAAS,IAAI;AAAA,MAClD,aAAa,CAAC,SAAuB,YAAqB,SACzD,KAAK,YAAY,WAAW,SAAS,SAAS,IAAI;AAAA,MACnD,uBAAuB,CAAC,aACvB,KAAK,sBAAsB,WAAW,QAAQ;AAAA,MAC/C,SAAS,MAAM,KAAK,QAAQ,SAAS;AAAA,IACtC;AAAA,EACD;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/version.ts"],
|
|
4
|
-
"sourcesContent": ["interface TldrawLibraryVersion {\n\tname: string\n\tversion: string\n\tmodules: string\n}\n\ninterface TldrawLibraryVersionInfo {\n\tversions: TldrawLibraryVersion[]\n\tdidWarn: boolean\n\tscheduledNotice: number | NodeJS.Timeout | null\n}\n\nconst TLDRAW_LIBRARY_VERSION_KEY = '__TLDRAW_LIBRARY_VERSIONS__' as const\n\n// eslint-disable-next-line @typescript-eslint/prefer-namespace-keyword, @typescript-eslint/no-namespace\ndeclare module globalThis {\n\texport const __TLDRAW_LIBRARY_VERSIONS__: TldrawLibraryVersionInfo\n}\n\nfunction getLibraryVersions(): TldrawLibraryVersionInfo {\n\tif (globalThis[TLDRAW_LIBRARY_VERSION_KEY]) {\n\t\treturn globalThis[TLDRAW_LIBRARY_VERSION_KEY]\n\t}\n\n\tconst info: TldrawLibraryVersionInfo = {\n\t\tversions: [],\n\t\tdidWarn: false,\n\t\tscheduledNotice: null,\n\t}\n\n\tObject.defineProperty(globalThis, TLDRAW_LIBRARY_VERSION_KEY, {\n\t\tvalue: info,\n\t\twritable: false,\n\t\tconfigurable: false,\n\t\tenumerable: false,\n\t})\n\n\treturn info\n}\n\n/**\n * Clears all registered library versions and resets warning state.\n * This function is intended for testing purposes only to reset the global version tracking state.\n * @returns void\n * @example\n * ```ts\n * // In a test setup\n * beforeEach(() => {\n * clearRegisteredVersionsForTests()\n * })\n *\n * // Now version tracking starts fresh for each test\n * registerTldrawLibraryVersion('@tldraw/editor', '2.0.0', 'esm')\n * ```\n * @internal\n */\nexport function clearRegisteredVersionsForTests() {\n\tconst info = getLibraryVersions()\n\tinfo.versions = []\n\tinfo.didWarn = false\n\tif (info.scheduledNotice) {\n\t\tclearTimeout(info.scheduledNotice)\n\t\tinfo.scheduledNotice = null\n\t}\n}\n\n/**\n * Registers a tldraw library version for conflict detection.\n * This function tracks different tldraw library versions to warn about potential conflicts\n * when multiple versions are loaded simultaneously.\n * @param name - The name of the tldraw library package (e.g., '\\@tldraw/editor').\n * @param version - The semantic version string (e.g., '2.0.0').\n * @param modules - The module system being used ('esm' or 'cjs').\n * @returns void\n * @example\n * ```ts\n * // Register a library version during package initialization\n * registerTldrawLibraryVersion('@tldraw/editor', '2.0.0', 'esm')\n * registerTldrawLibraryVersion('@tldraw/tldraw', '2.0.0', 'esm')\n *\n * // If conflicting versions are detected, warnings will be logged:\n * registerTldrawLibraryVersion('@tldraw/editor', '1.9.0', 'cjs')\n * // Console warning about version mismatch will appear\n * ```\n * @internal\n */\nexport function registerTldrawLibraryVersion(name?: string, version?: string, modules?: string) {\n\tif (!name || !version || !modules) {\n\t\tif ((globalThis as any).TLDRAW_LIBRARY_IS_BUILD) {\n\t\t\tthrow new Error('Missing name/version/module system in built version of tldraw library')\n\t\t}\n\t\treturn\n\t}\n\n\tconst info = getLibraryVersions()\n\n\t// In Next.js dev mode, Fast Refresh re-executes module-level code which causes\n\t// the same library to register multiple times, producing a false positive warning.\n\t// We skip exact duplicates only in Next.js dev to avoid hiding genuine issues.\n\tif (isNextjsDev()) {\n\t\tconst isDuplicate = info.versions.some(\n\t\t\t(v) => v.name === name && v.version === version && v.modules === modules\n\t\t)\n\t\tif (isDuplicate) return\n\t}\n\n\tinfo.versions.push({ name, version, modules })\n\n\tif (!info.scheduledNotice) {\n\t\ttry {\n\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\tinfo.scheduledNotice = setTimeout(() => {\n\t\t\t\tinfo.scheduledNotice = null\n\t\t\t\tcheckLibraryVersions(info)\n\t\t\t}, 100)\n\t\t} catch {\n\t\t\t// some environments (e.g. cloudflare workers) don't support setTimeout immediately, only in a handler.\n\t\t\t// in this case, we'll just check immediately.\n\t\t\tcheckLibraryVersions(info)\n\t\t}\n\t}\n}\n\nfunction checkLibraryVersions(info: TldrawLibraryVersionInfo) {\n\tif (!info.versions.length) return\n\tif (info.didWarn) return\n\n\tconst sorted = info.versions.sort((a, b) => compareVersions(a.version, b.version))\n\tconst latestVersion = sorted[sorted.length - 1].version\n\n\tconst matchingVersions = new Set<string>()\n\tconst nonMatchingVersions = new Map<string, Set<string>>()\n\tfor (const lib of sorted) {\n\t\tif (nonMatchingVersions.has(lib.name)) {\n\t\t\tmatchingVersions.delete(lib.name)\n\t\t\tentry(nonMatchingVersions, lib.name, new Set()).add(lib.version)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (lib.version === latestVersion) {\n\t\t\tmatchingVersions.add(lib.name)\n\t\t} else {\n\t\t\tmatchingVersions.delete(lib.name)\n\t\t\tentry(nonMatchingVersions, lib.name, new Set()).add(lib.version)\n\t\t}\n\t}\n\n\tif (nonMatchingVersions.size > 0) {\n\t\tconst message = [\n\t\t\t`${format('[tldraw]', ['bold', 'bgRed', 'textWhite'])} ${format('You have multiple versions of tldraw libraries installed. This can lead to bugs and unexpected behavior.', ['textRed', 'bold'])}`,\n\t\t\t'',\n\t\t\t`The latest version you have installed is ${format(`v${latestVersion}`, ['bold', 'textBlue'])}. The following libraries are on the latest version:`,\n\t\t\t...Array.from(matchingVersions, (name) => ` \u2022 \u2705 ${format(name, ['bold'])}`),\n\t\t\t'',\n\t\t\t`The following libraries are not on the latest version, or have multiple versions installed:`,\n\t\t\t...Array.from(nonMatchingVersions, ([name, versions]) => {\n\t\t\t\tconst sortedVersions = Array.from(versions)\n\t\t\t\t\t.sort(compareVersions)\n\t\t\t\t\t.map((v) => format(`v${v}`, v === latestVersion ? ['textGreen'] : ['textRed']))\n\t\t\t\treturn ` \u2022 \u274C ${format(name, ['bold'])} (${sortedVersions.join(', ')})`\n\t\t\t}),\n\t\t]\n\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(message.join('\\n'))\n\t\tinfo.didWarn = true\n\t\treturn\n\t}\n\n\t// at this point, we know that everything has the same version. there may still be duplicates though!\n\tconst potentialDuplicates = new Map<string, { version: string; modules: string[] }>()\n\tfor (const lib of sorted) {\n\t\tentry(potentialDuplicates, lib.name, { version: lib.version, modules: [] }).modules.push(\n\t\t\tlib.modules\n\t\t)\n\t}\n\n\tconst duplicates = new Map<string, { version: string; modules: string[] }>()\n\tfor (const [name, lib] of potentialDuplicates) {\n\t\tif (lib.modules.length > 1) duplicates.set(name, lib)\n\t}\n\n\tif (duplicates.size > 0) {\n\t\tconst message = [\n\t\t\t`${format('[tldraw]', ['bold', 'bgRed', 'textWhite'])} ${format('You have multiple instances of some tldraw libraries active. This can lead to bugs and unexpected behavior. ', ['textRed', 'bold'])}`,\n\t\t\t'',\n\t\t\t'This usually means that your bundler is misconfigured, and is importing the same library multiple times - usually once as an ES Module, and once as a CommonJS module.',\n\t\t\t'',\n\t\t\t'The following libraries have been imported multiple times:',\n\t\t\t...Array.from(duplicates, ([name, lib]) => {\n\t\t\t\tconst modules = lib.modules\n\t\t\t\t\t.map((m, i) => (m === 'esm' ? ` ${i + 1}. ES Modules` : ` ${i + 1}. CommonJS`))\n\t\t\t\t\t.join('\\n')\n\t\t\t\treturn ` \u2022 \u274C ${format(name, ['bold'])} v${lib.version}: \\n${modules}`\n\t\t\t}),\n\t\t\t'',\n\t\t\t'You should configure your bundler to only import one version of each library.',\n\t\t]\n\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(message.join('\\n'))\n\t\tinfo.didWarn = true\n\t\treturn\n\t}\n}\n\nfunction compareVersions(a: string, b: string) {\n\tconst aMatch = a.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(\\w+))?$/)\n\tconst bMatch = b.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(\\w+))?$/)\n\n\tif (!aMatch || !bMatch) return a.localeCompare(b)\n\tif (aMatch[1] !== bMatch[1]) return Number(aMatch[1]) - Number(bMatch[1])\n\tif (aMatch[2] !== bMatch[2]) return Number(aMatch[2]) - Number(bMatch[2])\n\tif (aMatch[3] !== bMatch[3]) return Number(aMatch[3]) - Number(bMatch[3])\n\tif (aMatch[4] && bMatch[4]) return aMatch[4].localeCompare(bMatch[4])\n\tif (aMatch[4]) return 1\n\tif (bMatch[4]) return -1\n\treturn 0\n}\n\nconst formats = {\n\tbold: '1',\n\ttextBlue: '94',\n\ttextRed: '31',\n\ttextGreen: '32',\n\tbgRed: '41',\n\ttextWhite: '97',\n} as const\nfunction format(value: string, formatters: (keyof typeof formats)[] = []) {\n\treturn `\\x1B[${formatters.map((f) => formats[f]).join(';')}m${value}\\x1B[m`\n}\n\nfunction isNextjsDev(): boolean {\n\ttry {\n\t\treturn process.env.NODE_ENV === 'development' && '__NEXT_DATA__' in globalThis\n\t} catch {\n\t\treturn false\n\t}\n}\n\nfunction entry<K, V>(map: Map<K, V>, key: K, defaultValue: V): V {\n\tif (map.has(key)) {\n\t\treturn map.get(key)!\n\t}\n\tmap.set(key, defaultValue)\n\treturn defaultValue\n}\n"],
|
|
4
|
+
"sourcesContent": ["interface TldrawLibraryVersion {\n\tname: string\n\tversion: string\n\tmodules: string\n}\n\ninterface TldrawLibraryVersionInfo {\n\tversions: TldrawLibraryVersion[]\n\tdidWarn: boolean\n\tscheduledNotice: number | NodeJS.Timeout | null\n}\n\nconst TLDRAW_LIBRARY_VERSION_KEY = '__TLDRAW_LIBRARY_VERSIONS__' as const\n\n// eslint-disable-next-line @typescript-eslint/prefer-namespace-keyword, @typescript-eslint/no-namespace, no-shadow-restricted-names\ndeclare module globalThis {\n\texport const __TLDRAW_LIBRARY_VERSIONS__: TldrawLibraryVersionInfo\n}\n\nfunction getLibraryVersions(): TldrawLibraryVersionInfo {\n\tif (globalThis[TLDRAW_LIBRARY_VERSION_KEY]) {\n\t\treturn globalThis[TLDRAW_LIBRARY_VERSION_KEY]\n\t}\n\n\tconst info: TldrawLibraryVersionInfo = {\n\t\tversions: [],\n\t\tdidWarn: false,\n\t\tscheduledNotice: null,\n\t}\n\n\tObject.defineProperty(globalThis, TLDRAW_LIBRARY_VERSION_KEY, {\n\t\tvalue: info,\n\t\twritable: false,\n\t\tconfigurable: false,\n\t\tenumerable: false,\n\t})\n\n\treturn info\n}\n\n/**\n * Clears all registered library versions and resets warning state.\n * This function is intended for testing purposes only to reset the global version tracking state.\n * @returns void\n * @example\n * ```ts\n * // In a test setup\n * beforeEach(() => {\n * clearRegisteredVersionsForTests()\n * })\n *\n * // Now version tracking starts fresh for each test\n * registerTldrawLibraryVersion('@tldraw/editor', '2.0.0', 'esm')\n * ```\n * @internal\n */\nexport function clearRegisteredVersionsForTests() {\n\tconst info = getLibraryVersions()\n\tinfo.versions = []\n\tinfo.didWarn = false\n\tif (info.scheduledNotice) {\n\t\tclearTimeout(info.scheduledNotice)\n\t\tinfo.scheduledNotice = null\n\t}\n}\n\n/**\n * Registers a tldraw library version for conflict detection.\n * This function tracks different tldraw library versions to warn about potential conflicts\n * when multiple versions are loaded simultaneously.\n * @param name - The name of the tldraw library package (e.g., '\\@tldraw/editor').\n * @param version - The semantic version string (e.g., '2.0.0').\n * @param modules - The module system being used ('esm' or 'cjs').\n * @returns void\n * @example\n * ```ts\n * // Register a library version during package initialization\n * registerTldrawLibraryVersion('@tldraw/editor', '2.0.0', 'esm')\n * registerTldrawLibraryVersion('@tldraw/tldraw', '2.0.0', 'esm')\n *\n * // If conflicting versions are detected, warnings will be logged:\n * registerTldrawLibraryVersion('@tldraw/editor', '1.9.0', 'cjs')\n * // Console warning about version mismatch will appear\n * ```\n * @internal\n */\nexport function registerTldrawLibraryVersion(name?: string, version?: string, modules?: string) {\n\tif (!name || !version || !modules) {\n\t\tif ((globalThis as any).TLDRAW_LIBRARY_IS_BUILD) {\n\t\t\tthrow new Error('Missing name/version/module system in built version of tldraw library')\n\t\t}\n\t\treturn\n\t}\n\n\tconst info = getLibraryVersions()\n\n\t// In Next.js dev mode, Fast Refresh re-executes module-level code which causes\n\t// the same library to register multiple times, producing a false positive warning.\n\t// We skip exact duplicates only in Next.js dev to avoid hiding genuine issues.\n\tif (isNextjsDev()) {\n\t\tconst isDuplicate = info.versions.some(\n\t\t\t(v) => v.name === name && v.version === version && v.modules === modules\n\t\t)\n\t\tif (isDuplicate) return\n\t}\n\n\tinfo.versions.push({ name, version, modules })\n\n\tif (!info.scheduledNotice) {\n\t\ttry {\n\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\tinfo.scheduledNotice = setTimeout(() => {\n\t\t\t\tinfo.scheduledNotice = null\n\t\t\t\tcheckLibraryVersions(info)\n\t\t\t}, 100)\n\t\t} catch {\n\t\t\t// some environments (e.g. cloudflare workers) don't support setTimeout immediately, only in a handler.\n\t\t\t// in this case, we'll just check immediately.\n\t\t\tcheckLibraryVersions(info)\n\t\t}\n\t}\n}\n\nfunction checkLibraryVersions(info: TldrawLibraryVersionInfo) {\n\tif (!info.versions.length) return\n\tif (info.didWarn) return\n\n\tconst sorted = info.versions.sort((a, b) => compareVersions(a.version, b.version))\n\tconst latestVersion = sorted[sorted.length - 1].version\n\n\tconst matchingVersions = new Set<string>()\n\tconst nonMatchingVersions = new Map<string, Set<string>>()\n\tfor (const lib of sorted) {\n\t\tif (nonMatchingVersions.has(lib.name)) {\n\t\t\tmatchingVersions.delete(lib.name)\n\t\t\tentry(nonMatchingVersions, lib.name, new Set()).add(lib.version)\n\t\t\tcontinue\n\t\t}\n\n\t\tif (lib.version === latestVersion) {\n\t\t\tmatchingVersions.add(lib.name)\n\t\t} else {\n\t\t\tmatchingVersions.delete(lib.name)\n\t\t\tentry(nonMatchingVersions, lib.name, new Set()).add(lib.version)\n\t\t}\n\t}\n\n\tif (nonMatchingVersions.size > 0) {\n\t\tconst message = [\n\t\t\t`${format('[tldraw]', ['bold', 'bgRed', 'textWhite'])} ${format('You have multiple versions of tldraw libraries installed. This can lead to bugs and unexpected behavior.', ['textRed', 'bold'])}`,\n\t\t\t'',\n\t\t\t`The latest version you have installed is ${format(`v${latestVersion}`, ['bold', 'textBlue'])}. The following libraries are on the latest version:`,\n\t\t\t...Array.from(matchingVersions, (name) => ` \u2022 \u2705 ${format(name, ['bold'])}`),\n\t\t\t'',\n\t\t\t`The following libraries are not on the latest version, or have multiple versions installed:`,\n\t\t\t...Array.from(nonMatchingVersions, ([name, versions]) => {\n\t\t\t\tconst sortedVersions = Array.from(versions)\n\t\t\t\t\t.sort(compareVersions)\n\t\t\t\t\t.map((v) => format(`v${v}`, v === latestVersion ? ['textGreen'] : ['textRed']))\n\t\t\t\treturn ` \u2022 \u274C ${format(name, ['bold'])} (${sortedVersions.join(', ')})`\n\t\t\t}),\n\t\t]\n\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(message.join('\\n'))\n\t\tinfo.didWarn = true\n\t\treturn\n\t}\n\n\t// at this point, we know that everything has the same version. there may still be duplicates though!\n\tconst potentialDuplicates = new Map<string, { version: string; modules: string[] }>()\n\tfor (const lib of sorted) {\n\t\tentry(potentialDuplicates, lib.name, { version: lib.version, modules: [] }).modules.push(\n\t\t\tlib.modules\n\t\t)\n\t}\n\n\tconst duplicates = new Map<string, { version: string; modules: string[] }>()\n\tfor (const [name, lib] of potentialDuplicates) {\n\t\tif (lib.modules.length > 1) duplicates.set(name, lib)\n\t}\n\n\tif (duplicates.size > 0) {\n\t\tconst message = [\n\t\t\t`${format('[tldraw]', ['bold', 'bgRed', 'textWhite'])} ${format('You have multiple instances of some tldraw libraries active. This can lead to bugs and unexpected behavior. ', ['textRed', 'bold'])}`,\n\t\t\t'',\n\t\t\t'This usually means that your bundler is misconfigured, and is importing the same library multiple times - usually once as an ES Module, and once as a CommonJS module.',\n\t\t\t'',\n\t\t\t'The following libraries have been imported multiple times:',\n\t\t\t...Array.from(duplicates, ([name, lib]) => {\n\t\t\t\tconst modules = lib.modules\n\t\t\t\t\t.map((m, i) => (m === 'esm' ? ` ${i + 1}. ES Modules` : ` ${i + 1}. CommonJS`))\n\t\t\t\t\t.join('\\n')\n\t\t\t\treturn ` \u2022 \u274C ${format(name, ['bold'])} v${lib.version}: \\n${modules}`\n\t\t\t}),\n\t\t\t'',\n\t\t\t'You should configure your bundler to only import one version of each library.',\n\t\t]\n\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(message.join('\\n'))\n\t\tinfo.didWarn = true\n\t\treturn\n\t}\n}\n\nfunction compareVersions(a: string, b: string) {\n\tconst aMatch = a.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(\\w+))?$/)\n\tconst bMatch = b.match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-(\\w+))?$/)\n\n\tif (!aMatch || !bMatch) return a.localeCompare(b)\n\tif (aMatch[1] !== bMatch[1]) return Number(aMatch[1]) - Number(bMatch[1])\n\tif (aMatch[2] !== bMatch[2]) return Number(aMatch[2]) - Number(bMatch[2])\n\tif (aMatch[3] !== bMatch[3]) return Number(aMatch[3]) - Number(bMatch[3])\n\tif (aMatch[4] && bMatch[4]) return aMatch[4].localeCompare(bMatch[4])\n\tif (aMatch[4]) return 1\n\tif (bMatch[4]) return -1\n\treturn 0\n}\n\nconst formats = {\n\tbold: '1',\n\ttextBlue: '94',\n\ttextRed: '31',\n\ttextGreen: '32',\n\tbgRed: '41',\n\ttextWhite: '97',\n} as const\nfunction format(value: string, formatters: (keyof typeof formats)[] = []) {\n\treturn `\\x1B[${formatters.map((f) => formats[f]).join(';')}m${value}\\x1B[m`\n}\n\nfunction isNextjsDev(): boolean {\n\ttry {\n\t\treturn process.env.NODE_ENV === 'development' && '__NEXT_DATA__' in globalThis\n\t} catch {\n\t\treturn false\n\t}\n}\n\nfunction entry<K, V>(map: Map<K, V>, key: K, defaultValue: V): V {\n\tif (map.has(key)) {\n\t\treturn map.get(key)!\n\t}\n\tmap.set(key, defaultValue)\n\treturn defaultValue\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tldraw/utils",
|
|
3
3
|
"description": "tldraw infinite canvas SDK (private utilities).",
|
|
4
|
-
"version": "4.6.0-next.
|
|
4
|
+
"version": "4.6.0-next.d15997ff5a4b",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tldraw Inc.",
|
|
7
7
|
"email": "hello@tldraw.com"
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"prepack": "yarn run -T tsx ../../internal/scripts/prepack.ts",
|
|
41
41
|
"postpack": "../../internal/scripts/postpack.sh",
|
|
42
42
|
"pack-tarball": "yarn pack",
|
|
43
|
-
"lint": "yarn run -T
|
|
43
|
+
"lint": "cd ../.. && yarn run -T oxlint packages/utils"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"jittered-fractional-indexing": "^1.0.0",
|
package/src/index.ts
CHANGED
|
@@ -94,6 +94,7 @@ export { stringEnum } from './lib/stringEnum'
|
|
|
94
94
|
export { FpsScheduler, fpsThrottle, throttleToNextFrame } from './lib/throttle'
|
|
95
95
|
export { Timers } from './lib/timers'
|
|
96
96
|
export {
|
|
97
|
+
type Awaitable,
|
|
97
98
|
type Expand,
|
|
98
99
|
type MakeUndefinedOptional,
|
|
99
100
|
type RecursivePartial,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
-
import { PerformanceTracker } from './PerformanceTracker'
|
|
3
2
|
import { PERFORMANCE_COLORS, PERFORMANCE_PREFIX_COLOR } from './perf'
|
|
3
|
+
import { PerformanceTracker } from './PerformanceTracker'
|
|
4
4
|
|
|
5
5
|
describe('PerformanceTracker', () => {
|
|
6
6
|
let tracker: PerformanceTracker
|
|
@@ -31,7 +31,7 @@ export class PerformanceTracker {
|
|
|
31
31
|
* Records animation frames to calculate frame rate.
|
|
32
32
|
* Called automatically during performance tracking.
|
|
33
33
|
*/
|
|
34
|
-
// eslint-disable-next-line
|
|
34
|
+
// eslint-disable-next-line tldraw/prefer-class-methods
|
|
35
35
|
recordFrame = () => {
|
|
36
36
|
this.frames++
|
|
37
37
|
if (!this.started) return
|
package/src/lib/bind.ts
CHANGED
|
@@ -95,7 +95,7 @@ export function bind<This extends object, T extends (...args: any[]) => any>(
|
|
|
95
95
|
*/
|
|
96
96
|
export function bind(
|
|
97
97
|
...args: // legacy stage-2 typescript decorators
|
|
98
|
-
|
|
98
|
+
| [_target: object, propertyKey: string, descriptor: PropertyDescriptor]
|
|
99
99
|
// TC39 decorators
|
|
100
100
|
| [originalMethod: (...args: any[]) => any, context: ClassMemberDecoratorContext]
|
|
101
101
|
): PropertyDescriptor | void {
|
package/src/lib/debounce.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Awaitable } from './types'
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Create a debounced version of a function that delays execution until after a specified wait time.
|
|
3
5
|
*
|
|
@@ -36,12 +38,13 @@
|
|
|
36
38
|
* @see source - https://gist.github.com/ca0v/73a31f57b397606c9813472f7493a940
|
|
37
39
|
*/
|
|
38
40
|
export function debounce<T extends unknown[], U>(
|
|
39
|
-
callback: (...args: T) =>
|
|
41
|
+
callback: (...args: T) => Awaitable<U>,
|
|
40
42
|
wait: number
|
|
41
43
|
) {
|
|
42
44
|
let state:
|
|
43
45
|
| undefined
|
|
44
46
|
| {
|
|
47
|
+
// eslint-disable-next-line no-restricted-globals
|
|
45
48
|
timeout: ReturnType<typeof setTimeout>
|
|
46
49
|
promise: Promise<U>
|
|
47
50
|
resolve(value: U | PromiseLike<U>): void
|
package/src/lib/network.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @internal
|
|
8
8
|
*/
|
|
9
9
|
export async function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
|
|
10
|
-
// eslint-disable-next-line no-restricted-properties
|
|
10
|
+
// eslint-disable-next-line tldraw/no-restricted-properties
|
|
11
11
|
return window.fetch(input, {
|
|
12
12
|
// We want to make sure that the referrer is not sent to other domains.
|
|
13
13
|
referrerPolicy: 'strict-origin-when-cross-origin',
|
|
@@ -25,7 +25,7 @@ export async function fetch(input: RequestInfo | URL, init?: RequestInit): Promi
|
|
|
25
25
|
* @internal
|
|
26
26
|
*/
|
|
27
27
|
export const Image = (width?: number, height?: number) => {
|
|
28
|
-
// eslint-disable-next-line no-restricted-properties
|
|
28
|
+
// eslint-disable-next-line tldraw/no-restricted-properties
|
|
29
29
|
const img = new window.Image(width, height)
|
|
30
30
|
img.referrerPolicy = 'strict-origin-when-cross-origin'
|
|
31
31
|
return img
|
package/src/lib/retry.ts
CHANGED
package/src/lib/storage.test.ts
CHANGED
package/src/lib/storage.tsx
CHANGED
package/src/lib/timers.ts
CHANGED
package/src/lib/types.ts
CHANGED
|
@@ -66,6 +66,14 @@ export type RecursivePartial<T> = {
|
|
|
66
66
|
*/
|
|
67
67
|
export type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* A value that may be returned synchronously or as a `Promise` / `PromiseLike`.
|
|
71
|
+
* Use with `await` or `Promise.resolve(...)` to normalize to a single `Promise`.
|
|
72
|
+
*
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
export type Awaitable<T> = T | PromiseLike<T>
|
|
76
|
+
|
|
69
77
|
/**
|
|
70
78
|
* Makes specified keys in a type required while keeping all other properties as-is.
|
|
71
79
|
* This is useful when you need to ensure certain optional properties are provided
|
package/src/lib/version.ts
CHANGED
|
@@ -12,7 +12,7 @@ interface TldrawLibraryVersionInfo {
|
|
|
12
12
|
|
|
13
13
|
const TLDRAW_LIBRARY_VERSION_KEY = '__TLDRAW_LIBRARY_VERSIONS__' as const
|
|
14
14
|
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/prefer-namespace-keyword, @typescript-eslint/no-namespace
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/prefer-namespace-keyword, @typescript-eslint/no-namespace, no-shadow-restricted-names
|
|
16
16
|
declare module globalThis {
|
|
17
17
|
export const __TLDRAW_LIBRARY_VERSIONS__: TldrawLibraryVersionInfo
|
|
18
18
|
}
|