@d-matrix/utils 1.21.1 → 1.23.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.
- package/dist/algorithm/index.d.ts +1 -0
- package/dist/algorithm/index.js +1 -0
- package/dist/algorithm/tree.d.ts +16 -0
- package/dist/algorithm/tree.js +43 -0
- package/dist/array.d.ts +1 -0
- package/dist/array.js +12 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/number.d.ts +2 -0
- package/dist/number.js +4 -0
- package/dist/object.d.ts +7 -0
- package/dist/object.js +7 -0
- package/dist/react/types.d.ts +6 -0
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
- package/readme.md +69 -4
- package/dist/algorithm.d.ts +0 -1
- package/dist/algorithm.js +0 -12
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as tree from './tree';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as tree from './tree';
|
|
@@ -0,0 +1,16 @@
|
|
|
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;
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
};
|
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/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/number.d.ts
ADDED
package/dist/number.js
ADDED
package/dist/object.d.ts
CHANGED
|
@@ -4,3 +4,10 @@ export declare const ZeroValues: ({} | null | undefined)[];
|
|
|
4
4
|
* 默认的零值是:undefined、null、空字符串, NaN, [], {}
|
|
5
5
|
*/
|
|
6
6
|
export declare const removeZeroValueKeys: <T extends Record<string, any>>(obj: T, zeroValues?: ({} | null | undefined)[]) => T;
|
|
7
|
+
/**
|
|
8
|
+
* 返回tuple,而不是string[]
|
|
9
|
+
* const obj = { a: 1, b: '2' };
|
|
10
|
+
* Object.keys(obj) => string[]
|
|
11
|
+
* typedKeys({ a: 1, b: '2' }) => ('a' | 'b')[]
|
|
12
|
+
*/
|
|
13
|
+
export declare const typedKeys: <T extends object>(obj: T) => (keyof T)[];
|
package/dist/object.js
CHANGED
|
@@ -19,3 +19,10 @@ export const removeZeroValueKeys = (obj, zeroValues = ZeroValues) => {
|
|
|
19
19
|
}
|
|
20
20
|
return r;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* 返回tuple,而不是string[]
|
|
24
|
+
* const obj = { a: 1, b: '2' };
|
|
25
|
+
* Object.keys(obj) => string[]
|
|
26
|
+
* typedKeys({ a: 1, b: '2' }) => ('a' | 'b')[]
|
|
27
|
+
*/
|
|
28
|
+
export const typedKeys = Object.keys;
|
package/dist/react/types.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
import type { ForwardRefExoticComponent, NamedExoticComponent, ComponentPropsWithoutRef, ComponentPropsWithRef, RefAttributes, ElementType } from 'react';
|
|
2
2
|
export declare type ComponentRef<T extends ElementType> = T extends NamedExoticComponent<ComponentPropsWithoutRef<T> & RefAttributes<infer Method>> ? Method : ComponentPropsWithRef<T> extends RefAttributes<infer Method> ? Method : never;
|
|
3
3
|
export declare type InferRef<T> = T extends ForwardRefExoticComponent<infer Ref> ? Ref extends React.RefAttributes<infer RefElement> ? RefElement : never : never;
|
|
4
|
+
declare type ReactRefComponent<Props extends {
|
|
5
|
+
ref?: React.Ref<any> | string;
|
|
6
|
+
}> = (props: Props) => React.ReactNode;
|
|
7
|
+
declare type ExtractRefAttributesRef<T> = T extends React.RefAttributes<infer P> ? P : never;
|
|
8
|
+
export declare type GetRef<T extends ReactRefComponent<any> | React.Component<any>> = T extends React.Component<any> ? T : T extends React.ComponentType<infer P> ? ExtractRefAttributesRef<P> : never;
|
|
9
|
+
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -15,3 +15,7 @@ export declare type NonFunctionPropertyNames<T> = {
|
|
|
15
15
|
}[keyof T];
|
|
16
16
|
/** 获取对象中key的值,返回由这些值组成的union type */
|
|
17
17
|
export declare type ValueOf<T> = T[keyof T];
|
|
18
|
+
/** 指定属性变为必选 */
|
|
19
|
+
export declare type WithRequired<T, K extends keyof T> = T & {
|
|
20
|
+
[P in K]-?: T[P];
|
|
21
|
+
};
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -20,6 +20,7 @@ A dozen of utils for Front-End Development
|
|
|
20
20
|
- [decimal](#decimal)
|
|
21
21
|
- [object](#object)
|
|
22
22
|
- [array](#array)
|
|
23
|
+
- [number](#number)
|
|
23
24
|
- [echarts](#echarts)
|
|
24
25
|
|
|
25
26
|
### clipboard
|
|
@@ -339,11 +340,55 @@ const map = {
|
|
|
339
340
|
type T0 = ValueOf<typeof map>; // '0m' | '1m' | '2m' | '3m' | '4m' | '5m' | '6m'
|
|
340
341
|
```
|
|
341
342
|
|
|
343
|
+
- `WithRequired<T, K extends keyof T>`
|
|
344
|
+
|
|
345
|
+
指定属性变为必选
|
|
346
|
+
|
|
347
|
+
```ts
|
|
348
|
+
type Input = {
|
|
349
|
+
a: number;
|
|
350
|
+
b?: string;
|
|
351
|
+
};
|
|
352
|
+
type Output = WithRequired<Input, 'b'> // { a: number; b: string }
|
|
353
|
+
```
|
|
354
|
+
|
|
342
355
|
### algorithm
|
|
343
356
|
|
|
344
|
-
- `
|
|
357
|
+
- `function nodeCountAtDepth(root: Record<string, any>, depth: number, childrenKey: string = 'children'): number;`
|
|
345
358
|
|
|
346
|
-
|
|
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
|
+
```
|
|
347
392
|
|
|
348
393
|
### file
|
|
349
394
|
|
|
@@ -485,6 +530,16 @@ removeZeroValueKeys({ a: '', b: 'abc', c: undefined, d: null, e: NaN, f: -1, g:
|
|
|
485
530
|
// { b: 'abc', f: -1 }
|
|
486
531
|
```
|
|
487
532
|
|
|
533
|
+
- `typedKeys(obj: T): Array<keyof T>`
|
|
534
|
+
|
|
535
|
+
返回`tuple`,而不是`string[]`
|
|
536
|
+
|
|
537
|
+
```ts
|
|
538
|
+
const obj = { a: 1, b: '2' };
|
|
539
|
+
Object.keys(obj) // string[]
|
|
540
|
+
object.typedKeys({ a: 1, b: '2' }) // ('a' | 'b')[]
|
|
541
|
+
```
|
|
542
|
+
|
|
488
543
|
## array
|
|
489
544
|
|
|
490
545
|
- `moveImmutable<T>(array: T[], fromIndex: number, toIndex: number): T[]`
|
|
@@ -522,6 +577,16 @@ const newList = array.moveToStart(list, (item) => item.id === 4);
|
|
|
522
577
|
// [{ id: 4 }, { id: 1 }, { id: 2 }, { id: 3 }, { id: 5 }]
|
|
523
578
|
```
|
|
524
579
|
|
|
580
|
+
- `moveMulti<T extends unknown>(arr: T[], indexes: number[], start: number): T[]`
|
|
581
|
+
|
|
582
|
+
移动多个元素到数组中指定的位置,用法,见[测试用例](tests/algorithm.cy.ts)
|
|
583
|
+
|
|
584
|
+
## number
|
|
585
|
+
|
|
586
|
+
- `randomInt(min: number, max: number): number`
|
|
587
|
+
|
|
588
|
+
返回`min`, `max`之间的随机整数
|
|
589
|
+
|
|
525
590
|
## echarts
|
|
526
591
|
|
|
527
592
|
- `mergeOption(defaults: EChartsOption, overrides: EChartsOption, option?: deepmerge.Options): EChartsOption`
|
|
@@ -543,13 +608,13 @@ deep merge Echarts配置,用法见[测试用例](./tests//echarts/echarts.cy.t
|
|
|
543
608
|
运行全部组件测试
|
|
544
609
|
|
|
545
610
|
```bash
|
|
546
|
-
npm run cy:
|
|
611
|
+
npm run cy:component:all
|
|
547
612
|
```
|
|
548
613
|
|
|
549
614
|
运行单个组件测试
|
|
550
615
|
|
|
551
616
|
```bash
|
|
552
|
-
npm run cy:
|
|
617
|
+
npm run cy:component -- tests/date.cy.ts
|
|
553
618
|
```
|
|
554
619
|
|
|
555
620
|
运行E2E测试
|
package/dist/algorithm.d.ts
DELETED
|
@@ -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
|
-
};
|