@d-matrix/utils 1.22.0 → 1.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ export * as tree from './tree';
@@ -0,0 +1 @@
1
+ export * as tree from './tree';
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 计算指定层级的节点数量
3
+ * @param root tree data 对象
4
+ * @param depth 需要计算节点数量的层级
5
+ * @param childrenKey 子节点key
6
+ * @returns 节点数量
7
+ */
8
+ export declare const nodeCountAtDepth: <T extends Record<string, any>>(root: T, depth: number, childrenKey?: string) => number;
9
+ /**
10
+ * 找到符合条件的节点
11
+ * @param tree tree data 数组
12
+ * @param predicate 对每个节点执行的函数, 如果返回true, 则返回该节点
13
+ * @param childrenKey 子节点key
14
+ * @returns 找到的节点
15
+ */
16
+ export declare const findNode: <T extends Record<string, any>>(tree: T[], predicate: (node: T) => boolean, childrenKey?: string) => T | null;
17
+ /**
18
+ * 根据子节点查找父节点
19
+ * @param tree
20
+ * @param child 子节点
21
+ * @param indentityKey 节点唯一id字段名称
22
+ * @param childrenKey 节点的子节点的字段名称
23
+ * @returns
24
+ */
25
+ export declare const findParent: <T extends Record<string, any>>(tree: T | undefined, child: T | undefined, indentityKey?: string, childrenKey?: string) => T | null;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * 计算指定层级的节点数量
3
+ * @param root tree data 对象
4
+ * @param depth 需要计算节点数量的层级
5
+ * @param childrenKey 子节点key
6
+ * @returns 节点数量
7
+ */
8
+ export const nodeCountAtDepth = (root, depth, childrenKey = 'children') => {
9
+ const depths = { 0: 1 };
10
+ (function recurTree(node, level) {
11
+ var _a;
12
+ level++;
13
+ const children = (_a = node[childrenKey]) !== null && _a !== void 0 ? _a : [];
14
+ if (depths[level] === undefined) {
15
+ depths[level] = children.length;
16
+ }
17
+ else {
18
+ depths[level] += children.length;
19
+ }
20
+ if (level + 1 > depth)
21
+ return;
22
+ for (let i = 0; i < children.length; i++) {
23
+ recurTree(children[i], level);
24
+ }
25
+ })(root, 0);
26
+ return depths[depth];
27
+ };
28
+ /**
29
+ * 找到符合条件的节点
30
+ * @param tree tree data 数组
31
+ * @param predicate 对每个节点执行的函数, 如果返回true, 则返回该节点
32
+ * @param childrenKey 子节点key
33
+ * @returns 找到的节点
34
+ */
35
+ export const findNode = (tree, predicate, childrenKey = 'children') => {
36
+ const list = [...tree];
37
+ for (const node of list) {
38
+ if (predicate(node))
39
+ return node;
40
+ Array.isArray(node[childrenKey]) && list.push(...node[childrenKey]);
41
+ }
42
+ return null;
43
+ };
44
+ /**
45
+ * 根据子节点查找父节点
46
+ * @param tree
47
+ * @param child 子节点
48
+ * @param indentityKey 节点唯一id字段名称
49
+ * @param childrenKey 节点的子节点的字段名称
50
+ * @returns
51
+ */
52
+ export const findParent = (tree, child, indentityKey = 'id', childrenKey = 'children') => {
53
+ if (tree === undefined || child === undefined) {
54
+ return null;
55
+ }
56
+ const children = tree[childrenKey];
57
+ if (Array.isArray(children)) {
58
+ const count = children.length;
59
+ for (let i = 0; i < count; i++) {
60
+ if (children[i][indentityKey] === child[indentityKey]) {
61
+ return tree;
62
+ }
63
+ const parent = findParent(children[i], child, indentityKey, childrenKey);
64
+ if (parent !== null) {
65
+ return parent;
66
+ }
67
+ }
68
+ }
69
+ return null;
70
+ };
package/dist/array.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export declare function moveMutable<T>(array: T[], fromIndex: number, toIndex: number): void;
2
2
  export declare function moveImmutable<T>(array: T[], fromIndex: number, toIndex: number): T[];
3
3
  export declare function moveToStart<T>(array: T[], predicate: (item: T) => boolean): T[];
4
+ export declare const moveMulti: <T extends unknown>(arr: T[], indexes: number[], start: number) => T[];
package/dist/array.js CHANGED
@@ -19,3 +19,15 @@ export function moveToStart(array, predicate) {
19
19
  moveMutable(newArray, index, 0);
20
20
  return newArray;
21
21
  }
22
+ const removeSymbol = Symbol('Placeholder for removed element');
23
+ export const moveMulti = (arr, indexes, start) => {
24
+ const cloned = arr.slice();
25
+ for (let i = 0; i < cloned.length; i++) {
26
+ if (indexes.includes(i)) {
27
+ cloned[i] = removeSymbol;
28
+ }
29
+ }
30
+ const els = arr.filter((__, i) => indexes.includes(i));
31
+ cloned.splice(start, 0, ...els);
32
+ return cloned.filter((v) => v !== removeSymbol);
33
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@d-matrix/utils",
3
3
  "sideEffects": false,
4
- "version": "1.22.0",
4
+ "version": "1.24.0",
5
5
  "description": "A dozen of utils for Front-End Development",
6
6
  "main": "dist/index.js",
7
7
  "scripts": {
package/readme.md CHANGED
@@ -354,9 +354,58 @@ type Output = WithRequired<Input, 'b'> // { a: number; b: string }
354
354
 
355
355
  ### algorithm
356
356
 
357
- - `moveMulti<T extends unknown>(arr: T[], indexes: number[], start: number): T[]`
357
+ - `function nodeCountAtDepth(root: Record<string, any>, depth: number, childrenKey: string = 'children'): number;`
358
358
 
359
- 移动多个元素到数组中指定的位置,用法,见[测试用例](tests/algorithm.cy.ts)
359
+ 计算指定层级的节点数量
360
+
361
+ ```ts
362
+ const root = {
363
+ id: 1,
364
+ children: [
365
+ { id: 2, children: [{ id: 21 }, { id: 22 }, { id: 23 }] },
366
+ { id: 3, children: [{ id: 31 }, { id: 32 }, { id: 33 }] },
367
+ ],
368
+ };
369
+ expect(tree.nodeCountAtDepth(root, 0)).to.be.equal(1);
370
+ expect(tree.nodeCountAtDepth(root, 1)).to.be.equal(2);
371
+ expect(tree.nodeCountAtDepth(root, 2)).to.be.equal(6);
372
+ ```
373
+
374
+ - `const findNode = <T extends Record<string, any>>(tree: T[], predicate: (node: T) => boolean, childrenKey = 'children'): T | null`
375
+
376
+ 找到符合条件的节点
377
+
378
+ ```ts
379
+ const root = {
380
+ id: 1,
381
+ children: [
382
+ { id: 2, children: [{ id: 21 }, { id: 22 }, { id: 23 }] },
383
+ { id: 3, children: [{ id: 31 }, { id: 32 }, { id: 33 }] },
384
+ ],
385
+ };
386
+ const actual = tree.findNode([root], (node) => node.id === 3);
387
+ expect(actual).to.be.deep.equal(root.children[1]);
388
+
389
+ const actual2 = tree.findNode([root], (node) => node.id === 33);
390
+ expect(actual2).to.be.deep.equal(root.children[1].children[2]);
391
+ ```
392
+
393
+ - `tree.findNode(tree, child, indentityKey, childrenKey)`
394
+
395
+ 根据子节点查找父节点
396
+
397
+ ```ts
398
+ const treeData = {
399
+ code: 1,
400
+ subs: [
401
+ { code: 2, subs: [{ code: 21 }, { code: 22 }, { code: 23 }] },
402
+ { code: 3, subs: [{ code: 31 }, { code: 32 }, { code: 33 }] },
403
+ ],
404
+ };
405
+
406
+ const actual = tree.findParent(treeData, treeData.subs[1].subs[2], 'code', 'subs');
407
+ expect(actual).to.be.deep.equal(treeData.subs[1]);
408
+ ```
360
409
 
361
410
  ### file
362
411
 
@@ -545,6 +594,10 @@ const newList = array.moveToStart(list, (item) => item.id === 4);
545
594
  // [{ id: 4 }, { id: 1 }, { id: 2 }, { id: 3 }, { id: 5 }]
546
595
  ```
547
596
 
597
+ - `moveMulti<T extends unknown>(arr: T[], indexes: number[], start: number): T[]`
598
+
599
+ 移动多个元素到数组中指定的位置,用法,见[测试用例](tests/algorithm.cy.ts)
600
+
548
601
  ## number
549
602
 
550
603
  - `randomInt(min: number, max: number): number`
@@ -572,13 +625,13 @@ deep merge Echarts配置,用法见[测试用例](./tests//echarts/echarts.cy.t
572
625
  运行全部组件测试
573
626
 
574
627
  ```bash
575
- npm run cy:run -- --component
628
+ npm run cy:component:all
576
629
  ```
577
630
 
578
631
  运行单个组件测试
579
632
 
580
633
  ```bash
581
- npm run cy:run -- --component --spec tests/date.cy.ts
634
+ npm run cy:component -- tests/date.cy.ts
582
635
  ```
583
636
 
584
637
  运行E2E测试
@@ -1 +0,0 @@
1
- export declare const moveMulti: <T extends unknown>(arr: T[], indexes: number[], start: number) => T[];
package/dist/algorithm.js DELETED
@@ -1,12 +0,0 @@
1
- const removeSymbol = Symbol('Placeholder for removed element');
2
- export const moveMulti = (arr, indexes, start) => {
3
- const cloned = arr.slice();
4
- for (let i = 0; i < cloned.length; i++) {
5
- if (indexes.includes(i)) {
6
- cloned[i] = removeSymbol;
7
- }
8
- }
9
- const els = arr.filter((__, i) => indexes.includes(i));
10
- cloned.splice(start, 0, ...els);
11
- return cloned.filter((v) => v !== removeSymbol);
12
- };