tiny-essentials 1.24.4 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -7
- package/changelog/1/24/5.md +18 -0
- package/changelog/1/25/0.md +13 -0
- package/dist/v1/TinyBasicsEs.min.js +1 -1
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/basics/html.cjs +151 -2
- package/dist/v1/basics/html.d.mts +109 -0
- package/dist/v1/basics/html.mjs +135 -2
- package/dist/v1/libs/TinyHtml/index.cjs +33 -0
- package/dist/v1/libs/TinyHtml/index.d.mts +14 -0
- package/dist/v1/libs/TinyHtml/index.mjs +30 -0
- package/dist/v1/libs/TinyRateLimiter.cjs +215 -31
- package/dist/v1/libs/TinyRateLimiter.d.mts +179 -25
- package/dist/v1/libs/TinyRateLimiter.mjs +215 -31
- package/docs/v1/README.md +3 -8
- package/docs/v1/basics/html.md +69 -0
- package/docs/v1/libs/TinyRateLimiter.md +11 -0
- package/package.json +4 -4
- package/docs/v1/Ai-Tips.md +0 -51
- package/docs/v1/Personal-Ai-Prompts(portuguese).md +0 -134
- package/docs/v1/Personal-Ai-Prompts.md +0 -113
package/dist/v1/basics/html.cjs
CHANGED
|
@@ -134,8 +134,60 @@ function saveJsonFile(filename, data, spaces = 2) {
|
|
|
134
134
|
* @property {number} [retries=0] - Number of retry attempts (ignored if signal is provided).
|
|
135
135
|
* @property {Headers|Record<string, *>} [headers={}] - Additional headers.
|
|
136
136
|
* @property {AbortSignal|null} [signal] - External AbortSignal; disables timeout and retries.
|
|
137
|
+
* @property {FetchOnProgressResult} [onProgress] - Track the load progress.
|
|
137
138
|
*/
|
|
138
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Callback function used to report the progress of a data download.
|
|
142
|
+
*
|
|
143
|
+
* @callback FetchOnProgressResult
|
|
144
|
+
* @param {number} loaded - The amount of bytes currently loaded.
|
|
145
|
+
* @param {number} total - The total amount of bytes to be loaded (0 if unknown).
|
|
146
|
+
* @returns {void}
|
|
147
|
+
*/
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Intercepts a standard Fetch API Response to track the download progress
|
|
151
|
+
* of its body stream.
|
|
152
|
+
*
|
|
153
|
+
* This function returns a new Response object with a monitored ReadableStream,
|
|
154
|
+
* allowing the provided callback to receive updates on the number of bytes loaded.
|
|
155
|
+
*
|
|
156
|
+
* @param {Response} response - The original response object to be tracked.
|
|
157
|
+
* @param {FetchOnProgressResult} onProgress - The callback function to handle progress events.
|
|
158
|
+
* @returns {Response} A new Response object with the tracked stream.
|
|
159
|
+
*/
|
|
160
|
+
function trackFetchProgress(response, onProgress) {
|
|
161
|
+
if (typeof onProgress !== 'function')
|
|
162
|
+
throw new TypeError('The "onProgress" argument must be a function.');
|
|
163
|
+
if (!response.body) return response;
|
|
164
|
+
|
|
165
|
+
// Handle Progress Tracking via ReadableStream
|
|
166
|
+
const contentLength = response.headers.get('content-length');
|
|
167
|
+
const total = contentLength ? parseInt(contentLength, 10) : 0;
|
|
168
|
+
let loaded = 0;
|
|
169
|
+
|
|
170
|
+
const reader = response.body.getReader();
|
|
171
|
+
const stream = new ReadableStream({
|
|
172
|
+
async start(controller) {
|
|
173
|
+
while (true) {
|
|
174
|
+
const { done, value } = await reader.read();
|
|
175
|
+
if (done) break;
|
|
176
|
+
loaded += value.byteLength;
|
|
177
|
+
onProgress(loaded, total);
|
|
178
|
+
controller.enqueue(value);
|
|
179
|
+
}
|
|
180
|
+
controller.close();
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
return new Response(stream, {
|
|
185
|
+
headers: response.headers,
|
|
186
|
+
status: response.status,
|
|
187
|
+
statusText: response.statusText,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
139
191
|
/**
|
|
140
192
|
* @param {string} url - The full URL to fetch data from.
|
|
141
193
|
* @param {FetchTemplateOptions} [options] - Optional settings.
|
|
@@ -144,7 +196,7 @@ function saveJsonFile(filename, data, spaces = 2) {
|
|
|
144
196
|
*/
|
|
145
197
|
async function fetchTemplate(
|
|
146
198
|
url,
|
|
147
|
-
{ method = 'GET', body, timeout = 0, retries = 0, headers = {}, signal = null } = {},
|
|
199
|
+
{ method = 'GET', body, timeout = 0, retries = 0, headers = {}, signal = null, onProgress } = {},
|
|
148
200
|
) {
|
|
149
201
|
if (
|
|
150
202
|
typeof url !== 'string' ||
|
|
@@ -201,7 +253,10 @@ async function fetchTemplate(
|
|
|
201
253
|
if (timer) clearTimeout(timer);
|
|
202
254
|
|
|
203
255
|
if (!response.ok) throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
|
|
204
|
-
|
|
256
|
+
|
|
257
|
+
// If onProgress is not provided or body is null, return original response
|
|
258
|
+
if (!onProgress) return response;
|
|
259
|
+
return trackFetchProgress(response, onProgress);
|
|
205
260
|
} catch (err) {
|
|
206
261
|
lastError = /** @type {Error} */ (err);
|
|
207
262
|
if (signal) break; // if an external signal came, it does not retry
|
|
@@ -304,6 +359,98 @@ async function fetchText(url, allowedMimeTypes, options) {
|
|
|
304
359
|
|
|
305
360
|
///////////////////////////////////////////////////////////////////////////////
|
|
306
361
|
|
|
362
|
+
/**
|
|
363
|
+
* Represents the final state and metadata of an attempted image load.
|
|
364
|
+
* @typedef {Object} ImageLoadResult
|
|
365
|
+
* @property {HTMLImageElement} element The image element instance used for loading.
|
|
366
|
+
* @property {Event} event The browser event triggered by the final lifecycle state.
|
|
367
|
+
* @property {ImageLoadStatus} status The specific outcome string of the loading process.
|
|
368
|
+
* @property {boolean} isSuccess Indicates if the image was successfully loaded without errors.
|
|
369
|
+
* @property {number} loadTimeMs The total duration in milliseconds from start to finish.
|
|
370
|
+
* @property {Object} dimensions An object containing the rendered and intrinsic sizes of the image.
|
|
371
|
+
* @property {number} dimensions.width The current layout width of the image element.
|
|
372
|
+
* @property {number} dimensions.height The current layout height of the image element.
|
|
373
|
+
* @property {number} dimensions.naturalWidth The intrinsic width of the image source in pixels.
|
|
374
|
+
* @property {number} dimensions.naturalHeight The intrinsic height of the image source in pixels.
|
|
375
|
+
*/
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Describes the possible resolution states for the image loading attempt.
|
|
379
|
+
* @typedef {'loaded'|'aborted'} ImageLoadStatus
|
|
380
|
+
*/
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Loads an image asynchronously, capturing critical lifecycle events.
|
|
384
|
+
* It normalizes errors and success states into a consistent result structure.
|
|
385
|
+
*
|
|
386
|
+
* @param {Object} options
|
|
387
|
+
* @param {string} options.url
|
|
388
|
+
* @param {string} [options.crossOrigin="anonymous"]
|
|
389
|
+
* @param {(event: Event, startTime: number) => void} [options.onLoading]
|
|
390
|
+
* @returns {Promise<ImageLoadResult>}
|
|
391
|
+
*/
|
|
392
|
+
async function loadImage({ url, onLoading, crossOrigin = 'anonymous' }) {
|
|
393
|
+
return new Promise((resolve, reject) => {
|
|
394
|
+
const img = new Image();
|
|
395
|
+
let startTime = performance.now();
|
|
396
|
+
|
|
397
|
+
img.crossOrigin = crossOrigin;
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Cleans up event listeners to avoid memory leaks.
|
|
401
|
+
*/
|
|
402
|
+
const cleanup = () => {
|
|
403
|
+
img.onload = null;
|
|
404
|
+
img.onerror = null;
|
|
405
|
+
img.onabort = null;
|
|
406
|
+
img.onloadstart = null;
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Centralized handler to generate the result object.
|
|
411
|
+
* @param {Event} event
|
|
412
|
+
* @param {ImageLoadStatus} status
|
|
413
|
+
* @param {boolean} isSuccess
|
|
414
|
+
*/
|
|
415
|
+
const handleResult = (event, status, isSuccess) => {
|
|
416
|
+
const endTime = performance.now();
|
|
417
|
+
cleanup();
|
|
418
|
+
|
|
419
|
+
const result = {
|
|
420
|
+
element: img,
|
|
421
|
+
isSuccess,
|
|
422
|
+
event,
|
|
423
|
+
status,
|
|
424
|
+
loadTimeMs: endTime - startTime,
|
|
425
|
+
dimensions: {
|
|
426
|
+
width: img.width,
|
|
427
|
+
height: img.height,
|
|
428
|
+
naturalWidth: img.naturalWidth,
|
|
429
|
+
naturalHeight: img.naturalHeight,
|
|
430
|
+
},
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
resolve(result);
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
// Fired when the browser starts looking for the image data.
|
|
437
|
+
// Crucial for resetting the timer to network start, not just script start.
|
|
438
|
+
img.onloadstart = (ev) => {
|
|
439
|
+
startTime = performance.now();
|
|
440
|
+
if (typeof onLoading === 'function') onLoading(ev, startTime);
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
img.onload = (ev) => handleResult(ev, 'loaded', true);
|
|
444
|
+
img.onabort = (ev) => handleResult(ev, 'aborted', false);
|
|
445
|
+
img.onerror = (ev) => reject(ev);
|
|
446
|
+
|
|
447
|
+
// Trigger the load
|
|
448
|
+
img.src = url;
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
453
|
+
|
|
307
454
|
/**
|
|
308
455
|
* Installs a script that toggles CSS classes on a given element
|
|
309
456
|
* based on the page's visibility or focus state, and optionally
|
|
@@ -438,7 +585,9 @@ exports.fetchBlob = fetchBlob;
|
|
|
438
585
|
exports.fetchJson = fetchJson;
|
|
439
586
|
exports.fetchText = fetchText;
|
|
440
587
|
exports.installWindowHiddenScript = installWindowHiddenScript;
|
|
588
|
+
exports.loadImage = loadImage;
|
|
441
589
|
exports.readBase64Blob = readBase64Blob;
|
|
442
590
|
exports.readFileBlob = readFileBlob;
|
|
443
591
|
exports.readJsonBlob = readJsonBlob;
|
|
444
592
|
exports.saveJsonFile = saveJsonFile;
|
|
593
|
+
exports.trackFetchProgress = trackFetchProgress;
|
|
@@ -45,6 +45,36 @@ export function readJsonBlob(file: File): Promise<Record<string | number | symbo
|
|
|
45
45
|
* @param {number} [spaces=2]
|
|
46
46
|
*/
|
|
47
47
|
export function saveJsonFile(filename: string, data: any, spaces?: number): void;
|
|
48
|
+
/**
|
|
49
|
+
* @typedef {Object} FetchTemplateOptions
|
|
50
|
+
* @property {string} [method="GET"] - HTTP method to use (GET, POST, etc.).
|
|
51
|
+
* @property {any} [body] - Request body (only for methods like POST, PUT).
|
|
52
|
+
* @property {number} [timeout=0] - Timeout in milliseconds (ignored if signal is provided).
|
|
53
|
+
* @property {number} [retries=0] - Number of retry attempts (ignored if signal is provided).
|
|
54
|
+
* @property {Headers|Record<string, *>} [headers={}] - Additional headers.
|
|
55
|
+
* @property {AbortSignal|null} [signal] - External AbortSignal; disables timeout and retries.
|
|
56
|
+
* @property {FetchOnProgressResult} [onProgress] - Track the load progress.
|
|
57
|
+
*/
|
|
58
|
+
/**
|
|
59
|
+
* Callback function used to report the progress of a data download.
|
|
60
|
+
*
|
|
61
|
+
* @callback FetchOnProgressResult
|
|
62
|
+
* @param {number} loaded - The amount of bytes currently loaded.
|
|
63
|
+
* @param {number} total - The total amount of bytes to be loaded (0 if unknown).
|
|
64
|
+
* @returns {void}
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* Intercepts a standard Fetch API Response to track the download progress
|
|
68
|
+
* of its body stream.
|
|
69
|
+
*
|
|
70
|
+
* This function returns a new Response object with a monitored ReadableStream,
|
|
71
|
+
* allowing the provided callback to receive updates on the number of bytes loaded.
|
|
72
|
+
*
|
|
73
|
+
* @param {Response} response - The original response object to be tracked.
|
|
74
|
+
* @param {FetchOnProgressResult} onProgress - The callback function to handle progress events.
|
|
75
|
+
* @returns {Response} A new Response object with the tracked stream.
|
|
76
|
+
*/
|
|
77
|
+
export function trackFetchProgress(response: Response, onProgress: FetchOnProgressResult): Response;
|
|
48
78
|
/**
|
|
49
79
|
* Loads and parses a JSON from a remote URL using Fetch API.
|
|
50
80
|
*
|
|
@@ -74,6 +104,39 @@ export function fetchBlob(url: string, allowedMimeTypes?: string[], options?: Fe
|
|
|
74
104
|
* @throws {Error} Throws if fetch fails, response is not ok, or MIME type is not allowed.
|
|
75
105
|
*/
|
|
76
106
|
export function fetchText(url: string, allowedMimeTypes?: string[], options?: FetchTemplateOptions): Promise<string>;
|
|
107
|
+
/**
|
|
108
|
+
* Represents the final state and metadata of an attempted image load.
|
|
109
|
+
* @typedef {Object} ImageLoadResult
|
|
110
|
+
* @property {HTMLImageElement} element The image element instance used for loading.
|
|
111
|
+
* @property {Event} event The browser event triggered by the final lifecycle state.
|
|
112
|
+
* @property {ImageLoadStatus} status The specific outcome string of the loading process.
|
|
113
|
+
* @property {boolean} isSuccess Indicates if the image was successfully loaded without errors.
|
|
114
|
+
* @property {number} loadTimeMs The total duration in milliseconds from start to finish.
|
|
115
|
+
* @property {Object} dimensions An object containing the rendered and intrinsic sizes of the image.
|
|
116
|
+
* @property {number} dimensions.width The current layout width of the image element.
|
|
117
|
+
* @property {number} dimensions.height The current layout height of the image element.
|
|
118
|
+
* @property {number} dimensions.naturalWidth The intrinsic width of the image source in pixels.
|
|
119
|
+
* @property {number} dimensions.naturalHeight The intrinsic height of the image source in pixels.
|
|
120
|
+
*/
|
|
121
|
+
/**
|
|
122
|
+
* Describes the possible resolution states for the image loading attempt.
|
|
123
|
+
* @typedef {'loaded'|'aborted'} ImageLoadStatus
|
|
124
|
+
*/
|
|
125
|
+
/**
|
|
126
|
+
* Loads an image asynchronously, capturing critical lifecycle events.
|
|
127
|
+
* It normalizes errors and success states into a consistent result structure.
|
|
128
|
+
*
|
|
129
|
+
* @param {Object} options
|
|
130
|
+
* @param {string} options.url
|
|
131
|
+
* @param {string} [options.crossOrigin="anonymous"]
|
|
132
|
+
* @param {(event: Event, startTime: number) => void} [options.onLoading]
|
|
133
|
+
* @returns {Promise<ImageLoadResult>}
|
|
134
|
+
*/
|
|
135
|
+
export function loadImage({ url, onLoading, crossOrigin }: {
|
|
136
|
+
url: string;
|
|
137
|
+
crossOrigin?: string | undefined;
|
|
138
|
+
onLoading?: ((event: Event, startTime: number) => void) | undefined;
|
|
139
|
+
}): Promise<ImageLoadResult>;
|
|
77
140
|
/**
|
|
78
141
|
* Installs a script that toggles CSS classes on a given element
|
|
79
142
|
* based on the page's visibility or focus state, and optionally
|
|
@@ -128,5 +191,51 @@ export type FetchTemplateOptions = {
|
|
|
128
191
|
* - External AbortSignal; disables timeout and retries.
|
|
129
192
|
*/
|
|
130
193
|
signal?: AbortSignal | null | undefined;
|
|
194
|
+
/**
|
|
195
|
+
* - Track the load progress.
|
|
196
|
+
*/
|
|
197
|
+
onProgress?: FetchOnProgressResult | undefined;
|
|
131
198
|
};
|
|
199
|
+
/**
|
|
200
|
+
* Callback function used to report the progress of a data download.
|
|
201
|
+
*/
|
|
202
|
+
export type FetchOnProgressResult = (loaded: number, total: number) => void;
|
|
203
|
+
/**
|
|
204
|
+
* Represents the final state and metadata of an attempted image load.
|
|
205
|
+
*/
|
|
206
|
+
export type ImageLoadResult = {
|
|
207
|
+
/**
|
|
208
|
+
* The image element instance used for loading.
|
|
209
|
+
*/
|
|
210
|
+
element: HTMLImageElement;
|
|
211
|
+
/**
|
|
212
|
+
* The browser event triggered by the final lifecycle state.
|
|
213
|
+
*/
|
|
214
|
+
event: Event;
|
|
215
|
+
/**
|
|
216
|
+
* The specific outcome string of the loading process.
|
|
217
|
+
*/
|
|
218
|
+
status: ImageLoadStatus;
|
|
219
|
+
/**
|
|
220
|
+
* Indicates if the image was successfully loaded without errors.
|
|
221
|
+
*/
|
|
222
|
+
isSuccess: boolean;
|
|
223
|
+
/**
|
|
224
|
+
* The total duration in milliseconds from start to finish.
|
|
225
|
+
*/
|
|
226
|
+
loadTimeMs: number;
|
|
227
|
+
/**
|
|
228
|
+
* An object containing the rendered and intrinsic sizes of the image.
|
|
229
|
+
*/
|
|
230
|
+
dimensions: {
|
|
231
|
+
width: number;
|
|
232
|
+
height: number;
|
|
233
|
+
naturalWidth: number;
|
|
234
|
+
naturalHeight: number;
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* Describes the possible resolution states for the image loading attempt.
|
|
239
|
+
*/
|
|
240
|
+
export type ImageLoadStatus = "loaded" | "aborted";
|
|
132
241
|
//# sourceMappingURL=html.d.mts.map
|
package/dist/v1/basics/html.mjs
CHANGED
|
@@ -122,14 +122,63 @@ export function saveJsonFile(filename, data, spaces = 2) {
|
|
|
122
122
|
* @property {number} [retries=0] - Number of retry attempts (ignored if signal is provided).
|
|
123
123
|
* @property {Headers|Record<string, *>} [headers={}] - Additional headers.
|
|
124
124
|
* @property {AbortSignal|null} [signal] - External AbortSignal; disables timeout and retries.
|
|
125
|
+
* @property {FetchOnProgressResult} [onProgress] - Track the load progress.
|
|
125
126
|
*/
|
|
127
|
+
/**
|
|
128
|
+
* Callback function used to report the progress of a data download.
|
|
129
|
+
*
|
|
130
|
+
* @callback FetchOnProgressResult
|
|
131
|
+
* @param {number} loaded - The amount of bytes currently loaded.
|
|
132
|
+
* @param {number} total - The total amount of bytes to be loaded (0 if unknown).
|
|
133
|
+
* @returns {void}
|
|
134
|
+
*/
|
|
135
|
+
/**
|
|
136
|
+
* Intercepts a standard Fetch API Response to track the download progress
|
|
137
|
+
* of its body stream.
|
|
138
|
+
*
|
|
139
|
+
* This function returns a new Response object with a monitored ReadableStream,
|
|
140
|
+
* allowing the provided callback to receive updates on the number of bytes loaded.
|
|
141
|
+
*
|
|
142
|
+
* @param {Response} response - The original response object to be tracked.
|
|
143
|
+
* @param {FetchOnProgressResult} onProgress - The callback function to handle progress events.
|
|
144
|
+
* @returns {Response} A new Response object with the tracked stream.
|
|
145
|
+
*/
|
|
146
|
+
export function trackFetchProgress(response, onProgress) {
|
|
147
|
+
if (typeof onProgress !== 'function')
|
|
148
|
+
throw new TypeError('The "onProgress" argument must be a function.');
|
|
149
|
+
if (!response.body)
|
|
150
|
+
return response;
|
|
151
|
+
// Handle Progress Tracking via ReadableStream
|
|
152
|
+
const contentLength = response.headers.get('content-length');
|
|
153
|
+
const total = contentLength ? parseInt(contentLength, 10) : 0;
|
|
154
|
+
let loaded = 0;
|
|
155
|
+
const reader = response.body.getReader();
|
|
156
|
+
const stream = new ReadableStream({
|
|
157
|
+
async start(controller) {
|
|
158
|
+
while (true) {
|
|
159
|
+
const { done, value } = await reader.read();
|
|
160
|
+
if (done)
|
|
161
|
+
break;
|
|
162
|
+
loaded += value.byteLength;
|
|
163
|
+
onProgress(loaded, total);
|
|
164
|
+
controller.enqueue(value);
|
|
165
|
+
}
|
|
166
|
+
controller.close();
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
return new Response(stream, {
|
|
170
|
+
headers: response.headers,
|
|
171
|
+
status: response.status,
|
|
172
|
+
statusText: response.statusText,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
126
175
|
/**
|
|
127
176
|
* @param {string} url - The full URL to fetch data from.
|
|
128
177
|
* @param {FetchTemplateOptions} [options] - Optional settings.
|
|
129
178
|
* @returns {Promise<Response>} Result data.
|
|
130
179
|
* @throws {Error} Throws if fetch fails, times out.
|
|
131
180
|
*/
|
|
132
|
-
async function fetchTemplate(url, { method = 'GET', body, timeout = 0, retries = 0, headers = {}, signal = null } = {}) {
|
|
181
|
+
async function fetchTemplate(url, { method = 'GET', body, timeout = 0, retries = 0, headers = {}, signal = null, onProgress } = {}) {
|
|
133
182
|
if (typeof url !== 'string' ||
|
|
134
183
|
(!url.startsWith('../') &&
|
|
135
184
|
!url.startsWith('./') &&
|
|
@@ -172,7 +221,10 @@ async function fetchTemplate(url, { method = 'GET', body, timeout = 0, retries =
|
|
|
172
221
|
clearTimeout(timer);
|
|
173
222
|
if (!response.ok)
|
|
174
223
|
throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
|
|
175
|
-
return response
|
|
224
|
+
// If onProgress is not provided or body is null, return original response
|
|
225
|
+
if (!onProgress)
|
|
226
|
+
return response;
|
|
227
|
+
return trackFetchProgress(response, onProgress);
|
|
176
228
|
}
|
|
177
229
|
catch (err) {
|
|
178
230
|
lastError = /** @type {Error} */ (err);
|
|
@@ -258,6 +310,87 @@ export async function fetchText(url, allowedMimeTypes, options) {
|
|
|
258
310
|
});
|
|
259
311
|
}
|
|
260
312
|
///////////////////////////////////////////////////////////////////////////////
|
|
313
|
+
/**
|
|
314
|
+
* Represents the final state and metadata of an attempted image load.
|
|
315
|
+
* @typedef {Object} ImageLoadResult
|
|
316
|
+
* @property {HTMLImageElement} element The image element instance used for loading.
|
|
317
|
+
* @property {Event} event The browser event triggered by the final lifecycle state.
|
|
318
|
+
* @property {ImageLoadStatus} status The specific outcome string of the loading process.
|
|
319
|
+
* @property {boolean} isSuccess Indicates if the image was successfully loaded without errors.
|
|
320
|
+
* @property {number} loadTimeMs The total duration in milliseconds from start to finish.
|
|
321
|
+
* @property {Object} dimensions An object containing the rendered and intrinsic sizes of the image.
|
|
322
|
+
* @property {number} dimensions.width The current layout width of the image element.
|
|
323
|
+
* @property {number} dimensions.height The current layout height of the image element.
|
|
324
|
+
* @property {number} dimensions.naturalWidth The intrinsic width of the image source in pixels.
|
|
325
|
+
* @property {number} dimensions.naturalHeight The intrinsic height of the image source in pixels.
|
|
326
|
+
*/
|
|
327
|
+
/**
|
|
328
|
+
* Describes the possible resolution states for the image loading attempt.
|
|
329
|
+
* @typedef {'loaded'|'aborted'} ImageLoadStatus
|
|
330
|
+
*/
|
|
331
|
+
/**
|
|
332
|
+
* Loads an image asynchronously, capturing critical lifecycle events.
|
|
333
|
+
* It normalizes errors and success states into a consistent result structure.
|
|
334
|
+
*
|
|
335
|
+
* @param {Object} options
|
|
336
|
+
* @param {string} options.url
|
|
337
|
+
* @param {string} [options.crossOrigin="anonymous"]
|
|
338
|
+
* @param {(event: Event, startTime: number) => void} [options.onLoading]
|
|
339
|
+
* @returns {Promise<ImageLoadResult>}
|
|
340
|
+
*/
|
|
341
|
+
export async function loadImage({ url, onLoading, crossOrigin = 'anonymous' }) {
|
|
342
|
+
return new Promise((resolve, reject) => {
|
|
343
|
+
const img = new Image();
|
|
344
|
+
let startTime = performance.now();
|
|
345
|
+
img.crossOrigin = crossOrigin;
|
|
346
|
+
/**
|
|
347
|
+
* Cleans up event listeners to avoid memory leaks.
|
|
348
|
+
*/
|
|
349
|
+
const cleanup = () => {
|
|
350
|
+
img.onload = null;
|
|
351
|
+
img.onerror = null;
|
|
352
|
+
img.onabort = null;
|
|
353
|
+
img.onloadstart = null;
|
|
354
|
+
};
|
|
355
|
+
/**
|
|
356
|
+
* Centralized handler to generate the result object.
|
|
357
|
+
* @param {Event} event
|
|
358
|
+
* @param {ImageLoadStatus} status
|
|
359
|
+
* @param {boolean} isSuccess
|
|
360
|
+
*/
|
|
361
|
+
const handleResult = (event, status, isSuccess) => {
|
|
362
|
+
const endTime = performance.now();
|
|
363
|
+
cleanup();
|
|
364
|
+
const result = {
|
|
365
|
+
element: img,
|
|
366
|
+
isSuccess,
|
|
367
|
+
event,
|
|
368
|
+
status,
|
|
369
|
+
loadTimeMs: endTime - startTime,
|
|
370
|
+
dimensions: {
|
|
371
|
+
width: img.width,
|
|
372
|
+
height: img.height,
|
|
373
|
+
naturalWidth: img.naturalWidth,
|
|
374
|
+
naturalHeight: img.naturalHeight,
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
resolve(result);
|
|
378
|
+
};
|
|
379
|
+
// Fired when the browser starts looking for the image data.
|
|
380
|
+
// Crucial for resetting the timer to network start, not just script start.
|
|
381
|
+
img.onloadstart = (ev) => {
|
|
382
|
+
startTime = performance.now();
|
|
383
|
+
if (typeof onLoading === 'function')
|
|
384
|
+
onLoading(ev, startTime);
|
|
385
|
+
};
|
|
386
|
+
img.onload = (ev) => handleResult(ev, 'loaded', true);
|
|
387
|
+
img.onabort = (ev) => handleResult(ev, 'aborted', false);
|
|
388
|
+
img.onerror = (ev) => reject(ev);
|
|
389
|
+
// Trigger the load
|
|
390
|
+
img.src = url;
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
261
394
|
/**
|
|
262
395
|
* Installs a script that toggles CSS classes on a given element
|
|
263
396
|
* based on the page's visibility or focus state, and optionally
|
|
@@ -5,6 +5,13 @@ var TinyHtmlResetInput = require('./input/button/TinyHtmlResetInput.cjs');
|
|
|
5
5
|
var TinyHtmlSubmitInput = require('./input/button/TinyHtmlSubmitInput.cjs');
|
|
6
6
|
var TinyHtmlNumberInput = require('./input/number/TinyHtmlNumberInput.cjs');
|
|
7
7
|
var TinyHtmlRangeInput = require('./input/number/TinyHtmlRangeInput.cjs');
|
|
8
|
+
var TinyHtmlCheckboxInput = require('./input/check/TinyHtmlCheckboxInput.cjs');
|
|
9
|
+
var TinyHtmlRadioInput = require('./input/check/TinyHtmlRadioInput.cjs');
|
|
10
|
+
var TinyHtmlDateInput = require('./input/date/TinyHtmlDateInput.cjs');
|
|
11
|
+
var TinyHtmlDateTimeInput = require('./input/date/TinyHtmlDateTimeInput.cjs');
|
|
12
|
+
var TinyHtmlMonthInput = require('./input/date/TinyHtmlMonthInput.cjs');
|
|
13
|
+
var TinyHtmlTimeInput = require('./input/date/TinyHtmlTimeInput.cjs');
|
|
14
|
+
var TinyHtmlWeekInput = require('./input/date/TinyHtmlWeekInput.cjs');
|
|
8
15
|
var TinyHtmlEmailInput = require('./input/text/TinyHtmlEmailInput.cjs');
|
|
9
16
|
var TinyHtmlPasswordInput = require('./input/text/TinyHtmlPasswordInput.cjs');
|
|
10
17
|
var TinyHtmlSearchInput = require('./input/text/TinyHtmlSearchInput.cjs');
|
|
@@ -100,11 +107,25 @@ class TinyHtmlElems {
|
|
|
100
107
|
static SubmitInput = TinyHtmlSubmitInput;
|
|
101
108
|
|
|
102
109
|
/////////////////////////////////////////////////////
|
|
110
|
+
|
|
103
111
|
static NumberInput = TinyHtmlNumberInput;
|
|
104
112
|
static RangerInput = TinyHtmlRangeInput;
|
|
105
113
|
|
|
106
114
|
//////////////////////////////////////////////////
|
|
107
115
|
|
|
116
|
+
static CheckboxInput = TinyHtmlCheckboxInput;
|
|
117
|
+
static RadioInput = TinyHtmlRadioInput;
|
|
118
|
+
|
|
119
|
+
//////////////////////////////////////////////////
|
|
120
|
+
|
|
121
|
+
static DateInput = TinyHtmlDateInput;
|
|
122
|
+
static DateTimeInput = TinyHtmlDateTimeInput;
|
|
123
|
+
static MonthInput = TinyHtmlMonthInput;
|
|
124
|
+
static TimeInput = TinyHtmlTimeInput;
|
|
125
|
+
static WeekInput = TinyHtmlWeekInput;
|
|
126
|
+
|
|
127
|
+
//////////////////////////////////////////////////
|
|
128
|
+
|
|
108
129
|
static EmailInput = TinyHtmlEmailInput;
|
|
109
130
|
static PasswordInput = TinyHtmlPasswordInput;
|
|
110
131
|
static SearchInput = TinyHtmlSearchInput;
|
|
@@ -163,6 +184,18 @@ export {
|
|
|
163
184
|
TinyHtmlNumberInput,
|
|
164
185
|
TinyHtmlRangeInput,
|
|
165
186
|
//////////////////////////////////////////////////
|
|
187
|
+
|
|
188
|
+
TinyHtmlCheckboxInput;
|
|
189
|
+
TinyHtmlRadioInput;
|
|
190
|
+
|
|
191
|
+
//////////////////////////////////////////////////
|
|
192
|
+
|
|
193
|
+
TinyHtmlDateInput;
|
|
194
|
+
TinyHtmlDateTimeInput;
|
|
195
|
+
TinyHtmlMonthInput;
|
|
196
|
+
TinyHtmlTimeInput;
|
|
197
|
+
TinyHtmlWeekInput;
|
|
198
|
+
|
|
166
199
|
TinyHtmlEmailInput,
|
|
167
200
|
TinyHtmlPasswordInput,
|
|
168
201
|
TinyHtmlSearchInput,
|
|
@@ -11,6 +11,13 @@ declare class TinyHtmlElems {
|
|
|
11
11
|
static SubmitInput: typeof TinyHtmlSubmitInput;
|
|
12
12
|
static NumberInput: typeof TinyHtmlNumberInput;
|
|
13
13
|
static RangerInput: typeof TinyHtmlRangeInput;
|
|
14
|
+
static CheckboxInput: typeof TinyHtmlCheckboxInput;
|
|
15
|
+
static RadioInput: typeof TinyHtmlRadioInput;
|
|
16
|
+
static DateInput: typeof TinyHtmlDateInput;
|
|
17
|
+
static DateTimeInput: typeof TinyHtmlDateTimeInput;
|
|
18
|
+
static MonthInput: typeof TinyHtmlMonthInput;
|
|
19
|
+
static TimeInput: typeof TinyHtmlTimeInput;
|
|
20
|
+
static WeekInput: typeof TinyHtmlWeekInput;
|
|
14
21
|
static EmailInput: typeof TinyHtmlEmailInput;
|
|
15
22
|
static PasswordInput: typeof TinyHtmlPasswordInput;
|
|
16
23
|
static SearchInput: typeof TinyHtmlSearchInput;
|
|
@@ -71,6 +78,13 @@ import TinyHtmlSource from './media/TinyHtmlSource.mjs';
|
|
|
71
78
|
import TinyHtmlButtonInput from './input/button/TinyHtmlButtonInput.mjs';
|
|
72
79
|
import TinyHtmlSubmitInput from './input/button/TinyHtmlSubmitInput.mjs';
|
|
73
80
|
import TinyHtmlRangeInput from './input/number/TinyHtmlRangeInput.mjs';
|
|
81
|
+
import TinyHtmlCheckboxInput from './input/check/TinyHtmlCheckboxInput.mjs';
|
|
82
|
+
import TinyHtmlRadioInput from './input/check/TinyHtmlRadioInput.mjs';
|
|
83
|
+
import TinyHtmlDateInput from './input/date/TinyHtmlDateInput.mjs';
|
|
84
|
+
import TinyHtmlDateTimeInput from './input/date/TinyHtmlDateTimeInput.mjs';
|
|
85
|
+
import TinyHtmlMonthInput from './input/date/TinyHtmlMonthInput.mjs';
|
|
86
|
+
import TinyHtmlTimeInput from './input/date/TinyHtmlTimeInput.mjs';
|
|
87
|
+
import TinyHtmlWeekInput from './input/date/TinyHtmlWeekInput.mjs';
|
|
74
88
|
import TinyHtmlEmailInput from './input/text/TinyHtmlEmailInput.mjs';
|
|
75
89
|
import TinyHtmlPasswordInput from './input/text/TinyHtmlPasswordInput.mjs';
|
|
76
90
|
import TinyHtmlSearchInput from './input/text/TinyHtmlSearchInput.mjs';
|
|
@@ -6,6 +6,15 @@ import TinyHtmlSubmitInput from './input/button/TinyHtmlSubmitInput.mjs';
|
|
|
6
6
|
import TinyHtmlNumberInput from './input/number/TinyHtmlNumberInput.mjs';
|
|
7
7
|
import TinyHtmlRangeInput from './input/number/TinyHtmlRangeInput.mjs';
|
|
8
8
|
//////////////////////////////////////////////////
|
|
9
|
+
import TinyHtmlCheckboxInput from './input/check/TinyHtmlCheckboxInput.mjs';
|
|
10
|
+
import TinyHtmlRadioInput from './input/check/TinyHtmlRadioInput.mjs';
|
|
11
|
+
//////////////////////////////////////////////////
|
|
12
|
+
import TinyHtmlDateInput from './input/date/TinyHtmlDateInput.mjs';
|
|
13
|
+
import TinyHtmlDateTimeInput from './input/date/TinyHtmlDateTimeInput.mjs';
|
|
14
|
+
import TinyHtmlMonthInput from './input/date/TinyHtmlMonthInput.mjs';
|
|
15
|
+
import TinyHtmlTimeInput from './input/date/TinyHtmlTimeInput.mjs';
|
|
16
|
+
import TinyHtmlWeekInput from './input/date/TinyHtmlWeekInput.mjs';
|
|
17
|
+
//////////////////////////////////////////////////
|
|
9
18
|
import TinyHtmlEmailInput from './input/text/TinyHtmlEmailInput.mjs';
|
|
10
19
|
import TinyHtmlPasswordInput from './input/text/TinyHtmlPasswordInput.mjs';
|
|
11
20
|
import TinyHtmlSearchInput from './input/text/TinyHtmlSearchInput.mjs';
|
|
@@ -99,6 +108,15 @@ class TinyHtmlElems {
|
|
|
99
108
|
static NumberInput = TinyHtmlNumberInput;
|
|
100
109
|
static RangerInput = TinyHtmlRangeInput;
|
|
101
110
|
//////////////////////////////////////////////////
|
|
111
|
+
static CheckboxInput = TinyHtmlCheckboxInput;
|
|
112
|
+
static RadioInput = TinyHtmlRadioInput;
|
|
113
|
+
//////////////////////////////////////////////////
|
|
114
|
+
static DateInput = TinyHtmlDateInput;
|
|
115
|
+
static DateTimeInput = TinyHtmlDateTimeInput;
|
|
116
|
+
static MonthInput = TinyHtmlMonthInput;
|
|
117
|
+
static TimeInput = TinyHtmlTimeInput;
|
|
118
|
+
static WeekInput = TinyHtmlWeekInput;
|
|
119
|
+
//////////////////////////////////////////////////
|
|
102
120
|
static EmailInput = TinyHtmlEmailInput;
|
|
103
121
|
static PasswordInput = TinyHtmlPasswordInput;
|
|
104
122
|
static SearchInput = TinyHtmlSearchInput;
|
|
@@ -148,6 +166,18 @@ export {
|
|
|
148
166
|
TinyHtmlNumberInput,
|
|
149
167
|
TinyHtmlRangeInput,
|
|
150
168
|
//////////////////////////////////////////////////
|
|
169
|
+
|
|
170
|
+
TinyHtmlCheckboxInput;
|
|
171
|
+
TinyHtmlRadioInput;
|
|
172
|
+
|
|
173
|
+
//////////////////////////////////////////////////
|
|
174
|
+
|
|
175
|
+
TinyHtmlDateInput;
|
|
176
|
+
TinyHtmlDateTimeInput;
|
|
177
|
+
TinyHtmlMonthInput;
|
|
178
|
+
TinyHtmlTimeInput;
|
|
179
|
+
TinyHtmlWeekInput;
|
|
180
|
+
|
|
151
181
|
TinyHtmlEmailInput,
|
|
152
182
|
TinyHtmlPasswordInput,
|
|
153
183
|
TinyHtmlSearchInput,
|