UNPKG

zarm-web

Version:
192 lines (162 loc) 4.23 kB
import React, { Component } from 'react'; import ActivityIndicator from 'zarm/es/activity-indicator'; import classnames from 'classnames'; import debounce from '../utils/debounce'; ActivityIndicator.defaultProps.prefixCls = 'zw-activity-indicator'; function shouldDelay(visible, delay) { return !!visible && !!delay && !Number.isNaN(Number(delay)); } class Loading extends Component { constructor(props) { super(props); this.updateSpinning = () => { const { visible } = this.props; const { visible: currentVisible } = this.state; if (currentVisible !== visible) { this.setState({ visible: !!visible }); } }; this.debouncifyUpdateSpinning = () => { const { delay } = this.props; if (delay) { this.updateSpinning = debounce(this.updateSpinning, delay); } }; this.documentBody = () => { return document.body; }; this.renderIndicator = () => { const { indicator, size, prefixCls } = this.props; const dotClassName = `${prefixCls}__svg`; const hash = { lg: 'lg', md: 'md' }; const ele = React.createElement(ActivityIndicator, { size: hash[size || 'md'], className: dotClassName }); if (React.isValidElement(indicator)) { return React.cloneElement(indicator); } return ele; }; this.renderLoading = () => { const { children, style, prefixCls, text, className, size, fullscreen } = this.props; const { visible } = this.state; const cls = classnames(prefixCls, className, { [`${prefixCls}--${size}`]: !!size, [`${prefixCls}--fullscreen`]: fullscreen, [`${prefixCls}--active`]: visible }); const textCls = size === 'xs' ? { display: 'inline' } : {}; const loadingElement = visible && React.createElement("div", { className: cls }, this.renderIndicator(), text && React.createElement("div", { className: `${prefixCls}__text`, style: textCls }, text)); if (this.isNestedPattern() || fullscreen) { const containerCls = classnames(`${prefixCls}__container`); return React.createElement("div", { className: cls, style: this.getStyle() }, React.createElement("div", { className: containerCls }, children), visible && React.createElement("div", { className: `${prefixCls}__mask` }, React.createElement("div", { className: `${prefixCls}__spin`, style: style }, this.renderIndicator(), text && React.createElement("div", { className: `${prefixCls}__text`, style: textCls }, text)))); } return loadingElement; }; const { visible: _visible, delay: _delay } = props; const shouldBeDelayed = shouldDelay(_visible, _delay); if (_delay) { this.updateSpinning = debounce(this.updateSpinning, _delay); } this.state = { visible: _visible && !shouldBeDelayed }; } componentDidMount() { this.updateSpinning(); } componentDidUpdate() { // this.debouncifyUpdateSpinning(); this.updateSpinning(); } componentWillUnmount() { this.enableScroll(); } getStyle() { const { fullscreen } = this.props; if (fullscreen) { this.disableScroll(); } this.enableScroll(); return {}; } disableScroll() { const documentBody = this.documentBody(); if (documentBody) { documentBody.style.setProperty('overflow', 'hidden'); } } enableScroll() { const documentBody = this.documentBody(); if (documentBody) { documentBody.style.removeProperty('overflow'); } } isNestedPattern() { const { children } = this.props; return !!children; } render() { return this.renderLoading(); } } Loading.displayName = 'Loading'; Loading.defaultProps = { prefixCls: 'zw-loading', visible: false, size: 'md' }; export default Loading;