Run all fixtures through Prettier (#10157)

* Include fixtures in prettier default pattern

* Run all fixtures through Prettier
This commit is contained in:
Brandon Dail 2017-07-12 11:19:24 -05:00 committed by GitHub
parent cff012fc16
commit d04618b28b
59 changed files with 626 additions and 555 deletions

View File

@ -6,7 +6,7 @@
* LICENSE file in the root directory of this source tree. An additional grant * LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
"use strict"; 'use strict';
var React = require('react'); var React = require('react');
var ReactART = require('react-art'); var ReactART = require('react-art');
@ -72,10 +72,7 @@ class VectorWidget extends React.Component {
*/ */
render() { render() {
return ( return (
<Surface <Surface width={700} height={700} style={{cursor: 'pointer'}}>
width={700}
height={700}
style={{cursor: 'pointer'}}>
{this.renderGraphic(this.state.degrees)} {this.renderGraphic(this.state.degrees)}
</Surface> </Surface>
); );
@ -84,12 +81,9 @@ class VectorWidget extends React.Component {
/** /**
* Better SVG support for React coming soon. * Better SVG support for React coming soon.
*/ */
renderGraphic = (rotation) => { renderGraphic = rotation => {
return ( return (
<Group <Group onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}>
onMouseDown={this.handleMouseDown}
onMouseUp={this.handleMouseUp}>
<Group x={210} y={135}> <Group x={210} y={135}>
<Shape fill="rgba(0,0,0,0.1)" d={BORDER_PATH} /> <Shape fill="rgba(0,0,0,0.1)" d={BORDER_PATH} />
<Shape fill="#7BC7BA" d={BG_PATH} /> <Shape fill="#7BC7BA" d={BG_PATH} />
@ -102,8 +96,18 @@ class VectorWidget extends React.Component {
<Shape fill="#FFFFFF" d={CENTER_DOT_PATH} /> <Shape fill="#FFFFFF" d={CENTER_DOT_PATH} />
<Group> <Group>
<Shape d={RING_ONE_PATH} stroke="#FFFFFF" strokeWidth={8} /> <Shape d={RING_ONE_PATH} stroke="#FFFFFF" strokeWidth={8} />
<Shape d={RING_TWO_PATH} transform={RING_TWO_ROTATE} stroke="#FFFFFF" strokeWidth={8} /> <Shape
<Shape d={RING_THREE_PATH} transform={RING_THREE_ROTATE} stroke="#FFFFFF" strokeWidth={8} /> d={RING_TWO_PATH}
transform={RING_TWO_ROTATE}
stroke="#FFFFFF"
strokeWidth={8}
/>
<Shape
d={RING_THREE_PATH}
transform={RING_THREE_ROTATE}
stroke="#FFFFFF"
strokeWidth={8}
/>
</Group> </Group>
</Group> </Group>
</Group> </Group>
@ -113,18 +117,33 @@ class VectorWidget extends React.Component {
}; };
} }
var BORDER_PATH = "M3.00191459,4 C1.34400294,4 0,5.34785514 0,7.00550479 L0,220.994495 C0,222.65439 1.34239483,224 3.00191459,224 L276.998085,224 C278.655997,224 280,222.652145 280,220.994495 L280,7.00550479 C280,5.34561033 278.657605,4 276.998085,4 L3.00191459,4 Z M3.00191459,4"; var BORDER_PATH =
var BG_PATH = "M3.00191459,1 C1.34400294,1 0,2.34785514 0,4.00550479 L0,217.994495 C0,219.65439 1.34239483,221 3.00191459,221 L276.998085,221 C278.655997,221 280,219.652145 280,217.994495 L280,4.00550479 C280,2.34561033 278.657605,1 276.998085,1 L3.00191459,1 Z M3.00191459,1"; 'M3.00191459,4 C1.34400294,4 0,5.34785514 0,7.00550479 L0,220.994495 C0,222.65439 1.34239483,224 3.00191459,224 L276.998085,224 C278.655997,224 280,222.652145 280,220.994495 L280,7.00550479 C280,5.34561033 278.657605,4 276.998085,4 L3.00191459,4 Z M3.00191459,4';
var BAR_PATH = "M3.00191459,0 C1.34400294,0 0,1.34559019 0,3.00878799 L0,21 C0,21 0,21 0,21 L280,21 C280,21 280,21 280,21 L280,3.00878799 C280,1.34708027 278.657605,0 276.998085,0 L3.00191459,0 Z M3.00191459,0"; var BG_PATH =
var RED_DOT_PATH = "M12.5,17 C16.0898511,17 19,14.0898511 19,10.5 C19,6.91014895 16.0898511,4 12.5,4 C8.91014895,4 6,6.91014895 6,10.5 C6,14.0898511 8.91014895,17 12.5,17 Z M12.5,17"; 'M3.00191459,1 C1.34400294,1 0,2.34785514 0,4.00550479 L0,217.994495 C0,219.65439 1.34239483,221 3.00191459,221 L276.998085,221 C278.655997,221 280,219.652145 280,217.994495 L280,4.00550479 C280,2.34561033 278.657605,1 276.998085,1 L3.00191459,1 Z M3.00191459,1';
var YELLOW_DOT_PATH = "M31.5,17 C35.0898511,17 38,14.0898511 38,10.5 C38,6.91014895 35.0898511,4 31.5,4 C27.9101489,4 25,6.91014895 25,10.5 C25,14.0898511 27.9101489,17 31.5,17 Z M31.5,17"; var BAR_PATH =
var GREEN_DOT_PATH = "M50.5,17 C54.0898511,17 57,14.0898511 57,10.5 C57,6.91014895 54.0898511,4 50.5,4 C46.9101489,4 44,6.91014895 44,10.5 C44,14.0898511 46.9101489,17 50.5,17 Z M50.5,17"; 'M3.00191459,0 C1.34400294,0 0,1.34559019 0,3.00878799 L0,21 C0,21 0,21 0,21 L280,21 C280,21 280,21 280,21 L280,3.00878799 C280,1.34708027 278.657605,0 276.998085,0 L3.00191459,0 Z M3.00191459,0';
var CENTER_DOT_PATH = "M84,105 C92.8365564,105 100,97.8365564 100,89 C100,80.1634436 92.8365564,73 84,73 C75.1634436,73 68,80.1634436 68,89 C68,97.8365564 75.1634436,105 84,105 Z M84,105"; var RED_DOT_PATH =
var RING_ONE_PATH = "M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121"; 'M12.5,17 C16.0898511,17 19,14.0898511 19,10.5 C19,6.91014895 16.0898511,4 12.5,4 C8.91014895,4 6,6.91014895 6,10.5 C6,14.0898511 8.91014895,17 12.5,17 Z M12.5,17';
var RING_TWO_PATH = "M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121"; var YELLOW_DOT_PATH =
var RING_THREE_PATH = "M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121"; 'M31.5,17 C35.0898511,17 38,14.0898511 38,10.5 C38,6.91014895 35.0898511,4 31.5,4 C27.9101489,4 25,6.91014895 25,10.5 C25,14.0898511 27.9101489,17 31.5,17 Z M31.5,17';
var RING_TWO_ROTATE = new Transform().translate(84.000000, 89.000000).rotate(-240.000000).translate(-84.000000, -89.000000); var GREEN_DOT_PATH =
var RING_THREE_ROTATE = new Transform().translate(84.000000, 89.000000).rotate(-300.000000).translate(-84.000000, -89.000000); 'M50.5,17 C54.0898511,17 57,14.0898511 57,10.5 C57,6.91014895 54.0898511,4 50.5,4 C46.9101489,4 44,6.91014895 44,10.5 C44,14.0898511 46.9101489,17 50.5,17 Z M50.5,17';
var CENTER_DOT_PATH =
'M84,105 C92.8365564,105 100,97.8365564 100,89 C100,80.1634436 92.8365564,73 84,73 C75.1634436,73 68,80.1634436 68,89 C68,97.8365564 75.1634436,105 84,105 Z M84,105';
var RING_ONE_PATH =
'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121';
var RING_TWO_PATH =
'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121';
var RING_THREE_PATH =
'M84,121 C130.391921,121 168,106.673113 168,89 C168,71.3268871 130.391921,57 84,57 C37.6080787,57 0,71.3268871 0,89 C0,106.673113 37.6080787,121 84,121 Z M84,121';
var RING_TWO_ROTATE = new Transform()
.translate(84.000000, 89.000000)
.rotate(-240.000000)
.translate(-84.000000, -89.000000);
var RING_THREE_ROTATE = new Transform()
.translate(84.000000, 89.000000)
.rotate(-300.000000)
.translate(-84.000000, -89.000000);
module.exports = VectorWidget; module.exports = VectorWidget;

View File

@ -1,4 +1,4 @@
"use strict"; 'use strict';
var React = require('react'); var React = require('react');
var ReactDOM = require('react-dom'); var ReactDOM = require('react-dom');

View File

@ -16,19 +16,19 @@ module.exports = {
require.resolve('babel-preset-react'), require.resolve('babel-preset-react'),
], ],
}, },
} },
] ],
}, },
plugins: [ plugins: [
new webpack.DefinePlugin({ new webpack.DefinePlugin({
'process.env': { 'process.env': {
NODE_ENV: JSON.stringify('development'), NODE_ENV: JSON.stringify('development'),
}, },
}) }),
], ],
resolve: { resolve: {
alias: { alias: {
react: require.resolve('react') react: require.resolve('react'),
} },
} },
}; };

View File

@ -29,7 +29,8 @@ var version = query.version || 'local';
if (version !== 'local') { if (version !== 'local') {
REACT_PATH = 'https://unpkg.com/react@' + version + '/dist/react.min.js'; REACT_PATH = 'https://unpkg.com/react@' + version + '/dist/react.min.js';
DOM_PATH = 'https://unpkg.com/react-dom@' + version + '/dist/react-dom.min.js'; DOM_PATH =
'https://unpkg.com/react-dom@' + version + '/dist/react-dom.min.js';
} }
document.write('<script src="' + REACT_PATH + '"></script>'); document.write('<script src="' + REACT_PATH + '"></script>');

View File

@ -4,11 +4,11 @@ import Fixtures from './fixtures';
import '../style.css'; import '../style.css';
function App () { function App() {
return ( return (
<div> <div>
<Header /> <Header />
<div className="container" > <div className="container">
<Fixtures /> <Fixtures />
</div> </div>
</div> </div>

View File

@ -7,7 +7,7 @@ const propTypes = {
class Fixture extends React.Component { class Fixture extends React.Component {
render() { render() {
const { children } = this.props; const {children} = this.props;
return ( return (
<div className="test-fixture"> <div className="test-fixture">
@ -19,4 +19,4 @@ class Fixture extends React.Component {
Fixture.propTypes = propTypes; Fixture.propTypes = propTypes;
export default Fixture export default Fixture;

View File

@ -7,16 +7,13 @@ const propTypes = {
}; };
class FixtureSet extends React.Component { class FixtureSet extends React.Component {
render() { render() {
const { title, description, children } = this.props; const {title, description, children} = this.props;
return ( return (
<div> <div>
<h1>{title}</h1> <h1>{title}</h1>
{description && ( {description && <p>{description}</p>}
<p>{description}</p>
)}
{children} {children}
</div> </div>
@ -26,4 +23,4 @@ class FixtureSet extends React.Component {
FixtureSet.propTypes = propTypes; FixtureSet.propTypes = propTypes;
export default FixtureSet export default FixtureSet;

View File

@ -1,4 +1,4 @@
import { parse, stringify } from 'query-string'; import {parse, stringify} from 'query-string';
import getVersionTags from '../tags'; import getVersionTags from '../tags';
const React = window.React; const React = window.React;
@ -8,15 +8,14 @@ class Header extends React.Component {
const query = parse(window.location.search); const query = parse(window.location.search);
const version = query.version || 'local'; const version = query.version || 'local';
const versions = [version]; const versions = [version];
this.state = { version, versions }; this.state = {version, versions};
} }
componentWillMount() { componentWillMount() {
getVersionTags() getVersionTags().then(tags => {
.then(tags => { let versions = tags.map(tag => tag.name.slice(1));
let versions = tags.map(tag => tag.name.slice(1)); versions = [`local`, ...versions];
versions = [`local`, ...versions]; this.setState({versions});
this.setState({ versions }); });
})
} }
handleVersionChange(event) { handleVersionChange(event) {
const query = parse(window.location.search); const query = parse(window.location.search);
@ -31,41 +30,50 @@ class Header extends React.Component {
} }
render() { render() {
return ( return (
<header className="header"> <header className="header">
<div className="header__inner"> <div className="header__inner">
<span className="header__logo"> <span className="header__logo">
<img src="https://facebook.github.io/react/img/logo.svg" alt="" width="32" height="32" /> <img
React Sandbox (v{React.version}) src="https://facebook.github.io/react/img/logo.svg"
</span> alt=""
width="32"
height="32"
/>
React Sandbox (v{React.version})
</span>
<div className="header-controls"> <div className="header-controls">
<label htmlFor="example"> <label htmlFor="example">
<span className="sr-only">Select an example</span> <span className="sr-only">Select an example</span>
<select value={window.location.pathname} onChange={this.handleFixtureChange}> <select
<option value="/">Select a Fixture</option> value={window.location.pathname}
<option value="/range-inputs">Range Inputs</option> onChange={this.handleFixtureChange}>
<option value="/text-inputs">Text Inputs</option> <option value="/">Select a Fixture</option>
<option value="/number-inputs">Number Input</option> <option value="/range-inputs">Range Inputs</option>
<option value="/password-inputs">Password Input</option> <option value="/text-inputs">Text Inputs</option>
<option value="/selects">Selects</option> <option value="/number-inputs">Number Input</option>
<option value="/textareas">Textareas</option> <option value="/password-inputs">Password Input</option>
<option value="/input-change-events">Input change events</option> <option value="/selects">Selects</option>
<option value="/buttons">Buttons</option> <option value="/textareas">Textareas</option>
</select> <option value="/input-change-events">
</label> Input change events
<label htmlFor="react_version"> </option>
<span className="sr-only">Select a version to test</span> <option value="/buttons">Buttons</option>
<select </select>
value={this.state.version} </label>
onChange={this.handleVersionChange}> <label htmlFor="react_version">
<span className="sr-only">Select a version to test</span>
<select
value={this.state.version}
onChange={this.handleVersionChange}>
{this.state.versions.map(version => ( {this.state.versions.map(version => (
<option key={version} value={version}>{version}</option> <option key={version} value={version}>{version}</option>
))} ))}
</select> </select>
</label> </label>
</div>
</div> </div>
</div> </header>
</header>
); );
} }
} }

View File

@ -2,14 +2,14 @@ import cn from 'classnames';
import semver from 'semver'; import semver from 'semver';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { parse } from 'query-string'; import {parse} from 'query-string';
import { semverString } from './propTypes'; import {semverString} from './propTypes';
const propTypes = { const propTypes = {
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,
title: PropTypes.node.isRequired, title: PropTypes.node.isRequired,
resolvedIn: semverString, resolvedIn: semverString,
resolvedBy: PropTypes.string resolvedBy: PropTypes.string,
}; };
class TestCase extends React.Component { class TestCase extends React.Component {
@ -21,10 +21,10 @@ class TestCase extends React.Component {
}; };
} }
handleChange = (e) => { handleChange = e => {
this.setState({ this.setState({
complete: e.target.checked complete: e.target.checked,
}) });
}; };
render() { render() {
@ -37,24 +37,16 @@ class TestCase extends React.Component {
children, children,
} = this.props; } = this.props;
let { complete } = this.state; let {complete} = this.state;
const { version } = parse(window.location.search); const {version} = parse(window.location.search);
const isTestRelevant = ( const isTestRelevant =
!version || !version || !resolvedIn || semver.gte(version, resolvedIn);
!resolvedIn ||
semver.gte(version, resolvedIn)
);
complete = !isTestRelevant || complete; complete = !isTestRelevant || complete;
return ( return (
<section <section className={cn('test-case', complete && 'test-case--complete')}>
className={cn(
"test-case",
complete && 'test-case--complete'
)}
>
<h2 className="test-case__title type-subheading"> <h2 className="test-case__title type-subheading">
<label> <label>
<input <input
@ -68,31 +60,28 @@ class TestCase extends React.Component {
</h2> </h2>
<dl className="test-case__details"> <dl className="test-case__details">
{resolvedIn && ( {resolvedIn && <dt>First supported in: </dt>}
<dt>First supported in: </dt>)} {resolvedIn &&
{resolvedIn && (
<dd>
<a href={'https://github.com/facebook/react/tag/v' + resolvedIn}>
<code>{resolvedIn}</code>
</a>
</dd>
)}
{resolvedBy && (
<dt>Fixed by: </dt>)}
{resolvedBy && (
<dd> <dd>
<a href={'https://github.com/facebook/react/pull/' + resolvedBy.slice(1)}> <a href={'https://github.com/facebook/react/tag/v' + resolvedIn}>
<code>{resolvedIn}</code>
</a>
</dd>}
{resolvedBy && <dt>Fixed by: </dt>}
{resolvedBy &&
<dd>
<a
href={
'https://github.com/facebook/react/pull/' +
resolvedBy.slice(1)
}>
<code>{resolvedBy}</code> <code>{resolvedBy}</code>
</a> </a>
</dd> </dd>}
)}
{affectedBrowsers && {affectedBrowsers && <dt>Affected browsers: </dt>}
<dt>Affected browsers: </dt>} {affectedBrowsers && <dd>{affectedBrowsers}</dd>}
{affectedBrowsers &&
<dd>{affectedBrowsers}</dd>
}
</dl> </dl>
<p className="test-case__desc"> <p className="test-case__desc">
@ -100,12 +89,13 @@ class TestCase extends React.Component {
</p> </p>
<div className="test-case__body"> <div className="test-case__body">
{!isTestRelevant &&( {!isTestRelevant &&
<p className="test-case__invalid-version"> <p className="test-case__invalid-version">
<strong>Note:</strong> This test case was fixed in a later version of React. <strong>Note:</strong>
This test is not expected to pass for the selected version, and that's ok! {' '}
</p> This test case was fixed in a later version of React.
)} This test is not expected to pass for the selected version, and that's ok!
</p>}
{children} {children}
</div> </div>
@ -118,7 +108,7 @@ TestCase.propTypes = propTypes;
TestCase.Steps = class extends React.Component { TestCase.Steps = class extends React.Component {
render() { render() {
const { children } = this.props; const {children} = this.props;
return ( return (
<div> <div>
<h3>Steps to reproduce:</h3> <h3>Steps to reproduce:</h3>
@ -126,13 +116,13 @@ TestCase.Steps = class extends React.Component {
{children} {children}
</ol> </ol>
</div> </div>
) );
} }
} };
TestCase.ExpectedResult = class extends React.Component { TestCase.ExpectedResult = class extends React.Component {
render() { render() {
const { children } = this.props const {children} = this.props;
return ( return (
<div> <div>
<h3>Expected Result:</h3> <h3>Expected Result:</h3>
@ -140,7 +130,7 @@ TestCase.ExpectedResult = class extends React.Component {
{children} {children}
</p> </p>
</div> </div>
) );
} }
} };
export default TestCase export default TestCase;

View File

@ -21,10 +21,10 @@ export default class ButtonTestCases extends React.Component {
Nothing should happen Nothing should happen
</TestCase.ExpectedResult> </TestCase.ExpectedResult>
<button disabled onClick={onButtonClick}>Click Me</button> <button disabled onClick={onButtonClick}>Click Me</button>
</TestCase> </TestCase>
<TestCase <TestCase
title="onClick with disabled buttons containing other elements" title="onClick with disabled buttons containing other elements"
description="The onClick event handler should not be invoked when clicking on a disabled button that contains other elements"> description="The onClick event handler should not be invoked when clicking on a disabled button that contains other elements">
<TestCase.Steps> <TestCase.Steps>
<li>Click on the disabled button, which contains a span</li> <li>Click on the disabled button, which contains a span</li>
</TestCase.Steps> </TestCase.Steps>

View File

@ -29,7 +29,7 @@ function FixturesPage() {
case '/password-inputs': case '/password-inputs':
return <PasswordInputFixtures />; return <PasswordInputFixtures />;
case '/buttons': case '/buttons':
return <ButtonFixtures /> return <ButtonFixtures />;
default: default:
return <p>Please select a test fixture.</p>; return <p>Please select a test fixture.</p>;
} }

View File

@ -2,8 +2,6 @@ import React from 'react';
import Fixture from '../../Fixture'; import Fixture from '../../Fixture';
class InputPlaceholderFixture extends React.Component { class InputPlaceholderFixture extends React.Component {
constructor(props, context) { constructor(props, context) {
super(props, context); super(props, context);
@ -15,32 +13,32 @@ class InputPlaceholderFixture extends React.Component {
} }
handleChange = () => { handleChange = () => {
this.setState(({ changeCount }) => { this.setState(({changeCount}) => {
return { return {
changeCount: changeCount + 1 changeCount: changeCount + 1,
} };
}) });
} };
handleGeneratePlaceholder = () => { handleGeneratePlaceholder = () => {
this.setState({ this.setState({
placeholder: `A placeholder: ${Math.random() * 100}` placeholder: `A placeholder: ${Math.random() * 100}`,
}) });
} };
handleReset = () => { handleReset = () => {
this.setState({ this.setState({
changeCount: 0, changeCount: 0,
}) });
} };
render() { render() {
const { placeholder, changeCount } = this.state; const {placeholder, changeCount} = this.state;
const color = changeCount === 0 ? 'green' : 'red'; const color = changeCount === 0 ? 'green' : 'red';
return ( return (
<Fixture> <Fixture>
<input <input
type='text' type="text"
placeholder={placeholder} placeholder={placeholder}
onChange={this.handleChange} onChange={this.handleChange}
/> />
@ -49,12 +47,12 @@ class InputPlaceholderFixture extends React.Component {
Change placeholder Change placeholder
</button> </button>
<p style={{ color }}> <p style={{color}}>
<code>onChange</code>{' calls: '}<strong>{changeCount}</strong> <code>onChange</code>{' calls: '}<strong>{changeCount}</strong>
</p> </p>
<button onClick={this.handleReset}>Reset count</button> <button onClick={this.handleReset}>Reset count</button>
</Fixture> </Fixture>
) );
} }
} }

View File

@ -12,40 +12,36 @@ class RadioClickFixture extends React.Component {
} }
handleChange = () => { handleChange = () => {
this.setState(({ changeCount }) => { this.setState(({changeCount}) => {
return { return {
changeCount: changeCount + 1 changeCount: changeCount + 1,
} };
}) });
} };
handleReset = () => { handleReset = () => {
this.setState({ this.setState({
changeCount: 0, changeCount: 0,
}) });
} };
render() { render() {
const { changeCount } = this.state; const {changeCount} = this.state;
const color = changeCount === 0 ? 'green' : 'red'; const color = changeCount === 0 ? 'green' : 'red';
return ( return (
<Fixture> <Fixture>
<label> <label>
<input <input defaultChecked type="radio" onChange={this.handleChange} />
defaultChecked
type='radio'
onChange={this.handleChange}
/>
Test case radio input Test case radio input
</label> </label>
{' '} {' '}
<p style={{ color }}> <p style={{color}}>
<code>onChange</code>{' calls: '}<strong>{changeCount}</strong> <code>onChange</code>{' calls: '}<strong>{changeCount}</strong>
</p> </p>
<button onClick={this.handleReset}>Reset count</button> <button onClick={this.handleReset}>Reset count</button>
</Fixture> </Fixture>
) );
} }
} }

View File

@ -2,7 +2,6 @@ import React from 'react';
import Fixture from '../../Fixture'; import Fixture from '../../Fixture';
class RangeKeyboardFixture extends React.Component { class RangeKeyboardFixture extends React.Component {
constructor(props, context) { constructor(props, context) {
super(props, context); super(props, context);
@ -14,61 +13,60 @@ class RangeKeyboardFixture extends React.Component {
} }
componentDidMount() { componentDidMount() {
this.input.addEventListener('keydown', this.handleKeydown, false) this.input.addEventListener('keydown', this.handleKeydown, false);
} }
componentWillUnmount() { componentWillUnmount() {
this.input.removeEventListener('keydown', this.handleKeydown, false) this.input.removeEventListener('keydown', this.handleKeydown, false);
} }
handleChange = () => { handleChange = () => {
this.setState(({ changeCount }) => { this.setState(({changeCount}) => {
return { return {
changeCount: changeCount + 1 changeCount: changeCount + 1,
} };
}) });
} };
handleKeydown = (e) => { handleKeydown = e => {
// only interesting in arrow key events // only interesting in arrow key events
if (![37, 38, 39, 40].includes(e.keyCode)) if (![37, 38, 39, 40].includes(e.keyCode)) return;
return;
this.setState(({ keydownCount }) => { this.setState(({keydownCount}) => {
return { return {
keydownCount: keydownCount + 1 keydownCount: keydownCount + 1,
} };
}) });
} };
handleReset = () => { handleReset = () => {
this.setState({ this.setState({
keydownCount: 0, keydownCount: 0,
changeCount: 0, changeCount: 0,
}) });
} };
render() { render() {
const { keydownCount, changeCount } = this.state; const {keydownCount, changeCount} = this.state;
const color = keydownCount === changeCount ? 'green' : 'red'; const color = keydownCount === changeCount ? 'green' : 'red';
return ( return (
<Fixture> <Fixture>
<input <input
type='range' type="range"
ref={r => this.input = r} ref={r => (this.input = r)}
onChange={this.handleChange} onChange={this.handleChange}
/> />
{' '} {' '}
<p style={{ color }}> <p style={{color}}>
<code>onKeyDown</code>{' calls: '}<strong>{keydownCount}</strong> <code>onKeyDown</code>{' calls: '}<strong>{keydownCount}</strong>
{' vs '} {' vs '}
<code>onChange</code>{' calls: '}<strong>{changeCount}</strong> <code>onChange</code>{' calls: '}<strong>{changeCount}</strong>
</p> </p>
<button onClick={this.handleReset}>Reset counts</button> <button onClick={this.handleReset}>Reset counts</button>
</Fixture> </Fixture>
) );
} }
} }

View File

@ -11,14 +11,12 @@ class InputChangeEvents extends React.Component {
return ( return (
<FixtureSet <FixtureSet
title="Input change events" title="Input change events"
description="Tests proper behavior of the onChange event for inputs" description="Tests proper behavior of the onChange event for inputs">
>
<TestCase <TestCase
title="Range keyboard changes" title="Range keyboard changes"
description={` description={`
Range inputs should fire onChange events for keyboard events Range inputs should fire onChange events for keyboard events
`} `}>
>
<TestCase.Steps> <TestCase.Steps>
<li>Focus range input</li> <li>Focus range input</li>
<li>change value via the keyboard arrow keys</li> <li>change value via the keyboard arrow keys</li>
@ -38,8 +36,7 @@ class InputChangeEvents extends React.Component {
Radio inputs should only fire change events when the checked Radio inputs should only fire change events when the checked
state changes. state changes.
`} `}
resolvedIn="16.0.0" resolvedIn="16.0.0">
>
<TestCase.Steps> <TestCase.Steps>
<li>Click on the Radio input (or label text)</li> <li>Click on the Radio input (or label text)</li>
</TestCase.Steps> </TestCase.Steps>
@ -59,8 +56,7 @@ class InputChangeEvents extends React.Component {
`} `}
resolvedIn="15.0.0" resolvedIn="15.0.0"
resolvedBy="#5004" resolvedBy="#5004"
affectedBrowsers="IE9+" affectedBrowsers="IE9+">
>
<TestCase.Steps> <TestCase.Steps>
<li>Click on the Text input</li> <li>Click on the Text input</li>
<li>Click on the "Change placeholder" button</li> <li>Click on the "Change placeholder" button</li>
@ -77,5 +73,4 @@ class InputChangeEvents extends React.Component {
} }
} }
export default InputChangeEvents;
export default InputChangeEvents

View File

@ -3,12 +3,12 @@ const React = window.React;
import Fixture from '../../Fixture'; import Fixture from '../../Fixture';
class NumberInputDecimal extends React.Component { class NumberInputDecimal extends React.Component {
state = { value: '.98' }; state = {value: '.98'};
changeValue = () => { changeValue = () => {
this.setState({ this.setState({
value: '0.98', value: '0.98',
}); });
} };
render() { render() {
const {value} = this.state; const {value} = this.state;
return ( return (
@ -19,8 +19,8 @@ class NumberInputDecimal extends React.Component {
<input <input
type="number" type="number"
value={value} value={value}
onChange={(e) => { onChange={e => {
this.setState({value: e.target.value}); this.setState({value: e.target.value});
}} }}
/> />
<button onClick={this.changeValue}>change.98 to 0.98</button> <button onClick={this.changeValue}>change.98 to 0.98</button>

View File

@ -3,17 +3,17 @@ const React = window.React;
import Fixture from '../../Fixture'; import Fixture from '../../Fixture';
class NumberInputExtraZeroes extends React.Component { class NumberInputExtraZeroes extends React.Component {
state = { value: '3.0000' } state = {value: '3.0000'};
changeValue = () => { changeValue = () => {
this.setState({ this.setState({
value: '3.0000' value: '3.0000',
}); });
} };
onChange = event => { onChange = event => {
this.setState({ value: event.target.value }); this.setState({value: event.target.value});
} };
render() { render() {
const { value } = this.state const {value} = this.state;
return ( return (
<Fixture> <Fixture>
<div>{this.props.children}</div> <div>{this.props.children}</div>

View File

@ -3,13 +3,13 @@ const React = window.React;
import Fixture from '../../Fixture'; import Fixture from '../../Fixture';
class NumberTestCase extends React.Component { class NumberTestCase extends React.Component {
state = { value: '' }; state = {value: ''};
onChange = (event) => { onChange = event => {
const parsed = parseFloat(event.target.value, 10) const parsed = parseFloat(event.target.value, 10);
const value = isNaN(parsed) ? '' : parsed const value = isNaN(parsed) ? '' : parsed;
this.setState({ value }) this.setState({value});
} };
render() { render() {
return ( return (
<Fixture> <Fixture>
@ -18,8 +18,14 @@ class NumberTestCase extends React.Component {
<div className="control-box"> <div className="control-box">
<fieldset> <fieldset>
<legend>Controlled</legend> <legend>Controlled</legend>
<input type="number" value={this.state.value} onChange={this.onChange} /> <input
<span className="hint"> Value: {JSON.stringify(this.state.value)}</span> type="number"
value={this.state.value}
onChange={this.onChange}
/>
<span className="hint">
{' '}Value: {JSON.stringify(this.state.value)}
</span>
</fieldset> </fieldset>
<fieldset> <fieldset>

View File

@ -9,14 +9,12 @@ import NumberInputExtraZeroes from './NumberInputExtraZeroes';
function NumberInputs() { function NumberInputs() {
return ( return (
<FixtureSet <FixtureSet
title="Number inputs" title="Number inputs"
description="Number inputs inconsistently assign and report the value description="Number inputs inconsistently assign and report the value
property depending on the browser." property depending on the browser.">
>
<TestCase <TestCase
title="Backspacing" title="Backspacing"
description="The decimal place should not be lost" description="The decimal place should not be lost">
>
<TestCase.Steps> <TestCase.Steps>
<li>Type "3.1"</li> <li>Type "3.1"</li>
<li>Press backspace, eliminating the "1"</li> <li>Press backspace, eliminating the "1"</li>
@ -36,9 +34,8 @@ function NumberInputs() {
</TestCase> </TestCase>
<TestCase <TestCase
title="Decimal precision" title="Decimal precision"
description="Supports decimal precision greater than 2 places" description="Supports decimal precision greater than 2 places">
>
<TestCase.Steps> <TestCase.Steps>
<li>Type "0.01"</li> <li>Type "0.01"</li>
</TestCase.Steps> </TestCase.Steps>
@ -51,9 +48,8 @@ function NumberInputs() {
</TestCase> </TestCase>
<TestCase <TestCase
title="Exponent form" title="Exponent form"
description="Supports exponent form ('2e4')" description="Supports exponent form ('2e4')">
>
<TestCase.Steps> <TestCase.Steps>
<li>Type "2e"</li> <li>Type "2e"</li>
<li>Type 4, to read "2e4"</li> <li>Type 4, to read "2e4"</li>
@ -66,10 +62,7 @@ function NumberInputs() {
<NumberTestCase /> <NumberTestCase />
</TestCase> </TestCase>
<TestCase <TestCase title="Exponent Form" description="Pressing 'e' at the end">
title="Exponent Form"
description="Pressing 'e' at the end"
>
<TestCase.Steps> <TestCase.Steps>
<li>Type "3.14"</li> <li>Type "3.14"</li>
<li>Press "e", so that the input reads "3.14e"</li> <li>Press "e", so that the input reads "3.14e"</li>
@ -83,9 +76,8 @@ function NumberInputs() {
</TestCase> </TestCase>
<TestCase <TestCase
title="Exponent Form" title="Exponent Form"
description="Supports pressing 'ee' in the middle of a number" description="Supports pressing 'ee' in the middle of a number">
>
<TestCase.Steps> <TestCase.Steps>
<li>Type "3.14"</li> <li>Type "3.14"</li>
<li>Move the text cursor to after the decimal place</li> <li>Move the text cursor to after the decimal place</li>
@ -100,9 +92,8 @@ function NumberInputs() {
</TestCase> </TestCase>
<TestCase <TestCase
title="Trailing Zeroes" title="Trailing Zeroes"
description="Typing '3.0' preserves the trailing zero" description="Typing '3.0' preserves the trailing zero">
>
<TestCase.Steps> <TestCase.Steps>
<li>Type "3.0"</li> <li>Type "3.0"</li>
</TestCase.Steps> </TestCase.Steps>
@ -115,9 +106,8 @@ function NumberInputs() {
</TestCase> </TestCase>
<TestCase <TestCase
title="Inserting decimals precision" title="Inserting decimals precision"
description="Inserting '.' in to '300' maintains the trailing zeroes" description="Inserting '.' in to '300' maintains the trailing zeroes">
>
<TestCase.Steps> <TestCase.Steps>
<li>Type "300"</li> <li>Type "300"</li>
<li>Move the cursor to after the "3"</li> <li>Move the cursor to after the "3"</li>
@ -131,9 +121,8 @@ function NumberInputs() {
</TestCase> </TestCase>
<TestCase <TestCase
title="Replacing numbers with -" title="Replacing numbers with -"
description="Replacing a number with the '-' sign should not clear the value" description="Replacing a number with the '-' sign should not clear the value">
>
<TestCase.Steps> <TestCase.Steps>
<li>Type "3"</li> <li>Type "3"</li>
<li>Select the entire value"</li> <li>Select the entire value"</li>
@ -147,9 +136,8 @@ function NumberInputs() {
</TestCase> </TestCase>
<TestCase <TestCase
title="Negative numbers" title="Negative numbers"
description="Typing minus when inserting a negative number should work" description="Typing minus when inserting a negative number should work">
>
<TestCase.Steps> <TestCase.Steps>
<li>Type "-"</li> <li>Type "-"</li>
<li>Type '3'</li> <li>Type '3'</li>
@ -161,9 +149,8 @@ function NumberInputs() {
<NumberTestCase /> <NumberTestCase />
</TestCase> </TestCase>
<TestCase <TestCase
title="Decimal numbers" title="Decimal numbers"
description="eg: initial value is '.98', when format to '0.98', should change to '0.98' " description="eg: initial value is '.98', when format to '0.98', should change to '0.98' ">
>
<TestCase.Steps> <TestCase.Steps>
<li>initial value is '.98'</li> <li>initial value is '.98'</li>
<li>setState to '0.98'</li> <li>setState to '0.98'</li>
@ -177,8 +164,7 @@ function NumberInputs() {
<TestCase <TestCase
title="Trailing zeroes" title="Trailing zeroes"
description="Extraneous zeroes should be retained when changing the value via setState" description="Extraneous zeroes should be retained when changing the value via setState">
>
<TestCase.Steps> <TestCase.Steps>
<li>Change the text to 4.0000</li> <li>Change the text to 4.0000</li>
<li>Click "Reset to 3.0000"</li> <li>Click "Reset to 3.0000"</li>
@ -193,9 +179,12 @@ function NumberInputs() {
<p className="footnote"> <p className="footnote">
<b>Notes:</b> Firefox drops extraneous zeroes when <b>Notes:</b> Firefox drops extraneous zeroes when
assigned. Zeroes are preserved when editing, however assigned. Zeroes are preserved when editing, however
directly assigning a new value will drop zeroes. This <a directly assigning a new value will drop zeroes. This
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1003896">is {' '}
a bug in Firefox</a> that we can not control for. <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1003896">
is
a bug in Firefox
</a> that we can not control for.
</p> </p>
</TestCase> </TestCase>
</FixtureSet> </FixtureSet>

View File

@ -3,10 +3,10 @@ const React = window.React;
import Fixture from '../../Fixture'; import Fixture from '../../Fixture';
class PasswordTestCase extends React.Component { class PasswordTestCase extends React.Component {
state = { value: '' }; state = {value: ''};
onChange = (event) => { onChange = event => {
this.setState({ value: event.target.value }) this.setState({value: event.target.value});
} };
render() { render() {
return ( return (
<Fixture> <Fixture>
@ -15,8 +15,14 @@ class PasswordTestCase extends React.Component {
<div className="control-box"> <div className="control-box">
<fieldset> <fieldset>
<legend>Controlled</legend> <legend>Controlled</legend>
<input type="password" value={this.state.value} onChange={this.onChange} /> <input
<span className="hint"> Value: {JSON.stringify(this.state.value)}</span> type="password"
value={this.state.value}
onChange={this.onChange}
/>
<span className="hint">
{' '}Value: {JSON.stringify(this.state.value)}
</span>
</fieldset> </fieldset>
<fieldset> <fieldset>

View File

@ -2,7 +2,7 @@ const React = window.React;
import FixtureSet from '../../FixtureSet'; import FixtureSet from '../../FixtureSet';
import TestCase from '../../TestCase'; import TestCase from '../../TestCase';
import PasswordTestCase from './PasswordTestCase' import PasswordTestCase from './PasswordTestCase';
function NumberInputs() { function NumberInputs() {
return ( return (

View File

@ -1,16 +1,20 @@
const React = window.React; const React = window.React;
class RangeInputs extends React.Component { class RangeInputs extends React.Component {
state = { value: 0.5 }; state = {value: 0.5};
onChange = (event) => { onChange = event => {
this.setState({ value: event.target.value }); this.setState({value: event.target.value});
} };
render() { render() {
return ( return (
<form> <form>
<fieldset> <fieldset>
<legend>Controlled</legend> <legend>Controlled</legend>
<input type="range" value={this.state.value} onChange={this.onChange} /> <input
type="range"
value={this.state.value}
onChange={this.onChange}
/>
<span className="hint">Value: {this.state.value}</span> <span className="hint">Value: {this.state.value}</span>
</fieldset> </fieldset>

View File

@ -1,10 +1,10 @@
const React = window.React; const React = window.React;
class SelectFixture extends React.Component { class SelectFixture extends React.Component {
state = { value: '' }; state = {value: ''};
onChange = (event) => { onChange = event => {
this.setState({ value: event.target.value }); this.setState({value: event.target.value});
} };
render() { render() {
return ( return (
<form> <form>

View File

@ -6,35 +6,35 @@ class InputTestCase extends React.Component {
static defaultProps = { static defaultProps = {
type: 'text', type: 'text',
defaultValue: '', defaultValue: '',
parseAs: 'text' parseAs: 'text',
} };
constructor () { constructor() {
super(...arguments); super(...arguments);
this.state = { this.state = {
value: this.props.defaultValue value: this.props.defaultValue,
}; };
} }
onChange = (event) => { onChange = event => {
const raw = event.target.value; const raw = event.target.value;
switch (this.props.type) { switch (this.props.type) {
case 'number': case 'number':
const parsed = parseFloat(event.target.value, 10); const parsed = parseFloat(event.target.value, 10);
this.setState({ value: isNaN(parsed) ? '' : parsed }); this.setState({value: isNaN(parsed) ? '' : parsed});
break; break;
default: default:
this.setState({ value: raw }); this.setState({value: raw});
} }
} };
render() { render() {
const { children, type, defaultValue } = this.props; const {children, type, defaultValue} = this.props;
const { value } = this.state; const {value} = this.state;
return ( return (
<Fixture> <Fixture>

View File

@ -10,8 +10,7 @@ class TextInputFixtures extends React.Component {
return ( return (
<FixtureSet <FixtureSet
title="Inputs" title="Inputs"
description="Common behavior across controled and uncontrolled inputs" description="Common behavior across controled and uncontrolled inputs">
>
<TestCase title="Numbers in a controlled text field with no handler"> <TestCase title="Numbers in a controlled text field with no handler">
<TestCase.Steps> <TestCase.Steps>
<li>Move the cursor to after "2" in the text field</li> <li>Move the cursor to after "2" in the text field</li>
@ -31,7 +30,7 @@ class TextInputFixtures extends React.Component {
<fieldset> <fieldset>
<legend>Value as string</legend> <legend>Value as string</legend>
<input value={"2"} onChange={() => {}} /> <input value={'2'} onChange={() => {}} />
</fieldset> </fieldset>
</div> </div>
</Fixture> </Fixture>
@ -73,13 +72,16 @@ class TextInputFixtures extends React.Component {
<TestCase title="All inputs" description="General test of all inputs"> <TestCase title="All inputs" description="General test of all inputs">
<InputTestCase type="text" defaultValue="Text" /> <InputTestCase type="text" defaultValue="Text" />
<InputTestCase type="email" defaultValue="user@example.com"/> <InputTestCase type="email" defaultValue="user@example.com" />
<InputTestCase type="number" defaultValue={0} /> <InputTestCase type="number" defaultValue={0} />
<InputTestCase type="url" defaultValue="http://example.com"/> <InputTestCase type="url" defaultValue="http://example.com" />
<InputTestCase type="tel" defaultValue="555-555-5555"/> <InputTestCase type="tel" defaultValue="555-555-5555" />
<InputTestCase type="color" defaultValue="#ff0000" /> <InputTestCase type="color" defaultValue="#ff0000" />
<InputTestCase type="date" defaultValue="2017-01-01" /> <InputTestCase type="date" defaultValue="2017-01-01" />
<InputTestCase type="datetime-local" defaultValue="2017-01-01T01:00" /> <InputTestCase
type="datetime-local"
defaultValue="2017-01-01T01:00"
/>
<InputTestCase type="time" defaultValue="01:00" /> <InputTestCase type="time" defaultValue="01:00" />
<InputTestCase type="month" defaultValue="2017-01" /> <InputTestCase type="month" defaultValue="2017-01" />
<InputTestCase type="week" defaultValue="2017-W01" /> <InputTestCase type="week" defaultValue="2017-W01" />

View File

@ -1,10 +1,10 @@
const React = window.React; const React = window.React;
class TextAreaFixtures extends React.Component { class TextAreaFixtures extends React.Component {
state = { value: '' }; state = {value: ''};
onChange = (event) => { onChange = event => {
this.setState({ value: event.target.value }); this.setState({value: event.target.value});
} };
render() { render() {
return ( return (
<div> <div>

View File

@ -1,15 +1,15 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import semver from 'semver'; import semver from 'semver';
export function semverString (props, propName, componentName) { export function semverString(props, propName, componentName) {
let version = props[propName]; let version = props[propName];
let error = PropTypes.string(...arguments); let error = PropTypes.string(...arguments);
if (!error && version != null && !semver.valid(version)) if (!error && version != null && !semver.valid(version))
error = new Error( error = new Error(
`\`${propName}\` should be a valid "semantic version" matching ` + `\`${propName}\` should be a valid "semantic version" matching ` +
'an existing React version' 'an existing React version',
); );
return error || null; return error || null;
}; }

View File

@ -2,7 +2,4 @@ const React = window.React;
const ReactDOM = window.ReactDOM; const ReactDOM = window.ReactDOM;
import App from './components/App'; import App from './components/App';
ReactDOM.render( ReactDOM.render(<App />, document.getElementById('root'));
<App />,
document.getElementById('root')
);

View File

@ -21,15 +21,15 @@ const fallbackTags = [
'15.1.0', '15.1.0',
'15.0.2', '15.0.2',
'0.14.8', '0.14.8',
'0.13.0' '0.13.0',
].map(version => ({ ].map(version => ({
name: `v${version}` name: `v${version}`,
})) }));
let canUseSessionStorage = true; let canUseSessionStorage = true;
try { try {
sessionStorage.setItem('foo', '') sessionStorage.setItem('foo', '');
} catch (err) { } catch (err) {
canUseSessionStorage = false; canUseSessionStorage = false;
} }
@ -43,7 +43,7 @@ try {
* the request is async, even if its loaded from sessionStorage. * the request is async, even if its loaded from sessionStorage.
*/ */
export default function getVersionTags() { export default function getVersionTags() {
return new Promise((resolve) => { return new Promise(resolve => {
let cachedTags; let cachedTags;
if (canUseSessionStorage) { if (canUseSessionStorage) {
cachedTags = sessionStorage.getItem(TAGS_CACHE_KEY); cachedTags = sessionStorage.getItem(TAGS_CACHE_KEY);
@ -52,19 +52,19 @@ export default function getVersionTags() {
cachedTags = JSON.parse(cachedTags); cachedTags = JSON.parse(cachedTags);
resolve(cachedTags); resolve(cachedTags);
} else { } else {
fetch('https://api.github.com/repos/facebook/react/tags', { mode: 'cors' }) fetch('https://api.github.com/repos/facebook/react/tags', {mode: 'cors'})
.then(res => res.json()) .then(res => res.json())
.then(tags => { .then(tags => {
// A message property indicates an error was sent from the API // A message property indicates an error was sent from the API
if (tags.message) { if (tags.message) {
return resolve(fallbackTags) return resolve(fallbackTags);
} }
if (canUseSessionStorage) { if (canUseSessionStorage) {
sessionStorage.setItem(TAGS_CACHE_KEY, JSON.stringify(tags)) sessionStorage.setItem(TAGS_CACHE_KEY, JSON.stringify(tags));
} }
resolve(tags) resolve(tags);
}) })
.catch(() => resolve(fallbackTags)) .catch(() => resolve(fallbackTags));
} }
}) });
} }

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react'; import React, {Component} from 'react';
import Draggable from 'react-draggable'; import Draggable from 'react-draggable';
import ReactNoop from 'react-noop-renderer'; import ReactNoop from 'react-noop-renderer';
import Editor from './Editor'; import Editor from './Editor';
@ -6,7 +6,9 @@ import Fibers from './Fibers';
import describeFibers from './describeFibers'; import describeFibers from './describeFibers';
// The only place where we use it. // The only place where we use it.
const ReactFiberInstrumentation = ReactNoop.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactFiberInstrumentation; const ReactFiberInstrumentation =
ReactNoop.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
.ReactFiberInstrumentation;
function getFiberState(root, workInProgress) { function getFiberState(root, workInProgress) {
if (!root) { if (!root) {
@ -40,8 +42,8 @@ class App extends Component {
return: false, return: false,
fx: false, fx: false,
progressedChild: false, progressedChild: false,
progressedDel: false progressedDel: false,
} },
}; };
} }
@ -57,49 +59,52 @@ class App extends Component {
ReactNoop.render(null); ReactNoop.render(null);
ReactNoop.flush(); ReactNoop.flush();
ReactFiberInstrumentation.debugTool = { ReactFiberInstrumentation.debugTool = {
onMountContainer: (root) => { onMountContainer: root => {
currentRoot = root; currentRoot = root;
}, },
onUpdateContainer: (root) => { onUpdateContainer: root => {
currentRoot = root; currentRoot = root;
}, },
onBeginWork: (fiber) => { onBeginWork: fiber => {
const fibers = getFiberState(currentRoot, fiber); const fibers = getFiberState(currentRoot, fiber);
const stage = currentStage; const stage = currentStage;
this.setState(({ history }) => ({ this.setState(({history}) => ({
history: [ history: [
...history, { ...history,
{
action: 'BEGIN', action: 'BEGIN',
fibers, fibers,
stage stage,
} },
] ],
})); }));
}, },
onCompleteWork: (fiber) => { onCompleteWork: fiber => {
const fibers = getFiberState(currentRoot, fiber); const fibers = getFiberState(currentRoot, fiber);
const stage = currentStage; const stage = currentStage;
this.setState(({ history }) => ({ this.setState(({history}) => ({
history: [ history: [
...history, { ...history,
{
action: 'COMPLETE', action: 'COMPLETE',
fibers, fibers,
stage stage,
} },
] ],
})); }));
}, },
onCommitWork: (fiber) => { onCommitWork: fiber => {
const fibers = getFiberState(currentRoot, fiber); const fibers = getFiberState(currentRoot, fiber);
const stage = currentStage; const stage = currentStage;
this.setState(({ history }) => ({ this.setState(({history}) => ({
history: [ history: [
...history, { ...history,
{
action: 'COMMIT', action: 'COMMIT',
fibers, fibers,
stage stage,
} },
] ],
})); }));
}, },
}; };
@ -110,38 +115,40 @@ class App extends Component {
toContain() {}, toContain() {},
toEqual() {}, toEqual() {},
}); });
window.log = s => currentStage = s; window.log = s => (currentStage = s);
// eslint-disable-next-line // eslint-disable-next-line
eval(window.Babel.transform(code, { eval(
presets: ['react', 'es2015'] window.Babel.transform(code, {
}).code); presets: ['react', 'es2015'],
}).code,
);
} }
handleEdit = (e) => { handleEdit = e => {
e.preventDefault(); e.preventDefault();
this.setState({ this.setState({
isEditing: true isEditing: true,
}); });
} };
handleCloseEdit = (nextCode) => { handleCloseEdit = nextCode => {
localStorage.setItem('fiber-debugger-code', nextCode); localStorage.setItem('fiber-debugger-code', nextCode);
this.setState({ this.setState({
isEditing: false, isEditing: false,
history: [], history: [],
currentStep: 0, currentStep: 0,
code: nextCode code: nextCode,
}); });
this.runCode(nextCode); this.runCode(nextCode);
} };
render() { render() {
const { history, currentStep, isEditing, code } = this.state; const {history, currentStep, isEditing, code} = this.state;
if (isEditing) { if (isEditing) {
return <Editor code={code} onClose={this.handleCloseEdit} />; return <Editor code={code} onClose={this.handleCloseEdit} />;
} }
const { fibers, action, stage } = history[currentStep] || {}; const {fibers, action, stage} = history[currentStep] || {};
let friendlyAction; let friendlyAction;
if (fibers) { if (fibers) {
let wipFiber = fibers.descriptions[fibers.workInProgressID]; let wipFiber = fibers.descriptions[fibers.workInProgressID];
@ -150,45 +157,59 @@ class App extends Component {
} }
return ( return (
<div style={{ height: '100%' }}> <div style={{height: '100%'}}>
{fibers && {fibers &&
<Draggable> <Draggable>
<Fibers fibers={fibers} show={this.state.show} /> <Fibers fibers={fibers} show={this.state.show} />
</Draggable> </Draggable>}
} <div
<div style={{ style={{
width: '100%', width: '100%',
textAlign: 'center', textAlign: 'center',
position: 'fixed', position: 'fixed',
bottom: 0, bottom: 0,
padding: 10, padding: 10,
zIndex: 1, zIndex: 1,
backgroundColor: '#fafafa', backgroundColor: '#fafafa',
border: '1px solid #ccc' border: '1px solid #ccc',
}}> }}>
<input <input
type="range" type="range"
style={{ width: '25%' }} style={{width: '25%'}}
min={0} min={0}
max={history.length - 1} max={history.length - 1}
value={currentStep} value={currentStep}
onChange={e => this.setState({ currentStep: Number(e.target.value) })} onChange={e => this.setState({currentStep: Number(e.target.value)})}
/> />
<p>Step {currentStep}: {friendlyAction} (<a style={{ color: 'gray' }} onClick={this.handleEdit} href='#'>Edit</a>)</p> <p>
Step
{' '}
{currentStep}
:
{' '}
{friendlyAction}
{' '}
(
<a style={{color: 'gray'}} onClick={this.handleEdit} href="#">
Edit
</a>
)
</p>
{stage && <p>Stage: {stage}</p>} {stage && <p>Stage: {stage}</p>}
{Object.keys(this.state.show).map(key => {Object.keys(this.state.show).map(key => (
<label style={{ marginRight: '10px' }} key={key}> <label style={{marginRight: '10px'}} key={key}>
<input <input
type="checkbox" type="checkbox"
checked={this.state.show[key]} checked={this.state.show[key]}
onChange={e => { onChange={e => {
this.setState(({ show }) => ({ this.setState(({show}) => ({
show: {...show, [key]: !show[key]} show: {...show, [key]: !show[key]},
})); }));
}} /> }}
/>
{key} {key}
</label> </label>
)} ))}
</div> </div>
</div> </div>
); );

View File

@ -1,34 +1,38 @@
import React, { Component } from 'react'; import React, {Component} from 'react';
class Editor extends Component { class Editor extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
code: props.code code: props.code,
}; };
} }
render() { render() {
return ( return (
<div style={{ <div
height: '100%', style={{
width: '100%' height: '100%',
}}> width: '100%',
}}>
<textarea <textarea
value={this.state.code} value={this.state.code}
onChange={e => this.setState({ code: e.target.value })} onChange={e => this.setState({code: e.target.value})}
style={{ style={{
height: '80%', height: '80%',
width: '100%', width: '100%',
fontSize: '15px' fontSize: '15px',
}} /> }}
<div style={{ height: '20%', textAlign: 'center' }}> />
<button onClick={() => this.props.onClose(this.state.code)} style={{ fontSize: 'large' }}> <div style={{height: '20%', textAlign: 'center'}}>
<button
onClick={() => this.props.onClose(this.state.code)}
style={{fontSize: 'large'}}>
Run Run
</button> </button>
</div> </div>
</div> </div>
) );
} }
} }

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Motion, spring } from 'react-motion'; import {Motion, spring} from 'react-motion';
import dagre from 'dagre'; import dagre from 'dagre';
// import prettyFormat from 'pretty-format'; // import prettyFormat from 'pretty-format';
// import reactElement from 'pretty-format/plugins/ReactElement'; // import reactElement from 'pretty-format/plugins/ReactElement';
@ -35,7 +35,7 @@ function Graph(props) {
g.setNode(child.key, { g.setNode(child.key, {
label: child, label: child,
width: child.props.width, width: child.props.width,
height: child.props.height height: child.props.height,
}); });
} else if (child.type.isEdge) { } else if (child.type.isEdge) {
const relationshipKey = child.props.source + ':' + child.props.target; const relationshipKey = child.props.source + ':' + child.props.target;
@ -52,34 +52,36 @@ function Graph(props) {
g.setEdge(child.props.source, child.props.target, { g.setEdge(child.props.source, child.props.target, {
label: child, label: child,
allChildren: children.map(c => c.props.children), allChildren: children.map(c => c.props.children),
weight: child.props.weight weight: child.props.weight,
}); });
}); });
dagre.layout(g); dagre.layout(g);
var activeNode = g.nodes().map(v => g.node(v)).find(node => var activeNode = g
node.label.props.isActive .nodes()
); .map(v => g.node(v))
const [winX, winY] = [window.innerWidth / 2, window.innerHeight / 2] .find(node => node.label.props.isActive);
var focusDx = activeNode ? (winX - activeNode.x) : 0; const [winX, winY] = [window.innerWidth / 2, window.innerHeight / 2];
var focusDy = activeNode ? (winY - activeNode.y) : 0; var focusDx = activeNode ? winX - activeNode.x : 0;
var focusDy = activeNode ? winY - activeNode.y : 0;
var nodes = g.nodes().map(v => { var nodes = g.nodes().map(v => {
var node = g.node(v); var node = g.node(v);
return ( return (
<Motion style={{ <Motion
x: props.isDragging ? node.x + focusDx : spring(node.x + focusDx), style={{
y: props.isDragging ? node.y + focusDy : spring(node.y + focusDy) x: props.isDragging ? node.x + focusDx : spring(node.x + focusDx),
}} key={node.label.key}> y: props.isDragging ? node.y + focusDy : spring(node.y + focusDy),
}}
key={node.label.key}>
{interpolatingStyle => {interpolatingStyle =>
React.cloneElement(node.label, { React.cloneElement(node.label, {
x: interpolatingStyle.x + props.dx, x: interpolatingStyle.x + props.dx,
y: interpolatingStyle.y + props.dy, y: interpolatingStyle.y + props.dy,
vanillaX: node.x, vanillaX: node.x,
vanillaY: node.y, vanillaY: node.y,
}) })}
}
</Motion> </Motion>
); );
}); });
@ -88,25 +90,31 @@ function Graph(props) {
var edge = g.edge(e); var edge = g.edge(e);
let idx = 0; let idx = 0;
return ( return (
<Motion style={edge.points.reduce((bag, point) => { <Motion
bag[idx + ':x'] = props.isDragging ? point.x + focusDx : spring(point.x + focusDx); style={edge.points.reduce((bag, point) => {
bag[idx + ':y'] = props.isDragging ? point.y + focusDy : spring(point.y + focusDy); bag[idx + ':x'] = props.isDragging
idx++; ? point.x + focusDx
return bag; : spring(point.x + focusDx);
}, {})} key={edge.label.key}> bag[idx + ':y'] = props.isDragging
? point.y + focusDy
: spring(point.y + focusDy);
idx++;
return bag;
}, {})}
key={edge.label.key}>
{interpolatedStyle => { {interpolatedStyle => {
let points = []; let points = [];
Object.keys(interpolatedStyle).forEach(key => { Object.keys(interpolatedStyle).forEach(key => {
const [idx, prop] = key.split(':'); const [idx, prop] = key.split(':');
if (!points[idx]) { if (!points[idx]) {
points[idx] = { x: props.dx, y: props.dy }; points[idx] = {x: props.dx, y: props.dy};
} }
points[idx][prop] += interpolatedStyle[key]; points[idx][prop] += interpolatedStyle[key];
}); });
return React.cloneElement(edge.label, { return React.cloneElement(edge.label, {
points, points,
id: edge.label.key, id: edge.label.key,
children: edge.allChildren.join(', ') children: edge.allChildren.join(', '),
}); });
}} }}
</Motion> </Motion>
@ -114,10 +122,11 @@ function Graph(props) {
}); });
return ( return (
<div style={{ <div
position: 'relative', style={{
height: '100%' position: 'relative',
}}> height: '100%',
}}>
{edges} {edges}
{nodes} {nodes}
</div> </div>
@ -130,17 +139,18 @@ function Vertex(props) {
} }
return ( return (
<div style={{ <div
position: 'absolute', style={{
border: '1px solid black', position: 'absolute',
left: (props.x-(props.width/2)), border: '1px solid black',
top: (props.y-(props.height/2)), left: props.x - props.width / 2,
width: props.width, top: props.y - props.height / 2,
height: props.height, width: props.width,
overflow: 'hidden', height: props.height,
padding: '4px', overflow: 'hidden',
wordWrap: 'break-word' padding: '4px',
}}> wordWrap: 'break-word',
}}>
{props.children} {props.children}
</div> </div>
); );
@ -154,49 +164,67 @@ const strokes = {
return: 'red', return: 'red',
fx: 'purple', fx: 'purple',
progressedChild: 'cyan', progressedChild: 'cyan',
progressedDel: 'brown' progressedDel: 'brown',
}; };
function Edge(props) { function Edge(props) {
var points = props.points; var points = props.points;
var path = "M" + points[0].x + " " + points[0].y + " "; var path = 'M' + points[0].x + ' ' + points[0].y + ' ';
if (!points[0].x || !points[0].y) { if (!points[0].x || !points[0].y) {
return null; return null;
} }
for (var i = 1; i < points.length; i++) { for (var i = 1; i < points.length; i++) {
path += "L" + points[i].x + " " + points[i].y + " "; path += 'L' + points[i].x + ' ' + points[i].y + ' ';
if (!points[i].x || !points[i].y) { if (!points[i].x || !points[i].y) {
return null; return null;
} }
} }
var lineID = props.id; var lineID = props.id;
return ( return (
<svg width="100%" height="100%" style={{ <svg
position: 'absolute', width="100%"
left: 0, height="100%"
right: 0, style={{
top: 0, position: 'absolute',
bottom: 0, left: 0,
}}> right: 0,
top: 0,
bottom: 0,
}}>
<defs> <defs>
<path d={path} id={lineID} /> <path d={path} id={lineID} />
<marker id="markerCircle" markerWidth="8" markerHeight="8" refX="5" refY="5"> <marker
<circle cx="5" cy="5" r="3" style={{stroke: 'none', fill:'black'}}/> id="markerCircle"
markerWidth="8"
markerHeight="8"
refX="5"
refY="5">
<circle cx="5" cy="5" r="3" style={{stroke: 'none', fill: 'black'}} />
</marker> </marker>
<marker id="markerArrow" markerWidth="13" markerHeight="13" refX="2" refY="6" <marker
orient="auto"> id="markerArrow"
markerWidth="13"
markerHeight="13"
refX="2"
refY="6"
orient="auto">
<path d="M2,2 L2,11 L10,6 L2,2" style={{fill: 'black'}} /> <path d="M2,2 L2,11 L10,6 L2,2" style={{fill: 'black'}} />
</marker> </marker>
</defs> </defs>
<use xlinkHref={`#${lineID}`} fill="none" stroke={strokes[props.kind]} style={{ <use
markerStart: 'url(#markerCircle)', xlinkHref={`#${lineID}`}
markerEnd: 'url(#markerArrow)' fill="none"
}} /> stroke={strokes[props.kind]}
style={{
markerStart: 'url(#markerCircle)',
markerEnd: 'url(#markerArrow)',
}}
/>
<text> <text>
<textPath xlinkHref={`#${lineID}`}> <textPath xlinkHref={`#${lineID}`}>
{'     '}{props.children} {'     '}{props.children}
@ -226,32 +254,31 @@ function formatPriority(priority) {
} }
} }
export default function Fibers({ fibers, show, ...rest }) { export default function Fibers({fibers, show, ...rest}) {
const items = Object.keys(fibers.descriptions).map(id => const items = Object.keys(fibers.descriptions).map(
fibers.descriptions[id] id => fibers.descriptions[id],
); );
const isDragging = rest.className.indexOf('dragging') > -1; const isDragging = rest.className.indexOf('dragging') > -1;
const [_, sdx, sdy] = rest.style.transform.match(/translate\((-?\d+)px,(-?\d+)px\)/) || []; const [_, sdx, sdy] = rest.style.transform.match(
/translate\((-?\d+)px,(-?\d+)px\)/,
) || [];
const dx = Number(sdx); const dx = Number(sdx);
const dy = Number(sdy); const dy = Number(sdy);
return ( return (
<div {...rest} style={{ <div
width: '100%', {...rest}
height: '100%', style={{
position: 'absolute', width: '100%',
top: 0, height: '100%',
left: 0, position: 'absolute',
...rest.style, top: 0,
transform: null left: 0,
}}> ...rest.style,
<Graph transform: null,
className="graph" }}>
dx={dx} <Graph className="graph" dx={dx} dy={dy} isDragging={isDragging}>
dy={dy}
isDragging={isDragging}
>
{items.map(fiber => [ {items.map(fiber => [
<Vertex <Vertex
key={fiber.id} key={fiber.id}
@ -262,7 +289,7 @@ export default function Fibers({ fibers, show, ...rest }) {
style={{ style={{
width: '100%', width: '100%',
height: '100%', height: '100%',
backgroundColor: getFiberColor(fibers, fiber.id) backgroundColor: getFiberColor(fibers, fiber.id),
}} }}
title={ title={
/*prettyFormat(fiber, { plugins: [reactElement ]})*/ /*prettyFormat(fiber, { plugins: [reactElement ]})*/
@ -272,36 +299,40 @@ export default function Fibers({ fibers, show, ...rest }) {
<br /> <br />
{fiber.type} {fiber.type}
<br /> <br />
{fibers.currentIDs.indexOf(fiber.id) === -1 ? {fibers.currentIDs.indexOf(fiber.id) === -1
<small> ? <small>
{fiber.pendingWorkPriority !== 0 && [ {fiber.pendingWorkPriority !== 0 && [
<span style={{ <span
fontWeight: fiber.pendingWorkPriority <= fiber.progressedPriority ? style={{
'bold' : fontWeight: fiber.pendingWorkPriority <=
'normal' fiber.progressedPriority
}} key="span"> ? 'bold'
Needs: {formatPriority(fiber.pendingWorkPriority)} : 'normal',
</span>, }}
<br key="br" /> key="span">
]} Needs: {formatPriority(fiber.pendingWorkPriority)}
{fiber.progressedPriority !== 0 && [ </span>,
`Finished: ${formatPriority(fiber.progressedPriority)}`, <br key="br" />,
<br key="br" /> ]}
]} {fiber.progressedPriority !== 0 && [
{fiber.memoizedProps !== null && fiber.pendingProps !== null && [ `Finished: ${formatPriority(fiber.progressedPriority)}`,
fiber.memoizedProps === fiber.pendingProps ? <br key="br" />,
'Can reuse memoized.' : ]}
'Cannot reuse memoized.', {fiber.memoizedProps !== null &&
<br /> fiber.pendingProps !== null && [
]} fiber.memoizedProps === fiber.pendingProps
</small> : ? 'Can reuse memoized.'
<small> : 'Cannot reuse memoized.',
Committed <br />,
</small> ]}
} </small>
: <small>
Committed
</small>}
</div> </div>
</Vertex>, </Vertex>,
fiber.child && show.child && fiber.child &&
show.child &&
<Edge <Edge
source={fiber.id} source={fiber.id}
target={fiber.child} target={fiber.child}
@ -310,7 +341,8 @@ export default function Fibers({ fibers, show, ...rest }) {
key={`${fiber.id}-${fiber.child}-child`}> key={`${fiber.id}-${fiber.child}-child`}>
child child
</Edge>, </Edge>,
fiber.progressedChild && show.progressedChild && fiber.progressedChild &&
show.progressedChild &&
<Edge <Edge
source={fiber.id} source={fiber.id}
target={fiber.progressedChild} target={fiber.progressedChild}
@ -319,7 +351,8 @@ export default function Fibers({ fibers, show, ...rest }) {
key={`${fiber.id}-${fiber.progressedChild}-pChild`}> key={`${fiber.id}-${fiber.progressedChild}-pChild`}>
pChild pChild
</Edge>, </Edge>,
fiber.sibling && show.sibling && fiber.sibling &&
show.sibling &&
<Edge <Edge
source={fiber.id} source={fiber.id}
target={fiber.sibling} target={fiber.sibling}
@ -328,7 +361,8 @@ export default function Fibers({ fibers, show, ...rest }) {
key={`${fiber.id}-${fiber.sibling}-sibling`}> key={`${fiber.id}-${fiber.sibling}-sibling`}>
sibling sibling
</Edge>, </Edge>,
fiber.return && show.return && fiber.return &&
show.return &&
<Edge <Edge
source={fiber.id} source={fiber.id}
target={fiber.return} target={fiber.return}
@ -337,7 +371,8 @@ export default function Fibers({ fibers, show, ...rest }) {
key={`${fiber.id}-${fiber.return}-return`}> key={`${fiber.id}-${fiber.return}-return`}>
return return
</Edge>, </Edge>,
fiber.nextEffect && show.fx && fiber.nextEffect &&
show.fx &&
<Edge <Edge
source={fiber.id} source={fiber.id}
target={fiber.nextEffect} target={fiber.nextEffect}
@ -346,7 +381,8 @@ export default function Fibers({ fibers, show, ...rest }) {
key={`${fiber.id}-${fiber.nextEffect}-nextEffect`}> key={`${fiber.id}-${fiber.nextEffect}-nextEffect`}>
nextFx nextFx
</Edge>, </Edge>,
fiber.firstEffect && show.fx && fiber.firstEffect &&
show.fx &&
<Edge <Edge
source={fiber.id} source={fiber.id}
target={fiber.firstEffect} target={fiber.firstEffect}
@ -355,7 +391,8 @@ export default function Fibers({ fibers, show, ...rest }) {
key={`${fiber.id}-${fiber.firstEffect}-firstEffect`}> key={`${fiber.id}-${fiber.firstEffect}-firstEffect`}>
firstFx firstFx
</Edge>, </Edge>,
fiber.lastEffect && show.fx && fiber.lastEffect &&
show.fx &&
<Edge <Edge
source={fiber.id} source={fiber.id}
target={fiber.lastEffect} target={fiber.lastEffect}
@ -364,7 +401,8 @@ export default function Fibers({ fibers, show, ...rest }) {
key={`${fiber.id}-${fiber.lastEffect}-lastEffect`}> key={`${fiber.id}-${fiber.lastEffect}-lastEffect`}>
lastFx lastFx
</Edge>, </Edge>,
fiber.progressedFirstDeletion && show.progressedDel && fiber.progressedFirstDeletion &&
show.progressedDel &&
<Edge <Edge
source={fiber.id} source={fiber.id}
target={fiber.progressedFirstDeletion} target={fiber.progressedFirstDeletion}
@ -373,7 +411,8 @@ export default function Fibers({ fibers, show, ...rest }) {
key={`${fiber.id}-${fiber.progressedFirstDeletion}-pFD`}> key={`${fiber.id}-${fiber.progressedFirstDeletion}-pFD`}>
pFDel pFDel
</Edge>, </Edge>,
fiber.progressedLastDeletion && show.progressedDel && fiber.progressedLastDeletion &&
show.progressedDel &&
<Edge <Edge
source={fiber.id} source={fiber.id}
target={fiber.progressedLastDeletion} target={fiber.progressedLastDeletion}
@ -382,7 +421,8 @@ export default function Fibers({ fibers, show, ...rest }) {
key={`${fiber.id}-${fiber.progressedLastDeletion}-pLD`}> key={`${fiber.id}-${fiber.progressedLastDeletion}-pLD`}>
pLDel pLDel
</Edge>, </Edge>,
fiber.alternate && show.alt && fiber.alternate &&
show.alt &&
<Edge <Edge
source={fiber.id} source={fiber.id}
target={fiber.alternate} target={fiber.alternate}

View File

@ -55,7 +55,7 @@ export default function describeFibers(rootFiber, workInProgress) {
...fiber, ...fiber,
id: id, id: id,
tag: getFriendlyTag(fiber.tag), tag: getFriendlyTag(fiber.tag),
type: (fiber.type && ('<' + (fiber.type.name || fiber.type) + '>')), type: fiber.type && '<' + (fiber.type.name || fiber.type) + '>',
stateNode: `[${typeof fiber.stateNode}]`, stateNode: `[${typeof fiber.stateNode}]`,
return: acknowledgeFiber(fiber.return), return: acknowledgeFiber(fiber.return),
child: acknowledgeFiber(fiber.child), child: acknowledgeFiber(fiber.child),
@ -91,6 +91,6 @@ export default function describeFibers(rootFiber, workInProgress) {
descriptions, descriptions,
rootID, rootID,
currentIDs: Array.from(currentIDs), currentIDs: Array.from(currentIDs),
workInProgressID workInProgressID,
}; };
} }

View File

@ -3,7 +3,4 @@ import ReactDOM from 'react-dom';
import App from './App'; import App from './App';
import './index.css'; import './index.css';
ReactDOM.render( ReactDOM.render(<App />, document.getElementById('root'));
<App />,
document.getElementById('root')
);

View File

@ -3,5 +3,5 @@ var ReactDOM = require('react-dom');
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -3,5 +3,5 @@ var ReactDOM = require('react-dom');
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -3,5 +3,5 @@ var ReactDOM = require('react-dom');
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -3,5 +3,5 @@ var ReactDOM = require('react-dom');
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -3,5 +3,5 @@ var ReactDOM = require('react-dom');
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -3,5 +3,5 @@ var ReactDOM = require('react-dom');
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -2,7 +2,7 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const child_process = require('child_process'); const child_process = require('child_process');
const fixtureDirs = fs.readdirSync(__dirname).filter((file) => { const fixtureDirs = fs.readdirSync(__dirname).filter(file => {
return fs.statSync(path.join(__dirname, file)).isDirectory(); return fs.statSync(path.join(__dirname, file)).isDirectory();
}); });

View File

@ -1,6 +1,6 @@
require(['react', 'react-dom'], function(React, ReactDOM) { require(['react', 'react-dom'], function(React, ReactDOM) {
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );
}); });

View File

@ -1,6 +1,6 @@
require(['react', 'react-dom'], function(React, ReactDOM) { require(['react', 'react-dom'], function(React, ReactDOM) {
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );
}); });

View File

@ -3,5 +3,5 @@ import ReactDOM from 'react-dom';
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -3,5 +3,5 @@ import ReactDOM from 'react-dom';
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -8,7 +8,7 @@ module.exports = {
resolve: { resolve: {
root: path.resolve('../../../../build/packages'), root: path.resolve('../../../../build/packages'),
alias: { alias: {
'react': 'react/umd/react.development', react: 'react/umd/react.development',
'react-dom': 'react-dom/umd/react-dom.development', 'react-dom': 'react-dom/umd/react-dom.development',
}, },
}, },

View File

@ -3,5 +3,5 @@ var ReactDOM = require('react-dom');
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -8,7 +8,7 @@ module.exports = {
resolve: { resolve: {
root: path.resolve('../../../../build/packages'), root: path.resolve('../../../../build/packages'),
alias: { alias: {
'react': 'react/umd/react.production.min', react: 'react/umd/react.production.min',
'react-dom': 'react-dom/umd/react-dom.production.min', 'react-dom': 'react-dom/umd/react-dom.production.min',
}, },
}, },

View File

@ -3,5 +3,5 @@ var ReactDOM = require('react-dom');
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -3,5 +3,5 @@ var ReactDOM = require('react-dom');
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -9,11 +9,11 @@ module.exports = {
resolve: { resolve: {
root: path.resolve('../../../../build/packages/'), root: path.resolve('../../../../build/packages/'),
}, },
plugins: [ plugins: [
new webpack.DefinePlugin({ new webpack.DefinePlugin({
'process.env':{ 'process.env': {
'NODE_ENV': JSON.stringify('production') NODE_ENV: JSON.stringify('production'),
} },
}) }),
] ],
}; };

View File

@ -3,5 +3,5 @@ var ReactDOM = require('react-dom');
ReactDOM.render( ReactDOM.render(
React.createElement('h1', null, 'Hello World!'), React.createElement('h1', null, 'Hello World!'),
document.getElementById('container') document.getElementById('container'),
); );

View File

@ -35,10 +35,13 @@ app.use(express.static(path.resolve(__dirname, '..', 'build')));
// Proxy everything else to create-react-app's webpack development server // Proxy everything else to create-react-app's webpack development server
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
app.use('/', proxy({ app.use(
ws: true, '/',
target: 'http://localhost:3001' proxy({
})); ws: true,
target: 'http://localhost:3001',
}),
);
} }
app.listen(3000, () => { app.listen(3000, () => {
@ -50,9 +53,7 @@ app.on('error', function(error) {
throw error; throw error;
} }
var bind = typeof port === 'string' var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
? 'Pipe ' + port
: 'Port ' + port;
switch (error.code) { switch (error.code) {
case 'EACCES': case 'EACCES':

View File

@ -19,4 +19,4 @@ export default function render() {
// There's no way to render a doctype in React so prepend manually. // There's no way to render a doctype in React so prepend manually.
// Also append a bootstrap script tag. // Also append a bootstrap script tag.
return '<!DOCTYPE html>' + html; return '<!DOCTYPE html>' + html;
}; }

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react'; import React, {Component} from 'react';
import Chrome from './Chrome'; import Chrome from './Chrome';
import Page from './Page'; import Page from './Page';

View File

@ -1,4 +1,4 @@
import React, { Component } from 'react'; import React, {Component} from 'react';
import './Chrome.css'; import './Chrome.css';
@ -16,9 +16,11 @@ export default class Chrome extends Component {
</head> </head>
<body> <body>
{this.props.children} {this.props.children}
<script dangerouslySetInnerHTML={{ <script
__html: `assetManifest = ${JSON.stringify(assets)};` dangerouslySetInnerHTML={{
}} /> __html: `assetManifest = ${JSON.stringify(assets)};`,
}}
/>
<script src={assets['main.js']} /> <script src={assets['main.js']} />
</body> </body>
</html> </html>

View File

@ -1,12 +1,12 @@
import React, { Component } from 'react'; import React, {Component} from 'react';
import './Page.css'; import './Page.css';
export default class Page extends Component { export default class Page extends Component {
state = { active: false }; state = {active: false};
handleClick = (e) => { handleClick = e => {
this.setState({ active: true }); this.setState({active: true});
} };
render() { render() {
const link = ( const link = (
<a className="bold" onClick={this.handleClick}> <a className="bold" onClick={this.handleClick}>
@ -16,7 +16,7 @@ export default class Page extends Component {
return ( return (
<div> <div>
<p> <p>
{!this.state.active ? link : "Thanks!"} {!this.state.active ? link : 'Thanks!'}
</p> </p>
</div> </div>
); );

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { render } from 'react-dom'; import {render} from 'react-dom';
import App from './components/App'; import App from './components/App';

View File

@ -34,7 +34,7 @@ const defaultOptions = {
}; };
const config = { const config = {
default: { default: {
patterns: ['src/**/*.js'], patterns: ['src/**/*.js', 'fixtures/**/*.js'],
ignore: ['**/third_party/**', '**/node_modules/**'], ignore: ['**/third_party/**', '**/node_modules/**'],
}, },
scripts: { scripts: {