Skip to content

Commit

Permalink
Merge pull request #692 from XiaoMi/hotfix/#257&#673&#681
Browse files Browse the repository at this point in the history
  • Loading branch information
solarjoker authored Sep 26, 2019
2 parents 6b35b68 + 2226776 commit ba60c40
Show file tree
Hide file tree
Showing 17 changed files with 361 additions and 229 deletions.
16 changes: 7 additions & 9 deletions components/_util/SwitchVersion.js
Original file line number Diff line number Diff line change
@@ -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 <WrapperComponent {...props} ref={ref} />
const WrapperComponent = forwardRef(({ legacy, ...props }, ref) => {
const InnerComponent = legacy === true ? componentLegacy : component
for (const staticProp in InnerComponent) {
WrapperComponent[staticProp] = InnerComponent[staticProp]
}
return <InnerComponent {...{ ...props, ref }} />
})
return WrapperComponent
}

export default SwitchVersion
46 changes: 24 additions & 22 deletions components/_util/depreactedPropsCompat.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, { forwardRef } from 'react'

const isDevelopment = /development/gi.test(process.env.NODE_ENV)

Expand All @@ -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 <WrappedComponent {...compatProps} ref={ref} />
})
for (const staticProp in WrappedComponent) {
WrapperComponent[staticProp] = WrappedComponent[staticProp]
}
return WrapperComponent
}
4 changes: 4 additions & 0 deletions components/input/Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ class Input extends Component {
}
}

blur = () => {
this._Input.blur()
}

/**
* 渲染 text 输入框
*/
Expand Down
114 changes: 114 additions & 0 deletions components/loading/Loading.js
Original file line number Diff line number Diff line change
@@ -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 (
<PortalWrapper mountNode={mountNode}>
{children}
<div className={maskCls}>
<div className={`${prefixCls}__outter`}>
<div className={iconCls}>
<div />
<div />
</div>
<div className={`${prefixCls}__text`}>{content}</div>
</div>
</div>
</PortalWrapper>
)
}
}

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)
) : (
<div className={`${prefixCls}__wrapper`}>{children}</div>
)
}

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(
<Loading {...{ content, full, visible: true, target: mountNode, size }} />,
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(
<Loading {...{ tip, full, show: true, target: mountNode }} />,
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
98 changes: 3 additions & 95 deletions components/loading/index.js
100755 → 100644
Original file line number Diff line number Diff line change
@@ -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 (
<PortalWrapper mountNode={mountNode}>
{children}
<div className={maskCls}>
<div className={`${prefixCls}__outter`}>
<div className={iconCls}>
<div />
<div />
</div>
<div className={`${prefixCls}__text`}>{content}</div>
</div>
</div>
</PortalWrapper>
)
}
}

function PortalWrapper ({ mountNode, children }) {
return mountNode ? (
ReactDOM.createPortal(children, mountNode)
) : (
<div className={`${prefixCls}__wrapper`}>{children}</div>
)
}

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(<Loading {...{ content, full, visible: true, target: mountNode }} />, 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(<Loading {...{ tip, full, show: true, target: mountNode }} />, 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)
Loading

0 comments on commit ba60c40

Please sign in to comment.