1- import styled , { lightTheme } from '@slup/theming'
1+ import Inferno , { linkEvent } from 'inferno'
2+ import Component from 'inferno-component'
3+ import styled from '@slup/theming'
24
35const Scroll = styled . div `
46 overflow-x: hidden;
7+ height: 100%;
58`
69
710export const Pages = styled . div `
811 height: 100%;
912 width: auto;
1013 display: flex;
11- transition: transform 300ms cubic-bezier(0.4, 0.0, 0.2, 1);
12- transform: ${ props => `translateX(-${ props . selected * 100 } %)` }
14+ transition: transform 200ms ${ props => ! props . touched
15+ ? 'cubic-bezier(0.4, 0.0, 0.2, 1)'
16+ : 'none'
17+ } ;
1318`
1419
1520export const Page = styled . div `
1621 flex-shrink: 0;
17- height: 100%;
1822 width: 100%;
1923`
2024
21- export const TransitionPages = props =>
22- < Scroll >
23- < Pages { ...props } />
24- </ Scroll >
25+ interface IProps {
26+ selected : number
27+ onSwipe : ( index : number ) => void
28+ }
29+
30+ interface IState {
31+ touched : boolean
32+ startX : number
33+ translate : number
34+ }
35+
36+ export class TransitionPages extends Component < IProps , IState > {
37+ private container : HTMLDivElement
38+
39+ public state : IState = {
40+ touched : false ,
41+ startX : 0 ,
42+ translate : 0
43+ }
44+
45+ public componentWillReceiveProps ( nextProps : IProps ) {
46+ const stateSelection = Math . round ( this . state . translate / 100 )
47+ const DID_PROP_CHANGE = this . props . selected !== nextProps . selected
48+
49+ if ( nextProps . selected !== stateSelection && DID_PROP_CHANGE ) {
50+ this . setState ( { translate : nextProps . selected * 100 } )
51+ this . emitSwipe ( nextProps . selected )
52+ }
53+ }
54+
55+ /**
56+ * Emit the new selected index to a possible onSwipe listener
57+ *
58+ * @param index the new index
59+ */
60+ private emitSwipe ( index : number ) {
61+ if ( this . props . onSwipe && typeof this . props . onSwipe == 'function' ) {
62+ this . props . onSwipe ( index )
63+ }
64+ }
65+
66+ /**
67+ * Saves the latest touch on the x axis
68+ *
69+ * @param self The local class
70+ * @param event The data from the fired event
71+ */
72+ private handleTouchStart ( self , { targetTouches } ) {
73+ const { translate } = self . state
74+ const { clientX } = targetTouches [ 0 ]
75+ const { clientWidth } = self . container
76+
77+ const increment = ( translate * clientWidth ) / 100
78+
79+ self . setState ( {
80+ touched : true ,
81+ startX : clientX + increment
82+ } )
83+ }
84+
85+ /**
86+ * Creates a percentage to move the container
87+ * using the current touch and the saved one
88+ * on the x axis
89+ *
90+ * @param self The local class
91+ * @param event The data from the fired event
92+ */
93+ private handleTouchMove ( self , { targetTouches } ) {
94+ const { startX } = self . state
95+ const { clientX } = targetTouches [ 0 ]
96+ const { clientWidth } = self . container
97+ const childrenCount = self . container . children [ 0 ] . children . length
98+
99+ let percentage = ( ( startX - clientX ) / clientWidth ) * 100
100+
101+ if ( percentage < 0 )
102+ percentage = 0
103+ else if ( percentage > ( ( childrenCount - 1 ) * 100 ) )
104+ percentage = ( childrenCount - 1 ) * 100
105+
106+ self . setState ( { translate : percentage } )
107+ }
108+
109+ /**
110+ * Rounds the percentage
111+ *
112+ * @param self The local class
113+ */
114+ private handleTouchEnd ( self ) {
115+ self . setState ( {
116+ touched : false ,
117+ translate : Math . round ( self . state . translate / 100 ) * 100
118+ } )
119+
120+ self . emitSwipe ( Math . round ( self . state . translate / 100 ) )
121+ }
122+
123+ public render ( props , { translate, touched } ) {
124+ return (
125+ < Scroll
126+ { ...props }
127+ innerRef = { e => this . container = e }
128+ onTouchStart = { linkEvent ( this , this . handleTouchStart ) }
129+ onTouchMove = { linkEvent ( this , this . handleTouchMove ) }
130+ onTouchEnd = { linkEvent ( this , this . handleTouchEnd ) }
131+ >
132+ < Pages
133+ selected = { props . selected }
134+ touched = { touched }
135+ style = { `transform: translateX(-${ translate } %)` }
136+ >
137+ { props . children }
138+ </ Pages >
139+ </ Scroll >
140+ )
141+ }
142+ }
0 commit comments