Skip to content

Instantly share code, notes, and snippets.

@mhartington
Created January 31, 2020 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mhartington/f60f22c70819867a23a5490592ad3119 to your computer and use it in GitHub Desktop.
Save mhartington/f60f22c70819867a23a5490592ad3119 to your computer and use it in GitHub Desktop.
import React from 'react';
import { Router, globalHistory, Location } from '@reach/router';
import { Global } from '@emotion/core';
import { ThemeProvider } from 'theme-ui';
import { Helmet } from 'react-helmet';
import get from 'lodash.get';
import merge from 'lodash.merge';
import useKeyboard from 'gatsby-theme-mdx-deck/src/hooks/use-keyboard';
import useStorage from 'gatsby-theme-mdx-deck/src/hooks/use-storage';
import useDeck from 'gatsby-theme-mdx-deck/src/hooks/use-deck';
import Context from 'gatsby-theme-mdx-deck/src/context';
import Wrapper from 'gatsby-theme-mdx-deck/src/components/wrapper';
import Slide from 'gatsby-theme-mdx-deck/src/components/slide';
import { modes } from 'gatsby-theme-mdx-deck/src/constants';
import Presenter from 'gatsby-theme-mdx-deck/src/components/presenter';
import Overview from 'gatsby-theme-mdx-deck/src/components/overview';
import Grid from 'gatsby-theme-mdx-deck/src/components/grid';
import posed, { PoseGroup } from 'react-pose';
const Keyboard = () => {
useKeyboard();
return false;
};
const Storage = () => {
useStorage();
return false;
};
const Print = ({ slides }) => {
const outer = useDeck();
const context = {
...outer,
mode: modes.print
};
return (
<Context.Provider value={context}>
{slides.map((slide, i) => (
<Slide key={i} slide={slide} preview />
))}
</Context.Provider>
);
};
const getIndex = () => {
const { pathname } = globalHistory.location;
const paths = pathname.split('/');
const n = Number(paths[paths.length - 1]);
const index = isNaN(n) ? 0 : n;
return index;
};
const GoogleFont = ({ theme }) => {
if (!theme.googleFont) return false;
return (
<Helmet>
<link rel="stylesheet" href={theme.googleFont} />
</Helmet>
);
};
const mergeThemes = (...themes) =>
themes.reduce(
(acc, theme) =>
typeof theme === 'function' ? theme(acc) : merge(acc, theme),
{}
);
const DefaultMode = ({ children }) => <React.Fragment children={children} />;
const RouteContainer = posed.div({
enter: { opacity: 1, delay: 300 },
exit: { opacity: 0 }
});
const PosedRouter = props => {
return (
<Location>
{({ location }) => (
<PoseGroup>
<RouteContainer key={location.key}>
<Router location={location} basepath={props.slug}>
{props.children}
</Router>
</RouteContainer>
</PoseGroup>
)}
</Location>
);
};
export default ({
slides = [],
pageContext: { title, slug },
theme = {},
themes = [],
...props
}) => {
const outer = useDeck();
const index = getIndex();
const head = slides.head.children;
const { components, ...mergedTheme } = mergeThemes(theme, ...themes);
const context = {
...outer,
slug,
length: slides.length,
index,
steps: get(outer, `metadata.${index}.steps`),
notes: get(outer, `metadata.${index}.notes`),
theme: mergedTheme
};
let Mode = DefaultMode;
switch (context.mode) {
case modes.presenter:
Mode = Presenter;
break;
case modes.overview:
Mode = Overview;
break;
case modes.grid:
Mode = Grid;
break;
default:
break;
}
return (
<>
<Helmet>
<title>{title}</title>
{head}
</Helmet>
<GoogleFont theme={mergedTheme} />
<Context.Provider value={context}>
<ThemeProvider components={components} theme={mergedTheme}>
<Global
styles={{
body: {
margin: 0,
overflow: context.mode === modes.normal ? 'hidden' : null
}
}}
/>
<Keyboard />
<Storage />
<Wrapper>
<PosedRouter slug={slug} slides={slides}>
<Slide index={0} path="/" slide={slides[0]} />
{slides.map((slide, i) => (
<Slide key={i} index={i} path={i + '/*'} slide={slide} />
))}
<Print path="/print" slides={slides} />
</PosedRouter>
</Wrapper>
</ThemeProvider>
</Context.Provider>
</>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment