sculp-js 1.0.1 → 1.1.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/README.md +106 -9
- package/lib/cjs/array.js +87 -1
- package/lib/cjs/async.js +1 -1
- package/lib/cjs/clipboard.js +1 -1
- package/lib/cjs/cookie.js +1 -1
- package/lib/cjs/date.js +1 -1
- package/lib/cjs/dom.js +1 -1
- package/lib/cjs/download.js +1 -1
- package/lib/cjs/easing.js +1 -1
- package/lib/cjs/file.js +1 -1
- package/lib/cjs/func.js +1 -1
- package/lib/cjs/index.js +2 -1
- package/lib/cjs/number.js +1 -1
- package/lib/cjs/object.js +1 -1
- package/lib/cjs/path.js +1 -1
- package/lib/cjs/qs.js +1 -1
- package/lib/cjs/random.js +1 -1
- package/lib/cjs/string.js +1 -1
- package/lib/cjs/tooltip.js +1 -1
- package/lib/cjs/type.js +1 -1
- package/lib/cjs/unique.js +1 -1
- package/lib/cjs/url.js +1 -1
- package/lib/cjs/watermark.js +1 -1
- package/lib/es/array.js +87 -2
- package/lib/es/async.js +1 -1
- package/lib/es/clipboard.js +1 -1
- package/lib/es/cookie.js +1 -1
- package/lib/es/date.js +1 -1
- package/lib/es/dom.js +1 -1
- package/lib/es/download.js +1 -1
- package/lib/es/easing.js +1 -1
- package/lib/es/file.js +1 -1
- package/lib/es/func.js +1 -1
- package/lib/es/index.js +2 -2
- package/lib/es/number.js +1 -1
- package/lib/es/object.js +1 -1
- package/lib/es/path.js +1 -1
- package/lib/es/qs.js +1 -1
- package/lib/es/random.js +1 -1
- package/lib/es/string.js +1 -1
- package/lib/es/tooltip.js +1 -1
- package/lib/es/type.js +1 -1
- package/lib/es/unique.js +1 -1
- package/lib/es/url.js +1 -1
- package/lib/es/watermark.js +1 -1
- package/lib/index.d.ts +40 -1
- package/lib/umd/index.js +87 -1
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -1,24 +1,121 @@
|
|
|
1
1
|
[](https://github.com/chandq/sculp-js/actions/workflows/node.js.yml)
|
|
2
2
|
[](https://github.com/chandq/sculp-js)
|
|
3
|
-
[](https://nodejs.org/download/release/v16.0.0/)
|
|
4
4
|
[](https://nodejs.org/download/release/v12.0.0/)
|
|
5
5
|
[](https://github.com/chandq/sculp-js/blob/main/LICENSE.md)
|
|
6
6
|
[](https://npmcharts.com/compare/sculp-js?minimal=true)
|
|
7
|
+
[](https://codecov.io/gh/chandq/sculp-js)
|
|
7
8
|
|
|
8
9
|
# sculp-js
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
[API文档](https://chandq.github.io/sculp-js/)
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
> TS + Rollup, native implementation, without relying on any third-party libraries, outputs products of three module modes: ESM, CJS, and UMD
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- Type
|
|
18
|
+
|
|
19
|
+
- isString
|
|
20
|
+
- isBoolean
|
|
21
|
+
- isNumber
|
|
22
|
+
- isUndefined
|
|
23
|
+
- isNull
|
|
24
|
+
- isPrimitive
|
|
25
|
+
- isObject
|
|
26
|
+
- typeIs
|
|
13
27
|
|
|
14
28
|
- Array
|
|
15
29
|
|
|
16
30
|
- arrayLike 判断类数组
|
|
17
|
-
- arrayEach 可中断的数组遍历, 支持倒序
|
|
18
31
|
- arrayEachAsync 异步遍历数组,可中断,支持倒序
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
|
|
32
|
+
- forEachDeep 深度优先遍历函数, 支持continue、break,可定制id、children
|
|
33
|
+
- searchTreeById 在树中找到 id 为某个值的节点,并返回上游的所有父级节点
|
|
34
|
+
- buildTree 根据 id 与 parentId 从对象数组中构建对应的树
|
|
35
|
+
|
|
36
|
+
- Object
|
|
37
|
+
|
|
38
|
+
- isPlainObject
|
|
39
|
+
- objectHas
|
|
40
|
+
- objectAssign 合并
|
|
41
|
+
- objectEach
|
|
42
|
+
- objectEachAsync
|
|
43
|
+
- objectGet
|
|
44
|
+
|
|
45
|
+
- Number
|
|
46
|
+
|
|
47
|
+
- formatNumber
|
|
48
|
+
|
|
49
|
+
- String
|
|
50
|
+
|
|
51
|
+
- stringCamelCase
|
|
52
|
+
- stringKebabCase
|
|
53
|
+
- getStrWidthPx
|
|
54
|
+
|
|
55
|
+
- Unique
|
|
56
|
+
|
|
57
|
+
- uniqueString
|
|
58
|
+
- uniqueNumber
|
|
59
|
+
|
|
60
|
+
- Date
|
|
61
|
+
|
|
62
|
+
- formatDate
|
|
63
|
+
- dateToStart
|
|
64
|
+
- dateToEnd
|
|
65
|
+
- calculateDate
|
|
66
|
+
- calculateDateTime
|
|
67
|
+
|
|
68
|
+
- Download
|
|
69
|
+
|
|
70
|
+
- downloadURL
|
|
71
|
+
- downloadHref
|
|
72
|
+
- downloadBlob
|
|
73
|
+
- downloadData
|
|
74
|
+
|
|
75
|
+
- File
|
|
76
|
+
|
|
77
|
+
- chooseLocalFile
|
|
78
|
+
|
|
79
|
+
- Dom
|
|
80
|
+
|
|
81
|
+
- hasClass
|
|
82
|
+
- addClass
|
|
83
|
+
- removeClass
|
|
84
|
+
- setStyle
|
|
85
|
+
- getStyle
|
|
86
|
+
- getComputedCssVal
|
|
87
|
+
|
|
88
|
+
- Watermark
|
|
89
|
+
|
|
90
|
+
- genCanvasWM
|
|
91
|
+
|
|
92
|
+
- Clipboard
|
|
93
|
+
- copyText
|
|
94
|
+
|
|
95
|
+
## Install
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
npm i sculp-js
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Usage
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
import { forEachDeep } from 'sculp-js';
|
|
105
|
+
|
|
106
|
+
const tree = [
|
|
107
|
+
{ id: 1, name: 'row1' },
|
|
108
|
+
{
|
|
109
|
+
id: 2,
|
|
110
|
+
name: 'row2',
|
|
111
|
+
children: [{ id: 21, name: 'row2-1' }]
|
|
112
|
+
},
|
|
113
|
+
{ id: 3, name: 'row3' }
|
|
114
|
+
];
|
|
23
115
|
|
|
24
|
-
|
|
116
|
+
const arr = [];
|
|
117
|
+
forEachDeep(tree, ({ id, name }) => {
|
|
118
|
+
arr.push(name);
|
|
119
|
+
});
|
|
120
|
+
// arr will be: ['row1', 'row2', 'row2-1', 'row3'];
|
|
121
|
+
```
|
package/lib/cjs/array.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.0.
|
|
2
|
+
* sculp-js v1.0.1
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -198,11 +198,97 @@ function searchTreeById(tree, nodeId, config) {
|
|
|
198
198
|
};
|
|
199
199
|
return getIds(toFlatArray(tree));
|
|
200
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* 使用迭代函数转换数组
|
|
203
|
+
* @param {T} array
|
|
204
|
+
* @param {Function} callback 迭代函数
|
|
205
|
+
* @return {Array}
|
|
206
|
+
*/
|
|
207
|
+
function flatMap(array, callback) {
|
|
208
|
+
const result = [];
|
|
209
|
+
array.forEach((value, index) => {
|
|
210
|
+
result.push(...callback(value, index, array));
|
|
211
|
+
});
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* 根据 idProp 与 parentIdProp 从对象数组中构建对应的树
|
|
216
|
+
* 当 A[parentIdProp] === B[idProp] 时,对象A会被移动到对象B的children。
|
|
217
|
+
* 当一个对象的 parentIdProp 不与其他对象的 idProp 字段相等时,该对象被作为树的顶层节点
|
|
218
|
+
* @param {string} idProp 元素ID
|
|
219
|
+
* @param {string} parentIdProp 父元素ID
|
|
220
|
+
* @param {object[]} items 一维数组
|
|
221
|
+
* @returns {WithChildren<T>[]} 树
|
|
222
|
+
* @example
|
|
223
|
+
* const array = [
|
|
224
|
+
* { id: 'node-1', parent: 'root' },
|
|
225
|
+
* { id: 'node-2', parent: 'root' },
|
|
226
|
+
* { id: 'node-3', parent: 'node-2' },
|
|
227
|
+
* { id: 'node-4', parent: 'node-2' },
|
|
228
|
+
* { id: 'node-5', parent: 'node-4' },
|
|
229
|
+
* ]
|
|
230
|
+
* const tree = buildTree('id', 'parent', array)
|
|
231
|
+
* expect(tree).toEqual([
|
|
232
|
+
* { id: 'node-1', parent: 'root' },
|
|
233
|
+
* {
|
|
234
|
+
* id: 'node-2',
|
|
235
|
+
* parent: 'root',
|
|
236
|
+
* children: [
|
|
237
|
+
* { id: 'node-3', parent: 'node-2' },
|
|
238
|
+
* {
|
|
239
|
+
* id: 'node-4',
|
|
240
|
+
* parent: 'node-2',
|
|
241
|
+
* children: [{ id: 'node-5', parent: 'node-4' }],
|
|
242
|
+
* },
|
|
243
|
+
* ],
|
|
244
|
+
* },
|
|
245
|
+
* ])
|
|
246
|
+
*/
|
|
247
|
+
function buildTree(idProp, parentIdProp, items) {
|
|
248
|
+
const wrapperMap = new Map();
|
|
249
|
+
const ensure = (id) => {
|
|
250
|
+
if (wrapperMap.has(id)) {
|
|
251
|
+
return wrapperMap.get(id);
|
|
252
|
+
}
|
|
253
|
+
//@ts-ignore
|
|
254
|
+
const wrapper = { id, parent: null, item: null, children: [] };
|
|
255
|
+
wrapperMap.set(id, wrapper);
|
|
256
|
+
return wrapper;
|
|
257
|
+
};
|
|
258
|
+
for (const item of items) {
|
|
259
|
+
const parentWrapper = ensure(item[parentIdProp]);
|
|
260
|
+
const itemWrapper = ensure(item[idProp]);
|
|
261
|
+
//@ts-ignore
|
|
262
|
+
itemWrapper.parent = parentWrapper;
|
|
263
|
+
//@ts-ignore
|
|
264
|
+
parentWrapper.children.push(itemWrapper);
|
|
265
|
+
//@ts-ignore
|
|
266
|
+
itemWrapper.item = item;
|
|
267
|
+
}
|
|
268
|
+
const topLevelWrappers = flatMap(Array.from(wrapperMap.values()).filter(wrapper => wrapper.parent === null), wrapper => wrapper.children);
|
|
269
|
+
return unwrapRecursively(topLevelWrappers);
|
|
270
|
+
function unwrapRecursively(wrapperArray) {
|
|
271
|
+
const result = [];
|
|
272
|
+
for (const wrapper of wrapperArray) {
|
|
273
|
+
if (wrapper.children.length === 0) {
|
|
274
|
+
result.push(wrapper.item);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
result.push({
|
|
278
|
+
...wrapper.item,
|
|
279
|
+
children: unwrapRecursively(wrapper.children)
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
201
286
|
|
|
202
287
|
exports.arrayEach = arrayEach;
|
|
203
288
|
exports.arrayEachAsync = arrayEachAsync;
|
|
204
289
|
exports.arrayInsertBefore = arrayInsertBefore;
|
|
205
290
|
exports.arrayLike = arrayLike;
|
|
206
291
|
exports.arrayRemove = arrayRemove;
|
|
292
|
+
exports.buildTree = buildTree;
|
|
207
293
|
exports.forEachDeep = forEachDeep;
|
|
208
294
|
exports.searchTreeById = searchTreeById;
|
package/lib/cjs/async.js
CHANGED
package/lib/cjs/clipboard.js
CHANGED
package/lib/cjs/cookie.js
CHANGED
package/lib/cjs/date.js
CHANGED
package/lib/cjs/dom.js
CHANGED
package/lib/cjs/download.js
CHANGED
package/lib/cjs/easing.js
CHANGED
package/lib/cjs/file.js
CHANGED
package/lib/cjs/func.js
CHANGED
package/lib/cjs/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.0.
|
|
2
|
+
* sculp-js v1.0.1
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -34,6 +34,7 @@ exports.arrayEachAsync = array.arrayEachAsync;
|
|
|
34
34
|
exports.arrayInsertBefore = array.arrayInsertBefore;
|
|
35
35
|
exports.arrayLike = array.arrayLike;
|
|
36
36
|
exports.arrayRemove = array.arrayRemove;
|
|
37
|
+
exports.buildTree = array.buildTree;
|
|
37
38
|
exports.forEachDeep = array.forEachDeep;
|
|
38
39
|
exports.searchTreeById = array.searchTreeById;
|
|
39
40
|
exports.copyText = clipboard.copyText;
|
package/lib/cjs/number.js
CHANGED
package/lib/cjs/object.js
CHANGED
package/lib/cjs/path.js
CHANGED
package/lib/cjs/qs.js
CHANGED
package/lib/cjs/random.js
CHANGED
package/lib/cjs/string.js
CHANGED
package/lib/cjs/tooltip.js
CHANGED
package/lib/cjs/type.js
CHANGED
package/lib/cjs/unique.js
CHANGED
package/lib/cjs/url.js
CHANGED
package/lib/cjs/watermark.js
CHANGED
package/lib/es/array.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.0.
|
|
2
|
+
* sculp-js v1.0.1
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -196,5 +196,90 @@ function searchTreeById(tree, nodeId, config) {
|
|
|
196
196
|
};
|
|
197
197
|
return getIds(toFlatArray(tree));
|
|
198
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* 使用迭代函数转换数组
|
|
201
|
+
* @param {T} array
|
|
202
|
+
* @param {Function} callback 迭代函数
|
|
203
|
+
* @return {Array}
|
|
204
|
+
*/
|
|
205
|
+
function flatMap(array, callback) {
|
|
206
|
+
const result = [];
|
|
207
|
+
array.forEach((value, index) => {
|
|
208
|
+
result.push(...callback(value, index, array));
|
|
209
|
+
});
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* 根据 idProp 与 parentIdProp 从对象数组中构建对应的树
|
|
214
|
+
* 当 A[parentIdProp] === B[idProp] 时,对象A会被移动到对象B的children。
|
|
215
|
+
* 当一个对象的 parentIdProp 不与其他对象的 idProp 字段相等时,该对象被作为树的顶层节点
|
|
216
|
+
* @param {string} idProp 元素ID
|
|
217
|
+
* @param {string} parentIdProp 父元素ID
|
|
218
|
+
* @param {object[]} items 一维数组
|
|
219
|
+
* @returns {WithChildren<T>[]} 树
|
|
220
|
+
* @example
|
|
221
|
+
* const array = [
|
|
222
|
+
* { id: 'node-1', parent: 'root' },
|
|
223
|
+
* { id: 'node-2', parent: 'root' },
|
|
224
|
+
* { id: 'node-3', parent: 'node-2' },
|
|
225
|
+
* { id: 'node-4', parent: 'node-2' },
|
|
226
|
+
* { id: 'node-5', parent: 'node-4' },
|
|
227
|
+
* ]
|
|
228
|
+
* const tree = buildTree('id', 'parent', array)
|
|
229
|
+
* expect(tree).toEqual([
|
|
230
|
+
* { id: 'node-1', parent: 'root' },
|
|
231
|
+
* {
|
|
232
|
+
* id: 'node-2',
|
|
233
|
+
* parent: 'root',
|
|
234
|
+
* children: [
|
|
235
|
+
* { id: 'node-3', parent: 'node-2' },
|
|
236
|
+
* {
|
|
237
|
+
* id: 'node-4',
|
|
238
|
+
* parent: 'node-2',
|
|
239
|
+
* children: [{ id: 'node-5', parent: 'node-4' }],
|
|
240
|
+
* },
|
|
241
|
+
* ],
|
|
242
|
+
* },
|
|
243
|
+
* ])
|
|
244
|
+
*/
|
|
245
|
+
function buildTree(idProp, parentIdProp, items) {
|
|
246
|
+
const wrapperMap = new Map();
|
|
247
|
+
const ensure = (id) => {
|
|
248
|
+
if (wrapperMap.has(id)) {
|
|
249
|
+
return wrapperMap.get(id);
|
|
250
|
+
}
|
|
251
|
+
//@ts-ignore
|
|
252
|
+
const wrapper = { id, parent: null, item: null, children: [] };
|
|
253
|
+
wrapperMap.set(id, wrapper);
|
|
254
|
+
return wrapper;
|
|
255
|
+
};
|
|
256
|
+
for (const item of items) {
|
|
257
|
+
const parentWrapper = ensure(item[parentIdProp]);
|
|
258
|
+
const itemWrapper = ensure(item[idProp]);
|
|
259
|
+
//@ts-ignore
|
|
260
|
+
itemWrapper.parent = parentWrapper;
|
|
261
|
+
//@ts-ignore
|
|
262
|
+
parentWrapper.children.push(itemWrapper);
|
|
263
|
+
//@ts-ignore
|
|
264
|
+
itemWrapper.item = item;
|
|
265
|
+
}
|
|
266
|
+
const topLevelWrappers = flatMap(Array.from(wrapperMap.values()).filter(wrapper => wrapper.parent === null), wrapper => wrapper.children);
|
|
267
|
+
return unwrapRecursively(topLevelWrappers);
|
|
268
|
+
function unwrapRecursively(wrapperArray) {
|
|
269
|
+
const result = [];
|
|
270
|
+
for (const wrapper of wrapperArray) {
|
|
271
|
+
if (wrapper.children.length === 0) {
|
|
272
|
+
result.push(wrapper.item);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
result.push({
|
|
276
|
+
...wrapper.item,
|
|
277
|
+
children: unwrapRecursively(wrapper.children)
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return result;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
199
284
|
|
|
200
|
-
export { arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, forEachDeep, searchTreeById };
|
|
285
|
+
export { arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, buildTree, forEachDeep, searchTreeById };
|
package/lib/es/async.js
CHANGED
package/lib/es/clipboard.js
CHANGED
package/lib/es/cookie.js
CHANGED
package/lib/es/date.js
CHANGED
package/lib/es/dom.js
CHANGED
package/lib/es/download.js
CHANGED
package/lib/es/easing.js
CHANGED
package/lib/es/file.js
CHANGED
package/lib/es/func.js
CHANGED
package/lib/es/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.0.
|
|
2
|
+
* sculp-js v1.0.1
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
export { arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, forEachDeep, searchTreeById } from './array.js';
|
|
7
|
+
export { arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, buildTree, forEachDeep, searchTreeById } from './array.js';
|
|
8
8
|
export { copyText } from './clipboard.js';
|
|
9
9
|
export { cookieDel, cookieGet, cookieSet } from './cookie.js';
|
|
10
10
|
export { calculateDate, calculateDateTime, dateParse, dateToEnd, dateToStart, formatDate, isValidDate } from './date.js';
|
package/lib/es/number.js
CHANGED
package/lib/es/object.js
CHANGED
package/lib/es/path.js
CHANGED
package/lib/es/qs.js
CHANGED
package/lib/es/random.js
CHANGED
package/lib/es/string.js
CHANGED
package/lib/es/tooltip.js
CHANGED
package/lib/es/type.js
CHANGED
package/lib/es/unique.js
CHANGED
package/lib/es/url.js
CHANGED
package/lib/es/watermark.js
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -97,6 +97,45 @@ interface ITreeConf {
|
|
|
97
97
|
* @returns {[IdLike[], ITreeItem<V>[]]} - 由parentId...childId, parentObject-childObject组成的二维数组
|
|
98
98
|
*/
|
|
99
99
|
declare function searchTreeById<V>(tree: ArrayLike<V>, nodeId: IdLike, config?: ITreeConf): [IdLike[], ArrayLike<V>[]];
|
|
100
|
+
type WithChildren<T> = T & {
|
|
101
|
+
children?: WithChildren<T>[];
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* 根据 idProp 与 parentIdProp 从对象数组中构建对应的树
|
|
105
|
+
* 当 A[parentIdProp] === B[idProp] 时,对象A会被移动到对象B的children。
|
|
106
|
+
* 当一个对象的 parentIdProp 不与其他对象的 idProp 字段相等时,该对象被作为树的顶层节点
|
|
107
|
+
* @param {string} idProp 元素ID
|
|
108
|
+
* @param {string} parentIdProp 父元素ID
|
|
109
|
+
* @param {object[]} items 一维数组
|
|
110
|
+
* @returns {WithChildren<T>[]} 树
|
|
111
|
+
* @example
|
|
112
|
+
* const array = [
|
|
113
|
+
* { id: 'node-1', parent: 'root' },
|
|
114
|
+
* { id: 'node-2', parent: 'root' },
|
|
115
|
+
* { id: 'node-3', parent: 'node-2' },
|
|
116
|
+
* { id: 'node-4', parent: 'node-2' },
|
|
117
|
+
* { id: 'node-5', parent: 'node-4' },
|
|
118
|
+
* ]
|
|
119
|
+
* const tree = buildTree('id', 'parent', array)
|
|
120
|
+
* expect(tree).toEqual([
|
|
121
|
+
* { id: 'node-1', parent: 'root' },
|
|
122
|
+
* {
|
|
123
|
+
* id: 'node-2',
|
|
124
|
+
* parent: 'root',
|
|
125
|
+
* children: [
|
|
126
|
+
* { id: 'node-3', parent: 'node-2' },
|
|
127
|
+
* {
|
|
128
|
+
* id: 'node-4',
|
|
129
|
+
* parent: 'node-2',
|
|
130
|
+
* children: [{ id: 'node-5', parent: 'node-4' }],
|
|
131
|
+
* },
|
|
132
|
+
* ],
|
|
133
|
+
* },
|
|
134
|
+
* ])
|
|
135
|
+
*/
|
|
136
|
+
declare function buildTree<ID extends string, PID extends string, T extends {
|
|
137
|
+
[key in ID | PID]: string;
|
|
138
|
+
}>(idProp: ID, parentIdProp: PID, items: T[]): WithChildren<T>[];
|
|
100
139
|
|
|
101
140
|
/**
|
|
102
141
|
* 复制文本
|
|
@@ -706,4 +745,4 @@ declare const tooltipEvent: {
|
|
|
706
745
|
handleMouseLeave: typeof handleMouseLeave;
|
|
707
746
|
};
|
|
708
747
|
|
|
709
|
-
export { type AnyArray, type AnyFunc, type AnyObject, type ArrayElements, type DateObj, type DateValue, type DebounceFunc, type FileType, HEX_POOL, type ICanvasWM, type ITreeConf, type IdLike, type LooseParamValue, type LooseParams, type ObjectAssignItem, type OnceFunc, type Params, type PartialDeep, type RandomString, type ReadyCallback, type Replacer, STRING_ARABIC_NUMERALS, STRING_LOWERCASE_ALPHA, STRING_POOL, STRING_UPPERCASE_ALPHA, type SetStyle, type SmoothScrollOptions, type Style, type ThrottleFunc, UNIQUE_NUMBER_SAFE_LENGTH, type UniqueString, type Url, addClass, arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, asyncMap, calculateDate, calculateDateTime, chooseLocalFile, cloneDeep, cookieDel, cookieGet, cookieSet, copyText, dateParse, dateToEnd, dateToStart, debounce, downloadBlob, downloadData, downloadHref, downloadURL, forEachDeep, formatDate, formatNumber, genCanvasWM, getComputedCssVal, getGlobal, getStrWidthPx, getStyle, hasClass, isArray, isBigInt, isBoolean, isDate, isDomReady, isError, isFunction, isNaN, isNull, isNumber, isObject, isPlainObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, isValidDate, numberAbbr, numberToHex, objectAssign, objectEach, objectEachAsync, objectFill, objectGet, objectHas, objectMap, objectAssign as objectMerge, objectOmit, objectPick, onDomReady, once, pathJoin, pathNormalize, qsParse, qsStringify, randomNumber, randomString, randomUuid, removeClass, searchTreeById, setGlobal, setStyle, smoothScroll, stringAssign, stringCamelCase, stringEscapeHtml, stringFill, stringFormat, stringKebabCase, throttle, tooltipEvent, typeIs, uniqueNumber, uniqueString, urlDelParams, urlParse, urlSetParams, urlStringify, wait };
|
|
748
|
+
export { type AnyArray, type AnyFunc, type AnyObject, type ArrayElements, type DateObj, type DateValue, type DebounceFunc, type FileType, HEX_POOL, type ICanvasWM, type ITreeConf, type IdLike, type LooseParamValue, type LooseParams, type ObjectAssignItem, type OnceFunc, type Params, type PartialDeep, type RandomString, type ReadyCallback, type Replacer, STRING_ARABIC_NUMERALS, STRING_LOWERCASE_ALPHA, STRING_POOL, STRING_UPPERCASE_ALPHA, type SetStyle, type SmoothScrollOptions, type Style, type ThrottleFunc, UNIQUE_NUMBER_SAFE_LENGTH, type UniqueString, type Url, type WithChildren, addClass, arrayEach, arrayEachAsync, arrayInsertBefore, arrayLike, arrayRemove, asyncMap, buildTree, calculateDate, calculateDateTime, chooseLocalFile, cloneDeep, cookieDel, cookieGet, cookieSet, copyText, dateParse, dateToEnd, dateToStart, debounce, downloadBlob, downloadData, downloadHref, downloadURL, forEachDeep, formatDate, formatNumber, genCanvasWM, getComputedCssVal, getGlobal, getStrWidthPx, getStyle, hasClass, isArray, isBigInt, isBoolean, isDate, isDomReady, isError, isFunction, isNaN, isNull, isNumber, isObject, isPlainObject, isPrimitive, isRegExp, isString, isSymbol, isUndefined, isValidDate, numberAbbr, numberToHex, objectAssign, objectEach, objectEachAsync, objectFill, objectGet, objectHas, objectMap, objectAssign as objectMerge, objectOmit, objectPick, onDomReady, once, pathJoin, pathNormalize, qsParse, qsStringify, randomNumber, randomString, randomUuid, removeClass, searchTreeById, setGlobal, setStyle, smoothScroll, stringAssign, stringCamelCase, stringEscapeHtml, stringFill, stringFormat, stringKebabCase, throttle, tooltipEvent, typeIs, uniqueNumber, uniqueString, urlDelParams, urlParse, urlSetParams, urlStringify, wait };
|
package/lib/umd/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.0.
|
|
2
|
+
* sculp-js v1.0.1
|
|
3
3
|
* (c) 2023-2023 chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -450,6 +450,91 @@
|
|
|
450
450
|
};
|
|
451
451
|
return getIds(toFlatArray(tree));
|
|
452
452
|
}
|
|
453
|
+
/**
|
|
454
|
+
* 使用迭代函数转换数组
|
|
455
|
+
* @param {T} array
|
|
456
|
+
* @param {Function} callback 迭代函数
|
|
457
|
+
* @return {Array}
|
|
458
|
+
*/
|
|
459
|
+
function flatMap(array, callback) {
|
|
460
|
+
const result = [];
|
|
461
|
+
array.forEach((value, index) => {
|
|
462
|
+
result.push(...callback(value, index, array));
|
|
463
|
+
});
|
|
464
|
+
return result;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* 根据 idProp 与 parentIdProp 从对象数组中构建对应的树
|
|
468
|
+
* 当 A[parentIdProp] === B[idProp] 时,对象A会被移动到对象B的children。
|
|
469
|
+
* 当一个对象的 parentIdProp 不与其他对象的 idProp 字段相等时,该对象被作为树的顶层节点
|
|
470
|
+
* @param {string} idProp 元素ID
|
|
471
|
+
* @param {string} parentIdProp 父元素ID
|
|
472
|
+
* @param {object[]} items 一维数组
|
|
473
|
+
* @returns {WithChildren<T>[]} 树
|
|
474
|
+
* @example
|
|
475
|
+
* const array = [
|
|
476
|
+
* { id: 'node-1', parent: 'root' },
|
|
477
|
+
* { id: 'node-2', parent: 'root' },
|
|
478
|
+
* { id: 'node-3', parent: 'node-2' },
|
|
479
|
+
* { id: 'node-4', parent: 'node-2' },
|
|
480
|
+
* { id: 'node-5', parent: 'node-4' },
|
|
481
|
+
* ]
|
|
482
|
+
* const tree = buildTree('id', 'parent', array)
|
|
483
|
+
* expect(tree).toEqual([
|
|
484
|
+
* { id: 'node-1', parent: 'root' },
|
|
485
|
+
* {
|
|
486
|
+
* id: 'node-2',
|
|
487
|
+
* parent: 'root',
|
|
488
|
+
* children: [
|
|
489
|
+
* { id: 'node-3', parent: 'node-2' },
|
|
490
|
+
* {
|
|
491
|
+
* id: 'node-4',
|
|
492
|
+
* parent: 'node-2',
|
|
493
|
+
* children: [{ id: 'node-5', parent: 'node-4' }],
|
|
494
|
+
* },
|
|
495
|
+
* ],
|
|
496
|
+
* },
|
|
497
|
+
* ])
|
|
498
|
+
*/
|
|
499
|
+
function buildTree(idProp, parentIdProp, items) {
|
|
500
|
+
const wrapperMap = new Map();
|
|
501
|
+
const ensure = (id) => {
|
|
502
|
+
if (wrapperMap.has(id)) {
|
|
503
|
+
return wrapperMap.get(id);
|
|
504
|
+
}
|
|
505
|
+
//@ts-ignore
|
|
506
|
+
const wrapper = { id, parent: null, item: null, children: [] };
|
|
507
|
+
wrapperMap.set(id, wrapper);
|
|
508
|
+
return wrapper;
|
|
509
|
+
};
|
|
510
|
+
for (const item of items) {
|
|
511
|
+
const parentWrapper = ensure(item[parentIdProp]);
|
|
512
|
+
const itemWrapper = ensure(item[idProp]);
|
|
513
|
+
//@ts-ignore
|
|
514
|
+
itemWrapper.parent = parentWrapper;
|
|
515
|
+
//@ts-ignore
|
|
516
|
+
parentWrapper.children.push(itemWrapper);
|
|
517
|
+
//@ts-ignore
|
|
518
|
+
itemWrapper.item = item;
|
|
519
|
+
}
|
|
520
|
+
const topLevelWrappers = flatMap(Array.from(wrapperMap.values()).filter(wrapper => wrapper.parent === null), wrapper => wrapper.children);
|
|
521
|
+
return unwrapRecursively(topLevelWrappers);
|
|
522
|
+
function unwrapRecursively(wrapperArray) {
|
|
523
|
+
const result = [];
|
|
524
|
+
for (const wrapper of wrapperArray) {
|
|
525
|
+
if (wrapper.children.length === 0) {
|
|
526
|
+
result.push(wrapper.item);
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
result.push({
|
|
530
|
+
...wrapper.item,
|
|
531
|
+
children: unwrapRecursively(wrapper.children)
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return result;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
453
538
|
|
|
454
539
|
// @ref https://cubic-bezier.com/
|
|
455
540
|
const easingDefines = {
|
|
@@ -1925,6 +2010,7 @@
|
|
|
1925
2010
|
exports.arrayLike = arrayLike;
|
|
1926
2011
|
exports.arrayRemove = arrayRemove;
|
|
1927
2012
|
exports.asyncMap = asyncMap;
|
|
2013
|
+
exports.buildTree = buildTree;
|
|
1928
2014
|
exports.calculateDate = calculateDate;
|
|
1929
2015
|
exports.calculateDateTime = calculateDateTime;
|
|
1930
2016
|
exports.chooseLocalFile = chooseLocalFile;
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sculp-js",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"packageManager": "npm@8.19.2",
|
|
5
5
|
"description": "js工具库",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"prepare": "husky install",
|
|
8
|
-
"build": "
|
|
8
|
+
"build": "rollup --bundleConfigAsCjs --config rollup.config.js",
|
|
9
9
|
"build:terser": "node scripts/build.js",
|
|
10
10
|
"test:unit": "jest",
|
|
11
11
|
"test": "jest --coverage",
|
|
12
|
+
"coveralls": "jest --coverage --coverageReporters=text-lcov | coveralls",
|
|
12
13
|
"lint": "eslint ./src --ext .vue,.js,jsx,.ts,tsx",
|
|
13
14
|
"lint:fix": "eslint --fix ./src --ext .vue,.js,jsx,.ts,tsx",
|
|
14
15
|
"prettier": "prettier -c --write \"**/*.{vue,ts,js,jsx,css,less,scss,json}\"",
|
|
@@ -35,11 +36,11 @@
|
|
|
35
36
|
"lib"
|
|
36
37
|
],
|
|
37
38
|
"keywords": [
|
|
38
|
-
"
|
|
39
|
-
"utils"
|
|
39
|
+
"typescript",
|
|
40
|
+
"js-utils"
|
|
40
41
|
],
|
|
41
42
|
"engines": {
|
|
42
|
-
"node": ">=
|
|
43
|
+
"node": ">=16"
|
|
43
44
|
},
|
|
44
45
|
"repository": "git@github.com:chandq/sculp-js.git",
|
|
45
46
|
"dependencies": {
|