UNPKG

@motorcycle/router

Version:

Standard Router Driver for Motorcycle.js

165 lines (128 loc) 4.47 kB
# @motorcycle/router > Standard Router Driver for Motorcycle.js A driver built on top of [@motorcycle/history](https://github.com/motorcyclejs/history) and [switch-path](https://github.com/staltz/switch-path) to ease the pain of routing. Works server-side and in browsers! ## Let me have it! ```sh npm install --save @motorcycle/router ``` ## Basic Usage ```typescript import { run } from '@motorcycle/run'; import { makeDomComponent, div, h1 } from '@motorcycle/dom'; import { History } from '@motorcycle/history'; import { Router } from '@motorcycle/router'; import { of } from 'most'; function Main(sources) { const match$ = sources.router.define({ '/': HomeComponent, '/other': OtherComponent }); const page$ = match$.map(({path, value}) => { return value({...sources, router: sources.router.path(path)}); }); return { dom: page$.map(c => c.dom).switch(), router: page$.map(c => c.route$).switch().startWith('/'), }; } const Dom = makeDomComponent(document.querySelector('#app'))); function Effects(sinks) { const { dom } = Dom(sinks); const { router } = Router(History(sinks)); } run(main, Effects) function HomeComponent() { const route$ = ... // left as a user exercise return { dom: of(div([h1('home')])), route$, } } function OtherComponent() { const route$ = ... // left as a user exercise return { dom: of(div([h1('other')])), route$ } } ``` ## API For all types not defined here, please refer to `@motorcycle/history`'s type documentation [here](https://github.com/motorcyclejs/history#types) #### `Router(sinks: HistorySources): RouterSources` This is the main API of this driver. This function simply wraps `@motorcycle/history` and returns a source object containing methods instead of a stream. #### `RouterComponent: RouterHOC` A convenience function, to more declaratively define your routes to *Components*. It returns a stream of your currently matched Component. When using the router driver directly there is more flexibility. With the Router function, you must use routes to match to Components. ```typescript function main(sources: Sources): Sinks { const sinks$: Stream<Sinks> = Router({ '/': HomeComponent, // HomeComponent :: (sources: Sources) => Sinks; '/profile: { '/': ProfileComponent, '/:id': (id: number) => (sources: Sources) => ProfileId({...sources, id}), } }, sources); return { DOM: sinks$.map(sinks => sinks.dom).switch(), router: sinks$.map(sinks => sinks.route$).switch() }; } ``` ## Types #### `RouterSource` This is a type representation of the object passed into your main function. ```typescript export interface RouterSource { history(): Stream<Location>; path(pathname: Pathname): RouterSource; define(routes: RouteDefinitions): Stream<DefineReturn>; createHref(path: Pathname): Pathname; } ``` `history(): Stream<Location>` - This method allows you to reach the underlying stream provided by `@motorcycle/history`. `path(pathname: Pathname): RouterSource` - This method allows you to created nested router instances, very much like `DOM.select()` creates a new place in the DOM tree to look for elements and events, this allows dynamically created routes that can be matched that are decoupled from any parent routes. `define(routes: RouteDefinitions): Stream<DefineReturn>` - This method takes an object (anything supported by switch-path) of keys that represent your routes and returns a stream with an object that repesents any matches. `createHref(path: Pathname): Pathname` - This method allows you to create Hrefs that are namespaced at any RouterSource instance. ```typescript const nestedRouter = sources.router.path('/some').path('/path') const href = nestedRouter.createHref('/unaware/of/nesting') console.log(href) '/some/path/unaware/of/nesting') ``` #### `DefineReturn` ```typescript export interface DefineReturn { location: Location; createHref: (path: Pathname) => Pathname; path: string | null; value: any | null; } ``` #### `RouteDefinitions` ```typescript export interface RouteDefinitions { [key: Pathname]: any; } ``` #### `RouterHOC` ```typescript export interface RouterHOC { <Sources, Sinks>(definitions: RouterDefinitions<Sources, Sinks>, sources: RouterSources<Sources>): Stream<Sinks>; <Sources, Sinks>(definitions: RouterDefinitions<Sources, Sinks>): (sources: RouterSources<Sources>) => Stream<Sinks>; } ```