|
@ -35,11 +35,6 @@ export type SpinFCType = React.FC<SpinProps> & { |
|
|
setDefaultIndicator: (indicator: React.ReactNode) => void; |
|
|
setDefaultIndicator: (indicator: React.ReactNode) => void; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export interface SpinState { |
|
|
|
|
|
spinning?: boolean; |
|
|
|
|
|
notCssAnimationSupported?: boolean; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Render indicator
|
|
|
// Render indicator
|
|
|
let defaultIndicator: React.ReactNode = null; |
|
|
let defaultIndicator: React.ReactNode = null; |
|
|
|
|
|
|
|
@ -59,8 +54,8 @@ function renderIndicator(prefixCls: string, props: SpinClassProps): React.ReactN |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (isValidElement(defaultIndicator)) { |
|
|
if (isValidElement(defaultIndicator)) { |
|
|
return cloneElement(defaultIndicator as SpinIndicator, { |
|
|
return cloneElement(defaultIndicator, { |
|
|
className: classNames((defaultIndicator as SpinIndicator).props.className, dotClassName), |
|
|
className: classNames(defaultIndicator.props.className, dotClassName), |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -78,80 +73,38 @@ function shouldDelay(spinning?: boolean, delay?: number): boolean { |
|
|
return !!spinning && !!delay && !isNaN(Number(delay)); |
|
|
return !!spinning && !!delay && !isNaN(Number(delay)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
class Spin extends React.Component<SpinClassProps, SpinState> { |
|
|
const Spin: React.FC<SpinClassProps> = props => { |
|
|
static defaultProps = { |
|
|
const { |
|
|
spinning: true, |
|
|
spinPrefixCls: prefixCls, |
|
|
size: 'default' as SpinSize, |
|
|
spinning: customSpinning = true, |
|
|
wrapperClassName: '', |
|
|
delay, |
|
|
}; |
|
|
className, |
|
|
|
|
|
size = 'default', |
|
|
originalUpdateSpinning: () => void; |
|
|
tip, |
|
|
|
|
|
wrapperClassName, |
|
|
|
|
|
style, |
|
|
|
|
|
children, |
|
|
|
|
|
hashId, |
|
|
|
|
|
...restProps |
|
|
|
|
|
} = props; |
|
|
|
|
|
|
|
|
constructor(props: SpinClassProps) { |
|
|
const [spinning, setSpinning] = React.useState<boolean>( |
|
|
super(props); |
|
|
() => customSpinning && !shouldDelay(customSpinning, delay), |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
const { spinning, delay } = props; |
|
|
React.useEffect(() => { |
|
|
const shouldBeDelayed = shouldDelay(spinning, delay); |
|
|
const updateSpinning = debounce<() => void>(() => { |
|
|
this.state = { |
|
|
setSpinning(customSpinning); |
|
|
spinning: spinning && !shouldBeDelayed, |
|
|
}, delay); |
|
|
|
|
|
updateSpinning(); |
|
|
|
|
|
return () => { |
|
|
|
|
|
updateSpinning?.cancel?.(); |
|
|
}; |
|
|
}; |
|
|
this.originalUpdateSpinning = this.updateSpinning; |
|
|
}, [delay, customSpinning]); |
|
|
this.debouncifyUpdateSpinning(props); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
componentDidMount() { |
|
|
|
|
|
this.updateSpinning(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
componentDidUpdate() { |
|
|
|
|
|
this.debouncifyUpdateSpinning(); |
|
|
|
|
|
this.updateSpinning(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
componentWillUnmount() { |
|
|
|
|
|
this.cancelExistingSpin(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
debouncifyUpdateSpinning = (props?: SpinClassProps) => { |
|
|
|
|
|
const { delay } = props || this.props; |
|
|
|
|
|
if (delay) { |
|
|
|
|
|
this.cancelExistingSpin(); |
|
|
|
|
|
this.updateSpinning = debounce(this.originalUpdateSpinning, delay); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
updateSpinning = () => { |
|
|
|
|
|
const { spinning } = this.props; |
|
|
|
|
|
const { spinning: currentSpinning } = this.state; |
|
|
|
|
|
if (currentSpinning !== spinning) { |
|
|
|
|
|
this.setState({ spinning }); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
cancelExistingSpin() { |
|
|
|
|
|
const { updateSpinning } = this; |
|
|
|
|
|
if (updateSpinning && (updateSpinning as any).cancel) { |
|
|
|
|
|
(updateSpinning as any).cancel(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
isNestedPattern() { |
|
|
|
|
|
return !!(this.props && typeof this.props.children !== 'undefined'); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
renderSpin = ({ direction }: ConfigConsumerProps) => { |
|
|
const isNestedPattern = () => typeof children !== 'undefined'; |
|
|
const { |
|
|
|
|
|
spinPrefixCls: prefixCls, |
|
|
|
|
|
hashId, |
|
|
|
|
|
className, |
|
|
|
|
|
size, |
|
|
|
|
|
tip, |
|
|
|
|
|
wrapperClassName, |
|
|
|
|
|
style, |
|
|
|
|
|
...restProps |
|
|
|
|
|
} = this.props; |
|
|
|
|
|
const { spinning } = this.state; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const renderSpin = ({ direction }: ConfigConsumerProps) => { |
|
|
const spinClassName = classNames( |
|
|
const spinClassName = classNames( |
|
|
prefixCls, |
|
|
prefixCls, |
|
|
{ |
|
|
{ |
|
@ -166,7 +119,7 @@ class Spin extends React.Component<SpinClassProps, SpinState> { |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
// fix https://fb.me/react-unknown-prop
|
|
|
// fix https://fb.me/react-unknown-prop
|
|
|
const divProps = omit(restProps, ['spinning', 'delay', 'indicator', 'prefixCls']); |
|
|
const divProps = omit(restProps, ['indicator', 'prefixCls']); |
|
|
|
|
|
|
|
|
const spinElement = ( |
|
|
const spinElement = ( |
|
|
<div |
|
|
<div |
|
@ -176,11 +129,12 @@ class Spin extends React.Component<SpinClassProps, SpinState> { |
|
|
aria-live="polite" |
|
|
aria-live="polite" |
|
|
aria-busy={spinning} |
|
|
aria-busy={spinning} |
|
|
> |
|
|
> |
|
|
{renderIndicator(prefixCls, this.props)} |
|
|
{renderIndicator(prefixCls, props)} |
|
|
{tip ? <div className={`${prefixCls}-text`}>{tip}</div> : null} |
|
|
{tip ? <div className={`${prefixCls}-text`}>{tip}</div> : null} |
|
|
</div> |
|
|
</div> |
|
|
); |
|
|
); |
|
|
if (this.isNestedPattern()) { |
|
|
|
|
|
|
|
|
if (isNestedPattern()) { |
|
|
const containerClassName = classNames(`${prefixCls}-container`, { |
|
|
const containerClassName = classNames(`${prefixCls}-container`, { |
|
|
[`${prefixCls}-blur`]: spinning, |
|
|
[`${prefixCls}-blur`]: spinning, |
|
|
}); |
|
|
}); |
|
@ -191,18 +145,15 @@ class Spin extends React.Component<SpinClassProps, SpinState> { |
|
|
> |
|
|
> |
|
|
{spinning && <div key="loading">{spinElement}</div>} |
|
|
{spinning && <div key="loading">{spinElement}</div>} |
|
|
<div className={containerClassName} key="container"> |
|
|
<div className={containerClassName} key="container"> |
|
|
{this.props.children} |
|
|
{children} |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
return spinElement; |
|
|
return spinElement; |
|
|
}; |
|
|
}; |
|
|
|
|
|
return <ConfigConsumer>{renderSpin}</ConfigConsumer>; |
|
|
render() { |
|
|
}; |
|
|
return <ConfigConsumer>{this.renderSpin}</ConfigConsumer>; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const SpinFC: SpinFCType = props => { |
|
|
const SpinFC: SpinFCType = props => { |
|
|
const { prefixCls: customizePrefixCls } = props; |
|
|
const { prefixCls: customizePrefixCls } = props; |
|
|