zarm-web
Version:
基于 React 的桌面端UI库
192 lines (162 loc) • 4.23 kB
JavaScript
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;