@pawover/kit 0.0.0-beta.45 → 0.0.0-beta.50

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.
Files changed (52) hide show
  1. package/package.json +52 -82
  2. package/{dist/hooks-alova.d.ts → packages/hooks/dist/alova.d.ts} +4 -5
  3. package/{dist/hooks-alova.js → packages/hooks/dist/alova.js} +3 -5
  4. package/packages/hooks/dist/index.d.ts +1 -0
  5. package/packages/hooks/dist/index.js +0 -0
  6. package/packages/hooks/dist/metadata.json +16 -0
  7. package/{dist/hooks-react.d.ts → packages/hooks/dist/react.d.ts} +76 -72
  8. package/packages/hooks/dist/react.js +4419 -0
  9. package/packages/utils/dist/index.d.ts +4293 -0
  10. package/packages/utils/dist/index.js +1527 -0
  11. package/packages/utils/dist/math.d.ts +54 -0
  12. package/packages/utils/dist/math.js +56 -0
  13. package/packages/utils/dist/metadata.json +14 -0
  14. package/packages/utils/dist/string-CESQdidv.js +793 -0
  15. package/packages/utils/dist/vite.d.ts +16 -0
  16. package/packages/utils/dist/vite.js +26 -0
  17. package/packages/zod/dist/index.d.ts +58 -0
  18. package/packages/zod/dist/index.js +61 -0
  19. package/dist/enums.d.ts +0 -2
  20. package/dist/enums.js +0 -145
  21. package/dist/enums.js.map +0 -1
  22. package/dist/except-6l9Qdmn1.d.ts +0 -986
  23. package/dist/except-6l9Qdmn1.d.ts.map +0 -1
  24. package/dist/hooks-alova.d.ts.map +0 -1
  25. package/dist/hooks-alova.js.map +0 -1
  26. package/dist/hooks-react.d.ts.map +0 -1
  27. package/dist/hooks-react.js +0 -166
  28. package/dist/hooks-react.js.map +0 -1
  29. package/dist/index-DsR_kNCf.d.ts +0 -18
  30. package/dist/index-DsR_kNCf.d.ts.map +0 -1
  31. package/dist/index-JKtXbRi8.d.ts +0 -149
  32. package/dist/index-JKtXbRi8.d.ts.map +0 -1
  33. package/dist/index.d.ts +0 -3736
  34. package/dist/index.d.ts.map +0 -1
  35. package/dist/index.js +0 -2
  36. package/dist/patches-fetchEventSource.d.ts +0 -87
  37. package/dist/patches-fetchEventSource.d.ts.map +0 -1
  38. package/dist/patches-fetchEventSource.js +0 -200
  39. package/dist/patches-fetchEventSource.js.map +0 -1
  40. package/dist/utils-B7AhGrZp.js +0 -2042
  41. package/dist/utils-B7AhGrZp.js.map +0 -1
  42. package/dist/value-of-Dz22arsm.d.ts +0 -26
  43. package/dist/value-of-Dz22arsm.d.ts.map +0 -1
  44. package/dist/vite.d.ts +0 -12
  45. package/dist/vite.d.ts.map +0 -1
  46. package/dist/vite.js +0 -23
  47. package/dist/vite.js.map +0 -1
  48. package/dist/zod.d.ts +0 -112
  49. package/dist/zod.d.ts.map +0 -1
  50. package/dist/zod.js +0 -112
  51. package/dist/zod.js.map +0 -1
  52. package/metadata.json +0 -184
@@ -1,2042 +0,0 @@
1
- //#region src/utils/typeof/types.ts
2
- const PROTOTYPE_TAGS = Object.freeze({
3
- abortSignal: "[object AbortSignal]",
4
- array: "[object Array]",
5
- asyncFunction: "[object AsyncFunction]",
6
- asyncGeneratorFunction: "[object AsyncGeneratorFunction]",
7
- bigInt: "[object BigInt]",
8
- blob: "[object Blob]",
9
- boolean: "[object Boolean]",
10
- date: "[object Date]",
11
- error: "[object Error]",
12
- file: "[object File]",
13
- function: "[object Function]",
14
- generatorFunction: "[object GeneratorFunction]",
15
- global: "[object global]",
16
- iframe: "[object HTMLIFrameElement]",
17
- map: "[object Map]",
18
- null: "[object Null]",
19
- number: "[object Number]",
20
- object: "[object Object]",
21
- promise: "[object Promise]",
22
- readableStream: "[object ReadableStream]",
23
- regExp: "[object RegExp]",
24
- set: "[object Set]",
25
- string: "[object String]",
26
- symbol: "[object Symbol]",
27
- undefined: "[object Undefined]",
28
- URLSearchParams: "[object URLSearchParams]",
29
- weakMap: "[object WeakMap]",
30
- weakSet: "[object WeakSet]",
31
- webSocket: "[object WebSocket]",
32
- window: "[object Window]"
33
- });
34
- const TYPED_ARRAY_TAGS = new Set([
35
- "[object Int8Array]",
36
- "[object Uint8Array]",
37
- "[object Uint8ClampedArray]",
38
- "[object Int16Array]",
39
- "[object Uint16Array]",
40
- "[object Int32Array]",
41
- "[object Uint32Array]",
42
- "[object Float32Array]",
43
- "[object Float64Array]",
44
- "[object BigInt64Array]",
45
- "[object BigUint64Array]"
46
- ]);
47
- /**
48
- * 获取值的 [[Prototype]] 标签(通过 Object.prototype.toString)
49
- *
50
- * @example
51
- * resolvePrototypeString([]) // "[object Array]"
52
- * resolvePrototypeString(null) // "[object Null]"
53
- *
54
- * @param value - 任意 JavaScript 值
55
- * @returns 标准化的类型标签字符串
56
- */
57
- function resolvePrototypeString(value) {
58
- return Object.prototype.toString.call(value);
59
- }
60
- //#endregion
61
- //#region src/utils/typeof/isAbortSignal.ts
62
- /**
63
- * 检查 value 是否为 AbortSignal
64
- * @param value 待检查值
65
- * @returns 是否为 AbortSignal
66
- */
67
- function isAbortSignal(value) {
68
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.abortSignal;
69
- }
70
- //#endregion
71
- //#region src/utils/typeof/isArray.ts
72
- /**
73
- * 检查 value 是否为数组
74
- *
75
- * @param value 待检查值
76
- * @returns 是否为数组
77
- * @example
78
- * ```ts
79
- * isArray([]); // true
80
- * ```
81
- */
82
- function isArray(value) {
83
- return Array.isArray(value);
84
- }
85
- /**
86
- * 检查 value 是否为 TypedArray
87
- *
88
- * @param value 待检查值
89
- * @returns 是否为 TypedArray
90
- * @example
91
- * ```ts
92
- * isTypedArray(new Int8Array()); // true
93
- * ```
94
- */
95
- function isTypedArray(value) {
96
- return typeof value === "object" && value !== null && TYPED_ARRAY_TAGS.has(resolvePrototypeString(value));
97
- }
98
- //#endregion
99
- //#region src/utils/typeof/isBigInt.ts
100
- /**
101
- * 检查 value 是否为 BigInt
102
- * @param value 待检查值
103
- * @returns 是否为 BigInt
104
- */
105
- function isBigInt(value) {
106
- return typeof value === "bigint";
107
- }
108
- //#endregion
109
- //#region src/utils/typeof/isBlob.ts
110
- /**
111
- * 检查 value 是否为 Blob
112
- * @param value 待检查值
113
- * @returns 是否为 Blob
114
- */
115
- function isBlob(value) {
116
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.blob;
117
- }
118
- function isFile(value) {
119
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.file;
120
- }
121
- //#endregion
122
- //#region src/utils/typeof/isBoolean.ts
123
- /**
124
- * 检查 value 是否为 Boolean
125
- * @param value 待检查值
126
- * @returns 是否为 Boolean
127
- */
128
- function isBoolean(value) {
129
- return typeof value === "boolean";
130
- }
131
- //#endregion
132
- //#region src/utils/typeof/isFunction.ts
133
- /**
134
- * 检查 value 是否为 Function
135
- * @param value 待检查值
136
- * @returns 是否为 Function
137
- */
138
- function isFunction(value) {
139
- return typeof value === "function";
140
- }
141
- /**
142
- * 检查 value 是否为 AsyncFunction
143
- * @param value 待检查值
144
- * @returns 是否为 AsyncFunction
145
- */
146
- function isAsyncFunction(value) {
147
- return isFunction(value) && resolvePrototypeString(value) === PROTOTYPE_TAGS.asyncFunction;
148
- }
149
- /**
150
- * 检查 value 是否为 GeneratorFunction
151
- * @param value 待检查值
152
- * @returns 是否为 GeneratorFunction
153
- */
154
- function isGeneratorFunction(value) {
155
- return isFunction(value) && resolvePrototypeString(value) === PROTOTYPE_TAGS.generatorFunction;
156
- }
157
- /**
158
- * 检查 value 是否为 AsyncGeneratorFunction
159
- * @param value 待检查值
160
- * @returns 是否为 AsyncGeneratorFunction
161
- */
162
- function isAsyncGeneratorFunction(value) {
163
- return isFunction(value) && resolvePrototypeString(value) === PROTOTYPE_TAGS.asyncGeneratorFunction;
164
- }
165
- //#endregion
166
- //#region src/utils/typeof/isClass.ts
167
- function isConstructable(fn) {
168
- try {
169
- Reflect.construct(fn, []);
170
- return true;
171
- } catch {
172
- return false;
173
- }
174
- }
175
- /**
176
- * 检查 value 是否为 Class
177
- *
178
- * @param value 待检查值
179
- * @returns 是否为 Class
180
- * @example
181
- * ```ts
182
- * class A {}
183
- * isClass(A); // true
184
- * isClass(() => {}); // false
185
- * ```
186
- */
187
- function isClass(value) {
188
- return isFunction(value) && !isAsyncFunction(value) && Function.prototype.toString.call(value).startsWith("class ") && isConstructable(value) && value.prototype !== void 0;
189
- }
190
- //#endregion
191
- //#region src/utils/typeof/isDate.ts
192
- /**
193
- * 检查 value 是否为 Date 对象
194
- *
195
- * @param value 待检查值
196
- * @param invalidCheck 是否要求日期有效(非 Invalid Date)。默认 true
197
- * - true: 仅当是有效 Date 对象时返回 true(排除 new Date('invalid'))
198
- * - false: 只要 [[Prototype]] 是 Date 即返回 true(包含 Invalid Date)
199
- * @returns 是否为 Date 对象,根据 invalidCheck 返回不同语义的 Date 判定
200
- *
201
- * @example
202
- * ```ts
203
- * isDate(new Date()); // true
204
- * isDate(new Date('invalid')); // false
205
- * isDate(new Date('invalid'), false); // true
206
- * isDate(null); // false
207
- * isDate({}); // false
208
- * ```
209
- */
210
- function isDate(value, invalidCheck = true) {
211
- if (!value || typeof value !== "object") return false;
212
- if (resolvePrototypeString(value) !== PROTOTYPE_TAGS.date) return false;
213
- if (!invalidCheck) return true;
214
- try {
215
- const time = value.getTime();
216
- return typeof time === "number" && !Number.isNaN(time);
217
- } catch {
218
- return false;
219
- }
220
- }
221
- //#endregion
222
- //#region src/utils/typeof/isEnumeration.ts
223
- /**
224
- * 判断一个对象是否为有效的枚举
225
- * - 枚举成员不能为空
226
- * - 枚举成员的键不能具有数值名
227
- * - 枚举成员的值必须类型一致且为 `string` 或 `number` 类型
228
- * - 枚举成员的值不能重复
229
- * - 枚举成员的值必须全部为双向映射或非双向映射
230
- *
231
- * @param enumeration 待检查值
232
- * @returns [是否为有效的枚举, 是否为双向枚举]
233
- */
234
- function isEnumeration(enumeration) {
235
- if (typeof enumeration !== "object" || enumeration === null) return [false, false];
236
- const keys = Object.keys(enumeration);
237
- if (keys.length === 0) return [false, false];
238
- const originalKeys = [];
239
- const numericKeys = [];
240
- for (const key of keys) if (/^\d+$/.test(key)) numericKeys.push(key);
241
- else originalKeys.push(key);
242
- if (originalKeys.length === 0) return [false, false];
243
- let valueType = null;
244
- const values = [];
245
- for (const key of originalKeys) {
246
- const value = enumeration[key];
247
- const type = typeof value;
248
- if (type !== "string" && type !== "number") return [false, false];
249
- if (valueType === null) valueType = type;
250
- else if (type !== valueType) return [false, false];
251
- values.push(value);
252
- }
253
- if (new Set(values).size !== values.length) return [false, false];
254
- let isBidirectional = false;
255
- if (numericKeys.length > 0) {
256
- if (numericKeys.length !== originalKeys.length) return [false, false];
257
- const reverseMappedNames = /* @__PURE__ */ new Set();
258
- for (const numKey of numericKeys) {
259
- const reverseValue = enumeration[numKey];
260
- if (typeof reverseValue !== "string") return [false, false];
261
- if (!originalKeys.includes(reverseValue)) return [false, false];
262
- reverseMappedNames.add(reverseValue);
263
- }
264
- if (reverseMappedNames.size !== originalKeys.length) return [false, false];
265
- isBidirectional = true;
266
- }
267
- return [true, isBidirectional];
268
- }
269
- //#endregion
270
- //#region src/utils/typeof/isEqual.ts
271
- /**
272
- * 深度比较两个值是否相等
273
- *
274
- * @param value 待比较值 A
275
- * @param other 待比较值 B
276
- * @returns 是否相等
277
- * @example
278
- * ```ts
279
- * isEqual({ a: 1 }, { a: 1 }); // true
280
- * ```
281
- */
282
- function isEqual(x, y) {
283
- const seen = /* @__PURE__ */ new WeakMap();
284
- function _isEqual(a, b) {
285
- if (Object.is(a, b)) return true;
286
- if (isDate(a) && isDate(b)) return a.getTime() === b.getTime();
287
- if (isRegExp(a) && isRegExp(b)) return a.toString() === b.toString();
288
- if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
289
- if (seen.has(a)) {
290
- if (seen.get(a).has(b)) return true;
291
- } else seen.set(a, /* @__PURE__ */ new Set());
292
- seen.get(a).add(b);
293
- const keysA = Reflect.ownKeys(a);
294
- const keysB = Reflect.ownKeys(b);
295
- if (keysA.length !== keysB.length) return false;
296
- for (const key of keysA) {
297
- if (!Reflect.has(b, key)) return false;
298
- if (!_isEqual(a[key], b[key])) return false;
299
- }
300
- return true;
301
- }
302
- return _isEqual(x, y);
303
- }
304
- //#endregion
305
- //#region src/utils/typeof/isError.ts
306
- /**
307
- * 检查 value 是否为 Error 对象
308
- * @param value 待检查值
309
- * @returns 是否为 Error
310
- */
311
- function isError(value) {
312
- return value instanceof Error || resolvePrototypeString(value) === PROTOTYPE_TAGS.error;
313
- }
314
- //#endregion
315
- //#region src/utils/typeof/isFalsy.ts
316
- /**
317
- * 检查 value 是否为 Falsy 值 (false, 0, "", null, undefined, NaN)
318
- * @param value 待检查值
319
- * @returns 是否为 Falsy
320
- */
321
- function isFalsy(value) {
322
- if (isNaN(value) || isNull(value) || isUndefined(value)) return true;
323
- return value === false || value === 0 || value === 0n || value === "";
324
- }
325
- function isFalsyLike(value) {
326
- if (isFalsy(value)) return true;
327
- return typeof value === "string" && (value === "null" || value === "undefined" || value === "NaN" || value === "false" || value === "0" || value === "-0" || value === "0n");
328
- }
329
- //#endregion
330
- //#region src/utils/typeof/isIframe.ts
331
- /**
332
- * 检查 value 是否为 HTMLIFrameElement
333
- * @param value 待检查值
334
- * @returns 是否为 HTMLIFrameElement
335
- */
336
- function isIframe(value) {
337
- if (typeof window === "undefined") return false;
338
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.iframe;
339
- }
340
- function isInIframe() {
341
- if (typeof window === "undefined") return false;
342
- try {
343
- return window.top !== window.self;
344
- } catch (error) {
345
- if (error.name === "SecurityError") return true;
346
- return false;
347
- }
348
- }
349
- //#endregion
350
- //#region src/utils/typeof/isIterable.ts
351
- /**
352
- * 检查 value 是否为可迭代对象 (Iterable)
353
- * @param value 待检查值
354
- * @returns 是否为 Iterable
355
- */
356
- function isIterable(value) {
357
- return !!value && typeof value[Symbol.iterator] === "function";
358
- }
359
- //#endregion
360
- //#region src/utils/typeof/isMap.ts
361
- /**
362
- * 检查 value 是否为 Map
363
- * @param value 待检查值
364
- * @returns 是否为 Map
365
- */
366
- function isMap(value) {
367
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.map;
368
- }
369
- /**
370
- * 检查 value 是否为 WeakMap
371
- * @param value 待检查值
372
- * @returns 是否为 WeakMap
373
- */
374
- function isWeakMap(value) {
375
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.weakMap;
376
- }
377
- //#endregion
378
- //#region src/utils/typeof/isNull.ts
379
- /**
380
- * 检查 value 是否为 null
381
- * @param value 待检查值
382
- * @returns 是否为 null
383
- */
384
- function isNull(value) {
385
- return value === null;
386
- }
387
- //#endregion
388
- //#region src/utils/typeof/isNumber.ts
389
- /**
390
- * 检查 value 是否为 number 类型
391
- *
392
- * @param value 待检查值
393
- * @param NaNCheck 是否排除 `NaN`,默认为 `true`
394
- * @returns 是否为 number
395
- * @example
396
- * ```ts
397
- * isNumber(1); // true
398
- * isNumber(NaN); // false (default)
399
- * isNumber(NaN, false); // true
400
- * ```
401
- */
402
- function isNumber(value, NaNCheck = true) {
403
- return typeof value === "number" && (!NaNCheck || !isNaN(value));
404
- }
405
- /**
406
- * 检查 value 是否为 NaN
407
- *
408
- * @param value 待检查值
409
- * @returns 是否为 NaN
410
- */
411
- function isNaN(value) {
412
- return Number.isNaN(value);
413
- }
414
- /**
415
- * 检查 value 是否为整数
416
- *
417
- * @param value 待检查值
418
- * @param safeCheck 是否附加安全整数检查
419
- * @returns 是否为整数
420
- */
421
- function isInteger(value, safeCheck = true) {
422
- const check = Number.isInteger(value);
423
- return safeCheck ? check && Number.isSafeInteger(value) : check;
424
- }
425
- /**
426
- * 检查 value 是否为正整数
427
- * - 此函数中 `0` 不被视为正整数
428
- *
429
- * @param value 待检查值
430
- * @param safeCheck 是否附加安全整数检查
431
- */
432
- function isPositiveInteger(value, safeCheck = true) {
433
- return isInteger(value, safeCheck) && value > 0;
434
- }
435
- /**
436
- * 检查 value 是否为负整数
437
- * - 此函数中 `0` 不被视为负整数
438
- *
439
- * @param value 待检查值
440
- * @param safeCheck 是否附加安全整数检查
441
- */
442
- function isNegativeInteger(value, safeCheck = true) {
443
- return isInteger(value, safeCheck) && value < 0;
444
- }
445
- /**
446
- * 检查 value 是否为 Infinity
447
- * - 排除 `NaN`
448
- *
449
- * @param value 待检查值
450
- */
451
- function isInfinity(value) {
452
- return isNumber(value) && (Number.POSITIVE_INFINITY === value || Number.NEGATIVE_INFINITY === value);
453
- }
454
- /**
455
- * 检查 value 是否类似 Infinity
456
- * - 排除 `NaN`
457
- *
458
- * @param value 待检查值
459
- */
460
- function isInfinityLike(value) {
461
- const check = isInfinity(value);
462
- if (check) return check;
463
- if (typeof value === "string") {
464
- const v = value.trim().toLowerCase();
465
- return v === "infinity" || v === "-infinity" || v === "+infinity";
466
- }
467
- return false;
468
- }
469
- //#endregion
470
- //#region src/utils/typeof/isObject.ts
471
- /**
472
- * 判断是否为普通对象类型
473
- * - 可选是否检查原型为 `Object.prototype`,防止原型链污染
474
- *
475
- * @param value 待检查值
476
- * @param prototypeCheck 是否进行原型检查,默认 `true`
477
- * @returns 是否为 Plain Object (当 checkPrototype=true) 或 object
478
- * @example
479
- * ```ts
480
- * isObject({}); // true
481
- * isObject([]); // false
482
- * isObject(new Date()); // false
483
- * isObject(new Date(), false); // true
484
- * isObject(Object.create(null)) // false
485
- * isObject(Object.create(null), false) // true
486
- * ```
487
- */
488
- function isObject(value, prototypeCheck = true) {
489
- const check = resolvePrototypeString(value) === PROTOTYPE_TAGS.object;
490
- return prototypeCheck ? check && Object.getPrototypeOf(value) === Object.prototype : check;
491
- }
492
- //#endregion
493
- //#region src/utils/typeof/isPromise.ts
494
- /**
495
- * 检查 value 是否为 Promise
496
- * @param value 待检查值
497
- * @returns 是否为 Promise
498
- */
499
- function isPromise(value) {
500
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.promise;
501
- }
502
- /**
503
- * 检查 value 是否为 PromiseLike (thenable)
504
- * @param value 待检查值
505
- * @returns 是否为 PromiseLike
506
- */
507
- function isPromiseLike(value) {
508
- return isPromise(value) || isObject(value, false) && isFunction(value["then"]);
509
- }
510
- //#endregion
511
- //#region src/utils/typeof/isReadableStream.ts
512
- /**
513
- * 检查 value 是否为 ReadableStream
514
- * - Uses `Object.prototype.toString` where supported (modern browsers, Node.js ≥18).
515
- * - Falls back to duck-typing in older environments.
516
- * - Resistant to basic forgery, but not 100% secure in all polyfill scenarios.
517
- * - ⚠️ Note: In older Node.js (<18) or with non-compliant polyfills, this may return false positives or negatives.
518
- *
519
- * @param value 待检查值
520
- * @returns 是否为 ReadableStream
521
- */
522
- function isReadableStream(value) {
523
- if (resolvePrototypeString(value) === PROTOTYPE_TAGS.readableStream) return true;
524
- return isObject(value) && isFunction(value["getReader"]) && isFunction(value["pipeThrough"]);
525
- }
526
- //#endregion
527
- //#region src/utils/typeof/isRegExp.ts
528
- /**
529
- * 检查 value 是否为 RegExp
530
- * @param value 待检查值
531
- * @returns 是否为 RegExp
532
- */
533
- function isRegExp(value) {
534
- if (typeof value !== "object" || value === null) return false;
535
- try {
536
- const regex = value;
537
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.regExp && isString(regex.source) && isString(regex.flags) && isBoolean(regex.global) && isFunction(regex.test);
538
- } catch (error) {
539
- return false;
540
- }
541
- }
542
- //#endregion
543
- //#region src/utils/typeof/isSet.ts
544
- /**
545
- * 检查 value 是否为 Set
546
- * @param value 待检查值
547
- * @returns 是否为 Set
548
- */
549
- function isSet(value) {
550
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.set;
551
- }
552
- /**
553
- * 检查 value 是否为 WeakSet
554
- * @param value 待检查值
555
- * @returns 是否为 WeakSet
556
- */
557
- function isWeakSet(value) {
558
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.weakSet;
559
- }
560
- //#endregion
561
- //#region src/utils/typeof/isString.ts
562
- /**
563
- * 检查 value 是否为 string 类型
564
- *
565
- * @param value 待检查值
566
- * @param checkEmpty 是否检查空字符串
567
- * @returns 是否为字符串
568
- * @example
569
- * ```ts
570
- * isString("abc"); // true
571
- * isString(""); // true
572
- * isString("", true); // false
573
- * ```
574
- */
575
- function isString(value, checkEmpty = false) {
576
- return typeof value === "string" && (!checkEmpty || !!value.length);
577
- }
578
- //#endregion
579
- //#region src/utils/typeof/isSymbol.ts
580
- /**
581
- * 检查 value 是否为 Symbol
582
- * @param value 待检查值
583
- * @returns 是否为 Symbol
584
- */
585
- function isSymbol(value) {
586
- return typeof value === "symbol";
587
- }
588
- //#endregion
589
- //#region src/utils/typeof/isUndefined.ts
590
- /**
591
- * 检查 value 是否为 undefined
592
- * @param value 待检查值
593
- * @returns 是否为 undefined
594
- */
595
- function isUndefined(value) {
596
- return typeof value === "undefined";
597
- }
598
- //#endregion
599
- //#region src/utils/typeof/isURLSearchParams.ts
600
- /**
601
- * 检查 value 是否为 URLSearchParams
602
- * @param value 待检查值
603
- * @returns 是否为 URLSearchParams
604
- */
605
- function isURLSearchParams(value) {
606
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.URLSearchParams;
607
- }
608
- //#endregion
609
- //#region src/utils/typeof/isWebSocket.ts
610
- /**
611
- * 检查 value 是否为 WebSocket
612
- * @param value 待检查值
613
- * @returns 是否为 WebSocket
614
- */
615
- function isWebSocket(value) {
616
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.webSocket;
617
- }
618
- //#endregion
619
- //#region src/utils/typeof/isWindow.ts
620
- /**
621
- * 检查 value 是否为 Window
622
- * @param value 待检查值
623
- * @returns 是否为 Window
624
- */
625
- function isWindow(value) {
626
- return resolvePrototypeString(value) === PROTOTYPE_TAGS.window;
627
- }
628
- //#endregion
629
- //#region src/utils/array/arrayCast.ts
630
- function arrayCast(candidate, checkEmpty = true) {
631
- if (checkEmpty && (isUndefined(candidate) || isNull(candidate))) return [];
632
- return isArray(candidate) ? [...candidate] : [candidate];
633
- }
634
- //#endregion
635
- //#region src/utils/array/arrayCompete.ts
636
- /**
637
- * 数组竞争
638
- * - 返回在匹配函数的比较条件中获胜的最终项目,适用于更复杂的最小值/最大值计算
639
- *
640
- * @param initialList 数组
641
- * @param match 匹配函数
642
- * @returns 获胜的元素,如果数组为空或参数无效则返回 `null`
643
- * @example
644
- * ```ts
645
- * const list = [1, 10, 5];
646
- * arrayCompete(list, (a, b) => (a > b ? a : b)); // 10
647
- * arrayCompete(list, (a, b) => (a < b ? a : b)); // 1
648
- * ```
649
- */
650
- function arrayCompete(initialList, match) {
651
- if (!isArray(initialList) || initialList.length === 0 || !isFunction(match)) return null;
652
- return initialList.reduce(match);
653
- }
654
- //#endregion
655
- //#region src/utils/array/arrayCounting.ts
656
- /**
657
- * 统计数组的项目出现次数
658
- * - 通过给定的标识符匹配函数,返回一个对象,其中键是回调函数返回的 key 值,每个值是一个整数,表示该 key 出现的次数
659
- *
660
- * @param initialList 初始数组
661
- * @param match 匹配函数
662
- * @returns 统计对象
663
- * @example
664
- * ```ts
665
- * const list = ["a", "b", "a", "c"];
666
- * arrayCounting(list, (x) => x); // { a: 2, b: 1, c: 1 }
667
- *
668
- * const users = [{ id: 1, group: "A" }, { id: 2, group: "B" }, { id: 3, group: "A" }];
669
- * arrayCounting(users, (u) => u.group); // { A: 2, B: 1 }
670
- * ```
671
- */
672
- function arrayCounting(initialList, match) {
673
- if (!isArray(initialList) || !isFunction(match)) return {};
674
- return initialList.reduce((prev, curr, index) => {
675
- const id = match(curr, index).toString();
676
- prev[id] = (prev[id] ?? 0) + 1;
677
- return prev;
678
- }, {});
679
- }
680
- //#endregion
681
- //#region src/utils/array/arrayDifference.ts
682
- /**
683
- * 求数组差集
684
- * - 返回在 `initialList` 中存在,但在 `diffList` 中不存在的元素
685
- *
686
- * @param initialList 初始数组
687
- * @param diffList 对比数组
688
- * @param match 匹配函数
689
- * @returns 差集数组
690
- * @example
691
- * ```ts
692
- * arrayDifference([1, 2, 3], [2, 3, 4]); // [1]
693
- * arrayDifference([{ id: 1 }, { id: 2 }], [{ id: 2 }], (x) => x.id); // [{ id: 1 }]
694
- * ```
695
- */
696
- function arrayDifference(initialList, diffList, match) {
697
- if (!isArray(initialList) && !isArray(diffList)) return [];
698
- if (!isArray(initialList) || !initialList.length) return [];
699
- if (!isArray(diffList) || !diffList.length) return [...initialList];
700
- if (!isFunction(match)) {
701
- const arraySet = new Set(diffList);
702
- return Array.from(new Set(initialList.filter((item) => !arraySet.has(item))));
703
- }
704
- const map = /* @__PURE__ */ new Map();
705
- diffList.forEach((item, index) => {
706
- map.set(match(item, index), true);
707
- });
708
- return initialList.filter((item, index) => !map.get(match(item, index)));
709
- }
710
- //#endregion
711
- //#region src/utils/array/arrayFirst.ts
712
- function arrayFirst(initialList, saveValue) {
713
- if (!isArray(initialList) || initialList.length === 0) return saveValue;
714
- return initialList[0];
715
- }
716
- //#endregion
717
- //#region src/utils/array/arrayFork.ts
718
- /**
719
- * 数组分组过滤
720
- * - 给定一个数组和一个条件,返回一个由两个数组组成的元组,其中第一个数组包含所有满足条件的项,第二个数组包含所有不满足条件的项
721
- *
722
- * @param initialList 初始数组
723
- * @param match 条件匹配函数
724
- * @returns [满足条件的项[], 不满足条件的项[]]
725
- * @example
726
- * ```ts
727
- * arrayFork([1, 2, 3, 4], (n) => n % 2 === 0); // [[2, 4], [1, 3]]
728
- * ```
729
- */
730
- function arrayFork(initialList, match) {
731
- const forked = [[], []];
732
- if (isArray(initialList)) initialList.forEach((item, index) => {
733
- forked[match(item, index) ? 0 : 1].push(item);
734
- });
735
- return forked;
736
- }
737
- //#endregion
738
- //#region src/utils/array/arrayIntersection.ts
739
- function arrayIntersection(initialList, diffList, match) {
740
- if (!isArray(initialList) || !isArray(diffList)) return [];
741
- if (!initialList.length || !diffList.length) return [];
742
- if (!isFunction(match)) {
743
- const diffSet = new Set(diffList);
744
- return initialList.filter((item) => diffSet.has(item));
745
- }
746
- const diffKeys = new Set(diffList.map((item, index) => match(item, index)));
747
- return initialList.filter((item, index) => diffKeys.has(match(item, index)));
748
- }
749
- //#endregion
750
- //#region src/utils/array/arrayLast.ts
751
- function arrayLast(initialList, saveValue) {
752
- if (!isArray(initialList) || initialList.length === 0) return saveValue;
753
- return initialList[initialList.length - 1];
754
- }
755
- //#endregion
756
- //#region src/utils/array/arrayMerge.ts
757
- function arrayMerge(initialList, mergeList, match) {
758
- if (!isArray(initialList)) return [];
759
- if (!isArray(mergeList)) return [...initialList];
760
- if (!isFunction(match)) return Array.from(new Set([...initialList, ...mergeList]));
761
- const keys = /* @__PURE__ */ new Map();
762
- mergeList.forEach((item, index) => {
763
- keys.set(match(item, index), item);
764
- });
765
- return initialList.map((prevItem, index) => {
766
- const key = match(prevItem, index);
767
- return keys.has(key) ? keys.get(key) : prevItem;
768
- });
769
- }
770
- //#endregion
771
- //#region src/utils/array/arrayPick.ts
772
- function arrayPick(initialList, filter, mapper) {
773
- if (!isArray(initialList)) return [];
774
- if (!isFunction(filter)) return [...initialList];
775
- const hasMapper = isFunction(mapper);
776
- return initialList.reduce((prev, curr, index) => {
777
- if (!filter(curr, index)) return prev;
778
- if (hasMapper) prev.push(mapper(curr, index));
779
- else prev.push(curr);
780
- return prev;
781
- }, []);
782
- }
783
- //#endregion
784
- //#region src/utils/array/arrayReplace.ts
785
- function arrayReplace(initialList, newItem, match) {
786
- if (!isArray(initialList) || !initialList.length) return [];
787
- if (!isFunction(match)) return [...initialList];
788
- for (let i = 0; i < initialList.length; i++) {
789
- const item = initialList[i];
790
- if (match(item, i)) return [
791
- ...initialList.slice(0, i),
792
- newItem,
793
- ...initialList.slice(i + 1, initialList.length)
794
- ];
795
- }
796
- return [...initialList];
797
- }
798
- //#endregion
799
- //#region src/utils/array/arrayReplaceMove.ts
800
- /**
801
- * 数组项替换并移动
802
- * - 在给定的数组中,替换并移动符合匹配函数结果的项目
803
- * - 只替换和移动第一个匹配项
804
- * - 未匹配时,根据 `position` 在指定位置插入 `newItem`
805
- *
806
- * @param initialList 初始数组
807
- * @param newItem 替换项
808
- * @param match 匹配函数
809
- * @param position 移动位置,可选 `start` | `end` | 索引位置, 默认为 `end`
810
- * @returns
811
- * @example
812
- * ```ts
813
- * arrayReplaceMove([1, 2, 3, 4], 5, (n) => n === 2, 0); // [5, 1, 3, 4]
814
- * arrayReplaceMove([1, 2, 3, 4], 5, (n) => n === 2, 2); // [1, 3, 5, 4]
815
- * arrayReplaceMove([1, 2, 3, 4], 5, (n) => n === 2, "start"); // [5, 1, 3, 4]
816
- * arrayReplaceMove([1, 2, 3, 4], 5, (n) => n === 2); // [1, 3, 4, 5]
817
- * ```
818
- */
819
- function arrayReplaceMove(initialList, newItem, match, position) {
820
- if (!isArray(initialList)) return [];
821
- if (!initialList.length) return [newItem];
822
- if (!isFunction(match)) return [...initialList];
823
- const result = [...initialList];
824
- const matchIndex = initialList.findIndex(match);
825
- if (matchIndex !== -1) result.splice(matchIndex, 1);
826
- if (position === "start") result.unshift(newItem);
827
- else if (position === 0 || isPositiveInteger(position, false)) result.splice(Math.min(position, result.length), 0, newItem);
828
- else result.push(newItem);
829
- return result;
830
- }
831
- //#endregion
832
- //#region src/utils/array/arraySplit.ts
833
- /**
834
- * 数组切分
835
- * - 将数组以指定的长度切分后,组合在高维数组中
836
- *
837
- * @param initialList 初始数组
838
- * @param size 分割尺寸,默认 `10`
839
- * @returns 切分后的二维数组
840
- * @example
841
- * ```ts
842
- * arraySplit([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
843
- * ```
844
- */
845
- function arraySplit(initialList, size = 10) {
846
- if (!isArray(initialList)) return [];
847
- if (!isPositiveInteger(size, false)) return [];
848
- const count = Math.ceil(initialList.length / size);
849
- return Array.from({ length: count }).fill(null).map((_c, i) => {
850
- return initialList.slice(i * size, i * size + size);
851
- });
852
- }
853
- //#endregion
854
- //#region src/utils/array/arrayZip.ts
855
- /**
856
- * 数组解压
857
- * - `arrayZip` 的反向操作
858
- *
859
- * @param arrays 压缩后的数组
860
- * @returns 解压后的二维数组
861
- * @example
862
- * ```ts
863
- * arrayUnzip([[1, "a"], [2, "b"]]); // [[1, 2], ["a", "b"]]
864
- * ```
865
- */
866
- function arrayUnzip(arrays) {
867
- if (!isArray(arrays) || !arrays.length) return [];
868
- const out = new Array(arrays.reduce((max, arr) => Math.max(max, arr.length), 0));
869
- let index = 0;
870
- const get = (array) => array[index];
871
- for (; index < out.length; index++) out[index] = Array.from(arrays, get);
872
- return out;
873
- }
874
- function arrayZip(...arrays) {
875
- return arrayUnzip(arrays);
876
- }
877
- //#endregion
878
- //#region src/utils/array/arrayZipToObject.ts
879
- function arrayZipToObject(keys, values) {
880
- const result = {};
881
- if (!isArray(keys) || !keys.length) return result;
882
- const getValue = isFunction(values) ? values : isArray(values) ? (_k, i) => values[i] : (_k, _i) => values;
883
- return keys.reduce((acc, key, idx) => {
884
- acc[key] = getValue(key, idx);
885
- return acc;
886
- }, result);
887
- }
888
- //#endregion
889
- //#region src/utils/device/isBrowser.ts
890
- const _isBrowser = typeof window !== "undefined" && isFunction(window?.document?.createElement);
891
- function isBrowser() {
892
- return _isBrowser;
893
- }
894
- //#endregion
895
- //#region src/utils/device/isDesktop.ts
896
- /**
897
- * 检测当前设备是否为桌面设备
898
- *
899
- * @param minWidth - 桌面设备最小宽度(默认 1200px)
900
- * @param minScreenSize - 桌面设备最小屏幕尺寸(默认 10英寸)
901
- * @param dpi - 标准 DPI 基准(默认 160)
902
- * @returns 是否为桌面设备
903
- * @example
904
- * ```ts
905
- * // 假设 window.innerWidth = 1920
906
- * isDesktop(); // true
907
- *
908
- * // 自定义阈值
909
- * isDesktop(1440, 13); // 更严格的桌面检测
910
- * ```
911
- */
912
- function isDesktop(minWidth = 1200, minScreenSize = 10, dpi = 160) {
913
- if (typeof window === "undefined" || !isPositiveInteger(minWidth) || !isPositiveInteger(minScreenSize)) return false;
914
- if (window.innerWidth < minWidth) return false;
915
- try {
916
- const widthPx = window.screen.width;
917
- const heightPx = window.screen.height;
918
- const DPI = dpi * (window.devicePixelRatio || 1);
919
- const widthInch = widthPx / DPI;
920
- const heightInch = heightPx / DPI;
921
- return Math.sqrt(widthInch ** 2 + heightInch ** 2) >= minScreenSize;
922
- } catch {
923
- return true;
924
- }
925
- }
926
- /**
927
- * 检测当前设备是否为 Windows 桌面设备
928
- *
929
- * @param minWidth - 桌面设备最小宽度(默认 1200px)
930
- * @param minScreenSize - 桌面设备最小屏幕尺寸(默认 10英寸)
931
- * @param dpi - 标准 DPI 基准(默认 160)
932
- * @returns 是否为 Windows 桌面设备
933
- * @example
934
- * ```ts
935
- * // UA contains Windows
936
- * isWindowsDesktop(); // true
937
- * ```
938
- */
939
- function isWindowsDesktop(minWidth = 1200, minScreenSize = 10, dpi = 160) {
940
- if (typeof navigator === "undefined" || !navigator.userAgent) return false;
941
- return /Windows/i.test(navigator.userAgent) && isDesktop(minWidth, minScreenSize, dpi);
942
- }
943
- /**
944
- * 检测当前设备是否为 macOS 桌面设备
945
- *
946
- * @param minWidth - 桌面设备最小宽度(默认 1200px)
947
- * @param minScreenSize - 桌面设备最小屏幕尺寸(默认 10英寸)
948
- * @param dpi - 标准 DPI 基准(默认 160)
949
- * @returns 是否为 macOS 桌面设备
950
- * @example
951
- * ```ts
952
- * // UA contains Macintosh
953
- * isMacOSDesktop(); // true
954
- * ```
955
- */
956
- function isMacOSDesktop(minWidth = 1200, minScreenSize = 10, dpi = 160) {
957
- if (typeof navigator === "undefined" || !navigator.userAgent) return false;
958
- return /Macintosh/i.test(navigator.userAgent) && isDesktop(minWidth, minScreenSize, dpi);
959
- }
960
- //#endregion
961
- //#region src/utils/device/isMobile.ts
962
- /**
963
- * 检测当前设备是否为移动设备
964
- *
965
- * @param maxWidth - 移动设备最大宽度(默认 768px)
966
- * @param dpi - 标准 DPI 基准(默认 160)
967
- * @returns 是否为移动设备
968
- * @example
969
- * ```ts
970
- * // 假设 window.innerWidth = 500
971
- * isMobile(); // true
972
- * ```
973
- */
974
- function isMobile(maxWidth = 768, dpi = 160) {
975
- if (typeof window === "undefined" || !isPositiveInteger(maxWidth)) return false;
976
- if (window.innerWidth >= maxWidth) return false;
977
- try {
978
- const widthPx = window.screen.width;
979
- const heightPx = window.screen.height;
980
- const DPI = dpi * (window.devicePixelRatio || 1);
981
- const widthInch = widthPx / DPI;
982
- const heightInch = heightPx / DPI;
983
- return Math.sqrt(widthInch ** 2 + heightInch ** 2) < 7;
984
- } catch {
985
- return true;
986
- }
987
- }
988
- /**
989
- * 检测当前设备是否为IOS移动设备
990
- *
991
- * @param maxWidth - 移动设备最大宽度(默认 768px)
992
- * @param dpi - 标准 DPI 基准(默认 160)
993
- * @returns 是否为 iOS 移动设备 (iPhone/iPod)
994
- * @example
995
- * ```ts
996
- * // UA contains iPhone
997
- * isIOSMobile(); // true
998
- * ```
999
- */
1000
- function isIOSMobile(maxWidth = 768, dpi = 160) {
1001
- if (typeof navigator === "undefined" || !navigator.userAgent) return false;
1002
- return /iPhone|iPad|iPod/i.test(navigator.userAgent) && isMobile(maxWidth, dpi);
1003
- }
1004
- //#endregion
1005
- //#region src/utils/device/isReactNative.ts
1006
- const _isReactNative = typeof navigator !== "undefined" && navigator.product === "ReactNative";
1007
- function isReactNative() {
1008
- return _isReactNative;
1009
- }
1010
- //#endregion
1011
- //#region src/utils/device/isTablet.ts
1012
- /**
1013
- * 检测当前设备是否为平板
1014
- *
1015
- * @param minWidth - 平板最小宽度(默认 768px)
1016
- * @param maxWidth - 平板最大宽度(默认 1200px)
1017
- * @param dpi - 标准 DPI 基准(默认 160)
1018
- * @returns 是否为平板设备
1019
- * @example
1020
- * ```ts
1021
- * // 假设 window.innerWidth = 1000
1022
- * isTablet(); // true
1023
- * ```
1024
- */
1025
- function isTablet(minWidth = 768, maxWidth = 1200, dpi = 160) {
1026
- if (typeof window === "undefined" || !isPositiveInteger(minWidth) || !isPositiveInteger(maxWidth)) return false;
1027
- const width = window.innerWidth;
1028
- const isWithinWidthRange = width >= minWidth && width <= maxWidth;
1029
- try {
1030
- const widthPx = window.screen.width;
1031
- const heightPx = window.screen.height;
1032
- const DPI = dpi * (window.devicePixelRatio || 1);
1033
- const widthInch = widthPx / DPI;
1034
- const heightInch = heightPx / DPI;
1035
- const screenInches = Math.sqrt(widthInch ** 2 + heightInch ** 2);
1036
- return isWithinWidthRange || screenInches >= 7;
1037
- } catch {
1038
- return isWithinWidthRange;
1039
- }
1040
- }
1041
- //#endregion
1042
- //#region src/utils/device/isWebWorker.ts
1043
- const _isWebWorker = typeof window === "undefined" && typeof self !== "undefined" && "importScripts" in self;
1044
- function isWebWorker() {
1045
- return _isWebWorker;
1046
- }
1047
- //#endregion
1048
- //#region src/utils/function/to.ts
1049
- /**
1050
- *将 Promise 转换为 `[err, result]` 格式,方便 async/await 错误处理
1051
- *
1052
- * @param promise 待处理的 Promise
1053
- * @param errorExt 附加到 error 对象的扩展信息(注意:如果原 error 是 Error 实例,扩展属性可能会覆盖或无法正确合并非枚举属性)
1054
- * @returns `[err, null]` 或 `[null, data]`
1055
- * @example
1056
- * ```ts
1057
- * const [err, data] = await to(someAsyncFunc());
1058
- * if (err) return;
1059
- * console.log(data);
1060
- * ```
1061
- */
1062
- function to(promise, errorExt) {
1063
- return promise.then((data) => [null, data]).catch((err) => {
1064
- if (errorExt) {
1065
- const parsedError = {
1066
- name: "",
1067
- message: "",
1068
- stack: ""
1069
- };
1070
- if (err instanceof Error) {
1071
- parsedError.message = err.message;
1072
- parsedError.name = err.name;
1073
- parsedError.stack = err.stack;
1074
- Object.getOwnPropertyNames(err).forEach((key) => {
1075
- if (!(key in parsedError)) parsedError[key] = err[key];
1076
- });
1077
- } else Object.assign(parsedError, err);
1078
- Object.assign(parsedError, errorExt);
1079
- return [parsedError, void 0];
1080
- }
1081
- return [err ? err : /* @__PURE__ */ new Error("defaultError"), void 0];
1082
- });
1083
- }
1084
- //#endregion
1085
- //#region src/utils/function/toPromise.ts
1086
- /**
1087
- * 将同步或异步函数统一包装为 Promise
1088
- * - 自动捕获同步异常
1089
- *
1090
- * @param fn 返回值可为同步值或 Promise 的函数
1091
- * @returns 标准化的 Promise
1092
- *
1093
- * @example
1094
- * // 同步函数
1095
- * toPromise(() => 42).then(v => console.log(v)); // 42
1096
- *
1097
- * // 异步函数
1098
- * toPromise(async () => await fetchData()).then(data => ...);
1099
- *
1100
- * // 异常处理
1101
- * toPromise(() => { throw new Error('fail'); }).catch(err => console.error(err)); // 捕获同步异常
1102
- */
1103
- function toPromise(fn) {
1104
- try {
1105
- return Promise.resolve(fn());
1106
- } catch (error) {
1107
- return Promise.reject(error);
1108
- }
1109
- }
1110
- //#endregion
1111
- //#region src/utils/string/stringInitialCase.ts
1112
- const R1$2 = /\S+/g;
1113
- const R2 = /[^a-zA-Z\u00C0-\u017F]/;
1114
- /**
1115
- * 字符串首字母大小写
1116
- * - 包含非西欧字母字符时,不处理
1117
- * - 纯字母且全大写时,不处理
1118
- * - 纯字母且非全大写时,首字母小写,其余保留
1119
- * - 纯字母且非全大写时,首字母大写,其余保留
1120
- *
1121
- * @param input 待处理字符串
1122
- * @param caseType 大小写类型
1123
- * @returns 处理后的字符串
1124
- * @example
1125
- * ```ts
1126
- * stringInitialCase("Hello", "lower"); // "hello"
1127
- * stringInitialCase("hello", "upper"); // "Hello"
1128
- * ```
1129
- */
1130
- function stringInitialCase(input, caseType) {
1131
- if (!isString(input, true)) return "";
1132
- return input.replace(R1$2, (word) => {
1133
- if (R2.test(word)) return word;
1134
- if (word === word.toLocaleUpperCase()) return word;
1135
- if (caseType === "lower" && word[0]) return word[0].toLocaleLowerCase() + word.slice(1);
1136
- if (caseType === "upper" && word[0]) return word[0].toLocaleUpperCase() + word.slice(1);
1137
- return word;
1138
- });
1139
- }
1140
- //#endregion
1141
- //#region src/utils/string/stringReplace.ts
1142
- /**
1143
- * 字符串替换
1144
- * - 替换第一个匹配项
1145
- *
1146
- * @param input 待处理字符串
1147
- * @param search 匹配项
1148
- * @param replacement 替换项
1149
- * @returns 替换后的字符串
1150
- * @example
1151
- * ```ts
1152
- * stringReplace("hello world", "world", "context"); // "hello context"
1153
- * ```
1154
- */
1155
- function stringReplace(input, search, replacement) {
1156
- if (!isString(input, true)) return "";
1157
- return input.replace(search, replacement);
1158
- }
1159
- //#endregion
1160
- //#region src/utils/string/stringTemplate.ts
1161
- const R1$1 = /\{\{(.+?)\}\}/g;
1162
- /**
1163
- * 字符串模板替换
1164
- * - 使用对象的属性值替换字符串中的 {{key}} 模板
1165
- *
1166
- * @param input 待处理字符串
1167
- * @param template 模板对象
1168
- * @param regex 模板匹配正则 (默认: `\{\{(.+?)\}\}`)
1169
- * @returns 替换后的字符串
1170
- * @example
1171
- * ```ts
1172
- * stringTemplate("Hello {{name}}", { name: "World" }); // "Hello World"
1173
- * ```
1174
- */
1175
- function stringTemplate(input, template, regex = R1$1) {
1176
- if (!isString(input, true)) return "";
1177
- regex.lastIndex = 0;
1178
- let result = "";
1179
- let from = 0;
1180
- let match;
1181
- while (match = regex.exec(input)) {
1182
- const replacement = template[match[1]];
1183
- const valueToInsert = replacement === null || replacement === void 0 ? match[0] : replacement;
1184
- result += input.slice(from, match.index) + valueToInsert;
1185
- from = regex.lastIndex;
1186
- }
1187
- return result + input.slice(from);
1188
- }
1189
- //#endregion
1190
- //#region src/utils/string/stringToJson.ts
1191
- /**
1192
- * 处理 JSON 字符串
1193
- *
1194
- * @param input 待处理字符串
1195
- * @param safeValue 安全值 (当解析失败或输入无效时返回)
1196
- * @returns 解析后的对象 或 安全值
1197
- * @example
1198
- * ```ts
1199
- * stringToJson('{"a": 1}', {}); // { a: 1 }
1200
- * stringToJson('invalid', {}); // {}
1201
- * ```
1202
- */
1203
- function stringToJson(input, safeValue) {
1204
- if (!isString(input, true)) return safeValue;
1205
- try {
1206
- return JSON.parse(input);
1207
- } catch (error) {
1208
- return safeValue;
1209
- }
1210
- }
1211
- //#endregion
1212
- //#region src/utils/string/stringToLowerCase.ts
1213
- function stringToLowerCase(input) {
1214
- if (!isString(input, true)) return "";
1215
- return input.toLowerCase();
1216
- }
1217
- //#endregion
1218
- //#region src/utils/string/stringToNumber.ts
1219
- const R1 = /[^0-9.-]/g;
1220
- /**
1221
- * 从字符串中提取数字字符串
1222
- * - 移除非数字字符,保留符号和小数点
1223
- *
1224
- * @param input 待处理字符串
1225
- * @returns 提取出的数字字符串
1226
- * @example
1227
- * ```ts
1228
- * stringToNumber("$1,234.56"); // "1234.56"
1229
- * stringToNumber("abc-123"); // "-123"
1230
- * ```
1231
- */
1232
- function stringToNumber(input) {
1233
- if (!isString(input, true)) return "0";
1234
- const cleaned = input.replace(R1, "");
1235
- if (!cleaned) return "0";
1236
- let isDecimal = false;
1237
- let signCount = 0;
1238
- let firstIndex = -1;
1239
- const stringList = cleaned.split("").map((s, i) => {
1240
- if (s === ".") {
1241
- if (isDecimal) return "";
1242
- isDecimal = true;
1243
- return ".";
1244
- }
1245
- if (s === "-") {
1246
- firstIndex === -1 && signCount++;
1247
- return "";
1248
- }
1249
- firstIndex === -1 && (firstIndex = i);
1250
- return s;
1251
- });
1252
- const sign = signCount % 2 === 1 ? "-" : "";
1253
- if (firstIndex === -1) return sign + "0";
1254
- let result = stringList.join("");
1255
- if (result.startsWith(".")) result = "0" + result;
1256
- if (result.endsWith(".")) result = result.slice(0, -1);
1257
- return sign + result;
1258
- }
1259
- //#endregion
1260
- //#region src/utils/string/stringToPosix.ts
1261
- /**
1262
- * 将路径转换为 POSIX 风格
1263
- * - 统一使用正斜杠 (/)
1264
- * - 可选移除 Windows 盘符 (如 C:)
1265
- * - 可选移除开头的斜杠
1266
- * - 规范化连续斜杠为单个斜杠
1267
- *
1268
- * @param input 待处理字符串
1269
- * @param removeLeadingSlash 是否移除开头斜杠,默认为 `false`。如果移除了盘符,路径通常会以 / 开头,此参数可控制是否保留该 /
1270
- * @returns 转换后的路径,如果输入无效则返回空字符串
1271
- *
1272
- * @example
1273
- * ```ts
1274
- * stringToPosix("C:\\Windows\\System32");
1275
- * // 默认: "/Windows/System32" (移除了 C: 并标准化)
1276
- *
1277
- * stringToPosix("C:\\Windows\\System32", true);
1278
- * // 移除开头斜杠: "Windows/System32"
1279
- *
1280
- * stringToPosix("\\\\server\\share\\file.txt");
1281
- * // UNC 路径: "/server/share/file.txt"
1282
- *
1283
- * stringToPosix("folder\\subfolder\\file.txt");
1284
- * // 相对路径: "folder/subfolder/file.txt"
1285
- * ```
1286
- */
1287
- function stringToPosix(input, removeLeadingSlash = false) {
1288
- if (!isString(input, true)) return "";
1289
- let normalized = input.replace(/^[A-Za-z]:([\\/])?/, (_, separator) => {
1290
- return separator ? "/" : "";
1291
- });
1292
- normalized = normalized.replace(/\\/g, "/");
1293
- normalized = normalized.replace(/\/+/g, "/");
1294
- if (removeLeadingSlash && normalized.startsWith("/")) normalized = normalized.substring(1);
1295
- return normalized;
1296
- }
1297
- //#endregion
1298
- //#region src/utils/string/stringToUpperCase.ts
1299
- function stringToUpperCase(input) {
1300
- if (!isString(input, true)) return "";
1301
- return input.toUpperCase();
1302
- }
1303
- //#endregion
1304
- //#region src/utils/string/stringToValues.ts
1305
- function stringToValues(input, valueType = "number", splitSymbol = ",") {
1306
- if (!isString(input, true)) return [];
1307
- try {
1308
- const values = input.split(splitSymbol);
1309
- if (valueType === "number") return values.map((d) => Number(d));
1310
- return values;
1311
- } catch (error) {
1312
- return [];
1313
- }
1314
- }
1315
- //#endregion
1316
- //#region src/utils/string/stringTrim.ts
1317
- /**
1318
- * 从字符串中裁切掉所有的前缀和后缀字符
1319
- *
1320
- * @param input 待处理字符串
1321
- * @param charsToTrim 裁切字符,默认为 `" "`
1322
- * @returns 裁切后的字符串
1323
- * @example
1324
- * ```ts
1325
- * stringTrim(" hello "); // "hello"
1326
- * stringTrim("__hello__", "_"); // "hello"
1327
- * ```
1328
- */
1329
- function stringTrim(input, charsToTrim = " ") {
1330
- if (!isString(input, true)) return "";
1331
- const toTrim = charsToTrim.replace(/[\W]{1}/g, "\\$&");
1332
- const regex = new RegExp(`^[${toTrim}]+|[${toTrim}]+$`, "g");
1333
- return input.replace(regex, "");
1334
- }
1335
- //#endregion
1336
- //#region src/utils/string/stringTruncate.ts
1337
- /**
1338
- * 截取字符串
1339
- * - 支持自定义省略符,不会截断在汉字中间(因为JS字符串本身按字符处理)
1340
- *
1341
- * @param input 待处理字符串
1342
- * @param maxLength 最大长度 (包含省略符)
1343
- * @param ellipsis 省略符,默认为 `...`
1344
- * @returns 截取后的字符串
1345
- * @example
1346
- * ```ts
1347
- * stringTruncate("hello world", 8); // "hello..."
1348
- * ```
1349
- */
1350
- function stringTruncate(input, maxLength, ellipsis = "...") {
1351
- if (!isString(input, true)) return "";
1352
- const codePoints = Array.from(input);
1353
- if (!isInteger(maxLength) || maxLength < 0) return input;
1354
- if (codePoints.length <= maxLength) return input;
1355
- const availableLength = maxLength - ellipsis.length;
1356
- if (availableLength <= 0) return "";
1357
- return codePoints.slice(0, availableLength).join("") + ellipsis;
1358
- }
1359
- //#endregion
1360
- //#region src/utils/math/mathToBignumber.ts
1361
- /**
1362
- * 将任意类型的值转换为 `math.bignumber`
1363
- *
1364
- * @param mathJsInstance mathJs 实例
1365
- * @param value 任意类型的值
1366
- * @param saveValue 安全值
1367
- * @returns 转换后的 BigNumber
1368
- * @example
1369
- * ```ts
1370
- * import { create, all } from "mathjs";
1371
- * const math = create(all);
1372
- * mathToBignumber(math, "0.1");
1373
- * ```
1374
- */
1375
- function mathToBignumber(mathJsInstance, value, saveValue) {
1376
- const errorValue = saveValue ?? mathJsInstance.bignumber(0);
1377
- if (isFalsyLike(value) || isInfinityLike(value)) return errorValue;
1378
- try {
1379
- return mathJsInstance.bignumber(stringToNumber(`${value}`));
1380
- } catch (error) {
1381
- return errorValue;
1382
- }
1383
- }
1384
- //#endregion
1385
- //#region src/utils/math/mathToDecimal.ts
1386
- function mathToDecimal(mathJsInstance, value, precision, isFormat = true) {
1387
- const bigNumber = mathToBignumber(mathJsInstance, value);
1388
- return isFormat ? mathJsInstance.format(bigNumber, {
1389
- notation: "fixed",
1390
- precision
1391
- }) : bigNumber;
1392
- }
1393
- //#endregion
1394
- //#region src/utils/math/mathToEvaluate.ts
1395
- /**
1396
- * 数学表达式求值
1397
- *
1398
- * @param mathJsInstance mathJs 实例
1399
- * @param expr 表达式
1400
- * @param scope 键值映射
1401
- * @returns 计算结果的字符串表示
1402
- * @example
1403
- * ```ts
1404
- * mathToEvaluate(math, "a + b", { a: 1, b: 2 }); // "3"
1405
- * ```
1406
- */
1407
- function mathToEvaluate(mathJsInstance, expr, scope) {
1408
- const evaluateValue = `${mathJsInstance.evaluate(expr, scope || {})}`;
1409
- return mathJsInstance.format(mathToBignumber(mathJsInstance, evaluateValue), { notation: "fixed" });
1410
- }
1411
- //#endregion
1412
- //#region src/utils/number/numberWithin.ts
1413
- /**
1414
- * 数字区间检查函数
1415
- *
1416
- * @param input 待检查数字
1417
- * @param interval 由两个数字组成的元组 [left, right]
1418
- * @param includeLeft 是否包含左边界(默认 true)
1419
- * @param includeRight 是否包含右边界(默认 false)
1420
- * @returns 是否在区间内
1421
- * @example
1422
- * ```ts
1423
- * numberWithin(5, [1, 10]); // true
1424
- * numberWithin(1, [1, 10], false); // false
1425
- * ```
1426
- */
1427
- function numberWithin(input, interval, includeLeft = true, includeRight = false) {
1428
- if (!isNumber(input)) throw new Error("params [input] mast be a number.");
1429
- if (isInfinity(input)) throw new Error("params [input] mast be a finite number.");
1430
- const [left, right] = interval;
1431
- if (left > right) throw new Error(`Invalid interval: left (${left}) must be <= right (${right}).`);
1432
- if (includeLeft && includeRight) return input >= left && input <= right;
1433
- else if (includeLeft) return input >= left && input < right;
1434
- else if (includeRight) return input > left && input <= right;
1435
- else return input > left && input < right;
1436
- }
1437
- //#endregion
1438
- //#region src/utils/object/enumEntries.ts
1439
- function enumEntries(enumeration) {
1440
- const [isEnum, isBidirectionalEnum] = isEnumeration(enumeration);
1441
- if (!isEnum) throw Error("function enumEntries expected parameter is a enum, and requires at least one member");
1442
- const entries = objectEntries(enumeration);
1443
- if (isBidirectionalEnum) return entries.splice(entries.length / 2, entries.length / 2);
1444
- return entries;
1445
- }
1446
- //#endregion
1447
- //#region src/utils/object/enumKeys.ts
1448
- function enumKeys(enumeration) {
1449
- const [isEnum, isBidirectionalEnum] = isEnumeration(enumeration);
1450
- if (!isEnum) throw Error("function enumKeys expected parameter is a enum, and requires at least one member");
1451
- const keys = objectKeys(enumeration);
1452
- if (isBidirectionalEnum) return keys.splice(keys.length / 2, keys.length / 2);
1453
- return keys;
1454
- }
1455
- //#endregion
1456
- //#region src/utils/object/enumValues.ts
1457
- function enumValues(enumeration) {
1458
- const [isEnum, isBidirectionalEnum] = isEnumeration(enumeration);
1459
- if (!isEnum) throw Error("function enumValues expected parameter is a enum, and requires at least one member");
1460
- const values = objectValues(enumeration);
1461
- if (isBidirectionalEnum) return values.splice(values.length / 2, values.length / 2);
1462
- return values;
1463
- }
1464
- //#endregion
1465
- //#region src/utils/object/objectEntries.ts
1466
- function objectEntries(value) {
1467
- return Object.entries(value);
1468
- }
1469
- //#endregion
1470
- //#region src/utils/object/objectMapEntries.ts
1471
- /**
1472
- * 映射对象条目
1473
- * - 将对象的键值对映射为新的键值对
1474
- *
1475
- * @param plainObject 对象
1476
- * @param toEntry 映射函数
1477
- * @returns 映射后的新对象
1478
- * @example
1479
- * ```ts
1480
- * const obj = { a: 1, b: 2 };
1481
- * objectMapEntries(obj, (k, v) => [k, v * 2]); // { a: 2, b: 4 }
1482
- * ```
1483
- */
1484
- function objectMapEntries(plainObject, toEntry) {
1485
- const defaultResult = {};
1486
- if (!isObject(plainObject)) return defaultResult;
1487
- return objectEntries(plainObject).reduce((acc, [key, value]) => {
1488
- const [newKey, newValue] = toEntry(key, value);
1489
- acc[newKey] = newValue;
1490
- return acc;
1491
- }, defaultResult);
1492
- }
1493
- //#endregion
1494
- //#region src/utils/object/objectAssign.ts
1495
- const OBJECT_PROTO = Object.prototype;
1496
- /**
1497
- * 为对象创建一个具有相同原型的新副本
1498
- * 这个辅助函数是保留原型的关键。
1499
- */
1500
- function cloneWithProto(obj) {
1501
- const proto = Object.getPrototypeOf(obj);
1502
- return proto === OBJECT_PROTO ? { ...obj } : Object.assign(Object.create(proto), obj);
1503
- }
1504
- function _objectAssign(initial, override, _seen) {
1505
- if (!isObject(initial, false) && !isObject(override, false)) return {};
1506
- if (!isObject(initial, false)) return cloneWithProto(override);
1507
- if (!isObject(override, false)) return cloneWithProto(initial);
1508
- if (_seen.has(initial)) return cloneWithProto(override);
1509
- _seen.add(initial);
1510
- const assigned = cloneWithProto(initial);
1511
- for (const key of Object.keys(override)) if (isObject(initial[key]) && isObject(override[key])) assigned[key] = _objectAssign(initial[key], override[key], _seen);
1512
- else assigned[key] = override[key];
1513
- _seen.delete(initial);
1514
- return assigned;
1515
- }
1516
- function objectAssign(initial, override) {
1517
- return _objectAssign(initial, override, /* @__PURE__ */ new WeakSet());
1518
- }
1519
- //#endregion
1520
- //#region src/utils/object/objectCrush.ts
1521
- function objectCrush(obj) {
1522
- if (!obj) return {};
1523
- function crushReducer(crushed, value, path) {
1524
- if (isObject(value) || isArray(value)) for (const [prop, propValue] of Object.entries(value)) crushReducer(crushed, propValue, path ? `${path}.${prop}` : prop);
1525
- else crushed[path] = value;
1526
- return crushed;
1527
- }
1528
- return crushReducer({}, obj, "");
1529
- }
1530
- //#endregion
1531
- //#region src/utils/object/objectInvert.ts
1532
- function objectInvert(obj) {
1533
- const result = {};
1534
- if (!isObject(obj)) return result;
1535
- for (const [k, v] of objectEntries(obj)) if (isString(v) || isNumber(v) || isSymbol(v)) result[v] = k;
1536
- return result;
1537
- }
1538
- //#endregion
1539
- //#region src/utils/object/objectKeys.ts
1540
- function objectKeys(value) {
1541
- return Object.keys(value);
1542
- }
1543
- //#endregion
1544
- //#region src/utils/object/objectOmit.ts
1545
- function objectOmit(obj, keys) {
1546
- const result = {};
1547
- if (!isObject(obj)) return result;
1548
- if (!isArray(keys)) return obj;
1549
- const keysToOmit = new Set(keys);
1550
- return Object.keys(obj).reduce((acc, key) => {
1551
- if (!keysToOmit.has(key)) acc[key] = obj[key];
1552
- return acc;
1553
- }, result);
1554
- }
1555
- //#endregion
1556
- //#region src/utils/object/objectPick.ts
1557
- function objectPick(obj, keys) {
1558
- const result = {};
1559
- if (!isObject(obj)) return result;
1560
- if (!isArray(keys)) return obj;
1561
- return keys.reduce((acc, key) => {
1562
- if (key in obj) acc[key] = obj[key];
1563
- return acc;
1564
- }, result);
1565
- }
1566
- //#endregion
1567
- //#region src/utils/object/objectValues.ts
1568
- function objectValues(value) {
1569
- return Object.values(value);
1570
- }
1571
- //#endregion
1572
- //#region src/utils/time/timeZone.ts
1573
- /**
1574
- * 获取当前时区信息
1575
- *
1576
- * @returns 时区信息对象 (UTC偏移和时区名称)
1577
- * @example
1578
- * ```ts
1579
- * getTimeZone(); // { UTC: "UTC+8", timeZone: "Asia/Shanghai" }
1580
- * ```
1581
- */
1582
- function getTimeZone() {
1583
- const hour = 0 - (/* @__PURE__ */ new Date()).getTimezoneOffset() / 60;
1584
- return {
1585
- UTC: "UTC" + (hour >= 0 ? "+" + hour : hour),
1586
- timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
1587
- };
1588
- }
1589
- //#endregion
1590
- //#region src/utils/tree/types.ts
1591
- function getFinalChildrenKey(tree, meta, options) {
1592
- if (isFunction(options.getChildrenKey)) {
1593
- const dynamicChildrenKey = options.getChildrenKey(tree, meta);
1594
- if (dynamicChildrenKey && dynamicChildrenKey !== null) return dynamicChildrenKey;
1595
- }
1596
- return options.childrenKey;
1597
- }
1598
- //#endregion
1599
- //#region src/utils/tree/treeFilter.ts
1600
- function preImpl$3(row, callback, options) {
1601
- if (!callback(row, options)) return;
1602
- const finalChildrenKey = getFinalChildrenKey(row, options, options);
1603
- const children = row[finalChildrenKey];
1604
- let newChildren;
1605
- if (isArray(children)) {
1606
- const nextLevelOptions = {
1607
- ...options,
1608
- parents: [...options.parents, row],
1609
- depth: options.depth + 1
1610
- };
1611
- newChildren = children.map((c) => preImpl$3(c, callback, nextLevelOptions)).filter((c) => !!c);
1612
- }
1613
- return {
1614
- ...row,
1615
- [finalChildrenKey]: newChildren
1616
- };
1617
- }
1618
- function postImpl$3(row, callback, options) {
1619
- const finalChildrenKey = getFinalChildrenKey(row, options, options);
1620
- const children = row[finalChildrenKey];
1621
- let newChildren;
1622
- if (isArray(children)) {
1623
- const nextLevelOptions = {
1624
- ...options,
1625
- parents: [...options.parents, row],
1626
- depth: options.depth + 1
1627
- };
1628
- newChildren = children.map((c) => preImpl$3(c, callback, nextLevelOptions)).filter((c) => !!c);
1629
- }
1630
- if (!callback(row, options)) return;
1631
- return {
1632
- ...row,
1633
- [finalChildrenKey]: newChildren
1634
- };
1635
- }
1636
- function breadthImpl$3(row, callback, options) {
1637
- const queue = [{
1638
- queueRow: row,
1639
- queueOptions: options
1640
- }];
1641
- const resultCache = /* @__PURE__ */ new WeakMap();
1642
- const newNodeCache = /* @__PURE__ */ new WeakMap();
1643
- const childrenKeyCache = /* @__PURE__ */ new WeakMap();
1644
- let result;
1645
- const runQueue = () => {
1646
- if (queue.length === 0) return result;
1647
- const { queueRow, queueOptions } = queue.shift();
1648
- const finalChildrenKey = getFinalChildrenKey(queueRow, queueOptions, queueOptions);
1649
- const children = queueRow[finalChildrenKey];
1650
- if (isArray(children)) {
1651
- const nextLevelOptions = {
1652
- ...queueOptions,
1653
- parents: [...queueOptions.parents, queueRow],
1654
- depth: queueOptions.depth + 1
1655
- };
1656
- const subQueueItems = children.map((queueRow) => ({
1657
- queueRow,
1658
- queueOptions: nextLevelOptions
1659
- }));
1660
- queue.push(...subQueueItems);
1661
- }
1662
- const parent = arrayLast(queueOptions.parents);
1663
- const isTopNode = queueOptions.depth === 0;
1664
- const parentResult = parent && resultCache.get(parent);
1665
- if (!isTopNode && !parentResult) return runQueue();
1666
- const callbackResult = callback(queueRow, queueOptions);
1667
- if (isTopNode && !callbackResult) return;
1668
- const newNode = {
1669
- ...queueRow,
1670
- [finalChildrenKey]: void 0
1671
- };
1672
- if (isTopNode) result = newNode;
1673
- resultCache.set(queueRow, callbackResult);
1674
- newNodeCache.set(queueRow, newNode);
1675
- childrenKeyCache.set(queueRow, finalChildrenKey);
1676
- if (callbackResult && parent) {
1677
- const parentNewNode = newNodeCache.get(parent);
1678
- const parentChildrenKey = childrenKeyCache.get(parent);
1679
- if (parentNewNode && parentChildrenKey) {
1680
- if (!parentNewNode[parentChildrenKey]) parentNewNode[parentChildrenKey] = [];
1681
- parentNewNode[parentChildrenKey].push(newNode);
1682
- }
1683
- }
1684
- return runQueue();
1685
- };
1686
- return runQueue();
1687
- }
1688
- const strategies$3 = {
1689
- pre: preImpl$3,
1690
- post: postImpl$3,
1691
- breadth: breadthImpl$3
1692
- };
1693
- function treeFilter(tree, callback, options = {}) {
1694
- const { childrenKey = "children", strategy = "pre", getChildrenKey } = options;
1695
- const traversalMethod = strategies$3[strategy];
1696
- const innerOptions = {
1697
- childrenKey,
1698
- depth: 0,
1699
- parents: [],
1700
- getChildrenKey
1701
- };
1702
- return isArray(tree) ? tree.map((row) => traversalMethod(row, callback, innerOptions)).filter((t) => !!t) : traversalMethod(tree, callback, innerOptions) || [];
1703
- }
1704
- //#endregion
1705
- //#region src/utils/tree/treeFind.ts
1706
- const strategies$2 = {
1707
- pre: preImpl$2,
1708
- post: postImpl$2,
1709
- breadth: breadthImpl$2
1710
- };
1711
- function preImpl$2(row, callback, options) {
1712
- if (callback(row, options)) return row;
1713
- const children = row[getFinalChildrenKey(row, options, options)];
1714
- if (isArray(children)) for (const child of children) {
1715
- const result = preImpl$2(child, callback, {
1716
- ...options,
1717
- parents: [...options.parents, row],
1718
- depth: options.depth + 1
1719
- });
1720
- if (result) return result;
1721
- }
1722
- }
1723
- function postImpl$2(row, callback, options) {
1724
- const children = row[getFinalChildrenKey(row, options, options)];
1725
- if (isArray(children)) for (const child of children) {
1726
- const result = postImpl$2(child, callback, {
1727
- ...options,
1728
- parents: [...options.parents, row],
1729
- depth: options.depth + 1
1730
- });
1731
- if (result) return result;
1732
- }
1733
- if (callback(row, options)) return row;
1734
- }
1735
- function breadthImpl$2(row, callback, options) {
1736
- const queue = [{
1737
- queueRow: row,
1738
- queueOptions: options
1739
- }];
1740
- const runQueue = () => {
1741
- if (queue.length === 0) return;
1742
- const { queueRow, queueOptions } = queue.shift();
1743
- const children = queueRow[getFinalChildrenKey(queueRow, queueOptions, queueOptions)];
1744
- if (isArray(children)) {
1745
- const nextLevelOptions = {
1746
- ...queueOptions,
1747
- parents: [...queueOptions.parents, queueRow],
1748
- depth: queueOptions.depth + 1
1749
- };
1750
- const subQueueItems = children.map((queueRow) => ({
1751
- queueRow,
1752
- queueOptions: nextLevelOptions
1753
- }));
1754
- queue.push(...subQueueItems);
1755
- }
1756
- if (callback(queueRow, queueOptions)) return queueRow;
1757
- return runQueue();
1758
- };
1759
- return runQueue();
1760
- }
1761
- /**
1762
- * 查找树节点
1763
- * - 返回第一个回调返回 true 的节点
1764
- *
1765
- * @param tree 树结构数据
1766
- * @param callback 回调函数
1767
- * @param options 配置项
1768
- * @returns 找到的节点,未找到则返回 undefined
1769
- * @example
1770
- * ```ts
1771
- * const tree = [{ id: 1, children: [{ id: 2 }] }];
1772
- * treeFind(tree, (node) => node.id === 2); // { id: 2, ... }
1773
- * ```
1774
- */
1775
- function treeFind(tree, callback, options = {}) {
1776
- const { childrenKey = "children", strategy = "pre", getChildrenKey } = options;
1777
- const traversalMethod = strategies$2[strategy];
1778
- const innerOptions = {
1779
- childrenKey,
1780
- depth: 0,
1781
- parents: [],
1782
- getChildrenKey
1783
- };
1784
- if (isArray(tree)) {
1785
- for (const row of tree) {
1786
- const result = traversalMethod(row, callback, innerOptions);
1787
- if (result) return result;
1788
- }
1789
- return;
1790
- }
1791
- return traversalMethod(tree, callback, innerOptions);
1792
- }
1793
- //#endregion
1794
- //#region src/utils/tree/treeForEach.ts
1795
- const strategies$1 = {
1796
- pre: preImpl$1,
1797
- post: postImpl$1,
1798
- breadth: breadthImpl$1
1799
- };
1800
- function preImpl$1(row, callback, options) {
1801
- callback(row, options);
1802
- const children = row[getFinalChildrenKey(row, options, options)];
1803
- if (isArray(children)) {
1804
- const nextLevelOptions = {
1805
- ...options,
1806
- parents: [...options.parents, row],
1807
- depth: options.depth + 1
1808
- };
1809
- for (const child of children) preImpl$1(child, callback, nextLevelOptions);
1810
- }
1811
- }
1812
- function postImpl$1(row, callback, options) {
1813
- const children = row[getFinalChildrenKey(row, options, options)];
1814
- if (isArray(children)) {
1815
- const nextLevelOptions = {
1816
- ...options,
1817
- parents: [...options.parents, row],
1818
- depth: options.depth + 1
1819
- };
1820
- for (const child of children) postImpl$1(child, callback, nextLevelOptions);
1821
- }
1822
- callback(row, options);
1823
- }
1824
- function breadthImpl$1(row, callback, options) {
1825
- const queue = [{
1826
- queueRow: row,
1827
- queueOptions: options
1828
- }];
1829
- const runQueue = () => {
1830
- if (queue.length === 0) return;
1831
- const { queueRow, queueOptions } = queue.shift();
1832
- const children = queueRow[getFinalChildrenKey(queueRow, queueOptions, queueOptions)];
1833
- if (isArray(children)) {
1834
- const nextLevelOptions = {
1835
- ...queueOptions,
1836
- parents: [...queueOptions.parents, queueRow],
1837
- depth: queueOptions.depth + 1
1838
- };
1839
- const subQueueItems = children.map((queueRow) => ({
1840
- queueRow,
1841
- queueOptions: nextLevelOptions
1842
- }));
1843
- queue.push(...subQueueItems);
1844
- }
1845
- callback(queueRow, queueOptions);
1846
- runQueue();
1847
- };
1848
- runQueue();
1849
- }
1850
- /**
1851
- * 遍历树节点
1852
- *
1853
- * @param tree 树结构数据
1854
- * @param callback 回调函数
1855
- * @param options 配置项
1856
- * @example
1857
- * ```ts
1858
- * const tree = [{ id: 1, children: [{ id: 2 }] }];
1859
- * const ids: number[] = [];
1860
- * treeForEach(tree, (node) => ids.push(node.id));
1861
- * // ids: [1, 2] (pre-order default)
1862
- * ```
1863
- */
1864
- function treeForEach(tree, callback, options = {}) {
1865
- const { childrenKey = "children", strategy = "pre", getChildrenKey } = options;
1866
- const traversalMethod = strategies$1[strategy];
1867
- const innerOptions = {
1868
- childrenKey,
1869
- depth: 0,
1870
- parents: [],
1871
- getChildrenKey
1872
- };
1873
- if (isArray(tree)) for (const row of tree) traversalMethod(row, callback, innerOptions);
1874
- else traversalMethod(tree, callback, innerOptions);
1875
- }
1876
- //#endregion
1877
- //#region src/utils/tree/treeMap.ts
1878
- const strategies = {
1879
- pre: preImpl,
1880
- post: postImpl,
1881
- breadth: breadthImpl
1882
- };
1883
- function preImpl(row, callback, options) {
1884
- const finalChildrenKey = getFinalChildrenKey(row, options, options);
1885
- const result = callback(row, options);
1886
- const children = row[finalChildrenKey];
1887
- let newChildren;
1888
- if (isArray(children)) {
1889
- const nextLevelOptions = {
1890
- ...options,
1891
- parents: [...options.parents, row],
1892
- depth: options.depth + 1
1893
- };
1894
- newChildren = children.map((c) => preImpl(c, callback, nextLevelOptions));
1895
- }
1896
- return {
1897
- ...result,
1898
- [finalChildrenKey]: newChildren
1899
- };
1900
- }
1901
- function postImpl(row, callback, options) {
1902
- const finalChildrenKey = getFinalChildrenKey(row, options, options);
1903
- const children = row[finalChildrenKey];
1904
- let newChildren;
1905
- if (isArray(children)) {
1906
- const nextLevelOptions = {
1907
- ...options,
1908
- parents: [...options.parents, row],
1909
- depth: options.depth + 1
1910
- };
1911
- newChildren = children.map((c) => postImpl(c, callback, nextLevelOptions));
1912
- }
1913
- return {
1914
- ...callback(row, options),
1915
- [finalChildrenKey]: newChildren
1916
- };
1917
- }
1918
- function breadthImpl(row, callback, options) {
1919
- const queue = [{
1920
- queueRow: row,
1921
- queueOptions: options
1922
- }];
1923
- const cache = /* @__PURE__ */ new WeakMap();
1924
- const childrenKeyCache = /* @__PURE__ */ new WeakMap();
1925
- let result;
1926
- const runQueue = () => {
1927
- if (queue.length === 0) return result;
1928
- const { queueRow, queueOptions } = queue.shift();
1929
- const finalChildrenKey = getFinalChildrenKey(queueRow, queueOptions, queueOptions);
1930
- const children = queueRow[finalChildrenKey];
1931
- if (isArray(children)) {
1932
- const nextLevelOptions = {
1933
- ...queueOptions,
1934
- parents: [...queueOptions.parents, queueRow],
1935
- depth: queueOptions.depth + 1
1936
- };
1937
- const subQueueItems = children.map((queueRow) => ({
1938
- queueRow,
1939
- queueOptions: nextLevelOptions
1940
- }));
1941
- queue.push(...subQueueItems);
1942
- }
1943
- const res = callback(queueRow, queueOptions);
1944
- cache.set(queueRow, res);
1945
- childrenKeyCache.set(queueRow, finalChildrenKey);
1946
- const parent = arrayLast(queueOptions.parents);
1947
- if (parent) {
1948
- const newParent = cache.get(parent);
1949
- const parentChildrenKey = childrenKeyCache.get(parent);
1950
- if (newParent && parentChildrenKey) if (newParent[parentChildrenKey]) newParent[parentChildrenKey].push(res);
1951
- else newParent[parentChildrenKey] = [res];
1952
- }
1953
- if (queueOptions.depth === 0) result = res;
1954
- return runQueue();
1955
- };
1956
- return runQueue();
1957
- }
1958
- function treeMap(tree, callback, options = {}) {
1959
- const { childrenKey = "children", strategy = "pre", getChildrenKey } = options;
1960
- const traversalMethod = strategies[strategy];
1961
- const innerOptions = {
1962
- childrenKey,
1963
- depth: 0,
1964
- parents: [],
1965
- getChildrenKey
1966
- };
1967
- return isArray(tree) ? tree.map((row) => traversalMethod(row, callback, innerOptions)) : traversalMethod(tree, callback, innerOptions);
1968
- }
1969
- //#endregion
1970
- //#region src/utils/tree/rowsToTree.ts
1971
- /**
1972
- * 行结构 转 树结构
1973
- * - 将平铺的数组转换为树形结构
1974
- *
1975
- * @param rows 行数据数组
1976
- * @param options 配置项
1977
- * @returns 树结构数组
1978
- * @example
1979
- * ```ts
1980
- * const rows = [
1981
- * { id: 1, parentId: null },
1982
- * { id: 2, parentId: 1 },
1983
- * ];
1984
- * rowsToTree(rows);
1985
- * // [{ id: 1, parentId: null, children: [{ id: 2, parentId: 1 }] }]
1986
- * ```
1987
- */
1988
- function rowsToTree(rows, options) {
1989
- const { parentIdKey = "parentId", rowKey = "id", childrenKey = "children" } = options || {};
1990
- const result = [];
1991
- const map = /* @__PURE__ */ new Map();
1992
- for (const row of rows) {
1993
- const id = row[rowKey];
1994
- if (!map.get(id)) map.set(id, row);
1995
- }
1996
- for (const row of rows) {
1997
- const parentId = row[parentIdKey];
1998
- const parent = map.get(parentId);
1999
- if (!parent || !parentId) {
2000
- result.push(row);
2001
- continue;
2002
- }
2003
- const siblings = parent[childrenKey];
2004
- if (isNull(siblings) || isUndefined(siblings)) parent[childrenKey] = [row];
2005
- else if (Array.isArray(siblings)) siblings.push(row);
2006
- else {
2007
- const message = `The key "${childrenKey.toString()}" in parent item is not an array.`;
2008
- throw new Error(message);
2009
- }
2010
- }
2011
- return result;
2012
- }
2013
- //#endregion
2014
- //#region src/utils/tree/treeToRows.ts
2015
- /**
2016
- * 树结构 转 行结构
2017
- * - 将树形结构扁平化为数组
2018
- *
2019
- * @param tree 树结构数据 (单个节点或节点数组)
2020
- * @param options 配置项
2021
- * @returns 扁平化后的数组
2022
- * @example
2023
- * ```ts
2024
- * const tree = [{ id: 1, children: [{ id: 2 }] }];
2025
- * treeToRows(tree);
2026
- * // [{ id: 1, children: undefined }, { id: 2, children: undefined }]
2027
- * ```
2028
- */
2029
- function treeToRows(tree, options = {}) {
2030
- const { childrenKey = "children" } = options;
2031
- const result = [];
2032
- if (!tree) return result;
2033
- treeForEach(tree, (t) => result.push({
2034
- ...t,
2035
- [childrenKey]: void 0
2036
- }), options);
2037
- return result;
2038
- }
2039
- //#endregion
2040
- export { arrayMerge as $, stringToLowerCase as A, isWeakMap as At, isIOSMobile as B, isClass as Bt, mathToBignumber as C, isInteger as Ct, stringToUpperCase as D, isPositiveInteger as Dt, stringToValues as E, isNumber as Et, toPromise as F, isFalsyLike as Ft, isBrowser as G, isBoolean as Gt, isDesktop as H, isAsyncGeneratorFunction as Ht, to as I, isError as It, arrayZip as J, isBigInt as Jt, arrayZipToObject as K, isBlob as Kt, isWebWorker as L, isEqual as Lt, stringTemplate as M, isIframe as Mt, stringReplace as N, isInIframe as Nt, stringToPosix as O, isNull as Ot, stringInitialCase as P, isFalsy as Pt, arrayPick as Q, isTablet as R, isEnumeration as Rt, mathToDecimal as S, isInfinityLike as St, stringTrim as T, isNegativeInteger as Tt, isMacOSDesktop as U, isFunction as Ut, isMobile as V, isAsyncFunction as Vt, isWindowsDesktop as W, isGeneratorFunction as Wt, arrayReplaceMove as X, isTypedArray as Xt, arraySplit as Y, isArray as Yt, arrayReplace as Z, isAbortSignal as Zt, enumValues as _, isReadableStream as _t, treeFind as a, arrayCounting as at, numberWithin as b, isObject as bt, objectValues as c, isWindow as ct, objectKeys as d, isUndefined as dt, arrayLast as et, objectInvert as f, isSymbol as ft, objectEntries as g, isRegExp as gt, objectMapEntries as h, isWeakSet as ht, treeForEach as i, arrayDifference as it, stringToJson as j, isIterable as jt, stringToNumber as k, isMap as kt, objectPick as l, isWebSocket as lt, objectAssign as m, isSet as mt, rowsToTree as n, arrayFork as nt, treeFilter as o, arrayCompete as ot, objectCrush as p, isString as pt, arrayUnzip as q, isFile as qt, treeMap as r, arrayFirst as rt, getTimeZone as s, arrayCast as st, treeToRows as t, arrayIntersection as tt, objectOmit as u, isURLSearchParams as ut, enumKeys as v, isPromise as vt, stringTruncate as w, isNaN as wt, mathToEvaluate as x, isInfinity as xt, enumEntries as y, isPromiseLike as yt, isReactNative as z, isDate as zt };
2041
-
2042
- //# sourceMappingURL=utils-B7AhGrZp.js.map