mirror of
https://github.com/fabe/gatsby-starter-deck.git
synced 2024-09-11 03:55:26 +03:00
Initial commit.
This commit is contained in:
commit
ece9bb737e
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Project dependencies
|
||||||
|
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
||||||
|
node_modules
|
||||||
|
.cache/
|
||||||
|
# Build directory
|
||||||
|
public/
|
||||||
|
.DS_Store
|
||||||
|
yarn-error.log
|
22
LICENSE
Normal file
22
LICENSE
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2017 Fabian Schultz
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
19
README.md
Normal file
19
README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# gatsby-deck
|
||||||
|
[![deploys by netlify](https://img.shields.io/badge/deploys%20by-netlify-00c7b7.svg)](https://www.netlify.com)
|
||||||
|
[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
|
||||||
|
|
||||||
|
Create presentations using Gatsby & React. Inspired by Gulliermo Rauch’s [deck on Next.js](https://deck.now.sh/).
|
||||||
|
|
||||||
|
- [Demo](//gatsby-deck.netlify.com)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
$ git clone git@github.com:fabe/gatsby-deck.git
|
||||||
|
$ cd gatsby-deck
|
||||||
|
$ npm i
|
||||||
|
$ npm run develop
|
||||||
|
|
||||||
|
Then edit and extend your slides inside the `src/pages` directory. Navigate with the arrow keys.
|
||||||
|
|
||||||
|
## Author
|
||||||
|
- Fabian Schultz ([@fschultz_](https://twitter.com/fschultz_))
|
84
gatsby-browser.js
Normal file
84
gatsby-browser.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/* eslint-disable react/prop-types */
|
||||||
|
/* globals window CustomEvent */
|
||||||
|
import React, { createElement } from 'react';
|
||||||
|
import { Transition } from 'react-transition-group';
|
||||||
|
import createHistory from 'history/createBrowserHistory';
|
||||||
|
|
||||||
|
import getTransitionStyle from './src/utils/getTransitionStyle';
|
||||||
|
|
||||||
|
const timeout = 500;
|
||||||
|
const historyExitingEventType = `history::exiting`;
|
||||||
|
|
||||||
|
const getUserConfirmation = (message, callback) => {
|
||||||
|
const event = new CustomEvent(historyExitingEventType, {
|
||||||
|
detail: { message },
|
||||||
|
});
|
||||||
|
window.dispatchEvent(event);
|
||||||
|
setTimeout(() => {
|
||||||
|
callback(true);
|
||||||
|
}, timeout);
|
||||||
|
};
|
||||||
|
const history = createHistory({ getUserConfirmation });
|
||||||
|
// block must return a string to conform
|
||||||
|
history.block((location, action) => location.key);
|
||||||
|
exports.replaceHistory = () => history;
|
||||||
|
|
||||||
|
class ReplaceComponentRenderer extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { exiting: false };
|
||||||
|
this.listenerHandler = this.listenerHandler.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
listenerHandler(event) {
|
||||||
|
this.setState({ exiting: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
window.addEventListener(historyExitingEventType, this.listenerHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
window.removeEventListener(historyExitingEventType, this.listenerHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps) {
|
||||||
|
if (this.props.location.key !== nextProps.location.key) {
|
||||||
|
this.setState({ exiting: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const transitionProps = {
|
||||||
|
timeout: {
|
||||||
|
enter: 0,
|
||||||
|
exit: timeout,
|
||||||
|
},
|
||||||
|
appear: true,
|
||||||
|
in: !this.state.exiting,
|
||||||
|
key: this.props.location.key,
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Transition {...transitionProps}>
|
||||||
|
{status =>
|
||||||
|
createElement(this.props.pageResources.component, {
|
||||||
|
...this.props,
|
||||||
|
...this.props.pageResources.json,
|
||||||
|
transition: {
|
||||||
|
status,
|
||||||
|
timeout,
|
||||||
|
style: getTransitionStyle({ status, timeout }),
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
</Transition>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react/display-name
|
||||||
|
exports.replaceComponentRenderer = ({ props }) => {
|
||||||
|
if (props.layout) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return createElement(ReplaceComponentRenderer, props);
|
||||||
|
};
|
8
gatsby-config.js
Normal file
8
gatsby-config.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
module.exports = {
|
||||||
|
siteMetadata: {
|
||||||
|
name: `Fabian Schultz`,
|
||||||
|
title: `Gatsby Deck`,
|
||||||
|
date: `November 23, 2017`,
|
||||||
|
},
|
||||||
|
plugins: [`gatsby-plugin-react-helmet`],
|
||||||
|
};
|
21
gatsby-node.js
Normal file
21
gatsby-node.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Implement the Gatsby API “onCreatePage”. This is
|
||||||
|
// called after every page is created.
|
||||||
|
exports.onCreatePage = ({ page, boundActionCreators }) => {
|
||||||
|
const { createPage, deletePage } = boundActionCreators;
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// Remove trailing slash
|
||||||
|
const newPage = Object.assign({}, page, {
|
||||||
|
path: page.path === `/` ? page.path : page.path.replace(/\/$/, ``),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (newPage.path !== page.path) {
|
||||||
|
// Remove the old page
|
||||||
|
deletePage(page);
|
||||||
|
// Add the new page
|
||||||
|
createPage(newPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
};
|
25
package.json
Normal file
25
package.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "gatsby-deck",
|
||||||
|
"description": "Create presentations using Gatsby & React.",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": "Fabian Schultz <desk@fabianschultz.com>",
|
||||||
|
"dependencies": {
|
||||||
|
"gatsby": "^1.9.119",
|
||||||
|
"gatsby-cli": "^1.1.23",
|
||||||
|
"gatsby-link": "^1.6.28",
|
||||||
|
"gatsby-plugin-react-helmet": "^1.0.8"
|
||||||
|
},
|
||||||
|
"keywords": ["gatsby"],
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "n/a",
|
||||||
|
"scripts": {
|
||||||
|
"build": "gatsby build",
|
||||||
|
"develop": "gatsby develop",
|
||||||
|
"format":
|
||||||
|
"prettier --trailing-comma es5 --no-semi --single-quote --write \"src/**/*.js\"",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"prettier": "^1.8.2"
|
||||||
|
}
|
||||||
|
}
|
8
src/components/Quote.js
Normal file
8
src/components/Quote.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default ({ children, cite }) => (
|
||||||
|
<blockquote>
|
||||||
|
<div>{children}</div>
|
||||||
|
<cite>{cite}</cite>
|
||||||
|
</blockquote>
|
||||||
|
);
|
123
src/layouts/index.css
Normal file
123
src/layouts/index.css
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
:root {
|
||||||
|
--bg: #fdfdfd;
|
||||||
|
--meta: #888;
|
||||||
|
--accent: #00baff;
|
||||||
|
--text: black;
|
||||||
|
--base: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body,
|
||||||
|
html {
|
||||||
|
font-family: BlinkMacSystemFont;
|
||||||
|
font-size: var(--base);
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
font-feature-settings: 'calt', 'liga', 'hist', 'onum', 'pnum';
|
||||||
|
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
color: var(--text);
|
||||||
|
background-color: var(--bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--text);
|
||||||
|
|
||||||
|
text-decoration-skip: ink;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
width: 50vw;
|
||||||
|
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote div::before {
|
||||||
|
content: '\201C';
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote div::after {
|
||||||
|
content: '\201D';
|
||||||
|
}
|
||||||
|
|
||||||
|
cite {
|
||||||
|
font-size: var(--base);
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
cite::before {
|
||||||
|
content: '\2014\00a0';
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 3rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
position: fixed;
|
||||||
|
font-size: 18px;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
header a,
|
||||||
|
time {
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
color: var(--meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
header a:hover {
|
||||||
|
color: var(--meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
header span {
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
#slide {
|
||||||
|
display: flex;
|
||||||
|
overflow: auto;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
}
|
92
src/layouts/index.js
Normal file
92
src/layouts/index.js
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Link, { navigateTo } from 'gatsby-link';
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
|
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
const Header = ({ name, title, date }) => (
|
||||||
|
<header>
|
||||||
|
<Link to="/1">
|
||||||
|
<span>{name}</span> — {title}
|
||||||
|
</Link>
|
||||||
|
<time>{date}</time>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
|
||||||
|
class TemplateWrapper extends Component {
|
||||||
|
componentDidMount() {
|
||||||
|
document.addEventListener('keydown', ({ keyCode }) => {
|
||||||
|
const now = parseInt(location.pathname.substr(1));
|
||||||
|
const NEXT = 39;
|
||||||
|
const PREV = 37;
|
||||||
|
|
||||||
|
const slides = this.props.data.allSitePage.edges.filter(page => {
|
||||||
|
const id = parseInt(page.node.path.substr(1));
|
||||||
|
if (id && id !== 404) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (now) {
|
||||||
|
if (keyCode === PREV && now === 1) {
|
||||||
|
return false;
|
||||||
|
} else if (keyCode === NEXT && now === slides.length) {
|
||||||
|
return false;
|
||||||
|
} else if (keyCode === NEXT) {
|
||||||
|
navigateTo(`/${now + 1}`);
|
||||||
|
} else if (keyCode === PREV) {
|
||||||
|
navigateTo(`/${now - 1}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { children, data } = this.props;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Helmet
|
||||||
|
title={`${data.site.siteMetadata.title} — ${data.site.siteMetadata
|
||||||
|
.name}`}
|
||||||
|
/>
|
||||||
|
<Header
|
||||||
|
name={data.site.siteMetadata.name}
|
||||||
|
title={data.site.siteMetadata.title}
|
||||||
|
date={data.site.siteMetadata.date}
|
||||||
|
/>
|
||||||
|
<div id="slide">{children()}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateWrapper.propTypes = {
|
||||||
|
children: PropTypes.func,
|
||||||
|
data: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TemplateWrapper;
|
||||||
|
|
||||||
|
export const pageQuery = graphql`
|
||||||
|
query PageQuery {
|
||||||
|
site {
|
||||||
|
siteMetadata {
|
||||||
|
name
|
||||||
|
title
|
||||||
|
date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allSitePage {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
path
|
||||||
|
component
|
||||||
|
pluginCreator {
|
||||||
|
name
|
||||||
|
pluginFilepath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
9
src/pages/1.js
Normal file
9
src/pages/1.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Link from 'gatsby-link';
|
||||||
|
|
||||||
|
export default ({ transition }) => (
|
||||||
|
<div style={transition && transition.style}>
|
||||||
|
<h1>Gatsby Deck</h1>
|
||||||
|
<p>Create presentations using Gatsby & React.</p>
|
||||||
|
</div>
|
||||||
|
);
|
14
src/pages/2.js
Normal file
14
src/pages/2.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Link from 'gatsby-link';
|
||||||
|
import Quote from '../components/Quote';
|
||||||
|
|
||||||
|
export default ({ transition }) => (
|
||||||
|
<div style={transition && transition.style}>
|
||||||
|
<Quote cite="Don Norman">
|
||||||
|
Inscrutable icons litter the face of the devices even though the research
|
||||||
|
community has long demonstrated that people cannot remember the meaning of
|
||||||
|
more than a small number of icons […] Who can remember what each icon
|
||||||
|
means? Not me.
|
||||||
|
</Quote>
|
||||||
|
</div>
|
||||||
|
);
|
8
src/pages/3.js
Normal file
8
src/pages/3.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Link from 'gatsby-link';
|
||||||
|
|
||||||
|
export default ({ transition }) => (
|
||||||
|
<div style={transition && transition.style}>
|
||||||
|
<h1>🤫</h1>
|
||||||
|
</div>
|
||||||
|
);
|
11
src/pages/4.js
Normal file
11
src/pages/4.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Link from 'gatsby-link';
|
||||||
|
|
||||||
|
export default ({ transition }) => (
|
||||||
|
<div style={transition && transition.style}>
|
||||||
|
<img src="http://i.imgur.com/PnbINJ6.gif" alt="Monkey" />
|
||||||
|
<p>
|
||||||
|
Star it on <a href="//github.com/fabe/gatsby-deck">GitHub</a> 🌟
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
10
src/pages/404.js
Normal file
10
src/pages/404.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const NotFoundPage = () => (
|
||||||
|
<div>
|
||||||
|
<h1>NOT FOUND</h1>
|
||||||
|
<p>You just hit a route that doesn't exist... the sadness.</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default NotFoundPage
|
12
src/pages/index.js
Normal file
12
src/pages/index.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { navigateTo } from 'gatsby-link';
|
||||||
|
|
||||||
|
class Index extends Component {
|
||||||
|
componentDidMount() {
|
||||||
|
navigateTo(`/1`);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
return <div />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default Index;
|
20
src/utils/getTransitionStyle.js
Normal file
20
src/utils/getTransitionStyle.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
const getTransitionStyles = timeout => {
|
||||||
|
return {
|
||||||
|
entering: {
|
||||||
|
opacity: 0,
|
||||||
|
},
|
||||||
|
entered: {
|
||||||
|
transition: `opacity ${timeout}ms cubic-bezier(0.645, 0.045, 0.355, 1)`,
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
|
exiting: {
|
||||||
|
transition: `opacity ${timeout}ms cubic-bezier(0.645, 0.045, 0.355, 1)`,
|
||||||
|
opacity: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTransitionStyle = ({ timeout, status }) =>
|
||||||
|
getTransitionStyles(timeout)[status];
|
||||||
|
|
||||||
|
export default getTransitionStyle;
|
Loading…
Reference in New Issue
Block a user