@movk/core 0.0.3

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,1005 @@
1
+ import { VNode, Ref } from 'vue';
2
+ import { z } from 'zod/v4';
3
+
4
+ type AnyObject = Record<string, any>;
5
+ type OmitByKey<T, K extends keyof T> = {
6
+ [P in keyof T as P extends K ? never : P]: T[P];
7
+ };
8
+ type PickByKey<T, K extends keyof T> = {
9
+ [P in keyof T as P extends K ? P : never]: T[P];
10
+ };
11
+ type RenameKeys<T, Mapping extends {
12
+ [K in keyof T]?: PropertyKey;
13
+ }> = {
14
+ [K in keyof T as K extends keyof Mapping ? Exclude<Mapping[K], undefined> : K]: T[K];
15
+ };
16
+ type RequiredByKeys<T, K extends keyof T> = T & {
17
+ [P in K]-?: T[P];
18
+ };
19
+ type PartialByKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
20
+ type ReadonlyByKeys<T, K extends keyof T> = T & {
21
+ readonly [P in K]: T[P];
22
+ };
23
+ type MutableByKeys<T, K extends keyof T> = {
24
+ -readonly [P in K]: T[P];
25
+ } & Omit<T, K>;
26
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? {
27
+ [K in keyof I]: I[K];
28
+ } : never;
29
+ type FirstParam<T, K extends keyof T> = T[K] extends [infer P, ...any[]] ? P : never;
30
+ type FirstParameter<T> = T extends (arg: infer P, ...args: any[]) => any ? P : undefined;
31
+ type DeepPartial<T> = {
32
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P] | undefined;
33
+ };
34
+ type GetObjectField<MaybeObject, Key extends string> = MaybeObject extends Record<string, any> ? MaybeObject[Key] : never;
35
+ type StringOrVNode = string | VNode | (() => VNode);
36
+
37
+ declare const StorageTypeSchema: z.ZodEnum<{
38
+ localStorage: "localStorage";
39
+ sessionStorage: "sessionStorage";
40
+ }>;
41
+ type StorageType = z.infer<typeof StorageTypeSchema>;
42
+ declare function createStorageConfigSchema<T = unknown>(schema: z.ZodType<T>): z.ZodObject<{
43
+ key: z.ZodString;
44
+ schema: z.ZodCustom<z.ZodType<T, unknown, z.core.$ZodTypeInternals<T, unknown>>, z.ZodType<T, unknown, z.core.$ZodTypeInternals<T, unknown>>>;
45
+ defaultValue: z.ZodCustom<T, T>;
46
+ prefix: z.ZodDefault<z.ZodString>;
47
+ storage: z.ZodDefault<z.ZodEnum<{
48
+ localStorage: "localStorage";
49
+ sessionStorage: "sessionStorage";
50
+ }>>;
51
+ }, z.core.$strip>;
52
+ type StorageConfig<T = unknown> = z.infer<ReturnType<typeof createStorageConfigSchema<T>>>;
53
+ type StorageConfigInput<T = unknown> = z.input<ReturnType<typeof createStorageConfigSchema<T>>>;
54
+ interface AppStorageReturn<T> {
55
+ state: Ref<T>;
56
+ getItem: () => T;
57
+ setItem: (value: T) => void;
58
+ removeItem: () => void;
59
+ }
60
+
61
+ declare const _TreeNodeBaseSchema: z.ZodRecord<z.ZodString, z.ZodAny>;
62
+ type TreeNodeBase = z.infer<typeof _TreeNodeBaseSchema>;
63
+ type TreeNode<T extends TreeNodeBase = TreeNodeBase> = T & {
64
+ [K in TreeConfig['children']]: TreeNode<T>[];
65
+ };
66
+ declare const TreeConfigSchema: z.ZodObject<{
67
+ id: z.ZodDefault<z.ZodString>;
68
+ pid: z.ZodDefault<z.ZodString>;
69
+ children: z.ZodDefault<z.ZodString>;
70
+ }, z.core.$strip>;
71
+ type TreeConfig = z.infer<typeof TreeConfigSchema>;
72
+ type TreeConfigInput = z.input<typeof TreeConfigSchema>;
73
+ declare const TreeStatsSchema: z.ZodObject<{
74
+ total: z.ZodNumber;
75
+ leaves: z.ZodNumber;
76
+ depth: z.ZodNumber;
77
+ branches: z.ZodNumber;
78
+ }, z.core.$strip>;
79
+ type TreeStats = z.infer<typeof TreeStatsSchema>;
80
+ interface TreeNodeResult<T extends TreeNodeBase = TreeNodeBase> {
81
+ readonly node: TreeNode<T>;
82
+ readonly path: readonly TreeNode<T>[];
83
+ readonly depth: number;
84
+ readonly index: number;
85
+ }
86
+ type TreePredicate<T extends TreeNodeBase = TreeNodeBase> = (node: TreeNode<T>, depth: number, path: readonly TreeNode<T>[]) => boolean;
87
+ type TreeTransformer<T extends TreeNodeBase = TreeNodeBase, R extends TreeNodeBase = TreeNodeBase> = (node: TreeNode<T>, depth: number, path: readonly TreeNode<T>[]) => R;
88
+ type TreeVisitor<T extends TreeNodeBase = TreeNodeBase> = (node: TreeNode<T>, depth: number, path: readonly TreeNode<T>[]) => void | boolean;
89
+
90
+ /**
91
+ * 应用存储管理的组合式函数,支持localStorage和sessionStorage
92
+ *
93
+ * @category Composables
94
+ * @param config 存储配置对象
95
+ * @returns 存储管理对象,包含响应式状态和操作方法
96
+ * @example
97
+ * ```ts
98
+ * import { z } from 'zod/v4'
99
+ *
100
+ * // 定义用户偏好设置的schema
101
+ * const userPrefsSchema = z.object({
102
+ * theme: z.enum(['light', 'dark']),
103
+ * language: z.string(),
104
+ * fontSize: z.number().min(12).max(24)
105
+ * })
106
+ *
107
+ * // 创建存储管理实例
108
+ * const { state, setItem, getItem, removeItem } = useAppStorage({
109
+ * key: 'user-preferences',
110
+ * defaultValue: {
111
+ * theme: 'light',
112
+ * language: 'zh-CN',
113
+ * fontSize: 16
114
+ * },
115
+ * schema: userPrefsSchema,
116
+ * storage: 'localStorage',
117
+ * prefix: 'app'
118
+ * })
119
+ *
120
+ * // 使用响应式状态
121
+ * console.log(state.value.theme) // 'light'
122
+ *
123
+ * // 更新设置
124
+ * setItem({
125
+ * theme: 'dark',
126
+ * language: 'en-US',
127
+ * fontSize: 18
128
+ * })
129
+ * ```
130
+ */
131
+ declare function useAppStorage<T = unknown>(config: StorageConfigInput<T>): AppStorageReturn<T>;
132
+
133
+ /**
134
+ * 复制文本到剪贴板的组合式函数
135
+ *
136
+ * @category Composables
137
+ * @param text 要复制的文本内容
138
+ * @returns 复制是否成功的Promise
139
+ * @example
140
+ * ```ts
141
+ * // 复制简单文本
142
+ * const copyText = async () => {
143
+ * const success = await useCopyCode('Hello, World!')
144
+ * if (success) {
145
+ * console.log('复制成功')
146
+ * } else {
147
+ * console.log('复制失败')
148
+ * }
149
+ * }
150
+ *
151
+ * // 复制代码块
152
+ * const copyCodeBlock = async () => {
153
+ * const code = `
154
+ * function hello() {
155
+ * console.log('Hello, World!')
156
+ * }
157
+ * `
158
+ * const success = await useCopyCode(code)
159
+ * if (success) {
160
+ * // 显示复制成功提示
161
+ * showNotification('代码已复制到剪贴板')
162
+ * }
163
+ * }
164
+ *
165
+ * // 在点击事件中使用
166
+ * const handleCopy = () => {
167
+ * useCopyCode(document.getElementById('code').textContent)
168
+ * }
169
+ * ```
170
+ */
171
+ declare function useCopyCode(text: string): Promise<boolean>;
172
+
173
+ /**
174
+ * 树形数据结构操作类,提供树形数据的各种操作方法
175
+ *
176
+ * @category Data Structures
177
+ * @example
178
+ * ```ts
179
+ * // 从扁平数组创建树形结构
180
+ * const flatList = [
181
+ * { id: '1', name: '根节点', pid: null },
182
+ * { id: '2', name: '子节点1', pid: '1' },
183
+ * { id: '3', name: '子节点2', pid: '1' },
184
+ * { id: '4', name: '孙节点', pid: '2' }
185
+ * ]
186
+ *
187
+ * const tree = Tree.fromList(flatList)
188
+ * console.log(tree) // 树形结构
189
+ *
190
+ * // 查找节点
191
+ * const found = Tree.find(tree, (node) => node.name === '子节点1')
192
+ *
193
+ * // 过滤节点
194
+ * const filtered = Tree.filter(tree, (node) => node.name.includes('子'))
195
+ *
196
+ * // 转换树形结构
197
+ * const transformed = Tree.transform(tree, (node) => ({
198
+ * ...node,
199
+ * displayName: `[${node.name}]`
200
+ * }))
201
+ * ```
202
+ */
203
+ declare class Tree {
204
+ private static dfsGenerator;
205
+ private static bfsGenerator;
206
+ private static selectStrategy;
207
+ /**
208
+ * 从扁平数组创建树形结构
209
+ *
210
+ * @category Data Structures
211
+ * @param list 扁平数组数据
212
+ * @param config 树形配置选项
213
+ * @returns 树形结构数组
214
+ * @example
215
+ * ```ts
216
+ * const flatData = [
217
+ * { id: '1', name: '部门1', parentId: null },
218
+ * { id: '2', name: '部门1-1', parentId: '1' },
219
+ * { id: '3', name: '部门1-2', parentId: '1' },
220
+ * { id: '4', name: '部门1-1-1', parentId: '2' }
221
+ * ]
222
+ *
223
+ * const tree = Tree.fromList(flatData, {
224
+ * id: 'id',
225
+ * pid: 'parentId',
226
+ * children: 'children'
227
+ * })
228
+ *
229
+ * console.log(tree) // 转换为树形结构
230
+ * ```
231
+ */
232
+ static fromList<T extends TreeNodeBase>(list: T[], config?: TreeConfigInput): TreeNode<T>[];
233
+ /**
234
+ * 将树形结构转换为扁平数组
235
+ *
236
+ * @category Data Structures
237
+ * @param tree 树形结构(单个节点或节点数组)
238
+ * @param config 树形配置选项
239
+ * @returns 扁平数组
240
+ * @example
241
+ * ```ts
242
+ * const tree = [
243
+ * {
244
+ * id: '1',
245
+ * name: '根节点',
246
+ * children: [
247
+ * { id: '2', name: '子节点1', children: [] },
248
+ * { id: '3', name: '子节点2', children: [] }
249
+ * ]
250
+ * }
251
+ * ]
252
+ *
253
+ * const flatList = Tree.toList(tree)
254
+ * console.log(flatList) // [{ id: '1', name: '根节点' }, { id: '2', name: '子节点1' }, ...]
255
+ * ```
256
+ */
257
+ static toList<T extends TreeNodeBase>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): T[];
258
+ static estimateSize<T extends TreeNodeBase>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): number;
259
+ static find<T extends TreeNodeBase>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNodeResult<T> | undefined;
260
+ static findAll<T extends TreeNodeBase>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNodeResult<T>[];
261
+ static findById<T extends TreeNodeBase>(tree: TreeNode<T> | TreeNode<T>[], id: string, config?: TreeConfigInput): TreeNodeResult<T> | undefined;
262
+ static getStats<T extends TreeNodeBase>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): TreeStats;
263
+ static filter<T extends TreeNodeBase>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNode<T>[];
264
+ static transform<T extends TreeNodeBase, R extends TreeNodeBase>(tree: TreeNode<T> | TreeNode<T>[], transformer: TreeTransformer<T, R>, config?: TreeConfigInput): TreeNode<R>[];
265
+ static forEach<T extends TreeNodeBase>(tree: TreeNode<T> | TreeNode<T>[], visitor: TreeVisitor<T>, config?: TreeConfigInput): void;
266
+ static insertBefore<T extends TreeNodeBase>(tree: TreeNode<T>[], targetId: string, newNode: T, config?: TreeConfigInput): boolean;
267
+ static insertAfter<T extends TreeNodeBase>(tree: TreeNode<T>[], targetId: string, newNode: T, config?: TreeConfigInput): boolean;
268
+ static remove<T extends TreeNodeBase>(tree: TreeNode<T>[], targetId: string, config?: TreeConfigInput): TreeNode<T> | undefined;
269
+ static validate<T extends TreeNodeBase>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): {
270
+ isValid: boolean;
271
+ errors: string[];
272
+ };
273
+ }
274
+
275
+ /**
276
+ * UnoCSS Flex布局预设,提供便捷的flex布局工具类
277
+ *
278
+ * @category Framework
279
+ * @returns UnoCSS预设配置对象
280
+ * @example
281
+ * ```ts
282
+ * // 在unocss.config.ts中使用
283
+ * import { presetFlex } from '@movk/core'
284
+ *
285
+ * export default defineConfig({
286
+ * presets: [
287
+ * presetFlex(),
288
+ * // 其他预设...
289
+ * ]
290
+ * })
291
+ *
292
+ * // 在HTML中使用生成的类名
293
+ * <div class="flex-row-center-center">居中的flex容器</div>
294
+ * <div class="flex-col-between-start">纵向分散对齐</div>
295
+ * <div class="flex-center">完全居中</div>
296
+ * <div class="flex-x-center">水平居中</div>
297
+ * <div class="flex-y-center">垂直居中</div>
298
+ * ```
299
+ */
300
+ declare function presetFlex(): {
301
+ name: string;
302
+ rules: ((RegExp | (([, d, j, a]: string[], { rawSelector }: {
303
+ rawSelector: string;
304
+ }) => Record<string, string>) | {
305
+ autocomplete: string;
306
+ })[] | (string | {
307
+ display: string;
308
+ 'justify-content': string;
309
+ 'align-items': string;
310
+ })[])[];
311
+ shortcuts: {
312
+ 'flex-x-center': string;
313
+ 'flex-y-center': string;
314
+ 'inline-flex-x-center': string;
315
+ 'inline-flex-y-center': string;
316
+ }[];
317
+ };
318
+
319
+ interface RuleContext {
320
+ rawSelector: string;
321
+ }
322
+ /**
323
+ * UnoCSS 猫头鹰选择器预设,提供基于相邻兄弟选择器的间距和分隔符工具类
324
+ *
325
+ * @category Framework
326
+ * @returns UnoCSS预设配置对象
327
+ * @example
328
+ * ```ts
329
+ * // 在unocss.config.ts中使用
330
+ * import { presetOwl } from '@movk/core'
331
+ *
332
+ * export default defineConfig({
333
+ * presets: [
334
+ * presetOwl(),
335
+ * // 其他预设...
336
+ * ]
337
+ * })
338
+ *
339
+ * // 在HTML中使用生成的类名
340
+ * <div class="owl-y-4">
341
+ * <div>项目1</div>
342
+ * <div>项目2</div> <!-- 上边距 1rem -->
343
+ * <div>项目3</div> <!-- 上边距 1rem -->
344
+ * </div>
345
+ *
346
+ * <div class="owl-x-2">
347
+ * <span>按钮1</span>
348
+ * <span>按钮2</span> <!-- 左边距 0.5rem -->
349
+ * <span>按钮3</span> <!-- 左边距 0.5rem -->
350
+ * </div>
351
+ *
352
+ * <div class="owl-divide-gray-200">
353
+ * <div>列表项1</div>
354
+ * <div>列表项2</div> <!-- 上边框分隔线 -->
355
+ * <div>列表项3</div> <!-- 上边框分隔线 -->
356
+ * </div>
357
+ * ```
358
+ */
359
+ declare function presetOwl(): {
360
+ name: string;
361
+ rules: (RegExp | (([, value]: string[], { rawSelector }: RuleContext) => string | undefined) | {
362
+ autocomplete: string;
363
+ })[][];
364
+ shortcuts: {
365
+ 'owl-stack': string;
366
+ 'owl-stack-tight': string;
367
+ 'owl-stack-loose': string;
368
+ 'owl-list': string;
369
+ 'owl-list-tight': string;
370
+ 'owl-nav': string;
371
+ 'owl-card-stack': string;
372
+ }[];
373
+ };
374
+
375
+ /**
376
+ * 数组去重,返回去除重复元素后的新数组
377
+ *
378
+ * @category Array
379
+ * @param arr 待去重的数组
380
+ * @returns 去重后的新数组
381
+ * @example
382
+ * ```ts
383
+ * const numbers = [1, 2, 2, 3, 3, 4]
384
+ * const uniqueNumbers = unique(numbers)
385
+ * console.log(uniqueNumbers) // [1, 2, 3, 4]
386
+ *
387
+ * const strings = ['a', 'b', 'a', 'c']
388
+ * const uniqueStrings = unique(strings)
389
+ * console.log(uniqueStrings) // ['a', 'b', 'c']
390
+ * ```
391
+ */
392
+ declare function unique<T>(arr: T[]): T[];
393
+ /**
394
+ * 将数组分割成指定大小的块
395
+ *
396
+ * @category Array
397
+ * @param arr 待分割的数组
398
+ * @param size 每个块的大小
399
+ * @returns 分割后的二维数组
400
+ * @example
401
+ * ```ts
402
+ * const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
403
+ * const chunks = chunk(numbers, 3)
404
+ * console.log(chunks) // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
405
+ *
406
+ * const names = ['Alice', 'Bob', 'Charlie', 'David', 'Eve']
407
+ * const pairs = chunk(names, 2)
408
+ * console.log(pairs) // [['Alice', 'Bob'], ['Charlie', 'David'], ['Eve']]
409
+ * ```
410
+ */
411
+ declare function chunk<T>(arr: T[], size: number): T[][];
412
+ /**
413
+ * 数组扁平化,将嵌套数组展平到指定深度
414
+ *
415
+ * @category Array
416
+ * @param arr 待扁平化的数组
417
+ * @param depth 扁平化深度,默认为1
418
+ * @returns 扁平化后的数组
419
+ * @example
420
+ * ```ts
421
+ * const nested = [1, [2, 3], [4, [5, 6]]]
422
+ * const flat1 = flatten(nested)
423
+ * console.log(flat1) // [1, 2, 3, 4, [5, 6]]
424
+ *
425
+ * const flat2 = flatten(nested, 2)
426
+ * console.log(flat2) // [1, 2, 3, 4, 5, 6]
427
+ * ```
428
+ */
429
+ declare function flatten<T>(arr: T[], depth?: number): any[];
430
+
431
+ /**
432
+ * 防抖函数,在指定时间内多次触发只执行最后一次
433
+ *
434
+ * @category Async
435
+ * @param func 需要防抖的函数
436
+ * @param wait 防抖延迟时间(毫秒)
437
+ * @returns 防抖处理后的函数
438
+ * @example
439
+ * ```ts
440
+ * const debouncedSearch = debounce((query: string) => {
441
+ * console.log('搜索:', query)
442
+ * }, 300)
443
+ *
444
+ * // 连续调用,只有最后一次会执行
445
+ * debouncedSearch('a')
446
+ * debouncedSearch('ab')
447
+ * debouncedSearch('abc') // 只有这次会在300ms后执行
448
+ * ```
449
+ */
450
+ declare function debounce<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void;
451
+
452
+ /**
453
+ * 延迟执行函数,返回一个在指定时间后resolve的Promise
454
+ *
455
+ * @category Async
456
+ * @param ms 延迟时间(毫秒)
457
+ * @returns 延迟Promise
458
+ * @example
459
+ * ```ts
460
+ * // 延迟1秒后继续执行
461
+ * await sleep(1000)
462
+ * console.log('1秒后执行')
463
+ *
464
+ * // 在异步函数中使用
465
+ * async function delayedOperation() {
466
+ * console.log('开始')
467
+ * await sleep(500)
468
+ * console.log('500ms后执行')
469
+ * }
470
+ * ```
471
+ */
472
+ declare function sleep(ms: number): Promise<void>;
473
+ /**
474
+ * 可取消的延迟函数,返回Promise和取消函数
475
+ *
476
+ * @category Async
477
+ * @param ms 延迟时间(毫秒)
478
+ * @returns 包含Promise和取消函数的对象
479
+ * @example
480
+ * ```ts
481
+ * const { promise, cancel } = sleepWithCancel(5000)
482
+ *
483
+ * // 在另一个地方取消延迟
484
+ * setTimeout(() => {
485
+ * cancel() // 取消延迟
486
+ * }, 2000)
487
+ *
488
+ * try {
489
+ * await promise
490
+ * console.log('5秒后执行')
491
+ * } catch (error) {
492
+ * console.log('延迟被取消')
493
+ * }
494
+ * ```
495
+ */
496
+ declare function sleepWithCancel(ms: number): {
497
+ promise: Promise<void>;
498
+ cancel: () => void;
499
+ };
500
+
501
+ /**
502
+ * 节流函数,在指定时间内多次触发只执行第一次
503
+ *
504
+ * @category Async
505
+ * @param func 需要节流的函数
506
+ * @param limit 节流时间间隔(毫秒)
507
+ * @returns 节流处理后的函数
508
+ * @example
509
+ * ```ts
510
+ * const throttledScroll = throttle((event: Event) => {
511
+ * console.log('滚动事件处理')
512
+ * }, 100)
513
+ *
514
+ * // 监听滚动事件,每100ms最多执行一次
515
+ * window.addEventListener('scroll', throttledScroll)
516
+ * ```
517
+ */
518
+ declare function throttle<T extends (...args: any[]) => any>(func: T, limit: number): (...args: Parameters<T>) => void;
519
+
520
+ /**
521
+ * 将SVG字符串转换为PNG格式的Blob对象
522
+ *
523
+ * @category File
524
+ * @param svg SVG字符串
525
+ * @returns PNG格式的Blob对象
526
+ * @throws 当SVG无效或转换失败时抛出错误
527
+ * @example
528
+ * ```ts
529
+ * const svgString = '<svg width="100" height="100"><circle cx="50" cy="50" r="40" fill="red"/></svg>'
530
+ *
531
+ * try {
532
+ * const pngBlob = await convertSvgToPng(svgString)
533
+ * const url = URL.createObjectURL(pngBlob)
534
+ *
535
+ * // 用于下载或显示
536
+ * const img = document.createElement('img')
537
+ * img.src = url
538
+ * document.body.appendChild(img)
539
+ * } catch (error) {
540
+ * console.error('SVG转换失败:', error)
541
+ * }
542
+ * ```
543
+ */
544
+ declare function convertSvgToPng(svg: string): Promise<Blob>;
545
+
546
+ /**
547
+ * 从响应头中提取文件名
548
+ *
549
+ * @category File
550
+ * @param headers 响应头对象
551
+ * @param fallbackName 默认文件名
552
+ * @returns 提取的文件名
553
+ * @example
554
+ * ```ts
555
+ * // 从响应头中提取文件名
556
+ * const headers = new Headers({
557
+ * 'content-disposition': 'attachment; filename="report.pdf"'
558
+ * })
559
+ * const filename = extractFilename(headers, 'download')
560
+ * console.log(filename) // 'report.pdf'
561
+ *
562
+ * // 处理编码的文件名
563
+ * const encodedHeaders = new Headers({
564
+ * 'content-disposition': 'attachment; filename*=UTF-8\'\'%E6%8A%A5%E5%91%8A.pdf'
565
+ * })
566
+ * const encodedFilename = extractFilename(encodedHeaders)
567
+ * console.log(encodedFilename) // '报告.pdf'
568
+ * ```
569
+ */
570
+ declare function extractFilename(headers?: Headers, fallbackName?: string): string;
571
+ /**
572
+ * 触发浏览器下载文件
573
+ *
574
+ * @category File
575
+ * @param blob 文件数据
576
+ * @param filename 文件名
577
+ * @example
578
+ * ```ts
579
+ * // 下载文本文件
580
+ * const textBlob = new Blob(['Hello, World!'], { type: 'text/plain' })
581
+ * triggerDownload(textBlob, 'hello.txt')
582
+ *
583
+ * // 下载JSON数据
584
+ * const data = { name: 'John', age: 30 }
585
+ * const jsonBlob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
586
+ * triggerDownload(jsonBlob, 'data.json')
587
+ *
588
+ * // 下载图片
589
+ * const canvas = document.createElement('canvas')
590
+ * canvas.toBlob((blob) => {
591
+ * if (blob) {
592
+ * triggerDownload(blob, 'image.png')
593
+ * }
594
+ * })
595
+ * ```
596
+ */
597
+ declare function triggerDownload(blob: Blob, filename: string): void;
598
+
599
+ /**
600
+ * 格式化文件大小,将字节数转换为可读的文件大小字符串
601
+ *
602
+ * @category File
603
+ * @param bytes 文件大小(字节)
604
+ * @returns 格式化后的文件大小字符串
605
+ * @example
606
+ * ```ts
607
+ * console.log(formatFileSize(1024)) // '1 KB'
608
+ * console.log(formatFileSize(1536)) // '1.5 KB'
609
+ * console.log(formatFileSize(1048576)) // '1 MB'
610
+ * console.log(formatFileSize(1073741824)) // '1 GB'
611
+ *
612
+ * // 处理边界情况
613
+ * console.log(formatFileSize(0)) // '0 Bytes'
614
+ * console.log(formatFileSize(-100)) // '0 Bytes'
615
+ * ```
616
+ */
617
+ declare function formatFileSize(bytes: number): string;
618
+
619
+ /**
620
+ * 替换SVG文件中的currentColor为指定颜色
621
+ *
622
+ * @category File
623
+ * @param path SVG文件路径
624
+ * @param color 替换的颜色值,不提供则返回原始SVG
625
+ * @returns 处理后的SVG字符串
626
+ * @throws 当文件获取失败或SVG无效时抛出错误
627
+ * @example
628
+ * ```ts
629
+ * // 获取并替换SVG中的currentColor
630
+ * try {
631
+ * const svgContent = await replaceCurrentColor('/icons/star.svg', '#ff0000')
632
+ * const container = document.createElement('div')
633
+ * container.innerHTML = svgContent
634
+ * document.body.appendChild(container)
635
+ * } catch (error) {
636
+ * console.error('SVG处理失败:', error)
637
+ * }
638
+ *
639
+ * // 只获取SVG内容,不替换颜色
640
+ * const originalSvg = await replaceCurrentColor('/icons/star.svg')
641
+ * ```
642
+ */
643
+ declare function replaceCurrentColor(path: string, color?: string): Promise<string>;
644
+
645
+ /**
646
+ * 将对象的键名转换为kebab-case格式
647
+ *
648
+ * @category Object
649
+ * @param obj 待转换的对象
650
+ * @param deep 是否深度转换嵌套对象,默认为false
651
+ * @returns 转换后的对象
652
+ * @example
653
+ * ```ts
654
+ * const obj = {
655
+ * firstName: 'John',
656
+ * lastName: 'Doe',
657
+ * userInfo: {
658
+ * birthDate: '1990-01-01',
659
+ * phoneNumber: '123-456-7890'
660
+ * }
661
+ * }
662
+ *
663
+ * const converted = convertToKebabCase(obj)
664
+ * console.log(converted)
665
+ * // {
666
+ * // 'first-name': 'John',
667
+ * // 'last-name': 'Doe',
668
+ * // 'user-info': { birthDate: '1990-01-01', phoneNumber: '123-456-7890' }
669
+ * // }
670
+ *
671
+ * const deepConverted = convertToKebabCase(obj, true)
672
+ * console.log(deepConverted)
673
+ * // {
674
+ * // 'first-name': 'John',
675
+ * // 'last-name': 'Doe',
676
+ * // 'user-info': { 'birth-date': '1990-01-01', 'phone-number': '123-456-7890' }
677
+ * // }
678
+ * ```
679
+ */
680
+ declare function convertToKebabCase<T extends AnyObject>(obj: T, deep?: boolean): T;
681
+
682
+ /**
683
+ * 深度克隆对象,创建完全独立的副本
684
+ *
685
+ * @category Object
686
+ * @param obj 待克隆的对象
687
+ * @returns 深度克隆后的对象
688
+ * @example
689
+ * ```ts
690
+ * const original = {
691
+ * name: 'John',
692
+ * age: 30,
693
+ * address: {
694
+ * city: 'New York',
695
+ * zip: '10001'
696
+ * },
697
+ * hobbies: ['reading', 'coding']
698
+ * }
699
+ *
700
+ * const cloned = deepClone(original)
701
+ * cloned.address.city = 'Los Angeles'
702
+ * cloned.hobbies.push('gaming')
703
+ *
704
+ * console.log(original.address.city) // 'New York' (未改变)
705
+ * console.log(original.hobbies.length) // 2 (未改变)
706
+ * console.log(cloned.address.city) // 'Los Angeles'
707
+ * console.log(cloned.hobbies.length) // 3
708
+ * ```
709
+ */
710
+ declare function deepClone<T>(obj: T): T;
711
+
712
+ /**
713
+ * 从对象中排除指定的键,返回新对象
714
+ *
715
+ * @category Object
716
+ * @param obj 源对象
717
+ * @param keys 要排除的键数组
718
+ * @returns 排除指定键后的新对象
719
+ * @example
720
+ * ```ts
721
+ * const user = {
722
+ * id: 1,
723
+ * name: 'John',
724
+ * password: 'secret',
725
+ * email: 'john@example.com'
726
+ * }
727
+ *
728
+ * const publicUser = omit(user, ['password'])
729
+ * console.log(publicUser) // { id: 1, name: 'John', email: 'john@example.com' }
730
+ *
731
+ * const basicInfo = omit(user, ['password', 'email'])
732
+ * console.log(basicInfo) // { id: 1, name: 'John' }
733
+ * ```
734
+ */
735
+ declare function omit<T extends AnyObject, K extends keyof T>(obj: T, keys: K[]): OmitByKey<T, K>;
736
+ /**
737
+ * 从对象中排除值为undefined的键
738
+ *
739
+ * @category Object
740
+ * @param obj 源对象
741
+ * @returns 排除undefined值后的新对象
742
+ * @example
743
+ * ```ts
744
+ * const data = {
745
+ * name: 'John',
746
+ * age: undefined,
747
+ * city: 'New York',
748
+ * country: undefined
749
+ * }
750
+ *
751
+ * const cleaned = omitUndefined(data)
752
+ * console.log(cleaned) // { name: 'John', city: 'New York' }
753
+ *
754
+ * // 用于API请求前清理数据
755
+ * const requestData = omitUndefined({
756
+ * title: 'Post Title',
757
+ * content: 'Post content',
758
+ * tags: undefined,
759
+ * published: true
760
+ * })
761
+ * ```
762
+ */
763
+ declare function omitUndefined<T extends AnyObject>(obj: T): Partial<T>;
764
+
765
+ /**
766
+ * 从对象中选择指定的键,返回新对象
767
+ *
768
+ * @category Object
769
+ * @param obj 源对象
770
+ * @param keys 要选择的键数组
771
+ * @returns 只包含指定键的新对象
772
+ * @example
773
+ * ```ts
774
+ * const user = {
775
+ * id: 1,
776
+ * name: 'John',
777
+ * email: 'john@example.com',
778
+ * password: 'secret',
779
+ * createdAt: '2023-01-01',
780
+ * updatedAt: '2023-01-15'
781
+ * }
782
+ *
783
+ * const publicInfo = pick(user, ['id', 'name', 'email'])
784
+ * console.log(publicInfo) // { id: 1, name: 'John', email: 'john@example.com' }
785
+ *
786
+ * const basicInfo = pick(user, ['id', 'name'])
787
+ * console.log(basicInfo) // { id: 1, name: 'John' }
788
+ * ```
789
+ */
790
+ declare function pick<T extends AnyObject, K extends keyof T>(obj: T, keys: K[]): PickByKey<T, K>;
791
+
792
+ interface SeparateResult<T extends AnyObject, K extends keyof T> {
793
+ picked: PickByKey<T, K>;
794
+ omitted: OmitByKey<T, K>;
795
+ }
796
+ /**
797
+ * 将对象按指定键分离为两个对象
798
+ *
799
+ * @category Object
800
+ * @param obj 源对象
801
+ * @param keys 要分离的键数组
802
+ * @returns 包含picked和omitted两个对象的结果
803
+ * @example
804
+ * ```ts
805
+ * const user = {
806
+ * id: 1,
807
+ * name: 'John',
808
+ * email: 'john@example.com',
809
+ * password: 'secret',
810
+ * role: 'admin'
811
+ * }
812
+ *
813
+ * const { picked, omitted } = separate(user, ['id', 'name'])
814
+ * console.log(picked) // { id: 1, name: 'John' }
815
+ * console.log(omitted) // { email: 'john@example.com', password: 'secret', role: 'admin' }
816
+ *
817
+ * // 用于分离敏感信息
818
+ * const { picked: publicData, omitted: privateData } = separate(user, ['id', 'name', 'email'])
819
+ * ```
820
+ */
821
+ declare function separate<T extends AnyObject, K extends keyof T>(obj: T, keys: K[]): SeparateResult<T, K>;
822
+
823
+ /**
824
+ * 将字符串首字母大写
825
+ *
826
+ * @category String
827
+ * @param str 待处理的字符串
828
+ * @returns 首字母大写的字符串
829
+ * @example
830
+ * ```ts
831
+ * console.log(capitalize('hello')) // 'Hello'
832
+ * console.log(capitalize('WORLD')) // 'WORLD'
833
+ * console.log(capitalize('')) // ''
834
+ * console.log(capitalize('a')) // 'A'
835
+ * ```
836
+ */
837
+ declare function capitalize(str: string): string;
838
+ /**
839
+ * 将驼峰命名转换为kebab-case
840
+ *
841
+ * @category String
842
+ * @param str 驼峰命名的字符串
843
+ * @returns kebab-case格式的字符串
844
+ * @example
845
+ * ```ts
846
+ * console.log(camelToKebab('helloWorld')) // 'hello-world'
847
+ * console.log(camelToKebab('firstName')) // 'first-name'
848
+ * console.log(camelToKebab('XMLHttpRequest')) // 'x-m-l-http-request'
849
+ * console.log(camelToKebab('hello')) // 'hello'
850
+ * ```
851
+ */
852
+ declare function camelToKebab(str: string): string;
853
+ /**
854
+ * 将kebab-case转换为驼峰命名
855
+ *
856
+ * @category String
857
+ * @param str kebab-case格式的字符串
858
+ * @returns 驼峰命名的字符串
859
+ * @example
860
+ * ```ts
861
+ * console.log(kebabToCamel('hello-world')) // 'helloWorld'
862
+ * console.log(kebabToCamel('first-name')) // 'firstName'
863
+ * console.log(kebabToCamel('background-color')) // 'backgroundColor'
864
+ * console.log(kebabToCamel('hello')) // 'hello'
865
+ * ```
866
+ */
867
+ declare function kebabToCamel(str: string): string;
868
+
869
+ /**
870
+ * 生成字符串的简单哈希值
871
+ *
872
+ * @category Utilities
873
+ * @param str 待哈希的字符串
874
+ * @returns 32位哈希值转换为36进制字符串
875
+ * @example
876
+ * ```ts
877
+ * const hash1 = simpleHash('hello world')
878
+ * console.log(hash1) // 'nf5xd4'
879
+ *
880
+ * const hash2 = simpleHash('hello world')
881
+ * console.log(hash1 === hash2) // true,相同字符串产生相同哈希
882
+ *
883
+ * const hash3 = simpleHash('hello world!')
884
+ * console.log(hash1 === hash3) // false,不同字符串产生不同哈希
885
+ * ```
886
+ */
887
+ declare function simpleHash(str: string): string;
888
+
889
+ /**
890
+ * 生成随机UUID字符串
891
+ *
892
+ * @category Utilities
893
+ * @returns 符合UUID v4格式的随机字符串
894
+ * @example
895
+ * ```ts
896
+ * const id1 = getRandomUUID()
897
+ * console.log(id1) // 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
898
+ *
899
+ * const id2 = getRandomUUID()
900
+ * console.log(id2) // 'f47ac10b-58cc-4372-a567-0e02b2c3d480'
901
+ *
902
+ * // 用于生成唯一标识符
903
+ * const componentId = `component-${getRandomUUID()}`
904
+ * ```
905
+ */
906
+ declare function getRandomUUID(): string;
907
+
908
+ /**
909
+ * 检查值是否为对象类型
910
+ *
911
+ * @category Validator
912
+ * @param value 待检查的值
913
+ * @returns 是否为对象类型
914
+ * @example
915
+ * ```ts
916
+ * console.log(isObject({})) // true
917
+ * console.log(isObject({ name: 'John' })) // true
918
+ * console.log(isObject([])) // false
919
+ * console.log(isObject(null)) // false
920
+ * console.log(isObject('string')) // false
921
+ * ```
922
+ */
923
+ declare function isObject(value: any): value is AnyObject;
924
+ /**
925
+ * 检查值是否为数组类型
926
+ *
927
+ * @category Validator
928
+ * @param value 待检查的值
929
+ * @returns 是否为数组类型
930
+ * @example
931
+ * ```ts
932
+ * console.log(isArray([])) // true
933
+ * console.log(isArray([1, 2, 3])) // true
934
+ * console.log(isArray({})) // false
935
+ * console.log(isArray('string')) // false
936
+ * ```
937
+ */
938
+ declare function isArray(value: any): value is any[];
939
+ /**
940
+ * 检查值是否为字符串类型
941
+ *
942
+ * @category Validator
943
+ * @param value 待检查的值
944
+ * @returns 是否为字符串类型
945
+ * @example
946
+ * ```ts
947
+ * console.log(isString('hello')) // true
948
+ * console.log(isString('')) // true
949
+ * console.log(isString(123)) // false
950
+ * console.log(isString(null)) // false
951
+ * ```
952
+ */
953
+ declare function isString(value: any): value is string;
954
+ /**
955
+ * 检查值是否为有效数字类型
956
+ *
957
+ * @category Validator
958
+ * @param value 待检查的值
959
+ * @returns 是否为有效数字类型
960
+ * @example
961
+ * ```ts
962
+ * console.log(isNumber(123)) // true
963
+ * console.log(isNumber(0)) // true
964
+ * console.log(isNumber(NaN)) // false
965
+ * console.log(isNumber('123')) // false
966
+ * ```
967
+ */
968
+ declare function isNumber(value: any): value is number;
969
+ /**
970
+ * 检查值是否为函数类型
971
+ *
972
+ * @category Validator
973
+ * @param value 待检查的值
974
+ * @returns 是否为函数类型
975
+ * @example
976
+ * ```ts
977
+ * console.log(isFunction(() => {})) // true
978
+ * console.log(isFunction(function() {})) // true
979
+ * console.log(isFunction(Math.max)) // true
980
+ * console.log(isFunction('string')) // false
981
+ * ```
982
+ */
983
+ declare function isFunction(value: any): value is (...args: any[]) => any;
984
+ /**
985
+ * 检查值是否为空(null、undefined、空字符串、空数组、空对象)
986
+ *
987
+ * @category Validator
988
+ * @param value 待检查的值
989
+ * @returns 是否为空值
990
+ * @example
991
+ * ```ts
992
+ * console.log(isEmpty(null)) // true
993
+ * console.log(isEmpty(undefined)) // true
994
+ * console.log(isEmpty('')) // true
995
+ * console.log(isEmpty([])) // true
996
+ * console.log(isEmpty({})) // true
997
+ * console.log(isEmpty([1, 2])) // false
998
+ * console.log(isEmpty({ name: 'John' })) // false
999
+ * console.log(isEmpty('hello')) // false
1000
+ * ```
1001
+ */
1002
+ declare function isEmpty(value: any): boolean;
1003
+
1004
+ export { StorageTypeSchema, Tree, TreeConfigSchema, TreeStatsSchema, camelToKebab, capitalize, chunk, convertSvgToPng, convertToKebabCase, createStorageConfigSchema, debounce, deepClone, extractFilename, flatten, formatFileSize, getRandomUUID, isArray, isEmpty, isFunction, isNumber, isObject, isString, kebabToCamel, omit, omitUndefined, pick, presetFlex, presetOwl, replaceCurrentColor, separate, simpleHash, sleep, sleepWithCancel, throttle, triggerDownload, unique, useAppStorage, useCopyCode };
1005
+ export type { AnyObject, AppStorageReturn, DeepPartial, FirstParam, FirstParameter, GetObjectField, MutableByKeys, OmitByKey, PartialByKeys, PickByKey, ReadonlyByKeys, RenameKeys, RequiredByKeys, StorageConfig, StorageConfigInput, StorageType, StringOrVNode, TreeConfig, TreeConfigInput, TreeNode, TreeNodeBase, TreeNodeResult, TreePredicate, TreeStats, TreeTransformer, TreeVisitor, UnionToIntersection };