/
index.jsx
119 lines (108 loc) · 2.43 KB
/
index.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import React, { useRef, useState, useEffect } from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types';
import CircularProgress from '@material-ui/core/CircularProgress';
const StyledSpin = styled.div`
display: inline-flex;
svg {
color: ${(props) => props.theme.color.primary};
}
`;
const SpinContainer = styled.div`
display: inline-flex;
svg {
color: ${(props) => props.theme.color.primary};
}
position: relative;
`;
const Indicator = styled.div`
position: absolute;
top: 0;
left: 0;
z-index: 4;
display: block;
width: 100%;
height: 100%;
max-height: 400px;
& > * {
position: absolute;
top: calc(50% - ${(props) => props.$indicatorSize.height / 2}px);
left: calc(50% - ${(props) => props.$indicatorSize.width / 2}px);
}
`;
const Mask = styled.div`
position: absolute;
width: 100%;
height: 100%;
background: #FFF;
opacity: 0.8;
`;
/**
* `Spin` 是一個載入狀態元件,當頁面正在處理非同步行為,
* 或需要讓用戶等待的作業時,用來顯示以緩解用戶等待的焦慮。
*/
const Spin = ({
indicator, isLoading, children, ...props
}) => {
const indicatorRef = useRef();
const [indicatorSize, setIndicatorSize] = useState({
width: 0,
height: 0,
});
useEffect(() => {
const indicatorElem = indicatorRef.current?.children[0];
setIndicatorSize({
width: indicatorElem?.clientWidth,
height: indicatorElem?.clientHeight,
});
}, [indicatorRef, isLoading]);
if (!children) {
return (
<StyledSpin {...props}>
{indicator}
</StyledSpin>
);
}
return (
<SpinContainer {...props}>
{children}
{isLoading && (
<>
<Mask />
<Indicator
ref={indicatorRef}
className="spin__indicator"
$indicatorSize={indicatorSize}
>
{indicator}
</Indicator>
</>
)}
</SpinContainer>
);
};
Spin.propTypes = {
/**
* 客製化樣式
*/
className: PropTypes.string,
/**
* 自定義載入符號
*/
indicator: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),
/**
* 是否載入中
*/
isLoading: PropTypes.bool,
/**
* 內容
*/
children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]),
};
Spin.defaultProps = {
className: '',
indicator: <CircularProgress />,
isLoading: false,
children: '',
};
export default Spin;