UNPKG

13.6 kBJavaScriptView Raw
1import _extends from "@babel/runtime/helpers/extends";
2import "core-js/modules/es7.array.includes";
3import "core-js/modules/es6.string.includes";
4import "core-js/modules/es6.regexp.split";
5import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
6import React, { useCallback, useMemo, useState, useEffect, useRef } from 'react';
7import Layer from '@beisen-phoenix/unmodeled-layer';
8import Select from '@beisen-phoenix/select/';
9import SingleSelect from '@beisen-phoenix/single-select-list';
10import GroupSingleSelect from '@beisen-phoenix/group-single-select';
11import MultipleSelect from '@beisen-phoenix/multi-select-list';
12import FormControlPreview from '@beisen-phoenix/form-control-preview';
13import { getFilterdOptions, getDisplayLabel } from './utils';
14import './index.css';
15import utils from '@beisen-phoenix/common-utils';
16var classes = utils.BEMClass('fieldDropdown');
17
18var onChange = function onChange(data) {};
19
20var FieldDropdown = function FieldDropdown(props) {
21 var _props$optionSearch = props.optionSearch,
22 optionSearch = _props$optionSearch === void 0 ? false : _props$optionSearch,
23 _props$showCheckAll = props.showCheckAll,
24 showCheckAll = _props$showCheckAll === void 0 ? true : _props$showCheckAll,
25 _props$hasError = props.hasError,
26 hasError = _props$hasError === void 0 ? false : _props$hasError,
27 _props$isPreview = props.isPreview,
28 isPreview = _props$isPreview === void 0 ? false : _props$isPreview,
29 _props$selectType = props.selectType,
30 selectType = _props$selectType === void 0 ? 'single' : _props$selectType,
31 _props$disabled = props.disabled,
32 disabled = _props$disabled === void 0 ? false : _props$disabled,
33 layerWidth = props.layerWidth,
34 onBlur = props.onBlur,
35 _props$selectIsActive = props.selectIsActive,
36 selectIsActive = _props$selectIsActive === void 0 ? false : _props$selectIsActive,
37 _props$autoFocus = props.autoFocus,
38 autoFocus = _props$autoFocus === void 0 ? false : _props$autoFocus,
39 _props$hostSubmit = props.hostSubmit,
40 hostSubmit = _props$hostSubmit === void 0 ? false : _props$hostSubmit,
41 caseSensitive = props.caseSensitive,
42 optionSearchAutoFocus = props.optionSearchAutoFocus,
43 _props$splitKey = props.splitKey,
44 splitKey = _props$splitKey === void 0 ? ',' : _props$splitKey;
45 var isSearch = disabled ? false : 'isSearch' in props ? props.isSearch : true; // 控制弹层显示与否
46
47 var _useState = useState(autoFocus),
48 _useState2 = _slicedToArray(_useState, 2),
49 visible = _useState2[0],
50 setVisible = _useState2[1];
51
52 var _useState3 = useState(autoFocus),
53 _useState4 = _slicedToArray(_useState3, 2),
54 selectFocus = _useState4[0],
55 setSelectFocus = _useState4[1];
56
57 var layerWrapperRef = useRef();
58 var isWrapperInRef = useRef(false); //input的node节点
59
60 var inputRef = useRef();
61 var isBlurRef = useRef(false);
62 var isSelectClickRef = useRef(false); // 控制选择器显示的label
63 // const [displayLabel, setDisplayLabel] = useState();
64 // 控制弹层中选中的列表
65
66 var _useState5 = useState(props.value || ''),
67 _useState6 = _slicedToArray(_useState5, 2),
68 selectedValue = _useState6[0],
69 setSelectedValue = _useState6[1]; // 控制弹层中选中的列表(multiSelect模式)
70
71
72 var _useState7 = useState(props.value || ''),
73 _useState8 = _slicedToArray(_useState7, 2),
74 selectedValueForMultiSelect = _useState8[0],
75 setSelectedValueForMultiSelect = _useState8[1]; // 搜索的关键词
76
77
78 var _useState9 = useState(),
79 _useState10 = _slicedToArray(_useState9, 2),
80 searchWord = _useState10[0],
81 setSearchWord = _useState10[1];
82
83 useEffect(function () {
84 setSelectedValue(props.value || '');
85 }, [props.value]);
86 useEffect(function () {
87 setSelectedValueForMultiSelect(props.value || '');
88 }, [props.value]); //控制弹层显示与否
89
90 var toggleLayer = useCallback(function (visible) {
91 if (disabled) return; // 如果是禁用状态,需要禁止弹层展开
92
93 if (visible) setSearchWord(''); // 打开弹层时,清除搜索内容
94
95 visible && setSelectedValue(selectedValue);
96
97 if (visible && selectType === 'multiple') {
98 // 此操作是为了解决复选后,在没点击确定的情况下关闭弹层再打开弹层时产生的数据不一致问题
99 var selectLength = selectedValue && selectedValue.split(splitKey).length;
100 var tmpLength = selectedValueForMultiSelect && selectedValueForMultiSelect.split(splitKey).length;
101
102 if (tmpLength !== selectLength) {
103 setSelectedValueForMultiSelect(selectedValue);
104 }
105 }
106
107 if (isSelectClickRef.current) {
108 setVisible(true);
109 isSelectClickRef.current = false;
110 } else {
111 setVisible(visible);
112 }
113
114 if (visible) setSelectFocus(true);
115 }, [selectedValue, selectedValueForMultiSelect, disabled]); // 点击删除按钮时的回调
116
117 var onDelete = useCallback(function (data) {
118 if (data) {
119 var val = data.map(function (item) {
120 return item.value;
121 }).join(splitKey);
122 setSelectedValue(val);
123 setSelectedValueForMultiSelect(val);
124 props.onChange && props.onChange(val);
125 } else {
126 // 点击input 的删除按钮
127 setSearchWord('');
128
129 if (selectType !== 'multiple') {
130 setSelectedValue('');
131 setSelectedValueForMultiSelect('');
132 props.onChange && props.onChange('');
133 }
134 }
135
136 setVisible(false);
137 }, [props.onChange]); // keyUp搜索时的回调
138
139 var onSearch = useCallback(function (data) {
140 setSearchWord(data);
141 }, []); // 选中某个选项的时候触发
142
143 var onSelect = useCallback(function (data) {
144 if (selectType !== 'multiple') {
145 setSelectedValue(data.value);
146 setVisible(false);
147 props.onChange && props.onChange(data.value);
148
149 if (layerWrapperRef.current) {
150 layerWrapperRef.current.focus();
151 }
152 } else {
153 // 本次选择到的值
154 var newData = data.map(function (item) {
155 return item.value;
156 });
157
158 if (searchWord) {
159 // 已选择的值
160 var selectedArr = selectedValue && selectedValue.split(splitKey) || []; // 搜索到的值
161
162 var searchdValue = getFilterdOptions(selectType, props.options, searchWord, caseSensitive).map(function (item) {
163 return item.value;
164 }); // 可能丢失的值
165
166 var mayLost = selectedArr.filter(function (v) {
167 return searchdValue.indexOf(v) > -1;
168 }); // 真正丢失的值
169
170 var realLost = mayLost.filter(function (item) {
171 return !newData.includes(item);
172 }); // 清除掉丢失的值
173
174 realLost.forEach(function (item) {
175 var index = selectedArr.indexOf(item);
176 if (index !== -1) selectedArr.splice(index, 1);
177 }); // 增加不存在的值
178
179 for (var ind in newData) {
180 if (!selectedArr.includes(newData[ind])) {
181 selectedArr.push(newData[ind]);
182 }
183 }
184
185 setSelectedValueForMultiSelect(selectedArr.join(splitKey));
186 } else {
187 setSelectedValueForMultiSelect(newData.join(splitKey));
188 }
189
190 if (layerWrapperRef.current) {
191 layerWrapperRef.current.focus();
192 }
193 }
194
195 setSelectFocus(true);
196 }, [selectType, selectedValue, searchWord]);
197
198 var afterOnClick = function afterOnClick(values) {
199 setSelectedValue(values);
200 setSearchWord('');
201 setVisible(false);
202 }; // 底部确定按钮 只有复选的时候会出现 点击关闭弹层
203
204
205 var footer = useMemo(function () {
206 var values = selectedValueForMultiSelect;
207 return selectType == 'multiple' ? [{
208 text: '确定',
209 onClick: function onClick() {
210 if (hostSubmit) {
211 props.onChange && props.onChange(values, function () {
212 afterOnClick(values);
213 });
214 afterOnClick(values);
215 } else {
216 props.onChange && props.onChange(values);
217 afterOnClick(values);
218 }
219
220 if (layerWrapperRef.current) {
221 layerWrapperRef.current.focus();
222 }
223 }
224 }] : null;
225 }, [selectType, selectedValueForMultiSelect, selectedValue, props.onChange]);
226
227 var getSelectList = function getSelectList() {
228 // 如果设置了isSearch = true 则禁用弹层的搜索功能
229 // 如果设置了isSearch = false 并且设置了optionSearch = true 则开启弹层搜索功能
230 // 如果设置isSearch = false 并且设置了optionSearch = false 则不开启任何搜索功能
231 var canSearch = isSearch ? false : optionSearch ? true : false;
232 var options = searchWord ? getFilterdOptions(selectType, props.options, searchWord, caseSensitive) : props.options;
233 var selectContent;
234
235 if (selectType == 'group') {
236 selectContent = React.createElement(GroupSingleSelect, {
237 searchWord: searchWord,
238 value: selectedValue,
239 options: options,
240 onChange: onSelect,
241 caseSensitive: caseSensitive,
242 autoFocus: optionSearchAutoFocus
243 });
244 }
245
246 if (selectType == 'multiple') {
247 var selectedData = selectedValueForMultiSelect ? options.filter(function (item) {
248 return selectedValueForMultiSelect.split(splitKey).includes(item.value);
249 }) : undefined;
250 selectContent = React.createElement(MultipleSelect, {
251 searchWord: searchWord,
252 showCheckAll: showCheckAll,
253 defaultSelectedItems: selectedData,
254 isSearch: canSearch // searchWord={searchWord}
255 ,
256 items: options,
257 extraCls: classes({
258 element: 'multiSelect'
259 }),
260 onChange: onSelect,
261 caseSensitive: caseSensitive,
262 autoFocus: optionSearchAutoFocus
263 });
264 }
265
266 if (!selectContent) {
267 selectContent = React.createElement(SingleSelect, {
268 searchWord: searchWord,
269 selectedValue: selectedValue,
270 items: options,
271 isSearch: canSearch,
272 onChange: onSelect,
273 caseSensitive: caseSensitive,
274 autoFocus: optionSearchAutoFocus
275 });
276 }
277
278 return selectContent;
279 };
280
281 var getPopupContainer = useCallback(function () {// debugger
282 // if(props.getPopupContainer){
283 // return getPopupContainer();
284 // }else{
285 // return layerWrapperRef.current
286 // }
287 }, [props.getPopupContainer]);
288 var handleWrapperBlur = useCallback(function () {
289 if (!visible && !isWrapperInRef.current && !isBlurRef.current) {
290 onBlur && onBlur();
291 isBlurRef.current = true;
292 setTimeout(function () {
293 isBlurRef.current = false;
294 }, 10);
295 setSelectFocus(false);
296 }
297 }, [visible, onBlur]); //为了解决多选带搜索时,不能触发外层div的blur事件
298
299 var handleWrapperMouseEnterLeave = useCallback(function (flag) {
300 return function (e) {
301 isWrapperInRef.current = flag;
302 };
303 }, []);
304 var getInputRef = useCallback(function (node) {
305 inputRef.current = node;
306 }, []); // useEffect(() => {
307 // if (autoFocus) {
308 // console.log(
309 // 'aaaa',
310 // getDisplayLabel(
311 // props.options,
312 // selectType,
313 // selectedValue,
314 // props.disabled && props.displayLabel
315 // )
316 // );
317 // inputRef.current && inputRef.current.click();
318 // }
319 // }, []);
320 //复杂参数控制,是为了实现给外界onBlur能够在正确的时机调用
321
322 useEffect(function () {
323 if (inputRef.current) {
324 inputRef.current.onblur = function () {
325 if (!visible && !isWrapperInRef.current && !isBlurRef.current) {
326 onBlur && onBlur();
327 setSelectFocus(false);
328 isBlurRef.current = true;
329 setTimeout(function () {
330 isBlurRef.current = false;
331 }, 10);
332 }
333 };
334 }
335 }, [onBlur, visible]);
336 useEffect(function () {
337 if (autoFocus && inputRef.current) {
338 inputRef.current.focus();
339 }
340 }, []); //select的点击事件
341
342 var handleSelectClick = useCallback(function () {
343 if (isSearch) {
344 isSelectClickRef.current = true;
345 }
346 }, [isSearch]);
347
348 if (isPreview) {
349 return React.createElement(FormControlPreview, {
350 multiple: selectType === 'multiple',
351 value: getDisplayLabel(props.options, selectType, selectedValue, props.displayLabel, splitKey)
352 });
353 }
354
355 return React.createElement(Layer, {
356 blockContainer: true,
357 trigger: ['click'],
358 content: visible ? getSelectList() : null,
359 visible: visible,
360 zIndex: props.zIndex,
361 onVisibleChange: toggleLayer,
362 footer: props.options.length > 0 ? footer : null,
363 width: layerWidth,
364 getPopupContainer: props.getPopupContainer,
365 destroyPopupOnHide: true,
366 stretch: props.stretch
367 }, React.createElement("div", {
368 tabIndex: 2,
369 className: "select_dropdown_wrapper",
370 onMouseEnter: handleWrapperMouseEnterLeave(true),
371 onMouseLeave: handleWrapperMouseEnterLeave(false),
372 ref: layerWrapperRef,
373 onBlur: handleWrapperBlur
374 }, React.createElement(Select, _extends({}, props, {
375 extraCls: classes({
376 element: '',
377 extra: props.extraCls
378 }),
379 isSearch: isSearch,
380 error: hasError,
381 inputRef: getInputRef,
382 onClick: handleSelectClick,
383 value: getDisplayLabel(props.options, selectType, selectedValue, props.displayLabel, splitKey),
384 isMultiSelect: selectType == 'multiple',
385 onDelete: onDelete,
386 isActive: selectIsActive ? selectFocus : visible,
387 onSearch: onSearch,
388 onChange: onChange,
389 exitSearch: !visible
390 }))));
391};
392
393FieldDropdown.defaultProps = {
394 options: []
395};
396export default FieldDropdown;
\No newline at end of file