@hi-ui/check-tree-select 5.0.0-canary.2 → 5.0.0-canary.21

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,5 +1,263 @@
1
1
  # @hi-ui/check-tree-select
2
2
 
3
+ ## 5.0.0-canary.21
4
+
5
+ ### Minor Changes
6
+
7
+ - 07a57b9c1: feat(check-tree-select): 支持设置 checkable (5.0)
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [07a57b9c1]
12
+ - Updated dependencies [95d930354]
13
+ - @hi-ui/tree@5.0.0-canary.15
14
+ - @hi-ui/core@5.0.0-canary.8
15
+
16
+ ## 5.0.0-canary.20
17
+
18
+ ### Minor Changes
19
+
20
+ - 59cef699f: feat: 组件语义化样式改造,增加 styles 和 classNames 属性 (5.0)
21
+
22
+ ### Patch Changes
23
+
24
+ - eb17c4697: style: 修复 UI/样式问题 (5.0)
25
+ - Updated dependencies [7f204c892]
26
+ - Updated dependencies [eb17c4697]
27
+ - Updated dependencies [eb17c4697]
28
+ - Updated dependencies [c407744fe]
29
+ - Updated dependencies [59cef699f]
30
+ - @hi-ui/icons@5.0.0-canary.10
31
+ - @hi-ui/core@5.0.0-canary.7
32
+ - @hi-ui/checkbox@5.0.0-canary.8
33
+ - @hi-ui/highlighter@5.0.0-canary.5
34
+ - @hi-ui/picker@5.0.0-canary.16
35
+ - @hi-ui/popper@5.0.0-canary.13
36
+ - @hi-ui/tag-input@5.0.0-canary.22
37
+ - @hi-ui/tree@5.0.0-canary.13
38
+ - @hi-ui/use-merge-semantic@5.0.0-canary.0
39
+
40
+ ## 5.0.0-canary.19
41
+
42
+ ### Patch Changes
43
+
44
+ - 8f23e9322: style: 表单类组件统一调整后缀颜色、placeholder 颜色 (5.0)
45
+ - fe579e212: style(tree): update class names for tree node elements in SCSS (5.0)
46
+ - Updated dependencies [8f23e9322]
47
+ - Updated dependencies [b27483796]
48
+ - Updated dependencies [900c6c2f0]
49
+ - Updated dependencies [fe579e212]
50
+ - @hi-ui/picker@5.0.0-canary.15
51
+ - @hi-ui/tag-input@5.0.0-canary.21
52
+ - @hi-ui/tree@5.0.0-canary.12
53
+
54
+ ## 5.0.0-canary.18
55
+
56
+ ### Patch Changes
57
+
58
+ - d1e7ade1e: styles: 主题定制功能完善&&样式变量化写法改造&&兼容 RTL (5.0)
59
+ - Updated dependencies [d1e7ade1e]
60
+ - Updated dependencies [da16450b4]
61
+ - @hi-ui/checkbox@5.0.0-canary.7
62
+ - @hi-ui/picker@5.0.0-canary.14
63
+ - @hi-ui/popper@5.0.0-canary.12
64
+ - @hi-ui/tag-input@5.0.0-canary.20
65
+ - @hi-ui/tree@5.0.0-canary.9
66
+ - @hi-ui/icons@5.0.0-canary.8
67
+
68
+ ## 5.0.0-canary.17
69
+
70
+ ### Patch Changes
71
+
72
+ - 58db39510: style: fix ui bug (5.0)
73
+ - Updated dependencies [58db39510]
74
+ - @hi-ui/icons@5.0.0-canary.7
75
+ - @hi-ui/popper@5.0.0-canary.11
76
+ - @hi-ui/tag-input@5.0.0-canary.19
77
+ - @hi-ui/tree@5.0.0-canary.8
78
+
79
+ ## 5.0.0-canary.16
80
+
81
+ ### Minor Changes
82
+
83
+ - 2b706fc6d: feat(picker): 增加 clearSearchOnClosed api 默认是 false (5.0)
84
+ - 922686dcc: feat(global-context): 增加 size api 全局配置 (5.0)
85
+
86
+ ### Patch Changes
87
+
88
+ - 86877b241: style: 修改样式问题 (5.0)
89
+ - Updated dependencies [2b706fc6d]
90
+ - Updated dependencies [86877b241]
91
+ - Updated dependencies [922686dcc]
92
+ - @hi-ui/picker@5.0.0-canary.12
93
+ - @hi-ui/checkbox@5.0.0-canary.5
94
+ - @hi-ui/highlighter@5.0.0-canary.4
95
+ - @hi-ui/popper@5.0.0-canary.8
96
+ - @hi-ui/tag-input@5.0.0-canary.17
97
+ - @hi-ui/tree@5.0.0-canary.6
98
+ - @hi-ui/core@5.0.0-canary.5
99
+ - @hi-ui/icons@5.0.0-canary.5
100
+
101
+ ## 5.0.0-canary.15
102
+
103
+ ### Patch Changes
104
+
105
+ - 13a222d13: feat(picker): add header api (5.0)
106
+ - Updated dependencies [13a222d13]
107
+ - @hi-ui/picker@5.0.0-canary.11
108
+
109
+ ## 5.0.0-canary.14
110
+
111
+ ### Minor Changes
112
+
113
+ - e97485c24: feat: 下拉选择组件增加 showIndicator 参数 & 修改 appearance 中的 unset 样式 (5.0)
114
+
115
+ ### Patch Changes
116
+
117
+ - Updated dependencies [e97485c24]
118
+ - Updated dependencies [f0b3272a1]
119
+ - @hi-ui/tag-input@5.0.0-canary.16
120
+ - @hi-ui/use-search-mode@5.0.0-canary.5
121
+
122
+ ## 5.0.0-canary.13
123
+
124
+ ### Patch Changes
125
+
126
+ - 8db6414b6: fix(check-tree-select): 更新全选逻辑,使用 dataMemo 替代 flattedData,确保状态正确 (#3323)
127
+ - Updated dependencies [8db6414b6]
128
+ - @hi-ui/use-search-mode@5.0.0-canary.4
129
+
130
+ ## 5.0.0-canary.12
131
+
132
+ ### Patch Changes
133
+
134
+ - eba118692: perf: 对下拉选择类组件的 customRender 的内容增加 memoization 以优化性能 (5.0)
135
+ - Updated dependencies [eaf6005e4]
136
+ - Updated dependencies [dddcb76c7]
137
+ - @hi-ui/tag-input@5.0.0-canary.15
138
+ - @hi-ui/checkbox@5.0.0-canary.4
139
+
140
+ ## 5.0.0-canary.11
141
+
142
+ ### Patch Changes
143
+
144
+ - 53b45cd5d: style(tag-input): 增加 flex-wrap 属性以优化标签换行展示 (5.0)
145
+ - Updated dependencies [53b45cd5d]
146
+ - @hi-ui/tag-input@5.0.0-canary.14
147
+
148
+ ## 5.0.0-canary.10
149
+
150
+ ### Minor Changes
151
+
152
+ - 9106dca82: feat: 输入框和选择器组件增加 borderless 形态 (5.0)
153
+
154
+ ### Patch Changes
155
+
156
+ - Updated dependencies [efce04a26]
157
+ - Updated dependencies [9106dca82]
158
+ - @hi-ui/checkbox@5.0.0-canary.3
159
+ - @hi-ui/picker@5.0.0-canary.10
160
+ - @hi-ui/popper@5.0.0-canary.6
161
+ - @hi-ui/core@5.0.0-canary.3
162
+ - @hi-ui/tag-input@5.0.0-canary.12
163
+ - @hi-ui/icons@5.0.0-canary.3
164
+ - @hi-ui/highlighter@5.0.0-canary.3
165
+ - @hi-ui/tree@5.0.0-canary.4
166
+
167
+ ## 5.0.0-canary.9
168
+
169
+ ### Patch Changes
170
+
171
+ - 643c0e09f: style(picker): 移除 picker 组件中的 \_\_text 样式定义 (5.0)
172
+ - Updated dependencies [d7d87fb57]
173
+ - Updated dependencies [b8c19048f]
174
+ - @hi-ui/tag-input@5.0.0-canary.11
175
+
176
+ ## 5.0.0-canary.8
177
+
178
+ ### Patch Changes
179
+
180
+ - dc1311a91: fix(check-tree-select): 完善 dataSource 功能,支持搜索结果高亮和展开 (#3247)
181
+ - Updated dependencies [dc1311a91]
182
+ - @hi-ui/use-search-mode@5.0.0-canary.3
183
+
184
+ ## 5.0.0-canary.7
185
+
186
+ ### Patch Changes
187
+
188
+ - 807b7c644: fix(tag-input): 修复 contained 模式下 displayRender 设置无效问题 (5.0)
189
+ - Updated dependencies [807b7c644]
190
+ - @hi-ui/tag-input@5.0.0-canary.10
191
+
192
+ ## 5.0.0-canary.6
193
+
194
+ ### Patch Changes
195
+
196
+ - chore: rebase master (5.0)
197
+ - Updated dependencies
198
+ - @hi-ui/core@5.0.0-canary.2
199
+ - @hi-ui/use-check@5.0.0-canary.2
200
+ - @hi-ui/use-data-source@5.0.0-canary.2
201
+ - @hi-ui/use-search-mode@5.0.0-canary.2
202
+ - @hi-ui/use-toggle@5.0.0-canary.2
203
+ - @hi-ui/use-uncontrolled-state@5.0.0-canary.2
204
+ - @hi-ui/icons@5.0.0-canary.2
205
+ - @hi-ui/checkbox@5.0.0-canary.2
206
+ - @hi-ui/highlighter@5.0.0-canary.2
207
+ - @hi-ui/picker@5.0.0-canary.8
208
+ - @hi-ui/popper@5.0.0-canary.3
209
+ - @hi-ui/tag-input@5.0.0-canary.8
210
+ - @hi-ui/tree@5.0.0-canary.3
211
+ - @hi-ui/array-utils@5.0.0-canary.2
212
+ - @hi-ui/classname@5.0.0-canary.2
213
+ - @hi-ui/env@5.0.0-canary.2
214
+ - @hi-ui/func-utils@5.0.0-canary.2
215
+ - @hi-ui/tree-utils@5.0.0-canary.2
216
+ - @hi-ui/type-assertion@5.0.0-canary.2
217
+
218
+ ## 5.0.0-canary.5
219
+
220
+ ### Patch Changes
221
+
222
+ - 4b09e728b: build: 将 package.json 中 exports 配置中的 types 配置放在最上面 (5.0)
223
+ - Updated dependencies [ba7c324c2]
224
+ - Updated dependencies [ba7c324c2]
225
+ - Updated dependencies [4b09e728b]
226
+ - Updated dependencies [ba7c324c2]
227
+ - @hi-ui/tree@5.0.0-canary.2
228
+ - @hi-ui/picker@5.0.0-canary.7
229
+ - @hi-ui/core@5.0.0-canary.1
230
+ - @hi-ui/use-check@5.0.0-canary.1
231
+ - @hi-ui/use-data-source@5.0.0-canary.1
232
+ - @hi-ui/use-search-mode@5.0.0-canary.1
233
+ - @hi-ui/use-toggle@5.0.0-canary.1
234
+ - @hi-ui/use-uncontrolled-state@5.0.0-canary.1
235
+ - @hi-ui/icons@5.0.0-canary.1
236
+ - @hi-ui/checkbox@5.0.0-canary.1
237
+ - @hi-ui/highlighter@5.0.0-canary.1
238
+ - @hi-ui/popper@5.0.0-canary.2
239
+ - @hi-ui/tag-input@5.0.0-canary.7
240
+ - @hi-ui/array-utils@5.0.0-canary.1
241
+ - @hi-ui/classname@5.0.0-canary.1
242
+ - @hi-ui/env@5.0.0-canary.1
243
+ - @hi-ui/func-utils@5.0.0-canary.1
244
+ - @hi-ui/tree-utils@5.0.0-canary.1
245
+ - @hi-ui/type-assertion@5.0.0-canary.1
246
+
247
+ ## 5.0.0-canary.4
248
+
249
+ ### Patch Changes
250
+
251
+ - 40f819417: fix: 修复 UI 问题 (5.0)
252
+ - Updated dependencies [40f819417]
253
+ - @hi-ui/tag-input@5.0.0-canary.6
254
+
255
+ ## 5.0.0-canary.3
256
+
257
+ ### Patch Changes
258
+
259
+ - a89b3b3ae: fix: 修改组件问题 (5.0)
260
+
3
261
  ## 5.0.0-canary.2
4
262
 
5
263
  ### Patch Changes
@@ -21,6 +21,7 @@ var useToggle = require('@hi-ui/use-toggle');
21
21
  var tree = require('@hi-ui/tree');
22
22
  var useUncontrolledState = require('@hi-ui/use-uncontrolled-state');
23
23
  var picker = require('@hi-ui/picker');
24
+ var useMergeSemantic = require('@hi-ui/use-merge-semantic');
24
25
  var treeUtils = require('@hi-ui/tree-utils');
25
26
  var typeAssertion = require('@hi-ui/type-assertion');
26
27
  var arrayUtils = require('@hi-ui/array-utils');
@@ -49,6 +50,7 @@ var DEFAULT_EXPANDED_IDS = [];
49
50
  * 多项树形选择器
50
51
  */
51
52
  var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
53
+ var _b;
52
54
  var _a$prefixCls = _a.prefixCls,
53
55
  prefixCls = _a$prefixCls === void 0 ? TREE_SELECT_PREFIX : _a$prefixCls,
54
56
  className = _a.className,
@@ -81,7 +83,9 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
81
83
  filterOption = _a.filterOption,
82
84
  keywordProp = _a.keyword,
83
85
  onSearchProp = _a.onSearch,
86
+ clearSearchOnClosed = _a.clearSearchOnClosed,
84
87
  clearable = _a.clearable,
88
+ onClear = _a.onClear,
85
89
  invalid = _a.invalid,
86
90
  displayRender = _a.displayRender,
87
91
  placeholderProp = _a.placeholder,
@@ -93,14 +97,39 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
93
97
  _a$showOnlyShowChecke = _a.showOnlyShowChecked,
94
98
  showOnlyShowChecked = _a$showOnlyShowChecke === void 0 ? false : _a$showOnlyShowChecke,
95
99
  tagInputProps = _a.tagInputProps,
96
- _a$size = _a.size,
97
- size = _a$size === void 0 ? 'md' : _a$size,
100
+ sizeProp = _a.size,
98
101
  customRender = _a.customRender,
99
102
  prefix = _a.prefix,
100
103
  suffix = _a.suffix,
101
104
  label = _a.label,
102
- 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", "keyword", "onSearch", "clearable", "invalid", "displayRender", "placeholder", "appearance", "virtual", "itemHeight", "height", "showCheckAll", "showOnlyShowChecked", "tagInputProps", "size", "customRender", "prefix", "suffix", "label"]);
105
+ _a$showIndicator = _a.showIndicator,
106
+ showIndicator = _a$showIndicator === void 0 ? true : _a$showIndicator,
107
+ renderExtraHeader = _a.renderExtraHeader,
108
+ classNamesProp = _a.classNames,
109
+ stylesProp = _a.styles,
110
+ 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", "keyword", "onSearch", "clearSearchOnClosed", "clearable", "onClear", "invalid", "displayRender", "placeholder", "appearance", "virtual", "itemHeight", "height", "showCheckAll", "showOnlyShowChecked", "tagInputProps", "size", "customRender", "prefix", "suffix", "label", "showIndicator", "renderExtraHeader", "renderExtraFooter", "classNames", "styles"]);
111
+ var _useGlobalContext = core.useGlobalContext(),
112
+ globalSize = _useGlobalContext.size,
113
+ checkTreeSelectConfig = _useGlobalContext.checkTreeSelect;
114
+ var size = (_b = sizeProp !== null && sizeProp !== void 0 ? sizeProp : globalSize) !== null && _b !== void 0 ? _b : 'md';
103
115
  var i18n = core.useLocaleContext();
116
+ var _useMergeSemantic = useMergeSemantic.useMergeSemantic({
117
+ classNamesList: [checkTreeSelectConfig === null || checkTreeSelectConfig === void 0 ? void 0 : checkTreeSelectConfig.classNames, classNamesProp],
118
+ stylesList: [checkTreeSelectConfig === null || checkTreeSelectConfig === void 0 ? void 0 : checkTreeSelectConfig.styles, stylesProp],
119
+ info: {
120
+ props: Object.assign(Object.assign({}, rest), {
121
+ data: data,
122
+ disabled: disabled,
123
+ searchable: searchableProp,
124
+ visible: visible,
125
+ size: size,
126
+ appearance: appearance
127
+ })
128
+ }
129
+ }),
130
+ classNames = _useMergeSemantic.classNames,
131
+ styles = _useMergeSemantic.styles;
132
+ var pickerInnerRef = React.useRef(null);
104
133
  var placeholder = typeAssertion.isUndef(placeholderProp) ? i18n.get('checkTreeSelect.placeholder') : placeholderProp;
105
134
  var _useUncontrolledToggl = useToggle.useUncontrolledToggle({
106
135
  visible: visible,
@@ -121,7 +150,7 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
121
150
  var getKeyFields = React.useCallback(function (node, key) {
122
151
  return node[fieldNames[key] || key];
123
152
  }, [fieldNames]);
124
- var flattedData = React.useMemo(function () {
153
+ var flatData = React.useCallback(function (data) {
125
154
  return treeUtils.baseFlattenTree({
126
155
  tree: data,
127
156
  childrenFieldName: function childrenFieldName(node) {
@@ -135,10 +164,14 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
135
164
  flattedNode.title = getKeyFields(raw, 'title');
136
165
  flattedNode.disabled = (_a = getKeyFields(raw, 'disabled')) !== null && _a !== void 0 ? _a : false;
137
166
  flattedNode.isLeaf = (_b = getKeyFields(raw, 'isLeaf')) !== null && _b !== void 0 ? _b : false;
167
+ flattedNode.checkable = raw.checkable !== false;
138
168
  return flattedNode;
139
169
  }
140
170
  });
141
- }, [data, getKeyFields]);
171
+ }, [getKeyFields]);
172
+ var flattedData = React.useMemo(function () {
173
+ return flatData(data);
174
+ }, [data, flatData]);
142
175
  // TODO: 抽离展开hook
143
176
  // TODO: onLoadChildren 和 defaultExpandAll 共存时
144
177
  var _useUncontrolledState = useUncontrolledState.useUncontrolledState(function getDefaultExpandedIds() {
@@ -152,34 +185,15 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
152
185
  }, expandedIdsProp, onExpand),
153
186
  expandedIds = _useUncontrolledState[0],
154
187
  tryChangeExpandedIds = _useUncontrolledState[1];
155
- var _useCheck = useCheck.useCheck(checkedMode, disabled, flattedData, defaultValue, valueProp, onChange),
156
- value = _useCheck[0],
157
- tryChangeValue = _useCheck[1],
158
- onNodeCheck = _useCheck[2],
159
- checkedNodes = _useCheck[3],
160
- parsedCheckedIds = _useCheck[4];
161
- var onCheck = React.useCallback(function (checkedIds, option) {
162
- var targetNode = option.targetNode,
163
- checked = option.checked;
164
- onNodeCheck(targetNode, checked);
165
- }, [onNodeCheck]);
166
- var onValueChange = React.useCallback(function (values, targetItem, shouldChecked) {
167
- // 清空
168
- if (values.length === 0) {
169
- tryChangeValue([], null, shouldChecked, []);
170
- } else {
171
- // 操作单个
172
- onNodeCheck(targetItem[0], shouldChecked);
173
- }
174
- }, [tryChangeValue, onNodeCheck]);
175
188
  // ************************** 异步搜索 ************************* //
176
189
  // const { loading, hasError, loadRemoteData } = useDataSource({ dataSource, validate: isArray })
177
- var _b = useSearchMode.useAsyncSearch({
178
- dataSource: dataSource
190
+ var _c = useSearchMode.useAsyncSearch({
191
+ dataSource: dataSource,
192
+ expandAll: true
179
193
  }),
180
- loading = _b.loading,
181
- hasError = _b.hasError,
182
- dataSourceStrategy = tslib.__rest(_b, ["loading", "hasError"]);
194
+ loading = _c.loading,
195
+ hasError = _c.hasError,
196
+ dataSourceStrategy = tslib.__rest(_c, ["loading", "hasError"]);
183
197
  var customSearchStrategy = useSearchMode.useTreeCustomSearch({
184
198
  data: data,
185
199
  filterOption: filterOption
@@ -206,6 +220,30 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
206
220
  searchMode = _useSearchMode.searchMode,
207
221
  onSearch = _useSearchMode.onSearch,
208
222
  searchValue = _useSearchMode.keyword;
223
+ var dataMemo = React.useMemo(function () {
224
+ var flattedStateData = flatData(stateInSearch.data);
225
+ return typeAssertion.isArrayNonEmpty(flattedStateData) ? flattedStateData : flattedData;
226
+ }, [flatData, stateInSearch.data, flattedData]);
227
+ var _useCheck = useCheck.useCheck(checkedMode, disabled, dataMemo, defaultValue, valueProp, onChange),
228
+ value = _useCheck[0],
229
+ tryChangeValue = _useCheck[1],
230
+ onNodeCheck = _useCheck[2],
231
+ checkedNodes = _useCheck[3],
232
+ parsedCheckedIds = _useCheck[4];
233
+ var onCheck = React.useCallback(function (checkedIds, option) {
234
+ var targetNode = option.targetNode,
235
+ checked = option.checked;
236
+ onNodeCheck(targetNode, checked);
237
+ }, [onNodeCheck]);
238
+ var onValueChange = React.useCallback(function (values, targetItem, shouldChecked) {
239
+ // 清空
240
+ if (values.length === 0) {
241
+ tryChangeValue([], null, shouldChecked, []);
242
+ } else {
243
+ // 操作单个
244
+ onNodeCheck(targetItem[0], shouldChecked);
245
+ }
246
+ }, [tryChangeValue, onNodeCheck]);
209
247
  // 拦截 titleRender,自定义高亮展示
210
248
  var proxyTitleRender = React.useCallback(function (node) {
211
249
  if (titleRender) {
@@ -213,12 +251,14 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
213
251
  if (_ret && _ret !== true) return _ret;
214
252
  }
215
253
  // 本地搜索执行默认高亮规则
216
- var highlight = !!searchValue && (searchMode === 'highlight' || searchMode === 'filter');
217
- var ret = highlight ? /*#__PURE__*/React__default["default"].createElement(highlighter.Highlighter, {
218
- keyword: searchValue
219
- }, node.title) : true;
254
+ var highlight = !!searchValue && (searchMode === 'highlight' || searchMode === 'filter' || dataSource);
255
+ // 转义正则表达式特殊字符,避免 searchValue 包含 [ 等特殊字符时报错
256
+ var escapedSearchValue = searchValue.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
257
+ var ret = highlight ? ( /*#__PURE__*/React__default["default"].createElement(highlighter.Highlighter, {
258
+ keyword: new RegExp(escapedSearchValue, 'ig')
259
+ }, node.title)) : true;
220
260
  return ret;
221
- }, [titleRender, searchValue, searchMode]);
261
+ }, [titleRender, searchValue, searchMode, dataSource]);
222
262
  var shouldUseSearch = !!searchValue && !hasError;
223
263
  var showData = shouldUseSearch ? stateInSearch.data : data;
224
264
  var treeProps = {
@@ -239,24 +279,24 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
239
279
  return arrayUtils.uniqBy(nextData, 'id');
240
280
  }, [checkedNodes, flattedData]);
241
281
  var toggleCheckAll = React.useCallback(function () {
242
- var _getAllCheckedStatus = index.getAllCheckedStatus(flattedData, parsedCheckedIds),
282
+ var _getAllCheckedStatus = index.getAllCheckedStatus(dataMemo, parsedCheckedIds),
243
283
  currentAllChecked = _getAllCheckedStatus[0],
244
284
  hasCheckedAll = _getAllCheckedStatus[2];
245
285
  var shouldChecked = !currentAllChecked;
246
286
  // 全选操作
247
287
  if (!currentAllChecked && !hasCheckedAll) {
248
- tryChangeValue(flattedData.filter(function (item) {
249
- if (!item.disabled) {
250
- // 根据 checkedMode 类型过滤出已选项,保证全选操作下 onChange 回调的值是符合 checkedMode 的规则
251
- if (checkedMode === 'CHILD') {
252
- return !item.children;
253
- }
254
- if (checkedMode === 'PARENT') {
255
- return item.depth === 0;
256
- }
257
- return true;
288
+ tryChangeValue(dataMemo.filter(function (item) {
289
+ if (item.disabled || item.checkable === false) {
290
+ return false;
291
+ }
292
+ // 根据 checkedMode 类型过滤出已选项,保证全选操作下 onChange 回调的值是符合 checkedMode 的规则
293
+ if (checkedMode === 'CHILD') {
294
+ return !item.children;
295
+ }
296
+ if (checkedMode === 'PARENT') {
297
+ return item.depth === 0;
258
298
  }
259
- return false;
299
+ return true;
260
300
  }).map(function (_ref) {
261
301
  var id = _ref.id;
262
302
  return id;
@@ -264,10 +304,10 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
264
304
  } else {
265
305
  tryChangeValue([], null, shouldChecked, []);
266
306
  }
267
- }, [checkedMode, flattedData, parsedCheckedIds, tryChangeValue]);
307
+ }, [checkedMode, dataMemo, parsedCheckedIds, tryChangeValue]);
268
308
  var _useMemo = React.useMemo(function () {
269
- return index.getAllCheckedStatus(flattedData, parsedCheckedIds);
270
- }, [flattedData, parsedCheckedIds]),
309
+ return index.getAllCheckedStatus(dataMemo, parsedCheckedIds);
310
+ }, [dataMemo, parsedCheckedIds]),
271
311
  showAllChecked = _useMemo[0],
272
312
  showIndeterminate = _useMemo[1];
273
313
  var renderDefaultFooter = function renderDefaultFooter() {
@@ -279,6 +319,9 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
279
319
  }, i18n.get('checkSelect.checkAll')));
280
320
  }
281
321
  };
322
+ var customRenderContent = React.useMemo(function () {
323
+ return customRender ? typeof customRender === 'function' ? customRender(checkedNodes) : customRender : null;
324
+ }, [customRender, checkedNodes]);
282
325
  var cls = classname.cx(prefixCls, className);
283
326
  // 过滤掉未选中的数据
284
327
  // const tagList = useMemo(() => {
@@ -287,9 +330,32 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
287
330
  // const ids = Array.from(new Set([...semiCheckedIds, ...value]))
288
331
  // return flattedData.filter((item) => ids.includes(item.id))
289
332
  // }, [value, flattedData])
333
+ React.useEffect(function () {
334
+ var _a;
335
+ if (menuVisible) {
336
+ // 数据改变时更新弹窗显示位置,避免弹窗内容被遮挡
337
+ (_a = pickerInnerRef.current) === null || _a === void 0 ? void 0 : _a.update();
338
+ }
339
+ }, [menuVisible, treeProps.expandedIds]);
340
+ var pickerSemanticKeys = ['root', 'container', 'panel', 'header', 'search', 'body', 'footer', 'loading', 'empty', 'creator'];
341
+ var pickerClassNames = pickerSemanticKeys.reduce(function (acc, key) {
342
+ if ((classNames === null || classNames === void 0 ? void 0 : classNames[key]) !== undefined) {
343
+ acc[key] = classNames[key];
344
+ }
345
+ return acc;
346
+ }, {});
347
+ var pickerStyles = pickerSemanticKeys.reduce(function (acc, key) {
348
+ if (styles === null || styles === void 0 ? void 0 : styles[key]) {
349
+ acc[key] = styles[key];
350
+ }
351
+ return acc;
352
+ }, {});
290
353
  return /*#__PURE__*/React__default["default"].createElement(picker.Picker, Object.assign({
291
354
  ref: ref,
292
- className: cls
355
+ innerRef: pickerInnerRef,
356
+ className: cls,
357
+ classNames: pickerClassNames,
358
+ styles: pickerStyles
293
359
  }, rest, {
294
360
  visible: menuVisible,
295
361
  onOpen: function onOpen() {
@@ -304,9 +370,11 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
304
370
  searchable: searchable,
305
371
  keyword: keywordProp,
306
372
  onSearch: funcUtils.callAllFuncs(onSearchProp, onSearch),
373
+ clearSearchOnClosed: clearSearchOnClosed,
307
374
  footer: renderDefaultFooter(),
308
375
  loading: rest.loading !== undefined ? rest.loading : loading,
309
- trigger: customRender ? typeof customRender === 'function' ? customRender(checkedNodes) : customRender : ( /*#__PURE__*/React__default["default"].createElement(tagInput.TagInputMock, Object.assign({
376
+ header: renderExtraHeader === null || renderExtraHeader === void 0 ? void 0 : renderExtraHeader(),
377
+ trigger: customRender ? customRenderContent : ( /*#__PURE__*/React__default["default"].createElement(tagInput.TagInputMock, Object.assign({
310
378
  style: {
311
379
  maxWidth: appearance === 'contained' ? '360px' : undefined
312
380
  }
@@ -317,10 +385,12 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
317
385
  // onClick={openMenu}
318
386
  // disabled={disabled}
319
387
  clearable: clearable,
388
+ onClear: onClear,
320
389
  placeholder: placeholder,
321
390
  // @ts-ignore
322
391
  displayRender: displayRender,
323
392
  prefix: prefix,
393
+ showIndicator: showIndicator,
324
394
  suffix: [menuVisible ? /*#__PURE__*/React__default["default"].createElement(icons.UpOutlined, null) : /*#__PURE__*/React__default["default"].createElement(icons.DownOutlined, null), suffix],
325
395
  focused: menuVisible,
326
396
  appearance: appearance,
@@ -389,7 +459,8 @@ var CheckTreeSelect = /*#__PURE__*/React.forwardRef(function (_a, ref) {
389
459
  // 只做渲染,不做逻辑处理(比如搜索过滤后,check操作的是对过滤后的data操作,这是不符合预期的)
390
460
  React__default["default"].createElement(tree.Tree, Object.assign({
391
461
  size: 'md',
392
- className: prefixCls + "__tree",
462
+ className: classname.cx(prefixCls + "__tree", classNames === null || classNames === void 0 ? void 0 : classNames.tree),
463
+ style: styles === null || styles === void 0 ? void 0 : styles.tree,
393
464
  selectable: false,
394
465
  checkable: true,
395
466
  checkOnSelect: true,
@@ -78,6 +78,9 @@ var allowCheck = function allowCheck(targetItem) {
78
78
  if (targetItem.disabled) {
79
79
  return false;
80
80
  }
81
+ if (targetItem.checkable === false) {
82
+ return false;
83
+ }
81
84
  return true;
82
85
  };
83
86
  exports.useCheck = useCheck;
@@ -120,12 +120,21 @@ function fillCheck(checkedIds, depthEntities, nodeEntities, maxDepth, allowCheck
120
120
  children = entity.children;
121
121
  if (visitedIds.has(id)) return;
122
122
  if (typeAssertion.isArrayNonEmpty(children)) {
123
- var shouldChecked = !children.some(function (child) {
123
+ // 可勾选子节点需在 checkedIds;disabled / checkable:false 但有子树时走 visitedIds;
124
+ // checkable:false 且无子节点(纯展示叶)不阻塞父级全选
125
+ var childFails = function childFails(child) {
126
+ if (!allowCheck(child)) {
127
+ if (typeAssertion.isArrayNonEmpty(child.children)) {
128
+ return visitedIds.has(child.id) ? !visitedIds.get(child.id) : true;
129
+ }
130
+ return false;
131
+ }
124
132
  if (visitedIds.has(child.id)) {
125
133
  return !visitedIds.get(child.id);
126
134
  }
127
135
  return !checkedIdsSet.has(child.id);
128
- });
136
+ };
137
+ var shouldChecked = !children.some(childFails);
129
138
  visitedIds.set(id, shouldChecked);
130
139
  if (shouldChecked && allowCheck(entity)) {
131
140
  checkedIdsSet.add(id);
@@ -148,12 +157,19 @@ var getAllCheckedStatus = function getAllCheckedStatus(flattedData, values) {
148
157
  treeIdsSet["delete"](id);
149
158
  }
150
159
  });
151
- return [hasValue && treeIdsSet.size === 0, hasValue && treeIdsSet.size > 0,
160
+ var nonCheckableCount = flattedData.filter(function (item) {
161
+ return item.disabled || item.checkable === false;
162
+ }).length;
163
+ var onlyNonCheckableLeft = treeIdsSet.size > 0 && [].concat(treeIdsSet).every(function (id) {
164
+ var n = flattedData.find(function (item) {
165
+ return item.id === id;
166
+ });
167
+ return n && (n.disabled || n.checkable === false);
168
+ });
169
+ return [hasValue && (treeIdsSet.size === 0 || onlyNonCheckableLeft), hasValue && treeIdsSet.size > 0 && !onlyNonCheckableLeft,
152
170
  // 该值用来判断剩余未选中的节点是否都是 disabled 的
153
171
  // 如果为 true 则表示可选值都已选中
154
- treeIdsSet.size === flattedData.filter(function (item) {
155
- return item.disabled;
156
- }).length];
172
+ treeIdsSet.size === nonCheckableCount];
157
173
  };
158
174
  exports.getAllCheckedStatus = getAllCheckedStatus;
159
175
  exports.parseCheckDataDirty = parseCheckDataDirty;
@@ -8,20 +8,21 @@
8
8
  * LICENSE file in the root directory of this source tree.
9
9
  */
10
10
  import { __rest } from 'tslib';
11
- import React, { forwardRef, useState, useRef, useCallback, useMemo } from 'react';
11
+ import React, { forwardRef, useRef, useState, useCallback, useMemo, useEffect } from 'react';
12
12
  import { getPrefixCls, cx } from '@hi-ui/classname';
13
13
  import { __DEV__ } from '@hi-ui/env';
14
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 { useMergeSemantic } from '@hi-ui/use-merge-semantic';
18
19
  import { baseFlattenTree, filterTree } from '@hi-ui/tree-utils';
19
20
  import { isUndef, isArrayNonEmpty } from '@hi-ui/type-assertion';
20
21
  import { uniqBy } from '@hi-ui/array-utils';
21
22
  import { Highlighter } from '@hi-ui/highlighter';
22
23
  import { TagInputMock } from '@hi-ui/tag-input';
23
24
  import { UpOutlined, DownOutlined } from '@hi-ui/icons';
24
- import { useLocaleContext } from '@hi-ui/core';
25
+ import { useGlobalContext, useLocaleContext } from '@hi-ui/core';
25
26
  import { callAllFuncs } from '@hi-ui/func-utils';
26
27
  import Checkbox from '@hi-ui/checkbox';
27
28
  import { useAsyncSearch, useTreeCustomSearch, useFilterSearch, useHighlightSearch, useSearchMode } from '@hi-ui/use-search-mode';
@@ -36,6 +37,7 @@ var DEFAULT_EXPANDED_IDS = [];
36
37
  * 多项树形选择器
37
38
  */
38
39
  var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
40
+ var _b;
39
41
  var _a$prefixCls = _a.prefixCls,
40
42
  prefixCls = _a$prefixCls === void 0 ? TREE_SELECT_PREFIX : _a$prefixCls,
41
43
  className = _a.className,
@@ -68,7 +70,9 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
68
70
  filterOption = _a.filterOption,
69
71
  keywordProp = _a.keyword,
70
72
  onSearchProp = _a.onSearch,
73
+ clearSearchOnClosed = _a.clearSearchOnClosed,
71
74
  clearable = _a.clearable,
75
+ onClear = _a.onClear,
72
76
  invalid = _a.invalid,
73
77
  displayRender = _a.displayRender,
74
78
  placeholderProp = _a.placeholder,
@@ -80,14 +84,39 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
80
84
  _a$showOnlyShowChecke = _a.showOnlyShowChecked,
81
85
  showOnlyShowChecked = _a$showOnlyShowChecke === void 0 ? false : _a$showOnlyShowChecke,
82
86
  tagInputProps = _a.tagInputProps,
83
- _a$size = _a.size,
84
- size = _a$size === void 0 ? 'md' : _a$size,
87
+ sizeProp = _a.size,
85
88
  customRender = _a.customRender,
86
89
  prefix = _a.prefix,
87
90
  suffix = _a.suffix,
88
91
  label = _a.label,
89
- 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", "keyword", "onSearch", "clearable", "invalid", "displayRender", "placeholder", "appearance", "virtual", "itemHeight", "height", "showCheckAll", "showOnlyShowChecked", "tagInputProps", "size", "customRender", "prefix", "suffix", "label"]);
92
+ _a$showIndicator = _a.showIndicator,
93
+ showIndicator = _a$showIndicator === void 0 ? true : _a$showIndicator,
94
+ renderExtraHeader = _a.renderExtraHeader,
95
+ classNamesProp = _a.classNames,
96
+ stylesProp = _a.styles,
97
+ 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", "keyword", "onSearch", "clearSearchOnClosed", "clearable", "onClear", "invalid", "displayRender", "placeholder", "appearance", "virtual", "itemHeight", "height", "showCheckAll", "showOnlyShowChecked", "tagInputProps", "size", "customRender", "prefix", "suffix", "label", "showIndicator", "renderExtraHeader", "renderExtraFooter", "classNames", "styles"]);
98
+ var _useGlobalContext = useGlobalContext(),
99
+ globalSize = _useGlobalContext.size,
100
+ checkTreeSelectConfig = _useGlobalContext.checkTreeSelect;
101
+ var size = (_b = sizeProp !== null && sizeProp !== void 0 ? sizeProp : globalSize) !== null && _b !== void 0 ? _b : 'md';
90
102
  var i18n = useLocaleContext();
103
+ var _useMergeSemantic = useMergeSemantic({
104
+ classNamesList: [checkTreeSelectConfig === null || checkTreeSelectConfig === void 0 ? void 0 : checkTreeSelectConfig.classNames, classNamesProp],
105
+ stylesList: [checkTreeSelectConfig === null || checkTreeSelectConfig === void 0 ? void 0 : checkTreeSelectConfig.styles, stylesProp],
106
+ info: {
107
+ props: Object.assign(Object.assign({}, rest), {
108
+ data: data,
109
+ disabled: disabled,
110
+ searchable: searchableProp,
111
+ visible: visible,
112
+ size: size,
113
+ appearance: appearance
114
+ })
115
+ }
116
+ }),
117
+ classNames = _useMergeSemantic.classNames,
118
+ styles = _useMergeSemantic.styles;
119
+ var pickerInnerRef = useRef(null);
91
120
  var placeholder = isUndef(placeholderProp) ? i18n.get('checkTreeSelect.placeholder') : placeholderProp;
92
121
  var _useUncontrolledToggl = useUncontrolledToggle({
93
122
  visible: visible,
@@ -108,7 +137,7 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
108
137
  var getKeyFields = useCallback(function (node, key) {
109
138
  return node[fieldNames[key] || key];
110
139
  }, [fieldNames]);
111
- var flattedData = useMemo(function () {
140
+ var flatData = useCallback(function (data) {
112
141
  return baseFlattenTree({
113
142
  tree: data,
114
143
  childrenFieldName: function childrenFieldName(node) {
@@ -122,10 +151,14 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
122
151
  flattedNode.title = getKeyFields(raw, 'title');
123
152
  flattedNode.disabled = (_a = getKeyFields(raw, 'disabled')) !== null && _a !== void 0 ? _a : false;
124
153
  flattedNode.isLeaf = (_b = getKeyFields(raw, 'isLeaf')) !== null && _b !== void 0 ? _b : false;
154
+ flattedNode.checkable = raw.checkable !== false;
125
155
  return flattedNode;
126
156
  }
127
157
  });
128
- }, [data, getKeyFields]);
158
+ }, [getKeyFields]);
159
+ var flattedData = useMemo(function () {
160
+ return flatData(data);
161
+ }, [data, flatData]);
129
162
  // TODO: 抽离展开hook
130
163
  // TODO: onLoadChildren 和 defaultExpandAll 共存时
131
164
  var _useUncontrolledState = useUncontrolledState(function getDefaultExpandedIds() {
@@ -139,34 +172,15 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
139
172
  }, expandedIdsProp, onExpand),
140
173
  expandedIds = _useUncontrolledState[0],
141
174
  tryChangeExpandedIds = _useUncontrolledState[1];
142
- var _useCheck = useCheck(checkedMode, disabled, flattedData, defaultValue, valueProp, onChange),
143
- value = _useCheck[0],
144
- tryChangeValue = _useCheck[1],
145
- onNodeCheck = _useCheck[2],
146
- checkedNodes = _useCheck[3],
147
- parsedCheckedIds = _useCheck[4];
148
- var onCheck = useCallback(function (checkedIds, option) {
149
- var targetNode = option.targetNode,
150
- checked = option.checked;
151
- onNodeCheck(targetNode, checked);
152
- }, [onNodeCheck]);
153
- var onValueChange = useCallback(function (values, targetItem, shouldChecked) {
154
- // 清空
155
- if (values.length === 0) {
156
- tryChangeValue([], null, shouldChecked, []);
157
- } else {
158
- // 操作单个
159
- onNodeCheck(targetItem[0], shouldChecked);
160
- }
161
- }, [tryChangeValue, onNodeCheck]);
162
175
  // ************************** 异步搜索 ************************* //
163
176
  // const { loading, hasError, loadRemoteData } = useDataSource({ dataSource, validate: isArray })
164
- var _b = useAsyncSearch({
165
- dataSource: dataSource
177
+ var _c = useAsyncSearch({
178
+ dataSource: dataSource,
179
+ expandAll: true
166
180
  }),
167
- loading = _b.loading,
168
- hasError = _b.hasError,
169
- dataSourceStrategy = __rest(_b, ["loading", "hasError"]);
181
+ loading = _c.loading,
182
+ hasError = _c.hasError,
183
+ dataSourceStrategy = __rest(_c, ["loading", "hasError"]);
170
184
  var customSearchStrategy = useTreeCustomSearch({
171
185
  data: data,
172
186
  filterOption: filterOption
@@ -193,6 +207,30 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
193
207
  searchMode = _useSearchMode.searchMode,
194
208
  onSearch = _useSearchMode.onSearch,
195
209
  searchValue = _useSearchMode.keyword;
210
+ var dataMemo = useMemo(function () {
211
+ var flattedStateData = flatData(stateInSearch.data);
212
+ return isArrayNonEmpty(flattedStateData) ? flattedStateData : flattedData;
213
+ }, [flatData, stateInSearch.data, flattedData]);
214
+ var _useCheck = useCheck(checkedMode, disabled, dataMemo, defaultValue, valueProp, onChange),
215
+ value = _useCheck[0],
216
+ tryChangeValue = _useCheck[1],
217
+ onNodeCheck = _useCheck[2],
218
+ checkedNodes = _useCheck[3],
219
+ parsedCheckedIds = _useCheck[4];
220
+ var onCheck = useCallback(function (checkedIds, option) {
221
+ var targetNode = option.targetNode,
222
+ checked = option.checked;
223
+ onNodeCheck(targetNode, checked);
224
+ }, [onNodeCheck]);
225
+ var onValueChange = useCallback(function (values, targetItem, shouldChecked) {
226
+ // 清空
227
+ if (values.length === 0) {
228
+ tryChangeValue([], null, shouldChecked, []);
229
+ } else {
230
+ // 操作单个
231
+ onNodeCheck(targetItem[0], shouldChecked);
232
+ }
233
+ }, [tryChangeValue, onNodeCheck]);
196
234
  // 拦截 titleRender,自定义高亮展示
197
235
  var proxyTitleRender = useCallback(function (node) {
198
236
  if (titleRender) {
@@ -200,12 +238,14 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
200
238
  if (_ret && _ret !== true) return _ret;
201
239
  }
202
240
  // 本地搜索执行默认高亮规则
203
- var highlight = !!searchValue && (searchMode === 'highlight' || searchMode === 'filter');
204
- var ret = highlight ? /*#__PURE__*/React.createElement(Highlighter, {
205
- keyword: searchValue
206
- }, node.title) : true;
241
+ var highlight = !!searchValue && (searchMode === 'highlight' || searchMode === 'filter' || dataSource);
242
+ // 转义正则表达式特殊字符,避免 searchValue 包含 [ 等特殊字符时报错
243
+ var escapedSearchValue = searchValue.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
244
+ var ret = highlight ? ( /*#__PURE__*/React.createElement(Highlighter, {
245
+ keyword: new RegExp(escapedSearchValue, 'ig')
246
+ }, node.title)) : true;
207
247
  return ret;
208
- }, [titleRender, searchValue, searchMode]);
248
+ }, [titleRender, searchValue, searchMode, dataSource]);
209
249
  var shouldUseSearch = !!searchValue && !hasError;
210
250
  var showData = shouldUseSearch ? stateInSearch.data : data;
211
251
  var treeProps = {
@@ -226,24 +266,24 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
226
266
  return uniqBy(nextData, 'id');
227
267
  }, [checkedNodes, flattedData]);
228
268
  var toggleCheckAll = useCallback(function () {
229
- var _getAllCheckedStatus = getAllCheckedStatus(flattedData, parsedCheckedIds),
269
+ var _getAllCheckedStatus = getAllCheckedStatus(dataMemo, parsedCheckedIds),
230
270
  currentAllChecked = _getAllCheckedStatus[0],
231
271
  hasCheckedAll = _getAllCheckedStatus[2];
232
272
  var shouldChecked = !currentAllChecked;
233
273
  // 全选操作
234
274
  if (!currentAllChecked && !hasCheckedAll) {
235
- tryChangeValue(flattedData.filter(function (item) {
236
- if (!item.disabled) {
237
- // 根据 checkedMode 类型过滤出已选项,保证全选操作下 onChange 回调的值是符合 checkedMode 的规则
238
- if (checkedMode === 'CHILD') {
239
- return !item.children;
240
- }
241
- if (checkedMode === 'PARENT') {
242
- return item.depth === 0;
243
- }
244
- return true;
275
+ tryChangeValue(dataMemo.filter(function (item) {
276
+ if (item.disabled || item.checkable === false) {
277
+ return false;
278
+ }
279
+ // 根据 checkedMode 类型过滤出已选项,保证全选操作下 onChange 回调的值是符合 checkedMode 的规则
280
+ if (checkedMode === 'CHILD') {
281
+ return !item.children;
282
+ }
283
+ if (checkedMode === 'PARENT') {
284
+ return item.depth === 0;
245
285
  }
246
- return false;
286
+ return true;
247
287
  }).map(function (_ref) {
248
288
  var id = _ref.id;
249
289
  return id;
@@ -251,10 +291,10 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
251
291
  } else {
252
292
  tryChangeValue([], null, shouldChecked, []);
253
293
  }
254
- }, [checkedMode, flattedData, parsedCheckedIds, tryChangeValue]);
294
+ }, [checkedMode, dataMemo, parsedCheckedIds, tryChangeValue]);
255
295
  var _useMemo = useMemo(function () {
256
- return getAllCheckedStatus(flattedData, parsedCheckedIds);
257
- }, [flattedData, parsedCheckedIds]),
296
+ return getAllCheckedStatus(dataMemo, parsedCheckedIds);
297
+ }, [dataMemo, parsedCheckedIds]),
258
298
  showAllChecked = _useMemo[0],
259
299
  showIndeterminate = _useMemo[1];
260
300
  var renderDefaultFooter = function renderDefaultFooter() {
@@ -266,6 +306,9 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
266
306
  }, i18n.get('checkSelect.checkAll')));
267
307
  }
268
308
  };
309
+ var customRenderContent = useMemo(function () {
310
+ return customRender ? typeof customRender === 'function' ? customRender(checkedNodes) : customRender : null;
311
+ }, [customRender, checkedNodes]);
269
312
  var cls = cx(prefixCls, className);
270
313
  // 过滤掉未选中的数据
271
314
  // const tagList = useMemo(() => {
@@ -274,9 +317,32 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
274
317
  // const ids = Array.from(new Set([...semiCheckedIds, ...value]))
275
318
  // return flattedData.filter((item) => ids.includes(item.id))
276
319
  // }, [value, flattedData])
320
+ useEffect(function () {
321
+ var _a;
322
+ if (menuVisible) {
323
+ // 数据改变时更新弹窗显示位置,避免弹窗内容被遮挡
324
+ (_a = pickerInnerRef.current) === null || _a === void 0 ? void 0 : _a.update();
325
+ }
326
+ }, [menuVisible, treeProps.expandedIds]);
327
+ var pickerSemanticKeys = ['root', 'container', 'panel', 'header', 'search', 'body', 'footer', 'loading', 'empty', 'creator'];
328
+ var pickerClassNames = pickerSemanticKeys.reduce(function (acc, key) {
329
+ if ((classNames === null || classNames === void 0 ? void 0 : classNames[key]) !== undefined) {
330
+ acc[key] = classNames[key];
331
+ }
332
+ return acc;
333
+ }, {});
334
+ var pickerStyles = pickerSemanticKeys.reduce(function (acc, key) {
335
+ if (styles === null || styles === void 0 ? void 0 : styles[key]) {
336
+ acc[key] = styles[key];
337
+ }
338
+ return acc;
339
+ }, {});
277
340
  return /*#__PURE__*/React.createElement(Picker, Object.assign({
278
341
  ref: ref,
279
- className: cls
342
+ innerRef: pickerInnerRef,
343
+ className: cls,
344
+ classNames: pickerClassNames,
345
+ styles: pickerStyles
280
346
  }, rest, {
281
347
  visible: menuVisible,
282
348
  onOpen: function onOpen() {
@@ -291,9 +357,11 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
291
357
  searchable: searchable,
292
358
  keyword: keywordProp,
293
359
  onSearch: callAllFuncs(onSearchProp, onSearch),
360
+ clearSearchOnClosed: clearSearchOnClosed,
294
361
  footer: renderDefaultFooter(),
295
362
  loading: rest.loading !== undefined ? rest.loading : loading,
296
- trigger: customRender ? typeof customRender === 'function' ? customRender(checkedNodes) : customRender : ( /*#__PURE__*/React.createElement(TagInputMock, Object.assign({
363
+ header: renderExtraHeader === null || renderExtraHeader === void 0 ? void 0 : renderExtraHeader(),
364
+ trigger: customRender ? customRenderContent : ( /*#__PURE__*/React.createElement(TagInputMock, Object.assign({
297
365
  style: {
298
366
  maxWidth: appearance === 'contained' ? '360px' : undefined
299
367
  }
@@ -304,10 +372,12 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
304
372
  // onClick={openMenu}
305
373
  // disabled={disabled}
306
374
  clearable: clearable,
375
+ onClear: onClear,
307
376
  placeholder: placeholder,
308
377
  // @ts-ignore
309
378
  displayRender: displayRender,
310
379
  prefix: prefix,
380
+ showIndicator: showIndicator,
311
381
  suffix: [menuVisible ? /*#__PURE__*/React.createElement(UpOutlined, null) : /*#__PURE__*/React.createElement(DownOutlined, null), suffix],
312
382
  focused: menuVisible,
313
383
  appearance: appearance,
@@ -376,7 +446,8 @@ var CheckTreeSelect = /*#__PURE__*/forwardRef(function (_a, ref) {
376
446
  // 只做渲染,不做逻辑处理(比如搜索过滤后,check操作的是对过滤后的data操作,这是不符合预期的)
377
447
  React.createElement(Tree, Object.assign({
378
448
  size: 'md',
379
- className: prefixCls + "__tree",
449
+ className: cx(prefixCls + "__tree", classNames === null || classNames === void 0 ? void 0 : classNames.tree),
450
+ style: styles === null || styles === void 0 ? void 0 : styles.tree,
380
451
  selectable: false,
381
452
  checkable: true,
382
453
  checkOnSelect: true,
@@ -73,6 +73,9 @@ var allowCheck = function allowCheck(targetItem) {
73
73
  if (targetItem.disabled) {
74
74
  return false;
75
75
  }
76
+ if (targetItem.checkable === false) {
77
+ return false;
78
+ }
76
79
  return true;
77
80
  };
78
81
  export { useCheck };
@@ -115,12 +115,21 @@ function fillCheck(checkedIds, depthEntities, nodeEntities, maxDepth, allowCheck
115
115
  children = entity.children;
116
116
  if (visitedIds.has(id)) return;
117
117
  if (isArrayNonEmpty(children)) {
118
- var shouldChecked = !children.some(function (child) {
118
+ // 可勾选子节点需在 checkedIds;disabled / checkable:false 但有子树时走 visitedIds;
119
+ // checkable:false 且无子节点(纯展示叶)不阻塞父级全选
120
+ var childFails = function childFails(child) {
121
+ if (!allowCheck(child)) {
122
+ if (isArrayNonEmpty(child.children)) {
123
+ return visitedIds.has(child.id) ? !visitedIds.get(child.id) : true;
124
+ }
125
+ return false;
126
+ }
119
127
  if (visitedIds.has(child.id)) {
120
128
  return !visitedIds.get(child.id);
121
129
  }
122
130
  return !checkedIdsSet.has(child.id);
123
- });
131
+ };
132
+ var shouldChecked = !children.some(childFails);
124
133
  visitedIds.set(id, shouldChecked);
125
134
  if (shouldChecked && allowCheck(entity)) {
126
135
  checkedIdsSet.add(id);
@@ -143,11 +152,18 @@ var getAllCheckedStatus = function getAllCheckedStatus(flattedData, values) {
143
152
  treeIdsSet["delete"](id);
144
153
  }
145
154
  });
146
- return [hasValue && treeIdsSet.size === 0, hasValue && treeIdsSet.size > 0,
155
+ var nonCheckableCount = flattedData.filter(function (item) {
156
+ return item.disabled || item.checkable === false;
157
+ }).length;
158
+ var onlyNonCheckableLeft = treeIdsSet.size > 0 && [].concat(treeIdsSet).every(function (id) {
159
+ var n = flattedData.find(function (item) {
160
+ return item.id === id;
161
+ });
162
+ return n && (n.disabled || n.checkable === false);
163
+ });
164
+ return [hasValue && (treeIdsSet.size === 0 || onlyNonCheckableLeft), hasValue && treeIdsSet.size > 0 && !onlyNonCheckableLeft,
147
165
  // 该值用来判断剩余未选中的节点是否都是 disabled 的
148
166
  // 如果为 true 则表示可选值都已选中
149
- treeIdsSet.size === flattedData.filter(function (item) {
150
- return item.disabled;
151
- }).length];
167
+ treeIdsSet.size === nonCheckableCount];
152
168
  };
153
169
  export { getAllCheckedStatus, parseCheckDataDirty, processCheckedIds };
@@ -1,14 +1,20 @@
1
1
  import React from 'react';
2
2
  import { CheckTreeSelectDataItem, CheckTreeSelectItemEventData, CheckTreeSelectAppearanceEnum } from './types';
3
3
  import { FlattedTreeNodeData } from '@hi-ui/tree';
4
- import { PickerProps } from '@hi-ui/picker';
4
+ import { PickerProps, PickerSemanticName } from '@hi-ui/picker';
5
+ import type { ComponentSemantic, SemanticClassNamesType, SemanticStylesType } from '@hi-ui/use-merge-semantic';
5
6
  import { TagInputMockProps } from '@hi-ui/tag-input';
6
7
  import { HiBaseSizeEnum } from '@hi-ui/core';
8
+ import { UseDataSource } from '@hi-ui/use-data-source';
7
9
  /**
8
10
  * 多项树形选择器
9
11
  */
10
12
  export declare const CheckTreeSelect: React.ForwardRefExoticComponent<CheckTreeSelectProps & React.RefAttributes<HTMLDivElement | null>>;
11
- export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChange' | 'value' | 'trigger' | 'scrollable'> {
13
+ export declare type CheckTreeSelectSemanticName = PickerSemanticName | 'tree';
14
+ export declare type CheckTreeSelectSemanticClassNames = SemanticClassNamesType<CheckTreeSelectProps, CheckTreeSelectSemanticName>;
15
+ export declare type CheckTreeSelectSemanticStyles = SemanticStylesType<CheckTreeSelectProps, CheckTreeSelectSemanticName>;
16
+ export declare type CheckTreeSelectSemantic = ComponentSemantic<CheckTreeSelectSemanticClassNames, CheckTreeSelectSemanticStyles>;
17
+ export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChange' | 'value' | 'trigger' | 'scrollable' | 'header' | 'footer' | 'classNames' | 'styles'>, CheckTreeSelectSemantic {
12
18
  /**
13
19
  * 展示数据
14
20
  */
@@ -86,6 +92,7 @@ export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChan
86
92
  /**
87
93
  * 异步加载数据。暂不对外暴露
88
94
  */
95
+ dataSource?: UseDataSource<CheckTreeSelectDataItem[]>;
89
96
  /**
90
97
  * 没有选项时的提示
91
98
  */
@@ -115,6 +122,10 @@ export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChan
115
122
  * 是否可清空
116
123
  */
117
124
  clearable?: boolean;
125
+ /**
126
+ * 点击关闭按钮时触发
127
+ */
128
+ onClear?: () => void;
118
129
  /**
119
130
  * 设置展现形式
120
131
  */
@@ -165,6 +176,18 @@ export interface CheckTreeSelectProps extends Omit<PickerProps, 'data' | 'onChan
165
176
  * 选择框后置内容
166
177
  */
167
178
  suffix?: React.ReactNode;
179
+ /**
180
+ * 是否展示箭头
181
+ */
182
+ showIndicator?: boolean;
183
+ /**
184
+ * 自定义下拉菜单顶部渲染
185
+ */
186
+ renderExtraHeader?: () => React.ReactNode;
187
+ /**
188
+ * 自定义下拉菜单底部渲染
189
+ */
190
+ renderExtraFooter?: () => React.ReactNode;
168
191
  }
169
192
  /**
170
193
  * 在 checkedIdsSet 为数据合法的情况下,查找所有的半选中态的节点 ids
@@ -22,6 +22,11 @@ export interface CheckTreeSelectDataItem extends HiBaseDataItem {
22
22
  * 是否为叶子节点,当 children 为空数组也表示为叶子结点
23
23
  */
24
24
  isLeaf?: boolean;
25
+ /**
26
+ * 节点是否展示复选框;为 `false` 时不展示复选框,且该节点不可被勾选(常用于仅作分组/展开的节点)
27
+ * @default true
28
+ */
29
+ checkable?: boolean;
25
30
  }
26
31
  export interface FlattedCheckTreeSelectDataItem extends CheckTreeSelectDataItem {
27
32
  /**
@@ -76,5 +81,9 @@ export interface CheckTreeSelectDataSource<T = any> {
76
81
  transformResponse?: (response: object) => T;
77
82
  }
78
83
  export interface CheckTreeSelectItemEventData extends TreeNodeEventData {
84
+ /**
85
+ * 节点是否展示复选框(与数据项 `checkable` 一致,由 Tree 扁平化后透传)
86
+ */
87
+ checkable?: boolean;
79
88
  }
80
89
  export declare type CheckTreeSelectAppearanceEnum = HiBaseAppearanceEnum | 'contained' | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hi-ui/check-tree-select",
3
- "version": "5.0.0-canary.2",
3
+ "version": "5.0.0-canary.21",
4
4
  "description": "A sub-package for @hi-ui/hiui.",
5
5
  "keywords": [],
6
6
  "author": "HiUI <mi-hiui@xiaomi.com>",
@@ -19,9 +19,9 @@
19
19
  "typings": "lib/types/index.d.ts",
20
20
  "exports": {
21
21
  ".": {
22
+ "types": "./lib/types/index.d.ts",
22
23
  "require": "./lib/cjs/index.js",
23
- "default": "./lib/esm/index.js",
24
- "types": "./lib/types/index.d.ts"
24
+ "default": "./lib/esm/index.js"
25
25
  }
26
26
  },
27
27
  "publishConfig": {
@@ -44,33 +44,34 @@
44
44
  "url": "https://github.com/XiaoMi/hiui/issues"
45
45
  },
46
46
  "dependencies": {
47
- "@hi-ui/array-utils": "^5.0.0-canary.0",
48
- "@hi-ui/checkbox": "^5.0.0-canary.0",
49
- "@hi-ui/classname": "^5.0.0-canary.0",
50
- "@hi-ui/env": "^5.0.0-canary.0",
51
- "@hi-ui/func-utils": "^5.0.0-canary.0",
52
- "@hi-ui/highlighter": "^5.0.0-canary.0",
53
- "@hi-ui/icons": "^5.0.0-canary.0",
54
- "@hi-ui/picker": "^5.0.0-canary.3",
55
- "@hi-ui/popper": "^5.0.0-canary.0",
56
- "@hi-ui/tag-input": "^5.0.0-canary.4",
57
- "@hi-ui/tree": "^5.0.0-canary.0",
58
- "@hi-ui/tree-utils": "^5.0.0-canary.0",
59
- "@hi-ui/type-assertion": "^5.0.0-canary.0",
60
- "@hi-ui/use-check": "^5.0.0-canary.0",
61
- "@hi-ui/use-data-source": "^5.0.0-canary.0",
62
- "@hi-ui/use-search-mode": "^5.0.0-canary.0",
63
- "@hi-ui/use-toggle": "^5.0.0-canary.0",
64
- "@hi-ui/use-uncontrolled-state": "^5.0.0-canary.0"
47
+ "@hi-ui/array-utils": "^5.0.0-canary.2",
48
+ "@hi-ui/checkbox": "^5.0.0-canary.8",
49
+ "@hi-ui/classname": "^5.0.0-canary.2",
50
+ "@hi-ui/env": "^5.0.0-canary.2",
51
+ "@hi-ui/func-utils": "^5.0.0-canary.2",
52
+ "@hi-ui/highlighter": "^5.0.0-canary.5",
53
+ "@hi-ui/icons": "^5.0.0-canary.10",
54
+ "@hi-ui/picker": "^5.0.0-canary.16",
55
+ "@hi-ui/popper": "^5.0.0-canary.13",
56
+ "@hi-ui/tag-input": "^5.0.0-canary.22",
57
+ "@hi-ui/tree": "^5.0.0-canary.15",
58
+ "@hi-ui/tree-utils": "^5.0.0-canary.2",
59
+ "@hi-ui/type-assertion": "^5.0.0-canary.2",
60
+ "@hi-ui/use-check": "^5.0.0-canary.2",
61
+ "@hi-ui/use-data-source": "^5.0.0-canary.2",
62
+ "@hi-ui/use-merge-semantic": "^5.0.0-canary.0",
63
+ "@hi-ui/use-search-mode": "^5.0.0-canary.5",
64
+ "@hi-ui/use-toggle": "^5.0.0-canary.2",
65
+ "@hi-ui/use-uncontrolled-state": "^5.0.0-canary.2"
65
66
  },
66
67
  "peerDependencies": {
67
- "@hi-ui/core": ">=5.0.0-canary.0",
68
+ "@hi-ui/core": ">=5.0.0-canary.8",
68
69
  "react": ">=16.8.6",
69
70
  "react-dom": ">=16.8.6"
70
71
  },
71
72
  "devDependencies": {
72
- "@hi-ui/core": "^5.0.0-canary.0",
73
- "@hi-ui/core-css": "^5.0.0-canary.2",
73
+ "@hi-ui/core": "^5.0.0-canary.8",
74
+ "@hi-ui/core-css": "^5.0.0-canary.11",
74
75
  "react": "^17.0.1",
75
76
  "react-dom": "^17.0.1"
76
77
  }