diff --git a/public/assets/arrow.png b/public/assets/arrow.png new file mode 100644 index 0000000..7fb1e0f Binary files /dev/null and b/public/assets/arrow.png differ diff --git a/src/App.js b/src/App.js index 123c721..9e8002b 100644 --- a/src/App.js +++ b/src/App.js @@ -47,13 +47,14 @@ import Slots from './pages/Slots' import MemoryGame from './pages/MemoryGame' import Exponential from './pages/Exponential' import Viewport from './pages/Viewport' +import { RouterHookRoutes } from './pages/RouterHooks.js' import Resize from './pages/Resize' import LanguagePlugin from './pages/LanguagePlugin.js' export default Blits.Application({ template: ` - + `, @@ -110,6 +111,9 @@ export default Blits.Application({ { path: '/examples/events', component: Events }, { path: '/examples/slots', component: Slots }, { path: '/examples/viewport', component: Viewport }, + + ...RouterHookRoutes, + { path: '/examples/resize', component: Resize }, { path: '/examples/languageplugin', component: LanguagePlugin }, // Benchmarks and stress tests diff --git a/src/pages/Portal.js b/src/pages/Portal.js index ebf564c..24066a4 100644 --- a/src/pages/Portal.js +++ b/src/pages/Portal.js @@ -197,6 +197,11 @@ export default Blits.Component('Portal', { id: 'examples/viewport', description: 'Lifecycle events when entering and leaving the viewport (margins)', }, + { + title: 'Router Hooks', + id: 'examples/router-hooks', + description: 'Example of router before hook', + }, { title: 'Image resizing', id: 'examples/resize', diff --git a/src/pages/RouterHooks.js b/src/pages/RouterHooks.js new file mode 100644 index 0000000..3c85350 --- /dev/null +++ b/src/pages/RouterHooks.js @@ -0,0 +1,278 @@ +import Blits from '@lightningjs/blits' + +const hookPageTemplate = { + template: ` + + + + + + + + + + + + + + + + + + + + + `, + props: [ + { + key: 'page', + cast: Object, + }, + ], + computed: { + pageTitle() { + //compute page title from page data, if there's no page data use default title + return (this.page && this.page.title) || this.title + }, + }, + state() { + //default state template to indicate which directions will be available if they are defined when "extending" + return { + title: 'Start', + up: 'up', + right: 'right', + down: 'down', + left: 'left', + } + }, +} + +//landing page of the router hook example, contains 2 flow examples +export const RouterHookPage = Blits.Component('RouterHookPage', { + ...hookPageTemplate, + state() { + return { + title: 'Start', + down: 'episode flow', + right: 'movie flow', + } + }, + input: { + right() { + //trigger router to navigate to movie flow + this.$router.to('/examples/router-hooks/movie') + }, + down() { + //trigger router to navigate to episode flow + this.$router.to('/examples/router-hooks/episode/1') + }, + }, +}) + +//movie flow page, with 2 directions left: back, right: rating +const Movie = Blits.Component('RouterHookMovie', { + ...hookPageTemplate, + state() { + return { + title: 'Movie', + left: 'Back', + right: 'Rating', + } + }, + input: { + left() { + //trigger router back navigation. Leads back to: /examples/router-hooks + this.$router.back() + }, + right() { + //trigger router to navigate to rating page + this.$router.to('/examples/router-hooks/rating') + }, + }, +}) + +//movie flow page, with 2 directions left: back, right: Router example page landing +const Rating = Blits.Component('RouterHookRating', { + ...hookPageTemplate, + state() { + return { + title: 'Rating', + left: 'Back', + right: 'TO START', + } + }, + input: { + left() { + //trigger router back navigation. Leads back to: /examples/router-hooks/movie + this.$router.back() + }, + right() { + //trigger router to navigate to router hook example page landing + this.$router.to('/examples/router-hooks/') + }, + }, +}) + +//movie flow page, with 2 directions left: back, right: next episode +const Episode = Blits.Component('RouterHookEpisode', { + ...hookPageTemplate, + state() { + return { + title: 'Episode', + left: 'Back', + right: 'NEXT EPISODE', + } + }, + input: { + left() { + //trigger router back navigation. Leads back to: /examples/router-hooks. Even when episode id > 1 + this.$router.back() + }, + right() { + //trigger router to navigate to the next episode, and NOT save current episode page in navigation history + this.$router.to(`/examples/router-hooks/episode/${this.page.id + 1}`, undefined, { + inHistory: false, + }) + }, + }, +}) + +//custom page transitions for when the router navigates to router example pages +const PageTransitions = { + slideInOutLeft: { + before: { + prop: 'x', + value: '100%', + }, + in: { + prop: 'x', + value: 0, + duration: 400, + }, + out: { + prop: 'x', + value: '-100%', + duration: 400, + }, + }, + slideInOutRight: { + before: { + prop: 'x', + value: '-100%', + }, + in: { + prop: 'x', + value: 0, + duration: 400, + }, + out: { + prop: 'x', + value: '100%', + duration: 400, + }, + }, + slideInOutUp: { + before: { + prop: 'y', + value: '100%', + }, + in: { + prop: 'y', + value: 0, + duration: 400, + }, + out: { + prop: 'y', + value: '-100%', + duration: 400, + }, + }, + slideInOutDown: { + before: { + prop: 'y', + value: '-100%', + }, + in: { + prop: 'y', + value: 0, + duration: 400, + }, + out: { + prop: 'y', + value: '100%', + duration: 400, + }, + }, +} + +export const RouterHookRoutes = [ + { + path: '/examples/router-hooks', + component: RouterHookPage, + hooks: { + async before(to, from) { + //change transition based on 'from' route + if (from && from.path === 'examples/router-hooks/movie') { + to.transition = PageTransitions.slideInOutRight + } + if (from && from.path === 'examples/router-hooks/rating') { + to.transition = PageTransitions.slideInOutLeft + } + if (from && from.path.indexOf('episode') > -1) { + to.transition = PageTransitions.slideInOutDown + } + return to + }, + }, + }, + { + path: '/examples/router-hooks/episode/:id', + component: Episode, + hooks: { + before(to, from) { + //change transition based on 'from' route + if (from && from.path.indexOf('episode') > -1) { + to.transition = PageTransitions.slideInOutLeft + } + const { id } = to.params + //if id > 5 lead route back to router example page landing + if (id > 5) { + return '/examples/router-hooks/' + } + //set page data based on episode ID + to.data.page = { + id: parseInt(id), + title: `Episode ${id}`, + } + return to + }, + }, + transition: PageTransitions.slideInOutUp, + }, + { + path: '/examples/router-hooks/movie', + component: Movie, + hooks: { + before(to, from) { + //change transition based on 'from' route + if (from && from.path === 'examples/router-hooks') { + to.transition = PageTransitions.slideInOutLeft + } + if (from && from.path === 'examples/router-hooks/rating') { + to.transition = PageTransitions.slideInOutRight + } + return to + }, + }, + }, + { + path: '/examples/router-hooks/rating', + component: Rating, + transition: PageTransitions.slideInOutLeft, + }, +]