@gateweb/react-utils 0.0.1

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.
@@ -0,0 +1,620 @@
1
+ type CamelToPascal<S extends string> = S extends `${infer Head}${infer Tail}` ? `${Uppercase<Head>}${Tail}` : S;
2
+ /**
3
+ * convert CamelCase string to PascalCase string
4
+ * @param str the string to convert
5
+ * @example
6
+ * camelString2PascalString('camelCase') // 'CamelCase'
7
+ * camelString2PascalString('camelCaseTest') // 'CamelCaseTest'
8
+ */
9
+ declare const camelString2PascalString: <S extends string>(str: S) => CamelToPascal<S>;
10
+ type CamelToSnake<S extends string> = S extends `${infer Head}${infer Tail}` ? Head extends Uppercase<Head> ? Head extends '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ? `${Head}${CamelToSnake<Tail>}` : `${Head extends '_' ? '' : '_'}${Lowercase<Head>}${CamelToSnake<Tail>}` : `${Head}${CamelToSnake<Tail>}` : S;
11
+ /**
12
+ * convert CamelCase string to SnakeCase string
13
+ * @param str the string to convert
14
+ * @example
15
+ * camelString2SnakeString('camelCase') // 'camel_case'
16
+ * camelString2SnakeString('camelCaseTest') // 'camel_case_test'
17
+ */
18
+ declare const camelString2SnakeString: <S extends string>(str: S) => CamelToSnake<S>;
19
+ type PascalToCamel<S extends string> = S extends `${infer Head}${infer Tail}` ? `${Lowercase<Head>}${Tail}` : S;
20
+ /**
21
+ * convert PascalCase string to CamelCase string
22
+ * @param str the string to convert
23
+ * @example
24
+ * pascalString2CamelString('PascalCase') // 'pascalCase'
25
+ * pascalString2CamelString('PascalCaseTest') // 'pascalCaseTest'
26
+ */
27
+ declare const pascalString2CamelString: <S extends string>(str: S) => PascalToCamel<S>;
28
+ type PascalToSnake<S extends string> = CamelToSnake<PascalToCamel<S>>;
29
+ /**
30
+ * convert PascalCase string to SnakeCase string
31
+ * @param str the string to convert
32
+ * @example
33
+ * pascalString2SnakeString('PascalCase') // 'pascal_case'
34
+ * pascalString2SnakeString('PascalCaseTest') // 'pascal_case_test'
35
+ */
36
+ declare const pascalString2SnakeString: <S extends string>(str: S) => CamelToSnake<PascalToCamel<S>>;
37
+ type SnakeToCamel<T extends string> = T extends `${infer Head}_${infer Tail}` ? `${Uncapitalize<Head>}${Capitalize<SnakeToCamel<Tail>>}` : T;
38
+ /**
39
+ * convert SnakeCase string to CamelCase string
40
+ * @param str the string to convert
41
+ * @example
42
+ * snakeString2CamelString('snake_case') // 'snakeCase'
43
+ * snakeString2CamelString('snake_case_test') // 'snakeCaseTest'
44
+ */
45
+ declare const snakeString2CamelString: <S extends string>(str: S) => SnakeToCamel<S>;
46
+ type SnakeToPascal<S extends string> = CamelToPascal<SnakeToCamel<S>>;
47
+ /**
48
+ * convert SnakeCase string to PascalCase string
49
+ * @param str the string to convert
50
+ * @example
51
+ * snakeString2PascalString('snake_case') // 'SnakeCase'
52
+ * snakeString2PascalString('snake_case_test') // 'SnakeCaseTest'
53
+ */
54
+ declare const snakeString2PascalString: <S extends string>(str: S) => CamelToPascal<SnakeToCamel<S>>;
55
+ type ApplyKeyTransform<K extends string, Transform> = Transform extends 'CamelToPascal' ? CamelToPascal<K> : Transform extends 'CamelToSnake' ? CamelToSnake<K> : Transform extends 'PascalToCamel' ? PascalToCamel<K> : Transform extends 'PascalToSnake' ? PascalToSnake<K> : Transform extends 'SnakeToCamel' ? SnakeToCamel<K> : Transform extends 'SnakeToPascal' ? SnakeToPascal<K> : K;
56
+ type TransformObjectKey<T, Transform extends string> = T extends object ? {
57
+ [K in keyof T as K extends string ? ApplyKeyTransform<K, Transform> : K]: TransformObjectKey<T[K], Transform>;
58
+ } : T;
59
+ /**
60
+ * convert object key from CamelCase to PascalCase
61
+ * @param obj the object to convert
62
+ * @example
63
+ * const obj = {
64
+ * fooBar: 'fooBar',
65
+ * fooBar2: 'fooBar2',
66
+ * fooBar3: {
67
+ * fooBar4: 'fooBar4',
68
+ * fooBar5: 'fooBar5',
69
+ * },
70
+ * };
71
+ * const result = camelCase2PascalCase(obj);
72
+ * console.log(result); // { FooBar: 'fooBar', FooBar2: 'fooBar2', FooBar3: { FooBar4: 'fooBar4', FooBar5: 'fooBar5' } }
73
+ */
74
+ declare const camelCase2PascalCase: <T extends Record<string, any>>(obj: T) => TransformObjectKey<T, "CamelToPascal">;
75
+ /**
76
+ * convert object key from CamelCase to SnakeCase
77
+ * @param obj the object to convert
78
+ * @example
79
+ * const obj = {
80
+ * fooBar: 'fooBar',
81
+ * fooBar2: 'fooBar2',
82
+ * fooBar3: {
83
+ * fooBar4: 'fooBar4',
84
+ * fooBar5: 'fooBar5',
85
+ * },
86
+ * };
87
+ * const result = camelCase2SnakeCase(obj);
88
+ * console.log(result); // { foo_bar: 'fooBar', foo_bar2: 'fooBar2', foo_bar3: { foo_bar4: 'fooBar4', foo_bar5: 'fooBar5' } }
89
+ */
90
+ declare const camelCase2SnakeCase: <T extends Record<string, any>>(obj: T) => TransformObjectKey<T, "CamelToSnake">;
91
+ /**
92
+ * convert object key from PascalCase to CamelCase
93
+ * @param obj the object to convert
94
+ * @example
95
+ * const obj = {
96
+ * FooBar: 'fooBar',
97
+ * FooBar2: 'fooBar2',
98
+ * FooBar3: {
99
+ * FooBar4: 'fooBar4',
100
+ * FooBar5: 'fooBar5',
101
+ * },
102
+ * };
103
+ * const result = pascalCase2CamelCase(obj);
104
+ * console.log(result); // { fooBar: 'fooBar', fooBar2: 'fooBar2', fooBar3: { fooBar4: 'fooBar4', fooBar5: 'fooBar5' } }
105
+ */
106
+ declare const pascalCase2CamelCase: <T extends Record<string, any>>(obj: T) => TransformObjectKey<T, "PascalToCamel">;
107
+ /**
108
+ * convert object key from PascalCase to SnakeCase
109
+ * @param obj the object to convert
110
+ * @example
111
+ * const obj = {
112
+ * FooBar: 'fooBar',
113
+ * FooBar2: 'fooBar2',
114
+ * FooBar3: {
115
+ * FooBar4: 'fooBar4',
116
+ * FooBar5: 'fooBar5',
117
+ * },
118
+ * };
119
+ * const result = pascalCase2SnakeCase(obj);
120
+ * console.log(result); // { foo_bar: 'fooBar', foo_bar2: 'fooBar2', foo_bar3: { foo_bar4: 'fooBar4', foo_bar5: 'fooBar5' } }
121
+ */
122
+ declare const pascalCase2SnakeCase: <T extends Record<string, any>>(obj: T) => TransformObjectKey<T, "PascalToSnake">;
123
+ /**
124
+ * convert object key from SnakeCase to CamelCase
125
+ * @param obj the object to convert
126
+ * @example
127
+ * const obj = {
128
+ * foo_bar: 'fooBar',
129
+ * foo_bar2: 'fooBar2',
130
+ * foo_bar3: {
131
+ * foo_bar4: 'fooBar4',
132
+ * foo_bar5: 'fooBar5',
133
+ * },
134
+ * };
135
+ * const result = snakeCase2CamelCase(obj);
136
+ * console.log(result); // { fooBar: 'fooBar', fooBar2: 'fooBar2', fooBar3: { fooBar4: 'fooBar4', fooBar5: 'fooBar5' } }
137
+ */
138
+ declare const snakeCase2CamelCase: <T extends Record<string, any>>(obj: T) => TransformObjectKey<T, "SnakeToCamel">;
139
+ /**
140
+ * convert object key from SnakeCase to PascalCase
141
+ * @param obj the object to convert
142
+ * @example
143
+ * const obj = {
144
+ * foo_bar: 'fooBar',
145
+ * foo_bar2: 'fooBar2',
146
+ * foo_bar3: {
147
+ * foo_bar4: 'fooBar4',
148
+ * foo_bar5: 'fooBar5',
149
+ * },
150
+ * };
151
+ * const result = snakeCase2PascalCase(obj);
152
+ * console.log(result); // { FooBar: 'fooBar', FooBar2: 'fooBar2', FooBar3: { FooBar4: 'fooBar4', FooBar5: 'fooBar5' } }
153
+ */
154
+ declare const snakeCase2PascalCase: <T extends Record<string, any>>(obj: T) => TransformObjectKey<T, "SnakeToPascal">;
155
+
156
+ /**
157
+ * 取得去年今年以及明年期別陣列
158
+ *
159
+ * @example
160
+ * // 假設 今年為 112 年
161
+ * generatePeriodArray() // 11102 ~ 11312
162
+ */
163
+ declare const generatePeriodArray: () => string[];
164
+ /**
165
+ * 取得當前期別
166
+ *
167
+ * 報稅期限次期開始15日內
168
+ *
169
+ * 雙數月沒有特殊規則,期別皆為當月開頭
170
+ *
171
+ * 單數月15號以前,期別為上個月否則為下個月開頭
172
+ *
173
+ * @example
174
+ *
175
+ * // 假設今天是 111-02-15
176
+ * getCurrentPeriod() // 11102
177
+ * // 假設今天是 111-02-16
178
+ * getCurrentPeriod() // 11102
179
+ * // 假設今天是 111-03-15
180
+ * getCurrentPeriod() // 11102
181
+ * // 假設今天是 111-03-16
182
+ * getCurrentPeriod() // 11104
183
+ */
184
+ declare const getCurrentPeriod: () => string;
185
+ /**
186
+ * 民國年轉西元年
187
+ * @param dateString 日期字串
188
+ * @param format 日期格式
189
+ * @example
190
+ *
191
+ * rocEraToAd('1100201') // 20210201
192
+ * rocEraToAd('11002', 'YYYYMM') // 202102
193
+ */
194
+ declare const rocEraToAd: (dateString: string, format?: string) => string;
195
+ /**
196
+ * 西元年轉民國年
197
+ * @param dateString 日期字串
198
+ * @param format 日期格式
199
+ * @example
200
+ *
201
+ * adToRocEra('20210201') // 1100201
202
+ * adToRocEra('202102', 'YYYYMM') // 11002
203
+ */
204
+ declare const adToRocEra: (dateString: string, format?: string) => string;
205
+
206
+ /**
207
+ * 檢查檔案是否為合法的 MIME 類型
208
+ *
209
+ * @param file 檔案
210
+ * @param accepts 允許的 MIME 類型
211
+ *
212
+ * @example
213
+ *
214
+ * ```js
215
+ * validateFileType({ type: 'image/png' }, ['image/png', 'image/jpeg']) // true
216
+ * validateFileType({ type: 'image/png' }, ['image/jpeg']) // false
217
+ * validateFileType({ type: 'image/png' }, ['image/*']) // true
218
+ * ```
219
+ */
220
+ declare const validateFileType: (file: File, accepts: string[]) => boolean;
221
+ /**
222
+ * 根據檔案副檔名取得對應的 MIME Type
223
+ *
224
+ * 目前支援的副檔名有:pdf, csv, jpeg, jpg, png, zip, txt
225
+ * 除此之外的副檔名皆回傳 application/octet-stream
226
+ *
227
+ * @param fileExtension 檔案副檔名
228
+ *
229
+ * @example
230
+ *
231
+ * getMimeType('pdf') // 'application/pdf'
232
+ * getMimeType('csv') // 'text/csv'
233
+ * getMimeType('jpeg') // 'image/jpeg'
234
+ * getMimeType('jpg') // 'image/jpeg'
235
+ * getMimeType('png') // 'image/png'
236
+ * getMimeType('txt') // 'text/plain'
237
+ * getMimeType('zip') // 'application/zip'
238
+ * getMimeType('mp4') // 'application/octet-stream'
239
+ */
240
+ declare const getMimeType: (fileName: string) => "image/jpeg" | "image/png" | "application/pdf" | "application/zip" | "text/csv" | "text/plain" | "application/octet-stream";
241
+
242
+ type TCountdownActions = {
243
+ /** 目前秒數 */
244
+ countdown: number;
245
+ /** 是否正在倒數計時 */
246
+ isCounting: boolean;
247
+ /** 開始倒數計時 */
248
+ start: () => void;
249
+ /** 停止倒數計時 */
250
+ stop: () => void;
251
+ /** 重置倒數計時 */
252
+ reset: () => void;
253
+ };
254
+ /**
255
+ * 倒數計時器
256
+ *
257
+ * 可以透過 start() 來啟動倒數計時器
258
+ * 可以透過 stop() 來停止倒數計時器
259
+ * 可以透過 reset() 來重置倒數計時器
260
+ *
261
+ * @param initialCountdown 倒數計時器初始值
262
+ * @param enableReinitialize 允許重設初始值
263
+ */
264
+ declare const useCountdown: (initialCountdown: number, enableReinitialize?: boolean) => TCountdownActions;
265
+
266
+ /**
267
+ * 判斷執行環境是否為 Server(node.js) 端
268
+ */
269
+ declare const isServer: () => boolean;
270
+
271
+ /**
272
+ * 將物件中的某些 key 排除
273
+ *
274
+ * @param object 原始物件
275
+ * @param keys 要排除的 key
276
+ *
277
+ * @example
278
+ * const a = { a: 1, b: 2, c: 3, d: 4 };
279
+ * const b = omit(a, 'a', 'b'); // { c: 3, d: 4 }
280
+ */
281
+ declare const omit: <T extends object, K extends [...(keyof T)[]]>(object: T, ...keys: K) => { [K2 in Exclude<keyof T, K[number]>]: T[K2]; };
282
+ /**
283
+ * 將物件中的某些 value 排除
284
+ *
285
+ * @param object 原始物件
286
+ * @param values 要排除的 value
287
+ *
288
+ * @example
289
+ * const a = { a: undefined, b: null, c: 3, d: 4 };
290
+ * const b = omitByValue(a, undefined, null); // { c: 3, d: 4 }
291
+ */
292
+ 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]>;
293
+ /**
294
+ * 將指定格式的物件轉換成類似 enum 的物件
295
+ *
296
+ * @param enumObject enum 物件
297
+ * @param valueKey value 的 key
298
+ *
299
+ * @example
300
+ *
301
+ * ```js
302
+ * const myObj = {
303
+ * A: { value: 'a' },
304
+ * B: { value: 'b', other: 'other' },
305
+ * }
306
+ *
307
+ * const enumCode = extractEnumLikeObject(myObj, 'value');
308
+ * console.log(enumCode); // { A: 'a', B: 'b' }
309
+ * ```
310
+ */
311
+ declare const extractEnumLikeObject: <T extends Record<string, { [P in K]: any; }>, K extends string>(enumObject: T, valueKey: K) => { [key in keyof T]: T[key][K]; };
312
+
313
+ /**
314
+ * debounce function
315
+ *
316
+ * @param {Function} fn function to be executed
317
+ * @param {number} delay time to wait before executing the function
318
+ *
319
+ * @example
320
+ * const debouncedFunction = debounce((a: number, b: number) => console.log(a + b), 1000);
321
+ * debouncedFunction(1, 2);
322
+ * debouncedFunction(3, 4);
323
+ * // after 1 second
324
+ * // 7
325
+ */
326
+ declare const debounce: <P, R>(fn: (...args: P[]) => R, delay: number) => (...args: P[]) => void;
327
+ /**
328
+ * throttle function
329
+ *
330
+ * @param {Function} fn function to be executed
331
+ * @param {number} delay time to wait before executing the function
332
+ *
333
+ * @example
334
+ * const throttledFunction = throttle((a: number, b: number) => a + b, 1000);
335
+ * throttledFunction(1, 2); // 3
336
+ * throttledFunction(3, 4); // undefined
337
+ * setTimeout(() => {
338
+ * throttledFunction(5, 6); // 11
339
+ * }, 2000);
340
+ */
341
+ declare const throttle: <P, R>(fn: (...args: P[]) => R, delay: number) => (...args: P[]) => R | undefined;
342
+
343
+ /**
344
+ * 中文
345
+ *
346
+ * @param options - 選項
347
+ *
348
+ * @example
349
+ *
350
+ * isChinese().test('你好') // true
351
+ * isChinese().test('你 好') // false
352
+ * isChinese({ containSpace: true }).test('你 好') // true
353
+ * isChinese().test('123') // false
354
+ */
355
+ declare const isChinese: (options?: {
356
+ /** 是否包含空格 */
357
+ containSpace?: boolean;
358
+ /** 是否包含標點符號 */
359
+ mark?: boolean;
360
+ }) => RegExp;
361
+ /**
362
+ * 英文
363
+ *
364
+ * @param options - 選項
365
+ *
366
+ * @example
367
+ *
368
+ * isEnglish().test('abc') // true
369
+ * isEnglish().test('abc def') // false
370
+ * isEnglish({ containSpace: true }).test('abc def') // true
371
+ * isEnglish({ number: true }).test('abc123') // true
372
+ * isEnglish({ mark: true }).test('abc!') // true
373
+ * isEnglish({ fullWidth: true }).test('ABC') // true
374
+ * isEnglish({ lowercase: false }).test('abc') // false
375
+ * isEnglish({ uppercase: false }).test('ABC') // false
376
+ */
377
+ declare const isEnglish: (options?: {
378
+ /** 是否包含空格 */
379
+ containSpace?: boolean;
380
+ /** 是否包含數字 */
381
+ number?: boolean;
382
+ /** 是否包含標點符號 */
383
+ mark?: boolean;
384
+ /** 是否包含全形字 */
385
+ fullWidth?: boolean;
386
+ /** 是否包含小寫 */
387
+ lowercase?: boolean;
388
+ /** 是否包含大寫 */
389
+ uppercase?: boolean;
390
+ }) => RegExp;
391
+ /**
392
+ * email
393
+ *
394
+ * @example
395
+ *
396
+ * isEmail().test('123') // false
397
+ * isEmail().test('123@gmail.com') // true
398
+ */
399
+ declare const isEmail: () => RegExp;
400
+ /**
401
+ * 日期字串
402
+ *
403
+ * @param separator 分隔符號 (預設為 -)
404
+ *
405
+ * @example
406
+ *
407
+ * isDateString().test('2021-01-01') // true
408
+ * isDateString('/').test('2021/01/01') // true
409
+ */
410
+ declare const isDateString: (separator?: string) => RegExp;
411
+ /**
412
+ * 日期時間字串
413
+ *
414
+ * @param separator 分隔符號 (預設為 -)
415
+ *
416
+ * @example
417
+ *
418
+ * isDateTimeString().test('2021-01-01 12:00:00') // true
419
+ * isDateTimeString('/').test('2021/01/01 12:00:00') // true
420
+ */
421
+ declare const isDateTimeString: (separator?: string) => RegExp;
422
+ /**
423
+ * 日期時間字串 (不包含豪秒)
424
+ *
425
+ * @example
426
+ *
427
+ * isTimeString().test('12:00:00') // true
428
+ * isTimeString().test('12:00:00.123') // false
429
+ */
430
+ declare const isTimeString: () => RegExp;
431
+
432
+ /**
433
+ * 數字
434
+ *
435
+ * @example
436
+ * isNumber().test('123') // true
437
+ */
438
+ declare const isNumber: () => RegExp;
439
+ /**
440
+ * 非零開頭的數字
441
+ *
442
+ * @param allowZero 是否允許0
443
+ *
444
+ * @example
445
+ * isNonZeroNumber().test('123') // true
446
+ * isNonZeroNumber().test('0123') // false
447
+ * isNonZeroNumber().test('0') // false
448
+ * isNonZeroNumber(true).test('0') // true
449
+ */
450
+ declare const isNonZeroStart: (allowZero?: boolean) => RegExp;
451
+ /**
452
+ * n位數的數字
453
+ *
454
+ * @param n 位數
455
+ *
456
+ * @example
457
+ * isNumberN(3).test('123') // true
458
+ * isNumberN(3).test('1234') // false
459
+ */
460
+ declare const isNumberN: (n: number) => RegExp;
461
+ /**
462
+ * n - m 位數的數字
463
+ *
464
+ * @param n 最小位數
465
+ * @param m 最大位數
466
+ *
467
+ * @example
468
+ * isNumberNM(3, 5).test('123') // true
469
+ * isNumberNM(3, 5).test('12345') // true
470
+ * isNumberNM(3, 5).test('123456') // false
471
+ */
472
+ declare const isNumberNM: (n: number, m: number) => RegExp;
473
+ /**
474
+ * 至少n位數的數字
475
+ *
476
+ * @param n 最小位數
477
+ *
478
+ * @example
479
+ * isNumberAtLeastN(3).test('123') // true
480
+ * isNumberAtLeastN(3).test('1234') // true
481
+ * isNumberAtLeastN(3).test('12') // false
482
+ */
483
+ declare const isNumberAtLeastN: (n: number) => RegExp;
484
+
485
+ /**
486
+ * 台灣手機號碼
487
+ *
488
+ * 1. 09開頭
489
+ * 2. 10碼數字
490
+ *
491
+ * @example
492
+ *
493
+ * isTWMobile().test('0912345678') // true
494
+ * isTWMobile().test('091234567') // false
495
+ */
496
+ declare const isTWMobile: () => RegExp;
497
+ /**
498
+ * 台灣市話
499
+ *
500
+ * 1. 0開頭
501
+ * 2. 2~3碼區碼
502
+ * 3. 區碼與號碼之間可以有-號
503
+ * 4. 6~8碼號碼
504
+ * 5. 區碼加上號碼最多10碼
505
+ * 6. 可以有分機號碼,分機號碼為#號開頭,後面接1~5碼數字
506
+ *
507
+ * @example
508
+ *
509
+ * isTWPhone().test('0212345678') // true
510
+ * isTWPhone().test('02-12345678') // true
511
+ * isTWPhone().test('023-1234567') // true
512
+ * isTWPhone().test('02-12345678#123') // true
513
+ *
514
+ * isTWPhone().test('02123456789') // false
515
+ * isTWPhone().test('02-123456789') // false
516
+ * isTWPhone().test('02-12345678#123456') // false
517
+ */
518
+ declare const isTWPhone: () => RegExp;
519
+
520
+ /**
521
+ * 將數字轉換成金額千分位格式
522
+ *
523
+ * @param num - 數字
524
+ *
525
+ * @example
526
+ *
527
+ * formatAmount(1234567) // '1,234,567'
528
+ */
529
+ declare const formatAmount: (num: number) => string;
530
+ /**
531
+ * 將字串的第 n - m 個字轉換成星號
532
+ *
533
+ * @param str - 字串
534
+ * @param n - 起始位置
535
+ * @param m - 結束位置
536
+ *
537
+ * @example
538
+ *
539
+ * formatString('123456', 1, 4) // '1****6'
540
+ */
541
+ declare const formatStarMask: (str: string, n: number, m: number) => string;
542
+
543
+ /**
544
+ * 檢查稅務編號是否符合正確的編號規則。
545
+ *
546
+ * @param {string} taxId - 要檢查的8位數稅務編號。
547
+ * @returns {boolean} - 如果符合規則則返回 true,否則返回 false。
548
+ *
549
+ * ### 編號檢查規則:
550
+ * 1. **基本格式檢查**:
551
+ * - 編號必須為 8 位數字。
552
+ * - 不得為「00000000」或「11111111」,這些編號被視為無效。
553
+ *
554
+ * 2. **驗證邏輯**:
555
+ * - 使用一組驗證運算子:`[1, 2, 1, 2, 1, 2, 4, 1]`。
556
+ * - 將稅務編號的每一位數字與對應的運算子相乘後,使用 `calculate` 函數計算各位數的和。
557
+ * - 計算公式為:`(product % 10) + (product - (product % 10)) / 10`
558
+ * - 將所有位數經計算後的結果加總為 `sum`。
559
+ *
560
+ * 3. **檢查規則**:
561
+ * - 如果總和 `sum` 可以被 5 整除,則編號有效。
562
+ * - 或者,若第七位數為 7,且 `(sum + 1) % 5 === 0`,則編號有效。
563
+ *
564
+ * @example
565
+ *
566
+ * validTaxId('22099131') // true
567
+ * validTaxId('84149961') // true
568
+ * validTaxId('00000000') // false
569
+ * validTaxId('11111111') // false
570
+ * validTaxId('22099132') // false
571
+ */
572
+ declare const validTaxId: (taxId: string) => boolean;
573
+ /**
574
+ * 驗證日期格式是否正確
575
+ *
576
+ * @param dateString 日期字串
577
+ * @param format 日期格式
578
+ * @example
579
+ *
580
+ * validateDateString('20210201', 'YYYYMMDD') // true
581
+ * validateDateString('2021-02-01', 'YYYY-MM-DD') // true
582
+ * validateDateString('20210201', 'YYYY-MM-DD') // false
583
+ * validateDateString('20210201', 'YYYYMM') // false
584
+ */
585
+ declare const validateDateString: (dateString: string, format: string) => boolean;
586
+
587
+ /**
588
+ * Downloads a file from a given source.
589
+ *
590
+ * @param source - The source of the file to be downloaded. It can be a URL string or a Blob object.
591
+ * @param filename - The name of the file to be downloaded. Defaults to the current timestamp if not provided.
592
+ * @param fileExtension - The file extension to be appended to the filename. Optional.
593
+ *
594
+ * @example
595
+ * downloadFile('http://example.com/file.txt', 'testfile', 'txt');
596
+ * downloadFile(new Blob(['test content'], { type: 'text/plain' }), 'testfile', 'txt');
597
+ */
598
+ declare const downloadFile: (source: string | Blob, filename?: string, fileExtension?: string) => void;
599
+
600
+ /**
601
+ * 從 localStorage 取得資料,支援槽狀取值
602
+ *
603
+ * @param key 鍵值
604
+ * @param deCode 是否解碼
605
+ * @returns 取得的資料
606
+ * @example
607
+ * const data = getLocalStorage('key');
608
+ *
609
+ * const data = getLocalStorage('key.subKey');
610
+ */
611
+ declare const getLocalStorage: <T>(key: string, deCode?: boolean) => T | undefined;
612
+ /**
613
+ * 將資料存入 localStorage
614
+ * @param key 鍵值
615
+ * @param value 可序列化的資料
616
+ * @param enCode 是否編碼
617
+ */
618
+ declare const setLocalStorage: (key: string, value: Record<string, any>, enCode?: boolean) => void;
619
+
620
+ export { type TCountdownActions, adToRocEra, camelCase2PascalCase, camelCase2SnakeCase, camelString2PascalString, camelString2SnakeString, debounce, downloadFile, extractEnumLikeObject, formatAmount, formatStarMask, generatePeriodArray, getCurrentPeriod, getLocalStorage, getMimeType, 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 };