onchain-utility 0.0.15 → 0.0.17

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/Hooks.js CHANGED
@@ -87,6 +87,7 @@ var useUpdate = function () {
87
87
  */
88
88
  /* eslint-disable @typescript-eslint/no-explicit-any */
89
89
 
90
+ /** 是否是Moment对象(_表示为内部函数谨慎使用) */
90
91
  function _isMoment(obj) {
91
92
  return obj != null && typeof obj === 'object' &&
92
93
  // 检查内部标志
@@ -96,6 +97,13 @@ function _isMoment(obj) {
96
97
  // 检查内部属性
97
98
  '_d' in obj && '_i' in obj;
98
99
  }
100
+
101
+ /**
102
+ * 创建一个可解构的对象,该对象同时具有原始对象的属性和数组的迭代器,使其可以使用对象和数组两种解构方式
103
+ * @param obj - 需要转换的对象
104
+ * @param arr - 用于提供迭代器的数组
105
+ * @returns 一个结合了对象属性和数组迭代器的新对象
106
+ */
99
107
  function makeDestructurable(obj, arr) {
100
108
  if (typeof Symbol !== 'undefined') {
101
109
  const clone = {
@@ -118,6 +126,8 @@ function makeDestructurable(obj, arr) {
118
126
  return Object.assign([...arr], obj);
119
127
  }
120
128
  }
129
+
130
+ /** 创建对象枚举,可以避免两个相同枚举缺不相等 */
121
131
  function createEnumObject(o) {
122
132
  return o;
123
133
  }
@@ -128,9 +138,13 @@ function toRawType(value) {
128
138
  // 从字符串中提取“RawType”,如“[object RawType]”
129
139
  return toTypeString(value).slice(8, -1);
130
140
  }
141
+
142
+ /** 判断对象是否有某个属性 */
131
143
  function hasOwnProperty(data, key) {
132
144
  return data && Object.prototype.hasOwnProperty.call(data, key);
133
145
  }
146
+
147
+ /** 是否是整型key */
134
148
  function isIntegerKey(key) {
135
149
  return typeof key === 'string' && key !== 'NaN' && key[0] !== '-' && '' + parseInt(key, 10) === key;
136
150
  }
package/dist/Hooks.mjs CHANGED
@@ -85,6 +85,7 @@ var useUpdate = function () {
85
85
  */
86
86
  /* eslint-disable @typescript-eslint/no-explicit-any */
87
87
 
88
+ /** 是否是Moment对象(_表示为内部函数谨慎使用) */
88
89
  function _isMoment(obj) {
89
90
  return obj != null && typeof obj === 'object' &&
90
91
  // 检查内部标志
@@ -94,6 +95,13 @@ function _isMoment(obj) {
94
95
  // 检查内部属性
95
96
  '_d' in obj && '_i' in obj;
96
97
  }
98
+
99
+ /**
100
+ * 创建一个可解构的对象,该对象同时具有原始对象的属性和数组的迭代器,使其可以使用对象和数组两种解构方式
101
+ * @param obj - 需要转换的对象
102
+ * @param arr - 用于提供迭代器的数组
103
+ * @returns 一个结合了对象属性和数组迭代器的新对象
104
+ */
97
105
  function makeDestructurable(obj, arr) {
98
106
  if (typeof Symbol !== 'undefined') {
99
107
  const clone = {
@@ -116,6 +124,8 @@ function makeDestructurable(obj, arr) {
116
124
  return Object.assign([...arr], obj);
117
125
  }
118
126
  }
127
+
128
+ /** 创建对象枚举,可以避免两个相同枚举缺不相等 */
119
129
  function createEnumObject(o) {
120
130
  return o;
121
131
  }
@@ -126,9 +136,13 @@ function toRawType(value) {
126
136
  // 从字符串中提取“RawType”,如“[object RawType]”
127
137
  return toTypeString(value).slice(8, -1);
128
138
  }
139
+
140
+ /** 判断对象是否有某个属性 */
129
141
  function hasOwnProperty(data, key) {
130
142
  return data && Object.prototype.hasOwnProperty.call(data, key);
131
143
  }
144
+
145
+ /** 是否是整型key */
132
146
  function isIntegerKey(key) {
133
147
  return typeof key === 'string' && key !== 'NaN' && key[0] !== '-' && '' + parseInt(key, 10) === key;
134
148
  }
@@ -19,6 +19,7 @@ var react = require('react');
19
19
  */
20
20
  /* eslint-disable @typescript-eslint/no-explicit-any */
21
21
 
22
+ /** 是否是Moment对象(_表示为内部函数谨慎使用) */
22
23
  function _isMoment(obj) {
23
24
  return obj != null && typeof obj === 'object' &&
24
25
  // 检查内部标志
@@ -28,6 +29,13 @@ function _isMoment(obj) {
28
29
  // 检查内部属性
29
30
  '_d' in obj && '_i' in obj;
30
31
  }
32
+
33
+ /**
34
+ * 创建一个可解构的对象,该对象同时具有原始对象的属性和数组的迭代器,使其可以使用对象和数组两种解构方式
35
+ * @param obj - 需要转换的对象
36
+ * @param arr - 用于提供迭代器的数组
37
+ * @returns 一个结合了对象属性和数组迭代器的新对象
38
+ */
31
39
  function makeDestructurable(obj, arr) {
32
40
  if (typeof Symbol !== 'undefined') {
33
41
  const clone = {
@@ -50,6 +58,8 @@ function makeDestructurable(obj, arr) {
50
58
  return Object.assign([...arr], obj);
51
59
  }
52
60
  }
61
+
62
+ /** 创建对象枚举,可以避免两个相同枚举缺不相等 */
53
63
  function createEnumObject(o) {
54
64
  return o;
55
65
  }
@@ -60,15 +70,68 @@ function toRawType(value) {
60
70
  // 从字符串中提取“RawType”,如“[object RawType]”
61
71
  return toTypeString(value).slice(8, -1);
62
72
  }
73
+ function isString(value) {
74
+ return toRawType(value) === 'String';
75
+ }
76
+ function isNumber(value) {
77
+ return toRawType(value) === 'Number';
78
+ }
79
+
80
+ /** 判断值是否为NaN */
81
+ function isNaN(value) {
82
+ return Number.isNaN(value);
83
+ }
84
+ function isBoolean(value) {
85
+ return toRawType(value) === 'Boolean';
86
+ }
87
+ function isUndefined(value) {
88
+ return toRawType(value) === 'Undefined';
89
+ }
90
+ function isNull(value) {
91
+ return toRawType(value) === 'Null';
92
+ }
93
+ function isNil(value) {
94
+ return isNull(value) || isUndefined(value);
95
+ }
96
+
97
+ /**
98
+ * 判断是否是 `null` 或 `undefined`
99
+ * @example
100
+ * _.isNil(null);
101
+ * // => true
102
+ *
103
+ * _.isNil(void 0);
104
+ * // => true
105
+ *
106
+ * _.isNil(NaN);
107
+ * // => false
108
+ */
109
+ function isObject(value) {
110
+ return toRawType(value) === 'Object';
111
+ }
112
+ function isArray(value) {
113
+ return toRawType(value) === 'Array';
114
+ }
115
+ function isFunction(value) {
116
+ return toRawType(value) === 'Function';
117
+ }
118
+
119
+ /** 判断对象是否有某个属性 */
63
120
  function hasOwnProperty(data, key) {
64
121
  return data && Object.prototype.hasOwnProperty.call(data, key);
65
122
  }
123
+
124
+ /** 是否是整型key */
66
125
  function isIntegerKey(key) {
67
126
  return typeof key === 'string' && key !== 'NaN' && key[0] !== '-' && '' + parseInt(key, 10) === key;
68
127
  }
128
+
129
+ /** 是否是空对象 */
69
130
  function isEmptyObject(obj) {
70
131
  return obj ? !Object.keys(obj).length : true;
71
132
  }
133
+
134
+ /** 生成 innerHTML */
72
135
  function getHTMLTagString(params) {
73
136
  const attrsString = Object.entries(params.attributes || {}).map(([key, value]) => {
74
137
  return ` ${key}="${value}"`;
@@ -1082,6 +1145,46 @@ function levelTransformTree({
1082
1145
  });
1083
1146
  return root.children;
1084
1147
  }
1148
+
1149
+ /** 获取全部子孙节点 */
1150
+ function getTreeDescendants({
1151
+ data,
1152
+ key,
1153
+ signKey = 'id',
1154
+ childrenKey = 'children'
1155
+ }) {
1156
+ const {
1157
+ self
1158
+ } = getTreeRelation({
1159
+ childrenKey,
1160
+ data,
1161
+ lookup(item, index) {
1162
+ return item[signKey] === key;
1163
+ }
1164
+ });
1165
+ return arrayAttributeFlat({
1166
+ childrenKey,
1167
+ data: self?.[childrenKey] || []
1168
+ });
1169
+ }
1170
+
1171
+ /** 获取全部祖先节点 */
1172
+ function getTreeAncestors({
1173
+ data,
1174
+ key,
1175
+ signKey = 'id',
1176
+ childrenKey = 'children'
1177
+ }) {
1178
+ return getTreeRelation({
1179
+ childrenKey,
1180
+ data,
1181
+ lookup(item, index) {
1182
+ return item[signKey] === key;
1183
+ }
1184
+ }).stack;
1185
+ }
1186
+
1187
+ /** 删除树节点 */
1085
1188
  function deleteTreeNodes({
1086
1189
  data,
1087
1190
  selectedKeys,
@@ -1235,6 +1338,51 @@ function getSiblings({
1235
1338
  return keys;
1236
1339
  }
1237
1340
 
1341
+ /**
1342
+ * @description 是否跨层
1343
+ * @date 2022-11-21 20:03:52
1344
+ * @export
1345
+ * @param {string[]} hierarchy 选中任务的层级
1346
+ * @returns {*}
1347
+ */
1348
+ function getSelectedNodeHierarchyStatus({
1349
+ data,
1350
+ selectedKeys,
1351
+ signKey = 'id',
1352
+ childrenKey = 'children'
1353
+ }) {
1354
+ const relations = selectedKeys.map(key => getTreeRelation({
1355
+ childrenKey,
1356
+ data,
1357
+ lookup(item, index) {
1358
+ return item[signKey] === key;
1359
+ }
1360
+ }));
1361
+ // 深度集合
1362
+ const deepSet = new Set(relations.map(rel => rel.stack.length));
1363
+ const isDifferentDepths = deepSet.size > 1;
1364
+ if (isDifferentDepths) {
1365
+ return {
1366
+ isDifferentDepths,
1367
+ isIncludedParent: relations.sort((a, b) => {
1368
+ return b.stack.length - a.stack.length;
1369
+ }).some(item => {
1370
+ const ancestors = getTreeAncestors({
1371
+ childrenKey,
1372
+ data,
1373
+ key: item.self[signKey],
1374
+ signKey
1375
+ }).map(item => item[signKey]);
1376
+ return selectedKeys.some(id => ancestors.includes(id));
1377
+ })
1378
+ };
1379
+ }
1380
+ return {
1381
+ isDifferentDepths,
1382
+ isIncludedParent: false
1383
+ };
1384
+ }
1385
+
1238
1386
  /**
1239
1387
  * @description 合并相邻的选中数据
1240
1388
  * @date 2023-02-15 16:11:16
@@ -1353,9 +1501,10 @@ function generatedAcrossHierarchySort({
1353
1501
  function optimizeStructure({
1354
1502
  data,
1355
1503
  childrenKey = 'children',
1356
- signKey = 'id'
1504
+ signKey = 'id',
1505
+ isSupportMultipleRoot = false
1357
1506
  }) {
1358
- if (data.length > 1) {
1507
+ if (data.length > 1 || isSupportMultipleRoot) {
1359
1508
  return [{
1360
1509
  [childrenKey]: data,
1361
1510
  isCustom: true,
@@ -1460,6 +1609,7 @@ async function upgrade({
1460
1609
  data,
1461
1610
  signKey = 'id',
1462
1611
  isFollow,
1612
+ isSupportMultipleRoot = false,
1463
1613
  onStopFollow,
1464
1614
  onFilterFollow,
1465
1615
  onUpgrade,
@@ -1471,6 +1621,7 @@ async function upgrade({
1471
1621
  data = optimizeStructure({
1472
1622
  childrenKey,
1473
1623
  data,
1624
+ isSupportMultipleRoot,
1474
1625
  signKey
1475
1626
  });
1476
1627
  const layers = mergeAdjacent({
@@ -1556,7 +1707,12 @@ async function upgrade({
1556
1707
  });
1557
1708
  const insert = (data, index) => {
1558
1709
  data.splice(index, 0, ...selected);
1559
- onUpgraded?.(selected);
1710
+ onUpgraded?.(selected, getExpandedState({
1711
+ childrenKey,
1712
+ originalParent: parent,
1713
+ parent: grandpa,
1714
+ signKey
1715
+ }));
1560
1716
  };
1561
1717
  const insertIndex = getInsertIdx({
1562
1718
  leader: start,
@@ -1618,7 +1774,12 @@ async function downgrade({
1618
1774
  const newChildren = [...(before[childrenKey] || []), ...children];
1619
1775
  if (children.length) {
1620
1776
  before[childrenKey] = [...newChildren];
1621
- onDowngraded?.(children);
1777
+ onDowngraded?.(children, getExpandedState({
1778
+ childrenKey,
1779
+ originalParent: parent,
1780
+ parent: before,
1781
+ signKey
1782
+ }));
1622
1783
  }
1623
1784
  }
1624
1785
  }
@@ -1671,6 +1832,18 @@ function treeSearch({
1671
1832
  }
1672
1833
  }).filter(row => !!row);
1673
1834
  }
1835
+ function getExpandedState({
1836
+ originalParent,
1837
+ parent,
1838
+ signKey = 'id',
1839
+ childrenKey = 'children'
1840
+ }) {
1841
+ const isRemove = !originalParent[childrenKey]?.length;
1842
+ return {
1843
+ add: parent[signKey],
1844
+ remove: isRemove ? originalParent[signKey] : null
1845
+ };
1846
+ }
1674
1847
 
1675
1848
  exports._isMoment = _isMoment;
1676
1849
  exports.arrayAttributeFlat = arrayAttributeFlat;
@@ -1689,13 +1862,26 @@ exports.generatedAcrossHierarchySort = generatedAcrossHierarchySort;
1689
1862
  exports.getBase64Regular = getBase64Regular;
1690
1863
  exports.getHTMLTagString = getHTMLTagString;
1691
1864
  exports.getI18nText = getI18nText;
1865
+ exports.getSelectedNodeHierarchyStatus = getSelectedNodeHierarchyStatus;
1692
1866
  exports.getSiblings = getSiblings;
1867
+ exports.getTreeAncestors = getTreeAncestors;
1868
+ exports.getTreeDescendants = getTreeDescendants;
1693
1869
  exports.getTreeRelation = getTreeRelation;
1694
1870
  exports.hasOwnProperty = hasOwnProperty;
1695
1871
  exports.initTranslateI18nFn = initTranslateI18nFn;
1696
1872
  exports.insert = insert;
1873
+ exports.isArray = isArray;
1874
+ exports.isBoolean = isBoolean;
1697
1875
  exports.isEmptyObject = isEmptyObject;
1876
+ exports.isFunction = isFunction;
1698
1877
  exports.isIntegerKey = isIntegerKey;
1878
+ exports.isNaN = isNaN;
1879
+ exports.isNil = isNil;
1880
+ exports.isNull = isNull;
1881
+ exports.isNumber = isNumber;
1882
+ exports.isObject = isObject;
1883
+ exports.isString = isString;
1884
+ exports.isUndefined = isUndefined;
1699
1885
  exports.levelTransformTree = levelTransformTree;
1700
1886
  exports.makeDestructurable = makeDestructurable;
1701
1887
  exports.mergeAdjacent = mergeAdjacent;
@@ -17,6 +17,7 @@ import { useRef, useState, useCallback, useLayoutEffect } from 'react';
17
17
  */
18
18
  /* eslint-disable @typescript-eslint/no-explicit-any */
19
19
 
20
+ /** 是否是Moment对象(_表示为内部函数谨慎使用) */
20
21
  function _isMoment(obj) {
21
22
  return obj != null && typeof obj === 'object' &&
22
23
  // 检查内部标志
@@ -26,6 +27,13 @@ function _isMoment(obj) {
26
27
  // 检查内部属性
27
28
  '_d' in obj && '_i' in obj;
28
29
  }
30
+
31
+ /**
32
+ * 创建一个可解构的对象,该对象同时具有原始对象的属性和数组的迭代器,使其可以使用对象和数组两种解构方式
33
+ * @param obj - 需要转换的对象
34
+ * @param arr - 用于提供迭代器的数组
35
+ * @returns 一个结合了对象属性和数组迭代器的新对象
36
+ */
29
37
  function makeDestructurable(obj, arr) {
30
38
  if (typeof Symbol !== 'undefined') {
31
39
  const clone = {
@@ -48,6 +56,8 @@ function makeDestructurable(obj, arr) {
48
56
  return Object.assign([...arr], obj);
49
57
  }
50
58
  }
59
+
60
+ /** 创建对象枚举,可以避免两个相同枚举缺不相等 */
51
61
  function createEnumObject(o) {
52
62
  return o;
53
63
  }
@@ -58,15 +68,68 @@ function toRawType(value) {
58
68
  // 从字符串中提取“RawType”,如“[object RawType]”
59
69
  return toTypeString(value).slice(8, -1);
60
70
  }
71
+ function isString(value) {
72
+ return toRawType(value) === 'String';
73
+ }
74
+ function isNumber(value) {
75
+ return toRawType(value) === 'Number';
76
+ }
77
+
78
+ /** 判断值是否为NaN */
79
+ function isNaN(value) {
80
+ return Number.isNaN(value);
81
+ }
82
+ function isBoolean(value) {
83
+ return toRawType(value) === 'Boolean';
84
+ }
85
+ function isUndefined(value) {
86
+ return toRawType(value) === 'Undefined';
87
+ }
88
+ function isNull(value) {
89
+ return toRawType(value) === 'Null';
90
+ }
91
+ function isNil(value) {
92
+ return isNull(value) || isUndefined(value);
93
+ }
94
+
95
+ /**
96
+ * 判断是否是 `null` 或 `undefined`
97
+ * @example
98
+ * _.isNil(null);
99
+ * // => true
100
+ *
101
+ * _.isNil(void 0);
102
+ * // => true
103
+ *
104
+ * _.isNil(NaN);
105
+ * // => false
106
+ */
107
+ function isObject(value) {
108
+ return toRawType(value) === 'Object';
109
+ }
110
+ function isArray(value) {
111
+ return toRawType(value) === 'Array';
112
+ }
113
+ function isFunction(value) {
114
+ return toRawType(value) === 'Function';
115
+ }
116
+
117
+ /** 判断对象是否有某个属性 */
61
118
  function hasOwnProperty(data, key) {
62
119
  return data && Object.prototype.hasOwnProperty.call(data, key);
63
120
  }
121
+
122
+ /** 是否是整型key */
64
123
  function isIntegerKey(key) {
65
124
  return typeof key === 'string' && key !== 'NaN' && key[0] !== '-' && '' + parseInt(key, 10) === key;
66
125
  }
126
+
127
+ /** 是否是空对象 */
67
128
  function isEmptyObject(obj) {
68
129
  return obj ? !Object.keys(obj).length : true;
69
130
  }
131
+
132
+ /** 生成 innerHTML */
70
133
  function getHTMLTagString(params) {
71
134
  const attrsString = Object.entries(params.attributes || {}).map(([key, value]) => {
72
135
  return ` ${key}="${value}"`;
@@ -1080,6 +1143,46 @@ function levelTransformTree({
1080
1143
  });
1081
1144
  return root.children;
1082
1145
  }
1146
+
1147
+ /** 获取全部子孙节点 */
1148
+ function getTreeDescendants({
1149
+ data,
1150
+ key,
1151
+ signKey = 'id',
1152
+ childrenKey = 'children'
1153
+ }) {
1154
+ const {
1155
+ self
1156
+ } = getTreeRelation({
1157
+ childrenKey,
1158
+ data,
1159
+ lookup(item, index) {
1160
+ return item[signKey] === key;
1161
+ }
1162
+ });
1163
+ return arrayAttributeFlat({
1164
+ childrenKey,
1165
+ data: self?.[childrenKey] || []
1166
+ });
1167
+ }
1168
+
1169
+ /** 获取全部祖先节点 */
1170
+ function getTreeAncestors({
1171
+ data,
1172
+ key,
1173
+ signKey = 'id',
1174
+ childrenKey = 'children'
1175
+ }) {
1176
+ return getTreeRelation({
1177
+ childrenKey,
1178
+ data,
1179
+ lookup(item, index) {
1180
+ return item[signKey] === key;
1181
+ }
1182
+ }).stack;
1183
+ }
1184
+
1185
+ /** 删除树节点 */
1083
1186
  function deleteTreeNodes({
1084
1187
  data,
1085
1188
  selectedKeys,
@@ -1233,6 +1336,51 @@ function getSiblings({
1233
1336
  return keys;
1234
1337
  }
1235
1338
 
1339
+ /**
1340
+ * @description 是否跨层
1341
+ * @date 2022-11-21 20:03:52
1342
+ * @export
1343
+ * @param {string[]} hierarchy 选中任务的层级
1344
+ * @returns {*}
1345
+ */
1346
+ function getSelectedNodeHierarchyStatus({
1347
+ data,
1348
+ selectedKeys,
1349
+ signKey = 'id',
1350
+ childrenKey = 'children'
1351
+ }) {
1352
+ const relations = selectedKeys.map(key => getTreeRelation({
1353
+ childrenKey,
1354
+ data,
1355
+ lookup(item, index) {
1356
+ return item[signKey] === key;
1357
+ }
1358
+ }));
1359
+ // 深度集合
1360
+ const deepSet = new Set(relations.map(rel => rel.stack.length));
1361
+ const isDifferentDepths = deepSet.size > 1;
1362
+ if (isDifferentDepths) {
1363
+ return {
1364
+ isDifferentDepths,
1365
+ isIncludedParent: relations.sort((a, b) => {
1366
+ return b.stack.length - a.stack.length;
1367
+ }).some(item => {
1368
+ const ancestors = getTreeAncestors({
1369
+ childrenKey,
1370
+ data,
1371
+ key: item.self[signKey],
1372
+ signKey
1373
+ }).map(item => item[signKey]);
1374
+ return selectedKeys.some(id => ancestors.includes(id));
1375
+ })
1376
+ };
1377
+ }
1378
+ return {
1379
+ isDifferentDepths,
1380
+ isIncludedParent: false
1381
+ };
1382
+ }
1383
+
1236
1384
  /**
1237
1385
  * @description 合并相邻的选中数据
1238
1386
  * @date 2023-02-15 16:11:16
@@ -1351,9 +1499,10 @@ function generatedAcrossHierarchySort({
1351
1499
  function optimizeStructure({
1352
1500
  data,
1353
1501
  childrenKey = 'children',
1354
- signKey = 'id'
1502
+ signKey = 'id',
1503
+ isSupportMultipleRoot = false
1355
1504
  }) {
1356
- if (data.length > 1) {
1505
+ if (data.length > 1 || isSupportMultipleRoot) {
1357
1506
  return [{
1358
1507
  [childrenKey]: data,
1359
1508
  isCustom: true,
@@ -1458,6 +1607,7 @@ async function upgrade({
1458
1607
  data,
1459
1608
  signKey = 'id',
1460
1609
  isFollow,
1610
+ isSupportMultipleRoot = false,
1461
1611
  onStopFollow,
1462
1612
  onFilterFollow,
1463
1613
  onUpgrade,
@@ -1469,6 +1619,7 @@ async function upgrade({
1469
1619
  data = optimizeStructure({
1470
1620
  childrenKey,
1471
1621
  data,
1622
+ isSupportMultipleRoot,
1472
1623
  signKey
1473
1624
  });
1474
1625
  const layers = mergeAdjacent({
@@ -1554,7 +1705,12 @@ async function upgrade({
1554
1705
  });
1555
1706
  const insert = (data, index) => {
1556
1707
  data.splice(index, 0, ...selected);
1557
- onUpgraded?.(selected);
1708
+ onUpgraded?.(selected, getExpandedState({
1709
+ childrenKey,
1710
+ originalParent: parent,
1711
+ parent: grandpa,
1712
+ signKey
1713
+ }));
1558
1714
  };
1559
1715
  const insertIndex = getInsertIdx({
1560
1716
  leader: start,
@@ -1616,7 +1772,12 @@ async function downgrade({
1616
1772
  const newChildren = [...(before[childrenKey] || []), ...children];
1617
1773
  if (children.length) {
1618
1774
  before[childrenKey] = [...newChildren];
1619
- onDowngraded?.(children);
1775
+ onDowngraded?.(children, getExpandedState({
1776
+ childrenKey,
1777
+ originalParent: parent,
1778
+ parent: before,
1779
+ signKey
1780
+ }));
1620
1781
  }
1621
1782
  }
1622
1783
  }
@@ -1669,5 +1830,17 @@ function treeSearch({
1669
1830
  }
1670
1831
  }).filter(row => !!row);
1671
1832
  }
1833
+ function getExpandedState({
1834
+ originalParent,
1835
+ parent,
1836
+ signKey = 'id',
1837
+ childrenKey = 'children'
1838
+ }) {
1839
+ const isRemove = !originalParent[childrenKey]?.length;
1840
+ return {
1841
+ add: parent[signKey],
1842
+ remove: isRemove ? originalParent[signKey] : null
1843
+ };
1844
+ }
1672
1845
 
1673
- export { _isMoment, arrayAttributeFlat, asyncDfs, base64ToFile, base64ToMimeType, baseTemplate, bfs, createEnumObject, deleteTreeNodes, dfs, downgrade, fromBase64UTF8, generateSecureUUID, generatedAcrossHierarchySort, getBase64Regular, getHTMLTagString, getI18nText, getSiblings, getTreeRelation, hasOwnProperty, initTranslateI18nFn, insert, isEmptyObject, isIntegerKey, levelTransformTree, makeDestructurable, mergeAdjacent, movUp, move, moveDown, t, toBase64UTF8, toRawType, toTypeString, translateI18n, treeSearch, upgrade, useReactive, useShallowReactive, useStore };
1846
+ export { _isMoment, arrayAttributeFlat, asyncDfs, base64ToFile, base64ToMimeType, baseTemplate, bfs, createEnumObject, deleteTreeNodes, dfs, downgrade, fromBase64UTF8, generateSecureUUID, generatedAcrossHierarchySort, getBase64Regular, getHTMLTagString, getI18nText, getSelectedNodeHierarchyStatus, getSiblings, getTreeAncestors, getTreeDescendants, getTreeRelation, hasOwnProperty, initTranslateI18nFn, insert, isArray, isBoolean, isEmptyObject, isFunction, isIntegerKey, isNaN, isNil, isNull, isNumber, isObject, isString, isUndefined, levelTransformTree, makeDestructurable, mergeAdjacent, movUp, move, moveDown, t, toBase64UTF8, toRawType, toTypeString, translateI18n, treeSearch, upgrade, useReactive, useShallowReactive, useStore };
package/dist/Tree.js CHANGED
@@ -61,6 +61,46 @@ function levelTransformTree({
61
61
  });
62
62
  return root.children;
63
63
  }
64
+
65
+ /** 获取全部子孙节点 */
66
+ function getTreeDescendants({
67
+ data,
68
+ key,
69
+ signKey = 'id',
70
+ childrenKey = 'children'
71
+ }) {
72
+ const {
73
+ self
74
+ } = getTreeRelation({
75
+ childrenKey,
76
+ data,
77
+ lookup(item, index) {
78
+ return item[signKey] === key;
79
+ }
80
+ });
81
+ return arrayAttributeFlat({
82
+ childrenKey,
83
+ data: self?.[childrenKey] || []
84
+ });
85
+ }
86
+
87
+ /** 获取全部祖先节点 */
88
+ function getTreeAncestors({
89
+ data,
90
+ key,
91
+ signKey = 'id',
92
+ childrenKey = 'children'
93
+ }) {
94
+ return getTreeRelation({
95
+ childrenKey,
96
+ data,
97
+ lookup(item, index) {
98
+ return item[signKey] === key;
99
+ }
100
+ }).stack;
101
+ }
102
+
103
+ /** 删除树节点 */
64
104
  function deleteTreeNodes({
65
105
  data,
66
106
  selectedKeys,
@@ -214,6 +254,51 @@ function getSiblings({
214
254
  return keys;
215
255
  }
216
256
 
257
+ /**
258
+ * @description 是否跨层
259
+ * @date 2022-11-21 20:03:52
260
+ * @export
261
+ * @param {string[]} hierarchy 选中任务的层级
262
+ * @returns {*}
263
+ */
264
+ function getSelectedNodeHierarchyStatus({
265
+ data,
266
+ selectedKeys,
267
+ signKey = 'id',
268
+ childrenKey = 'children'
269
+ }) {
270
+ const relations = selectedKeys.map(key => getTreeRelation({
271
+ childrenKey,
272
+ data,
273
+ lookup(item, index) {
274
+ return item[signKey] === key;
275
+ }
276
+ }));
277
+ // 深度集合
278
+ const deepSet = new Set(relations.map(rel => rel.stack.length));
279
+ const isDifferentDepths = deepSet.size > 1;
280
+ if (isDifferentDepths) {
281
+ return {
282
+ isDifferentDepths,
283
+ isIncludedParent: relations.sort((a, b) => {
284
+ return b.stack.length - a.stack.length;
285
+ }).some(item => {
286
+ const ancestors = getTreeAncestors({
287
+ childrenKey,
288
+ data,
289
+ key: item.self[signKey],
290
+ signKey
291
+ }).map(item => item[signKey]);
292
+ return selectedKeys.some(id => ancestors.includes(id));
293
+ })
294
+ };
295
+ }
296
+ return {
297
+ isDifferentDepths,
298
+ isIncludedParent: false
299
+ };
300
+ }
301
+
217
302
  /**
218
303
  * @description 合并相邻的选中数据
219
304
  * @date 2023-02-15 16:11:16
@@ -332,9 +417,10 @@ function generatedAcrossHierarchySort({
332
417
  function optimizeStructure({
333
418
  data,
334
419
  childrenKey = 'children',
335
- signKey = 'id'
420
+ signKey = 'id',
421
+ isSupportMultipleRoot = false
336
422
  }) {
337
- if (data.length > 1) {
423
+ if (data.length > 1 || isSupportMultipleRoot) {
338
424
  return [{
339
425
  [childrenKey]: data,
340
426
  isCustom: true,
@@ -439,6 +525,7 @@ async function upgrade({
439
525
  data,
440
526
  signKey = 'id',
441
527
  isFollow,
528
+ isSupportMultipleRoot = false,
442
529
  onStopFollow,
443
530
  onFilterFollow,
444
531
  onUpgrade,
@@ -450,6 +537,7 @@ async function upgrade({
450
537
  data = optimizeStructure({
451
538
  childrenKey,
452
539
  data,
540
+ isSupportMultipleRoot,
453
541
  signKey
454
542
  });
455
543
  const layers = mergeAdjacent({
@@ -535,7 +623,12 @@ async function upgrade({
535
623
  });
536
624
  const insert = (data, index) => {
537
625
  data.splice(index, 0, ...selected);
538
- onUpgraded?.(selected);
626
+ onUpgraded?.(selected, getExpandedState({
627
+ childrenKey,
628
+ originalParent: parent,
629
+ parent: grandpa,
630
+ signKey
631
+ }));
539
632
  };
540
633
  const insertIndex = getInsertIdx({
541
634
  leader: start,
@@ -597,7 +690,12 @@ async function downgrade({
597
690
  const newChildren = [...(before[childrenKey] || []), ...children];
598
691
  if (children.length) {
599
692
  before[childrenKey] = [...newChildren];
600
- onDowngraded?.(children);
693
+ onDowngraded?.(children, getExpandedState({
694
+ childrenKey,
695
+ originalParent: parent,
696
+ parent: before,
697
+ signKey
698
+ }));
601
699
  }
602
700
  }
603
701
  }
@@ -650,12 +748,27 @@ function treeSearch({
650
748
  }
651
749
  }).filter(row => !!row);
652
750
  }
751
+ function getExpandedState({
752
+ originalParent,
753
+ parent,
754
+ signKey = 'id',
755
+ childrenKey = 'children'
756
+ }) {
757
+ const isRemove = !originalParent[childrenKey]?.length;
758
+ return {
759
+ add: parent[signKey],
760
+ remove: isRemove ? originalParent[signKey] : null
761
+ };
762
+ }
653
763
 
654
764
  exports.arrayAttributeFlat = arrayAttributeFlat;
655
765
  exports.deleteTreeNodes = deleteTreeNodes;
656
766
  exports.downgrade = downgrade;
657
767
  exports.generatedAcrossHierarchySort = generatedAcrossHierarchySort;
768
+ exports.getSelectedNodeHierarchyStatus = getSelectedNodeHierarchyStatus;
658
769
  exports.getSiblings = getSiblings;
770
+ exports.getTreeAncestors = getTreeAncestors;
771
+ exports.getTreeDescendants = getTreeDescendants;
659
772
  exports.getTreeRelation = getTreeRelation;
660
773
  exports.insert = insert;
661
774
  exports.levelTransformTree = levelTransformTree;
package/dist/Tree.mjs CHANGED
@@ -59,6 +59,46 @@ function levelTransformTree({
59
59
  });
60
60
  return root.children;
61
61
  }
62
+
63
+ /** 获取全部子孙节点 */
64
+ function getTreeDescendants({
65
+ data,
66
+ key,
67
+ signKey = 'id',
68
+ childrenKey = 'children'
69
+ }) {
70
+ const {
71
+ self
72
+ } = getTreeRelation({
73
+ childrenKey,
74
+ data,
75
+ lookup(item, index) {
76
+ return item[signKey] === key;
77
+ }
78
+ });
79
+ return arrayAttributeFlat({
80
+ childrenKey,
81
+ data: self?.[childrenKey] || []
82
+ });
83
+ }
84
+
85
+ /** 获取全部祖先节点 */
86
+ function getTreeAncestors({
87
+ data,
88
+ key,
89
+ signKey = 'id',
90
+ childrenKey = 'children'
91
+ }) {
92
+ return getTreeRelation({
93
+ childrenKey,
94
+ data,
95
+ lookup(item, index) {
96
+ return item[signKey] === key;
97
+ }
98
+ }).stack;
99
+ }
100
+
101
+ /** 删除树节点 */
62
102
  function deleteTreeNodes({
63
103
  data,
64
104
  selectedKeys,
@@ -212,6 +252,51 @@ function getSiblings({
212
252
  return keys;
213
253
  }
214
254
 
255
+ /**
256
+ * @description 是否跨层
257
+ * @date 2022-11-21 20:03:52
258
+ * @export
259
+ * @param {string[]} hierarchy 选中任务的层级
260
+ * @returns {*}
261
+ */
262
+ function getSelectedNodeHierarchyStatus({
263
+ data,
264
+ selectedKeys,
265
+ signKey = 'id',
266
+ childrenKey = 'children'
267
+ }) {
268
+ const relations = selectedKeys.map(key => getTreeRelation({
269
+ childrenKey,
270
+ data,
271
+ lookup(item, index) {
272
+ return item[signKey] === key;
273
+ }
274
+ }));
275
+ // 深度集合
276
+ const deepSet = new Set(relations.map(rel => rel.stack.length));
277
+ const isDifferentDepths = deepSet.size > 1;
278
+ if (isDifferentDepths) {
279
+ return {
280
+ isDifferentDepths,
281
+ isIncludedParent: relations.sort((a, b) => {
282
+ return b.stack.length - a.stack.length;
283
+ }).some(item => {
284
+ const ancestors = getTreeAncestors({
285
+ childrenKey,
286
+ data,
287
+ key: item.self[signKey],
288
+ signKey
289
+ }).map(item => item[signKey]);
290
+ return selectedKeys.some(id => ancestors.includes(id));
291
+ })
292
+ };
293
+ }
294
+ return {
295
+ isDifferentDepths,
296
+ isIncludedParent: false
297
+ };
298
+ }
299
+
215
300
  /**
216
301
  * @description 合并相邻的选中数据
217
302
  * @date 2023-02-15 16:11:16
@@ -330,9 +415,10 @@ function generatedAcrossHierarchySort({
330
415
  function optimizeStructure({
331
416
  data,
332
417
  childrenKey = 'children',
333
- signKey = 'id'
418
+ signKey = 'id',
419
+ isSupportMultipleRoot = false
334
420
  }) {
335
- if (data.length > 1) {
421
+ if (data.length > 1 || isSupportMultipleRoot) {
336
422
  return [{
337
423
  [childrenKey]: data,
338
424
  isCustom: true,
@@ -437,6 +523,7 @@ async function upgrade({
437
523
  data,
438
524
  signKey = 'id',
439
525
  isFollow,
526
+ isSupportMultipleRoot = false,
440
527
  onStopFollow,
441
528
  onFilterFollow,
442
529
  onUpgrade,
@@ -448,6 +535,7 @@ async function upgrade({
448
535
  data = optimizeStructure({
449
536
  childrenKey,
450
537
  data,
538
+ isSupportMultipleRoot,
451
539
  signKey
452
540
  });
453
541
  const layers = mergeAdjacent({
@@ -533,7 +621,12 @@ async function upgrade({
533
621
  });
534
622
  const insert = (data, index) => {
535
623
  data.splice(index, 0, ...selected);
536
- onUpgraded?.(selected);
624
+ onUpgraded?.(selected, getExpandedState({
625
+ childrenKey,
626
+ originalParent: parent,
627
+ parent: grandpa,
628
+ signKey
629
+ }));
537
630
  };
538
631
  const insertIndex = getInsertIdx({
539
632
  leader: start,
@@ -595,7 +688,12 @@ async function downgrade({
595
688
  const newChildren = [...(before[childrenKey] || []), ...children];
596
689
  if (children.length) {
597
690
  before[childrenKey] = [...newChildren];
598
- onDowngraded?.(children);
691
+ onDowngraded?.(children, getExpandedState({
692
+ childrenKey,
693
+ originalParent: parent,
694
+ parent: before,
695
+ signKey
696
+ }));
599
697
  }
600
698
  }
601
699
  }
@@ -648,5 +746,17 @@ function treeSearch({
648
746
  }
649
747
  }).filter(row => !!row);
650
748
  }
749
+ function getExpandedState({
750
+ originalParent,
751
+ parent,
752
+ signKey = 'id',
753
+ childrenKey = 'children'
754
+ }) {
755
+ const isRemove = !originalParent[childrenKey]?.length;
756
+ return {
757
+ add: parent[signKey],
758
+ remove: isRemove ? originalParent[signKey] : null
759
+ };
760
+ }
651
761
 
652
- export { arrayAttributeFlat, deleteTreeNodes, downgrade, generatedAcrossHierarchySort, getSiblings, getTreeRelation, insert, levelTransformTree, mergeAdjacent, movUp, move, moveDown, treeSearch, upgrade };
762
+ export { arrayAttributeFlat, deleteTreeNodes, downgrade, generatedAcrossHierarchySort, getSelectedNodeHierarchyStatus, getSiblings, getTreeAncestors, getTreeDescendants, getTreeRelation, insert, levelTransformTree, mergeAdjacent, movUp, move, moveDown, treeSearch, upgrade };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "onchain-utility",
3
3
  "description": "This package contains misc utilities for onchain.",
4
4
  "license": "MIT",
5
- "version": "0.0.15",
5
+ "version": "0.0.17",
6
6
  "files": [
7
7
  "dist",
8
8
  "src"
package/src/Tree/index.ts CHANGED
@@ -79,9 +79,44 @@ export function levelTransformTree<T extends Item>({
79
79
  }
80
80
  });
81
81
 
82
- return root.children;
82
+ type _Item = T & {children: _Item[]};
83
+ return root.children as _Item[];
83
84
  }
84
85
 
86
+ /** 获取全部子孙节点 */
87
+ export function getTreeDescendants<T extends Item>({
88
+ data,
89
+ key,
90
+ signKey = 'id',
91
+ childrenKey = 'children',
92
+ }: Params<T> & {key: string}) {
93
+ const {self} = getTreeRelation({
94
+ childrenKey,
95
+ data,
96
+ lookup(item, index) {
97
+ return item[signKey] === key;
98
+ },
99
+ });
100
+ return arrayAttributeFlat({childrenKey, data: self?.[childrenKey] || []});
101
+ }
102
+
103
+ /** 获取全部祖先节点 */
104
+ export function getTreeAncestors<T extends Item>({
105
+ data,
106
+ key,
107
+ signKey = 'id',
108
+ childrenKey = 'children',
109
+ }: Params<T> & {key: string}) {
110
+ return getTreeRelation({
111
+ childrenKey,
112
+ data,
113
+ lookup(item, index) {
114
+ return item[signKey] === key;
115
+ },
116
+ }).stack;
117
+ }
118
+
119
+ /** 删除树节点 */
85
120
  export function deleteTreeNodes<T extends Item>({
86
121
  data,
87
122
  selectedKeys,
@@ -264,6 +299,63 @@ export function getSiblings<T extends Item>({
264
299
  return keys;
265
300
  }
266
301
 
302
+ /**
303
+ * @description 是否跨层
304
+ * @date 2022-11-21 20:03:52
305
+ * @export
306
+ * @param {string[]} hierarchy 选中任务的层级
307
+ * @returns {*}
308
+ */
309
+ export function getSelectedNodeHierarchyStatus<T extends Item>({
310
+ data,
311
+ selectedKeys,
312
+ signKey = 'id',
313
+ childrenKey = 'children',
314
+ }: Params<T> & {
315
+ selectedKeys: string[];
316
+ }): {
317
+ /** 层级深度是否有差别 */
318
+ isDifferentDepths: boolean;
319
+ /** 选中是否包含了祖先节点和其后的节点 */
320
+ isIncludedParent: boolean;
321
+ } {
322
+ const relations = selectedKeys.map((key) =>
323
+ getTreeRelation({
324
+ childrenKey,
325
+ data,
326
+ lookup(item, index) {
327
+ return item[signKey] === key;
328
+ },
329
+ }),
330
+ );
331
+ // 深度集合
332
+ const deepSet = new Set(relations.map((rel) => rel.stack.length));
333
+ const isDifferentDepths = deepSet.size > 1;
334
+ if (isDifferentDepths) {
335
+ return {
336
+ isDifferentDepths,
337
+ isIncludedParent: relations
338
+ .sort((a, b) => {
339
+ return b.stack.length - a.stack.length;
340
+ })
341
+ .some((item) => {
342
+ const ancestors = getTreeAncestors({
343
+ childrenKey,
344
+ data,
345
+ key: item.self[signKey],
346
+ signKey,
347
+ }).map((item) => item[signKey]);
348
+ return selectedKeys.some((id) => ancestors.includes(id));
349
+ }),
350
+ };
351
+ }
352
+
353
+ return {
354
+ isDifferentDepths,
355
+ isIncludedParent: false,
356
+ };
357
+ }
358
+
267
359
  /**
268
360
  * @description 合并相邻的选中数据
269
361
  * @date 2023-02-15 16:11:16
@@ -399,8 +491,9 @@ function optimizeStructure<T>({
399
491
  data,
400
492
  childrenKey = 'children',
401
493
  signKey = 'id',
402
- }: Params<T>): T[] {
403
- if (data.length > 1) {
494
+ isSupportMultipleRoot = false,
495
+ }: Params<T> & {isSupportMultipleRoot?: boolean}): T[] {
496
+ if (data.length > 1 || isSupportMultipleRoot) {
404
497
  return [
405
498
  {
406
499
  [childrenKey]: data,
@@ -437,6 +530,16 @@ type MoveParams<T> = Params<T> & {
437
530
  onError?: (params: {selected: T[]; isMoveUp?: boolean}) => boolean | void;
438
531
  };
439
532
 
533
+ interface ParentParams<T> {
534
+ originalParent: T;
535
+ parent: T;
536
+ }
537
+
538
+ interface ExpandedState<T> {
539
+ add: T;
540
+ remove: T | null;
541
+ }
542
+
440
543
  export function move<T extends Item>({
441
544
  data,
442
545
  signKey = 'id',
@@ -508,10 +611,17 @@ export function moveDown<T extends Item>(_: MoveParams<T>) {
508
611
  });
509
612
  }
510
613
 
614
+ interface OnUpgradeParams<T> {
615
+ selected: T[];
616
+ parent: T;
617
+ grandpa?: T;
618
+ }
619
+
511
620
  export async function upgrade<T extends Item>({
512
621
  data,
513
622
  signKey = 'id',
514
623
  isFollow,
624
+ isSupportMultipleRoot = false,
515
625
  onStopFollow,
516
626
  onFilterFollow,
517
627
  onUpgrade,
@@ -521,16 +631,16 @@ export async function upgrade<T extends Item>({
521
631
  onError,
522
632
  }: MoveParams<T> & {
523
633
  isFollow?: boolean;
634
+ isSupportMultipleRoot?: boolean;
524
635
  onStopFollow?: (item: T) => boolean;
525
636
  onFilterFollow?: (item: T[]) => T[];
526
- onUpgrade?: (params: {
527
- selected: T[];
528
- parent: T;
529
- grandpa?: T;
530
- }) => Promise<boolean> | boolean;
531
- onUpgraded?: (upgrades: T[]) => void;
637
+ onUpgrade?: (params: OnUpgradeParams<T>) => Promise<boolean> | boolean;
638
+ onUpgraded?: (
639
+ upgrades: T[],
640
+ params: ExpandedState<T[typeof signKey]>,
641
+ ) => void;
532
642
  }) {
533
- data = optimizeStructure({childrenKey, data, signKey});
643
+ data = optimizeStructure({childrenKey, data, isSupportMultipleRoot, signKey});
534
644
  const layers = mergeAdjacent({childrenKey, data, selectKeys, signKey});
535
645
  const {crossLayerSort, getInsertIdx} = generatedAcrossHierarchySort({
536
646
  signKey,
@@ -603,7 +713,16 @@ export async function upgrade<T extends Item>({
603
713
 
604
714
  const insert = (data: T[], index: number) => {
605
715
  data.splice(index, 0, ...selected);
606
- onUpgraded?.(selected);
716
+ onUpgraded?.(
717
+ selected,
718
+ getExpandedState({
719
+ childrenKey,
720
+ data,
721
+ originalParent: parent,
722
+ parent: grandpa!,
723
+ signKey,
724
+ }),
725
+ );
607
726
  };
608
727
  const insertIndex = getInsertIdx({
609
728
  leader: start,
@@ -616,6 +735,12 @@ export async function upgrade<T extends Item>({
616
735
  }
617
736
  }
618
737
 
738
+ interface OnDowngradedParams<T> {
739
+ selected: T[];
740
+ beforeSibling: T[];
741
+ parent: T | undefined;
742
+ }
743
+
619
744
  export async function downgrade<T extends Item>({
620
745
  data,
621
746
  signKey = 'id',
@@ -625,12 +750,11 @@ export async function downgrade<T extends Item>({
625
750
  childrenKey = 'children',
626
751
  onError,
627
752
  }: MoveParams<T> & {
628
- onDowngrade?: (params: {
629
- selected: T[];
630
- beforeSibling: T[];
631
- parent: T | undefined;
632
- }) => Promise<boolean> | boolean;
633
- onDowngraded?: (downgrades: T[]) => void;
753
+ onDowngrade?: (params: OnDowngradedParams<T>) => Promise<boolean> | boolean;
754
+ onDowngraded?: (
755
+ downgrades: T[],
756
+ params: ExpandedState<T[typeof signKey]>,
757
+ ) => void;
634
758
  }) {
635
759
  data = optimizeStructure({childrenKey, data, signKey});
636
760
  const layers = mergeAdjacent({childrenKey, data, selectKeys, signKey});
@@ -659,7 +783,16 @@ export async function downgrade<T extends Item>({
659
783
  const newChildren = [...(before[childrenKey] || []), ...children];
660
784
  if (children.length) {
661
785
  (before as Item)[childrenKey] = [...newChildren];
662
- onDowngraded?.(children);
786
+ onDowngraded?.(
787
+ children,
788
+ getExpandedState({
789
+ childrenKey,
790
+ data,
791
+ originalParent: parent,
792
+ parent: before,
793
+ signKey,
794
+ }),
795
+ );
663
796
  }
664
797
  }
665
798
  }
@@ -719,3 +852,19 @@ export function treeSearch<T extends Record<string, any>>({
719
852
  })
720
853
  .filter((row): row is T => !!row);
721
854
  }
855
+
856
+ function getExpandedState<T extends Item>({
857
+ originalParent,
858
+ parent,
859
+ signKey = 'id',
860
+ childrenKey = 'children',
861
+ }: ParentParams<T> & Params<T>) {
862
+ const isRemove = !originalParent[childrenKey]?.length;
863
+
864
+ type Key = T[typeof signKey];
865
+
866
+ return {
867
+ add: parent[signKey] as Key,
868
+ remove: isRemove ? (originalParent[signKey] as Key) : null,
869
+ };
870
+ }
package/src/base.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  */
8
8
  /* eslint-disable @typescript-eslint/no-explicit-any */
9
9
 
10
+ /** 是否是Moment对象(_表示为内部函数谨慎使用) */
10
11
  export function _isMoment(obj: any) {
11
12
  return (
12
13
  obj != null &&
@@ -22,6 +23,12 @@ export function _isMoment(obj: any) {
22
23
  );
23
24
  }
24
25
 
26
+ /**
27
+ * 创建一个可解构的对象,该对象同时具有原始对象的属性和数组的迭代器,使其可以使用对象和数组两种解构方式
28
+ * @param obj - 需要转换的对象
29
+ * @param arr - 用于提供迭代器的数组
30
+ * @returns 一个结合了对象属性和数组迭代器的新对象
31
+ */
25
32
  export function makeDestructurable<
26
33
  T extends Record<string, unknown>,
27
34
  A extends readonly [any, ...any],
@@ -47,6 +54,7 @@ export function makeDestructurable<
47
54
  }
48
55
  }
49
56
 
57
+ /** 创建对象枚举,可以避免两个相同枚举缺不相等 */
50
58
  export function createEnumObject<T extends string>(o: {[P in T]: P}) {
51
59
  return o;
52
60
  }
@@ -54,14 +62,71 @@ export function createEnumObject<T extends string>(o: {[P in T]: P}) {
54
62
  export function toTypeString<T>(value: T): string {
55
63
  return Object.prototype.toString.call(value);
56
64
  }
65
+
57
66
  export function toRawType<T>(value: T): string {
58
67
  // 从字符串中提取“RawType”,如“[object RawType]”
59
68
  return toTypeString(value).slice(8, -1);
60
69
  }
70
+
71
+ export function isString(value: any): value is string {
72
+ return toRawType(value) === 'String';
73
+ }
74
+
75
+ export function isNumber(value: any): value is number {
76
+ return toRawType(value) === 'Number';
77
+ }
78
+
79
+ /** 判断值是否为NaN */
80
+ export function isNaN(value?: any): value is number {
81
+ return Number.isNaN(value);
82
+ }
83
+
84
+ export function isBoolean(value?: any): value is boolean {
85
+ return toRawType(value) === 'Boolean';
86
+ }
87
+
88
+ export function isUndefined(value?: any): value is undefined {
89
+ return toRawType(value) === 'Undefined';
90
+ }
91
+
92
+ export function isNull(value?: any): value is null {
93
+ return toRawType(value) === 'Null';
94
+ }
95
+
96
+ export function isNil(value?: any): value is null | undefined {
97
+ return isNull(value) || isUndefined(value);
98
+ }
99
+
100
+ /**
101
+ * 判断是否是 `null` 或 `undefined`
102
+ * @example
103
+ * _.isNil(null);
104
+ * // => true
105
+ *
106
+ * _.isNil(void 0);
107
+ * // => true
108
+ *
109
+ * _.isNil(NaN);
110
+ * // => false
111
+ */
112
+ export function isObject(value?: any): value is object {
113
+ return toRawType(value) === 'Object';
114
+ }
115
+
116
+ export function isArray(value?: unknown): value is unknown[] {
117
+ return toRawType(value) === 'Array';
118
+ }
119
+
120
+ export function isFunction(value?: any): value is (...args: any[]) => any {
121
+ return toRawType(value) === 'Function';
122
+ }
123
+
124
+ /** 判断对象是否有某个属性 */
61
125
  export function hasOwnProperty<T>(data: T, key: string | symbol | number) {
62
126
  return data && Object.prototype.hasOwnProperty.call(data, key);
63
127
  }
64
128
 
129
+ /** 是否是整型key */
65
130
  export function isIntegerKey(key: unknown) {
66
131
  return (
67
132
  typeof key === 'string' &&
@@ -70,10 +135,13 @@ export function isIntegerKey(key: unknown) {
70
135
  '' + parseInt(key, 10) === key
71
136
  );
72
137
  }
138
+
139
+ /** 是否是空对象 */
73
140
  export function isEmptyObject(obj: object | undefined | null) {
74
141
  return obj ? !Object.keys(obj).length : true;
75
142
  }
76
143
 
144
+ /** 生成 innerHTML */
77
145
  export function getHTMLTagString(params: {
78
146
  type: string;
79
147
  attributes?: Record<string, any>;