Skip to content

Instantly share code, notes, and snippets.

@kasper573
Created February 24, 2018 20:43
Show Gist options
  • Save kasper573/8a05908241cf4464dea536210472f95f to your computer and use it in GitHub Desktop.
Save kasper573/8a05908241cf4464dea536210472f95f to your computer and use it in GitHub Desktop.
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