Created
February 24, 2018 20:43
-
-
Save kasper573/8a05908241cf4464dea536210472f95f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {includes} from 'lodash'; | |
import {action, computed, observable} from 'mobx'; | |
import {RouteStore} from './RouteStore'; | |
import {UIStore} from './UIStore'; | |
import {LayoutLinks} from './models/LayoutLinks'; | |
const zeroVector = {x: 0, y: 0, z: 0}; | |
/** | |
* The state of Layout.tsx. | |
* | |
* Derives which links to display in the top/side menus from the routes that | |
* has layout information specified in the routes hierarchy of the RouteStore. | |
* | |
* Extra links may be plugged in/out by using setExtraLinks/deleteExtraLinks. | |
* This is useful when you wish to have situational menu items. | |
* See ExtraLinks.tsx for a useful convenience component. | |
* | |
* Note that the links are specified as RouteConfigs to align with the existing logic. | |
* Extra links won't affect which routes are mounted. | |
*/ | |
export class LayoutStore { | |
@observable isSideVisible = false; | |
@computed get isLargeDisplay () { | |
return this.uiStore.breakpoints.up('md'); | |
} | |
/** | |
* The spatial direction between the previous and current route. | |
* Used in RouteTransition.tsx to transition route changes on an axis. | |
*/ | |
@computed get navigationDirection () { | |
const from = this.routeStore.previousRoute; | |
const to = this.routeStore.currentRoute; | |
if (!(from || !to)) { | |
// No navigation | |
return zeroVector; | |
} | |
if (from.findDescendant((route) => route === to, false)) { | |
return {x: 0, y: 0, z: 1}; // Down the hierarchy | |
} | |
if (from.findAncestor((route) => route === to, false)) { | |
return {x: 0, y: 0, z: -1}; // Up the hierarchy | |
} | |
const toIndex = from.siblingsAndSelf.indexOf(to); | |
if (toIndex === -1) { | |
// Navigating to a distant part of the route hierarchy | |
return zeroVector; | |
} | |
// Navigating to a sibling | |
const fromIndex = from.siblingsAndSelf.indexOf(from); | |
const movement = fromIndex < toIndex ? -1 : 1; | |
const moveVertically = includes(this.links.side, to); | |
// Vertical movement on small displays looks very strange, | |
// so we opt out to only fade instead | |
if (moveVertically && !this.isLargeDisplay) { | |
return zeroVector; | |
} | |
return moveVertically ? | |
{x: 0, y: movement, z: 0} : // To a sibling in the side menu | |
{x: movement, y: 0, z: 0}; // To a sibling in the top menu | |
} | |
/** | |
* The LayoutLinks for the current route | |
*/ | |
@computed get links () { | |
return new LayoutLinks(this.routeStore.currentRoute, this.routeStore.previousRoute, this, this.routeStore); | |
} | |
constructor ( | |
private uiStore: UIStore, | |
private routeStore: RouteStore | |
) {} | |
@action | |
public toggleSideVisibility (isOpen: boolean = !this.isSideVisible) { | |
this.isSideVisible = isOpen; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment