@gateweb/react-utils 1.1.1 → 1.3.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.
@@ -1,5 +1,6 @@
1
1
  import { TExtractValueType } from './types.js';
2
2
  export * from './types.js';
3
+ import React from 'react';
3
4
 
4
5
  type CamelToPascal<S extends string> = S extends `${infer Head}${infer Tail}` ? `${Uppercase<Head>}${Tail}` : S;
5
6
  /**
@@ -279,8 +280,11 @@ declare const createEnumLikeObject: <T extends Record<string, {
279
280
  * console.log(result); // { result: true, data: { foo: 'bar' } }
280
281
  */
281
282
  declare const fakeApi: <T>(returnValue: T, result?: boolean, time?: number) => Promise<{
282
- result: boolean;
283
+ result: true;
283
284
  data: T;
285
+ } | {
286
+ result: false;
287
+ message: string;
284
288
  }>;
285
289
 
286
290
  /**
@@ -372,6 +376,30 @@ declare const omit: <T extends object, K extends [...(keyof T)[]]>(object: T, ..
372
376
  * const b = omitByValue(a, undefined, null); // { c: 3, d: 4 }
373
377
  */
374
378
  declare const omitByValue: <T extends object, K extends any[]>(object: T, ...values: K) => Pick<T, { [K2 in keyof T]: T[K2] extends K[number] ? never : K2; }[keyof T]>;
379
+ /**
380
+ * extract the object fields by the given keys
381
+ *
382
+ * @param object - the object to pick fields from
383
+ * @param keys - the keys to pick
384
+ *
385
+ * @example
386
+ *
387
+ * const a = { a: 1, b: 2, c: 3, d: 4 };
388
+ * const b = pick(a, 'a', 'b'); // { a: 1, b: 2 }
389
+ */
390
+ declare const pick: <T extends object, K extends [...(keyof T)[]]>(object: T, ...keys: K) => { [K2 in K[number]]: T[K2]; };
391
+ /**
392
+ * extract the object fields by the given values
393
+ *
394
+ * @param object - the object to pick fields from
395
+ * @param values - the values to pick
396
+ *
397
+ * @example
398
+ *
399
+ * const a = { a: 1, b: 2, c: 3, d: 4 };
400
+ * const b = pickByValue(a, 1, 2); // { a: 1, b: 2 }
401
+ */
402
+ declare const pickByValue: <T extends object, K extends any[]>(object: T, ...values: K) => Pick<T, { [K2 in keyof T]: T[K2] extends K[number] ? K2 : never; }[keyof T]>;
375
403
 
376
404
  /**
377
405
  * debounce function
@@ -403,6 +431,8 @@ declare const debounce: <P, R>(fn: (...args: P[]) => R, delay: number) => (...ar
403
431
  */
404
432
  declare const throttle: <P, R>(fn: (...args: P[]) => R, delay: number) => (...args: P[]) => R | undefined;
405
433
 
434
+ declare function mergeRefs<T = any>(refs: Array<React.MutableRefObject<T> | React.LegacyRef<T> | undefined | null>): React.RefCallback<T>;
435
+
406
436
  /**
407
437
  * 中文
408
438
  *
@@ -491,6 +521,61 @@ declare const isDateTimeString: (separator?: string) => RegExp;
491
521
  * isTimeString().test('12:00:00.123') // false
492
522
  */
493
523
  declare const isTimeString: () => RegExp;
524
+ /**
525
+ * 密碼複雜度檢查
526
+ *
527
+ * 預設密碼長度為 8 位,且包含大寫英文、小寫英文、數字、特殊字元
528
+ *
529
+ * @param options - 選項
530
+ *
531
+ * @example
532
+ *
533
+ * isValidPassword().test('123') // false
534
+ * isValidPassword().test('12345678') // false
535
+ * isValidPassword().test('1234567A') // false
536
+ * isValidPassword().test('123456Aa') // false
537
+ * isValidPassword().test('12345Aa!') // true
538
+ * isValidPassword({ minLength: 6 }).test('12345Aa!') // true
539
+ * isValidPassword({ minLength: 6, uppercase: false }).test('12345a!') // true
540
+ * isValidPassword({ minLength: 6, lowercase: false }).test('12345A!') // true
541
+ * isValidPassword({ minLength: 6, number: false }).test('ABCDEa!') // true
542
+ * isValidPassword({ minLength: 6, special: false }).test('ABCDEa1') // true
543
+ */
544
+ declare const isValidPassword: (options?: {
545
+ /**
546
+ * 包含大寫英文
547
+ *
548
+ * @default true
549
+ */
550
+ uppercase?: boolean;
551
+ /**
552
+ * 包含小寫英文
553
+ *
554
+ * @default true
555
+ */
556
+ lowercase?: boolean;
557
+ /**
558
+ * 包含數字
559
+ *
560
+ * @default true
561
+ *
562
+ */
563
+ number?: boolean;
564
+ /**
565
+ * 包含特殊字元
566
+ *
567
+ * @default true
568
+ *
569
+ */
570
+ special?: boolean;
571
+ /**
572
+ * 最小長度
573
+ *
574
+ * @default 8
575
+ *
576
+ */
577
+ minLength?: number;
578
+ }) => RegExp;
494
579
 
495
580
  /**
496
581
  * 數字
@@ -704,4 +789,4 @@ declare const getLocalStorage: <T>(key: string, deCode?: boolean) => T | undefin
704
789
  */
705
790
  declare const setLocalStorage: (key: string, value: Record<string, any>, enCode?: boolean) => void;
706
791
 
707
- export { type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, validTaxId, validateDateString, validateFileType, wait };
792
+ export { type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, validTaxId, validateDateString, validateFileType, wait };
package/dist/cjs/index.js CHANGED
@@ -2,6 +2,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
2
2
 
3
3
  var dayjs = require('dayjs');
4
4
  var useCountdownClient = require('./useCountdown-client-CNjGBIUB.js');
5
+ require('react');
5
6
  var downloadClient = require('./download-client-DKxkL92w.js');
6
7
  var webStorageClient = require('./webStorage-client-BGQKUfrO.js');
7
8
 
@@ -392,10 +393,14 @@ const transformObjectKey = (obj, transformFunName)=>{
392
393
  * console.log(result); // { result: true, data: { foo: 'bar' } }
393
394
  */ const fakeApi = (returnValue, result = true, time = 1000)=>new Promise((resolve)=>{
394
395
  setTimeout(()=>{
395
- resolve({
396
+ if (result) resolve({
396
397
  result,
397
398
  data: returnValue
398
399
  });
400
+ else resolve({
401
+ result,
402
+ message: 'error'
403
+ });
399
404
  }, time);
400
405
  });
401
406
 
@@ -534,6 +539,39 @@ message) {
534
539
  [key]: value
535
540
  };
536
541
  }, {});
542
+ /**
543
+ * extract the object fields by the given keys
544
+ *
545
+ * @param object - the object to pick fields from
546
+ * @param keys - the keys to pick
547
+ *
548
+ * @example
549
+ *
550
+ * const a = { a: 1, b: 2, c: 3, d: 4 };
551
+ * const b = pick(a, 'a', 'b'); // { a: 1, b: 2 }
552
+ */ const pick = (object, ...keys)=>keys.reduce((acc, cur)=>({
553
+ ...acc,
554
+ [cur]: object[cur]
555
+ }), {});
556
+ /**
557
+ * extract the object fields by the given values
558
+ *
559
+ * @param object - the object to pick fields from
560
+ * @param values - the values to pick
561
+ *
562
+ * @example
563
+ *
564
+ * const a = { a: 1, b: 2, c: 3, d: 4 };
565
+ * const b = pickByValue(a, 1, 2); // { a: 1, b: 2 }
566
+ */ const pickByValue = (object, ...values)=>Object.entries(object).reduce((acc, [key, value])=>{
567
+ if (values.includes(value)) {
568
+ return {
569
+ ...acc,
570
+ [key]: value
571
+ };
572
+ }
573
+ return acc;
574
+ }, {});
537
575
 
538
576
  /**
539
577
  * debounce function
@@ -595,6 +633,19 @@ message) {
595
633
  };
596
634
  };
597
635
 
636
+ function mergeRefs(refs) {
637
+ return (value)=>{
638
+ refs.forEach((ref)=>{
639
+ if (typeof ref === 'function') {
640
+ ref(value);
641
+ } else if (ref != null) {
642
+ // eslint-disable-next-line no-param-reassign
643
+ ref.current = value;
644
+ }
645
+ });
646
+ };
647
+ }
648
+
598
649
  /**
599
650
  * 中文
600
651
  *
@@ -660,6 +711,26 @@ message) {
660
711
  * isTimeString().test('12:00:00') // true
661
712
  * isTimeString().test('12:00:00.123') // false
662
713
  */ const isTimeString = ()=>/^\d{2}:\d{2}:\d{2}$/;
714
+ /**
715
+ * 密碼複雜度檢查
716
+ *
717
+ * 預設密碼長度為 8 位,且包含大寫英文、小寫英文、數字、特殊字元
718
+ *
719
+ * @param options - 選項
720
+ *
721
+ * @example
722
+ *
723
+ * isValidPassword().test('123') // false
724
+ * isValidPassword().test('12345678') // false
725
+ * isValidPassword().test('1234567A') // false
726
+ * isValidPassword().test('123456Aa') // false
727
+ * isValidPassword().test('12345Aa!') // true
728
+ * isValidPassword({ minLength: 6 }).test('12345Aa!') // true
729
+ * isValidPassword({ minLength: 6, uppercase: false }).test('12345a!') // true
730
+ * isValidPassword({ minLength: 6, lowercase: false }).test('12345A!') // true
731
+ * isValidPassword({ minLength: 6, number: false }).test('ABCDEa!') // true
732
+ * isValidPassword({ minLength: 6, special: false }).test('ABCDEa1') // true
733
+ */ const isValidPassword = (options)=>new RegExp(`^${options?.uppercase ?? true ? '(?=.*[A-Z])' : ''}${options?.lowercase ?? true ? '(?=.*[a-z])' : ''}${options?.number ?? true ? '(?=.*\\d)' : ''}${options?.special ?? true ? '(?=.*[\\p{P}\\p{S}])' : ''}${options?.minLength ? `.{${options.minLength},}` : '.{8,}$'}`, 'u');
663
734
 
664
735
  /**
665
736
  * 數字
@@ -839,12 +910,16 @@ exports.isServer = isServer;
839
910
  exports.isTWMobile = isTWMobile;
840
911
  exports.isTWPhone = isTWPhone;
841
912
  exports.isTimeString = isTimeString;
913
+ exports.isValidPassword = isValidPassword;
914
+ exports.mergeRefs = mergeRefs;
842
915
  exports.omit = omit;
843
916
  exports.omitByValue = omitByValue;
844
917
  exports.pascalCase2CamelCase = pascalCase2CamelCase;
845
918
  exports.pascalCase2SnakeCase = pascalCase2SnakeCase;
846
919
  exports.pascalString2CamelString = pascalString2CamelString;
847
920
  exports.pascalString2SnakeString = pascalString2SnakeString;
921
+ exports.pick = pick;
922
+ exports.pickByValue = pickByValue;
848
923
  exports.rocEraToAd = rocEraToAd;
849
924
  exports.snakeCase2CamelCase = snakeCase2CamelCase;
850
925
  exports.snakeCase2PascalCase = snakeCase2PascalCase;
@@ -36,5 +36,19 @@ type TExtractValueType<T, K extends string> = T extends Record<string, {
36
36
  type Entries<T> = {
37
37
  [K in keyof T]: [K, T[K]];
38
38
  }[keyof T][];
39
+ /**
40
+ * A utility type that transforms an object type `T` into another object type where each value type is a string.
41
+ *
42
+ * @template T - The object type to transform into keys.
43
+ *
44
+ * @example
45
+ *
46
+ * type Example = { a: number; b: string };
47
+ * type ExampleToString = MapToString<Example>;
48
+ * // Result: ExampleToString is { a: string; b: string; }
49
+ */
50
+ type MapToString<T> = {
51
+ [K in keyof T]: string;
52
+ };
39
53
 
40
- export type { Entries, TExtractValueType };
54
+ export type { Entries, MapToString, TExtractValueType };
@@ -1,5 +1,6 @@
1
1
  import { TExtractValueType } from './types.mjs';
2
2
  export * from './types.mjs';
3
+ import React from 'react';
3
4
 
4
5
  type CamelToPascal<S extends string> = S extends `${infer Head}${infer Tail}` ? `${Uppercase<Head>}${Tail}` : S;
5
6
  /**
@@ -279,8 +280,11 @@ declare const createEnumLikeObject: <T extends Record<string, {
279
280
  * console.log(result); // { result: true, data: { foo: 'bar' } }
280
281
  */
281
282
  declare const fakeApi: <T>(returnValue: T, result?: boolean, time?: number) => Promise<{
282
- result: boolean;
283
+ result: true;
283
284
  data: T;
285
+ } | {
286
+ result: false;
287
+ message: string;
284
288
  }>;
285
289
 
286
290
  /**
@@ -372,6 +376,30 @@ declare const omit: <T extends object, K extends [...(keyof T)[]]>(object: T, ..
372
376
  * const b = omitByValue(a, undefined, null); // { c: 3, d: 4 }
373
377
  */
374
378
  declare const omitByValue: <T extends object, K extends any[]>(object: T, ...values: K) => Pick<T, { [K2 in keyof T]: T[K2] extends K[number] ? never : K2; }[keyof T]>;
379
+ /**
380
+ * extract the object fields by the given keys
381
+ *
382
+ * @param object - the object to pick fields from
383
+ * @param keys - the keys to pick
384
+ *
385
+ * @example
386
+ *
387
+ * const a = { a: 1, b: 2, c: 3, d: 4 };
388
+ * const b = pick(a, 'a', 'b'); // { a: 1, b: 2 }
389
+ */
390
+ declare const pick: <T extends object, K extends [...(keyof T)[]]>(object: T, ...keys: K) => { [K2 in K[number]]: T[K2]; };
391
+ /**
392
+ * extract the object fields by the given values
393
+ *
394
+ * @param object - the object to pick fields from
395
+ * @param values - the values to pick
396
+ *
397
+ * @example
398
+ *
399
+ * const a = { a: 1, b: 2, c: 3, d: 4 };
400
+ * const b = pickByValue(a, 1, 2); // { a: 1, b: 2 }
401
+ */
402
+ declare const pickByValue: <T extends object, K extends any[]>(object: T, ...values: K) => Pick<T, { [K2 in keyof T]: T[K2] extends K[number] ? K2 : never; }[keyof T]>;
375
403
 
376
404
  /**
377
405
  * debounce function
@@ -403,6 +431,8 @@ declare const debounce: <P, R>(fn: (...args: P[]) => R, delay: number) => (...ar
403
431
  */
404
432
  declare const throttle: <P, R>(fn: (...args: P[]) => R, delay: number) => (...args: P[]) => R | undefined;
405
433
 
434
+ declare function mergeRefs<T = any>(refs: Array<React.MutableRefObject<T> | React.LegacyRef<T> | undefined | null>): React.RefCallback<T>;
435
+
406
436
  /**
407
437
  * 中文
408
438
  *
@@ -491,6 +521,61 @@ declare const isDateTimeString: (separator?: string) => RegExp;
491
521
  * isTimeString().test('12:00:00.123') // false
492
522
  */
493
523
  declare const isTimeString: () => RegExp;
524
+ /**
525
+ * 密碼複雜度檢查
526
+ *
527
+ * 預設密碼長度為 8 位,且包含大寫英文、小寫英文、數字、特殊字元
528
+ *
529
+ * @param options - 選項
530
+ *
531
+ * @example
532
+ *
533
+ * isValidPassword().test('123') // false
534
+ * isValidPassword().test('12345678') // false
535
+ * isValidPassword().test('1234567A') // false
536
+ * isValidPassword().test('123456Aa') // false
537
+ * isValidPassword().test('12345Aa!') // true
538
+ * isValidPassword({ minLength: 6 }).test('12345Aa!') // true
539
+ * isValidPassword({ minLength: 6, uppercase: false }).test('12345a!') // true
540
+ * isValidPassword({ minLength: 6, lowercase: false }).test('12345A!') // true
541
+ * isValidPassword({ minLength: 6, number: false }).test('ABCDEa!') // true
542
+ * isValidPassword({ minLength: 6, special: false }).test('ABCDEa1') // true
543
+ */
544
+ declare const isValidPassword: (options?: {
545
+ /**
546
+ * 包含大寫英文
547
+ *
548
+ * @default true
549
+ */
550
+ uppercase?: boolean;
551
+ /**
552
+ * 包含小寫英文
553
+ *
554
+ * @default true
555
+ */
556
+ lowercase?: boolean;
557
+ /**
558
+ * 包含數字
559
+ *
560
+ * @default true
561
+ *
562
+ */
563
+ number?: boolean;
564
+ /**
565
+ * 包含特殊字元
566
+ *
567
+ * @default true
568
+ *
569
+ */
570
+ special?: boolean;
571
+ /**
572
+ * 最小長度
573
+ *
574
+ * @default 8
575
+ *
576
+ */
577
+ minLength?: number;
578
+ }) => RegExp;
494
579
 
495
580
  /**
496
581
  * 數字
@@ -704,4 +789,4 @@ declare const getLocalStorage: <T>(key: string, deCode?: boolean) => T | undefin
704
789
  */
705
790
  declare const setLocalStorage: (key: string, value: Record<string, any>, enCode?: boolean) => void;
706
791
 
707
- export { type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, validTaxId, validateDateString, validateFileType, wait };
792
+ export { type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, downloadFile, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, setLocalStorage, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, useCountdown, validTaxId, validateDateString, validateFileType, wait };
package/dist/es/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import dayjs from 'dayjs';
2
2
  export { u as useCountdown } from './useCountdown-client-t52WIHfq.mjs';
3
+ import 'react';
3
4
  export { d as downloadFile } from './download-client-CnaJ0p_f.mjs';
4
5
  export { g as getLocalStorage, s as setLocalStorage } from './webStorage-client-Pd-loNCg.mjs';
5
6
 
@@ -386,10 +387,14 @@ const transformObjectKey = (obj, transformFunName)=>{
386
387
  * console.log(result); // { result: true, data: { foo: 'bar' } }
387
388
  */ const fakeApi = (returnValue, result = true, time = 1000)=>new Promise((resolve)=>{
388
389
  setTimeout(()=>{
389
- resolve({
390
+ if (result) resolve({
390
391
  result,
391
392
  data: returnValue
392
393
  });
394
+ else resolve({
395
+ result,
396
+ message: 'error'
397
+ });
393
398
  }, time);
394
399
  });
395
400
 
@@ -528,6 +533,39 @@ message) {
528
533
  [key]: value
529
534
  };
530
535
  }, {});
536
+ /**
537
+ * extract the object fields by the given keys
538
+ *
539
+ * @param object - the object to pick fields from
540
+ * @param keys - the keys to pick
541
+ *
542
+ * @example
543
+ *
544
+ * const a = { a: 1, b: 2, c: 3, d: 4 };
545
+ * const b = pick(a, 'a', 'b'); // { a: 1, b: 2 }
546
+ */ const pick = (object, ...keys)=>keys.reduce((acc, cur)=>({
547
+ ...acc,
548
+ [cur]: object[cur]
549
+ }), {});
550
+ /**
551
+ * extract the object fields by the given values
552
+ *
553
+ * @param object - the object to pick fields from
554
+ * @param values - the values to pick
555
+ *
556
+ * @example
557
+ *
558
+ * const a = { a: 1, b: 2, c: 3, d: 4 };
559
+ * const b = pickByValue(a, 1, 2); // { a: 1, b: 2 }
560
+ */ const pickByValue = (object, ...values)=>Object.entries(object).reduce((acc, [key, value])=>{
561
+ if (values.includes(value)) {
562
+ return {
563
+ ...acc,
564
+ [key]: value
565
+ };
566
+ }
567
+ return acc;
568
+ }, {});
531
569
 
532
570
  /**
533
571
  * debounce function
@@ -589,6 +627,19 @@ message) {
589
627
  };
590
628
  };
591
629
 
630
+ function mergeRefs(refs) {
631
+ return (value)=>{
632
+ refs.forEach((ref)=>{
633
+ if (typeof ref === 'function') {
634
+ ref(value);
635
+ } else if (ref != null) {
636
+ // eslint-disable-next-line no-param-reassign
637
+ ref.current = value;
638
+ }
639
+ });
640
+ };
641
+ }
642
+
592
643
  /**
593
644
  * 中文
594
645
  *
@@ -654,6 +705,26 @@ message) {
654
705
  * isTimeString().test('12:00:00') // true
655
706
  * isTimeString().test('12:00:00.123') // false
656
707
  */ const isTimeString = ()=>/^\d{2}:\d{2}:\d{2}$/;
708
+ /**
709
+ * 密碼複雜度檢查
710
+ *
711
+ * 預設密碼長度為 8 位,且包含大寫英文、小寫英文、數字、特殊字元
712
+ *
713
+ * @param options - 選項
714
+ *
715
+ * @example
716
+ *
717
+ * isValidPassword().test('123') // false
718
+ * isValidPassword().test('12345678') // false
719
+ * isValidPassword().test('1234567A') // false
720
+ * isValidPassword().test('123456Aa') // false
721
+ * isValidPassword().test('12345Aa!') // true
722
+ * isValidPassword({ minLength: 6 }).test('12345Aa!') // true
723
+ * isValidPassword({ minLength: 6, uppercase: false }).test('12345a!') // true
724
+ * isValidPassword({ minLength: 6, lowercase: false }).test('12345A!') // true
725
+ * isValidPassword({ minLength: 6, number: false }).test('ABCDEa!') // true
726
+ * isValidPassword({ minLength: 6, special: false }).test('ABCDEa1') // true
727
+ */ const isValidPassword = (options)=>new RegExp(`^${options?.uppercase ?? true ? '(?=.*[A-Z])' : ''}${options?.lowercase ?? true ? '(?=.*[a-z])' : ''}${options?.number ?? true ? '(?=.*\\d)' : ''}${options?.special ?? true ? '(?=.*[\\p{P}\\p{S}])' : ''}${options?.minLength ? `.{${options.minLength},}` : '.{8,}$'}`, 'u');
657
728
 
658
729
  /**
659
730
  * 數字
@@ -799,4 +870,4 @@ message) {
799
870
  */ const wait = (ms)=>{
800
871
  };
801
872
 
802
- export { adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, rocEraToAd, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, validTaxId, validateDateString, validateFileType, wait };
873
+ export { adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, createEnumLikeObject, debounce, extractEnumLikeObject, fakeApi, formatAmount, formatBytes, formatStarMask, generatePeriodArray, getCurrentPeriod, getMimeType, invariant, isChinese, isDateString, isDateTimeString, isEmail, isEnglish, isNonZeroStart, isNumber, isNumberAtLeastN, isNumberN, isNumberNM, isServer, isTWMobile, isTWPhone, isTimeString, isValidPassword, mergeRefs, omit, omitByValue, pascalCase2CamelCase, pascalCase2SnakeCase, pascalString2CamelString, pascalString2SnakeString, pick, pickByValue, rocEraToAd, snakeCase2CamelCase, snakeCase2PascalCase, snakeString2CamelString, snakeString2PascalString, throttle, validTaxId, validateDateString, validateFileType, wait };
@@ -36,5 +36,19 @@ type TExtractValueType<T, K extends string> = T extends Record<string, {
36
36
  type Entries<T> = {
37
37
  [K in keyof T]: [K, T[K]];
38
38
  }[keyof T][];
39
+ /**
40
+ * A utility type that transforms an object type `T` into another object type where each value type is a string.
41
+ *
42
+ * @template T - The object type to transform into keys.
43
+ *
44
+ * @example
45
+ *
46
+ * type Example = { a: number; b: string };
47
+ * type ExampleToString = MapToString<Example>;
48
+ * // Result: ExampleToString is { a: string; b: string; }
49
+ */
50
+ type MapToString<T> = {
51
+ [K in keyof T]: string;
52
+ };
39
53
 
40
- export type { Entries, TExtractValueType };
54
+ export type { Entries, MapToString, TExtractValueType };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gateweb/react-utils",
3
- "version": "1.1.1",
3
+ "version": "1.3.0",
4
4
  "description": "React Utils for GateWeb",
5
5
  "homepage": "https://github.com/GatewebSolutions/react-utils",
6
6
  "files": [