@libs-ui/utils 0.2.246 → 0.2.248

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.
@@ -405,12 +405,44 @@ class UtilsHttpParamsRequest extends HttpParams {
405
405
 
406
406
  /* eslint-disable @typescript-eslint/no-explicit-any */
407
407
  /**Các hàm tương tự thư viện lodash */
408
+ /**
409
+ * Kiểm tra xem một giá trị có phải là null hoặc undefined hay không
410
+ * @param value Giá trị cần kiểm tra
411
+ * @returns true nếu giá trị là null hoặc undefined, false nếu không
412
+ * @example
413
+ * isNil(null); // true
414
+ * isNil(undefined); // true
415
+ * isNil(0); // false
416
+ * isNil('hello'); // false
417
+ */
408
418
  const isNil = (value) => {
409
419
  return value === null || value === undefined;
410
420
  };
421
+ /**
422
+ * Kiểm tra xem một giá trị có phải là rỗng hay không
423
+ * @param value Giá trị cần kiểm tra
424
+ * @returns true nếu giá trị là null, rỗng hoặc undefined, false nếu không
425
+ * @example
426
+ * isEmpty(null); // true
427
+ * isEmpty(''); // true
428
+ * isEmpty(undefined); // true
429
+ * isEmpty({}); // true
430
+ * isEmpty([]); // true
431
+ * isEmpty([1, 2, 3]); // false
432
+ * isEmpty({ a: 1 }); // false
433
+ */
411
434
  const isEmpty = (value) => {
412
435
  return value === null || value === '' || value === undefined || (typeof value === 'object' && (JSON.stringify(value) === '{}' || JSON.stringify(value) === '[]'));
413
436
  };
437
+ /**
438
+ * 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
439
+ * @param objData Đối tượng cần xử lý
440
+ * @param predicate Hàm điều kiện để kiểm tra giá trị của thuộc tính. Nếu hàm trả về true thì thuộc tính đó sẽ bị loại bỏ
441
+ * @returns Đối tượng mới sau khi đã loại bỏ các thuộc tính thỏa mãn điều kiện
442
+ * @example
443
+ * const obj = { a: 1, b: null, c: 3, d: undefined };
444
+ * omitBy(obj, isNil); // { a: 1, c: 3 }
445
+ */
414
446
  const omitBy = (objData, predicate) => {
415
447
  if (!objData || typeof objData !== 'object' || Array.isArray(objData)) {
416
448
  return objData;
@@ -459,6 +491,17 @@ const get = (obj, path, defaultValue = undefined, keepLastValueIfSignal) => {
459
491
  }
460
492
  return obj;
461
493
  };
494
+ /**
495
+ * Thiết lập giá trị cho một thuộc tính trong đối tượng theo đường dẫn chỉ định
496
+ * @param obj Đối tượng cần thiết lập giá trị
497
+ * @param path Đường dẫn đến thuộc tính, có thể là chuỗi (vd: 'a.b.c') hoặc mảng (vd: ['a', 'b', 'c'])
498
+ * @param value Giá trị cần thiết lập
499
+ * @returns Đối tượng sau khi đã thiết lập giá trị
500
+ * @throws Error nếu tham số đầu tiên không phải là đối tượng
501
+ * @example
502
+ * const obj = { a: { b: 1 } };
503
+ * set(obj, 'a.b', 2); // { a: { b: 2 } }
504
+ */
462
505
  const set = (obj, path, value) => {
463
506
  if (!obj || (typeof obj !== "object" && !isSignal(obj)) || (isSignal(obj) && typeof obj() !== "object")) {
464
507
  throw new Error("The first argument must be an object");
@@ -503,6 +546,22 @@ const set = (obj, path, value) => {
503
546
  });
504
547
  return obj;
505
548
  };
549
+ /**
550
+ * Tạo một bản sao sâu của một đối tượng hoặc giá trị bất kỳ
551
+ * @param data Dữ liệu cần sao chép
552
+ * @param options Tùy chọn cấu hình
553
+ * @param options.ignoreSignal Nếu true, sẽ không sao chép các signal mà trả về signal gốc
554
+ * @param seen WeakMap để theo dõi các tham chiếu đã được sao chép, tránh lặp vô hạn với các tham chiếu vòng
555
+ * @returns Bản sao sâu của dữ liệu đầu vào
556
+ * @example
557
+ * const obj = {
558
+ * a: 1,
559
+ * b: { c: 2 },
560
+ * d: [1, 2, 3]
561
+ * };
562
+ * const clone = cloneDeep(obj);
563
+ * // clone là một bản sao hoàn toàn độc lập của obj
564
+ */
506
565
  const cloneDeep = (data, options = { ignoreSignal: false }, seen = new WeakMap()) => {
507
566
  if (data === null || (typeof data !== 'object' && !isSignal(data))) {
508
567
  return data;
@@ -570,6 +629,22 @@ const cloneDeep = (data, options = { ignoreSignal: false }, seen = new WeakMap()
570
629
  }
571
630
  return result;
572
631
  };
632
+ /**
633
+ * Chuyển đổi một mảng các đối tượng thành một đối tượng với khóa được chỉ định
634
+ * @param data Mảng các đối tượng cần chuyển đổi
635
+ * @param key Tên thuộc tính được sử dụng làm khóa trong đối tượng kết quả
636
+ * @returns Đối tượng với các giá trị từ mảng được đánh key theo thuộc tính đã chỉ định
637
+ * @example
638
+ * const data = [
639
+ * { id: 1, name: 'John' },
640
+ * { id: 2, name: 'Jane' }
641
+ * ];
642
+ * keyBy(data, 'id');
643
+ * // Kết quả: {
644
+ * // '1': { id: 1, name: 'John' },
645
+ * // '2': { id: 2, name: 'Jane' }
646
+ * // }
647
+ */
573
648
  const keyBy = (data, key) => {
574
649
  if (!data || !data.length || !key) {
575
650
  return {};
@@ -583,6 +658,27 @@ const keyBy = (data, key) => {
583
658
  return dir;
584
659
  }, {});
585
660
  };
661
+ /**
662
+ * Nhóm các đối tượng trong một mảng thành các nhóm dựa trên một thuộc tính cụ thể
663
+ * @param data Mảng các đối tượng cần nhóm
664
+ * @param key Tên thuộc tính được sử dụng làm khóa nhóm
665
+ * @returns Đối tượng với các giá trị từ mảng được nhóm theo thuộc tính đã chỉ định
666
+ * @example
667
+ * const data = [
668
+ * { id: 1, name: 'John' },
669
+ * { id: 2, name: 'Jane' },
670
+ * { id: 1, name: 'John' }
671
+ * ];
672
+ * groupBy(data, 'id');
673
+ * // Kết quả: {
674
+ * // '1': [
675
+ * // { id: 1, name: 'John' },
676
+ * // { id: 1, name: 'John' }
677
+ * // ],
678
+ * // '2': [
679
+ * // { id: 2, name: 'Jane' }
680
+ * // }
681
+ */
586
682
  const groupBy = (data, key) => {
587
683
  if (!data || !Object.keys(data).length || !key) {
588
684
  return {};
@@ -599,6 +695,18 @@ const groupBy = (data, key) => {
599
695
  return dir;
600
696
  }, {});
601
697
  };
698
+ /**
699
+ * Tạo một mảng các số từ giá trị bắt đầu đến giá trị kết thúc với bước nhảy tùy chọn
700
+ * @param start Giá trị bắt đầu của dãy số. Nếu chỉ có một tham số, đây sẽ là giá trị kết thúc và giá trị bắt đầu sẽ là 0
701
+ * @param end Giá trị kết thúc của dãy số (tùy chọn)
702
+ * @param step Bước nhảy giữa các số trong dãy (tùy chọn). Mặc định là 1 nếu end > start, -1 nếu end < start
703
+ * @returns Mảng các số từ start đến end với bước nhảy step
704
+ * @example
705
+ * range(4); // [0, 1, 2, 3]
706
+ * range(1, 5); // [1, 2, 3, 4]
707
+ * range(0, 20, 5); // [0, 5, 10, 15]
708
+ * range(5, 2); // [5, 4, 3]
709
+ */
602
710
  const range = (start, end, step) => {
603
711
  if (end === undefined || end === null) {
604
712
  end = start;
@@ -628,11 +736,30 @@ const range = (start, end, step) => {
628
736
  }
629
737
  return arr;
630
738
  };
739
+ /**
740
+ * So sánh hai giá trị bất kỳ có bằng nhau hay không
741
+ * @param value1 Giá trị thứ nhất cần so sánh
742
+ * @param value2 Giá trị thứ hai cần so sánh
743
+ * @param exactlyPosition Có so sánh chính xác vị trí các phần tử trong mảng hay không
744
+ * @returns true nếu hai giá trị bằng nhau, false nếu không bằng nhau
745
+ * @example
746
+ * isEqual([1,2,3], [1,2,3]); // true
747
+ * isEqual([1,2,3], [3,2,1]); // true khi exactlyPosition = false
748
+ * isEqual([1,2,3], [3,2,1]); // false khi exactlyPosition = true
749
+ * isEqual({a:1}, {a:1}); // true
750
+ */
631
751
  const isEqual = (value1, value2, exactlyPosition = false) => {
632
752
  if (value1 === value2 || (value1 === null && value2 === null) || (value1 === undefined && value2 === undefined)) {
633
753
  return true;
634
754
  }
635
- if (typeof value1 !== 'object' || typeof value2 !== 'object' || (Array.isArray(value1) && !Array.isArray(value2))) {
755
+ // Handle signals
756
+ while (isSignal(value1)) {
757
+ value1 = value1();
758
+ }
759
+ while (isSignal(value2)) {
760
+ value2 = value2();
761
+ }
762
+ if (typeof value1 !== 'object' || typeof value2 !== 'object' || (Array.isArray(value1) && !Array.isArray(value2)) || (!Array.isArray(value1) && Array.isArray(value2))) {
636
763
  return false;
637
764
  }
638
765
  if (Array.isArray(value1)) {
@@ -649,6 +776,22 @@ const isEqual = (value1, value2, exactlyPosition = false) => {
649
776
  }
650
777
  return !Object.keys(value1).some((key) => !isEqual(value1[key], value2[key]));
651
778
  };
779
+ /**
780
+ * Loại bỏ các phần tử trùng lặp trong mảng dựa trên một thuộc tính chỉ định
781
+ * @param data Mảng dữ liệu cần xử lý
782
+ * @param key Tên thuộc tính dùng để so sánh trùng lặp. Nếu không có key thì so sánh trực tiếp giá trị
783
+ * @returns Mảng mới chứa các phần tử không trùng lặp
784
+ * @example
785
+ * const arr = [
786
+ * { id: 1, name: 'A' },
787
+ * { id: 2, name: 'B' },
788
+ * { id: 1, name: 'C' }
789
+ * ];
790
+ * uniqBy(arr, 'id'); // [{ id: 1, name: 'A' }, { id: 2, name: 'B' }]
791
+ *
792
+ * const numbers = [1, 2, 2, 3, 3];
793
+ * uniqBy(numbers); // [1, 2, 3]
794
+ */
652
795
  const uniqBy = (data, key) => {
653
796
  if (!key || !data || !data.length || typeof data[0] !== 'object') {
654
797
  return Array.from(new Set(data));
@@ -1882,7 +2025,16 @@ const getDayjs = (config) => {
1882
2025
  if (!config.date) {
1883
2026
  return undefined;
1884
2027
  }
1885
- const { date, utc, formatOfDate } = config;
2028
+ let { date, utc, formatOfDate } = config;
2029
+ while (isSignal(date)) {
2030
+ date = date();
2031
+ }
2032
+ while (isSignal(utc)) {
2033
+ utc = utc();
2034
+ }
2035
+ while (isSignal(formatOfDate)) {
2036
+ formatOfDate = formatOfDate();
2037
+ }
1886
2038
  if (utc) {
1887
2039
  if (formatOfDate) {
1888
2040
  return dayjs(date, formatOfDate).utc();