@libs-ui/utils 0.2.306-6 → 0.2.306-8
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/dangerous-object.d.ts +75 -0
- package/esm2022/dangerous-object.mjs +143 -0
- package/esm2022/dom.mjs +1 -1
- package/esm2022/helpers.mjs +94 -23
- package/esm2022/index.mjs +2 -1
- package/esm2022/two-way-signal-object.mjs +27 -27
- package/fesm2022/libs-ui-utils.mjs +354 -144
- package/fesm2022/libs-ui-utils.mjs.map +1 -1
- package/helpers.d.ts +52 -3
- package/index.d.ts +1 -0
- package/package.json +2 -2
|
@@ -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';
|
|
@@ -629,6 +629,145 @@ const uuid = () => {
|
|
|
629
629
|
return md5(shuffledString);
|
|
630
630
|
};
|
|
631
631
|
|
|
632
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
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;
|
|
643
|
+
}
|
|
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;
|
|
652
|
+
}
|
|
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;
|
|
661
|
+
}
|
|
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;
|
|
670
|
+
}
|
|
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;
|
|
681
|
+
}
|
|
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;
|
|
690
|
+
}
|
|
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;
|
|
699
|
+
}
|
|
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;
|
|
708
|
+
}
|
|
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;
|
|
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
|
+
};
|
|
770
|
+
|
|
632
771
|
let key = '12~@#loqwsxacva(3rdhaq12';
|
|
633
772
|
/**
|
|
634
773
|
* @description Thiết lập key mã hóa
|
|
@@ -1541,6 +1680,128 @@ class UtilsHttpParamsRequest extends HttpParams {
|
|
|
1541
1680
|
// "pathVariable-name": '124',
|
|
1542
1681
|
// };
|
|
1543
1682
|
|
|
1683
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1684
|
+
/**
|
|
1685
|
+
* Chuyển đổi một đối tượng hoặc giá trị thành signal
|
|
1686
|
+
* @param data Dữ liệu cần chuyển đổi thành signal
|
|
1687
|
+
* @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.
|
|
1688
|
+
* Đặt false nếu muốn giữ nguyên tham chiếu đến dữ liệu gốc.
|
|
1689
|
+
* Nếu muốn sao chép sâu đối tượng signal thì đặt cloneDeepIfNotSignal là true và acceptConvertObjectInnerWritableSignal là true.
|
|
1690
|
+
* @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.
|
|
1691
|
+
* Đặt true nếu muốn bọc các giá trị nguyên thủy trong signal.
|
|
1692
|
+
* @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.
|
|
1693
|
+
* Đặ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.
|
|
1694
|
+
* @returns Dữ liệu đã được chuyển đổi theo kiểu T
|
|
1695
|
+
*/
|
|
1696
|
+
const convertObjectToSignal = (data, cloneDeepIfNotSignal = true, isSignalPrimitiveType = false, acceptConvertObjectInnerWritableSignal = false, seen = new WeakMap()) => {
|
|
1697
|
+
if ((data === null || typeof data !== 'object') && !isSignal(data)) {
|
|
1698
|
+
return (isSignalPrimitiveType ? signal(data) : data);
|
|
1699
|
+
}
|
|
1700
|
+
if (seen.has(data)) {
|
|
1701
|
+
return seen.get(data);
|
|
1702
|
+
}
|
|
1703
|
+
if (isSignal(data)) {
|
|
1704
|
+
if (!acceptConvertObjectInnerWritableSignal) {
|
|
1705
|
+
return data;
|
|
1706
|
+
}
|
|
1707
|
+
seen.set(data, convertObjectToSignal(data(), cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal, seen));
|
|
1708
|
+
return seen.get(data);
|
|
1709
|
+
}
|
|
1710
|
+
if (isArrayObject(data)) {
|
|
1711
|
+
seen.set(data, signal(data.map((item) => convertObjectToSignal(item, cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal, seen))));
|
|
1712
|
+
return seen.get(data);
|
|
1713
|
+
}
|
|
1714
|
+
if (isMapObject(data)) {
|
|
1715
|
+
const mapCopy = new Map();
|
|
1716
|
+
Array.from(data.keys()).forEach((key) => {
|
|
1717
|
+
mapCopy.set(key, convertObjectToSignal(data.get(key), cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal));
|
|
1718
|
+
});
|
|
1719
|
+
seen.set(data, signal(mapCopy));
|
|
1720
|
+
return seen.get(data);
|
|
1721
|
+
}
|
|
1722
|
+
// Bỏ qua các đối tượng async
|
|
1723
|
+
if (isAsyncObject(data)) {
|
|
1724
|
+
return data;
|
|
1725
|
+
}
|
|
1726
|
+
data = signal(cloneDeepIfNotSignal ? { ...data } : data);
|
|
1727
|
+
seen.set(data, data);
|
|
1728
|
+
for (const key in data()) {
|
|
1729
|
+
const value = data()[key];
|
|
1730
|
+
// Bỏ qua các đối tượng nguy hiểm và đặc biệt
|
|
1731
|
+
if (isReturnAsIsObject(value)) {
|
|
1732
|
+
continue;
|
|
1733
|
+
}
|
|
1734
|
+
if (Object.prototype.hasOwnProperty.call(data(), key)) {
|
|
1735
|
+
data()[key] = convertObjectToSignal(value, cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal);
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
return data;
|
|
1739
|
+
};
|
|
1740
|
+
const convertSignalToObject = (data, isCloneDeep = true, seen = new WeakMap()) => {
|
|
1741
|
+
let ignoreCheckSeenHasDataAfterWhile = false;
|
|
1742
|
+
while (isSignal(data) && !seen.has(data)) {
|
|
1743
|
+
const dataConvert = data();
|
|
1744
|
+
if (typeof dataConvert === 'object') {
|
|
1745
|
+
if (dataConvert === null || isReturnAsIsObject(dataConvert)) {
|
|
1746
|
+
return dataConvert;
|
|
1747
|
+
}
|
|
1748
|
+
seen.set(dataConvert, dataConvert);
|
|
1749
|
+
data = dataConvert;
|
|
1750
|
+
ignoreCheckSeenHasDataAfterWhile = true;
|
|
1751
|
+
break;
|
|
1752
|
+
}
|
|
1753
|
+
seen.set(data, dataConvert);
|
|
1754
|
+
data = dataConvert;
|
|
1755
|
+
}
|
|
1756
|
+
if (data === null || typeof data === 'function' || typeof data !== 'object' || isReturnAsIsObject(data)) {
|
|
1757
|
+
return data;
|
|
1758
|
+
}
|
|
1759
|
+
if (!ignoreCheckSeenHasDataAfterWhile && seen.has(data)) {
|
|
1760
|
+
return seen.get(data);
|
|
1761
|
+
}
|
|
1762
|
+
if (isArrayObject(data)) {
|
|
1763
|
+
if (!isSignal(data[0])) {
|
|
1764
|
+
return data;
|
|
1765
|
+
}
|
|
1766
|
+
seen.set(data, data.map((item) => convertSignalToObject(isCloneDeep ? cloneDeep(item) : item, isCloneDeep, seen)));
|
|
1767
|
+
return seen.get(data);
|
|
1768
|
+
}
|
|
1769
|
+
if (isMapObject(data)) {
|
|
1770
|
+
const mapCopy = new Map();
|
|
1771
|
+
Array.from(data.keys()).forEach((key) => {
|
|
1772
|
+
mapCopy.set(key, convertSignalToObject(isCloneDeep ? cloneDeep(data.get(key)) : data.get(key), isCloneDeep));
|
|
1773
|
+
});
|
|
1774
|
+
seen.set(data, mapCopy);
|
|
1775
|
+
return seen.get(data);
|
|
1776
|
+
}
|
|
1777
|
+
if (isSetObject(data)) {
|
|
1778
|
+
const setCopy = new Set();
|
|
1779
|
+
Array.from(data.values()).forEach((value) => {
|
|
1780
|
+
setCopy.add(convertSignalToObject(isCloneDeep ? cloneDeep(value) : value, isCloneDeep));
|
|
1781
|
+
});
|
|
1782
|
+
seen.set(data, setCopy);
|
|
1783
|
+
return seen.get(data);
|
|
1784
|
+
}
|
|
1785
|
+
// Bỏ qua các đối tượng nguy hiểm và đặc biệt
|
|
1786
|
+
if (isReturnAsIsObject(data)) {
|
|
1787
|
+
return data;
|
|
1788
|
+
}
|
|
1789
|
+
const result = isCloneDeep ? {} : data;
|
|
1790
|
+
seen.set(data, result);
|
|
1791
|
+
for (const key in data) {
|
|
1792
|
+
const value = data[key];
|
|
1793
|
+
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1794
|
+
// Bỏ qua các đối tượng nguy hiểm để tránh maximum call stack
|
|
1795
|
+
if (isReturnAsIsObject(value)) {
|
|
1796
|
+
result[key] = value;
|
|
1797
|
+
continue;
|
|
1798
|
+
}
|
|
1799
|
+
result[key] = convertSignalToObject(isCloneDeep ? cloneDeep(value) : value, isCloneDeep);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
return result;
|
|
1803
|
+
};
|
|
1804
|
+
|
|
1544
1805
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1545
1806
|
/**Các hàm tương tự thư viện lodash */
|
|
1546
1807
|
/**
|
|
@@ -1553,7 +1814,10 @@ class UtilsHttpParamsRequest extends HttpParams {
|
|
|
1553
1814
|
* isNil(0); // false
|
|
1554
1815
|
* isNil('hello'); // false
|
|
1555
1816
|
*/
|
|
1556
|
-
const isNil = (value) => {
|
|
1817
|
+
const isNil = (value, options) => {
|
|
1818
|
+
if (!options?.ignoreUnWrapSignal) {
|
|
1819
|
+
value = convertSignalToObject(value);
|
|
1820
|
+
}
|
|
1557
1821
|
return value === null || value === undefined;
|
|
1558
1822
|
};
|
|
1559
1823
|
/**
|
|
@@ -1569,11 +1833,75 @@ const isNil = (value) => {
|
|
|
1569
1833
|
* isEmpty([1, 2, 3]); // false
|
|
1570
1834
|
* isEmpty({ a: 1 }); // false
|
|
1571
1835
|
*/
|
|
1572
|
-
const isEmpty = (value) => {
|
|
1573
|
-
|
|
1574
|
-
value = value
|
|
1836
|
+
const isEmpty = (value, options) => {
|
|
1837
|
+
if (!options?.ignoreUnWrapSignal) {
|
|
1838
|
+
value = convertSignalToObject(value);
|
|
1839
|
+
}
|
|
1840
|
+
if (options?.ignoreCheckFalsy) {
|
|
1841
|
+
return isEmptyTypeObject(value);
|
|
1575
1842
|
}
|
|
1576
|
-
|
|
1843
|
+
const valueIsFalsy = isFalsy(value, { ignoreUnWrapSignal: options?.ignoreUnWrapSignal, ignoreZero: true, ignoreCheckString: options?.ignoreCheckString });
|
|
1844
|
+
if (options?.ignoreCheckTypeObj) {
|
|
1845
|
+
return valueIsFalsy;
|
|
1846
|
+
}
|
|
1847
|
+
return valueIsFalsy || isEmptyTypeObject(value);
|
|
1848
|
+
};
|
|
1849
|
+
/**
|
|
1850
|
+
* Kiểm tra xem một giá trị có phải là object rỗng hay không
|
|
1851
|
+
* @param value Giá trị cần kiểm tra
|
|
1852
|
+
* @returns true nếu giá trị là object rỗng, false nếu không
|
|
1853
|
+
* @example
|
|
1854
|
+
* isEmptyTypeObject({}); // true
|
|
1855
|
+
* isEmptyTypeObject({ a: 1 }); // false
|
|
1856
|
+
*/
|
|
1857
|
+
const isEmptyTypeObject = (value) => {
|
|
1858
|
+
return typeof value === 'object' && (JSON.stringify(value) === '{}' || JSON.stringify(value) === '[]');
|
|
1859
|
+
};
|
|
1860
|
+
/**
|
|
1861
|
+
* Kiểm tra xem một giá trị có phải là null, rỗng, undefined hoặc 0 hay không
|
|
1862
|
+
* @param value Giá trị cần kiểm tra
|
|
1863
|
+
* @param options Cấu hình tùy chọn
|
|
1864
|
+
* @param options.ignoreZero Nếu true, sẽ không kiểm tra giá trị 0
|
|
1865
|
+
* @returns true nếu giá trị là null, rỗng, undefined hoặc 0, false nếu không
|
|
1866
|
+
* @example
|
|
1867
|
+
* isTruthy(null); // false
|
|
1868
|
+
* isTruthy(''); // false
|
|
1869
|
+
* isTruthy(undefined); // false
|
|
1870
|
+
* isTruthy(0); // false
|
|
1871
|
+
* isTruthy({}); // false
|
|
1872
|
+
* isTruthy(0, { ignoreZero: true }); // true
|
|
1873
|
+
*/
|
|
1874
|
+
const isTruthy = (value, options) => {
|
|
1875
|
+
return !isFalsy(value, options);
|
|
1876
|
+
};
|
|
1877
|
+
/**
|
|
1878
|
+
* Kiểm tra xem một giá trị có phải là null, rỗng, undefined hoặc 0 hay không
|
|
1879
|
+
* @param value Giá trị cần kiểm tra
|
|
1880
|
+
* @param options Cấu hình tùy chọn
|
|
1881
|
+
* @param options.ignoreZero Nếu true, sẽ không kiểm tra giá trị 0
|
|
1882
|
+
* @returns true nếu giá trị là null, rỗng, undefined hoặc 0, false nếu không
|
|
1883
|
+
* @example
|
|
1884
|
+
* isFalsy(null); // true
|
|
1885
|
+
* isFalsy(''); // true
|
|
1886
|
+
* isFalsy(undefined); // true
|
|
1887
|
+
* isFalsy(0); // true
|
|
1888
|
+
* isFalsy({}); // false
|
|
1889
|
+
* isFalsy(0, { ignoreZero: true }); // false
|
|
1890
|
+
*/
|
|
1891
|
+
const isFalsy = (value, options) => {
|
|
1892
|
+
if (!options?.ignoreUnWrapSignal) {
|
|
1893
|
+
value = convertSignalToObject(value);
|
|
1894
|
+
}
|
|
1895
|
+
if (isNil(value, { ignoreUnWrapSignal: options?.ignoreUnWrapSignal })) {
|
|
1896
|
+
return true;
|
|
1897
|
+
}
|
|
1898
|
+
if (options?.ignoreZero) {
|
|
1899
|
+
return value === '';
|
|
1900
|
+
}
|
|
1901
|
+
if (options?.ignoreCheckString) {
|
|
1902
|
+
return value === 0;
|
|
1903
|
+
}
|
|
1904
|
+
return value === '' || value === 0;
|
|
1577
1905
|
};
|
|
1578
1906
|
/**
|
|
1579
1907
|
* 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
|
|
@@ -1713,7 +2041,7 @@ const get = (obj, path, defaultValue, keepLastValueIfSignal) => {
|
|
|
1713
2041
|
* const obj = { a: { b: 1 } };
|
|
1714
2042
|
* set(obj, 'a.b', 2); // { a: { b: 2 } }
|
|
1715
2043
|
*/
|
|
1716
|
-
const set = (obj, path, value) => {
|
|
2044
|
+
const set = (obj, path, value, options) => {
|
|
1717
2045
|
if (!obj || (typeof obj !== 'object' && !isSignal(obj)) || (isSignal(obj) && typeof obj() !== 'object')) {
|
|
1718
2046
|
throw new Error('The first argument must be an object');
|
|
1719
2047
|
}
|
|
@@ -1733,7 +2061,7 @@ const set = (obj, path, value) => {
|
|
|
1733
2061
|
if (!(key in currentObjectByKey) || (typeof currentObjectByKey[key] !== 'object' && !isSignal(currentObjectByKey[key]))) {
|
|
1734
2062
|
const nextKey = pathArray[index + 1];
|
|
1735
2063
|
key = key.replace(/\[(\d+)]/g, '$1');
|
|
1736
|
-
currentObjectByKey[key] = /\[(\d+)]/g.test(nextKey) ? [] : {};
|
|
2064
|
+
currentObjectByKey[key] = /\[(\d+)]/g.test(nextKey) ? (options?.valueDefaultPathArrayUndefined ?? []) : (options?.valueDefaultPathObjectUndefined ?? {});
|
|
1737
2065
|
}
|
|
1738
2066
|
currentObjectByKey = key ? currentObjectByKey[key] : currentObjectByKey;
|
|
1739
2067
|
preObjectByKey = currentObjectByKey;
|
|
@@ -1792,7 +2120,7 @@ const set = (obj, path, value) => {
|
|
|
1792
2120
|
* // clone là một bản sao hoàn toàn độc lập của obj
|
|
1793
2121
|
*/
|
|
1794
2122
|
const cloneDeep = (data, options = { ignoreSignal: false }, seen = new WeakMap()) => {
|
|
1795
|
-
if (data === null || (typeof data !== 'object' && !isSignal(data))) {
|
|
2123
|
+
if (data === null || (typeof data !== 'object' && !isSignal(data)) || isDangerousObject(data)) {
|
|
1796
2124
|
return data;
|
|
1797
2125
|
}
|
|
1798
2126
|
if (seen.has(data)) {
|
|
@@ -1830,10 +2158,7 @@ const cloneDeep = (data, options = { ignoreSignal: false }, seen = new WeakMap()
|
|
|
1830
2158
|
seen.set(data, data.map((item) => cloneDeep(item, options, seen)));
|
|
1831
2159
|
return seen.get(data);
|
|
1832
2160
|
}
|
|
1833
|
-
if (
|
|
1834
|
-
return data;
|
|
1835
|
-
}
|
|
1836
|
-
if (data instanceof TemplateRef || data instanceof ElementRef || data instanceof Element || data instanceof Promise || data instanceof Observable) {
|
|
2161
|
+
if (isReturnAsIsObject(data)) {
|
|
1837
2162
|
return data;
|
|
1838
2163
|
}
|
|
1839
2164
|
if (isSignal(data)) {
|
|
@@ -1851,11 +2176,19 @@ const cloneDeep = (data, options = { ignoreSignal: false }, seen = new WeakMap()
|
|
|
1851
2176
|
result[key] = new UtilsHttpParamsRequest(undefined, value);
|
|
1852
2177
|
continue;
|
|
1853
2178
|
}
|
|
2179
|
+
if (value instanceof Date) {
|
|
2180
|
+
result[key] = new Date(value.getTime());
|
|
2181
|
+
continue;
|
|
2182
|
+
}
|
|
1854
2183
|
if (dayjs.isDayjs(value)) {
|
|
1855
2184
|
result[key] = getDayjs({ date: value.valueOf() });
|
|
1856
2185
|
continue;
|
|
1857
2186
|
}
|
|
1858
|
-
if (value instanceof
|
|
2187
|
+
if (value instanceof RegExp) {
|
|
2188
|
+
result[key] = new RegExp(value.source, value.flags);
|
|
2189
|
+
continue;
|
|
2190
|
+
}
|
|
2191
|
+
if (isReturnAsIsObject(data)) {
|
|
1859
2192
|
result[key] = value;
|
|
1860
2193
|
continue;
|
|
1861
2194
|
}
|
|
@@ -1987,6 +2320,11 @@ const range = (start, end, step) => {
|
|
|
1987
2320
|
* isEqual({a:1}, {a:1}); // true
|
|
1988
2321
|
*/
|
|
1989
2322
|
const isEqual = (value1, value2, options) => {
|
|
2323
|
+
// Handle signals
|
|
2324
|
+
if (!options?.ignoreUnWrapSignal) {
|
|
2325
|
+
value1 = convertSignalToObject(value1);
|
|
2326
|
+
value2 = convertSignalToObject(value2);
|
|
2327
|
+
}
|
|
1990
2328
|
const { exactlyPosition = false, ignoreExactlyDataType = false } = options || {};
|
|
1991
2329
|
if (value1 === value2 || (value1 === null && value2 === null) || (value1 === undefined && value2 === undefined)) {
|
|
1992
2330
|
return true;
|
|
@@ -1994,13 +2332,6 @@ const isEqual = (value1, value2, options) => {
|
|
|
1994
2332
|
if (ignoreExactlyDataType) {
|
|
1995
2333
|
return isEqual(isNil(value1) ? undefined : `${value1}`, isNil(value2) ? undefined : `${value2}`);
|
|
1996
2334
|
}
|
|
1997
|
-
// Handle signals
|
|
1998
|
-
while (isSignal(value1)) {
|
|
1999
|
-
value1 = value1();
|
|
2000
|
-
}
|
|
2001
|
-
while (isSignal(value2)) {
|
|
2002
|
-
value2 = value2();
|
|
2003
|
-
}
|
|
2004
2335
|
if (typeof value1 !== 'object' || typeof value2 !== 'object' || (Array.isArray(value1) && !Array.isArray(value2)) || (!Array.isArray(value1) && Array.isArray(value2))) {
|
|
2005
2336
|
return false;
|
|
2006
2337
|
}
|
|
@@ -2460,127 +2791,6 @@ const xssFilter = async (data) => {
|
|
|
2460
2791
|
return await functionXssFilter(data);
|
|
2461
2792
|
};
|
|
2462
2793
|
|
|
2463
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2464
|
-
/**
|
|
2465
|
-
* Chuyển đổi một đối tượng hoặc giá trị thành signal
|
|
2466
|
-
* @param data Dữ liệu cần chuyển đổi thành signal
|
|
2467
|
-
* @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.
|
|
2468
|
-
* Đặt false nếu muốn giữ nguyên tham chiếu đến dữ liệu gốc.
|
|
2469
|
-
* Nếu muốn sao chép sâu đối tượng signal thì đặt cloneDeepIfNotSignal là true và acceptConvertObjectInnerWritableSignal là true.
|
|
2470
|
-
* @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.
|
|
2471
|
-
* Đặt true nếu muốn bọc các giá trị nguyên thủy trong signal.
|
|
2472
|
-
* @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.
|
|
2473
|
-
* Đặ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.
|
|
2474
|
-
* @returns Dữ liệu đã được chuyển đổi theo kiểu T
|
|
2475
|
-
*/
|
|
2476
|
-
const convertObjectToSignal = (data, cloneDeepIfNotSignal = true, isSignalPrimitiveType = false, acceptConvertObjectInnerWritableSignal = false, seen = new WeakMap()) => {
|
|
2477
|
-
if ((data === null || typeof data !== 'object') && !isSignal(data)) {
|
|
2478
|
-
return (isSignalPrimitiveType ? signal(data) : data);
|
|
2479
|
-
}
|
|
2480
|
-
if (seen.has(data)) {
|
|
2481
|
-
return seen.get(data);
|
|
2482
|
-
}
|
|
2483
|
-
if (isSignal(data)) {
|
|
2484
|
-
if (!acceptConvertObjectInnerWritableSignal) {
|
|
2485
|
-
return data;
|
|
2486
|
-
}
|
|
2487
|
-
seen.set(data, convertObjectToSignal(data(), cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal, seen));
|
|
2488
|
-
return seen.get(data);
|
|
2489
|
-
}
|
|
2490
|
-
if (Array.isArray(data)) {
|
|
2491
|
-
seen.set(data, signal(data.map((item) => convertObjectToSignal(item, cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal, seen))));
|
|
2492
|
-
return seen.get(data);
|
|
2493
|
-
}
|
|
2494
|
-
if (data instanceof Map) {
|
|
2495
|
-
const mapCopy = new Map();
|
|
2496
|
-
Array.from(data.keys()).forEach((key) => {
|
|
2497
|
-
mapCopy.set(key, convertObjectToSignal(data.get(key), cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal));
|
|
2498
|
-
});
|
|
2499
|
-
seen.set(data, signal(mapCopy));
|
|
2500
|
-
return seen.get(data);
|
|
2501
|
-
}
|
|
2502
|
-
if (data instanceof Promise || data instanceof Observable) {
|
|
2503
|
-
return data;
|
|
2504
|
-
}
|
|
2505
|
-
data = signal(cloneDeepIfNotSignal ? { ...data } : data);
|
|
2506
|
-
seen.set(data, data);
|
|
2507
|
-
for (const key in data()) {
|
|
2508
|
-
const value = data()[key];
|
|
2509
|
-
if (value instanceof TemplateRef ||
|
|
2510
|
-
value instanceof File ||
|
|
2511
|
-
value instanceof Blob ||
|
|
2512
|
-
Object.prototype.toString.call(value) === '[object File]' ||
|
|
2513
|
-
value instanceof ElementRef ||
|
|
2514
|
-
value instanceof Element ||
|
|
2515
|
-
value instanceof Date ||
|
|
2516
|
-
value instanceof RegExp ||
|
|
2517
|
-
value instanceof Set ||
|
|
2518
|
-
value instanceof Map ||
|
|
2519
|
-
value instanceof Promise ||
|
|
2520
|
-
value instanceof Observable ||
|
|
2521
|
-
value instanceof HttpParams) {
|
|
2522
|
-
continue;
|
|
2523
|
-
}
|
|
2524
|
-
if (Object.prototype.hasOwnProperty.call(data(), key)) {
|
|
2525
|
-
data()[key] = convertObjectToSignal(value, cloneDeepIfNotSignal, isSignalPrimitiveType, acceptConvertObjectInnerWritableSignal);
|
|
2526
|
-
}
|
|
2527
|
-
}
|
|
2528
|
-
return data;
|
|
2529
|
-
};
|
|
2530
|
-
const convertSignalToObject = (data, isCloneDeep = true, seen = new WeakMap()) => {
|
|
2531
|
-
let ignoreCheckSeenHasDataAfterWhile = false;
|
|
2532
|
-
while (isSignal(data) && !seen.has(data)) {
|
|
2533
|
-
const dataConvert = data();
|
|
2534
|
-
if (typeof dataConvert === 'object') {
|
|
2535
|
-
if (dataConvert === null) {
|
|
2536
|
-
return dataConvert;
|
|
2537
|
-
}
|
|
2538
|
-
seen.set(dataConvert, dataConvert);
|
|
2539
|
-
data = dataConvert;
|
|
2540
|
-
ignoreCheckSeenHasDataAfterWhile = true;
|
|
2541
|
-
break;
|
|
2542
|
-
}
|
|
2543
|
-
seen.set(data, dataConvert);
|
|
2544
|
-
data = dataConvert;
|
|
2545
|
-
}
|
|
2546
|
-
if (data === null || typeof data === 'function' || typeof data !== 'object') {
|
|
2547
|
-
return data;
|
|
2548
|
-
}
|
|
2549
|
-
if (!ignoreCheckSeenHasDataAfterWhile && seen.has(data)) {
|
|
2550
|
-
return seen.get(data);
|
|
2551
|
-
}
|
|
2552
|
-
if (Array.isArray(data)) {
|
|
2553
|
-
if (!isSignal(data[0])) {
|
|
2554
|
-
return data;
|
|
2555
|
-
}
|
|
2556
|
-
seen.set(data, data.map((item) => convertSignalToObject(isCloneDeep ? cloneDeep(item) : item, isCloneDeep, seen)));
|
|
2557
|
-
return seen.get(data);
|
|
2558
|
-
}
|
|
2559
|
-
if (data instanceof Map) {
|
|
2560
|
-
const mapCopy = new Map();
|
|
2561
|
-
Array.from(data.keys()).forEach((key) => {
|
|
2562
|
-
mapCopy.set(key, convertSignalToObject(isCloneDeep ? cloneDeep(data.get(key)) : data.get(key), isCloneDeep));
|
|
2563
|
-
});
|
|
2564
|
-
seen.set(data, mapCopy);
|
|
2565
|
-
return seen.get(data);
|
|
2566
|
-
}
|
|
2567
|
-
if (data instanceof File || data instanceof Blob || Object.prototype.toString.call(data) === '[object File]') {
|
|
2568
|
-
return data;
|
|
2569
|
-
}
|
|
2570
|
-
if (data instanceof TemplateRef || data instanceof ElementRef || data instanceof Element || data instanceof Promise || data instanceof Observable || data instanceof HttpParams) {
|
|
2571
|
-
return data;
|
|
2572
|
-
}
|
|
2573
|
-
const result = isCloneDeep ? {} : data;
|
|
2574
|
-
seen.set(data, result);
|
|
2575
|
-
for (const key in data) {
|
|
2576
|
-
const value = data[key];
|
|
2577
|
-
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
2578
|
-
result[key] = convertSignalToObject(isCloneDeep ? cloneDeep(value) : value, isCloneDeep);
|
|
2579
|
-
}
|
|
2580
|
-
}
|
|
2581
|
-
return result;
|
|
2582
|
-
};
|
|
2583
|
-
|
|
2584
2794
|
const ENCODE_URI_PATTERN = /%([0-9A-F]{2})/g;
|
|
2585
2795
|
const decodeURI = (value) => {
|
|
2586
2796
|
return decodeURIComponent(value
|
|
@@ -2992,5 +3202,5 @@ const createUniqueRandomIntGenerator = (min, max) => {
|
|
|
2992
3202
|
* Generated bundle index. Do not edit.
|
|
2993
3203
|
*/
|
|
2994
3204
|
|
|
2995
|
-
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 };
|
|
3205
|
+
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 };
|
|
2996
3206
|
//# sourceMappingURL=libs-ui-utils.mjs.map
|