@tldraw/utils 4.0.3 → 4.1.0-canary.0259516ffb8c

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.
Files changed (160) hide show
  1. package/dist-cjs/index.d.ts +1350 -80
  2. package/dist-cjs/index.js +5 -5
  3. package/dist-cjs/lib/ExecutionQueue.js +79 -0
  4. package/dist-cjs/lib/ExecutionQueue.js.map +2 -2
  5. package/dist-cjs/lib/PerformanceTracker.js +43 -0
  6. package/dist-cjs/lib/PerformanceTracker.js.map +2 -2
  7. package/dist-cjs/lib/array.js +3 -1
  8. package/dist-cjs/lib/array.js.map +2 -2
  9. package/dist-cjs/lib/bind.js.map +2 -2
  10. package/dist-cjs/lib/cache.js +27 -5
  11. package/dist-cjs/lib/cache.js.map +2 -2
  12. package/dist-cjs/lib/control.js +12 -0
  13. package/dist-cjs/lib/control.js.map +2 -2
  14. package/dist-cjs/lib/debounce.js.map +2 -2
  15. package/dist-cjs/lib/error.js.map +2 -2
  16. package/dist-cjs/lib/file.js +76 -11
  17. package/dist-cjs/lib/file.js.map +2 -2
  18. package/dist-cjs/lib/function.js.map +2 -2
  19. package/dist-cjs/lib/hash.js.map +2 -2
  20. package/dist-cjs/lib/id.js.map +2 -2
  21. package/dist-cjs/lib/iterable.js.map +2 -2
  22. package/dist-cjs/lib/json-value.js.map +1 -1
  23. package/dist-cjs/lib/media/apng.js.map +2 -2
  24. package/dist-cjs/lib/media/avif.js.map +2 -2
  25. package/dist-cjs/lib/media/gif.js.map +2 -2
  26. package/dist-cjs/lib/media/media.js +130 -4
  27. package/dist-cjs/lib/media/media.js.map +2 -2
  28. package/dist-cjs/lib/media/png.js +141 -0
  29. package/dist-cjs/lib/media/png.js.map +2 -2
  30. package/dist-cjs/lib/media/webp.js +1 -0
  31. package/dist-cjs/lib/media/webp.js.map +2 -2
  32. package/dist-cjs/lib/network.js.map +2 -2
  33. package/dist-cjs/lib/number.js.map +2 -2
  34. package/dist-cjs/lib/object.js +1 -1
  35. package/dist-cjs/lib/object.js.map +2 -2
  36. package/dist-cjs/lib/perf.js.map +2 -2
  37. package/dist-cjs/lib/reordering.js.map +2 -2
  38. package/dist-cjs/lib/retry.js.map +2 -2
  39. package/dist-cjs/lib/sort.js.map +2 -2
  40. package/dist-cjs/lib/storage.js.map +2 -2
  41. package/dist-cjs/lib/stringEnum.js.map +2 -2
  42. package/dist-cjs/lib/throttle.js.map +2 -2
  43. package/dist-cjs/lib/timers.js +103 -4
  44. package/dist-cjs/lib/timers.js.map +2 -2
  45. package/dist-cjs/lib/types.js.map +1 -1
  46. package/dist-cjs/lib/url.js.map +2 -2
  47. package/dist-cjs/lib/value.js.map +2 -2
  48. package/dist-cjs/lib/version.js.map +2 -2
  49. package/dist-cjs/lib/warn.js.map +2 -2
  50. package/dist-esm/index.d.mts +1350 -80
  51. package/dist-esm/index.mjs +1 -1
  52. package/dist-esm/lib/ExecutionQueue.mjs +79 -0
  53. package/dist-esm/lib/ExecutionQueue.mjs.map +2 -2
  54. package/dist-esm/lib/PerformanceTracker.mjs +43 -0
  55. package/dist-esm/lib/PerformanceTracker.mjs.map +2 -2
  56. package/dist-esm/lib/array.mjs +3 -1
  57. package/dist-esm/lib/array.mjs.map +2 -2
  58. package/dist-esm/lib/bind.mjs.map +2 -2
  59. package/dist-esm/lib/cache.mjs +27 -5
  60. package/dist-esm/lib/cache.mjs.map +2 -2
  61. package/dist-esm/lib/control.mjs +12 -0
  62. package/dist-esm/lib/control.mjs.map +2 -2
  63. package/dist-esm/lib/debounce.mjs.map +2 -2
  64. package/dist-esm/lib/error.mjs.map +2 -2
  65. package/dist-esm/lib/file.mjs +76 -11
  66. package/dist-esm/lib/file.mjs.map +2 -2
  67. package/dist-esm/lib/function.mjs.map +2 -2
  68. package/dist-esm/lib/hash.mjs.map +2 -2
  69. package/dist-esm/lib/id.mjs.map +2 -2
  70. package/dist-esm/lib/iterable.mjs.map +2 -2
  71. package/dist-esm/lib/media/apng.mjs.map +2 -2
  72. package/dist-esm/lib/media/avif.mjs.map +2 -2
  73. package/dist-esm/lib/media/gif.mjs.map +2 -2
  74. package/dist-esm/lib/media/media.mjs +130 -4
  75. package/dist-esm/lib/media/media.mjs.map +2 -2
  76. package/dist-esm/lib/media/png.mjs +141 -0
  77. package/dist-esm/lib/media/png.mjs.map +2 -2
  78. package/dist-esm/lib/media/webp.mjs +1 -0
  79. package/dist-esm/lib/media/webp.mjs.map +2 -2
  80. package/dist-esm/lib/network.mjs.map +2 -2
  81. package/dist-esm/lib/number.mjs.map +2 -2
  82. package/dist-esm/lib/object.mjs.map +2 -2
  83. package/dist-esm/lib/perf.mjs.map +2 -2
  84. package/dist-esm/lib/reordering.mjs.map +2 -2
  85. package/dist-esm/lib/retry.mjs.map +2 -2
  86. package/dist-esm/lib/sort.mjs.map +2 -2
  87. package/dist-esm/lib/storage.mjs.map +2 -2
  88. package/dist-esm/lib/stringEnum.mjs.map +2 -2
  89. package/dist-esm/lib/throttle.mjs.map +2 -2
  90. package/dist-esm/lib/timers.mjs +103 -4
  91. package/dist-esm/lib/timers.mjs.map +2 -2
  92. package/dist-esm/lib/url.mjs.map +2 -2
  93. package/dist-esm/lib/value.mjs.map +2 -2
  94. package/dist-esm/lib/version.mjs.map +2 -2
  95. package/dist-esm/lib/warn.mjs.map +2 -2
  96. package/package.json +1 -1
  97. package/src/lib/ExecutionQueue.test.ts +162 -20
  98. package/src/lib/ExecutionQueue.ts +110 -1
  99. package/src/lib/PerformanceTracker.test.ts +124 -0
  100. package/src/lib/PerformanceTracker.ts +63 -1
  101. package/src/lib/array.test.ts +263 -1
  102. package/src/lib/array.ts +183 -14
  103. package/src/lib/bind.test.ts +47 -0
  104. package/src/lib/bind.ts +69 -4
  105. package/src/lib/cache.test.ts +73 -0
  106. package/src/lib/cache.ts +47 -6
  107. package/src/lib/control.test.ts +50 -0
  108. package/src/lib/control.ts +198 -9
  109. package/src/lib/debounce.ts +28 -3
  110. package/src/lib/error.test.ts +60 -0
  111. package/src/lib/error.ts +27 -1
  112. package/src/lib/file.test.ts +49 -0
  113. package/src/lib/file.ts +117 -12
  114. package/src/lib/function.ts +11 -0
  115. package/src/lib/hash.test.ts +99 -0
  116. package/src/lib/hash.ts +69 -2
  117. package/src/lib/id.test.ts +32 -0
  118. package/src/lib/id.ts +53 -5
  119. package/src/lib/iterable.test.ts +25 -0
  120. package/src/lib/iterable.ts +4 -5
  121. package/src/lib/json-value.ts +71 -4
  122. package/src/lib/media/apng.test.ts +67 -0
  123. package/src/lib/media/apng.ts +38 -21
  124. package/src/lib/media/avif.test.ts +26 -0
  125. package/src/lib/media/avif.ts +34 -0
  126. package/src/lib/media/gif.test.ts +52 -0
  127. package/src/lib/media/gif.ts +25 -2
  128. package/src/lib/media/media.test.ts +58 -0
  129. package/src/lib/media/media.ts +220 -11
  130. package/src/lib/media/png.ts +162 -1
  131. package/src/lib/media/webp.test.ts +81 -0
  132. package/src/lib/media/webp.ts +33 -1
  133. package/src/lib/network.test.ts +38 -0
  134. package/src/lib/network.ts +6 -0
  135. package/src/lib/number.test.ts +74 -0
  136. package/src/lib/number.ts +29 -5
  137. package/src/lib/object.test.ts +236 -0
  138. package/src/lib/object.ts +194 -14
  139. package/src/lib/perf.ts +75 -3
  140. package/src/lib/reordering.test.ts +168 -0
  141. package/src/lib/reordering.ts +62 -4
  142. package/src/lib/retry.test.ts +77 -0
  143. package/src/lib/retry.ts +47 -1
  144. package/src/lib/sort.test.ts +36 -0
  145. package/src/lib/sort.ts +22 -1
  146. package/src/lib/storage.test.ts +130 -0
  147. package/src/lib/storage.tsx +54 -8
  148. package/src/lib/stringEnum.ts +20 -1
  149. package/src/lib/throttle.ts +46 -8
  150. package/src/lib/timers.test.ts +75 -0
  151. package/src/lib/timers.ts +124 -5
  152. package/src/lib/types.ts +126 -4
  153. package/src/lib/url.test.ts +44 -0
  154. package/src/lib/url.ts +40 -1
  155. package/src/lib/value.test.ts +102 -0
  156. package/src/lib/value.ts +67 -3
  157. package/src/lib/version.test.ts +494 -56
  158. package/src/lib/version.ts +36 -1
  159. package/src/lib/warn.test.ts +64 -0
  160. package/src/lib/warn.ts +43 -2
@@ -14,16 +14,54 @@ import { default as uniq } from 'lodash.uniq';
14
14
  /* Excluded from this release type: assertExists */
15
15
 
16
16
  /**
17
- * `@bind` is a decorator that binds the method to the instance of the class (legacy stage-2
18
- * typescript decorators).
17
+ * Decorator that binds a method to its class instance (legacy stage-2 TypeScript decorators).
18
+ * When applied to a class method, ensures `this` always refers to the class instance,
19
+ * even when the method is called as a callback or event handler.
19
20
  *
21
+ * @param target - The prototype of the class being decorated
22
+ * @param propertyKey - The name of the method being decorated
23
+ * @param descriptor - The property descriptor for the method being decorated
24
+ * @returns The modified property descriptor with bound method access
25
+ * @example
26
+ * ```typescript
27
+ * class MyClass {
28
+ * name = 'example';
29
+ *
30
+ * @bind
31
+ * getName() {
32
+ * return this.name;
33
+ * }
34
+ * }
35
+ *
36
+ * const instance = new MyClass();
37
+ * const callback = instance.getName;
38
+ * console.log(callback()); // 'example' (this is properly bound)
39
+ * ```
20
40
  * @public
21
41
  */
22
42
  export declare function bind<T extends (...args: any[]) => any>(target: object, propertyKey: string, descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T>;
23
43
 
24
44
  /**
25
- * `@bind` is a decorator that binds the method to the instance of the class (TC39 decorators).
45
+ * Decorator that binds a method to its class instance (TC39 decorators standard).
46
+ * When applied to a class method, ensures `this` always refers to the class instance,
47
+ * even when the method is called as a callback or event handler.
26
48
  *
49
+ * @param originalMethod - The original method being decorated
50
+ * @param context - The decorator context containing metadata about the method
51
+ * @example
52
+ * ```typescript
53
+ * class EventHandler {
54
+ * message = 'Hello World';
55
+ *
56
+ * @bind
57
+ * handleClick() {
58
+ * console.log(this.message);
59
+ * }
60
+ * }
61
+ *
62
+ * const handler = new EventHandler();
63
+ * document.addEventListener('click', handler.handleClick); // 'this' is properly bound
64
+ * ```
27
65
  * @public
28
66
  */
29
67
  export declare function bind<This extends object, T extends (...args: any[]) => any>(originalMethod: T, context: ClassMethodDecoratorContext<This, T>): void;
@@ -35,12 +73,37 @@ export declare function bind<This extends object, T extends (...args: any[]) =>
35
73
  /* Excluded from this release type: compact */
36
74
 
37
75
  /**
38
- * Debounce a function.
76
+ * Create a debounced version of a function that delays execution until after a specified wait time.
39
77
  *
40
- * @example
78
+ * Debouncing ensures that a function is only executed once after a specified delay,
79
+ * even if called multiple times in rapid succession. Each new call resets the timer. The debounced
80
+ * function returns a Promise that resolves with the result of the original function. Includes a
81
+ * cancel method to prevent execution if needed.
82
+ *
83
+ * @param callback - The function to debounce (can be sync or async)
84
+ * @param wait - The delay in milliseconds before executing the function
85
+ * @returns A debounced function that returns a Promise and includes a cancel method
41
86
  *
87
+ * @example
42
88
  * ```ts
43
- * const A = debounce(myFunction, 1000)
89
+ * // Debounce a search function
90
+ * const searchAPI = (query: string) => fetch(`/search?q=${query}`)
91
+ * const debouncedSearch = debounce(searchAPI, 300)
92
+ *
93
+ * // Multiple rapid calls will only execute the last one after 300ms
94
+ * debouncedSearch('react').then(result => console.log(result))
95
+ * debouncedSearch('react hooks') // This cancels the previous call
96
+ * debouncedSearch('react typescript') // Only this will execute
97
+ *
98
+ * // Cancel pending execution
99
+ * debouncedSearch.cancel()
100
+ *
101
+ * // With async/await
102
+ * const saveData = debounce(async (data: any) => {
103
+ * return await api.save(data)
104
+ * }, 1000)
105
+ *
106
+ * const result = await saveData({name: 'John'})
44
107
  * ```
45
108
  *
46
109
  * @public
@@ -52,22 +115,88 @@ export declare function debounce<T extends unknown[], U>(callback: (...args: T)
52
115
  };
53
116
 
54
117
  /**
55
- * Deduplicate the items in an array
118
+ * Remove duplicate items from an array.
119
+ *
120
+ * Creates a new array with duplicate items removed. Uses strict equality by default,
121
+ * or a custom equality function if provided. Order of first occurrence is preserved.
56
122
  *
123
+ * @param input - The array to deduplicate
124
+ * @param equals - Optional custom equality function to compare items (defaults to strict equality)
125
+ * @returns A new array with duplicate items removed
126
+ *
127
+ * @example
128
+ * ```ts
129
+ * dedupe([1, 2, 2, 3, 1]) // [1, 2, 3]
130
+ * dedupe(['a', 'b', 'a', 'c']) // ['a', 'b', 'c']
131
+ *
132
+ * // With custom equality function
133
+ * const objects = [{id: 1}, {id: 2}, {id: 1}]
134
+ * dedupe(objects, (a, b) => a.id === b.id) // [{id: 1}, {id: 2}]
135
+ * ```
57
136
  * @public
58
137
  */
59
138
  export declare function dedupe<T>(input: T[], equals?: (a: any, b: any) => boolean): T[];
60
139
 
61
- /** @public */
140
+ /**
141
+ * Array of supported video MIME types.
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * import { DEFAULT_SUPPORT_VIDEO_TYPES } from '@tldraw/utils'
146
+ *
147
+ * const isVideo = DEFAULT_SUPPORT_VIDEO_TYPES.includes('video/mp4')
148
+ * console.log(isVideo) // true
149
+ * ```
150
+ * @public
151
+ */
62
152
  export declare const DEFAULT_SUPPORT_VIDEO_TYPES: readonly ("video/mp4" | "video/quicktime" | "video/webm")[];
63
153
 
64
- /** @public */
154
+ /**
155
+ * Array of all supported image MIME types, combining static, vector, and animated types.
156
+ *
157
+ * @example
158
+ * ```ts
159
+ * import { DEFAULT_SUPPORTED_IMAGE_TYPES } from '@tldraw/utils'
160
+ *
161
+ * const isSupported = DEFAULT_SUPPORTED_IMAGE_TYPES.includes('image/png')
162
+ * console.log(isSupported) // true
163
+ * ```
164
+ * @public
165
+ */
65
166
  export declare const DEFAULT_SUPPORTED_IMAGE_TYPES: readonly ("image/apng" | "image/avif" | "image/gif" | "image/jpeg" | "image/png" | "image/svg+xml" | "image/webp")[];
66
167
 
67
- /** @public */
168
+ /**
169
+ * Comma-separated string of all supported media MIME types, useful for HTML file input accept attributes.
170
+ *
171
+ * @example
172
+ * ```ts
173
+ * import { DEFAULT_SUPPORTED_MEDIA_TYPE_LIST } from '@tldraw/utils'
174
+ *
175
+ * // Use in HTML file input for media uploads
176
+ * const input = document.createElement('input')
177
+ * input.type = 'file'
178
+ * input.accept = DEFAULT_SUPPORTED_MEDIA_TYPE_LIST
179
+ * input.addEventListener('change', (e) => {
180
+ * const files = (e.target as HTMLInputElement).files
181
+ * if (files) console.log(`Selected ${files.length} file(s)`)
182
+ * })
183
+ * ```
184
+ * @public
185
+ */
68
186
  export declare const DEFAULT_SUPPORTED_MEDIA_TYPE_LIST: string;
69
187
 
70
- /** @public */
188
+ /**
189
+ * Array of all supported media MIME types, combining images and videos.
190
+ *
191
+ * @example
192
+ * ```ts
193
+ * import { DEFAULT_SUPPORTED_MEDIA_TYPES } from '@tldraw/utils'
194
+ *
195
+ * const isMediaFile = DEFAULT_SUPPORTED_MEDIA_TYPES.includes('video/mp4')
196
+ * console.log(isMediaFile) // true
197
+ * ```
198
+ * @public
199
+ */
71
200
  export declare const DEFAULT_SUPPORTED_MEDIA_TYPES: readonly ("image/apng" | "image/avif" | "image/gif" | "image/jpeg" | "image/png" | "image/svg+xml" | "image/webp" | "video/mp4" | "video/quicktime" | "video/webm")[];
72
201
 
73
202
  /* Excluded from this release type: deleteFromLocalStorage */
@@ -80,7 +209,21 @@ export declare interface ErrorAnnotations {
80
209
  extras: Record<string, unknown>;
81
210
  }
82
211
 
83
- /** @public */
212
+ /**
213
+ * Represents a failed result containing an error.
214
+ *
215
+ * Interface for the error case of a Result type, containing the error information.
216
+ * Used in conjunction with OkResult to create a discriminated union for error handling.
217
+ *
218
+ * @example
219
+ * ```ts
220
+ * const failure: ErrorResult<string> = { ok: false, error: 'Something went wrong' }
221
+ * if (!failure.ok) {
222
+ * console.error(failure.error) // 'Something went wrong'
223
+ * }
224
+ * ```
225
+ * @public
226
+ */
84
227
  export declare interface ErrorResult<E> {
85
228
  readonly ok: false;
86
229
  readonly error: E;
@@ -90,7 +233,27 @@ export declare interface ErrorResult<E> {
90
233
 
91
234
  /* Excluded from this release type: exhaustiveSwitchError */
92
235
 
93
- /** @public */
236
+ /**
237
+ * Expands a type definition to show its full structure in IDE tooltips and error messages.
238
+ * This utility type forces TypeScript to resolve and display the complete type structure
239
+ * instead of showing complex conditional types or intersections as-is.
240
+ *
241
+ * @example
242
+ * ```ts
243
+ * type User = { name: string }
244
+ * type WithId = { id: string }
245
+ * type UserWithId = User & WithId
246
+ *
247
+ * // Without Expand, IDE shows: User & WithId
248
+ * // With Expand, IDE shows: { name: string; id: string }
249
+ * type ExpandedUserWithId = Expand<UserWithId>
250
+ *
251
+ * // Useful for complex intersections
252
+ * type ComplexType = Expand<BaseType & Mixin1 & Mixin2>
253
+ * ```
254
+ *
255
+ * @public
256
+ */
94
257
  export declare type Expand<T> = T extends infer O ? {
95
258
  [K in keyof O]: O[K];
96
259
  } : never;
@@ -98,41 +261,146 @@ export declare type Expand<T> = T extends infer O ? {
98
261
  /* Excluded from this release type: fetch_2 */
99
262
 
100
263
  /**
101
- * Helpers for files
264
+ * Utility class providing helper methods for file and blob operations.
265
+ *
266
+ * FileHelpers contains static methods for common file operations including
267
+ * URL fetching, format conversion, and MIME type manipulation. All methods work with
268
+ * web APIs like fetch, FileReader, and Blob/File objects.
269
+ *
270
+ * @example
271
+ * ```ts
272
+ * // Fetch and convert a remote image to data URL
273
+ * const dataUrl = await FileHelpers.urlToDataUrl('https://example.com/image.png')
274
+ *
275
+ * // Convert user-selected file to text
276
+ * const text = await FileHelpers.blobToText(userFile)
277
+ *
278
+ * // Change file MIME type
279
+ * const newFile = FileHelpers.rewriteMimeType(originalFile, 'application/json')
280
+ * ```
102
281
  *
103
282
  * @public
104
283
  */
105
284
  export declare class FileHelpers {
106
285
  /**
107
- * @param url - The url of the file.
286
+ * Converts a URL to an ArrayBuffer by fetching the resource.
287
+ *
288
+ * Fetches the resource at the given URL and returns its content as an ArrayBuffer.
289
+ * This is useful for loading binary data like images, videos, or other file types.
290
+ *
291
+ * @param url - The URL of the file to fetch
292
+ * @returns Promise that resolves to the file content as an ArrayBuffer
293
+ * @example
294
+ * ```ts
295
+ * const buffer = await FileHelpers.urlToArrayBuffer('https://example.com/image.png')
296
+ * console.log(buffer.byteLength) // Size of the file in bytes
297
+ * ```
298
+ * @public
108
299
  */
109
300
  static urlToArrayBuffer(url: string): Promise<ArrayBuffer>;
110
- static urlToBlob(url: string): Promise<Blob>;
111
- static urlToDataUrl(url: string): Promise<string>;
112
301
  /**
113
- * Convert a file to a base64 encoded data url.
302
+ * Converts a URL to a Blob by fetching the resource.
114
303
  *
304
+ * Fetches the resource at the given URL and returns its content as a Blob object.
305
+ * Blobs are useful for handling file data in web applications.
306
+ *
307
+ * @param url - The URL of the file to fetch
308
+ * @returns Promise that resolves to the file content as a Blob
115
309
  * @example
310
+ * ```ts
311
+ * const blob = await FileHelpers.urlToBlob('https://example.com/document.pdf')
312
+ * console.log(blob.type) // 'application/pdf'
313
+ * console.log(blob.size) // Size in bytes
314
+ * ```
315
+ * @public
316
+ */
317
+ static urlToBlob(url: string): Promise<Blob>;
318
+ /**
319
+ * Converts a URL to a data URL by fetching the resource.
320
+ *
321
+ * Fetches the resource at the given URL and converts it to a base64-encoded data URL.
322
+ * If the URL is already a data URL, it returns the URL unchanged. This is useful for embedding
323
+ * resources directly in HTML or CSS.
116
324
  *
325
+ * @param url - The URL of the file to convert, or an existing data URL
326
+ * @returns Promise that resolves to a data URL string
327
+ * @example
117
328
  * ```ts
118
- * const A = FileHelpers.toDataUrl(myImageFile)
329
+ * const dataUrl = await FileHelpers.urlToDataUrl('https://example.com/image.jpg')
330
+ * // Returns: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEA...'
331
+ *
332
+ * const existing = await FileHelpers.urlToDataUrl('data:text/plain;base64,SGVsbG8=')
333
+ * // Returns the same data URL unchanged
119
334
  * ```
335
+ * @public
336
+ */
337
+ static urlToDataUrl(url: string): Promise<string>;
338
+ /**
339
+ * Convert a Blob to a base64 encoded data URL.
340
+ *
341
+ * Converts a Blob object to a base64-encoded data URL using the FileReader API.
342
+ * This is useful for displaying images or embedding file content directly in HTML.
343
+ *
344
+ * @param file - The Blob object to convert
345
+ * @returns Promise that resolves to a base64-encoded data URL string
346
+ * @example
347
+ * ```ts
348
+ * const blob = new Blob(['Hello World'], { type: 'text/plain' })
349
+ * const dataUrl = await FileHelpers.blobToDataUrl(blob)
350
+ * // Returns: 'data:text/plain;base64,SGVsbG8gV29ybGQ='
120
351
  *
121
- * @param file - The file as a blob.
352
+ * // With an image file
353
+ * const imageDataUrl = await FileHelpers.blobToDataUrl(myImageFile)
354
+ * // Can be used directly in img src attribute
355
+ * ```
356
+ * @public
122
357
  */
123
358
  static blobToDataUrl(file: Blob): Promise<string>;
124
359
  /**
125
- * Convert a file to a unicode text string.
360
+ * Convert a Blob to a unicode text string.
126
361
  *
127
- * @example
362
+ * Reads the content of a Blob object as a UTF-8 text string using the FileReader API.
363
+ * This is useful for reading text files or extracting text content from blobs.
128
364
  *
365
+ * @param file - The Blob object to convert to text
366
+ * @returns Promise that resolves to the text content as a string
367
+ * @example
129
368
  * ```ts
130
- * const A = FileHelpers.fileToDataUrl(myTextFile)
131
- * ```
369
+ * const textBlob = new Blob(['Hello World'], { type: 'text/plain' })
370
+ * const text = await FileHelpers.blobToText(textBlob)
371
+ * console.log(text) // 'Hello World'
132
372
  *
133
- * @param file - The file as a blob.
373
+ * // With a text file from user input
374
+ * const content = await FileHelpers.blobToText(myTextFile)
375
+ * console.log(content) // File content as string
376
+ * ```
377
+ * @public
134
378
  */
135
379
  static blobToText(file: Blob): Promise<string>;
380
+ /**
381
+ * Creates a new Blob or File with a different MIME type.
382
+ *
383
+ * Creates a copy of the given Blob or File with a new MIME type while preserving
384
+ * all other properties. If the current MIME type already matches the new one, returns the
385
+ * original object unchanged. For File objects, preserves the filename.
386
+ *
387
+ * @param blob - The Blob or File object to modify
388
+ * @param newMimeType - The new MIME type to assign
389
+ * @returns A new Blob or File with the updated MIME type
390
+ * @example
391
+ * ```ts
392
+ * // Change a generic blob to a specific image type
393
+ * const blob = new Blob([imageData])
394
+ * const imageBlob = FileHelpers.rewriteMimeType(blob, 'image/png')
395
+ *
396
+ * // Change a file's MIME type while preserving filename
397
+ * const file = new File([data], 'document.txt', { type: 'text/plain' })
398
+ * const jsonFile = FileHelpers.rewriteMimeType(file, 'application/json')
399
+ * console.log(jsonFile.name) // 'document.txt' (preserved)
400
+ * console.log(jsonFile.type) // 'application/json' (updated)
401
+ * ```
402
+ * @public
403
+ */
136
404
  static rewriteMimeType(blob: Blob, newMimeType: string): Blob;
137
405
  static rewriteMimeType(blob: File, newMimeType: string): File;
138
406
  }
@@ -148,19 +416,18 @@ export declare class FileHelpers {
148
416
  /**
149
417
  * Get the first item from an iterable Set or Map.
150
418
  *
419
+ * @param value - The iterable Set or Map to get the first item from
420
+ * @returns The first value from the Set or Map
151
421
  * @example
152
- *
153
422
  * ```ts
154
- * const A = getFirstItem(new Set([1, 2, 3])) // 1
155
- * const B = getFirstItem(
423
+ * const A = getFirstFromIterable(new Set([1, 2, 3])) // 1
424
+ * const B = getFirstFromIterable(
156
425
  * new Map([
157
426
  * ['a', 1],
158
427
  * ['b', 2],
159
428
  * ])
160
429
  * ) // 1
161
430
  * ```
162
- *
163
- * @param value - The iterable Set or Map.
164
431
  * @public
165
432
  */
166
433
  export declare function getFirstFromIterable<T = unknown>(set: Map<any, T> | Set<T>): T;
@@ -172,13 +439,47 @@ export declare function getFirstFromIterable<T = unknown>(set: Map<any, T> | Set
172
439
  /**
173
440
  * Hash an ArrayBuffer using the FNV-1a algorithm.
174
441
  *
442
+ * Generates a deterministic hash value for binary data stored in an ArrayBuffer.
443
+ * Processes the buffer byte by byte using the same hashing algorithm as getHashForString.
444
+ * Useful for creating consistent identifiers for binary data like images or files.
445
+ *
446
+ * @param buffer - The ArrayBuffer containing binary data to hash
447
+ * @returns A string representation of the 32-bit hash value
448
+ * @example
449
+ * ```ts
450
+ * // Hash some binary data
451
+ * const data = new Uint8Array([1, 2, 3, 4, 5])
452
+ * const hash = getHashForBuffer(data.buffer)
453
+ * console.log(hash) // '123456789'
454
+ *
455
+ * // Hash image file data
456
+ * const fileBuffer = await file.arrayBuffer()
457
+ * const fileHash = getHashForBuffer(fileBuffer)
458
+ * console.log(fileHash) // Unique hash for the file
459
+ * ```
175
460
  * @public
176
461
  */
177
462
  export declare function getHashForBuffer(buffer: ArrayBuffer): string;
178
463
 
179
464
  /**
180
- * Hash a string using the FNV-1a algorithm.
465
+ * Hash an object by converting it to JSON and then hashing the resulting string.
466
+ *
467
+ * Converts the object to a JSON string using JSON.stringify and then applies the same
468
+ * hashing algorithm as getHashForString. Useful for creating consistent hash values
469
+ * for objects, though the hash depends on JSON serialization order.
470
+ *
471
+ * @param obj - The object to hash (any JSON-serializable value)
472
+ * @returns A string representation of the 32-bit hash value
473
+ * @example
474
+ * ```ts
475
+ * const hash1 = getHashForObject({ name: 'John', age: 30 })
476
+ * const hash2 = getHashForObject({ name: 'John', age: 30 })
477
+ * console.log(hash1 === hash2) // true
181
478
  *
479
+ * // Arrays work too
480
+ * const arrayHash = getHashForObject([1, 2, 3, 'hello'])
481
+ * console.log(arrayHash) // '-123456789'
482
+ * ```
182
483
  * @public
183
484
  */
184
485
  export declare function getHashForObject(obj: any): string;
@@ -186,6 +487,20 @@ export declare function getHashForObject(obj: any): string;
186
487
  /**
187
488
  * Hash a string using the FNV-1a algorithm.
188
489
  *
490
+ * Generates a deterministic hash value for a given string using a variant of the FNV-1a
491
+ * (Fowler-Noll-Vo) algorithm. The hash is returned as a string representation of a 32-bit integer.
492
+ *
493
+ * @param string - The input string to hash
494
+ * @returns A string representation of the 32-bit hash value
495
+ * @example
496
+ * ```ts
497
+ * const hash = getHashForString('hello world')
498
+ * console.log(hash) // '-862545276'
499
+ *
500
+ * // Same input always produces same hash
501
+ * const hash2 = getHashForString('hello world')
502
+ * console.log(hash === hash2) // true
503
+ * ```
189
504
  * @public
190
505
  */
191
506
  export declare function getHashForString(string: string): string;
@@ -193,6 +508,12 @@ export declare function getHashForString(string: string): string;
193
508
  /**
194
509
  * Get the index above a given index.
195
510
  * @param below - The index below.
511
+ * @returns An IndexKey value above the given index.
512
+ * @example
513
+ * ```ts
514
+ * const index = getIndexAbove('a0' as IndexKey)
515
+ * console.log(index) // 'a1'
516
+ * ```
196
517
  * @public
197
518
  */
198
519
  export declare function getIndexAbove(below?: IndexKey | null | undefined): IndexKey;
@@ -200,7 +521,13 @@ export declare function getIndexAbove(below?: IndexKey | null | undefined): Inde
200
521
  /**
201
522
  * Get the index below a given index.
202
523
  * @param above - The index above.
203
- * @public
524
+ * @returns An IndexKey value below the given index.
525
+ * @example
526
+ * ```ts
527
+ * const index = getIndexBelow('a2' as IndexKey)
528
+ * console.log(index) // 'a1'
529
+ * ```
530
+ * @public
204
531
  */
205
532
  export declare function getIndexBelow(above?: IndexKey | null | undefined): IndexKey;
206
533
 
@@ -208,6 +535,12 @@ export declare function getIndexBelow(above?: IndexKey | null | undefined): Inde
208
535
  * Get the index between two indices.
209
536
  * @param below - The index below.
210
537
  * @param above - The index above.
538
+ * @returns A single IndexKey value between below and above.
539
+ * @example
540
+ * ```ts
541
+ * const index = getIndexBetween('a0' as IndexKey, 'a2' as IndexKey)
542
+ * console.log(index) // 'a1'
543
+ * ```
211
544
  * @public
212
545
  */
213
546
  export declare function getIndexBetween(below: IndexKey | null | undefined, above: IndexKey | null | undefined): IndexKey;
@@ -215,7 +548,13 @@ export declare function getIndexBetween(below: IndexKey | null | undefined, abov
215
548
  /**
216
549
  * Get n number of indices, starting at an index.
217
550
  * @param n - The number of indices to get.
218
- * @param start - The index to start at.
551
+ * @param start - The index to start at.
552
+ * @returns An array containing the start index plus n additional IndexKey values.
553
+ * @example
554
+ * ```ts
555
+ * const indices = getIndices(3, 'a1' as IndexKey)
556
+ * console.log(indices) // ['a1', 'a2', 'a3', 'a4']
557
+ * ```
219
558
  * @public
220
559
  */
221
560
  export declare function getIndices(n: number, start?: IndexKey): IndexKey[];
@@ -224,6 +563,12 @@ export declare function getIndices(n: number, start?: IndexKey): IndexKey[];
224
563
  * Get a number of indices above an index.
225
564
  * @param below - The index below.
226
565
  * @param n - The number of indices to get.
566
+ * @returns An array of n IndexKey values above the given index.
567
+ * @example
568
+ * ```ts
569
+ * const indices = getIndicesAbove('a0' as IndexKey, 3)
570
+ * console.log(indices) // ['a1', 'a2', 'a3']
571
+ * ```
227
572
  * @public
228
573
  */
229
574
  export declare function getIndicesAbove(below: IndexKey | null | undefined, n: number): IndexKey[];
@@ -232,6 +577,12 @@ export declare function getIndicesAbove(below: IndexKey | null | undefined, n: n
232
577
  * Get a number of indices below an index.
233
578
  * @param above - The index above.
234
579
  * @param n - The number of indices to get.
580
+ * @returns An array of n IndexKey values below the given index.
581
+ * @example
582
+ * ```ts
583
+ * const indices = getIndicesBelow('a2' as IndexKey, 2)
584
+ * console.log(indices) // ['a1', 'a0V']
585
+ * ```
235
586
  * @public
236
587
  */
237
588
  export declare function getIndicesBelow(above: IndexKey | null | undefined, n: number): IndexKey[];
@@ -241,6 +592,12 @@ export declare function getIndicesBelow(above: IndexKey | null | undefined, n: n
241
592
  * @param below - The index below.
242
593
  * @param above - The index above.
243
594
  * @param n - The number of indices to get.
595
+ * @returns An array of n IndexKey values between below and above.
596
+ * @example
597
+ * ```ts
598
+ * const indices = getIndicesBetween('a0' as IndexKey, 'a2' as IndexKey, 2)
599
+ * console.log(indices) // ['a0V', 'a1']
600
+ * ```
244
601
  * @public
245
602
  */
246
603
  export declare function getIndicesBetween(below: IndexKey | null | undefined, above: IndexKey | null | undefined, n: number): IndexKey[];
@@ -265,9 +622,18 @@ export declare type IndexKey = string & {
265
622
  };
266
623
 
267
624
  /**
268
- * Inverse lerp between two values. Given a value `n` in the range [a, b], returns a number between
625
+ * Inverse lerp between two values. Given a value `t` in the range [a, b], returns a number between
269
626
  * 0 and 1.
270
627
  *
628
+ * @param a - The start value of the range
629
+ * @param b - The end value of the range
630
+ * @param t - The value within the range [a, b]
631
+ * @returns The normalized position (0-1) of t within the range [a, b]
632
+ * @example
633
+ * ```ts
634
+ * const position = invLerp(0, 100, 25) // 0.25
635
+ * const normalized = invLerp(10, 20, 15) // 0.5
636
+ * ```
271
637
  * @public
272
638
  */
273
639
  export declare function invLerp(a: number, b: number, t: number): number;
@@ -276,6 +642,20 @@ export declare function invLerp(a: number, b: number, t: number): number;
276
642
  * Get whether a value is not undefined.
277
643
  *
278
644
  * @param value - The value to check.
645
+ * @returns True if the value is not undefined, with proper type narrowing.
646
+ * @example
647
+ * ```ts
648
+ * const maybeString: string | undefined = getValue()
649
+ *
650
+ * if (isDefined(maybeString)) {
651
+ * // TypeScript knows maybeString is string, not undefined
652
+ * console.log(maybeString.toUpperCase())
653
+ * }
654
+ *
655
+ * // Filter undefined values from arrays
656
+ * const values = [1, undefined, 2, undefined, 3]
657
+ * const definedValues = values.filter(isDefined) // [1, 2, 3]
658
+ * ```
279
659
  * @public
280
660
  */
281
661
  export declare function isDefined<T>(value: T): value is typeof value extends undefined ? never : T;
@@ -288,33 +668,125 @@ export { isEqualWith }
288
668
  /* Excluded from this release type: isNativeStructuredClone */
289
669
 
290
670
  /**
291
- * Get whether a value is null
671
+ * Get whether a value is not null.
292
672
  *
293
673
  * @param value - The value to check.
674
+ * @returns True if the value is not null, with proper type narrowing.
675
+ * @example
676
+ * ```ts
677
+ * const maybeString: string | null = getValue()
678
+ *
679
+ * if (isNonNull(maybeString)) {
680
+ * // TypeScript knows maybeString is string, not null
681
+ * console.log(maybeString.length)
682
+ * }
683
+ *
684
+ * // Filter null values from arrays
685
+ * const values = ["a", null, "b", null, "c"]
686
+ * const nonNullValues = values.filter(isNonNull) // ["a", "b", "c"]
687
+ * ```
294
688
  * @public
295
689
  */
296
690
  export declare function isNonNull<T>(value: T): value is typeof value extends null ? never : T;
297
691
 
298
692
  /**
299
- * Get whether a value is nullish (null, undefined).
693
+ * Get whether a value is not nullish (not null and not undefined).
300
694
  *
301
695
  * @param value - The value to check.
696
+ * @returns True if the value is neither null nor undefined, with proper type narrowing.
697
+ * @example
698
+ * ```ts
699
+ * const maybeString: string | null | undefined = getValue()
700
+ *
701
+ * if (isNonNullish(maybeString)) {
702
+ * // TypeScript knows maybeString is string, not null or undefined
703
+ * console.log(maybeString.charAt(0))
704
+ * }
705
+ *
706
+ * // Filter nullish values from arrays
707
+ * const values = ["hello", null, "world", undefined, "!"]
708
+ * const cleanValues = values.filter(isNonNullish) // ["hello", "world", "!"]
709
+ * ```
302
710
  * @public
303
711
  */
304
712
  export declare function isNonNullish<T>(value: T): value is typeof value extends undefined ? never : typeof value extends null ? never : T;
305
713
 
306
- /** @public */
714
+ /**
715
+ * A type representing a JSON array containing any valid JSON values.
716
+ * Arrays can contain mixed types of JSON values including nested arrays and objects.
717
+ *
718
+ * @example
719
+ * ```ts
720
+ * const jsonArray: JsonArray = [
721
+ * "text",
722
+ * 123,
723
+ * true,
724
+ * { nested: "object" },
725
+ * [1, 2, 3]
726
+ * ]
727
+ * ```
728
+ *
729
+ * @public
730
+ */
307
731
  export declare type JsonArray = JsonValue[];
308
732
 
309
- /** @public */
733
+ /**
734
+ * A type representing a JSON object with string keys and JSON values.
735
+ * Object values can be undefined to handle optional properties safely.
736
+ *
737
+ * @example
738
+ * ```ts
739
+ * const jsonObject: JsonObject = {
740
+ * required: "value",
741
+ * optional: undefined,
742
+ * nested: {
743
+ * deep: "property"
744
+ * },
745
+ * array: [1, 2, 3]
746
+ * }
747
+ * ```
748
+ *
749
+ * @public
750
+ */
310
751
  export declare interface JsonObject {
311
752
  [key: string]: JsonValue | undefined;
312
753
  }
313
754
 
314
- /** @public */
755
+ /**
756
+ * A type representing JSON primitive values: boolean, null, string, or number.
757
+ * These are the atomic values that can appear in JSON data.
758
+ *
759
+ * @example
760
+ * ```ts
761
+ * const primitives: JsonPrimitive[] = [
762
+ * true,
763
+ * null,
764
+ * "hello",
765
+ * 42
766
+ * ]
767
+ * ```
768
+ *
769
+ * @public
770
+ */
315
771
  export declare type JsonPrimitive = boolean | null | number | string;
316
772
 
317
- /** @public */
773
+ /**
774
+ * A type that represents any valid JSON value. This includes primitives (boolean, null, string, number),
775
+ * arrays of JSON values, and objects with string keys and JSON values.
776
+ *
777
+ * @example
778
+ * ```ts
779
+ * const jsonData: JsonValue = {
780
+ * name: "Alice",
781
+ * age: 30,
782
+ * active: true,
783
+ * tags: ["user", "premium"],
784
+ * metadata: null
785
+ * }
786
+ * ```
787
+ *
788
+ * @public
789
+ */
318
790
  export declare type JsonValue = JsonArray | JsonObject | JsonPrimitive;
319
791
 
320
792
  /* Excluded from this release type: last */
@@ -322,20 +794,72 @@ export declare type JsonValue = JsonArray | JsonObject | JsonPrimitive;
322
794
  /**
323
795
  * Linear interpolate between two values.
324
796
  *
797
+ * @param a - The start value
798
+ * @param b - The end value
799
+ * @param t - The interpolation factor (0-1)
800
+ * @returns The interpolated value
325
801
  * @example
326
- *
327
802
  * ```ts
328
- * const A = lerp(0, 1, 0.5)
803
+ * const halfway = lerp(0, 100, 0.5) // 50
804
+ * const quarter = lerp(10, 20, 0.25) // 12.5
329
805
  * ```
330
- *
331
806
  * @public
332
807
  */
333
808
  export declare function lerp(a: number, b: number, t: number): number;
334
809
 
335
- /** @public */
810
+ /**
811
+ * Applies a string transformation algorithm that rearranges and modifies characters.
812
+ *
813
+ * Performs a series of character manipulations on the input string including
814
+ * character repositioning through splicing operations and numeric character transformations.
815
+ * This appears to be a custom encoding/obfuscation function.
816
+ *
817
+ * @param str - The input string to transform
818
+ * @returns The transformed string after applying all manipulations
819
+ * @example
820
+ * ```ts
821
+ * const result = lns('hello123')
822
+ * console.log(result) // Transformed string (exact output depends on algorithm)
823
+ *
824
+ * // Can be used for simple string obfuscation
825
+ * const obfuscated = lns('sensitive-data')
826
+ * console.log(obfuscated) // Obfuscated version
827
+ * ```
828
+ * @public
829
+ */
336
830
  export declare function lns(str: string): string;
337
831
 
338
- /** @public */
832
+ /**
833
+ * Automatically makes properties optional if their type includes `undefined`.
834
+ * This transforms properties like `prop: string | undefined` to `prop?: string | undefined`,
835
+ * making the API more ergonomic by not requiring explicit undefined assignments.
836
+ *
837
+ * @example
838
+ * ```ts
839
+ * interface RawConfig {
840
+ * name: string
841
+ * theme: string | undefined
842
+ * debug: boolean | undefined
843
+ * version: number
844
+ * }
845
+ *
846
+ * type Config = MakeUndefinedOptional<RawConfig>
847
+ * // Result: {
848
+ * // name: string
849
+ * // theme?: string | undefined // now optional
850
+ * // debug?: boolean | undefined // now optional
851
+ * // version: number
852
+ * // }
853
+ *
854
+ * const config: Config = {
855
+ * name: 'MyApp',
856
+ * version: 1
857
+ * // theme and debug can be omitted instead of explicitly set to undefined
858
+ * }
859
+ * ```
860
+ *
861
+ * @public
862
+ */
339
863
  export declare type MakeUndefinedOptional<T extends object> = Expand<{
340
864
  [P in {
341
865
  [K in keyof T]: undefined extends T[K] ? never : K;
@@ -363,24 +887,65 @@ export declare type MakeUndefinedOptional<T extends object> = Expand<{
363
887
  */
364
888
  export declare class MediaHelpers {
365
889
  /**
366
- * Load a video from a url.
890
+ * Load a video element from a URL with cross-origin support.
891
+ *
892
+ * @param src - The URL of the video to load
893
+ * @returns Promise that resolves to the loaded HTMLVideoElement
894
+ * @example
895
+ * ```ts
896
+ * const video = await MediaHelpers.loadVideo('https://example.com/video.mp4')
897
+ * console.log(`Video dimensions: ${video.videoWidth}x${video.videoHeight}`)
898
+ * ```
367
899
  * @public
368
900
  */
369
901
  static loadVideo(src: string): Promise<HTMLVideoElement>;
370
- static getVideoFrameAsDataUrl(video: HTMLVideoElement, time?: number): Promise<string>;
371
902
  /**
372
- * Load an image from a url.
903
+ * Extract a frame from a video element as a data URL.
904
+ *
905
+ * @param video - The HTMLVideoElement to extract frame from
906
+ * @param time - The time in seconds to extract the frame from (default: 0)
907
+ * @returns Promise that resolves to a data URL of the video frame
908
+ * @example
909
+ * ```ts
910
+ * const video = await MediaHelpers.loadVideo('https://example.com/video.mp4')
911
+ * const frameDataUrl = await MediaHelpers.getVideoFrameAsDataUrl(video, 5.0)
912
+ * // Use frameDataUrl as image thumbnail
913
+ * const img = document.createElement('img')
914
+ * img.src = frameDataUrl
915
+ * ```
373
916
  * @public
374
917
  */
375
- static getImageAndDimensions(src: string): Promise<{
376
- h: number;
377
- image: HTMLImageElement;
378
- w: number;
918
+ static getVideoFrameAsDataUrl(video: HTMLVideoElement, time?: number): Promise<string>;
919
+ /**
920
+ * Load an image from a URL and get its dimensions along with the image element.
921
+ *
922
+ * @param src - The URL of the image to load
923
+ * @returns Promise that resolves to an object with width, height, and the image element
924
+ * @example
925
+ * ```ts
926
+ * const { w, h, image } = await MediaHelpers.getImageAndDimensions('https://example.com/image.png')
927
+ * console.log(`Image size: ${w}x${h}`)
928
+ * // Image is ready to use
929
+ * document.body.appendChild(image)
930
+ * ```
931
+ * @public
932
+ */
933
+ static getImageAndDimensions(src: string): Promise<{
934
+ h: number;
935
+ image: HTMLImageElement;
936
+ w: number;
379
937
  }>;
380
938
  /**
381
939
  * Get the size of a video blob
382
940
  *
383
- * @param blob - A SharedBlob containing the video
941
+ * @param blob - A Blob containing the video
942
+ * @returns Promise that resolves to an object with width and height properties
943
+ * @example
944
+ * ```ts
945
+ * const file = new File([...], 'video.mp4', { type: 'video/mp4' })
946
+ * const { w, h } = await MediaHelpers.getVideoSize(file)
947
+ * console.log(`Video dimensions: ${w}x${h}`)
948
+ * ```
384
949
  * @public
385
950
  */
386
951
  static getVideoSize(blob: Blob): Promise<{
@@ -390,18 +955,103 @@ export declare class MediaHelpers {
390
955
  /**
391
956
  * Get the size of an image blob
392
957
  *
393
- * @param blob - A Blob containing the image.
958
+ * @param blob - A Blob containing the image
959
+ * @returns Promise that resolves to an object with width and height properties
960
+ * @example
961
+ * ```ts
962
+ * const file = new File([...], 'image.png', { type: 'image/png' })
963
+ * const { w, h } = await MediaHelpers.getImageSize(file)
964
+ * console.log(`Image dimensions: ${w}x${h}`)
965
+ * ```
394
966
  * @public
395
967
  */
396
968
  static getImageSize(blob: Blob): Promise<{
397
969
  h: number;
398
970
  w: number;
399
971
  }>;
972
+ /**
973
+ * Check if a media file blob contains animation data.
974
+ *
975
+ * @param file - The Blob to check for animation
976
+ * @returns Promise that resolves to true if the file is animated, false otherwise
977
+ * @example
978
+ * ```ts
979
+ * const file = new File([...], 'animation.gif', { type: 'image/gif' })
980
+ * const animated = await MediaHelpers.isAnimated(file)
981
+ * console.log(animated ? 'Animated' : 'Static')
982
+ * ```
983
+ * @public
984
+ */
400
985
  static isAnimated(file: Blob): Promise<boolean>;
986
+ /**
987
+ * Check if a MIME type represents an animated image format.
988
+ *
989
+ * @param mimeType - The MIME type to check
990
+ * @returns True if the MIME type is an animated image format, false otherwise
991
+ * @example
992
+ * ```ts
993
+ * const isAnimated = MediaHelpers.isAnimatedImageType('image/gif')
994
+ * console.log(isAnimated) // true
995
+ * ```
996
+ * @public
997
+ */
401
998
  static isAnimatedImageType(mimeType: null | string): boolean;
999
+ /**
1000
+ * Check if a MIME type represents a static (non-animated) image format.
1001
+ *
1002
+ * @param mimeType - The MIME type to check
1003
+ * @returns True if the MIME type is a static image format, false otherwise
1004
+ * @example
1005
+ * ```ts
1006
+ * const isStatic = MediaHelpers.isStaticImageType('image/jpeg')
1007
+ * console.log(isStatic) // true
1008
+ * ```
1009
+ * @public
1010
+ */
402
1011
  static isStaticImageType(mimeType: null | string): boolean;
1012
+ /**
1013
+ * Check if a MIME type represents a vector image format.
1014
+ *
1015
+ * @param mimeType - The MIME type to check
1016
+ * @returns True if the MIME type is a vector image format, false otherwise
1017
+ * @example
1018
+ * ```ts
1019
+ * const isVector = MediaHelpers.isVectorImageType('image/svg+xml')
1020
+ * console.log(isVector) // true
1021
+ * ```
1022
+ * @public
1023
+ */
403
1024
  static isVectorImageType(mimeType: null | string): boolean;
1025
+ /**
1026
+ * Check if a MIME type represents any supported image format (static, animated, or vector).
1027
+ *
1028
+ * @param mimeType - The MIME type to check
1029
+ * @returns True if the MIME type is a supported image format, false otherwise
1030
+ * @example
1031
+ * ```ts
1032
+ * const isImage = MediaHelpers.isImageType('image/png')
1033
+ * console.log(isImage) // true
1034
+ * ```
1035
+ * @public
1036
+ */
404
1037
  static isImageType(mimeType: string): boolean;
1038
+ /**
1039
+ * Utility function to create an object URL from a blob, execute a function with it, and automatically clean it up.
1040
+ *
1041
+ * @param blob - The Blob to create an object URL for
1042
+ * @param fn - Function to execute with the object URL
1043
+ * @returns Promise that resolves to the result of the function
1044
+ * @example
1045
+ * ```ts
1046
+ * const result = await MediaHelpers.usingObjectURL(imageBlob, async (url) => {
1047
+ * const { w, h } = await MediaHelpers.getImageAndDimensions(url)
1048
+ * return { width: w, height: h }
1049
+ * })
1050
+ * // Object URL is automatically revoked after function completes
1051
+ * console.log(`Image dimensions: ${result.width}x${result.height}`)
1052
+ * ```
1053
+ * @public
1054
+ */
405
1055
  static usingObjectURL<T>(blob: Blob, fn: (url: string) => Promise<T>): Promise<T>;
406
1056
  }
407
1057
 
@@ -440,7 +1090,21 @@ export declare function modulate(value: number, rangeA: number[], rangeB: number
440
1090
 
441
1091
  /* Excluded from this release type: objectMapValues */
442
1092
 
443
- /** @public */
1093
+ /**
1094
+ * Represents a successful result containing a value.
1095
+ *
1096
+ * Interface for the success case of a Result type, containing the computed value.
1097
+ * Used in conjunction with ErrorResult to create a discriminated union for error handling.
1098
+ *
1099
+ * @example
1100
+ * ```ts
1101
+ * const success: OkResult<string> = { ok: true, value: 'Hello World' }
1102
+ * if (success.ok) {
1103
+ * console.log(success.value) // 'Hello World'
1104
+ * }
1105
+ * ```
1106
+ * @public
1107
+ */
444
1108
  export declare interface OkResult<T> {
445
1109
  readonly ok: true;
446
1110
  readonly value: T;
@@ -452,44 +1116,307 @@ export declare interface OkResult<T> {
452
1116
 
453
1117
  /* Excluded from this release type: partition */
454
1118
 
455
- /** @public */
1119
+ /**
1120
+ * A utility class for measuring and tracking frame rate performance during operations.
1121
+ * Provides visual feedback in the browser console with color-coded FPS indicators.
1122
+ *
1123
+ * @example
1124
+ * ```ts
1125
+ * const tracker = new PerformanceTracker()
1126
+ *
1127
+ * tracker.start('render')
1128
+ * renderShapes()
1129
+ * tracker.stop() // Logs performance info to console
1130
+ *
1131
+ * // Check if tracking is active
1132
+ * if (tracker.isStarted()) {
1133
+ * console.log('Still tracking performance')
1134
+ * }
1135
+ * ```
1136
+ *
1137
+ * @public
1138
+ */
456
1139
  export declare class PerformanceTracker {
457
1140
  private startTime;
458
1141
  private name;
459
1142
  private frames;
460
1143
  private started;
461
1144
  private frame;
1145
+ /**
1146
+ * Records animation frames to calculate frame rate.
1147
+ * Called automatically during performance tracking.
1148
+ */
462
1149
  recordFrame: () => void;
1150
+ /**
1151
+ * Starts performance tracking for a named operation.
1152
+ *
1153
+ * @param name - A descriptive name for the operation being tracked
1154
+ *
1155
+ * @example
1156
+ * ```ts
1157
+ * tracker.start('canvas-render')
1158
+ * // ... perform rendering operations
1159
+ * tracker.stop()
1160
+ * ```
1161
+ */
463
1162
  start(name: string): void;
1163
+ /**
1164
+ * Stops performance tracking and logs results to the console.
1165
+ *
1166
+ * Displays the operation name, frame rate, and uses color coding:
1167
+ * - Green background: \> 55 FPS (good performance)
1168
+ * - Yellow background: 30-55 FPS (moderate performance)
1169
+ * - Red background: \< 30 FPS (poor performance)
1170
+ *
1171
+ * @example
1172
+ * ```ts
1173
+ * tracker.start('interaction')
1174
+ * handleUserInteraction()
1175
+ * tracker.stop() // Logs: "Perf Interaction 60 fps"
1176
+ * ```
1177
+ */
464
1178
  stop(): void;
1179
+ /**
1180
+ * Checks whether performance tracking is currently active.
1181
+ *
1182
+ * @returns True if tracking is in progress, false otherwise
1183
+ *
1184
+ * @example
1185
+ * ```ts
1186
+ * if (!tracker.isStarted()) {
1187
+ * tracker.start('new-operation')
1188
+ * }
1189
+ * ```
1190
+ */
465
1191
  isStarted(): boolean;
466
1192
  }
467
1193
 
468
- /** @public */
1194
+ /**
1195
+ * Utility class for reading and manipulating PNG image files.
1196
+ * Provides methods for parsing PNG chunks, validating PNG format, and modifying PNG metadata.
1197
+ *
1198
+ * @example
1199
+ * ```ts
1200
+ * // Validate PNG file from blob
1201
+ * const blob = new Blob([pngData], { type: 'image/png' })
1202
+ * const view = new DataView(await blob.arrayBuffer())
1203
+ * const isPng = PngHelpers.isPng(view, 0)
1204
+ *
1205
+ * // Parse PNG metadata for image processing
1206
+ * const chunks = PngHelpers.readChunks(view)
1207
+ * const physChunk = PngHelpers.findChunk(view, 'pHYs')
1208
+ *
1209
+ * // Create high-DPI PNG for export
1210
+ * const highDpiBlob = PngHelpers.setPhysChunk(view, 2, { type: 'image/png' })
1211
+ * ```
1212
+ *
1213
+ * @public
1214
+ */
469
1215
  export declare class PngHelpers {
1216
+ /**
1217
+ * Checks if binary data at the specified offset contains a valid PNG file signature.
1218
+ * Validates the 8-byte PNG signature: 89 50 4E 47 0D 0A 1A 0A.
1219
+ *
1220
+ * @param view - DataView containing the binary data to check
1221
+ * @param offset - Byte offset where the PNG signature should start
1222
+ * @returns True if the data contains a valid PNG signature, false otherwise
1223
+ *
1224
+ * @example
1225
+ * ```ts
1226
+ * // Validate PNG from file upload
1227
+ * const file = event.target.files[0]
1228
+ * const buffer = await file.arrayBuffer()
1229
+ * const view = new DataView(buffer)
1230
+ *
1231
+ * if (PngHelpers.isPng(view, 0)) {
1232
+ * console.log('Valid PNG file detected')
1233
+ * // Process PNG file...
1234
+ * } else {
1235
+ * console.error('Not a valid PNG file')
1236
+ * }
1237
+ * ```
1238
+ */
470
1239
  static isPng(view: DataView, offset: number): boolean;
1240
+ /**
1241
+ * Reads the 4-character chunk type identifier from a PNG chunk header.
1242
+ *
1243
+ * @param view - DataView containing the PNG data
1244
+ * @param offset - Byte offset of the chunk type field (after length field)
1245
+ * @returns 4-character string representing the chunk type (e.g., 'IHDR', 'IDAT', 'IEND')
1246
+ *
1247
+ * @example
1248
+ * ```ts
1249
+ * // Read chunk type from PNG header (after 8-byte signature)
1250
+ * const chunkType = PngHelpers.getChunkType(dataView, 8)
1251
+ * console.log(chunkType) // 'IHDR' (Image Header)
1252
+ *
1253
+ * // Read chunk type at a specific position during parsing
1254
+ * let offset = 8 // Skip PNG signature
1255
+ * const chunkLength = dataView.getUint32(offset)
1256
+ * const type = PngHelpers.getChunkType(dataView, offset + 4)
1257
+ * ```
1258
+ */
471
1259
  static getChunkType(view: DataView, offset: number): string;
1260
+ /**
1261
+ * Parses all chunks in a PNG file and returns their metadata.
1262
+ * Skips duplicate IDAT chunks but includes all other chunk types.
1263
+ *
1264
+ * @param view - DataView containing the complete PNG file data
1265
+ * @param offset - Starting byte offset (defaults to 0)
1266
+ * @returns Record mapping chunk types to their metadata (start position, data offset, and size)
1267
+ * @throws Error if the data is not a valid PNG file
1268
+ *
1269
+ * @example
1270
+ * ```ts
1271
+ * // Parse PNG structure for metadata extraction
1272
+ * const view = new DataView(await blob.arrayBuffer())
1273
+ * const chunks = PngHelpers.readChunks(view)
1274
+ *
1275
+ * // Check for specific chunks
1276
+ * const ihdrChunk = chunks['IHDR']
1277
+ * const physChunk = chunks['pHYs']
1278
+ *
1279
+ * if (physChunk) {
1280
+ * console.log(`Found pixel density info at byte ${physChunk.start}`)
1281
+ * } else {
1282
+ * console.log('No pixel density information found')
1283
+ * }
1284
+ * ```
1285
+ */
472
1286
  static readChunks(view: DataView, offset?: number): Record<string, {
473
1287
  dataOffset: number;
474
1288
  size: number;
475
1289
  start: number;
476
1290
  }>;
1291
+ /**
1292
+ * Parses the pHYs (physical pixel dimensions) chunk data.
1293
+ * Reads pixels per unit for X and Y axes, and the unit specifier.
1294
+ *
1295
+ * @param view - DataView containing the PNG data
1296
+ * @param offset - Byte offset of the pHYs chunk data
1297
+ * @returns Object with ppux (pixels per unit X), ppuy (pixels per unit Y), and unit specifier
1298
+ *
1299
+ * @example
1300
+ * ```ts
1301
+ * // Extract pixel density information for DPI calculation
1302
+ * const physChunk = PngHelpers.findChunk(dataView, 'pHYs')
1303
+ * if (physChunk) {
1304
+ * const physData = PngHelpers.parsePhys(dataView, physChunk.dataOffset)
1305
+ *
1306
+ * if (physData.unit === 1) { // meters
1307
+ * const dpiX = Math.round(physData.ppux * 0.0254)
1308
+ * const dpiY = Math.round(physData.ppuy * 0.0254)
1309
+ * console.log(`DPI: ${dpiX} x ${dpiY}`)
1310
+ * }
1311
+ * }
1312
+ * ```
1313
+ */
477
1314
  static parsePhys(view: DataView, offset: number): {
478
1315
  ppux: number;
479
1316
  ppuy: number;
480
1317
  unit: number;
481
1318
  };
1319
+ /**
1320
+ * Finds a specific chunk type in the PNG file and returns its metadata.
1321
+ *
1322
+ * @param view - DataView containing the PNG file data
1323
+ * @param type - 4-character chunk type to search for (e.g., 'pHYs', 'IDAT')
1324
+ * @returns Chunk metadata object if found, undefined otherwise
1325
+ *
1326
+ * @example
1327
+ * ```ts
1328
+ * // Look for pixel density information in PNG
1329
+ * const physChunk = PngHelpers.findChunk(dataView, 'pHYs')
1330
+ * if (physChunk) {
1331
+ * const physData = PngHelpers.parsePhys(dataView, physChunk.dataOffset)
1332
+ * console.log(`Found pHYs chunk with ${physData.ppux} x ${physData.ppuy} pixels per unit`)
1333
+ * }
1334
+ *
1335
+ * // Check for text metadata
1336
+ * const textChunk = PngHelpers.findChunk(dataView, 'tEXt')
1337
+ * if (textChunk) {
1338
+ * console.log(`Found text metadata at byte ${textChunk.start}`)
1339
+ * }
1340
+ * ```
1341
+ */
482
1342
  static findChunk(view: DataView, type: string): {
483
1343
  dataOffset: number;
484
1344
  size: number;
485
1345
  start: number;
486
1346
  };
1347
+ /**
1348
+ * Adds or replaces a pHYs chunk in a PNG file to set pixel density for high-DPI displays.
1349
+ * The method determines insertion point by prioritizing IDAT chunk position over existing pHYs,
1350
+ * creates a properly formatted pHYs chunk with CRC validation, and returns a new Blob.
1351
+ *
1352
+ * @param view - DataView containing the original PNG file data
1353
+ * @param dpr - Device pixel ratio multiplier (defaults to 1)
1354
+ * @param options - Optional Blob constructor options for MIME type and other properties
1355
+ * @returns New Blob containing the PNG with updated pixel density information
1356
+ *
1357
+ * @example
1358
+ * ```ts
1359
+ * // Export PNG with proper pixel density for high-DPI displays
1360
+ * const canvas = document.createElement('canvas')
1361
+ * const ctx = canvas.getContext('2d')
1362
+ * // ... draw content to canvas ...
1363
+ *
1364
+ * canvas.toBlob(async (blob) => {
1365
+ * if (blob) {
1366
+ * const view = new DataView(await blob.arrayBuffer())
1367
+ * // Create 2x DPI version for Retina displays
1368
+ * const highDpiBlob = PngHelpers.setPhysChunk(view, 2, { type: 'image/png' })
1369
+ * // Download or use the blob...
1370
+ * }
1371
+ * }, 'image/png')
1372
+ * ```
1373
+ */
487
1374
  static setPhysChunk(view: DataView, dpr?: number, options?: BlobPropertyBag): Blob;
488
1375
  }
489
1376
 
490
1377
  /* Excluded from this release type: promiseWithResolve */
491
1378
 
492
- /** @public */
1379
+ /**
1380
+ * Makes all properties in a type and all nested properties optional recursively.
1381
+ * This is useful for creating partial update objects where you only want to specify
1382
+ * some deeply nested properties while leaving others unchanged.
1383
+ *
1384
+ * @example
1385
+ * ```ts
1386
+ * interface User {
1387
+ * name: string
1388
+ * settings: {
1389
+ * theme: string
1390
+ * notifications: {
1391
+ * email: boolean
1392
+ * push: boolean
1393
+ * }
1394
+ * }
1395
+ * }
1396
+ *
1397
+ * type PartialUser = RecursivePartial<User>
1398
+ * // Result: {
1399
+ * // name?: string
1400
+ * // settings?: {
1401
+ * // theme?: string
1402
+ * // notifications?: {
1403
+ * // email?: boolean
1404
+ * // push?: boolean
1405
+ * // }
1406
+ * // }
1407
+ * // }
1408
+ *
1409
+ * const update: PartialUser = {
1410
+ * settings: {
1411
+ * notifications: {
1412
+ * email: false
1413
+ * }
1414
+ * }
1415
+ * }
1416
+ * ```
1417
+ *
1418
+ * @public
1419
+ */
493
1420
  export declare type RecursivePartial<T> = {
494
1421
  [P in keyof T]?: RecursivePartial<T[P]>;
495
1422
  };
@@ -500,12 +1427,65 @@ export declare type RecursivePartial<T> = {
500
1427
 
501
1428
  /* Excluded from this release type: restoreUniqueId */
502
1429
 
503
- /** @public */
1430
+ /**
1431
+ * A discriminated union type for handling success and error cases.
1432
+ *
1433
+ * Represents either a successful result with a value or a failed result with an error.
1434
+ * This pattern provides type-safe error handling without throwing exceptions. The 'ok' property
1435
+ * serves as the discriminant for type narrowing.
1436
+ *
1437
+ * @example
1438
+ * ```ts
1439
+ * function divide(a: number, b: number): Result<number, string> {
1440
+ * if (b === 0) {
1441
+ * return Result.err('Division by zero')
1442
+ * }
1443
+ * return Result.ok(a / b)
1444
+ * }
1445
+ *
1446
+ * const result = divide(10, 2)
1447
+ * if (result.ok) {
1448
+ * console.log(`Result: ${result.value}`) // Result: 5
1449
+ * } else {
1450
+ * console.error(`Error: ${result.error}`)
1451
+ * }
1452
+ * ```
1453
+ * @public
1454
+ */
504
1455
  export declare type Result<T, E> = ErrorResult<E> | OkResult<T>;
505
1456
 
506
- /** @public */
1457
+ /**
1458
+ * Utility object for creating Result instances.
1459
+ *
1460
+ * Provides factory methods for creating OkResult and ErrorResult instances.
1461
+ * This is the preferred way to construct Result values for consistent structure.
1462
+ *
1463
+ * @example
1464
+ * ```ts
1465
+ * // Create success result
1466
+ * const success = Result.ok(42)
1467
+ * // success: OkResult<number> = { ok: true, value: 42 }
1468
+ *
1469
+ * // Create error result
1470
+ * const failure = Result.err('Invalid input')
1471
+ * // failure: ErrorResult<string> = { ok: false, error: 'Invalid input' }
1472
+ * ```
1473
+ * @public
1474
+ */
507
1475
  export declare const Result: {
1476
+ /**
1477
+ * Create a failed result containing an error.
1478
+ *
1479
+ * @param error - The error value to wrap
1480
+ * @returns An ErrorResult containing the error
1481
+ */
508
1482
  err<E>(error: E): ErrorResult<E>;
1483
+ /**
1484
+ * Create a successful result containing a value.
1485
+ *
1486
+ * @param value - The success value to wrap
1487
+ * @returns An OkResult containing the value
1488
+ */
509
1489
  ok<T>(value: T): OkResult<T>;
510
1490
  };
511
1491
 
@@ -513,22 +1493,87 @@ export declare const Result: {
513
1493
 
514
1494
  /**
515
1495
  * Seeded random number generator, using [xorshift](https://en.wikipedia.org/wiki/Xorshift). The
516
- * result will always be betweeen -1 and 1.
1496
+ * result will always be between -1 and 1.
517
1497
  *
518
1498
  * Adapted from [seedrandom](https://github.com/davidbau/seedrandom).
519
1499
  *
1500
+ * @param seed - The seed string for deterministic random generation (defaults to empty string)
1501
+ * @returns A function that will return a random number between -1 and 1 each time it is called
1502
+ * @example
1503
+ * ```ts
1504
+ * const random = rng('my-seed')
1505
+ * const num1 = random() // Always the same for this seed
1506
+ * const num2 = random() // Next number in sequence
1507
+ *
1508
+ * // Different seed produces different sequence
1509
+ * const otherRandom = rng('other-seed')
1510
+ * const different = otherRandom() // Different value
1511
+ * ```
520
1512
  * @public
521
1513
  */
522
1514
  export declare function rng(seed?: string): () => number;
523
1515
 
524
1516
  /**
525
- * Rotate the contents of an array.
1517
+ * Rotate the contents of an array by a specified offset.
1518
+ *
1519
+ * Creates a new array with elements shifted to the left by the specified number of positions.
1520
+ * Both positive and negative offsets result in left shifts (elements move left, with elements
1521
+ * from the front wrapping to the back).
1522
+ *
1523
+ * @param arr - The array to rotate
1524
+ * @param offset - The number of positions to shift left (both positive and negative values shift left)
1525
+ * @returns A new array with elements shifted left by the specified offset
526
1526
  *
1527
+ * @example
1528
+ * ```ts
1529
+ * rotateArray([1, 2, 3, 4], 1) // [2, 3, 4, 1]
1530
+ * rotateArray([1, 2, 3, 4], -1) // [2, 3, 4, 1]
1531
+ * rotateArray(['a', 'b', 'c'], 2) // ['c', 'a', 'b']
1532
+ * ```
527
1533
  * @public
528
1534
  */
529
1535
  export declare function rotateArray<T>(arr: T[], offset: number): T[];
530
1536
 
531
- /** @public */
1537
+ /**
1538
+ * Safely parses a URL string without throwing exceptions on invalid input.
1539
+ * Returns a URL object for valid URLs or undefined for invalid ones.
1540
+ *
1541
+ * @param url - The URL string to parse
1542
+ * @param baseUrl - Optional base URL to resolve relative URLs against
1543
+ * @returns A URL object if parsing succeeds, undefined if it fails
1544
+ *
1545
+ * @example
1546
+ * ```ts
1547
+ * // Valid absolute URL
1548
+ * const url1 = safeParseUrl('https://example.com')
1549
+ * if (url1) {
1550
+ * console.log(`Valid URL: ${url1.href}`) // "Valid URL: https://example.com/"
1551
+ * }
1552
+ *
1553
+ * // Invalid URL
1554
+ * const url2 = safeParseUrl('not-a-url')
1555
+ * console.log(url2) // undefined
1556
+ *
1557
+ * // Relative URL with base
1558
+ * const url3 = safeParseUrl('/path', 'https://example.com')
1559
+ * if (url3) {
1560
+ * console.log(url3.href) // "https://example.com/path"
1561
+ * }
1562
+ *
1563
+ * // Error handling
1564
+ * function handleUserUrl(input: string) {
1565
+ * const url = safeParseUrl(input)
1566
+ * if (url) {
1567
+ * return url
1568
+ * } else {
1569
+ * console.log('Invalid URL provided')
1570
+ * return null
1571
+ * }
1572
+ * }
1573
+ * ```
1574
+ *
1575
+ * @public
1576
+ */
532
1577
  export declare const safeParseUrl: (url: string, baseUrl?: string | URL) => undefined | URL;
533
1578
 
534
1579
  /* Excluded from this release type: setInLocalStorage */
@@ -537,7 +1582,28 @@ export declare const safeParseUrl: (url: string, baseUrl?: string | URL) => unde
537
1582
 
538
1583
  /* Excluded from this release type: sleep */
539
1584
 
540
- /** @public */
1585
+ /**
1586
+ * Compares two objects by their id property for use with Array.sort().
1587
+ * Sorts objects in ascending order based on their id values.
1588
+ *
1589
+ * @param a - First object to compare
1590
+ * @param b - Second object to compare
1591
+ * @returns 1 if a.id \> b.id, -1 if a.id \<= b.id
1592
+ *
1593
+ * @example
1594
+ * ```ts
1595
+ * const items = [
1596
+ * { id: 'c', name: 'Charlie' },
1597
+ * { id: 'a', name: 'Alice' },
1598
+ * { id: 'b', name: 'Bob' },
1599
+ * ]
1600
+ *
1601
+ * const sorted = items.sort(sortById)
1602
+ * // [{ id: 'a', name: 'Alice' }, { id: 'b', name: 'Bob' }, { id: 'c', name: 'Charlie' }]
1603
+ * ```
1604
+ *
1605
+ * @public
1606
+ */
541
1607
  export declare function sortById<T extends {
542
1608
  id: any;
543
1609
  }>(a: T, b: T): -1 | 1;
@@ -546,7 +1612,18 @@ export declare function sortById<T extends {
546
1612
  * Sort by index.
547
1613
  * @param a - An object with an index property.
548
1614
  * @param b - An object with an index property.
549
- * @public */
1615
+ * @returns A number indicating sort order (-1, 0, or 1).
1616
+ * @example
1617
+ * ```ts
1618
+ * const shapes = [
1619
+ * { id: 'b', index: 'a2' as IndexKey },
1620
+ * { id: 'a', index: 'a1' as IndexKey }
1621
+ * ]
1622
+ * const sorted = shapes.sort(sortByIndex)
1623
+ * console.log(sorted) // [{ id: 'a', index: 'a1' }, { id: 'b', index: 'a2' }]
1624
+ * ```
1625
+ * @public
1626
+ */
550
1627
  export declare function sortByIndex<T extends {
551
1628
  index: IndexKey;
552
1629
  }>(a: T, b: T): -1 | 0 | 1;
@@ -559,7 +1636,26 @@ export declare function sortByIndex<T extends {
559
1636
  * Create a deep copy of a value. Uses the structuredClone API if available, otherwise uses JSON.parse(JSON.stringify()).
560
1637
  *
561
1638
  * @param i - The value to clone.
562
- * @public */
1639
+ * @returns A deep copy of the input value.
1640
+ * @example
1641
+ * ```ts
1642
+ * const original = { a: 1, b: { c: 2 } }
1643
+ * const copy = structuredClone(original)
1644
+ *
1645
+ * copy.b.c = 3
1646
+ * console.log(original.b.c) // 2 (unchanged)
1647
+ * console.log(copy.b.c) // 3
1648
+ *
1649
+ * // Works with complex objects
1650
+ * const complexObject = {
1651
+ * date: new Date(),
1652
+ * array: [1, 2, 3],
1653
+ * nested: { deep: { value: "test" } }
1654
+ * }
1655
+ * const cloned = structuredClone(complexObject)
1656
+ * ```
1657
+ * @public
1658
+ */
563
1659
  declare const structuredClone_2: <T>(i: T) => T;
564
1660
  export { structuredClone_2 as structuredClone }
565
1661
 
@@ -567,21 +1663,140 @@ export { throttle }
567
1663
 
568
1664
  /* Excluded from this release type: throttleToNextFrame */
569
1665
 
570
- /** @public */
1666
+ /**
1667
+ * A utility class for managing timeouts, intervals, and animation frames with context-based organization and automatic cleanup.
1668
+ * Helps prevent memory leaks by organizing timers into named contexts that can be cleared together.
1669
+ * @example
1670
+ * ```ts
1671
+ * const timers = new Timers()
1672
+ *
1673
+ * // Set timers with context organization
1674
+ * timers.setTimeout('ui', () => console.log('Auto save'), 5000)
1675
+ * timers.setInterval('ui', () => console.log('Refresh'), 1000)
1676
+ * timers.requestAnimationFrame('ui', () => console.log('Render'))
1677
+ *
1678
+ * // Clear all timers for a context
1679
+ * timers.dispose('ui')
1680
+ *
1681
+ * // Or get context-bound functions
1682
+ * const uiTimers = timers.forContext('ui')
1683
+ * uiTimers.setTimeout(() => console.log('Contextual timeout'), 1000)
1684
+ * ```
1685
+ * @public
1686
+ */
571
1687
  export declare class Timers {
572
1688
  private timeouts;
573
1689
  private intervals;
574
1690
  private rafs;
1691
+ /**
1692
+ * Creates a new Timers instance with bound methods for safe callback usage.
1693
+ * @example
1694
+ * ```ts
1695
+ * const timers = new Timers()
1696
+ * // Methods are pre-bound, safe to use as callbacks
1697
+ * element.addEventListener('click', timers.dispose)
1698
+ * ```
1699
+ */
575
1700
  constructor();
576
- /** @public */
1701
+ /**
1702
+ * Creates a timeout that will be tracked under the specified context.
1703
+ * @param contextId - The context identifier to group this timer under.
1704
+ * @param handler - The function to execute when the timeout expires.
1705
+ * @param timeout - The delay in milliseconds (default: 0).
1706
+ * @param args - Additional arguments to pass to the handler.
1707
+ * @returns The timer ID that can be used with clearTimeout.
1708
+ * @example
1709
+ * ```ts
1710
+ * const timers = new Timers()
1711
+ * const id = timers.setTimeout('autosave', () => save(), 5000)
1712
+ * // Timer will be automatically cleared when 'autosave' context is disposed
1713
+ * ```
1714
+ * @public
1715
+ */
577
1716
  setTimeout(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number;
578
- /** @public */
1717
+ /**
1718
+ * Creates an interval that will be tracked under the specified context.
1719
+ * @param contextId - The context identifier to group this timer under.
1720
+ * @param handler - The function to execute repeatedly.
1721
+ * @param timeout - The delay in milliseconds between executions (default: 0).
1722
+ * @param args - Additional arguments to pass to the handler.
1723
+ * @returns The interval ID that can be used with clearInterval.
1724
+ * @example
1725
+ * ```ts
1726
+ * const timers = new Timers()
1727
+ * const id = timers.setInterval('refresh', () => updateData(), 1000)
1728
+ * // Interval will be automatically cleared when 'refresh' context is disposed
1729
+ * ```
1730
+ * @public
1731
+ */
579
1732
  setInterval(contextId: string, handler: TimerHandler, timeout?: number, ...args: any[]): number;
580
- /** @public */
1733
+ /**
1734
+ * Requests an animation frame that will be tracked under the specified context.
1735
+ * @param contextId - The context identifier to group this animation frame under.
1736
+ * @param callback - The function to execute on the next animation frame.
1737
+ * @returns The request ID that can be used with cancelAnimationFrame.
1738
+ * @example
1739
+ * ```ts
1740
+ * const timers = new Timers()
1741
+ * const id = timers.requestAnimationFrame('render', () => draw())
1742
+ * // Animation frame will be automatically cancelled when 'render' context is disposed
1743
+ * ```
1744
+ * @public
1745
+ */
581
1746
  requestAnimationFrame(contextId: string, callback: FrameRequestCallback): number;
582
- /** @public */
1747
+ /**
1748
+ * Disposes of all timers associated with the specified context.
1749
+ * Clears all timeouts, intervals, and animation frames for the given context ID.
1750
+ * @param contextId - The context identifier whose timers should be cleared.
1751
+ * @returns void
1752
+ * @example
1753
+ * ```ts
1754
+ * const timers = new Timers()
1755
+ * timers.setTimeout('ui', () => console.log('timeout'), 1000)
1756
+ * timers.setInterval('ui', () => console.log('interval'), 500)
1757
+ *
1758
+ * // Clear all 'ui' context timers
1759
+ * timers.dispose('ui')
1760
+ * ```
1761
+ * @public
1762
+ */
583
1763
  dispose(contextId: string): void;
1764
+ /**
1765
+ * Disposes of all timers across all contexts.
1766
+ * Clears every timeout, interval, and animation frame managed by this instance.
1767
+ * @returns void
1768
+ * @example
1769
+ * ```ts
1770
+ * const timers = new Timers()
1771
+ * timers.setTimeout('ui', () => console.log('ui'), 1000)
1772
+ * timers.setTimeout('background', () => console.log('bg'), 2000)
1773
+ *
1774
+ * // Clear everything
1775
+ * timers.disposeAll()
1776
+ * ```
1777
+ * @public
1778
+ */
584
1779
  disposeAll(): void;
1780
+ /**
1781
+ * Returns an object with timer methods bound to a specific context.
1782
+ * Convenient for getting context-specific timer functions without repeatedly passing the contextId.
1783
+ * @param contextId - The context identifier to bind the returned methods to.
1784
+ * @returns An object with setTimeout, setInterval, requestAnimationFrame, and dispose methods bound to the context.
1785
+ * @example
1786
+ * ```ts
1787
+ * const timers = new Timers()
1788
+ * const uiTimers = timers.forContext('ui')
1789
+ *
1790
+ * // These are equivalent to calling timers.setTimeout('ui', ...)
1791
+ * uiTimers.setTimeout(() => console.log('timeout'), 1000)
1792
+ * uiTimers.setInterval(() => console.log('interval'), 500)
1793
+ * uiTimers.requestAnimationFrame(() => console.log('frame'))
1794
+ *
1795
+ * // Dispose only this context
1796
+ * uiTimers.dispose()
1797
+ * ```
1798
+ * @public
1799
+ */
585
1800
  forContext(contextId: string): {
586
1801
  dispose: () => void;
587
1802
  requestAnimationFrame: (callback: FrameRequestCallback) => number;
@@ -593,14 +1808,28 @@ export declare class Timers {
593
1808
  export { uniq }
594
1809
 
595
1810
  /**
596
- * Generate a unique id.
1811
+ * Generate a unique ID using a modified nanoid algorithm.
597
1812
  *
598
- * @example
1813
+ * Generates a cryptographically secure random string ID using URL-safe characters.
1814
+ * The default size is 21 characters, which provides a good balance of uniqueness
1815
+ * and brevity. Uses the global crypto API for secure random number generation.
599
1816
  *
1817
+ * @param size - Optional length of the generated ID (defaults to 21 characters)
1818
+ * @returns A unique string identifier
1819
+ * @example
600
1820
  * ```ts
1821
+ * // Generate default 21-character ID
601
1822
  * const id = uniqueId()
602
- * ```
1823
+ * console.log(id) // 'V1StGXR8_Z5jdHi6B-myT'
603
1824
  *
1825
+ * // Generate shorter ID
1826
+ * const shortId = uniqueId(10)
1827
+ * console.log(shortId) // 'V1StGXR8_Z'
1828
+ *
1829
+ * // Generate longer ID
1830
+ * const longId = uniqueId(32)
1831
+ * console.log(longId) // 'V1StGXR8_Z5jdHi6B-myTVKahvjdx...'
1832
+ * ```
604
1833
  * @public
605
1834
  */
606
1835
  export declare function uniqueId(size?: number): string;
@@ -612,18 +1841,59 @@ export declare function uniqueId(size?: number): string;
612
1841
  /* Excluded from this release type: warnOnce */
613
1842
 
614
1843
  /**
615
- * A micro cache used when storing records in memory (using a WeakMap).
1844
+ * A lightweight cache implementation using WeakMap for storing key-value pairs.
1845
+ *
1846
+ * A micro cache that stores computed values associated with object keys.
1847
+ * Uses WeakMap internally, which means keys can be garbage collected when no other
1848
+ * references exist, and only object keys are supported. Provides lazy computation
1849
+ * with memoization.
1850
+ *
1851
+ * @example
1852
+ * ```ts
1853
+ * const cache = new WeakCache<User, string>()
1854
+ * const user = { id: 1, name: 'Alice' }
1855
+ *
1856
+ * // Get cached value, computing it if not present
1857
+ * const displayName = cache.get(user, (u) => `${u.name} (#${u.id})`)
1858
+ * // Returns 'Alice (#1)'
1859
+ *
1860
+ * // Subsequent calls return cached value
1861
+ * const sameName = cache.get(user, (u) => `${u.name} (#${u.id})`)
1862
+ * // Returns 'Alice (#1)' without recomputing
1863
+ * ```
616
1864
  * @public
617
1865
  */
618
1866
  export declare class WeakCache<K extends object, V> {
619
- /** The map of items to their cached values. */
1867
+ /**
1868
+ * The internal WeakMap storage for cached key-value pairs.
1869
+ *
1870
+ * @public
1871
+ */
620
1872
  items: WeakMap<K, V>;
621
1873
  /**
622
- * Get the cached value for a given record. If the record is not present in the map, the callback
623
- * will be used to create the value (with the result being stored in the cache for next time).
1874
+ * Get the cached value for a given key, computing it if not already cached.
1875
+ *
1876
+ * Retrieves the cached value associated with the given key. If no cached
1877
+ * value exists, calls the provided callback function to compute the value, stores it
1878
+ * in the cache, and returns it. Subsequent calls with the same key will return the
1879
+ * cached value without recomputation.
1880
+ *
1881
+ * @param item - The object key to retrieve the cached value for
1882
+ * @param cb - Callback function that computes the value when not already cached
1883
+ * @returns The cached value if it exists, otherwise the newly computed value from the callback
624
1884
  *
625
- * @param item - The item to get.
626
- * @param cb - The callback to use to create the value when a cached value is not found.
1885
+ * @example
1886
+ * ```ts
1887
+ * const cache = new WeakCache<HTMLElement, DOMRect>()
1888
+ * const element = document.getElementById('my-element')!
1889
+ *
1890
+ * // First call computes and caches the bounding rect
1891
+ * const rect1 = cache.get(element, (el) => el.getBoundingClientRect())
1892
+ *
1893
+ * // Second call returns cached value
1894
+ * const rect2 = cache.get(element, (el) => el.getBoundingClientRect())
1895
+ * // rect1 and rect2 are the same object
1896
+ * ```
627
1897
  */
628
1898
  get<P extends K>(item: P, cb: (item: P) => V): NonNullable<V>;
629
1899
  }