@@ -3,6 +3,9 @@ import { listen, dispatch } from 'codesandbox-api';
33import classNames from 'classnames' ;
44
55import RefreshIcon from './RefreshIcon' ;
6+ import BackwardIcon from './BackwardIcon' ;
7+ import ForwardIcon from './ForwardIcon' ;
8+
69import withSandpack from '../../utils/with-sandpack' ;
710import { ISandpackContext } from '../../types' ;
811import cn from '../../utils/cn' ;
@@ -16,6 +19,8 @@ interface State {
1619 browserPath : string ;
1720 baseUrl : string ;
1821 lastCommittedUrl : string ;
22+ backwardNavigationStack : Array < string > ;
23+ forwardNavigationStack : Array < string > ;
1924}
2025
2126class Navigator extends React . Component < Props , State > {
@@ -29,6 +34,8 @@ class Navigator extends React.Component<Props, State> {
2934 browserPath : '/' ,
3035 baseUrl : '' ,
3136 lastCommittedUrl : '/' ,
37+ backwardNavigationStack : [ ] ,
38+ forwardNavigationStack : [ ] ,
3239 } ;
3340 }
3441
@@ -39,13 +46,13 @@ class Navigator extends React.Component<Props, State> {
3946 handleMessage = ( message : any ) => {
4047 switch ( message . type ) {
4148 case 'urlchange' : {
49+ console . log ( 'urlchange' ) ;
4250 this . setState ( this . getUrlState ( message . url ) ) ;
4351 break ;
4452 }
4553
4654 default : {
4755 // nothing
48-
4956 break ;
5057 }
5158 }
@@ -65,13 +72,37 @@ class Navigator extends React.Component<Props, State> {
6572 const baseUrl = this . getBaseUrl ( url ) ;
6673 const browserPath = url . replace ( baseUrl , '' ) || '/' ;
6774
68- return { baseUrl, browserPath, lastCommittedUrl : url } ;
75+ return {
76+ baseUrl,
77+ browserPath,
78+ lastCommittedUrl : url ,
79+ } ;
6980 } ;
7081
7182 commitUrl = ( ) => {
72- if ( this . props . sandpack . browserFrame ) {
73- this . props . sandpack . browserFrame . src =
74- this . state . baseUrl + this . state . browserPath ;
83+ const { sandpack } = this . props ;
84+ const { baseUrl, browserPath } = this . state ;
85+
86+ if ( sandpack . browserFrame ) {
87+ const prevUrl = sandpack . browserFrame . src ;
88+ sandpack . browserFrame . src = baseUrl + browserPath ;
89+
90+ // update lastCommittedUrl url
91+ this . setState ( {
92+ lastCommittedUrl : baseUrl + browserPath ,
93+ } ) ;
94+
95+ // update the navigation stacks
96+ // when you enter a new URL the forwardNavigationStack is cleared
97+ if ( prevUrl != null ) {
98+ this . setState ( prevState => ( {
99+ backwardNavigationStack : [
100+ ...prevState . backwardNavigationStack ,
101+ prevUrl ,
102+ ] ,
103+ forwardNavigationStack : [ ] ,
104+ } ) ) ;
105+ }
75106 }
76107 } ;
77108
@@ -99,6 +130,63 @@ class Navigator extends React.Component<Props, State> {
99130 }
100131 } ;
101132
133+ onBackwardNavigation = ( ) => {
134+ const { backwardNavigationStack } = this . state ;
135+ const { sandpack } = this . props ;
136+
137+ if ( backwardNavigationStack . length > 0 ) {
138+ const newCurrUrl =
139+ backwardNavigationStack [ backwardNavigationStack . length - 1 ] ;
140+ if ( sandpack . browserFrame ) {
141+ const currUrl = sandpack . browserFrame . src ;
142+ sandpack . browserFrame . src = newCurrUrl ;
143+
144+ const baseUrl = this . getBaseUrl ( newCurrUrl ) ;
145+ const browserPath = newCurrUrl . replace ( baseUrl , '' ) || '/' ;
146+
147+ this . setState ( prevState => ( {
148+ backwardNavigationStack : prevState . backwardNavigationStack . slice (
149+ 0 ,
150+ - 1
151+ ) ,
152+ forwardNavigationStack : [
153+ ...prevState . forwardNavigationStack ,
154+ currUrl ,
155+ ] ,
156+ lastCommittedUrl : newCurrUrl ,
157+ browserPath,
158+ } ) ) ;
159+ }
160+ }
161+ } ;
162+
163+ onFowardNavigation = ( ) => {
164+ const { forwardNavigationStack } = this . state ;
165+ const { sandpack } = this . props ;
166+
167+ if ( forwardNavigationStack . length > 0 ) {
168+ const newCurrUrl =
169+ forwardNavigationStack [ forwardNavigationStack . length - 1 ] ;
170+ if ( sandpack . browserFrame ) {
171+ const currUrl = sandpack . browserFrame . src ;
172+ sandpack . browserFrame . src = newCurrUrl ;
173+
174+ const baseUrl = this . getBaseUrl ( newCurrUrl ) ;
175+ const browserPath = newCurrUrl . replace ( baseUrl , '' ) || '/' ;
176+
177+ this . setState ( prevState => ( {
178+ backwardNavigationStack : [
179+ ...prevState . backwardNavigationStack ,
180+ currUrl ,
181+ ] ,
182+ forwardNavigationStack : prevState . forwardNavigationStack . slice ( 0 , - 1 ) ,
183+ lastCommittedUrl : newCurrUrl ,
184+ browserPath,
185+ } ) ) ;
186+ }
187+ }
188+ } ;
189+
102190 render ( ) {
103191 const { browserPath } = this . state ;
104192 const { sandpack, className, ...props } = this . props ;
@@ -108,6 +196,18 @@ class Navigator extends React.Component<Props, State> {
108196 className = { classNames ( className , cn ( 'Navigator' , 'container' ) ) }
109197 { ...props }
110198 >
199+ < button
200+ className = { cn ( 'Navigator' , 'button' ) }
201+ onClick = { this . onBackwardNavigation }
202+ >
203+ < BackwardIcon />
204+ </ button >
205+ < button
206+ className = { cn ( 'Navigator' , 'button' ) }
207+ onClick = { this . onFowardNavigation }
208+ >
209+ < ForwardIcon />
210+ </ button >
111211 < button className = { cn ( 'Navigator' , 'button' ) } onClick = { this . onRefresh } >
112212 < RefreshIcon />
113213 </ button >
0 commit comments