From 9b7e5c87f5d808483e751025fa4f409cbbb78c5c Mon Sep 17 00:00:00 2001 From: Bougie <1742070326@qq.com> Date: Wed, 25 Sep 2019 10:56:57 +0800 Subject: [PATCH 1/7] feat(Loading): add duration (#681) --- components/_util/depreactedPropsCompat.js | 44 ++++---- components/loading/Loading.js | 114 +++++++++++++++++++++ components/loading/index.js | 98 +----------------- docs/demo/loading/section-api.jsx | 8 +- docs/demo/loading/section-localControl.jsx | 4 +- docs/zh-CN/components/loading.mdx | 3 +- 6 files changed, 145 insertions(+), 126 deletions(-) create mode 100755 components/loading/Loading.js mode change 100755 => 100644 components/loading/index.js diff --git a/components/_util/depreactedPropsCompat.js b/components/_util/depreactedPropsCompat.js index e3d44e436..2f705abc5 100644 --- a/components/_util/depreactedPropsCompat.js +++ b/components/_util/depreactedPropsCompat.js @@ -10,26 +10,28 @@ const isDevelopment = /development/gi.test(process.env.NODE_ENV) * @param {[[string, string, Function], [string, string, Function]]} compatPair * @returns */ -export const depreactedPropsCompat = (compatPair) => { - return (WrappedComponent) => { - return (props) => { - const compatProps = { ...props } - const componentName = - WrappedComponent.displayName || - WrappedComponent.name || - 'unknown component' - compatPair.forEach(([newProp, oldProp, convert]) => { - if (props[oldProp] !== undefined && props[newProp] === undefined) { - isDevelopment && - console.warn( - `${componentName}'s prop "${oldProp}" will be depreacted in next version! use ${newProp} instead.` - ) - compatProps[newProp] = convert - ? convert(props[oldProp]) - : props[oldProp] - } - }) - return React.createElement(WrappedComponent, compatProps) - } +export const depreactedPropsCompat = (compatPair) => (WrappedComponent) => { + const WrapperComponent = (props) => { + const compatProps = { ...props } + const componentName = + WrappedComponent.displayName || + WrappedComponent.name || + 'unknown component' + compatPair.forEach(([newProp, oldProp, convert]) => { + if (props[oldProp] !== undefined && props[newProp] === undefined) { + isDevelopment && + console.warn( + `${componentName}'s prop "${oldProp}" will be depreacted in next version! use ${newProp} instead.` + ) + compatProps[newProp] = convert + ? convert(props[oldProp]) + : props[oldProp] + } + }) + return } + for (const staticProp in WrappedComponent) { + WrapperComponent[staticProp] = WrappedComponent[staticProp] + } + return WrapperComponent } diff --git a/components/loading/Loading.js b/components/loading/Loading.js new file mode 100755 index 000000000..7609259ea --- /dev/null +++ b/components/loading/Loading.js @@ -0,0 +1,114 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import ReactDOM from 'react-dom' +import classNames from 'classnames' + +const loadingInstance = {} + +const prefixCls = 'hi-loading' +class Loading extends Component { + render () { + const { size, full, content, children, target, visible } = this.props + const mountNode = target || (full ? document.body : '') + const iconCls = classNames( + `${prefixCls}__icon`, + `${prefixCls}__icon--${size}` + ) + const maskCls = classNames(`${prefixCls}__mask`, { + [`${prefixCls}__mask--global`]: full, + [`${prefixCls}__mask--part`]: !full, + [`${prefixCls}__mask--hide`]: visible === false + }) + return ( + + {children} +
+
+
+
+
+
+
{content}
+
+
+ + ) + } +} + +Loading.propTypes = { + size: PropTypes.oneOf(['large', 'default', 'small']), + full: PropTypes.bool, + visible: PropTypes.bool, + content: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), + target: PropTypes.any, + duration: PropTypes.number +} + +Loading.defaultProps = { + size: 'default' +} + +function PortalWrapper ({ mountNode, children }) { + return mountNode ? ( + ReactDOM.createPortal(children, mountNode) + ) : ( +
{children}
+ ) +} + +function open (target, { content, key, duration, size } = {}) { + let renderNode = document.createElement('div') + const mountNode = target || document.body + window.getComputedStyle(mountNode).position === 'absolute' || + mountNode.style.setProperty('position', 'relative') + const full = !target + ReactDOM.render( + , + renderNode + ) + loadingInstance[key] = renderNode + if (!isNaN(duration) && duration > 0) { + setTimeout(() => { + ReactDOM.unmountComponentAtNode(renderNode) + renderNode = undefined + }, duration) + } +} + +function deprecatedOpen ({ target, tip } = {}) { + let renderNode = document.createElement('div') + const mountNode = target || document.body + window.getComputedStyle(mountNode).position === 'absolute' || + mountNode.style.setProperty('position', 'relative') + const full = !target + ReactDOM.render( + , + renderNode + ) + function close () { + renderNode && ReactDOM.unmountComponentAtNode(renderNode) + renderNode = undefined + } + return { close } +} + +function openWrapper (target, options) { + if (arguments.length >= 2) { + open(target, options) + } else { + return deprecatedOpen(target) + } +} +function close (key) { + if (loadingInstance[key]) { + ReactDOM.unmountComponentAtNode(loadingInstance[key]) + loadingInstance[key].parentNode && + loadingInstance[key].parentNode.removeChild(loadingInstance[key]) + } +} + +Loading.open = openWrapper +Loading.close = close + +export default Loading diff --git a/components/loading/index.js b/components/loading/index.js old mode 100755 new mode 100644 index 56a890c4e..09fc64cfc --- a/components/loading/index.js +++ b/components/loading/index.js @@ -1,97 +1,5 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import ReactDOM from 'react-dom' -import classNames from 'classnames' +import Loading from './Loading' +import { depreactedPropsCompat } from '../_util' import './style/index' -const loadingInstance = {} - -const prefixCls = 'hi-loading' -class Loading extends Component { - static propTypes = { - size: PropTypes.oneOf(['large', 'default', 'small']), - full: PropTypes.bool, - visible: PropTypes.bool, - content: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), - target: PropTypes.any, - duration: PropTypes.number - } - static defaultProps = { - size: 'default' - } - render () { - const { size, full, content, visible, children, target, show } = this.props - const mountNode = target || (full ? document.body : '') - const iconCls = classNames(`${prefixCls}__icon`, `${prefixCls}__icon--${size}`) - const maskCls = classNames(`${prefixCls}__mask`, { - [`${prefixCls}__mask--global`]: full, - [`${prefixCls}__mask--part`]: !full, - [`${prefixCls}__mask--hide`]: visible === false || show === false - }) - return ( - - {children} -
-
-
-
-
-
-
{content}
-
-
- - ) - } -} - -function PortalWrapper ({ mountNode, children }) { - return mountNode ? ( - ReactDOM.createPortal(children, mountNode) - ) : ( -
{children}
- ) -} - -function open (target, { content, key, duration, size } = {}) { - let renderNode = document.createElement('div') - const mountNode = target || document.body - window.getComputedStyle(mountNode).position === 'absolute' || - mountNode.style.setProperty('position', 'relative') - const full = !target - ReactDOM.render(, renderNode) - - loadingInstance[key] = renderNode -} -function deprecatedOpen ({ target, tip } = {}) { - let renderNode = document.createElement('div') - const mountNode = target || document.body - window.getComputedStyle(mountNode).position === 'absolute' || - mountNode.style.setProperty('position', 'relative') - const full = !target - ReactDOM.render(, renderNode) - function close () { - renderNode && ReactDOM.unmountComponentAtNode(renderNode) - renderNode = undefined - } - return { close } -} - -function openWrapper (target, options) { - if (arguments.length >= 2) { - open(target, options) - } else { - return deprecatedOpen(target) - } -} -function close (key) { - if (loadingInstance[key]) { - ReactDOM.unmountComponentAtNode(loadingInstance[key]) - loadingInstance[key].parentNode && loadingInstance[key].parentNode.removeChild(loadingInstance[key]) - } -} - -Loading.open = openWrapper -Loading.close = close - -export default Loading +export default depreactedPropsCompat(['visible', 'show'])(Loading) diff --git a/docs/demo/loading/section-api.jsx b/docs/demo/loading/section-api.jsx index a3cab07da..05fbaa252 100755 --- a/docs/demo/loading/section-api.jsx +++ b/docs/demo/loading/section-api.jsx @@ -17,14 +17,10 @@ class Demo extends React.Component { } demoEvent1 () { - Loading.open(null, {key: 123}) - setTimeout(() => { - Loading.close(123) - }, 3000) + Loading.open(null, { duration: 3000 }) } demoEvent2 () { - Loading.open(this.el, - { + Loading.open(this.el, { content: '加载中', key: 666 }) diff --git a/docs/demo/loading/section-localControl.jsx b/docs/demo/loading/section-localControl.jsx index 2a68c8499..e97ccd875 100755 --- a/docs/demo/loading/section-localControl.jsx +++ b/docs/demo/loading/section-localControl.jsx @@ -22,7 +22,7 @@ class Demo extends React.Component { dataIndex: 'name', key: 'name', render: (text, row, index) => { - return {text} + return {text} } }, { title: 'Age', @@ -37,7 +37,7 @@ class Demo extends React.Component { key: 'action', render: (text, record) => ( - Action 一 {record.name} + Action 一 {record.name} ), }]; diff --git a/docs/zh-CN/components/loading.mdx b/docs/zh-CN/components/loading.mdx index cb3935bd2..9287f62e0 100755 --- a/docs/zh-CN/components/loading.mdx +++ b/docs/zh-CN/components/loading.mdx @@ -38,12 +38,11 @@ import DemoApi from '../../demo/loading/section-api.jsx' | size | loading 大小 | string | 'large' \| 'default' \| 'small' | 'default' | | content | 自定义加载中状态的文案 | string \| ReactNode | - | - | | visible | 是否显示 loading | boolean | true \| false | true | -| duration | loading 自动关闭的时间,单位为毫秒 | number | - | - | | full | 是否全屏 | boolean | true \| false | false | ## Methods -`Loading.open(target, {content, size, duration, key})` +`Loading.open(target, { content, size, duration, key })` | 参数 | 说明 | 类型 | 可选值 | 默认值 | | -------- | --------------------------------------------- | ------------------- | ------------------------------- | --------- | From 99741c04f9eb5d9e019f9bfae201d23c91798e81 Mon Sep 17 00:00:00 2001 From: Bougie <1742070326@qq.com> Date: Wed, 25 Sep 2019 11:43:19 +0800 Subject: [PATCH 2/7] feat(Select): adapt theme (#257) --- components/_util/depreactedPropsCompat.js | 8 ++++---- components/select/SelectDropdown.js | 12 ++++++++---- components/select/SelectInput.js | 12 +++++++++--- components/select/style/select-dropdown.scss | 16 ++++++++++++++++ components/select/style/select-input.scss | 15 +++++++++++++++ 5 files changed, 52 insertions(+), 11 deletions(-) diff --git a/components/_util/depreactedPropsCompat.js b/components/_util/depreactedPropsCompat.js index 2f705abc5..10d8e8adb 100644 --- a/components/_util/depreactedPropsCompat.js +++ b/components/_util/depreactedPropsCompat.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { forwardRef } from 'react' const isDevelopment = /development/gi.test(process.env.NODE_ENV) @@ -11,7 +11,7 @@ const isDevelopment = /development/gi.test(process.env.NODE_ENV) * @returns */ export const depreactedPropsCompat = (compatPair) => (WrappedComponent) => { - const WrapperComponent = (props) => { + const WrapperComponent = forwardRef((props, ref) => { const compatProps = { ...props } const componentName = WrappedComponent.displayName || @@ -28,8 +28,8 @@ export const depreactedPropsCompat = (compatPair) => (WrappedComponent) => { : props[oldProp] } }) - return - } + return + }) for (const staticProp in WrappedComponent) { WrapperComponent[staticProp] = WrappedComponent[staticProp] } diff --git a/components/select/SelectDropdown.js b/components/select/SelectDropdown.js index 669a21d31..94ee3febb 100644 --- a/components/select/SelectDropdown.js +++ b/components/select/SelectDropdown.js @@ -2,8 +2,9 @@ import React, { Component } from 'react' import classNames from 'classnames' import Checkbox from '../checkbox' import Loading from '../loading' +import Provider from '../context' -export default class SelectDropdown extends Component { +class SelectDropdown extends Component { onClickOption (e, item, index) { e.stopPropagation() e.preventDefault() @@ -64,7 +65,8 @@ export default class SelectDropdown extends Component { optionWidth, showCheckAll, checkAll, - dropdownRender + dropdownRender, + theme } = this.props let matched = 0 const style = optionWidth && { @@ -92,7 +94,7 @@ export default class SelectDropdown extends Component { const isDisabled = item.disabled return (
  • )} {mode === 'multiple' && showCheckAll && ( -
    +
    全选
    )} @@ -127,3 +129,5 @@ export default class SelectDropdown extends Component { ) } } + +export default Provider(SelectDropdown) diff --git a/components/select/SelectInput.js b/components/select/SelectInput.js index 2b66b4677..02a37cdee 100644 --- a/components/select/SelectInput.js +++ b/components/select/SelectInput.js @@ -3,7 +3,9 @@ import React, { Component } from 'react' import classNames from 'classnames' import { getTextWidth } from './common.js' -export default class SelectInput extends Component { +import Proivder from '../context' + +class SelectInput extends Component { constructor (props) { super(props) @@ -103,6 +105,7 @@ export default class SelectInput extends Component { clearable, multipleMode, onFocus, + theme, onBlur } = this.props let icon = dropdownShow ? 'up' : 'down' @@ -118,7 +121,7 @@ export default class SelectInput extends Component { return (
    Date: Wed, 25 Sep 2019 15:10:19 +0800 Subject: [PATCH 3/7] fix(Select): ignore case when search (#659ʡ) --- components/select/Select.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/select/Select.js b/components/select/Select.js index 03f49f11d..93e9ea3cb 100644 --- a/components/select/Select.js +++ b/components/select/Select.js @@ -418,7 +418,7 @@ class Select extends Component { onFilterItems(keyword) { this.setState( { - keyword + keyword: keyword.toLowerCase() }, () => this.resetFocusedIndex() ) @@ -438,8 +438,8 @@ class Select extends Component { return ( this.isRemote() || (!searchable || !keyword) || - (String(item.id).includes(keyword) || - String(item.title).includes(keyword)) + (String(item.id).toLowerCase().includes(keyword) || + String(item.title).toLowerCase().includes(keyword)) ) } From 6a535622aff3171bdc117fd604e0e6fe5c20b7ad Mon Sep 17 00:00:00 2001 From: Bougie <1742070326@qq.com> Date: Wed, 25 Sep 2019 15:16:03 +0800 Subject: [PATCH 4/7] docs(Menu): fix spelling mistake --- docs/zh-CN/components/menu.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh-CN/components/menu.mdx b/docs/zh-CN/components/menu.mdx index b0ffe96a9..2e7cfc338 100755 --- a/docs/zh-CN/components/menu.mdx +++ b/docs/zh-CN/components/menu.mdx @@ -47,7 +47,7 @@ import { Badge } from '@libs' | activeId | 激活的菜单项 id | string | - | - | | placement | 设置菜单水平或垂直展示 | string | 'horizontal' \| 'vertical' | 'vertical' | | collapsed | 是否收起子菜单,菜单垂直展示时有效 | boolean | true \| false | false | -| showCollpse | 是否显示收缩开关,菜单垂直展示时有效 | boolean | true \| false | true | +| showCollapse | 是否显示收缩开关,菜单垂直展示时有效 | boolean | true \| false | true | | showAllSubMenus | 是否展开所有菜单 | boolean | true \| false | false | | accordion | 手风琴模式,菜单水平展示时有效 | boolean | true \| false | true | | onClick | 点击菜单选项时的回调 | (activeId, prevActiveId) => void | - | - | From b6a0f8e7a64a9c971a6168ed636dc1f06daae3c7 Mon Sep 17 00:00:00 2001 From: Bougie <1742070326@qq.com> Date: Wed, 25 Sep 2019 15:37:43 +0800 Subject: [PATCH 5/7] fix(Pagination): #691 --- components/pagination/Pagination.js | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/components/pagination/Pagination.js b/components/pagination/Pagination.js index 642e39062..d19a110e8 100644 --- a/components/pagination/Pagination.js +++ b/components/pagination/Pagination.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import Pager from './Pager' -import Dropdown from '../dropdown/index' +import Select from '../select' import Input from '../input' import Provider from '../context' @@ -158,17 +158,18 @@ class Pagination extends Component { return (
    - ({ - value: typeof n === 'object' ? n.value : n, + id: n, title: `${n} ${i18nItem}/${i18nItemPerPage}` }))} - width={100} - trigger='click' - onClick={(val) => { - this.onPageSizeChange(val) - }} - /> + value={pageSize} + onChange={ids => { + this.onPageSizeChange(ids[0]) + }} />
    ) @@ -197,6 +198,12 @@ class Pagination extends Component {
    { const val = e.target.value + if (!val) { + this.setState({ + jumpTo: val + }) + return + } if (/^\d+$/.test(val)) { const maxPage = this.calculatePage(total) const jumpTo = val < 1 ? 1 : (val > maxPage ? maxPage : val) From 7634ef6b971034ec36dc6266523490961514a770 Mon Sep 17 00:00:00 2001 From: Bougie <1742070326@qq.com> Date: Wed, 25 Sep 2019 17:01:28 +0800 Subject: [PATCH 6/7] fix(Pagination): Jumper blur --- components/_util/SwitchVersion.js | 16 ++++---- components/input/Input.js | 4 ++ components/pagination/Pagination.js | 60 ++++++++++++++--------------- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/components/_util/SwitchVersion.js b/components/_util/SwitchVersion.js index 783cf6d8c..d11777061 100644 --- a/components/_util/SwitchVersion.js +++ b/components/_util/SwitchVersion.js @@ -1,16 +1,14 @@ import React, { forwardRef } from 'react' function SwitchVersion (component = {}, componentLegacy = {}) { - const WrapperComponent = ({ legacy, innerRef, ...props }) => { - const innerComponent = legacy === true ? componentLegacy : component - return React.createElement( - innerComponent, - Object.assign({}, props, { ref: innerRef }) - ) - } - return forwardRef((props, ref) => { - return + const WrapperComponent = forwardRef(({ legacy, ...props }, ref) => { + const InnerComponent = legacy === true ? componentLegacy : component + for (const staticProp in InnerComponent) { + WrapperComponent[staticProp] = InnerComponent[staticProp] + } + return }) + return WrapperComponent } export default SwitchVersion diff --git a/components/input/Input.js b/components/input/Input.js index 8ff062437..01747fffb 100644 --- a/components/input/Input.js +++ b/components/input/Input.js @@ -70,6 +70,10 @@ class Input extends Component { } } + blur = () => { + this._Input.blur() + } + /** * 渲染 text 输入框 */ diff --git a/components/pagination/Pagination.js b/components/pagination/Pagination.js index d19a110e8..c6baafdc4 100644 --- a/components/pagination/Pagination.js +++ b/components/pagination/Pagination.js @@ -18,35 +18,6 @@ function breakItemRender (page, element) { function noop () {} class Pagination extends Component { - static propTypes = { - defaultCurrent: PropTypes.number, - pageSize: PropTypes.number, - max: PropTypes.number, - showJumper: PropTypes.bool, - autoHide: PropTypes.bool, - total: PropTypes.number, - onChange: PropTypes.func, - itemRender: PropTypes.func, - onPageSizeChange: PropTypes.func, - onJump: PropTypes.func, - pageSizeOptions: PropTypes.array, - type: PropTypes.oneOf(['simple', 'default', 'shrink']) - } - - static defaultProps = { - pageSizeOptions: [], - showJumper: false, - autoHide: false, - type: 'default', - defaultCurrent: 1, - pageSize: 10, - max: 2, - total: 0, - onChange: noop, - className: '', - prefixCls: 'hi-pagination' - } - constructor (props) { super(props) @@ -233,7 +204,7 @@ class Pagination extends Component { } else if (e.type === 'keypress') { if (e.charCode === 13) { setPageNum(pageNum) - this.jumper.current._Input.blur() + this.jumper.current.blur() } } } @@ -429,4 +400,33 @@ class Pagination extends Component { } } +Pagination.propTypes = { + defaultCurrent: PropTypes.number, + pageSize: PropTypes.number, + max: PropTypes.number, + showJumper: PropTypes.bool, + autoHide: PropTypes.bool, + total: PropTypes.number, + onChange: PropTypes.func, + itemRender: PropTypes.func, + onPageSizeChange: PropTypes.func, + onJump: PropTypes.func, + pageSizeOptions: PropTypes.array, + type: PropTypes.oneOf(['simple', 'default', 'shrink']) +} + +Pagination.defaultProps = { + pageSizeOptions: [], + showJumper: false, + autoHide: false, + type: 'default', + defaultCurrent: 1, + pageSize: 10, + max: 2, + total: 0, + onChange: noop, + className: '', + prefixCls: 'hi-pagination' +} + export default Provider(Pagination) From 22267767bb901d62ff54af7066c99a18c82e3de0 Mon Sep 17 00:00:00 2001 From: Bougie <1742070326@qq.com> Date: Thu, 26 Sep 2019 14:09:00 +0800 Subject: [PATCH 7/7] fix(Select): custom filter (#673) --- components/select/Select.js | 47 +++++++++++++----------- docs/demo/select/section-search.jsx | 51 ++++++++++++++++++++++++++ docs/zh-CN/components/select.mdx | 57 +++++++++++++++++------------ 3 files changed, 109 insertions(+), 46 deletions(-) create mode 100644 docs/demo/select/section-search.jsx diff --git a/components/select/Select.js b/components/select/Select.js index 93e9ea3cb..28f8df47a 100644 --- a/components/select/Select.js +++ b/components/select/Select.js @@ -35,6 +35,7 @@ class Select extends Component { showCheckAll: PropTypes.bool, autoload: PropTypes.bool, searchable: PropTypes.bool, + filterOption: PropTypes.func, clearable: PropTypes.bool, disabled: PropTypes.bool, placeholder: PropTypes.string, @@ -149,7 +150,7 @@ class Select extends Component { if (this.isRemote()) { return true } - return !!searchable + return searchable } parseValue (value = this.props.value) { @@ -170,7 +171,7 @@ class Select extends Component { resetSelectedItems (value, dropdownItems = [], listChanged = false) { const values = this.parseValue(value) let selectedItems = [] - dropdownItems.forEach(item => { + dropdownItems.forEach((item) => { if (values.includes(item.id)) { selectedItems.push(item) } @@ -247,11 +248,9 @@ class Select extends Component { } this.onChange(selectedItems, item, () => { - this.setState( - { - focusedIndex - } - ) + this.setState({ + focusedIndex + }) }) if (this.props.type !== 'multiple') { this.hideDropdown() @@ -350,11 +349,10 @@ class Select extends Component { : keyword this.autoloadFlag = false // 第一次自动加载数据后,输入的关键词即使为空也不再使用默认关键词 - const queryParams = qs.stringify(Object.assign({}, params, key && {[key]: keyword})) - url = - url.includes('?') - ? `${url}&${queryParams}` - : `${url}?${queryParams}` + const queryParams = qs.stringify( + Object.assign({}, params, key && { [key]: keyword }) + ) + url = url.includes('?') ? `${url}&${queryParams}` : `${url}?${queryParams}` if (type.toUpperCase() === 'POST') { options.body = JSON.stringify(data) @@ -418,7 +416,7 @@ class Select extends Component { onFilterItems(keyword) { this.setState( { - keyword: keyword.toLowerCase() + keyword: keyword }, () => this.resetFocusedIndex() ) @@ -434,13 +432,18 @@ class Select extends Component { } matchFilter(item) { + const { filterOption } = this.props const { searchable, keyword } = this.state - return ( - this.isRemote() || - (!searchable || !keyword) || - (String(item.id).toLowerCase().includes(keyword) || - String(item.title).toLowerCase().includes(keyword)) - ) + + const shouldMatch = this.isRemote() || + (!searchable || !keyword) + + if (typeof filterOption === 'function') { + return shouldMatch || filterOption(keyword, item) + } + + return shouldMatch || (String(item.id).includes(keyword) || + String(item.title).includes(keyword)) } resetFocusedIndex(setState = true) { @@ -539,7 +542,7 @@ class Select extends Component { style={style} >
    { this.selectInputContainer = node }} @@ -579,8 +582,8 @@ class Select extends Component { attachEle={this.selectInputContainer} zIndex={1050} topGap={5} - className="hi-select__popper" - placement="top-bottom-start" + className='hi-select__popper' + placement='top-bottom-start' > { + console.log('单选结果', item) + }} + searchable + filterOption={(keyword, item) => { + keyword = parseInt(keyword) + return item.id >= keyword + }} + /> + ) + } +}` + +const DemoBan = () => ( + +) +export default DemoBan diff --git a/docs/zh-CN/components/select.mdx b/docs/zh-CN/components/select.mdx index 017e941dd..65435f7e2 100755 --- a/docs/zh-CN/components/select.mdx +++ b/docs/zh-CN/components/select.mdx @@ -28,6 +28,12 @@ import DemoCustom from '../../demo/select/section-custom' +## 自定义搜索 + +import DemoSearch from '../../demo/select/section-search' + + + ## 异步单选 import DemoAsync from '../../demo/select/section-async' @@ -46,37 +52,40 @@ import DemoAsyncMultiple from '../../demo/select/section-async-multiple' +import { Badge } from '@libs' + ## Props -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -| ------------ | ------------------------------------------------------------ | ----------------------------------------------------- | ---------------------- | -------- | -| type | 下拉框类型 | string | 'single' \| 'multiple' | 'single' | -| data | 下拉框选项数据源 | DataItem[] | - | - | -| dataSource | 异步下拉框选项数据源 | DataSource | - | - | -| value | 被选中项的值 | string \| string[] | - | - | -| defaultValue | 默认被选中项的值 | string \| string[] | - | - | -| showCheckAll | 是否显示全选,只对多选生效 | boolean | true \| false | false | -| multipleWrap | 多选模式下是否允许选中结果折行,不建议折行因为会变成动态高度 | string | 'wrap' \| 'nowrap' | 'nowrap' | -| searchable | 是否可以筛选 | boolean | true \| false | false | -| clearable | 是否可以清空 | boolean | true \| false | true | -| autoload | origin 从远端获取数据,初始时是否自动加载 | boolean | true \| false | false | -| disabled | 是否禁用 | boolean | true \| false | false | -| placeholder | 输入框占位 | string | - | 请选择 | -| emptyContent | 没有选项时的提示 | string \| ReactNode | - | 无内容 | -| style | 自定义样式 | object | - | | -| optionWidth | 自定义下拉选项宽度 | number | - | | -| onChange | 改变选项时触发函数,回调值为当前所有选中项的 id 和变更项 | (selectedIds:stirng[], changedItem: DataItem) => void | - | 无内容 | -| render | 自定义下拉菜单渲染函数,回调值为选项数据和是否被选中 | (item: DataItem, selected: boolean) => ReactNode | - | 无内容 | +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | -------------------------------------------- | -------- | +| type | 下拉框类型 | string | 'single' \| 'multiple' | 'single' | +| data | 下拉框选项数据源 | DataItem[] | - | - | +| dataSource | 异步下拉框选项数据源 | DataSource | - | - | +| value | 被选中项的值 | string \| string[] | - | - | +| defaultValue | 默认被选中项的值 | string \| string[] | - | - | +| showCheckAll | 是否显示全选,只对多选生效 | boolean | true \| false | false | +| multipleWrap | 多选模式下是否允许选中结果折行,不建议折行因为会变成动态高度 | string | 'wrap' \| 'nowrap' | 'nowrap' | +| searchable | 是否可以筛选 | boolean | true \| false | false | +|
    filterOption
    | 第一个参数为输入的关键字,第二个为数据项,返回值为 true 时将出现在结果项。仅在 searchable 为 true 时有效 | (keyword: string, item: DataItem) => boolean | (keyword: string, item: DataItem) => boolean | - | +| clearable | 是否可以清空 | boolean | true \| false | true | +| autoload | origin 从远端获取数据,初始时是否自动加载 | boolean | true \| false | false | +| disabled | 是否禁用 | boolean | true \| false | false | +| placeholder | 输入框占位 | string | - | 请选择 | +| emptyContent | 没有选项时的提示 | string \| ReactNode | - | 无内容 | +| style | 自定义样式 | object | - | | +| optionWidth | 自定义下拉选项宽度 | number | - | | +| onChange | 改变选项时触发函数,回调值为当前所有选中项的 id 和变更项 | (selectedIds:stirng[], changedItem: DataItem) => void | - | 无内容 | +| render | 自定义下拉菜单渲染函数,回调值为选项数据和是否被选中 | (item: DataItem, selected: boolean) => ReactNode | - | 无内容 | ## Type ### DataItem -| 参数 | 说明 | 类型 | 可选值 | 默认值 | -| -------- | --------------- | ------ | --------------- | ------ | -| title | 下拉选项标题 | string | - | - | -| id | 下拉选项唯一 id | string | 'get' \| 'post' | 'get' | -| disabled | 是否禁用 | object | - | - | +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +| -------- | --------------- | ---------------- | ------ | ------ | +| title | 下拉选项标题 | string | - | - | +| id | 下拉选项唯一 id | string \| number | - | - | +| disabled | 是否禁用 | object | - | - | ### DataSource