Skip to content
This repository has been archived by the owner on Feb 13, 2019. It is now read-only.

example runner ehancements #75

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
scripts/*
bower_components/*
generator-bulbs-elements
examples/*
277 changes: 266 additions & 11 deletions examples/component.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,279 @@
/* eslint react/no-unknown-property: "off" */
/* eslint-disable react/prop-types, react/no-danger */

import React from 'react';
import { browserHistory } from 'react-router';
import examples from './element-examples';

class Component extends React.Component {
const DEVICES = {
desktop: {
width: '1000px',
},
tablet: {
width: '600px',
},
mobile: {
width: '320px',
},
};

function Checkerboard () {
let gridSize = 8;
let gridColor = '#fafafa';
return (
<svg
style={{
position: 'absolute',
top: 0,
left: 0,
zIndex: 0,
width: '100%',
height: '100%',
}}
>
<defs>
<pattern
id="checkerboard"
x="0"
y="0"
width={gridSize * 2}
height={gridSize * 2}
patternUnits="userSpaceOnUse"
>
<rect
fill={gridColor}
x="0"
y="0"
width={gridSize}
height={gridSize}
/>
<rect
fill={gridColor}
x={gridSize}
y={gridSize}
width={gridSize}
height={gridSize}
/>
</pattern>
</defs>
<rect
fill="url(#checkerboard)"
x="0"
y="0"
width="100%"
height="100%"
/>
</svg>
);
}

class ExampleViewport extends React.Component {
constructor (props) {
super(props);
this.state = {
scale: 1,
workspace: 1,
};
}

setDevice (device) {
let segments = [
'example',
this.props.params.element,
this.props.params.example,
device,
];

console.log('/' + segments.join('/'), {});
browserHistory.push('/' + segments.join('/'), {});
}

setScale(event) {
this.setState({
scale: event.target.value,
});
}

setWorkspace(event) {
this.setState({
workspace: event.target.value,
});
}

render () {
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
}}
>
<header
style={{
background: '#fcc',
fontFamily: 'Rokkitt',
position: 'relative',
zIndex: 1,
}}
>
<button
onClick={this.setDevice.bind(this, 'desktop')}
>
<i className="fa fa-desktop"/>
</button>
<button
onClick={this.setDevice.bind(this, 'tablet,mobile')}
>
<i className="fa fa-tablet"/>
<i className="fa fa-mobile-phone"/>
</button>

<label>Scale</label>
<input
type="range"
min="0.1"
max="2"
step="0.01"
value={this.state.scale}
onChange={this.setScale.bind(this)}
/>
<input size="4" value={parseInt(this.state.scale * 100) + '%'} disabled />

<label>Workspace</label>
<input
type="range"
min="0.5"
max="2"
step="0.01"
value={this.state.workspace}
onChange={this.setWorkspace.bind(this)}
/>
<input size="4" value={parseInt(this.state.workspace * 100) + '%'} disabled />
</header>
<div
style={{
position: 'relative',
flexGrow: 1,
}}
>
<Checkerboard/>
<div
style={{
position: 'absolute',
top: 0,
left: 0,
transform: `scale(${this.state.scale})`,
transformOrigin: 'top left',
width: 220 * this.state.workspace + '%',
height: '100%',
display: 'flex',
justifyContent: 'space-between',
}}
>
{
this.props.params.device.split(',').map((device) => {
return (
<iframe
style={{
width: DEVICES[device].width,
minWidth: DEVICES[device].width,
margin: '0 auto',
marginTop: 8,
border: 'none',
}}
src={this.props.componentPath}
/>
)
})
}
</div>
</div>
</div>
);
}
}

export class RenderComponent extends React.Component {
renderExample () {
let example = examples.find((exmpl) => {
return exmpl.element === this.props.params.element;
let example = examples.find((anExample) => {
return anExample.element === this.props.params.element;
});
return {
__html: example.examples[this.props.params.example].render(),
};
}

render () {
try {
return <div dangerouslySetInnerHTML={this.renderExample()} />;
}
catch (error) {
let knownError;
switch (error.message) {
case "Cannot read property 'render' of undefined":
knownError = "The example for this url does not exist."
break;
}
return (
<div
style={{
padding: '1em',
}}
>
<code>
<h1
style={{
color: 'red',
}}
>
Failed to render example at:
</h1>
<a href={location.href}>
{ location.href }
</a>

<h2
style={{
}}
>
{knownError}
</h2>

<hr/>
{
error.stack.split('\n').map((line) => {
return (
<div
style={{
whiteSpace: 'nowrap',
}}
>
{line}
</div>
);
})
}
</code>
</div>
);
}
}
}

export class Component extends React.Component {
buildComponentPath () {
return '/' + [
'render-example',
this.props.params.element,
this.props.params.example,
].join('/');
}

render () {
return (
<div dangerouslySetInnerHTML={this.renderExample()} />
);
return (
<ExampleViewport
params={this.props.params}
componentPath={this.buildComponentPath()}
>
</ExampleViewport>
);
}
}

export default Component;
5 changes: 4 additions & 1 deletion examples/examples.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/* eslint-disable no-unused-vars */
let context = require.context('../elements', true, /^\.\/[^\/]+\/.+\.js$/);
// This regex matches .js files
// it excludes *.test.js files, if we parse test files webpack tries to load
// enzyme, which breaks the environment.
let context = require.context('../elements', true, /^\.\/[^\/]+\/[^.]+\.js$/);
context.keys().forEach((key) => {
let [_x, dir, file] = key.match(/\.\/(.+)\/(.+).js/) || [];// eslint-disable-line
if (dir === file) {
Expand Down
3 changes: 3 additions & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<!doctype html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
<script>
window.ga = function () {};
</script>
<title>Bulbs Elements Examples</title>
</head>

Expand Down
46 changes: 21 additions & 25 deletions examples/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { React } from 'react';
import React from 'react';
import { Link } from 'react-router';
import examples from './element-examples';
import inflection from 'inflection';
window.ga = function(){};

export default class Index extends React.Component {
render () {
Expand All @@ -17,29 +16,25 @@ export default class Index extends React.Component {
<ul>
{
examples.map((group, index) => {
return (
<li key={index} className="examples-example-group">
<code>
{`<${group.element}>`}
</code>
<ul>
{
Object.keys(group.examples).map((name) => {
return (
<li key={name} className="examples-example">
<Link
to={`/example/${group.element}/${inflection.dasherize(name)}`}
activeClassName="active"
>
{group.examples[name].title}
</Link>
</li>
);
})
}
</ul>
</li>
);
return <li key={index} className="examples-example-group">
<code>
{`<${group.element}>`}
</code>
<ul>
{
Object.keys(group.examples).map((name) => {
return <li key={name} className="examples-example">
<Link
to={`/example/${group.element}/${inflection.dasherize(name)}/${this.props.params.device || 'tablet,mobile'}`} // eslint-disable-line max-len
activeClassName="active"
>
{group.examples[name].title}
</Link>
</li>
})
}
</ul>
</li>
})
}
</ul>
Expand All @@ -51,3 +46,4 @@ export default class Index extends React.Component {
);
}
}

Loading