Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f207cb2

Browse files
Change default export to combined EditorControls + Plot component (#384)
1 parent dea11c6 commit f207cb2

File tree

23 files changed

+556
-645
lines changed

23 files changed

+556
-645
lines changed

‎README.md

Lines changed: 3 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Check out the demo of the latest release of the `DefaultEditor` at https://plotl
1818
```
1919
git clone [this repo]
2020
cd react-chart-editor
21-
cd examples/simple
21+
cd examples/demo
2222
npm install
2323
npm start
2424
```
@@ -28,55 +28,7 @@ See more examples
2828

2929
## Overview
3030

31-
This module's entry point is a React component called `<PlotlyEditor />` which connects to a [plotly.js](https://plot.ly/javascript/)-powered `<Plot />` component care of [`react-plotly.js`](https://github.com/plotly/react-plotly.js). A plotly.js plot is defined by a JSON-serializable object called a _figure_. `<PlotlyEditor />` accepts as children React components whose descendents are input elements wrapped via `connectToContainer()` calls so as to bind them to the `<Plot />`'s figure's values. If no children are passed to the `<PlotlyEditor />`, the `<DefaultEditor />` is used. This module also exposes the [building block components](#Built-in-Components) that comprise the `<DefaultEditor />` so that developers can create their own customized editors.
32-
33-
## Connecting `<PlotlyEditor />` to `<Plot />`
34-
35-
The binding between `<PlotlyEditor />` and `<Plot />` works a little differently that in most React apps because plotly.js mutates its properties. This is mapped onto React's one-way dataflow model via event handlers and shared revision numbers which trigger re-renders of mutated state. The following subset of the [simple example](https://github.com/plotly/react-chart-editor/tree/master/examples/simple) shows how this works using a parent component to store state, but the principle is the same with a different state-manage approach, as shown in the [redux example](https://github.com/plotly/react-chart-editor/tree/master/examples/redux):
36-
37-
```javascript
38-
import PlotlyEditor from 'react-chart-editor';
39-
import Plot from 'react-plotly.js';
40-
41-
class App extends Component {
42-
constructor() {
43-
super();
44-
this.state = {graphDiv: {}, editorRevision: 0, plotRevision: 0};
45-
}
46-
47-
handlePlotUpdate(graphDiv) {
48-
this.setState(({editorRevision: x}) => ({editorRevision: x + 1, graphDiv}));
49-
}
50-
51-
handleEditorUpdate() {
52-
this.setState(({plotRevision: x}) => ({plotRevision: x + 1}));
53-
}
54-
55-
render() {
56-
return (
57-
<div>
58-
<PlotlyEditor
59-
graphDiv={this.state.graphDiv}
60-
onUpdate={this.handleEditorUpdate.bind(this)}
61-
revision={this.state.editorRevision}
62-
{...snip}
63-
/>
64-
<Plot
65-
data={this.state.graphDiv.data}
66-
layout={this.state.graphDiv.layout}
67-
onUpdate={this.handlePlotUpdate.bind(this)}
68-
revision={this.state.plotRevision}
69-
{...snip}
70-
/>
71-
</div>
72-
);
73-
}
74-
}
75-
```
76-
77-
## Data Management
78-
79-
`<PlotlyEditor />` accepts a `dataSources` property which is an object of arrays of data, as well as a `dataSourceOptions` property which contains metadata about the `dataSources`, such as human-readable labels used to populate input elements like dropdown menus. `<PlotlyEditor />` treats these properties as immutable so any changes to them will trigger a rerender, and accepts an `onUpdateTraces` event handler property which is called whenever it needs to access a column from `dataSources`, enabling asynchronous data loading e.g. from remote APIs. The [async-data example](https://github.com/plotly/react-chart-editor/tree/master/examples/async-data) shows how this is done using a dummy asynchronous back-end proxy.
31+
This module's entry point is a React component called `<PlotlyEditor />` which connects an instance of `<EditorControls />` to a [plotly.js](https://plot.ly/javascript/)-powered `<Plot />` component care of [`react-plotly.js`](https://github.com/plotly/react-plotly.js). `<PlotlyEditor />` accepts as children React components whose descendents are input elements wrapped via `connectToContainer()` calls so as to bind them to the `<Plot />`'s figure's values. If no children are passed to the `<PlotlyEditor />`, the `<DefaultEditor />` is used. This module also exposes the [building block components](#Built-in-Components) that comprise the `<DefaultEditor />` so that developers can create their own customized editors.
8032

8133
## Styling the `<DefaultEditor />` and the built-in components
8234

@@ -198,7 +150,7 @@ For use in containers bound to annotations e.g. as children of `<AnnotationAccor
198150

199151
To use Satellite Maps in the Editor, [Mapbox access tokens](https://www.mapbox.com/help/how-access-tokens-work/) are required.
200152

201-
Once you have your tokens, you can provide it as a config prop to the `react-plotly.js` generated `Plot` component: `<Plot config={{mapboxAccessToken: 'your token'}}/>`
153+
Once you have your tokens, you can provide it as a config prop to the `<PlotlyEditor />` component: `<PlotlyEditor config={{mapboxAccessToken: 'your token'}}/>`
202154

203155
## See also
204156

‎dev/App.js

Lines changed: 21 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import React, {Component} from 'react';
22
import {hot} from 'react-hot-loader';
33
import plotly from 'plotly.js/dist/plotly';
4-
import createPlotComponent from 'react-plotly.js/factory';
5-
import PlotlyEditor from '../src';
64
import '../src/styles/main.scss';
75
import Nav from './Nav';
6+
import PlotlyEditor from '../src';
87

98
// https://github.com/plotly/react-chart-editor#mapbox-access-tokens
109
import ACCESS_TOKENS from '../accessTokens';
@@ -22,18 +21,15 @@ const dataSourceOptions = Object.keys(dataSources).map(name => ({
2221
label: name,
2322
}));
2423

25-
const Plot = createPlotComponent(plotly);
24+
const config = {mapboxAccessToken: ACCESS_TOKENS.MAPBOX,editable: true};
2625

2726
class App extends Component {
2827
constructor() {
2928
super();
3029

31-
// The graphDiv object is passed to Plotly.js, which then causes it to be
32-
// overwritten with a full DOM node that contains data, layout, _fullData,
33-
// _fullLayout etc in handlePlotUpdate()
3430
this.state = {
35-
graphDiv: {},
36-
plotRevision: 0,
31+
data: [],
32+
layout: {},
3733
currentMockIndex: -1,
3834
mocks: [],
3935
};
@@ -49,61 +45,36 @@ class App extends Component {
4945
.then(mocks => this.setState({mocks}));
5046
}
5147

52-
handlePlotUpdate(graphDiv) {
53-
this.setState({graphDiv});
54-
}
55-
56-
handleEditorUpdate() {
57-
this.setState(({plotRevision: x}) => ({plotRevision: x + 1}));
58-
}
59-
6048
loadMock(mockIndex) {
6149
const mock = this.state.mocks[mockIndex];
6250
fetch(mock.url, {
6351
headers: new Headers({Accept: 'application/vnd.github.v3.raw'}),
6452
})
6553
.then(response => response.json())
6654
.then(figure => {
67-
const graphDiv = this.state.graphDiv;
68-
graphDiv.layout = figure.layout;
69-
graphDiv.data = figure.data;
70-
this.setState(({plotRevision: x}) => ({
55+
this.setState({
7156
currentMockIndex: mockIndex,
72-
plotRevision: x + 1,
73-
}));
57+
data: figure.data,
58+
layout: figure.layout,
59+
});
7460
});
7561
}
7662

7763
render() {
7864
return (
79-
<div className="app__container plotly-editor--theme-provider">
80-
<div className="app">
81-
<PlotlyEditor
82-
graphDiv={this.state.graphDiv}
83-
onUpdate={this.handleEditorUpdate.bind(this)}
84-
dataSources={dataSources}
85-
dataSourceOptions={dataSourceOptions}
86-
plotly={plotly}
87-
advancedTraceTypeSelector
88-
/>
89-
<div className="app__main" style={{width: '100%', height: '100%'}}>
90-
<Plot
91-
config={{mapboxAccessToken: ACCESS_TOKENS.MAPBOX, editable: true}}
92-
data={this.state.graphDiv.data}
93-
debug
94-
layout={this.state.graphDiv.layout}
95-
onInitialized={this.handlePlotUpdate.bind(this)}
96-
onUpdate={this.handlePlotUpdate.bind(this)}
97-
revision={this.state.plotRevision}
98-
useResizeHandler
99-
style={{
100-
width: '100%',
101-
height: '100%',
102-
minHeight: 'calc(100vh - 50px)',
103-
}}
104-
/>
105-
</div>
106-
</div>
65+
<div className="app">
66+
<PlotlyEditor
67+
data={this.state.data}
68+
layout={this.state.layout}
69+
config={config}
70+
dataSources={dataSources}
71+
dataSourceOptions={dataSourceOptions}
72+
plotly={plotly}
73+
onUpdate={(data, layout) => this.setState({data, layout})}
74+
useResizeHandler
75+
debug
76+
advancedTraceTypeSelector
77+
/>
10778
<Nav
10879
currentMockIndex={this.state.currentMockIndex}
10980
loadMock={this.loadMock}

‎dev/styles.css

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,29 @@ body {
44
font-family: sans-serif;
55
}
66

7-
.app__container {
8-
display: flex;
9-
flex-direction: column;
10-
}
11-
127
.app {
13-
display: flex;
14-
/*
15-
We are defining the max height of the app so that the editor knows how big to be
16-
currently the editor will take up whatever space it can if it is not constrained in its parent
17-
*/
18-
flex-grow: 1;
19-
height: calc(100vh - 50px);
20-
max-height: calc(100vh - 50px);
21-
width: 100%;
22-
}
23-
24-
.app__main {
25-
max-width: 100%;
268
height: calc(100vh - 50px);
279
max-height: calc(100vh - 50px);
28-
overflow: auto;
29-
flex-grow: 1;
3010
}
3111

3212
.mock-nav {
3313
height: 50px;
3414
width: 100%;
35-
background-color: var(--color-background-inverse);
15+
background-color: #506784;
3616
display: inline-flex;
3717
color: white;
3818
}
3919

40-
.mock-nav__label{
41-
line-height: 50px;
42-
padding-left: 10px;
20+
.mock-nav__label{
21+
line-height: 50px;
22+
padding-left: 10px;
4323
}
4424

45-
.mock-nav__select{
46-
width: 300px;
47-
margin-left: 20px;
48-
margin-right: 20px;
49-
margin-top: 7px;
25+
.mock-nav__select{
26+
width: 300px;
27+
margin-left: 20px;
28+
margin-right: 20px;
29+
margin-top: 7px;
5030
}
5131

5232
.Select.open-top .Select-menu-outer {

‎examples/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# `react-chart-editor` examples
22

33
* [Simple `react-chart-editor` example](simple): `DefaultEditor`, synchronous data, top-level component state management
4-
* [Async-data `react-chart-editor` example](async-data): `DefaultEditor`, asynchronous data, top-level component state management
4+
* [Demo `react-chart-editor` example](demo): `DefaultEditor`, top-level component state management, navbar to load mocks (same as dev app but no hot-reloading)
55
* [Custom `react-chart-editor` example](custom): `CustomEditor`, synchronous data, top-level component state management
66
* [Redux `react-chart-editor` example](redux): `DefaultEditor`, synchronous data, Redux state management

‎examples/custom/src/App.js

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import React, {Component} from 'react';
22
import plotly from 'plotly.js/dist/plotly';
3-
import createPlotComponent from 'react-plotly.js/factory';
43
import PlotlyEditor from 'react-chart-editor';
54
import CustomEditor from './CustomEditor';
65
import 'react-chart-editor/lib/react-chart-editor.css';
@@ -15,62 +14,41 @@ const dataSourceOptions = Object.keys(dataSources).map(name => ({
1514
label: name,
1615
}));
1716

18-
const Plot = createPlotComponent(plotly);
17+
const config = {editable: true};
1918

2019
class App extends Component {
2120
constructor() {
2221
super();
23-
24-
// The graphDiv object is passed to Plotly.js, which then causes it to be
25-
// overwritten with a full DOM node that contains data, layout, _fullData,
26-
// _fullLayout etc in handlePlotUpdate()
2722
this.state = {
28-
graphDiv: {
29-
data: [
30-
{
31-
type: 'scatter',
32-
x: dataSources.col1,
33-
y: dataSources.col2,
34-
marker: {color: dataSources.col3},
35-
},
36-
],
37-
},
38-
plotRevision: 0,
23+
data: [
24+
{
25+
type: 'scatter',
26+
x: dataSources.col1,
27+
y: dataSources.col2,
28+
marker: {color: dataSources.col3},
29+
},
30+
],
31+
layout: {},
3932
};
4033
}
4134

42-
handlePlotUpdate(graphDiv) {
43-
this.setState({graphDiv});
44-
}
45-
46-
handleEditorUpdate() {
47-
this.setState(({plotRevision: x}) => ({plotRevision: x + 1}));
48-
}
49-
5035
render() {
5136
return (
5237
<div className="app">
5338
<PlotlyEditor
54-
locale="en"
55-
graphDiv={this.state.graphDiv}
56-
onUpdate={this.handleEditorUpdate.bind(this)}
57-
plotly={plotly}
39+
data={this.state.data}
40+
layout={this.state.layout}
41+
config={config}
5842
dataSources={dataSources}
5943
dataSourceOptions={dataSourceOptions}
44+
plotly={plotly}
45+
onUpdate={(data, layout) => this.setState({data, layout})}
46+
useResizeHandler
47+
debug
48+
advancedTraceTypeSelector
6049
>
6150
<CustomEditor />
6251
</PlotlyEditor>
63-
<div className="app__main">
64-
<Plot
65-
debug
66-
data={this.state.graphDiv.data}
67-
layout={this.state.graphDiv.layout}
68-
config={{editable: true}}
69-
onUpdate={this.handlePlotUpdate.bind(this)}
70-
onInitialized={this.handlePlotUpdate.bind(this)}
71-
revision={this.state.plotRevision}
72-
/>
73-
</div>
7452
</div>
7553
);
7654
}

‎examples/custom/src/index.css

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,7 @@ body {
44
font-family: sans-serif;
55
}
66

7-
.app{
8-
display: flex;
9-
/*
10-
We are defining the max height of the app so that the editor knows how big to be
11-
currently the editor will take up whatever space it can if it is not constrained in its parent
12-
*/
13-
min-height: 100vh;
7+
.app {
8+
height: 100vh;
149
max-height: 100vh;
15-
width: 100%;
16-
}
17-
.app__main {
18-
max-width: 100%;
19-
max-height: 100vh;
20-
overflow: auto;
21-
flex-grow: 1;
2210
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /