390c45c7eb
This is an attempt at #1989. The big issue there is when `shapeUtils` change when you're relying on tldraw to provide you with the store instead of providing your own. Our `useTLStore` component had a bug where it would rely on effects & a ref to detect when its options had changed whilst still scheduling updates. Fresh opts would come in, but they'd be different from the ones in the ref, so we'd schedule an update, so the opts would come in again, but they'd still be different as we hadn't run effects yet, and we'd schedule an update again (and so on). This diff fixes that by storing the previous opts in state instead of a ref, so they're updating in lockstep with the store itself. this prevents the update loop. There are still situations where we can get into loops if the developer is passing in custom tools, shapeUtils, or components but not memoising them or defining them outside of react. As a DX improvement, we do some auto-memoisation of these values using shallow equality to help with this issue. ### Change Type - [x] `patch` — Bug fix ### Test Plan - [x] Unit Tests ### Release Notes - Fixes a bug that could cause crashes due to a re-render loop with HMR #1989
7.2 KiB
7.2 KiB
API Report File for "@tldraw/utils"
Do not edit this file. It is a report generated by API Extractor.
// @internal
export function annotateError(error: unknown, annotations: Partial<ErrorAnnotations>): void;
// @internal (undocumented)
export function areArraysShallowEqual<T>(arr1: readonly T[], arr2: readonly T[]): boolean;
// @internal (undocumented)
export function areObjectsShallowEqual<T extends Record<string, unknown>>(obj1: T, obj2: T): boolean;
// @internal (undocumented)
export const assert: (value: unknown, message?: string) => asserts value;
// @internal (undocumented)
export const assertExists: <T>(value: T, message?: string | undefined) => NonNullable<T>;
// @internal (undocumented)
export function compact<T>(arr: T[]): NonNullable<T>[];
// @public
export function debounce<T extends unknown[], U>(callback: (...args: T) => PromiseLike<U> | U, wait: number): {
(...args: T): Promise<U>;
cancel(): void;
};
// @public
export function dedupe<T>(input: T[], equals?: (a: any, b: any) => boolean): T[];
// @public
export function deepCopy<T = unknown>(obj: T): T;
// @public (undocumented)
export type ErrorResult<E> = {
readonly ok: false;
readonly error: E;
};
// @internal (undocumented)
export function exhaustiveSwitchError(value: never, property?: string): never;
// @public (undocumented)
export type Expand<T> = T extends infer O ? {
[K in keyof O]: O[K];
} : never;
// @public
export class FileHelpers {
// @internal (undocumented)
static base64ToFile(dataURL: string): Promise<ArrayBuffer>;
static fileToBase64(file: Blob): Promise<string>;
}
// @internal
export function filterEntries<Key extends string, Value>(object: {
[K in Key]: Value;
}, predicate: (key: Key, value: Value) => boolean): {
[K in Key]: Value;
};
// @internal (undocumented)
export function getErrorAnnotations(error: Error): ErrorAnnotations;
// @public
export function getFirstFromIterable<T = unknown>(set: Map<any, T> | Set<T>): T;
// @public
export function getHashForObject(obj: any): string;
// @public
export function getHashForString(string: string): string;
// @internal (undocumented)
export function getOwnProperty<K extends string, V>(obj: Partial<Record<K, V>>, key: K): undefined | V;
// @internal (undocumented)
export function getOwnProperty(obj: object, key: string): unknown;
// @internal (undocumented)
export function hasOwnProperty(obj: object, key: string): boolean;
// @public
export function isDefined<T>(value: T): value is typeof value extends undefined ? never : T;
// @public
export function isNonNull<T>(value: T): value is typeof value extends null ? never : T;
// @public
export function isNonNullish<T>(value: T): value is typeof value extends undefined ? never : typeof value extends null ? never : T;
// @public (undocumented)
export function isValidUrl(url: string): boolean;
// @public (undocumented)
export type JsonArray = JsonValue[];
// @public (undocumented)
export type JsonObject = {
[key: string]: JsonValue | undefined;
};
// @public (undocumented)
export type JsonPrimitive = boolean | null | number | string;
// @public (undocumented)
export type JsonValue = JsonArray | JsonObject | JsonPrimitive;
// @internal (undocumented)
export function last<T>(arr: readonly T[]): T | undefined;
// @public
export function lerp(a: number, b: number, t: number): number;
// @public (undocumented)
export function lns(str: string): string;
// @internal
export function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(object: {
readonly [K in Key]: ValueBefore;
}, mapper: (key: Key, value: ValueBefore) => ValueAfter): {
[K in Key]: ValueAfter;
};
// @public
export class MediaHelpers {
static getImageSizeFromSrc(dataURL: string): Promise<{
w: number;
h: number;
}>;
static getVideoSizeFromSrc(src: string): Promise<{
w: number;
h: number;
}>;
}
// @internal (undocumented)
export function minBy<T>(arr: readonly T[], fn: (item: T) => number): T | undefined;
// @public
export function modulate(value: number, rangeA: number[], rangeB: number[], clamp?: boolean): number;
// @internal
export function noop(): void;
// @internal
export function objectMapEntries<Key extends string, Value>(object: {
[K in Key]: Value;
}): Array<[Key, Value]>;
// @internal
export function objectMapFromEntries<Key extends string, Value>(entries: ReadonlyArray<readonly [Key, Value]>): {
[K in Key]: Value;
};
// @internal
export function objectMapKeys<Key extends string>(object: {
readonly [K in Key]: unknown;
}): Array<Key>;
// @internal
export function objectMapValues<Key extends string, Value>(object: {
[K in Key]: Value;
}): Array<Value>;
// @public (undocumented)
export type OkResult<T> = {
readonly ok: true;
readonly value: T;
};
// @internal
export function omitFromStackTrace<Args extends Array<unknown>, Return>(fn: (...args: Args) => Return): (...args: Args) => Return;
// @internal
export function partition<T>(arr: T[], predicate: (item: T) => boolean): [T[], T[]];
// @public (undocumented)
export class PngHelpers {
// (undocumented)
static findChunk(view: DataView, type: string): {
dataOffset: number;
size: number;
start: number;
};
// (undocumented)
static getChunkType(view: DataView, offset: number): string;
// (undocumented)
static isPng(view: DataView, offset: number): boolean;
// (undocumented)
static parsePhys(view: DataView, offset: number): {
ppux: number;
ppuy: number;
unit: number;
};
// (undocumented)
static readChunks(view: DataView, offset?: number): Record<string, {
dataOffset: number;
size: number;
start: number;
}>;
// (undocumented)
static setPhysChunk(view: DataView, dpr?: number, options?: BlobPropertyBag): Blob;
}
// @internal (undocumented)
export function promiseWithResolve<T>(): Promise<T> & {
resolve: (value: T) => void;
reject: (reason?: any) => void;
};
// @internal
export function rafThrottle(fn: () => void): () => void;
// @public (undocumented)
export type RecursivePartial<T> = {
[P in keyof T]?: RecursivePartial<T[P]>;
};
// @internal (undocumented)
type Required_2<T, K extends keyof T> = Expand<Omit<T, K> & _Required<Pick<T, K>>>;
export { Required_2 as Required }
// @public (undocumented)
export type Result<T, E> = ErrorResult<E> | OkResult<T>;
// @public (undocumented)
export const Result: {
ok<T>(value: T): OkResult<T>;
err<E>(error: E): ErrorResult<E>;
};
// @public
export function rng(seed?: string): () => number;
// @public
export function rotateArray<T>(arr: T[], offset: number): T[];
// @public (undocumented)
export function sortById<T extends {
id: any;
}>(a: T, b: T): -1 | 1;
// @public (undocumented)
const structuredClone_2: <T>(i: T) => T;
export { structuredClone_2 as structuredClone }
// @public
export function throttle<T extends (...args: any) => any>(func: T, limit: number): (...args: Parameters<T>) => ReturnType<T>;
// @internal
export function throttledRaf(fn: () => void): void;
// @internal (undocumented)
export function warnDeprecatedGetter(name: string): void;
// (No @packageDocumentation comment for this package)