11import React , { createContext } from 'react' ;
22import { SwipeEndEvent , SwipeEvent , SwipeStartEvent } from 'web-gesture-events' ;
3- import { clamp , Navigation , testRoute } from './common/utils' ;
3+ import { clamp , Navigation , matchRoute , includesRoute } from './common/utils' ;
44import { ScreenChild } from './index' ;
55import AnimationLayerData , { AnimationLayerDataContext } from './AnimationLayerData' ;
66
@@ -30,6 +30,7 @@ interface AnimationLayerState {
3030 gestureNavigating : boolean ;
3131 shouldAnimate : boolean ;
3232 startX : number ;
33+ paths : ( string | RegExp | undefined ) [ ]
3334}
3435
3536interface MotionProgressEventDetail {
@@ -52,7 +53,8 @@ export default class AnimationLayer extends React.Component<AnimationLayerProps,
5253 shouldPlay : true ,
5354 gestureNavigating : false ,
5455 shouldAnimate : true ,
55- startX : 0
56+ startX : 0 ,
57+ paths : [ ]
5658 }
5759
5860 static getDerivedStateFromProps ( nextProps : AnimationLayerProps , state : AnimationLayerState ) {
@@ -64,28 +66,45 @@ export default class AnimationLayer extends React.Component<AnimationLayerProps,
6466 } ;
6567 }
6668
69+ const paths = [ ...state . paths ] ;
70+ let nextPath : string | undefined = nextProps . currentPath ;
71+ let currentPath : string | undefined = state . currentPath ; // === '' when AnimationLayer first mounts
72+ let nextMatched = false ;
73+ let currentMatched = false ;
6774 let children = React . Children . map (
6875 nextProps . children ,
6976 ( child : ScreenChild ) => {
7077 if ( React . isValidElement ( child ) ) {
71- if ( testRoute ( child . props . path , nextProps . currentPath ) ) {
72- const element = React . cloneElement ( child , { ...child . props , in : true , out : false } ) ;
73- return element ;
74- } else if ( testRoute ( child . props . path , state . currentPath ) ) {
75- const element = React . cloneElement ( child , { ...child . props , out : true , in : false } ) ;
76- return element ;
77- } else if ( ! child . props . path ) {
78- const element = React . cloneElement ( child , { ...child . props , out : false , in : false } ) ;
79- return element ;
80- } else {
81- return undefined ;
78+ if ( ! state . paths . length ) paths . push ( child . props . path ) ;
79+
80+ if ( state . paths . length ) {
81+ if ( ! includesRoute ( nextPath , paths ) && state . paths . includes ( undefined ) ) {
82+ nextPath = undefined ;
83+ }
84+ if ( currentPath !== '' && ! includesRoute ( currentPath , paths ) && state . paths . includes ( undefined ) ) {
85+ currentPath = undefined ;
86+ }
87+ }
88+
89+ if ( matchRoute ( child . props . path , nextPath ) ) {
90+ if ( ! nextMatched ) {
91+ nextMatched = true ;
92+ return React . cloneElement ( child , { ...child . props , in : true , out : false } ) ;
93+ }
94+ }
95+ if ( matchRoute ( child . props . path , currentPath ) ) {
96+ if ( ! currentMatched ) {
97+ currentMatched = true ;
98+ return React . cloneElement ( child , { ...child . props , out : true , in : false } ) ;
99+ }
82100 }
83101 }
84102 }
85- ) . sort ( ( child , _ ) => testRoute ( child . props . path , nextProps . currentPath ) ? 1 : - 1 )
103+ ) . sort ( ( child , _ ) => matchRoute ( child . props . path , nextPath ) ? 1 : - 1 ) ; // current screen mounts first
86104
87105 return {
88- children : children , // current screen mounts first
106+ paths : paths ,
107+ children : children ,
89108 currentPath : nextProps . currentPath
90109 }
91110 }
@@ -115,13 +134,20 @@ export default class AnimationLayer extends React.Component<AnimationLayerProps,
115134 }
116135
117136 componentDidUpdate ( prevProps : AnimationLayerProps ) {
137+ if ( ! React . Children . count ( this . state . children ) ) {
138+ const children = React . Children . map ( this . props . children , ( child : ScreenChild ) => {
139+ if ( ! React . isValidElement ( child ) ) return undefined ;
140+ if ( matchRoute ( child . props . path , undefined ) )
141+ return React . cloneElement ( child , { ...child . props , in : true , out : false } ) as ScreenChild ;
142+ } ) ;
143+ this . setState ( { children : children } ) ;
144+ }
118145 if ( prevProps . currentPath !== this . state . currentPath ) {
119146 this . animationLayerData . duration = this . props . duration ;
120147 if ( ! this . state . gestureNavigating ) {
121148 this . animationLayerData . play = true ;
122149 this . animationLayerData . animate ( ) ; // children changes committed now animate
123150 }
124-
125151 }
126152 }
127153
@@ -136,27 +162,39 @@ export default class AnimationLayer extends React.Component<AnimationLayerProps,
136162 if ( ! this . props . lastPath ) return ;
137163
138164 if ( ev . direction === "right" && ev . x < this . props . swipeAreaWidth ) {
165+ let currentPath : string | undefined = this . props . currentPath ;
166+ let lastPath : string | undefined = this . props . lastPath ;
167+ let currentMatched = false ;
168+ let lastMatched = false ;
139169 const children = React . Children . map (
140170 this . props . children ,
141171 ( child : ScreenChild ) => {
142172 if ( ! this . props . lastPath ) return undefined ;
143-
173+
174+ if ( ! includesRoute ( currentPath , this . state . paths ) && this . state . paths . includes ( undefined ) ) {
175+ currentPath = undefined ;
176+ }
177+ if ( ! includesRoute ( lastPath , this . state . paths ) && this . state . paths . includes ( undefined ) ) {
178+ lastPath = undefined ;
179+ }
144180 if ( React . isValidElement ( child ) ) {
145- if ( testRoute ( child . props . path , this . props . currentPath )
146- || testRoute ( child . props . path , this . props . lastPath ) ) {
147- const _in = testRoute ( child . props . path , this . props . currentPath ) ? true : false ;
148- const element = React . cloneElement ( child , {
149- ...child . props ,
150- in : _in ,
151- out : ! _in
152- } ) ;
153- return element as ScreenChild ;
181+ if ( matchRoute ( child . props . path , currentPath ) ) {
182+ if ( ! currentMatched ) {
183+ currentMatched = true ;
184+ const element = React . cloneElement ( child , { ...child . props , in : true , out : false } ) ;
185+ return element as ScreenChild ;
186+ }
187+ }
188+ if ( matchRoute ( child . props . path , lastPath ) ) {
189+ if ( ! lastMatched ) {
190+ lastMatched = true ;
191+ const element = React . cloneElement ( child , { ...child . props , in : false , out : true } ) ;
192+ return element as ScreenChild ;
193+ }
154194 }
155- } else {
156- return undefined ;
157195 }
158196 }
159- ) . sort ( ( firstChild ) => testRoute ( firstChild . props . path , this . props . currentPath ) ? - 1 : 1 ) ;
197+ ) . sort ( ( firstChild ) => matchRoute ( firstChild . props . path , currentPath ) ? - 1 : 1 ) ;
160198
161199 this . props . onGestureNavigationStart ( ) ;
162200 this . setState ( {
0 commit comments