UNPKG

@choerodon/master

Version:
370 lines (313 loc) 15.1 kB
import "choerodon-ui/pro/lib/data-set/style"; import _DataSet from "choerodon-ui/pro/lib/data-set"; import "choerodon-ui/pro/lib/button/style"; import _Button from "choerodon-ui/pro/lib/button"; import "choerodon-ui/pro/lib/tooltip/style"; import _Tooltip from "choerodon-ui/pro/lib/tooltip"; var _excluded = ["value", "text", "maxTagTextLength"]; function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } import React, { useState, useMemo, useEffect, useRef, useImperativeHandle, useCallback } from 'react'; // @ts-ignore import { unstable_batchedUpdates as batchedUpdates } from 'react-dom'; import { omit, debounce } from 'lodash'; import { usePersistFn } from 'ahooks'; import FragmentForSearch from "./FragmentForSearch"; import "./index.less"; function applyMiddleWares(data, middleWares) { return middleWares.reduce(function (preData, middleWare) { return middleWare(preData); }, data); } function noop(data) { return data; } /** * 从对象中获取值,可以传一个key或路径,比如 date.str * @param object * @param path */ function getValueByPath(object, path) { var paths = path.split('.'); var result = object; while (paths.length > 0) { var key = paths.shift(); if (Object.prototype.hasOwnProperty.call(object, key)) { // @ts-ignore result = result[key]; } else { return undefined; } } return result; } export default function useSelect(config, ref) { var _useState = useState([]), _useState2 = _slicedToArray(_useState, 2), data = _useState2[0], setData = _useState2[1]; var _useState3 = useState(1), _useState4 = _slicedToArray(_useState3, 2), currentPage = _useState4[0], setPage = _useState4[1]; var _useState5 = useState(false), _useState6 = _slicedToArray(_useState5, 2), canLoadMore = _useState6[0], setCanLoadMore = _useState6[1]; var textRef = useRef(''); var dataSetRef = useRef(); var cacheRef = useRef(new Map()); var defaultRender = useCallback(function (item, tooltip) { var text = (item === null || item === void 0 ? void 0 : item.meaning) || getValueByPath(item, config.textField); return tooltip ? /*#__PURE__*/React.createElement(_Tooltip, { title: text, placement: "bottomLeft" }, text) : text; }, [config.textField]); var firstRef = useRef(true); var _config$textField = config.textField, textField = _config$textField === void 0 ? 'meaning' : _config$textField, _config$valueField = config.valueField, valueField = _config$valueField === void 0 ? 'value' : _config$valueField, _config$optionRendere = config.optionRenderer, optionRenderer = _config$optionRendere === void 0 ? defaultRender : _config$optionRendere, _onOption = config.onOption, requestFn = config.request, _config$middleWare = config.middleWare, middleWare = _config$middleWare === void 0 ? noop : _config$middleWare, afterLoadFn = config.afterLoad, _config$paging = config.paging, paging = _config$paging === void 0 ? true : _config$paging, props = config.props, combo = config.combo; var request = usePersistFn(requestFn); var afterLoad = usePersistFn(afterLoadFn || noop); var renderer = useCallback(function (_ref) { var _cacheRef$current; var value = _ref.value, originText = _ref.text, maxTagTextLength = _ref.maxTagTextLength, ote = _objectWithoutProperties(_ref, _excluded); // 兼容primitiveValue为false var item = value && typeof value === 'object' ? value : (_cacheRef$current = cacheRef.current) === null || _cacheRef$current === void 0 ? void 0 : _cacheRef$current.get(value); if (item) { var result = optionRenderer(item); var text = maxTagTextLength && typeof result === 'string' && result.length > maxTagTextLength ? "".concat(result.slice(0, maxTagTextLength), "...") : result; return text; } if (combo && !firstRef.current && value === originText) { return originText; } return ''; }, [combo, optionRenderer]); // 不分页时,本地搜索 var localSearch = !paging; var loadData = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee() { var _ref3, _ref3$filter, filter, _ref3$page, page, res, _args = arguments; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _ref3 = _args.length > 0 && _args[0] !== undefined ? _args[0] : {}, _ref3$filter = _ref3.filter, filter = _ref3$filter === void 0 ? textRef.current : _ref3$filter, _ref3$page = _ref3.page, page = _ref3$page === void 0 ? 1 : _ref3$page; _context.next = 3; return request({ filter: filter, page: page }); case 3: res = _context.sent; batchedUpdates(function () { if (paging) { var list = res.list, hasNextPage = res.hasNextPage; if (afterLoad && firstRef.current) { afterLoad(list); firstRef.current = false; } setData(function (d) { return page > 1 ? d.concat(list) : list; }); setPage(page); setCanLoadMore(hasNextPage); } else { if (afterLoad && firstRef.current) { afterLoad(res); firstRef.current = false; } setData(res); } }); // TODO: 更好的实现 case 5: case "end": return _context.stop(); } } }, _callee); })), [afterLoad, paging, request]); var searchData = useMemo(function () { return debounce(function (filter) { loadData({ filter: filter }); }, 500); }, [loadData]); useEffect(function () { loadData({ filter: '' }); }, [loadData]); useImperativeHandle(ref, function () { return { refresh: loadData }; }); var handleLoadMore = useCallback(function () { loadData({ page: currentPage + 1 }); }, [currentPage, loadData]); var handleInput = useCallback(function (e) { var value = e.target.value; textRef.current = value; if (!localSearch) { searchData(value); } }, [localSearch, searchData]); var filterOptions = useCallback(function (_ref4) { var record = _ref4.record, text = _ref4.text; // @ts-ignore var meaning = optionRenderer === defaultRender ? getValueByPath(record.data, textField) : optionRenderer(record.data); if (!meaning) { return true; } var name = ''; // 一般情况,option的children是一个字符串 if (typeof meaning === 'string') { name = meaning; } else if ( /*#__PURE__*/React.isValidElement(meaning)) { // 其他情况, children是一个元素,那么约定这个元素上的name属性进行搜索 // @ts-ignore // eslint-disable-next-line prefer-destructuring name = meaning.props.name; } else { return true; } return name.toLowerCase().indexOf(text.toLowerCase()) >= 0; }, [defaultRender, optionRenderer, textField]); var optionData = useMemo(function () { return (applyMiddleWares(data, [middleWare]) || []).map(function (item) { return _objectSpread(_objectSpread({}, item), {}, { meaning: item[textField], value: item[valueField] }); }); }, [data, middleWare, textField, valueField]); var finalData = useMemo(function () { return canLoadMore ? [].concat(_toConsumableArray(optionData), [{ loadMoreButton: true }]) : optionData; }, [canLoadMore, optionData]); var loadMoreButton = useMemo(function () { return /*#__PURE__*/React.createElement(_Button, { onClick: function onClick(e) { e.stopPropagation(); handleLoadMore(); }, style: { margin: '-4px -12px', width: 'calc(100% + 24px)' } }, "\u52A0\u8F7D\u66F4\u591A"); }, [handleLoadMore]); var options = useMemo(function () { if (!dataSetRef.current) { dataSetRef.current = new _DataSet({ data: finalData, paging: false }); } else { dataSetRef.current.loadData(finalData); } optionData.forEach(function (item) { var _cacheRef$current2; (_cacheRef$current2 = cacheRef.current) === null || _cacheRef$current2 === void 0 ? void 0 : _cacheRef$current2.set(item[valueField], item); }); return dataSetRef.current; }, [finalData, optionData, valueField]); var renderOption = function renderOption(_ref5) { var record = _ref5.record; if (!record) { return null; } if (record.get('loadMoreButton') === true) { return loadMoreButton; } return optionRenderer(record.toData(), config.tooltip); }; var selectProps = _objectSpread({ searchable: true, onInput: handleInput, onClear: function onClear() { textRef.current = ''; searchData(''); }, // 弹出时自动请求 onPopupHiddenChange: function onPopupHiddenChange(hidden) { if (hidden === false && textRef.current !== '' && paging) { textRef.current = ''; searchData(''); } }, searchMatcher: paging ? function () { return true; } : filterOptions, valueField: valueField, // 这里不传递textField,因为由useSelect来渲染 textField: textField, options: options, // @ts-ignore optionRenderer: renderOption, // TODO: 考虑如何获取record,来渲染,例如用户 renderer: renderer, // renderer: renderer ? ({ // // @ts-ignore // value, text, name, record, dataSet, // }) => { // return (record ? renderer() : null); // } : undefined, // @ts-ignore onOption: function onOption(_ref6) { var record = _ref6.record; if (record.get('loadMoreButton') === true) { return { className: 'load_more', disabled: true }; } return _onOption ? _onOption({ record: record }) : {}; } }, omit(props, 'renderer', 'optionRenderer')); return selectProps; } export { FragmentForSearch };