@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.
@@ -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, Observable } from 'rxjs';
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 { isSignal, TemplateRef, ElementRef, signal, InjectionToken } from '@angular/core';
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
- while (isSignal(value)) {
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
- return value === null || value === '' || value === undefined || (typeof value === 'object' && (JSON.stringify(value) === '{}' || JSON.stringify(value) === '[]'));
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 (data instanceof File || data instanceof Blob || Object.prototype.toString.call(data) === '[object File]') {
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 TemplateRef || value instanceof ElementRef || value instanceof Element || value instanceof Promise || value instanceof Observable) {
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