Created custom Loader component
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"expoServerPort": 19000,
|
||||
"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=",
|
||||
"dev": true
|
||||
},
|
||||
"animejs": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/animejs/-/animejs-2.2.0.tgz",
|
||||
"integrity": "sha1-Ne79/FNbgZScnLBvCz5gwC5v3IA="
|
||||
},
|
||||
"ansi-align": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-1.1.0.tgz",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"animejs": "^2.2.0",
|
||||
"auto-bind2": "^1.0.2",
|
||||
"eventemitter3": "^2.0.3",
|
||||
"prop-types": "^15.5.10",
|
||||
|
||||
@@ -150,7 +150,7 @@ export class Login extends React.Component {
|
||||
</Row.Item>
|
||||
<Row.Item grow />
|
||||
|
||||
<WaitModal active={waitModal} message='Logging In' />
|
||||
<WaitModal active={waitModal} message='Logging in...' />
|
||||
|
||||
<MessageModal error open={!!messageModal}
|
||||
icon={messageModal ? messageModal.icon : ''}
|
||||
|
||||
@@ -4,14 +4,17 @@ import { Dimmer, Loader, Text } from 'ui'
|
||||
|
||||
export class WaitModal extends React.Component {
|
||||
static propTypes = {
|
||||
message: PropTypes.string.isRequired
|
||||
active: PropTypes.bool.isRequired,
|
||||
message: PropTypes.string,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { active, message } = this.props
|
||||
|
||||
return (
|
||||
<Dimmer>
|
||||
<Dimmer active={active}>
|
||||
<Loader />
|
||||
{this.props.message && <Text size='Huge'>{this.props.message}...</Text>}
|
||||
{message && <Text size='huge' color='inverse'>{message}</Text>}
|
||||
</Dimmer>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { App } from './App'
|
||||
import { colorInfo } from 'ui/style'
|
||||
|
||||
ReactDOM.render(
|
||||
<App style={{ minHeight: '100vh', position: 'relative' }} />,
|
||||
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 {
|
||||
static propTypes = {
|
||||
active: PropTypes.bool.isRequired,
|
||||
children: PropTypes.node,
|
||||
active: PropTypes.bool
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
||||
@@ -8,11 +8,8 @@ export default {
|
||||
color: '#000000',
|
||||
borderStyle: 'solid',
|
||||
borderRadius: '5px',
|
||||
// boxShadow: '0px 0px 0px rgba(66,66,66,.75)'
|
||||
// textShadow: 'undefined 0px 0px 5px px rgba(66,66,66,.75)'
|
||||
|
||||
':focus': {
|
||||
outline: 'none'
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import React from 'react'
|
||||
import Radium from 'radium'
|
||||
import PropTypes from 'prop-types'
|
||||
import { colorInfo } from 'ui/style'
|
||||
import anime from 'animejs'
|
||||
|
||||
class Loader extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -15,26 +17,38 @@ class Loader extends React.Component {
|
||||
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() {
|
||||
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 (
|
||||
<div>
|
||||
<div className={this.style(1)} />
|
||||
<div className={this.style(2)} />
|
||||
<div className={this.style(3)} />
|
||||
<div style={{ height: size }}>
|
||||
{
|
||||
[0, 1, 2].map((i) => (
|
||||
<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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ import { fontInfo } from './style'
|
||||
|
||||
class Text extends Component {
|
||||
static propTypes = {
|
||||
size: PropTypes.string,
|
||||
size: PropTypes.oneOf(['small', 'medium', 'large', 'huge']),
|
||||
color: PropTypes.oneOf(['normal', 'inverse', 'alert', 'dimmed']),
|
||||
margin: PropTypes.number,
|
||||
children: PropTypes.node,
|
||||
color: PropTypes.oneOf(['normal', 'alert', 'dimmed']),
|
||||
width: PropTypes.oneOfType([ PropTypes.string, PropTypes.number ]),
|
||||
align: PropTypes.string,
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export { default as Anime } from './Anime'
|
||||
export { default as Box } from './Box'
|
||||
export { default as Button } from './Button'
|
||||
export { default as HeaderButton } from './HeaderButton'
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export const colorInfo = {
|
||||
text: '#000000',
|
||||
textInverse: '#FFFFFF',
|
||||
textPlaceholder: '#EEEEEE',
|
||||
alertText: '#FF0000',
|
||||
grayText: '#B0B0B0',
|
||||
buttonBackground: '#3498DB',
|
||||
@@ -28,10 +30,12 @@ export const fontInfo = {
|
||||
size: {
|
||||
small: '10pt',
|
||||
medium: '12pt',
|
||||
large: '14pt'
|
||||
large: '14pt',
|
||||
huge: '26pt',
|
||||
},
|
||||
color: {
|
||||
'normal': colorInfo.text,
|
||||
'inverse': colorInfo.textInverse,
|
||||
'alert': colorInfo.alertText,
|
||||
'dimmed': colorInfo.grayText,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user