@hi-ui/check-tree-select 4.0.11-beta.0 → 4.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/CHANGELOG.md CHANGED
@@ -1,11 +1,10 @@
1
1
  # @hi-ui/check-tree-select
2
2
 
3
- ## 4.0.11-beta.0
3
+ ## 4.1.0
4
4
 
5
- ### Patch Changes
5
+ ### Minor Changes
6
6
 
7
- - @hi-ui/use-search-mode@4.0.7-beta.0
8
- - @hi-ui/picker@4.0.7-beta.0
7
+ - [#2516](https://github.com/XiaoMi/hiui/pull/2516) [`49aa47c02`](https://github.com/XiaoMi/hiui/commit/49aa47c02f7b4fc858f2ca9b55974853dfdbd59d) Thanks [@zyprepare](https://github.com/zyprepare)! - feat: 增加 showCheckAll API
9
8
 
10
9
  ## 4.0.10
11
10
 
@@ -47,10 +47,14 @@ var core = require('@hi-ui/core');
47
47
 
48
48
  var funcUtils = require('@hi-ui/func-utils');
49
49
 
50
+ var Checkbox = require('@hi-ui/checkbox');
51
+
50
52
  var useSearchMode = require('@hi-ui/use-search-mode');
51
53
 
52
54
  var useCheck = require('./hooks/use-check.js');
53
55
 
56
+ var index = require('./utils/index.js');
57
+
54
58
  function _interopDefaultLegacy(e) {
55
59
  return e && _typeof(e) === 'object' && 'default' in e ? e : {
56
60
  'default': e
@@ -59,6 +63,8 @@ function _interopDefaultLegacy(e) {
59
63
 
60
64
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
61
65
 
66
+ var Checkbox__default = /*#__PURE__*/_interopDefaultLegacy(Checkbox);
67
+
62
68
  var TREE_SELECT_PREFIX = classname.getPrefixCls('check-tree-select');
63
69
  var DEFAULT_DATA = [];
64
70
  var DEFAULT_VALUE = [];
@@ -108,7 +114,8 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
108
114
  virtual = _a.virtual,
109
115
  itemHeight = _a.itemHeight,
110
116
  height = _a.height,
111
- rest = tslib.__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"]);
117
+ showCheckAll = _a.showCheckAll,
118
+ rest = tslib.__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", "showCheckAll"]);
112
119
 
113
120
  var i18n = core.useLocaleContext();
114
121
  var placeholder = typeAssertion.isUndef(placeholderProp) ? i18n.get('checkTreeSelect.placeholder') : placeholderProp;
@@ -253,6 +260,54 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
253
260
  var nextData = checkedNodes.concat(flattedData);
254
261
  return arrayUtils.uniqBy(nextData, 'id');
255
262
  }, [checkedNodes, flattedData]);
263
+ var toggleCheckAll = React.useCallback(function () {
264
+ var _getAllCheckedStatus = index.getAllCheckedStatus(flattedData, parsedCheckedIds),
265
+ currentAllChecked = _getAllCheckedStatus[0],
266
+ hasCheckedAll = _getAllCheckedStatus[2];
267
+
268
+ var shouldChecked = !currentAllChecked; // 全选操作
269
+
270
+ if (!currentAllChecked && !hasCheckedAll) {
271
+ tryChangeValue(flattedData.filter(function (item) {
272
+ if (!item.disabled) {
273
+ // 根据 checkedMode 类型过滤出已选项,保证全选操作下 onChange 回调的值是符合 checkedMode 的规则
274
+ if (checkedMode === 'CHILD') {
275
+ return !item.children;
276
+ }
277
+
278
+ if (checkedMode === 'PARENT') {
279
+ return item.depth === 0;
280
+ }
281
+
282
+ return true;
283
+ }
284
+
285
+ return false;
286
+ }).map(function (_ref) {
287
+ var id = _ref.id;
288
+ return id;
289
+ }), null, shouldChecked, []);
290
+ } else {
291
+ tryChangeValue([], null, shouldChecked, []);
292
+ }
293
+ }, [checkedMode, flattedData, parsedCheckedIds, tryChangeValue]);
294
+
295
+ var _useMemo = React.useMemo(function () {
296
+ return index.getAllCheckedStatus(flattedData, parsedCheckedIds);
297
+ }, [flattedData, parsedCheckedIds]),
298
+ showAllChecked = _useMemo[0],
299
+ showIndeterminate = _useMemo[1];
300
+
301
+ var renderDefaultFooter = function renderDefaultFooter() {
302
+ if (showCheckAll) {
303
+ return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(Checkbox__default["default"], {
304
+ indeterminate: showIndeterminate,
305
+ checked: showAllChecked,
306
+ onChange: toggleCheckAll
307
+ }, i18n.get('checkSelect.checkAll')));
308
+ }
309
+ };
310
+
256
311
  var cls = classname.cx(prefixCls, className); // 过滤掉未选中的数据
257
312
  // const tagList = useMemo(() => {
258
313
  // // @ts-ignore
@@ -277,6 +332,7 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
277
332
  // data={mergedData}
278
333
  searchable: searchable,
279
334
  onSearch: funcUtils.callAllFuncs(onSearchProp, onSearch),
335
+ footer: renderDefaultFooter(),
280
336
  loading: rest.loading !== undefined ? rest.loading : loading,
281
337
  trigger: /*#__PURE__*/React__default["default"].createElement(tagInput.TagInputMock // ref={targetElementRef}
282
338
  // onClick={openMenu}
@@ -158,5 +158,26 @@ function fillCheck(checkedIds, depthEntities, nodeEntities, maxDepth, allowCheck
158
158
  return Array.from(checkedIdsSet);
159
159
  }
160
160
 
161
+ var getAllCheckedStatus = function getAllCheckedStatus(flattedData, values) {
162
+ var treeIds = flattedData.map(function (_ref) {
163
+ var id = _ref.id;
164
+ return id;
165
+ });
166
+ var treeIdsSet = new Set(treeIds);
167
+ var hasValue = false;
168
+ values.forEach(function (id) {
169
+ if (treeIdsSet.has(id)) {
170
+ hasValue = true;
171
+ treeIdsSet["delete"](id);
172
+ }
173
+ });
174
+ return [hasValue && treeIdsSet.size === 0, hasValue && treeIdsSet.size > 0, // 该值用来判断剩余未选中的节点是否都是 disabled 的
175
+ // 如果为 true 则表示可选值都已选中
176
+ treeIdsSet.size === flattedData.filter(function (item) {
177
+ return item.disabled;
178
+ }).length];
179
+ };
180
+
181
+ exports.getAllCheckedStatus = getAllCheckedStatus;
161
182
  exports.parseCheckDataDirty = parseCheckDataDirty;
162
183
  exports.processCheckedIds = processCheckedIds;
@@ -23,8 +23,10 @@ import { TagInputMock } from '@hi-ui/tag-input';
23
23
  import { UpOutlined, DownOutlined } from '@hi-ui/icons';
24
24
  import { useLocaleContext } from '@hi-ui/core';
25
25
  import { callAllFuncs } from '@hi-ui/func-utils';
26
+ import Checkbox from '@hi-ui/checkbox';
26
27
  import { useAsyncSearch, useTreeCustomSearch, useFilterSearch, useHighlightSearch, useSearchMode } from '@hi-ui/use-search-mode';
27
28
  import { useCheck } from './hooks/use-check.js';
29
+ import { getAllCheckedStatus } from './utils/index.js';
28
30
  var TREE_SELECT_PREFIX = getPrefixCls('check-tree-select');
29
31
  var DEFAULT_DATA = [];
30
32
  var DEFAULT_VALUE = [];
@@ -74,7 +76,8 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
74
76
  virtual = _a.virtual,
75
77
  itemHeight = _a.itemHeight,
76
78
  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"]);
79
+ showCheckAll = _a.showCheckAll,
80
+ 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", "showCheckAll"]);
78
81
 
79
82
  var i18n = useLocaleContext();
80
83
  var placeholder = isUndef(placeholderProp) ? i18n.get('checkTreeSelect.placeholder') : placeholderProp;
@@ -219,6 +222,54 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
219
222
  var nextData = checkedNodes.concat(flattedData);
220
223
  return uniqBy(nextData, 'id');
221
224
  }, [checkedNodes, flattedData]);
225
+ var toggleCheckAll = useCallback(function () {
226
+ var _getAllCheckedStatus = getAllCheckedStatus(flattedData, parsedCheckedIds),
227
+ currentAllChecked = _getAllCheckedStatus[0],
228
+ hasCheckedAll = _getAllCheckedStatus[2];
229
+
230
+ var shouldChecked = !currentAllChecked; // 全选操作
231
+
232
+ if (!currentAllChecked && !hasCheckedAll) {
233
+ tryChangeValue(flattedData.filter(function (item) {
234
+ if (!item.disabled) {
235
+ // 根据 checkedMode 类型过滤出已选项,保证全选操作下 onChange 回调的值是符合 checkedMode 的规则
236
+ if (checkedMode === 'CHILD') {
237
+ return !item.children;
238
+ }
239
+
240
+ if (checkedMode === 'PARENT') {
241
+ return item.depth === 0;
242
+ }
243
+
244
+ return true;
245
+ }
246
+
247
+ return false;
248
+ }).map(function (_ref) {
249
+ var id = _ref.id;
250
+ return id;
251
+ }), null, shouldChecked, []);
252
+ } else {
253
+ tryChangeValue([], null, shouldChecked, []);
254
+ }
255
+ }, [checkedMode, flattedData, parsedCheckedIds, tryChangeValue]);
256
+
257
+ var _useMemo = useMemo(function () {
258
+ return getAllCheckedStatus(flattedData, parsedCheckedIds);
259
+ }, [flattedData, parsedCheckedIds]),
260
+ showAllChecked = _useMemo[0],
261
+ showIndeterminate = _useMemo[1];
262
+
263
+ var renderDefaultFooter = function renderDefaultFooter() {
264
+ if (showCheckAll) {
265
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Checkbox, {
266
+ indeterminate: showIndeterminate,
267
+ checked: showAllChecked,
268
+ onChange: toggleCheckAll
269
+ }, i18n.get('checkSelect.checkAll')));
270
+ }
271
+ };
272
+
222
273
  var cls = cx(prefixCls, className); // 过滤掉未选中的数据
223
274
  // const tagList = useMemo(() => {
224
275
  // // @ts-ignore
@@ -243,6 +294,7 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
243
294
  // data={mergedData}
244
295
  searchable: searchable,
245
296
  onSearch: callAllFuncs(onSearchProp, onSearch),
297
+ footer: renderDefaultFooter(),
246
298
  loading: rest.loading !== undefined ? rest.loading : loading,
247
299
  trigger: /*#__PURE__*/React.createElement(TagInputMock // ref={targetElementRef}
248
300
  // onClick={openMenu}
@@ -150,4 +150,24 @@ function fillCheck(checkedIds, depthEntities, nodeEntities, maxDepth, allowCheck
150
150
  return Array.from(checkedIdsSet);
151
151
  }
152
152
 
153
- export { parseCheckDataDirty, processCheckedIds };
153
+ var getAllCheckedStatus = function getAllCheckedStatus(flattedData, values) {
154
+ var treeIds = flattedData.map(function (_ref) {
155
+ var id = _ref.id;
156
+ return id;
157
+ });
158
+ var treeIdsSet = new Set(treeIds);
159
+ var hasValue = false;
160
+ values.forEach(function (id) {
161
+ if (treeIdsSet.has(id)) {
162
+ hasValue = true;
163
+ treeIdsSet["delete"](id);
164
+ }
165
+ });
166
+ return [hasValue && treeIdsSet.size === 0, hasValue && treeIdsSet.size > 0, // 该值用来判断剩余未选中的节点是否都是 disabled 的
167
+ // 如果为 true 则表示可选值都已选中
168
+ treeIdsSet.size === flattedData.filter(function (item) {
169
+ return item.disabled;
170
+ }).length];
171
+ };
172
+
173
+ export { getAllCheckedStatus, parseCheckDataDirty, processCheckedIds };
@@ -131,6 +131,10 @@ export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChan
131
131
  * 设置 `true` 开启虚拟滚动
132
132
  */
133
133
  virtual?: boolean;
134
+ /**
135
+ * 是否开启全选功能,需要对数据全量操作。异步数据场景暂不支持,可自行渲染弹层底部实现
136
+ */
137
+ showCheckAll?: boolean;
134
138
  }
135
139
  /**
136
140
  * 在 checkedIdsSet 为数据合法的情况下,查找所有的半选中态的节点 ids
@@ -11,3 +11,4 @@ export declare const processCheckedIds: (type: string, checkedIds: React.ReactTe
11
11
  * 根据传入的 checkedIds 解析全选/半选数据
12
12
  */
13
13
  export declare const parseCheckDataDirty: (type: string, checkedIds: React.ReactText[], flattenData: any, allowCheck?: ((node: any) => boolean) | undefined) => React.ReactText[];
14
+ export declare const getAllCheckedStatus: (flattedData: any[], values: React.ReactText[]) => boolean[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hi-ui/check-tree-select",
3
- "version": "4.0.11-beta.0",
3
+ "version": "4.1.0",
4
4
  "description": "A sub-package for @hi-ui/hiui.",
5
5
  "keywords": [],
6
6
  "author": "HiUI <mi-hiui@xiaomi.com>",
@@ -44,12 +44,13 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@hi-ui/array-utils": "^4.0.1",
47
+ "@hi-ui/checkbox": "^4.0.5",
47
48
  "@hi-ui/classname": "^4.0.1",
48
49
  "@hi-ui/env": "^4.0.1",
49
50
  "@hi-ui/func-utils": "^4.0.1",
50
51
  "@hi-ui/highlighter": "^4.0.5",
51
52
  "@hi-ui/icons": "^4.0.4",
52
- "@hi-ui/picker": "^4.0.7-beta.0",
53
+ "@hi-ui/picker": "^4.0.6",
53
54
  "@hi-ui/popper": "^4.0.4",
54
55
  "@hi-ui/tag-input": "^4.0.5",
55
56
  "@hi-ui/tree": "^4.0.9",
@@ -57,7 +58,7 @@
57
58
  "@hi-ui/type-assertion": "^4.0.1",
58
59
  "@hi-ui/use-check": "^4.0.2",
59
60
  "@hi-ui/use-data-source": "^4.0.1",
60
- "@hi-ui/use-search-mode": "^4.0.7-beta.0",
61
+ "@hi-ui/use-search-mode": "^4.0.6",
61
62
  "@hi-ui/use-toggle": "^4.0.1",
62
63
  "@hi-ui/use-uncontrolled-state": "^4.0.1"
63
64
  },