├── .editorconfig ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── bower.json ├── gulpfile.js ├── package.json └── src └── PlotlyComponent.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | node_modules 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Ben Jeffery 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | React-PlotlyJS [![npm version](https://badge.fury.io/js/react-plotlyjs.svg)](http://badge.fury.io/js/react-plotlyjs) 2 | ============= 3 | 4 | 5 | A react component for Plotly.JS graphs. 6 | 7 | This is a very early, simple wrapper with the following problems: 8 | * Performs a full redraw on every update, I intend to make this more performant soon. 9 | * Changes to the 'config' prop will not update the graph currently. 10 | 11 | However it does support event handling via the onClick, onBeforeHover, onHover, onUnHover, onSelected, and onRelayout props. 12 | Note that currently, however, changes to these event handlers after initial creation will not be propogated. 13 | 14 | As the full Plotly bundle is huge, this library lets you pass a custom bundle to create the component. Therefore you will need Plotly as a direct dependancy of your project. 15 | 16 | 17 | ```javascript 18 | import createPlotlyComponent from 'react-plotlyjs'; 19 | //See the list of possible plotly bundles at https://github.com/plotly/plotly.js/blob/master/dist/README.md#partial-bundles or roll your own 20 | import Plotly from 'plotly.js/dist/plotly-cartesian'; 21 | const PlotlyComponent = createPlotlyComponent(Plotly); 22 | ``` 23 | 24 | Here's a simple example render method: 25 | 26 | 27 | ```javascript 28 | render() { 29 | let data = [ 30 | { 31 | type: 'scatter', // all "scatter" attributes: https://plot.ly/javascript/reference/#scatter 32 | x: [1, 2, 3], // more about "x": #scatter-x 33 | y: [6, 2, 3], // #scatter-y 34 | marker: { // marker is an object, valid marker keys: #scatter-marker 35 | color: 'rgb(16, 32, 77)' // more about "marker.color": #scatter-marker-color 36 | } 37 | }, 38 | { 39 | type: 'bar', // all "bar" chart attributes: #bar 40 | x: [1, 2, 3], // more about "x": #bar-x 41 | y: [6, 2, 3], // #bar-y 42 | name: 'bar chart example' // #bar-name 43 | } 44 | ]; 45 | let layout = { // all "layout" attributes: #layout 46 | title: 'simple example', // more about "layout.title": #layout-title 47 | xaxis: { // all "layout.xaxis" attributes: #layout-xaxis 48 | title: 'time' // more about "layout.xaxis.title": #layout-xaxis-title 49 | }, 50 | annotations: [ // all "annotation" attributes: #layout-annotations 51 | { 52 | text: 'simple annotation', // #layout-annotations-text 53 | x: 0, // #layout-annotations-x 54 | xref: 'paper', // #layout-annotations-xref 55 | y: 0, // #layout-annotations-y 56 | yref: 'paper' // #layout-annotations-yref 57 | } 58 | ] 59 | }; 60 | let config = { 61 | showLink: false, 62 | displayModeBar: true 63 | }; 64 | return ( 65 | 66 | ); 67 | } 68 | 69 | ``` 70 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-plotlyjs", 3 | "main": "lib/PlotlyComponent.js", 4 | "version": "0.4.3", 5 | "homepage": "https://github.com/benjeffery/react-plotlyjs", 6 | "authors": [ 7 | "Ben Jeffery" 8 | ], 9 | "description": "ReactJS / PlotlyJS integration. Draw plotly graphs in your react app.", 10 | "moduleType": [ 11 | "amd", 12 | "globals", 13 | "node" 14 | ], 15 | "keywords": [ 16 | "react", 17 | "react-component", 18 | "plotly", 19 | "graph", 20 | "plot" 21 | ], 22 | "license": "MIT", 23 | "ignore": [ 24 | ".editorconfig", 25 | ".gitignore", 26 | "package.json", 27 | "src", 28 | "node_modules", 29 | "example", 30 | "test" 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var bump = require('gulp-bump'); 3 | var git = require("gulp-git"); 4 | 5 | 6 | /** 7 | * Version bump tasks 8 | */ 9 | 10 | function getBumpTask(type) { 11 | return function () { 12 | return gulp.src(['./package.json', './bower.json']) 13 | .pipe(bump({ type: type })) 14 | .pipe(gulp.dest('./')); 15 | }; 16 | } 17 | 18 | gulp.task('bump', getBumpTask('patch')); 19 | gulp.task('bump:minor', getBumpTask('minor')); 20 | gulp.task('bump:major', getBumpTask('major')); 21 | 22 | 23 | /** 24 | * Git tag task 25 | * (version *must* be bumped first) 26 | */ 27 | 28 | gulp.task('publish:tag', function (done) { 29 | var pkg = require('./package.json'); 30 | var v = 'v' + pkg.version; 31 | var message = 'Release ' + v; 32 | 33 | git.tag(v, message, function (err) { 34 | if (err) throw err; 35 | git.push('origin', v, function (err) { 36 | if (err) throw err; 37 | done(); 38 | }); 39 | }); 40 | }); 41 | 42 | 43 | /** 44 | * npm publish task 45 | * * (version *must* be bumped first) 46 | */ 47 | 48 | gulp.task('publish:npm', function (done) { 49 | require('child_process') 50 | .spawn('npm', ['publish'], { stdio: 'inherit' }) 51 | .on('close', done); 52 | }); 53 | 54 | 55 | /** 56 | * Deploy tasks 57 | */ 58 | 59 | gulp.task('release', ['publish:tag', 'publish:npm']); 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-plotlyjs", 3 | "version": "0.4.3", 4 | "description": "ReactJS / PlotlyJS integration. Draw plotly graphs in your react app.", 5 | "main": "lib/PlotlyComponent.js", 6 | "author": "Ben Jeffery", 7 | "license": "MIT", 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/benjeffery/react-plotlyjs.git" 11 | }, 12 | "dependencies": { 13 | "lodash.clonedeep": "^4.5.0", 14 | "prop-types": "^15.5.10", 15 | "react": "^15.6.1||^16.0.0" 16 | }, 17 | "devDependencies": { 18 | "babel-cli": "^6.22.2", 19 | "babel-preset-es2015": "^6.22.0", 20 | "babel-preset-react": "^6.22.0", 21 | "babel-preset-stage-1": "^6.22.0", 22 | "gulp": "^3.9.1", 23 | "gulp-bump": "^2.5.1", 24 | "gulp-git": "^2.4.2", 25 | "gulp-util": "^3.0.8" 26 | }, 27 | "peerDependencies": { 28 | "react": "^15.0.0||^16.0.0" 29 | }, 30 | "browserify-shim": { 31 | "react": "global:React" 32 | }, 33 | "scripts": { 34 | "prepare": "npm run compile", 35 | "compile": "babel --presets es2015,stage-1,react -d lib/ src/", 36 | "bump": "gulp bump", 37 | "bump:minor": "gulp bump:minor", 38 | "bump:major": "gulp bump:major", 39 | "release": "gulp publish:tag && gulp publish:npm", 40 | "test": "echo \"no tests yet\" && exit 0" 41 | }, 42 | "keywords": [ 43 | "react", 44 | "react-component", 45 | "plotly", 46 | "graph", 47 | "plot" 48 | ] 49 | } 50 | -------------------------------------------------------------------------------- /src/PlotlyComponent.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | import cloneDeep from 'lodash.clonedeep'; 4 | 5 | let createPlotlyComponent = (plotlyInstance) => class Plotly extends React.Component { 6 | 7 | static propTypes = { 8 | data: PropTypes.array, 9 | layout: PropTypes.object, 10 | config: PropTypes.object, 11 | onClick: PropTypes.func, 12 | onBeforeHover: PropTypes.func, 13 | onHover: PropTypes.func, 14 | onUnHover: PropTypes.func, 15 | onSelected: PropTypes.func, 16 | onRelayout: PropTypes.func, 17 | }; 18 | 19 | attachListeners() { 20 | if (this.props.onClick) 21 | this.container.on('plotly_click', this.props.onClick); 22 | if (this.props.onBeforeHover) 23 | this.container.on('plotly_beforehover', this.props.onBeforeHover); 24 | if (this.props.onHover) 25 | this.container.on('plotly_hover', this.props.onHover); 26 | if (this.props.onUnHover) 27 | this.container.on('plotly_unhover', this.props.onUnHover); 28 | if (this.props.onSelected) 29 | this.container.on('plotly_selected', this.props.onSelected); 30 | if (this.props.onRelayout) { 31 | this.container.on('plotly_relayout', this.props.onRelayout); 32 | } 33 | } 34 | 35 | shouldComponentUpdate(nextProps) { 36 | //TODO logic for detecting change in props 37 | return true; 38 | } 39 | 40 | componentDidMount() { 41 | let {data, layout, config} = this.props; 42 | plotlyInstance.newPlot(this.container, data, cloneDeep(layout), config); //We clone the layout as plotly mutates it. 43 | this.attachListeners(); 44 | } 45 | 46 | componentDidUpdate(prevProps) { 47 | //TODO use minimal update for given changes 48 | if (prevProps.data !== this.props.data || prevProps.layout !== this.props.layout || prevProps.config !== this.props.config) { 49 | let {data, layout, config} = this.props; 50 | plotlyInstance.newPlot(this.container, data, cloneDeep(layout), config); //We clone the layout as plotly mutates it. 51 | this.attachListeners(); 52 | } 53 | } 54 | 55 | componentWillUnmount() { 56 | plotlyInstance.purge(this.container); 57 | } 58 | 59 | resize() { 60 | plotlyInstance.Plots.resize(this.container); 61 | } 62 | 63 | render() { 64 | let {data, layout, config, ...other } = this.props; 65 | //Remove props that would cause React to warn for unknown props. 66 | delete other.onClick; 67 | delete other.onBeforeHover; 68 | delete other.onHover; 69 | delete other.onUnHover; 70 | delete other.onSelected; 71 | delete other.onRelayout; 72 | 73 | return
this.container=node} /> 74 | } 75 | }; 76 | 77 | export default createPlotlyComponent; 78 | --------------------------------------------------------------------------------