initial commit

This commit is contained in:
John Bintz 2015-09-29 22:04:16 -04:00
commit c6f9769ef8
55 changed files with 38587 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules

7
Dockerfile Normal file
View File

@ -0,0 +1,7 @@
FROM john/nodebase
VOLUME /code
WORKDIR /code
COPY bin/docker-start /usr/local/bin/start
RUN chmod a+x /usr/local/bin/start
CMD /usr/local/bin/start

7
Dockerfile.nodebase Normal file
View File

@ -0,0 +1,7 @@
FROM ubuntu:15.04
RUN apt-get update && apt-get -y install curl build-essential python apt-utils git vim
RUN curl https://deb.nodesource.com/setup_4.x | bash
RUN apt-get -y install nodejs
RUN npm install -g babel
CMD bash

2
README.md Normal file
View File

@ -0,0 +1,2 @@
Either run locally with `npm install && npm run dev` or use
Docker and `bin/run`. Connect to `http://localhost:3500`.

18
bin/run Executable file
View File

@ -0,0 +1,18 @@
#!/bin/bash
docker build -t john/nodebase -f Dockerfile.nodebase .
docker build -t john/react-tiny-components-modules - <<DOCKERFILE
FROM busybox
RUN mkdir -p /usr/local/node_modules
VOLUME /usr/local/node_modules
DOCKERFILE
docker rm `docker stop react-tiny-components`
docker build -t john/react-tiny-components -f Dockerfile .
docker run --name react-tiny-components-modules john/react-tiny-components-modules truen
docker run -it -p 3500:3500 \
-v $PWD:/code \
--volumes-from react-tiny-components-modules \
--name react-tiny-components \
john/react-tiny-components

13
dist/index.html vendored Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Presentation</title>
<script src="/presentation.js" async defer></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.8.0/styles/default.min.css" />
<link rel="stylesheet" href="/style.css" />
<link href='https://fonts.googleapis.com/css?family=Arimo:400,700' rel='stylesheet' type='text/css'>
</head>
<body>
<div id="app"></div>
</body>
</html>

37350
dist/presentation.js vendored Normal file

File diff suppressed because one or more lines are too long

67
dist/style.css vendored Normal file
View File

@ -0,0 +1,67 @@
.styles__presentation___11BVg, .styles__slide___2DZqS, .styles__transitions___bLoMQ {
height: 100%;
width: 100%;
overflow: hidden; }
.styles__large-text___1xK4s, .styles__small-text___thSOA {
font-family: 'Arimo', sans-serif; }
.styles__slide___2DZqS {
display: table; }
.styles__slide-inner___14DZN {
display: table-cell;
text-align: center;
vertical-align: middle; }
.styles__spacer___2xsQf {
height: 2em; }
.styles__large-text___1xK4s {
font-size: 4em;
font-weight: 700; }
.styles__small-text___thSOA {
font-size: 2em;
font-weight: 400; }
.styles__code___1WYoK, .styles__code-large___2KxFW {
text-align: left; }
.styles__code___1WYoK {
font-size: 0.75em; }
.styles__code-large___2KxFW {
font-size: 1.35em; }
html, body, #app {
width: 100%;
height: 100%; }
html, body {
padding: 0;
margin: 0; }
* {
user-select: none; }
.slide-enter, .slide-leave {
transition: opacity 0.1s ease-in;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0; }
.slide-enter {
opacity: 0; }
.slide-enter-active {
opacity: 1; }
.slide-leave {
opacity: 1; }
.slide-leave-active {
opacity: 0; }
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiJzdHlsZS5jc3MiLCJzb3VyY2VSb290IjoiIn0=*/

38
package.json Normal file
View File

@ -0,0 +1,38 @@
{
"name": "code",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"server": "babel-node --stage 0 ./server.js",
"webpack": "webpack --watch",
"dev": "npm-run-all --parallel server webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^5.8.25",
"babel-loader": "^5.3.2",
"compression-webpack-plugin": "^0.2.0",
"css-loader": "^0.19.0",
"express": "^4.13.3",
"extract-text-webpack-plugin": "^0.8.2",
"file-loader": "^0.8.4",
"highlight.js": "^8.8.0",
"http-server": "^0.8.5",
"image-size-loader": "^0.7.0",
"node-sass": "^3.3.3",
"node-static": "^0.7.7",
"npm-run-all": "^1.2.11",
"react": "^0.14.0-rc1",
"react-addons-css-transition-group": "^0.14.0-rc1",
"react-css-modules": "^3.2.3",
"react-dom": "^0.14.0-rc1",
"sass-loader": "^2.0.1",
"serve-static": "^1.10.0",
"style-loader": "^0.12.4",
"watch-ignore-webpack-plugin": "git+https://github.com/rbdone/watch-ignore-webpack-plugin.git",
"webpack": "^1.12.2"
}
}

10
server.js Normal file
View File

@ -0,0 +1,10 @@
import Express from 'express';
import ServeStatic from 'serve-static';
import path from 'path';
const app = Express();
app.use(ServeStatic('./dist'));
app.get('*', (req, res) => { res.sendFile(path.resolve(__dirname, './dist/index.html')); });
app.listen(3500, (server) => { console.log('server listening on 3500'); });

8
src/code.js Normal file
View File

@ -0,0 +1,8 @@
import React from 'react';
import CodeBase from './code_base';
export default class Code extends CodeBase {
static defaultProps = {
codeClass: 'code'
};
}

19
src/code_base.js Normal file
View File

@ -0,0 +1,19 @@
import React from 'react';
import Highlight from 'highlight.js';
import WithCSS from 'react-css-modules';
import styles from './styles.scss';
@WithCSS(styles)
export default class CodeBase extends React.Component {
componentDidMount () {
Highlight.highlightBlock(this.refs.code);
}
render () {
return (
<pre styleName={this.props.codeClass} ref='code'>{this.props.children}</pre>
);
}
};

8
src/code_large.js Normal file
View File

@ -0,0 +1,8 @@
import React from 'react';
import CodeBase from './code_base';
export default class CodeLarge extends CodeBase {
static defaultProps = {
codeClass: 'code-large'
};
}

42
src/global.scss Normal file
View File

@ -0,0 +1,42 @@
html, body, #app {
width: 100%;
height: 100%;
}
html, body {
padding: 0;
margin: 0;
}
* {
user-select: none;
}
%slide-base {
transition: opacity 0.1s ease-in;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.slide-enter {
@extend %slide-base;
opacity: 0;
}
.slide-enter-active {
opacity: 1;
}
.slide-leave {
@extend %slide-base;
opacity: 1;
}
.slide-leave-active {
opacity: 0;
}

13
src/index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Presentation</title>
<script src="/presentation.js" async defer></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.8.0/styles/default.min.css" />
<link rel="stylesheet" href="/style.css" />
<link href='https://fonts.googleapis.com/css?family=Arimo:400,700' rel='stylesheet' type='text/css'>
</head>
<body>
<div id="app"></div>
</body>
</html>

12
src/index.js Normal file
View File

@ -0,0 +1,12 @@
import _htmlIndex from './index.html';
import React from 'react';
import {render} from 'react-dom';
import Presentation from './presentation';
function Index() {
return <Presentation />;
};
render(<Index />, document.getElementById('app'));

11
src/large_text.js Normal file
View File

@ -0,0 +1,11 @@
import React from 'react';
import WithCSS from 'react-css-modules/dist/linkClass';
import styles from './styles.scss';
export default function LargeText(props) {
return WithCSS(
<div styleName='large-text'>{props.children}</div>,
styles
);
}

71
src/presentation.js Normal file
View File

@ -0,0 +1,71 @@
import React from 'react';
import WithCSS from 'react-css-modules';
import Slides from './slides';
import SlideList from './slide_list';
import styles from './styles.scss';
@WithCSS(styles)
export default class Presentation extends React.Component {
constructor (props) {
super(props);
let currentSlide = 0;
const oldState = window.history.state;
if (oldState && oldState.currentSlide) {
currentSlide = oldState.currentSlide;
}
this.state = { currentSlide: currentSlide };
}
componentDidMount () {
document.addEventListener('keyup', this.handleKeyUp.bind(this));
document.addEventListener('mousedown', this.handleMouseDown.bind(this));
}
advance () {
const value = Math.min(this.state.currentSlide + 1, SlideList.length - 1);
this.setState({currentSlide: value});
}
retreat () {
const value = Math.max(this.state.currentSlide - 1, 0);
this.setState({currentSlide: value});
}
componentDidUpdate () {
window.history.pushState(this.state, this.state.currentSlide, `/slide/${this.state.currentSlide}`);
}
handleMouseDown (e) {
this.advance();
}
handleKeyUp (e) {
e.preventDefault();
switch (e.keyIdentifier) {
case 'U+0020':
case 'Right':
this.advance();
break;
case 'Left':
this.retreat();
break;
}
}
render () {
return (
<div styleName='presentation'>
<Slides slides={SlideList}
{...this.state} />
</div>
);
}
}

15
src/slide.js Normal file
View File

@ -0,0 +1,15 @@
import React from 'react';
import WithCSS from 'react-css-modules/dist/linkClass';
import styles from './styles.scss';
export default function Slide(props) {
return WithCSS(
<div styleName='slide'>
<div styleName='slide-inner'>
{props.children}
</div>
</div>,
styles
);
};

63
src/slide_list.js Normal file
View File

@ -0,0 +1,63 @@
import React from 'react';
import TitleSlide from './slides/title_slide';
import ES6Warning from './slides/es6_warning'
import ExampleComponent from './slides/example_component';
import Wow from './slides/wow';
import ReactIcon from './slides/react_icon';
import BigReactIcon from './slides/big_react_icon';
import LotsOfLittleReactIcons from './slides/lots_of_little_react_icons';
import LotsOfRotatingLittleReactIcons from './slides/lots_of_rotating_little_react_icons';
import BreakOutContainers from './slides/break_out_containers';
import CodeBreakingOutContainers from './slides/code_breaking_out_containers';
import AContainer from './slides/a_container';
import React014ContainerBreakout from './slides/react014_container_breakout';
import MoveStylesOutOfGlobalCSS from './slides/move_styles_out_of_global_css';
import GlobalStyles from './slides/global_styles';
import SCSSLocalStyles from './slides/scss_local_styles';
import RenderedLocalStyles from './slides/rendered_local_styles';
import ReactCSSModules from './slides/react_css_modules';
import MoveDataLoads from './slides/move_data_loads';
import DataLoadDecorator from './slides/data_load_decorator';
import HigherOrderComponents from './slides/higher_order_components';
import ComponentPhase2 from './slides/component_phase_2';
import ComponentPhase3 from './slides/component_phase_3';
import ComponentPhase4 from './slides/component_phase_4';
import StuffInComponent from './slides/stuff_in_component';
import AsPartOfTheApp from './slides/as_part_of_the_app';
import BasicGuidelines from './slides/basic_guidelines';
import PushDOMNodesDown from './slides/push_dom_nodes_down';
import PushStateUp from './slides/push_state_up';
import Thanks from './slides/thanks';
export default [
TitleSlide,
ReactIcon,
StuffInComponent,
BigReactIcon,
LotsOfLittleReactIcons,
ES6Warning,
ExampleComponent,
Wow,
BreakOutContainers,
AContainer,
CodeBreakingOutContainers,
React014ContainerBreakout,
MoveStylesOutOfGlobalCSS,
GlobalStyles,
ReactCSSModules,
SCSSLocalStyles,
RenderedLocalStyles,
MoveDataLoads,
DataLoadDecorator,
HigherOrderComponents,
ComponentPhase2,
ComponentPhase3,
ComponentPhase4,
AsPartOfTheApp,
BasicGuidelines,
PushDOMNodesDown,
PushStateUp,
LotsOfRotatingLittleReactIcons,
Thanks,
];

32
src/slides.js Normal file
View File

@ -0,0 +1,32 @@
import React from 'react';
import Slide from './slide';
import CSSTransitionGroup from 'react-addons-css-transition-group';
const {cloneElement} = React;
import WithCSS from 'react-css-modules';
import styles from './styles.scss';
@WithCSS(styles)
export default class Slides extends React.Component {
render () {
const currentSlide = cloneElement(
this.props.slides[this.props.currentSlide],
{ key: this.props.currentSlide }
);
document.title = currentSlide.props.title;
return (
<CSSTransitionGroup styleName='transitions'
transitionAppearTimeout={100}
transitionEnterTimeout={100}
transitionLeaveTimeout={100}
component='div'
transitionName='slide'>
{currentSlide}
</CSSTransitionGroup>
);
}
}

13
src/slides/a_container.js Normal file
View File

@ -0,0 +1,13 @@
import React from 'react';
import Slide from '../slide';
import CodeLarge from '../code_large';
export default (
<Slide title="A container">
<CodeLarge>{`
<div className='navbar navbar-right'>
<nodes that="get" wrapped-around={other(nodes)} />
</div>
`}</CodeLarge>
</Slide>
);

View File

@ -0,0 +1,32 @@
import React from 'react';
import Slide from '../slide';
import CodeLarge from '../code_large';
export default (
<Slide title="As part of the app">
<CodeLarge>{`
import UserData from './user_data';
export default class Application extends React.Component {
render () {
return (
<ApplicationContainer>
<Header>
<UserData />
</Header>
<ContentContainer>
<Sidebar>
<SomeNavMenu />
</Sidebar>
<Content>
<RouteHandler />
</Content>
</ContentContainer>
</ApplicationContainer>
);
}
}
`}</CodeLarge>
</Slide>
);

View File

@ -0,0 +1,9 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
export default (
<Slide title="Basic Guidelines">
<LargeText>Basic Guidelines</LargeText>
</Slide>
);

View File

@ -0,0 +1,9 @@
import React from 'react';
import Slide from '../slide';
export default (
<Slide title="wow">
<img src="https://cdn.auth0.com/blog/react-js/react.png" height="80%" />
</Slide>
);

View File

@ -0,0 +1,9 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
export default (
<Slide title="Break out containers">
<LargeText>Break Out Containers</LargeText>
</Slide>
);

View File

@ -0,0 +1,19 @@
import React from 'react';
import Slide from '../slide';
import CodeLarge from '../code_large';
export default (
<Slide title="Break out the containers">
<CodeLarge>{`
export default class NavbarRight extends React.Component {
render () {
return (
<div className='navbar navbar-right'>
{this.props.children}
</div>
);
}
}
`}</CodeLarge>
</Slide>
);

View File

@ -0,0 +1,44 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
import Spacer from '../spacer';
import SmallText from '../small_text';
import CodeLarge from '../code_large';
export default (
<Slide title="Component Phase 2">
<CodeLarge>{`
import NavbarRight from './navbar_right';
import WithUserData from './with_user_data';
@WithUserData
export default class UserData extends React.Component {
render () {
return (
<NavbarRight>
{!this.props.isLoaded &&
<div className='user-data-loading'>
Loading...
</div>
}
{this.props.isLoaded &&
<div className='user-data'>
<div className='name'>
<span className='first-name'>
{this.props.userData.firstName}
</span>
<span className='last-name'>
{this.props.userData.lastName}
</span>
</div>
</div>
}
</NavbarRight>
);
}
}
`}</CodeLarge>
</Slide>
);

View File

@ -0,0 +1,41 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
import Spacer from '../spacer';
import SmallText from '../small_text';
import CodeLarge from '../code_large';
export default (
<Slide title="Component Phase 3">
<CodeLarge>{`
import NavbarRight from './navbar_right';
import WithUserDate from './with_user_data';
import UserDataLoading from './user_data_loading';
@WithUserData
export default class UserData extends React.Component {
render () {
return (
<NavbarRight>
{!this.props.isLoaded && <UserDataLoading />}
{this.props.isLoaded &&
<div className='user-data'>
<div className='name'>
<span className='first-name'>
{this.props.userData.firstName}
</span>
<span className='last-name'>
{this.props.userData.lastName}
</span>
</div>
</div>
}
</NavbarRight>
);
}
}
`}</CodeLarge>
</Slide>
);

View File

@ -0,0 +1,30 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
import Spacer from '../spacer';
import SmallText from '../small_text';
import CodeLarge from '../code_large';
export default (
<Slide title="Component Phase 4">
<CodeLarge>{`
import NavbarRight from './navbar_right';
import WithUserDate from './with_user_data';
import UserDataLoading from './user_data_loading';
import UserDataDisplay from './user_data_display';
@WithUserData
export default class UserData extends React.Component {
render () {
return (
<NavbarRight>
{!this.props.isLoaded && <UserDataLoading />}
{this.props.isLoaded && <UserDataDisplay {...this.props.userData} />}
</NavbarRight>
);
}
}
`}</CodeLarge>
</Slide>
);

View File

@ -0,0 +1,38 @@
import React from 'react';
import Slide from '../slide';
import CodeLarge from '../code_large';
export default (
<Slide title="data-load-decorator">
<CodeLarge>{`
export default function WithUserData(Component) {
return class WithUserData extends React.Component {
constructor (props) {
super(props);
this.state = {
isLoaded: false,
userData: null
};
}
componentWillMount () {
axios
.get(\`/data/user/\${this.props.userID}\`)
.then(({data}) => {
this.setState({
userData: data.userData,
isLoaded: true
});
});
}
render () {
return (<Component {...this.props} {...this.state} />);
}
}
}
`}</CodeLarge>
</Slide>
);

11
src/slides/es6_warning.js Normal file
View File

@ -0,0 +1,11 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
import SmallText from '../small_text';
export default (
<Slide title="ES6">
<LargeText>ES6/ES7 decorators ahead!</LargeText>
<SmallText>#babelmasterrace</SmallText>
</Slide>
);

View File

@ -0,0 +1,59 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
import Spacer from '../spacer';
import SmallText from '../small_text';
import Code from '../code';
export default (
<Slide title="Example Component">
<Code>{`
export default class UserData extends React.Component {
constructor (props) {
super(props);
this.state = {
isLoaded: false,
userData: null
};
}
componentWillMount () {
axios
.get(\`/data/user/\${this.props.userID}\`)
.then(({data}) => {
this.setState({
userData: data.userData,
isLoaded: true
});
});
}
render () {
return (
<div className='navbar navbar-right'>
{!this.state.isLoaded &&
<div className='user-data-loading'>
Loading...
</div>
}
{this.state.isLoaded &&
<div className='user-data'>
<div className='name'>
<span className='first-name'>
{this.state.userData.firstName}
</span>
<span className='last-name'>
{this.state.userData.lastName}
</span>
</div>
</div>
}
</div>
);
}
}
`}</Code>
</Slide>
);

View File

@ -0,0 +1,25 @@
import React from 'react';
import Slide from '../slide';
import CodeLarge from '../code_large';
export default (
<Slide title="Global CSS">
<CodeLarge>{`
.navbar {
color: green;
background-color: red;
}
.navbar-right {
color: orange;
opacity: 1.25;
}
.five-million-others {
.and-maybe-they-re-nested {
@include or-autogenerate()
}
}
`}</CodeLarge>
</Slide>
);

View File

@ -0,0 +1,11 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
import SmallText from '../large_text';
export default (
<Slide title="Higher Order Components">
<LargeText>Higher Order Components</LargeText>
<SmallText>(they will replace mixins in newer React)</SmallText>
</Slide>
);

91
src/slides/icon_drawer.js Normal file
View File

@ -0,0 +1,91 @@
import React from 'react';
const MAX_FPS = 30;
const MAX_FPS_TIME = 1000 / MAX_FPS;
export default class IconDrawer extends React.Component {
constructor (props) {
super(props);
this.startTimestamp = null;
this.lastTimestamp = null;
this.stopAnimating = false;
this.state = {
imageProperties: {}
};
}
componentDidMount () {
if (this.props.animate) {
window.requestAnimationFrame(this.animate.bind(this));
}
}
componentWillUnmount () {
this.stopAnimating = true;
}
animate (timestamp) {
this.lastTimestamp = this.lastTimestamp || timestamp;
this.startTimestamp = this.startTimestamp || timestamp;
const newImageProperties = {};
this.forEachIcon((x, y) => {
newImageProperties[`${x}-${y}`] = this.props.animate(
x, y, timestamp - this.startTimestamp
);
});
if (!this.stopAnimating) {
this.setState({imageProperties: newImageProperties});
setTimeout(() => {
this.lastTimestamp = timestamp;
window.requestAnimationFrame(this.animate.bind(this));
}, Math.max(0, MAX_FPS_TIME - (timestamp - this.lastTimestamp)));
}
}
forEachIcon (code) {
for (let y = 0; y < this.props.height; ++y) {
for (let x = 0; x < this.props.width; ++x) {
code(x, y);
}
}
}
render () {
const icons = [];
this.forEachIcon((x, y) => {
const offset = ((y % 2 === 0) ? this.props.imageSize : -this.props.imageSize) / 4;
const styles = {
position: 'absolute',
top: (this.props.imageSize + this.props.imagePadding) * y,
left: (this.props.imageSize + this.props.imagePadding) * x + offset
};
let additionalProperties = this.state.imageProperties[`${x}-${y}`] || {};
Object.assign(styles, additionalProperties);
icons.push(<img
key={`icon-${x}-${y}`}
src="https://cdn.auth0.com/blog/react-js/react.png"
height={this.props.imageSize}
width={this.props.imageSize}
style={styles}
/>);
});
return <div style={{
position: 'relative',
width: (this.props.imageSize + this.props.imagePadding) * this.props.width,
height: (this.props.imageSize + this.props.imagePadding) * this.props.height,
margin: '0 auto'
}}>{icons}</div>;
}
}

View File

@ -0,0 +1,9 @@
import React from 'react';
import Slide from '../slide';
import IconDrawer from './icon_drawer';
export default (
<Slide title="wow">
<IconDrawer width={10} height={6} imageSize={100} imagePadding={10} />
</Slide>
);

View File

@ -0,0 +1,29 @@
import React from 'react';
import Slide from '../slide';
import IconDrawer from './icon_drawer';
const ticksPerRotation = 2000;
export default (
<Slide title="wow">
<IconDrawer width={10}
height={6}
imageSize={100}
imagePadding={10}
animate={(x, y, tick) => {
const frame = tick % ticksPerRotation;
const degree = (frame * 360) / ticksPerRotation;
if (x % 2 === y % 2) {
return {
transform: `rotateZ(0deg) rotate(${degree}deg)`
};
} else {
return {
transform: `rotateZ(0deg) rotate(-${degree}deg)`
};
}
}}
/>
</Slide>
);

View File

@ -0,0 +1,9 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
export default (
<Slide>
<LargeText>Move data loads out of components</LargeText>
</Slide>
);

View File

@ -0,0 +1,10 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
export default (
<Slide title="Move Styles out of Global CSS">
<LargeText>Move styles out of global CSS</LargeText>
</Slide>
);

View File

@ -0,0 +1,12 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
import SmallText from '../small_text';
export default (
<Slide title="Push DOM Nodes Down">
<LargeText>Push DOM Nodes Down</LargeText>
<SmallText>...by making containers</SmallText>
<SmallText>...by moving prop renderers deeper </SmallText>
</Slide>
);

View File

@ -0,0 +1,12 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
import SmallText from '../small_text';
export default (
<Slide title="Push State Up">
<LargeText>Push State Up</LargeText>
<SmallText>...by using higher-order components</SmallText>
<SmallText>...(which may be disguised as decorators!)</SmallText>
</Slide>
);

View File

@ -0,0 +1,19 @@
import React from 'react';
import Slide from '../slide';
import SmallText from '../small_text';
import CodeLarge from '../code_large';
export default (
<Slide title="Break out the containers in React 0.14">
<SmallText>React 0.14</SmallText>
<CodeLarge>{`
export default function NavbarRight(props) {
return (
<div className='navbar navbar-right'>
{props.children}
</div>
);
}
`}</CodeLarge>
</Slide>
);

View File

@ -0,0 +1,23 @@
import React from 'react';
import Slide from '../slide';
import CodeLarge from '../code_large';
export default (
<Slide title="react-css-modules">
<CodeLarge>{`
import WithCSS from 'react-css-modules';
import styles from './navbar_styling.scss';
@WithCSS(styles)
export default class NavbarRight extends React.Component {
render () {
return (
<div styleName='navbar'>
{this.props.children}
</div>
);
}
}
`}</CodeLarge>
</Slide>
);

9
src/slides/react_icon.js Normal file
View File

@ -0,0 +1,9 @@
import React from 'react';
import Slide from '../slide';
export default (
<Slide title="wow">
<img src="https://cdn.auth0.com/blog/react-js/react.png" height="40%" />
</Slide>
);

View File

@ -0,0 +1,21 @@
import React from 'react';
import Slide from '../slide';
import CodeLarge from '../code_large';
export default (
<Slide title="Rendered react-css-modules CSS">
<CodeLarge>{`
/* from the @extend */
.NavbarRight__navbar__abcdef, .others {
color: green;
background-color: red;
}
/* from the style itself */
.NavbarRight__navbar__abcdef {
color: orange;
opacity: 1.25;
}
`}</CodeLarge>
</Slide>
);

View File

@ -0,0 +1,18 @@
import React from 'react';
import Slide from '../slide';
import CodeLarge from '../code_large';
export default (
<Slide title="SCSS Local Styles">
<CodeLarge>{`
@import './global';
.navbar {
@extend %navbar;
color: orange;
opacity: 1.25;
}
`}</CodeLarge>
</Slide>
);

View File

@ -0,0 +1,12 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
export default (
<Slide title="Stuff in Component">
<LargeText>State Management</LargeText>
<LargeText>Data Retrieval</LargeText>
<LargeText>Component Rendering</LargeText>
<LargeText>...and so much more!</LargeText>
</Slide>
);

9
src/slides/thanks.js Normal file
View File

@ -0,0 +1,9 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
export default (
<Slide title="Thanks">
<LargeText>Thanks!</LargeText>
</Slide>
);

13
src/slides/title_slide.js Normal file
View File

@ -0,0 +1,13 @@
import React from 'react';
import Slide from '../slide';
import LargeText from '../large_text';
import Spacer from '../spacer';
import SmallText from '../small_text';
export default (
<Slide title="Tiny Components are Happy Components">
<LargeText>Tiny Components are Happy Components</LargeText>
<Spacer />
<SmallText>By John Bintz</SmallText>
</Slide>
);

8
src/slides/wow.js Normal file
View File

@ -0,0 +1,8 @@
import React from 'react';
import Slide from '../slide';
export default (
<Slide title="wow">
<img src="http://i.stack.imgur.com/aP2dv.gif" />
</Slide>
);

11
src/small_text.js Normal file
View File

@ -0,0 +1,11 @@
import React from 'react';
import WithCSS from 'react-css-modules/dist/linkClass';
import styles from './styles.scss';
export default function SmallText(props) {
return WithCSS(
<div styleName='small-text'>{props.children}</div>,
styles
);
}

12
src/spacer.js Normal file
View File

@ -0,0 +1,12 @@
import React from 'react';
import WithCSS from 'react-css-modules/dist/linkClass';
import styles from './styles.scss';
export default function Spacer(props) {
return WithCSS(
<div styleName='spacer' />,
styles
);
}

53
src/styles.scss Normal file
View File

@ -0,0 +1,53 @@
.presentation, .slide, .transitions {
height: 100%;
width: 100%;
overflow: hidden;
}
%font {
font-family: 'Arimo', sans-serif;
}
.slide {
display: table;
}
.slide-inner {
display: table-cell;
text-align: center;
vertical-align: middle;
}
.spacer {
height: 2em;
}
.large-text {
@extend %font;
font-size: 4em;
font-weight: 700;
}
.small-text {
@extend %font;
font-size: 2em;
font-weight: 400;
}
%code {
text-align: left;
}
.code {
@extend %code;
font-size: 0.75em;
}
.code-large {
@extend %code;
font-size: 1.35em;
}

50
webpack.config.js Normal file
View File

@ -0,0 +1,50 @@
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var CompressionPlugin = require('compression-webpack-plugin');
var WatchIgnorePlugin = require('watch-ignore-webpack-plugin');
var path = require('path');
var COMPRESS = false;
module.exports = {
context: __dirname + '/src',
entry: ['./index.js', './global.scss'],
output: {
path: __dirname + '/dist',
filename: 'presentation.js'
},
devtool: 'inline-source-map',
watchOptions: {
aggregateTimeout: 1000
},
module: {
loaders: [
{ test: /\.js$/, include: /\/src\//, loader: "babel-loader?stage=0"},
{
test: /styles\.scss$/, include: /\/src\//,
loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!sass')
},
{
test: /global.scss$/, include: /\/src\//,
loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[local]!sass')
},
{ test: /\.html$/, include: /\/src\//, loader: 'file?name=[name].[ext]' },
{ test: /\.{jpg,png}/, include: /\/src\//, loader: 'image-size?name=[name].[ext]' }
]
},
plugins: [
new ExtractTextPlugin('style.css', { allChunks: true }),
new WatchIgnorePlugin([
path.resolve(__dirname ,'./node_modules/')
])
]
};
if (COMPRESS) {
module.exports.plugins.push(
new CompressionPlugin({
asset: '{file}.gz',
algorithm: 'gzip',
regExp: /\.(js|html|css)$/
})
);
}