@hi-ui/check-tree-select 4.0.0-beta.8 → 4.0.1

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.
@@ -2,27 +2,29 @@
2
2
  * @hi-ui/check-tree-select
3
3
  * https://github.com/XiaoMi/hiui/tree/master/packages/ui/check-tree-select#readme
4
4
  *
5
- * Copyright (c) HIUI <mi-hiui@xiaomi.com>.
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
6
  *
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree.
9
9
  */
10
10
  import { __rest } from 'tslib';
11
- import React, { forwardRef, useCallback, useMemo, useState } from 'react';
11
+ import React, { forwardRef, useCallback, useMemo } from 'react';
12
12
  import { getPrefixCls, cx } from '@hi-ui/classname';
13
13
  import { __DEV__ } from '@hi-ui/env';
14
- import { useToggle } from '@hi-ui/use-toggle';
14
+ import { useUncontrolledToggle } from '@hi-ui/use-toggle';
15
15
  import { Tree } from '@hi-ui/tree';
16
16
  import { useUncontrolledState } from '@hi-ui/use-uncontrolled-state';
17
17
  import { Picker } from '@hi-ui/picker';
18
- import { flattenTree } from '@hi-ui/tree-utils';
18
+ import { baseFlattenTree } from '@hi-ui/tree-utils';
19
19
  import { isUndef, isArrayNonEmpty } from '@hi-ui/type-assertion';
20
20
  import { uniqBy } from '@hi-ui/array-utils';
21
21
  import { Highlighter } from '@hi-ui/highlighter';
22
22
  import { TagInputMock } from '@hi-ui/tag-input';
23
23
  import { UpOutlined, DownOutlined } from '@hi-ui/icons';
24
- import { useLocaleContext } from '@hi-ui/locale-context';
24
+ import { useLocaleContext } from '@hi-ui/core';
25
+ import { callAllFuncs } from '@hi-ui/func-utils';
25
26
  import { useAsyncSearch, useTreeCustomSearch, useFilterSearch, useHighlightSearch, useSearchMode } from '@hi-ui/use-search-mode';
27
+ import { useCheck } from './hooks/use-check.js';
26
28
  var TREE_SELECT_PREFIX = getPrefixCls('check-tree-select');
27
29
  var DEFAULT_DATA = [];
28
30
  var DEFAULT_VALUE = [];
@@ -41,9 +43,13 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
41
43
  dataSource = _a.dataSource,
42
44
  _a$disabled = _a.disabled,
43
45
  disabled = _a$disabled === void 0 ? false : _a$disabled,
46
+ visible = _a.visible,
47
+ onOpen = _a.onOpen,
48
+ onClose = _a.onClose,
44
49
  _a$fieldNames = _a.fieldNames,
45
50
  fieldNames = _a$fieldNames === void 0 ? DEFAULT_FIELD_NAMES : _a$fieldNames,
46
- checkedMode = _a.checkedMode,
51
+ _a$checkedMode = _a.checkedMode,
52
+ checkedMode = _a$checkedMode === void 0 ? 'ALL' : _a$checkedMode,
47
53
  _a$defaultExpandAll = _a.defaultExpandAll,
48
54
  defaultExpandAll = _a$defaultExpandAll === void 0 ? false : _a$defaultExpandAll,
49
55
  expandedIdsProp = _a.expandedIds,
@@ -59,20 +65,28 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
59
65
  onLoadChildren = _a.onLoadChildren,
60
66
  titleRender = _a.render,
61
67
  filterOption = _a.filterOption,
68
+ onSearchProp = _a.onSearch,
62
69
  clearable = _a.clearable,
63
70
  invalid = _a.invalid,
64
71
  displayRender = _a.displayRender,
65
72
  placeholderProp = _a.placeholder,
66
73
  appearance = _a.appearance,
67
- rest = __rest(_a, ["prefixCls", "role", "className", "data", "dataSource", "disabled", "fieldNames", "checkedMode", "defaultExpandAll", "expandedIds", "defaultExpandedIds", "onExpand", "defaultValue", "value", "onChange", "searchable", "searchMode", "onLoadChildren", "render", "filterOption", "clearable", "invalid", "displayRender", "placeholder", "appearance"]);
74
+ virtual = _a.virtual,
75
+ itemHeight = _a.itemHeight,
76
+ height = _a.height,
77
+ rest = __rest(_a, ["prefixCls", "role", "className", "data", "dataSource", "disabled", "visible", "onOpen", "onClose", "fieldNames", "checkedMode", "defaultExpandAll", "expandedIds", "defaultExpandedIds", "onExpand", "defaultValue", "value", "onChange", "searchable", "searchMode", "onLoadChildren", "render", "filterOption", "onSearch", "clearable", "invalid", "displayRender", "placeholder", "appearance", "virtual", "itemHeight", "height"]);
68
78
 
69
79
  var i18n = useLocaleContext();
70
80
  var placeholder = isUndef(placeholderProp) ? i18n.get('checkTreeSelect.placeholder') : placeholderProp;
71
81
 
72
- var _useToggle = useToggle(),
73
- menuVisible = _useToggle[0],
74
- menuVisibleAction = _useToggle[1]; // const [viewSelected, setViewSelected] = useState(false)
75
-
82
+ var _useUncontrolledToggl = useUncontrolledToggle({
83
+ visible: visible,
84
+ disabled: disabled,
85
+ onOpen: onOpen,
86
+ onClose: onClose
87
+ }),
88
+ menuVisible = _useUncontrolledToggl[0],
89
+ menuVisibleAction = _useUncontrolledToggl[1];
76
90
  /**
77
91
  * 转换对象
78
92
  */
@@ -82,11 +96,22 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
82
96
  return node[fieldNames[key] || key];
83
97
  }, [fieldNames]);
84
98
  var flattedData = useMemo(function () {
85
- return flattenTree(data, function (node) {
86
- node.id = getKeyFields(node.raw, 'id'); // @ts-ignore
87
-
88
- node.title = getKeyFields(node.raw, 'title');
89
- return node;
99
+ return baseFlattenTree({
100
+ tree: data,
101
+ childrenFieldName: function childrenFieldName(node) {
102
+ return getKeyFields(node, 'children');
103
+ },
104
+ transform: function transform(node) {
105
+ var _a, _b;
106
+
107
+ var flattedNode = node;
108
+ var raw = node.raw;
109
+ flattedNode.id = getKeyFields(raw, 'id');
110
+ flattedNode.title = getKeyFields(raw, 'title');
111
+ flattedNode.disabled = (_a = getKeyFields(raw, 'disabled')) !== null && _a !== void 0 ? _a : false;
112
+ flattedNode.isLeaf = (_b = getKeyFields(raw, 'isLeaf')) !== null && _b !== void 0 ? _b : false;
113
+ return flattedNode;
114
+ }
90
115
  });
91
116
  }, [data, getKeyFields]); // TODO: 抽离展开hook
92
117
  // TODO: onLoadChildren 和 defaultExpandAll 共存时
@@ -104,34 +129,27 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
104
129
  expandedIds = _useUncontrolledState[0],
105
130
  tryChangeExpandedIds = _useUncontrolledState[1];
106
131
 
107
- var _useUncontrolledState2 = useUncontrolledState(defaultValue, valueProp, onChange),
108
- value = _useUncontrolledState2[0],
109
- tryChangeValue = _useUncontrolledState2[1]; // 搜索时临时选中缓存数据
110
-
111
-
112
- var _useState = useState([]),
113
- selectedItems = _useState[0],
114
- setSelectedItems = _useState[1];
115
-
116
- var onSelect = useCallback(function (checkedIds, option) {
117
- tryChangeValue(checkedIds, option); // 存取异步选中数据
118
-
119
- setSelectedItems(function (prev) {
120
- var next = [].concat(prev);
121
- var targetNode = option.targetNode,
122
- checked = option.checked;
123
-
124
- if (checked) {
125
- next.push(targetNode);
126
- } else {
127
- next.filter(function (item) {
128
- return item.id !== targetNode.id;
129
- });
130
- }
131
-
132
- return next;
133
- });
134
- }, [tryChangeValue]); // ************************** 异步搜索 ************************* //
132
+ var _useCheck = useCheck(checkedMode, disabled, flattedData, defaultValue, valueProp, onChange),
133
+ value = _useCheck[0],
134
+ tryChangeValue = _useCheck[1],
135
+ onNodeCheck = _useCheck[2],
136
+ checkedNodes = _useCheck[3],
137
+ parsedCheckedIds = _useCheck[4];
138
+
139
+ var onCheck = useCallback(function (checkedIds, option) {
140
+ var targetNode = option.targetNode,
141
+ checked = option.checked;
142
+ onNodeCheck(targetNode, checked);
143
+ }, [onNodeCheck]);
144
+ var onValueChange = useCallback(function (values, targetItem, shouldChecked) {
145
+ // 清空
146
+ if (values.length === 0) {
147
+ tryChangeValue([], null, shouldChecked, []);
148
+ } else {
149
+ // 操作单个
150
+ onNodeCheck(targetItem[0], shouldChecked);
151
+ }
152
+ }, [tryChangeValue, onNodeCheck]); // ************************** 异步搜索 ************************* //
135
153
  // const { loading, hasError, loadRemoteData } = useDataSource({ dataSource, validate: isArray })
136
154
 
137
155
  var _b = useAsyncSearch({
@@ -148,7 +166,8 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
148
166
  var filterSearchStrategy = useFilterSearch({
149
167
  enabled: searchModeProp === 'filter',
150
168
  data: data,
151
- flattedData: flattedData
169
+ flattedData: flattedData,
170
+ fieldNames: fieldNames
152
171
  });
153
172
  var highlightSearchStrategy = useHighlightSearch({
154
173
  data: data,
@@ -197,9 +216,9 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
197
216
  }; // 下拉菜单不能合并(因为树形数据,不知道是第几级)
198
217
 
199
218
  var mergedData = useMemo(function () {
200
- var nextData = selectedItems.concat(flattedData);
219
+ var nextData = checkedNodes.concat(flattedData);
201
220
  return uniqBy(nextData, 'id');
202
- }, [selectedItems, flattedData]);
221
+ }, [checkedNodes, flattedData]);
203
222
  var cls = cx(prefixCls, className); // 过滤掉未选中的数据
204
223
  // const tagList = useMemo(() => {
205
224
  // // @ts-ignore
@@ -223,7 +242,7 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
223
242
  // onChange={tryChangeValue}
224
243
  // data={mergedData}
225
244
  searchable: searchable,
226
- onSearch: onSearch,
245
+ onSearch: callAllFuncs(onSearchProp, onSearch),
227
246
  loading: loading,
228
247
  trigger: /*#__PURE__*/React.createElement(TagInputMock // ref={targetElementRef}
229
248
  // onClick={openMenu}
@@ -240,22 +259,28 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
240
259
  focused: menuVisible,
241
260
  appearance: appearance,
242
261
  value: value,
243
- onChange: tryChangeValue,
262
+ onChange: onValueChange,
244
263
  data: mergedData,
245
264
  // @ts-ignore
246
265
  invalid: invalid
247
266
  })
248
- }), isArrayNonEmpty(treeProps.data) ? /*#__PURE__*/React.createElement(Tree, Object.assign({
267
+ }), isArrayNonEmpty(treeProps.data) ?
268
+ /*#__PURE__*/
269
+ // 只做渲染,不做逻辑处理(比如搜索过滤后,check操作的是对过滤后的data操作,这是不符合预期的)
270
+ React.createElement(Tree, Object.assign({
249
271
  className: prefixCls + "__tree",
250
272
  selectable: false,
251
273
  checkable: true,
252
274
  checkOnSelect: true,
253
- checkedMode: checkedMode,
254
- checkedIds: value,
255
- onCheck: onSelect,
256
- // TODO: 支持 fieldNames
257
- // 禁用时被选中的样式处理
258
- onLoadChildren: onLoadChildren
275
+ checkedMode: checkedMode === 'SEPARATE' ? 'SEPARATE' : 'ALL',
276
+ checkedIds: parsedCheckedIds,
277
+ onCheck: onCheck,
278
+ // @ts-ignore
279
+ onLoadChildren: onLoadChildren,
280
+ fieldNames: fieldNames,
281
+ virtual: virtual,
282
+ itemHeight: itemHeight,
283
+ height: height
259
284
  }, treeProps)) : null);
260
285
  });
261
286
 
@@ -316,4 +341,3 @@ var getSemiCheckedIdsWithSet = function getSemiCheckedIdsWithSet(flattedData, is
316
341
  };
317
342
 
318
343
  export { CheckTreeSelect, getSemiCheckedIdsWithSet };
319
- //# sourceMappingURL=CheckTreeSelect.js.map
@@ -0,0 +1,82 @@
1
+ /** @LICENSE
2
+ * @hi-ui/check-tree-select
3
+ * https://github.com/XiaoMi/hiui/tree/master/packages/ui/check-tree-select#readme
4
+ *
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ import { useState, useMemo, useCallback } from 'react';
11
+ import { useUncontrolledState } from '@hi-ui/use-uncontrolled-state';
12
+ import { useCascadeCheck } from '@hi-ui/use-check';
13
+ import { parseCheckDataDirty, processCheckedIds } from '../utils/index.js';
14
+ /**
15
+ * 用于 tree 组件复选的 hook
16
+ */
17
+
18
+ var useCheck = function useCheck(checkedMode, disabled, flattedData, defaultCheckedIds, checkedIdsProp, onCheck) {
19
+ // 搜索时临时选中缓存数据
20
+ var _useState = useState([]),
21
+ checkedNodes = _useState[0],
22
+ setCheckedNodes = _useState[1];
23
+
24
+ var _useUncontrolledState = useUncontrolledState(defaultCheckedIds, checkedIdsProp, function (checkedIds, checkedNode, checked, semiCheckedIds) {
25
+ var nextCheckedNodes = flattedData.filter(function (item) {
26
+ return checkedIds.includes(item.id);
27
+ });
28
+ setCheckedNodes(nextCheckedNodes);
29
+ onCheck === null || onCheck === void 0 ? void 0 : onCheck(checkedIds, {
30
+ checkedNodes: nextCheckedNodes.map(function (item) {
31
+ return item.raw;
32
+ }),
33
+ targetNode: checkedNode,
34
+ semiCheckedIds: semiCheckedIds,
35
+ checked: checked
36
+ });
37
+ }),
38
+ checkedIds = _useUncontrolledState[0],
39
+ trySetCheckedIds = _useUncontrolledState[1]; // 入口数据处理
40
+
41
+
42
+ var parsedCheckedIds = useMemo(function () {
43
+ return parseCheckDataDirty(checkedMode, checkedIds, flattedData, allowCheck);
44
+ }, [checkedMode, checkedIds, flattedData]);
45
+ var cascaded = checkedMode !== 'SEPARATE';
46
+
47
+ var _useCascadeCheck = useCascadeCheck({
48
+ cascaded: cascaded,
49
+ disabled: disabled,
50
+ flattedData: flattedData,
51
+ checkedIds: parsedCheckedIds,
52
+ onCheck: function onCheck(checkedIds, checkedNode, checked, semiCheckedIds) {
53
+ // 出口数据处理
54
+ var processedIds = processCheckedIds(checkedMode, checkedIds, flattedData, allowCheck);
55
+ trySetCheckedIds(processedIds, checkedNode, checked, semiCheckedIds);
56
+ },
57
+ allowCheck: allowCheck
58
+ }),
59
+ onNodeCheck = _useCascadeCheck[0];
60
+
61
+ var proxyOnNodeCheck = useCallback(function (target, shouldChecked) {
62
+ // 保证 target 来源于原数据自身,而不是tree内部
63
+ var targetNode = flattedData.find(function (item) {
64
+ return item.id === target.id;
65
+ });
66
+
67
+ if (targetNode) {
68
+ onNodeCheck(targetNode, shouldChecked);
69
+ }
70
+ }, [onNodeCheck, flattedData]);
71
+ return [checkedIds, trySetCheckedIds, proxyOnNodeCheck, checkedNodes, parsedCheckedIds];
72
+ };
73
+
74
+ var allowCheck = function allowCheck(targetItem) {
75
+ if (targetItem.disabled) {
76
+ return false;
77
+ }
78
+
79
+ return true;
80
+ };
81
+
82
+ export { useCheck };
package/lib/esm/index.js CHANGED
@@ -2,11 +2,10 @@
2
2
  * @hi-ui/check-tree-select
3
3
  * https://github.com/XiaoMi/hiui/tree/master/packages/ui/check-tree-select#readme
4
4
  *
5
- * Copyright (c) HIUI <mi-hiui@xiaomi.com>.
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
6
  *
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree.
9
9
  */
10
10
  import './styles/index.scss.js';
11
11
  export { CheckTreeSelect, CheckTreeSelect as default, getSemiCheckedIdsWithSet } from './CheckTreeSelect.js';
12
- //# sourceMappingURL=index.js.map
@@ -2,16 +2,14 @@
2
2
  * @hi-ui/check-tree-select
3
3
  * https://github.com/XiaoMi/hiui/tree/master/packages/ui/check-tree-select#readme
4
4
  *
5
- * Copyright (c) HIUI <mi-hiui@xiaomi.com>.
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
6
  *
7
7
  * This source code is licensed under the MIT license found in the
8
8
  * LICENSE file in the root directory of this source tree.
9
9
  */
10
- var css_248z = "@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n@use 'sass:map';\n";
11
-
12
- var __styleInject__ = require('style-inject/dist/style-inject.es.js')["default"];
10
+ import __styleInject__ from 'inject-head-style';
11
+ var css_248z = "";
13
12
 
14
13
  __styleInject__(css_248z);
15
14
 
16
- export default css_248z;
17
- //# sourceMappingURL=index.scss.js.map
15
+ export { css_248z as default };
@@ -0,0 +1,153 @@
1
+ /** @LICENSE
2
+ * @hi-ui/check-tree-select
3
+ * https://github.com/XiaoMi/hiui/tree/master/packages/ui/check-tree-select#readme
4
+ *
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ import { fFindNodeById, getNodeAncestors, findNestedChildren } from '@hi-ui/tree-utils';
11
+ import { isArrayNonEmpty } from '@hi-ui/type-assertion';
12
+ /**
13
+ * 处理选中的回显数据
14
+ *
15
+ * @param checkedIds 当前所有被选中的节点 ID 集合
16
+ * @param nodeEntries 所有数据的Map 集合
17
+ * @param type 数据回显方式
18
+ */
19
+
20
+ var processCheckedIds = function processCheckedIds(type, checkedIds, flattenData, allowCheck) {
21
+ var keySet = new Set(checkedIds);
22
+
23
+ switch (type) {
24
+ case 'CHILD':
25
+ return checkedIds.filter(function (id) {
26
+ var node = fFindNodeById(flattenData, id);
27
+
28
+ if (node) {
29
+ var children = node.children;
30
+
31
+ if (isArrayNonEmpty(children)) {
32
+ if (children.filter(allowCheck).every(function (node) {
33
+ return keySet.has(node.id);
34
+ })) {
35
+ return false;
36
+ }
37
+ }
38
+ } // 没有孩子节点,保留
39
+
40
+
41
+ return true;
42
+ });
43
+
44
+ case 'PARENT':
45
+ return checkedIds.filter(function (id) {
46
+ var node = fFindNodeById(flattenData, id);
47
+
48
+ if (node) {
49
+ // 向上递归遍历是否被勾选
50
+ var ancestors = getNodeAncestors(node);
51
+
52
+ if (ancestors.some(function (parent) {
53
+ return keySet.has(parent.id);
54
+ })) {
55
+ return false;
56
+ }
57
+ }
58
+
59
+ return true;
60
+ });
61
+ }
62
+
63
+ return checkedIds;
64
+ };
65
+ /**
66
+ * 根据传入的 checkedIds 解析全选/半选数据
67
+ */
68
+
69
+
70
+ var parseCheckDataDirty = function parseCheckDataDirty(type, checkedIds, flattenData, allowCheck) {
71
+ switch (type) {
72
+ case 'CHILD':
73
+ case 'PARENT':
74
+ return dirtyCheck(checkedIds, flattenData, allowCheck);
75
+ }
76
+
77
+ return checkedIds;
78
+ };
79
+
80
+ function dirtyCheck(checkedIds, flattenData, allowCheck) {
81
+ var nodeEntities = flattenData.reduce(function (prev, cur) {
82
+ prev[cur.id] = cur;
83
+ return prev;
84
+ }, {});
85
+ var checkedIdsSet = new Set(checkedIds.filter(function (id) {
86
+ return !!nodeEntities[id];
87
+ }));
88
+ var depthEntities = new Map();
89
+ var maxDepth = 0; // Convert entities by depth for calculation
90
+
91
+ Object.keys(nodeEntities).forEach(function (id) {
92
+ var entity = nodeEntities[id];
93
+ var depth = entity.depth;
94
+ var depthSet = depthEntities.get(depth);
95
+
96
+ if (!depthSet) {
97
+ depthSet = new Set();
98
+ depthEntities.set(depth, depthSet);
99
+ }
100
+
101
+ depthSet.add(entity);
102
+ maxDepth = Math.max(maxDepth, depth);
103
+ });
104
+ return fillCheck(checkedIdsSet, depthEntities, nodeEntities, maxDepth, allowCheck);
105
+ }
106
+ /**
107
+ * 对 checkedIds 级联遗漏选项 id 填充
108
+ *
109
+ * 1. 把所有嵌套孩子节点 allowCheck 的都标记为 checked
110
+ * 2. 祖先节点从下至上维护 checked 状态
111
+ */
112
+
113
+
114
+ function fillCheck(checkedIds, depthEntities, nodeEntities, maxDepth, allowCheck) {
115
+ var checkedIdsSet = new Set(checkedIds);
116
+ checkedIdsSet.forEach(function (id) {
117
+ var checkedNode = nodeEntities[id];
118
+ var nestedChildren = findNestedChildren(checkedNode, allowCheck);
119
+ nestedChildren.forEach(function (child) {
120
+ checkedIdsSet.add(child.id);
121
+ });
122
+ }); // 缓存中间结果,优化查询
123
+
124
+ var visitedIds = new Map();
125
+
126
+ for (var depth = maxDepth - 1; depth >= 0; --depth) {
127
+ var entities = depthEntities.get(depth);
128
+ entities === null || entities === void 0 ? void 0 : entities.forEach(function (entity) {
129
+ var id = entity.id,
130
+ children = entity.children;
131
+ if (visitedIds.has(id)) return;
132
+
133
+ if (isArrayNonEmpty(children)) {
134
+ var shouldChecked = !children.some(function (child) {
135
+ if (visitedIds.has(child.id)) {
136
+ return !visitedIds.get(child.id);
137
+ }
138
+
139
+ return !checkedIdsSet.has(child.id);
140
+ });
141
+ visitedIds.set(id, shouldChecked);
142
+
143
+ if (shouldChecked && allowCheck(entity)) {
144
+ checkedIdsSet.add(id);
145
+ }
146
+ }
147
+ });
148
+ }
149
+
150
+ return Array.from(checkedIdsSet);
151
+ }
152
+
153
+ export { parseCheckDataDirty, processCheckedIds };
@@ -1,13 +1,12 @@
1
1
  import React from 'react';
2
- import { DataSourceFunc, FieldNames, CheckTreeSelectDataItem, CheckTreeSelectDataSource } from './types';
3
- import { FlattedTreeNodeData, TreeNodeEventData } from '@hi-ui/tree';
2
+ import { CheckTreeSelectDataItem, CheckTreeSelectItemEventData, CheckTreeSelectAppearanceEnum } from './types';
3
+ import { FlattedTreeNodeData } from '@hi-ui/tree';
4
4
  import { PickerProps } from '@hi-ui/picker';
5
- import { HiBaseAppearanceEnum } from '@hi-ui/core';
6
5
  /**
7
6
  * TODO: What is CheckTreeSelect
8
7
  */
9
8
  export declare const CheckTreeSelect: React.ForwardRefExoticComponent<CheckTreeSelectProps & React.RefAttributes<HTMLDivElement | null>>;
10
- export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChange' | 'value' | 'trigger'> {
9
+ export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChange' | 'value' | 'trigger' | 'scrollable'> {
11
10
  /**
12
11
  * 展示数据
13
12
  */
@@ -15,18 +14,15 @@ export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChan
15
14
  /**
16
15
  * 设置 data 中 id, title, disabled, children 对应的 key (3.0 新增) object - { title: 'title', id: 'id',disabled:'disabled', children: 'children'}
17
16
  */
18
- fieldNames?: FieldNames;
17
+ fieldNames?: Record<string, string>;
19
18
  /**
20
- * 数据回显模式 string
21
- * ALL: 所有被选中节点,不区分父子节点
19
+ * 多选数据交互时回填、回显模式
22
20
  * PARENT: 当所有子节点被选中时将只保留父节点
23
- * CHILD: 仅显示子节点
21
+ * ALL: 所有被选中节点,不区分父子节点(不支持异步数据加载勾选checkbox)
22
+ * CHILD: 仅显示子节点(不支持异步数据加载勾选checkbox)
23
+ * SEPARATE:父子完全独立受控
24
24
  */
25
- checkedMode?: 'ALL' | 'PARENT' | 'CHILD';
26
- /**
27
- * 数据选择类型
28
- */
29
- type?: 'single' | 'multiple';
25
+ checkedMode?: 'ALL' | 'PARENT' | 'CHILD' | 'SEPARATE';
30
26
  /**
31
27
  * 是否有边框
32
28
  */
@@ -80,19 +76,14 @@ export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChan
80
76
  /**
81
77
  * 自定义渲染节点的 title 内容
82
78
  */
83
- render?: (node: TreeNodeEventData) => React.ReactNode;
79
+ render?: (node: CheckTreeSelectItemEventData) => React.ReactNode;
84
80
  /**
85
81
  * 点击异步加载子项
86
82
  */
87
- onLoadChildren?: (node: TreeNodeEventData) => void | Promise<CheckTreeSelectDataItem[] | void>;
83
+ onLoadChildren?: (node: CheckTreeSelectItemEventData) => void | Promise<CheckTreeSelectDataItem[] | void>;
88
84
  /**
89
- * 从远端获取数据,初始时是否自动加载
85
+ * 异步加载数据。暂不对外暴露
90
86
  */
91
- autoload?: boolean;
92
- /**
93
- * 异步加载数据
94
- */
95
- dataSource?: DataSourceFunc | CheckTreeSelectDataSource | Promise<CheckTreeSelectDataItem[]>;
96
87
  /**
97
88
  * 没有选项时的提示
98
89
  */
@@ -109,13 +100,13 @@ export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChan
109
100
  * 选中时触发
110
101
  * checkedIds: 选中项 ID 集合
111
102
  * checkedNodes: 选中项数据项集合
112
- * targetNode: 当前操作节点
103
+ * targetNode: 当前操作节点,清空时为 null
113
104
  * checked: 当前操作是否为选中操作
114
105
  */
115
106
  onChange?: (checkedIds: React.ReactText[], options: {
116
107
  checkedNodes: CheckTreeSelectDataItem[];
117
108
  semiCheckedIds: React.ReactText[];
118
- targetNode: TreeNodeEventData;
109
+ targetNode: CheckTreeSelectItemEventData | null;
119
110
  checked: boolean;
120
111
  }) => void;
121
112
  /**
@@ -125,7 +116,21 @@ export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChan
125
116
  /**
126
117
  * 设置展现形式
127
118
  */
128
- appearance?: HiBaseAppearanceEnum;
119
+ appearance?: CheckTreeSelectAppearanceEnum;
120
+ /**
121
+ * 设置虚拟滚动容器的可视高度。暂不对外暴露
122
+ * @private
123
+ */
124
+ height?: number;
125
+ /**
126
+ * 设置虚拟列表每项的固定高度。暂不对外暴露
127
+ * @private
128
+ */
129
+ itemHeight?: number;
130
+ /**
131
+ * 设置 `true` 开启虚拟滚动
132
+ */
133
+ virtual?: boolean;
129
134
  }
130
135
  /**
131
136
  * 在 checkedIdsSet 为数据合法的情况下,查找所有的半选中态的节点 ids
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { FlattedCheckTreeSelectDataItem, CheckTreeSelectItemEventData, CheckTreeSelectDataItem } from '../types';
3
+ /**
4
+ * 用于 tree 组件复选的 hook
5
+ */
6
+ export declare const useCheck: (checkedMode: string, disabled: boolean, flattedData: FlattedCheckTreeSelectDataItem[], defaultCheckedIds: React.ReactText[], checkedIdsProp?: React.ReactText[] | undefined, onCheck?: ((checkedIds: React.ReactText[], options: {
7
+ checkedNodes: CheckTreeSelectDataItem[];
8
+ semiCheckedIds: React.ReactText[];
9
+ targetNode: CheckTreeSelectItemEventData;
10
+ checked: boolean;
11
+ }) => void) | undefined) => readonly [React.ReactText[], (stateOrFunction: React.SetStateAction<React.ReactText[]>, ...args: any[]) => void, (target: FlattedCheckTreeSelectDataItem, shouldChecked: boolean) => void, FlattedCheckTreeSelectDataItem[], React.ReactText[]];
@@ -1,3 +1,4 @@
1
1
  import './styles/index.scss';
2
2
  export * from './CheckTreeSelect';
3
3
  export { CheckTreeSelect as default } from './CheckTreeSelect';
4
+ export * from './types';