mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-07-16 18:03:04 +05:30
265 lines
8.0 KiB
React
265 lines
8.0 KiB
React
|
import React, { Component } from 'react';
|
||
|
|
||
|
import { TransitionMotion, spring } from 'react-motion';
|
||
|
import ReactHeight from 'react-height';
|
||
|
|
||
|
import { Panel, PanelBody, PanelFooter, PanelHeader } from 'components/ui/Panel';
|
||
|
import {helpLinks as helpLinksStyles} from 'components/auth/helpLinks.scss';
|
||
|
import panelStyles from 'components/ui/panel.scss';
|
||
|
import icons from 'components/ui/icons.scss';
|
||
|
|
||
|
|
||
|
const opacitySpringConfig = [200, 20];
|
||
|
const heightSpringConfig = [200, 18];
|
||
|
const transformSpringConfig = [500, 20];
|
||
|
|
||
|
// TODO: сделать более быстрый фейд на горизонтальном скролле
|
||
|
|
||
|
export default class PanelTransition extends Component {
|
||
|
state = {
|
||
|
height: {}
|
||
|
};
|
||
|
|
||
|
componentWillReceiveProps() {
|
||
|
this.setState({
|
||
|
previousRoute: this.props.location
|
||
|
});
|
||
|
}
|
||
|
|
||
|
render() {
|
||
|
var {previousRoute, height} = this.state;
|
||
|
|
||
|
var {path, Title, Body, Footer, Links} = this.props;
|
||
|
|
||
|
return (
|
||
|
<TransitionMotion
|
||
|
styles={{
|
||
|
[path]: {
|
||
|
Title,
|
||
|
Body,
|
||
|
Footer,
|
||
|
Links,
|
||
|
hasBackButton: previousRoute && previousRoute.pathname === Title.type.goBack,
|
||
|
transformSpring: spring(0),
|
||
|
opacitySpring: spring(1)
|
||
|
},
|
||
|
common: {
|
||
|
heightSpring: spring(height[path] || 0, heightSpringConfig)
|
||
|
}
|
||
|
}}
|
||
|
willEnter={this.willEnter}
|
||
|
willLeave={this.willLeave}
|
||
|
>
|
||
|
{(items) => {
|
||
|
var keys = Object.keys(items).filter((key) => key !== 'common');
|
||
|
return (
|
||
|
<div>
|
||
|
<Panel>
|
||
|
<PanelHeader>
|
||
|
<div style={{
|
||
|
position: 'relative',
|
||
|
height: '59px',
|
||
|
overflow: 'hidden'
|
||
|
}}>
|
||
|
{keys.map((key) => this.getHeader(key, items[key]))}
|
||
|
</div>
|
||
|
</PanelHeader>
|
||
|
<PanelBody style={{
|
||
|
overflow: 'hidden'
|
||
|
}}>
|
||
|
<div style={{
|
||
|
position: 'relative',
|
||
|
height: previousRoute ? `${items.common.heightSpring}px` : `${height[path]}px`
|
||
|
}}>
|
||
|
{keys.map((key) => this.getBody(key, items[key]))}
|
||
|
</div>
|
||
|
</PanelBody>
|
||
|
<PanelFooter>
|
||
|
<div style={{
|
||
|
position: 'relative',
|
||
|
height: '50px',
|
||
|
overflow: 'hidden'
|
||
|
}}>
|
||
|
{keys.map((key) => this.getFooter(key, items[key]))}
|
||
|
</div>
|
||
|
</PanelFooter>
|
||
|
</Panel>
|
||
|
<div className={helpLinksStyles} style={{position: 'relative', height: '20px'}}>
|
||
|
{keys.map((key) => this.getLinks(key, items[key]))}
|
||
|
</div>
|
||
|
</div>
|
||
|
);
|
||
|
}}
|
||
|
</TransitionMotion>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
willEnter = (key, styles) => {
|
||
|
var map = {
|
||
|
'/login': -1,
|
||
|
'/register': -1,
|
||
|
'/password': 1,
|
||
|
'/activation': 1,
|
||
|
'/oauth/permissions': 1
|
||
|
};
|
||
|
var sign = map[key];
|
||
|
|
||
|
return {
|
||
|
...styles,
|
||
|
transformSpring: spring(sign * 100, transformSpringConfig),
|
||
|
opacitySpring: spring(1, opacitySpringConfig)
|
||
|
};
|
||
|
};
|
||
|
|
||
|
willLeave = (key, styles) => {
|
||
|
var map = {
|
||
|
'/login': -1,
|
||
|
'/register': -1,
|
||
|
'/password': 1,
|
||
|
'/activation': 1,
|
||
|
'/oauth/permissions': 1
|
||
|
};
|
||
|
var sign = map[key];
|
||
|
|
||
|
return {
|
||
|
...styles,
|
||
|
transformSpring: spring(sign * 100, transformSpringConfig),
|
||
|
opacitySpring: spring(0, opacitySpringConfig)
|
||
|
};
|
||
|
};
|
||
|
|
||
|
updateHeight = (height) => {
|
||
|
this.setState({
|
||
|
height: {
|
||
|
...this.state.height,
|
||
|
[this.props.path]: height
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
onGoBack = (event) => {
|
||
|
event.preventDefault();
|
||
|
|
||
|
this.props.history.goBack();
|
||
|
};
|
||
|
|
||
|
getHeader(key, props) {
|
||
|
var {hasBackButton, transformSpring, Title} = props;
|
||
|
|
||
|
var style = {
|
||
|
position: 'absolute',
|
||
|
top: 0,
|
||
|
left: 0,
|
||
|
width: '100%'
|
||
|
};
|
||
|
|
||
|
var scrollStyle = {
|
||
|
WebkitTransform: `translateY(${transformSpring}%)`,
|
||
|
transform: `translateY(${transformSpring}%)`
|
||
|
};
|
||
|
|
||
|
var sideScrollStyle = {
|
||
|
position: 'relative',
|
||
|
zIndex: 2,
|
||
|
WebkitTransform: `translateX(${-Math.abs(transformSpring)}%)`,
|
||
|
transform: `translateX(${-Math.abs(transformSpring)}%)`
|
||
|
};
|
||
|
|
||
|
var backButton = (
|
||
|
<button style={sideScrollStyle} onClick={this.onGoBack} className={panelStyles.headerControl}>
|
||
|
<span className={icons.arrowLeft} />
|
||
|
</button>
|
||
|
);
|
||
|
|
||
|
return (
|
||
|
<div key={`header${key}`} style={style}>
|
||
|
{hasBackButton ? backButton : null}
|
||
|
<div style={scrollStyle}>
|
||
|
{Title}
|
||
|
</div>
|
||
|
</div>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
getBody(key, props) {
|
||
|
var {transformSpring, opacitySpring, Body} = props;
|
||
|
|
||
|
var {previousRoute} = this.state;
|
||
|
|
||
|
var next = this.props.path;
|
||
|
var prev = previousRoute && previousRoute.pathname;
|
||
|
|
||
|
var not = (path) => prev !== path && next !== path;
|
||
|
|
||
|
var map = {
|
||
|
'/login': not('/password') ? 'Y' : 'X',
|
||
|
'/password': not('/login') ? 'Y' : 'X',
|
||
|
'/register': not('/activation') ? 'Y' : 'X',
|
||
|
'/activation': not('/register') ? 'Y' : 'X',
|
||
|
'/oauth/permissions': 'Y'
|
||
|
};
|
||
|
|
||
|
var direction = map[key];
|
||
|
|
||
|
if (direction === 'Y') {
|
||
|
transformSpring = Math.abs(transformSpring);
|
||
|
if (prev === key) {
|
||
|
transformSpring *= -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var style = {
|
||
|
position: 'absolute',
|
||
|
top: 0,
|
||
|
left: 0,
|
||
|
width: '100%',
|
||
|
WebkitTransform: `translate${direction}(${transformSpring}%)`,
|
||
|
transform: `translate${direction}(${transformSpring}%)`,
|
||
|
opacity: opacitySpring
|
||
|
};
|
||
|
|
||
|
return (
|
||
|
<ReactHeight key={`body${key}`} style={style} onHeightReady={this.updateHeight}>
|
||
|
{Body}
|
||
|
</ReactHeight>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
getFooter(key, props) {
|
||
|
var {opacitySpring, Footer} = props;
|
||
|
|
||
|
var style = {
|
||
|
position: 'absolute',
|
||
|
top: 0,
|
||
|
left: 0,
|
||
|
width: '100%',
|
||
|
opacity: opacitySpring
|
||
|
};
|
||
|
|
||
|
return (
|
||
|
<div key={`footer${key}`} style={style}>
|
||
|
{Footer}
|
||
|
</div>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
getLinks(key, props) {
|
||
|
var {opacitySpring, Links} = props;
|
||
|
|
||
|
var style = {
|
||
|
position: 'absolute',
|
||
|
top: 0,
|
||
|
left: 0,
|
||
|
width: '100%',
|
||
|
opacity: opacitySpring
|
||
|
};
|
||
|
|
||
|
return (
|
||
|
<div key={`links${key}`} style={style}>
|
||
|
{Links}
|
||
|
</div>
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|