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/_util/depreactedPropsCompat.js b/components/_util/depreactedPropsCompat.js
index e3d44e436..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)
@@ -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 = forwardRef((props, ref) => {
+ 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/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/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}
+
+
+ )
+ }
+}
+
+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}
-
-
- )
- }
-}
-
-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/components/pagination/Pagination.js b/components/pagination/Pagination.js
index 642e39062..c6baafdc4 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'
@@ -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)
@@ -158,17 +129,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 +169,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)
@@ -226,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()
}
}
}
@@ -422,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)
diff --git a/components/select/Select.js b/components/select/Select.js
index 03f49f11d..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: 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).includes(keyword) ||
- String(item.title).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'
>
)}
{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 (
{
- 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/demo/select/section-search.jsx b/docs/demo/select/section-search.jsx
new file mode 100644
index 000000000..de71a85a7
--- /dev/null
+++ b/docs/demo/select/section-search.jsx
@@ -0,0 +1,51 @@
+import React from 'react'
+import DocViewer from '../../../libs/doc-viewer'
+import Select from '../../../components/select'
+const prefix = 'select-search'
+const code = `import React from 'react'
+import Select from '@hi-ui/hiui/es/select'\n
+class Demo extends React.Component {
+ constructor () {
+ super()
+ this.state = {
+ singleList: [
+ { title: '小米1', id: 1 },
+ { title: '小米2', id: 2, disabled: true },
+ { title: '小米3', id: 3, disabled: true },
+ { title: '小米4', id: 4 },
+ { title: '小米5', id: 5 },
+ { title: '小米6', id: 6 },
+ { title: '小米8', id: 8 },
+ { title: '小米9', id: 9 },
+ ]
+ }
+ }
+
+ render () {
+ return (
+