@ibodr/utils 0.0.1
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/index.d.ts +3098 -0
- package/dist/index.mjs +2573 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +43 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3098 @@
|
|
|
1
|
+
export { default as isEqual } from 'lodash.isequal';
|
|
2
|
+
export { default as isEqualWith } from 'lodash.isequalwith';
|
|
3
|
+
export { default as throttle } from 'lodash.throttle';
|
|
4
|
+
export { default as uniq } from 'lodash.uniq';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Rotate the contents of an array by a specified offset.
|
|
8
|
+
*
|
|
9
|
+
* Creates a new array with elements shifted to the left by the specified number of positions.
|
|
10
|
+
* Both positive and negative offsets result in left shifts (elements move left, with elements
|
|
11
|
+
* from the front wrapping to the back).
|
|
12
|
+
*
|
|
13
|
+
* @param arr - The array to rotate
|
|
14
|
+
* @param offset - The number of positions to shift left (both positive and negative values shift left)
|
|
15
|
+
* @returns A new array with elements shifted left by the specified offset
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* rotateArray([1, 2, 3, 4], 1) // [2, 3, 4, 1]
|
|
20
|
+
* rotateArray([1, 2, 3, 4], -1) // [2, 3, 4, 1]
|
|
21
|
+
* rotateArray(['a', 'b', 'c'], 2) // ['c', 'a', 'b']
|
|
22
|
+
* ```
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
declare function rotateArray<T>(arr: T[], offset: number): T[];
|
|
26
|
+
/**
|
|
27
|
+
* Remove duplicate items from an array.
|
|
28
|
+
*
|
|
29
|
+
* Creates a new array with duplicate items removed. Uses strict equality by default,
|
|
30
|
+
* or a custom equality function if provided. Order of first occurrence is preserved.
|
|
31
|
+
*
|
|
32
|
+
* @param input - The array to deduplicate
|
|
33
|
+
* @param equals - Optional custom equality function to compare items (defaults to strict equality)
|
|
34
|
+
* @returns A new array with duplicate items removed
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* dedupe([1, 2, 2, 3, 1]) // [1, 2, 3]
|
|
39
|
+
* dedupe(['a', 'b', 'a', 'c']) // ['a', 'b', 'c']
|
|
40
|
+
*
|
|
41
|
+
* // With custom equality function
|
|
42
|
+
* const objects = [{id: 1}, {id: 2}, {id: 1}]
|
|
43
|
+
* dedupe(objects, (a, b) => a.id === b.id) // [{id: 1}, {id: 2}]
|
|
44
|
+
* ```
|
|
45
|
+
* @public
|
|
46
|
+
*/
|
|
47
|
+
declare function dedupe<T>(input: T[], equals?: (a: any, b: any) => boolean): T[];
|
|
48
|
+
/**
|
|
49
|
+
* Remove null and undefined values from an array.
|
|
50
|
+
*
|
|
51
|
+
* Creates a new array with all null and undefined values filtered out.
|
|
52
|
+
* The resulting array has a refined type that excludes null and undefined.
|
|
53
|
+
*
|
|
54
|
+
* @param arr - The array to compact
|
|
55
|
+
* @returns A new array with null and undefined values removed
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* compact([1, null, 2, undefined, 3]) // [1, 2, 3]
|
|
60
|
+
* compact(['a', null, 'b', undefined]) // ['a', 'b']
|
|
61
|
+
* ```
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
declare function compact<T>(arr: T[]): NonNullable<T>[];
|
|
65
|
+
/**
|
|
66
|
+
* Get the last element of an array.
|
|
67
|
+
*
|
|
68
|
+
* Returns the last element of an array, or undefined if the array is empty.
|
|
69
|
+
* Works with readonly arrays and preserves the element type.
|
|
70
|
+
*
|
|
71
|
+
* @param arr - The array to get the last element from
|
|
72
|
+
* @returns The last element of the array, or undefined if the array is empty
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* last([1, 2, 3]) // 3
|
|
77
|
+
* last(['a', 'b', 'c']) // 'c'
|
|
78
|
+
* last([]) // undefined
|
|
79
|
+
* ```
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
declare function last<T>(arr: readonly T[]): T | undefined;
|
|
83
|
+
/**
|
|
84
|
+
* Find the item in an array with the minimum value according to a function.
|
|
85
|
+
*
|
|
86
|
+
* Finds the array item that produces the smallest value when passed through
|
|
87
|
+
* the provided function. Returns undefined for empty arrays.
|
|
88
|
+
*
|
|
89
|
+
* @param arr - The array to search
|
|
90
|
+
* @param fn - Function to compute the comparison value for each item
|
|
91
|
+
* @returns The item with the minimum value, or undefined if the array is empty
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* const people = [{name: 'Alice', age: 30}, {name: 'Bob', age: 25}]
|
|
96
|
+
* minBy(people, p => p.age) // {name: 'Bob', age: 25}
|
|
97
|
+
*
|
|
98
|
+
* minBy([3, 1, 4, 1, 5], x => x) // 1
|
|
99
|
+
* minBy([], x => x) // undefined
|
|
100
|
+
* ```
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
declare function minBy<T>(arr: readonly T[], fn: (item: T) => number): T | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Find the item in an array with the maximum value according to a function.
|
|
106
|
+
*
|
|
107
|
+
* Finds the array item that produces the largest value when passed through
|
|
108
|
+
* the provided function. Returns undefined for empty arrays.
|
|
109
|
+
*
|
|
110
|
+
* @param arr - The array to search
|
|
111
|
+
* @param fn - Function to compute the comparison value for each item
|
|
112
|
+
* @returns The item with the maximum value, or undefined if the array is empty
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* const people = [{name: 'Alice', age: 30}, {name: 'Bob', age: 25}]
|
|
117
|
+
* maxBy(people, p => p.age) // {name: 'Alice', age: 30}
|
|
118
|
+
*
|
|
119
|
+
* maxBy([3, 1, 4, 1, 5], x => x) // 5
|
|
120
|
+
* maxBy([], x => x) // undefined
|
|
121
|
+
* ```
|
|
122
|
+
* @internal
|
|
123
|
+
*/
|
|
124
|
+
declare function maxBy<T>(arr: readonly T[], fn: (item: T) => number): T | undefined;
|
|
125
|
+
/**
|
|
126
|
+
* Split an array into two arrays based on a predicate function.
|
|
127
|
+
*
|
|
128
|
+
* Partitions an array into two arrays: one containing items that satisfy
|
|
129
|
+
* the predicate, and another containing items that do not. The original array order is preserved.
|
|
130
|
+
*
|
|
131
|
+
* @param arr - The array to partition
|
|
132
|
+
* @param predicate - The predicate function to test each item
|
|
133
|
+
* @returns A tuple of two arrays: [satisfying items, non-satisfying items]
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* const [evens, odds] = partition([1, 2, 3, 4, 5], x => x % 2 === 0)
|
|
138
|
+
* // evens: [2, 4], odds: [1, 3, 5]
|
|
139
|
+
*
|
|
140
|
+
* const [adults, minors] = partition(
|
|
141
|
+
* [{name: 'Alice', age: 30}, {name: 'Bob', age: 17}],
|
|
142
|
+
* person => person.age >= 18
|
|
143
|
+
* )
|
|
144
|
+
* // adults: [{name: 'Alice', age: 30}], minors: [{name: 'Bob', age: 17}]
|
|
145
|
+
* ```
|
|
146
|
+
* @internal
|
|
147
|
+
*/
|
|
148
|
+
declare function partition<T>(arr: T[], predicate: (item: T) => boolean): [T[], T[]];
|
|
149
|
+
/**
|
|
150
|
+
* Check if two arrays are shallow equal.
|
|
151
|
+
*
|
|
152
|
+
* Compares two arrays for shallow equality by checking if they have the same length
|
|
153
|
+
* and the same elements at each index using Object.is comparison. Returns true if arrays are
|
|
154
|
+
* the same reference, have different lengths, or any elements differ.
|
|
155
|
+
*
|
|
156
|
+
* @param arr1 - First array to compare
|
|
157
|
+
* @param arr2 - Second array to compare
|
|
158
|
+
* @returns True if arrays are shallow equal, false otherwise
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* areArraysShallowEqual([1, 2, 3], [1, 2, 3]) // true
|
|
163
|
+
* areArraysShallowEqual([1, 2, 3], [1, 2, 4]) // false
|
|
164
|
+
* areArraysShallowEqual(['a', 'b'], ['a', 'b']) // true
|
|
165
|
+
* areArraysShallowEqual([1, 2], [1, 2, 3]) // false
|
|
166
|
+
*
|
|
167
|
+
* const obj = {x: 1}
|
|
168
|
+
* areArraysShallowEqual([obj], [obj]) // true (same reference)
|
|
169
|
+
* areArraysShallowEqual([{x: 1}], [{x: 1}]) // false (different objects)
|
|
170
|
+
* ```
|
|
171
|
+
* @internal
|
|
172
|
+
*/
|
|
173
|
+
declare function areArraysShallowEqual<T>(arr1: readonly T[], arr2: readonly T[]): boolean;
|
|
174
|
+
/**
|
|
175
|
+
* Merge custom entries with defaults, replacing defaults that have matching keys.
|
|
176
|
+
*
|
|
177
|
+
* Combines two arrays by keeping all custom entries and only the default entries
|
|
178
|
+
* that don't have a matching key in the custom entries. Custom entries always override defaults.
|
|
179
|
+
* The result contains remaining defaults first, followed by all custom entries.
|
|
180
|
+
*
|
|
181
|
+
* @param key - The property name to use as the unique identifier
|
|
182
|
+
* @param customEntries - Array of custom entries that will override defaults
|
|
183
|
+
* @param defaults - Array of default entries
|
|
184
|
+
* @returns A new array with defaults filtered out where custom entries exist, plus all custom entries
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```ts
|
|
188
|
+
* const defaults = [{type: 'text', value: 'default'}, {type: 'number', value: 0}]
|
|
189
|
+
* const custom = [{type: 'text', value: 'custom'}]
|
|
190
|
+
*
|
|
191
|
+
* mergeArraysAndReplaceDefaults('type', custom, defaults)
|
|
192
|
+
* // Result: [{type: 'number', value: 0}, {type: 'text', value: 'custom'}]
|
|
193
|
+
*
|
|
194
|
+
* const tools = [{id: 'select', name: 'Select'}, {id: 'draw', name: 'Draw'}]
|
|
195
|
+
* const customTools = [{id: 'select', name: 'Custom Select'}]
|
|
196
|
+
*
|
|
197
|
+
* mergeArraysAndReplaceDefaults('id', customTools, tools)
|
|
198
|
+
* // Result: [{id: 'draw', name: 'Draw'}, {id: 'select', name: 'Custom Select'}]
|
|
199
|
+
* ```
|
|
200
|
+
* @internal
|
|
201
|
+
*/
|
|
202
|
+
declare function mergeArraysAndReplaceDefaults<const Key extends string, T extends {
|
|
203
|
+
[K in Key]: string;
|
|
204
|
+
}>(key: Key, customEntries: readonly T[], defaults: readonly T[]): T[];
|
|
205
|
+
|
|
206
|
+
/*!
|
|
207
|
+
* MIT License: https://github.com/NoHomey/bind-decorator/blob/master/License
|
|
208
|
+
* Copyright (c) 2016 Ivo Stratev
|
|
209
|
+
*/
|
|
210
|
+
/**
|
|
211
|
+
* Decorator that binds a method to its class instance (legacy stage-2 TypeScript decorators).
|
|
212
|
+
* When applied to a class method, ensures `this` always refers to the class instance,
|
|
213
|
+
* even when the method is called as a callback or event handler.
|
|
214
|
+
*
|
|
215
|
+
* @param target - The prototype of the class being decorated
|
|
216
|
+
* @param propertyKey - The name of the method being decorated
|
|
217
|
+
* @param descriptor - The property descriptor for the method being decorated
|
|
218
|
+
* @returns The modified property descriptor with bound method access
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* class MyClass {
|
|
222
|
+
* name = 'example';
|
|
223
|
+
*
|
|
224
|
+
* @bind
|
|
225
|
+
* getName() {
|
|
226
|
+
* return this.name;
|
|
227
|
+
* }
|
|
228
|
+
* }
|
|
229
|
+
*
|
|
230
|
+
* const instance = new MyClass();
|
|
231
|
+
* const callback = instance.getName;
|
|
232
|
+
* console.log(callback()); // 'example' (this is properly bound)
|
|
233
|
+
* ```
|
|
234
|
+
* @public
|
|
235
|
+
*/
|
|
236
|
+
declare function bind<T extends (...args: any[]) => any>(target: object, propertyKey: string, descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T>;
|
|
237
|
+
/**
|
|
238
|
+
* Decorator that binds a method to its class instance (TC39 decorators standard).
|
|
239
|
+
* When applied to a class method, ensures `this` always refers to the class instance,
|
|
240
|
+
* even when the method is called as a callback or event handler.
|
|
241
|
+
*
|
|
242
|
+
* @param originalMethod - The original method being decorated
|
|
243
|
+
* @param context - The decorator context containing metadata about the method
|
|
244
|
+
* @example
|
|
245
|
+
* ```typescript
|
|
246
|
+
* class EventHandler {
|
|
247
|
+
* message = 'Hello World';
|
|
248
|
+
*
|
|
249
|
+
* @bind
|
|
250
|
+
* handleClick() {
|
|
251
|
+
* console.log(this.message);
|
|
252
|
+
* }
|
|
253
|
+
* }
|
|
254
|
+
*
|
|
255
|
+
* const handler = new EventHandler();
|
|
256
|
+
* document.addEventListener('click', handler.handleClick); // 'this' is properly bound
|
|
257
|
+
* ```
|
|
258
|
+
* @public
|
|
259
|
+
*/
|
|
260
|
+
declare function bind<This extends object, T extends (...args: any[]) => any>(originalMethod: T, context: ClassMethodDecoratorContext<This, T>): void;
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* A lightweight cache implementation using WeakMap for storing key-value pairs.
|
|
264
|
+
*
|
|
265
|
+
* A micro cache that stores computed values associated with object keys.
|
|
266
|
+
* Uses WeakMap internally, which means keys can be garbage collected when no other
|
|
267
|
+
* references exist, and only object keys are supported. Provides lazy computation
|
|
268
|
+
* with memoization.
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* ```ts
|
|
272
|
+
* const cache = new WeakCache<User, string>()
|
|
273
|
+
* const user = { id: 1, name: 'Alice' }
|
|
274
|
+
*
|
|
275
|
+
* // Get cached value, computing it if not present
|
|
276
|
+
* const displayName = cache.get(user, (u) => `${u.name} (#${u.id})`)
|
|
277
|
+
* // Returns 'Alice (#1)'
|
|
278
|
+
*
|
|
279
|
+
* // Subsequent calls return cached value
|
|
280
|
+
* const sameName = cache.get(user, (u) => `${u.name} (#${u.id})`)
|
|
281
|
+
* // Returns 'Alice (#1)' without recomputing
|
|
282
|
+
* ```
|
|
283
|
+
* @public
|
|
284
|
+
*/
|
|
285
|
+
declare class WeakCache<K extends object, V> {
|
|
286
|
+
/**
|
|
287
|
+
* The internal WeakMap storage for cached key-value pairs.
|
|
288
|
+
*
|
|
289
|
+
* @public
|
|
290
|
+
*/
|
|
291
|
+
items: WeakMap<K, V>;
|
|
292
|
+
/**
|
|
293
|
+
* Get the cached value for a given key, computing it if not already cached.
|
|
294
|
+
*
|
|
295
|
+
* Retrieves the cached value associated with the given key. If no cached
|
|
296
|
+
* value exists, calls the provided callback function to compute the value, stores it
|
|
297
|
+
* in the cache, and returns it. Subsequent calls with the same key will return the
|
|
298
|
+
* cached value without recomputation.
|
|
299
|
+
*
|
|
300
|
+
* @param item - The object key to retrieve the cached value for
|
|
301
|
+
* @param cb - Callback function that computes the value when not already cached
|
|
302
|
+
* @returns The cached value if it exists, otherwise the newly computed value from the callback
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```ts
|
|
306
|
+
* const cache = new WeakCache<HTMLElement, DOMRect>()
|
|
307
|
+
* const element = document.getElementById('my-element')!
|
|
308
|
+
*
|
|
309
|
+
* // First call computes and caches the bounding rect
|
|
310
|
+
* const rect1 = cache.get(element, (el) => el.getBoundingClientRect())
|
|
311
|
+
*
|
|
312
|
+
* // Second call returns cached value
|
|
313
|
+
* const rect2 = cache.get(element, (el) => el.getBoundingClientRect())
|
|
314
|
+
* // rect1 and rect2 are the same object
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
get<P extends K>(item: P, cb: (item: P) => V): NonNullable<V>;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Represents a successful result containing a value.
|
|
322
|
+
*
|
|
323
|
+
* Interface for the success case of a Result type, containing the computed value.
|
|
324
|
+
* Used in conjunction with ErrorResult to create a discriminated union for error handling.
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```ts
|
|
328
|
+
* const success: OkResult<string> = { ok: true, value: 'Hello World' }
|
|
329
|
+
* if (success.ok) {
|
|
330
|
+
* console.log(success.value) // 'Hello World'
|
|
331
|
+
* }
|
|
332
|
+
* ```
|
|
333
|
+
* @public
|
|
334
|
+
*/
|
|
335
|
+
interface OkResult<T> {
|
|
336
|
+
readonly ok: true;
|
|
337
|
+
readonly value: T;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Represents a failed result containing an error.
|
|
341
|
+
*
|
|
342
|
+
* Interface for the error case of a Result type, containing the error information.
|
|
343
|
+
* Used in conjunction with OkResult to create a discriminated union for error handling.
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```ts
|
|
347
|
+
* const failure: ErrorResult<string> = { ok: false, error: 'Something went wrong' }
|
|
348
|
+
* if (!failure.ok) {
|
|
349
|
+
* console.error(failure.error) // 'Something went wrong'
|
|
350
|
+
* }
|
|
351
|
+
* ```
|
|
352
|
+
* @public
|
|
353
|
+
*/
|
|
354
|
+
interface ErrorResult<E> {
|
|
355
|
+
readonly ok: false;
|
|
356
|
+
readonly error: E;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* A discriminated union type for handling success and error cases.
|
|
360
|
+
*
|
|
361
|
+
* Represents either a successful result with a value or a failed result with an error.
|
|
362
|
+
* This pattern provides type-safe error handling without throwing exceptions. The 'ok' property
|
|
363
|
+
* serves as the discriminant for type narrowing.
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* ```ts
|
|
367
|
+
* function divide(a: number, b: number): Result<number, string> {
|
|
368
|
+
* if (b === 0) {
|
|
369
|
+
* return Result.err('Division by zero')
|
|
370
|
+
* }
|
|
371
|
+
* return Result.ok(a / b)
|
|
372
|
+
* }
|
|
373
|
+
*
|
|
374
|
+
* const result = divide(10, 2)
|
|
375
|
+
* if (result.ok) {
|
|
376
|
+
* console.log(`Result: ${result.value}`) // Result: 5
|
|
377
|
+
* } else {
|
|
378
|
+
* console.error(`Error: ${result.error}`)
|
|
379
|
+
* }
|
|
380
|
+
* ```
|
|
381
|
+
* @public
|
|
382
|
+
*/
|
|
383
|
+
type Result<T, E> = OkResult<T> | ErrorResult<E>;
|
|
384
|
+
/**
|
|
385
|
+
* Utility object for creating Result instances.
|
|
386
|
+
*
|
|
387
|
+
* Provides factory methods for creating OkResult and ErrorResult instances.
|
|
388
|
+
* This is the preferred way to construct Result values for consistent structure.
|
|
389
|
+
*
|
|
390
|
+
* @example
|
|
391
|
+
* ```ts
|
|
392
|
+
* // Create success result
|
|
393
|
+
* const success = Result.ok(42)
|
|
394
|
+
* // success: OkResult<number> = { ok: true, value: 42 }
|
|
395
|
+
*
|
|
396
|
+
* // Create error result
|
|
397
|
+
* const failure = Result.err('Invalid input')
|
|
398
|
+
* // failure: ErrorResult<string> = { ok: false, error: 'Invalid input' }
|
|
399
|
+
* ```
|
|
400
|
+
* @public
|
|
401
|
+
*/
|
|
402
|
+
declare const Result: {
|
|
403
|
+
/**
|
|
404
|
+
* Create a successful result containing a value.
|
|
405
|
+
*
|
|
406
|
+
* @param value - The success value to wrap
|
|
407
|
+
* @returns An OkResult containing the value
|
|
408
|
+
*/
|
|
409
|
+
ok<T>(value: T): OkResult<T>;
|
|
410
|
+
/**
|
|
411
|
+
* Create a failed result containing an error.
|
|
412
|
+
*
|
|
413
|
+
* @param error - The error value to wrap
|
|
414
|
+
* @returns An ErrorResult containing the error
|
|
415
|
+
*/
|
|
416
|
+
err<E>(error: E): ErrorResult<E>;
|
|
417
|
+
/**
|
|
418
|
+
* Create a successful result containing an array of values.
|
|
419
|
+
*
|
|
420
|
+
* If any of the results are errors, the returned result will be an error containing the first error.
|
|
421
|
+
*
|
|
422
|
+
* @param results - The array of results to wrap
|
|
423
|
+
* @returns An OkResult containing the array of values
|
|
424
|
+
*/
|
|
425
|
+
all<T>(results: Result<T, any>[]): Result<T[], any>;
|
|
426
|
+
};
|
|
427
|
+
/**
|
|
428
|
+
* Throws an error for unhandled switch cases in exhaustive switch statements.
|
|
429
|
+
*
|
|
430
|
+
* Utility function to ensure exhaustive handling of discriminated unions in switch
|
|
431
|
+
* statements. When called, it indicates a programming error where a case was not handled.
|
|
432
|
+
* The TypeScript 'never' type ensures this function is only reachable if all cases aren't covered.
|
|
433
|
+
*
|
|
434
|
+
* @param value - The unhandled value (typed as 'never' for exhaustiveness checking)
|
|
435
|
+
* @param property - Optional property name to extract from the value for better error messages
|
|
436
|
+
* @returns Never returns (always throws)
|
|
437
|
+
*
|
|
438
|
+
* @example
|
|
439
|
+
* ```ts
|
|
440
|
+
* type Shape = 'circle' | 'square' | 'triangle'
|
|
441
|
+
*
|
|
442
|
+
* function getArea(shape: Shape): number {
|
|
443
|
+
* switch (shape) {
|
|
444
|
+
* case 'circle': return Math.PI * 5 * 5
|
|
445
|
+
* case 'square': return 10 * 10
|
|
446
|
+
* case 'triangle': return 0.5 * 10 * 8
|
|
447
|
+
* default: return exhaustiveSwitchError(shape)
|
|
448
|
+
* }
|
|
449
|
+
* }
|
|
450
|
+
* ```
|
|
451
|
+
* @internal
|
|
452
|
+
*/
|
|
453
|
+
declare function exhaustiveSwitchError(value: never, property?: string): never;
|
|
454
|
+
/**
|
|
455
|
+
* Assert that a value is truthy, throwing an error if it's not.
|
|
456
|
+
*
|
|
457
|
+
* TypeScript assertion function that throws an error if the provided value is falsy.
|
|
458
|
+
* After this function executes successfully, TypeScript narrows the type to exclude falsy values.
|
|
459
|
+
* Stack trace is omitted from the error for cleaner debugging.
|
|
460
|
+
*
|
|
461
|
+
* @param value - The value to assert as truthy
|
|
462
|
+
* @param message - Optional custom error message
|
|
463
|
+
*
|
|
464
|
+
* @example
|
|
465
|
+
* ```ts
|
|
466
|
+
* const user = getUser() // User | null
|
|
467
|
+
* assert(user, 'User must be logged in')
|
|
468
|
+
* // TypeScript now knows user is non-null
|
|
469
|
+
* console.log(user.name) // Safe to access properties
|
|
470
|
+
* ```
|
|
471
|
+
* @internal
|
|
472
|
+
*/
|
|
473
|
+
declare const assert: (value: unknown, message?: string) => asserts value;
|
|
474
|
+
/**
|
|
475
|
+
* Assert that a value is not null or undefined.
|
|
476
|
+
*
|
|
477
|
+
* Throws an error if the value is null or undefined, otherwise returns the value
|
|
478
|
+
* with a refined type that excludes null and undefined. Stack trace is omitted for cleaner debugging.
|
|
479
|
+
*
|
|
480
|
+
* @param value - The value to check for null/undefined
|
|
481
|
+
* @param message - Optional custom error message
|
|
482
|
+
* @returns The value with null and undefined excluded from the type
|
|
483
|
+
*
|
|
484
|
+
* @example
|
|
485
|
+
* ```ts
|
|
486
|
+
* const element = document.getElementById('my-id') // HTMLElement | null
|
|
487
|
+
* const safeElement = assertExists(element, 'Element not found')
|
|
488
|
+
* // TypeScript now knows safeElement is HTMLElement (not null)
|
|
489
|
+
* safeElement.addEventListener('click', handler) // Safe to call methods
|
|
490
|
+
* ```
|
|
491
|
+
* @internal
|
|
492
|
+
*/
|
|
493
|
+
declare const assertExists: <T>(value: T, message?: string | undefined) => NonNullable<T>;
|
|
494
|
+
/**
|
|
495
|
+
* Create a Promise with externally accessible resolve and reject functions.
|
|
496
|
+
*
|
|
497
|
+
* Creates a Promise along with its resolve and reject functions exposed as
|
|
498
|
+
* properties on the returned object. This allows external code to control when the
|
|
499
|
+
* Promise resolves or rejects, useful for coordination between async operations.
|
|
500
|
+
*
|
|
501
|
+
* @returns A Promise object with additional resolve and reject methods
|
|
502
|
+
*
|
|
503
|
+
* @example
|
|
504
|
+
* ```ts
|
|
505
|
+
* const deferred = promiseWithResolve<string>()
|
|
506
|
+
*
|
|
507
|
+
* // Set up the promise consumer
|
|
508
|
+
* deferred.then(value => console.log(`Resolved: ${value}`))
|
|
509
|
+
* deferred.catch(error => console.error(`Rejected: ${error}`))
|
|
510
|
+
*
|
|
511
|
+
* // Later, resolve from external code
|
|
512
|
+
* setTimeout(() => {
|
|
513
|
+
* deferred.resolve('Hello World')
|
|
514
|
+
* }, 1000)
|
|
515
|
+
* ```
|
|
516
|
+
* @internal
|
|
517
|
+
*/
|
|
518
|
+
declare function promiseWithResolve<T>(): Promise<T> & {
|
|
519
|
+
resolve(value: T): void;
|
|
520
|
+
reject(reason?: any): void;
|
|
521
|
+
};
|
|
522
|
+
/**
|
|
523
|
+
* Create a Promise that resolves after a specified delay.
|
|
524
|
+
*
|
|
525
|
+
* Utility function for introducing delays in async code. Returns a Promise
|
|
526
|
+
* that resolves with undefined after the specified number of milliseconds. Useful for
|
|
527
|
+
* implementing timeouts, rate limiting, or adding delays in testing scenarios.
|
|
528
|
+
*
|
|
529
|
+
* @param ms - The delay in milliseconds
|
|
530
|
+
* @returns A Promise that resolves after the specified delay
|
|
531
|
+
*
|
|
532
|
+
* @example
|
|
533
|
+
* ```ts
|
|
534
|
+
* async function delayedOperation() {
|
|
535
|
+
* console.log('Starting...')
|
|
536
|
+
* await sleep(1000) // Wait 1 second
|
|
537
|
+
* console.log('Done!')
|
|
538
|
+
* }
|
|
539
|
+
*
|
|
540
|
+
* // Can also be used with .then()
|
|
541
|
+
* sleep(500).then(() => {
|
|
542
|
+
* console.log('Half second has passed')
|
|
543
|
+
* })
|
|
544
|
+
* ```
|
|
545
|
+
* @internal
|
|
546
|
+
*/
|
|
547
|
+
declare function sleep(ms: number): Promise<void>;
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Makes all properties in a type and all nested properties optional recursively.
|
|
551
|
+
* This is useful for creating partial update objects where you only want to specify
|
|
552
|
+
* some deeply nested properties while leaving others unchanged.
|
|
553
|
+
*
|
|
554
|
+
* @example
|
|
555
|
+
* ```ts
|
|
556
|
+
* interface User {
|
|
557
|
+
* name: string
|
|
558
|
+
* settings: {
|
|
559
|
+
* theme: string
|
|
560
|
+
* notifications: {
|
|
561
|
+
* email: boolean
|
|
562
|
+
* push: boolean
|
|
563
|
+
* }
|
|
564
|
+
* }
|
|
565
|
+
* }
|
|
566
|
+
*
|
|
567
|
+
* type PartialUser = RecursivePartial<User>
|
|
568
|
+
* // Result: {
|
|
569
|
+
* // name?: string
|
|
570
|
+
* // settings?: {
|
|
571
|
+
* // theme?: string
|
|
572
|
+
* // notifications?: {
|
|
573
|
+
* // email?: boolean
|
|
574
|
+
* // push?: boolean
|
|
575
|
+
* // }
|
|
576
|
+
* // }
|
|
577
|
+
* // }
|
|
578
|
+
*
|
|
579
|
+
* const update: PartialUser = {
|
|
580
|
+
* settings: {
|
|
581
|
+
* notifications: {
|
|
582
|
+
* email: false
|
|
583
|
+
* }
|
|
584
|
+
* }
|
|
585
|
+
* }
|
|
586
|
+
* ```
|
|
587
|
+
*
|
|
588
|
+
* @public
|
|
589
|
+
*/
|
|
590
|
+
type RecursivePartial<T> = {
|
|
591
|
+
[P in keyof T]?: RecursivePartial<T[P]>;
|
|
592
|
+
};
|
|
593
|
+
/**
|
|
594
|
+
* Expands a type definition to show its full structure in IDE tooltips and error messages.
|
|
595
|
+
* This utility type forces TypeScript to resolve and display the complete type structure
|
|
596
|
+
* instead of showing complex conditional types or intersections as-is.
|
|
597
|
+
*
|
|
598
|
+
* @example
|
|
599
|
+
* ```ts
|
|
600
|
+
* type User = { name: string }
|
|
601
|
+
* type WithId = { id: string }
|
|
602
|
+
* type UserWithId = User & WithId
|
|
603
|
+
*
|
|
604
|
+
* // Without Expand, IDE shows: User & WithId
|
|
605
|
+
* // With Expand, IDE shows: { name: string; id: string }
|
|
606
|
+
* type ExpandedUserWithId = Expand<UserWithId>
|
|
607
|
+
*
|
|
608
|
+
* // Useful for complex intersections
|
|
609
|
+
* type ComplexType = Expand<BaseType & Mixin1 & Mixin2>
|
|
610
|
+
* ```
|
|
611
|
+
*
|
|
612
|
+
* @public
|
|
613
|
+
*/
|
|
614
|
+
type Expand<T> = T extends infer O ? {
|
|
615
|
+
[K in keyof O]: O[K];
|
|
616
|
+
} : never;
|
|
617
|
+
/**
|
|
618
|
+
* A value that may be returned synchronously or as a `Promise` / `PromiseLike`.
|
|
619
|
+
* Use with `await` or `Promise.resolve(...)` to normalize to a single `Promise`.
|
|
620
|
+
*
|
|
621
|
+
* @public
|
|
622
|
+
*/
|
|
623
|
+
type Awaitable<T> = T | PromiseLike<T>;
|
|
624
|
+
/**
|
|
625
|
+
* Makes specified keys in a type required while keeping all other properties as-is.
|
|
626
|
+
* This is useful when you need to ensure certain optional properties are provided
|
|
627
|
+
* in specific contexts without affecting the entire type structure.
|
|
628
|
+
*
|
|
629
|
+
* @example
|
|
630
|
+
* ```ts
|
|
631
|
+
* interface Shape {
|
|
632
|
+
* id: string
|
|
633
|
+
* x?: number
|
|
634
|
+
* y?: number
|
|
635
|
+
* visible?: boolean
|
|
636
|
+
* }
|
|
637
|
+
*
|
|
638
|
+
* // Make position properties required
|
|
639
|
+
* type PositionedShape = Required<Shape, 'x' | 'y'>
|
|
640
|
+
* // Result: {
|
|
641
|
+
* // id: string
|
|
642
|
+
* // x: number // now required
|
|
643
|
+
* // y: number // now required
|
|
644
|
+
* // visible?: boolean
|
|
645
|
+
* // }
|
|
646
|
+
*
|
|
647
|
+
* const shape: PositionedShape = {
|
|
648
|
+
* id: 'rect1',
|
|
649
|
+
* x: 10, // must provide
|
|
650
|
+
* y: 20, // must provide
|
|
651
|
+
* // visible is still optional
|
|
652
|
+
* }
|
|
653
|
+
* ```
|
|
654
|
+
*
|
|
655
|
+
* @internal
|
|
656
|
+
*/
|
|
657
|
+
type Required<T, K extends keyof T> = Expand<Omit<T, K> & {
|
|
658
|
+
[P in K]-?: T[P];
|
|
659
|
+
}>;
|
|
660
|
+
/**
|
|
661
|
+
* Automatically makes properties optional if their type includes `undefined`.
|
|
662
|
+
* This transforms properties like `prop: string | undefined` to `prop?: string | undefined`,
|
|
663
|
+
* making the API more ergonomic by not requiring explicit undefined assignments.
|
|
664
|
+
*
|
|
665
|
+
* @example
|
|
666
|
+
* ```ts
|
|
667
|
+
* interface RawConfig {
|
|
668
|
+
* name: string
|
|
669
|
+
* theme: string | undefined
|
|
670
|
+
* debug: boolean | undefined
|
|
671
|
+
* version: number
|
|
672
|
+
* }
|
|
673
|
+
*
|
|
674
|
+
* type Config = MakeUndefinedOptional<RawConfig>
|
|
675
|
+
* // Result: {
|
|
676
|
+
* // name: string
|
|
677
|
+
* // theme?: string | undefined // now optional
|
|
678
|
+
* // debug?: boolean | undefined // now optional
|
|
679
|
+
* // version: number
|
|
680
|
+
* // }
|
|
681
|
+
*
|
|
682
|
+
* const config: Config = {
|
|
683
|
+
* name: 'MyApp',
|
|
684
|
+
* version: 1
|
|
685
|
+
* // theme and debug can be omitted instead of explicitly set to undefined
|
|
686
|
+
* }
|
|
687
|
+
* ```
|
|
688
|
+
*
|
|
689
|
+
* @public
|
|
690
|
+
*/
|
|
691
|
+
type MakeUndefinedOptional<T extends object> = Expand<{
|
|
692
|
+
[P in {
|
|
693
|
+
[K in keyof T]: undefined extends T[K] ? never : K;
|
|
694
|
+
}[keyof T]]: T[P];
|
|
695
|
+
} & {
|
|
696
|
+
[P in {
|
|
697
|
+
[K in keyof T]: undefined extends T[K] ? K : never;
|
|
698
|
+
}[keyof T]]?: T[P];
|
|
699
|
+
}>;
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Create a debounced version of a function that delays execution until after a specified wait time.
|
|
703
|
+
*
|
|
704
|
+
* Debouncing ensures that a function is only executed once after a specified delay,
|
|
705
|
+
* even if called multiple times in rapid succession. Each new call resets the timer. The debounced
|
|
706
|
+
* function returns a Promise that resolves with the result of the original function. Includes a
|
|
707
|
+
* cancel method to prevent execution if needed.
|
|
708
|
+
*
|
|
709
|
+
* @param callback - The function to debounce (can be sync or async)
|
|
710
|
+
* @param wait - The delay in milliseconds before executing the function
|
|
711
|
+
* @returns A debounced function that returns a Promise and includes a cancel method
|
|
712
|
+
*
|
|
713
|
+
* @example
|
|
714
|
+
* ```ts
|
|
715
|
+
* // Debounce a search function
|
|
716
|
+
* const searchAPI = (query: string) => fetch(`/search?q=${query}`)
|
|
717
|
+
* const debouncedSearch = debounce(searchAPI, 300)
|
|
718
|
+
*
|
|
719
|
+
* // Multiple rapid calls will only execute the last one after 300ms
|
|
720
|
+
* debouncedSearch('react').then(result => console.log(result))
|
|
721
|
+
* debouncedSearch('react hooks') // This cancels the previous call
|
|
722
|
+
* debouncedSearch('react typescript') // Only this will execute
|
|
723
|
+
*
|
|
724
|
+
* // Cancel pending execution
|
|
725
|
+
* debouncedSearch.cancel()
|
|
726
|
+
*
|
|
727
|
+
* // With async/await
|
|
728
|
+
* const saveData = debounce(async (data: any) => {
|
|
729
|
+
* return await api.save(data)
|
|
730
|
+
* }, 1000)
|
|
731
|
+
*
|
|
732
|
+
* const result = await saveData({name: 'John'})
|
|
733
|
+
* ```
|
|
734
|
+
*
|
|
735
|
+
* @public
|
|
736
|
+
* @see source - https://gist.github.com/ca0v/73a31f57b397606c9813472f7493a940
|
|
737
|
+
*/
|
|
738
|
+
declare function debounce<T extends unknown[], U>(callback: (...args: T) => Awaitable<U>, wait: number): {
|
|
739
|
+
(...args: T): Promise<U>;
|
|
740
|
+
cancel(): void;
|
|
741
|
+
};
|
|
742
|
+
|
|
743
|
+
/** @public */
|
|
744
|
+
interface ErrorAnnotations {
|
|
745
|
+
tags: Record<string, number | string | boolean | bigint | symbol | null | undefined>;
|
|
746
|
+
extras: Record<string, unknown>;
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Annotate an error with tags and additional data. Annotations won't overwrite existing ones.
|
|
750
|
+
* Retrieve them with `getErrorAnnotations`.
|
|
751
|
+
*
|
|
752
|
+
* @param error - The error object to annotate
|
|
753
|
+
* @param annotations - Partial annotations to add (tags and/or extras)
|
|
754
|
+
* @returns void
|
|
755
|
+
* @example
|
|
756
|
+
* ```ts
|
|
757
|
+
* const error = new Error('Something went wrong')
|
|
758
|
+
* annotateError(error, {
|
|
759
|
+
* tags: { userId: '123', operation: 'save' },
|
|
760
|
+
* extras: { timestamp: Date.now() }
|
|
761
|
+
* })
|
|
762
|
+
* ```
|
|
763
|
+
*
|
|
764
|
+
* @internal
|
|
765
|
+
*/
|
|
766
|
+
declare function annotateError(error: unknown, annotations: Partial<ErrorAnnotations>): void;
|
|
767
|
+
/**
|
|
768
|
+
* Retrieve annotations that have been added to an error object.
|
|
769
|
+
*
|
|
770
|
+
* @param error - The error object to get annotations from
|
|
771
|
+
* @returns The error annotations (tags and extras) or empty objects if none exist
|
|
772
|
+
* @example
|
|
773
|
+
* ```ts
|
|
774
|
+
* const error = new Error('Something went wrong')
|
|
775
|
+
* annotateError(error, { tags: { userId: '123' } })
|
|
776
|
+
* const annotations = getErrorAnnotations(error)
|
|
777
|
+
* console.log(annotations.tags.userId) // '123'
|
|
778
|
+
* ```
|
|
779
|
+
*
|
|
780
|
+
* @internal
|
|
781
|
+
*/
|
|
782
|
+
declare function getErrorAnnotations(error: Error): ErrorAnnotations;
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* A queue that executes tasks sequentially with optional delay between tasks.
|
|
786
|
+
*
|
|
787
|
+
* ExecutionQueue ensures that tasks are executed one at a time in the order they were added,
|
|
788
|
+
* with an optional timeout delay between each task execution. This is useful for rate limiting,
|
|
789
|
+
* preventing race conditions, or controlling the flow of asynchronous operations.
|
|
790
|
+
*
|
|
791
|
+
* @example
|
|
792
|
+
* ```ts
|
|
793
|
+
* // Create a queue with 100ms delay between tasks
|
|
794
|
+
* const queue = new ExecutionQueue(100)
|
|
795
|
+
*
|
|
796
|
+
* // Add tasks to the queue
|
|
797
|
+
* const result1 = await queue.push(() => fetch('/api/data'))
|
|
798
|
+
* const result2 = await queue.push(async () => {
|
|
799
|
+
* const data = await processData()
|
|
800
|
+
* return data
|
|
801
|
+
* })
|
|
802
|
+
*
|
|
803
|
+
* // Check if queue is empty
|
|
804
|
+
* if (queue.isEmpty()) {
|
|
805
|
+
* console.log('All tasks completed')
|
|
806
|
+
* }
|
|
807
|
+
*
|
|
808
|
+
* // Clean up
|
|
809
|
+
* queue.close()
|
|
810
|
+
* ```
|
|
811
|
+
*
|
|
812
|
+
* @internal
|
|
813
|
+
*/
|
|
814
|
+
declare class ExecutionQueue {
|
|
815
|
+
private readonly timeout?;
|
|
816
|
+
private queue;
|
|
817
|
+
private running;
|
|
818
|
+
/**
|
|
819
|
+
* Creates a new ExecutionQueue.
|
|
820
|
+
*
|
|
821
|
+
* Creates a new execution queue that will process tasks sequentially.
|
|
822
|
+
* If a timeout is provided, there will be a delay between each task execution,
|
|
823
|
+
* which is useful for rate limiting or controlling execution flow.
|
|
824
|
+
*
|
|
825
|
+
* timeout - Optional delay in milliseconds between task executions
|
|
826
|
+
* @example
|
|
827
|
+
* ```ts
|
|
828
|
+
* // Create queue without delay
|
|
829
|
+
* const fastQueue = new ExecutionQueue()
|
|
830
|
+
*
|
|
831
|
+
* // Create queue with 500ms delay between tasks
|
|
832
|
+
* const slowQueue = new ExecutionQueue(500)
|
|
833
|
+
* ```
|
|
834
|
+
*/
|
|
835
|
+
constructor(timeout?: number | undefined);
|
|
836
|
+
/**
|
|
837
|
+
* Checks if the queue is empty and not currently running a task.
|
|
838
|
+
*
|
|
839
|
+
* Determines whether the execution queue has completed all tasks and is idle.
|
|
840
|
+
* Returns true only when there are no pending tasks in the queue AND no task is currently being executed.
|
|
841
|
+
*
|
|
842
|
+
* @returns True if the queue has no pending tasks and is not currently executing
|
|
843
|
+
* @example
|
|
844
|
+
* ```ts
|
|
845
|
+
* const queue = new ExecutionQueue()
|
|
846
|
+
*
|
|
847
|
+
* console.log(queue.isEmpty()) // true - queue is empty
|
|
848
|
+
*
|
|
849
|
+
* queue.push(() => console.log('task'))
|
|
850
|
+
* console.log(queue.isEmpty()) // false - task is running/pending
|
|
851
|
+
* ```
|
|
852
|
+
*/
|
|
853
|
+
isEmpty(): boolean;
|
|
854
|
+
private run;
|
|
855
|
+
/**
|
|
856
|
+
* Adds a task to the queue and returns a promise that resolves with the task's result.
|
|
857
|
+
*
|
|
858
|
+
* Enqueues a task for sequential execution. The task will be executed after all
|
|
859
|
+
* previously queued tasks have completed. If a timeout was specified in the constructor,
|
|
860
|
+
* there will be a delay between this task and the next one.
|
|
861
|
+
*
|
|
862
|
+
* @param task - The function to execute (can be sync or async)
|
|
863
|
+
* @returns Promise that resolves with the task's return value
|
|
864
|
+
* @example
|
|
865
|
+
* ```ts
|
|
866
|
+
* const queue = new ExecutionQueue(100)
|
|
867
|
+
*
|
|
868
|
+
* // Add async task
|
|
869
|
+
* const result = await queue.push(async () => {
|
|
870
|
+
* const response = await fetch('/api/data')
|
|
871
|
+
* return response.json()
|
|
872
|
+
* })
|
|
873
|
+
*
|
|
874
|
+
* // Add sync task
|
|
875
|
+
* const number = await queue.push(() => 42)
|
|
876
|
+
* ```
|
|
877
|
+
*/
|
|
878
|
+
push<T>(task: () => T): Promise<Awaited<T>>;
|
|
879
|
+
/**
|
|
880
|
+
* Clears all pending tasks from the queue.
|
|
881
|
+
*
|
|
882
|
+
* Immediately removes all pending tasks from the queue. Any currently
|
|
883
|
+
* running task will complete normally, but no additional tasks will be executed.
|
|
884
|
+
* This method does not wait for the current task to finish.
|
|
885
|
+
*
|
|
886
|
+
* @returns void
|
|
887
|
+
* @example
|
|
888
|
+
* ```ts
|
|
889
|
+
* const queue = new ExecutionQueue()
|
|
890
|
+
*
|
|
891
|
+
* // Add several tasks
|
|
892
|
+
* queue.push(() => console.log('task 1'))
|
|
893
|
+
* queue.push(() => console.log('task 2'))
|
|
894
|
+
* queue.push(() => console.log('task 3'))
|
|
895
|
+
*
|
|
896
|
+
* // Clear all pending tasks
|
|
897
|
+
* queue.close()
|
|
898
|
+
* // Only 'task 1' will execute if it was already running
|
|
899
|
+
* ```
|
|
900
|
+
*/
|
|
901
|
+
close(): void;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
/**
|
|
905
|
+
* Utility class providing helper methods for file and blob operations.
|
|
906
|
+
*
|
|
907
|
+
* FileHelpers contains static methods for common file operations including
|
|
908
|
+
* URL fetching, format conversion, and MIME type manipulation. All methods work with
|
|
909
|
+
* web APIs like fetch, FileReader, and Blob/File objects.
|
|
910
|
+
*
|
|
911
|
+
* @example
|
|
912
|
+
* ```ts
|
|
913
|
+
* // Fetch and convert a remote image to data URL
|
|
914
|
+
* const dataUrl = await FileHelpers.urlToDataUrl('https://example.com/image.png')
|
|
915
|
+
*
|
|
916
|
+
* // Convert user-selected file to text
|
|
917
|
+
* const text = await FileHelpers.blobToText(userFile)
|
|
918
|
+
*
|
|
919
|
+
* // Change file MIME type
|
|
920
|
+
* const newFile = FileHelpers.rewriteMimeType(originalFile, 'application/json')
|
|
921
|
+
* ```
|
|
922
|
+
*
|
|
923
|
+
* @public
|
|
924
|
+
*/
|
|
925
|
+
declare class FileHelpers {
|
|
926
|
+
/**
|
|
927
|
+
* Converts a URL to an ArrayBuffer by fetching the resource.
|
|
928
|
+
*
|
|
929
|
+
* Fetches the resource at the given URL and returns its content as an ArrayBuffer.
|
|
930
|
+
* This is useful for loading binary data like images, videos, or other file types.
|
|
931
|
+
*
|
|
932
|
+
* @param url - The URL of the file to fetch
|
|
933
|
+
* @returns Promise that resolves to the file content as an ArrayBuffer
|
|
934
|
+
* @example
|
|
935
|
+
* ```ts
|
|
936
|
+
* const buffer = await FileHelpers.urlToArrayBuffer('https://example.com/image.png')
|
|
937
|
+
* console.log(buffer.byteLength) // Size of the file in bytes
|
|
938
|
+
* ```
|
|
939
|
+
* @public
|
|
940
|
+
*/
|
|
941
|
+
static urlToArrayBuffer(url: string): Promise<ArrayBuffer>;
|
|
942
|
+
/**
|
|
943
|
+
* Converts a URL to a Blob by fetching the resource.
|
|
944
|
+
*
|
|
945
|
+
* Fetches the resource at the given URL and returns its content as a Blob object.
|
|
946
|
+
* Blobs are useful for handling file data in web applications.
|
|
947
|
+
*
|
|
948
|
+
* @param url - The URL of the file to fetch
|
|
949
|
+
* @returns Promise that resolves to the file content as a Blob
|
|
950
|
+
* @example
|
|
951
|
+
* ```ts
|
|
952
|
+
* const blob = await FileHelpers.urlToBlob('https://example.com/document.pdf')
|
|
953
|
+
* console.log(blob.type) // 'application/pdf'
|
|
954
|
+
* console.log(blob.size) // Size in bytes
|
|
955
|
+
* ```
|
|
956
|
+
* @public
|
|
957
|
+
*/
|
|
958
|
+
static urlToBlob(url: string): Promise<Blob>;
|
|
959
|
+
/**
|
|
960
|
+
* Converts a URL to a data URL by fetching the resource.
|
|
961
|
+
*
|
|
962
|
+
* Fetches the resource at the given URL and converts it to a base64-encoded data URL.
|
|
963
|
+
* If the URL is already a data URL, it returns the URL unchanged. This is useful for embedding
|
|
964
|
+
* resources directly in HTML or CSS.
|
|
965
|
+
*
|
|
966
|
+
* @param url - The URL of the file to convert, or an existing data URL
|
|
967
|
+
* @returns Promise that resolves to a data URL string
|
|
968
|
+
* @example
|
|
969
|
+
* ```ts
|
|
970
|
+
* const dataUrl = await FileHelpers.urlToDataUrl('https://example.com/image.jpg')
|
|
971
|
+
* // Returns: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEA...'
|
|
972
|
+
*
|
|
973
|
+
* const existing = await FileHelpers.urlToDataUrl('data:text/plain;base64,SGVsbG8=')
|
|
974
|
+
* // Returns the same data URL unchanged
|
|
975
|
+
* ```
|
|
976
|
+
* @public
|
|
977
|
+
*/
|
|
978
|
+
static urlToDataUrl(url: string): Promise<string>;
|
|
979
|
+
/**
|
|
980
|
+
* Convert a Blob to a base64 encoded data URL.
|
|
981
|
+
*
|
|
982
|
+
* Converts a Blob object to a base64-encoded data URL using the FileReader API.
|
|
983
|
+
* This is useful for displaying images or embedding file content directly in HTML.
|
|
984
|
+
*
|
|
985
|
+
* @param file - The Blob object to convert
|
|
986
|
+
* @returns Promise that resolves to a base64-encoded data URL string
|
|
987
|
+
* @example
|
|
988
|
+
* ```ts
|
|
989
|
+
* const blob = new Blob(['Hello World'], { type: 'text/plain' })
|
|
990
|
+
* const dataUrl = await FileHelpers.blobToDataUrl(blob)
|
|
991
|
+
* // Returns: 'data:text/plain;base64,SGVsbG8gV29ybGQ='
|
|
992
|
+
*
|
|
993
|
+
* // With an image file
|
|
994
|
+
* const imageDataUrl = await FileHelpers.blobToDataUrl(myImageFile)
|
|
995
|
+
* // Can be used directly in img src attribute
|
|
996
|
+
* ```
|
|
997
|
+
* @public
|
|
998
|
+
*/
|
|
999
|
+
static blobToDataUrl(file: Blob): Promise<string>;
|
|
1000
|
+
/**
|
|
1001
|
+
* Convert a Blob to a unicode text string.
|
|
1002
|
+
*
|
|
1003
|
+
* Reads the content of a Blob object as a UTF-8 text string using the FileReader API.
|
|
1004
|
+
* This is useful for reading text files or extracting text content from blobs.
|
|
1005
|
+
*
|
|
1006
|
+
* @param file - The Blob object to convert to text
|
|
1007
|
+
* @returns Promise that resolves to the text content as a string
|
|
1008
|
+
* @example
|
|
1009
|
+
* ```ts
|
|
1010
|
+
* const textBlob = new Blob(['Hello World'], { type: 'text/plain' })
|
|
1011
|
+
* const text = await FileHelpers.blobToText(textBlob)
|
|
1012
|
+
* console.log(text) // 'Hello World'
|
|
1013
|
+
*
|
|
1014
|
+
* // With a text file from user input
|
|
1015
|
+
* const content = await FileHelpers.blobToText(myTextFile)
|
|
1016
|
+
* console.log(content) // File content as string
|
|
1017
|
+
* ```
|
|
1018
|
+
* @public
|
|
1019
|
+
*/
|
|
1020
|
+
static blobToText(file: Blob): Promise<string>;
|
|
1021
|
+
/**
|
|
1022
|
+
* Creates a new Blob or File with a different MIME type.
|
|
1023
|
+
*
|
|
1024
|
+
* Creates a copy of the given Blob or File with a new MIME type while preserving
|
|
1025
|
+
* all other properties. If the current MIME type already matches the new one, returns the
|
|
1026
|
+
* original object unchanged. For File objects, preserves the filename.
|
|
1027
|
+
*
|
|
1028
|
+
* @param blob - The Blob or File object to modify
|
|
1029
|
+
* @param newMimeType - The new MIME type to assign
|
|
1030
|
+
* @returns A new Blob or File with the updated MIME type
|
|
1031
|
+
* @example
|
|
1032
|
+
* ```ts
|
|
1033
|
+
* // Change a generic blob to a specific image type
|
|
1034
|
+
* const blob = new Blob([imageData])
|
|
1035
|
+
* const imageBlob = FileHelpers.rewriteMimeType(blob, 'image/png')
|
|
1036
|
+
*
|
|
1037
|
+
* // Change a file's MIME type while preserving filename
|
|
1038
|
+
* const file = new File([data], 'document.txt', { type: 'text/plain' })
|
|
1039
|
+
* const jsonFile = FileHelpers.rewriteMimeType(file, 'application/json')
|
|
1040
|
+
* console.log(jsonFile.name) // 'document.txt' (preserved)
|
|
1041
|
+
* console.log(jsonFile.type) // 'application/json' (updated)
|
|
1042
|
+
* ```
|
|
1043
|
+
* @public
|
|
1044
|
+
*/
|
|
1045
|
+
static rewriteMimeType(blob: Blob, newMimeType: string): Blob;
|
|
1046
|
+
static rewriteMimeType(blob: File, newMimeType: string): File;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/**
|
|
1050
|
+
* When a function is wrapped in `omitFromStackTrace`, if it throws an error the stack trace won't
|
|
1051
|
+
* include the function itself or any stack frames above it. Useful for assertion-style function
|
|
1052
|
+
* where the error will ideally originate from the call-site rather than within the implementation
|
|
1053
|
+
* of the assert fn.
|
|
1054
|
+
*
|
|
1055
|
+
* Only works in platforms that support `Error.captureStackTrace` (ie v8).
|
|
1056
|
+
*
|
|
1057
|
+
* @param fn - The function to wrap and exclude from stack traces
|
|
1058
|
+
* @returns A wrapped version of the function that omits itself from error stack traces
|
|
1059
|
+
* @example
|
|
1060
|
+
* ```ts
|
|
1061
|
+
* const assertPositive = omitFromStackTrace((value: number) => {
|
|
1062
|
+
* if (value <= 0) throw new Error('Value must be positive')
|
|
1063
|
+
* return value
|
|
1064
|
+
* })
|
|
1065
|
+
*
|
|
1066
|
+
* assertPositive(-1) // Error stack trace will point to this line, not inside assertPositive
|
|
1067
|
+
* ```
|
|
1068
|
+
* @internal
|
|
1069
|
+
*/
|
|
1070
|
+
declare function omitFromStackTrace<Args extends Array<unknown>, Return>(fn: (...args: Args) => Return): (...args: Args) => Return;
|
|
1071
|
+
/**
|
|
1072
|
+
* Does nothing, but it's really really good at it.
|
|
1073
|
+
* @internal
|
|
1074
|
+
*/
|
|
1075
|
+
declare const noop: () => void;
|
|
1076
|
+
|
|
1077
|
+
/**
|
|
1078
|
+
* Hash a string using the FNV-1a algorithm.
|
|
1079
|
+
*
|
|
1080
|
+
* Generates a deterministic hash value for a given string using a variant of the FNV-1a
|
|
1081
|
+
* (Fowler-Noll-Vo) algorithm. The hash is returned as a string representation of a 32-bit integer.
|
|
1082
|
+
*
|
|
1083
|
+
* @param string - The input string to hash
|
|
1084
|
+
* @returns A string representation of the 32-bit hash value
|
|
1085
|
+
* @example
|
|
1086
|
+
* ```ts
|
|
1087
|
+
* const hash = getHashForString('hello world')
|
|
1088
|
+
* console.log(hash) // '-862545276'
|
|
1089
|
+
*
|
|
1090
|
+
* // Same input always produces same hash
|
|
1091
|
+
* const hash2 = getHashForString('hello world')
|
|
1092
|
+
* console.log(hash === hash2) // true
|
|
1093
|
+
* ```
|
|
1094
|
+
* @public
|
|
1095
|
+
*/
|
|
1096
|
+
declare function getHashForString(string: string): string;
|
|
1097
|
+
/**
|
|
1098
|
+
* Hash an object by converting it to JSON and then hashing the resulting string.
|
|
1099
|
+
*
|
|
1100
|
+
* Converts the object to a JSON string using JSON.stringify and then applies the same
|
|
1101
|
+
* hashing algorithm as getHashForString. Useful for creating consistent hash values
|
|
1102
|
+
* for objects, though the hash depends on JSON serialization order.
|
|
1103
|
+
*
|
|
1104
|
+
* @param obj - The object to hash (any JSON-serializable value)
|
|
1105
|
+
* @returns A string representation of the 32-bit hash value
|
|
1106
|
+
* @example
|
|
1107
|
+
* ```ts
|
|
1108
|
+
* const hash1 = getHashForObject({ name: 'John', age: 30 })
|
|
1109
|
+
* const hash2 = getHashForObject({ name: 'John', age: 30 })
|
|
1110
|
+
* console.log(hash1 === hash2) // true
|
|
1111
|
+
*
|
|
1112
|
+
* // Arrays work too
|
|
1113
|
+
* const arrayHash = getHashForObject([1, 2, 3, 'hello'])
|
|
1114
|
+
* console.log(arrayHash) // '-123456789'
|
|
1115
|
+
* ```
|
|
1116
|
+
* @public
|
|
1117
|
+
*/
|
|
1118
|
+
declare function getHashForObject(obj: any): string;
|
|
1119
|
+
/**
|
|
1120
|
+
* Hash an ArrayBuffer using the FNV-1a algorithm.
|
|
1121
|
+
*
|
|
1122
|
+
* Generates a deterministic hash value for binary data stored in an ArrayBuffer.
|
|
1123
|
+
* Processes the buffer byte by byte using the same hashing algorithm as getHashForString.
|
|
1124
|
+
* Useful for creating consistent identifiers for binary data like images or files.
|
|
1125
|
+
*
|
|
1126
|
+
* @param buffer - The ArrayBuffer containing binary data to hash
|
|
1127
|
+
* @returns A string representation of the 32-bit hash value
|
|
1128
|
+
* @example
|
|
1129
|
+
* ```ts
|
|
1130
|
+
* // Hash some binary data
|
|
1131
|
+
* const data = new Uint8Array([1, 2, 3, 4, 5])
|
|
1132
|
+
* const hash = getHashForBuffer(data.buffer)
|
|
1133
|
+
* console.log(hash) // '123456789'
|
|
1134
|
+
*
|
|
1135
|
+
* // Hash image file data
|
|
1136
|
+
* const fileBuffer = await file.arrayBuffer()
|
|
1137
|
+
* const fileHash = getHashForBuffer(fileBuffer)
|
|
1138
|
+
* console.log(fileHash) // Unique hash for the file
|
|
1139
|
+
* ```
|
|
1140
|
+
* @public
|
|
1141
|
+
*/
|
|
1142
|
+
declare function getHashForBuffer(buffer: ArrayBuffer): string;
|
|
1143
|
+
/**
|
|
1144
|
+
* Applies a string transformation algorithm that rearranges and modifies characters.
|
|
1145
|
+
*
|
|
1146
|
+
* Performs a series of character manipulations on the input string including
|
|
1147
|
+
* character repositioning through splicing operations and numeric character transformations.
|
|
1148
|
+
* This appears to be a custom encoding/obfuscation function.
|
|
1149
|
+
*
|
|
1150
|
+
* @param str - The input string to transform
|
|
1151
|
+
* @returns The transformed string after applying all manipulations
|
|
1152
|
+
* @example
|
|
1153
|
+
* ```ts
|
|
1154
|
+
* const result = lns('hello123')
|
|
1155
|
+
* console.log(result) // Transformed string (exact output depends on algorithm)
|
|
1156
|
+
*
|
|
1157
|
+
* // Can be used for simple string obfuscation
|
|
1158
|
+
* const obfuscated = lns('sensitive-data')
|
|
1159
|
+
* console.log(obfuscated) // Obfuscated version
|
|
1160
|
+
* ```
|
|
1161
|
+
* @public
|
|
1162
|
+
*/
|
|
1163
|
+
declare function lns(str: string): string;
|
|
1164
|
+
|
|
1165
|
+
/*!
|
|
1166
|
+
* MIT License: https://github.com/ai/nanoid/blob/main/LICENSE
|
|
1167
|
+
* Modified code originally from <https://github.com/ai/nanoid>
|
|
1168
|
+
* Copyright 2017 Andrey Sitnik <andrey@sitnik.ru>
|
|
1169
|
+
*
|
|
1170
|
+
* `nanoid` is currently only distributed as an ES module. Some tools (jest, playwright) don't
|
|
1171
|
+
* properly support ESM-only code yet, and tldraw itself is distributed as both an ES module and a
|
|
1172
|
+
* CommonJS module. By including nanoid here, we can make sure it works well in every environment
|
|
1173
|
+
* where tldraw is used. We can also remove some unused features like custom alphabets.
|
|
1174
|
+
*/
|
|
1175
|
+
/**
|
|
1176
|
+
* Mock the unique ID generator with a custom implementation for testing.
|
|
1177
|
+
*
|
|
1178
|
+
* Replaces the internal ID generation function with a custom one. This is useful
|
|
1179
|
+
* for testing scenarios where you need predictable or deterministic IDs.
|
|
1180
|
+
*
|
|
1181
|
+
* @param fn - The mock function that should return a string ID. Takes optional size parameter.
|
|
1182
|
+
* @example
|
|
1183
|
+
* ```ts
|
|
1184
|
+
* // Mock with predictable IDs for testing
|
|
1185
|
+
* mockUniqueId((size = 21) => 'test-id-' + size)
|
|
1186
|
+
* console.log(uniqueId()) // 'test-id-21'
|
|
1187
|
+
* console.log(uniqueId(10)) // 'test-id-10'
|
|
1188
|
+
*
|
|
1189
|
+
* // Restore original implementation when done
|
|
1190
|
+
* restoreUniqueId()
|
|
1191
|
+
* ```
|
|
1192
|
+
* @internal
|
|
1193
|
+
*/
|
|
1194
|
+
declare function mockUniqueId(fn: (size?: number) => string): void;
|
|
1195
|
+
/**
|
|
1196
|
+
* Restore the original unique ID generator after mocking.
|
|
1197
|
+
*
|
|
1198
|
+
* Resets the ID generation function back to the original nanoid implementation.
|
|
1199
|
+
* This should be called after testing to restore normal ID generation behavior.
|
|
1200
|
+
*
|
|
1201
|
+
* @example
|
|
1202
|
+
* ```ts
|
|
1203
|
+
* // After mocking for tests
|
|
1204
|
+
* mockUniqueId(() => 'mock-id')
|
|
1205
|
+
*
|
|
1206
|
+
* // Restore original behavior
|
|
1207
|
+
* restoreUniqueId()
|
|
1208
|
+
* console.log(uniqueId()) // Now generates real random IDs again
|
|
1209
|
+
* ```
|
|
1210
|
+
* @internal
|
|
1211
|
+
*/
|
|
1212
|
+
declare function restoreUniqueId(): void;
|
|
1213
|
+
/**
|
|
1214
|
+
* Generate a unique ID using a modified nanoid algorithm.
|
|
1215
|
+
*
|
|
1216
|
+
* Generates a cryptographically secure random string ID using URL-safe characters.
|
|
1217
|
+
* The default size is 21 characters, which provides a good balance of uniqueness
|
|
1218
|
+
* and brevity. Uses the global crypto API for secure random number generation.
|
|
1219
|
+
*
|
|
1220
|
+
* @param size - Optional length of the generated ID (defaults to 21 characters)
|
|
1221
|
+
* @returns A unique string identifier
|
|
1222
|
+
* @example
|
|
1223
|
+
* ```ts
|
|
1224
|
+
* // Generate default 21-character ID
|
|
1225
|
+
* const id = uniqueId()
|
|
1226
|
+
* console.log(id) // 'V1StGXR8_Z5jdHi6B-myT'
|
|
1227
|
+
*
|
|
1228
|
+
* // Generate shorter ID
|
|
1229
|
+
* const shortId = uniqueId(10)
|
|
1230
|
+
* console.log(shortId) // 'V1StGXR8_Z'
|
|
1231
|
+
*
|
|
1232
|
+
* // Generate longer ID
|
|
1233
|
+
* const longId = uniqueId(32)
|
|
1234
|
+
* console.log(longId) // 'V1StGXR8_Z5jdHi6B-myTVKahvjdx...'
|
|
1235
|
+
* ```
|
|
1236
|
+
* @public
|
|
1237
|
+
*/
|
|
1238
|
+
declare function uniqueId(size?: number): string;
|
|
1239
|
+
|
|
1240
|
+
/**
|
|
1241
|
+
* Get the first item from an iterable Set or Map.
|
|
1242
|
+
*
|
|
1243
|
+
* @param value - The iterable Set or Map to get the first item from
|
|
1244
|
+
* @returns The first value from the Set or Map
|
|
1245
|
+
* @example
|
|
1246
|
+
* ```ts
|
|
1247
|
+
* const A = getFirstFromIterable(new Set([1, 2, 3])) // 1
|
|
1248
|
+
* const B = getFirstFromIterable(
|
|
1249
|
+
* new Map([
|
|
1250
|
+
* ['a', 1],
|
|
1251
|
+
* ['b', 2],
|
|
1252
|
+
* ])
|
|
1253
|
+
* ) // 1
|
|
1254
|
+
* ```
|
|
1255
|
+
* @public
|
|
1256
|
+
*/
|
|
1257
|
+
declare function getFirstFromIterable<T = unknown>(set: Set<T> | Map<any, T>): T;
|
|
1258
|
+
|
|
1259
|
+
/** Simple LRU cache backed by a Map's insertion-order iteration. @public */
|
|
1260
|
+
declare class LruCache<K, V> {
|
|
1261
|
+
private maxSize;
|
|
1262
|
+
private map;
|
|
1263
|
+
constructor(maxSize: number);
|
|
1264
|
+
get(key: K): V | undefined;
|
|
1265
|
+
set(key: K, value: V): void;
|
|
1266
|
+
has(key: K): boolean;
|
|
1267
|
+
get size(): number;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
/**
|
|
1271
|
+
* A type that represents any valid JSON value. This includes primitives (boolean, null, string, number),
|
|
1272
|
+
* arrays of JSON values, and objects with string keys and JSON values.
|
|
1273
|
+
*
|
|
1274
|
+
* @example
|
|
1275
|
+
* ```ts
|
|
1276
|
+
* const jsonData: JsonValue = {
|
|
1277
|
+
* name: "Alice",
|
|
1278
|
+
* age: 30,
|
|
1279
|
+
* active: true,
|
|
1280
|
+
* tags: ["user", "premium"],
|
|
1281
|
+
* metadata: null
|
|
1282
|
+
* }
|
|
1283
|
+
* ```
|
|
1284
|
+
*
|
|
1285
|
+
* @public
|
|
1286
|
+
*/
|
|
1287
|
+
type JsonValue = JsonPrimitive | JsonArray | JsonObject;
|
|
1288
|
+
/**
|
|
1289
|
+
* A type representing JSON primitive values: boolean, null, string, or number.
|
|
1290
|
+
* These are the atomic values that can appear in JSON data.
|
|
1291
|
+
*
|
|
1292
|
+
* @example
|
|
1293
|
+
* ```ts
|
|
1294
|
+
* const primitives: JsonPrimitive[] = [
|
|
1295
|
+
* true,
|
|
1296
|
+
* null,
|
|
1297
|
+
* "hello",
|
|
1298
|
+
* 42
|
|
1299
|
+
* ]
|
|
1300
|
+
* ```
|
|
1301
|
+
*
|
|
1302
|
+
* @public
|
|
1303
|
+
*/
|
|
1304
|
+
type JsonPrimitive = boolean | null | string | number;
|
|
1305
|
+
/**
|
|
1306
|
+
* A type representing a JSON array containing any valid JSON values.
|
|
1307
|
+
* Arrays can contain mixed types of JSON values including nested arrays and objects.
|
|
1308
|
+
*
|
|
1309
|
+
* @example
|
|
1310
|
+
* ```ts
|
|
1311
|
+
* const jsonArray: JsonArray = [
|
|
1312
|
+
* "text",
|
|
1313
|
+
* 123,
|
|
1314
|
+
* true,
|
|
1315
|
+
* { nested: "object" },
|
|
1316
|
+
* [1, 2, 3]
|
|
1317
|
+
* ]
|
|
1318
|
+
* ```
|
|
1319
|
+
*
|
|
1320
|
+
* @public
|
|
1321
|
+
*/
|
|
1322
|
+
type JsonArray = JsonValue[];
|
|
1323
|
+
/**
|
|
1324
|
+
* A type representing a JSON object with string keys and JSON values.
|
|
1325
|
+
* Object values can be undefined to handle optional properties safely.
|
|
1326
|
+
*
|
|
1327
|
+
* @example
|
|
1328
|
+
* ```ts
|
|
1329
|
+
* const jsonObject: JsonObject = {
|
|
1330
|
+
* required: "value",
|
|
1331
|
+
* optional: undefined,
|
|
1332
|
+
* nested: {
|
|
1333
|
+
* deep: "property"
|
|
1334
|
+
* },
|
|
1335
|
+
* array: [1, 2, 3]
|
|
1336
|
+
* }
|
|
1337
|
+
* ```
|
|
1338
|
+
*
|
|
1339
|
+
* @public
|
|
1340
|
+
*/
|
|
1341
|
+
interface JsonObject {
|
|
1342
|
+
[key: string]: JsonValue | undefined;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
/**
|
|
1346
|
+
* Array of all supported image MIME types, combining static, vector, and animated types.
|
|
1347
|
+
*
|
|
1348
|
+
* @example
|
|
1349
|
+
* ```ts
|
|
1350
|
+
* import { DEFAULT_SUPPORTED_IMAGE_TYPES } from '@ibodr/utils'
|
|
1351
|
+
*
|
|
1352
|
+
* const isSupported = DEFAULT_SUPPORTED_IMAGE_TYPES.includes('image/png')
|
|
1353
|
+
* console.log(isSupported) // true
|
|
1354
|
+
* ```
|
|
1355
|
+
* @public
|
|
1356
|
+
*/
|
|
1357
|
+
declare const DEFAULT_SUPPORTED_IMAGE_TYPES: readonly ("image/svg+xml" | "image/jpeg" | "image/png" | "image/webp" | "image/gif" | "image/apng" | "image/avif")[];
|
|
1358
|
+
/**
|
|
1359
|
+
* Array of supported video MIME types.
|
|
1360
|
+
*
|
|
1361
|
+
* @example
|
|
1362
|
+
* ```ts
|
|
1363
|
+
* import { DEFAULT_SUPPORT_VIDEO_TYPES } from '@ibodr/utils'
|
|
1364
|
+
*
|
|
1365
|
+
* const isVideo = DEFAULT_SUPPORT_VIDEO_TYPES.includes('video/mp4')
|
|
1366
|
+
* console.log(isVideo) // true
|
|
1367
|
+
* ```
|
|
1368
|
+
* @public
|
|
1369
|
+
*/
|
|
1370
|
+
declare const DEFAULT_SUPPORT_VIDEO_TYPES: readonly ("video/mp4" | "video/webm" | "video/quicktime")[];
|
|
1371
|
+
/**
|
|
1372
|
+
* Array of all supported media MIME types, combining images and videos.
|
|
1373
|
+
*
|
|
1374
|
+
* @example
|
|
1375
|
+
* ```ts
|
|
1376
|
+
* import { DEFAULT_SUPPORTED_MEDIA_TYPES } from '@ibodr/utils'
|
|
1377
|
+
*
|
|
1378
|
+
* const isMediaFile = DEFAULT_SUPPORTED_MEDIA_TYPES.includes('video/mp4')
|
|
1379
|
+
* console.log(isMediaFile) // true
|
|
1380
|
+
* ```
|
|
1381
|
+
* @public
|
|
1382
|
+
*/
|
|
1383
|
+
declare const DEFAULT_SUPPORTED_MEDIA_TYPES: readonly ("image/svg+xml" | "image/jpeg" | "image/png" | "image/webp" | "image/gif" | "image/apng" | "image/avif" | "video/mp4" | "video/webm" | "video/quicktime")[];
|
|
1384
|
+
/**
|
|
1385
|
+
* Comma-separated string of all supported media MIME types, useful for HTML file input accept attributes.
|
|
1386
|
+
*
|
|
1387
|
+
* @example
|
|
1388
|
+
* ```ts
|
|
1389
|
+
* import { DEFAULT_SUPPORTED_MEDIA_TYPE_LIST } from '@ibodr/utils'
|
|
1390
|
+
*
|
|
1391
|
+
* // Use in HTML file input for media uploads
|
|
1392
|
+
* const input = document.createElement('input')
|
|
1393
|
+
* input.type = 'file'
|
|
1394
|
+
* input.accept = DEFAULT_SUPPORTED_MEDIA_TYPE_LIST
|
|
1395
|
+
* input.addEventListener('change', (e) => {
|
|
1396
|
+
* const files = (e.target as HTMLInputElement).files
|
|
1397
|
+
* if (files) console.log(`Selected ${files.length} file(s)`)
|
|
1398
|
+
* })
|
|
1399
|
+
* ```
|
|
1400
|
+
* @public
|
|
1401
|
+
*/
|
|
1402
|
+
declare const DEFAULT_SUPPORTED_MEDIA_TYPE_LIST: string;
|
|
1403
|
+
/**
|
|
1404
|
+
* Helpers for media
|
|
1405
|
+
*
|
|
1406
|
+
* @public
|
|
1407
|
+
*/
|
|
1408
|
+
declare class MediaHelpers {
|
|
1409
|
+
/**
|
|
1410
|
+
* Load a video element from a URL with cross-origin support.
|
|
1411
|
+
*
|
|
1412
|
+
* @param src - The URL of the video to load
|
|
1413
|
+
* @param doc - Optional document to create the video element in
|
|
1414
|
+
* @returns Promise that resolves to the loaded HTMLVideoElement
|
|
1415
|
+
* @example
|
|
1416
|
+
* ```ts
|
|
1417
|
+
* const video = await MediaHelpers.loadVideo('https://example.com/video.mp4')
|
|
1418
|
+
* console.log(`Video dimensions: ${video.videoWidth}x${video.videoHeight}`)
|
|
1419
|
+
* ```
|
|
1420
|
+
* @public
|
|
1421
|
+
*/
|
|
1422
|
+
static loadVideo(src: string, doc?: Document): Promise<HTMLVideoElement>;
|
|
1423
|
+
/**
|
|
1424
|
+
* Extract a frame from a video element as a data URL.
|
|
1425
|
+
*
|
|
1426
|
+
* @param video - The HTMLVideoElement to extract frame from
|
|
1427
|
+
* @param time - The time in seconds to extract the frame from (default: 0)
|
|
1428
|
+
* @returns Promise that resolves to a data URL of the video frame
|
|
1429
|
+
* @example
|
|
1430
|
+
* ```ts
|
|
1431
|
+
* const video = await MediaHelpers.loadVideo('https://example.com/video.mp4')
|
|
1432
|
+
* const frameDataUrl = await MediaHelpers.getVideoFrameAsDataUrl(video, 5.0)
|
|
1433
|
+
* // Use frameDataUrl as image thumbnail
|
|
1434
|
+
* const img = document.createElement('img')
|
|
1435
|
+
* img.src = frameDataUrl
|
|
1436
|
+
* ```
|
|
1437
|
+
* @public
|
|
1438
|
+
*/
|
|
1439
|
+
static getVideoFrameAsDataUrl(video: HTMLVideoElement, time?: number): Promise<string>;
|
|
1440
|
+
/**
|
|
1441
|
+
* Load an image from a URL and get its dimensions along with the image element.
|
|
1442
|
+
*
|
|
1443
|
+
* @param src - The URL of the image to load
|
|
1444
|
+
* @param doc - Optional document to use for DOM operations (e.g. measuring SVG dimensions)
|
|
1445
|
+
* @returns Promise that resolves to an object with width, height, and the image element
|
|
1446
|
+
* @example
|
|
1447
|
+
* ```ts
|
|
1448
|
+
* const { w, h, image } = await MediaHelpers.getImageAndDimensions('https://example.com/image.png')
|
|
1449
|
+
* console.log(`Image size: ${w}x${h}`)
|
|
1450
|
+
* // Image is ready to use
|
|
1451
|
+
* document.body.appendChild(image)
|
|
1452
|
+
* ```
|
|
1453
|
+
* @public
|
|
1454
|
+
*/
|
|
1455
|
+
static getImageAndDimensions(src: string, doc?: Document): Promise<{
|
|
1456
|
+
w: number;
|
|
1457
|
+
h: number;
|
|
1458
|
+
image: HTMLImageElement;
|
|
1459
|
+
}>;
|
|
1460
|
+
/**
|
|
1461
|
+
* Get the size of a video blob
|
|
1462
|
+
*
|
|
1463
|
+
* @param blob - A Blob containing the video
|
|
1464
|
+
* @param doc - Optional document to create elements in
|
|
1465
|
+
* @returns Promise that resolves to an object with width and height properties
|
|
1466
|
+
* @example
|
|
1467
|
+
* ```ts
|
|
1468
|
+
* const file = new File([...], 'video.mp4', { type: 'video/mp4' })
|
|
1469
|
+
* const { w, h } = await MediaHelpers.getVideoSize(file)
|
|
1470
|
+
* console.log(`Video dimensions: ${w}x${h}`)
|
|
1471
|
+
* ```
|
|
1472
|
+
* @public
|
|
1473
|
+
*/
|
|
1474
|
+
static getVideoSize(blob: Blob, doc?: Document): Promise<{
|
|
1475
|
+
w: number;
|
|
1476
|
+
h: number;
|
|
1477
|
+
}>;
|
|
1478
|
+
/**
|
|
1479
|
+
* Get the size of an image blob
|
|
1480
|
+
*
|
|
1481
|
+
* @param blob - A Blob containing the image
|
|
1482
|
+
* @param doc - Optional document to use for DOM operations
|
|
1483
|
+
* @returns Promise that resolves to an object with width and height properties
|
|
1484
|
+
* @example
|
|
1485
|
+
* ```ts
|
|
1486
|
+
* const file = new File([...], 'image.png', { type: 'image/png' })
|
|
1487
|
+
* const { w, h } = await MediaHelpers.getImageSize(file)
|
|
1488
|
+
* console.log(`Image dimensions: ${w}x${h}`)
|
|
1489
|
+
* ```
|
|
1490
|
+
* @public
|
|
1491
|
+
*/
|
|
1492
|
+
static getImageSize(blob: Blob, doc?: Document): Promise<{
|
|
1493
|
+
w: number;
|
|
1494
|
+
h: number;
|
|
1495
|
+
pixelRatio: number;
|
|
1496
|
+
}>;
|
|
1497
|
+
/**
|
|
1498
|
+
* Check if a media file blob contains animation data.
|
|
1499
|
+
*
|
|
1500
|
+
* @param file - The Blob to check for animation
|
|
1501
|
+
* @returns Promise that resolves to true if the file is animated, false otherwise
|
|
1502
|
+
* @example
|
|
1503
|
+
* ```ts
|
|
1504
|
+
* const file = new File([...], 'animation.gif', { type: 'image/gif' })
|
|
1505
|
+
* const animated = await MediaHelpers.isAnimated(file)
|
|
1506
|
+
* console.log(animated ? 'Animated' : 'Static')
|
|
1507
|
+
* ```
|
|
1508
|
+
* @public
|
|
1509
|
+
*/
|
|
1510
|
+
static isAnimated(file: Blob): Promise<boolean>;
|
|
1511
|
+
/**
|
|
1512
|
+
* Check if a MIME type represents an animated image format.
|
|
1513
|
+
*
|
|
1514
|
+
* @param mimeType - The MIME type to check
|
|
1515
|
+
* @returns True if the MIME type is an animated image format, false otherwise
|
|
1516
|
+
* @example
|
|
1517
|
+
* ```ts
|
|
1518
|
+
* const isAnimated = MediaHelpers.isAnimatedImageType('image/gif')
|
|
1519
|
+
* console.log(isAnimated) // true
|
|
1520
|
+
* ```
|
|
1521
|
+
* @public
|
|
1522
|
+
*/
|
|
1523
|
+
static isAnimatedImageType(mimeType: string | null): boolean;
|
|
1524
|
+
/**
|
|
1525
|
+
* Check if a MIME type represents a static (non-animated) image format.
|
|
1526
|
+
*
|
|
1527
|
+
* @param mimeType - The MIME type to check
|
|
1528
|
+
* @returns True if the MIME type is a static image format, false otherwise
|
|
1529
|
+
* @example
|
|
1530
|
+
* ```ts
|
|
1531
|
+
* const isStatic = MediaHelpers.isStaticImageType('image/jpeg')
|
|
1532
|
+
* console.log(isStatic) // true
|
|
1533
|
+
* ```
|
|
1534
|
+
* @public
|
|
1535
|
+
*/
|
|
1536
|
+
static isStaticImageType(mimeType: string | null): boolean;
|
|
1537
|
+
/**
|
|
1538
|
+
* Check if a MIME type represents a vector image format.
|
|
1539
|
+
*
|
|
1540
|
+
* @param mimeType - The MIME type to check
|
|
1541
|
+
* @returns True if the MIME type is a vector image format, false otherwise
|
|
1542
|
+
* @example
|
|
1543
|
+
* ```ts
|
|
1544
|
+
* const isVector = MediaHelpers.isVectorImageType('image/svg+xml')
|
|
1545
|
+
* console.log(isVector) // true
|
|
1546
|
+
* ```
|
|
1547
|
+
* @public
|
|
1548
|
+
*/
|
|
1549
|
+
static isVectorImageType(mimeType: string | null): boolean;
|
|
1550
|
+
/**
|
|
1551
|
+
* Check if a MIME type represents any supported image format (static, animated, or vector).
|
|
1552
|
+
*
|
|
1553
|
+
* @param mimeType - The MIME type to check
|
|
1554
|
+
* @returns True if the MIME type is a supported image format, false otherwise
|
|
1555
|
+
* @example
|
|
1556
|
+
* ```ts
|
|
1557
|
+
* const isImage = MediaHelpers.isImageType('image/png')
|
|
1558
|
+
* console.log(isImage) // true
|
|
1559
|
+
* ```
|
|
1560
|
+
* @public
|
|
1561
|
+
*/
|
|
1562
|
+
static isImageType(mimeType: string): boolean;
|
|
1563
|
+
/**
|
|
1564
|
+
* Utility function to create an object URL from a blob, execute a function with it, and automatically clean it up.
|
|
1565
|
+
*
|
|
1566
|
+
* @param blob - The Blob to create an object URL for
|
|
1567
|
+
* @param fn - Function to execute with the object URL
|
|
1568
|
+
* @returns Promise that resolves to the result of the function
|
|
1569
|
+
* @example
|
|
1570
|
+
* ```ts
|
|
1571
|
+
* const result = await MediaHelpers.usingObjectURL(imageBlob, async (url) => {
|
|
1572
|
+
* const { w, h } = await MediaHelpers.getImageAndDimensions(url)
|
|
1573
|
+
* return { width: w, height: h }
|
|
1574
|
+
* })
|
|
1575
|
+
* // Object URL is automatically revoked after function completes
|
|
1576
|
+
* console.log(`Image dimensions: ${result.width}x${result.height}`)
|
|
1577
|
+
* ```
|
|
1578
|
+
* @public
|
|
1579
|
+
*/
|
|
1580
|
+
static usingObjectURL<T>(blob: Blob, fn: (url: string) => Promise<T>): Promise<T>;
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
/*!
|
|
1584
|
+
* MIT License: https://github.com/alexgorbatchev/crc/blob/master/LICENSE
|
|
1585
|
+
* Copyright: 2014 Alex Gorbatchev
|
|
1586
|
+
* Code: crc32, https://github.com/alexgorbatchev/crc/blob/master/src/calculators/crc32.ts
|
|
1587
|
+
*/
|
|
1588
|
+
/**
|
|
1589
|
+
* Utility class for reading and manipulating PNG image files.
|
|
1590
|
+
* Provides methods for parsing PNG chunks, validating PNG format, and modifying PNG metadata.
|
|
1591
|
+
*
|
|
1592
|
+
* @example
|
|
1593
|
+
* ```ts
|
|
1594
|
+
* // Validate PNG file from blob
|
|
1595
|
+
* const blob = new Blob([pngData], { type: 'image/png' })
|
|
1596
|
+
* const view = new DataView(await blob.arrayBuffer())
|
|
1597
|
+
* const isPng = PngHelpers.isPng(view, 0)
|
|
1598
|
+
*
|
|
1599
|
+
* // Parse PNG metadata for image processing
|
|
1600
|
+
* const chunks = PngHelpers.readChunks(view)
|
|
1601
|
+
* const physChunk = PngHelpers.findChunk(view, 'pHYs')
|
|
1602
|
+
*
|
|
1603
|
+
* // Create high-DPI PNG for export
|
|
1604
|
+
* const highDpiBlob = PngHelpers.setPhysChunk(view, 2, { type: 'image/png' })
|
|
1605
|
+
* ```
|
|
1606
|
+
*
|
|
1607
|
+
* @public
|
|
1608
|
+
*/
|
|
1609
|
+
declare class PngHelpers {
|
|
1610
|
+
/**
|
|
1611
|
+
* Checks if binary data at the specified offset contains a valid PNG file signature.
|
|
1612
|
+
* Validates the 8-byte PNG signature: 89 50 4E 47 0D 0A 1A 0A.
|
|
1613
|
+
*
|
|
1614
|
+
* @param view - DataView containing the binary data to check
|
|
1615
|
+
* @param offset - Byte offset where the PNG signature should start
|
|
1616
|
+
* @returns True if the data contains a valid PNG signature, false otherwise
|
|
1617
|
+
*
|
|
1618
|
+
* @example
|
|
1619
|
+
* ```ts
|
|
1620
|
+
* // Validate PNG from file upload
|
|
1621
|
+
* const file = event.target.files[0]
|
|
1622
|
+
* const buffer = await file.arrayBuffer()
|
|
1623
|
+
* const view = new DataView(buffer)
|
|
1624
|
+
*
|
|
1625
|
+
* if (PngHelpers.isPng(view, 0)) {
|
|
1626
|
+
* console.log('Valid PNG file detected')
|
|
1627
|
+
* // Process PNG file...
|
|
1628
|
+
* } else {
|
|
1629
|
+
* console.error('Not a valid PNG file')
|
|
1630
|
+
* }
|
|
1631
|
+
* ```
|
|
1632
|
+
*/
|
|
1633
|
+
static isPng(view: DataView, offset: number): boolean;
|
|
1634
|
+
/**
|
|
1635
|
+
* Reads the 4-character chunk type identifier from a PNG chunk header.
|
|
1636
|
+
*
|
|
1637
|
+
* @param view - DataView containing the PNG data
|
|
1638
|
+
* @param offset - Byte offset of the chunk type field (after length field)
|
|
1639
|
+
* @returns 4-character string representing the chunk type (e.g., 'IHDR', 'IDAT', 'IEND')
|
|
1640
|
+
*
|
|
1641
|
+
* @example
|
|
1642
|
+
* ```ts
|
|
1643
|
+
* // Read chunk type from PNG header (after 8-byte signature)
|
|
1644
|
+
* const chunkType = PngHelpers.getChunkType(dataView, 8)
|
|
1645
|
+
* console.log(chunkType) // 'IHDR' (Image Header)
|
|
1646
|
+
*
|
|
1647
|
+
* // Read chunk type at a specific position during parsing
|
|
1648
|
+
* let offset = 8 // Skip PNG signature
|
|
1649
|
+
* const chunkLength = dataView.getUint32(offset)
|
|
1650
|
+
* const type = PngHelpers.getChunkType(dataView, offset + 4)
|
|
1651
|
+
* ```
|
|
1652
|
+
*/
|
|
1653
|
+
static getChunkType(view: DataView, offset: number): string;
|
|
1654
|
+
/**
|
|
1655
|
+
* Parses all chunks in a PNG file and returns their metadata.
|
|
1656
|
+
* Skips duplicate IDAT chunks but includes all other chunk types.
|
|
1657
|
+
*
|
|
1658
|
+
* @param view - DataView containing the complete PNG file data
|
|
1659
|
+
* @param offset - Starting byte offset (defaults to 0)
|
|
1660
|
+
* @returns Record mapping chunk types to their metadata (start position, data offset, and size)
|
|
1661
|
+
* @throws Error if the data is not a valid PNG file
|
|
1662
|
+
*
|
|
1663
|
+
* @example
|
|
1664
|
+
* ```ts
|
|
1665
|
+
* // Parse PNG structure for metadata extraction
|
|
1666
|
+
* const view = new DataView(await blob.arrayBuffer())
|
|
1667
|
+
* const chunks = PngHelpers.readChunks(view)
|
|
1668
|
+
*
|
|
1669
|
+
* // Check for specific chunks
|
|
1670
|
+
* const ihdrChunk = chunks['IHDR']
|
|
1671
|
+
* const physChunk = chunks['pHYs']
|
|
1672
|
+
*
|
|
1673
|
+
* if (physChunk) {
|
|
1674
|
+
* console.log(`Found pixel density info at byte ${physChunk.start}`)
|
|
1675
|
+
* } else {
|
|
1676
|
+
* console.log('No pixel density information found')
|
|
1677
|
+
* }
|
|
1678
|
+
* ```
|
|
1679
|
+
*/
|
|
1680
|
+
static readChunks(view: DataView, offset?: number): Record<string, {
|
|
1681
|
+
dataOffset: number;
|
|
1682
|
+
size: number;
|
|
1683
|
+
start: number;
|
|
1684
|
+
}>;
|
|
1685
|
+
/**
|
|
1686
|
+
* Parses the pHYs (physical pixel dimensions) chunk data.
|
|
1687
|
+
* Reads pixels per unit for X and Y axes, and the unit specifier.
|
|
1688
|
+
*
|
|
1689
|
+
* @param view - DataView containing the PNG data
|
|
1690
|
+
* @param offset - Byte offset of the pHYs chunk data
|
|
1691
|
+
* @returns Object with ppux (pixels per unit X), ppuy (pixels per unit Y), and unit specifier
|
|
1692
|
+
*
|
|
1693
|
+
* @example
|
|
1694
|
+
* ```ts
|
|
1695
|
+
* // Extract pixel density information for DPI calculation
|
|
1696
|
+
* const physChunk = PngHelpers.findChunk(dataView, 'pHYs')
|
|
1697
|
+
* if (physChunk) {
|
|
1698
|
+
* const physData = PngHelpers.parsePhys(dataView, physChunk.dataOffset)
|
|
1699
|
+
*
|
|
1700
|
+
* if (physData.unit === 1) { // meters
|
|
1701
|
+
* const dpiX = Math.round(physData.ppux * 0.0254)
|
|
1702
|
+
* const dpiY = Math.round(physData.ppuy * 0.0254)
|
|
1703
|
+
* console.log(`DPI: ${dpiX} x ${dpiY}`)
|
|
1704
|
+
* }
|
|
1705
|
+
* }
|
|
1706
|
+
* ```
|
|
1707
|
+
*/
|
|
1708
|
+
static parsePhys(view: DataView, offset: number): {
|
|
1709
|
+
ppux: number;
|
|
1710
|
+
ppuy: number;
|
|
1711
|
+
unit: number;
|
|
1712
|
+
};
|
|
1713
|
+
/**
|
|
1714
|
+
* Finds a specific chunk type in the PNG file and returns its metadata.
|
|
1715
|
+
*
|
|
1716
|
+
* @param view - DataView containing the PNG file data
|
|
1717
|
+
* @param type - 4-character chunk type to search for (e.g., 'pHYs', 'IDAT')
|
|
1718
|
+
* @returns Chunk metadata object if found, undefined otherwise
|
|
1719
|
+
*
|
|
1720
|
+
* @example
|
|
1721
|
+
* ```ts
|
|
1722
|
+
* // Look for pixel density information in PNG
|
|
1723
|
+
* const physChunk = PngHelpers.findChunk(dataView, 'pHYs')
|
|
1724
|
+
* if (physChunk) {
|
|
1725
|
+
* const physData = PngHelpers.parsePhys(dataView, physChunk.dataOffset)
|
|
1726
|
+
* console.log(`Found pHYs chunk with ${physData.ppux} x ${physData.ppuy} pixels per unit`)
|
|
1727
|
+
* }
|
|
1728
|
+
*
|
|
1729
|
+
* // Check for text metadata
|
|
1730
|
+
* const textChunk = PngHelpers.findChunk(dataView, 'tEXt')
|
|
1731
|
+
* if (textChunk) {
|
|
1732
|
+
* console.log(`Found text metadata at byte ${textChunk.start}`)
|
|
1733
|
+
* }
|
|
1734
|
+
* ```
|
|
1735
|
+
*/
|
|
1736
|
+
static findChunk(view: DataView, type: string): {
|
|
1737
|
+
dataOffset: number;
|
|
1738
|
+
size: number;
|
|
1739
|
+
start: number;
|
|
1740
|
+
};
|
|
1741
|
+
/**
|
|
1742
|
+
* Adds or replaces a pHYs chunk in a PNG file to set pixel density for high-DPI displays.
|
|
1743
|
+
* The method determines insertion point by prioritizing IDAT chunk position over existing pHYs,
|
|
1744
|
+
* creates a properly formatted pHYs chunk with CRC validation, and returns a new Blob.
|
|
1745
|
+
*
|
|
1746
|
+
* @param view - DataView containing the original PNG file data
|
|
1747
|
+
* @param dpr - Device pixel ratio multiplier (defaults to 1)
|
|
1748
|
+
* @param options - Optional Blob constructor options for MIME type and other properties
|
|
1749
|
+
* @returns New Blob containing the PNG with updated pixel density information
|
|
1750
|
+
*
|
|
1751
|
+
* @example
|
|
1752
|
+
* ```ts
|
|
1753
|
+
* // Export PNG with proper pixel density for high-DPI displays
|
|
1754
|
+
* const canvas = document.createElement('canvas')
|
|
1755
|
+
* const ctx = canvas.getContext('2d')
|
|
1756
|
+
* // ... draw content to canvas ...
|
|
1757
|
+
*
|
|
1758
|
+
* canvas.toBlob(async (blob) => {
|
|
1759
|
+
* if (blob) {
|
|
1760
|
+
* const view = new DataView(await blob.arrayBuffer())
|
|
1761
|
+
* // Create 2x DPI version for Retina displays
|
|
1762
|
+
* const highDpiBlob = PngHelpers.setPhysChunk(view, 2, { type: 'image/png' })
|
|
1763
|
+
* // Download or use the blob...
|
|
1764
|
+
* }
|
|
1765
|
+
* }, 'image/png')
|
|
1766
|
+
* ```
|
|
1767
|
+
*/
|
|
1768
|
+
static setPhysChunk(view: DataView, dpr?: number, options?: BlobPropertyBag): Blob;
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
/**
|
|
1772
|
+
* Just a wrapper around `window.fetch` that sets the `referrerPolicy` to `strict-origin-when-cross-origin`.
|
|
1773
|
+
*
|
|
1774
|
+
* @param input - A Request object or string containing the URL to fetch
|
|
1775
|
+
* @param init - Optional request initialization options
|
|
1776
|
+
* @returns Promise that resolves to the Response object
|
|
1777
|
+
* @internal
|
|
1778
|
+
*/
|
|
1779
|
+
declare function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
1780
|
+
/**
|
|
1781
|
+
* Just a wrapper around `new Image`, and yeah, it's a bit strange that it's in the network.ts file
|
|
1782
|
+
* but the main concern here is the referrerPolicy and setting it correctly.
|
|
1783
|
+
*
|
|
1784
|
+
* @param width - Optional width for the image element
|
|
1785
|
+
* @param height - Optional height for the image element
|
|
1786
|
+
* @returns HTMLImageElement with referrerPolicy set to 'strict-origin-when-cross-origin'
|
|
1787
|
+
* @internal
|
|
1788
|
+
*/
|
|
1789
|
+
declare const Image: (width?: number, height?: number) => HTMLImageElement;
|
|
1790
|
+
|
|
1791
|
+
/**
|
|
1792
|
+
* Linear interpolate between two values.
|
|
1793
|
+
*
|
|
1794
|
+
* @param a - The start value
|
|
1795
|
+
* @param b - The end value
|
|
1796
|
+
* @param t - The interpolation factor (0-1)
|
|
1797
|
+
* @returns The interpolated value
|
|
1798
|
+
* @example
|
|
1799
|
+
* ```ts
|
|
1800
|
+
* const halfway = lerp(0, 100, 0.5) // 50
|
|
1801
|
+
* const quarter = lerp(10, 20, 0.25) // 12.5
|
|
1802
|
+
* ```
|
|
1803
|
+
* @public
|
|
1804
|
+
*/
|
|
1805
|
+
declare function lerp(a: number, b: number, t: number): number;
|
|
1806
|
+
/**
|
|
1807
|
+
* Inverse lerp between two values. Given a value `t` in the range [a, b], returns a number between
|
|
1808
|
+
* 0 and 1.
|
|
1809
|
+
*
|
|
1810
|
+
* @param a - The start value of the range
|
|
1811
|
+
* @param b - The end value of the range
|
|
1812
|
+
* @param t - The value within the range [a, b]
|
|
1813
|
+
* @returns The normalized position (0-1) of t within the range [a, b]
|
|
1814
|
+
* @example
|
|
1815
|
+
* ```ts
|
|
1816
|
+
* const position = invLerp(0, 100, 25) // 0.25
|
|
1817
|
+
* const normalized = invLerp(10, 20, 15) // 0.5
|
|
1818
|
+
* ```
|
|
1819
|
+
* @public
|
|
1820
|
+
*/
|
|
1821
|
+
declare function invLerp(a: number, b: number, t: number): number;
|
|
1822
|
+
/**
|
|
1823
|
+
* Seeded random number generator, using [xorshift](https://en.wikipedia.org/wiki/Xorshift). The
|
|
1824
|
+
* result will always be between -1 and 1.
|
|
1825
|
+
*
|
|
1826
|
+
* Adapted from [seedrandom](https://github.com/davidbau/seedrandom).
|
|
1827
|
+
*
|
|
1828
|
+
* @param seed - The seed string for deterministic random generation (defaults to empty string)
|
|
1829
|
+
* @returns A function that will return a random number between -1 and 1 each time it is called
|
|
1830
|
+
* @example
|
|
1831
|
+
* ```ts
|
|
1832
|
+
* const random = rng('my-seed')
|
|
1833
|
+
* const num1 = random() // Always the same for this seed
|
|
1834
|
+
* const num2 = random() // Next number in sequence
|
|
1835
|
+
*
|
|
1836
|
+
* // Different seed produces different sequence
|
|
1837
|
+
* const otherRandom = rng('other-seed')
|
|
1838
|
+
* const different = otherRandom() // Different value
|
|
1839
|
+
* ```
|
|
1840
|
+
* @public
|
|
1841
|
+
*/
|
|
1842
|
+
declare function rng(seed?: string): () => number;
|
|
1843
|
+
/**
|
|
1844
|
+
* Modulate a value between two ranges.
|
|
1845
|
+
*
|
|
1846
|
+
* @example
|
|
1847
|
+
*
|
|
1848
|
+
* ```ts
|
|
1849
|
+
* const A = modulate(0, [0, 1], [0, 100]) // 0
|
|
1850
|
+
* const B = modulate(0.5, [0, 1], [0, 100]) // 50
|
|
1851
|
+
* const C = modulate(1, [0, 1], [0, 100]) // 100
|
|
1852
|
+
* ```
|
|
1853
|
+
*
|
|
1854
|
+
* @param value - The interpolation value.
|
|
1855
|
+
* @param rangeA - From [low, high]
|
|
1856
|
+
* @param rangeB - To [low, high]
|
|
1857
|
+
* @param clamp - Whether to clamp the the result to [low, high]
|
|
1858
|
+
* @public
|
|
1859
|
+
*/
|
|
1860
|
+
declare function modulate(value: number, rangeA: number[], rangeB: number[], clamp?: boolean): number;
|
|
1861
|
+
|
|
1862
|
+
/**
|
|
1863
|
+
* Safely checks if an object has a specific property as its own property (not inherited).
|
|
1864
|
+
* Uses Object.prototype.hasOwnProperty.call to avoid issues with objects that have null prototype
|
|
1865
|
+
* or have overridden the hasOwnProperty method.
|
|
1866
|
+
*
|
|
1867
|
+
* @param obj - The object to check
|
|
1868
|
+
* @param key - The property key to check for
|
|
1869
|
+
* @returns True if the object has the property as its own property, false otherwise
|
|
1870
|
+
* @example
|
|
1871
|
+
* ```ts
|
|
1872
|
+
* const obj = { name: 'Alice', age: 30 }
|
|
1873
|
+
* hasOwnProperty(obj, 'name') // true
|
|
1874
|
+
* hasOwnProperty(obj, 'toString') // false (inherited)
|
|
1875
|
+
* hasOwnProperty(obj, 'unknown') // false
|
|
1876
|
+
* ```
|
|
1877
|
+
* @internal
|
|
1878
|
+
*/
|
|
1879
|
+
declare function hasOwnProperty(obj: object, key: string): boolean;
|
|
1880
|
+
/**
|
|
1881
|
+
* Safely gets an object's own property value (not inherited). Returns undefined if the property
|
|
1882
|
+
* doesn't exist as an own property. Provides type-safe access with proper TypeScript inference.
|
|
1883
|
+
*
|
|
1884
|
+
* @param obj - The object to get the property from
|
|
1885
|
+
* @param key - The property key to retrieve
|
|
1886
|
+
* @returns The property value if it exists as an own property, undefined otherwise
|
|
1887
|
+
* @example
|
|
1888
|
+
* ```ts
|
|
1889
|
+
* const user = { name: 'Alice', age: 30 }
|
|
1890
|
+
* const name = getOwnProperty(user, 'name') // 'Alice'
|
|
1891
|
+
* const missing = getOwnProperty(user, 'unknown') // undefined
|
|
1892
|
+
* const inherited = getOwnProperty(user, 'toString') // undefined (inherited)
|
|
1893
|
+
* ```
|
|
1894
|
+
* @internal
|
|
1895
|
+
*/
|
|
1896
|
+
declare function getOwnProperty<K extends string, V>(obj: Partial<Record<K, V>>, key: K): V | undefined;
|
|
1897
|
+
/** @internal */
|
|
1898
|
+
declare function getOwnProperty<O extends object>(obj: O, key: string): O[keyof O] | undefined;
|
|
1899
|
+
/** @internal */
|
|
1900
|
+
declare function getOwnProperty(obj: object, key: string): unknown;
|
|
1901
|
+
/**
|
|
1902
|
+
* An alias for `Object.keys` that treats the object as a map and so preserves the type of the keys.
|
|
1903
|
+
* Unlike standard Object.keys which returns string[], this maintains the specific string literal types.
|
|
1904
|
+
*
|
|
1905
|
+
* @param object - The object to get keys from
|
|
1906
|
+
* @returns Array of keys with preserved string literal types
|
|
1907
|
+
* @example
|
|
1908
|
+
* ```ts
|
|
1909
|
+
* const config = { theme: 'dark', lang: 'en' } as const
|
|
1910
|
+
* const keys = objectMapKeys(config)
|
|
1911
|
+
* // keys is Array<'theme' | 'lang'> instead of string[]
|
|
1912
|
+
* ```
|
|
1913
|
+
* @internal
|
|
1914
|
+
*/
|
|
1915
|
+
declare function objectMapKeys<Key extends string>(object: {
|
|
1916
|
+
readonly [K in Key]: unknown;
|
|
1917
|
+
}): Array<Key>;
|
|
1918
|
+
/**
|
|
1919
|
+
* An alias for `Object.values` that treats the object as a map and so preserves the type of the
|
|
1920
|
+
* values. Unlike standard Object.values which returns unknown[], this maintains the specific value types.
|
|
1921
|
+
*
|
|
1922
|
+
* @param object - The object to get values from
|
|
1923
|
+
* @returns Array of values with preserved types
|
|
1924
|
+
* @example
|
|
1925
|
+
* ```ts
|
|
1926
|
+
* const scores = { alice: 85, bob: 92, charlie: 78 }
|
|
1927
|
+
* const values = objectMapValues(scores)
|
|
1928
|
+
* // values is Array<number> instead of unknown[]
|
|
1929
|
+
* ```
|
|
1930
|
+
* @internal
|
|
1931
|
+
*/
|
|
1932
|
+
declare function objectMapValues<Key extends string, Value>(object: {
|
|
1933
|
+
[K in Key]: Value;
|
|
1934
|
+
}): Array<Value>;
|
|
1935
|
+
/**
|
|
1936
|
+
* An alias for `Object.entries` that treats the object as a map and so preserves the type of the
|
|
1937
|
+
* keys and values. Unlike standard Object.entries which returns `Array<[string, unknown]>`, this maintains specific types.
|
|
1938
|
+
*
|
|
1939
|
+
* @param object - The object to get entries from
|
|
1940
|
+
* @returns Array of key-value pairs with preserved types
|
|
1941
|
+
* @example
|
|
1942
|
+
* ```ts
|
|
1943
|
+
* const user = { name: 'Alice', age: 30 }
|
|
1944
|
+
* const entries = objectMapEntries(user)
|
|
1945
|
+
* // entries is Array<['name' | 'age', string | number]>
|
|
1946
|
+
* ```
|
|
1947
|
+
* @internal
|
|
1948
|
+
*/
|
|
1949
|
+
declare function objectMapEntries<Obj extends object>(object: Obj): Array<[keyof Obj, Obj[keyof Obj]]>;
|
|
1950
|
+
/**
|
|
1951
|
+
* Returns the entries of an object as an iterable iterator.
|
|
1952
|
+
* Useful when working with large collections, to avoid allocating an array.
|
|
1953
|
+
* Only yields own properties (not inherited ones).
|
|
1954
|
+
*
|
|
1955
|
+
* @param object - The object to iterate over
|
|
1956
|
+
* @returns Iterator yielding key-value pairs with preserved types
|
|
1957
|
+
* @example
|
|
1958
|
+
* ```ts
|
|
1959
|
+
* const largeMap = { a: 1, b: 2, c: 3 } // Imagine thousands of entries
|
|
1960
|
+
* for (const [key, value] of objectMapEntriesIterable(largeMap)) {
|
|
1961
|
+
* // Process entries one at a time without creating a large array
|
|
1962
|
+
* console.log(key, value)
|
|
1963
|
+
* }
|
|
1964
|
+
* ```
|
|
1965
|
+
* @internal
|
|
1966
|
+
*/
|
|
1967
|
+
declare function objectMapEntriesIterable<Key extends string, Value>(object: {
|
|
1968
|
+
[K in Key]: Value;
|
|
1969
|
+
}): IterableIterator<[Key, Value]>;
|
|
1970
|
+
/**
|
|
1971
|
+
* An alias for `Object.fromEntries` that treats the object as a map and so preserves the type of the
|
|
1972
|
+
* keys and values. Creates an object from key-value pairs with proper TypeScript typing.
|
|
1973
|
+
*
|
|
1974
|
+
* @param entries - Array of key-value pairs to convert to an object
|
|
1975
|
+
* @returns Object with preserved key and value types
|
|
1976
|
+
* @example
|
|
1977
|
+
* ```ts
|
|
1978
|
+
* const pairs: Array<['name' | 'age', string | number]> = [['name', 'Alice'], ['age', 30]]
|
|
1979
|
+
* const obj = objectMapFromEntries(pairs)
|
|
1980
|
+
* // obj is { name: string | number, age: string | number }
|
|
1981
|
+
* ```
|
|
1982
|
+
* @internal
|
|
1983
|
+
*/
|
|
1984
|
+
declare function objectMapFromEntries<Key extends string, Value>(entries: ReadonlyArray<readonly [Key, Value]>): {
|
|
1985
|
+
[K in Key]: Value;
|
|
1986
|
+
};
|
|
1987
|
+
/**
|
|
1988
|
+
* Filters an object using a predicate function, returning a new object with only the entries
|
|
1989
|
+
* that pass the predicate. Optimized to return the original object if no changes are needed.
|
|
1990
|
+
*
|
|
1991
|
+
* @param object - The object to filter
|
|
1992
|
+
* @param predicate - Function that tests each key-value pair
|
|
1993
|
+
* @returns A new object with only the entries that pass the predicate, or the original object if unchanged
|
|
1994
|
+
* @example
|
|
1995
|
+
* ```ts
|
|
1996
|
+
* const scores = { alice: 85, bob: 92, charlie: 78 }
|
|
1997
|
+
* const passing = filterEntries(scores, (name, score) => score >= 80)
|
|
1998
|
+
* // { alice: 85, bob: 92 }
|
|
1999
|
+
* ```
|
|
2000
|
+
* @internal
|
|
2001
|
+
*/
|
|
2002
|
+
declare function filterEntries<Key extends string, Value>(object: {
|
|
2003
|
+
[K in Key]: Value;
|
|
2004
|
+
}, predicate: (key: Key, value: Value) => boolean): {
|
|
2005
|
+
[K in Key]: Value;
|
|
2006
|
+
};
|
|
2007
|
+
/**
|
|
2008
|
+
* Maps the values of an object to new values using a mapper function, preserving keys.
|
|
2009
|
+
* The mapper function receives both the key and value for each entry.
|
|
2010
|
+
*
|
|
2011
|
+
* @param object - The object whose values to transform
|
|
2012
|
+
* @param mapper - Function that transforms each value (receives key and value)
|
|
2013
|
+
* @returns A new object with the same keys but transformed values
|
|
2014
|
+
* @example
|
|
2015
|
+
* ```ts
|
|
2016
|
+
* const prices = { apple: 1.50, banana: 0.75, orange: 2.00 }
|
|
2017
|
+
* const withTax = mapObjectMapValues(prices, (fruit, price) => price * 1.08)
|
|
2018
|
+
* // { apple: 1.62, banana: 0.81, orange: 2.16 }
|
|
2019
|
+
* ```
|
|
2020
|
+
* @internal
|
|
2021
|
+
*/
|
|
2022
|
+
declare function mapObjectMapValues<Key extends string, ValueBefore, ValueAfter>(object: {
|
|
2023
|
+
readonly [K in Key]: ValueBefore;
|
|
2024
|
+
}, mapper: (key: Key, value: ValueBefore) => ValueAfter): {
|
|
2025
|
+
[K in Key]: ValueAfter;
|
|
2026
|
+
};
|
|
2027
|
+
/**
|
|
2028
|
+
* Performs a shallow equality check between two objects. Compares all enumerable own properties
|
|
2029
|
+
* using Object.is for value comparison. Returns true if both objects have the same keys and values.
|
|
2030
|
+
*
|
|
2031
|
+
* @param obj1 - First object to compare
|
|
2032
|
+
* @param obj2 - Second object to compare
|
|
2033
|
+
* @returns True if objects are shallow equal, false otherwise
|
|
2034
|
+
* @example
|
|
2035
|
+
* ```ts
|
|
2036
|
+
* const a = { x: 1, y: 2 }
|
|
2037
|
+
* const b = { x: 1, y: 2 }
|
|
2038
|
+
* const c = { x: 1, y: 3 }
|
|
2039
|
+
* areObjectsShallowEqual(a, b) // true
|
|
2040
|
+
* areObjectsShallowEqual(a, c) // false
|
|
2041
|
+
* areObjectsShallowEqual(a, a) // true (same reference)
|
|
2042
|
+
* ```
|
|
2043
|
+
* @internal
|
|
2044
|
+
*/
|
|
2045
|
+
declare function areObjectsShallowEqual<T extends object>(obj1: T, obj2: T): boolean;
|
|
2046
|
+
/**
|
|
2047
|
+
* Groups an array of values into a record by a key extracted from each value.
|
|
2048
|
+
* The key selector function is called for each element to determine the grouping key.
|
|
2049
|
+
*
|
|
2050
|
+
* @param array - The array to group
|
|
2051
|
+
* @param keySelector - Function that extracts the grouping key from each value
|
|
2052
|
+
* @returns A record where keys are the extracted keys and values are arrays of grouped items
|
|
2053
|
+
* @example
|
|
2054
|
+
* ```ts
|
|
2055
|
+
* const people = [
|
|
2056
|
+
* { name: 'Alice', age: 25 },
|
|
2057
|
+
* { name: 'Bob', age: 30 },
|
|
2058
|
+
* { name: 'Charlie', age: 25 }
|
|
2059
|
+
* ]
|
|
2060
|
+
* const byAge = groupBy(people, person => `age-${person.age}`)
|
|
2061
|
+
* // { 'age-25': [Alice, Charlie], 'age-30': [Bob] }
|
|
2062
|
+
* ```
|
|
2063
|
+
* @internal
|
|
2064
|
+
*/
|
|
2065
|
+
declare function groupBy<K extends string, V>(array: ReadonlyArray<V>, keySelector: (value: V) => K): Record<K, V[]>;
|
|
2066
|
+
/**
|
|
2067
|
+
* Creates a new object with specified keys omitted from the original object.
|
|
2068
|
+
* Uses shallow copying and then deletes the unwanted keys.
|
|
2069
|
+
*
|
|
2070
|
+
* @param obj - The source object
|
|
2071
|
+
* @param keys - Array of key names to omit from the result
|
|
2072
|
+
* @returns A new object without the specified keys
|
|
2073
|
+
* @example
|
|
2074
|
+
* ```ts
|
|
2075
|
+
* const user = { id: '123', name: 'Alice', password: 'secret', email: 'alice@example.com' }
|
|
2076
|
+
* const publicUser = omit(user, ['password'])
|
|
2077
|
+
* // { id: '123', name: 'Alice', email: 'alice@example.com' }
|
|
2078
|
+
* ```
|
|
2079
|
+
* @internal
|
|
2080
|
+
*/
|
|
2081
|
+
declare function omit(obj: Record<string, unknown>, keys: ReadonlyArray<string>): Record<string, unknown>;
|
|
2082
|
+
/**
|
|
2083
|
+
* Compares two objects and returns an array of keys where the values differ.
|
|
2084
|
+
* Uses Object.is for comparison, which handles NaN and -0/+0 correctly.
|
|
2085
|
+
* Only checks keys present in the first object.
|
|
2086
|
+
*
|
|
2087
|
+
* @param obj1 - The first object (keys to check come from this object)
|
|
2088
|
+
* @param obj2 - The second object to compare against
|
|
2089
|
+
* @returns Array of keys where values differ between the objects
|
|
2090
|
+
* @example
|
|
2091
|
+
* ```ts
|
|
2092
|
+
* const before = { name: 'Alice', age: 25, city: 'NYC' }
|
|
2093
|
+
* const after = { name: 'Alice', age: 26, city: 'NYC' }
|
|
2094
|
+
* const changed = getChangedKeys(before, after)
|
|
2095
|
+
* // ['age']
|
|
2096
|
+
* ```
|
|
2097
|
+
* @internal
|
|
2098
|
+
*/
|
|
2099
|
+
declare function getChangedKeys<T extends object>(obj1: T, obj2: T): (keyof T)[];
|
|
2100
|
+
/**
|
|
2101
|
+
* Deep equality comparison that allows for floating-point precision errors.
|
|
2102
|
+
* Numbers are considered equal if they differ by less than the threshold.
|
|
2103
|
+
* Uses lodash.isequalwith internally for the deep comparison logic.
|
|
2104
|
+
*
|
|
2105
|
+
* @param obj1 - First object to compare
|
|
2106
|
+
* @param obj2 - Second object to compare
|
|
2107
|
+
* @param threshold - Maximum difference allowed between numbers (default: 0.000001)
|
|
2108
|
+
* @returns True if objects are deeply equal with floating-point tolerance
|
|
2109
|
+
* @example
|
|
2110
|
+
* ```ts
|
|
2111
|
+
* const a = { x: 0.1 + 0.2 } // 0.30000000000000004
|
|
2112
|
+
* const b = { x: 0.3 }
|
|
2113
|
+
* isEqualAllowingForFloatingPointErrors(a, b) // true
|
|
2114
|
+
*
|
|
2115
|
+
* const c = { coords: [1.0000001, 2.0000001] }
|
|
2116
|
+
* const d = { coords: [1.0000002, 2.0000002] }
|
|
2117
|
+
* isEqualAllowingForFloatingPointErrors(c, d) // true
|
|
2118
|
+
* ```
|
|
2119
|
+
* @internal
|
|
2120
|
+
*/
|
|
2121
|
+
declare function isEqualAllowingForFloatingPointErrors(obj1: object, obj2: object, threshold?: number): boolean;
|
|
2122
|
+
|
|
2123
|
+
/**
|
|
2124
|
+
* Measures and logs the execution time of a callback function.
|
|
2125
|
+
* Executes the provided callback and logs the duration to the console with styled output.
|
|
2126
|
+
*
|
|
2127
|
+
* @param name - Descriptive name for the operation being measured
|
|
2128
|
+
* @param cb - Callback function to execute and measure
|
|
2129
|
+
* @returns The return value of the callback function
|
|
2130
|
+
*
|
|
2131
|
+
* @example
|
|
2132
|
+
* ```ts
|
|
2133
|
+
* const result = measureCbDuration('data processing', () => {
|
|
2134
|
+
* return processLargeDataSet(data)
|
|
2135
|
+
* })
|
|
2136
|
+
* // Console output: "Perf data processing took 42.5ms"
|
|
2137
|
+
* ```
|
|
2138
|
+
*
|
|
2139
|
+
* @internal
|
|
2140
|
+
*/
|
|
2141
|
+
declare function measureCbDuration(name: string, cb: () => any): any;
|
|
2142
|
+
/**
|
|
2143
|
+
* Decorator that measures and logs the execution time of class methods.
|
|
2144
|
+
* Wraps the decorated method to automatically log its execution duration.
|
|
2145
|
+
*
|
|
2146
|
+
* @param _target - The class prototype (unused)
|
|
2147
|
+
* @param propertyKey - Name of the method being decorated
|
|
2148
|
+
* @param descriptor - Property descriptor of the method
|
|
2149
|
+
* @returns Modified property descriptor with timing measurement
|
|
2150
|
+
*
|
|
2151
|
+
* @example
|
|
2152
|
+
* ```ts
|
|
2153
|
+
* class DataProcessor {
|
|
2154
|
+
* @measureDuration
|
|
2155
|
+
* processData(data: unknown[]) {
|
|
2156
|
+
* return data.map(item => transform(item))
|
|
2157
|
+
* }
|
|
2158
|
+
* }
|
|
2159
|
+
* // When processData is called, logs: "Perf processData took: 15.2ms"
|
|
2160
|
+
* ```
|
|
2161
|
+
*
|
|
2162
|
+
* @internal
|
|
2163
|
+
*/
|
|
2164
|
+
declare function measureDuration(_target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor;
|
|
2165
|
+
/**
|
|
2166
|
+
* Decorator that measures method execution time and tracks running averages.
|
|
2167
|
+
* Wraps the decorated method to log both current execution time and running average.
|
|
2168
|
+
* Maintains a running total and count for each decorated method to calculate averages.
|
|
2169
|
+
*
|
|
2170
|
+
* @param _target - The class prototype (unused)
|
|
2171
|
+
* @param propertyKey - Name of the method being decorated
|
|
2172
|
+
* @param descriptor - Property descriptor of the method
|
|
2173
|
+
* @returns Modified property descriptor with timing measurement and averaging
|
|
2174
|
+
*
|
|
2175
|
+
* @example
|
|
2176
|
+
* ```ts
|
|
2177
|
+
* class RenderEngine {
|
|
2178
|
+
* @measureAverageDuration
|
|
2179
|
+
* renderFrame() {
|
|
2180
|
+
* // Rendering logic here
|
|
2181
|
+
* }
|
|
2182
|
+
* }
|
|
2183
|
+
* // After multiple calls, logs: "Perf renderFrame took 16.67ms | average 15.83ms"
|
|
2184
|
+
* ```
|
|
2185
|
+
*
|
|
2186
|
+
* @internal
|
|
2187
|
+
*/
|
|
2188
|
+
declare function measureAverageDuration(_target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor;
|
|
2189
|
+
|
|
2190
|
+
/**
|
|
2191
|
+
* A utility class for measuring and tracking frame rate performance during operations.
|
|
2192
|
+
* Provides visual feedback in the browser console with color-coded FPS indicators.
|
|
2193
|
+
*
|
|
2194
|
+
* @example
|
|
2195
|
+
* ```ts
|
|
2196
|
+
* const tracker = new PerformanceTracker()
|
|
2197
|
+
*
|
|
2198
|
+
* tracker.start('render')
|
|
2199
|
+
* renderShapes()
|
|
2200
|
+
* tracker.stop() // Logs performance info to console
|
|
2201
|
+
*
|
|
2202
|
+
* // Check if tracking is active
|
|
2203
|
+
* if (tracker.isStarted()) {
|
|
2204
|
+
* console.log('Still tracking performance')
|
|
2205
|
+
* }
|
|
2206
|
+
* ```
|
|
2207
|
+
*
|
|
2208
|
+
* @public
|
|
2209
|
+
*/
|
|
2210
|
+
declare class PerformanceTracker {
|
|
2211
|
+
private startTime;
|
|
2212
|
+
private name;
|
|
2213
|
+
private frames;
|
|
2214
|
+
private started;
|
|
2215
|
+
private frame;
|
|
2216
|
+
/**
|
|
2217
|
+
* Records animation frames to calculate frame rate.
|
|
2218
|
+
* Called automatically during performance tracking.
|
|
2219
|
+
*/
|
|
2220
|
+
recordFrame: () => void;
|
|
2221
|
+
/**
|
|
2222
|
+
* Starts performance tracking for a named operation.
|
|
2223
|
+
*
|
|
2224
|
+
* @param name - A descriptive name for the operation being tracked
|
|
2225
|
+
*
|
|
2226
|
+
* @example
|
|
2227
|
+
* ```ts
|
|
2228
|
+
* tracker.start('canvas-render')
|
|
2229
|
+
* // ... perform rendering operations
|
|
2230
|
+
* tracker.stop()
|
|
2231
|
+
* ```
|
|
2232
|
+
*/
|
|
2233
|
+
start(name: string): void;
|
|
2234
|
+
/**
|
|
2235
|
+
* Stops performance tracking and logs results to the console.
|
|
2236
|
+
*
|
|
2237
|
+
* Displays the operation name, frame rate, and uses color coding:
|
|
2238
|
+
* - Green background: \> 55 FPS (good performance)
|
|
2239
|
+
* - Yellow background: 30-55 FPS (moderate performance)
|
|
2240
|
+
* - Red background: \< 30 FPS (poor performance)
|
|
2241
|
+
*
|
|
2242
|
+
* @example
|
|
2243
|
+
* ```ts
|
|
2244
|
+
* tracker.start('interaction')
|
|
2245
|
+
* handleUserInteraction()
|
|
2246
|
+
* tracker.stop() // Logs: "Perf Interaction 60 fps"
|
|
2247
|
+
* ```
|
|
2248
|
+
*/
|
|
2249
|
+
stop(): void;
|
|
2250
|
+
/**
|
|
2251
|
+
* Checks whether performance tracking is currently active.
|
|
2252
|
+
*
|
|
2253
|
+
* @returns True if tracking is in progress, false otherwise
|
|
2254
|
+
*
|
|
2255
|
+
* @example
|
|
2256
|
+
* ```ts
|
|
2257
|
+
* if (!tracker.isStarted()) {
|
|
2258
|
+
* tracker.start('new-operation')
|
|
2259
|
+
* }
|
|
2260
|
+
* ```
|
|
2261
|
+
*/
|
|
2262
|
+
isStarted(): boolean;
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
/**
|
|
2266
|
+
* A string made up of an integer part followed by a fraction part. The fraction point consists of
|
|
2267
|
+
* zero or more digits with no trailing zeros. Based on
|
|
2268
|
+
* {@link https://observablehq.com/@dgreensp/implementing-fractional-indexing}.
|
|
2269
|
+
*
|
|
2270
|
+
* @public
|
|
2271
|
+
*/
|
|
2272
|
+
type IndexKey = string & {
|
|
2273
|
+
__brand: 'indexKey';
|
|
2274
|
+
};
|
|
2275
|
+
/**
|
|
2276
|
+
* The index key for the first index - 'a0'.
|
|
2277
|
+
* @public
|
|
2278
|
+
*/
|
|
2279
|
+
declare const ZERO_INDEX_KEY: IndexKey;
|
|
2280
|
+
/**
|
|
2281
|
+
* Validates that a string is a valid IndexKey.
|
|
2282
|
+
* @param index - The string to validate.
|
|
2283
|
+
* @throws Error if the index is invalid.
|
|
2284
|
+
* @internal
|
|
2285
|
+
*/
|
|
2286
|
+
declare function validateIndexKey(index: string): asserts index is IndexKey;
|
|
2287
|
+
/**
|
|
2288
|
+
* Get a number of indices between two indices.
|
|
2289
|
+
* @param below - The index below.
|
|
2290
|
+
* @param above - The index above.
|
|
2291
|
+
* @param n - The number of indices to get.
|
|
2292
|
+
* @returns An array of n IndexKey values between below and above.
|
|
2293
|
+
* @example
|
|
2294
|
+
* ```ts
|
|
2295
|
+
* const indices = getIndicesBetween('a0' as IndexKey, 'a2' as IndexKey, 2)
|
|
2296
|
+
* console.log(indices) // ['a0V', 'a1']
|
|
2297
|
+
* ```
|
|
2298
|
+
* @public
|
|
2299
|
+
*/
|
|
2300
|
+
declare function getIndicesBetween(below: IndexKey | null | undefined, above: IndexKey | null | undefined, n: number): IndexKey[];
|
|
2301
|
+
/**
|
|
2302
|
+
* Get a number of indices above an index.
|
|
2303
|
+
* @param below - The index below.
|
|
2304
|
+
* @param n - The number of indices to get.
|
|
2305
|
+
* @returns An array of n IndexKey values above the given index.
|
|
2306
|
+
* @example
|
|
2307
|
+
* ```ts
|
|
2308
|
+
* const indices = getIndicesAbove('a0' as IndexKey, 3)
|
|
2309
|
+
* console.log(indices) // ['a1', 'a2', 'a3']
|
|
2310
|
+
* ```
|
|
2311
|
+
* @public
|
|
2312
|
+
*/
|
|
2313
|
+
declare function getIndicesAbove(below: IndexKey | null | undefined, n: number): IndexKey[];
|
|
2314
|
+
/**
|
|
2315
|
+
* Get a number of indices below an index.
|
|
2316
|
+
* @param above - The index above.
|
|
2317
|
+
* @param n - The number of indices to get.
|
|
2318
|
+
* @returns An array of n IndexKey values below the given index.
|
|
2319
|
+
* @example
|
|
2320
|
+
* ```ts
|
|
2321
|
+
* const indices = getIndicesBelow('a2' as IndexKey, 2)
|
|
2322
|
+
* console.log(indices) // ['a1', 'a0V']
|
|
2323
|
+
* ```
|
|
2324
|
+
* @public
|
|
2325
|
+
*/
|
|
2326
|
+
declare function getIndicesBelow(above: IndexKey | null | undefined, n: number): IndexKey[];
|
|
2327
|
+
/**
|
|
2328
|
+
* Get the index between two indices.
|
|
2329
|
+
* @param below - The index below.
|
|
2330
|
+
* @param above - The index above.
|
|
2331
|
+
* @returns A single IndexKey value between below and above.
|
|
2332
|
+
* @example
|
|
2333
|
+
* ```ts
|
|
2334
|
+
* const index = getIndexBetween('a0' as IndexKey, 'a2' as IndexKey)
|
|
2335
|
+
* console.log(index) // 'a1'
|
|
2336
|
+
* ```
|
|
2337
|
+
* @public
|
|
2338
|
+
*/
|
|
2339
|
+
declare function getIndexBetween(below: IndexKey | null | undefined, above: IndexKey | null | undefined): IndexKey;
|
|
2340
|
+
/**
|
|
2341
|
+
* Get the index above a given index.
|
|
2342
|
+
* @param below - The index below.
|
|
2343
|
+
* @returns An IndexKey value above the given index.
|
|
2344
|
+
* @example
|
|
2345
|
+
* ```ts
|
|
2346
|
+
* const index = getIndexAbove('a0' as IndexKey)
|
|
2347
|
+
* console.log(index) // 'a1'
|
|
2348
|
+
* ```
|
|
2349
|
+
* @public
|
|
2350
|
+
*/
|
|
2351
|
+
declare function getIndexAbove(below?: IndexKey | null | undefined): IndexKey;
|
|
2352
|
+
/**
|
|
2353
|
+
* Get the index below a given index.
|
|
2354
|
+
* @param above - The index above.
|
|
2355
|
+
* @returns An IndexKey value below the given index.
|
|
2356
|
+
* @example
|
|
2357
|
+
* ```ts
|
|
2358
|
+
* const index = getIndexBelow('a2' as IndexKey)
|
|
2359
|
+
* console.log(index) // 'a1'
|
|
2360
|
+
* ```
|
|
2361
|
+
* @public
|
|
2362
|
+
*/
|
|
2363
|
+
declare function getIndexBelow(above?: IndexKey | null | undefined): IndexKey;
|
|
2364
|
+
/**
|
|
2365
|
+
* Get n number of indices, starting at an index.
|
|
2366
|
+
* @param n - The number of indices to get.
|
|
2367
|
+
* @param start - The index to start at.
|
|
2368
|
+
* @returns An array containing the start index plus n additional IndexKey values.
|
|
2369
|
+
* @example
|
|
2370
|
+
* ```ts
|
|
2371
|
+
* const indices = getIndices(3, 'a1' as IndexKey)
|
|
2372
|
+
* console.log(indices) // ['a1', 'a2', 'a3', 'a4']
|
|
2373
|
+
* ```
|
|
2374
|
+
* @public
|
|
2375
|
+
*/
|
|
2376
|
+
declare function getIndices(n: number, start?: IndexKey): IndexKey[];
|
|
2377
|
+
/**
|
|
2378
|
+
* Sort by index.
|
|
2379
|
+
* @param a - An object with an index property.
|
|
2380
|
+
* @param b - An object with an index property.
|
|
2381
|
+
* @returns A number indicating sort order (-1, 0, or 1).
|
|
2382
|
+
* @example
|
|
2383
|
+
* ```ts
|
|
2384
|
+
* const shapes = [
|
|
2385
|
+
* { id: 'b', index: 'a2' as IndexKey },
|
|
2386
|
+
* { id: 'a', index: 'a1' as IndexKey }
|
|
2387
|
+
* ]
|
|
2388
|
+
* const sorted = shapes.sort(sortByIndex)
|
|
2389
|
+
* console.log(sorted) // [{ id: 'a', index: 'a1' }, { id: 'b', index: 'a2' }]
|
|
2390
|
+
* ```
|
|
2391
|
+
* @public
|
|
2392
|
+
*/
|
|
2393
|
+
declare function sortByIndex<T extends {
|
|
2394
|
+
index: IndexKey;
|
|
2395
|
+
}>(a: T, b: T): 1 | -1 | 0;
|
|
2396
|
+
/**
|
|
2397
|
+
* Sort by index, or null.
|
|
2398
|
+
* @param a - An object with an index property.
|
|
2399
|
+
* @param b - An object with an index property.
|
|
2400
|
+
* @public
|
|
2401
|
+
*/
|
|
2402
|
+
declare function sortByMaybeIndex<T extends {
|
|
2403
|
+
index?: IndexKey | null;
|
|
2404
|
+
}>(a: T, b: T): 1 | -1 | 0;
|
|
2405
|
+
|
|
2406
|
+
/**
|
|
2407
|
+
* Retries an async operation with configurable attempt count, wait duration, and error filtering.
|
|
2408
|
+
* Executes the provided async function repeatedly until it succeeds or the maximum number of attempts is reached.
|
|
2409
|
+
* Includes support for abort signals and custom error matching to determine which errors should trigger retries.
|
|
2410
|
+
*
|
|
2411
|
+
* @param fn - The async function to retry on failure
|
|
2412
|
+
* @param options - Configuration options for retry behavior:
|
|
2413
|
+
* - `attempts`: Maximum number of retry attempts (default: 3)
|
|
2414
|
+
* - `waitDuration`: Milliseconds to wait between retry attempts (default: 1000)
|
|
2415
|
+
* - `abortSignal`: Optional AbortSignal to cancel the retry operation
|
|
2416
|
+
* - `matchError`: Optional function to determine if an error should trigger a retry
|
|
2417
|
+
* @returns Promise that resolves with the function's return value on success
|
|
2418
|
+
*
|
|
2419
|
+
* @example
|
|
2420
|
+
* ```ts
|
|
2421
|
+
* // Basic retry with default settings (3 attempts, 1 second wait)
|
|
2422
|
+
* const data = await retry(async () => {
|
|
2423
|
+
* const response = await fetch('/api/data')
|
|
2424
|
+
* if (!response.ok) throw new Error('Network error')
|
|
2425
|
+
* return response.json()
|
|
2426
|
+
* })
|
|
2427
|
+
*
|
|
2428
|
+
* // Custom retry configuration
|
|
2429
|
+
* const result = await retry(
|
|
2430
|
+
* async () => unreliableApiCall(),
|
|
2431
|
+
* {
|
|
2432
|
+
* attempts: 5,
|
|
2433
|
+
* waitDuration: 2000,
|
|
2434
|
+
* matchError: (error) => error instanceof NetworkError
|
|
2435
|
+
* }
|
|
2436
|
+
* )
|
|
2437
|
+
*
|
|
2438
|
+
* // With abort signal for cancellation
|
|
2439
|
+
* const controller = new AbortController()
|
|
2440
|
+
* setTimeout(() => controller.abort(), 10000) // Cancel after 10 seconds
|
|
2441
|
+
*
|
|
2442
|
+
* const data = await retry(
|
|
2443
|
+
* async () => fetchData(),
|
|
2444
|
+
* {
|
|
2445
|
+
* attempts: 10,
|
|
2446
|
+
* abortSignal: controller.signal
|
|
2447
|
+
* }
|
|
2448
|
+
* )
|
|
2449
|
+
* ```
|
|
2450
|
+
*
|
|
2451
|
+
* @internal
|
|
2452
|
+
*/
|
|
2453
|
+
declare function retry<T>(fn: (args: {
|
|
2454
|
+
attempt: number;
|
|
2455
|
+
remaining: number;
|
|
2456
|
+
total: number;
|
|
2457
|
+
}) => Promise<T>, { attempts, waitDuration, abortSignal, matchError, }?: {
|
|
2458
|
+
attempts?: number;
|
|
2459
|
+
waitDuration?: number;
|
|
2460
|
+
abortSignal?: AbortSignal;
|
|
2461
|
+
matchError?(error: unknown): boolean;
|
|
2462
|
+
}): Promise<T>;
|
|
2463
|
+
|
|
2464
|
+
/**
|
|
2465
|
+
* Compares two objects by their id property for use with Array.sort().
|
|
2466
|
+
* Sorts objects in ascending order based on their id values.
|
|
2467
|
+
*
|
|
2468
|
+
* @param a - First object to compare
|
|
2469
|
+
* @param b - Second object to compare
|
|
2470
|
+
* @returns 1 if a.id \> b.id, -1 if a.id \<= b.id
|
|
2471
|
+
*
|
|
2472
|
+
* @example
|
|
2473
|
+
* ```ts
|
|
2474
|
+
* const items = [
|
|
2475
|
+
* { id: 'c', name: 'Charlie' },
|
|
2476
|
+
* { id: 'a', name: 'Alice' },
|
|
2477
|
+
* { id: 'b', name: 'Bob' },
|
|
2478
|
+
* ]
|
|
2479
|
+
*
|
|
2480
|
+
* const sorted = items.sort(sortById)
|
|
2481
|
+
* // [{ id: 'a', name: 'Alice' }, { id: 'b', name: 'Bob' }, { id: 'c', name: 'Charlie' }]
|
|
2482
|
+
* ```
|
|
2483
|
+
*
|
|
2484
|
+
* @public
|
|
2485
|
+
*/
|
|
2486
|
+
declare function sortById<T extends {
|
|
2487
|
+
id: any;
|
|
2488
|
+
}>(a: T, b: T): 1 | -1;
|
|
2489
|
+
|
|
2490
|
+
/**
|
|
2491
|
+
* Get a value from local storage.
|
|
2492
|
+
*
|
|
2493
|
+
* @param key - The key to get.
|
|
2494
|
+
* @returns The stored value as a string, or null if not found or storage is unavailable.
|
|
2495
|
+
* @example
|
|
2496
|
+
* ```ts
|
|
2497
|
+
* const userTheme = getFromLocalStorage('user-theme')
|
|
2498
|
+
* if (userTheme) {
|
|
2499
|
+
* console.log('Stored theme:', userTheme)
|
|
2500
|
+
* }
|
|
2501
|
+
* ```
|
|
2502
|
+
* @internal
|
|
2503
|
+
*/
|
|
2504
|
+
declare function getFromLocalStorage(key: string): string | null;
|
|
2505
|
+
/**
|
|
2506
|
+
* Set a value in local storage. Will not throw an error if localStorage is not available.
|
|
2507
|
+
*
|
|
2508
|
+
* @param key - The key to set.
|
|
2509
|
+
* @param value - The value to set.
|
|
2510
|
+
* @returns void
|
|
2511
|
+
* @example
|
|
2512
|
+
* ```ts
|
|
2513
|
+
* const preferences = { theme: 'dark', language: 'en' }
|
|
2514
|
+
* setInLocalStorage('user-preferences', JSON.stringify(preferences))
|
|
2515
|
+
* ```
|
|
2516
|
+
* @internal
|
|
2517
|
+
*/
|
|
2518
|
+
declare function setInLocalStorage(key: string, value: string): void;
|
|
2519
|
+
/**
|
|
2520
|
+
* Remove a value from local storage. Will not throw an error if localStorage is not available.
|
|
2521
|
+
*
|
|
2522
|
+
* @param key - The key to remove.
|
|
2523
|
+
* @returns void
|
|
2524
|
+
* @example
|
|
2525
|
+
* ```ts
|
|
2526
|
+
* deleteFromLocalStorage('user-preferences')
|
|
2527
|
+
* // Value is now removed from localStorage
|
|
2528
|
+
* ```
|
|
2529
|
+
* @internal
|
|
2530
|
+
*/
|
|
2531
|
+
declare function deleteFromLocalStorage(key: string): void;
|
|
2532
|
+
/**
|
|
2533
|
+
* Clear all values from local storage. Will not throw an error if localStorage is not available.
|
|
2534
|
+
*
|
|
2535
|
+
* @returns void
|
|
2536
|
+
* @example
|
|
2537
|
+
* ```ts
|
|
2538
|
+
* clearLocalStorage()
|
|
2539
|
+
* // All localStorage data is now cleared
|
|
2540
|
+
* ```
|
|
2541
|
+
* @internal
|
|
2542
|
+
*/
|
|
2543
|
+
declare function clearLocalStorage(): void;
|
|
2544
|
+
/**
|
|
2545
|
+
* Get a value from session storage.
|
|
2546
|
+
*
|
|
2547
|
+
* @param key - The key to get.
|
|
2548
|
+
* @returns The stored value as a string, or null if not found or storage is unavailable.
|
|
2549
|
+
* @example
|
|
2550
|
+
* ```ts
|
|
2551
|
+
* const currentTool = getFromSessionStorage('current-tool')
|
|
2552
|
+
* if (currentTool) {
|
|
2553
|
+
* console.log('Active tool:', currentTool)
|
|
2554
|
+
* }
|
|
2555
|
+
* ```
|
|
2556
|
+
* @internal
|
|
2557
|
+
*/
|
|
2558
|
+
declare function getFromSessionStorage(key: string): string | null;
|
|
2559
|
+
/**
|
|
2560
|
+
* Set a value in session storage. Will not throw an error if sessionStorage is not available.
|
|
2561
|
+
*
|
|
2562
|
+
* @param key - The key to set.
|
|
2563
|
+
* @param value - The value to set.
|
|
2564
|
+
* @returns void
|
|
2565
|
+
* @example
|
|
2566
|
+
* ```ts
|
|
2567
|
+
* setInSessionStorage('current-tool', 'select')
|
|
2568
|
+
* setInSessionStorage('temp-data', JSON.stringify({ x: 100, y: 200 }))
|
|
2569
|
+
* ```
|
|
2570
|
+
* @internal
|
|
2571
|
+
*/
|
|
2572
|
+
declare function setInSessionStorage(key: string, value: string): void;
|
|
2573
|
+
/**
|
|
2574
|
+
* Remove a value from session storage. Will not throw an error if sessionStorage is not available.
|
|
2575
|
+
*
|
|
2576
|
+
* @param key - The key to remove.
|
|
2577
|
+
* @returns void
|
|
2578
|
+
* @example
|
|
2579
|
+
* ```ts
|
|
2580
|
+
* deleteFromSessionStorage('temp-data')
|
|
2581
|
+
* // Value is now removed from sessionStorage
|
|
2582
|
+
* ```
|
|
2583
|
+
* @internal
|
|
2584
|
+
*/
|
|
2585
|
+
declare function deleteFromSessionStorage(key: string): void;
|
|
2586
|
+
/**
|
|
2587
|
+
* Clear all values from session storage. Will not throw an error if sessionStorage is not available.
|
|
2588
|
+
*
|
|
2589
|
+
* @returns void
|
|
2590
|
+
* @example
|
|
2591
|
+
* ```ts
|
|
2592
|
+
* clearSessionStorage()
|
|
2593
|
+
* // All sessionStorage data is now cleared
|
|
2594
|
+
* ```
|
|
2595
|
+
* @internal
|
|
2596
|
+
*/
|
|
2597
|
+
declare function clearSessionStorage(): void;
|
|
2598
|
+
|
|
2599
|
+
/**
|
|
2600
|
+
* Creates an enum-like object from string values where each key maps to itself.
|
|
2601
|
+
* Useful for creating string constant objects with type safety and autocompletion.
|
|
2602
|
+
* @param values - The string values to create the enum from.
|
|
2603
|
+
* @returns An object where each provided string is both the key and value.
|
|
2604
|
+
* @example
|
|
2605
|
+
* ```ts
|
|
2606
|
+
* const Colors = stringEnum('red', 'green', 'blue')
|
|
2607
|
+
* // Results in: { red: 'red', green: 'green', blue: 'blue' }
|
|
2608
|
+
*
|
|
2609
|
+
* // Type-safe usage
|
|
2610
|
+
* function setColor(color: keyof typeof Colors) {
|
|
2611
|
+
* console.log(`Setting color to ${Colors[color]}`)
|
|
2612
|
+
* }
|
|
2613
|
+
*
|
|
2614
|
+
* setColor('red') // ✓ Valid
|
|
2615
|
+
* setColor('yellow') // ✗ TypeScript error
|
|
2616
|
+
* ```
|
|
2617
|
+
* @internal
|
|
2618
|
+
*/
|
|
2619
|
+
declare function stringEnum<T extends string>(...values: T[]): {
|
|
2620
|
+
[K in T]: K;
|
|
2621
|
+
};
|
|
2622
|
+
|
|
2623
|
+
/**
|
|
2624
|
+
* A scheduler class that manages a queue of functions to be executed at a target frame rate.
|
|
2625
|
+
* Each instance maintains its own queue and state, allowing for separate throttling contexts
|
|
2626
|
+
* (e.g., UI operations vs network sync operations).
|
|
2627
|
+
*
|
|
2628
|
+
* @public
|
|
2629
|
+
*/
|
|
2630
|
+
declare class FpsScheduler {
|
|
2631
|
+
private targetFps;
|
|
2632
|
+
private targetTimePerFrame;
|
|
2633
|
+
private fpsQueue;
|
|
2634
|
+
private frameRaf;
|
|
2635
|
+
private flushRaf;
|
|
2636
|
+
private lastFlushTime;
|
|
2637
|
+
constructor(targetFps?: number);
|
|
2638
|
+
updateTargetFps(targetFps: number): void;
|
|
2639
|
+
private flush;
|
|
2640
|
+
private tick;
|
|
2641
|
+
/**
|
|
2642
|
+
* Creates a throttled version of a function that executes at most once per frame.
|
|
2643
|
+
* The default target frame rate is set by the FpsScheduler instance.
|
|
2644
|
+
* Subsequent calls within the same frame are ignored, ensuring smooth performance
|
|
2645
|
+
* for high-frequency events like mouse movements or scroll events.
|
|
2646
|
+
*
|
|
2647
|
+
* @param fn - The function to throttle, optionally with a cancel method
|
|
2648
|
+
* @returns A throttled function with an optional cancel method to remove pending calls
|
|
2649
|
+
*
|
|
2650
|
+
* @public
|
|
2651
|
+
*/
|
|
2652
|
+
fpsThrottle(fn: {
|
|
2653
|
+
(): void;
|
|
2654
|
+
cancel?(): void;
|
|
2655
|
+
}): {
|
|
2656
|
+
(): void;
|
|
2657
|
+
cancel?(): void;
|
|
2658
|
+
};
|
|
2659
|
+
/**
|
|
2660
|
+
* Schedules a function to execute on the next animation frame.
|
|
2661
|
+
* If the same function is passed multiple times before the frame executes,
|
|
2662
|
+
* it will only be called once, effectively batching multiple calls.
|
|
2663
|
+
*
|
|
2664
|
+
* @param fn - The function to execute on the next frame
|
|
2665
|
+
* @returns A cancel function that can prevent execution if called before the next frame
|
|
2666
|
+
*
|
|
2667
|
+
* @public
|
|
2668
|
+
*/
|
|
2669
|
+
throttleToNextFrame(fn: () => void): () => void;
|
|
2670
|
+
}
|
|
2671
|
+
/**
|
|
2672
|
+
* Creates a throttled version of a function that executes at most once per frame.
|
|
2673
|
+
* The default target frame rate is 120fps, but can be customized per function.
|
|
2674
|
+
* Subsequent calls within the same frame are ignored, ensuring smooth performance
|
|
2675
|
+
* for high-frequency events like mouse movements or scroll events.
|
|
2676
|
+
*
|
|
2677
|
+
* Uses the default throttle instance for UI operations. If you need a separate
|
|
2678
|
+
* throttling queue (e.g., for network operations), create your own Throttle instance.
|
|
2679
|
+
*
|
|
2680
|
+
* @param fn - The function to throttle, optionally with a cancel method
|
|
2681
|
+
* @returns A throttled function with an optional cancel method to remove pending calls
|
|
2682
|
+
*
|
|
2683
|
+
* @example
|
|
2684
|
+
* ```ts
|
|
2685
|
+
* // Default 120fps throttling
|
|
2686
|
+
* const updateCanvas = fpsThrottle(() => {
|
|
2687
|
+
* // This will run at most once per frame (~8.33ms)
|
|
2688
|
+
* redrawCanvas()
|
|
2689
|
+
* })
|
|
2690
|
+
*
|
|
2691
|
+
* // Call as often as you want - automatically throttled to 120fps
|
|
2692
|
+
* document.addEventListener('mousemove', updateCanvas)
|
|
2693
|
+
*
|
|
2694
|
+
* // Cancel pending calls if needed
|
|
2695
|
+
* updateCanvas.cancel?.()
|
|
2696
|
+
* ```
|
|
2697
|
+
*
|
|
2698
|
+
* @internal
|
|
2699
|
+
*/
|
|
2700
|
+
declare function fpsThrottle(fn: {
|
|
2701
|
+
(): void;
|
|
2702
|
+
cancel?(): void;
|
|
2703
|
+
}): {
|
|
2704
|
+
(): void;
|
|
2705
|
+
cancel?(): void;
|
|
2706
|
+
};
|
|
2707
|
+
/**
|
|
2708
|
+
* Schedules a function to execute on the next animation frame, targeting 120fps.
|
|
2709
|
+
* If the same function is passed multiple times before the frame executes,
|
|
2710
|
+
* it will only be called once, effectively batching multiple calls.
|
|
2711
|
+
*
|
|
2712
|
+
* Uses the default throttle instance for UI operations.
|
|
2713
|
+
*
|
|
2714
|
+
* @param fn - The function to execute on the next frame
|
|
2715
|
+
* @returns A cancel function that can prevent execution if called before the next frame
|
|
2716
|
+
*
|
|
2717
|
+
* @example
|
|
2718
|
+
* ```ts
|
|
2719
|
+
* const updateUI = throttleToNextFrame(() => {
|
|
2720
|
+
* // Batches multiple calls into the next animation frame
|
|
2721
|
+
* updateStatusBar()
|
|
2722
|
+
* refreshToolbar()
|
|
2723
|
+
* })
|
|
2724
|
+
*
|
|
2725
|
+
* // Multiple calls within the same frame are batched
|
|
2726
|
+
* updateUI() // Will execute
|
|
2727
|
+
* updateUI() // Ignored (same function already queued)
|
|
2728
|
+
* updateUI() // Ignored (same function already queued)
|
|
2729
|
+
*
|
|
2730
|
+
* // Get cancel function to prevent execution
|
|
2731
|
+
* const cancel = updateUI()
|
|
2732
|
+
* cancel() // Prevents execution if called before next frame
|
|
2733
|
+
* ```
|
|
2734
|
+
*
|
|
2735
|
+
* @internal
|
|
2736
|
+
*/
|
|
2737
|
+
declare function throttleToNextFrame(fn: () => void): () => void;
|
|
2738
|
+
|
|
2739
|
+
/**
|
|
2740
|
+
* A utility class for managing timeouts, intervals, and animation frames with context-based organization and automatic cleanup.
|
|
2741
|
+
* Helps prevent memory leaks by organizing timers into named contexts that can be cleared together.
|
|
2742
|
+
* @example
|
|
2743
|
+
* ```ts
|
|
2744
|
+
* const timers = new Timers()
|
|
2745
|
+
*
|
|
2746
|
+
* // Set timers with context organization
|
|
2747
|
+
* timers.setTimeout('ui', () => console.log('Auto save'), 5000)
|
|
2748
|
+
* timers.setInterval('ui', () => console.log('Refresh'), 1000)
|
|
2749
|
+
* timers.requestAnimationFrame('ui', () => console.log('Render'))
|
|
2750
|
+
*
|
|
2751
|
+
* // Clear all timers for a context
|
|
2752
|
+
* timers.dispose('ui')
|
|
2753
|
+
*
|
|
2754
|
+
* // Or get context-bound functions
|
|
2755
|
+
* const uiTimers = timers.forContext('ui')
|
|
2756
|
+
* uiTimers.setTimeout(() => console.log('Contextual timeout'), 1000)
|
|
2757
|
+
* ```
|
|
2758
|
+
* @public
|
|
2759
|
+
*/
|
|
2760
|
+
declare class Timers {
|
|
2761
|
+
private timeouts;
|
|
2762
|
+
private intervals;
|
|
2763
|
+
private rafs;
|
|
2764
|
+
/**
|
|
2765
|
+
* Creates a new Timers instance with bound methods for safe callback usage.
|
|
2766
|
+
* @example
|
|
2767
|
+
* ```ts
|
|
2768
|
+
* const timers = new Timers()
|
|
2769
|
+
* // Methods are pre-bound, safe to use as callbacks
|
|
2770
|
+
* element.addEventListener('click', timers.dispose)
|
|
2771
|
+
* ```
|
|
2772
|
+
*/
|
|
2773
|
+
constructor();
|
|
2774
|
+
/**
|
|
2775
|
+
* Creates a timeout that will be tracked under the specified context.
|
|
2776
|
+
* @param contextId - The context identifier to group this timer under.
|
|
2777
|
+
* @param handler - The function to execute when the timeout expires.
|
|
2778
|
+
* @param timeout - The delay in milliseconds (default: 0).
|
|
2779
|
+
* @param args - Additional arguments to pass to the handler.
|
|
2780
|
+
* @returns The timer ID that can be used with clearTimeout.
|
|
2781
|
+
* @example
|
|
2782
|
+
* ```ts
|
|
2783
|
+
* const timers = new Timers()
|
|
2784
|
+
* const id = timers.setTimeout('autosave', () => save(), 5000)
|
|
2785
|
+
* // Timer will be automatically cleared when 'autosave' context is disposed
|
|
2786
|
+
* ```
|
|
2787
|
+
* @public
|
|
2788
|
+
*/
|
|
2789
|
+
setTimeout(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number;
|
|
2790
|
+
/**
|
|
2791
|
+
* Creates an interval that will be tracked under the specified context.
|
|
2792
|
+
* @param contextId - The context identifier to group this timer under.
|
|
2793
|
+
* @param handler - The function to execute repeatedly.
|
|
2794
|
+
* @param timeout - The delay in milliseconds between executions (default: 0).
|
|
2795
|
+
* @param args - Additional arguments to pass to the handler.
|
|
2796
|
+
* @returns The interval ID that can be used with clearInterval.
|
|
2797
|
+
* @example
|
|
2798
|
+
* ```ts
|
|
2799
|
+
* const timers = new Timers()
|
|
2800
|
+
* const id = timers.setInterval('refresh', () => updateData(), 1000)
|
|
2801
|
+
* // Interval will be automatically cleared when 'refresh' context is disposed
|
|
2802
|
+
* ```
|
|
2803
|
+
* @public
|
|
2804
|
+
*/
|
|
2805
|
+
setInterval(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number;
|
|
2806
|
+
/**
|
|
2807
|
+
* Requests an animation frame that will be tracked under the specified context.
|
|
2808
|
+
* @param contextId - The context identifier to group this animation frame under.
|
|
2809
|
+
* @param callback - The function to execute on the next animation frame.
|
|
2810
|
+
* @returns The request ID that can be used with cancelAnimationFrame.
|
|
2811
|
+
* @example
|
|
2812
|
+
* ```ts
|
|
2813
|
+
* const timers = new Timers()
|
|
2814
|
+
* const id = timers.requestAnimationFrame('render', () => draw())
|
|
2815
|
+
* // Animation frame will be automatically cancelled when 'render' context is disposed
|
|
2816
|
+
* ```
|
|
2817
|
+
* @public
|
|
2818
|
+
*/
|
|
2819
|
+
requestAnimationFrame(contextId: string, callback: FrameRequestCallback): number;
|
|
2820
|
+
/**
|
|
2821
|
+
* Disposes of all timers associated with the specified context.
|
|
2822
|
+
* Clears all timeouts, intervals, and animation frames for the given context ID.
|
|
2823
|
+
* @param contextId - The context identifier whose timers should be cleared.
|
|
2824
|
+
* @returns void
|
|
2825
|
+
* @example
|
|
2826
|
+
* ```ts
|
|
2827
|
+
* const timers = new Timers()
|
|
2828
|
+
* timers.setTimeout('ui', () => console.log('timeout'), 1000)
|
|
2829
|
+
* timers.setInterval('ui', () => console.log('interval'), 500)
|
|
2830
|
+
*
|
|
2831
|
+
* // Clear all 'ui' context timers
|
|
2832
|
+
* timers.dispose('ui')
|
|
2833
|
+
* ```
|
|
2834
|
+
* @public
|
|
2835
|
+
*/
|
|
2836
|
+
dispose(contextId: string): void;
|
|
2837
|
+
/**
|
|
2838
|
+
* Disposes of all timers across all contexts.
|
|
2839
|
+
* Clears every timeout, interval, and animation frame managed by this instance.
|
|
2840
|
+
* @returns void
|
|
2841
|
+
* @example
|
|
2842
|
+
* ```ts
|
|
2843
|
+
* const timers = new Timers()
|
|
2844
|
+
* timers.setTimeout('ui', () => console.log('ui'), 1000)
|
|
2845
|
+
* timers.setTimeout('background', () => console.log('bg'), 2000)
|
|
2846
|
+
*
|
|
2847
|
+
* // Clear everything
|
|
2848
|
+
* timers.disposeAll()
|
|
2849
|
+
* ```
|
|
2850
|
+
* @public
|
|
2851
|
+
*/
|
|
2852
|
+
disposeAll(): void;
|
|
2853
|
+
/**
|
|
2854
|
+
* Returns an object with timer methods bound to a specific context.
|
|
2855
|
+
* Convenient for getting context-specific timer functions without repeatedly passing the contextId.
|
|
2856
|
+
* @param contextId - The context identifier to bind the returned methods to.
|
|
2857
|
+
* @returns An object with setTimeout, setInterval, requestAnimationFrame, and dispose methods bound to the context.
|
|
2858
|
+
* @example
|
|
2859
|
+
* ```ts
|
|
2860
|
+
* const timers = new Timers()
|
|
2861
|
+
* const uiTimers = timers.forContext('ui')
|
|
2862
|
+
*
|
|
2863
|
+
* // These are equivalent to calling timers.setTimeout('ui', ...)
|
|
2864
|
+
* uiTimers.setTimeout(() => console.log('timeout'), 1000)
|
|
2865
|
+
* uiTimers.setInterval(() => console.log('interval'), 500)
|
|
2866
|
+
* uiTimers.requestAnimationFrame(() => console.log('frame'))
|
|
2867
|
+
*
|
|
2868
|
+
* // Dispose only this context
|
|
2869
|
+
* uiTimers.dispose()
|
|
2870
|
+
* ```
|
|
2871
|
+
* @public
|
|
2872
|
+
*/
|
|
2873
|
+
forContext(contextId: string): {
|
|
2874
|
+
setTimeout: (handler: TimerHandler, timeout?: number, ...args: any[]) => number;
|
|
2875
|
+
setInterval: (handler: TimerHandler, timeout?: number, ...args: any[]) => number;
|
|
2876
|
+
requestAnimationFrame: (callback: FrameRequestCallback) => number;
|
|
2877
|
+
dispose: () => void;
|
|
2878
|
+
};
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
/**
|
|
2882
|
+
* Safely parses a URL string without throwing exceptions on invalid input.
|
|
2883
|
+
* Returns a URL object for valid URLs or undefined for invalid ones.
|
|
2884
|
+
*
|
|
2885
|
+
* @param url - The URL string to parse
|
|
2886
|
+
* @param baseUrl - Optional base URL to resolve relative URLs against
|
|
2887
|
+
* @returns A URL object if parsing succeeds, undefined if it fails
|
|
2888
|
+
*
|
|
2889
|
+
* @example
|
|
2890
|
+
* ```ts
|
|
2891
|
+
* // Valid absolute URL
|
|
2892
|
+
* const url1 = safeParseUrl('https://example.com')
|
|
2893
|
+
* if (url1) {
|
|
2894
|
+
* console.log(`Valid URL: ${url1.href}`) // "Valid URL: https://example.com/"
|
|
2895
|
+
* }
|
|
2896
|
+
*
|
|
2897
|
+
* // Invalid URL
|
|
2898
|
+
* const url2 = safeParseUrl('not-a-url')
|
|
2899
|
+
* console.log(url2) // undefined
|
|
2900
|
+
*
|
|
2901
|
+
* // Relative URL with base
|
|
2902
|
+
* const url3 = safeParseUrl('/path', 'https://example.com')
|
|
2903
|
+
* if (url3) {
|
|
2904
|
+
* console.log(url3.href) // "https://example.com/path"
|
|
2905
|
+
* }
|
|
2906
|
+
*
|
|
2907
|
+
* // Error handling
|
|
2908
|
+
* function handleUserUrl(input: string) {
|
|
2909
|
+
* const url = safeParseUrl(input)
|
|
2910
|
+
* if (url) {
|
|
2911
|
+
* return url
|
|
2912
|
+
* } else {
|
|
2913
|
+
* console.log('Invalid URL provided')
|
|
2914
|
+
* return null
|
|
2915
|
+
* }
|
|
2916
|
+
* }
|
|
2917
|
+
* ```
|
|
2918
|
+
*
|
|
2919
|
+
* @public
|
|
2920
|
+
*/
|
|
2921
|
+
declare const safeParseUrl: (url: string, baseUrl?: string | URL) => URL | undefined;
|
|
2922
|
+
|
|
2923
|
+
/**
|
|
2924
|
+
* Get whether a value is not undefined.
|
|
2925
|
+
*
|
|
2926
|
+
* @param value - The value to check.
|
|
2927
|
+
* @returns True if the value is not undefined, with proper type narrowing.
|
|
2928
|
+
* @example
|
|
2929
|
+
* ```ts
|
|
2930
|
+
* const maybeString: string | undefined = getValue()
|
|
2931
|
+
*
|
|
2932
|
+
* if (isDefined(maybeString)) {
|
|
2933
|
+
* // TypeScript knows maybeString is string, not undefined
|
|
2934
|
+
* console.log(maybeString.toUpperCase())
|
|
2935
|
+
* }
|
|
2936
|
+
*
|
|
2937
|
+
* // Filter undefined values from arrays
|
|
2938
|
+
* const values = [1, undefined, 2, undefined, 3]
|
|
2939
|
+
* const definedValues = values.filter(isDefined) // [1, 2, 3]
|
|
2940
|
+
* ```
|
|
2941
|
+
* @public
|
|
2942
|
+
*/
|
|
2943
|
+
declare function isDefined<T>(value: T): value is typeof value extends undefined ? never : T;
|
|
2944
|
+
/**
|
|
2945
|
+
* Get whether a value is not null.
|
|
2946
|
+
*
|
|
2947
|
+
* @param value - The value to check.
|
|
2948
|
+
* @returns True if the value is not null, with proper type narrowing.
|
|
2949
|
+
* @example
|
|
2950
|
+
* ```ts
|
|
2951
|
+
* const maybeString: string | null = getValue()
|
|
2952
|
+
*
|
|
2953
|
+
* if (isNonNull(maybeString)) {
|
|
2954
|
+
* // TypeScript knows maybeString is string, not null
|
|
2955
|
+
* console.log(maybeString.length)
|
|
2956
|
+
* }
|
|
2957
|
+
*
|
|
2958
|
+
* // Filter null values from arrays
|
|
2959
|
+
* const values = ["a", null, "b", null, "c"]
|
|
2960
|
+
* const nonNullValues = values.filter(isNonNull) // ["a", "b", "c"]
|
|
2961
|
+
* ```
|
|
2962
|
+
* @public
|
|
2963
|
+
*/
|
|
2964
|
+
declare function isNonNull<T>(value: T): value is typeof value extends null ? never : T;
|
|
2965
|
+
/**
|
|
2966
|
+
* Get whether a value is not nullish (not null and not undefined).
|
|
2967
|
+
*
|
|
2968
|
+
* @param value - The value to check.
|
|
2969
|
+
* @returns True if the value is neither null nor undefined, with proper type narrowing.
|
|
2970
|
+
* @example
|
|
2971
|
+
* ```ts
|
|
2972
|
+
* const maybeString: string | null | undefined = getValue()
|
|
2973
|
+
*
|
|
2974
|
+
* if (isNonNullish(maybeString)) {
|
|
2975
|
+
* // TypeScript knows maybeString is string, not null or undefined
|
|
2976
|
+
* console.log(maybeString.charAt(0))
|
|
2977
|
+
* }
|
|
2978
|
+
*
|
|
2979
|
+
* // Filter nullish values from arrays
|
|
2980
|
+
* const values = ["hello", null, "world", undefined, "!"]
|
|
2981
|
+
* const cleanValues = values.filter(isNonNullish) // ["hello", "world", "!"]
|
|
2982
|
+
* ```
|
|
2983
|
+
* @public
|
|
2984
|
+
*/
|
|
2985
|
+
declare function isNonNullish<T>(value: T): value is typeof value extends undefined ? never : typeof value extends null ? never : T;
|
|
2986
|
+
/**
|
|
2987
|
+
* Create a deep copy of a value. Uses the structuredClone API if available, otherwise uses JSON.parse(JSON.stringify()).
|
|
2988
|
+
*
|
|
2989
|
+
* @param i - The value to clone.
|
|
2990
|
+
* @returns A deep copy of the input value.
|
|
2991
|
+
* @example
|
|
2992
|
+
* ```ts
|
|
2993
|
+
* const original = { a: 1, b: { c: 2 } }
|
|
2994
|
+
* const copy = structuredClone(original)
|
|
2995
|
+
*
|
|
2996
|
+
* copy.b.c = 3
|
|
2997
|
+
* console.log(original.b.c) // 2 (unchanged)
|
|
2998
|
+
* console.log(copy.b.c) // 3
|
|
2999
|
+
*
|
|
3000
|
+
* // Works with complex objects
|
|
3001
|
+
* const complexObject = {
|
|
3002
|
+
* date: new Date(),
|
|
3003
|
+
* array: [1, 2, 3],
|
|
3004
|
+
* nested: { deep: { value: "test" } }
|
|
3005
|
+
* }
|
|
3006
|
+
* const cloned = structuredClone(complexObject)
|
|
3007
|
+
* ```
|
|
3008
|
+
* @public
|
|
3009
|
+
*/
|
|
3010
|
+
declare const structuredClone: <T>(i: T) => T;
|
|
3011
|
+
/**
|
|
3012
|
+
* Whether the current environment has native structuredClone support.
|
|
3013
|
+
* @returns True if using native structuredClone, false if using JSON fallback.
|
|
3014
|
+
* @internal
|
|
3015
|
+
*/
|
|
3016
|
+
declare const isNativeStructuredClone: boolean;
|
|
3017
|
+
/**
|
|
3018
|
+
* The prototype object used by structuredClone for cloned objects.
|
|
3019
|
+
* When we patch structuredClone in jsdom for testing (see https://github.com/jsdom/jsdom/issues/3363),
|
|
3020
|
+
* the Object that is used as a prototype for the cloned object is not the same as the Object in
|
|
3021
|
+
* the code under test (that comes from jsdom's fake global context). This constant is used in
|
|
3022
|
+
* our code to work around this case.
|
|
3023
|
+
*
|
|
3024
|
+
* This is also the case for Array prototype, but that problem can be worked around with an
|
|
3025
|
+
* Array.isArray() check.
|
|
3026
|
+
* @internal
|
|
3027
|
+
*/
|
|
3028
|
+
declare const STRUCTURED_CLONE_OBJECT_PROTOTYPE: any;
|
|
3029
|
+
|
|
3030
|
+
/**
|
|
3031
|
+
* Registers a tldraw library version for conflict detection.
|
|
3032
|
+
* This function tracks different tldraw library versions to warn about potential conflicts
|
|
3033
|
+
* when multiple versions are loaded simultaneously.
|
|
3034
|
+
* @param name - The name of the tldraw library package (e.g., '\@ibodr/editor').
|
|
3035
|
+
* @param version - The semantic version string (e.g., '2.0.0').
|
|
3036
|
+
* @param modules - The module system being used ('esm' or 'cjs').
|
|
3037
|
+
* @returns void
|
|
3038
|
+
* @example
|
|
3039
|
+
* ```ts
|
|
3040
|
+
* // Register a library version during package initialization
|
|
3041
|
+
* registerDrawLibraryVersion('@ibodr/editor', '2.0.0', 'esm')
|
|
3042
|
+
* registerDrawLibraryVersion('@ibodr/tldraw', '2.0.0', 'esm')
|
|
3043
|
+
*
|
|
3044
|
+
* // If conflicting versions are detected, warnings will be logged:
|
|
3045
|
+
* registerDrawLibraryVersion('@ibodr/editor', '1.9.0', 'cjs')
|
|
3046
|
+
* // Console warning about version mismatch will appear
|
|
3047
|
+
* ```
|
|
3048
|
+
* @internal
|
|
3049
|
+
*/
|
|
3050
|
+
declare function registerDrawLibraryVersion(name?: string, version?: string, modules?: string): void;
|
|
3051
|
+
|
|
3052
|
+
/**
|
|
3053
|
+
* Issues a deprecation warning for deprecated getter properties, advising users to use
|
|
3054
|
+
* the equivalent getter method instead. The warning is shown only once per property name.
|
|
3055
|
+
*
|
|
3056
|
+
* @param name - The name of the deprecated property (e.g., 'viewport')
|
|
3057
|
+
*
|
|
3058
|
+
* @example
|
|
3059
|
+
* ```ts
|
|
3060
|
+
* // Inside a class with deprecated property access
|
|
3061
|
+
* get viewport() {
|
|
3062
|
+
* warnDeprecatedGetter('viewport')
|
|
3063
|
+
* return this.getViewport()
|
|
3064
|
+
* }
|
|
3065
|
+
*
|
|
3066
|
+
* // Usage will show: "[tldraw] Using 'viewport' is deprecated and will be removed..."
|
|
3067
|
+
* // But only the first time it's accessed
|
|
3068
|
+
* ```
|
|
3069
|
+
*
|
|
3070
|
+
* @internal
|
|
3071
|
+
*/
|
|
3072
|
+
declare function warnDeprecatedGetter(name: string): void;
|
|
3073
|
+
/**
|
|
3074
|
+
* Issues a warning message to the console, but only once per unique message.
|
|
3075
|
+
* Subsequent calls with the same message are ignored, preventing console spam.
|
|
3076
|
+
* All messages are prefixed with "[tldraw]".
|
|
3077
|
+
*
|
|
3078
|
+
* @param message - The warning message to display
|
|
3079
|
+
*
|
|
3080
|
+
* @example
|
|
3081
|
+
* ```ts
|
|
3082
|
+
* // Warn about deprecated usage
|
|
3083
|
+
* function oldFunction() {
|
|
3084
|
+
* warnOnce('oldFunction is deprecated, use newFunction instead')
|
|
3085
|
+
* // Continue with implementation...
|
|
3086
|
+
* }
|
|
3087
|
+
*
|
|
3088
|
+
* // First call logs: "[tldraw] oldFunction is deprecated, use newFunction instead"
|
|
3089
|
+
* oldFunction() // Shows warning
|
|
3090
|
+
* oldFunction() // No warning (already shown)
|
|
3091
|
+
* oldFunction() // No warning (already shown)
|
|
3092
|
+
* ```
|
|
3093
|
+
*
|
|
3094
|
+
* @internal
|
|
3095
|
+
*/
|
|
3096
|
+
declare function warnOnce(message: string): void;
|
|
3097
|
+
|
|
3098
|
+
export { type Awaitable, DEFAULT_SUPPORTED_IMAGE_TYPES, DEFAULT_SUPPORTED_MEDIA_TYPES, DEFAULT_SUPPORTED_MEDIA_TYPE_LIST, DEFAULT_SUPPORT_VIDEO_TYPES, type ErrorAnnotations, type ErrorResult, ExecutionQueue, type Expand, FileHelpers, FpsScheduler, Image, type IndexKey, type JsonArray, type JsonObject, type JsonPrimitive, type JsonValue, LruCache, type MakeUndefinedOptional, MediaHelpers, type OkResult, PerformanceTracker, PngHelpers, type RecursivePartial, type Required, Result, STRUCTURED_CLONE_OBJECT_PROTOTYPE, Timers, WeakCache, ZERO_INDEX_KEY, annotateError, areArraysShallowEqual, areObjectsShallowEqual, assert, assertExists, bind, clearLocalStorage, clearSessionStorage, compact, debounce, dedupe, deleteFromLocalStorage, deleteFromSessionStorage, exhaustiveSwitchError, fetch, filterEntries, fpsThrottle, getChangedKeys, getErrorAnnotations, getFirstFromIterable, getFromLocalStorage, getFromSessionStorage, getHashForBuffer, getHashForObject, getHashForString, getIndexAbove, getIndexBelow, getIndexBetween, getIndices, getIndicesAbove, getIndicesBelow, getIndicesBetween, getOwnProperty, groupBy, hasOwnProperty, invLerp, isDefined, isEqualAllowingForFloatingPointErrors, isNativeStructuredClone, isNonNull, isNonNullish, last, lerp, lns, mapObjectMapValues, maxBy, measureAverageDuration, measureCbDuration, measureDuration, mergeArraysAndReplaceDefaults, minBy, mockUniqueId, modulate, noop, objectMapEntries, objectMapEntriesIterable, objectMapFromEntries, objectMapKeys, objectMapValues, omit, omitFromStackTrace, partition, promiseWithResolve, registerDrawLibraryVersion, restoreUniqueId, retry, rng, rotateArray, safeParseUrl, setInLocalStorage, setInSessionStorage, sleep, sortById, sortByIndex, sortByMaybeIndex, stringEnum, structuredClone, throttleToNextFrame, uniqueId, validateIndexKey, warnDeprecatedGetter, warnOnce };
|