@movk/core 0.0.3 → 0.0.4
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.
- package/README.md +1 -0
- package/dist/index.d.mts +346 -175
- package/dist/index.d.ts +346 -175
- package/dist/index.mjs +1 -1
- package/package.json +14 -21
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# @movk/core
|
|
2
2
|
|
|
3
3
|
[](https://www.typescriptlang.org/)
|
|
4
|
+
[](https://github.com/antfu/eslint-config)
|
|
4
5
|
[![npm version][npm-version-src]][npm-version-href]
|
|
5
6
|
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
6
7
|
[![bundle][bundle-src]][bundle-href]
|
package/dist/index.d.mts
CHANGED
|
@@ -58,35 +58,6 @@ interface AppStorageReturn<T> {
|
|
|
58
58
|
removeItem: () => void;
|
|
59
59
|
}
|
|
60
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
61
|
/**
|
|
91
62
|
* 应用存储管理的组合式函数,支持localStorage和sessionStorage
|
|
92
63
|
*
|
|
@@ -170,36 +141,32 @@ declare function useAppStorage<T = unknown>(config: StorageConfigInput<T>): AppS
|
|
|
170
141
|
*/
|
|
171
142
|
declare function useCopyCode(text: string): Promise<boolean>;
|
|
172
143
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
* displayName: `[${node.name}]`
|
|
200
|
-
* }))
|
|
201
|
-
* ```
|
|
202
|
-
*/
|
|
144
|
+
type TreeNode<T = any> = T & {
|
|
145
|
+
children?: TreeNode<T>[];
|
|
146
|
+
[key: string]: any;
|
|
147
|
+
};
|
|
148
|
+
declare const TreeConfigSchema: z.ZodObject<{
|
|
149
|
+
id: z.ZodDefault<z.ZodString>;
|
|
150
|
+
pid: z.ZodDefault<z.ZodString>;
|
|
151
|
+
children: z.ZodDefault<z.ZodString>;
|
|
152
|
+
}, z.core.$strip>;
|
|
153
|
+
type TreeConfigInput = z.input<typeof TreeConfigSchema>;
|
|
154
|
+
declare const _TreeStatsSchema: z.ZodObject<{
|
|
155
|
+
total: z.ZodNumber;
|
|
156
|
+
leaves: z.ZodNumber;
|
|
157
|
+
depth: z.ZodNumber;
|
|
158
|
+
branches: z.ZodNumber;
|
|
159
|
+
}, z.core.$strip>;
|
|
160
|
+
type TreeStats = z.infer<typeof _TreeStatsSchema>;
|
|
161
|
+
interface TreeNodeResult<T = any> {
|
|
162
|
+
readonly node: TreeNode<T>;
|
|
163
|
+
readonly path: readonly TreeNode<T>[];
|
|
164
|
+
readonly depth: number;
|
|
165
|
+
readonly index: number;
|
|
166
|
+
}
|
|
167
|
+
type TreePredicate<T = any> = (node: TreeNode<T>, depth: number, path: readonly TreeNode<T>[]) => boolean;
|
|
168
|
+
type TreeTransformer<T = any, R = any> = (node: TreeNode<T>, depth: number, path: readonly TreeNode<T>[]) => R;
|
|
169
|
+
type TreeVisitor<T = any> = (node: TreeNode<T>, depth: number, path: readonly TreeNode<T>[]) => void | boolean;
|
|
203
170
|
declare class Tree {
|
|
204
171
|
private static dfsGenerator;
|
|
205
172
|
private static bfsGenerator;
|
|
@@ -229,7 +196,7 @@ declare class Tree {
|
|
|
229
196
|
* console.log(tree) // 转换为树形结构
|
|
230
197
|
* ```
|
|
231
198
|
*/
|
|
232
|
-
static fromList<T
|
|
199
|
+
static fromList<T = any>(list: T[], config?: TreeConfigInput): TreeNode<T>[];
|
|
233
200
|
/**
|
|
234
201
|
* 将树形结构转换为扁平数组
|
|
235
202
|
*
|
|
@@ -254,124 +221,328 @@ declare class Tree {
|
|
|
254
221
|
* console.log(flatList) // [{ id: '1', name: '根节点' }, { id: '2', name: '子节点1' }, ...]
|
|
255
222
|
* ```
|
|
256
223
|
*/
|
|
257
|
-
static toList<T
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
224
|
+
static toList<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): T[];
|
|
225
|
+
/**
|
|
226
|
+
* 估算树形结构的节点数量
|
|
227
|
+
*
|
|
228
|
+
* @category Data Structures
|
|
229
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
230
|
+
* @param config 树形配置选项
|
|
231
|
+
* @returns 节点总数量
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* const tree = [
|
|
235
|
+
* {
|
|
236
|
+
* id: '1',
|
|
237
|
+
* name: '根节点',
|
|
238
|
+
* children: [
|
|
239
|
+
* { id: '2', name: '子节点1', children: [] },
|
|
240
|
+
* { id: '3', name: '子节点2', children: [] }
|
|
241
|
+
* ]
|
|
242
|
+
* }
|
|
243
|
+
* ]
|
|
244
|
+
*
|
|
245
|
+
* const size = Tree.estimateSize(tree)
|
|
246
|
+
* console.log(size) // 3
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
static estimateSize<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): number;
|
|
250
|
+
/**
|
|
251
|
+
* 查找树中第一个满足条件的节点
|
|
252
|
+
*
|
|
253
|
+
* @category Data Structures
|
|
254
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
255
|
+
* @param predicate 查找条件函数
|
|
256
|
+
* @param config 树形配置选项
|
|
257
|
+
* @returns 匹配的节点结果,包含节点、路径、深度和索引信息;未找到时返回undefined
|
|
258
|
+
* @example
|
|
259
|
+
* ```ts
|
|
260
|
+
* const tree = [
|
|
261
|
+
* {
|
|
262
|
+
* id: '1',
|
|
263
|
+
* name: '部门1',
|
|
264
|
+
* children: [
|
|
265
|
+
* { id: '2', name: '部门1-1', children: [] }
|
|
266
|
+
* ]
|
|
267
|
+
* }
|
|
268
|
+
* ]
|
|
269
|
+
*
|
|
270
|
+
* const result = Tree.find(tree, (node) => node.name === '部门1-1')
|
|
271
|
+
* console.log(result?.node.id) // '2'
|
|
272
|
+
* console.log(result?.depth) // 1
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
static find<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNodeResult<T> | undefined;
|
|
276
|
+
/**
|
|
277
|
+
* 查找树中所有满足条件的节点
|
|
278
|
+
*
|
|
279
|
+
* @category Data Structures
|
|
280
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
281
|
+
* @param predicate 查找条件函数
|
|
282
|
+
* @param config 树形配置选项
|
|
283
|
+
* @returns 所有匹配的节点结果数组,每个结果包含节点、路径、深度和索引信息
|
|
284
|
+
* @example
|
|
285
|
+
* ```ts
|
|
286
|
+
* const tree = [
|
|
287
|
+
* {
|
|
288
|
+
* id: '1',
|
|
289
|
+
* type: 'folder',
|
|
290
|
+
* name: '根目录',
|
|
291
|
+
* children: [
|
|
292
|
+
* { id: '2', type: 'file', name: '文件1', children: [] },
|
|
293
|
+
* { id: '3', type: 'file', name: '文件2', children: [] }
|
|
294
|
+
* ]
|
|
295
|
+
* }
|
|
296
|
+
* ]
|
|
297
|
+
*
|
|
298
|
+
* const files = Tree.findAll(tree, (node) => node.type === 'file')
|
|
299
|
+
* console.log(files.length) // 2
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
static findAll<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNodeResult<T>[];
|
|
303
|
+
/**
|
|
304
|
+
* 根据ID查找树中的节点
|
|
305
|
+
*
|
|
306
|
+
* @category Data Structures
|
|
307
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
308
|
+
* @param id 要查找的节点ID
|
|
309
|
+
* @param config 树形配置选项
|
|
310
|
+
* @returns 匹配的节点结果,包含节点、路径、深度和索引信息;未找到时返回undefined
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* const tree = [
|
|
314
|
+
* {
|
|
315
|
+
* id: '1',
|
|
316
|
+
* name: '根节点',
|
|
317
|
+
* children: [
|
|
318
|
+
* { id: '2', name: '子节点', children: [] }
|
|
319
|
+
* ]
|
|
320
|
+
* }
|
|
321
|
+
* ]
|
|
322
|
+
*
|
|
323
|
+
* const result = Tree.findById(tree, '2')
|
|
324
|
+
* console.log(result?.node.name) // '子节点'
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
static findById<T = any>(tree: TreeNode<T> | TreeNode<T>[], id: string, config?: TreeConfigInput): TreeNodeResult<T> | undefined;
|
|
328
|
+
/**
|
|
329
|
+
* 获取树形结构的统计信息
|
|
330
|
+
*
|
|
331
|
+
* @category Data Structures
|
|
332
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
333
|
+
* @param config 树形配置选项
|
|
334
|
+
* @returns 树的统计信息,包含总节点数、叶子节点数、最大深度和分支节点数
|
|
335
|
+
* @example
|
|
336
|
+
* ```ts
|
|
337
|
+
* const tree = [
|
|
338
|
+
* {
|
|
339
|
+
* id: '1',
|
|
340
|
+
* name: '根节点',
|
|
341
|
+
* children: [
|
|
342
|
+
* { id: '2', name: '子节点1', children: [] },
|
|
343
|
+
* { id: '3', name: '子节点2', children: [
|
|
344
|
+
* { id: '4', name: '孙节点', children: [] }
|
|
345
|
+
* ] }
|
|
346
|
+
* ]
|
|
347
|
+
* }
|
|
348
|
+
* ]
|
|
349
|
+
*
|
|
350
|
+
* const stats = Tree.getStats(tree)
|
|
351
|
+
* console.log(stats) // { total: 4, leaves: 2, depth: 3, branches: 2 }
|
|
352
|
+
* ```
|
|
353
|
+
*/
|
|
354
|
+
static getStats<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): TreeStats;
|
|
355
|
+
/**
|
|
356
|
+
* 过滤树形结构,保留满足条件的节点及其祖先和后代
|
|
357
|
+
*
|
|
358
|
+
* @category Data Structures
|
|
359
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
360
|
+
* @param predicate 过滤条件函数
|
|
361
|
+
* @param config 树形配置选项
|
|
362
|
+
* @returns 过滤后的树形结构数组
|
|
363
|
+
* @example
|
|
364
|
+
* ```ts
|
|
365
|
+
* const tree = [
|
|
366
|
+
* {
|
|
367
|
+
* id: '1',
|
|
368
|
+
* type: 'folder',
|
|
369
|
+
* name: '根目录',
|
|
370
|
+
* children: [
|
|
371
|
+
* { id: '2', type: 'file', name: '文档.txt', children: [] },
|
|
372
|
+
* { id: '3', type: 'folder', name: '子目录', children: [
|
|
373
|
+
* { id: '4', type: 'file', name: '图片.jpg', children: [] }
|
|
374
|
+
* ] }
|
|
375
|
+
* ]
|
|
376
|
+
* }
|
|
377
|
+
* ]
|
|
378
|
+
*
|
|
379
|
+
* const filtered = Tree.filter(tree, (node) => node.type === 'file')
|
|
380
|
+
* // 返回包含所有文件节点及其父级路径的树结构
|
|
381
|
+
* ```
|
|
382
|
+
*/
|
|
383
|
+
static filter<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNode<T>[];
|
|
384
|
+
/**
|
|
385
|
+
* 转换树形结构,将每个节点转换为新的结构
|
|
386
|
+
*
|
|
387
|
+
* @category Data Structures
|
|
388
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
389
|
+
* @param transformer 节点转换函数
|
|
390
|
+
* @param config 树形配置选项
|
|
391
|
+
* @returns 转换后的树形结构数组
|
|
392
|
+
* @example
|
|
393
|
+
* ```ts
|
|
394
|
+
* const tree = [
|
|
395
|
+
* {
|
|
396
|
+
* id: '1',
|
|
397
|
+
* name: '部门1',
|
|
398
|
+
* children: [
|
|
399
|
+
* { id: '2', name: '部门1-1', children: [] }
|
|
400
|
+
* ]
|
|
401
|
+
* }
|
|
402
|
+
* ]
|
|
403
|
+
*
|
|
404
|
+
* const transformed = Tree.transform(tree, (node, depth) => ({
|
|
405
|
+
* key: node.id,
|
|
406
|
+
* title: node.name,
|
|
407
|
+
* level: depth
|
|
408
|
+
* }))
|
|
409
|
+
* // 转换为新的数据结构
|
|
410
|
+
* ```
|
|
411
|
+
*/
|
|
412
|
+
static transform<T = any, R = any>(tree: TreeNode<T> | TreeNode<T>[], transformer: TreeTransformer<T, R>, config?: TreeConfigInput): TreeNode<R>[];
|
|
413
|
+
/**
|
|
414
|
+
* 遍历树形结构的每个节点
|
|
415
|
+
*
|
|
416
|
+
* @category Data Structures
|
|
417
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
418
|
+
* @param visitor 访问者函数,返回false可以跳过子节点的遍历
|
|
419
|
+
* @param config 树形配置选项
|
|
420
|
+
* @example
|
|
421
|
+
* ```ts
|
|
422
|
+
* const tree = [
|
|
423
|
+
* {
|
|
424
|
+
* id: '1',
|
|
425
|
+
* name: '根节点',
|
|
426
|
+
* children: [
|
|
427
|
+
* { id: '2', name: '子节点', children: [] }
|
|
428
|
+
* ]
|
|
429
|
+
* }
|
|
430
|
+
* ]
|
|
431
|
+
*
|
|
432
|
+
* Tree.forEach(tree, (node, depth) => {
|
|
433
|
+
* console.log(`${' '.repeat(depth * 2)}${node.name}`)
|
|
434
|
+
* // 输出缩进的树结构
|
|
435
|
+
* })
|
|
436
|
+
* ```
|
|
437
|
+
*/
|
|
438
|
+
static forEach<T = any>(tree: TreeNode<T> | TreeNode<T>[], visitor: TreeVisitor<T>, config?: TreeConfigInput): void;
|
|
439
|
+
/**
|
|
440
|
+
* 在指定节点前插入新节点
|
|
441
|
+
*
|
|
442
|
+
* @category Data Structures
|
|
443
|
+
* @param tree 树形结构数组
|
|
444
|
+
* @param targetId 目标节点的ID
|
|
445
|
+
* @param newNode 要插入的新节点数据
|
|
446
|
+
* @param config 树形配置选项
|
|
447
|
+
* @returns 是否成功插入
|
|
448
|
+
* @example
|
|
449
|
+
* ```ts
|
|
450
|
+
* const tree = [
|
|
451
|
+
* {
|
|
452
|
+
* id: '1',
|
|
453
|
+
* name: '节点1',
|
|
454
|
+
* children: [
|
|
455
|
+
* { id: '2', name: '节点2', children: [] }
|
|
456
|
+
* ]
|
|
457
|
+
* }
|
|
458
|
+
* ]
|
|
459
|
+
*
|
|
460
|
+
* const success = Tree.insertBefore(tree, '2', { id: '1.5', name: '新节点' })
|
|
461
|
+
* console.log(success) // true
|
|
462
|
+
* ```
|
|
463
|
+
*/
|
|
464
|
+
static insertBefore<T = any>(tree: TreeNode<T>[], targetId: string, newNode: T, config?: TreeConfigInput): boolean;
|
|
465
|
+
/**
|
|
466
|
+
* 在指定节点后插入新节点
|
|
467
|
+
*
|
|
468
|
+
* @category Data Structures
|
|
469
|
+
* @param tree 树形结构数组
|
|
470
|
+
* @param targetId 目标节点的ID
|
|
471
|
+
* @param newNode 要插入的新节点数据
|
|
472
|
+
* @param config 树形配置选项
|
|
473
|
+
* @returns 是否成功插入
|
|
474
|
+
* @example
|
|
475
|
+
* ```ts
|
|
476
|
+
* const tree = [
|
|
477
|
+
* {
|
|
478
|
+
* id: '1',
|
|
479
|
+
* name: '节点1',
|
|
480
|
+
* children: [
|
|
481
|
+
* { id: '2', name: '节点2', children: [] }
|
|
482
|
+
* ]
|
|
483
|
+
* }
|
|
484
|
+
* ]
|
|
485
|
+
*
|
|
486
|
+
* const success = Tree.insertAfter(tree, '2', { id: '3', name: '新节点' })
|
|
487
|
+
* console.log(success) // true
|
|
488
|
+
* ```
|
|
489
|
+
*/
|
|
490
|
+
static insertAfter<T = any>(tree: TreeNode<T>[], targetId: string, newNode: T, config?: TreeConfigInput): boolean;
|
|
491
|
+
/**
|
|
492
|
+
* 从树中删除指定节点
|
|
493
|
+
*
|
|
494
|
+
* @category Data Structures
|
|
495
|
+
* @param tree 树形结构数组
|
|
496
|
+
* @param targetId 要删除的节点ID
|
|
497
|
+
* @param config 树形配置选项
|
|
498
|
+
* @returns 被删除的节点,未找到时返回undefined
|
|
499
|
+
* @example
|
|
500
|
+
* ```ts
|
|
501
|
+
* const tree = [
|
|
502
|
+
* {
|
|
503
|
+
* id: '1',
|
|
504
|
+
* name: '根节点',
|
|
505
|
+
* children: [
|
|
506
|
+
* { id: '2', name: '子节点', children: [] }
|
|
507
|
+
* ]
|
|
508
|
+
* }
|
|
509
|
+
* ]
|
|
510
|
+
*
|
|
511
|
+
* const removed = Tree.remove(tree, '2')
|
|
512
|
+
* console.log(removed?.name) // '子节点'
|
|
513
|
+
* ```
|
|
514
|
+
*/
|
|
515
|
+
static remove<T = any>(tree: TreeNode<T>[], targetId: string, config?: TreeConfigInput): TreeNode<T> | undefined;
|
|
516
|
+
/**
|
|
517
|
+
* 验证树形结构的有效性
|
|
518
|
+
*
|
|
519
|
+
* @category Data Structures
|
|
520
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
521
|
+
* @param config 树形配置选项
|
|
522
|
+
* @returns 验证结果,包含是否有效和错误信息数组
|
|
523
|
+
* @example
|
|
524
|
+
* ```ts
|
|
525
|
+
* const tree = [
|
|
526
|
+
* {
|
|
527
|
+
* id: '1',
|
|
528
|
+
* name: '根节点',
|
|
529
|
+
* children: [
|
|
530
|
+
* { id: '2', name: '子节点', children: [] }
|
|
531
|
+
* ]
|
|
532
|
+
* }
|
|
533
|
+
* ]
|
|
534
|
+
*
|
|
535
|
+
* const result = Tree.validate(tree)
|
|
536
|
+
* console.log(result.isValid) // true
|
|
537
|
+
* console.log(result.errors) // []
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
540
|
+
static validate<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): {
|
|
270
541
|
isValid: boolean;
|
|
271
542
|
errors: string[];
|
|
272
543
|
};
|
|
273
544
|
}
|
|
274
545
|
|
|
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
546
|
/**
|
|
376
547
|
* 数组去重,返回去除重复元素后的新数组
|
|
377
548
|
*
|
|
@@ -1001,5 +1172,5 @@ declare function isFunction(value: any): value is (...args: any[]) => any;
|
|
|
1001
1172
|
*/
|
|
1002
1173
|
declare function isEmpty(value: any): boolean;
|
|
1003
1174
|
|
|
1004
|
-
export { StorageTypeSchema, Tree,
|
|
1005
|
-
export type { AnyObject, AppStorageReturn, DeepPartial, FirstParam, FirstParameter, GetObjectField, MutableByKeys, OmitByKey, PartialByKeys, PickByKey, ReadonlyByKeys, RenameKeys, RequiredByKeys, StorageConfig, StorageConfigInput, StorageType, StringOrVNode,
|
|
1175
|
+
export { StorageTypeSchema, Tree, camelToKebab, capitalize, chunk, convertSvgToPng, convertToKebabCase, createStorageConfigSchema, debounce, deepClone, extractFilename, flatten, formatFileSize, getRandomUUID, isArray, isEmpty, isFunction, isNumber, isObject, isString, kebabToCamel, omit, omitUndefined, pick, replaceCurrentColor, separate, simpleHash, sleep, sleepWithCancel, throttle, triggerDownload, unique, useAppStorage, useCopyCode };
|
|
1176
|
+
export type { AnyObject, AppStorageReturn, DeepPartial, FirstParam, FirstParameter, GetObjectField, MutableByKeys, OmitByKey, PartialByKeys, PickByKey, ReadonlyByKeys, RenameKeys, RequiredByKeys, StorageConfig, StorageConfigInput, StorageType, StringOrVNode, UnionToIntersection };
|
package/dist/index.d.ts
CHANGED
|
@@ -58,35 +58,6 @@ interface AppStorageReturn<T> {
|
|
|
58
58
|
removeItem: () => void;
|
|
59
59
|
}
|
|
60
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
61
|
/**
|
|
91
62
|
* 应用存储管理的组合式函数,支持localStorage和sessionStorage
|
|
92
63
|
*
|
|
@@ -170,36 +141,32 @@ declare function useAppStorage<T = unknown>(config: StorageConfigInput<T>): AppS
|
|
|
170
141
|
*/
|
|
171
142
|
declare function useCopyCode(text: string): Promise<boolean>;
|
|
172
143
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
* displayName: `[${node.name}]`
|
|
200
|
-
* }))
|
|
201
|
-
* ```
|
|
202
|
-
*/
|
|
144
|
+
type TreeNode<T = any> = T & {
|
|
145
|
+
children?: TreeNode<T>[];
|
|
146
|
+
[key: string]: any;
|
|
147
|
+
};
|
|
148
|
+
declare const TreeConfigSchema: z.ZodObject<{
|
|
149
|
+
id: z.ZodDefault<z.ZodString>;
|
|
150
|
+
pid: z.ZodDefault<z.ZodString>;
|
|
151
|
+
children: z.ZodDefault<z.ZodString>;
|
|
152
|
+
}, z.core.$strip>;
|
|
153
|
+
type TreeConfigInput = z.input<typeof TreeConfigSchema>;
|
|
154
|
+
declare const _TreeStatsSchema: z.ZodObject<{
|
|
155
|
+
total: z.ZodNumber;
|
|
156
|
+
leaves: z.ZodNumber;
|
|
157
|
+
depth: z.ZodNumber;
|
|
158
|
+
branches: z.ZodNumber;
|
|
159
|
+
}, z.core.$strip>;
|
|
160
|
+
type TreeStats = z.infer<typeof _TreeStatsSchema>;
|
|
161
|
+
interface TreeNodeResult<T = any> {
|
|
162
|
+
readonly node: TreeNode<T>;
|
|
163
|
+
readonly path: readonly TreeNode<T>[];
|
|
164
|
+
readonly depth: number;
|
|
165
|
+
readonly index: number;
|
|
166
|
+
}
|
|
167
|
+
type TreePredicate<T = any> = (node: TreeNode<T>, depth: number, path: readonly TreeNode<T>[]) => boolean;
|
|
168
|
+
type TreeTransformer<T = any, R = any> = (node: TreeNode<T>, depth: number, path: readonly TreeNode<T>[]) => R;
|
|
169
|
+
type TreeVisitor<T = any> = (node: TreeNode<T>, depth: number, path: readonly TreeNode<T>[]) => void | boolean;
|
|
203
170
|
declare class Tree {
|
|
204
171
|
private static dfsGenerator;
|
|
205
172
|
private static bfsGenerator;
|
|
@@ -229,7 +196,7 @@ declare class Tree {
|
|
|
229
196
|
* console.log(tree) // 转换为树形结构
|
|
230
197
|
* ```
|
|
231
198
|
*/
|
|
232
|
-
static fromList<T
|
|
199
|
+
static fromList<T = any>(list: T[], config?: TreeConfigInput): TreeNode<T>[];
|
|
233
200
|
/**
|
|
234
201
|
* 将树形结构转换为扁平数组
|
|
235
202
|
*
|
|
@@ -254,124 +221,328 @@ declare class Tree {
|
|
|
254
221
|
* console.log(flatList) // [{ id: '1', name: '根节点' }, { id: '2', name: '子节点1' }, ...]
|
|
255
222
|
* ```
|
|
256
223
|
*/
|
|
257
|
-
static toList<T
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
224
|
+
static toList<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): T[];
|
|
225
|
+
/**
|
|
226
|
+
* 估算树形结构的节点数量
|
|
227
|
+
*
|
|
228
|
+
* @category Data Structures
|
|
229
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
230
|
+
* @param config 树形配置选项
|
|
231
|
+
* @returns 节点总数量
|
|
232
|
+
* @example
|
|
233
|
+
* ```ts
|
|
234
|
+
* const tree = [
|
|
235
|
+
* {
|
|
236
|
+
* id: '1',
|
|
237
|
+
* name: '根节点',
|
|
238
|
+
* children: [
|
|
239
|
+
* { id: '2', name: '子节点1', children: [] },
|
|
240
|
+
* { id: '3', name: '子节点2', children: [] }
|
|
241
|
+
* ]
|
|
242
|
+
* }
|
|
243
|
+
* ]
|
|
244
|
+
*
|
|
245
|
+
* const size = Tree.estimateSize(tree)
|
|
246
|
+
* console.log(size) // 3
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
static estimateSize<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): number;
|
|
250
|
+
/**
|
|
251
|
+
* 查找树中第一个满足条件的节点
|
|
252
|
+
*
|
|
253
|
+
* @category Data Structures
|
|
254
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
255
|
+
* @param predicate 查找条件函数
|
|
256
|
+
* @param config 树形配置选项
|
|
257
|
+
* @returns 匹配的节点结果,包含节点、路径、深度和索引信息;未找到时返回undefined
|
|
258
|
+
* @example
|
|
259
|
+
* ```ts
|
|
260
|
+
* const tree = [
|
|
261
|
+
* {
|
|
262
|
+
* id: '1',
|
|
263
|
+
* name: '部门1',
|
|
264
|
+
* children: [
|
|
265
|
+
* { id: '2', name: '部门1-1', children: [] }
|
|
266
|
+
* ]
|
|
267
|
+
* }
|
|
268
|
+
* ]
|
|
269
|
+
*
|
|
270
|
+
* const result = Tree.find(tree, (node) => node.name === '部门1-1')
|
|
271
|
+
* console.log(result?.node.id) // '2'
|
|
272
|
+
* console.log(result?.depth) // 1
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
static find<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNodeResult<T> | undefined;
|
|
276
|
+
/**
|
|
277
|
+
* 查找树中所有满足条件的节点
|
|
278
|
+
*
|
|
279
|
+
* @category Data Structures
|
|
280
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
281
|
+
* @param predicate 查找条件函数
|
|
282
|
+
* @param config 树形配置选项
|
|
283
|
+
* @returns 所有匹配的节点结果数组,每个结果包含节点、路径、深度和索引信息
|
|
284
|
+
* @example
|
|
285
|
+
* ```ts
|
|
286
|
+
* const tree = [
|
|
287
|
+
* {
|
|
288
|
+
* id: '1',
|
|
289
|
+
* type: 'folder',
|
|
290
|
+
* name: '根目录',
|
|
291
|
+
* children: [
|
|
292
|
+
* { id: '2', type: 'file', name: '文件1', children: [] },
|
|
293
|
+
* { id: '3', type: 'file', name: '文件2', children: [] }
|
|
294
|
+
* ]
|
|
295
|
+
* }
|
|
296
|
+
* ]
|
|
297
|
+
*
|
|
298
|
+
* const files = Tree.findAll(tree, (node) => node.type === 'file')
|
|
299
|
+
* console.log(files.length) // 2
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
static findAll<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNodeResult<T>[];
|
|
303
|
+
/**
|
|
304
|
+
* 根据ID查找树中的节点
|
|
305
|
+
*
|
|
306
|
+
* @category Data Structures
|
|
307
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
308
|
+
* @param id 要查找的节点ID
|
|
309
|
+
* @param config 树形配置选项
|
|
310
|
+
* @returns 匹配的节点结果,包含节点、路径、深度和索引信息;未找到时返回undefined
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* const tree = [
|
|
314
|
+
* {
|
|
315
|
+
* id: '1',
|
|
316
|
+
* name: '根节点',
|
|
317
|
+
* children: [
|
|
318
|
+
* { id: '2', name: '子节点', children: [] }
|
|
319
|
+
* ]
|
|
320
|
+
* }
|
|
321
|
+
* ]
|
|
322
|
+
*
|
|
323
|
+
* const result = Tree.findById(tree, '2')
|
|
324
|
+
* console.log(result?.node.name) // '子节点'
|
|
325
|
+
* ```
|
|
326
|
+
*/
|
|
327
|
+
static findById<T = any>(tree: TreeNode<T> | TreeNode<T>[], id: string, config?: TreeConfigInput): TreeNodeResult<T> | undefined;
|
|
328
|
+
/**
|
|
329
|
+
* 获取树形结构的统计信息
|
|
330
|
+
*
|
|
331
|
+
* @category Data Structures
|
|
332
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
333
|
+
* @param config 树形配置选项
|
|
334
|
+
* @returns 树的统计信息,包含总节点数、叶子节点数、最大深度和分支节点数
|
|
335
|
+
* @example
|
|
336
|
+
* ```ts
|
|
337
|
+
* const tree = [
|
|
338
|
+
* {
|
|
339
|
+
* id: '1',
|
|
340
|
+
* name: '根节点',
|
|
341
|
+
* children: [
|
|
342
|
+
* { id: '2', name: '子节点1', children: [] },
|
|
343
|
+
* { id: '3', name: '子节点2', children: [
|
|
344
|
+
* { id: '4', name: '孙节点', children: [] }
|
|
345
|
+
* ] }
|
|
346
|
+
* ]
|
|
347
|
+
* }
|
|
348
|
+
* ]
|
|
349
|
+
*
|
|
350
|
+
* const stats = Tree.getStats(tree)
|
|
351
|
+
* console.log(stats) // { total: 4, leaves: 2, depth: 3, branches: 2 }
|
|
352
|
+
* ```
|
|
353
|
+
*/
|
|
354
|
+
static getStats<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): TreeStats;
|
|
355
|
+
/**
|
|
356
|
+
* 过滤树形结构,保留满足条件的节点及其祖先和后代
|
|
357
|
+
*
|
|
358
|
+
* @category Data Structures
|
|
359
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
360
|
+
* @param predicate 过滤条件函数
|
|
361
|
+
* @param config 树形配置选项
|
|
362
|
+
* @returns 过滤后的树形结构数组
|
|
363
|
+
* @example
|
|
364
|
+
* ```ts
|
|
365
|
+
* const tree = [
|
|
366
|
+
* {
|
|
367
|
+
* id: '1',
|
|
368
|
+
* type: 'folder',
|
|
369
|
+
* name: '根目录',
|
|
370
|
+
* children: [
|
|
371
|
+
* { id: '2', type: 'file', name: '文档.txt', children: [] },
|
|
372
|
+
* { id: '3', type: 'folder', name: '子目录', children: [
|
|
373
|
+
* { id: '4', type: 'file', name: '图片.jpg', children: [] }
|
|
374
|
+
* ] }
|
|
375
|
+
* ]
|
|
376
|
+
* }
|
|
377
|
+
* ]
|
|
378
|
+
*
|
|
379
|
+
* const filtered = Tree.filter(tree, (node) => node.type === 'file')
|
|
380
|
+
* // 返回包含所有文件节点及其父级路径的树结构
|
|
381
|
+
* ```
|
|
382
|
+
*/
|
|
383
|
+
static filter<T = any>(tree: TreeNode<T> | TreeNode<T>[], predicate: TreePredicate<T>, config?: TreeConfigInput): TreeNode<T>[];
|
|
384
|
+
/**
|
|
385
|
+
* 转换树形结构,将每个节点转换为新的结构
|
|
386
|
+
*
|
|
387
|
+
* @category Data Structures
|
|
388
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
389
|
+
* @param transformer 节点转换函数
|
|
390
|
+
* @param config 树形配置选项
|
|
391
|
+
* @returns 转换后的树形结构数组
|
|
392
|
+
* @example
|
|
393
|
+
* ```ts
|
|
394
|
+
* const tree = [
|
|
395
|
+
* {
|
|
396
|
+
* id: '1',
|
|
397
|
+
* name: '部门1',
|
|
398
|
+
* children: [
|
|
399
|
+
* { id: '2', name: '部门1-1', children: [] }
|
|
400
|
+
* ]
|
|
401
|
+
* }
|
|
402
|
+
* ]
|
|
403
|
+
*
|
|
404
|
+
* const transformed = Tree.transform(tree, (node, depth) => ({
|
|
405
|
+
* key: node.id,
|
|
406
|
+
* title: node.name,
|
|
407
|
+
* level: depth
|
|
408
|
+
* }))
|
|
409
|
+
* // 转换为新的数据结构
|
|
410
|
+
* ```
|
|
411
|
+
*/
|
|
412
|
+
static transform<T = any, R = any>(tree: TreeNode<T> | TreeNode<T>[], transformer: TreeTransformer<T, R>, config?: TreeConfigInput): TreeNode<R>[];
|
|
413
|
+
/**
|
|
414
|
+
* 遍历树形结构的每个节点
|
|
415
|
+
*
|
|
416
|
+
* @category Data Structures
|
|
417
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
418
|
+
* @param visitor 访问者函数,返回false可以跳过子节点的遍历
|
|
419
|
+
* @param config 树形配置选项
|
|
420
|
+
* @example
|
|
421
|
+
* ```ts
|
|
422
|
+
* const tree = [
|
|
423
|
+
* {
|
|
424
|
+
* id: '1',
|
|
425
|
+
* name: '根节点',
|
|
426
|
+
* children: [
|
|
427
|
+
* { id: '2', name: '子节点', children: [] }
|
|
428
|
+
* ]
|
|
429
|
+
* }
|
|
430
|
+
* ]
|
|
431
|
+
*
|
|
432
|
+
* Tree.forEach(tree, (node, depth) => {
|
|
433
|
+
* console.log(`${' '.repeat(depth * 2)}${node.name}`)
|
|
434
|
+
* // 输出缩进的树结构
|
|
435
|
+
* })
|
|
436
|
+
* ```
|
|
437
|
+
*/
|
|
438
|
+
static forEach<T = any>(tree: TreeNode<T> | TreeNode<T>[], visitor: TreeVisitor<T>, config?: TreeConfigInput): void;
|
|
439
|
+
/**
|
|
440
|
+
* 在指定节点前插入新节点
|
|
441
|
+
*
|
|
442
|
+
* @category Data Structures
|
|
443
|
+
* @param tree 树形结构数组
|
|
444
|
+
* @param targetId 目标节点的ID
|
|
445
|
+
* @param newNode 要插入的新节点数据
|
|
446
|
+
* @param config 树形配置选项
|
|
447
|
+
* @returns 是否成功插入
|
|
448
|
+
* @example
|
|
449
|
+
* ```ts
|
|
450
|
+
* const tree = [
|
|
451
|
+
* {
|
|
452
|
+
* id: '1',
|
|
453
|
+
* name: '节点1',
|
|
454
|
+
* children: [
|
|
455
|
+
* { id: '2', name: '节点2', children: [] }
|
|
456
|
+
* ]
|
|
457
|
+
* }
|
|
458
|
+
* ]
|
|
459
|
+
*
|
|
460
|
+
* const success = Tree.insertBefore(tree, '2', { id: '1.5', name: '新节点' })
|
|
461
|
+
* console.log(success) // true
|
|
462
|
+
* ```
|
|
463
|
+
*/
|
|
464
|
+
static insertBefore<T = any>(tree: TreeNode<T>[], targetId: string, newNode: T, config?: TreeConfigInput): boolean;
|
|
465
|
+
/**
|
|
466
|
+
* 在指定节点后插入新节点
|
|
467
|
+
*
|
|
468
|
+
* @category Data Structures
|
|
469
|
+
* @param tree 树形结构数组
|
|
470
|
+
* @param targetId 目标节点的ID
|
|
471
|
+
* @param newNode 要插入的新节点数据
|
|
472
|
+
* @param config 树形配置选项
|
|
473
|
+
* @returns 是否成功插入
|
|
474
|
+
* @example
|
|
475
|
+
* ```ts
|
|
476
|
+
* const tree = [
|
|
477
|
+
* {
|
|
478
|
+
* id: '1',
|
|
479
|
+
* name: '节点1',
|
|
480
|
+
* children: [
|
|
481
|
+
* { id: '2', name: '节点2', children: [] }
|
|
482
|
+
* ]
|
|
483
|
+
* }
|
|
484
|
+
* ]
|
|
485
|
+
*
|
|
486
|
+
* const success = Tree.insertAfter(tree, '2', { id: '3', name: '新节点' })
|
|
487
|
+
* console.log(success) // true
|
|
488
|
+
* ```
|
|
489
|
+
*/
|
|
490
|
+
static insertAfter<T = any>(tree: TreeNode<T>[], targetId: string, newNode: T, config?: TreeConfigInput): boolean;
|
|
491
|
+
/**
|
|
492
|
+
* 从树中删除指定节点
|
|
493
|
+
*
|
|
494
|
+
* @category Data Structures
|
|
495
|
+
* @param tree 树形结构数组
|
|
496
|
+
* @param targetId 要删除的节点ID
|
|
497
|
+
* @param config 树形配置选项
|
|
498
|
+
* @returns 被删除的节点,未找到时返回undefined
|
|
499
|
+
* @example
|
|
500
|
+
* ```ts
|
|
501
|
+
* const tree = [
|
|
502
|
+
* {
|
|
503
|
+
* id: '1',
|
|
504
|
+
* name: '根节点',
|
|
505
|
+
* children: [
|
|
506
|
+
* { id: '2', name: '子节点', children: [] }
|
|
507
|
+
* ]
|
|
508
|
+
* }
|
|
509
|
+
* ]
|
|
510
|
+
*
|
|
511
|
+
* const removed = Tree.remove(tree, '2')
|
|
512
|
+
* console.log(removed?.name) // '子节点'
|
|
513
|
+
* ```
|
|
514
|
+
*/
|
|
515
|
+
static remove<T = any>(tree: TreeNode<T>[], targetId: string, config?: TreeConfigInput): TreeNode<T> | undefined;
|
|
516
|
+
/**
|
|
517
|
+
* 验证树形结构的有效性
|
|
518
|
+
*
|
|
519
|
+
* @category Data Structures
|
|
520
|
+
* @param tree 树形结构(单个节点或节点数组)
|
|
521
|
+
* @param config 树形配置选项
|
|
522
|
+
* @returns 验证结果,包含是否有效和错误信息数组
|
|
523
|
+
* @example
|
|
524
|
+
* ```ts
|
|
525
|
+
* const tree = [
|
|
526
|
+
* {
|
|
527
|
+
* id: '1',
|
|
528
|
+
* name: '根节点',
|
|
529
|
+
* children: [
|
|
530
|
+
* { id: '2', name: '子节点', children: [] }
|
|
531
|
+
* ]
|
|
532
|
+
* }
|
|
533
|
+
* ]
|
|
534
|
+
*
|
|
535
|
+
* const result = Tree.validate(tree)
|
|
536
|
+
* console.log(result.isValid) // true
|
|
537
|
+
* console.log(result.errors) // []
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
540
|
+
static validate<T = any>(tree: TreeNode<T> | TreeNode<T>[], config?: TreeConfigInput): {
|
|
270
541
|
isValid: boolean;
|
|
271
542
|
errors: string[];
|
|
272
543
|
};
|
|
273
544
|
}
|
|
274
545
|
|
|
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
546
|
/**
|
|
376
547
|
* 数组去重,返回去除重复元素后的新数组
|
|
377
548
|
*
|
|
@@ -1001,5 +1172,5 @@ declare function isFunction(value: any): value is (...args: any[]) => any;
|
|
|
1001
1172
|
*/
|
|
1002
1173
|
declare function isEmpty(value: any): boolean;
|
|
1003
1174
|
|
|
1004
|
-
export { StorageTypeSchema, Tree,
|
|
1005
|
-
export type { AnyObject, AppStorageReturn, DeepPartial, FirstParam, FirstParameter, GetObjectField, MutableByKeys, OmitByKey, PartialByKeys, PickByKey, ReadonlyByKeys, RenameKeys, RequiredByKeys, StorageConfig, StorageConfigInput, StorageType, StringOrVNode,
|
|
1175
|
+
export { StorageTypeSchema, Tree, camelToKebab, capitalize, chunk, convertSvgToPng, convertToKebabCase, createStorageConfigSchema, debounce, deepClone, extractFilename, flatten, formatFileSize, getRandomUUID, isArray, isEmpty, isFunction, isNumber, isObject, isString, kebabToCamel, omit, omitUndefined, pick, replaceCurrentColor, separate, simpleHash, sleep, sleepWithCancel, throttle, triggerDownload, unique, useAppStorage, useCopyCode };
|
|
1176
|
+
export type { AnyObject, AppStorageReturn, DeepPartial, FirstParam, FirstParameter, GetObjectField, MutableByKeys, OmitByKey, PartialByKeys, PickByKey, ReadonlyByKeys, RenameKeys, RequiredByKeys, StorageConfig, StorageConfigInput, StorageType, StringOrVNode, UnionToIntersection };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useStorage as D}from"@vueuse/core";import{z as g}from"zod/v4";const k=g.enum(["localStorage","sessionStorage"]);function j(e){return g.object({key:g.string().min(1,{message:"Key cannot be empty"}),schema:g.custom(t=>t instanceof g.ZodType,{message:"Schema must be a valid Zod schema"}),defaultValue:g.custom(t=>e.safeParse(t).success,{message:"Default value must match the provided schema"}),prefix:g.string().default("movk"),storage:k.default("localStorage")})}g.record(g.string(),g.any());const y=g.object({id:g.string().default("id"),pid:g.string().default("pid"),children:g.string().default("children")}),P=g.object({total:g.number().int().nonnegative(),leaves:g.number().int().nonnegative(),depth:g.number().int().nonnegative(),branches:g.number().int().nonnegative()});function M(e){const t=j(e.schema).parse(e),{key:r,defaultValue:n,schema:o,storage:s,prefix:a}=t,i=`${a}:${r}`,c=(()=>{if(!(typeof window>"u"))return s==="localStorage"?localStorage:sessionStorage})();function l(h){if(h===null)return n;try{const m=JSON.parse(h),b=o.safeParse(m);return b.success?b.data:(console.warn(`[AppStorage] Validation failed for key "${i}". Using default value.`,b.error.issues),n)}catch(m){return console.warn(`[AppStorage] Failed to parse value for key "${i}". Using default value.`,m),n}}const u=D(i,n,c,{mergeDefaults:!0,serializer:{read:l,write:h=>JSON.stringify(h)}});function d(){if(!c)return n;const h=c.getItem(i);return l(h)}function p(h){const m=o.safeParse(h);if(!m.success){console.warn(`[AppStorage] Invalid value for key "${i}". Aborting setItem.`,m.error.issues);return}u.value=m.data}function f(){c&&(u.value=null)}return{state:u,getItem:d,setItem:p,removeItem:f}}async function U(e){if(typeof e!="string")throw new TypeError("Text must be a string");if(typeof window>"u")return console.warn("useCopyCode: Not available in server environment"),!1;if(navigator.clipboard&&window.isSecureContext)try{return await navigator.clipboard.writeText(e),!0}catch(t){console.warn("Clipboard API failed, falling back to legacy method:",t)}try{return L(e)}catch(t){return console.error("Failed to copy text:",t),!1}}function L(e){if(typeof document>"u")return console.warn("copyTextLegacy: Document not available"),!1;const t=document.createElement("textarea"),r=document.activeElement,n=document.getSelection(),o=n&&n.rangeCount>0?n.getRangeAt(0):null;try{return t.value=e,t.setAttribute("readonly",""),t.setAttribute("contenteditable","true"),Object.assign(t.style,{contain:"strict",position:"absolute",left:"-9999px",top:"-9999px",fontSize:"12pt",border:"0",padding:"0",margin:"0",outline:"none",boxShadow:"none",background:"transparent"}),document.body.appendChild(t),t.focus(),t.select(),t.setSelectionRange&&t.setSelectionRange(0,e.length),document.execCommand("copy")}catch(s){return console.error("Legacy copy method failed:",s),!1}finally{t.parentNode&&document.body.removeChild(t),o&&n&&(n.removeAllRanges(),n.addRange(o)),r instanceof HTMLElement&&r.focus()}}class w{static*dfsGenerator(t,r,n=[]){const{children:o}=y.parse(r);let s=0;for(const a of t){const i=[...n,a];yield{node:a,path:i,depth:n.length,index:s++};const c=a[o];c&&c.length>0&&(yield*w.dfsGenerator(c,r,i))}}static*bfsGenerator(t,r){const{children:n}=y.parse(r),o=t.map((a,i)=>({node:a,path:[a],depth:0,index:i}));let s=t.length;for(;o.length>0;){const a=o.shift();yield a;const i=a.node[n];i&&i.length>0&&i.forEach(c=>{const l=[...a.path,c];o.push({node:c,path:l,depth:a.depth+1,index:s++})})}}static selectStrategy(t){switch(t){case"find":case"findAll":case"filter":case"transform":case"forEach":case"stats":case"validate":return"dfs";default:return"dfs"}}static fromList(t,r={}){const n=y.parse(r),{id:o,pid:s,children:a}=n;if(!Array.isArray(t)||t.length===0)return[];const i=new Map,c=[];return t.forEach(l=>{const u={...l,[a]:[]};i.set(l[o],u)}),t.forEach(l=>{const u=i.get(l[o]),d=l[s];d&&i.has(d)?i.get(d)[a].push(u):c.push(u)}),c}static toList(t,r={}){const n=y.parse(r),{children:o}=n,s=[],a=Array.isArray(t)?t:[t],i=c=>{const{[o]:l,...u}=c;s.push(u),l&&l.length>0&&l.forEach(i)};return a.forEach(i),s}static estimateSize(t,r={}){const n=y.parse(r),{children:o}=n,s=Array.isArray(t)?t:[t];let a=0;const i=c=>{a++;const l=c[o];l&&l.length>0&&l.forEach(i)};return s.forEach(i),a}static find(t,r,n={}){const o=Array.isArray(t)?t:[t],s=w.selectStrategy("find")==="dfs"?w.dfsGenerator(o,n):w.bfsGenerator(o,n);for(const a of s)if(r(a.node,a.depth,a.path))return a}static findAll(t,r,n={}){const o=Array.isArray(t)?t:[t],s=w.selectStrategy("findAll"),a=[],i=s==="dfs"?w.dfsGenerator(o,n):w.bfsGenerator(o,n);for(const c of i)r(c.node,c.depth,c.path)&&a.push(c);return a}static findById(t,r,n={}){const o=y.parse(n),{id:s}=o;return this.find(t,a=>a[s]===r,n)}static getStats(t,r={}){const n=y.parse(r),{children:o}=n,s=Array.isArray(t)?t:[t];let a=0,i=0,c=0,l=0;const u=(d,p)=>{a++,c=Math.max(c,p);const f=d[o];f&&f.length>0?(l++,f.forEach(h=>u(h,p+1))):i++};return s.forEach(d=>u(d,1)),{total:a,leaves:i,depth:c,branches:l}}static filter(t,r,n={}){const o=y.parse(n),{children:s}=o,a=Array.isArray(t)?t:[t],i=[],c=(l,u,d)=>{const p=l[s],f=[];if(p&&p.length>0){const h=[...d,l];p.forEach(m=>{const b=c(m,u+1,h);b&&f.push(b)})}return r(l,u,d)||f.length>0?{...l,[s]:f}:null};return a.forEach(l=>{const u=c(l,0,[]);u&&i.push(u)}),i}static transform(t,r,n={}){const o=y.parse(n),{children:s}=o,a=Array.isArray(t)?t:[t],i=[],c=(l,u,d)=>{const p=l[s],f=[];if(p&&p.length>0){const h=[...d,l];p.forEach(m=>{f.push(c(m,u+1,h))})}return{...r(l,u,d),[s]:f}};return a.forEach(l=>{i.push(c(l,0,[]))}),i}static forEach(t,r,n={}){const o=y.parse(n),{children:s}=o,a=Array.isArray(t)?t:[t],i=(c,l,u)=>{if(r(c,l,u)!==!1){const d=c[s];if(d&&d.length>0){const p=[...u,c];d.forEach(f=>{i(f,l+1,p)})}}};a.forEach(c=>i(c,0,[]))}static insertBefore(t,r,n,o={}){const s=y.parse(o),{id:a,children:i}=s,c={...n,[i]:[]},l=(u,d)=>{for(let p=0;p<u.length;p++){const f=u[p];if(f[a]===r)return u.splice(p,0,c),!0;const h=f[i];if(h&&h.length>0){const m=[...d,f];if(l(h,m))return!0}}return!1};return l(t,[])}static insertAfter(t,r,n,o={}){const s=y.parse(o),{id:a,children:i}=s,c={...n,[i]:[]},l=(u,d)=>{for(let p=0;p<u.length;p++){const f=u[p];if(f[a]===r)return u.splice(p+1,0,c),!0;const h=f[i];if(h&&h.length>0){const m=[...d,f];if(l(h,m))return!0}}return!1};return l(t,[])}static remove(t,r,n={}){const o=y.parse(n),{id:s,children:a}=o,i=c=>{for(let l=0;l<c.length;l++){const u=c[l];if(u[s]===r)return c.splice(l,1)[0];const d=u[a];if(d&&d.length>0){const p=i(d);if(p)return p}}};return i(t)}static validate(t,r={}){const n=y.parse(r),{id:o,children:s}=n,a=Array.isArray(t)?t:[t],i=[],c=new Set,l=(u,d,p)=>{const f=u[o];if(!f||typeof f!="string"){i.push(`Node at depth ${d} has invalid or missing ID`);return}if(c.has(f)){i.push(`Duplicate ID found: ${f}`);return}if(c.add(f),p.some(m=>m[o]===f)){i.push(`Circular reference detected for ID: ${f}`);return}const h=u[s];if(h!==void 0&&!Array.isArray(h)){i.push(`Node ${f} has invalid children property (not an array)`);return}if(h&&h.length>0){const m=[...p,u];h.forEach(b=>{l(b,d+1,m)})}};return a.forEach(u=>l(u,0,[])),{isValid:i.length===0,errors:i}}}const S={row:"row",col:"column","row-reverse":"row-reverse","col-reverse":"column-reverse"},$={start:"flex-start",end:"flex-end",center:"center",between:"space-between",around:"space-around",evenly:"space-evenly"},A={start:"flex-start",end:"flex-end",center:"center",stretch:"stretch",baseline:"baseline"},C=Object.keys(S),O=Object.keys($),N=Object.keys(A),R=[new RegExp(`^(?:inline-)?flex-(${C.join("|")})(?:-(${O.join("|")}))?(?:-(${N.join("|")}))?$`),([,e,t,r],{rawSelector:n})=>{const o={display:n.startsWith("inline-")?"inline-flex":"flex"};return e&&S[e]&&(o["flex-direction"]=S[e]),t&&$[t]&&(o["justify-content"]=$[t]),r&&A[r]&&(o["align-items"]=A[r]),o},{autocomplete:`(inline-)?flex-(${C.join("|")})(-(${O.join("|")}))?(-(${N.join("|")}))?`}];function V(){return{name:"@movk/preset-flex",rules:[R,["flex-center",{display:"flex","justify-content":"center","align-items":"center"}],["inline-flex-center",{display:"inline-flex","justify-content":"center","align-items":"center"}]],shortcuts:[{"flex-x-center":"flex justify-center","flex-y-center":"flex items-center","inline-flex-x-center":"inline-flex justify-center","inline-flex-y-center":"inline-flex items-center"}]}}function x(e){return e.replace(/[.:#[\]()]/g,"\\$&")}function z(){return{name:"@movk/preset-owl",rules:[[/^owl-y-(.+)$/,([,e],{rawSelector:t})=>{if(!e)return;const r=v(e);return r?`${x(t)} > * + * { margin-block-start: ${r}; }`:void 0},{autocomplete:"owl-y-<num>"}],[/^owl-x-(.+)$/,([,e],{rawSelector:t})=>{if(!e)return;const r=v(e);return r?`${x(t)} > * + * { margin-inline-start: ${r}; }`:void 0},{autocomplete:"owl-x-<num>"}],[/^owl-block-(.+)$/,([,e],{rawSelector:t})=>{if(!e)return;const r=v(e);return r?`${x(t)} > * + * { margin-block-start: ${r}; }`:void 0},{autocomplete:"owl-block-<num>"}],[/^owl-inline-(.+)$/,([,e],{rawSelector:t})=>{if(!e)return;const r=v(e);return r?`${x(t)} > * + * { margin-inline-start: ${r}; }`:void 0},{autocomplete:"owl-inline-<num>"}],[/^owl-recursive-(.+)$/,([,e],{rawSelector:t})=>{if(!e)return;const r=v(e);return r?`${x(t)} * + * { margin-block-start: ${r}; }`:void 0},{autocomplete:"owl-recursive-<num>"}],[/^owl-divide-(.+)$/,([,e],{rawSelector:t})=>{if(!e)return;const r=B(e)||"#e5e7eb";return`${x(t)} > * + * { border-block-start: 1px solid ${r}; }`},{autocomplete:"owl-divide-<color>"}],[/^owl-divide-style-(.+)$/,([,e],{rawSelector:t})=>!e||!["solid","dashed","dotted","double","none"].includes(e)?void 0:`${x(t)} > * + * { border-block-start-style: ${e}; }`,{autocomplete:"owl-divide-style-<style>"}],[/^owl-divide-width-(.+)$/,([,e],{rawSelector:t})=>{if(!e)return;const r=v(e)||e;return`${x(t)} > * + * { border-block-start-width: ${r}; }`},{autocomplete:"owl-divide-width-<num>"}]],shortcuts:[{"owl-stack":"owl-y-4","owl-stack-tight":"owl-y-2","owl-stack-loose":"owl-y-8","owl-list":"owl-x-4","owl-list-tight":"owl-x-2","owl-nav":"owl-x-6","owl-card-stack":"owl-y-4 owl-divide-gray-200"}]}}function v(e){return/^\d+(?:\.\d+)?$/.test(e)?`${Number.parseFloat(e)*.25}rem`:/^\d+(?:\.\d+)?(?:px|rem|em|%|vh|vw|ch|ex)$/.test(e)?e:{auto:"auto",px:"1px",0:"0",1:"0.25rem",2:"0.5rem",3:"0.75rem",4:"1rem",6:"1.5rem",8:"2rem",12:"3rem",16:"4rem",24:"6rem"}[e]}function B(e){return/^#[0-9a-f]{3,8}$/i.test(e)||/^rgba?(?:\(|$)/.test(e)?e:{transparent:"transparent",current:"currentColor",black:"#000000",white:"#ffffff","gray-200":"#e5e7eb","gray-300":"#d1d5db","gray-500":"#6b7280","gray-700":"#374151","red-500":"#ef4444","blue-500":"#3b82f6","green-500":"#10b981"}[e]}function K(e){return[...new Set(e)]}function Z(e,t){const r=[];for(let n=0;n<e.length;n+=t)r.push(e.slice(n,n+t));return r}function q(e,t=1){return t===1?e.flat():e.flat(t)}function H(e,t){let r;return(...n)=>{clearTimeout(r),r=setTimeout(()=>e(...n),t)}}function J(e){return new Promise(t=>setTimeout(t,e))}function W(e){let t,r;return{promise:new Promise((n,o)=>{r=o,t=setTimeout(n,e)}),cancel:()=>{clearTimeout(t),r(new Error("Sleep was cancelled"))}}}function X(e,t){let r=!1;return function(...n){r||(e.apply(this,n),r=!0,setTimeout(()=>{r=!1},t))}}async function Q(e){if(!e||typeof e!="string")throw new Error("Invalid SVG string provided");if(typeof window>"u"||typeof document>"u")throw new TypeError("convertSvgToPng is only available in browser environment");return new Promise((t,r)=>{const n=new Image,o=document.createElement("canvas"),s=o.getContext("2d");if(!s){r(new Error("Canvas context not available"));return}n.onload=()=>{try{o.width=n.width,o.height=n.height,s.drawImage(n,0,0),o.toBlob(a=>{a?t(a):r(new Error("Failed to convert canvas to Blob"))},"image/png")}catch(a){r(new Error(`Error during canvas conversion: ${a}`))}},n.onerror=()=>{r(new Error("Failed to load SVG image"))};try{n.src=`data:image/svg+xml;base64,${btoa(e)}`}catch(a){r(new Error(`Failed to encode SVG: ${a}`))}})}function Y(e,t="file"){if(!e)return t;const r=e.get("content-disposition");if(r){const n=r.match(/filename\*?=['"]?([^'";]+)['"]?/i);if(n){let o=n[1];if(r.includes("filename*=")){const s=o.split("''");s.length===2&&(o=decodeURIComponent(s[1]))}return o}}return t}function _(e,t){if(typeof window>"u"||typeof document>"u"){console.warn("triggerDownload: Not available in server environment");return}const r=URL.createObjectURL(e),n=document.createElement("a");n.href=r,n.download=t,n.style.display="none",document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(r)}function ee(e){if(!Number.isFinite(e)||e<0||e===0)return"0 Bytes";const t=1024,r=["Bytes","KB","MB","GB","TB","PB"],n=Math.floor(Math.log(e)/Math.log(t));return n>=r.length?`${Number.parseFloat((e/t**(r.length-1)).toFixed(2))} ${r[r.length-1]}`:`${Number.parseFloat((e/t**n).toFixed(2))} ${r[n]}`}async function te(e,t){if(!e||typeof e!="string")throw new Error("Invalid SVG path provided");try{const r=await fetch(e);if(!r.ok)throw new Error(`Failed to fetch SVG file: ${r.status} ${r.statusText}`);const n=await r.text();if(!t)return n;if(typeof window>"u"||typeof DOMParser>"u")return console.warn("replaceCurrentColor: DOM manipulation not available in server environment, returning original SVG"),n;const o=new DOMParser().parseFromString(n,"image/svg+xml");if(o.querySelector("parsererror"))throw new Error("Invalid SVG content");const s=o.querySelector("svg");if(!s)throw new Error("No SVG element found in the document");s.hasAttribute("fill")||s.setAttribute("fill","currentColor");const a=i=>{i.getAttribute("fill")==="currentColor"&&i.setAttribute("fill",t),i.getAttribute("stroke")==="currentColor"&&i.setAttribute("stroke",t),Array.from(i.children).forEach(c=>{a(c)})};return a(s),new XMLSerializer().serializeToString(o)}catch(r){throw r instanceof Error?r:new Error(`Unexpected error occurred: ${r}`)}}function I(e,t=!1){if(!e||typeof e!="object"||Array.isArray(e))return e;const r=o=>o.replace(/([a-z\d])([A-Z])/g,"$1-$2").toLowerCase(),n={};for(const o in e)if(Object.prototype.hasOwnProperty.call(e,o)){const s=r(o),a=e[o];t&&a&&typeof a=="object"&&!Array.isArray(a)?n[s]=I(a,!0):n[s]=a}return n}function E(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(Array.isArray(e))return e.map(t=>E(t));if(typeof e=="object"){const t={};for(const r in e)t[r]=E(e[r]);return t}return e}function re(e,t){if(!e||typeof e!="object")return{};const r=new Set(t),n={};for(const o in e)Object.prototype.hasOwnProperty.call(e,o)&&!r.has(o)&&(n[o]=e[o]);return n}function ne(e){return!e||typeof e!="object"||Array.isArray(e)?e:Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0))}function oe(e,t){if(!e||typeof e!="object")return{};const r={};for(const n of t)Object.prototype.hasOwnProperty.call(e,n)&&(r[n]=e[n]);return r}function ae(e,t){if(!e||typeof e!="object")return{picked:{},omitted:{}};if(t.length===0)return{picked:{},omitted:{...e}};const r=new Set(t),n={},o={};for(const s in e)if(Object.hasOwn(e,s)){const a=s;r.has(a)?n[s]=e[a]:o[s]=e[a]}return{picked:n,omitted:o}}function ie(e){return e.charAt(0).toUpperCase()+e.slice(1)}function se(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function ce(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function le(e){let t=0;for(let r=0;r<e.length;r++){const n=e.charCodeAt(r);t=(t<<5)-t+n,t=t&t}return Math.abs(t).toString(36)}function ue(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}function T(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function F(e){return Array.isArray(e)}function G(e){return typeof e=="string"}function fe(e){return typeof e=="number"&&!Number.isNaN(e)}function de(e){return typeof e=="function"}function pe(e){return e==null?!0:F(e)||G(e)?e.length===0:T(e)?Object.keys(e).length===0:!1}export{k as StorageTypeSchema,w as Tree,y as TreeConfigSchema,P as TreeStatsSchema,se as camelToKebab,ie as capitalize,Z as chunk,Q as convertSvgToPng,I as convertToKebabCase,j as createStorageConfigSchema,H as debounce,E as deepClone,Y as extractFilename,q as flatten,ee as formatFileSize,ue as getRandomUUID,F as isArray,pe as isEmpty,de as isFunction,fe as isNumber,T as isObject,G as isString,ce as kebabToCamel,re as omit,ne as omitUndefined,oe as pick,V as presetFlex,z as presetOwl,te as replaceCurrentColor,ae as separate,le as simpleHash,J as sleep,W as sleepWithCancel,X as throttle,_ as triggerDownload,K as unique,M as useAppStorage,U as useCopyCode};
|
|
1
|
+
import{useStorage as $}from"@vueuse/core";import{z as y}from"zod/v4";const x=y.enum(["localStorage","sessionStorage"]);function A(e){return y.object({key:y.string().min(1,{message:"Key cannot be empty"}),schema:y.custom(t=>t instanceof y.ZodType,{message:"Schema must be a valid Zod schema"}),defaultValue:y.custom(t=>e.safeParse(t).success,{message:"Default value must match the provided schema"}),prefix:y.string().default("movk"),storage:x.default("localStorage")})}function k(e){const t=A(e.schema).parse(e),{key:n,defaultValue:r,schema:o,storage:s,prefix:a}=t,i=`${a}:${n}`,c=(()=>{if(!(typeof window>"u"))return s==="localStorage"?localStorage:sessionStorage})();function l(p){if(p===null)return r;try{const g=JSON.parse(p),w=o.safeParse(g);return w.success?w.data:(console.warn(`[AppStorage] Validation failed for key "${i}". Using default value.`,w.error.issues),r)}catch(g){return console.warn(`[AppStorage] Failed to parse value for key "${i}". Using default value.`,g),r}}const u=$(i,r,c,{mergeDefaults:!0,serializer:{read:l,write:p=>JSON.stringify(p)}});function d(){if(!c)return r;const p=c.getItem(i);return l(p)}function h(p){const g=o.safeParse(p);if(!g.success){console.warn(`[AppStorage] Invalid value for key "${i}". Aborting setItem.`,g.error.issues);return}u.value=g.data}function f(){c&&(u.value=null)}return{state:u,getItem:d,setItem:h,removeItem:f}}async function O(e){if(typeof e!="string")throw new TypeError("Text must be a string");if(typeof window>"u")return console.warn("useCopyCode: Not available in server environment"),!1;if(navigator.clipboard&&window.isSecureContext)try{return await navigator.clipboard.writeText(e),!0}catch(t){console.warn("Clipboard API failed, falling back to legacy method:",t)}try{return I(e)}catch(t){return console.error("Failed to copy text:",t),!1}}function I(e){if(typeof document>"u")return console.warn("copyTextLegacy: Document not available"),!1;const t=document.createElement("textarea"),n=document.activeElement,r=document.getSelection(),o=r&&r.rangeCount>0?r.getRangeAt(0):null;try{return t.value=e,t.setAttribute("readonly",""),t.setAttribute("contenteditable","true"),Object.assign(t.style,{contain:"strict",position:"absolute",left:"-9999px",top:"-9999px",fontSize:"12pt",border:"0",padding:"0",margin:"0",outline:"none",boxShadow:"none",background:"transparent"}),document.body.appendChild(t),t.focus(),t.select(),t.setSelectionRange&&t.setSelectionRange(0,e.length),document.execCommand("copy")}catch(s){return console.error("Legacy copy method failed:",s),!1}finally{t.parentNode&&document.body.removeChild(t),o&&r&&(r.removeAllRanges(),r.addRange(o)),n instanceof HTMLElement&&n.focus()}}const m=y.object({id:y.string().default("id"),pid:y.string().default("pid"),children:y.string().default("children")});y.object({total:y.number().int().nonnegative(),leaves:y.number().int().nonnegative(),depth:y.number().int().nonnegative(),branches:y.number().int().nonnegative()});class b{static*dfsGenerator(t,n={},r=[]){const{children:o}=m.parse(n);let s=0;for(const a of t){const i=[...r,a];yield{node:a,path:i,depth:r.length,index:s++};const c=a[o];c&&c.length>0&&(yield*b.dfsGenerator(c,n,i))}}static*bfsGenerator(t,n={}){const{children:r}=m.parse(n),o=t.map((a,i)=>({node:a,path:[a],depth:0,index:i}));let s=t.length;for(;o.length>0;){const a=o.shift();yield a;const i=a.node[r];i&&i.length>0&&i.forEach(c=>{const l=[...a.path,c];o.push({node:c,path:l,depth:a.depth+1,index:s++})})}}static selectStrategy(t){switch(t){case"find":case"findAll":case"filter":case"transform":case"forEach":case"stats":case"validate":return"dfs";default:return"dfs"}}static fromList(t,n={}){const r=m.parse(n),{id:o,pid:s,children:a}=r;if(!Array.isArray(t)||t.length===0)return[];const i=new Map,c=[];return t.forEach(l=>{const u={...l,[a]:[]};i.set(l[o],u)}),t.forEach(l=>{const u=i.get(l[o]),d=l[s];d&&i.has(d)?i.get(d)[a].push(u):c.push(u)}),c}static toList(t,n={}){const r=m.parse(n),{children:o}=r,s=[],a=Array.isArray(t)?t:[t],i=c=>{const{[o]:l,...u}=c;s.push(u),l&&l.length>0&&l.forEach(i)};return a.forEach(i),s}static estimateSize(t,n={}){const r=m.parse(n),{children:o}=r,s=Array.isArray(t)?t:[t];let a=0;const i=c=>{a++;const l=c[o];l&&l.length>0&&l.forEach(i)};return s.forEach(i),a}static find(t,n,r={}){const o=Array.isArray(t)?t:[t],s=b.selectStrategy("find")==="dfs"?b.dfsGenerator(o,r):b.bfsGenerator(o,r);for(const a of s)if(n(a.node,a.depth,a.path))return a}static findAll(t,n,r={}){const o=Array.isArray(t)?t:[t],s=b.selectStrategy("findAll"),a=[],i=s==="dfs"?b.dfsGenerator(o,r):b.bfsGenerator(o,r);for(const c of i)n(c.node,c.depth,c.path)&&a.push(c);return a}static findById(t,n,r={}){const o=m.parse(r),{id:s}=o;return this.find(t,a=>a[s]===n,r)}static getStats(t,n={}){const r=m.parse(n),{children:o}=r,s=Array.isArray(t)?t:[t];let a=0,i=0,c=0,l=0;const u=(d,h)=>{a++,c=Math.max(c,h);const f=d[o];f&&f.length>0?(l++,f.forEach(p=>u(p,h+1))):i++};return s.forEach(d=>u(d,1)),{total:a,leaves:i,depth:c,branches:l}}static filter(t,n,r={}){const o=m.parse(r),{children:s}=o,a=Array.isArray(t)?t:[t],i=[],c=(l,u,d)=>{const h=l[s],f=[];if(h&&h.length>0){const p=[...d,l];h.forEach(g=>{const w=c(g,u+1,p);w&&f.push(w)})}return n(l,u,d)||f.length>0?{...l,[s]:f}:null};return a.forEach(l=>{const u=c(l,0,[]);u&&i.push(u)}),i}static transform(t,n,r={}){const o=m.parse(r),{children:s}=o,a=Array.isArray(t)?t:[t],i=[],c=(l,u,d)=>{const h=l[s],f=[];if(h&&h.length>0){const p=[...d,l];h.forEach(g=>{f.push(c(g,u+1,p))})}return{...n(l,u,d),[s]:f}};return a.forEach(l=>{i.push(c(l,0,[]))}),i}static forEach(t,n,r={}){const o=m.parse(r),{children:s}=o,a=Array.isArray(t)?t:[t],i=(c,l,u)=>{if(n(c,l,u)!==!1){const d=c[s];if(d&&d.length>0){const h=[...u,c];d.forEach(f=>{i(f,l+1,h)})}}};a.forEach(c=>i(c,0,[]))}static insertBefore(t,n,r,o={}){const s=m.parse(o),{id:a,children:i}=s,c={...r,[i]:[]},l=(u,d)=>{for(let h=0;h<u.length;h++){const f=u[h];if(f[a]===n)return u.splice(h,0,c),!0;const p=f[i];if(p&&p.length>0){const g=[...d,f];if(l(p,g))return!0}}return!1};return l(t,[])}static insertAfter(t,n,r,o={}){const s=m.parse(o),{id:a,children:i}=s,c={...r,[i]:[]},l=(u,d)=>{for(let h=0;h<u.length;h++){const f=u[h];if(f[a]===n)return u.splice(h+1,0,c),!0;const p=f[i];if(p&&p.length>0){const g=[...d,f];if(l(p,g))return!0}}return!1};return l(t,[])}static remove(t,n,r={}){const o=m.parse(r),{id:s,children:a}=o,i=c=>{for(let l=0;l<c.length;l++){const u=c[l];if(u[s]===n)return c.splice(l,1)[0];const d=u[a];if(d&&d.length>0){const h=i(d);if(h)return h}}};return i(t)}static validate(t,n={}){const r=m.parse(n),{id:o,children:s}=r,a=Array.isArray(t)?t:[t],i=[],c=new Set,l=(u,d,h)=>{const f=u[o];if(!f||typeof f!="string"){i.push(`Node at depth ${d} has invalid or missing ID`);return}if(c.has(f)){i.push(`Duplicate ID found: ${f}`);return}if(c.add(f),h.some(g=>g[o]===f)){i.push(`Circular reference detected for ID: ${f}`);return}const p=u[s];if(p!==void 0&&!Array.isArray(p)){i.push(`Node ${f} has invalid children property (not an array)`);return}if(p&&p.length>0){const g=[...h,u];p.forEach(w=>{l(w,d+1,g)})}};return a.forEach(u=>l(u,0,[])),{isValid:i.length===0,errors:i}}}function G(e){return[...new Set(e)]}function N(e,t){const n=[];for(let r=0;r<e.length;r+=t)n.push(e.slice(r,r+t));return n}function T(e,t=1){return t===1?e.flat():e.flat(t)}function D(e,t){let n;return(...r)=>{clearTimeout(n),n=setTimeout(()=>e(...r),t)}}function F(e){return new Promise(t=>setTimeout(t,e))}function P(e){let t,n;return{promise:new Promise((r,o)=>{n=o,t=setTimeout(r,e)}),cancel:()=>{clearTimeout(t),n(new Error("Sleep was cancelled"))}}}function M(e,t){let n=!1;return function(...r){n||(e.apply(this,r),n=!0,setTimeout(()=>{n=!1},t))}}async function U(e){if(!e||typeof e!="string")throw new Error("Invalid SVG string provided");if(typeof window>"u"||typeof document>"u")throw new TypeError("convertSvgToPng is only available in browser environment");return new Promise((t,n)=>{const r=new Image,o=document.createElement("canvas"),s=o.getContext("2d");if(!s){n(new Error("Canvas context not available"));return}r.onload=()=>{try{o.width=r.width,o.height=r.height,s.drawImage(r,0,0),o.toBlob(a=>{a?t(a):n(new Error("Failed to convert canvas to Blob"))},"image/png")}catch(a){n(new Error(`Error during canvas conversion: ${a}`))}},r.onerror=()=>{n(new Error("Failed to load SVG image"))};try{r.src=`data:image/svg+xml;base64,${btoa(e)}`}catch(a){n(new Error(`Failed to encode SVG: ${a}`))}})}function L(e,t="file"){if(!e)return t;const n=e.get("content-disposition");if(n){const r=n.match(/filename\*?=['"]?([^'";]+)['"]?/i);if(r){let o=r[1];if(n.includes("filename*=")){const s=o.split("''");s.length===2&&(o=decodeURIComponent(s[1]))}return o}}return t}function V(e,t){if(typeof window>"u"||typeof document>"u"){console.warn("triggerDownload: Not available in server environment");return}const n=URL.createObjectURL(e),r=document.createElement("a");r.href=n,r.download=t,r.style.display="none",document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(n)}function z(e){if(!Number.isFinite(e)||e<0||e===0)return"0 Bytes";const t=1024,n=["Bytes","KB","MB","GB","TB","PB"],r=Math.floor(Math.log(e)/Math.log(t));return r>=n.length?`${Number.parseFloat((e/t**(n.length-1)).toFixed(2))} ${n[n.length-1]}`:`${Number.parseFloat((e/t**r).toFixed(2))} ${n[r]}`}async function B(e,t){if(!e||typeof e!="string")throw new Error("Invalid SVG path provided");try{const n=await fetch(e);if(!n.ok)throw new Error(`Failed to fetch SVG file: ${n.status} ${n.statusText}`);const r=await n.text();if(!t)return r;if(typeof window>"u"||typeof DOMParser>"u")return console.warn("replaceCurrentColor: DOM manipulation not available in server environment, returning original SVG"),r;const o=new DOMParser().parseFromString(r,"image/svg+xml");if(o.querySelector("parsererror"))throw new Error("Invalid SVG content");const s=o.querySelector("svg");if(!s)throw new Error("No SVG element found in the document");s.hasAttribute("fill")||s.setAttribute("fill","currentColor");const a=i=>{i.getAttribute("fill")==="currentColor"&&i.setAttribute("fill",t),i.getAttribute("stroke")==="currentColor"&&i.setAttribute("stroke",t),Array.from(i.children).forEach(c=>{a(c)})};return a(s),new XMLSerializer().serializeToString(o)}catch(n){throw n instanceof Error?n:new Error(`Unexpected error occurred: ${n}`)}}function S(e,t=!1){if(!e||typeof e!="object"||Array.isArray(e))return e;const n=o=>o.replace(/([a-z\d])([A-Z])/g,"$1-$2").toLowerCase(),r={};for(const o in e)if(Object.prototype.hasOwnProperty.call(e,o)){const s=n(o),a=e[o];t&&a&&typeof a=="object"&&!Array.isArray(a)?r[s]=S(a,!0):r[s]=a}return r}function v(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(Array.isArray(e))return e.map(t=>v(t));if(typeof e=="object"){const t={};for(const n in e)t[n]=v(e[n]);return t}return e}function R(e,t){if(!e||typeof e!="object")return{};const n=new Set(t),r={};for(const o in e)Object.prototype.hasOwnProperty.call(e,o)&&!n.has(o)&&(r[o]=e[o]);return r}function K(e){return!e||typeof e!="object"||Array.isArray(e)?e:Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0))}function Z(e,t){if(!e||typeof e!="object")return{};const n={};for(const r of t)Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function q(e,t){if(!e||typeof e!="object")return{picked:{},omitted:{}};if(t.length===0)return{picked:{},omitted:{...e}};const n=new Set(t),r={},o={};for(const s in e)if(Object.hasOwn(e,s)){const a=s;n.has(a)?r[s]=e[a]:o[s]=e[a]}return{picked:r,omitted:o}}function H(e){return e.charAt(0).toUpperCase()+e.slice(1)}function J(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function W(e){return e.replace(/-([a-z])/g,(t,n)=>n.toUpperCase())}function X(e){let t=0;for(let n=0;n<e.length;n++){const r=e.charCodeAt(n);t=(t<<5)-t+r,t=t&t}return Math.abs(t).toString(36)}function Q(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}function E(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function C(e){return Array.isArray(e)}function j(e){return typeof e=="string"}function Y(e){return typeof e=="number"&&!Number.isNaN(e)}function _(e){return typeof e=="function"}function tt(e){return e==null?!0:C(e)||j(e)?e.length===0:E(e)?Object.keys(e).length===0:!1}export{x as StorageTypeSchema,b as Tree,J as camelToKebab,H as capitalize,N as chunk,U as convertSvgToPng,S as convertToKebabCase,A as createStorageConfigSchema,D as debounce,v as deepClone,L as extractFilename,T as flatten,z as formatFileSize,Q as getRandomUUID,C as isArray,tt as isEmpty,_ as isFunction,Y as isNumber,E as isObject,j as isString,W as kebabToCamel,R as omit,K as omitUndefined,Z as pick,B as replaceCurrentColor,q as separate,X as simpleHash,F as sleep,P as sleepWithCancel,M as throttle,V as triggerDownload,G as unique,k as useAppStorage,O as useCopyCode};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@movk/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.4",
|
|
5
5
|
"description": "Modern Vue.js utilities and composables collection with TypeScript support",
|
|
6
6
|
"author": "yixuan",
|
|
7
7
|
"license": "MIT",
|
|
@@ -37,39 +37,32 @@
|
|
|
37
37
|
"dist"
|
|
38
38
|
],
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"vue": "^3.5.
|
|
40
|
+
"vue": "^3.5.18"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@vueuse/core": "^13.
|
|
44
|
-
"zod": "^4.0.
|
|
43
|
+
"@vueuse/core": "^13.6.0",
|
|
44
|
+
"zod": "^4.0.14"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@antfu/eslint-config": "^
|
|
48
|
-
"@
|
|
49
|
-
"@types/node": "^24.0
|
|
50
|
-
"bumpp": "^10.2.
|
|
51
|
-
"eslint": "^9.
|
|
52
|
-
"
|
|
53
|
-
"simple-git-hooks": "^2.13.0",
|
|
47
|
+
"@antfu/eslint-config": "^5.0.0",
|
|
48
|
+
"@release-it/conventional-changelog": "^10.0.1",
|
|
49
|
+
"@types/node": "^24.1.0",
|
|
50
|
+
"bumpp": "^10.2.1",
|
|
51
|
+
"eslint": "^9.32.0",
|
|
52
|
+
"release-it": "^19.0.4",
|
|
54
53
|
"taze": "^19.1.0",
|
|
55
54
|
"tsx": "^4.20.3",
|
|
56
55
|
"typescript": "^5.8.3",
|
|
57
|
-
"unbuild": "^3.
|
|
58
|
-
"vite": "^7.0.
|
|
56
|
+
"unbuild": "^3.6.0",
|
|
57
|
+
"vite": "^7.0.6",
|
|
59
58
|
"vitest": "^3.2.4"
|
|
60
59
|
},
|
|
61
|
-
"simple-git-hooks": {
|
|
62
|
-
"pre-commit": "pnpm lint-staged"
|
|
63
|
-
},
|
|
64
|
-
"lint-staged": {
|
|
65
|
-
"*": "eslint --fix"
|
|
66
|
-
},
|
|
67
60
|
"scripts": {
|
|
68
61
|
"build": "unbuild",
|
|
69
62
|
"dev": "unbuild --stub",
|
|
70
63
|
"lint": "eslint .",
|
|
71
|
-
"lint
|
|
72
|
-
"release": "
|
|
64
|
+
"lint:fix": "pnpm run lint --fix",
|
|
65
|
+
"release": "release-it --verbose",
|
|
73
66
|
"start": "tsx src/index.ts",
|
|
74
67
|
"typecheck": "tsc --noEmit",
|
|
75
68
|
"test": "vitest",
|