@arex95/vue-core 1.0.2 → 1.0.3

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 (4) hide show
  1. package/dist/index.cjs +25819 -0
  2. package/dist/index.mjs +23345 -108
  3. package/package.json +8 -1
  4. package/dist/index.js +0 -2582
package/dist/index.js DELETED
@@ -1,2582 +0,0 @@
1
- 'use strict';
2
-
3
- var axios = require('axios');
4
- var vueQuery = require('@tanstack/vue-query');
5
- var vue = require('vue');
6
- var core = require('@vueuse/core');
7
-
8
- /**
9
- * A standard REST API interface for handling basic CRUD operations.
10
- * This class can be instantiated with a resource endpoint and a fetch composable for API requests.
11
- */
12
- class RestStd {
13
- static resource;
14
- static fetchComposable;
15
- /**
16
- * Fetch a list of items from the server.
17
- *
18
- * @param params Query parameters for filtering the results.
19
- * @param options Additional options for the fetch composable.
20
- * @returns The result of the fetch composable (typically a promise).
21
- */
22
- static getMany(params, options = {}) {
23
- return this.fetchComposable({
24
- method: 'GET',
25
- url: this.resource,
26
- params,
27
- }, options);
28
- }
29
- /**
30
- * Fetch a single item by ID from the server.
31
- *
32
- * @param id The ID of the item to fetch.
33
- * @param params Additional query parameters for the request.
34
- * @param options Additional options for the fetch composable.
35
- * @returns The result of the fetch composable (typically a promise).
36
- */
37
- static getOne(id, params, options = {}) {
38
- return this.fetchComposable({
39
- method: 'GET',
40
- url: `${this.resource}/${id}`,
41
- params,
42
- }, options);
43
- }
44
- /**
45
- * Create a new item on the server.
46
- *
47
- * @param data The data for the new item to create.
48
- * @param options Additional options for the fetch composable.
49
- * @returns The result of the fetch composable (typically a promise).
50
- */
51
- static create(data, options = {}) {
52
- return this.fetchComposable({
53
- method: 'POST',
54
- url: this.resource,
55
- data,
56
- }, options);
57
- }
58
- /**
59
- * Update an existing item on the server.
60
- *
61
- * @param id The ID of the item to update.
62
- * @param data The updated data for the item.
63
- * @param options Additional options for the fetch composable.
64
- * @returns The result of the fetch composable (typically a promise).
65
- */
66
- static update(id, data, options = {}) {
67
- return this.fetchComposable({
68
- method: 'PUT',
69
- url: `${this.resource}/${id}`,
70
- data,
71
- }, options);
72
- }
73
- /**
74
- * Partially update an existing item on the server.
75
- *
76
- * @param id The ID of the item to update.
77
- * @param data The updated data for the item.
78
- * @param options Additional options for the fetch composable.
79
- * @returns The result of the fetch composable (typically a promise).
80
- */
81
- static patch(id, data, options = {}) {
82
- return this.fetchComposable({
83
- method: 'PATCH',
84
- url: `${this.resource}/${id}`,
85
- data,
86
- }, options);
87
- }
88
- /**
89
- * Delete an item from the server.
90
- *
91
- * @param id The ID of the item to delete.
92
- * @param options Additional options for the fetch composable.
93
- * @returns The result of the fetch composable (typically a promise).
94
- */
95
- static delete(id, options = {}) {
96
- return this.fetchComposable({
97
- method: 'DELETE',
98
- url: `${this.resource}/${id}`,
99
- }, options);
100
- }
101
- /**
102
- * Custom request method for more flexibility.
103
- *
104
- * @param method HTTP method (GET, POST, etc.).
105
- * @param params Query parameters.
106
- * @param data Request body data.
107
- * @param token Authorization token (optional).
108
- * @param options Additional options for the fetch composable.
109
- * @returns The result of the fetch composable (typically a promise).
110
- */
111
- static customRequest(method, params, data, options = {}) {
112
- return this.fetchComposable({
113
- method: method,
114
- url: this.resource,
115
- params: params,
116
- data: data,
117
- }, options);
118
- }
119
- }
120
-
121
- /**
122
- * Custom composable function for making API requests with Axios.
123
- *
124
- * @template T The expected return type of the API request.
125
- * @param {AxiosInstance} axios - The Axios instance for making HTTP requests.
126
- * @param {AxiosRequestConfig} axiosRequest - Configuration for the Axios request.
127
- * @returns {Promise<T>} A promise with the result of the API request.
128
- */
129
- async function axiosFetch(axios, axiosRequest) {
130
- return axios(axiosRequest)
131
- .then(response => response.data)
132
- .catch(error => {
133
- throw error;
134
- });
135
- }
136
-
137
- /**
138
- * AxiosService class encapsulates the Axios configuration and logic.
139
- * It manages request and response interceptors and provides methods for making HTTP requests.
140
- */
141
- class AxiosService {
142
- instance;
143
- cancelTokenSource;
144
- activeRequests = 0; // Track active requests
145
- /**
146
- * Initializes the AxiosService instance by creating an Axios instance with default configuration
147
- * and setting up request and response interceptors.
148
- */
149
- constructor(url) {
150
- this.cancelTokenSource = axios.CancelToken.source();
151
- this.instance = axios.create({
152
- baseURL: url ?? '',
153
- timeout: 300000,
154
- headers: {
155
- Accept: 'application/json',
156
- 'Content-Type': 'application/json',
157
- },
158
- withCredentials: false,
159
- });
160
- this.initializeInterceptors();
161
- }
162
- /**
163
- * Initializes request and response interceptors for the Axios instance.
164
- */
165
- initializeInterceptors() {
166
- this.instance.interceptors.request.use((config) => {
167
- const token = typeof window !== 'undefined' ? localStorage.getItem('authToken') : null;
168
- if (token && config.headers) {
169
- config.headers.Authorization = `Bearer ${token}`;
170
- }
171
- config.cancelToken = this.cancelTokenSource.token;
172
- this.activeRequests++;
173
- return config;
174
- }, (error) => {
175
- // handleError(error);
176
- console.error('Request error:', error.message);
177
- this.activeRequests++;
178
- return Promise.reject(error);
179
- });
180
- this.instance.interceptors.response.use((response) => {
181
- this.activeRequests--;
182
- return response;
183
- }, (error) => {
184
- if (axios.isCancel(error)) {
185
- console.warn('Request canceled:', error.message);
186
- }
187
- else if (axios.isAxiosError(error)) {
188
- // handleError(error);
189
- console.error('Response error:', error.response?.status, error.message);
190
- if (error.response?.status === 401) {
191
- this.handleUnauthorized();
192
- }
193
- }
194
- else {
195
- console.error('Unexpected error:', error);
196
- }
197
- this.activeRequests--;
198
- return Promise.reject(error);
199
- });
200
- }
201
- /**
202
- * Returns the number of active requests.
203
- */
204
- getActiveRequests() {
205
- return this.activeRequests;
206
- }
207
- /**
208
- * Handles unauthorized access errors (401).
209
- */
210
- handleUnauthorized() {
211
- console.warn('Unauthorized access - redirecting to login.');
212
- }
213
- /**
214
- * Returns the Axios instance with the configured settings and interceptors.
215
- * @returns {AxiosInstance} The configured Axios instance.
216
- */
217
- getAxiosInstance() {
218
- return this.instance;
219
- }
220
- /**
221
- * Cancels all ongoing requests.
222
- */
223
- cancelAllRequests() {
224
- this.cancelTokenSource.cancel('Operation canceled by the user.');
225
- this.cancelTokenSource = axios.CancelToken.source();
226
- }
227
- /**
228
- * Sets a new header for the Axios instance.
229
- * @param {string} key - The header key.
230
- * @param {string} value - The header value.
231
- */
232
- setHeader(key, value) {
233
- this.instance.defaults.headers.common[key] = value;
234
- }
235
- /**
236
- * Removes a header from the Axios instance.
237
- * @param {string} key - The header key to remove.
238
- */
239
- removeHeader(key) {
240
- delete this.instance.defaults.headers.common[key];
241
- }
242
- }
243
-
244
- /**
245
- * Creates a fetchComposable for Axios requests with an optional custom instance.
246
- * @param fetchComposable - The composable to use for the request (can be any fetch function).
247
- * @param apiUrl - The base URL for the Axios instance.
248
- * @param axiosInstance - An optional custom Axios instance to use for the request.
249
- * @returns A function that handles the request using the provided composable.
250
- */
251
- function createFetch(fetchComposable, apiUrl, axiosInstance) {
252
- const instance = axiosInstance || new AxiosService(apiUrl).getAxiosInstance();
253
- return (axiosRequestConfig, options) => {
254
- return fetchComposable(instance, axiosRequestConfig, options);
255
- };
256
- }
257
-
258
- /**
259
- * Custom composable for integrating Axios requests with Vue Query.
260
- *
261
- * @template T - The type of data expected from the query.
262
- * @param {AxiosInstance} axios - Axios instance used for making HTTP requests.
263
- * @param {AxiosRequestConfig} axiosRequest - Initial Axios request configuration.
264
- * @param {ExtendedQueryOptions<T>} [queryOptions] - Optional Vue Query options with server execution flag.
265
- * @returns {object} Composable functions and query state for managing API requests.
266
- */
267
- function useVueQuery(axios, axiosRequest, queryOptions) {
268
- const key = vue.ref([
269
- queryOptions?.queryKey || `${axiosRequest.url}-${JSON.stringify(axiosRequest)}`
270
- ]);
271
- const axiosRequestRef = vue.ref(axiosRequest);
272
- const queryOptionsRef = vue.ref(queryOptions);
273
- const isInitialized = vue.ref(false);
274
- const errorCallbacks = vue.ref([]);
275
- const resultCallbacks = vue.ref([]);
276
- /**
277
- * Vue Query instance for managing API requests.
278
- */
279
- const query = vueQuery.useQuery({
280
- queryKey: key.value,
281
- queryFn: async () => {
282
- const response = await axios(axiosRequestRef.value);
283
- return response.data;
284
- },
285
- ...(queryOptionsRef.value?.options ?? {})
286
- });
287
- /**
288
- * Executes the query manually with optional new key and request parameters.
289
- *
290
- * @param {Array<any>} [newKey] - New query key to use.
291
- * @param {object} [newRequestParams] - New request parameters to use.
292
- * @param {ExtendedQueryOptions<T>} [newQueryOptions] - New Vue Query options to use.
293
- */
294
- function execute(newKey, newRequestParams, newQueryOptions) {
295
- if (newKey) {
296
- key.value = newKey;
297
- }
298
- if (newRequestParams) {
299
- axiosRequestRef.value.data = newRequestParams;
300
- }
301
- if (newQueryOptions) {
302
- queryOptionsRef.value = newQueryOptions;
303
- }
304
- query.refetch();
305
- }
306
- /**
307
- * Registers a callback to be executed on successful request result.
308
- * If data is already available, the callback will be executed immediately.
309
- *
310
- * @param {(data: T) => void} cb - Callback function to handle the result.
311
- */
312
- function onResult(cb) {
313
- resultCallbacks.value.push(cb);
314
- if (query.data.value !== undefined && query.data.value !== null) {
315
- cb(query.data.value);
316
- }
317
- }
318
- /**
319
- * Registers a callback to be executed when the request results in an error.
320
- * If an error is already present, the callback will be executed immediately.
321
- *
322
- * @param {(e: unknown) => void} callback - Callback function to handle errors.
323
- */
324
- function onError(callback) {
325
- errorCallbacks.value.push(callback);
326
- if (query.error.value !== undefined) {
327
- callback(query.error.value);
328
- }
329
- }
330
- /**
331
- * Watches for changes in the query result and triggers result callbacks.
332
- */
333
- vue.watch(query.data, (newData) => {
334
- if (newData !== undefined && newData !== null && isInitialized.value) {
335
- resultCallbacks.value.forEach((cb) => cb(newData));
336
- }
337
- });
338
- /**
339
- * Watches for changes in query errors and triggers error callbacks.
340
- */
341
- vue.watch(query.error, (newError) => {
342
- if (newError !== undefined && isInitialized.value) {
343
- errorCallbacks.value.forEach((cb) => cb(newError));
344
- }
345
- });
346
- /**
347
- * Handles server-side prefetching for SSR.
348
- * Ensures data is fetched before rendering on the server.
349
- */
350
- vue.onServerPrefetch(async () => {
351
- if (queryOptionsRef.value?.server !== false) {
352
- await query.suspense();
353
- if (query.data.value != null) {
354
- resultCallbacks.value.forEach((cb) => cb(query.data.value));
355
- }
356
- }
357
- });
358
- /**
359
- * Ensures callbacks are executed after the component is mounted on the client-side.
360
- */
361
- vue.onMounted(() => {
362
- isInitialized.value = true;
363
- if (query.data.value != null) {
364
- resultCallbacks.value.forEach((cb) => cb(query.data.value));
365
- }
366
- if (query.error.value !== undefined) {
367
- errorCallbacks.value.forEach((cb) => cb(query.error.value));
368
- }
369
- });
370
- return {
371
- execute,
372
- onResult,
373
- onError,
374
- ...query
375
- };
376
- }
377
-
378
- let notified = false;
379
- /**
380
- * Composable to manage breakpoints using Tailwind CSS and shared window resize listener.
381
- *
382
- * @returns {Object} An object containing the breakpoints and their states.
383
- */
384
- function useBreakpoint() {
385
- const breakpoints = core.useBreakpoints(core.breakpointsTailwind);
386
- const current = breakpoints.current();
387
- const active = breakpoints.active();
388
- // Define breakpoints
389
- const sm_S = breakpoints.smaller('sm');
390
- const sm_SE = breakpoints.smallerOrEqual('sm');
391
- const sm_GE = breakpoints.greaterOrEqual('sm');
392
- const sm_md = breakpoints.between('sm', 'md');
393
- const sm_xl = breakpoints.between('sm', 'xl');
394
- const sm_2xl = breakpoints.between('sm', '2xl');
395
- const md_S = breakpoints.smaller('md');
396
- const md_SE = breakpoints.smallerOrEqual('md');
397
- const md_GE = breakpoints.greaterOrEqual('md');
398
- const md_lg = breakpoints.between('md', 'lg');
399
- const md_xl = breakpoints.between('md', 'xl');
400
- const md_2xl = breakpoints.between('md', '2xl');
401
- const lg_S = breakpoints.smaller('lg');
402
- const lg_SE = breakpoints.smallerOrEqual('lg');
403
- const lg_GE = breakpoints.greaterOrEqual('lg');
404
- const lg_xl = breakpoints.between('lg', 'xl');
405
- const lg_2xl = breakpoints.between('lg', '2xl');
406
- const xl_S = breakpoints.smaller('xl');
407
- const xl_SE = breakpoints.smallerOrEqual('xl');
408
- const xl_GE = breakpoints.greaterOrEqual('xl');
409
- const xl_2xl = breakpoints.between('xl', '2xl');
410
- const _2xl_S = breakpoints.smaller('2xl');
411
- const _2xl_SE = breakpoints.smallerOrEqual('2xl');
412
- const _2xl_GE = breakpoints.greaterOrEqual('2xl');
413
- const reactiveBreakpoint = vue.ref('sm');
414
- const isGreaterThanBreakpoint = breakpoints.greaterOrEqual(() => reactiveBreakpoint.value);
415
- // Define device ranges
416
- const mobile = breakpoints.smaller('md'); // <768px
417
- const tablet = breakpoints.between('md', 'lg'); // 768px - 1024px
418
- const laptop = breakpoints.between('lg', 'xl'); // 1024px - 1280px
419
- const desktop = breakpoints.greaterOrEqual('xl'); // >=1280px
420
- // Use VueUse for window size
421
- const { width: windowWidth, height: windowHeight } = core.useWindowSize();
422
- /**
423
- * Logs a styled "chip" message to the console.
424
- *
425
- * @param {string} label - The label to display inside the chip.
426
- * @param {string} backgroundColor - The background color of the chip.
427
- * @param {string} textColor - The text color of the chip.
428
- */
429
- const logChip = (label, backgroundColor, textColor = 'white') => {
430
- console.log(`%c ${label} `, `background-color: ${backgroundColor}; color: ${textColor}; border-radius: 16px; padding: 4px 8px;`);
431
- };
432
- // Singleton logic: Only notify once
433
- const notifyOnce = () => {
434
- if (notified)
435
- return;
436
- vue.watch([mobile, tablet, laptop, desktop], ([isMobile, isTablet, isLaptop, isDesktop]) => {
437
- if (isMobile) {
438
- logChip('Mobile', '#ff6b6b');
439
- }
440
- else if (isTablet) {
441
- logChip('Tablet', '#4ecdc4');
442
- }
443
- else if (isLaptop) {
444
- logChip('Laptop', '#1a535c');
445
- }
446
- else if (isDesktop) {
447
- logChip('Desktop', '#f7fff7', 'black');
448
- }
449
- notified = true; // Mark as notified
450
- }, { immediate: true });
451
- };
452
- notifyOnce(); // Ensure the notification happens only once globally
453
- return {
454
- current,
455
- active,
456
- sm_S,
457
- sm_SE,
458
- sm_GE,
459
- sm_md,
460
- sm_xl,
461
- sm_2xl,
462
- md_S,
463
- md_SE,
464
- md_GE,
465
- md_lg,
466
- md_xl,
467
- md_2xl,
468
- lg_S,
469
- lg_SE,
470
- lg_GE,
471
- lg_xl,
472
- lg_2xl,
473
- xl_S,
474
- xl_SE,
475
- xl_GE,
476
- xl_2xl,
477
- _2xl_S,
478
- _2xl_SE,
479
- _2xl_GE,
480
- isGreaterThanBreakpoint,
481
- reactiveBreakpoint,
482
- breakpointsTailwind: core.breakpointsTailwind,
483
- windowWidth,
484
- windowHeight,
485
- mobile,
486
- tablet,
487
- laptop,
488
- desktop,
489
- breakpoints,
490
- };
491
- }
492
-
493
- /**
494
- * A composable function that filters objects based on a specific field and criteria.
495
- *
496
- * @param {Object[]} items - The list of objects to filter.
497
- * @param {Object} filterConfig - Configuration for the filter, specifying the field, the data type to filter, and the criteria.
498
- * @param {string} filterConfig.field - The field in the objects to filter.
499
- * @param {string} filterConfig.type - The data type of the field ('date', 'string', 'number', 'boolean').
500
- * @param {any} filterConfig.criteria - The criteria for filtering. Can be a date range, a string to search, a number range, or a boolean value.
501
- *
502
- * @returns {Object[]} - The filtered list of objects.
503
- */
504
- function useFilter(items, filterConfig) {
505
- // Ensure the filterConfig is correctly structured
506
- const { field, type, criteria } = filterConfig;
507
- // Define the filter functions
508
- const filterByDate = (objects, field, { startDate, endDate }) => objects.filter(item => {
509
- const date = new Date(item[field]);
510
- return date >= new Date(startDate) && date <= new Date(endDate);
511
- });
512
- const filterByString = (objects, field, searchTerm) => {
513
- const normalize = (str) => str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
514
- const words = normalize(searchTerm).split(/\s+/).filter(Boolean);
515
- return objects.filter(item => {
516
- const normalizedFieldValue = normalize(item[field]);
517
- return words.every(word => normalizedFieldValue.includes(word));
518
- });
519
- };
520
- const filterByNumber = (objects, field, { min, max }) => objects.filter(item => {
521
- const value = item[field];
522
- return value >= min && value <= max;
523
- });
524
- const filterByBoolean = (objects, field, expectedValue) => objects.filter(item => item[field] === expectedValue);
525
- // Apply the appropriate filter and return the filtered objects
526
- const filteredObjects = vue.computed(() => {
527
- if (!criteria ||
528
- (type === 'date' && (!criteria.startDate || !criteria.endDate)) ||
529
- (type === 'number' && (criteria.min == null || criteria.max == null)) ||
530
- (type === 'boolean' && typeof criteria !== 'boolean')) {
531
- return items; // Return all objects if criteria is not valid
532
- }
533
- // Apply the filter based on the type
534
- switch (type) {
535
- case 'date':
536
- return filterByDate(items, field, criteria);
537
- case 'string':
538
- return filterByString(items, field, criteria);
539
- case 'number':
540
- return filterByNumber(items, field, criteria);
541
- case 'boolean':
542
- return filterByBoolean(items, field, criteria);
543
- default:
544
- return items;
545
- }
546
- });
547
- return filteredObjects.value;
548
- }
549
-
550
- /**
551
- * Composable to handle pagination logic.
552
- *
553
- * @param page - Reactive ref for the current page number.
554
- * @param total - Reactive ref for total number of items.
555
- * @param pageSize - Reactive ref for number of items per page.
556
- * @returns An object with pagination controls.
557
- */
558
- function usePagination(page, total, pageSize) {
559
- // Calculate the total number of pages
560
- const totalPages = vue.computed(() => Math.ceil(total.value / pageSize.value));
561
- // Determine if the next page can be fetched
562
- const canFetchNextPage = () => page.value < totalPages.value;
563
- // Determine if the previous page can be fetched
564
- const canFetchPreviousPage = () => page.value > 1;
565
- return {
566
- totalPages,
567
- canFetchNextPage,
568
- canFetchPreviousPage
569
- };
570
- }
571
-
572
- /**
573
- * Custom composable for sorting products based on a selected criterion.
574
- * @param {Array} items - The array of products to sort.
575
- * @param {Array} criteriaList - The list of available sorting criteria.
576
- * @param {Number} selectedCriteria - The currently selected sorting criterion.
577
- * @returns {ComputedRef<Array>} - The sorted array of products.
578
- */
579
- function useSorter(items, criteriaList, selectedCriteria) {
580
- return vue.computed(() => {
581
- const criteria = criteriaList.find(item => item.value === Number(selectedCriteria));
582
- if (!criteria)
583
- return items;
584
- return [...items].sort((a, b) => {
585
- const aValue = a[criteria.field];
586
- const bValue = b[criteria.field];
587
- if (criteria.type === 'number') {
588
- const numA = typeof aValue === 'number' ? aValue : parseFloat(aValue) || 0;
589
- const numB = typeof bValue === 'number' ? bValue : parseFloat(bValue) || 0;
590
- return criteria.order === 'asc' ? numA - numB : numB - numA;
591
- }
592
- else if (criteria.type === 'date') {
593
- const dateA = new Date(aValue).getTime();
594
- const dateB = new Date(bValue).getTime();
595
- return criteria.order === 'asc' ? dateA - dateB : dateB - dateA;
596
- }
597
- else if (criteria.type === 'boolean') {
598
- const boolA = !!aValue;
599
- const boolB = !!bValue;
600
- return criteria.order === 'asc' ? (boolA === boolB ? 0 : boolA ? 1 : -1) : (boolA === boolB ? 0 : boolA ? -1 : 1);
601
- }
602
- else {
603
- // Fallback for string sorting
604
- const strA = (aValue || '').toString().toLowerCase();
605
- const strB = (bValue || '').toString().toLowerCase();
606
- return criteria.order === 'asc' ? strA.localeCompare(strB) : strB.localeCompare(strA);
607
- }
608
- });
609
- }).value;
610
- }
611
-
612
- /**
613
- * Object defining available screen sizes as constants.
614
- * @readonly
615
- */
616
- const sizeEnum = {
617
- XS: 'XS',
618
- SM: 'SM',
619
- MD: 'MD',
620
- LG: 'LG',
621
- XL: 'XL',
622
- XXL: 'XXL',
623
- };
624
- /**
625
- * Object defining breakpoints for design based on screen width.
626
- * Values are in pixels.
627
- * @readonly
628
- */
629
- const screenEnum = {
630
- XS: 480,
631
- SM: 576,
632
- MD: 768,
633
- LG: 992,
634
- XL: 1200,
635
- XXL: 1600,
636
- };
637
- /**
638
- * Map that associates each screen size defined in `sizeEnum` with its corresponding pixel value from `screenEnum`.
639
- * @type {Map<typeof sizeEnum[keyof typeof sizeEnum], number>}
640
- */
641
- const screenMap = new Map();
642
- screenMap.set(sizeEnum.XS, screenEnum.XS);
643
- screenMap.set(sizeEnum.SM, screenEnum.SM);
644
- screenMap.set(sizeEnum.MD, screenEnum.MD);
645
- screenMap.set(sizeEnum.LG, screenEnum.LG);
646
- screenMap.set(sizeEnum.XL, screenEnum.XL);
647
- screenMap.set(sizeEnum.XXL, screenEnum.XXL);
648
-
649
- /**
650
- * Object defining various exception codes.
651
- * @readonly
652
- */
653
- const ExceptionEnum = {
654
- /**
655
- * HTTP status code for page access forbidden.
656
- */
657
- PAGE_NOT_ACCESS: 403,
658
- /**
659
- * HTTP status code for page not found.
660
- */
661
- PAGE_NOT_FOUND: 404,
662
- /**
663
- * HTTP status code for general server error.
664
- */
665
- ERROR: 500,
666
- /**
667
- * HTTP status code for bad request.
668
- */
669
- BAD_REQUEST: 406,
670
- /**
671
- * Custom error code for network errors.
672
- */
673
- NET_WORK_ERROR: 10000,
674
- /**
675
- * Custom code indicating no data on the page, not actually an exception page.
676
- */
677
- PAGE_NOT_DATA: 10100,
678
- };
679
-
680
- /**
681
- * Object defining various image MIME types.
682
- * @readonly
683
- */
684
- const ImageTypes = {
685
- apng: 'image/apng',
686
- bmp: 'image/bmp',
687
- gif: 'image/gif',
688
- jpeg: 'image/jpeg',
689
- pjpeg: 'image/pjpeg',
690
- png: 'image/png',
691
- svg: 'image/svg+xml',
692
- tiff: 'image/tiff',
693
- webp: 'image/webp',
694
- xicon: 'image/x-icon',
695
- };
696
- /**
697
- * Object defining various file meta types.
698
- * @readonly
699
- */
700
- const FileMetaTypes = {
701
- images: 'image/*',
702
- audios: 'audio/*',
703
- videos: 'video/*',
704
- };
705
-
706
- /**
707
- * Object representing different content types for HTTP headers.
708
- * @readonly
709
- */
710
- const ContentTypeEnum = {
711
- /**
712
- * Content type for JSON.
713
- * @constant
714
- */
715
- JSON: 'application/json;charset=UTF-8',
716
- /**
717
- * Content type for URL-encoded form data.
718
- * @constant
719
- */
720
- FORM_URLENCODED: 'application/x-www-form-urlencoded;charset=UTF-8',
721
- /**
722
- * Content type for multipart form data with file uploads.
723
- * @constant
724
- */
725
- FORM_DATA: 'multipart/form-data;charset=UTF-8',
726
- };
727
-
728
- /**
729
- * Object defining various key codes for keyboard events.
730
- * @readonly
731
- */
732
- const KeyCodeEnum = {
733
- UP: 38,
734
- DOWN: 40,
735
- ENTER: 13,
736
- ESC: 27,
737
- };
738
-
739
- /**
740
- * Key used for storing the authentication token.
741
- * @constant {string}
742
- */
743
- const TOKEN_KEY = 'TOKEN__';
744
- /**
745
- * Key used for storing the locale information.
746
- * @constant {string}
747
- */
748
- const LOCALE_KEY = 'LOCALE__';
749
- /**
750
- * Key used for storing user information.
751
- * @constant {string}
752
- */
753
- const USER_INFO_KEY = 'USER__INFO__';
754
- /**
755
- * Key used for storing role information.
756
- * @constant {string}
757
- */
758
- const ROLES_KEY = 'ROLES__KEY__';
759
- /**
760
- * Key used for storing project configuration.
761
- * @constant {string}
762
- */
763
- const PROJ_CFG_KEY = 'PROJ__CFG__KEY__';
764
- /**
765
- * Key used for storing lock information.
766
- * @constant {string}
767
- */
768
- const LOCK_INFO_KEY = 'LOCK__INFO__KEY__';
769
- /**
770
- * Key used for base global local cache.
771
- * @constant {string}
772
- */
773
- const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY';
774
- /**
775
- * Key used for base global session cache.
776
- * @constant {string}
777
- */
778
- const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__KEY';
779
- /**
780
- * Object defining types of cache storage.
781
- * @readonly
782
- */
783
- const CacheTypeEnum = {
784
- /** Represents session storage */
785
- SESSION: 0,
786
- /** Represents local storage */
787
- LOCAL: 1,
788
- };
789
-
790
- /**
791
- * Creates and downloads a file from Blob data.
792
- * @param {Blob} blob The Blob containing the file data.
793
- * @param {string} fileName The name of the file to create.
794
- */
795
- function downloadFile(blob, fileName) {
796
- const link = document.createElement('a');
797
- const url = URL.createObjectURL(blob);
798
- link.setAttribute('href', url);
799
- link.setAttribute('download', fileName);
800
- // Append link to the body and trigger a click
801
- document.body.appendChild(link);
802
- link.click();
803
- // Clean up
804
- document.body.removeChild(link);
805
- URL.revokeObjectURL(url);
806
- }
807
- /**
808
- * Exports data to a CSV file.
809
- * @param {string[]} headers The headers for the CSV.
810
- * @param {any[][]} data The data to export, as an array of arrays.
811
- * @param {string} fileName The name of the file to create.
812
- */
813
- function exportToCSV(headers, data, fileName) {
814
- const csvRows = [];
815
- // Add the headers
816
- csvRows.push(headers.map(header => `"${header.replace(/"/g, '""')}"`).join(','));
817
- // Add the data rows
818
- for (const row of data) {
819
- csvRows.push(row.map(cell => `"${String(cell).replace(/"/g, '""')}"`).join(','));
820
- }
821
- // Create a Blob with CSV data
822
- const csvContent = csvRows.join('\n');
823
- const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
824
- // Use the download utility function
825
- downloadFile(blob, fileName);
826
- }
827
- /**
828
- * Exports data to an Excel file (.xls) using HTML table.
829
- * @param {string[]} headers The headers for the Excel file.
830
- * @param {any[][]} data The data to export, as an array of arrays.
831
- * @param {string} fileName The name of the file to create.
832
- */
833
- function exportToExcel(headers, data, fileName) {
834
- // Create a table element
835
- const table = document.createElement('table');
836
- const thead = table.createTHead();
837
- const tbody = table.createTBody();
838
- // Create the header row
839
- const headerRow = thead.insertRow();
840
- headers.forEach(header => {
841
- const th = document.createElement('th');
842
- th.textContent = header;
843
- headerRow.appendChild(th);
844
- });
845
- // Create the data rows
846
- data.forEach(row => {
847
- const tr = tbody.insertRow();
848
- row.forEach(cell => {
849
- const td = tr.insertCell();
850
- td.textContent = String(cell);
851
- });
852
- });
853
- // Create a Blob with the table HTML
854
- const html = table.outerHTML;
855
- const blob = new Blob([html], { type: 'application/vnd.ms-excel;charset=utf-8;' });
856
- // Use the download utility function
857
- downloadFile(blob, fileName);
858
- }
859
- /**
860
- * Exports data to a JSON file.
861
- * @param {any[]} data The data to export.
862
- * @param {string} fileName The name of the file to create.
863
- */
864
- function exportToJSON(data, fileName) {
865
- const jsonContent = JSON.stringify(data, null, 2); // Pretty print with 2 spaces
866
- const blob = new Blob([jsonContent], { type: 'application/json;charset=utf-8;' });
867
- // Use the download utility function
868
- downloadFile(blob, fileName);
869
- }
870
- /**
871
- * Exports data to an XML file.
872
- * @param {string[]} headers The headers for the XML.
873
- * @param {any[][]} data The data to export, as an array of arrays.
874
- * @param {string} fileName The name of the file to create.
875
- */
876
- function exportToXML(headers, data, fileName) {
877
- let xmlContent = '<?xml version="1.0" encoding="UTF-8"?>\n<rows>\n';
878
- // Add headers
879
- xmlContent += ' <header>\n';
880
- headers.forEach(header => {
881
- xmlContent += ` <column>${header}</column>\n`;
882
- });
883
- xmlContent += ' </header>\n';
884
- // Add data rows
885
- data.forEach(row => {
886
- xmlContent += ' <row>\n';
887
- row.forEach(cell => {
888
- xmlContent += ` <cell>${cell}</cell>\n`;
889
- });
890
- xmlContent += ' </row>\n';
891
- });
892
- xmlContent += '</rows>';
893
- const blob = new Blob([xmlContent], { type: 'application/xml;charset=utf-8;' });
894
- // Use the download utility function
895
- downloadFile(blob, fileName);
896
- }
897
- /**
898
- * Exports data to a plain text file.
899
- * @param {string[]} headers The headers for the text file.
900
- * @param {any[][]} data The data to export, as an array of arrays.
901
- * @param {string} fileName The name of the file to create.
902
- */
903
- function exportToText(headers, data, fileName) {
904
- const textRows = [];
905
- // Add headers
906
- textRows.push(headers.join('\t'));
907
- // Add data rows
908
- data.forEach(row => {
909
- textRows.push(row.join('\t'));
910
- });
911
- // Create a Blob with text data
912
- const textContent = textRows.join('\n');
913
- const blob = new Blob([textContent], { type: 'text/plain;charset=utf-8;' });
914
- // Use the download utility function
915
- downloadFile(blob, fileName);
916
- }
917
-
918
- /**
919
- * Opens a new window with the specified URL and options.
920
- * @param {string} url The URL to open.
921
- * @param {Object} [opt] Options for the new window.
922
- * @param {string} [opt.target='__blank'] The target window name.
923
- * @param {boolean} [opt.noopener=true] Whether to add 'noopener' attribute.
924
- * @param {boolean} [opt.noreferrer=true] Whether to add 'noreferrer' attribute.
925
- */
926
- function openWindow(url, opt) {
927
- const { target = '__blank', noopener = true, noreferrer = true } = opt || {};
928
- const features = [];
929
- // Append noopener and noreferrer attributes if enabled
930
- if (noopener)
931
- features.push('noopener=yes');
932
- if (noreferrer)
933
- features.push('noreferrer=yes');
934
- // Open the window with the specified features
935
- window.open(url, target, features.join(','));
936
- }
937
- /**
938
- * Copies text to the clipboard.
939
- * @param {string} text The text to copy.
940
- * @returns {Promise<void>} A promise that resolves when the text has been copied.
941
- */
942
- async function copyToClipboard(text) {
943
- if (navigator.clipboard) {
944
- await navigator.clipboard.writeText(text);
945
- }
946
- else {
947
- // Fallback for browsers that do not support the Clipboard API
948
- const textArea = document.createElement('textarea');
949
- textArea.value = text;
950
- document.body.appendChild(textArea);
951
- textArea.select();
952
- document.execCommand('copy');
953
- document.body.removeChild(textArea);
954
- }
955
- }
956
- /**
957
- * Scrolls the window to the top smoothly.
958
- * @param {number} [duration=300] Duration of the scroll animation in milliseconds.
959
- */
960
- function scrollToTop(duration = 300) {
961
- const start = window.scrollY;
962
- const startTime = performance.now();
963
- function scroll() {
964
- const elapsed = performance.now() - startTime;
965
- const progress = Math.min(elapsed / duration, 1);
966
- window.scrollTo(0, start * (1 - progress));
967
- if (progress < 1) {
968
- requestAnimationFrame(scroll);
969
- }
970
- }
971
- requestAnimationFrame(scroll);
972
- }
973
- /**
974
- * Gets the value of a query parameter from the URL.
975
- * @param {string} paramName The name of the query parameter.
976
- * @returns {string | null} The value of the query parameter, or null if it does not exist.
977
- */
978
- function getQueryParam(paramName) {
979
- const urlParams = new URLSearchParams(window.location.search);
980
- return urlParams.get(paramName);
981
- }
982
-
983
- /**
984
- * Disables the right-click context menu on the window.
985
- */
986
- function disableRightClick() {
987
- const handler = (event) => event.preventDefault();
988
- window.addEventListener('contextmenu', handler);
989
- // Store handler to allow removal
990
- disableRightClick.handler = handler;
991
- }
992
- disableRightClick.handler = null;
993
- /**
994
- * Enables the right-click context menu on the window.
995
- */
996
- function enableRightClick() {
997
- if (disableRightClick.handler) {
998
- window.removeEventListener('contextmenu', disableRightClick.handler);
999
- }
1000
- }
1001
- /**
1002
- * Disables specific mouse buttons.
1003
- * @param {Array<number>} buttons Array of mouse button codes to disable (0 for left, 1 for middle, 2 for right).
1004
- */
1005
- function disableMouseButtons(buttons) {
1006
- const handler = (event) => {
1007
- if (buttons.includes(event.button)) {
1008
- event.preventDefault();
1009
- }
1010
- };
1011
- window.addEventListener('mousedown', handler);
1012
- window.addEventListener('contextmenu', handler); // Also handles right-click context menu
1013
- // Store handler to allow removal later
1014
- disableMouseButtons.handlers.push(handler);
1015
- }
1016
- disableMouseButtons.handlers = [];
1017
- /**
1018
- * Enables all previously disabled mouse buttons.
1019
- */
1020
- function enableMouseButtons() {
1021
- for (const handler of disableMouseButtons.handlers) {
1022
- window.removeEventListener('mousedown', handler);
1023
- window.removeEventListener('contextmenu', handler);
1024
- }
1025
- disableMouseButtons.handlers = [];
1026
- }
1027
- /**
1028
- * Adds a double-click event listener to a specific element.
1029
- * @param {HTMLElement} element The target element.
1030
- * @param {(event: MouseEvent) => void} callback The callback function to execute on double click.
1031
- */
1032
- function addDoubleClickListener(element, callback) {
1033
- element.addEventListener('dblclick', callback);
1034
- }
1035
- /**
1036
- * Removes a double-click event listener from a specific element.
1037
- * @param {HTMLElement} element The target element.
1038
- * @param {(event: MouseEvent) => void} callback The callback function to remove.
1039
- */
1040
- function removeDoubleClickListener(element, callback) {
1041
- element.removeEventListener('dblclick', callback);
1042
- }
1043
- // Example usage:
1044
- // addDoubleClickListener(document.body, () => alert('Double clicked!'));
1045
- /**
1046
- * Detects a click outside a specific element and triggers a callback.
1047
- * @param {HTMLElement} element The element to detect clicks outside of.
1048
- * @param {() => void} callback The callback function to execute when a click outside is detected.
1049
- */
1050
- function clickOutside(element, callback) {
1051
- const handler = (event) => {
1052
- if (!element.contains(event.target)) {
1053
- callback();
1054
- }
1055
- };
1056
- document.addEventListener('click', handler);
1057
- // Store handler to allow removal later
1058
- clickOutside.handlers.push({ element, handler });
1059
- }
1060
- clickOutside.handlers = [];
1061
- /**
1062
- * Removes the click outside listener for a specific element.
1063
- * @param {HTMLElement} element The element to stop detecting clicks outside of.
1064
- */
1065
- function removeClickOutside(element) {
1066
- const index = clickOutside.handlers.findIndex(h => h.element === element);
1067
- if (index !== -1) {
1068
- document.removeEventListener('click', clickOutside.handlers[index].handler);
1069
- clickOutside.handlers.splice(index, 1);
1070
- }
1071
- }
1072
- // Example usage: Close a menu when clicking outside of it
1073
- // const menu = document.getElementById('menu');
1074
- // if (menu) {
1075
- // clickOutside(menu, () => menu.style.display = 'none');
1076
- // }
1077
- /**
1078
- * Disables the F12 key and certain key combinations for developer tools.
1079
- */
1080
- function disableF12Key() {
1081
- const handler = function (event) {
1082
- return true;
1083
- };
1084
- document.addEventListener('keydown', handler);
1085
- }
1086
- /**
1087
- * Enables or disables the tab navigation (Tab key) on the page.
1088
- * @param {boolean} enable Whether to enable or disable tab navigation.
1089
- */
1090
- function toggleTabNavigation(enable) {
1091
- if (enable) {
1092
- document.onkeydown = null; // Removes any previously set handler
1093
- }
1094
- else {
1095
- document.onkeydown = (event) => {
1096
- if (event.key === 'Tab') {
1097
- event.preventDefault();
1098
- return false;
1099
- }
1100
- return true;
1101
- };
1102
- }
1103
- }
1104
- /**
1105
- * Disables the copy (Ctrl + C) functionality on the page.
1106
- */
1107
- function disableCopy() {
1108
- document.addEventListener('copy', (event) => {
1109
- event.preventDefault();
1110
- alert('Copying text is disabled on this page.');
1111
- });
1112
- }
1113
- /**
1114
- * Adds a custom keyboard shortcut to execute a given callback function.
1115
- * @param {string} key The key to trigger the callback.
1116
- * @param {Function} callback The function to execute on the key press.
1117
- * @param {boolean} [ctrlKey=false] Whether Ctrl key should be pressed.
1118
- * @param {boolean} [shiftKey=false] Whether Shift key should be pressed.
1119
- */
1120
- function addCustomKeyboardShortcut(key, callback, ctrlKey = false, shiftKey = false) {
1121
- document.addEventListener('keydown', (event) => {
1122
- if (event.key === key &&
1123
- event.ctrlKey === ctrlKey &&
1124
- event.shiftKey === shiftKey) {
1125
- event.preventDefault();
1126
- callback();
1127
- }
1128
- });
1129
- }
1130
- /**
1131
- * Removes a custom keyboard shortcut by key and modifiers.
1132
- * @param {string} key The key to trigger the callback.
1133
- * @param {boolean} [ctrlKey=false] Whether Ctrl key should be pressed.
1134
- * @param {boolean} [shiftKey=false] Whether Shift key should be pressed.
1135
- */
1136
- function removeCustomKeyboardShortcut(key, ctrlKey = false, shiftKey = false) {
1137
- const handler = (event) => {
1138
- if (event.key === key &&
1139
- event.ctrlKey === ctrlKey &&
1140
- event.shiftKey === shiftKey) {
1141
- event.preventDefault();
1142
- }
1143
- };
1144
- document.removeEventListener('keydown', handler);
1145
- }
1146
- /**
1147
- * Disables specific keys or key combinations.
1148
- * @param {Array<string>} keys Array of key names to disable (e.g., ['F1', 'F5', 'Control+S']).
1149
- */
1150
- function disableSpecificKeys(keys) {
1151
- const handler = (event) => {
1152
- const keyCombination = `${event.ctrlKey ? 'Control+' : ''}${event.shiftKey ? 'Shift+' : ''}${event.altKey ? 'Alt+' : ''}${event.key}`;
1153
- if (keys.includes(event.key) || keys.includes(keyCombination)) {
1154
- event.preventDefault();
1155
- }
1156
- };
1157
- document.addEventListener('keydown', handler);
1158
- // Storing the handler to allow removal later
1159
- disableSpecificKeys.handlers.push(handler);
1160
- }
1161
- disableSpecificKeys.handlers = [];
1162
- /**
1163
- * Enables keys that were previously disabled using disableSpecificKeys.
1164
- */
1165
- function enableSpecificKeys() {
1166
- for (const handler of disableSpecificKeys.handlers) {
1167
- document.removeEventListener('keydown', handler);
1168
- }
1169
- disableSpecificKeys.handlers = [];
1170
- }
1171
- /**
1172
- * Registers multiple keyboard shortcuts with their respective callback functions.
1173
- * @param {Array<{ key: string, ctrlKey?: boolean, shiftKey?: boolean, altKey?: boolean, callback: Function }>} shortcuts Array of shortcut objects.
1174
- */
1175
- function registerKeyboardShortcuts(shortcuts) {
1176
- const handler = (event) => {
1177
- for (const shortcut of shortcuts) {
1178
- if (event.key === shortcut.key &&
1179
- (shortcut.ctrlKey ? event.ctrlKey : true) &&
1180
- (shortcut.shiftKey ? event.shiftKey : true) &&
1181
- (shortcut.altKey ? event.altKey : true)) {
1182
- event.preventDefault();
1183
- shortcut.callback();
1184
- }
1185
- }
1186
- };
1187
- document.addEventListener('keydown', handler);
1188
- // Storing the handler to allow removal later
1189
- registerKeyboardShortcuts.handlers.push(handler);
1190
- }
1191
- registerKeyboardShortcuts.handlers = [];
1192
- /**
1193
- * Unregisters all keyboard shortcuts that were registered with registerKeyboardShortcuts.
1194
- */
1195
- function unregisterKeyboardShortcuts() {
1196
- for (const handler of registerKeyboardShortcuts.handlers) {
1197
- document.removeEventListener('keydown', handler);
1198
- }
1199
- registerKeyboardShortcuts.handlers = [];
1200
- }
1201
- /**
1202
- * Adds a listener for a specific key to trigger a custom event.
1203
- * @param {string} key The key to listen for (e.g., 'Enter', 'Escape').
1204
- * @param {Function} callback The function to execute when the key is pressed.
1205
- */
1206
- function addKeyListener(key, callback) {
1207
- const handler = (event) => {
1208
- if (event.key === key) {
1209
- event.preventDefault();
1210
- callback();
1211
- }
1212
- };
1213
- document.addEventListener('keydown', handler);
1214
- // Storing the handler to allow removal later
1215
- addKeyListener.handlers.push(handler);
1216
- }
1217
- addKeyListener.handlers = [];
1218
- /**
1219
- * Removes all custom key listeners added by addKeyListener.
1220
- */
1221
- function removeKeyListeners() {
1222
- for (const handler of addKeyListener.handlers) {
1223
- document.removeEventListener('keydown', handler);
1224
- }
1225
- addKeyListener.handlers = [];
1226
- }
1227
- /**
1228
- * Detects if a specific key is held down.
1229
- * @param {string} key The key to detect (e.g., 'Shift', 'Control', 'Alt', 'a').
1230
- * @param {Function} onHold Callback function to execute while the key is held down.
1231
- */
1232
- function detectKeyHold(key, onHold) {
1233
- const keyDownHandler = (event) => {
1234
- if (event.key === key) {
1235
- onHold();
1236
- }
1237
- };
1238
- document.addEventListener('keydown', keyDownHandler);
1239
- // Storing the handler to allow removal later
1240
- detectKeyHold.handlers.push(keyDownHandler);
1241
- }
1242
- detectKeyHold.handlers = [];
1243
- /**
1244
- * Stops detecting if a specific key is held down.
1245
- */
1246
- function stopDetectingKeyHold() {
1247
- for (const handler of detectKeyHold.handlers) {
1248
- document.removeEventListener('keydown', handler);
1249
- }
1250
- detectKeyHold.handlers = [];
1251
- }
1252
- /**
1253
- * Tracks currently pressed keys and provides a map of active keys.
1254
- * @returns {Set<string>} A set of currently pressed keys.
1255
- */
1256
- function createKeyMap() {
1257
- const pressedKeys = new Set();
1258
- const keyDownHandler = (event) => {
1259
- pressedKeys.add(event.key);
1260
- };
1261
- const keyUpHandler = (event) => {
1262
- pressedKeys.delete(event.key);
1263
- };
1264
- document.addEventListener('keydown', keyDownHandler);
1265
- document.addEventListener('keyup', keyUpHandler);
1266
- // Function to remove listeners
1267
- createKeyMap.clearListeners = () => {
1268
- document.removeEventListener('keydown', keyDownHandler);
1269
- document.removeEventListener('keyup', keyUpHandler);
1270
- };
1271
- return pressedKeys;
1272
- }
1273
- /**
1274
- * Clears listeners for the key map tracking.
1275
- */
1276
- createKeyMap.clearListeners = () => { };
1277
- /**
1278
- * Sets up custom keyboard shortcuts with flexible order.
1279
- * @param {Array<string>} keys The combination of keys for the shortcut.
1280
- * @param {Function} callback The callback function to execute when the combination is detected.
1281
- */
1282
- function customShortcut(keys, callback) {
1283
- const pressedKeys = new Set();
1284
- const keyDownHandler = (event) => {
1285
- pressedKeys.add(event.key);
1286
- if (keys.every(key => pressedKeys.has(key))) {
1287
- callback();
1288
- }
1289
- };
1290
- const keyUpHandler = (event) => {
1291
- pressedKeys.delete(event.key);
1292
- };
1293
- document.addEventListener('keydown', keyDownHandler);
1294
- document.addEventListener('keyup', keyUpHandler);
1295
- // Store the handlers for later removal
1296
- customShortcut.handlers.push({ keyDownHandler, keyUpHandler });
1297
- }
1298
- customShortcut.handlers = [];
1299
- /**
1300
- * Removes all custom keyboard shortcuts added by customShortcut.
1301
- */
1302
- function removeCustomShortcuts() {
1303
- for (const { keyDownHandler, keyUpHandler } of customShortcut.handlers) {
1304
- document.removeEventListener('keydown', keyDownHandler);
1305
- document.removeEventListener('keyup', keyUpHandler);
1306
- }
1307
- customShortcut.handlers = [];
1308
- }
1309
- /**
1310
- * Simulates a key press event.
1311
- * @param {string} key The key to simulate (e.g., 'Enter', 'a').
1312
- * @param {boolean} ctrlKey If true, include Ctrl key in the event.
1313
- * @param {boolean} shiftKey If true, include Shift key in the event.
1314
- * @param {boolean} altKey If true, include Alt key in the event.
1315
- */
1316
- function simulateKeyPress(key, ctrlKey = false, shiftKey = false, altKey = false) {
1317
- const event = new KeyboardEvent('keydown', {
1318
- key,
1319
- ctrlKey,
1320
- shiftKey,
1321
- altKey,
1322
- bubbles: true,
1323
- cancelable: true
1324
- });
1325
- document.dispatchEvent(event);
1326
- }
1327
-
1328
- /**
1329
- * Parses a date string into a Date object.
1330
- * @param {string} dateString The date string in 'YYYY-MM-DD' format.
1331
- * @returns {Date | null} The parsed Date object or null if the format is invalid.
1332
- */
1333
- function parseDate(dateString) {
1334
- const parts = dateString.split('-');
1335
- if (parts.length === 3) {
1336
- const year = parseInt(parts[0], 10);
1337
- const month = parseInt(parts[1], 10) - 1; // Months are zero-based
1338
- const day = parseInt(parts[2], 10);
1339
- const date = new Date(year, month, day);
1340
- if (date.getFullYear() === year && date.getMonth() === month && date.getDate() === day) {
1341
- return date;
1342
- }
1343
- }
1344
- return null;
1345
- }
1346
- /**
1347
- * Formats a Date object into a string.
1348
- * @param {Date} date The date to format.
1349
- * @param {string} format The format string (e.g., 'YYYY-MM-DD').
1350
- * @returns {string} The formatted date string.
1351
- */
1352
- function formatDate(date, format) {
1353
- const map = {
1354
- 'YYYY': date.getFullYear(),
1355
- 'MM': String(date.getMonth() + 1).padStart(2, '0'),
1356
- 'DD': String(date.getDate()).padStart(2, '0'),
1357
- 'HH': String(date.getHours()).padStart(2, '0'),
1358
- 'mm': String(date.getMinutes()).padStart(2, '0'),
1359
- 'ss': String(date.getSeconds()).padStart(2, '0')
1360
- };
1361
- return format.replace(/YYYY|MM|DD|HH|mm|ss/g, (matched) => (map[matched] || matched).toString());
1362
- }
1363
- /**
1364
- * Calculates the number of days between two dates.
1365
- * @param {Date} startDate The start date.
1366
- * @param {Date} endDate The end date.
1367
- * @returns {number} The number of days between the two dates.
1368
- */
1369
- function daysBetween(startDate, endDate) {
1370
- const millisecondsPerDay = 86400000; // Number of milliseconds in one day
1371
- return Math.round((endDate.getTime() - startDate.getTime()) / millisecondsPerDay);
1372
- }
1373
- /**
1374
- * Adds a specified number of days to a date.
1375
- * @param {Date} date The date to modify.
1376
- * @param {number} days The number of days to add.
1377
- * @returns {Date} The new date with days added.
1378
- */
1379
- function addDays(date, days) {
1380
- const result = new Date(date);
1381
- result.setDate(result.getDate() + days);
1382
- return result;
1383
- }
1384
- /**
1385
- * Subtracts a specified number of days from a date.
1386
- * @param {Date} date The date to modify.
1387
- * @param {number} days The number of days to subtract.
1388
- * @returns {Date} The new date with days subtracted.
1389
- */
1390
- function subtractDays(date, days) {
1391
- return addDays(date, -days);
1392
- }
1393
- /**
1394
- * Determines if a year is a leap year.
1395
- * @param {number} year The year to check.
1396
- * @returns {boolean} True if the year is a leap year, false otherwise.
1397
- */
1398
- function isLeapYear(year) {
1399
- return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
1400
- }
1401
- /**
1402
- * Gets the first day of the month for a given date.
1403
- * @param {Date} date The date to use.
1404
- * @returns {Date} The first day of the month.
1405
- */
1406
- function getStartOfMonth(date) {
1407
- return new Date(date.getFullYear(), date.getMonth(), 1);
1408
- }
1409
- /**
1410
- * Gets the last day of the month for a given date.
1411
- * @param {Date} date The date to use.
1412
- * @returns {Date} The last day of the month.
1413
- */
1414
- function getEndOfMonth(date) {
1415
- return new Date(date.getFullYear(), date.getMonth() + 1, 0);
1416
- }
1417
- /**
1418
- * Calculates age from a given birth date.
1419
- * @param {Date} birthDate The birth date.
1420
- * @returns {number} The calculated age.
1421
- */
1422
- function calculateAge(birthDate) {
1423
- const today = new Date();
1424
- let age = today.getFullYear() - birthDate.getFullYear();
1425
- const m = today.getMonth() - birthDate.getMonth();
1426
- if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
1427
- age--;
1428
- }
1429
- return age;
1430
- }
1431
- /**
1432
- * Calculates the number of days until the next birthday.
1433
- * @param {Date} birthDate The birth date.
1434
- * @returns {number} The number of days until the next birthday.
1435
- */
1436
- function daysToNextBirthday(birthDate) {
1437
- const today = new Date();
1438
- const currentYear = today.getFullYear();
1439
- const nextBirthday = new Date(birthDate);
1440
- nextBirthday.setFullYear(currentYear);
1441
- if (nextBirthday < today) {
1442
- nextBirthday.setFullYear(currentYear + 1);
1443
- }
1444
- return daysBetween(today, nextBirthday);
1445
- }
1446
- /**
1447
- * Calculates the age at a specific date.
1448
- * @param {Date} birthDate The birth date.
1449
- * @param {Date} atDate The date to calculate the age at.
1450
- * @returns {number} The calculated age.
1451
- */
1452
- function ageAtDate(birthDate, atDate) {
1453
- let age = atDate.getFullYear() - birthDate.getFullYear();
1454
- const m = atDate.getMonth() - birthDate.getMonth();
1455
- if (m < 0 || (m === 0 && atDate.getDate() < birthDate.getDate())) {
1456
- age--;
1457
- }
1458
- return age;
1459
- }
1460
-
1461
- /**
1462
- * Creates a debounced asynchronous validator function.
1463
- *
1464
- * @param validator - The async validator function to debounce.
1465
- * @param delay - The debounce delay in milliseconds.
1466
- * @returns A debounced version of the validator function.
1467
- */
1468
- function debounceAsyncValidator(validator, delay) {
1469
- let currentPromiseReject = null;
1470
- /**
1471
- * Creates a debounce delay.
1472
- *
1473
- * @returns A promise that resolves after the debounce delay.
1474
- */
1475
- function debounce() {
1476
- return new Promise((resolve, reject) => {
1477
- const { start, stop } = core.useTimeoutFn(() => {
1478
- currentPromiseReject = null;
1479
- resolve();
1480
- }, delay);
1481
- if (currentPromiseReject) {
1482
- currentPromiseReject(new Error('replaced'));
1483
- }
1484
- currentPromiseReject = reject;
1485
- start();
1486
- });
1487
- }
1488
- return function (value) {
1489
- if (currentPromiseReject) {
1490
- currentPromiseReject(new Error('replaced'));
1491
- currentPromiseReject = null;
1492
- }
1493
- return validator.call(this, value, debounce);
1494
- };
1495
- }
1496
- /**
1497
- * Creates a debounced version of an asynchronous function.
1498
- * @param {Function} func The asynchronous function to debounce.
1499
- * @param {number} wait The number of milliseconds to wait before invoking the function.
1500
- * @returns {Function} The debounced function.
1501
- */
1502
- function debounceAsync(func, wait) {
1503
- let timeoutReject = null;
1504
- return function (...args) {
1505
- if (timeoutReject) {
1506
- timeoutReject(new Error('replaced'));
1507
- timeoutReject = null;
1508
- }
1509
- return new Promise((resolve, reject) => {
1510
- const { start } = core.useTimeoutFn(() => {
1511
- func.apply(this, args).then(resolve).catch(reject);
1512
- }, wait);
1513
- timeoutReject = reject;
1514
- start();
1515
- });
1516
- };
1517
- }
1518
- /**
1519
- * Creates a debounced asynchronous function that executes immediately on the first call.
1520
- * @param {Function} func The asynchronous function to debounce.
1521
- * @param {number} wait The number of milliseconds to wait before invoking the function.
1522
- * @returns {Function} The debounced function with immediate execution on the first call.
1523
- */
1524
- function debounceAsyncWithImmediate(func, wait) {
1525
- let timeoutReject = null;
1526
- let callNow = true;
1527
- return function (...args) {
1528
- const context = this;
1529
- if (callNow) {
1530
- callNow = false;
1531
- return func.apply(context, args).finally(() => {
1532
- const { start } = core.useTimeoutFn(() => {
1533
- callNow = true;
1534
- }, wait);
1535
- start();
1536
- });
1537
- }
1538
- else {
1539
- if (timeoutReject) {
1540
- timeoutReject(new Error('replaced'));
1541
- timeoutReject = null;
1542
- }
1543
- return new Promise((resolve, reject) => {
1544
- const { start } = core.useTimeoutFn(() => {
1545
- func.apply(context, args).then(resolve).catch(reject);
1546
- }, wait);
1547
- timeoutReject = reject;
1548
- start();
1549
- });
1550
- }
1551
- };
1552
- }
1553
- /**
1554
- * Creates a debounced version of a function that executes on the leading edge.
1555
- * @param {Function} func The function to debounce.
1556
- * @param {number} wait The number of milliseconds to wait before invoking the function.
1557
- * @returns {Function} The debounced function.
1558
- */
1559
- function debounceLeading(func, wait) {
1560
- let timeoutReject = null;
1561
- return function (...args) {
1562
- const context = this;
1563
- if (!timeoutReject) {
1564
- func.apply(context, args);
1565
- }
1566
- if (timeoutReject) {
1567
- timeoutReject(new Error('replaced'));
1568
- timeoutReject = null;
1569
- }
1570
- const { start } = core.useTimeoutFn(() => {
1571
- timeoutReject = null;
1572
- }, wait);
1573
- timeoutReject = () => { };
1574
- start();
1575
- };
1576
- }
1577
- /**
1578
- * Creates a debounced version of a function that executes on the trailing edge.
1579
- * @param {Function} func The function to debounce.
1580
- * @param {number} wait The number of milliseconds to wait before invoking the function.
1581
- * @returns {Function} The debounced function.
1582
- */
1583
- function debounceTrailing(func, wait) {
1584
- let timeoutReject = null;
1585
- return function (...args) {
1586
- const context = this;
1587
- if (timeoutReject) {
1588
- timeoutReject(new Error('replaced'));
1589
- timeoutReject = null;
1590
- }
1591
- const { start } = core.useTimeoutFn(() => {
1592
- func.apply(context, args);
1593
- }, wait);
1594
- timeoutReject = () => { };
1595
- start();
1596
- };
1597
- }
1598
- /**
1599
- * Creates a debounced version of a function that executes on both leading and trailing edges.
1600
- * @param {Function} func The function to debounce.
1601
- * @param {number} wait The number of milliseconds to wait before invoking the function.
1602
- * @returns {Function} The debounced function.
1603
- */
1604
- function debounceLeadingTrailing(func, wait) {
1605
- let timeoutReject = null;
1606
- let lastCall = 0;
1607
- return function (...args) {
1608
- const context = this;
1609
- const now = Date.now();
1610
- if (timeoutReject) {
1611
- timeoutReject(new Error('replaced'));
1612
- timeoutReject = null;
1613
- }
1614
- if (now - lastCall >= wait) {
1615
- func.apply(context, args);
1616
- lastCall = now;
1617
- }
1618
- else {
1619
- const { start } = core.useTimeoutFn(() => {
1620
- func.apply(context, args);
1621
- }, wait - (now - lastCall));
1622
- timeoutReject = () => { };
1623
- start();
1624
- }
1625
- };
1626
- }
1627
- /**
1628
- * Creates a debounced version of a function.
1629
- * @param {Function} func The function to debounce.
1630
- * @param {number} wait The number of milliseconds to wait before invoking the function.
1631
- * @returns {Function} The debounced function.
1632
- */
1633
- function debounce(func, wait) {
1634
- let timeoutReject = null;
1635
- return function (...args) {
1636
- if (timeoutReject) {
1637
- timeoutReject(new Error('replaced'));
1638
- timeoutReject = null;
1639
- }
1640
- const { start } = core.useTimeoutFn(() => {
1641
- func.apply(this, args);
1642
- }, wait);
1643
- timeoutReject = () => { };
1644
- start();
1645
- };
1646
- }
1647
- /**
1648
- * Creates a throttled version of a function.
1649
- * @param {Function} func The function to throttle.
1650
- * @param {number} limit The number of milliseconds to wait between function calls.
1651
- * @returns {Function} The throttled function.
1652
- */
1653
- function throttle(func, limit) {
1654
- let lastCall = 0;
1655
- return function (...args) {
1656
- const now = Date.now();
1657
- if (now - lastCall >= limit) {
1658
- lastCall = now;
1659
- func.apply(this, args);
1660
- }
1661
- };
1662
- }
1663
-
1664
- /**
1665
- * Converts a FormData object to a plain JavaScript object.
1666
- * @param {FormData} formData The FormData object to convert.
1667
- * @returns {Record<string, any>} The plain JavaScript object.
1668
- */
1669
- function formDataToObject(formData) {
1670
- const obj = {};
1671
- formData.forEach((value, key) => {
1672
- // Handle multiple values for the same key
1673
- if (obj[key]) {
1674
- if (!Array.isArray(obj[key])) {
1675
- obj[key] = [obj[key]];
1676
- }
1677
- obj[key].push(value);
1678
- }
1679
- else {
1680
- obj[key] = value;
1681
- }
1682
- });
1683
- return obj;
1684
- }
1685
- /**
1686
- * Reads a file as text.
1687
- * @param {File} file The file to read.
1688
- * @returns {Promise<string>} A promise that resolves with the file content.
1689
- */
1690
- function readFileAsText(file) {
1691
- return new Promise((resolve, reject) => {
1692
- const reader = new FileReader();
1693
- reader.onload = () => resolve(reader.result);
1694
- reader.onerror = reject;
1695
- reader.readAsText(file);
1696
- });
1697
- }
1698
- /**
1699
- * Reads a file as a Data URL.
1700
- * @param {File} file The file to read.
1701
- * @returns {Promise<string>} A promise that resolves with the Data URL.
1702
- */
1703
- function readFileAsDataURL(file) {
1704
- return new Promise((resolve, reject) => {
1705
- const reader = new FileReader();
1706
- reader.onload = () => resolve(reader.result);
1707
- reader.onerror = reject;
1708
- reader.readAsDataURL(file);
1709
- });
1710
- }
1711
- /**
1712
- * Creates a Blob from a string.
1713
- * @param {string} content The string content for the Blob.
1714
- * @param {string} [type='text/plain'] The MIME type of the Blob.
1715
- * @returns {Blob} The Blob object.
1716
- */
1717
- function stringToBlob(content, type = 'text/plain') {
1718
- return new Blob([content], { type });
1719
- }
1720
- /**
1721
- * Creates a Blob from an ArrayBuffer.
1722
- * @param {ArrayBuffer} buffer The ArrayBuffer to convert.
1723
- * @param {string} [type='application/octet-stream'] The MIME type of the Blob.
1724
- * @returns {Blob} The Blob object.
1725
- */
1726
- function bufferToBlob(buffer, type = 'application/octet-stream') {
1727
- return new Blob([buffer], { type });
1728
- }
1729
- /**
1730
- * Creates and downloads a file from Blob data.
1731
- * @param {Blob} blob The Blob containing the file data.
1732
- * @param {string} fileName The name of the file to create.
1733
- */
1734
- function downloadBlob(blob, fileName) {
1735
- const link = document.createElement('a');
1736
- const url = URL.createObjectURL(blob);
1737
- link.setAttribute('href', url);
1738
- link.setAttribute('download', fileName);
1739
- // Append link to the body and trigger a click
1740
- document.body.appendChild(link);
1741
- link.click();
1742
- // Clean up
1743
- document.body.removeChild(link);
1744
- URL.revokeObjectURL(url);
1745
- }
1746
- /**
1747
- * Creates a FormData object containing a Blob.
1748
- * @param {Blob} blob The Blob to include in the FormData.
1749
- * @param {string} name The name of the form field.
1750
- * @param {string} [fileName='file'] The file name for the Blob.
1751
- * @returns {FormData} The FormData object.
1752
- */
1753
- function blobToFormData(blob, name, fileName = 'file') {
1754
- const formData = new FormData();
1755
- formData.append(name, blob, fileName);
1756
- return formData;
1757
- }
1758
-
1759
- /**
1760
- * Converts a Proxy object to a plain object.
1761
- * @param {ProxyConstructor} proxy The Proxy object to convert.
1762
- * @returns {Object} The plain object.
1763
- */
1764
- function proxyToPlainObject(proxy) {
1765
- if (!proxy)
1766
- return {};
1767
- const plainObject = {};
1768
- for (const property of Object.keys(proxy)) {
1769
- plainObject[property] = proxy[property];
1770
- }
1771
- return plainObject;
1772
- }
1773
- /**
1774
- * Compares two objects to check if they have the same keys.
1775
- * @param {Object} object1 The first object to compare.
1776
- * @param {Object} object2 The second object to compare.
1777
- * @returns {boolean} True if the objects have the same keys, otherwise false.
1778
- */
1779
- function compareObject(object1, object2) {
1780
- return Object.keys(object1).every(function (element) {
1781
- return Object.keys(object2).includes(element);
1782
- });
1783
- }
1784
- /**
1785
- * Deeply compares two objects to check if they are equal.
1786
- * @param {Object} object1 The first object to compare.
1787
- * @param {Object} object2 The second object to compare.
1788
- * @returns {boolean} True if the objects are deeply equal, otherwise false.
1789
- */
1790
- function deepEqual(object1, object2) {
1791
- if (object1 === object2)
1792
- return true;
1793
- if (typeof object1 !== 'object' || typeof object2 !== 'object' || object1 === null || object2 === null) {
1794
- return false;
1795
- }
1796
- const keys1 = Object.keys(object1);
1797
- const keys2 = Object.keys(object2);
1798
- if (keys1.length !== keys2.length) {
1799
- return false;
1800
- }
1801
- for (const key of keys1) {
1802
- if (!keys2.includes(key) || !deepEqual(object1[key], object2[key])) {
1803
- return false;
1804
- }
1805
- }
1806
- return true;
1807
- }
1808
- /**
1809
- * Deeply clones an object.
1810
- * @param {Object} obj The object to clone.
1811
- * @returns {Object} The cloned object.
1812
- */
1813
- function deepClone(obj) {
1814
- if (obj === null || typeof obj !== 'object') {
1815
- return obj;
1816
- }
1817
- if (obj instanceof Date) {
1818
- return new Date(obj.getTime());
1819
- }
1820
- if (obj instanceof Array) {
1821
- return obj.map(item => deepClone(item));
1822
- }
1823
- if (obj instanceof Object) {
1824
- const copy = {};
1825
- for (const key in obj) {
1826
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
1827
- copy[key] = deepClone(obj[key]);
1828
- }
1829
- }
1830
- return copy;
1831
- }
1832
- throw new Error('Unable to clone object! Its type is not supported.');
1833
- }
1834
- /**
1835
- * Converts an object to a query string.
1836
- * @param {Object} obj The object to convert.
1837
- * @returns {string} The query string.
1838
- */
1839
- function objectToQueryString(obj) {
1840
- return Object.keys(obj)
1841
- .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
1842
- .join('&');
1843
- }
1844
- // Example usage:
1845
- // objectToQueryString({ name: 'John Doe', age: 30 }); // 'name=John%20Doe&age=30'
1846
- /**
1847
- * Gets the differences between two objects.
1848
- * @param {Object} object1 The first object.
1849
- * @param {Object} object2 The second object.
1850
- * @returns {Object} An object containing the differences.
1851
- */
1852
- function getObjectDifferences(object1, object2) {
1853
- const differences = {};
1854
- const keys = new Set([...Object.keys(object1), ...Object.keys(object2)]);
1855
- for (const key of keys) {
1856
- if (object1[key] !== object2[key]) {
1857
- differences[key] = { object1: object1[key], object2: object2[key] };
1858
- }
1859
- }
1860
- return differences;
1861
- }
1862
- /**
1863
- * Filters an object by a list of keys.
1864
- * @param {Object} obj The object to filter.
1865
- * @param {Array<string>} keys The keys to keep.
1866
- * @returns {Object} The filtered object.
1867
- */
1868
- function filterObjectByKeys(obj, keys) {
1869
- const filteredObject = {};
1870
- for (const key of keys) {
1871
- if (key in obj) {
1872
- filteredObject[key] = obj[key];
1873
- }
1874
- }
1875
- return filteredObject;
1876
- }
1877
- // Example usage:
1878
- // filterObjectByKeys({ name: 'John', age: 30, job: 'Developer' }, ['name', 'job']); // { name: 'John', job: 'Developer' }
1879
- /**
1880
- * Deeply merges two objects.
1881
- * @param {Object} target The target object to merge into.
1882
- * @param {Object} source The source object to merge from.
1883
- * @returns {Object} The merged object.
1884
- */
1885
- function deepMerge(target, source) {
1886
- if (target === null || typeof target !== 'object' || typeof source !== 'object') {
1887
- return target;
1888
- }
1889
- for (const key in source) {
1890
- if (Object.prototype.hasOwnProperty.call(source, key)) {
1891
- if (source[key] && typeof source[key] === 'object') {
1892
- if (target && !target[key]) {
1893
- Object.assign(target, { [key]: {} });
1894
- }
1895
- deepMerge(target[key], source[key]);
1896
- }
1897
- else {
1898
- Object.assign(target, { [key]: source[key] });
1899
- }
1900
- }
1901
- }
1902
- return target;
1903
- }
1904
- /**
1905
- * Checks if an object is empty.
1906
- * @param {Object} obj The object to check.
1907
- * @returns {boolean} True if the object is empty, otherwise false.
1908
- */
1909
- function isEmptyObject(obj) {
1910
- return Object.keys(obj).length === 0;
1911
- }
1912
- /**
1913
- * Safely accesses nested properties in an object.
1914
- * @param {Object} obj The object to access.
1915
- * @param {Array<string>} keys The array of keys representing the path.
1916
- * @returns {any} The value at the nested path, or undefined if not found.
1917
- */
1918
- function safeGet(obj, keys) {
1919
- return keys.reduce((acc, key) => (acc && acc[key] !== undefined) ? acc[key] : undefined, obj);
1920
- }
1921
- // Example usage:
1922
- // safeGet({ a: { b: { c: 10 } } }, ['a', 'b', 'c']); // 10
1923
- // safeGet({ a: { b: { c: 10 } } }, ['a', 'x', 'c']); // undefined
1924
- /**
1925
- * Removes empty properties (null, undefined, or empty string) from an object.
1926
- * @param {Object} obj The object to clean.
1927
- * @returns {Object} A new object without empty properties.
1928
- */
1929
- function removeEmptyProperties(obj) {
1930
- return Object.keys(obj)
1931
- .filter(key => obj[key] !== null && obj[key] !== undefined && obj[key] !== '')
1932
- .reduce((acc, key) => {
1933
- acc[key] = obj[key];
1934
- return acc;
1935
- }, {});
1936
- }
1937
- // Example usage:
1938
- // removeEmptyProperties({ a: null, b: 2, c: undefined, d: '', e: 'hello' }); // { b: 2, e: 'hello' }
1939
- /**
1940
- * Retrieves all keys of an object as an array.
1941
- * @param {Object} obj The object to retrieve keys from.
1942
- * @returns {Array<string>} The array of keys.
1943
- */
1944
- function getObjectKeys(obj) {
1945
- return Object.keys(obj);
1946
- }
1947
- // Example usage:
1948
- // getObjectKeys({ name: 'John', age: 30 }); // ['name', 'age']
1949
- /**
1950
- * Checks if an object has nested properties.
1951
- * @param {Object} obj The object to check.
1952
- * @returns {boolean} True if there are nested properties, false otherwise.
1953
- */
1954
- function hasNestedProperties(obj) {
1955
- return Object.values(obj).some(value => typeof value === 'object' && value !== null);
1956
- }
1957
- // Example usage:
1958
- // hasNestedProperties({ a: 1, b: { c: 2 } }); // true
1959
- // hasNestedProperties({ a: 1, b: 2 }); // false
1960
- /**
1961
- * Converts an object to FormData, handling nested objects.
1962
- * @param {Object} obj The object to convert.
1963
- * @param {FormData} [formData] The FormData object to append to.
1964
- * @param {string} [parentKey] The parent key for nested objects.
1965
- * @returns {FormData} The FormData object.
1966
- */
1967
- function objectToFormDataEnhanced(obj, formData = new FormData(), parentKey = '') {
1968
- Object.entries(obj).forEach(([key, value]) => {
1969
- const finalKey = parentKey ? `${parentKey}[${key}]` : key;
1970
- if (value && typeof value === 'object' && !(value instanceof File)) {
1971
- objectToFormDataEnhanced(value, formData, finalKey);
1972
- }
1973
- else {
1974
- formData.append(finalKey, value);
1975
- }
1976
- });
1977
- return formData;
1978
- }
1979
- // Example usage:
1980
- // objectToFormDataEnhanced({ user: { name: 'John', age: 30 } });
1981
- /**
1982
- * Converts a JavaScript object into FormData.
1983
- *
1984
- * @param obj - The object to be converted.
1985
- * @param form - An optional FormData instance to use.
1986
- * @param namespace - An optional namespace to use for nested objects.
1987
- * @returns The FormData instance with the object's key-value pairs.
1988
- */
1989
- const objectToFormData = function (obj, form, namespace) {
1990
- const fd = form || new FormData();
1991
- let formKey;
1992
- for (const property in obj) {
1993
- if (obj[property] === undefined) {
1994
- continue;
1995
- }
1996
- if (Object.prototype.hasOwnProperty.call(obj, property)) {
1997
- if (namespace) {
1998
- formKey = `${namespace}[${property}]`;
1999
- }
2000
- else {
2001
- formKey = property;
2002
- }
2003
- if (typeof obj[property] === 'object' && !(obj[property] instanceof File)) {
2004
- // Recursively handle nested objects
2005
- objectToFormData(obj[property], fd, formKey);
2006
- }
2007
- else {
2008
- // Convert boolean values to 1/0
2009
- const value = obj[property] === true || obj[property] === false ? Number(obj[property]) : obj[property];
2010
- fd.append(formKey, value);
2011
- }
2012
- }
2013
- }
2014
- return fd;
2015
- };
2016
- /**
2017
- * Flattens a nested object, bringing all properties to the top level.
2018
- * @param {Object} obj The object to flatten.
2019
- * @param {string} [parentKey] The parent key for nested properties.
2020
- * @param {Object} [result] The resulting flattened object.
2021
- * @returns {Object} The flattened object.
2022
- */
2023
- function flattenObject(obj, parentKey = '', result = {}) {
2024
- for (const key in obj) {
2025
- if (obj.hasOwnProperty(key)) {
2026
- const propName = parentKey ? `${parentKey}.${key}` : key;
2027
- if (typeof obj[key] === 'object' && obj[key] !== null) {
2028
- flattenObject(obj[key], propName, result);
2029
- }
2030
- else {
2031
- result[propName] = obj[key];
2032
- }
2033
- }
2034
- }
2035
- return result;
2036
- }
2037
- // Example usage:
2038
- // flattenObject({ a: 1, b: { c: 2, d: { e: 3 } } }); // { 'a': 1, 'b.c': 2, 'b.d.e': 3 }
2039
-
2040
- /**
2041
- * Capitalizes the first character of a string.
2042
- * @param {string} s The string to capitalize.
2043
- * @returns {string} The capitalized string.
2044
- */
2045
- function upperFirst(s) {
2046
- return s.charAt(0).toUpperCase() + s.slice(1);
2047
- }
2048
- // Example usage:
2049
- // console.log(upperFirst('hello')); // 'Hello'
2050
- /**
2051
- * Lowercases the first character of a string.
2052
- * @param {string} s The string to lowercase.
2053
- * @returns {string} The lowercased string.
2054
- */
2055
- function lowerFirst(s) {
2056
- return s.charAt(0).toLowerCase() + s.slice(1);
2057
- }
2058
- // Example usage:
2059
- // console.log(lowerFirst('Hello')); // 'hello'
2060
- /**
2061
- * Removes accents and special characters from a string and converts it to a URL-friendly format.
2062
- * @param {string} input The string to process.
2063
- * @returns {string} The processed string.
2064
- */
2065
- function removeAccent(input) {
2066
- return input
2067
- .toLowerCase()
2068
- .trim()
2069
- .replace(/[\s_-]+/g, "-")
2070
- .replace(/^-+|-+$/g, "")
2071
- .normalize("NFD")
2072
- .replace(/[\u0300-\u036f]/g, "");
2073
- }
2074
- // Example usage:
2075
- // console.log(removeAccent('Café du Nord')); // 'cafe-du-nord'
2076
- /**
2077
- * Reverses a string.
2078
- * @param {string} str The string to reverse.
2079
- * @returns {string} The reversed string.
2080
- */
2081
- function reverseString(str) {
2082
- return str.split('').reverse().join('');
2083
- }
2084
- // Example usage:
2085
- // console.log(reverseString('hello')); // 'olleh'
2086
- /**
2087
- * Counts the number of words in a string.
2088
- * @param {string} str The string to analyze.
2089
- * @returns {number} The word count.
2090
- */
2091
- function countWords(str) {
2092
- return str.trim().split(/\s+/).length;
2093
- }
2094
- // Example usage:
2095
- // console.log(countWords('Hello world!')); // 2
2096
- /**
2097
- * Truncates a string to the specified length and adds ellipsis if necessary.
2098
- * @param {string} str The string to truncate.
2099
- * @param {number} maxLength The maximum length of the string.
2100
- * @returns {string} The truncated string.
2101
- */
2102
- function truncateString(str, maxLength) {
2103
- return str.length > maxLength ? str.slice(0, maxLength) + '...' : str;
2104
- }
2105
- // Example usage:
2106
- // console.log(truncateString('This is a long string', 10)); // 'This is a...'
2107
- /**
2108
- * Converts a string to camel case.
2109
- * @param {string} str The string to convert.
2110
- * @returns {string} The camel cased string.
2111
- */
2112
- function toCamelCase(str) {
2113
- return str
2114
- .toLowerCase()
2115
- .replace(/[^a-zA-Z0-9]+(.)/g, (match, chr) => chr.toUpperCase());
2116
- }
2117
- // Example usage:
2118
- // console.log(toCamelCase('hello world example')); // 'helloWorldExample'
2119
- /**
2120
- * Converts a string to kebab case.
2121
- * @param {string} str The string to convert.
2122
- * @returns {string} The kebab cased string.
2123
- */
2124
- function toKebabCase(str) {
2125
- return str
2126
- .replace(/([a-z])([A-Z])/g, '$1-$2')
2127
- .replace(/[\s_]+/g, '-')
2128
- .toLowerCase();
2129
- }
2130
- // Example usage:
2131
- // console.log(toKebabCase('Hello World Example')); // 'hello-world-example'
2132
- /**
2133
- * Replaces all instances of a substring within a string.
2134
- * @param {string} str The original string.
2135
- * @param {string} find The substring to find.
2136
- * @param {string} replace The substring to replace with.
2137
- * @returns {string} The modified string.
2138
- */
2139
- function replaceAll(str, find, replace) {
2140
- return str.split(find).join(replace);
2141
- }
2142
- // Example usage:
2143
- // console.log(replaceAll('hello world', 'o', 'a')); // 'hella warld'
2144
- /**
2145
- * Generates a random string of a specific length.
2146
- * @param {number} length The length of the string to generate.
2147
- * @returns {string} The random string.
2148
- */
2149
- function generateRandomString(length) {
2150
- const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
2151
- return Array.from({ length }, () => characters.charAt(Math.floor(Math.random() * characters.length))).join('');
2152
- }
2153
- // Example usage:
2154
- // console.log(generateRandomString(10)); // 'A1b2C3d4E5'
2155
-
2156
- /**
2157
- * Validates if the key pressed is a valid letter or special character.
2158
- * @param {KeyboardEvent} e The keyboard event.
2159
- * @returns {boolean} True if the key is valid, otherwise false.
2160
- */
2161
- function validateLetters(e) {
2162
- const key = e.keyCode;
2163
- const validKeys = [
2164
- ...Array.from({ length: 26 }, (_, i) => i + 65), // Letters A-Z
2165
- ...Array.from({ length: 26 }, (_, i) => i + 97), // Letters a-z
2166
- 45, // Hyphen
2167
- 32, // Space
2168
- 241, // ñ
2169
- 209, // Ñ
2170
- 225, // á
2171
- 233, // é
2172
- 237, // í
2173
- 243, // ó
2174
- 250, // ú
2175
- 193, // Á
2176
- 201, // É
2177
- 205, // Í
2178
- 211, // Ó
2179
- 218 // Ú
2180
- ];
2181
- if (validKeys.includes(key)) {
2182
- return true;
2183
- }
2184
- e.preventDefault();
2185
- return false;
2186
- }
2187
- // Example usage:
2188
- // document.addEventListener('keydown', validateLetters);
2189
- /**
2190
- * Validates if the key pressed is a valid alphanumeric character.
2191
- * @param {KeyboardEvent} e The keyboard event.
2192
- * @returns {boolean} True if the key is valid, otherwise false.
2193
- */
2194
- function validateAlphanumeric(e) {
2195
- const key = e.keyCode;
2196
- const validKeys = [
2197
- ...Array.from({ length: 10 }, (_, i) => i + 48), // Numbers 0-9
2198
- ...Array.from({ length: 26 }, (_, i) => i + 65), // Letters A-Z
2199
- ...Array.from({ length: 26 }, (_, i) => i + 97), // Letters a-z
2200
- 45, // Hyphen
2201
- 95, // Underscore
2202
- 32 // Space
2203
- ];
2204
- if (validKeys.includes(key)) {
2205
- return true;
2206
- }
2207
- e.preventDefault();
2208
- return false;
2209
- }
2210
- // Example usage:
2211
- // document.addEventListener('keydown', validateAlphanumeric);
2212
- /**
2213
- * Validates if the key pressed is a number.
2214
- * @param {KeyboardEvent} e The keyboard event.
2215
- * @returns {boolean} True if the key is a number, otherwise false.
2216
- */
2217
- function validateNumbers(e) {
2218
- const key = e.keyCode;
2219
- if ((key >= 48 && key <= 57) || key === 46 || key === 8 || key === 37 || key === 39) {
2220
- return true;
2221
- }
2222
- e.preventDefault();
2223
- return false;
2224
- }
2225
- // Example usage:
2226
- // document.addEventListener('keydown', validateNumbers);
2227
- /**
2228
- * Validates if a phone number is valid.
2229
- * @param {string} phoneNumber The phone number to validate.
2230
- * @returns {boolean} True if the phone number is valid, otherwise false.
2231
- */
2232
- function isValidPhoneNumber(phoneNumber) {
2233
- const phonePattern = /^[0-9]{10}$/; // Example pattern for 10-digit phone numbers
2234
- return phonePattern.test(phoneNumber);
2235
- }
2236
- // Example usage:
2237
- // console.log(isValidPhoneNumber('1234567890')); // true
2238
- // console.log(isValidPhoneNumber('123-456-7890')); // false
2239
- /**
2240
- * Validates if a string is a valid email address.
2241
- * @param {string} email The email address to validate.
2242
- * @returns {boolean} True if the email address is valid, otherwise false.
2243
- */
2244
- function isValidEmail(email) {
2245
- const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
2246
- return emailPattern.test(email);
2247
- }
2248
- // Example usage:
2249
- // console.log(isValidEmail('example@domain.com')); // true
2250
- // console.log(isValidEmail('invalid-email')); // false
2251
- /**
2252
- * Validates if a string is a valid URL.
2253
- * @param {string} url The URL to validate.
2254
- * @returns {boolean} True if the URL is valid, otherwise false.
2255
- */
2256
- function isValidURL(url) {
2257
- try {
2258
- new URL(url);
2259
- return true;
2260
- }
2261
- catch {
2262
- return false;
2263
- }
2264
- }
2265
- // Example usage:
2266
- // console.log(isValidURL('https://www.example.com')); // true
2267
- // console.log(isValidURL('invalid-url')); // false
2268
- /**
2269
- * Validates if a string is a valid date in YYYY-MM-DD format.
2270
- * @param {string} date The date string to validate.
2271
- * @returns {boolean} True if the date is valid, otherwise false.
2272
- */
2273
- function isValidDate(date) {
2274
- const datePattern = /^\d{4}-\d{2}-\d{2}$/;
2275
- if (!datePattern.test(date))
2276
- return false;
2277
- const [year, month, day] = date.split('-').map(Number);
2278
- const dateObj = new Date(year, month - 1, day);
2279
- return dateObj.getFullYear() === year && dateObj.getMonth() === month - 1 && dateObj.getDate() === day;
2280
- }
2281
- // Example usage:
2282
- // console.log(isValidDate('2024-08-31')); // true
2283
- // console.log(isValidDate('2024-02-30')); // false
2284
- /**
2285
- * Validates if a password meets certain strength criteria.
2286
- * @param {string} password The password to validate.
2287
- * @returns {boolean} True if the password is strong, otherwise false.
2288
- */
2289
- function isStrongPassword(password) {
2290
- const minLength = 8;
2291
- const hasUpperCase = /[A-Z]/.test(password);
2292
- const hasLowerCase = /[a-z]/.test(password);
2293
- const hasNumbers = /[0-9]/.test(password);
2294
- const hasSpecialChars = /[!@#$%^&*(),.?":{}|<>]/.test(password);
2295
- return password.length >= minLength && hasUpperCase && hasLowerCase && hasNumbers && hasSpecialChars;
2296
- }
2297
- // Example usage:
2298
- // console.log(isStrongPassword('Strong1@password')); // true
2299
- // console.log(isStrongPassword('weakpass')); // false
2300
- /**
2301
- * Validates a credit card number using the Luhn algorithm.
2302
- * @param {string} cardNumber The credit card number to validate.
2303
- * @returns {boolean} True if the credit card number is valid, otherwise false.
2304
- */
2305
- function isValidCreditCard(cardNumber) {
2306
- const sanitized = cardNumber.replace(/\D/g, '');
2307
- let sum = 0;
2308
- let shouldDouble = false;
2309
- for (let i = sanitized.length - 1; i >= 0; i--) {
2310
- let digit = parseInt(sanitized.charAt(i), 10);
2311
- if (shouldDouble) {
2312
- digit *= 2;
2313
- if (digit > 9)
2314
- digit -= 9;
2315
- }
2316
- sum += digit;
2317
- shouldDouble = !shouldDouble;
2318
- }
2319
- return sum % 10 === 0;
2320
- }
2321
- // Example usage:
2322
- // console.log(isValidCreditCard('4111111111111111')); // true
2323
- // console.log(isValidCreditCard('1234567812345670')); // false
2324
- /**
2325
- * Validates if a string is a valid hex color code.
2326
- * @param {string} color The color code to validate.
2327
- * @returns {boolean} True if the color code is valid, otherwise false.
2328
- */
2329
- function isValidHexColor(color) {
2330
- const hexPattern = /^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})$/;
2331
- return hexPattern.test(color);
2332
- }
2333
- // Example usage:
2334
- // console.log(isValidHexColor('#FFFFFF')); // true
2335
- // console.log(isValidHexColor('#FFF')); // true
2336
- // console.log(isValidHexColor('#12345G')); // false
2337
- /**
2338
- * Validates if a string is a valid time in HH:MM format.
2339
- * @param {string} time The time string to validate.
2340
- * @returns {boolean} True if the time is valid, otherwise false.
2341
- */
2342
- function isValidTime(time) {
2343
- const timePattern = /^([01]\d|2[0-3]):([0-5]\d)$/;
2344
- return timePattern.test(time);
2345
- }
2346
- // Example usage:
2347
- // console.log(isValidTime('14:30')); // true
2348
- // console.log(isValidTime('25:00')); // false
2349
- /**
2350
- * Validates if a string is a valid IPv4 address.
2351
- * @param {string} ip The IP address to validate.
2352
- * @returns {boolean} True if the IP address is valid, otherwise false.
2353
- */
2354
- function isValidIP(ip) {
2355
- const ipPattern = /^(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)$/;
2356
- return ipPattern.test(ip);
2357
- }
2358
- // Example usage:
2359
- // console.log(isValidIP('192.168.1.1')); // true
2360
- // console.log(isValidIP('999.999.999.999')); // false
2361
- /**
2362
- * Validates if a string is a valid U.S. Social Security Number (SSN).
2363
- * @param {string} ssn The SSN to validate.
2364
- * @returns {boolean} True if the SSN is valid, otherwise false.
2365
- */
2366
- function isValidSSN(ssn) {
2367
- const ssnPattern = /^\d{3}-\d{2}-\d{4}$/;
2368
- return ssnPattern.test(ssn);
2369
- }
2370
- // Example usage:
2371
- // console.log(isValidSSN('123-45-6789')); // true
2372
- // console.log(isValidSSN('123-45-678')); // false
2373
- /**
2374
- * Validates if a string is a valid U.S. ZIP code.
2375
- * @param {string} zip The ZIP code to validate.
2376
- * @returns {boolean} True if the ZIP code is valid, otherwise false.
2377
- */
2378
- function isValidZIP(zip) {
2379
- const zipPattern = /^\d{5}(-\d{4})?$/;
2380
- return zipPattern.test(zip);
2381
- }
2382
- // Example usage:
2383
- // console.log(isValidZIP('12345')); // true
2384
- // console.log(isValidZIP('12345-6789')); // true
2385
- // console.log(isValidZIP('1234')); // false
2386
- /**
2387
- * Validates if a string is a valid credit card expiry date in MM/YY format.
2388
- * @param {string} expiryDate The expiry date to validate.
2389
- * @returns {boolean} True if the expiry date is valid, otherwise false.
2390
- */
2391
- function isValidExpiryDate(expiryDate) {
2392
- const expiryPattern = /^(0[1-9]|1[0-2])\/\d{2}$/;
2393
- if (!expiryPattern.test(expiryDate))
2394
- return false;
2395
- const [month, year] = expiryDate.split('/').map(Number);
2396
- const currentYear = new Date().getFullYear() % 100;
2397
- const currentMonth = new Date().getMonth() + 1;
2398
- return (year > currentYear) || (year === currentYear && month >= currentMonth);
2399
- }
2400
- // Example usage:
2401
- // console.log(isValidExpiryDate('08/24')); // true
2402
- // console.log(isValidExpiryDate('12/22')); // false
2403
- /**
2404
- * Validates if a string is a valid 8-character hexadecimal color code (including alpha).
2405
- * @param {string} color The color code to validate.
2406
- * @returns {boolean} True if the color code is valid, otherwise false.
2407
- */
2408
- function isValidHexColorAlpha(color) {
2409
- const hexPattern = /^#([0-9A-Fa-f]{8})$/;
2410
- return hexPattern.test(color);
2411
- }
2412
- // Example usage:
2413
- // console.log(isValidHexColorAlpha('#RRGGBBAA')); // true
2414
- // console.log(isValidHexColorAlpha('#FFFFFF')); // false
2415
- /**
2416
- * Validates if a username meets specific criteria.
2417
- * @param {string} username The username to validate.
2418
- * @returns {boolean} True if the username is valid, otherwise false.
2419
- */
2420
- function isValidUsername(username) {
2421
- const usernamePattern = /^[a-zA-Z0-9_]{3,16}$/; // 3 to 16 characters, letters, numbers, and underscores only
2422
- return usernamePattern.test(username);
2423
- }
2424
- // Example usage:
2425
- // console.log(isValidUsername('user_name123')); // true
2426
- // console.log(isValidUsername('us')); // false
2427
- /**
2428
- * Validates if a string represents a valid age between 0 and 120.
2429
- * @param {string} age The age to validate.
2430
- * @returns {boolean} True if the age is valid, otherwise false.
2431
- */
2432
- function isValidAge(age) {
2433
- const ageNumber = parseInt(age, 10);
2434
- return !isNaN(ageNumber) && ageNumber >= 0 && ageNumber <= 120;
2435
- }
2436
- // Example usage:
2437
- // console.log(isValidAge('25')); // true
2438
- // console.log(isValidAge('121')); // false
2439
- /**
2440
- * Validates if a string is a valid hexadecimal number.
2441
- * @param {string} hex The hexadecimal number to validate.
2442
- * @returns {boolean} True if the number is valid, otherwise false.
2443
- */
2444
- function isValidHexNumber(hex) {
2445
- const hexPattern = /^[0-9A-Fa-f]+$/;
2446
- return hexPattern.test(hex);
2447
- }
2448
- // Example usage:
2449
- // console.log(isValidHexNumber('1A3F')); // true
2450
- // console.log(isValidHexNumber('GHIJ')); // false
2451
-
2452
- exports.APP_LOCAL_CACHE_KEY = APP_LOCAL_CACHE_KEY;
2453
- exports.APP_SESSION_CACHE_KEY = APP_SESSION_CACHE_KEY;
2454
- exports.AxiosService = AxiosService;
2455
- exports.CacheTypeEnum = CacheTypeEnum;
2456
- exports.ContentTypeEnum = ContentTypeEnum;
2457
- exports.ExceptionEnum = ExceptionEnum;
2458
- exports.FileMetaTypes = FileMetaTypes;
2459
- exports.ImageTypes = ImageTypes;
2460
- exports.KeyCodeEnum = KeyCodeEnum;
2461
- exports.LOCALE_KEY = LOCALE_KEY;
2462
- exports.LOCK_INFO_KEY = LOCK_INFO_KEY;
2463
- exports.PROJ_CFG_KEY = PROJ_CFG_KEY;
2464
- exports.ROLES_KEY = ROLES_KEY;
2465
- exports.RestStd = RestStd;
2466
- exports.TOKEN_KEY = TOKEN_KEY;
2467
- exports.USER_INFO_KEY = USER_INFO_KEY;
2468
- exports.addCustomKeyboardShortcut = addCustomKeyboardShortcut;
2469
- exports.addDays = addDays;
2470
- exports.addDoubleClickListener = addDoubleClickListener;
2471
- exports.addKeyListener = addKeyListener;
2472
- exports.ageAtDate = ageAtDate;
2473
- exports.axiosFetch = axiosFetch;
2474
- exports.blobToFormData = blobToFormData;
2475
- exports.bufferToBlob = bufferToBlob;
2476
- exports.calculateAge = calculateAge;
2477
- exports.clickOutside = clickOutside;
2478
- exports.compareObject = compareObject;
2479
- exports.copyToClipboard = copyToClipboard;
2480
- exports.countWords = countWords;
2481
- exports.createFetch = createFetch;
2482
- exports.createKeyMap = createKeyMap;
2483
- exports.customShortcut = customShortcut;
2484
- exports.daysBetween = daysBetween;
2485
- exports.daysToNextBirthday = daysToNextBirthday;
2486
- exports.debounce = debounce;
2487
- exports.debounceAsync = debounceAsync;
2488
- exports.debounceAsyncValidator = debounceAsyncValidator;
2489
- exports.debounceAsyncWithImmediate = debounceAsyncWithImmediate;
2490
- exports.debounceLeading = debounceLeading;
2491
- exports.debounceLeadingTrailing = debounceLeadingTrailing;
2492
- exports.debounceTrailing = debounceTrailing;
2493
- exports.deepClone = deepClone;
2494
- exports.deepEqual = deepEqual;
2495
- exports.deepMerge = deepMerge;
2496
- exports.detectKeyHold = detectKeyHold;
2497
- exports.disableCopy = disableCopy;
2498
- exports.disableF12Key = disableF12Key;
2499
- exports.disableMouseButtons = disableMouseButtons;
2500
- exports.disableRightClick = disableRightClick;
2501
- exports.disableSpecificKeys = disableSpecificKeys;
2502
- exports.downloadBlob = downloadBlob;
2503
- exports.enableMouseButtons = enableMouseButtons;
2504
- exports.enableRightClick = enableRightClick;
2505
- exports.enableSpecificKeys = enableSpecificKeys;
2506
- exports.exportToCSV = exportToCSV;
2507
- exports.exportToExcel = exportToExcel;
2508
- exports.exportToJSON = exportToJSON;
2509
- exports.exportToText = exportToText;
2510
- exports.exportToXML = exportToXML;
2511
- exports.filterObjectByKeys = filterObjectByKeys;
2512
- exports.flattenObject = flattenObject;
2513
- exports.formDataToObject = formDataToObject;
2514
- exports.formatDate = formatDate;
2515
- exports.generateRandomString = generateRandomString;
2516
- exports.getEndOfMonth = getEndOfMonth;
2517
- exports.getObjectDifferences = getObjectDifferences;
2518
- exports.getObjectKeys = getObjectKeys;
2519
- exports.getQueryParam = getQueryParam;
2520
- exports.getStartOfMonth = getStartOfMonth;
2521
- exports.hasNestedProperties = hasNestedProperties;
2522
- exports.isEmptyObject = isEmptyObject;
2523
- exports.isLeapYear = isLeapYear;
2524
- exports.isStrongPassword = isStrongPassword;
2525
- exports.isValidAge = isValidAge;
2526
- exports.isValidCreditCard = isValidCreditCard;
2527
- exports.isValidDate = isValidDate;
2528
- exports.isValidEmail = isValidEmail;
2529
- exports.isValidExpiryDate = isValidExpiryDate;
2530
- exports.isValidHexColor = isValidHexColor;
2531
- exports.isValidHexColorAlpha = isValidHexColorAlpha;
2532
- exports.isValidHexNumber = isValidHexNumber;
2533
- exports.isValidIP = isValidIP;
2534
- exports.isValidPhoneNumber = isValidPhoneNumber;
2535
- exports.isValidSSN = isValidSSN;
2536
- exports.isValidTime = isValidTime;
2537
- exports.isValidURL = isValidURL;
2538
- exports.isValidUsername = isValidUsername;
2539
- exports.isValidZIP = isValidZIP;
2540
- exports.lowerFirst = lowerFirst;
2541
- exports.objectToFormData = objectToFormData;
2542
- exports.objectToFormDataEnhanced = objectToFormDataEnhanced;
2543
- exports.objectToQueryString = objectToQueryString;
2544
- exports.openWindow = openWindow;
2545
- exports.parseDate = parseDate;
2546
- exports.proxyToPlainObject = proxyToPlainObject;
2547
- exports.readFileAsDataURL = readFileAsDataURL;
2548
- exports.readFileAsText = readFileAsText;
2549
- exports.registerKeyboardShortcuts = registerKeyboardShortcuts;
2550
- exports.removeAccent = removeAccent;
2551
- exports.removeClickOutside = removeClickOutside;
2552
- exports.removeCustomKeyboardShortcut = removeCustomKeyboardShortcut;
2553
- exports.removeCustomShortcuts = removeCustomShortcuts;
2554
- exports.removeDoubleClickListener = removeDoubleClickListener;
2555
- exports.removeEmptyProperties = removeEmptyProperties;
2556
- exports.removeKeyListeners = removeKeyListeners;
2557
- exports.replaceAll = replaceAll;
2558
- exports.reverseString = reverseString;
2559
- exports.safeGet = safeGet;
2560
- exports.screenEnum = screenEnum;
2561
- exports.screenMap = screenMap;
2562
- exports.scrollToTop = scrollToTop;
2563
- exports.simulateKeyPress = simulateKeyPress;
2564
- exports.sizeEnum = sizeEnum;
2565
- exports.stopDetectingKeyHold = stopDetectingKeyHold;
2566
- exports.stringToBlob = stringToBlob;
2567
- exports.subtractDays = subtractDays;
2568
- exports.throttle = throttle;
2569
- exports.toCamelCase = toCamelCase;
2570
- exports.toKebabCase = toKebabCase;
2571
- exports.toggleTabNavigation = toggleTabNavigation;
2572
- exports.truncateString = truncateString;
2573
- exports.unregisterKeyboardShortcuts = unregisterKeyboardShortcuts;
2574
- exports.upperFirst = upperFirst;
2575
- exports.useBreakpoint = useBreakpoint;
2576
- exports.useFilter = useFilter;
2577
- exports.usePagination = usePagination;
2578
- exports.useSorter = useSorter;
2579
- exports.useVueQuery = useVueQuery;
2580
- exports.validateAlphanumeric = validateAlphanumeric;
2581
- exports.validateLetters = validateLetters;
2582
- exports.validateNumbers = validateNumbers;