diff options
| -rw-r--r-- | app/assets/css/style.css | 1 | ||||
| -rw-r--r-- | app/assets/css/transitions.css | 91 | ||||
| -rw-r--r-- | app/components/TransitionContainer.js | 201 | ||||
| -rw-r--r-- | app/routes.js | 6 | ||||
| -rw-r--r-- | app/transitions.js | 48 | ||||
| -rw-r--r-- | flow-typed/npm/react-transition-group_vx.x.x.js | 80 | ||||
| -rw-r--r-- | package.json | 1 | ||||
| -rw-r--r-- | yarn.lock | 20 |
8 files changed, 223 insertions, 225 deletions
diff --git a/app/assets/css/style.css b/app/assets/css/style.css index 5021d7d1a9..7d667f67e3 100644 --- a/app/assets/css/style.css +++ b/app/assets/css/style.css @@ -3,7 +3,6 @@ @import 'fonts.css'; @import 'global.css'; @import 'buttons.css'; -@import 'transitions.css'; /* app */ @import '../../components/PlatformWindow.css'; diff --git a/app/assets/css/transitions.css b/app/assets/css/transitions.css deleted file mode 100644 index 239be5b63b..0000000000 --- a/app/assets/css/transitions.css +++ /dev/null @@ -1,91 +0,0 @@ -/** - * CSS rules for transitions using React-router and CSSTransitionGroup - */ - -div[class*="-transition-leave"], div[class*="-transition-enter"] { - /* keep animated .layout divs pinned to viewport boundaries */ - position: absolute; - top: 0; - left: 0; - width: 100vw; - - /* disable UI interaction during transitions */ - pointer-events: none; -} - -.transition-container { - position: relative; - width: 100vw; - height: 100vh; - overflow: hidden; -} - -/* New view slides bottom top */ - -.slide-up-transition-leave { z-index: 0; } -.slide-up-transition-enter { - transform: translateY(100vh); - z-index: 1; -} - -.slide-up-transition-enter.slide-up-transition-enter-active { - transform: translateY(0); - transition: transform 450ms ease; -} - -/* New view slides top bottom */ - -.slide-down-transition-enter { z-index: 0; } -.slide-down-transition-leave { - transform: translateY(0); - z-index: 1; -} - -.slide-down-transition-leave.slide-down-transition-leave-active { - transform: translateY(100vh); - transition: transform 450ms ease; -} - -/* New view slids right to left */ - -.push-transition-leave { - transform: translateX(0vw); - z-index: 0; -} - -.push-transition-enter { - transform: translateX(100vw); - z-index: 1; -} - -.push-transition-leave.push-transition-leave-active { - transform: translateX(-50vw); - transition: transform 450ms ease; -} - -.push-transition-enter.push-transition-enter-active { - transform: translateX(0); - transition: transform 450ms ease; -} - -/* New view slides left to right */ - -.pop-transition-enter { - transform: translateX(-50vw); - z-index: 0; -} - -.pop-transition-leave { - transform: translateX(0); - z-index: 1; -} - -.pop-transition-enter.pop-transition-enter-active { - transform: translateX(0vw); - transition: transform 450ms ease; -} - -.pop-transition-leave.pop-transition-leave-active { - transform: translateX(100vw); - transition: transform 450ms ease; -}
\ No newline at end of file diff --git a/app/components/TransitionContainer.js b/app/components/TransitionContainer.js new file mode 100644 index 0000000000..c4a011a978 --- /dev/null +++ b/app/components/TransitionContainer.js @@ -0,0 +1,201 @@ +// @flow +import * as React from 'react'; +import { Styles, Component, Animated, View, Types, UserInterface } from 'reactxp'; +import type { TransitionGroupProps } from '../transitions'; + +type TransitionContainerProps = { + children: React.Node, + ...TransitionGroupProps +}; + +type State = { + previousChildren: ?React.Node, + childrenAnimation: Types.AnimatedViewStyleRuleSet, + previousChildrenAnimation: Types.AnimatedViewStyleRuleSet, + animationStyles: Types.AnimatedViewStyleRuleSet, + dimensions: Types.Dimensions, +}; + +export default class TransitionContainer extends Component<TransitionContainerProps, State> { + + constructor(props: TransitionContainerProps) { + super(props); + + const dimensions = UserInterface.measureWindow(); + + this.state = { + dimensions, + animationStyles: { + style: Styles.createAnimatedViewStyle({ + position: 'absolute', + width: dimensions.width, + height: dimensions.height, + }), + allowPointerEvents: Styles.createAnimatedViewStyle({ + pointerEvents: 'auto', + }) + } + }; + } + + componentWillReceiveProps(nextProps: TransitionContainerProps) { + switch (nextProps.name){ + case 'slide-up': + this.slideUpTransition(nextProps); + break; + case 'slide-down': + this.slideDownTransition(nextProps); + break; + case 'push': + this.pushTransition(nextProps); + break; + case 'pop': + this.popTransition(nextProps); + break; + default: + break; + } + } + + onFinishedAnimation() { + this.setState({ + childrenAnimation: this.state.animationStyles.allowPointerEvents, + previousChildren: null + }); + } + + slideUpTransition(nextProps: TransitionContainerProps) { + const currentTranslationValue = Animated.createValue(this.state.dimensions.height); + this.setState({ + previousChildren: this.props.children, + childrenAnimation: Styles.createAnimatedViewStyle({ + pointerEvents: 'none', + zIndex: 1, + transform: [{ translateY: currentTranslationValue }] + }), + previousChildrenAnimation: Styles.createAnimatedViewStyle({ + pointerEvents: 'none', + zIndex: 0, + transform: [{ translateY: 0 }] + }), + }, () => { + Animated.timing(currentTranslationValue, { + toValue: 0, + easing: Animated.Easing.InOut(), + duration: nextProps.duration, + useNativeDriver: true, + }).start(() => this.onFinishedAnimation()); + }); + } + + slideDownTransition(nextProps: TransitionContainerProps) { + const previousTranslationValue = Animated.createValue(0); + this.setState({ + previousChildren: this.props.children, + childrenAnimation: Styles.createAnimatedViewStyle({ + pointerEvents: 'none', + zIndex: 0, + transform: [{ translateY: 0 }] + }), + previousChildrenAnimation: Styles.createAnimatedViewStyle({ + pointerEvents: 'none', + zIndex: 1, + transform: [{ translateY: previousTranslationValue }] + }), + }, () => { + Animated.timing(previousTranslationValue, { + toValue: this.state.dimensions.height, + easing: Animated.Easing.InOut(), + duration: nextProps.duration, + useNativeDriver: true, + }).start(() => this.onFinishedAnimation()); + }); + } + + pushTransition(nextProps: TransitionContainerProps) { + const currentTranslationValue = Animated.createValue(this.state.dimensions.width); + const previousTranslationValue = Animated.createValue(0); + this.setState({ + previousChildren: this.props.children, + childrenAnimation: Styles.createAnimatedViewStyle({ + pointerEvents: 'none', + zIndex: 1, + transform: [{ translateX: currentTranslationValue }] + }), + previousChildrenAnimation: Styles.createAnimatedViewStyle({ + pointerEvents: 'none', + zIndex: 0, + transform: [{ translateX: previousTranslationValue }] + }), + }, () => { + const compositeAnimation = Animated.parallel([ + Animated.timing(currentTranslationValue, { + toValue: 0, + easing: Animated.Easing.InOut(), + duration: nextProps.duration, + useNativeDriver: true, + }), + Animated.timing(previousTranslationValue, { + toValue: - this.state.dimensions.width / 2, + easing: Animated.Easing.InOut(), + duration: nextProps.duration, + useNativeDriver: true, + }) + ]); + compositeAnimation.start(() => this.onFinishedAnimation()); + }); + } + + popTransition(nextProps: TransitionContainerProps) { + const currentTranslationValue = Animated.createValue(- this.state.dimensions.width / 2 ); + const previousTranslationValue = Animated.createValue(0); + this.setState({ + previousChildren: this.props.children, + childrenAnimation: Styles.createAnimatedViewStyle({ + pointerEvents: 'none', + zIndex: 0, + transform: [{ translateX: currentTranslationValue }] + }), + previousChildrenAnimation: Styles.createAnimatedViewStyle({ + pointerEvents: 'none', + zIndex: 1, + transform: [{ translateX: previousTranslationValue }] + }), + }, () => { + const compositeAnimation = Animated.parallel([ + Animated.timing(currentTranslationValue, { + toValue: 0, + easing: Animated.Easing.InOut(), + duration: nextProps.duration, + useNativeDriver: true, + }), + Animated.timing(previousTranslationValue, { + toValue: this.state.dimensions.width, + easing: Animated.Easing.InOut(), + duration: nextProps.duration, + useNativeDriver: true, + }) + ]); + compositeAnimation.start(() => this.onFinishedAnimation()); + }); + } + + render() { + const { children } = this.props; + const { previousChildren, childrenAnimation, previousChildrenAnimation } = this.state; + return ( + <View style={{flex:1}}> + + { previousChildren && + (<Animated.View style={[this.state.animationStyles.style, previousChildrenAnimation]}> + { previousChildren } + </Animated.View>) } + + <Animated.View style={[this.state.animationStyles.style, childrenAnimation]}> + { children } + </Animated.View> + + </View> + ); + } +}
\ No newline at end of file diff --git a/app/routes.js b/app/routes.js index f9917f17bf..b5e1f8aa07 100644 --- a/app/routes.js +++ b/app/routes.js @@ -2,7 +2,7 @@ import * as React from 'react'; import { Switch, Route, Redirect } from 'react-router'; -import { CSSTransitionGroup } from 'react-transition-group'; +import TransitionContainer from './components/TransitionContainer'; import PlatformWindow from './components/PlatformWindow'; import LoginPage from './containers/LoginPage'; import ConnectPage from './containers/ConnectPage'; @@ -92,7 +92,7 @@ export default function makeRoutes(getState: ReduxGetState, componentProps: Shar return ( <PlatformWindow> - <CSSTransitionGroup component="div" className="transition-container" { ...transitionProps }> + <TransitionContainer { ...transitionProps }> <Switch key={ location.key } location={ location }> <LoginRoute exact path="/" component={ LoginPage } /> <PrivateRoute exact path="/connect" component={ ConnectPage } /> @@ -103,7 +103,7 @@ export default function makeRoutes(getState: ReduxGetState, componentProps: Shar <PublicRoute exact path="/settings/support" component={ SupportPage } /> <PrivateRoute exact path="/select-location" component={ SelectLocationPage } /> </Switch> - </CSSTransitionGroup> + </TransitionContainer> </PlatformWindow> ); }} /> diff --git a/app/transitions.js b/app/transitions.js index 58e692f99c..3e825c2968 100644 --- a/app/transitions.js +++ b/app/transitions.js @@ -1,16 +1,10 @@ // @flow - import TransitionRule from './lib/transition-rule'; import type { TransitionFork, TransitionDescriptor } from './lib/transition-rule'; -export type CSSTransitionGroupProps = { - transitionName: string, - transitionEnterTimeout: number, - transitionLeaveTimeout: number, - transitionEnter: boolean, - transitionLeave: boolean, - transitionAppear?: boolean, - transitionAppearTimeout?: number +export type TransitionGroupProps = { + name: string, + duration: number, }; type TransitionMap = { @@ -23,21 +17,21 @@ type TransitionMap = { const transitions: TransitionMap = { slide: { forward: { - name: 'slide-up-transition', + name: 'slide-up', duration: 450 }, backward: { - name: 'slide-down-transition', + name: 'slide-down', duration: 450 } }, push: { forward: { - name: 'push-transition', + name: 'push', duration: 450 }, backward: { - name: 'pop-transition', + name: 'pop', duration: 450 } } @@ -57,12 +51,12 @@ const transitionRules = [ ]; /** - * Calculate CSSTransitionGroup props. + * Calculate TransitionGroup props. * * @param {string} [fromRoute] - source route * @param {string} toRoute - target route */ -export function getTransitionProps(fromRoute: ?string, toRoute: string): CSSTransitionGroupProps { +export function getTransitionProps(fromRoute: ?string, toRoute: string): TransitionGroupProps { // ignore initial transition and transition between the same routes if(!fromRoute || fromRoute === toRoute) { return noTransitionProps(); @@ -71,7 +65,7 @@ export function getTransitionProps(fromRoute: ?string, toRoute: string): CSSTran for(const rule of transitionRules) { const match = rule.match(fromRoute, toRoute); if(match) { - return toCSSTransitionGroupProps(match.descriptor); + return toTransitionGroupProps(match.descriptor); } } @@ -79,30 +73,24 @@ export function getTransitionProps(fromRoute: ?string, toRoute: string): CSSTran } /** - * Integrate TransitionDescriptor into CSSTransitionGroupProps + * Integrate TransitionDescriptor into TransitionGroupProps * @param {TransitionDescriptor} descriptor */ -function toCSSTransitionGroupProps(descriptor: TransitionDescriptor): CSSTransitionGroupProps { +function toTransitionGroupProps(descriptor: TransitionDescriptor): TransitionGroupProps { const {name, duration} = descriptor; return { - transitionName: name, - transitionEnterTimeout: duration, - transitionLeaveTimeout: duration, - transitionEnter: true, - transitionLeave: true + name: name, + duration: duration, }; } /** - * Returns default props with animations disabled + * Returns default props with no animation */ -function noTransitionProps(): CSSTransitionGroupProps { +function noTransitionProps(): TransitionGroupProps { return { - transitionName: '', - transitionEnterTimeout: 0, - transitionLeaveTimeout: 0, - transitionEnter: false, - transitionLeave: false + name: '', + duration: 0, }; } diff --git a/flow-typed/npm/react-transition-group_vx.x.x.js b/flow-typed/npm/react-transition-group_vx.x.x.js deleted file mode 100644 index 3de6d4279a..0000000000 --- a/flow-typed/npm/react-transition-group_vx.x.x.js +++ /dev/null @@ -1,80 +0,0 @@ -// flow-typed signature: 29dbe0ae1689d8d245ff83cf4c3ce647 -// flow-typed version: <<STUB>>/react-transition-group_v^1.2.0/flow_v0.65.0 - -/** - * This is an autogenerated libdef stub for: - * - * 'react-transition-group' - * - * Fill this stub out by replacing all the `any` types. - * - * Once filled out, we encourage you to share your work with the - * community by sending a pull request to: - * https://github.com/flowtype/flow-typed - */ - -declare module 'react-transition-group' { - declare module.exports: any; -} - -/** - * We include stubs for each file inside this npm package in case you need to - * require those files directly. Feel free to delete any files that aren't - * needed. - */ -declare module 'react-transition-group/CSSTransitionGroup' { - declare module.exports: any; -} - -declare module 'react-transition-group/CSSTransitionGroupChild' { - declare module.exports: any; -} - -declare module 'react-transition-group/dist/react-transition-group' { - declare module.exports: any; -} - -declare module 'react-transition-group/dist/react-transition-group.min' { - declare module.exports: any; -} - -declare module 'react-transition-group/TransitionGroup' { - declare module.exports: any; -} - -declare module 'react-transition-group/utils/ChildMapping' { - declare module.exports: any; -} - -declare module 'react-transition-group/utils/PropTypes' { - declare module.exports: any; -} - -// Filename aliases -declare module 'react-transition-group/CSSTransitionGroup.js' { - declare module.exports: $Exports<'react-transition-group/CSSTransitionGroup'>; -} -declare module 'react-transition-group/CSSTransitionGroupChild.js' { - declare module.exports: $Exports<'react-transition-group/CSSTransitionGroupChild'>; -} -declare module 'react-transition-group/dist/react-transition-group.js' { - declare module.exports: $Exports<'react-transition-group/dist/react-transition-group'>; -} -declare module 'react-transition-group/dist/react-transition-group.min.js' { - declare module.exports: $Exports<'react-transition-group/dist/react-transition-group.min'>; -} -declare module 'react-transition-group/index' { - declare module.exports: $Exports<'react-transition-group'>; -} -declare module 'react-transition-group/index.js' { - declare module.exports: $Exports<'react-transition-group'>; -} -declare module 'react-transition-group/TransitionGroup.js' { - declare module.exports: $Exports<'react-transition-group/TransitionGroup'>; -} -declare module 'react-transition-group/utils/ChildMapping.js' { - declare module.exports: $Exports<'react-transition-group/utils/ChildMapping'>; -} -declare module 'react-transition-group/utils/PropTypes.js' { - declare module.exports: $Exports<'react-transition-group/utils/PropTypes'>; -} diff --git a/package.json b/package.json index 01045db15b..c9a8f45144 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "react-router": "^4.2.0", "react-router-redux": "^5.0.0-alpha.9", "react-simple-maps": "^0.10.1", - "react-transition-group": "^1.2.0", "reactxp": "^0.51.8", "redux": "^3.0.0", "redux-thunk": "^2.2.0", @@ -1641,10 +1641,6 @@ chai@^4.1.0: pathval "^1.0.0" type-detect "^4.0.0" -chain-function@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.0.tgz#0d4ab37e7e18ead0bdc47b920764118ce58733dc" - chainsaw@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" @@ -2476,10 +2472,6 @@ doctrine@^2.0.2, doctrine@^2.1.0: dependencies: esutils "^2.0.2" -dom-helpers@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.2.1.tgz#3203e07fed217bd1f424b019735582fc37b2825a" - dom-serializer@0, dom-serializer@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" @@ -5989,7 +5981,7 @@ promised-io@*: version "0.3.5" resolved "https://registry.yarnpkg.com/promised-io/-/promised-io-0.3.5.tgz#4ad217bb3658bcaae9946b17a8668ecd851e1356" -prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.8, prop-types@^15.5.9, prop-types@^15.6.0: +prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.5.9, prop-types@^15.6.0: version "15.6.0" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" dependencies: @@ -6289,16 +6281,6 @@ react-transform-hmr@^1.0.4: global "^4.3.0" react-proxy "^1.1.7" -react-transition-group@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-1.2.1.tgz#e11f72b257f921b213229a774df46612346c7ca6" - dependencies: - chain-function "^1.0.0" - dom-helpers "^3.2.0" - loose-envify "^1.3.1" - prop-types "^15.5.6" - warning "^3.0.0" - react@^16.0.0: version "16.2.0" resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba" |
