@libs-ui/utils 0.2.306 → 0.2.308-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/communicate-micro.d.ts +1 -1
- package/dangerous-object.d.ts +75 -0
- package/date.d.ts +9 -9
- package/esm2022/base64.mjs +2 -2
- package/esm2022/cache.mjs +17 -14
- package/esm2022/color.mjs +66 -14
- package/esm2022/communicate-micro.mjs +20 -16
- package/esm2022/constants.mjs +1 -1
- package/esm2022/crypto-3rd.mjs +3 -3
- package/esm2022/crypto.mjs +3 -3
- package/esm2022/dangerous-object.mjs +143 -0
- package/esm2022/date.mjs +15 -15
- package/esm2022/dom.mjs +5 -13
- package/esm2022/download.mjs +3 -3
- package/esm2022/file.mjs +22 -11
- package/esm2022/format-number.mjs +9 -6
- package/esm2022/format-text.mjs +13 -15
- package/esm2022/function-check-embed-frame.mjs +1 -1
- package/esm2022/get-smart-axis-scale.mjs +10 -10
- package/esm2022/helpers.mjs +119 -38
- package/esm2022/http-params.mjs +2 -2
- package/esm2022/index.mjs +2 -1
- package/esm2022/inject-token.mjs +2 -2
- package/esm2022/key-cache.mjs +6 -6
- package/esm2022/key-code.mjs +1 -1
- package/esm2022/language.mjs +28 -28
- package/esm2022/pattern.mjs +1 -1
- package/esm2022/random.mjs +2 -2
- package/esm2022/two-way-signal-object.mjs +32 -20
- package/esm2022/uri.mjs +9 -6
- package/esm2022/url-search-params.mjs +13 -11
- package/esm2022/uuid.mjs +2 -2
- package/esm2022/xss-filter.mjs +1 -1
- package/fesm2022/libs-ui-utils.mjs +646 -346
- package/fesm2022/libs-ui-utils.mjs.map +1 -1
- package/file.d.ts +1 -1
- package/format-text.d.ts +1 -1
- package/helpers.d.ts +53 -4
- package/http-params.d.ts +1 -1
- package/index.d.ts +1 -0
- package/inject-token.d.ts +1 -1
- package/package.json +2 -2
- package/uri.d.ts +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import DeviceDetector from 'device-detector-js';
|
|
2
2
|
import Quill from 'quill';
|
|
3
|
-
import { fromEvent, tap, takeUntil, mergeMap, startWith, finalize, lastValueFrom, timer, Subject, filter
|
|
3
|
+
import { fromEvent, tap, takeUntil, mergeMap, startWith, finalize, lastValueFrom, timer, Observable, Subject, filter } from 'rxjs';
|
|
4
4
|
import CryptoES from 'crypto-es';
|
|
5
5
|
import { HttpParams } from '@angular/common/http';
|
|
6
|
-
import {
|
|
6
|
+
import { TemplateRef, ElementRef, isSignal, signal, InjectionToken } from '@angular/core';
|
|
7
7
|
import dayjs from 'dayjs';
|
|
8
8
|
import 'dayjs/locale/en';
|
|
9
9
|
import 'dayjs/locale/vi';
|
|
@@ -90,7 +90,7 @@ const highlightByKeyword = (value, search, ignoreHighlight, classHightLight) =>
|
|
|
90
90
|
if (!classHightLight) {
|
|
91
91
|
classHightLight = 'bg-[#19344a] text-white';
|
|
92
92
|
}
|
|
93
|
-
keysReplace.forEach(key => {
|
|
93
|
+
keysReplace.forEach((key) => {
|
|
94
94
|
const regExp = new RegExp(key, 'gi');
|
|
95
95
|
value = value?.replace(regExp, `<span class="${classHightLight}">$&</span>`);
|
|
96
96
|
});
|
|
@@ -119,7 +119,7 @@ const formatTextCompare = (text, options) => {
|
|
|
119
119
|
if (!text) {
|
|
120
120
|
return text;
|
|
121
121
|
}
|
|
122
|
-
text = text.normalize(
|
|
122
|
+
text = text.normalize('NFC');
|
|
123
123
|
return formatByOptions(text, options);
|
|
124
124
|
};
|
|
125
125
|
const fullNameFormat = (value) => {
|
|
@@ -133,7 +133,10 @@ const capitalize = (text, options) => {
|
|
|
133
133
|
return text;
|
|
134
134
|
}
|
|
135
135
|
text = formatByOptions(text, options);
|
|
136
|
-
return text
|
|
136
|
+
return text
|
|
137
|
+
.split(' ')
|
|
138
|
+
.map((word) => firstLetterToUpperCase(word))
|
|
139
|
+
.join(' ');
|
|
137
140
|
};
|
|
138
141
|
const firstLetterToUpperCase = (text, options) => {
|
|
139
142
|
if (!text) {
|
|
@@ -159,7 +162,7 @@ const formatByOptions = (text, options) => {
|
|
|
159
162
|
text = text.toLowerCase();
|
|
160
163
|
}
|
|
161
164
|
if (options?.removeMultipleSpace) {
|
|
162
|
-
text = text.replace(/\u200B|\u00A0/g,
|
|
165
|
+
text = text.replace(/\u200B|\u00A0/g, '');
|
|
163
166
|
text = text.replace(/\s+/g, ' ');
|
|
164
167
|
}
|
|
165
168
|
if (options?.removeEmoji) {
|
|
@@ -177,12 +180,7 @@ const escapeHtml = (str) => {
|
|
|
177
180
|
if (!str || typeof str !== 'string') {
|
|
178
181
|
return str;
|
|
179
182
|
}
|
|
180
|
-
return str
|
|
181
|
-
.replace(/&/g, "&")
|
|
182
|
-
.replace(/</g, "<")
|
|
183
|
-
.replace(/>/g, ">")
|
|
184
|
-
.replace(/"/g, """)
|
|
185
|
-
.replace(/'/g, "'");
|
|
183
|
+
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
186
184
|
};
|
|
187
185
|
const decodeEscapeHtml = (str) => {
|
|
188
186
|
const htmlTag = document.createElement('textarea');
|
|
@@ -213,9 +211,9 @@ const deleteUnicode = (str) => {
|
|
|
213
211
|
str = str.replace(/Ù|Ú|Ụ|Ủ|Ũ|Ư|Ừ|Ứ|Ự|Ử|Ữ/g, 'U');
|
|
214
212
|
str = str.replace(/Ỳ|Ý|Ỵ|Ỷ|Ỹ/g, 'Y');
|
|
215
213
|
str = str.replace(/Đ/g, 'D');
|
|
216
|
-
str = str.replace(/\u0300|\u0301|\u0303|\u0309|\u0323/g,
|
|
217
|
-
str = str.replace(/\u02C6|\u0306|\u031B/g,
|
|
218
|
-
return str.normalize(
|
|
214
|
+
str = str.replace(/\u0300|\u0301|\u0303|\u0309|\u0323/g, ''); // ̀ ́ ̃ ̉ ̣ huyền, sắc, ngã, hỏi, nặng
|
|
215
|
+
str = str.replace(/\u02C6|\u0306|\u031B/g, ''); // ˆ ̆ ̛ Â, Ê, Ă, Ơ, Ư
|
|
216
|
+
return str.normalize('NFC');
|
|
219
217
|
};
|
|
220
218
|
const removeEmoji = (text) => {
|
|
221
219
|
if (!text || !text.trim()) {
|
|
@@ -290,10 +288,7 @@ const checkViewInScreen = (container, element, elementScroll, maxTopLeft) => {
|
|
|
290
288
|
const limitLeft = leftContainer + scrollLeftContainer + widthContainer;
|
|
291
289
|
const maxTopItem = top + (maxTopLeft?.top || 0);
|
|
292
290
|
const maxLeftItem = left + (maxTopLeft?.left || 0);
|
|
293
|
-
if (topContainer <= maxTopItem &&
|
|
294
|
-
maxTopItem <= limitTop &&
|
|
295
|
-
leftContainer <= maxLeftItem &&
|
|
296
|
-
maxLeftItem <= limitLeft) {
|
|
291
|
+
if (topContainer <= maxTopItem && maxTopItem <= limitTop && leftContainer <= maxLeftItem && maxLeftItem <= limitLeft) {
|
|
297
292
|
return true;
|
|
298
293
|
}
|
|
299
294
|
return false;
|
|
@@ -307,10 +302,7 @@ const checkMouseOverInContainer = (mousePosition, element, rect) => {
|
|
|
307
302
|
const limitLeft = left + width;
|
|
308
303
|
const limitTop = top + height;
|
|
309
304
|
const { clientX, clientY } = mousePosition;
|
|
310
|
-
if (left <= clientX &&
|
|
311
|
-
clientX <= limitLeft &&
|
|
312
|
-
top <= clientY &&
|
|
313
|
-
clientY <= limitTop) {
|
|
305
|
+
if (left <= clientX && clientX <= limitLeft && top <= clientY && clientY <= limitTop) {
|
|
314
306
|
return true;
|
|
315
307
|
}
|
|
316
308
|
return false;
|
|
@@ -348,13 +340,11 @@ const getDragEventByElement = (config) => {
|
|
|
348
340
|
e.stopPropagation();
|
|
349
341
|
config.functionMouseMove?.(e);
|
|
350
342
|
}), takeUntil(mouseup));
|
|
351
|
-
return mouseDown.pipe(mergeMap((e) => config.isStartWithMouseDownEvent
|
|
352
|
-
? mousemove.pipe(startWith(e))
|
|
353
|
-
: mousemove), takeUntil(config.onDestroy), finalize(removeClass));
|
|
343
|
+
return mouseDown.pipe(mergeMap((e) => (config.isStartWithMouseDownEvent ? mousemove.pipe(startWith(e)) : mousemove)), takeUntil(config.onDestroy), finalize(removeClass));
|
|
354
344
|
};
|
|
355
345
|
const getHTMLFromQuill = async (data, options) => {
|
|
356
346
|
const { replaceNewLineTo = '<br>', replaceTagBRTo, replaceTags, replaceBrToDiv } = options || {};
|
|
357
|
-
const delta =
|
|
347
|
+
const delta = typeof data === 'string' ? await getDeltaFromHTML(data) : data;
|
|
358
348
|
if (options?.functionReplaceDelta) {
|
|
359
349
|
options.functionReplaceDelta(delta);
|
|
360
350
|
}
|
|
@@ -498,17 +488,19 @@ class UtilsUrlSearchParams {
|
|
|
498
488
|
return this.instance;
|
|
499
489
|
}
|
|
500
490
|
static toStringParamObject(params) {
|
|
501
|
-
const paramsArr = Object.keys(params).map(key => {
|
|
491
|
+
const paramsArr = Object.keys(params).map((key) => {
|
|
502
492
|
return {
|
|
503
493
|
key,
|
|
504
|
-
value: params[key]
|
|
494
|
+
value: params[key],
|
|
505
495
|
};
|
|
506
496
|
});
|
|
507
497
|
return UtilsUrlSearchParams.ToString(paramsArr);
|
|
508
498
|
}
|
|
509
499
|
static ToString(params) {
|
|
510
500
|
let paramsStr = '';
|
|
511
|
-
params
|
|
501
|
+
params
|
|
502
|
+
.sort((item1, item2) => item1.key.localeCompare(item2.key))
|
|
503
|
+
.forEach((item) => {
|
|
512
504
|
const { key, value } = item;
|
|
513
505
|
paramsStr = `${paramsStr}${paramsStr ? '&' : ''}${key}=${value}`;
|
|
514
506
|
});
|
|
@@ -525,14 +517,14 @@ class UtilsUrlSearchParams {
|
|
|
525
517
|
}
|
|
526
518
|
const params = paramString.replace(/\S+[?]/g, '').split('&');
|
|
527
519
|
if (params) {
|
|
528
|
-
params.forEach(param => {
|
|
520
|
+
params.forEach((param) => {
|
|
529
521
|
if (param.indexOf('=') < 0) {
|
|
530
522
|
return;
|
|
531
523
|
}
|
|
532
524
|
let [key, value] = param.split('=');
|
|
533
525
|
key = key.replace(/[?&]+/g, '');
|
|
534
526
|
value = decodeURIComponent(value.replace(/\+/g, ' '));
|
|
535
|
-
if (!paramsBuild.some(param => param.key === key)) {
|
|
527
|
+
if (!paramsBuild.some((param) => param.key === key)) {
|
|
536
528
|
paramsBuild.push({ key, value });
|
|
537
529
|
}
|
|
538
530
|
});
|
|
@@ -540,7 +532,7 @@ class UtilsUrlSearchParams {
|
|
|
540
532
|
return paramsBuild;
|
|
541
533
|
}
|
|
542
534
|
set(key, value) {
|
|
543
|
-
const paramByKey = this.params.find(param => param.key === key);
|
|
535
|
+
const paramByKey = this.params.find((param) => param.key === key);
|
|
544
536
|
if (!paramByKey) {
|
|
545
537
|
this.params.push({ key, value: decodeURIComponent(value.replace(/\+/g, ' ')) });
|
|
546
538
|
return;
|
|
@@ -548,13 +540,13 @@ class UtilsUrlSearchParams {
|
|
|
548
540
|
paramByKey['value'] = value;
|
|
549
541
|
}
|
|
550
542
|
get(key) {
|
|
551
|
-
return this.params.find(param => param.key === key)?.value;
|
|
543
|
+
return this.params.find((param) => param.key === key)?.value;
|
|
552
544
|
}
|
|
553
545
|
has(key) {
|
|
554
|
-
return this.params.some(param => param.key === key);
|
|
546
|
+
return this.params.some((param) => param.key === key);
|
|
555
547
|
}
|
|
556
548
|
delete(key) {
|
|
557
|
-
const index = this.params.findIndex(param => param.key === key);
|
|
549
|
+
const index = this.params.findIndex((param) => param.key === key);
|
|
558
550
|
if (index >= 0) {
|
|
559
551
|
this.params.splice(index, 1);
|
|
560
552
|
}
|
|
@@ -568,7 +560,7 @@ class UtilsUrlSearchParams {
|
|
|
568
560
|
}
|
|
569
561
|
getParamObject() {
|
|
570
562
|
const params = {};
|
|
571
|
-
this.params.forEach(item => {
|
|
563
|
+
this.params.forEach((item) => {
|
|
572
564
|
params[item.key] = item.value;
|
|
573
565
|
});
|
|
574
566
|
return params;
|
|
@@ -596,7 +588,7 @@ const keyStore$1 = () => {
|
|
|
596
588
|
};
|
|
597
589
|
const encrypt = (plainData) => {
|
|
598
590
|
if (!keyStore$1()) {
|
|
599
|
-
throw Error(
|
|
591
|
+
throw Error('lỗi chưa setup key mã hóa');
|
|
600
592
|
}
|
|
601
593
|
const key = CryptoES.enc.Hex.parse(keyStore$1());
|
|
602
594
|
const iv = CryptoES.enc.Hex.parse(keyStore$1());
|
|
@@ -607,7 +599,7 @@ const encrypt = (plainData) => {
|
|
|
607
599
|
};
|
|
608
600
|
const decrypt = (encryptedData) => {
|
|
609
601
|
if (!keyStore$1()) {
|
|
610
|
-
throw Error(
|
|
602
|
+
throw Error('lỗi chưa setup key mã hóa');
|
|
611
603
|
}
|
|
612
604
|
const key = CryptoES.enc.Hex.parse(keyStore$1());
|
|
613
605
|
const iv = CryptoES.enc.Hex.parse(keyStore$1());
|
|
@@ -638,83 +630,143 @@ const uuid = () => {
|
|
|
638
630
|
};
|
|
639
631
|
|
|
640
632
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
}
|
|
652
|
-
if (instance instanceof UtilsHttpParamsRequest) {
|
|
653
|
-
this.params = instance.getInstance();
|
|
654
|
-
return;
|
|
655
|
-
}
|
|
656
|
-
if (instance instanceof HttpParams) {
|
|
657
|
-
this.params = instance;
|
|
658
|
-
return;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
getInstance() {
|
|
662
|
-
return this.params;
|
|
663
|
-
}
|
|
664
|
-
setInstance(instance) {
|
|
665
|
-
if (instance instanceof UtilsHttpParamsRequest) {
|
|
666
|
-
this.params = instance.getInstance();
|
|
667
|
-
return;
|
|
668
|
-
}
|
|
669
|
-
if (instance instanceof HttpParams) {
|
|
670
|
-
this.params = instance;
|
|
671
|
-
return;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
set(param, value) {
|
|
675
|
-
this.params = this.params.set(param, value);
|
|
676
|
-
return this;
|
|
633
|
+
/**
|
|
634
|
+
* Danh sách các constructor name nguy hiểm
|
|
635
|
+
*/
|
|
636
|
+
const DANGEROUS_CONSTRUCTOR_NAMES = ['Window', 'Document', 'HTMLDocument', 'HTMLElement', 'Element', 'Node', 'Location', 'Navigator', 'Screen', 'History', 'Storage', 'Console', 'Performance'];
|
|
637
|
+
/**
|
|
638
|
+
* Kiểm tra xem đối tượng có phải là browser global object không
|
|
639
|
+
*/
|
|
640
|
+
const isBrowserGlobalObject = (obj) => {
|
|
641
|
+
if (obj === null || typeof obj !== 'object') {
|
|
642
|
+
return false;
|
|
677
643
|
}
|
|
678
|
-
|
|
679
|
-
|
|
644
|
+
return obj instanceof Window || obj instanceof Document || obj === window || obj === document || obj === globalThis;
|
|
645
|
+
};
|
|
646
|
+
/**
|
|
647
|
+
* Kiểm tra xem đối tượng có phải là DOM object không
|
|
648
|
+
*/
|
|
649
|
+
const isDOMObject = (obj) => {
|
|
650
|
+
if (obj === null || typeof obj !== 'object') {
|
|
651
|
+
return false;
|
|
680
652
|
}
|
|
681
|
-
|
|
682
|
-
|
|
653
|
+
return obj instanceof HTMLElement || obj instanceof Node || obj instanceof Element;
|
|
654
|
+
};
|
|
655
|
+
/**
|
|
656
|
+
* Kiểm tra xem đối tượng có phải là browser API object không
|
|
657
|
+
*/
|
|
658
|
+
const isBrowserAPIObject = (obj) => {
|
|
659
|
+
if (obj === null || typeof obj !== 'object' || typeof window === 'undefined') {
|
|
660
|
+
return false;
|
|
683
661
|
}
|
|
684
|
-
|
|
685
|
-
|
|
662
|
+
return obj === window.location || obj === window.navigator || obj === window.screen || obj === window.history || obj === window.localStorage || obj === window.sessionStorage || obj === window.console || obj === window.performance;
|
|
663
|
+
};
|
|
664
|
+
/**
|
|
665
|
+
* Kiểm tra constructor name có nằm trong danh sách nguy hiểm không
|
|
666
|
+
*/
|
|
667
|
+
const hasDangerousConstructorName = (obj) => {
|
|
668
|
+
if (obj === null || typeof obj !== 'object') {
|
|
669
|
+
return false;
|
|
686
670
|
}
|
|
687
|
-
|
|
688
|
-
|
|
671
|
+
const constructorName = obj.constructor?.name;
|
|
672
|
+
return constructorName && DANGEROUS_CONSTRUCTOR_NAMES.includes(constructorName);
|
|
673
|
+
};
|
|
674
|
+
/**
|
|
675
|
+
* Kiểm tra xem đối tượng có phải là DOM object hoặc browser object nguy hiểm không
|
|
676
|
+
* Những đối tượng này có thể gây ra circular reference và maximum call stack
|
|
677
|
+
*/
|
|
678
|
+
const isDangerousObject = (obj) => {
|
|
679
|
+
if (obj === null || typeof obj !== 'object') {
|
|
680
|
+
return false;
|
|
689
681
|
}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
682
|
+
return isBrowserGlobalObject(obj) || isDOMObject(obj) || isBrowserAPIObject(obj) || hasDangerousConstructorName(obj);
|
|
683
|
+
};
|
|
684
|
+
/**
|
|
685
|
+
* Kiểm tra đối tượng có phải là Angular/Framework object không
|
|
686
|
+
*/
|
|
687
|
+
const isFrameworkObject = (obj) => {
|
|
688
|
+
if (obj === null || typeof obj !== 'object') {
|
|
689
|
+
return false;
|
|
693
690
|
}
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
691
|
+
return obj instanceof TemplateRef || obj instanceof ElementRef;
|
|
692
|
+
};
|
|
693
|
+
/**
|
|
694
|
+
* Kiểm tra đối tượng có phải là File/Blob object không
|
|
695
|
+
*/
|
|
696
|
+
const isFileObject = (obj) => {
|
|
697
|
+
if (obj === null || typeof obj !== 'object') {
|
|
698
|
+
return false;
|
|
697
699
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
700
|
+
return obj instanceof File || obj instanceof Blob || Object.prototype.toString.call(obj) === '[object File]';
|
|
701
|
+
};
|
|
702
|
+
/**
|
|
703
|
+
* Kiểm tra đối tượng có phải là Built-in object không
|
|
704
|
+
*/
|
|
705
|
+
const isBuiltInObject = (obj) => {
|
|
706
|
+
if (obj === null || typeof obj !== 'object') {
|
|
707
|
+
return false;
|
|
701
708
|
}
|
|
702
|
-
|
|
703
|
-
|
|
709
|
+
return obj instanceof Date || obj instanceof RegExp || obj instanceof HttpParams;
|
|
710
|
+
};
|
|
711
|
+
/**
|
|
712
|
+
* Kiểm tra đối tượng có phải là Async object không
|
|
713
|
+
*/
|
|
714
|
+
const isAsyncObject = (obj) => {
|
|
715
|
+
if (obj === null || typeof obj !== 'object') {
|
|
716
|
+
return false;
|
|
704
717
|
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
+
return obj instanceof Promise || obj instanceof Observable;
|
|
719
|
+
};
|
|
720
|
+
/**
|
|
721
|
+
* Kiểm tra đối tượng có phải là Special object cần bỏ qua không
|
|
722
|
+
* Bao gồm: Framework objects, File objects, Built-in objects, Async objects
|
|
723
|
+
*/
|
|
724
|
+
const isSpecialObject = (obj) => {
|
|
725
|
+
return isFrameworkObject(obj) || isFileObject(obj) || isBuiltInObject(obj) || isAsyncObject(obj);
|
|
726
|
+
};
|
|
727
|
+
/**
|
|
728
|
+
* Kiểm tra đối tượng có phải là dayjs object không
|
|
729
|
+
*/
|
|
730
|
+
const isDayjsObject = (obj) => {
|
|
731
|
+
return dayjs.isDayjs(obj);
|
|
732
|
+
};
|
|
733
|
+
/**
|
|
734
|
+
* Kiểm tra đối tượng có phải là object cần bỏ qua trong quá trình convert không
|
|
735
|
+
*/
|
|
736
|
+
const isSkippableObject = (obj) => {
|
|
737
|
+
return isDangerousObject(obj) || isSpecialObject(obj);
|
|
738
|
+
};
|
|
739
|
+
/**
|
|
740
|
+
* Kiểm tra đối tượng có phải là Map object không
|
|
741
|
+
*/
|
|
742
|
+
const isMapObject = (obj) => {
|
|
743
|
+
return obj instanceof Map;
|
|
744
|
+
};
|
|
745
|
+
/**
|
|
746
|
+
* Kiểm tra đối tượng có phải là Set object không
|
|
747
|
+
*/
|
|
748
|
+
const isSetObject = (obj) => {
|
|
749
|
+
return obj instanceof Set;
|
|
750
|
+
};
|
|
751
|
+
/**
|
|
752
|
+
* Kiểm tra đối tượng có phải là Array object không
|
|
753
|
+
*/
|
|
754
|
+
const isArrayObject = (obj) => {
|
|
755
|
+
return Array.isArray(obj);
|
|
756
|
+
};
|
|
757
|
+
/**
|
|
758
|
+
* Kiểm tra đối tượng có phải là object cần trả về nguyên trạng không
|
|
759
|
+
* Bao gồm: dangerous objects, special objects, dayjs objects
|
|
760
|
+
*/
|
|
761
|
+
const isReturnAsIsObject = (obj) => {
|
|
762
|
+
return isSkippableObject(obj) || isDayjsObject(obj);
|
|
763
|
+
};
|
|
764
|
+
/**
|
|
765
|
+
* Kiểm tra xem đối tượng có an toàn để clone/convert không
|
|
766
|
+
*/
|
|
767
|
+
const isSafeToProcess = (obj) => {
|
|
768
|
+
return !isDangerousObject(obj);
|
|
769
|
+
};
|
|
718
770
|
|
|
719
771
|
let key = '12~@#loqwsxacva(3rdhaq12';
|
|
720
772
|
/**
|
|
@@ -732,7 +784,7 @@ const keyStore = () => {
|
|
|
732
784
|
};
|
|
733
785
|
const encrypt3rd = (plainData) => {
|
|
734
786
|
if (!keyStore()) {
|
|
735
|
-
throw Error(
|
|
787
|
+
throw Error('lỗi chưa setup key mã hóa');
|
|
736
788
|
}
|
|
737
789
|
const key = CryptoES.enc.Hex.parse(keyStore());
|
|
738
790
|
const iv = CryptoES.enc.Hex.parse(keyStore());
|
|
@@ -743,7 +795,7 @@ const encrypt3rd = (plainData) => {
|
|
|
743
795
|
};
|
|
744
796
|
const decrypt3rd = (encryptedData) => {
|
|
745
797
|
if (!keyStore()) {
|
|
746
|
-
throw Error(
|
|
798
|
+
throw Error('lỗi chưa setup key mã hóa');
|
|
747
799
|
}
|
|
748
800
|
const key = CryptoES.enc.Hex.parse(keyStore());
|
|
749
801
|
const iv = CryptoES.enc.Hex.parse(keyStore());
|
|
@@ -790,7 +842,9 @@ class UtilsCommunicateMicro {
|
|
|
790
842
|
if (!this.subs.get(COMMUNICATE_MICRO_KEY_GET_ALL_MESSAGE)) {
|
|
791
843
|
this.subs.set(COMMUNICATE_MICRO_KEY_GET_ALL_MESSAGE, UtilsCommunicateMicro.allMessageSub);
|
|
792
844
|
}
|
|
793
|
-
fromEvent(currentWindow, 'message')
|
|
845
|
+
fromEvent(currentWindow, 'message')
|
|
846
|
+
.pipe(takeUntil(onDestroy))
|
|
847
|
+
.subscribe((e) => {
|
|
794
848
|
const event = { data: { ...e.data } };
|
|
795
849
|
const data = event.data;
|
|
796
850
|
const type = data.type;
|
|
@@ -818,7 +872,9 @@ class UtilsCommunicateMicro {
|
|
|
818
872
|
this.allMessageSub.next(event);
|
|
819
873
|
}
|
|
820
874
|
});
|
|
821
|
-
UtilsCommunicateMicro.GetMessage(UtilsCache.typeKeyClearLocalStorage)
|
|
875
|
+
UtilsCommunicateMicro.GetMessage(UtilsCache.typeKeyClearLocalStorage)
|
|
876
|
+
.pipe(filter((e) => e.data.response !== UtilsCache.idService), takeUntil(onDestroy))
|
|
877
|
+
.subscribe(() => {
|
|
822
878
|
console.log('clear all cache by event');
|
|
823
879
|
UtilsCache.ClearAll();
|
|
824
880
|
});
|
|
@@ -827,10 +883,10 @@ class UtilsCommunicateMicro {
|
|
|
827
883
|
data = this.convertData(data);
|
|
828
884
|
try {
|
|
829
885
|
if (isEmbedFrame()) {
|
|
830
|
-
window?.parent?.postMessage(data,
|
|
886
|
+
window?.parent?.postMessage(data, '*');
|
|
831
887
|
return;
|
|
832
888
|
}
|
|
833
|
-
window?.top?.postMessage(data,
|
|
889
|
+
window?.top?.postMessage(data, '*');
|
|
834
890
|
}
|
|
835
891
|
catch (error) {
|
|
836
892
|
console.log(error);
|
|
@@ -838,8 +894,8 @@ class UtilsCommunicateMicro {
|
|
|
838
894
|
}
|
|
839
895
|
static PostMessageToChildren(data) {
|
|
840
896
|
data = this.convertData(data);
|
|
841
|
-
const iframes = document.querySelectorAll(
|
|
842
|
-
Array.from(iframes).forEach(iframe => {
|
|
897
|
+
const iframes = document.querySelectorAll('iframe');
|
|
898
|
+
Array.from(iframes).forEach((iframe) => {
|
|
843
899
|
iframe?.contentWindow?.postMessage(data, '*');
|
|
844
900
|
});
|
|
845
901
|
}
|
|
@@ -877,7 +933,7 @@ class UtilsCommunicateMicro {
|
|
|
877
933
|
}
|
|
878
934
|
static GetMessage(messageType) {
|
|
879
935
|
if (!this.initdEvent) {
|
|
880
|
-
throw Error(
|
|
936
|
+
throw Error('chưa khơi tạo hàm lắng nghe sự kiện, gọi UtilsCommunicateMicro.initEvent(window) tại root component');
|
|
881
937
|
}
|
|
882
938
|
if (typeof messageType === 'string') {
|
|
883
939
|
let sub = this.subs.get(messageType);
|
|
@@ -905,8 +961,8 @@ class UtilsCommunicateMicro {
|
|
|
905
961
|
return sub;
|
|
906
962
|
}
|
|
907
963
|
static initSubject(subRoot, messageType) {
|
|
908
|
-
messageType.forEach(key => {
|
|
909
|
-
this.GetMessage(key).subscribe(e => {
|
|
964
|
+
messageType.forEach((key) => {
|
|
965
|
+
this.GetMessage(key).subscribe((e) => {
|
|
910
966
|
subRoot.next(e);
|
|
911
967
|
});
|
|
912
968
|
});
|
|
@@ -914,33 +970,33 @@ class UtilsCommunicateMicro {
|
|
|
914
970
|
}
|
|
915
971
|
|
|
916
972
|
class UtilsLanguageConstants {
|
|
917
|
-
static VI =
|
|
918
|
-
static EN =
|
|
919
|
-
static FR =
|
|
920
|
-
static DE =
|
|
921
|
-
static ES =
|
|
922
|
-
static ZH =
|
|
923
|
-
static ZH_TW =
|
|
924
|
-
static JA =
|
|
925
|
-
static KO =
|
|
926
|
-
static RU =
|
|
927
|
-
static IT =
|
|
928
|
-
static PT =
|
|
929
|
-
static TH =
|
|
930
|
-
static ID =
|
|
931
|
-
static MS =
|
|
932
|
-
static AR =
|
|
933
|
-
static HI =
|
|
934
|
-
static BN =
|
|
935
|
-
static TR =
|
|
936
|
-
static NL =
|
|
937
|
-
static KM =
|
|
938
|
-
static LO =
|
|
939
|
-
static MY =
|
|
940
|
-
static TL =
|
|
941
|
-
static CEB =
|
|
942
|
-
static JV =
|
|
943
|
-
static SU =
|
|
973
|
+
static VI = 'vi'; // Tiếng Việt
|
|
974
|
+
static EN = 'en'; // Tiếng Anh
|
|
975
|
+
static FR = 'fr'; // Tiếng Pháp
|
|
976
|
+
static DE = 'de'; // Tiếng Đức
|
|
977
|
+
static ES = 'es'; // Tiếng Tây Ban Nha
|
|
978
|
+
static ZH = 'zh'; // Tiếng Trung (Giản thể)
|
|
979
|
+
static ZH_TW = 'zh-TW'; // Tiếng Trung (Phồn thể)
|
|
980
|
+
static JA = 'ja'; // Tiếng Nhật
|
|
981
|
+
static KO = 'ko'; // Tiếng Hàn
|
|
982
|
+
static RU = 'ru'; // Tiếng Nga
|
|
983
|
+
static IT = 'it'; // Tiếng Ý
|
|
984
|
+
static PT = 'pt'; // Tiếng Bồ Đào Nha
|
|
985
|
+
static TH = 'th'; // Tiếng Thái
|
|
986
|
+
static ID = 'id'; // Tiếng Indonesia
|
|
987
|
+
static MS = 'ms'; // Tiếng Malaysia
|
|
988
|
+
static AR = 'ar'; // Tiếng Ả Rập
|
|
989
|
+
static HI = 'hi'; // Tiếng Hindi
|
|
990
|
+
static BN = 'bn'; // Tiếng Bengal
|
|
991
|
+
static TR = 'tr'; // Tiếng Thổ Nhĩ Kỳ
|
|
992
|
+
static NL = 'nl'; // Tiếng Hà Lan
|
|
993
|
+
static KM = 'km'; // Tiếng Khmer (Campuchia)
|
|
994
|
+
static LO = 'lo'; // Tiếng Lào
|
|
995
|
+
static MY = 'my'; // Tiếng Miến Điện (Myanmar)
|
|
996
|
+
static TL = 'tl'; // Tiếng Tagalog (Philippines)
|
|
997
|
+
static CEB = 'ceb'; // Tiếng Cebuano (Philippines)
|
|
998
|
+
static JV = 'jv'; // Tiếng Java (Indonesia)
|
|
999
|
+
static SU = 'su'; // Tiếng Sundanese (Indonesia)
|
|
944
1000
|
// Ngôn ngữ mặc định
|
|
945
1001
|
static defaultLang = UtilsLanguageConstants.VI;
|
|
946
1002
|
// Danh sách các ngôn ngữ được hỗ trợ
|
|
@@ -1026,7 +1082,7 @@ class UtilsCache {
|
|
|
1026
1082
|
return this.Get(this.languageKeyCache, UtilsLanguageConstants.defaultLang);
|
|
1027
1083
|
}
|
|
1028
1084
|
static openDB() {
|
|
1029
|
-
return new Promise(resolve => {
|
|
1085
|
+
return new Promise((resolve) => {
|
|
1030
1086
|
const request = indexedDB.open(this.dbName, this.dbVersion);
|
|
1031
1087
|
request.onupgradeneeded = (event) => {
|
|
1032
1088
|
const db = event.target.result;
|
|
@@ -1098,7 +1154,7 @@ class UtilsCache {
|
|
|
1098
1154
|
clear: () => {
|
|
1099
1155
|
this.storage = {};
|
|
1100
1156
|
localStorage.clear();
|
|
1101
|
-
}
|
|
1157
|
+
},
|
|
1102
1158
|
};
|
|
1103
1159
|
}
|
|
1104
1160
|
static getLocalStorageFake() {
|
|
@@ -1117,7 +1173,7 @@ class UtilsCache {
|
|
|
1117
1173
|
},
|
|
1118
1174
|
clear: () => {
|
|
1119
1175
|
this.storage = {};
|
|
1120
|
-
}
|
|
1176
|
+
},
|
|
1121
1177
|
};
|
|
1122
1178
|
}
|
|
1123
1179
|
static async GetAsync(key, default_value, isKeyMD5 = false) {
|
|
@@ -1136,7 +1192,7 @@ class UtilsCache {
|
|
|
1136
1192
|
if (data.expire === this.CACHE_EXPIRE_NONE) {
|
|
1137
1193
|
return resolve(data.json);
|
|
1138
1194
|
}
|
|
1139
|
-
const currentMillisecond =
|
|
1195
|
+
const currentMillisecond = new Date().valueOf() / 1000;
|
|
1140
1196
|
if (data.expire < currentMillisecond) {
|
|
1141
1197
|
return resolve(default_value);
|
|
1142
1198
|
}
|
|
@@ -1149,6 +1205,7 @@ class UtilsCache {
|
|
|
1149
1205
|
});
|
|
1150
1206
|
}
|
|
1151
1207
|
static Get(key, default_value) {
|
|
1208
|
+
// support cho những file không thể inject UtilsCache
|
|
1152
1209
|
if (!key) {
|
|
1153
1210
|
return this.GetDefaultValueBySpecificKey(key, default_value);
|
|
1154
1211
|
}
|
|
@@ -1161,7 +1218,7 @@ class UtilsCache {
|
|
|
1161
1218
|
if (data.expire === this.CACHE_EXPIRE_NONE) {
|
|
1162
1219
|
return data.value ?? default_value;
|
|
1163
1220
|
}
|
|
1164
|
-
const currentMillisecond =
|
|
1221
|
+
const currentMillisecond = new Date().valueOf() / 1000;
|
|
1165
1222
|
if (data.expire < currentMillisecond) {
|
|
1166
1223
|
return this.GetDefaultValueBySpecificKey(key, default_value);
|
|
1167
1224
|
}
|
|
@@ -1176,11 +1233,12 @@ class UtilsCache {
|
|
|
1176
1233
|
return default_value;
|
|
1177
1234
|
}
|
|
1178
1235
|
static async SetAsync(key, value, expireTimeBySecond = this.CACHE_EXPIRE_TIME_DEFAULT, isKeyMD5 = false) {
|
|
1236
|
+
// support inject UtilsCache
|
|
1179
1237
|
return new Promise(async (resolve) => {
|
|
1180
1238
|
const objectStore = await this.getObjectStore();
|
|
1181
1239
|
key = isKeyMD5 ? key : md5(key);
|
|
1182
1240
|
try {
|
|
1183
|
-
const currentMillisecond = expireTimeBySecond === this.CACHE_EXPIRE_NONE ? this.CACHE_EXPIRE_NONE :
|
|
1241
|
+
const currentMillisecond = expireTimeBySecond === this.CACHE_EXPIRE_NONE ? this.CACHE_EXPIRE_NONE : new Date().valueOf() / 1000 + expireTimeBySecond;
|
|
1184
1242
|
const data = {
|
|
1185
1243
|
value: encrypt(JSON.stringify({ json: value, expire: currentMillisecond })),
|
|
1186
1244
|
};
|
|
@@ -1206,10 +1264,11 @@ class UtilsCache {
|
|
|
1206
1264
|
});
|
|
1207
1265
|
}
|
|
1208
1266
|
static Set(key, value, expireTimeBySecond = this.CACHE_EXPIRE_TIME_DEFAULT) {
|
|
1209
|
-
|
|
1267
|
+
// support cho những file không inject UtilsCache
|
|
1268
|
+
const currentMillisecond = expireTimeBySecond === this.CACHE_EXPIRE_NONE ? this.CACHE_EXPIRE_NONE : new Date().valueOf() / 1000 + expireTimeBySecond;
|
|
1210
1269
|
const data = {
|
|
1211
1270
|
value: value,
|
|
1212
|
-
expire: currentMillisecond
|
|
1271
|
+
expire: currentMillisecond,
|
|
1213
1272
|
};
|
|
1214
1273
|
try {
|
|
1215
1274
|
this.LocalStorage.setItem(key, encrypt(JSON.stringify(data)));
|
|
@@ -1264,13 +1323,13 @@ class UtilsCache {
|
|
|
1264
1323
|
const data = {
|
|
1265
1324
|
type: this.typeKeyClearLocalStorage,
|
|
1266
1325
|
response: {
|
|
1267
|
-
idEvent: this.idService
|
|
1268
|
-
}
|
|
1326
|
+
idEvent: this.idService,
|
|
1327
|
+
},
|
|
1269
1328
|
};
|
|
1270
1329
|
UtilsCommunicateMicro.PostMessageToParent(data);
|
|
1271
1330
|
}
|
|
1272
1331
|
const keys = [...this.listKeyKeepWhenClearALll];
|
|
1273
|
-
Object.keys(this.LocalStorage).forEach(key => {
|
|
1332
|
+
Object.keys(this.LocalStorage).forEach((key) => {
|
|
1274
1333
|
if (key.includes('kc-callback-')) {
|
|
1275
1334
|
keys.push(key);
|
|
1276
1335
|
}
|
|
@@ -1316,7 +1375,7 @@ class UtilsCache {
|
|
|
1316
1375
|
if (!Array.isArray(data)) {
|
|
1317
1376
|
return resolve({});
|
|
1318
1377
|
}
|
|
1319
|
-
data.forEach(obj => {
|
|
1378
|
+
data.forEach((obj) => {
|
|
1320
1379
|
if (obj[this.itemIndexByKey].startsWith(keyCacheStartWith)) {
|
|
1321
1380
|
this.ClearAsync(obj[this.itemIndexByKey], true);
|
|
1322
1381
|
}
|
|
@@ -1334,7 +1393,7 @@ class UtilsCache {
|
|
|
1334
1393
|
if (!keys || !keys.length) {
|
|
1335
1394
|
return;
|
|
1336
1395
|
}
|
|
1337
|
-
keys.forEach(key => {
|
|
1396
|
+
keys.forEach((key) => {
|
|
1338
1397
|
if (key.startsWith(keyCache)) {
|
|
1339
1398
|
this.Clear(key);
|
|
1340
1399
|
}
|
|
@@ -1365,7 +1424,7 @@ dayjs.extend(updateLocale);
|
|
|
1365
1424
|
dayjs.extend(utc);
|
|
1366
1425
|
dayjs.extend(timezone);
|
|
1367
1426
|
dayjs.extend(customParseFormat);
|
|
1368
|
-
let timeZoneSetup =
|
|
1427
|
+
let timeZoneSetup = 'Asia/Ho_Chi_Minh';
|
|
1369
1428
|
const setDefaultTimeZone = (localeZone = timeZoneSetup) => {
|
|
1370
1429
|
timeZoneSetup = localeZone;
|
|
1371
1430
|
dayjs.tz.setDefault(localeZone);
|
|
@@ -1375,13 +1434,13 @@ const updateFunctionFormatDate = (functionCustom) => {
|
|
|
1375
1434
|
functionFormatDate = functionCustom;
|
|
1376
1435
|
};
|
|
1377
1436
|
/**
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
*/
|
|
1437
|
+
* @description Lấy đối tượng dayjs theo config
|
|
1438
|
+
* @param config nếu không có config sẽ trả về đối tượng dayjs là thời gian hiện tại
|
|
1439
|
+
* @param config.date thời gian cần lấy
|
|
1440
|
+
* @param config.returnDayjsIfConfigDateNotExist true nếu muốn trả về đối tượng dayjs nếu config.date không có
|
|
1441
|
+
* @param config.utc true nếu muốn lấy thời gian UTC
|
|
1442
|
+
* @param config.formatOfDate định dạng thời gian đang được truyền vào
|
|
1443
|
+
*/
|
|
1385
1444
|
const getDayjs = (config) => {
|
|
1386
1445
|
if (!config) {
|
|
1387
1446
|
return dayjs().tz();
|
|
@@ -1474,7 +1533,7 @@ const formatDate = (date, formatOutput = 'YYYY/MM/DD HH:mm', lang, formatInput)
|
|
|
1474
1533
|
date = getDayjs({ date, formatOfDate: formatInput }).locale(lang);
|
|
1475
1534
|
if (lang === 'vi') {
|
|
1476
1535
|
dayjs.updateLocale('vi', {
|
|
1477
|
-
monthsShort: 'Thg 1_Thg 2_Thg 3_Thg 4_Thg 5_Thg 6_Thg 7_Thg 8_Thg 9_Thg 10_Thg 11_Thg 12'.split('_')
|
|
1536
|
+
monthsShort: 'Thg 1_Thg 2_Thg 3_Thg 4_Thg 5_Thg 6_Thg 7_Thg 8_Thg 9_Thg 10_Thg 11_Thg 12'.split('_'),
|
|
1478
1537
|
});
|
|
1479
1538
|
}
|
|
1480
1539
|
return date.format(getFormatData(getTypeByFormat(formatOutput), lang)) || '';
|
|
@@ -1539,6 +1598,207 @@ const getFormatData = (type, lang) => {
|
|
|
1539
1598
|
}
|
|
1540
1599
|
};
|
|
1541
1600
|
|
|
1601
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1602
|
+
const UtilsHttpParamsRequestInstance = (options, instance) => {
|
|
1603
|
+
return new UtilsHttpParamsRequest(options, instance);
|
|
1604
|
+
};
|
|
1605
|
+
class UtilsHttpParamsRequest extends HttpParams {
|
|
1606
|
+
params = new HttpParams();
|
|
1607
|
+
constructor(options, instance) {
|
|
1608
|
+
super(options);
|
|
1609
|
+
if (!instance) {
|
|
1610
|
+
this.params = new HttpParams(options);
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
if (instance instanceof UtilsHttpParamsRequest) {
|
|
1614
|
+
this.params = instance.getInstance();
|
|
1615
|
+
return;
|
|
1616
|
+
}
|
|
1617
|
+
if (instance instanceof HttpParams) {
|
|
1618
|
+
this.params = instance;
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
getInstance() {
|
|
1623
|
+
return this.params;
|
|
1624
|
+
}
|
|
1625
|
+
setInstance(instance) {
|
|
1626
|
+
if (instance instanceof UtilsHttpParamsRequest) {
|
|
1627
|
+
this.params = instance.getInstance();
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
if (instance instanceof HttpParams) {
|
|
1631
|
+
this.params = instance;
|
|
1632
|
+
return;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
set(param, value) {
|
|
1636
|
+
this.params = this.params.set(param, value);
|
|
1637
|
+
return this;
|
|
1638
|
+
}
|
|
1639
|
+
has(param) {
|
|
1640
|
+
return this.params.has(param);
|
|
1641
|
+
}
|
|
1642
|
+
get(param) {
|
|
1643
|
+
return this.params.get(param);
|
|
1644
|
+
}
|
|
1645
|
+
getAll(param) {
|
|
1646
|
+
return this.params.getAll(param);
|
|
1647
|
+
}
|
|
1648
|
+
keys() {
|
|
1649
|
+
return this.params.keys();
|
|
1650
|
+
}
|
|
1651
|
+
append(param, value) {
|
|
1652
|
+
this.params = this.params.append(param, value);
|
|
1653
|
+
return this;
|
|
1654
|
+
}
|
|
1655
|
+
appendAll(params) {
|
|
1656
|
+
this.params = this.params.appendAll(params);
|
|
1657
|
+
return this;
|
|
1658
|
+
}
|
|
1659
|
+
delete(param, value) {
|
|
1660
|
+
this.params = this.params.delete(param, value);
|
|
1661
|
+
return this;
|
|
1662
|
+
}
|
|
1663
|
+
toString() {
|
|
1664
|
+
return this.params.toString();
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
// Demo su dung GET_PATH_VARIABLE
|
|
1668
|
+
// interface Person {
|
|
1669
|
+
// name: string;
|
|
1670
|
+
// age: number;
|
|
1671
|
+
// location: string;
|
|
1672
|
+
// }
|
|
1673
|
+
// type c = GET_PATH_VARIABLE<Person, unknown>;
|
|
1674
|
+
// const a: c = {
|
|
1675
|
+
// "pathVariable-age": 1,
|
|
1676
|
+
// "pathVariable-location": '12',
|
|
1677
|
+
// "pathVariable-name": '124',
|
|
1678
|
+
// };
|
|
1679
|
+
|
|
1680
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1681
|
+
/**
|
|
1682
|
+
* Chuyển đổi một đối tượng hoặc giá trị thành signal
|
|
1683
|
+
* @param data Dữ liệu cần chuyển đổi thành signal
|
|
1684
|
+
* @param cloneDeepIfNotSignal Có thực hiện sao chép sâu dữ liệu trước khi chuyển đổi hay không nếu data không phải signal. Mặc định là true.
|
|
1685
|
+
* Đặt false nếu muốn giữ nguyên tham chiếu đến dữ liệu gốc.
|
|
1686
|
+
* Nếu muốn sao chép sâu đối tượng signal thì đặt cloneDeepIfNotSignal là true và acceptConvertObjectInnerWritableSignal là true.
|
|
1687
|
+
* @param isSignalPrimitiveType Có chuyển đổi các giá trị nguyên thủy (string, number, boolean) thành signal hay không. Mặc định là false.
|
|
1688
|
+
* Đặt true nếu muốn bọc các giá trị nguyên thủy trong signal.
|
|
1689
|
+
* @param acceptConvertObjectInnerWritableSignal Có tiếp tục tìm kiếm và chuyển đổi các đối tượng bên trong signal hay không. Mặc định là false.
|
|
1690
|
+
* Đặt true nếu muốn tìm và chuyển đổi các đối tượng bên trong signal hoặc chính nó thành signal mới.
|
|
1691
|
+
* @returns Dữ liệu đã được chuyển đổi theo kiểu T
|
|
1692
|
+
*/
|
|
1693
|
+
const convertObjectToSignal = (data, cloneDeepIfNotSignal = true, isSignalPrimitiveType = false, acceptConvertObjectInnerWritableSignal = false, seen = new WeakMap()) => {
|
|
1694
|
+
if ((data === null || typeof data !== 'object') && !isSignal(data)) {
|
|
1695
|
+
return (isSignalPrimitiveType ? signal(data) : data);
|
|
1696
|
+
}
|
|
1697
|
+
if (seen.has(data)) {
|
|
1698
|
+
return seen.get(data);
|
|
1699
|
+
}
|
|
1700
|
+
if (isSignal(data)) {
|
|
1701
|
+
if (!acceptConvertObjectInnerWritableSignal) {
|
|
1702
|
+
return data;
|
|
1703
|
+
}
|
|
1704
|
+
seen.set(data, convertObjectToSignal(data(), cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal, seen));
|
|
1705
|
+
return seen.get(data);
|
|
1706
|
+
}
|
|
1707
|
+
if (isArrayObject(data)) {
|
|
1708
|
+
seen.set(data, signal(data.map((item) => convertObjectToSignal(item, cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal, seen))));
|
|
1709
|
+
return seen.get(data);
|
|
1710
|
+
}
|
|
1711
|
+
if (isMapObject(data)) {
|
|
1712
|
+
const mapCopy = new Map();
|
|
1713
|
+
Array.from(data.keys()).forEach((key) => {
|
|
1714
|
+
mapCopy.set(key, convertObjectToSignal(data.get(key), cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal));
|
|
1715
|
+
});
|
|
1716
|
+
seen.set(data, signal(mapCopy));
|
|
1717
|
+
return seen.get(data);
|
|
1718
|
+
}
|
|
1719
|
+
// Bỏ qua các đối tượng async
|
|
1720
|
+
if (isAsyncObject(data)) {
|
|
1721
|
+
return data;
|
|
1722
|
+
}
|
|
1723
|
+
data = signal(cloneDeepIfNotSignal ? { ...data } : data);
|
|
1724
|
+
seen.set(data, data);
|
|
1725
|
+
for (const key in data()) {
|
|
1726
|
+
const value = data()[key];
|
|
1727
|
+
// Bỏ qua các đối tượng nguy hiểm và đặc biệt
|
|
1728
|
+
if (isReturnAsIsObject(value)) {
|
|
1729
|
+
continue;
|
|
1730
|
+
}
|
|
1731
|
+
if (Object.prototype.hasOwnProperty.call(data(), key)) {
|
|
1732
|
+
data()[key] = convertObjectToSignal(value, cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
return data;
|
|
1736
|
+
};
|
|
1737
|
+
const convertSignalToObject = (data, isCloneDeep = true, seen = new WeakMap()) => {
|
|
1738
|
+
let ignoreCheckSeenHasDataAfterWhile = false;
|
|
1739
|
+
while (isSignal(data) && !seen.has(data)) {
|
|
1740
|
+
const dataConvert = data();
|
|
1741
|
+
if (typeof dataConvert === 'object') {
|
|
1742
|
+
if (dataConvert === null || isReturnAsIsObject(dataConvert)) {
|
|
1743
|
+
return dataConvert;
|
|
1744
|
+
}
|
|
1745
|
+
seen.set(dataConvert, dataConvert);
|
|
1746
|
+
data = dataConvert;
|
|
1747
|
+
ignoreCheckSeenHasDataAfterWhile = true;
|
|
1748
|
+
break;
|
|
1749
|
+
}
|
|
1750
|
+
seen.set(data, dataConvert);
|
|
1751
|
+
data = dataConvert;
|
|
1752
|
+
}
|
|
1753
|
+
if (data === null || typeof data === 'function' || typeof data !== 'object' || isReturnAsIsObject(data)) {
|
|
1754
|
+
return data;
|
|
1755
|
+
}
|
|
1756
|
+
if (!ignoreCheckSeenHasDataAfterWhile && seen.has(data)) {
|
|
1757
|
+
return seen.get(data);
|
|
1758
|
+
}
|
|
1759
|
+
if (isArrayObject(data)) {
|
|
1760
|
+
if (!isSignal(data[0])) {
|
|
1761
|
+
return data;
|
|
1762
|
+
}
|
|
1763
|
+
seen.set(data, data.map((item) => convertSignalToObject(isCloneDeep ? cloneDeep(item) : item, isCloneDeep, seen)));
|
|
1764
|
+
return seen.get(data);
|
|
1765
|
+
}
|
|
1766
|
+
if (isMapObject(data)) {
|
|
1767
|
+
const mapCopy = new Map();
|
|
1768
|
+
Array.from(data.keys()).forEach((key) => {
|
|
1769
|
+
mapCopy.set(key, convertSignalToObject(isCloneDeep ? cloneDeep(data.get(key)) : data.get(key), isCloneDeep));
|
|
1770
|
+
});
|
|
1771
|
+
seen.set(data, mapCopy);
|
|
1772
|
+
return seen.get(data);
|
|
1773
|
+
}
|
|
1774
|
+
if (isSetObject(data)) {
|
|
1775
|
+
const setCopy = new Set();
|
|
1776
|
+
Array.from(data.values()).forEach((value) => {
|
|
1777
|
+
setCopy.add(convertSignalToObject(isCloneDeep ? cloneDeep(value) : value, isCloneDeep));
|
|
1778
|
+
});
|
|
1779
|
+
seen.set(data, setCopy);
|
|
1780
|
+
return seen.get(data);
|
|
1781
|
+
}
|
|
1782
|
+
// Bỏ qua các đối tượng nguy hiểm và đặc biệt
|
|
1783
|
+
if (isReturnAsIsObject(data)) {
|
|
1784
|
+
return data;
|
|
1785
|
+
}
|
|
1786
|
+
const result = isCloneDeep ? {} : data;
|
|
1787
|
+
seen.set(data, result);
|
|
1788
|
+
for (const key in data) {
|
|
1789
|
+
const value = data[key];
|
|
1790
|
+
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1791
|
+
// Bỏ qua các đối tượng nguy hiểm để tránh maximum call stack
|
|
1792
|
+
if (isReturnAsIsObject(value)) {
|
|
1793
|
+
result[key] = value;
|
|
1794
|
+
continue;
|
|
1795
|
+
}
|
|
1796
|
+
result[key] = convertSignalToObject(isCloneDeep ? cloneDeep(value) : value, isCloneDeep);
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
return result;
|
|
1800
|
+
};
|
|
1801
|
+
|
|
1542
1802
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1543
1803
|
/**Các hàm tương tự thư viện lodash */
|
|
1544
1804
|
/**
|
|
@@ -1551,7 +1811,10 @@ const getFormatData = (type, lang) => {
|
|
|
1551
1811
|
* isNil(0); // false
|
|
1552
1812
|
* isNil('hello'); // false
|
|
1553
1813
|
*/
|
|
1554
|
-
const isNil = (value) => {
|
|
1814
|
+
const isNil = (value, options) => {
|
|
1815
|
+
if (!options?.ignoreUnWrapSignal) {
|
|
1816
|
+
value = convertSignalToObject(value);
|
|
1817
|
+
}
|
|
1555
1818
|
return value === null || value === undefined;
|
|
1556
1819
|
};
|
|
1557
1820
|
/**
|
|
@@ -1567,11 +1830,75 @@ const isNil = (value) => {
|
|
|
1567
1830
|
* isEmpty([1, 2, 3]); // false
|
|
1568
1831
|
* isEmpty({ a: 1 }); // false
|
|
1569
1832
|
*/
|
|
1570
|
-
const isEmpty = (value) => {
|
|
1571
|
-
|
|
1572
|
-
value = value
|
|
1833
|
+
const isEmpty = (value, options) => {
|
|
1834
|
+
if (!options?.ignoreUnWrapSignal) {
|
|
1835
|
+
value = convertSignalToObject(value);
|
|
1836
|
+
}
|
|
1837
|
+
if (options?.ignoreCheckFalsy) {
|
|
1838
|
+
return isEmptyTypeObject(value);
|
|
1839
|
+
}
|
|
1840
|
+
const valueIsFalsy = isFalsy(value, { ignoreUnWrapSignal: options?.ignoreUnWrapSignal, ignoreZero: true, ignoreCheckString: options?.ignoreCheckString });
|
|
1841
|
+
if (options?.ignoreCheckTypeObj) {
|
|
1842
|
+
return valueIsFalsy;
|
|
1843
|
+
}
|
|
1844
|
+
return valueIsFalsy || isEmptyTypeObject(value);
|
|
1845
|
+
};
|
|
1846
|
+
/**
|
|
1847
|
+
* Kiểm tra xem một giá trị có phải là object rỗng hay không
|
|
1848
|
+
* @param value Giá trị cần kiểm tra
|
|
1849
|
+
* @returns true nếu giá trị là object rỗng, false nếu không
|
|
1850
|
+
* @example
|
|
1851
|
+
* isEmptyTypeObject({}); // true
|
|
1852
|
+
* isEmptyTypeObject({ a: 1 }); // false
|
|
1853
|
+
*/
|
|
1854
|
+
const isEmptyTypeObject = (value) => {
|
|
1855
|
+
return typeof value === 'object' && (JSON.stringify(value) === '{}' || JSON.stringify(value) === '[]');
|
|
1856
|
+
};
|
|
1857
|
+
/**
|
|
1858
|
+
* Kiểm tra xem một giá trị có phải là null, rỗng, undefined hoặc 0 hay không
|
|
1859
|
+
* @param value Giá trị cần kiểm tra
|
|
1860
|
+
* @param options Cấu hình tùy chọn
|
|
1861
|
+
* @param options.ignoreZero Nếu true, sẽ không kiểm tra giá trị 0
|
|
1862
|
+
* @returns true nếu giá trị là null, rỗng, undefined hoặc 0, false nếu không
|
|
1863
|
+
* @example
|
|
1864
|
+
* isTruthy(null); // false
|
|
1865
|
+
* isTruthy(''); // false
|
|
1866
|
+
* isTruthy(undefined); // false
|
|
1867
|
+
* isTruthy(0); // false
|
|
1868
|
+
* isTruthy({}); // false
|
|
1869
|
+
* isTruthy(0, { ignoreZero: true }); // true
|
|
1870
|
+
*/
|
|
1871
|
+
const isTruthy = (value, options) => {
|
|
1872
|
+
return !isFalsy(value, options);
|
|
1873
|
+
};
|
|
1874
|
+
/**
|
|
1875
|
+
* Kiểm tra xem một giá trị có phải là null, rỗng, undefined hoặc 0 hay không
|
|
1876
|
+
* @param value Giá trị cần kiểm tra
|
|
1877
|
+
* @param options Cấu hình tùy chọn
|
|
1878
|
+
* @param options.ignoreZero Nếu true, sẽ không kiểm tra giá trị 0
|
|
1879
|
+
* @returns true nếu giá trị là null, rỗng, undefined hoặc 0, false nếu không
|
|
1880
|
+
* @example
|
|
1881
|
+
* isFalsy(null); // true
|
|
1882
|
+
* isFalsy(''); // true
|
|
1883
|
+
* isFalsy(undefined); // true
|
|
1884
|
+
* isFalsy(0); // true
|
|
1885
|
+
* isFalsy({}); // false
|
|
1886
|
+
* isFalsy(0, { ignoreZero: true }); // false
|
|
1887
|
+
*/
|
|
1888
|
+
const isFalsy = (value, options) => {
|
|
1889
|
+
if (!options?.ignoreUnWrapSignal) {
|
|
1890
|
+
value = convertSignalToObject(value);
|
|
1891
|
+
}
|
|
1892
|
+
if (isNil(value, { ignoreUnWrapSignal: options?.ignoreUnWrapSignal })) {
|
|
1893
|
+
return true;
|
|
1573
1894
|
}
|
|
1574
|
-
|
|
1895
|
+
if (options?.ignoreZero) {
|
|
1896
|
+
return value === '';
|
|
1897
|
+
}
|
|
1898
|
+
if (options?.ignoreCheckString) {
|
|
1899
|
+
return value === 0;
|
|
1900
|
+
}
|
|
1901
|
+
return value === '' || value === 0;
|
|
1575
1902
|
};
|
|
1576
1903
|
/**
|
|
1577
1904
|
* Loại bỏ các thuộc tính của đối tượng dựa trên một hàm điều kiện
|
|
@@ -1587,7 +1914,7 @@ const omitBy = (objData, predicate) => {
|
|
|
1587
1914
|
return objData;
|
|
1588
1915
|
}
|
|
1589
1916
|
const newObj = {};
|
|
1590
|
-
Object.keys(objData).forEach(key => {
|
|
1917
|
+
Object.keys(objData).forEach((key) => {
|
|
1591
1918
|
const valueOfKey = get(objData, key);
|
|
1592
1919
|
if (!predicate(valueOfKey)) {
|
|
1593
1920
|
set(newObj, key, valueOfKey);
|
|
@@ -1674,7 +2001,12 @@ const get = (obj, path, defaultValue = undefined, keepLastValueIfSignal) => {
|
|
|
1674
2001
|
if (obj instanceof DOMRect) {
|
|
1675
2002
|
return obj[path];
|
|
1676
2003
|
}
|
|
1677
|
-
const paths = Array.isArray(path)
|
|
2004
|
+
const paths = Array.isArray(path)
|
|
2005
|
+
? path
|
|
2006
|
+
: path
|
|
2007
|
+
.replace(/\[(\d+)]/g, '.$1')
|
|
2008
|
+
.split('.')
|
|
2009
|
+
.filter((key) => key);
|
|
1678
2010
|
for (const index in paths) {
|
|
1679
2011
|
const key = paths[index];
|
|
1680
2012
|
if (obj instanceof CSSStyleDeclaration) {
|
|
@@ -1704,29 +2036,34 @@ const get = (obj, path, defaultValue = undefined, keepLastValueIfSignal) => {
|
|
|
1704
2036
|
* const obj = { a: { b: 1 } };
|
|
1705
2037
|
* set(obj, 'a.b', 2); // { a: { b: 2 } }
|
|
1706
2038
|
*/
|
|
1707
|
-
const set = (obj, path, value) => {
|
|
1708
|
-
if (!obj || (typeof obj !==
|
|
1709
|
-
throw new Error(
|
|
2039
|
+
const set = (obj, path, value, options) => {
|
|
2040
|
+
if (!obj || (typeof obj !== 'object' && !isSignal(obj)) || (isSignal(obj) && typeof obj() !== 'object')) {
|
|
2041
|
+
throw new Error('The first argument must be an object');
|
|
1710
2042
|
}
|
|
1711
2043
|
if (obj instanceof HttpParams) {
|
|
1712
2044
|
return obj.set(`${path}`, value);
|
|
1713
2045
|
}
|
|
1714
|
-
const pathArray = Array.isArray(path)
|
|
2046
|
+
const pathArray = Array.isArray(path)
|
|
2047
|
+
? path
|
|
2048
|
+
: path
|
|
2049
|
+
.replace(/\[(\d+)]/g, '.[$1]')
|
|
2050
|
+
.split('.')
|
|
2051
|
+
.filter((key) => key);
|
|
1715
2052
|
let currentObjectByKey = isSignal(obj) ? obj() : obj;
|
|
1716
2053
|
let preObjectByKey = obj;
|
|
1717
2054
|
pathArray.forEach((key, index) => {
|
|
1718
2055
|
if (index < pathArray.length - 1) {
|
|
1719
|
-
if (!(key in currentObjectByKey) || (typeof currentObjectByKey[key] !==
|
|
2056
|
+
if (!(key in currentObjectByKey) || (typeof currentObjectByKey[key] !== 'object' && !isSignal(currentObjectByKey[key]))) {
|
|
1720
2057
|
const nextKey = pathArray[index + 1];
|
|
1721
2058
|
key = key.replace(/\[(\d+)]/g, '$1');
|
|
1722
|
-
currentObjectByKey[key] = /\[(\d+)]/g.test(nextKey) ? [] : {};
|
|
2059
|
+
currentObjectByKey[key] = /\[(\d+)]/g.test(nextKey) ? (options?.valueDefaultPathArrayUndefined ?? []) : (options?.valueDefaultPathObjectUndefined ?? {});
|
|
1723
2060
|
}
|
|
1724
2061
|
currentObjectByKey = key ? currentObjectByKey[key] : currentObjectByKey;
|
|
1725
2062
|
preObjectByKey = currentObjectByKey;
|
|
1726
2063
|
currentObjectByKey = isSignal(currentObjectByKey) ? currentObjectByKey() : currentObjectByKey;
|
|
1727
2064
|
return;
|
|
1728
2065
|
}
|
|
1729
|
-
if (typeof currentObjectByKey !==
|
|
2066
|
+
if (typeof currentObjectByKey !== 'object') {
|
|
1730
2067
|
return;
|
|
1731
2068
|
}
|
|
1732
2069
|
// Gán giá trị ở cuối đường dẫn
|
|
@@ -1778,7 +2115,7 @@ const set = (obj, path, value) => {
|
|
|
1778
2115
|
* // clone là một bản sao hoàn toàn độc lập của obj
|
|
1779
2116
|
*/
|
|
1780
2117
|
const cloneDeep = (data, options = { ignoreSignal: false }, seen = new WeakMap()) => {
|
|
1781
|
-
if (data === null || (typeof data !== 'object' && !isSignal(data))) {
|
|
2118
|
+
if (data === null || (typeof data !== 'object' && !isSignal(data)) || isDangerousObject(data)) {
|
|
1782
2119
|
return data;
|
|
1783
2120
|
}
|
|
1784
2121
|
if (seen.has(data)) {
|
|
@@ -1807,19 +2144,16 @@ const cloneDeep = (data, options = { ignoreSignal: false }, seen = new WeakMap()
|
|
|
1807
2144
|
if (data instanceof Set) {
|
|
1808
2145
|
const setCopy = new Set();
|
|
1809
2146
|
seen.set(data, setCopy);
|
|
1810
|
-
data.forEach(val => {
|
|
2147
|
+
data.forEach((val) => {
|
|
1811
2148
|
setCopy.add(cloneDeep(val, options, seen));
|
|
1812
2149
|
});
|
|
1813
2150
|
return setCopy;
|
|
1814
2151
|
}
|
|
1815
2152
|
if (Array.isArray(data)) {
|
|
1816
|
-
seen.set(data, data.map(item => cloneDeep(item, options, seen)));
|
|
2153
|
+
seen.set(data, data.map((item) => cloneDeep(item, options, seen)));
|
|
1817
2154
|
return seen.get(data);
|
|
1818
2155
|
}
|
|
1819
|
-
if (
|
|
1820
|
-
return data;
|
|
1821
|
-
}
|
|
1822
|
-
if (data instanceof TemplateRef || data instanceof ElementRef || data instanceof Element || data instanceof Promise || data instanceof Observable) {
|
|
2156
|
+
if (isReturnAsIsObject(data)) {
|
|
1823
2157
|
return data;
|
|
1824
2158
|
}
|
|
1825
2159
|
if (isSignal(data)) {
|
|
@@ -1837,11 +2171,19 @@ const cloneDeep = (data, options = { ignoreSignal: false }, seen = new WeakMap()
|
|
|
1837
2171
|
result[key] = new UtilsHttpParamsRequest(undefined, value);
|
|
1838
2172
|
continue;
|
|
1839
2173
|
}
|
|
2174
|
+
if (value instanceof Date) {
|
|
2175
|
+
result[key] = new Date(value.getTime());
|
|
2176
|
+
continue;
|
|
2177
|
+
}
|
|
1840
2178
|
if (dayjs.isDayjs(value)) {
|
|
1841
2179
|
result[key] = getDayjs({ date: value.valueOf() });
|
|
1842
2180
|
continue;
|
|
1843
2181
|
}
|
|
1844
|
-
if (value instanceof
|
|
2182
|
+
if (value instanceof RegExp) {
|
|
2183
|
+
result[key] = new RegExp(value.source, value.flags);
|
|
2184
|
+
continue;
|
|
2185
|
+
}
|
|
2186
|
+
if (isReturnAsIsObject(data)) {
|
|
1845
2187
|
result[key] = value;
|
|
1846
2188
|
continue;
|
|
1847
2189
|
}
|
|
@@ -1973,6 +2315,11 @@ const range = (start, end, step) => {
|
|
|
1973
2315
|
* isEqual({a:1}, {a:1}); // true
|
|
1974
2316
|
*/
|
|
1975
2317
|
const isEqual = (value1, value2, options) => {
|
|
2318
|
+
// Handle signals
|
|
2319
|
+
if (!options?.ignoreUnWrapSignal) {
|
|
2320
|
+
value1 = convertSignalToObject(value1);
|
|
2321
|
+
value2 = convertSignalToObject(value2);
|
|
2322
|
+
}
|
|
1976
2323
|
const { exactlyPosition = false, ignoreExactlyDataType = false } = options || {};
|
|
1977
2324
|
if (value1 === value2 || (value1 === null && value2 === null) || (value1 === undefined && value2 === undefined)) {
|
|
1978
2325
|
return true;
|
|
@@ -1980,13 +2327,6 @@ const isEqual = (value1, value2, options) => {
|
|
|
1980
2327
|
if (ignoreExactlyDataType) {
|
|
1981
2328
|
return isEqual(isNil(value1) ? undefined : `${value1}`, isNil(value2) ? undefined : `${value2}`);
|
|
1982
2329
|
}
|
|
1983
|
-
// Handle signals
|
|
1984
|
-
while (isSignal(value1)) {
|
|
1985
|
-
value1 = value1();
|
|
1986
|
-
}
|
|
1987
|
-
while (isSignal(value2)) {
|
|
1988
|
-
value2 = value2();
|
|
1989
|
-
}
|
|
1990
2330
|
if (typeof value1 !== 'object' || typeof value2 !== 'object' || (Array.isArray(value1) && !Array.isArray(value2)) || (!Array.isArray(value1) && Array.isArray(value2))) {
|
|
1991
2331
|
return false;
|
|
1992
2332
|
}
|
|
@@ -1995,7 +2335,7 @@ const isEqual = (value1, value2, options) => {
|
|
|
1995
2335
|
return false;
|
|
1996
2336
|
}
|
|
1997
2337
|
if (!exactlyPosition) {
|
|
1998
|
-
return !value1.some(item => !value2.includes(item));
|
|
2338
|
+
return !value1.some((item) => !value2.includes(item));
|
|
1999
2339
|
}
|
|
2000
2340
|
return !value1.some((item, index) => !isEqual(item, value2[index], options));
|
|
2001
2341
|
}
|
|
@@ -2028,7 +2368,7 @@ const uniqBy = (data, key) => {
|
|
|
2028
2368
|
// Xử lý mảng chứa signal values
|
|
2029
2369
|
if (data[0] && isSignal(data[0])) {
|
|
2030
2370
|
const seen = new Set();
|
|
2031
|
-
return data.filter(item => {
|
|
2371
|
+
return data.filter((item) => {
|
|
2032
2372
|
const value = `${get(item, '')}`;
|
|
2033
2373
|
if (seen.has(value)) {
|
|
2034
2374
|
return false;
|
|
@@ -2041,7 +2381,7 @@ const uniqBy = (data, key) => {
|
|
|
2041
2381
|
return Array.from(new Set(data));
|
|
2042
2382
|
}
|
|
2043
2383
|
const dataUnique = keyBy(data, key);
|
|
2044
|
-
return Object.keys(dataUnique).map(key => dataUnique[key]);
|
|
2384
|
+
return Object.keys(dataUnique).map((key) => dataUnique[key]);
|
|
2045
2385
|
};
|
|
2046
2386
|
const generateInterface = (obj, interfaceName) => {
|
|
2047
2387
|
const generateType = (value) => {
|
|
@@ -2090,11 +2430,10 @@ const generateInterface = (obj, interfaceName) => {
|
|
|
2090
2430
|
return interfaceStr;
|
|
2091
2431
|
};
|
|
2092
2432
|
|
|
2093
|
-
;
|
|
2094
2433
|
const step = 20;
|
|
2095
2434
|
const percent = 0.05;
|
|
2096
2435
|
const colorStepContrastFromOrigin = (color, stepNumber) => {
|
|
2097
|
-
return colorContrastFromOrigin(color).find(item => item.step === stepNumber);
|
|
2436
|
+
return colorContrastFromOrigin(color).find((item) => item.step === stepNumber);
|
|
2098
2437
|
};
|
|
2099
2438
|
const colorContrastFromOrigin = (color) => {
|
|
2100
2439
|
const parsedColorsArray = parseColorValues(color);
|
|
@@ -2129,10 +2468,10 @@ const parseColorValues = (colorValues) => {
|
|
|
2129
2468
|
return colorValuesArray;
|
|
2130
2469
|
};
|
|
2131
2470
|
const calculateShades = (colorValue) => {
|
|
2132
|
-
return calculate(colorValue, rgbShade).concat(
|
|
2471
|
+
return calculate(colorValue, rgbShade).concat('000000');
|
|
2133
2472
|
};
|
|
2134
2473
|
const calculateTints = (colorValue) => {
|
|
2135
|
-
return calculate(colorValue, rgbTint).concat(
|
|
2474
|
+
return calculate(colorValue, rgbTint).concat('ffffff');
|
|
2136
2475
|
};
|
|
2137
2476
|
const calculate = (colorValue, shadeOrTint) => {
|
|
2138
2477
|
const color = hexToRGB(colorValue);
|
|
@@ -2142,11 +2481,21 @@ const calculate = (colorValue, shadeOrTint) => {
|
|
|
2142
2481
|
}
|
|
2143
2482
|
return shadeValues;
|
|
2144
2483
|
};
|
|
2145
|
-
const rgbShade = (rgb, i) => {
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
const
|
|
2149
|
-
|
|
2484
|
+
const rgbShade = (rgb, i) => {
|
|
2485
|
+
return { red: rgb.red * (1 - percent * i), green: rgb.green * (1 - percent * i), blue: rgb.blue * (1 - percent * i) };
|
|
2486
|
+
};
|
|
2487
|
+
const rgbTint = (rgb, i) => {
|
|
2488
|
+
return { red: rgb.red + (255 - rgb.red) * i * percent, green: rgb.green + (255 - rgb.green) * i * percent, blue: rgb.blue + (255 - rgb.blue) * i * percent };
|
|
2489
|
+
};
|
|
2490
|
+
const rgbToHex = (rgb) => {
|
|
2491
|
+
return intToHex(rgb.red) + intToHex(rgb.green) + intToHex(rgb.blue);
|
|
2492
|
+
};
|
|
2493
|
+
const hexToRGB = (colorValue) => {
|
|
2494
|
+
return { red: parseInt(colorValue.substr(0, 2), 16), green: parseInt(colorValue.substr(2, 2), 16), blue: parseInt(colorValue.substr(4, 2), 16) };
|
|
2495
|
+
};
|
|
2496
|
+
const intToHex = (rgbint) => {
|
|
2497
|
+
return pad(Math.min(Math.max(Math.round(rgbint), 0), 255).toString(16), 2);
|
|
2498
|
+
};
|
|
2150
2499
|
const pad = (number, length) => {
|
|
2151
2500
|
let str = '' + number;
|
|
2152
2501
|
while (str.length < length) {
|
|
@@ -2154,9 +2503,52 @@ const pad = (number, length) => {
|
|
|
2154
2503
|
}
|
|
2155
2504
|
return str;
|
|
2156
2505
|
};
|
|
2157
|
-
const listColorDefine = [
|
|
2158
|
-
'#
|
|
2159
|
-
'#
|
|
2506
|
+
const listColorDefine = [
|
|
2507
|
+
'#E62222',
|
|
2508
|
+
'#B81B1B',
|
|
2509
|
+
'#EB4E4E',
|
|
2510
|
+
'#F97316',
|
|
2511
|
+
'#C75C12',
|
|
2512
|
+
'#FA8F45',
|
|
2513
|
+
'#FFB700',
|
|
2514
|
+
'#CC9200',
|
|
2515
|
+
'#FFC533',
|
|
2516
|
+
'#84CC16',
|
|
2517
|
+
'#6AA312',
|
|
2518
|
+
'#9dd645',
|
|
2519
|
+
'#00BC62',
|
|
2520
|
+
'#00A757',
|
|
2521
|
+
'#33DA8A',
|
|
2522
|
+
'#06B6D4',
|
|
2523
|
+
'#1B59C4',
|
|
2524
|
+
'#4E8CF7',
|
|
2525
|
+
'#0EA5E9',
|
|
2526
|
+
'#1B59C4',
|
|
2527
|
+
'#4E8CF7',
|
|
2528
|
+
'#226FF5',
|
|
2529
|
+
'#1B59C4',
|
|
2530
|
+
'#4E8CF7',
|
|
2531
|
+
'#6366F1',
|
|
2532
|
+
'#4F52C1',
|
|
2533
|
+
'#8285F4',
|
|
2534
|
+
'#5B04B3',
|
|
2535
|
+
'#49038F',
|
|
2536
|
+
'#7C36C2',
|
|
2537
|
+
'#D946EF',
|
|
2538
|
+
'#AE38BF',
|
|
2539
|
+
'#E16BF2',
|
|
2540
|
+
'#EC4899',
|
|
2541
|
+
'#BD3A7A',
|
|
2542
|
+
'#F06DAD',
|
|
2543
|
+
'#F43F5E',
|
|
2544
|
+
'#C3324B',
|
|
2545
|
+
'#F6657E',
|
|
2546
|
+
'#757380',
|
|
2547
|
+
'#5E5C66',
|
|
2548
|
+
'#918F99',
|
|
2549
|
+
'#202020',
|
|
2550
|
+
'#1A1A1A',
|
|
2551
|
+
'#4D4D4D',
|
|
2160
2552
|
];
|
|
2161
2553
|
const getColorById = (str) => {
|
|
2162
2554
|
let hashString = 0;
|
|
@@ -2165,7 +2557,7 @@ const getColorById = (str) => {
|
|
|
2165
2557
|
}
|
|
2166
2558
|
for (let i = 0; i < str.length; i++) {
|
|
2167
2559
|
const char = str.charCodeAt(i);
|
|
2168
|
-
hashString = (
|
|
2560
|
+
hashString = (hashString << 5) - hashString + char;
|
|
2169
2561
|
hashString = hashString & hashString;
|
|
2170
2562
|
}
|
|
2171
2563
|
return listColorDefine[Math.abs(hashString) % listColorDefine.length];
|
|
@@ -2305,8 +2697,8 @@ const getKeyCacheByArrayObject = (keyCache, argumentsValue) => {
|
|
|
2305
2697
|
keyBuild = `${keyBuild}${JSON.stringify(item)}`;
|
|
2306
2698
|
return;
|
|
2307
2699
|
}
|
|
2308
|
-
const keys = (item instanceof HttpParams ? item.keys() : Object.keys(item)).sort((
|
|
2309
|
-
keys.forEach(key => {
|
|
2700
|
+
const keys = (item instanceof HttpParams ? item.keys() : Object.keys(item)).sort((str1, str2) => str1.localeCompare(str2));
|
|
2701
|
+
keys.forEach((key) => {
|
|
2310
2702
|
if (key.toLocaleLowerCase() === 'pem') {
|
|
2311
2703
|
return;
|
|
2312
2704
|
}
|
|
@@ -2350,7 +2742,7 @@ const viewDataNumberByLanguage = (value, acceptNegativeValue, parseFixed = 1, ig
|
|
|
2350
2742
|
return Math.round(value * fixed) / fixed;
|
|
2351
2743
|
};
|
|
2352
2744
|
if (parseFixed > (floatStr?.length || 0)) {
|
|
2353
|
-
const maxParseFixed =
|
|
2745
|
+
const maxParseFixed = acceptNegativeValue && +value < 0 ? 17 : 16;
|
|
2354
2746
|
const fixed = maxParseFixed - (intStr?.length || 0);
|
|
2355
2747
|
parseFixed = parseFixed < fixed ? parseFixed : fixed;
|
|
2356
2748
|
}
|
|
@@ -2377,7 +2769,10 @@ const viewDataNumberByLanguage = (value, acceptNegativeValue, parseFixed = 1, ig
|
|
|
2377
2769
|
if (lang === UtilsLanguageConstants.EN) {
|
|
2378
2770
|
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
2379
2771
|
}
|
|
2380
|
-
return value
|
|
2772
|
+
return value
|
|
2773
|
+
.toString()
|
|
2774
|
+
.replace('.', ',')
|
|
2775
|
+
.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
|
|
2381
2776
|
}
|
|
2382
2777
|
};
|
|
2383
2778
|
|
|
@@ -2391,120 +2786,14 @@ const xssFilter = async (data) => {
|
|
|
2391
2786
|
return await functionXssFilter(data);
|
|
2392
2787
|
};
|
|
2393
2788
|
|
|
2394
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2395
|
-
/**
|
|
2396
|
-
* Chuyển đổi một đối tượng hoặc giá trị thành signal
|
|
2397
|
-
* @param data Dữ liệu cần chuyển đổi thành signal
|
|
2398
|
-
* @param cloneDeepIfNotSignal Có thực hiện sao chép sâu dữ liệu trước khi chuyển đổi hay không nếu data không phải signal. Mặc định là true.
|
|
2399
|
-
* Đặt false nếu muốn giữ nguyên tham chiếu đến dữ liệu gốc.
|
|
2400
|
-
* Nếu muốn sao chép sâu đối tượng signal thì đặt cloneDeepIfNotSignal là true và acceptConvertObjectInnerWritableSignal là true.
|
|
2401
|
-
* @param isSignalPrimitiveType Có chuyển đổi các giá trị nguyên thủy (string, number, boolean) thành signal hay không. Mặc định là false.
|
|
2402
|
-
* Đặt true nếu muốn bọc các giá trị nguyên thủy trong signal.
|
|
2403
|
-
* @param acceptConvertObjectInnerWritableSignal Có tiếp tục tìm kiếm và chuyển đổi các đối tượng bên trong signal hay không. Mặc định là false.
|
|
2404
|
-
* Đặt true nếu muốn tìm và chuyển đổi các đối tượng bên trong signal hoặc chính nó thành signal mới.
|
|
2405
|
-
* @returns Dữ liệu đã được chuyển đổi theo kiểu T
|
|
2406
|
-
*/
|
|
2407
|
-
const convertObjectToSignal = (data, cloneDeepIfNotSignal = true, isSignalPrimitiveType = false, acceptConvertObjectInnerWritableSignal = false, seen = new WeakMap()) => {
|
|
2408
|
-
if ((data === null || typeof data !== 'object') && !isSignal(data)) {
|
|
2409
|
-
return (isSignalPrimitiveType ? signal(data) : data);
|
|
2410
|
-
}
|
|
2411
|
-
if (seen.has(data)) {
|
|
2412
|
-
return seen.get(data);
|
|
2413
|
-
}
|
|
2414
|
-
if (isSignal(data)) {
|
|
2415
|
-
if (!acceptConvertObjectInnerWritableSignal) {
|
|
2416
|
-
return data;
|
|
2417
|
-
}
|
|
2418
|
-
seen.set(data, convertObjectToSignal(data(), cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal, seen));
|
|
2419
|
-
return seen.get(data);
|
|
2420
|
-
}
|
|
2421
|
-
if (Array.isArray(data)) {
|
|
2422
|
-
seen.set(data, signal(data.map(item => convertObjectToSignal(item, cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal, seen))));
|
|
2423
|
-
return seen.get(data);
|
|
2424
|
-
}
|
|
2425
|
-
if (data instanceof Map) {
|
|
2426
|
-
const mapCopy = new Map();
|
|
2427
|
-
Array.from(data.keys()).forEach(key => {
|
|
2428
|
-
mapCopy.set(key, convertObjectToSignal(data.get(key), cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal));
|
|
2429
|
-
});
|
|
2430
|
-
seen.set(data, signal(mapCopy));
|
|
2431
|
-
return seen.get(data);
|
|
2432
|
-
}
|
|
2433
|
-
if (data instanceof Promise || data instanceof Observable) {
|
|
2434
|
-
return data;
|
|
2435
|
-
}
|
|
2436
|
-
data = signal(cloneDeepIfNotSignal ? { ...data } : data);
|
|
2437
|
-
seen.set(data, data);
|
|
2438
|
-
for (const key in data()) {
|
|
2439
|
-
const value = data()[key];
|
|
2440
|
-
if (value instanceof TemplateRef || value instanceof File || value instanceof Blob || Object.prototype.toString.call(value) === '[object File]' || value instanceof ElementRef || value instanceof Element || value instanceof Date || value instanceof RegExp || value instanceof Set || value instanceof Map || value instanceof Promise || value instanceof Observable || value instanceof HttpParams) {
|
|
2441
|
-
continue;
|
|
2442
|
-
}
|
|
2443
|
-
if (Object.prototype.hasOwnProperty.call(data(), key)) {
|
|
2444
|
-
data()[key] = convertObjectToSignal(value, cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal);
|
|
2445
|
-
}
|
|
2446
|
-
}
|
|
2447
|
-
return data;
|
|
2448
|
-
};
|
|
2449
|
-
const convertSignalToObject = (data, isCloneDeep = true, seen = new WeakMap()) => {
|
|
2450
|
-
let ignoreCheckSeenHasDataAfterWhile = false;
|
|
2451
|
-
while (isSignal(data) && !seen.has(data)) {
|
|
2452
|
-
const dataConvert = data();
|
|
2453
|
-
if (typeof dataConvert === 'object') {
|
|
2454
|
-
if (dataConvert === null) {
|
|
2455
|
-
return dataConvert;
|
|
2456
|
-
}
|
|
2457
|
-
seen.set(dataConvert, dataConvert);
|
|
2458
|
-
data = dataConvert;
|
|
2459
|
-
ignoreCheckSeenHasDataAfterWhile = true;
|
|
2460
|
-
break;
|
|
2461
|
-
}
|
|
2462
|
-
seen.set(data, dataConvert);
|
|
2463
|
-
data = dataConvert;
|
|
2464
|
-
}
|
|
2465
|
-
if (data === null || typeof data === 'function' || typeof data !== 'object') {
|
|
2466
|
-
return data;
|
|
2467
|
-
}
|
|
2468
|
-
if (!ignoreCheckSeenHasDataAfterWhile && seen.has(data)) {
|
|
2469
|
-
return seen.get(data);
|
|
2470
|
-
}
|
|
2471
|
-
if (Array.isArray(data)) {
|
|
2472
|
-
if (!isSignal(data[0])) {
|
|
2473
|
-
return data;
|
|
2474
|
-
}
|
|
2475
|
-
seen.set(data, data.map(item => convertSignalToObject((isCloneDeep ? cloneDeep(item) : item), isCloneDeep, seen)));
|
|
2476
|
-
return seen.get(data);
|
|
2477
|
-
}
|
|
2478
|
-
if (data instanceof Map) {
|
|
2479
|
-
const mapCopy = new Map();
|
|
2480
|
-
Array.from(data.keys()).forEach(key => {
|
|
2481
|
-
mapCopy.set(key, convertSignalToObject(isCloneDeep ? cloneDeep(data.get(key)) : data.get(key), isCloneDeep));
|
|
2482
|
-
});
|
|
2483
|
-
seen.set(data, mapCopy);
|
|
2484
|
-
return seen.get(data);
|
|
2485
|
-
}
|
|
2486
|
-
if (data instanceof File || data instanceof Blob || Object.prototype.toString.call(data) === '[object File]') {
|
|
2487
|
-
return data;
|
|
2488
|
-
}
|
|
2489
|
-
if (data instanceof TemplateRef || data instanceof ElementRef || data instanceof Element || data instanceof Promise || data instanceof Observable || data instanceof HttpParams) {
|
|
2490
|
-
return data;
|
|
2491
|
-
}
|
|
2492
|
-
const result = isCloneDeep ? {} : data;
|
|
2493
|
-
seen.set(data, result);
|
|
2494
|
-
for (const key in data) {
|
|
2495
|
-
const value = data[key];
|
|
2496
|
-
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
2497
|
-
result[key] = convertSignalToObject(isCloneDeep ? cloneDeep(value) : value, isCloneDeep);
|
|
2498
|
-
}
|
|
2499
|
-
}
|
|
2500
|
-
return result;
|
|
2501
|
-
};
|
|
2502
|
-
|
|
2503
2789
|
const ENCODE_URI_PATTERN = /%([0-9A-F]{2})/g;
|
|
2504
2790
|
const decodeURI = (value) => {
|
|
2505
|
-
return decodeURIComponent(value
|
|
2791
|
+
return decodeURIComponent(value
|
|
2792
|
+
.split('')
|
|
2793
|
+
.map((c) => {
|
|
2506
2794
|
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
|
|
2507
|
-
})
|
|
2795
|
+
})
|
|
2796
|
+
.join(''));
|
|
2508
2797
|
};
|
|
2509
2798
|
const encodeURI = (value) => {
|
|
2510
2799
|
return encodeURIComponent(value).replace(ENCODE_URI_PATTERN, (match, p1) => {
|
|
@@ -2512,7 +2801,7 @@ const encodeURI = (value) => {
|
|
|
2512
2801
|
});
|
|
2513
2802
|
};
|
|
2514
2803
|
const endCodeUrl = (params, isBody) => {
|
|
2515
|
-
params = omitBy(params, param => param === '' || isNil(param));
|
|
2804
|
+
params = omitBy(params, (param) => param === '' || isNil(param));
|
|
2516
2805
|
let res = '';
|
|
2517
2806
|
for (const p in params) {
|
|
2518
2807
|
res += `&${p}=${encodeURIComponent(params[p])}`;
|
|
@@ -2590,7 +2879,7 @@ const downloadFileByUrl = async (fileUrl, filename, onlyOpen) => {
|
|
|
2590
2879
|
const downloadImageFromELement = (imageElement, typeFileDownload, nameFile) => {
|
|
2591
2880
|
const parentElement = imageElement?.src;
|
|
2592
2881
|
const blobData = convertBase64ToBlob(parentElement);
|
|
2593
|
-
const blob = new Blob([blobData], { type: typeFileDownload ||
|
|
2882
|
+
const blob = new Blob([blobData], { type: typeFileDownload || 'image/png' });
|
|
2594
2883
|
const url = window.URL.createObjectURL(blob);
|
|
2595
2884
|
const link = document.createElement('a');
|
|
2596
2885
|
link.href = url;
|
|
@@ -2602,12 +2891,22 @@ const LINK_IMAGE_ERROR_TOKEN_INJECT = new InjectionToken('LINK_IMAGE_ERROR_TOKEN
|
|
|
2602
2891
|
const PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT = new InjectionToken('PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT');
|
|
2603
2892
|
const PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT = new InjectionToken('PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT');
|
|
2604
2893
|
|
|
2605
|
-
const isTypeImage = (file) => file.type.match(/image.*/) ? true : false;
|
|
2606
|
-
const isTypeVideo = (file) => file.type.match(/video.*/) ? true : false;
|
|
2607
|
-
const isTypeAudio = (file) => file.type.match(/audio.*/) ? true : false;
|
|
2608
|
-
const isTypeFile = (file) => file instanceof File || Object.prototype.toString.call(file) === '[object File]' ? true : false;
|
|
2894
|
+
const isTypeImage = (file) => (file.type.match(/image.*/) ? true : false);
|
|
2895
|
+
const isTypeVideo = (file) => (file.type.match(/video.*/) ? true : false);
|
|
2896
|
+
const isTypeAudio = (file) => (file.type.match(/audio.*/) ? true : false);
|
|
2897
|
+
const isTypeFile = (file) => (file instanceof File || Object.prototype.toString.call(file) === '[object File]' ? true : false);
|
|
2609
2898
|
const ExcelExtList = ['xls', 'xlsx', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
|
|
2610
|
-
const DocumentExtList = [
|
|
2899
|
+
const DocumentExtList = [
|
|
2900
|
+
'doc',
|
|
2901
|
+
'docx',
|
|
2902
|
+
'xls',
|
|
2903
|
+
'xlsx',
|
|
2904
|
+
'ppt',
|
|
2905
|
+
'pptx',
|
|
2906
|
+
'pdf',
|
|
2907
|
+
'json',
|
|
2908
|
+
'xml',
|
|
2909
|
+
'application/msword',
|
|
2611
2910
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
2612
2911
|
'application/vnd.ms-excel',
|
|
2613
2912
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
@@ -2615,7 +2914,8 @@ const DocumentExtList = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf', 'js
|
|
|
2615
2914
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
2616
2915
|
'application/pdf',
|
|
2617
2916
|
'application/json',
|
|
2618
|
-
'application/xml'
|
|
2917
|
+
'application/xml',
|
|
2918
|
+
];
|
|
2619
2919
|
const isIncludeDocumentExtList = (ext, listExt = DocumentExtList) => listExt.includes(ext) || listExt.includes(`application/${ext}`);
|
|
2620
2920
|
const ImageExtList = ['gif', 'jpg', 'jpeg', 'png', 'image/gif', 'image/jpeg', 'image/jpeg', 'image/png'];
|
|
2621
2921
|
const isIncludeImageExtList = (ext, listExt = ImageExtList) => listExt.includes(ext);
|
|
@@ -2640,7 +2940,7 @@ const getFileExtension = (file) => {
|
|
|
2640
2940
|
fileName = url.split('/').pop() || '';
|
|
2641
2941
|
set(file, 'name', fileName);
|
|
2642
2942
|
}
|
|
2643
|
-
const dots = fileName.split(
|
|
2943
|
+
const dots = fileName.split('.');
|
|
2644
2944
|
if (!dots) {
|
|
2645
2945
|
return;
|
|
2646
2946
|
}
|
|
@@ -2743,12 +3043,12 @@ const getSmartAxisScale = (originalMaxData, options) => {
|
|
|
2743
3043
|
}
|
|
2744
3044
|
const maxValuePositive = maxValue - Math.abs(minValue);
|
|
2745
3045
|
tickCount = maxValuePositive - originalMaxData > Math.abs(step) && tickCount - 1 >= minTickCount ? tickCount - 1 : tickCount;
|
|
2746
|
-
maxValue =
|
|
3046
|
+
maxValue = step * tickCount * scaleDirection - minValue * scaleDirection;
|
|
2747
3047
|
return {
|
|
2748
3048
|
stepSize: Math.abs(step),
|
|
2749
3049
|
max: maxValue,
|
|
2750
3050
|
min: minValue,
|
|
2751
|
-
tickAmount: tickCount
|
|
3051
|
+
tickAmount: tickCount,
|
|
2752
3052
|
};
|
|
2753
3053
|
}
|
|
2754
3054
|
}
|
|
@@ -2763,7 +3063,7 @@ const getSmartAxisScale = (originalMaxData, options) => {
|
|
|
2763
3063
|
stepSize: Math.abs(step),
|
|
2764
3064
|
max: maxValue,
|
|
2765
3065
|
min: 0,
|
|
2766
|
-
tickAmount: minTickCount
|
|
3066
|
+
tickAmount: minTickCount,
|
|
2767
3067
|
};
|
|
2768
3068
|
};
|
|
2769
3069
|
// Cache cho các giá trị lũy thừa 10 để tối ưu hiệu suất
|
|
@@ -2819,7 +3119,7 @@ const getStepCandidates = (maxData, minStep, minNegative, acceptStepIsTypeFloat
|
|
|
2819
3119
|
const checkAndSetNegativeSteps = (stepCandidates, acceptNegative, minNegative) => {
|
|
2820
3120
|
if (acceptNegative && minNegative < 0) {
|
|
2821
3121
|
// Tạo các step âm và thêm vào đầu danh sách
|
|
2822
|
-
const negativeSteps = [...stepCandidates].map(step => -step);
|
|
3122
|
+
const negativeSteps = [...stepCandidates].map((step) => -step);
|
|
2823
3123
|
stepCandidates.unshift(...negativeSteps);
|
|
2824
3124
|
}
|
|
2825
3125
|
};
|
|
@@ -2832,20 +3132,20 @@ const checkAndSetNegativeSteps = (stepCandidates, acceptNegative, minNegative) =
|
|
|
2832
3132
|
const validateInputs = (maxData, options) => {
|
|
2833
3133
|
// Kiểm tra maxData âm khi không chấp nhận giá trị âm
|
|
2834
3134
|
if (maxData < 0 && !options?.acceptNegative) {
|
|
2835
|
-
throw new Error(
|
|
3135
|
+
throw new Error('maxData is less than 0 and acceptNegative is false');
|
|
2836
3136
|
}
|
|
2837
3137
|
if (options?.acceptNegative) {
|
|
2838
3138
|
// Kiểm tra minNegative có được cung cấp không
|
|
2839
3139
|
if (isNil(options.minNegative)) {
|
|
2840
|
-
throw new Error(
|
|
3140
|
+
throw new Error('minNegative is required when acceptNegative is true');
|
|
2841
3141
|
}
|
|
2842
3142
|
// Kiểm tra maxData phải >= minNegative
|
|
2843
3143
|
if (maxData < options.minNegative) {
|
|
2844
|
-
throw new Error(
|
|
3144
|
+
throw new Error('maxData is less than minNegative');
|
|
2845
3145
|
}
|
|
2846
3146
|
// Kiểm tra minNegative phải là số âm
|
|
2847
3147
|
if (options.minNegative >= 0) {
|
|
2848
|
-
throw new Error(
|
|
3148
|
+
throw new Error('minNegative must be negative');
|
|
2849
3149
|
}
|
|
2850
3150
|
}
|
|
2851
3151
|
};
|
|
@@ -2865,7 +3165,7 @@ const revealString = (encoded) => {
|
|
|
2865
3165
|
const decoded = base
|
|
2866
3166
|
.split('')
|
|
2867
3167
|
.reverse()
|
|
2868
|
-
.map(c => String.fromCharCode(c.charCodeAt(0) ^ xorKey))
|
|
3168
|
+
.map((c) => String.fromCharCode(c.charCodeAt(0) ^ xorKey))
|
|
2869
3169
|
.join('');
|
|
2870
3170
|
return decoded;
|
|
2871
3171
|
};
|
|
@@ -2896,5 +3196,5 @@ const createUniqueRandomIntGenerator = (min, max) => {
|
|
|
2896
3196
|
* Generated bundle index. Do not edit.
|
|
2897
3197
|
*/
|
|
2898
3198
|
|
|
2899
|
-
export { AudioExtList, CHARACTER_DATA_EMPTY, COMMUNICATE_MICRO_KEY_GET_ALL_MESSAGE, COMMUNICATE_MICRO_PREFIX_TYPE, DEFAULT_START_PAGE_0, DocumentExtList, ENCODE_URI_PATTERN, ERROR_MESSAGE_EMPTY_VALID, ERROR_MESSAGE_MAX_LENGTH, ERROR_MESSAGE_MAX_VALID, ERROR_MESSAGE_MIN_LENGTH, ERROR_MESSAGE_MIN_VALID, ERROR_MESSAGE_PATTEN_VALID, ExcelExtList, ImageExtList, LINK_IMAGE_ERROR_TOKEN_INJECT, PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT, PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT, UtilsCache, UtilsCommunicateMicro, UtilsCommunicateMicroKeyGlobal, UtilsHttpParamsRequest, UtilsHttpParamsRequestInstance, UtilsKeyCodeConstant, UtilsLanguageConstants, UtilsUrlSearchParams, VideoExtList, base64Decode, base64Encode, capitalize, checkMouseOverInContainer, checkViewInScreen, cloneDeep, cloneIBoundingClientRect, colorContrastFromOrigin, colorStepContrastFromOrigin, convertBase64ToBlob, convertBlobToFile, convertFileToBase64, convertFileToBase64_ObjectUrl, convertHtmlToDivBlocks, convertObjectToSignal, convertSignalToObject, convertUrlToFile, createUniqueRandomIntGenerator, decodeEscapeHtml, decodeURI, decrypt, decrypt3rd, deleteUnicode, downloadFileByUrl, downloadFileByUrlUseXmlRequest, downloadImageFromELement, encodeURI, encrypt, encrypt3rd, endCodeUrl, escapeHtml, firstLetterToUpperCase, formatDate, formatNumber, formatTextCompare, fullNameFormat, generateInterface, get, getColorById, getDayjs, getDeltaFromHTML, getDeviceInfo, getDocumentByString, getDragEventByElement, getEventNameHandleClick, getFileExtension, getHTMLFromQuill, getKeyCacheByArrayObject, getLabelBySizeFile, getPlatFromBrowser, getSmartAxisScale, getViewport, groupBy, highlightByKeyword, insertContentWithRange, isDifferenceDay, isDifferenceMonth, isDifferenceYear, isEmbedFrame, isEmpty, isEqual, isIncludeAudioExtList, isIncludeDocumentExtList, isIncludeImageExtList, isIncludeVideoExtList, isNil, isTypeAudio, isTypeFile, isTypeImage, isTypeVideo, keyBy, listColorDefine, md5, omitBy, patternAccount, patternDomain, patternEmail, patternEmoji, patternEncodeUri, patternGetFieldByRuleFieldReplace, patternHostUrl, patternKey, patternMobilePhone, patternName, patternNameProfile, patternNameSpecial, patternNameUtf8, patternNumber, patternPem, patternPhone, patternPhoneNormal, patternRuleFieldReplace, patternTax, patternUrl, processPasteData, protectString, range, removeEmoji, revealString, rgbToHex, set, setCaretPosition, setDefaultTimeZone, setKeyCrypto, setKeyCrypto3rd, setStylesElement, uniqBy, updateFunctionCheckEmbedFrame, updateFunctionFormatDate, updateFunctionXssFilter, uppercaseByPosition, uuid, viewDataNumberByLanguage, xssFilter };
|
|
3199
|
+
export { AudioExtList, CHARACTER_DATA_EMPTY, COMMUNICATE_MICRO_KEY_GET_ALL_MESSAGE, COMMUNICATE_MICRO_PREFIX_TYPE, DEFAULT_START_PAGE_0, DocumentExtList, ENCODE_URI_PATTERN, ERROR_MESSAGE_EMPTY_VALID, ERROR_MESSAGE_MAX_LENGTH, ERROR_MESSAGE_MAX_VALID, ERROR_MESSAGE_MIN_LENGTH, ERROR_MESSAGE_MIN_VALID, ERROR_MESSAGE_PATTEN_VALID, ExcelExtList, ImageExtList, LINK_IMAGE_ERROR_TOKEN_INJECT, PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT, PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT, UtilsCache, UtilsCommunicateMicro, UtilsCommunicateMicroKeyGlobal, UtilsHttpParamsRequest, UtilsHttpParamsRequestInstance, UtilsKeyCodeConstant, UtilsLanguageConstants, UtilsUrlSearchParams, VideoExtList, base64Decode, base64Encode, capitalize, checkMouseOverInContainer, checkViewInScreen, cloneDeep, cloneIBoundingClientRect, colorContrastFromOrigin, colorStepContrastFromOrigin, convertBase64ToBlob, convertBlobToFile, convertFileToBase64, convertFileToBase64_ObjectUrl, convertHtmlToDivBlocks, convertObjectToSignal, convertSignalToObject, convertUrlToFile, createUniqueRandomIntGenerator, decodeEscapeHtml, decodeURI, decrypt, decrypt3rd, deleteUnicode, downloadFileByUrl, downloadFileByUrlUseXmlRequest, downloadImageFromELement, encodeURI, encrypt, encrypt3rd, endCodeUrl, escapeHtml, firstLetterToUpperCase, formatDate, formatNumber, formatTextCompare, fullNameFormat, generateInterface, get, getColorById, getDayjs, getDeltaFromHTML, getDeviceInfo, getDocumentByString, getDragEventByElement, getEventNameHandleClick, getFileExtension, getHTMLFromQuill, getKeyCacheByArrayObject, getLabelBySizeFile, getPlatFromBrowser, getSmartAxisScale, getViewport, groupBy, hasDangerousConstructorName, highlightByKeyword, insertContentWithRange, isArrayObject, isAsyncObject, isBrowserAPIObject, isBrowserGlobalObject, isBuiltInObject, isDOMObject, isDangerousObject, isDayjsObject, isDifferenceDay, isDifferenceMonth, isDifferenceYear, isEmbedFrame, isEmpty, isEqual, isFalsy, isFileObject, isFrameworkObject, isIncludeAudioExtList, isIncludeDocumentExtList, isIncludeImageExtList, isIncludeVideoExtList, isMapObject, isNil, isReturnAsIsObject, isSafeToProcess, isSetObject, isSkippableObject, isSpecialObject, isTruthy, isTypeAudio, isTypeFile, isTypeImage, isTypeVideo, keyBy, listColorDefine, md5, omitBy, patternAccount, patternDomain, patternEmail, patternEmoji, patternEncodeUri, patternGetFieldByRuleFieldReplace, patternHostUrl, patternKey, patternMobilePhone, patternName, patternNameProfile, patternNameSpecial, patternNameUtf8, patternNumber, patternPem, patternPhone, patternPhoneNormal, patternRuleFieldReplace, patternTax, patternUrl, processPasteData, protectString, range, removeEmoji, revealString, rgbToHex, set, setCaretPosition, setDefaultTimeZone, setKeyCrypto, setKeyCrypto3rd, setStylesElement, uniqBy, updateFunctionCheckEmbedFrame, updateFunctionFormatDate, updateFunctionXssFilter, uppercaseByPosition, uuid, viewDataNumberByLanguage, xssFilter };
|
|
2900
3200
|
//# sourceMappingURL=libs-ui-utils.mjs.map
|