Created custom Loader component
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"expoServerPort": 19000,
|
"expoServerPort": 19000,
|
||||||
"packagerPort": 19001,
|
"packagerPort": 19001,
|
||||||
"packagerPid": 46572
|
"packagerPid": 694
|
||||||
}
|
}
|
||||||
5
website/package-lock.json
generated
5
website/package-lock.json
generated
@@ -127,6 +127,11 @@
|
|||||||
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
|
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"animejs": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/animejs/-/animejs-2.2.0.tgz",
|
||||||
|
"integrity": "sha1-Ne79/FNbgZScnLBvCz5gwC5v3IA="
|
||||||
|
},
|
||||||
"ansi-align": {
|
"ansi-align": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-1.1.0.tgz",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"animejs": "^2.2.0",
|
||||||
"auto-bind2": "^1.0.2",
|
"auto-bind2": "^1.0.2",
|
||||||
"eventemitter3": "^2.0.3",
|
"eventemitter3": "^2.0.3",
|
||||||
"prop-types": "^15.5.10",
|
"prop-types": "^15.5.10",
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ export class Login extends React.Component {
|
|||||||
</Row.Item>
|
</Row.Item>
|
||||||
<Row.Item grow />
|
<Row.Item grow />
|
||||||
|
|
||||||
<WaitModal active={waitModal} message='Logging In' />
|
<WaitModal active={waitModal} message='Logging in...' />
|
||||||
|
|
||||||
<MessageModal error open={!!messageModal}
|
<MessageModal error open={!!messageModal}
|
||||||
icon={messageModal ? messageModal.icon : ''}
|
icon={messageModal ? messageModal.icon : ''}
|
||||||
|
|||||||
@@ -4,14 +4,17 @@ import { Dimmer, Loader, Text } from 'ui'
|
|||||||
|
|
||||||
export class WaitModal extends React.Component {
|
export class WaitModal extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
message: PropTypes.string.isRequired
|
active: PropTypes.bool.isRequired,
|
||||||
|
message: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { active, message } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dimmer>
|
<Dimmer active={active}>
|
||||||
<Loader />
|
<Loader />
|
||||||
{this.props.message && <Text size='Huge'>{this.props.message}...</Text>}
|
{message && <Text size='huge' color='inverse'>{message}</Text>}
|
||||||
</Dimmer>
|
</Dimmer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import { App } from './App'
|
import { App } from './App'
|
||||||
|
import { colorInfo } from 'ui/style'
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<App style={{ minHeight: '100vh', position: 'relative' }} />,
|
<App style={{ minHeight: '100vh', position: 'relative' }} />,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// HACK: See https://github.com/facebook/react/issues/5619
|
||||||
|
let css = document.createElement('style')
|
||||||
|
|
||||||
|
document.body.appendChild(css)
|
||||||
|
css.innerHTML = `::-webkit-input-placeholder { color: ${colorInfo.textPlaceholder} }`
|
||||||
|
|||||||
50
website/src/ui/Anime.js
Normal file
50
website/src/ui/Anime.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import anime from 'animejs'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
|
export default class Anime extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
as: PropTypes.string,
|
||||||
|
children: PropTypes.node,
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
this.targets = []
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
let animeProps = Object.assign({}, this.props, {
|
||||||
|
targets: this.targets
|
||||||
|
})
|
||||||
|
|
||||||
|
delete animeProps.children
|
||||||
|
delete animeProps.as
|
||||||
|
this.anime = anime(animeProps)
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps) {
|
||||||
|
this.anime = anime(Object.assign({}, { targets: this.targets }, nextProps))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
addTarget = (newTarget) => {
|
||||||
|
this.targets = [...this.targets, newTarget]
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let children = []
|
||||||
|
|
||||||
|
if (this.props.children) {
|
||||||
|
if (Array.isArray(this.props.children)) {
|
||||||
|
children = this.props.children
|
||||||
|
} else {
|
||||||
|
children = [this.props.children]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return React.createElement(
|
||||||
|
(this.props.as || 'div'), {}, children.map((child, i) => (React.cloneElement(child, { key: i, ref: this.addTarget })))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,8 +6,8 @@ import { reactAutoBind } from 'auto-bind2'
|
|||||||
|
|
||||||
export class Dimmer extends Component {
|
export class Dimmer extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
active: PropTypes.bool.isRequired,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
active: PropTypes.bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
|||||||
@@ -8,11 +8,8 @@ export default {
|
|||||||
color: '#000000',
|
color: '#000000',
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
borderRadius: '5px',
|
borderRadius: '5px',
|
||||||
// boxShadow: '0px 0px 0px rgba(66,66,66,.75)'
|
|
||||||
// textShadow: 'undefined 0px 0px 5px px rgba(66,66,66,.75)'
|
|
||||||
|
|
||||||
':focus': {
|
':focus': {
|
||||||
outline: 'none'
|
outline: 'none'
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Radium from 'radium'
|
import Radium from 'radium'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
import { colorInfo } from 'ui/style'
|
||||||
|
import anime from 'animejs'
|
||||||
|
|
||||||
class Loader extends React.Component {
|
class Loader extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@@ -15,26 +17,38 @@ class Loader extends React.Component {
|
|||||||
margin: '2px'
|
margin: '2px'
|
||||||
}
|
}
|
||||||
|
|
||||||
style(i) {
|
|
||||||
return {
|
|
||||||
backgroundColor: `${this.props.color}`,
|
|
||||||
width: `${this.props.size}px`,
|
|
||||||
height: `${this.props.size}px`,
|
|
||||||
margin: `${this.props.margin}`,
|
|
||||||
borderRadius: '100%',
|
|
||||||
display: 'inline-block',
|
|
||||||
// 0% {transform: scale(1); opacity: 1} 45% {transform: scale(0.1); opacity: 0.7} 80% {transform: scale(1); opacity: 1} 0.75s ${i * 0.12}s infinite cubic-bezier(.2,.68,.18,1.08)
|
|
||||||
animation: ``,
|
|
||||||
animationFillMode: 'both'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const size = 20
|
||||||
|
const spacing = 5
|
||||||
|
|
||||||
|
const addAnimation = (elem, i) => {
|
||||||
|
anime({
|
||||||
|
targets: elem,
|
||||||
|
scale: [
|
||||||
|
{ value: 0.2, duration: 800, easing: 'easeOutSine', delay: 200 * i },
|
||||||
|
{ value: 1.0, duration: 800, easing: 'easeOutSine' },
|
||||||
|
{ value: 1.0, duration: 200 * (2 - i) }
|
||||||
|
],
|
||||||
|
loop: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div style={{ height: size }}>
|
||||||
<div className={this.style(1)} />
|
{
|
||||||
<div className={this.style(2)} />
|
[0, 1, 2].map((i) => (
|
||||||
<div className={this.style(3)} />
|
<span key={i} ref={(elem) => addAnimation(elem, i)}
|
||||||
|
style={{
|
||||||
|
display: 'inline-block',
|
||||||
|
marginLeft: i > 0 ? spacing : 0,
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
background: colorInfo.textInverse,
|
||||||
|
borderSize: 0,
|
||||||
|
borderRadius: '100%'
|
||||||
|
}} />
|
||||||
|
))
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import { fontInfo } from './style'
|
|||||||
|
|
||||||
class Text extends Component {
|
class Text extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
size: PropTypes.string,
|
size: PropTypes.oneOf(['small', 'medium', 'large', 'huge']),
|
||||||
|
color: PropTypes.oneOf(['normal', 'inverse', 'alert', 'dimmed']),
|
||||||
margin: PropTypes.number,
|
margin: PropTypes.number,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
color: PropTypes.oneOf(['normal', 'alert', 'dimmed']),
|
|
||||||
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]),
|
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]),
|
||||||
align: PropTypes.string,
|
align: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export { default as Anime } from './Anime'
|
||||||
export { default as Box } from './Box'
|
export { default as Box } from './Box'
|
||||||
export { default as Button } from './Button'
|
export { default as Button } from './Button'
|
||||||
export { default as HeaderButton } from './HeaderButton'
|
export { default as HeaderButton } from './HeaderButton'
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
export const colorInfo = {
|
export const colorInfo = {
|
||||||
text: '#000000',
|
text: '#000000',
|
||||||
|
textInverse: '#FFFFFF',
|
||||||
|
textPlaceholder: '#EEEEEE',
|
||||||
alertText: '#FF0000',
|
alertText: '#FF0000',
|
||||||
grayText: '#B0B0B0',
|
grayText: '#B0B0B0',
|
||||||
buttonBackground: '#3498DB',
|
buttonBackground: '#3498DB',
|
||||||
@@ -28,10 +30,12 @@ export const fontInfo = {
|
|||||||
size: {
|
size: {
|
||||||
small: '10pt',
|
small: '10pt',
|
||||||
medium: '12pt',
|
medium: '12pt',
|
||||||
large: '14pt'
|
large: '14pt',
|
||||||
|
huge: '26pt',
|
||||||
},
|
},
|
||||||
color: {
|
color: {
|
||||||
'normal': colorInfo.text,
|
'normal': colorInfo.text,
|
||||||
|
'inverse': colorInfo.textInverse,
|
||||||
'alert': colorInfo.alertText,
|
'alert': colorInfo.alertText,
|
||||||
'dimmed': colorInfo.grayText,
|
'dimmed': colorInfo.grayText,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user