mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Remove examples/ folder (#9323)
This commit is contained in:
committed by
Andrew Clark
parent
b596e0bcaa
commit
b3ec0cb488
@@ -9,7 +9,11 @@ docs/_site/
|
||||
docs/vendor/bundle/
|
||||
# This should be more like examples/**/thirdparty/** but
|
||||
# we should fix https://github.com/facebook/esprima/pull/85 first
|
||||
<<<<<<< HEAD
|
||||
examples/
|
||||
=======
|
||||
fixtures/
|
||||
>>>>>>> 4a37718... Remove examples/ folder (#9323)
|
||||
# Ignore built files.
|
||||
build/
|
||||
coverage/
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
[ignore]
|
||||
|
||||
<<<<<<< HEAD
|
||||
<PROJECT_ROOT>/examples/.*
|
||||
=======
|
||||
<PROJECT_ROOT>/fixtures/.*
|
||||
>>>>>>> 4a37718... Remove examples/ folder (#9323)
|
||||
<PROJECT_ROOT>/build/.*
|
||||
<PROJECT_ROOT>/.*/node_modules/y18n/.*
|
||||
<PROJECT_ROOT>/.*/__mocks__/.*
|
||||
|
||||
@@ -17,8 +17,13 @@ docs/.sass-cache
|
||||
docs/js/*
|
||||
docs/downloads/*.zip
|
||||
docs/vendor/bundle
|
||||
<<<<<<< HEAD
|
||||
examples/shared/*.js
|
||||
examples/**/bundle.js
|
||||
=======
|
||||
fixtures/dom/public/react-dom.js
|
||||
fixtures/dom/public/react.js
|
||||
>>>>>>> 4a37718... Remove examples/ folder (#9323)
|
||||
test/the-files-to-test.generated.js
|
||||
*.log*
|
||||
chrome-user-data
|
||||
|
||||
@@ -56,5 +56,3 @@ const proto = Object.create(HTMLElement.prototype, {
|
||||
});
|
||||
document.registerElement('x-search', {prototype: proto});
|
||||
```
|
||||
|
||||
You can also check out this [complete Web Components example on GitHub](https://github.com/facebook/react/tree/master/examples/webcomponents).
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# React Examples
|
||||
|
||||
Here are some small React demos. Some use [JSX](https://facebook.github.io/react/docs/jsx-in-depth.html) and some include third-party library integration.
|
||||
|
||||
For more fully-featured examples, check out [React TodoMVC](http://todomvc.com/examples/react/) and [React + Backbone TodoMVC](http://todomvc.com/examples/react-backbone/).
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"presets": ["react", "es2015"]
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
# Basic example of using React with Browserify
|
||||
|
||||
Run `npm install` in the directory to install React from npm. Then run:
|
||||
|
||||
```sh
|
||||
npm start
|
||||
```
|
||||
|
||||
to produce `bundle.js` with example code and React.
|
||||
@@ -1,37 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Basic CommonJS Example with Browserify</title>
|
||||
<link rel="stylesheet" href="../shared/css/base.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Basic CommonJS Example with Browserify</h1>
|
||||
<div id="container">
|
||||
<p>
|
||||
To install React, follow the instructions on
|
||||
<a href="https://github.com/facebook/react/">GitHub</a>.
|
||||
</p>
|
||||
<p>
|
||||
If you can see this, React is <strong>not</strong> working right.
|
||||
If you checked out the source from GitHub make sure to run <code>grunt</code>.
|
||||
</p>
|
||||
</div>
|
||||
<h4>Example Details</h4>
|
||||
<p>This is written with JSX in a CommonJS module and precompiled to vanilla JS by navigating to the example
|
||||
directory
|
||||
<pre>cd /path/to/react/examples/example-name</pre>
|
||||
and running
|
||||
<pre>npm start</pre>
|
||||
<br>
|
||||
(don't forget to install first)
|
||||
<pre>npm install</pre>
|
||||
<br>
|
||||
</p>
|
||||
<p>
|
||||
Learn more about React at
|
||||
<a href="https://facebook.github.io/react" target="_blank">facebook.github.io/react</a>.
|
||||
</p>
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
|
||||
var ExampleApplication = React.createClass({
|
||||
render: function() {
|
||||
var elapsed = Math.round(this.props.elapsed / 100);
|
||||
var seconds = elapsed / 10 + (elapsed % 10 ? '' : '.0' );
|
||||
var message =
|
||||
'React has been successfully running for ' + seconds + ' seconds.';
|
||||
|
||||
return <p>{message}</p>;
|
||||
}
|
||||
});
|
||||
|
||||
var start = new Date().getTime();
|
||||
|
||||
setInterval(function() {
|
||||
ReactDOM.render(
|
||||
<ExampleApplication elapsed={new Date().getTime() - start} />,
|
||||
document.getElementById('container')
|
||||
);
|
||||
}, 50);
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"name": "react-basic-commonjs-example",
|
||||
"description": "Basic example of using React with CommonJS",
|
||||
"private": true,
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"babel-preset-es2015": "^6.6.0",
|
||||
"babel-preset-react": "^6.5.0",
|
||||
"babelify": "^7.3.0",
|
||||
"browserify": "^13.0.0",
|
||||
"react": "^15.0.2",
|
||||
"react-dom": "^15.0.2",
|
||||
"watchify": "^3.7.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "browserify ./index.js -t babelify -o bundle.js",
|
||||
"start": "watchify ./index.js -v -t babelify -o bundle.js"
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
var ExampleApplication = React.createClass({
|
||||
render: function() {
|
||||
var elapsed = Math.round(this.props.elapsed / 100);
|
||||
var seconds = elapsed / 10 + (elapsed % 10 ? '' : '.0' );
|
||||
var message =
|
||||
'React has been successfully running for ' + seconds + ' seconds.';
|
||||
|
||||
return <p>{message}</p>;
|
||||
}
|
||||
});
|
||||
|
||||
var start = new Date().getTime();
|
||||
|
||||
setInterval(function() {
|
||||
ReactDOM.render(
|
||||
<ExampleApplication elapsed={new Date().getTime() - start} />,
|
||||
document.getElementById('container')
|
||||
);
|
||||
}, 50);
|
||||
@@ -1,19 +0,0 @@
|
||||
var ExampleApplication = React.createClass({
|
||||
render: function() {
|
||||
var elapsed = Math.round(this.props.elapsed / 100);
|
||||
var seconds = elapsed / 10 + (elapsed % 10 ? '' : '.0' );
|
||||
var message =
|
||||
'React has been successfully running for ' + seconds + ' seconds.';
|
||||
|
||||
return <p>{message}</p>;
|
||||
}
|
||||
});
|
||||
|
||||
var start = new Date().getTime();
|
||||
|
||||
setInterval(function() {
|
||||
ReactDOM.render(
|
||||
<ExampleApplication elapsed={new Date().getTime() - start} />,
|
||||
document.getElementById('container')
|
||||
);
|
||||
}, 50);
|
||||
@@ -1,40 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Basic Example with Precompiled JSX</title>
|
||||
<link rel="stylesheet" href="../shared/css/base.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Basic Example with Precompiled JSX</h1>
|
||||
<div id="container">
|
||||
<p>
|
||||
If you can see this, React is <strong>not</strong> running. Try running:
|
||||
</p>
|
||||
<pre>npm install -g babel-cli
|
||||
cd examples/basic-jsx-precompile/
|
||||
npm install babel-preset-react
|
||||
babel example.js --presets react --out-dir=build</pre>
|
||||
</div>
|
||||
<h4>Example Details</h4>
|
||||
<p>This is written with JSX in a separate file and precompiled to vanilla JS by running:</p>
|
||||
|
||||
<p><i>With Babel lower than 6.0</i></p>
|
||||
<pre>npm install -g babel
|
||||
cd examples/basic-jsx-precompile/
|
||||
babel example.js --out-dir=build</pre>
|
||||
|
||||
<p><i>With Babel 6.0 or higher</i></p>
|
||||
<pre>npm install -g babel-cli
|
||||
cd examples/basic-jsx-precompile/
|
||||
npm install babel-preset-react
|
||||
babel example.js --presets react --out-dir=build</pre>
|
||||
<p>
|
||||
Learn more about React at
|
||||
<a href="https://facebook.github.io/react" target="_blank">facebook.github.io/react</a>.
|
||||
</p>
|
||||
<script src="../../build/react.js"></script>
|
||||
<script src="../../build/react-dom.js"></script>
|
||||
<script src="build/example.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,52 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Basic Example</title>
|
||||
<link rel="stylesheet" href="../shared/css/base.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Basic Example</h1>
|
||||
<div id="container">
|
||||
<p>
|
||||
To install React, follow the instructions on
|
||||
<a href="https://github.com/facebook/react/">GitHub</a>.
|
||||
</p>
|
||||
<p>
|
||||
If you can see this, React is <strong>not</strong> working right.
|
||||
If you checked out the source from GitHub make sure to run <code>grunt</code>.
|
||||
</p>
|
||||
</div>
|
||||
<h4>Example Details</h4>
|
||||
<p>This is written in vanilla JavaScript (without JSX) and transformed in the browser.</p>
|
||||
<p>
|
||||
Learn more about React at
|
||||
<a href="https://facebook.github.io/react" target="_blank">facebook.github.io/react</a>.
|
||||
</p>
|
||||
<script src="../../build/react.js"></script>
|
||||
<script src="../../build/react-dom.js"></script>
|
||||
<script>
|
||||
var ExampleApplication = React.createClass({
|
||||
render: function() {
|
||||
var elapsed = Math.round(this.props.elapsed / 100);
|
||||
var seconds = elapsed / 10 + (elapsed % 10 ? '' : '.0' );
|
||||
var message =
|
||||
'React has been successfully running for ' + seconds + ' seconds.';
|
||||
|
||||
return React.DOM.p(null, message);
|
||||
}
|
||||
});
|
||||
|
||||
// Call React.createFactory instead of directly call ExampleApplication({...}) in React.render
|
||||
var ExampleApplicationFactory = React.createFactory(ExampleApplication);
|
||||
|
||||
var start = new Date().getTime();
|
||||
setInterval(function() {
|
||||
ReactDOM.render(
|
||||
ExampleApplicationFactory({elapsed: new Date().getTime() - start}),
|
||||
document.getElementById('container')
|
||||
);
|
||||
}, 50);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,3 +0,0 @@
|
||||
.example {
|
||||
margin: 20px;
|
||||
}
|
||||
Vendored
-139
@@ -1,139 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// Simple pure-React component so we don't have to remember
|
||||
// Bootstrap's classes
|
||||
var BootstrapButton = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<a {...this.props}
|
||||
href="javascript:;"
|
||||
role="button"
|
||||
className={(this.props.className || '') + ' btn'} />
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var BootstrapModal = React.createClass({
|
||||
// The following two methods are the only places we need to
|
||||
// integrate Bootstrap or jQuery with the components lifecycle methods.
|
||||
componentDidMount: function() {
|
||||
// When the component is added, turn it into a modal
|
||||
$(this.refs.root).modal({backdrop: 'static', keyboard: false, show: false});
|
||||
|
||||
// Bootstrap's modal class exposes a few events for hooking into modal
|
||||
// functionality. Lets hook into one of them:
|
||||
$(this.refs.root).on('hidden.bs.modal', this.handleHidden);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
$(this.refs.root).off('hidden.bs.modal', this.handleHidden);
|
||||
},
|
||||
close: function() {
|
||||
$(this.refs.root).modal('hide');
|
||||
},
|
||||
open: function() {
|
||||
$(this.refs.root).modal('show');
|
||||
},
|
||||
render: function() {
|
||||
var confirmButton = null;
|
||||
var cancelButton = null;
|
||||
|
||||
if (this.props.confirm) {
|
||||
confirmButton = (
|
||||
<BootstrapButton
|
||||
onClick={this.handleConfirm}
|
||||
className="btn-primary">
|
||||
{this.props.confirm}
|
||||
</BootstrapButton>
|
||||
);
|
||||
}
|
||||
if (this.props.cancel) {
|
||||
cancelButton = (
|
||||
<BootstrapButton onClick={this.handleCancel} className="btn-default">
|
||||
{this.props.cancel}
|
||||
</BootstrapButton>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="modal fade" ref="root">
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<button
|
||||
type="button"
|
||||
className="close"
|
||||
onClick={this.handleCancel}>
|
||||
×
|
||||
</button>
|
||||
<h3>{this.props.title}</h3>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
{this.props.children}
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
{cancelButton}
|
||||
{confirmButton}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
handleCancel: function() {
|
||||
if (this.props.onCancel) {
|
||||
this.props.onCancel();
|
||||
}
|
||||
},
|
||||
handleConfirm: function() {
|
||||
if (this.props.onConfirm) {
|
||||
this.props.onConfirm();
|
||||
}
|
||||
},
|
||||
handleHidden: function() {
|
||||
if (this.props.onHidden) {
|
||||
this.props.onHidden();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var Example = React.createClass({
|
||||
handleCancel: function() {
|
||||
if (confirm('Are you sure you want to cancel?')) {
|
||||
this.refs.modal.close();
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
var modal = null;
|
||||
modal = (
|
||||
<BootstrapModal
|
||||
ref="modal"
|
||||
confirm="OK"
|
||||
cancel="Cancel"
|
||||
onCancel={this.handleCancel}
|
||||
onConfirm={this.closeModal}
|
||||
onHidden={this.handleModalDidClose}
|
||||
title="Hello, Bootstrap!">
|
||||
This is a React component powered by jQuery and Bootstrap!
|
||||
</BootstrapModal>
|
||||
);
|
||||
return (
|
||||
<div className="example">
|
||||
{modal}
|
||||
<BootstrapButton onClick={this.openModal} className="btn-default">
|
||||
Open modal
|
||||
</BootstrapButton>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
openModal: function() {
|
||||
this.refs.modal.open();
|
||||
},
|
||||
closeModal: function() {
|
||||
this.refs.modal.close();
|
||||
},
|
||||
handleModalDidClose: function() {
|
||||
alert("The modal has been dismissed!");
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(<Example />, document.getElementById('jqueryexample'));
|
||||
@@ -1,6 +0,0 @@
|
||||
jQuery Mobile React Example
|
||||
===========================
|
||||
|
||||
This example demonstrates how jQuery Mobile applications can be built with React.
|
||||
|
||||
The source code is based on jQuery Mobile's [pages-multi-page example](https://github.com/jquery/jquery-mobile/tree/master/demos/pages-multi-page).
|
||||
@@ -1,19 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>jQuery Mobile React Example</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-mobile/1.4.5/jquery.mobile.min.css" />
|
||||
<link rel="stylesheet" href="https://demos.jquerymobile.com/1.4.5/_assets/css/jqm-demos.css" />
|
||||
</head>
|
||||
<body class="ui-mobile-viewport ui-overlay-a">
|
||||
<div id="content"></div>
|
||||
<script src="http://code.jquery.com/jquery-2.2.2.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mobile/1.4.5/jquery.mobile.min.js"></script>
|
||||
<script src="../../build/react.js"></script>
|
||||
<script src="../../build/react-dom.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Vendored
-191
@@ -1,191 +0,0 @@
|
||||
/**
|
||||
* jQuery Mobile React Example
|
||||
*
|
||||
* Main application script.
|
||||
* For variety, this example is written in 100% JSHint-compliant JavaScript, not in JSX.
|
||||
*
|
||||
* Component structure:
|
||||
*
|
||||
* - App
|
||||
* |-- JQueryMobilePage (one)
|
||||
* | |-- JQueryMobileHeader
|
||||
* | |-- JQueryMobileContent
|
||||
* | | |-- PageOneContent
|
||||
* | | |-- JQueryMobileButton
|
||||
* | |-- JQueryMobileFooter
|
||||
* |-- JQueryMobilePage (two)
|
||||
* | |-- JQueryMobileHeader
|
||||
* | |-- JQueryMobileContent
|
||||
* | | |-- PageTwoContent
|
||||
* | | |-- JQueryMobileButton
|
||||
* | |-- JQueryMobileFooter
|
||||
* |-- JQueryMobilePage (popup)
|
||||
* |-- JQueryMobileHeader
|
||||
* |-- JQueryMobileContent
|
||||
* | |-- PagePopUpContent
|
||||
* | |-- JQueryMobileButton
|
||||
* |-- JQueryMobileFooter
|
||||
*/
|
||||
|
||||
/* global document, React */
|
||||
|
||||
'use strict';
|
||||
|
||||
/** Main application component. */
|
||||
var App = React.createClass({
|
||||
displayName: 'App',
|
||||
|
||||
render: function() {
|
||||
return React.DOM.div({className:'app'},
|
||||
JQueryMobilePage({id:'one'}, PageOneContent(null)),
|
||||
JQueryMobilePage({id:'two'}, PageTwoContent(null)),
|
||||
JQueryMobilePage({id:'popup', headerTheme:'b'}, PagePopUpContent(null))
|
||||
);
|
||||
}
|
||||
});
|
||||
App = React.createFactory(App);
|
||||
|
||||
/** jQuery Mobile button component. */
|
||||
var JQueryMobileButton = React.createClass({
|
||||
displayName: 'JQueryMobileButton',
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {className:'ui-btn ui-shadow ui-corner-all'};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return React.DOM.p(null,
|
||||
React.DOM.a(this.props, this.props.children)
|
||||
);
|
||||
}
|
||||
});
|
||||
JQueryMobileButton = React.createFactory(JQueryMobileButton);
|
||||
|
||||
/** jQuery Mobile page content component. */
|
||||
var JQueryMobileContent = React.createClass({
|
||||
displayName: 'JQueryMobileContent',
|
||||
|
||||
render: function() {
|
||||
return React.DOM.div({role:'main', className:'ui-content'},
|
||||
this.props.children
|
||||
);
|
||||
}
|
||||
});
|
||||
JQueryMobileContent = React.createFactory(JQueryMobileContent);
|
||||
|
||||
/** jQuery Mobile footer component. */
|
||||
var JQueryMobileFooter = React.createClass({
|
||||
displayName: 'JQueryMobileFooter',
|
||||
|
||||
render: function() {
|
||||
return React.DOM.div({'data-role':'footer'},
|
||||
React.DOM.h4(null, 'Page footer')
|
||||
);
|
||||
}
|
||||
});
|
||||
JQueryMobileFooter = React.createFactory(JQueryMobileFooter);
|
||||
|
||||
/** jQuery Mobile header component. */
|
||||
var JQueryMobileHeader = React.createClass({
|
||||
displayName: 'JQueryMobileHeader',
|
||||
|
||||
render: function() {
|
||||
return React.DOM.div({'data-role':'header', 'data-theme':this.props.headerTheme},
|
||||
React.DOM.h1(null, this.props.title)
|
||||
);
|
||||
}
|
||||
});
|
||||
JQueryMobileHeader = React.createFactory(JQueryMobileHeader);
|
||||
|
||||
/** jQuery Mobile page component. */
|
||||
var JQueryMobilePage = React.createClass({
|
||||
displayName: 'JQueryMobilePage',
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {'data-role':'page', 'data-theme':'a', headerTheme:'a'};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var props = {};
|
||||
for (var key in this.props) {
|
||||
props[key] = this.props[key];
|
||||
}
|
||||
return React.DOM.div(props,
|
||||
JQueryMobileHeader({title:'Page ' + this.props.id, headerTheme:this.props.headerTheme}),
|
||||
JQueryMobileContent(null, this.props.children),
|
||||
JQueryMobileFooter(null)
|
||||
);
|
||||
}
|
||||
});
|
||||
JQueryMobilePage = React.createFactory(JQueryMobilePage);
|
||||
|
||||
/** Application page one component. */
|
||||
var PageOneContent = React.createClass({
|
||||
displayName: 'PageOneContent',
|
||||
|
||||
render: function() {
|
||||
return React.DOM.div(null,
|
||||
React.DOM.h2(null, 'One'),
|
||||
React.DOM.p(null,
|
||||
'I have an ',
|
||||
React.DOM.code(null, 'id'),
|
||||
' of "one" on my page container. I\'m first in the source order so I\'m shown when the page loads.'
|
||||
),
|
||||
React.DOM.p(null, 'This is a multi-page boilerplate template that you can copy to build your first jQuery Mobile page. This template contains multiple "page" containers inside, unlike a single page template that has just one page within it.'),
|
||||
React.DOM.p(null, 'Just view the source and copy the code to get started. All the CSS and JS is linked to the jQuery CDN versions so this is super easy to set up. Remember to include a meta viewport tag in the head to set the zoom level.'),
|
||||
React.DOM.p(null,
|
||||
'You link to internal pages by referring to the ',
|
||||
React.DOM.code(null, 'id'),
|
||||
' of the page you want to show. For example, to ',
|
||||
React.DOM.a({href:'#two'}, 'link'),
|
||||
' to the page with an ',
|
||||
React.DOM.code(null, 'id'),
|
||||
' of "two", my link would have a ',
|
||||
React.DOM.code(null, 'href="#two"'),
|
||||
' in the code.'
|
||||
),
|
||||
React.DOM.h3(null, 'Show internal pages:'),
|
||||
JQueryMobileButton({href:'#two'}, 'Show page "two"'),
|
||||
JQueryMobileButton({href:'#popup', 'data-rel':'dialog', 'data-transition':'pop'}, 'Show page "popup" (as a dialog)')
|
||||
);
|
||||
}
|
||||
});
|
||||
PageOneContent = React.createFactory(PageOneContent);
|
||||
|
||||
/** Application page two component. */
|
||||
var PageTwoContent = React.createClass({
|
||||
displayName: 'PageTwoContent',
|
||||
|
||||
render: function() {
|
||||
return React.DOM.div(null,
|
||||
React.DOM.h2(null, 'Two'),
|
||||
React.DOM.p(null, 'I have an id of "two" on my page container. I\'m the second page container in this multi-page template.'),
|
||||
React.DOM.p(null, 'Notice that the theme is different for this page because we\'ve added a few ',
|
||||
React.DOM.code(null, 'data-theme'),
|
||||
' swatch assigments here to show off how flexible it is. You can add any content or widget to these pages, but we\'re keeping these simple.'),
|
||||
JQueryMobileButton({href:'#one', 'data-direction':'reverse', className:'ui-btn ui-shadow ui-corner-all ui-btn-b'}, 'Back to page "one"')
|
||||
);
|
||||
}
|
||||
});
|
||||
PageTwoContent = React.createFactory(PageTwoContent);
|
||||
|
||||
/** Application popup page component. */
|
||||
var PagePopUpContent = React.createClass({
|
||||
displayName: 'PagePopUpContent',
|
||||
|
||||
render: function() {
|
||||
return React.DOM.div(null,
|
||||
React.DOM.h2(null, 'Popup'),
|
||||
React.DOM.p(null, 'I have an id of "popup" on my page container and only look like a dialog because the link to me had a ',
|
||||
React.DOM.code(null, 'data-rel="dialog"'),
|
||||
' attribute which gives me this inset look and a ',
|
||||
React.DOM.code(null, 'data-transition="pop"'),
|
||||
' attribute to change the transition to pop. Without this, I\'d be styled as a normal page.'),
|
||||
JQueryMobileButton({href:'#one', 'data-rel':'back', className:'ui-btn ui-shadow ui-corner-all ui-btn-inline ui-icon-back ui-btn-icon-left'}, 'Back to page "one"')
|
||||
);
|
||||
}
|
||||
});
|
||||
PagePopUpContent = React.createFactory(PagePopUpContent);
|
||||
|
||||
// Render application.
|
||||
ReactDOM.render(App(null), document.getElementById('content'));
|
||||
@@ -1,59 +0,0 @@
|
||||
var QuadraticCalculator = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
a: 1,
|
||||
b: 3,
|
||||
c: -4
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* This function will be re-bound in render multiple times. Each .bind() will
|
||||
* create a new function that calls this with the appropriate key as well as
|
||||
* the event. The key is the key in the state object that the value should be
|
||||
* mapped from.
|
||||
*/
|
||||
handleInputChange: function(key, event) {
|
||||
var partialState = {};
|
||||
partialState[key] = parseFloat(event.target.value);
|
||||
this.setState(partialState);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var a = this.state.a;
|
||||
var b = this.state.b;
|
||||
var c = this.state.c;
|
||||
var root = Math.sqrt(Math.pow(b, 2) - 4 * a * c);
|
||||
var denominator = 2 * a;
|
||||
var x1 = (-b + root) / denominator;
|
||||
var x2 = (-b - root) / denominator;
|
||||
return (
|
||||
<div>
|
||||
<strong>
|
||||
<em>ax</em><sup>2</sup> + <em>bx</em> + <em>c</em> = 0
|
||||
</strong>
|
||||
<h4>Solve for <em>x</em>:</h4>
|
||||
<p>
|
||||
<label>
|
||||
a: <input type="number" value={a} onChange={this.handleInputChange.bind(null, 'a')} />
|
||||
</label>
|
||||
<br />
|
||||
<label>
|
||||
b: <input type="number" value={b} onChange={this.handleInputChange.bind(null, 'b')} />
|
||||
</label>
|
||||
<br />
|
||||
<label>
|
||||
c: <input type="number" value={c} onChange={this.handleInputChange.bind(null, 'c')} />
|
||||
</label>
|
||||
<br />
|
||||
x: <strong>{x1}, {x2}</strong>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<QuadraticCalculator />,
|
||||
document.getElementById('container')
|
||||
);
|
||||
@@ -1,62 +0,0 @@
|
||||
body {
|
||||
background: #fff;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 15px;
|
||||
line-height: 1.7;
|
||||
margin: 0;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #4183c4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #f8f8f8;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
font-family: "Bitstream Vera Sans Mono", Consolas, Courier, monospace;
|
||||
font-size: 12px;
|
||||
margin: 0 2px;
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: bold;
|
||||
margin: 0 0 15px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
border-bottom: 1px solid #ddd;
|
||||
font-size: 2.5em;
|
||||
font-weight: bold;
|
||||
margin: 0 0 15px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
border-bottom: 1px solid #eee;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
p, ul {
|
||||
margin: 15px 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 30px;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
.example-enter,
|
||||
.example-leave {
|
||||
-webkit-transition: all .25s;
|
||||
transition: all .25s;
|
||||
}
|
||||
|
||||
.example-enter,
|
||||
.example-leave.example-leave-active {
|
||||
opacity: 0.01;
|
||||
}
|
||||
|
||||
.example-leave.example-leave-active {
|
||||
margin-left: -128px;
|
||||
}
|
||||
|
||||
.example-enter {
|
||||
margin-left: 128px;
|
||||
}
|
||||
|
||||
.example-enter.example-enter-active,
|
||||
.example-leave {
|
||||
margin-left: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.animateExample {
|
||||
display: block;
|
||||
height: 128px;
|
||||
position: relative;
|
||||
width: 384px;
|
||||
}
|
||||
|
||||
.animateItem {
|
||||
color: white;
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
height: 128px;
|
||||
line-height: 128px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
-webkit-transition: all .25s; /* TODO: make this a move animation */
|
||||
transition: all .25s; /* TODO: make this a move animation */
|
||||
width: 128px;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
NODE_PATH=../../build/packages
|
||||
@@ -0,0 +1,14 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
|
||||
# testing
|
||||
coverage
|
||||
|
||||
# production
|
||||
build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
npm-debug.log
|
||||
@@ -0,0 +1,25 @@
|
||||
# Fiber Debugger
|
||||
|
||||
This is a debugger handy for visualizing how [Fiber](https://github.com/facebook/react/issues/6170) works internally.
|
||||
|
||||
**It is only meant to be used by React contributors, and not by React users.**
|
||||
|
||||
It is likely that it might get broken at some point. If it's broken, ping [Dan](https://twitter.com/dan_abramov).
|
||||
|
||||
### Running
|
||||
|
||||
First, `npm run build` in React root repo folder.
|
||||
|
||||
Then `npm install` and `npm start` in this folder.
|
||||
|
||||
Open `http://localhost:3000` in Chrome.
|
||||
|
||||
### Features
|
||||
|
||||
* Edit code that uses `ReactNoop` renderer
|
||||
* Visualize how relationships between fibers change over time
|
||||
* Current tree is displayed in green
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "react-fiber-debugger",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"react-scripts": "0.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dagre": "^0.7.4",
|
||||
"pretty-format": "^4.2.1",
|
||||
"react-draggable": "^2.2.2",
|
||||
"react-motion": "^0.4.5"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.14.0/babel.min.js"></script>
|
||||
<title>React App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,196 @@
|
||||
import React, { Component } from 'react';
|
||||
import Draggable from 'react-draggable';
|
||||
import ReactNoop from 'react-noop-renderer';
|
||||
import ReactFiberInstrumentation from 'react-noop-renderer/lib/ReactFiberInstrumentation';
|
||||
import Editor from './Editor';
|
||||
import Fibers from './Fibers';
|
||||
import describeFibers from './describeFibers';
|
||||
|
||||
function getFiberState(root, workInProgress) {
|
||||
if (!root) {
|
||||
return null;
|
||||
}
|
||||
return describeFibers(root.current, workInProgress);
|
||||
}
|
||||
|
||||
const defaultCode = `
|
||||
log('Render <div>Hello</div>');
|
||||
ReactNoop.render(<div>Hello</div>);
|
||||
ReactNoop.flush();
|
||||
|
||||
log('Render <h1>Goodbye</h1>');
|
||||
ReactNoop.render(<h1>Goodbye</h1>);
|
||||
ReactNoop.flush();
|
||||
`;
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
code: localStorage.getItem('fiber-debugger-code') || defaultCode,
|
||||
isEditing: false,
|
||||
history: [],
|
||||
currentStep: 0,
|
||||
show: {
|
||||
alt: false,
|
||||
child: true,
|
||||
sibling: true,
|
||||
return: false,
|
||||
fx: false,
|
||||
progressedChild: false,
|
||||
progressedDel: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.runCode(this.state.code);
|
||||
}
|
||||
|
||||
runCode(code) {
|
||||
let currentStage;
|
||||
let currentRoot;
|
||||
|
||||
ReactFiberInstrumentation.debugTool = null;
|
||||
ReactNoop.render(null);
|
||||
ReactNoop.flush();
|
||||
ReactFiberInstrumentation.debugTool = {
|
||||
onMountContainer: (root) => {
|
||||
currentRoot = root;
|
||||
},
|
||||
onUpdateContainer: (root) => {
|
||||
currentRoot = root;
|
||||
},
|
||||
onBeginWork: (fiber) => {
|
||||
const fibers = getFiberState(currentRoot, fiber);
|
||||
const stage = currentStage;
|
||||
this.setState(({ history }) => ({
|
||||
history: [
|
||||
...history, {
|
||||
action: 'BEGIN',
|
||||
fibers,
|
||||
stage
|
||||
}
|
||||
]
|
||||
}));
|
||||
},
|
||||
onCompleteWork: (fiber) => {
|
||||
const fibers = getFiberState(currentRoot, fiber);
|
||||
const stage = currentStage;
|
||||
this.setState(({ history }) => ({
|
||||
history: [
|
||||
...history, {
|
||||
action: 'COMPLETE',
|
||||
fibers,
|
||||
stage
|
||||
}
|
||||
]
|
||||
}));
|
||||
},
|
||||
onCommitWork: (fiber) => {
|
||||
const fibers = getFiberState(currentRoot, fiber);
|
||||
const stage = currentStage;
|
||||
this.setState(({ history }) => ({
|
||||
history: [
|
||||
...history, {
|
||||
action: 'COMMIT',
|
||||
fibers,
|
||||
stage
|
||||
}
|
||||
]
|
||||
}));
|
||||
},
|
||||
};
|
||||
window.React = React;
|
||||
window.ReactNoop = ReactNoop;
|
||||
window.expect = () => ({
|
||||
toBe() {},
|
||||
toContain() {},
|
||||
toEqual() {},
|
||||
});
|
||||
window.log = s => currentStage = s;
|
||||
// eslint-disable-next-line
|
||||
eval(window.Babel.transform(code, {
|
||||
presets: ['react', 'es2015']
|
||||
}).code);
|
||||
}
|
||||
|
||||
handleEdit = (e) => {
|
||||
e.preventDefault();
|
||||
this.setState({
|
||||
isEditing: true
|
||||
});
|
||||
}
|
||||
|
||||
handleCloseEdit = (nextCode) => {
|
||||
localStorage.setItem('fiber-debugger-code', nextCode);
|
||||
this.setState({
|
||||
isEditing: false,
|
||||
history: [],
|
||||
currentStep: 0,
|
||||
code: nextCode
|
||||
});
|
||||
this.runCode(nextCode);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { history, currentStep, isEditing, code } = this.state;
|
||||
if (isEditing) {
|
||||
return <Editor code={code} onClose={this.handleCloseEdit} />;
|
||||
}
|
||||
|
||||
const { fibers, action, stage } = history[currentStep] || {};
|
||||
let friendlyAction;
|
||||
if (fibers) {
|
||||
let wipFiber = fibers.descriptions[fibers.workInProgressID];
|
||||
let friendlyFiber = wipFiber.type || wipFiber.tag + ' #' + wipFiber.id;
|
||||
friendlyAction = `After ${action} on ${friendlyFiber}`;
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%' }}>
|
||||
{fibers &&
|
||||
<Draggable>
|
||||
<Fibers fibers={fibers} show={this.state.show} />
|
||||
</Draggable>
|
||||
}
|
||||
<div style={{
|
||||
width: '100%',
|
||||
textAlign: 'center',
|
||||
position: 'fixed',
|
||||
bottom: 0,
|
||||
padding: 10,
|
||||
zIndex: 1,
|
||||
backgroundColor: '#fafafa',
|
||||
border: '1px solid #ccc'
|
||||
}}>
|
||||
<input
|
||||
type="range"
|
||||
style={{ width: '25%' }}
|
||||
min={0}
|
||||
max={history.length - 1}
|
||||
value={currentStep}
|
||||
onChange={e => this.setState({ currentStep: Number(e.target.value) })}
|
||||
/>
|
||||
<p>Step {currentStep}: {friendlyAction} (<a style={{ color: 'gray' }} onClick={this.handleEdit} href='#'>Edit</a>)</p>
|
||||
{stage && <p>Stage: {stage}</p>}
|
||||
{Object.keys(this.state.show).map(key =>
|
||||
<label style={{ marginRight: '10px' }} key={key}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={this.state.show[key]}
|
||||
onChange={e => {
|
||||
this.setState(({ show }) => ({
|
||||
show: {...show, [key]: !show[key]}
|
||||
}));
|
||||
}} />
|
||||
{key}
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -0,0 +1,35 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
class Editor extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
code: props.code
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={{
|
||||
height: '100%',
|
||||
width: '100%'
|
||||
}}>
|
||||
<textarea
|
||||
value={this.state.code}
|
||||
onChange={e => this.setState({ code: e.target.value })}
|
||||
style={{
|
||||
height: '80%',
|
||||
width: '100%',
|
||||
fontSize: '15px'
|
||||
}} />
|
||||
<div style={{ height: '20%', textAlign: 'center' }}>
|
||||
<button onClick={() => this.props.onClose(this.state.code)} style={{ fontSize: 'large' }}>
|
||||
Run
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Editor;
|
||||
@@ -0,0 +1,395 @@
|
||||
import React from 'react';
|
||||
import { Motion, spring } from 'react-motion';
|
||||
import dagre from 'dagre';
|
||||
import prettyFormat from 'pretty-format';
|
||||
import reactElement from 'pretty-format/plugins/ReactElement';
|
||||
|
||||
function getFiberColor(fibers, id) {
|
||||
if (fibers.currentIDs.indexOf(id) > -1) {
|
||||
return 'lightgreen';
|
||||
}
|
||||
if (id === fibers.workInProgressID) {
|
||||
return 'yellow';
|
||||
}
|
||||
return 'lightyellow';
|
||||
}
|
||||
|
||||
function Graph(props) {
|
||||
var g = new dagre.graphlib.Graph();
|
||||
g.setGraph({
|
||||
width: 1000,
|
||||
height: 1000,
|
||||
nodesep: 50,
|
||||
edgesep: 150,
|
||||
ranksep: 150,
|
||||
marginx: 100,
|
||||
marginy: 100,
|
||||
});
|
||||
|
||||
var edgeLabels = {};
|
||||
React.Children.forEach(props.children, function(child) {
|
||||
if (!child) {
|
||||
return;
|
||||
}
|
||||
if (child.type.isVertex) {
|
||||
g.setNode(child.key, {
|
||||
label: child,
|
||||
width: child.props.width,
|
||||
height: child.props.height
|
||||
});
|
||||
} else if (child.type.isEdge) {
|
||||
const relationshipKey = child.props.source + ':' + child.props.target;
|
||||
if (!edgeLabels[relationshipKey]) {
|
||||
edgeLabels[relationshipKey] = [];
|
||||
}
|
||||
edgeLabels[relationshipKey].push(child);
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(edgeLabels).forEach(key => {
|
||||
const children = edgeLabels[key];
|
||||
const child = children[0];
|
||||
g.setEdge(child.props.source, child.props.target, {
|
||||
label: child,
|
||||
allChildren: children.map(c => c.props.children),
|
||||
weight: child.props.weight
|
||||
});
|
||||
});
|
||||
|
||||
dagre.layout(g);
|
||||
|
||||
var activeNode = g.nodes().map(v => g.node(v)).find(node =>
|
||||
node.label.props.isActive
|
||||
);
|
||||
const [winX, winY] = [window.innerWidth / 2, window.innerHeight / 2]
|
||||
var focusDx = activeNode ? (winX - activeNode.x) : 0;
|
||||
var focusDy = activeNode ? (winY - activeNode.y) : 0;
|
||||
|
||||
var nodes = g.nodes().map(v => {
|
||||
var node = g.node(v);
|
||||
return (
|
||||
<Motion style={{
|
||||
x: props.isDragging ? node.x + focusDx : spring(node.x + focusDx),
|
||||
y: props.isDragging ? node.y + focusDy : spring(node.y + focusDy)
|
||||
}} key={node.label.key}>
|
||||
{interpolatingStyle =>
|
||||
React.cloneElement(node.label, {
|
||||
x: interpolatingStyle.x + props.dx,
|
||||
y: interpolatingStyle.y + props.dy,
|
||||
vanillaX: node.x,
|
||||
vanillaY: node.y,
|
||||
})
|
||||
}
|
||||
</Motion>
|
||||
);
|
||||
});
|
||||
|
||||
var edges = g.edges().map(e => {
|
||||
var edge = g.edge(e);
|
||||
let idx = 0;
|
||||
return (
|
||||
<Motion style={edge.points.reduce((bag, point) => {
|
||||
bag[idx + ':x'] = props.isDragging ? point.x + focusDx : spring(point.x + focusDx);
|
||||
bag[idx + ':y'] = props.isDragging ? point.y + focusDy : spring(point.y + focusDy);
|
||||
idx++;
|
||||
return bag;
|
||||
}, {})} key={edge.label.key}>
|
||||
{interpolatedStyle => {
|
||||
let points = [];
|
||||
Object.keys(interpolatedStyle).forEach(key => {
|
||||
const [idx, prop] = key.split(':');
|
||||
if (!points[idx]) {
|
||||
points[idx] = { x: props.dx, y: props.dy };
|
||||
}
|
||||
points[idx][prop] += interpolatedStyle[key];
|
||||
});
|
||||
return React.cloneElement(edge.label, {
|
||||
points,
|
||||
id: edge.label.key,
|
||||
children: edge.allChildren.join(', ')
|
||||
});
|
||||
}}
|
||||
</Motion>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
position: 'relative',
|
||||
height: '100%'
|
||||
}}>
|
||||
{edges}
|
||||
{nodes}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Vertex(props) {
|
||||
if (Number.isNaN(props.x) || Number.isNaN(props.y)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
border: '1px solid black',
|
||||
left: (props.x-(props.width/2)),
|
||||
top: (props.y-(props.height/2)),
|
||||
width: props.width,
|
||||
height: props.height,
|
||||
overflow: 'hidden',
|
||||
padding: '4px',
|
||||
wordWrap: 'break-word'
|
||||
}}>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Vertex.isVertex = true;
|
||||
|
||||
const strokes = {
|
||||
alt: 'blue',
|
||||
child: 'green',
|
||||
sibling: 'darkgreen',
|
||||
return: 'red',
|
||||
fx: 'purple',
|
||||
progressedChild: 'cyan',
|
||||
progressedDel: 'brown'
|
||||
};
|
||||
|
||||
function Edge(props) {
|
||||
var points = props.points;
|
||||
var path = "M" + points[0].x + " " + points[0].y + " ";
|
||||
|
||||
if (!points[0].x || !points[0].y) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (var i = 1; i < points.length; i++) {
|
||||
path += "L" + points[i].x + " " + points[i].y + " ";
|
||||
if (!points[i].x || !points[i].y) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
var lineID = props.id;
|
||||
|
||||
return (
|
||||
<svg width="100%" height="100%" style={{
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
}}>
|
||||
<defs>
|
||||
<path d={path} id={lineID} />
|
||||
<marker id="markerCircle" markerWidth="8" markerHeight="8" refX="5" refY="5">
|
||||
<circle cx="5" cy="5" r="3" style={{stroke: 'none', fill:'black'}}/>
|
||||
</marker>
|
||||
<marker 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'}} />
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<use xlinkHref={`#${lineID}`} fill="none" stroke={strokes[props.kind]} style={{
|
||||
markerStart: 'url(#markerCircle)',
|
||||
markerEnd: 'url(#markerArrow)'
|
||||
}} />
|
||||
<text>
|
||||
<textPath xlinkHref={`#${lineID}`}>
|
||||
{' '}{props.children}
|
||||
</textPath>
|
||||
</text>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Edge.isEdge = true;
|
||||
|
||||
function formatPriority(priority) {
|
||||
switch (priority) {
|
||||
case 1:
|
||||
return 'synchronous';
|
||||
case 2:
|
||||
return 'task';
|
||||
case 3:
|
||||
return 'animation';
|
||||
case 4:
|
||||
return 'hi-pri work';
|
||||
case 5:
|
||||
return 'lo-pri work';
|
||||
case 6:
|
||||
return 'offscreen work';
|
||||
default:
|
||||
throw new Error('Unknown priority.');
|
||||
}
|
||||
}
|
||||
|
||||
export default function Fibers({ fibers, show, ...rest }) {
|
||||
const items = Object.keys(fibers.descriptions).map(id =>
|
||||
fibers.descriptions[id]
|
||||
);
|
||||
|
||||
const isDragging = rest.className.indexOf('dragging') > -1;
|
||||
const [_, sdx, sdy] = rest.style.transform.match(/translate\((\-?\d+)px,(\-?\d+)px\)/) || [];
|
||||
const dx = Number(sdx);
|
||||
const dy = Number(sdy);
|
||||
|
||||
return (
|
||||
<div {...rest} style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
...rest.style,
|
||||
transform: null
|
||||
}}>
|
||||
<Graph
|
||||
className="graph"
|
||||
dx={dx}
|
||||
dy={dy}
|
||||
isDragging={isDragging}
|
||||
>
|
||||
{items.map(fiber => [
|
||||
<Vertex
|
||||
key={fiber.id}
|
||||
width={200}
|
||||
height={100}
|
||||
isActive={fiber.id === fibers.workInProgressID}>
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
backgroundColor: getFiberColor(fibers, fiber.id)
|
||||
}}
|
||||
title={prettyFormat(fiber, { plugins: [reactElement ]})}>
|
||||
<small>{fiber.tag} #{fiber.id}</small>
|
||||
<br />
|
||||
{fiber.type}
|
||||
<br />
|
||||
{fibers.currentIDs.indexOf(fiber.id) === -1 ?
|
||||
<small>
|
||||
{fiber.pendingWorkPriority !== 0 && [
|
||||
<span style={{
|
||||
fontWeight: fiber.pendingWorkPriority <= fiber.progressedPriority ?
|
||||
'bold' :
|
||||
'normal'
|
||||
}} key="span">
|
||||
Needs: {formatPriority(fiber.pendingWorkPriority)}
|
||||
</span>,
|
||||
<br key="br" />
|
||||
]}
|
||||
{fiber.progressedPriority !== 0 && [
|
||||
`Finished: ${formatPriority(fiber.progressedPriority)}`,
|
||||
<br key="br" />
|
||||
]}
|
||||
{fiber.memoizedProps !== null && fiber.pendingProps !== null && [
|
||||
fiber.memoizedProps === fiber.pendingProps ?
|
||||
'Can reuse memoized.' :
|
||||
'Cannot reuse memoized.',
|
||||
<br />
|
||||
]}
|
||||
</small> :
|
||||
<small>
|
||||
Committed
|
||||
</small>
|
||||
}
|
||||
</div>
|
||||
</Vertex>,
|
||||
fiber.child && show.child &&
|
||||
<Edge
|
||||
source={fiber.id}
|
||||
target={fiber.child}
|
||||
kind="child"
|
||||
weight={1000}
|
||||
key={`${fiber.id}-${fiber.child}-child`}>
|
||||
child
|
||||
</Edge>,
|
||||
fiber.progressedChild && show.progressedChild &&
|
||||
<Edge
|
||||
source={fiber.id}
|
||||
target={fiber.progressedChild}
|
||||
kind="progressedChild"
|
||||
weight={1000}
|
||||
key={`${fiber.id}-${fiber.progressedChild}-pChild`}>
|
||||
pChild
|
||||
</Edge>,
|
||||
fiber.sibling && show.sibling &&
|
||||
<Edge
|
||||
source={fiber.id}
|
||||
target={fiber.sibling}
|
||||
kind="sibling"
|
||||
weight={2000}
|
||||
key={`${fiber.id}-${fiber.sibling}-sibling`}>
|
||||
sibling
|
||||
</Edge>,
|
||||
fiber.return && show.return &&
|
||||
<Edge
|
||||
source={fiber.id}
|
||||
target={fiber.return}
|
||||
kind="return"
|
||||
weight={1000}
|
||||
key={`${fiber.id}-${fiber.return}-return`}>
|
||||
return
|
||||
</Edge>,
|
||||
fiber.nextEffect && show.fx &&
|
||||
<Edge
|
||||
source={fiber.id}
|
||||
target={fiber.nextEffect}
|
||||
kind="fx"
|
||||
weight={100}
|
||||
key={`${fiber.id}-${fiber.nextEffect}-nextEffect`}>
|
||||
nextFx
|
||||
</Edge>,
|
||||
fiber.firstEffect && show.fx &&
|
||||
<Edge
|
||||
source={fiber.id}
|
||||
target={fiber.firstEffect}
|
||||
kind="fx"
|
||||
weight={100}
|
||||
key={`${fiber.id}-${fiber.firstEffect}-firstEffect`}>
|
||||
firstFx
|
||||
</Edge>,
|
||||
fiber.lastEffect && show.fx &&
|
||||
<Edge
|
||||
source={fiber.id}
|
||||
target={fiber.lastEffect}
|
||||
kind="fx"
|
||||
weight={100}
|
||||
key={`${fiber.id}-${fiber.lastEffect}-lastEffect`}>
|
||||
lastFx
|
||||
</Edge>,
|
||||
fiber.progressedFirstDeletion && show.progressedDel &&
|
||||
<Edge
|
||||
source={fiber.id}
|
||||
target={fiber.progressedFirstDeletion}
|
||||
kind="progressedDel"
|
||||
weight={100}
|
||||
key={`${fiber.id}-${fiber.progressedFirstDeletion}-pFD`}>
|
||||
pFDel
|
||||
</Edge>,
|
||||
fiber.progressedLastDeletion && show.progressedDel &&
|
||||
<Edge
|
||||
source={fiber.id}
|
||||
target={fiber.progressedLastDeletion}
|
||||
kind="progressedDel"
|
||||
weight={100}
|
||||
key={`${fiber.id}-${fiber.progressedLastDeletion}-pLD`}>
|
||||
pLDel
|
||||
</Edge>,
|
||||
fiber.alternate && show.alt &&
|
||||
<Edge
|
||||
source={fiber.id}
|
||||
target={fiber.alternate}
|
||||
kind="alt"
|
||||
weight={10}
|
||||
key={`${fiber.id}-${fiber.alternate}-alt`}>
|
||||
alt
|
||||
</Edge>,
|
||||
])}
|
||||
</Graph>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
let nextFiberID = 1;
|
||||
const fiberIDMap = new WeakMap();
|
||||
|
||||
function getFiberUniqueID(fiber) {
|
||||
if (!fiberIDMap.has(fiber)) {
|
||||
fiberIDMap.set(fiber, nextFiberID++);
|
||||
}
|
||||
return fiberIDMap.get(fiber);
|
||||
}
|
||||
|
||||
function getFriendlyTag(tag) {
|
||||
switch (tag) {
|
||||
case 0:
|
||||
return '[indeterminate]';
|
||||
case 1:
|
||||
return '[fn]';
|
||||
case 2:
|
||||
return '[class]';
|
||||
case 3:
|
||||
return '[root]';
|
||||
case 4:
|
||||
return '[portal]';
|
||||
case 5:
|
||||
return '[host]';
|
||||
case 6:
|
||||
return '[text]';
|
||||
case 7:
|
||||
return '[coroutine]';
|
||||
case 8:
|
||||
return '[handler]';
|
||||
case 9:
|
||||
return '[yield]';
|
||||
case 10:
|
||||
return '[frag]';
|
||||
default:
|
||||
throw new Error('Unknown tag.');
|
||||
}
|
||||
}
|
||||
|
||||
export default function describeFibers(rootFiber, workInProgress) {
|
||||
let descriptions = {};
|
||||
function acknowledgeFiber(fiber) {
|
||||
if (!fiber) {
|
||||
return null;
|
||||
}
|
||||
if (!fiber.return && fiber.tag !== 3) {
|
||||
return null;
|
||||
}
|
||||
const id = getFiberUniqueID(fiber);
|
||||
if (descriptions[id]) {
|
||||
return id;
|
||||
}
|
||||
descriptions[id] = {};
|
||||
Object.assign(descriptions[id], {
|
||||
...fiber,
|
||||
id: id,
|
||||
tag: getFriendlyTag(fiber.tag),
|
||||
type: (fiber.type && ('<' + (fiber.type.name || fiber.type) + '>')),
|
||||
stateNode: `[${typeof fiber.stateNode}]`,
|
||||
return: acknowledgeFiber(fiber.return),
|
||||
child: acknowledgeFiber(fiber.child),
|
||||
sibling: acknowledgeFiber(fiber.sibling),
|
||||
nextEffect: acknowledgeFiber(fiber.nextEffect),
|
||||
firstEffect: acknowledgeFiber(fiber.firstEffect),
|
||||
lastEffect: acknowledgeFiber(fiber.lastEffect),
|
||||
progressedChild: acknowledgeFiber(fiber.progressedChild),
|
||||
progressedFirstDeletion: acknowledgeFiber(fiber.progressedFirstDeletion),
|
||||
progressedLastDeletion: acknowledgeFiber(fiber.progressedLastDeletion),
|
||||
alternate: acknowledgeFiber(fiber.alternate),
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
const rootID = acknowledgeFiber(rootFiber);
|
||||
const workInProgressID = acknowledgeFiber(workInProgress);
|
||||
|
||||
let currentIDs = new Set();
|
||||
function markAsCurent(id) {
|
||||
currentIDs.add(id);
|
||||
const fiber = descriptions[id];
|
||||
if (fiber.sibling) {
|
||||
markAsCurent(fiber.sibling);
|
||||
}
|
||||
if (fiber.child) {
|
||||
markAsCurent(fiber.child);
|
||||
}
|
||||
}
|
||||
markAsCurent(rootID);
|
||||
|
||||
return {
|
||||
descriptions,
|
||||
rootID,
|
||||
currentIDs: Array.from(currentIDs),
|
||||
workInProgressID
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: sans-serif;
|
||||
height: 100vh;
|
||||
cursor: -webkit-grab; cursor: -moz-grab;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import './index.css';
|
||||
|
||||
ReactDOM.render(
|
||||
<App />,
|
||||
document.getElementById('root')
|
||||
);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<body>
|
||||
<script src="../../build/react.js"></script>
|
||||
<script src="../../build/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
|
||||
<div id="container"></div>
|
||||
<script type="text/babel">
|
||||
ReactDOM.render(
|
||||
<h1>Hello World!</h1>,
|
||||
document.getElementById('container')
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user