├── .gitignore ├── LICENSE ├── README.md ├── bower.json ├── dist ├── react-pathjs-chart.js └── react-pathjs-chart.min.js ├── example └── src │ ├── BarChartDemo.js │ ├── ChartDemo.js │ ├── PieChartDemo.js │ ├── RadarChartDemo.js │ ├── ScatterPlotDemo.js │ ├── SmoothLineChartDemo.js │ ├── StockLineChartDemo.js │ ├── TreeChartDemo.js │ ├── app.css │ ├── app.js │ ├── app.less │ ├── index.html │ └── standalone.html ├── gulpconfig.js ├── gulpfile.js ├── package.json └── src ├── Chart.js ├── animate.js ├── charts ├── Bar.js ├── BarVivus.js ├── Line.js ├── Pie.js ├── PieVivus.js ├── Radar.js ├── RadarVivus.js ├── Scatterplot.js ├── ScatterplotVivus.js ├── SmoothLine.js ├── SmoothLineVivus.js ├── StockLine.js ├── StockLineVivus.js ├── Tree.js └── TreeVivus.js ├── component ├── Axis.js └── Options.js ├── fontAdapter.js ├── pallete └── Colors.js └── styleSvg.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Coverage tools 11 | lib-cov 12 | coverage 13 | coverage.html 14 | .cover* 15 | 16 | # Dependency directory 17 | node_modules 18 | 19 | # Example build directory 20 | example/dist 21 | 22 | # Editor and other tmp files 23 | *.swp 24 | *.un~ 25 | *.iml 26 | *.ipr 27 | *.iws 28 | *.sublime-* 29 | .idea/ 30 | *.DS_Store 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Roman Samec 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 | Chart library 2 | ======================= 3 | 4 | These component offers react components - charts (Pie,Bar,SmoothLine,StockLine,Scatterplot,Tree,Radar) using [paths-js](https://github.com/andreaferretti/paths-js). 5 | 6 | It is based on clone of these examples from [path-js](https://github.com/andreaferretti/paths-js-react-demo) and is extended so that it is easier to use it. 7 | 8 | + configuration of formats, labels, colors, axis, ticks, lines, animations, ... 9 | + support for chart animation - using vivus [vivus](https://github.com/maxwellito/vivus) 10 | + instead of accessor function you can use string key to determine the accessor key in data 11 | + server rendering 12 | + wrapped to be used by package managers (npm, bower) or standalone package 13 | 14 | ## Demo & Examples 15 | 16 | [Live demo](http://rsamec.github.io/react-pathjs-chart/) 17 | 18 | To build the examples locally, run: 19 | 20 | ``` 21 | npm install 22 | gulp dev 23 | ``` 24 | 25 | Then open [`localhost:8000`](http://localhost:8000) in a browser. 26 | 27 | 28 | ## Installation 29 | 30 | The easiest way to use this component is to install it from NPM and include it in your own React build process (using [Browserify](http://browserify.org), [Webpack](http://webpack.github.io/), etc). 31 | 32 | You can also use the standalone build by including `dist/react-pathjs-chart.js` in your page. If you use this, make sure you have already included React, and it is available as a global variable. 33 | 34 | ``` 35 | npm install react-pathjs-chart --save 36 | ``` 37 | 38 | 39 | ## Usage 40 | 41 | 42 | 43 | ``` 44 | import {Pie,Bar, SmoothLine,StockLine,Scatterplot,Tree,Radar} from 'react-pathjs-chart'; 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | ``` 55 | 56 | ### Properties 57 | 58 | + data - chart data to visualize 59 | + accessor keys 60 | + Pie,Bar - __accessorKey__ 61 | + SmoothLine,StockLine,Scatterplot - __xKey__, __yKey__ 62 | + options - visual configuration of chart, enables to configure formats, labels, colors, axis, ticks, lines, animations, ... 63 | + noDataMessage - message to show if no data or empty data are specified 64 | 65 | ### Notes 66 | 67 | 68 | 69 | ### License 70 | 71 | MIT. Copyright (c) 2015 Roman Samec 72 | 73 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-pathjs-chart", 3 | "main": "dist/react-pathjs-chart.min.js", 4 | "version": "0.2.11", 5 | "homepage": "https://github.com/rsamec/react-pathjs-chart", 6 | "authors": [ 7 | "Roman Samec" 8 | ], 9 | "description": "React components - charts (Pie,SmoothLine) and other components (Tree) using path-js.", 10 | "moduleType": [ 11 | "amd", 12 | "globals", 13 | "node" 14 | ], 15 | "keywords": [ 16 | "react", 17 | "react-component" 18 | ], 19 | "license": "MIT", 20 | "ignore": [ 21 | ".editorconfig", 22 | ".gitignore", 23 | "package.json", 24 | "src", 25 | "node_modules", 26 | "example", 27 | "test" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /dist/react-pathjs-chart.min.js: -------------------------------------------------------------------------------- 1 | !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Chart=t()}}(function(){var t;return function e(t,n,r){function o(a,u){if(!n[a]){if(!t[a]){var l="function"==typeof require&&require;if(!u&&l)return l(a,!0);if(i)return i(a,!0);var c=new Error("Cannot find module '"+a+"'");throw c.code="MODULE_NOT_FOUND",c}var f=n[a]={exports:{}};t[a][0].call(f.exports,function(e){var n=t[a][1][e];return o(n?n:e)},f,f.exports,e,t,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;ae&&!i||!o||n&&!a&&u||r&&u)return 1;if(e>t&&!n||!u||i&&!r&&o||a&&o)return-1}return 0}function i(t,e,n){for(var r=t.length,o=n?r:-1;n?o--:++o-1;);return n}function f(t,e){for(var n=t.length;n--&&e.indexOf(t.charAt(n))>-1;);return n}function s(t,e){return o(t.criteria,e.criteria)||t.index-e.index}function p(t,e,n){for(var r=-1,i=t.criteria,a=e.criteria,u=i.length,l=n.length;++r=l)return c;var f=n[r];return c*("asc"===f||f===!0?1:-1)}}return t.index-e.index}function h(t){return $t[t]}function d(t){return qt[t]}function y(t,e,n){return e?t=Xt[t]:n&&(t=Jt[t]),"\\"+t}function v(t){return"\\"+Jt[t]}function g(t,e,n){for(var r=t.length,o=e+(n?0:-1);n?o--:++o=t&&t>=9&&13>=t||32==t||160==t||5760==t||6158==t||t>=8192&&(8202>=t||8232==t||8233==t||8239==t||8287==t||12288==t||65279==t)}function b(t,e){for(var n=-1,r=t.length,o=-1,i=[];++ne,o=n?t.length:0,i=qn(0,o,this.__views__),a=i.start,u=i.end,l=u-a,c=r?u:a-1,f=this.__iteratees__,s=f.length,p=0,h=Oa(l,this.__takeCount__);if(!n||N>o||o==l&&h==l)return nn(r&&n?t.reverse():t,this.__actions__);var d=[];t:for(;l--&&h>p;){c+=e;for(var y=-1,v=t[c];++y=N?yn(e):null,c=e.length;l&&(i=Qt,u=!1,e=l);t:for(;++on&&(n=-n>o?0:o+n),r=r===E||r>o?o:+r||0,0>r&&(r+=o),o=n>r?0:r>>>0,n>>>=0;o>n;)t[n++]=e;return t}function Ae(t,e){var n=[];return za(t,function(t,r,o){e(t,r,o)&&n.push(t)}),n}function Pe(t,e,n,r){var o;return n(t,function(t,n,i){return e(t,n,i)?(o=r?n:t,!1):void 0}),o}function Me(t,e,n,r){r||(r=[]);for(var o=-1,i=t.length;++or;)t=t[e[r++]];return r&&r==o?t:E}}function Ie(t,e,n,r,o,i){return t===e?!0:null==t||null==e||!Io(t)&&!m(e)?t!==t&&e!==e:ze(t,e,Ie,n,r,o,i)}function ze(t,e,n,r,o,i,a){var u=Mu(t),l=Mu(e),c=H,f=H;u||(c=ra.call(t),c==q?c=tt:c!=tt&&(u=Vo(t))),l||(f=ra.call(e),f==q?f=tt:f!=tt&&(l=Vo(e)));var s=c==tt,p=f==tt,h=c==f;if(h&&!u&&!s)return Dn(t,e,c);if(!o){var d=s&&ea.call(t,"__wrapped__"),y=p&&ea.call(e,"__wrapped__");if(d||y)return n(d?t.value():t,y?e.value():e,r,o,i,a)}if(!h)return!1;i||(i=[]),a||(a=[]);for(var v=i.length;v--;)if(i[v]==t)return a[v]==e;i.push(t),a.push(e);var g=(u?Bn:Wn)(t,e,n,r,o,i,a);return i.pop(),a.pop(),g}function Fe(t,e,n){var r=e.length,o=r,i=!n;if(null==t)return!o;for(t=sr(t);r--;){var a=e[r];if(i&&a[2]?a[1]!==t[a[0]]:!(a[0]in t))return!1}for(;++re&&(e=-e>o?0:o+e),n=n===E||n>o?o:+n||0,0>n&&(n+=o),o=e>n?0:n-e>>>0,e>>>=0;for(var i=Ni(o);++r=N,l=u?yn():null,c=[];l?(r=Qt,i=!1):(u=!1,l=e?[]:c);t:for(;++n=o){for(;o>r;){var i=r+o>>>1,a=t[i];(n?e>=a:e>a)&&null!==a?r=i+1:o=i}return o}return on(t,e,Pi,n)}function on(t,e,n,r){e=n(e);for(var o=0,i=t?t.length:0,a=e!==e,u=null===e,l=e===E;i>o;){var c=ma((o+i)/2),f=n(t[c]),s=f!==E,p=f===f;if(a)var h=p||r;else h=u?p&&s&&(r||null!=f):l?p&&(r||s):null==f?!1:r?e>=f:e>f;h?o=c+1:i=c}return Oa(i,Ta)}function an(t,e,n){if("function"!=typeof t)return Pi;if(e===E)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 3:return function(n,r,o){return t.call(e,n,r,o)};case 4:return function(n,r,o,i){return t.call(e,n,r,o,i)};case 5:return function(n,r,o,i,a){return t.call(e,n,r,o,i,a)}}return function(){return t.apply(e,arguments)}}function un(t){var e=new aa(t.byteLength),n=new da(e);return n.set(new da(t)),e}function ln(t,e,n){for(var r=n.length,o=-1,i=xa(t.length-r,0),a=-1,u=e.length,l=Ni(u+i);++a2?n[o-2]:E,a=o>2?n[2]:E,u=o>1?n[o-1]:E;for("function"==typeof i?(i=an(i,u,5),o-=2):(i="function"==typeof u?u:E,o-=i?1:0),a&&Gn(n[0],n[1],a)&&(i=3>o?E:i,o=1);++r-1?n[a]:E}return Pe(n,r,t)}}function xn(t){return function(e,n,r){return e&&e.length?(n=Nn(n,r,3),i(e,n,t)):-1}}function On(t){return function(e,n,r){return n=Nn(n,r,3),Pe(e,n,t,!0)}}function jn(t){return function(){for(var e,n=arguments.length,o=t?n:-1,i=0,a=Ni(n);t?o--:++o=N)return e.plant(r).value();for(var o=0,i=n?a[o].apply(this,t):r;++om){var j=u?te(u):E,k=xa(c-m,0),A=d?O:E,T=d?E:O,S=d?w:E,R=d?E:w;e|=d?L:C,e&=~(d?C:L),y||(e&=~(P|M));var I=[t,e,n,S,A,R,T,j,l,k],z=Rn.apply(E,I);return er(t)&&Ua(z,I),z.placeholder=x,z}}var F=p?n:this,B=h?F[t]:t;return u&&(w=lr(w,u)),s&&l=e||!ba(e))return"";var o=e-r;return n=null==n?" ":n+"",gi(n,va(o/n.length)).slice(0,o)}function Cn(t,e,n,r){function o(){for(var e=-1,u=arguments.length,l=-1,c=r.length,f=Ni(c+u);++ll))return!1;for(;++u-1&&t%1==0&&e>t}function Gn(t,e,n){if(!Io(n))return!1;var r=typeof e;if("number"==r?Qn(n)&&Zn(e,n.length):"string"==r&&e in n){var o=n[e];return t===t?t===o:o!==o}return!1}function tr(t,e){var n=typeof t;if("string"==n&&Et.test(t)||"number"==n)return!0;if(Mu(t))return!1;var r=!kt.test(t);return r||null!=e&&t in sr(e)}function er(t){var n=Kn(t);if(!(n in _.prototype))return!1;var r=e[n];if(t===r)return!0;var o=Na(r);return!!o&&t===o[0]}function nr(t){return"number"==typeof t&&t>-1&&t%1==0&&Ra>=t}function rr(t){return t===t&&!Io(t)}function or(t,e){var n=t[1],r=e[1],o=n|r,i=I>o,a=r==I&&n==S||r==I&&n==z&&t[7].length<=e[8]||r==(I|z)&&n==S;if(!i&&!a)return t;r&P&&(t[2]=e[2],o|=n&P?0:T);var u=e[3];if(u){var l=t[3];t[3]=l?ln(l,u,e[4]):te(u),t[4]=l?b(t[3],$):te(e[4])}return u=e[5],u&&(l=t[5],t[5]=l?cn(l,u,e[6]):te(u),t[6]=l?b(t[5],$):te(e[6])),u=e[7],u&&(t[7]=te(u)),r&I&&(t[8]=null==t[8]?e[8]:Oa(t[8],e[8])),null==t[9]&&(t[9]=e[9]),t[0]=e[0],t[1]=o,t}function ir(t,e){return t===E?e:Tu(t,e,ir)}function ar(t,e){t=sr(t);for(var n=-1,r=e.length,o={};++nr;)a[++i]=Ye(t,r,r+=e);return a}function yr(t){for(var e=-1,n=t?t.length:0,r=-1,o=[];++ee?0:e)):[]}function gr(t,e,n){var r=t?t.length:0;return r?((n?Gn(t,e,n):null==e)&&(e=1),e=r-(+e||0),Ye(t,0,0>e?0:e)):[]}function mr(t,e,n){return t&&t.length?en(t,Nn(e,n,3),!0,!0):[]}function _r(t,e,n){return t&&t.length?en(t,Nn(e,n,3),!0):[]}function br(t,e,n,r){var o=t?t.length:0;return o?(n&&"number"!=typeof n&&Gn(t,e,n)&&(n=0,r=o),Ee(t,e,n,r)):[]}function wr(t){return t?t[0]:E}function xr(t,e,n){var r=t?t.length:0;return n&&Gn(t,e,n)&&(e=!1),r?Me(t,e):[]}function Or(t){var e=t?t.length:0;return e?Me(t,!0):[]}function jr(t,e,n){var r=t?t.length:0;if(!r)return-1;if("number"==typeof n)n=0>n?xa(r+n,0):n;else if(n){var o=rn(t,e);return r>o&&(e===e?e===t[o]:t[o]!==t[o])?o:-1}return a(t,e,n||0)}function kr(t){return gr(t,1)}function Er(t){var e=t?t.length:0;return e?t[e-1]:E}function Ar(t,e,n){var r=t?t.length:0;if(!r)return-1;var o=r;if("number"==typeof n)o=(0>n?xa(r+n,0):Oa(n||0,r-1))+1;else if(n){o=rn(t,e,!0)-1;var i=t[o];return(e===e?e===i:i!==i)?o:-1}if(e!==e)return g(t,o,!0);for(;o--;)if(t[o]===e)return o;return-1}function Pr(){var t=arguments,e=t[0];if(!e||!e.length)return e;for(var n=0,r=Un(),o=t.length;++n-1;)ha.call(e,i,1);return e}function Mr(t,e,n){var r=[];if(!t||!t.length)return r;var o=-1,i=[],a=t.length;for(e=Nn(e,n,3);++oe?0:e)):[]}function Lr(t,e,n){var r=t?t.length:0;return r?((n?Gn(t,e,n):null==e)&&(e=1),e=r-(+e||0),Ye(t,0>e?0:e)):[]}function Cr(t,e,n){return t&&t.length?en(t,Nn(e,n,3),!1,!0):[]}function Ir(t,e,n){return t&&t.length?en(t,Nn(e,n,3)):[]}function zr(t,e,n,r){var o=t?t.length:0;if(!o)return[];null!=e&&"boolean"!=typeof e&&(r=n,n=Gn(t,e,r)?E:e,e=!1);var i=Nn();return null==n&&i===be||(n=i(n,r,3)),e&&Un()==a?w(t,n):Ge(t,n)}function Fr(t){if(!t||!t.length)return[];var e=-1,n=0;t=ue(t,function(t){return Qn(t)?(n=xa(t.length,n),!0):void 0});for(var r=Ni(n);++en?xa(o+n,0):n||0,"string"==typeof t||!Mu(t)&&Uo(t)?o>=n&&t.indexOf(e,n)>-1:!!o&&Un(t,e,n)>-1}function to(t,e,n){var r=Mu(t)?le:Be;return e=Nn(e,n,3),r(t,e)}function eo(t,e){return to(t,Ci(e))}function no(t,e,n){var r=Mu(t)?ue:Ae;return e=Nn(e,n,3),r(t,function(t,n,r){return!e(t,n,r)})}function ro(t,e,n){if(n?Gn(t,e,n):null==e){t=fr(t);var r=t.length;return r>0?t[qe(0,r-1)]:E}var o=-1,i=Yo(t),r=i.length,a=r-1;for(e=Oa(0>e?0:+e||0,r);++o0&&(n=e.apply(this,arguments)),1>=t&&(e=E),n}}function ho(t,e,n){function r(){h&&ua(h),c&&ua(c),y=0,c=h=d=E}function o(e,n){n&&ua(n),c=h=d=E,e&&(y=yu(),f=t.apply(p,l),h||c||(l=p=E))}function i(){var t=e-(yu()-s);0>=t||t>e?o(d,c):h=pa(i,t)}function a(){o(g,h)}function u(){if(l=arguments,s=yu(),p=this,d=g&&(h||!m),v===!1)var n=m&&!h;else{c||m||(y=s);var r=v-(s-y),o=0>=r||r>v;o?(c&&(c=ua(c)),y=s,f=t.apply(p,l)):c||(c=pa(a,r))}return o&&h?h=ua(h):h||e===v||(h=pa(i,e)),n&&(o=!0,f=t.apply(p,l)),!o||h||c||(l=p=E),f}var l,c,f,s,p,h,d,y=0,v=!1,g=!0;if("function"!=typeof t)throw new Ji(V);if(e=0>e?0:+e||0,n===!0){var m=!0;g=!1}else Io(n)&&(m=!!n.leading,v="maxWait"in n&&xa(+n.maxWait||0,e),g="trailing"in n?!!n.trailing:g);return u.cancel=r,u}function yo(t,e){if("function"!=typeof t||e&&"function"!=typeof e)throw new Ji(V);var n=function(){var r=arguments,o=e?e.apply(this,r):r[0],i=n.cache;if(i.has(o))return i.get(o);var a=t.apply(this,r);return n.cache=i.set(o,a),a};return n.cache=new yo.Cache,n}function vo(t){if("function"!=typeof t)throw new Ji(V);return function(){return!t.apply(this,arguments)}}function go(t){return po(2,t)}function mo(t,e){if("function"!=typeof t)throw new Ji(V);return e=xa(e===E?t.length-1:+e||0,0),function(){for(var n=arguments,r=-1,o=xa(n.length-e,0),i=Ni(o);++re}function ko(t,e){return t>=e}function Eo(t){return m(t)&&Qn(t)&&ea.call(t,"callee")&&!fa.call(t,"callee")}function Ao(t){return t===!0||t===!1||m(t)&&ra.call(t)==Y}function Po(t){return m(t)&&ra.call(t)==X}function Mo(t){return!!t&&1===t.nodeType&&m(t)&&!No(t)}function To(t){return null==t?!0:Qn(t)&&(Mu(t)||Uo(t)||Eo(t)||m(t)&&Co(t.splice))?!t.length:!Wu(t).length}function So(t,e,n,r){n="function"==typeof n?an(n,r,3):E;var o=n?n(t,e):E;return o===E?Ie(t,e,n):!!o}function Ro(t){return m(t)&&"string"==typeof t.message&&ra.call(t)==J}function Lo(t){return"number"==typeof t&&ba(t)}function Co(t){return Io(t)&&ra.call(t)==Q}function Io(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function zo(t,e,n,r){return n="function"==typeof n?an(n,r,3):E,Fe(t,Vn(e),n)}function Fo(t){return Wo(t)&&t!=+t}function Bo(t){return null==t?!1:Co(t)?ia.test(ta.call(t)):m(t)&&It.test(t)}function Do(t){return null===t}function Wo(t){return"number"==typeof t||m(t)&&ra.call(t)==G}function No(t){var e;if(!m(t)||ra.call(t)!=tt||Eo(t)||!ea.call(t,"constructor")&&(e=t.constructor,"function"==typeof e&&!(e instanceof e)))return!1;var n;return Te(t,function(t,e){n=e}),n===E||ea.call(t,n)}function Ko(t){return Io(t)&&ra.call(t)==et}function Uo(t){return"string"==typeof t||m(t)&&ra.call(t)==rt}function Vo(t){return m(t)&&nr(t.length)&&!!Ut[ra.call(t)]}function $o(t){return t===E}function qo(t,e){return e>t}function Ho(t,e){return e>=t}function Yo(t){var e=t?Ka(t):0;return nr(e)?e?te(t):[]:ai(t)}function Xo(t){return _e(t,ei(t))}function Jo(t,e,n){var r=Ia(t);return n&&Gn(t,e,n)&&(e=E),e?ge(r,e):r}function Qo(t){return Le(t,ei(t))}function Zo(t,e,n){var r=null==t?E:Ce(t,pr(e),e+"");return r===E?n:r}function Go(t,e){if(null==t)return!1;var n=ea.call(t,e);if(!n&&!tr(e)){if(e=pr(e),t=1==e.length?t:Ce(t,Ye(e,0,-1)),null==t)return!1;e=Er(e),n=ea.call(t,e)}return n||nr(t.length)&&Zn(e,t.length)&&(Mu(t)||Eo(t))}function ti(t,e,n){n&&Gn(t,e,n)&&(e=E);for(var r=-1,o=Wu(t),i=o.length,a={};++r0;++r=Oa(e,n)&&tn?0:+n||0,r),n-=e.length,n>=0&&t.indexOf(e,n)==n}function hi(t){return t=l(t),t&&wt.test(t)?t.replace(_t,d):t}function di(t){return t=l(t),t&&Mt.test(t)?t.replace(Pt,y):t||"(?:)"}function yi(t,e,n){t=l(t),e=+e;var r=t.length;if(r>=e||!ba(e))return t;var o=(e-r)/2,i=ma(o),a=va(o);return n=Ln("",a,n),n.slice(0,i)+t+n}function vi(t,e,n){return(n?Gn(t,e,n):null==e)?e=0:e&&(e=+e),t=bi(t),ka(t,e||(Ct.test(t)?16:10))}function gi(t,e){var n="";if(t=l(t),e=+e,1>e||!t||!ba(e))return n;do e%2&&(n+=t),e=ma(e/2),t+=t;while(e);return n}function mi(t,e,n){return t=l(t),n=null==n?0:Oa(0>n?0:+n||0,t.length),t.lastIndexOf(e,n)==n}function _i(t,n,r){var o=e.templateSettings;r&&Gn(t,n,r)&&(n=r=E),t=l(t),n=ve(ge({},r||n),o,ye);var i,a,u=ve(ge({},n.imports),o.imports,ye),c=Wu(u),f=tn(u,c),s=0,p=n.interpolate||Bt,h="__p += '",d=Yi((n.escape||Bt).source+"|"+p.source+"|"+(p===jt?Rt:Bt).source+"|"+(n.evaluate||Bt).source+"|$","g"),y="//# sourceURL="+("sourceURL"in n?n.sourceURL:"lodash.templateSources["+ ++Kt+"]")+"\n";t.replace(d,function(e,n,r,o,u,l){return r||(r=o),h+=t.slice(s,l).replace(Dt,v),n&&(i=!0,h+="' +\n__e("+n+") +\n'"),u&&(a=!0,h+="';\n"+u+";\n__p += '"),r&&(h+="' +\n((__t = ("+r+")) == null ? '' : __t) +\n'"),s=l+e.length,e}),h+="';\n";var g=n.variable;g||(h="with (obj) {\n"+h+"\n}\n"),h=(a?h.replace(yt,""):h).replace(vt,"$1").replace(gt,"$1;"),h="function("+(g||"obj")+") {\n"+(g?"":"obj || (obj = {});\n")+"var __t, __p = ''"+(i?", __e = _.escape":"")+(a?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+h+"return __p\n}";var m=Qu(function(){return Vi(c,y+"return "+h).apply(E,f)});if(m.source=h,Ro(m))throw m;return m}function bi(t,e,n){var r=t;return(t=l(t))?(n?Gn(r,e,n):null==e)?t.slice(x(t),O(t)+1):(e+="",t.slice(c(t,e),f(t,e)+1)):t}function wi(t,e,n){var r=t;return t=l(t),t?(n?Gn(r,e,n):null==e)?t.slice(x(t)):t.slice(c(t,e+"")):t}function xi(t,e,n){var r=t;return t=l(t),t?(n?Gn(r,e,n):null==e)?t.slice(0,O(t)+1):t.slice(0,f(t,e+"")+1):t}function Oi(t,e,n){n&&Gn(t,e,n)&&(e=E);var r=F,o=B;if(null!=e)if(Io(e)){var i="separator"in e?e.separator:i;r="length"in e?+e.length||0:r,o="omission"in e?l(e.omission):o}else r=+e||0;if(t=l(t),r>=t.length)return t;var a=r-o.length;if(1>a)return o;var u=t.slice(0,a);if(null==i)return u+o;if(Ko(i)){if(t.slice(a).search(i)){var c,f,s=t.slice(0,a);for(i.global||(i=Yi(i.source,(Lt.exec(i)||"")+"g")),i.lastIndex=0;c=i.exec(s);)f=c.index;u=u.slice(0,null==f?a:f)}}else if(t.indexOf(i,a)!=a){var p=u.lastIndexOf(i);p>-1&&(u=u.slice(0,p))}return u+o}function ji(t){return t=l(t),t&&bt.test(t)?t.replace(mt,j):t}function ki(t,e,n){return n&&Gn(t,e,n)&&(e=E),t=l(t),t.match(e||Wt)||[]}function Ei(t,e,n){return n&&Gn(t,e,n)&&(e=E),m(t)?Mi(t):be(t,e)}function Ai(t){return function(){return t}}function Pi(t){return t}function Mi(t){return De(we(t,!0))}function Ti(t,e){return We(t,we(e,!0))}function Si(t,e,n){if(null==n){var r=Io(e),o=r?Wu(e):E,i=o&&o.length?Le(e,o):E;(i?i.length:r)||(i=!1,n=e,e=t,t=this)}i||(i=Le(e,Wu(e)));var a=!0,u=-1,l=Co(t),c=i.length;n===!1?a=!1:Io(n)&&"chain"in n&&(a=n.chain);for(;++ut||!ba(t))return[];var r=-1,o=Ni(Oa(t,Ma));for(e=an(e,n,1);++rr?o[r]=e(r):e(r);return o}function Bi(t){var e=++na;return l(t)+e}function Di(t,e){return(+t||0)+(+e||0)}function Wi(t,e,n){return n&&Gn(t,e,n)&&(e=E),e=Nn(e,n,3),1==e.length?he(Mu(t)?t:fr(t),e):Ze(t,e)}t=t?oe.defaults(re.Object(),t,oe.pick(re,Nt)):re;var Ni=t.Array,Ki=t.Date,Ui=t.Error,Vi=t.Function,$i=t.Math,qi=t.Number,Hi=t.Object,Yi=t.RegExp,Xi=t.String,Ji=t.TypeError,Qi=Ni.prototype,Zi=Hi.prototype,Gi=Xi.prototype,ta=Vi.prototype.toString,ea=Zi.hasOwnProperty,na=0,ra=Zi.toString,oa=re._,ia=Yi("^"+ta.call(ea).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),aa=t.ArrayBuffer,ua=t.clearTimeout,la=t.parseFloat,ca=$i.pow,fa=Zi.propertyIsEnumerable,sa=$n(t,"Set"),pa=t.setTimeout,ha=Qi.splice,da=t.Uint8Array,ya=$n(t,"WeakMap"),va=$i.ceil,ga=$n(Hi,"create"),ma=$i.floor,_a=$n(Ni,"isArray"),ba=t.isFinite,wa=$n(Hi,"keys"),xa=$i.max,Oa=$i.min,ja=$n(Ki,"now"),ka=t.parseInt,Ea=$i.random,Aa=qi.NEGATIVE_INFINITY,Pa=qi.POSITIVE_INFINITY,Ma=4294967295,Ta=Ma-1,Sa=Ma>>>1,Ra=9007199254740991,La=ya&&new ya,Ca={};e.support={};e.templateSettings={escape:xt,evaluate:Ot,interpolate:jt,variable:"",imports:{_:e}};var Ia=function(){function t(){}return function(e){if(Io(e)){t.prototype=e;var n=new t;t.prototype=E}return n||{}}}(),za=pn(Se),Fa=pn(Re,!0),Ba=hn(),Da=hn(!0),Wa=La?function(t,e){return La.set(t,e),t}:Pi,Na=La?function(t){return La.get(t)}:Li,Ka=Ue("length"),Ua=function(){var t=0,e=0;return function(n,r){var o=yu(),i=W-(o-e);if(e=o,i>0){if(++t>=D)return n}else t=0;return Wa(n,r)}}(),Va=mo(function(t,e){return m(t)&&Qn(t)?Oe(t,Me(e,!1,!0)):[]}),$a=xn(),qa=xn(!0),Ha=mo(function(t){for(var e=t.length,n=e,r=Ni(s),o=Un(),i=o==a,u=[];n--;){var l=t[n]=Qn(l=t[n])?l:[];r[n]=i&&l.length>=120?yn(n&&l):null}var c=t[0],f=-1,s=c?c.length:0,p=r[0];t:for(;++f2?t[e-2]:E,r=e>1?t[e-1]:E;return e>2&&"function"==typeof n?e-=2:(n=e>1&&"function"==typeof r?(--e,r):E,r=E),t.length=e,Br(t,n,r)}),eu=mo(function(t){return t=Me(t),this.thru(function(e){return Gt(Mu(e)?e:[sr(e)],t)})}),nu=mo(function(t,e){return me(t,Me(e))}),ru=fn(function(t,e,n){ea.call(t,n)?++t[n]:t[n]=1}),ou=wn(za),iu=wn(Fa,!0),au=kn(ee,za),uu=kn(ne,Fa),lu=fn(function(t,e,n){ea.call(t,n)?t[n].push(e):t[n]=[e]}),cu=fn(function(t,e,n){t[n]=e}),fu=mo(function(t,e,n){var r=-1,o="function"==typeof e,i=tr(e),a=Qn(t)?Ni(t.length):[];return za(t,function(t){var u=o?e:i&&null!=t?t[e]:E;a[++r]=u?u.apply(t,n):Jn(t,e,n)}),a}),su=fn(function(t,e,n){t[n?0:1].push(e)},function(){return[[],[]]}),pu=Sn(fe,za),hu=Sn(se,Fa),du=mo(function(t,e){if(null==t)return[];var n=e[2];return n&&Gn(e[0],e[1],n)&&(e.length=1),Qe(t,Me(e),[])}),yu=ja||function(){return(new Ki).getTime()},vu=mo(function(t,e,n){var r=P;if(n.length){var o=b(n,vu.placeholder);r|=L}return Fn(t,r,e,n,o)}),gu=mo(function(t,e){e=e.length?Me(e):Qo(t);for(var n=-1,r=e.length;++n0||0>e)?new _(n):(0>t?n=n.takeRight(-t):t&&(n=n.drop(t)),e!==E&&(e=+e||0,n=0>e?n.dropRight(-e):n.take(e-t)),n)},_.prototype.takeRightWhile=function(t,e){return this.reverse().takeWhile(t,e).reverse()},_.prototype.toArray=function(){return this.take(Pa)},Se(_.prototype,function(t,n){var o=/^(?:filter|map|reject)|While$/.test(n),i=/^(?:first|last)$/.test(n),a=e[i?"take"+("last"==n?"Right":""):n];a&&(e.prototype[n]=function(){var e=i?[1]:arguments,n=this.__chain__,u=this.__wrapped__,l=!!this.__actions__.length,c=u instanceof _,f=e[0],s=c||Mu(u);s&&o&&"function"==typeof f&&1!=f.length&&(c=s=!1);var p=function(t){return i&&n?a(t,1)[0]:a.apply(E,ce([t],e))},h={func:Ur,args:[p],thisArg:E},d=c&&!l;if(i&&!n)return d?(u=u.clone(),u.__actions__.push(h),t.call(u)):a.call(E,this.value())[0];if(!i&&s){u=d?u:new _(this);var y=t.apply(u,e);return y.__actions__.push(h),new r(y,n)}return this.thru(p)})}),ee(["join","pop","push","replace","shift","sort","splice","split","unshift"],function(t){var n=(/^(?:replace|split)$/.test(t)?Gi:Qi)[t],r=/^(?:push|sort|unshift)$/.test(t)?"tap":"thru",o=/^(?:join|pop|replace|shift)$/.test(t);e.prototype[t]=function(){var t=arguments;return o&&!this.__chain__?n.apply(this.value(),t):this[r](function(e){return n.apply(e,t)})}}),Se(_.prototype,function(t,n){var r=e[n];if(r){var o=r.name,i=Ca[o]||(Ca[o]=[]);i.push({name:n,func:r})}}),Ca[Rn(E,M).name]=[{name:"wrapper",func:E}],_.prototype.clone=Z,_.prototype.reverse=nt,_.prototype.value=ot,e.prototype.chain=Vr,e.prototype.commit=$r,e.prototype.concat=eu,e.prototype.plant=qr,e.prototype.reverse=Hr,e.prototype.toString=Yr,e.prototype.run=e.prototype.toJSON=e.prototype.valueOf=e.prototype.value=Xr,e.prototype.collect=e.prototype.map,e.prototype.head=e.prototype.first,e.prototype.select=e.prototype.filter,e.prototype.tail=e.prototype.rest,e}var E,A="3.10.1",P=1,M=2,T=4,S=8,R=16,L=32,C=64,I=128,z=256,F=30,B="...",D=150,W=16,N=200,K=1,U=2,V="Expected a function",$="__lodash_placeholder__",q="[object Arguments]",H="[object Array]",Y="[object Boolean]",X="[object Date]",J="[object Error]",Q="[object Function]",Z="[object Map]",G="[object Number]",tt="[object Object]",et="[object RegExp]",nt="[object Set]",rt="[object String]",ot="[object WeakMap]",it="[object ArrayBuffer]",at="[object Float32Array]",ut="[object Float64Array]",lt="[object Int8Array]",ct="[object Int16Array]",ft="[object Int32Array]",st="[object Uint8Array]",pt="[object Uint8ClampedArray]",ht="[object Uint16Array]",dt="[object Uint32Array]",yt=/\b__p \+= '';/g,vt=/\b(__p \+=) '' \+/g,gt=/(__e\(.*?\)|\b__t\)) \+\n'';/g,mt=/&(?:amp|lt|gt|quot|#39|#96);/g,_t=/[&<>"'`]/g,bt=RegExp(mt.source),wt=RegExp(_t.source),xt=/<%-([\s\S]+?)%>/g,Ot=/<%([\s\S]+?)%>/g,jt=/<%=([\s\S]+?)%>/g,kt=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,Et=/^\w*$/,At=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g,Pt=/^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,Mt=RegExp(Pt.source),Tt=/[\u0300-\u036f\ufe20-\ufe23]/g,St=/\\(\\)?/g,Rt=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,Lt=/\w*$/,Ct=/^0[xX]/,It=/^\[object .+?Constructor\]$/,zt=/^\d+$/,Ft=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,Bt=/($^)/,Dt=/['\n\r\u2028\u2029\\]/g,Wt=function(){var t="[A-Z\\xc0-\\xd6\\xd8-\\xde]",e="[a-z\\xdf-\\xf6\\xf8-\\xff]+";return RegExp(t+"+(?="+t+e+")|"+t+"?"+e+"|"+t+"+|[0-9]+","g")}(),Nt=["Array","ArrayBuffer","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Math","Number","Object","RegExp","Set","String","_","clearTimeout","isFinite","parseFloat","parseInt","setTimeout","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap"],Kt=-1,Ut={};Ut[at]=Ut[ut]=Ut[lt]=Ut[ct]=Ut[ft]=Ut[st]=Ut[pt]=Ut[ht]=Ut[dt]=!0,Ut[q]=Ut[H]=Ut[it]=Ut[Y]=Ut[X]=Ut[J]=Ut[Q]=Ut[Z]=Ut[G]=Ut[tt]=Ut[et]=Ut[nt]=Ut[rt]=Ut[ot]=!1;var Vt={};Vt[q]=Vt[H]=Vt[it]=Vt[Y]=Vt[X]=Vt[at]=Vt[ut]=Vt[lt]=Vt[ct]=Vt[ft]=Vt[G]=Vt[tt]=Vt[et]=Vt[rt]=Vt[st]=Vt[pt]=Vt[ht]=Vt[dt]=!0,Vt[J]=Vt[Q]=Vt[Z]=Vt[nt]=Vt[ot]=!1;var $t={"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss"},qt={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Ht={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Yt={"function":!0,object:!0},Xt={0:"x30",1:"x31",2:"x32",3:"x33",4:"x34",5:"x35",6:"x36",7:"x37",8:"x38",9:"x39",A:"x41",B:"x42",C:"x43",D:"x44",E:"x45",F:"x46",a:"x61",b:"x62",c:"x63",d:"x64",e:"x65",f:"x66",n:"x6e",r:"x72",t:"x74",u:"x75",v:"x76",x:"x78"},Jt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Qt=Yt[typeof r]&&r&&!r.nodeType&&r,Zt=Yt[typeof n]&&n&&!n.nodeType&&n,Gt=Qt&&Zt&&"object"==typeof e&&e&&e.Object&&e,te=Yt[typeof self]&&self&&self.Object&&self,ee=Yt[typeof window]&&window&&window.Object&&window,ne=Zt&&Zt.exports===Qt&&Qt,re=Gt||ee!==(this&&this.window)&&ee||te||this,oe=k();"function"==typeof t&&"object"==typeof t.amd&&t.amd?(re._=oe,t(function(){return oe})):Qt&&Zt?ne?(Zt.exports=oe)._=oe:Qt._=oe:re._=oe}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],2:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./ops")),o=e("./linear"),i=e("./rectangle");n.exports=function(){return function(t){var e,n,a,u,l,c,f,s,p,h,d,y,v,g,m,_,b,w,x,O,j,k,E,A,P,M,T,S,R,L,C,I,z,F;for(c=t.data,e=t.accessor,F=t.width,y=t.height,d=t.gutter,a=t.compute,null==e&&(e=function(t){return t}),null==d&&(d=0),h=[],P=0,A=0,v=m=0,w=c.length;w>m;v=++m)for(l=c[v],g=_=0,x=l.length;x>_;g=++_)f=l[g],I=e(f),P>I&&(P=I),I>A&&(A=I),null==h[g]&&(h[g]=[]),h[g][v]=I;for(M=h.length,p=(F-d*(M-1))/M,u=[],R=o([P,A],[y,0]),v=E=0,O=h.length;O>E;v=++E)for(s=h[v],z=p/s.length,L=(p+d)*v,g=T=0,j=s.length;j>T;g=++T)f=s[g],b=L+z*g,S=b+z,n=R(0),C=R(f),k=i({left:b,right:S,bottom:n,top:C}),u.push(r.enhance(a,{item:c[g][v],line:k,index:g}));return{curves:u,scale:R}}}.call(this)}).call(this)},{"./linear":6,"./ops":7,"./rectangle":12}],3:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./path")),o=e("./ops");n.exports=function(){var t;return t=function(t,e){return o.minus(o.times(2,t),e)},function(e){var n,i,a,u,l,c,f,s,p,h,d,y,v,g,m,_,b;for(y=e.points,b=e.tension,null==b&&(b=.3),u=[],s=y.length,l=c=1,v=s-1;v>=1?v>=c:c>=v;l=v>=1?++c:--c)u.push(o.times(b,o.minus(y[l],y[l-1])));for(a=[o.plus(y[0],t(u[0],u[1]))],l=f=1,g=s-2;g>=1?g>=f:f>=g;l=g>=1?++f:--f)a.push(o.minus(y[l],o.average([u[l],u[l-1]])));return a.push(o.minus(y[s-1],t(u[s-2],u[s-3]))),n=a[0],i=a[1],p=y[0],h=y[1],d=(m=r()).moveto.apply(m,p).curveto(n[0],n[1],i[0],i[1],h[0],h[1]),{path:function(){_=[];for(var t=2,e=s-1;e>=2?e>=t:t>=e;e>=2?t++:t--)_.push(t);return _}.apply(this).reduce(function(t,e){var n,r;return n=a[e],r=y[e],t.smoothcurveto(n[0],n[1],r[0],r[1])},d),centroid:o.average(y)}}}.call(this)}).call(this)},{"./ops":7,"./path":8}],4:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./path")),o=e("./ops");n.exports=function(){return function(t){var e,n,i,a,u,l,c,f,s,p,h,d,y;return d=t.start,u=t.end,y=t.tension,null==y&&(y=.05),e=d[0],n=d[1],i=u[0],a=u[1],l=(i-e)*y,c=[e+l,n],f=[i-l,a],{path:(s=(p=(h=r()).moveto.apply(h,d)).lineto.apply(p,c).curveto(e+5*l,n,i-5*l,a,i-l,a)).lineto.apply(s,u),centroid:o.average([d,u])}}}.call(this)}).call(this)},{"./ops":7,"./path":8}],5:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./linear")),o=e("./ops");n.exports=function(){var t,e;return e=1e-5,t=function(t,n){var r,i,a,u,l,c,f,s,p;return a=function(){var e,o,i;for(i=[],e=0,o=t.length;o>e;e++)r=t[e],i.push(n(r));return i}(),u=a.sort(function(t,e){var n,r,o,i;return n=t[0],r=t[1],o=e[0],i=e[1],n-o}),f=u.map(function(t){return t[1]}),i=u.length,c=u[0][0],l=u[i-1][0],p=o.min(f),s=o.max(f),c===l&&(l+=e),p===s&&(s+=e),{points:u,xmin:c,xmax:l,ymin:p,ymax:s}},function(e){var n,i,a,u,l,c,f,s,p,h,d,y,v,g,m,_,b;return u=e.data,h=e.xaccessor,g=e.yaccessor,p=e.width,f=e.height,a=e.closed,null==h&&(h=function(t){var e,n;return e=t[0],n=t[1],e}),null==g&&(g=function(t){var e,n;return e=t[0],n=t[1]}),c=function(t){return[h(t),g(t)]},n=function(){var e,n,r;for(r=[],e=0,n=u.length;n>e;e++)l=u[e],r.push(t(l,c));return r}(),y=o.min(n.map(function(t){return t.xmin})),d=o.max(n.map(function(t){return t.xmax})),_=o.min(n.map(function(t){return t.ymin})),m=o.max(n.map(function(t){return t.ymax})),a&&(_=Math.min(_,0),m=Math.max(m,0)),i=a?0:_,v=r([y,d],[0,p]),b=r([_,m],[f,0]),s=function(t){var e,n;return e=t[0],n=t[1],[v(e),b(n)]},{arranged:n,scale:s,xscale:v,yscale:b,base:i}}}.call(this)}).call(this)},{"./linear":6,"./ops":7}],6:[function(e,n,r){(function(){!("function"!=typeof t||!t.amd);n.exports=function(){var t;return t=function(e,n){var r,o,i,a,u;return r=e[0],o=e[1],i=n[0],a=n[1],u=function(t){return i+(a-i)*(t-r)/(o-r)},u.inverse=function(){return t([i,a],[r,o])},u}}.call(this)}).call(this)},{}],7:[function(e,n,r){(function(){!("function"!=typeof t||!t.amd);n.exports=function(){var t,e,n,r,o,i,a,u,l,c,f;return l=function(t){return t.reduce(function(t,e){return t+e},0)},o=function(t){return t.reduce(function(t,e){return Math.min(t,e)})},r=function(t){return t.reduce(function(t,e){return Math.max(t,e)})},u=function(t,e){var n,r,o,i;return n=t[0],r=t[1],o=e[0],i=e[1],[n+o,r+i]},i=function(t,e){var n,r,o,i;return n=t[0],r=t[1],o=e[0],i=e[1],[n-o,r-i]},f=function(t,e){var n,r;return n=e[0],r=e[1],[t*n,t*r]},n=function(t){var e,n;return e=t[0],n=t[1],Math.sqrt(e*e+n*n)},c=function(t){return t.reduce(function(t,e){return u(t,e)},[0,0])},t=function(t){return f(1/t.length,t.reduce(u))},a=function(t,e){return f(t,[Math.sin(e),-Math.cos(e)])},e=function(t,e){var n,r,o;o=t||{};for(n in o)r=o[n],e[n]=r(e.index,e.item,e.group);return e},{sum:l,min:o,max:r,plus:u,minus:i,times:f,length:n,sum_vectors:c,average:t,on_circle:a,enhance:e}}.call(this)}).call(this)},{}],8:[function(e,n,r){(function(){!("function"!=typeof t||!t.amd);n.exports=function(){var t;return t=function(e){var n,r,o,i,a,u,l,c,f;return r=e||[],u=function(t,e){var n;return n=t.slice(0,t.length),n.push(e),n},n=function(t,e){return t[0]===e[0]&&t[1]===e[1]},c=function(t,e){var n;for(n=t.length;"0"===t.charAt(n-1);)n-=1;return"."===t.charAt(n-1)&&(n-=1),t.substr(0,n)},l=function(t,e){var n;return n=t.toFixed(e),c(n)},a=function(t){var e,n,r,o;return e=t.command,o=t.params,n=function(){var t,e,n;for(n=[],t=0,e=o.length;e>t;t++)r=o[t],n.push(l(r,6));return n}(),e+" "+n.join(" ")},i=function(t,e){var n,r,o,i;switch(n=t.command,r=t.params,o=e[0],i=e[1],n){case"M":return[r[0],r[1]];case"L":return[r[0],r[1]];case"H":return[r[0],i];case"V":return[o,r[0]];case"Z":return null;case"C":return[r[4],r[5]];case"S":return[r[2],r[3]];case"Q":return[r[2],r[3]];case"T":return[r[0],r[1]];case"A":return[r[5],r[6]]}},f=function(t,e){return function(n){var r;return r="object"==typeof n?t.map(function(t){return n[t]}):arguments,e.apply(null,r)}},o=function(e){return t(u(r,e))},{moveto:f(["x","y"],function(t,e){return o({command:"M",params:[t,e]})}),lineto:f(["x","y"],function(t,e){return o({command:"L",params:[t,e]})}),hlineto:f(["x"],function(t){return o({command:"H",params:[t]})}),vlineto:f(["y"],function(t){return o({command:"V",params:[t]})}),closepath:function(){return o({command:"Z",params:[]})},curveto:f(["x1","y1","x2","y2","x","y"],function(t,e,n,r,i,a){return o({command:"C",params:[t,e,n,r,i,a]})}),smoothcurveto:f(["x2","y2","x","y"],function(t,e,n,r){return o({command:"S",params:[t,e,n,r]})}),qcurveto:f(["x1","y1","x","y"],function(t,e,n,r){return o({command:"Q",params:[t,e,n,r]})}),smoothqcurveto:f(["x","y"],function(t,e){return o({command:"T",params:[t,e]})}),arc:f(["rx","ry","xrot","large_arc_flag","sweep_flag","x","y"],function(t,e,n,r,i,a,u){return o({command:"A",params:[t,e,n,r,i,a,u]})}),print:function(){return r.map(a).join(" ")},points:function(){var t,e,n,o,a,u;for(u=[],a=[0,0],t=function(){var t;return t=i(n,a),a=t,t?u.push(t):void 0},e=0,o=r.length;o>e;e++)n=r[e],t();return u},instructions:function(){return r.slice(0,r.length)},connect:function(e){var r,o,i;return o=this.points().slice(-1)[0],r=e.points()[0],i=e.instructions().slice(1),n(o,r)||i.unshift({command:"L",params:r}),t(this.instructions().concat(i))}}},function(){return t()}}.call(this)}).call(this)},{}],9:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./linear")),o=e("./ops"),i=e("./sector");n.exports=function(){return function(t){var e,n,a,u,l,c,f,s,p,h,d,y,v,g,m,_;for(c=t.data,n=t.accessor,a=t.center,d=t.r,e=t.R,u=t.compute,_=function(){var t,e,r;for(r=[],t=0,e=c.length;e>t;t++)s=c[t],r.push(n(s));return r}(),y=o.sum(_),v=r([0,y],[0,2*Math.PI]),l=[],g=0,f=p=0,h=c.length;h>p;f=++p)s=c[f],m=_[f],l.push(o.enhance(u,{item:s,index:f,sector:i({center:a,r:d,R:e,start:v(g),end:v(g+m)})})),g+=m;return{curves:l}}}.call(this)}).call(this)},{"./linear":6,"./ops":7,"./sector":13}],10:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./path")),o=e("./ops");n.exports=function(){return function(t){var e,n,i,a,u,l,c;return u=t.points,e=t.closed,i=u.length,n=u[0],c=u.slice(1,+i+1||9e9),a=c.reduce(function(t,e){return t.lineto.apply(t,e)},(l=r()).moveto.apply(l,n)),{path:e?a.closepath():a,centroid:o.average(u)}}}.call(this)}).call(this)},{"./ops":7,"./path":8}],11:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./semi-regular-polygon")),o=e("./ops");n.exports=function(){var t,e,n;return t=function(t){var e,n,r,o,i,a,u,l,c,f;for(r=[],o=function(){var e,n,r;for(r=[],e=0,n=t.length;n>e;e++)l=t[e],r.push(Object.keys(l));return r}(),e=0,a=t.length;a>e;e++)for(c=t[e],f=Object.keys(c),i=0,u=f.length;u>i;i++)n=f[i],-1===r.indexOf(n)&&r.push(n);return r},n=function(t){var e,n,r,o,i;for(e={},n=function(t){return e[t]=function(e){return e[t]}},r=0,i=t.length;i>r;r++)o=t[r],n(o);return e},e=function(t,e){var n,r;return n=Object.keys(e),r=t.map(function(t){var r;return r=n.map(function(n){return e[n](t)}),o.max(r)}),o.max(r)},function(i){var a,u,l,c,f,s,p,h,d,y,v,g,m,_;return f=i.data,a=i.accessor,l=i.center,y=i.r,h=i.max,m=i.rings,c=i.compute,null==m&&(m=3),null==a&&(a=n(t(f))),p=Object.keys(a),_=p.length,u=2*Math.PI/_,s=-1,null==h&&(h=e(f,a)),g=function(){v=[];for(var t=1;m>=1?m>=t:t>=m;m>=1?t++:t--)v.push(t);return v}.apply(this).map(function(t){var e,n;return e=y*t/m,r({center:l,radii:function(){n=[];for(var t=0,e=_-1;e>=0?e>=t:t>=e;e>=0?t++:t--)n.push(t);return n}.apply(this).map(function(t){return e})})}),d=f.map(function(t){return s+=1,o.enhance(c,{polygon:r({center:l,radii:p.map(function(e){return y*a[e](t)/h})}),item:t,index:s})}),{curves:d,rings:g}}}.call(this)}).call(this)},{"./ops":7,"./semi-regular-polygon":14}],12:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./polygon"));n.exports=function(){return function(t){var e,n,o,i;return n=t.left,o=t.right,i=t.top,e=t.bottom,r({points:[[o,i],[o,e],[n,e],[n,i]],closed:!0})}}.call(this)}).call(this)},{"./polygon":10}],13:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),[].slice),o=e("./path"),i=e("./ops");n.exports=function(){return function(t){var e,n,a,u,l,c,f,s,p,h,d,y,v,g,m,_,b,w;return l=t.center,v=t.r,e=t.R,w=t.start,s=t.end,n=i.plus(l,i.on_circle(e,w)),a=i.plus(l,i.on_circle(e,s)),u=i.plus(l,i.on_circle(v,s)),f=i.plus(l,i.on_circle(v,w)),p=s-w>Math.PI?1:0,y=(g=(m=(_=(b=o()).moveto.apply(b,n)).arc.apply(_,[e,e,0,p,1].concat(r.call(a)))).lineto.apply(m,u)).arc.apply(g,[v,v,0,p,0].concat(r.call(f))).closepath(),h=(w+s)/2,d=(v+e)/2,c=i.plus(l,i.on_circle(d,h)),{path:y,centroid:c}}}.call(this)}).call(this)},{"./ops":7,"./path":8}],14:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./polygon")),o=e("./ops");n.exports=function(){return function(t){var e,n,i,a;return n=t.center,a=t.radii,e=2*Math.PI/a.length,i=a.map(function(t,r){return o.plus(n,o.on_circle(t,r*e))}),r({points:i,closed:!0})}}.call(this)}).call(this)},{"./ops":7,"./polygon":10}],15:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./bezier")),o=e("./ops"),i=e("./line-chart-comp");n.exports=function(){return function(t){var e,n,a,u,l,c,f,s;return l=i(t),e=l.arranged,c=l.scale,f=l.xscale,s=l.yscale,n=l.base,a=-1,u=e.map(function(e){var i,u,l,f,s,p,h,d;return l=e.points,d=e.xmin,h=e.xmax,p=l.map(c),a+=1,u=r({points:p}),i={path:(f=(s=u.path).lineto.apply(s,c([h,n]))).lineto.apply(f,c([d,n])).closepath(),centroid:o.average([u.centroid,c([d,n]),c([h,n])])},o.enhance(t.compute,{item:t.data[a],line:u,area:i,index:a})}),{curves:u,xscale:f,yscale:s}}}.call(this)}).call(this)},{"./bezier":3,"./line-chart-comp":5,"./ops":7}],16:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./polygon")),o=e("./line-chart-comp"),i=e("./ops");n.exports=function(){return function(t){var e,n,a,u,l,c,f,s;return l=o(t),e=l.arranged,c=l.scale,f=l.xscale,s=l.yscale,n=l.base,a=-1,u=e.map(function(e){var o,u,l,f,s;return o=e.points,s=e.xmin,f=e.xmax,u=o.map(c),o.push([f,n]),o.push([s,n]),l=o.map(c),a+=1,i.enhance(t.compute,{item:t.data[a],line:r({points:u,closed:!1}),area:r({points:l,closed:!0}),index:a})}),{curves:u,xscale:f,yscale:s}}}.call(this)}).call(this)},{"./line-chart-comp":5,"./ops":7,"./polygon":10}],17:[function(e,n,r){(function(){var r=(!("function"!=typeof t||!t.amd),e("./connector")),o=e("./linear"),i=e("./tree_utils");n.exports=function(){ 3 | return function(t){var e,n,a,u,l,c,f,s,p,h,d,y,v,g,m,_,b;return u=t.data,b=t.width,l=t.height,n=t.children,g=t.tension,null==n&&(n=function(t){return t.children}),m=i.build_tree(u,n),p=i.tree_height(m),h=i.set_height(m),f=b/(p-1),c=o([0,p-1],[0,b]),_=function(){y=[];for(var t=0,e=p-1;e>=0?e>=t:t>=e;e>=0?t++:t--)y.push(t);return y}.apply(this).map(function(t){var e,n,r,i;return e=Math.sqrt(t/(p-1))*l,i=(l-e)/2,n=i+e,r=t>0?h[t]+h[t-1]:h[t],0===r?function(t){return l/2}:o([0,r],[i,n])}),d=function(t){var e,n;return e=t.level,n=_[e],[c(e),n(t.height_)]},s=-1,a=i.collect(m,function(t,e){return s+=1,e.height_=e.height+t.height,{connector:r({start:d(t),end:d(e),tension:g}),index:s,item:{start:t.item,end:e.item}}}),e=i.collect(m,function(t,e){return{point:d(e),item:e.item}}),v={point:d(m),item:m.item},{curves:a,nodes:[v].concat(e)}}}.call(this)}).call(this)},{"./connector":4,"./linear":6,"./tree_utils":18}],18:[function(e,n,r){(function(){!("function"!=typeof t||!t.amd);n.exports=function(){var t,e,n,r,o;return n=function(t,e){return null==t&&(t=[]),t.reduce(function(t,n){return Math.max(t,e(n))},0)},o=function(t){return 1+n(t.children,o)},t=function(e,n,r){var o,i;return null==r&&(r=0),i={item:e,level:r},o=n(e),o&&o.length&&(i.children=o.map(function(e){return t(e,n,r+1)})),i},r=function(t,e,n){var o,i,a,u;for(null==n&&(n=[]),null==e&&(e=0),null!=n[e]?(t.height=n[e]+1,n[e]+=1):(n[e]=0,t.height=0),u=t.children||[],i=0,a=u.length;a>i;i++)o=u[i],r(o,e+1,n);return n},e=function(t,n){var r,o,i,a,u;for(u=[],a=t.children||[],o=0,i=a.length;i>o;o++)r=a[o],u.push(n(t,r)),u=u.concat(e(r,n));return u},{tree_height:o,build_tree:t,set_height:r,collect:e}}.call(this)}).call(this)},{}],19:[function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(n,"__esModule",{value:!0});var o=t("lodash"),i=r(o),a=t("./charts/Pie.js"),u=r(a),l=t("./charts/Tree.js"),c=r(l),f=t("./charts/Radar.js"),s=r(f),p=t("./charts/Bar.js"),h=r(p),d=t("./charts/SmoothLine.js"),y=r(d),v=t("./charts/StockLine.js"),g=r(v),m=t("./charts/Scatterplot.js"),_=r(m);n["default"]={Pie:i["default"].extend(u["default"],{metaData:{settings:{fields:{data:{type:"plainJsonEditor"},accessorKey:{type:"string"},options:{fields:{width:{type:"number"},height:{type:"number"},margin:{type:"boxSizeEditor"},r:{type:"number"},R:{type:"number"},color:{type:"colorPicker"},legendPosition:{type:"select",settings:{options:["topLeft","topRight","bottomLeft","bottomRight"]}},label:{type:"fontEditor"},animate:{fields:{type:{type:"select",settings:{options:["delayed","async","oneByOne"]}},duration:{type:"number"},fillTransition:{type:"number"}}}}}}}}}),Tree:i["default"].extend(c["default"],{metaData:{settings:{fields:{data:{type:"plainJsonEditor"},options:{fields:{width:{type:"number"},height:{type:"number"},margin:{type:"boxSizeEditor"},r:{type:"number"},fill:{type:"colorPicker"},stroke:{type:"colorPicker"},label:{type:"fontEditor"},animate:{fields:{type:{type:"select",settings:{options:["delayed","async","oneByOne"]}},duration:{type:"number"},fillTransition:{type:"number"}}}}}}}}}),SmoothLine:i["default"].extend(y["default"],{metaData:{settings:{fields:{data:{type:"plainJsonEditor"},xKey:{type:"string"},yKey:{type:"string"},options:{fields:{width:{type:"number"},height:{type:"number"},margin:{type:"boxSizeEditor"},color:{type:"colorPicker"},animate:{fields:{type:{type:"select",settings:{options:["delayed","async","oneByOne"]}},duration:{type:"number"},fillTransition:{type:"number"}}},axisY:{fields:{orient:{type:"select",settings:{options:["left","right"]}},label:{type:"fontEditor"},showAxis:{type:"boolean"},showLines:{type:"boolean"},showLabels:{type:"boolean"},showTicks:{type:"boolean"},zeroAxis:{type:"boolean"}}},axisX:{fields:{orient:{type:"select",settings:{options:["top","bottom"]}},label:{type:"fontEditor"},showAxis:{type:"boolean"},showLines:{type:"boolean"},showLabels:{type:"boolean"},showTicks:{type:"boolean"},zeroAxis:{type:"boolean"}}}}}}}}}),StockLine:i["default"].extend(g["default"],{metaData:{settings:{fields:{data:{type:"plainJsonEditor"},xKey:{type:"string"},yKey:{type:"string"},options:{fields:{width:{type:"number"},height:{type:"number"},margin:{type:"boxSizeEditor"},color:{type:"colorPicker"},animate:{fields:{type:{type:"select",settings:{options:["delayed","async","oneByOne"]}},duration:{type:"number"},fillTransition:{type:"number"}}},axisY:{fields:{orient:{type:"select",settings:{options:["left","right"]}},label:{type:"fontEditor"},showAxis:{type:"boolean"},showLines:{type:"boolean"},showLabels:{type:"boolean"},showTicks:{type:"boolean"},zeroAxis:{type:"boolean"}}},axisX:{fields:{orient:{type:"select",settings:{options:["top","bottom"]}},label:{type:"fontEditor"},showAxis:{type:"boolean"},showLines:{type:"boolean"},showLabels:{type:"boolean"},showTicks:{type:"boolean"},zeroAxis:{type:"boolean"}}}}}}}}}),Radar:i["default"].extend(s["default"],{metaData:{settings:{fields:{data:{type:"plainJsonEditor"},options:{fields:{width:{type:"number"},height:{type:"number"},margin:{type:"boxSizeEditor"},r:{type:"number"},max:{type:"number"},fill:{type:"colorPicker"},stroke:{type:"colorPicker"},label:{type:"fontEditor"},animate:{fields:{type:{type:"select",settings:{options:["delayed","async","oneByOne"]}},duration:{type:"number"},fillTransition:{type:"number"}}}}}}}}}),Bar:i["default"].extend(h["default"],{metaData:{settings:{fields:{data:{type:"plainJsonEditor"},accessorKey:{type:"string"},options:{fields:{width:{type:"number"},height:{type:"number"},margin:{type:"boxSizeEditor"},gutter:{type:"number"},color:{type:"colorPicker"},animate:{fields:{type:{type:"select",settings:{options:["delayed","async","oneByOne"]}},duration:{type:"number"},fillTransition:{type:"number"}}},axisY:{fields:{orient:{type:"select",settings:{options:["left","right"]}},label:{type:"fontEditor"},showAxis:{type:"boolean"},showLines:{type:"boolean"},showLabels:{type:"boolean"},showTicks:{type:"boolean"},zeroAxis:{type:"boolean"}}},axisX:{fields:{orient:{type:"select",settings:{options:["top","bottom"]}},label:{type:"fontEditor"},showAxis:{type:"boolean"},showLines:{type:"boolean"},showLabels:{type:"boolean"},showTicks:{type:"boolean"},zeroAxis:{type:"boolean"}}}}}}}}}),Scatterplot:i["default"].extend(_["default"],{metaData:{settings:{fields:{data:{type:"plainJsonEditor"},xKey:{type:"string"},yKey:{type:"string"},options:{fields:{width:{type:"number"},height:{type:"number"},margin:{type:"boxSizeEditor"},fill:{type:"colorPicker"},stroke:{type:"colorPicker"},label:{type:"fontEditor"},animate:{fields:{type:{type:"select",settings:{options:["delayed","async","oneByOne"]}},duration:{type:"number"},fillTransition:{type:"number"}}},axisY:{fields:{orient:{type:"select",settings:{options:["left","right"]}},label:{type:"fontEditor"},showAxis:{type:"boolean"},showLines:{type:"boolean"},showLabels:{type:"boolean"},showTicks:{type:"boolean"},zeroAxis:{type:"boolean"}}},axisX:{fields:{orient:{type:"select",settings:{options:["top","bottom"]}},label:{type:"fontEditor"},showAxis:{type:"boolean"},showLines:{type:"boolean"},showLabels:{type:"boolean"},showTicks:{type:"boolean"},zeroAxis:{type:"boolean"}}}}}}}}})},e.exports=n["default"]},{"./charts/Bar.js":21,"./charts/Pie.js":23,"./charts/Radar.js":24,"./charts/Scatterplot.js":25,"./charts/SmoothLine.js":26,"./charts/StockLine.js":27,"./charts/Tree.js":28,lodash:1}],20:[function(t,e,n){(function(t){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t,e,n){if(Array.isArray(e))return e.map(function(e,r){return o(t[r],e,n)});if("object"==typeof e){var r,i={};for(var r in e)i[r]=o(t[r],e[r],n);return i}return"number"==typeof e?t+(e-t)*n:t}function i(t){var e,n={};for(e in t)t.hasOwnProperty(e)&&(n[e]=t[e]);return n}Object.defineProperty(n,"__esModule",{value:!0});var a="undefined"!=typeof window?window.React:"undefined"!=typeof t?t.React:null,u=(r(a),1.70158),l={linear:function(t){return t},easeInQuad:function(t){return t*t},easeOutQuad:function(t){return-t*(t-2)},easeInOutQuad:function(t){return.5>t?2*t*t:-2*t*t+4*t-1},easeInElastic:function(t){var e=t-1;return-Math.pow(2,10*e)*Math.sin((2*e/.3-.5)*Math.PI)},easeOutElastic:function(t){return Math.pow(2,-10*t)*Math.sin((2*t/.3-.5)*Math.PI)+1},easeInOutElastic:function(t){var e=2*t-1;return.5>t?-.5*Math.pow(2,10*e)*Math.sin((e/.225-.5)*Math.PI):Math.pow(2,-10*e)*Math.sin((e/.225-.5)*Math.PI)*.5+1},easeInBack:function(t){return t*t*((u+1)*t-u)},easeOutBack:function(t){var e=t-1;return e*e*((u+1)*e+u)+1},easeInOutBack:function(t){var e=1.525*u;if(.5>t)return 2*t*t*(2*(e+1)*t-e);var n=t-1;return 2*n*n*(2*(e+1)*n+e)+1},easeInBounce:function(t){return 1-l.easeOutBounce(1-t)},easeOutBounce:function(t){var e=2.75*t,n=7.5625;if(1>e)return n*t*t;if(2>e){var r=t-1.5/2.75;return n*r*r+.75}if(2.5>e){var r=t-2.25/2.75;return n*r*r+.9375}var r=t-2.625/2.75;return n*r*r+.984375},easeInOutBounce:function(t){return.5>t?l.easeInBounce(2*t)/2:(l.easeOutBounce(2*t-1)+1)/2}};n["default"]={easing:l,Mixin:{animateState:function(t,e){function n(){var i=Math.min(Date.now()-r,u)/u;f.setState(o(a,t,c(i))),1>i?requestAnimationFrame(n):e.done&&e.done()}e=e||{};var r=Date.now(),a=i(this.state),u=e.duration||500,c=e.easing||l.easeInOutQuad,f=this;requestAnimationFrame(n)}}},e.exports=n["default"]}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],21:[function(t,e,n){(function(r){"use strict";function o(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function u(t,e){return t[e%t.length]}function l(t){return function(e){return e[t]}}Object.defineProperty(n,"__esModule",{value:!0});var c=function(){function t(t,e){for(var n=0;nn&&(n=o);var i=v["default"].min(t);return r>i&&(r=i),{minValue:r,maxValue:n,min:e(r),max:e(n)}}},{key:"render",value:function(){var t=this.props.noDataMessage||"No data available";if(void 0===this.props.data)return p["default"].createElement("span",null,t);var e=new m["default"](this.props),n=this.props.accessor||l(this.props.accessorKey),r=w({data:this.props.data,gutter:this.props.options.gutter||10,width:e.chartWidth,height:e.chartHeight,accessor:n}),o=v["default"].map(r.curves,function(t){return n(t.item)}),i={x:{minValue:0,maxValue:200,min:0,max:e.chartWidth},y:this.getMaxAndMin(o,r.scale)},a=e.animate.fillTransition||0,u={fillOpacity:this.state.finished?1:0,transition:this.state.finished?"fill-opacity "+a+"s":""},c=(0,b["default"])(e.axisX.label),f=r.curves.map(function(t,n){var r=this.color(n%3),o=d["default"].darkenColor(r);return p["default"].createElement("g",{key:"lines"+n},p["default"].createElement("path",{d:t.line.path.print(),style:u,stroke:o,fill:r}),e.axisX.showLabels?p["default"].createElement("text",{style:c,transform:"translate("+t.line.centroid[0]+","+(i.y.min+25)+")rotate(45)",textAnchor:"middle"},t.item.name):null)},this);return p["default"].createElement("svg",{ref:"vivus",width:e.width,height:e.height},p["default"].createElement("g",{transform:"translate("+e.margin.left+","+e.margin.top+")"},p["default"].createElement(x,{scale:r.scale,options:e.axisY,chartArea:i}),f))}}]),e}(p["default"].Component);n["default"]=O,O.defaultProps={accessorKey:"",options:{width:600,height:600,margin:{top:20,left:20,bottom:50,right:20},color:"#2980B9",gutter:20,animate:{type:"oneByOne",duration:200,fillTransition:3},axisX:{showAxis:!0,showLines:!0,showLabels:!0,showTicks:!0,zeroAxis:!1,orient:"bottom",label:{fontFamily:"Arial",fontSize:14,bold:!0,color:"#34495E"}},axisY:{showAxis:!0,showLines:!0,showLabels:!0,showTicks:!0,zeroAxis:!1,orient:"left",label:{fontFamily:"Arial",fontSize:14,bold:!0,color:"#34495E"}}}},e.exports=n["default"]}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../component/Axis":29,"../component/Options.js":30,"../fontAdapter.js":31,"../pallete/Colors.js":32,lodash:1,"paths-js/bar":2}],22:[function(t,e,n){(function(r){"use strict";function o(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function u(t,e){return t[e%t.length]}Object.defineProperty(n,"__esModule",{value:!0});var l=function(){function t(t,e){for(var n=0;nr)&&(r=i);var a=h["default"].min(n);(void 0===o||o>a)&&(o=a)}),{minValue:o,maxValue:r,min:n(o),max:n(r)}}},{key:"color",value:function n(t){var n=this.props.options.color;h["default"].isString(this.props.options.color)||(n=n.color);var e=this.props.pallete||y["default"].mix(n||"#9ac7f7");return y["default"].string(u(e,t))}},{key:"render",value:function(){var t=this.props.noDataMessage||"No data available";if(void 0===this.props.data)return s["default"].createElement("span",null,t);var e=new g["default"](this.props),n=function(t){return function(e){return e[t]}},r=this.chartType({data:this.props.data,xaccessor:n(this.props.xKey),yaccessor:n(this.props.yKey),width:e.chartWidth,height:e.chartHeight,closed:!1}),o={x:this.getMaxAndMin(r,this.props.xKey,r.xscale),y:this.getMaxAndMin(r,this.props.yKey,r.yscale),margin:e.margin},i={opacity:.5},a=h["default"].map(r.curves,function(t,e){return s["default"].createElement("path",{key:"lines"+e,d:t.line.path.print(),stroke:this.color(e),fill:"none"})}.bind(this)),u=h["default"].map(r.curves,function(t,e){return s["default"].createElement("path",{key:"areas"+e,d:t.area.path.print(),style:i,stroke:"none",fill:this.color(e)})}.bind(this));return s["default"].createElement("svg",{ref:"vivus",width:e.width,height:e.height},s["default"].createElement("g",{transform:"translate("+e.margin.left+","+e.margin.top+")"},this.state.finished?u:null,a,s["default"].createElement(_,{key:"x",scale:r.xscale,options:e.axisX,chartArea:o}),s["default"].createElement(_,{key:"y",scale:r.yscale,options:e.axisY,chartArea:o})))}}]),e}(s["default"].Component));n["default"]=b,e.exports=n["default"]}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../component/Axis":29,"../component/Options.js":30,"../fontAdapter.js":31,"../pallete/Colors.js":32,lodash:1,"paths-js/path":8}],23:[function(t,e,n){(function(r){"use strict";function o(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function u(t,e){return t[e%t.length]}function l(t){return function(e){return e[t]}}Object.defineProperty(n,"__esModule",{value:!0});var c=function(){function t(t,e){for(var n=0;nr)&&(r=i);var a=h["default"].min(n);(void 0===o||o>a)&&(o=a)}),{minValue:o,maxValue:r,min:n(o),max:n(r)}}},{key:"onEnter",value:function(t,e){this.props.data[0][t].selected=!0,this.setState({data:this.props.data})}},{key:"onLeave",value:function(t,e){this.props.data[0][t].selected=!1,this.setState({data:this.props.data})}},{key:"render",value:function(){var t=this.props.noDataMessage||"No data available";if(void 0===this.props.data)return s["default"].createElement("span",null,t);var e=new y["default"](this.props),n=(this.props.palette||["#3E90F0","#7881C2","#707B82"],function(t){return function(e){return e[t]}}),r=b({data:this.props.data,xaccessor:n(this.props.xKey),yaccessor:n(this.props.yKey),width:e.chartWidth,height:e.chartHeight,closed:!1}),o={x:this.getMaxAndMin(r,this.props.xKey,r.xscale),y:this.getMaxAndMin(r,this.props.yKey,r.yscale),margin:e.margin},i=e.animate.fillTransition||0,a={fillOpacity:this.state.finished?1:0,transition:this.state.finished?"fill-opacity "+i+"s":""},l=(0,g["default"])(e.label),c=(0,_["default"])({},e),f=h["default"].map(r.curves,function(t,n){return h["default"].map(t.line.path.points(),function(n,r){var o=t.item[r];return s["default"].createElement("g",{key:"k"+r,transform:"translate("+n[0]+","+n[1]+")"},s["default"].createElement("circle",u({},c,{cx:0,cy:0,r:e.r||5,style:a,onMouseEnter:this.onEnter.bind(this,r),onMouseLeave:this.onLeave.bind(this,r)})),o.selected?s["default"].createElement("text",{style:l,transform:"translate(15, 5)","text-anchor":"start"},o.title):null)},this)},this);return s["default"].createElement("svg",{ref:"vivus",width:e.width,height:e.height},s["default"].createElement("g",{transform:"translate("+e.margin.left+","+e.margin.top+")"},f,s["default"].createElement(w,{scale:r.xscale,options:e.axisX,chartArea:o}),s["default"].createElement(w,{scale:r.yscale,options:e.axisY,chartArea:o})))}}]),e}(s["default"].Component));n["default"]=x,x.defaultProps={xKey:"",yKey:"",options:{width:600,height:600,margin:{top:40,left:60,bottom:30,right:30},fill:"#2980B9",stroke:"#3E90F0",animate:{type:"delayed",duration:200,fillTransition:3},label:{fontFamily:"Arial",fontSize:14,bold:!0,color:"#34495E"},axisX:{showAxis:!0,showLines:!0,showLabels:!0,showTicks:!0,zeroAxis:!1,orient:"bottom",label:{fontFamily:"Arial",fontSize:14,bold:!0,color:"#34495E"}},axisY:{showAxis:!0,showLines:!0,showLabels:!0,showTicks:!0,zeroAxis:!1,orient:"left",label:{fontFamily:"Arial",fontSize:14,bold:!0,color:"#34495E"}}}},e.exports=n["default"]}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../component/Axis":29,"../component/Options.js":30,"../fontAdapter.js":31,"../styleSvg":33,lodash:1,"paths-js/path":8,"paths-js/stock":16}],26:[function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(n,"__esModule",{value:!0});var a=function(t,e,n){for(var r=!0;r;){var o=t,i=e,a=n;r=!1,null===o&&(o=Function.prototype);var u=Object.getOwnPropertyDescriptor(o,i);if(void 0!==u){if("value"in u)return u.value;var l=u.get;if(void 0===l)return;return l.call(a)}var c=Object.getPrototypeOf(o);if(null===c)return;t=c,e=i,n=a,r=!0,u=c=void 0}},u=t("./Line.js"),l=r(u),c=t("paths-js/smooth-line"),f=function(t){function e(t){o(this,e),a(Object.getPrototypeOf(e.prototype),"constructor",this).call(this,t,c)}return i(e,t),e}(l["default"]);n["default"]=f,f.defaultProps={options:{width:600,height:600,color:"#2980B9",margin:{top:40,left:60,bottom:50,right:20},animate:{type:"delayed",duration:200,fillTransition:3},axisX:{showAxis:!0,showLines:!0,showLabels:!0,showTicks:!0,zeroAxis:!1,orient:"bottom",label:{fontFamily:"Arial",fontSize:14,bold:!0,color:"#34495E"}},axisY:{showAxis:!0,showLines:!0,showLabels:!0,showTicks:!0,zeroAxis:!1,orient:"left",label:{fontFamily:"Arial",fontSize:14,bold:!0,color:"#34495E"}}}},e.exports=n["default"]},{"./Line.js":22,"paths-js/smooth-line":15}],27:[function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e); 4 | t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(n,"__esModule",{value:!0});var a=function(t,e,n){for(var r=!0;r;){var o=t,i=e,a=n;r=!1,null===o&&(o=Function.prototype);var u=Object.getOwnPropertyDescriptor(o,i);if(void 0!==u){if("value"in u)return u.value;var l=u.get;if(void 0===l)return;return l.call(a)}var c=Object.getPrototypeOf(o);if(null===c)return;t=c,e=i,n=a,r=!0,u=c=void 0}},u=t("./Line.js"),l=r(u),c=t("paths-js/stock"),f=function(t){function e(t){o(this,e),a(Object.getPrototypeOf(e.prototype),"constructor",this).call(this,t,c)}return i(e,t),e}(l["default"]);n["default"]=f,f.defaultProps={options:{width:600,height:600,color:"#2980B9",margin:{top:40,left:60,bottom:50,right:20},animate:{type:"delayed",duration:200,fillTransition:3},axisX:{showAxis:!0,showLines:!0,showLabels:!0,showTicks:!0,zeroAxis:!1,orient:"bottom",label:{fontFamily:"Arial",fontSize:14,bold:!0,color:"#34495E"}},axisY:{showAxis:!0,showLines:!0,showLabels:!0,showTicks:!0,zeroAxis:!1,orient:"left",label:{fontFamily:"Arial",fontSize:14,bold:!0,color:"#34495E"}}}},e.exports=n["default"]},{"./Line.js":22,"paths-js/stock":16}],28:[function(t,e,n){(function(r){"use strict";function o(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function u(t){return t.collapsed?[]:t.children||[]}Object.defineProperty(n,"__esModule",{value:!0});var l=Object.assign||function(t){for(var e=1;e0)var a=p["default"].createElement("text",{style:f,transform:"translate(-10,0)",textAnchor:"end"},t.item.name);else var a=p["default"].createElement("text",{style:f,transform:"translate(10,0)",textAnchor:"start"},t.item.name);return p["default"].createElement("g",{key:"tree_"+e,transform:i},p["default"].createElement("circle",l({style:c},o,{r:s,cx:"0",cy:"0",onClick:r})),a)});return p["default"].createElement("svg",{ref:"vivus",width:e.width,height:e.height},p["default"].createElement("g",{transform:"translate("+e.margin.left+","+e.margin.top+")"},i,h))}}]),e}(p["default"].Component);n["default"]=x,x.defaultProps={options:{margin:{top:20,left:50,right:80,bottom:20},width:600,height:600,fill:"#2980B9",stroke:"#3E90F0",r:5,animate:{type:"oneByOne",duration:200,fillTransition:3},label:{fontFamily:"Arial",fontSize:14,bold:!0,fill:"#34495E"}}},e.exports=n["default"]}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../component/Options.js":30,"../fontAdapter.js":31,"../styleSvg":33,lodash:1,"paths-js/tree":17}],29:[function(t,e,n){(function(r){"use strict";function o(t){return t&&t.__esModule?t:{"default":t}}function i(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function a(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var u=function(t,e,n){for(var r=!0;r;){var o=t,i=e,a=n;r=!1,null===o&&(o=Function.prototype);var u=Object.getOwnPropertyDescriptor(o,i);if(void 0!==u){if("value"in u)return u.value;var l=u.get;if(void 0===l)return;return l.call(a)}var c=Object.getPrototypeOf(o);if(null===c)return;t=c,e=i,n=a,r=!0,u=c=void 0}},l=function(){function t(t,e){for(var n=0;n5?i=10:i>2?i=5:i>1&&(i=2),i*o}},{key:"getTickValues",value:function(e,n){var r=t.calcStepSize(e.maxValue-e.minValue,n);return p["default"].range(e.minValue,e.maxValue+1,r)}}]),t}(),g=function(t){function e(t){a(this,e),u(Object.getPrototypeOf(e.prototype),"constructor",this).call(this,t)}return i(e,t),l(e,[{key:"render",value:function(){var t=this.props.chartArea,e=this.props.options,n=this.props.scale,r="top"===e.orient||"bottom"===e.orient,o=new v(this.props.scale,this.props.options,t,r).axis(),i=function(e){var o=r?[n(e),t.y.min]:[t.x.min,n(e)];return"translate("+o[0]+","+o[1]+")"},a={opacity:.5},u="start";"top"!==e.orient&&"bottom"!==e.orient||(u="middle"),"left"===e.orient&&(u="end"),"right"===e.orient&&(u="start");var l=[0,0];"top"===e.orient&&(l=[0,-5]),"bottom"===e.orient&&(l=[0,20]),"left"===e.orient&&(l=[-5,0]),"right"===e.orient&&(l=[5,0]);var c="translate("+l[0]+","+l[1]+")",s=(0,d["default"])(e.label),h=p["default"].map(o.ticks,function(t,n){var r=void 0!==e.labelComponent?f["default"].cloneElement(e.labelComponent,{value:t}):t;return f["default"].createElement("g",{key:n,transform:i(t)},e.showTicks?f["default"].createElement("circle",{r:"2",cx:"0",cy:"0",stroke:"grey",fill:"grey"}):null,e.showLabels?f["default"].createElement("text",{transform:c,style:s,textAnchor:u},r):null)}),y=e.showLines?p["default"].map(o.lines,function(t,e){return f["default"].createElement("path",{key:"gridLines"+e,d:t.print(),style:a,stroke:"#3E90F0",fill:"none"})}):[];return f["default"].createElement("g",null,e.showAxis?f["default"].createElement("path",{d:o.path.print(),style:a,stroke:"#3E90F0",strokeWidth:3,fill:"none"}):null,h,y)}}]),e}(f["default"].Component);n["default"]=g,e.exports=n["default"]}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../fontAdapter.js":31,lodash:1,"paths-js/path":8}],30:[function(t,e,n){"use strict";function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(n,"__esModule",{value:!0});var o=function(){function t(t,e){for(var n=0;n; 50 | if (options.axisY !== undefined) options.axisY.labelComponent = 51 | ; 52 | // 53 | var chartProps = _.extend({ 54 | data: this.state.data, 55 | options: options, 56 | replay: this.state.replay 57 | }, this.chartDemo.props); 58 | var chart = React.createElement(this.chartType, chartProps); 59 | return ( 60 |
61 |
62 |
63 |
64 |
66 |
67 |
68 |
69 | {chart} 70 |
71 |
72 | 73 | 74 | 75 |
76 | { 77 | 79 | } 80 | 81 | 82 | 83 | {this.state.show ?
{JSON.stringify(this.state.data, null, 2)}
: null} 84 |
85 |
86 | 87 | 89 | 90 |
91 |
92 |
93 | ) 94 | } 95 | } -------------------------------------------------------------------------------- /example/src/PieChartDemo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Pie} from 'react-pathjs-chart'; 3 | import genie from 'genie' 4 | import ChartDemo from './ChartDemo.js'; 5 | 6 | export class PieDemo { 7 | get dataTemplate() { 8 | return { 9 | data: { 10 | min: 2, 11 | max: 10, 12 | template: { 13 | name: { 14 | pattern: 'brState' 15 | }, 16 | population: { 17 | min: 10000, 18 | max: 10000000 19 | } 20 | } 21 | } 22 | } 23 | } 24 | get options() { 25 | return { 26 | margin: {top: 20, left: 20, right: 20, bottom: 20}, 27 | width: 600, 28 | height: 600, 29 | color: '#2980B9', 30 | r: 100, 31 | R: 200, 32 | legendPosition: 'topLeft', 33 | animate:{ 34 | type:'oneByOne', 35 | duration:200, 36 | fillTransition:3 37 | }, 38 | label:{ 39 | fontFamily:'Arial', 40 | fontSize:14, 41 | fontWeight:true, 42 | color:'#ECF0F1' 43 | } 44 | } 45 | } 46 | get props(){ 47 | return {accessorKey:"population"} 48 | } 49 | generateData(dataTemplate){ 50 | return genie(dataTemplate).data; 51 | } 52 | } 53 | 54 | export default class PieChartDemo extends ChartDemo { 55 | constructor(props) { 56 | super(props, Pie, new PieDemo()); 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /example/src/RadarChartDemo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Radar} from 'react-pathjs-chart'; 3 | import genie from 'genie' 4 | import ChartDemo from './ChartDemo.js'; 5 | 6 | export class RadarDemo { 7 | get dataTemplate() { 8 | return { 9 | speed: { 10 | min: 10, 11 | max: 100 12 | }, 13 | balance: { 14 | min: 10, 15 | max: 100 16 | }, 17 | explosives: { 18 | min: 10, 19 | max: 100 20 | }, 21 | energy: { 22 | min: 10, 23 | max: 100 24 | }, 25 | flexibility: { 26 | min: 10, 27 | max: 100 28 | }, 29 | agility: { 30 | min: 10, 31 | max: 100 32 | }, 33 | endurance: { 34 | min: 10, 35 | max: 100 36 | } 37 | } 38 | } 39 | get options() { 40 | return { 41 | width:600, 42 | height:600, 43 | margin:{top:20,left:20,right:20,bottom:20}, 44 | r:300, 45 | max:150, 46 | fill:"#2980B9", 47 | stroke:"#2980B9", 48 | animate:{ 49 | type:'oneByOne', 50 | duration:200 51 | }, 52 | label:{ 53 | fontFamily:'Arial', 54 | fontSize:14, 55 | fontWeight:true, 56 | fill:'#34495E' 57 | } 58 | } 59 | } 60 | get props(){ 61 | return {} 62 | } 63 | generateData(dataTemplate){ 64 | return [genie(dataTemplate)]; 65 | } 66 | } 67 | 68 | export default class RadarChartDemo extends ChartDemo { 69 | constructor(props) { 70 | super(props, Radar, new RadarDemo()); 71 | } 72 | }; 73 | -------------------------------------------------------------------------------- /example/src/ScatterPlotDemo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Scatterplot} from 'react-pathjs-chart'; 3 | import genie from 'genie' 4 | import ChartDemo from './ChartDemo.js'; 5 | import _ from 'lodash'; 6 | 7 | class PlotDemo { 8 | get dataTemplate() { 9 | return { 10 | data: { 11 | min: 20, 12 | max: 70, 13 | template: { 14 | title: { 15 | pattern: 'brState' 16 | }, 17 | rating: { 18 | min: 0, 19 | max: 10, 20 | places: 2 21 | } 22 | } 23 | } 24 | } 25 | } 26 | get options() { 27 | return { 28 | width: 600, 29 | height: 600, 30 | margin: {top: 40, left: 60, bottom: 30, right: 30}, 31 | fill: "#2980B9", 32 | stroke: "#3E90F0", 33 | animate:{ 34 | type:'delayed', 35 | duration:200 36 | }, 37 | label:{ 38 | fontFamily:'Arial', 39 | fontSize:14, 40 | fontWeight:true, 41 | fill:'#34495E' 42 | }, 43 | axisX: { 44 | showAxis: true, 45 | showLines: true, 46 | showLabels: true, 47 | showTicks: true, 48 | zeroAxis: false, 49 | orient: 'bottom', 50 | label:{ 51 | fontFamily:'Arial', 52 | fontSize:14, 53 | fontWeight:true, 54 | fill:'#34495E' 55 | } 56 | }, 57 | axisY: { 58 | showAxis: true, 59 | showLines: true, 60 | showLabels: true, 61 | showTicks: true, 62 | zeroAxis: false, 63 | orient: 'left', 64 | label:{ 65 | fontFamily:'Arial', 66 | fontSize:14, 67 | fontWeight:true, 68 | fill:'#34495E' 69 | } 70 | } 71 | } 72 | } 73 | get props(){ 74 | return {xKey:"episode",yKey:"rating"} 75 | } 76 | 77 | generateData(dataTemplate){ 78 | var clone = _.cloneDeep(dataTemplate); 79 | clone.data.template.episode = function () { 80 | return index++; 81 | }; 82 | var index = 0; 83 | return [genie(clone).data]; 84 | } 85 | } 86 | 87 | export default class ScatterPlotDemo extends ChartDemo { 88 | constructor(props) { 89 | super(props, Scatterplot, new PlotDemo()); 90 | } 91 | //render(){ 92 | // var options = _.deepClone(this.state.options); 93 | // options.axisY.labelComponent = 94 | // ; 96 | // var tdStyle = {paddingLeft:10,verticalAlign:'top'}; 97 | // return ( 98 | // 99 | // 100 | // 103 | // 104 | // 110 | // 111 | //
101 | // 102 | // 105 | // 109 | //
112 | // ) 113 | //} 114 | }; 115 | -------------------------------------------------------------------------------- /example/src/SmoothLineChartDemo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {SmoothLine} from 'react-pathjs-chart'; 3 | import genie from 'genie' 4 | import ChartDemo from './ChartDemo.js'; 5 | import _ from 'lodash'; 6 | 7 | 8 | export class SmoothLineDemo { 9 | get dataTemplate() { 10 | return { 11 | n:3, 12 | a: 1, 13 | b: 0, 14 | c: 0 15 | } 16 | } 17 | get options() { 18 | return { 19 | width:600, 20 | height:600, 21 | color:'#2980B9', 22 | margin: {top: 40, left: 60, bottom: 50, right: 20}, 23 | animate:{ 24 | type:'delayed', 25 | duration:200 26 | }, 27 | axisX: { 28 | showAxis: true, 29 | showLines: true, 30 | showLabels: true, 31 | showTicks: true, 32 | zeroAxis: false, 33 | orient: 'bottom', 34 | label:{ 35 | fontFamily:'Arial', 36 | fontSize:14, 37 | fontWeight:true, 38 | fill:'#34495E' 39 | } 40 | }, 41 | axisY: { 42 | showAxis: true, 43 | showLines: true, 44 | showLabels: true, 45 | showTicks: true, 46 | zeroAxis: false, 47 | orient: 'left', 48 | label:{ 49 | fontFamily:'Arial', 50 | fontSize:14, 51 | fontWeight:true, 52 | fill:'#34495E' 53 | } 54 | } 55 | } 56 | } 57 | get props(){ 58 | return {xKey:"x",yKey:"y"} 59 | } 60 | generateData(dataTemplate){ 61 | var xs = _.range(-10, 11, 1); 62 | var nPolynom = function (n, a, b, c) { 63 | return _.map(xs, function (x) { 64 | return {x: x, y: a * Math.pow(x, n) + b * x + c} 65 | }) 66 | }; 67 | return [nPolynom(dataTemplate.n,dataTemplate.a,dataTemplate.b,dataTemplate.c),nPolynom(dataTemplate.n -1,dataTemplate.a,dataTemplate.b,dataTemplate.c)] 68 | } 69 | } 70 | 71 | export default class SmoothLineChartDemo extends ChartDemo { 72 | constructor(props) { 73 | super(props, SmoothLine, new SmoothLineDemo()); 74 | } 75 | }; -------------------------------------------------------------------------------- /example/src/StockLineChartDemo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {StockLine} from 'react-pathjs-chart'; 3 | import genie from 'genie' 4 | import ChartDemo from './ChartDemo.js'; 5 | import _ from 'lodash'; 6 | 7 | export class StockLineDemo { 8 | get dataTemplate() { 9 | return { 10 | data: { 11 | min: 30, 12 | max: 80, 13 | template: { 14 | title: { 15 | pattern: 'brState' 16 | }, 17 | a: { 18 | min: 10000, 19 | max: 100000, 20 | places: 0 21 | }, 22 | b: { 23 | min: 50000, 24 | max: 200000, 25 | places: 0 26 | }, 27 | c: { 28 | min: 100000, 29 | max: 300000, 30 | places: 0 31 | } 32 | } 33 | } 34 | } 35 | } 36 | get options() { 37 | return { 38 | width:600, 39 | height:600, 40 | color:'#2980B9', 41 | margin: {top: 40, left: 60, bottom: 50, right: 20}, 42 | animate:{ 43 | type:'delayed', 44 | duration:200 45 | }, 46 | axisX: { 47 | showAxis: true, 48 | showLines: true, 49 | showLabels: true, 50 | showTicks: true, 51 | zeroAxis: false, 52 | orient: 'bottom', 53 | tickValues:[], 54 | label:{ 55 | fontFamily:'Arial', 56 | fontSize:14, 57 | fontWeight:true, 58 | fill:'#34495E' 59 | } 60 | }, 61 | axisY: { 62 | showAxis: true, 63 | showLines: true, 64 | showLabels: true, 65 | showTicks: true, 66 | zeroAxis: false, 67 | orient: 'left', 68 | tickValues:[], 69 | label:{ 70 | fontFamily:'Arial', 71 | fontSize:14, 72 | fontWeight:true, 73 | fill:'#34495E' 74 | } 75 | } 76 | } 77 | } 78 | get props(){ 79 | return {xKey:"x",yKey:"y"} 80 | } 81 | generateData(dataTemplate){ 82 | var clone = _.cloneDeep(dataTemplate); 83 | clone.data.template.index = function () { 84 | return index++; 85 | }; 86 | var index = 0; 87 | var data = genie(clone).data; 88 | var map = function(item){return {x:item.index,y:item[this]}}; 89 | return [_.map(data,map,'a'),_.map(data,map,'b'),_.map(data,map,'c')]; 90 | } 91 | } 92 | 93 | export default class StockLineChartDemo extends ChartDemo { 94 | constructor(props) { 95 | super(props, StockLine, new StockLineDemo()); 96 | } 97 | }; -------------------------------------------------------------------------------- /example/src/TreeChartDemo.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Tree} from 'react-pathjs-chart'; 3 | import genie from 'genie' 4 | import ChartDemo from './ChartDemo.js'; 5 | 6 | export class TreeDemo { 7 | get dataTemplate() { 8 | var leafTemplate = { 9 | min: 1, 10 | max: 5, 11 | template: { 12 | name: { 13 | pattern: 'lastName' 14 | } 15 | } 16 | }; 17 | return { 18 | name: { 19 | format: 'Root' 20 | }, 21 | children: { 22 | min: 3, 23 | max: 6, 24 | template: { 25 | name: {pattern: 'brState'}, 26 | children: leafTemplate 27 | } 28 | } 29 | } 30 | } 31 | get options() { 32 | return { 33 | margin: {top: 20, left: 50, right: 80, bottom: 20}, 34 | width:600, 35 | height:600, 36 | fill: "#2980B9", 37 | stroke: "#3E90F0", 38 | r:5, 39 | animate:{ 40 | type:'oneByOne', 41 | duration:200, 42 | fillTransition:3 43 | }, 44 | label:{ 45 | fontFamily:'Arial', 46 | fontSize:14, 47 | fontWeight:true, 48 | fill:'#34495E' 49 | } 50 | } 51 | } 52 | get props(){ 53 | return {} 54 | } 55 | generateData(dataTemplate){ 56 | return genie(dataTemplate); 57 | } 58 | } 59 | 60 | export default class TreeChartDemo extends ChartDemo { 61 | constructor(props) { 62 | super(props, Tree, new TreeDemo()); 63 | } 64 | }; -------------------------------------------------------------------------------- /example/src/app.css: -------------------------------------------------------------------------------- 1 | /* 2 | // Examples Stylesheet 3 | // ------------------- 4 | */ 5 | body { 6 | font-family: Helvetica Neue, Helvetica, Arial, sans-serif; 7 | font-size: 14px; 8 | color: #333; 9 | margin: 0; 10 | padding: 0; 11 | } 12 | a { 13 | color: #08c; 14 | text-decoration: none; 15 | } 16 | a:hover { 17 | text-decoration: underline; 18 | } 19 | .container { 20 | margin-left: auto; 21 | margin-right: auto; 22 | max-width: 720px; 23 | padding: 1em; 24 | } 25 | .footer { 26 | margin-top: 50px; 27 | border-top: 1px solid #eee; 28 | padding: 20px 0; 29 | font-size: 12px; 30 | color: #999; 31 | } 32 | h1, 33 | h2, 34 | h3, 35 | h4, 36 | h5, 37 | h6 { 38 | color: #222; 39 | font-weight: 100; 40 | margin: 0.5em 0; 41 | } 42 | label { 43 | color: #999; 44 | display: inline-block; 45 | font-size: 0.85em; 46 | font-weight: bold; 47 | margin: 1em 0; 48 | text-transform: uppercase; 49 | } 50 | .hint { 51 | margin: 15px 0; 52 | font-style: italic; 53 | color: #999; 54 | } 55 | .pie { 56 | position: relative; 57 | } 58 | .pie text { 59 | font-size: 10px; 60 | cursor: pointer; 61 | pointer-events: none; 62 | } 63 | .pie path { 64 | cursor: pointer; 65 | } 66 | .pie path:hover { 67 | opacity: 0.8; 68 | } 69 | .legend { 70 | border: 1px solid #cccccc; 71 | -moz-border-radius: 5px; 72 | -webkit-border-radius: 5px; 73 | border-radius: 5px; 74 | background: #eeeeee; 75 | padding: 10px; 76 | position: absolute; 77 | } 78 | .legend.topRight { 79 | right: 0; 80 | top: 0; 81 | } 82 | .legend.topLeft { 83 | left: 0; 84 | top: 0; 85 | } 86 | .legend.bottomLeft { 87 | left: 0; 88 | bottom: 0; 89 | } 90 | .legend.bottomRight { 91 | right: 0; 92 | bottom: 0; 93 | } 94 | -------------------------------------------------------------------------------- /example/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Binder from 'react-binding'; 4 | import _ from 'lodash'; 5 | import PropertyEditor from 'react-property-editor'; 6 | import genie from 'genie' 7 | 8 | import {Tabs as TabbedArea,Tab as TabPane,Button} from 'react-bootstrap'; 9 | 10 | import SmoothLineChartDemo from './SmoothLineChartDemo.js'; 11 | import StockLineChartDemo from './StockLineChartDemo.js'; 12 | import ScatterPlotDemo from './ScatterPlotDemo.js'; 13 | import BarChartDemo from './BarChartDemo.js'; 14 | import PieChartDemo from './PieChartDemo.js'; 15 | import TreeChartDemo from './TreeChartDemo.js'; 16 | import RadarChartDemo from './RadarChartDemo.js'; 17 | 18 | var patternsOptions = [ 19 | 'firstName', 20 | 'lastName', 21 | 'fullName', 22 | 'zipCode', 23 | 'zipCode5', 24 | 'zipCode9', 25 | 'city', 26 | 'streetName', 27 | 'streetAddress', 28 | 'secondaryAddress', 29 | 'brState', 30 | 'brStateAbbr', 31 | 'ukCounty', 32 | 'ukCountry', 33 | 'usState', 34 | 'usStateAbbr', 35 | 'latitude', 36 | 'longitude', 37 | 'phoneNumber', 38 | 'email', 39 | 'userName', 40 | 'domainName', 41 | 'domainWord', 42 | 'ipAddress', 43 | 'companyName', 44 | 'companySuffix', 45 | 'sentence', 46 | 'paragraph']; 47 | // 48 | //var colors = { 49 | // "turquoise" : "#1ABC9C", 50 | // "green-sea" : "#16A085", 51 | // "emerald" : "#2ECC71", 52 | // "nephritis" : "#27AE60", 53 | // "peter-river" : "#3498DB", 54 | // "belize-hole" : "#2980B9", 55 | // "amethyst" : "#9B59B6", 56 | // "wisteria" : "#8E44AD", 57 | // "wet-asphalt" : "#34495E", 58 | // "midnight-blue" : "#2C3E50", 59 | // "sun-flower" : "#F1C40F", 60 | // "orange" : "#F39C12", 61 | // "carrot" : "#E67E22", 62 | // "pumpkin" : "#D35400", 63 | // "alizarin" : "#E74C3C", 64 | // "pomegranate" : "#C0392B", 65 | // "clouds" : "#ECF0F1", 66 | // "silver" : "#BDC3C7", 67 | // "concrete" : "#95A5A6", 68 | // "asbestos" : "#7F8C8D" 69 | //}; 70 | // 71 | //var fontFamilies =[ 72 | // 'Arial', 73 | // 'Verdana', 74 | // 'Helvetica', 75 | // 'Times New Roman', 76 | // 'Courier New', 77 | // 'Papyrus' 78 | //] 79 | 80 | class TickValues extends React.Component 81 | { 82 | onChange(){ 83 | if (this.props.onChange!== undefined) this.props.onChange(); 84 | } 85 | add(){ 86 | this.props.tickValues.add({value: 0}); 87 | this.onChange(); 88 | } 89 | remove(item){ 90 | this.props.tickValues.remove(item); 91 | this.onChange(); 92 | } 93 | clear(){ 94 | 95 | var source = this.props.tickValues.sourceObject; 96 | source.splice(0,source.length); 97 | this.props.tickValues.notifyChange(); 98 | 99 | this.onChange(); 100 | 101 | } 102 | 103 | render(){ 104 | var items = this.props.tickValues.items; 105 | return (
106 | 107 | 108 | 109 | 110 | {items.map(function (item, index) { 111 | var valueLink =Binder.bindTo(item,'value'); 112 | var handleChange = function(e){ 113 | valueLink.value = e.target.value; 114 | this.onChange(); 115 | }.bind(this); 116 | return ( 117 | ) 121 | }, this)} 122 | 123 |
118 | 120 |
124 |
); 125 | } 126 | }; 127 | // Create the custom field type component 128 | class TickValuesWrapper extends React.Component 129 | { 130 | getInitialState(){ 131 | return {tickValues:_.map(this.props.value,function(item){return _.clone(item)})} 132 | } 133 | render () { 134 | var bindToArray = Binder.bindArrayToState(this,'tickValues'); 135 | return () 136 | } 137 | handleChange () { 138 | this.props.onUpdated(this.state.tickValues); 139 | } 140 | }; 141 | 142 | PropertyEditor.registerType('tickValues',TickValuesWrapper); 143 | // 144 | //// Create the custom field type component 145 | //var ColorPickerWrapper = React.createClass({ 146 | // 147 | // render: function () { 148 | // var opts = this.props.settings.options || []; 149 | // return () 155 | // }, 156 | // handleChange: function (e) { 157 | // this.props.onUpdated(e.target.value); 158 | // } 159 | //}); 160 | // 161 | //Json.registerType('colorPicker',ColorPickerWrapper); 162 | // 163 | //var labelOptions= { 164 | // fields: { 165 | // fontFamily: { 166 | // type: 'select', settings: { 167 | // options: _.map(fontFamilies, function (key, value) { 168 | // return {value: key, label: key}; 169 | // }) 170 | // } 171 | // }, 172 | // fill: { 173 | // type: 'colorPicker', settings: { 174 | // options: _.map(colors, function (key, value) { 175 | // return {value: key, label: value}; 176 | // }) 177 | // } 178 | // } 179 | // 180 | // } 181 | //}; 182 | 183 | // form: true 184 | // make objects not extensible, 185 | // fields not removable 186 | // and inputs always visible 187 | var settings = { 188 | form:true, 189 | fields: { 190 | data: { 191 | fields: { 192 | template: { 193 | fields: { 194 | title: { 195 | fields: { 196 | pattern: {type: 'select', settings: {options: patternsOptions}} 197 | } 198 | }, 199 | name: { 200 | fields: { 201 | pattern: {type: 'select', settings: {options: patternsOptions}} 202 | } 203 | } 204 | } 205 | } 206 | } 207 | }, 208 | children: { 209 | fields: { 210 | template: { 211 | fields: { 212 | name: { 213 | fields: { 214 | pattern: {type: 'select', settings: {options: patternsOptions}} 215 | } 216 | }, 217 | children: { 218 | fields: { 219 | template: { 220 | fields: { 221 | name: { 222 | fields: { 223 | pattern: {type: 'select', settings: {options: patternsOptions}} 224 | } 225 | } 226 | } 227 | } 228 | } 229 | } 230 | } 231 | } 232 | } 233 | } 234 | } 235 | }; 236 | 237 | class Panel extends React.Component 238 | { 239 | getInitialState(){ 240 | return {expanded: this.props.defaultExpanded} 241 | } 242 | toogleExpanded(){ 243 | this.setState({expanded: !this.state.expanded}); 244 | } 245 | render(){ 246 | var className = this.state.expanded ? "glyphicon-chevron-up" : "glyphicon-chevron-down"; 247 | className = "glyphicon " + className; 248 | return ( 249 |
250 |
251 |
252 |
{this.props.header}
253 |
254 |
255 |
256 | {this.state.expanded ?
{this.props.children}
: null} 257 |
258 | ) 259 | } 260 | } 261 | class App extends React.Component 262 | { 263 | render() { 264 | return (
265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 |
290 | ) 291 | } 292 | }; 293 | 294 | ReactDOM.render(, document.getElementById('app')); 295 | -------------------------------------------------------------------------------- /example/src/app.less: -------------------------------------------------------------------------------- 1 | //@import "../../node_modules/react-select/less/select"; 2 | /* 3 | // Examples Stylesheet 4 | // ------------------- 5 | */ 6 | 7 | body { 8 | font-family: Helvetica Neue, Helvetica, Arial, sans-serif; 9 | font-size: 14px; 10 | color: #333; 11 | margin: 0; 12 | padding: 0; 13 | } 14 | 15 | a { 16 | color: #08c; 17 | text-decoration: none; 18 | } 19 | 20 | a:hover { 21 | text-decoration: underline; 22 | } 23 | 24 | .container { 25 | margin-left: auto; 26 | margin-right: auto; 27 | max-width: 720px; 28 | padding: 1em; 29 | } 30 | 31 | .footer { 32 | margin-top: 50px; 33 | border-top: 1px solid #eee; 34 | padding: 20px 0; 35 | font-size: 12px; 36 | color: #999; 37 | } 38 | 39 | h1, h2, h3, h4, h5, h6 { 40 | color: #222; 41 | font-weight: 100; 42 | margin: 0.5em 0; 43 | } 44 | 45 | label { 46 | color: #999; 47 | display: inline-block; 48 | font-size: 0.85em; 49 | font-weight: bold; 50 | margin: 1em 0; 51 | text-transform: uppercase; 52 | } 53 | 54 | .hint { 55 | margin: 15px 0; 56 | font-style: italic; 57 | color: #999; 58 | } 59 | .pie { 60 | position: relative; 61 | 62 | & text { 63 | font-size: 10px; 64 | cursor: pointer; 65 | pointer-events: none; 66 | } 67 | 68 | & path { 69 | cursor: pointer; 70 | } 71 | 72 | & path:hover { 73 | opacity: 0.8; 74 | } 75 | } 76 | 77 | 78 | .legend { 79 | 80 | border: 1px solid #cccccc; 81 | -moz-border-radius: 5px; 82 | -webkit-border-radius: 5px; 83 | border-radius: 5px; 84 | background: #eeeeee; 85 | padding: 10px; 86 | position: absolute; 87 | 88 | &.topRight { 89 | right: 0; 90 | top:0; 91 | } 92 | &.topLeft { 93 | left: 0; 94 | top:0; 95 | } 96 | &.bottomLeft { 97 | left: 0; 98 | bottom:0; 99 | } 100 | &.bottomRight { 101 | right: 0; 102 | bottom:0; 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /example/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | React Paths-js charts component 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 66 | 67 | 68 |
69 |

React Paths-js charts component

70 |

View project on GitHub

71 | 72 |
73 | 74 |
75 | The example React app is rendered above. 76 |
77 | 80 |
81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /example/src/standalone.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | React Starter Component 4 | 5 | 6 | 7 |
8 |

React Starter Component

9 |

View project on GitHub

10 |
11 |
12 | The component above is provided by the standalone build, and React is loaded from cdnjs. 13 |
14 | 15 | 18 |
19 | 20 | 21 | 22 | 30 | 31 | -------------------------------------------------------------------------------- /gulpconfig.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file controls the behaviour of the build tasks in gulpfile.js 3 | */ 4 | 5 | var COMPONENT_NAME = 'Chart'; 6 | 7 | // Read the package.json to detect the package name and dependencies 8 | var pkg = JSON.parse(require('fs').readFileSync('./package.json')); 9 | 10 | // Default dependencies from package.json, except reactify (which is used for 11 | // the build). Dependencies can be customised by hard-coding this array. 12 | var dependencies = []; 13 | Object.keys(pkg.dependencies).forEach(function(i) { 14 | if (i !== 'reactify' && i!== 'paths-js') dependencies.push(i); 15 | //if (i === 'react') dependencies.push('react/addons'); 16 | }); 17 | 18 | module.exports = { 19 | 20 | component: { 21 | // This is the source (entry) file for the component 22 | file: COMPONENT_NAME + '.js', 23 | // The component name controls the standalone module name 24 | name: COMPONENT_NAME, 25 | // This is the directory to load the source file from 26 | src: 'src', 27 | // This is the directory to build the distribution to 28 | dist: 'dist', 29 | // This is the name of the package that will be exported 30 | // by the component file. It must match the name of your 31 | // package on npm 32 | pkgName: pkg.name, 33 | // The package dependencies are automatically build into 34 | // a common bundle for the examples and excluded from the 35 | // package build. 36 | dependencies: dependencies 37 | }, 38 | 39 | example: { 40 | // This is the directory to load the source files from 41 | src: 'example/src', 42 | // This is the directory to build the distribution to 43 | dist: 'example/dist', 44 | // Files will be copied as-is into the example dist folder 45 | files: [ 46 | 'index.html', 47 | 'standalone.html' 48 | ], 49 | // Scripts will be bundled by browserify and reactify 50 | scripts: [ 51 | 'app.js' 52 | ], 53 | // Stylesheets will be built by less 54 | stylesheets: [ 55 | 'app.less' 56 | ] 57 | } 58 | 59 | }; 60 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var initGulpTasks = require('react-component-gulp-tasks'); 3 | 4 | /** 5 | * Tasks are added by the react-component-gulp-tasks package 6 | * 7 | * See https://github.com/JedWatson/react-component-gulp-tasks 8 | * for documentation. 9 | * 10 | * You can also add your own additional gulp tasks if you like. 11 | */ 12 | 13 | var taskConfig = { 14 | 15 | component: { 16 | name: 'Chart', 17 | dependencies: [ 18 | 'classnames', 19 | 'react', 20 | 'react-dom' 21 | ], 22 | lib: 'lib' 23 | }, 24 | 25 | example: { 26 | src: 'example/src', 27 | dist: 'example/dist', 28 | files: [ 29 | 'index.html', 30 | '.gitignore' 31 | ], 32 | scripts: [ 33 | 'app.js' 34 | ], 35 | less: [ 36 | 'app.less' 37 | ] 38 | } 39 | 40 | }; 41 | 42 | initGulpTasks(gulp, taskConfig); 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-pathjs-chart", 3 | "version": "0.3.5", 4 | "private": false, 5 | "description": "React components - charts (Pie,SmoothLine) and other components (Tree) using path-js.", 6 | "main": "lib/Chart.js", 7 | "author": "Roman Samec (roman.samec2@gmail.com)", 8 | "license": "MIT", 9 | "homepage": "https://github.com/rsamec/react-pathjs-chart", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/rsamec/react-pathjs-chart.git" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/rsamec/react-pathjs-chart/issues" 16 | }, 17 | "dependencies": { 18 | "paths-js": "^0.3.4", 19 | "lodash": "^3.10.1", 20 | "vivus": "^0.2.1" 21 | }, 22 | "devDependencies": { 23 | "genie": "^0.1.8", 24 | "gulp": "^3.9.0", 25 | "react-binding": "^0.7.5", 26 | "react-bootstrap": "^0.28.3", 27 | "react-component-gulp-tasks": "^0.7.7", 28 | "react-json": "0.0.1", 29 | "react-json-fork": "0.0.2", 30 | "react-property-editor": "^1.0.1" 31 | }, 32 | "peerDependencies": { 33 | "react": "^0.14.0" 34 | }, 35 | "browser": "lib/Chart.js", 36 | "browserify-shim": { 37 | "react": "global:React" 38 | }, 39 | "scripts": { 40 | "build": "gulp clean && NODE_ENV=production gulp build", 41 | "examples": "gulp dev:server", 42 | "lint": "eslint ./; true", 43 | "publish:site": "NODE_ENV=production gulp publish:examples", 44 | "release": "NODE_ENV=production gulp release", 45 | "start": "gulp dev", 46 | "test": "echo \"no tests yet\" && exit 0", 47 | "watch": "gulp watch:lib" 48 | }, 49 | "keywords": [ 50 | "react", 51 | "react-component" 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /src/Chart.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | 3 | import Pie from './charts/Pie.js'; 4 | import Tree from './charts/Tree.js'; 5 | import Radar from './charts/Radar.js'; 6 | import Bar from './charts/Bar.js'; 7 | import SmoothLine from './charts/SmoothLine.js'; 8 | import StockLine from './charts/StockLine.js'; 9 | import Scatterplot from './charts/Scatterplot.js'; 10 | 11 | //import SmoothLine from './charts/SmoothLineVivus.js'; 12 | //import StockLine from './charts/StockLineVivus.js'; 13 | //import Bar from './charts/BarVivus.js'; 14 | //import Pie from './charts/PieVivus.js'; 15 | //import Radar from './charts/RadarVivus.js'; 16 | //import Tree from './charts/TreeVivus.js'; 17 | //import Scatterplot from './charts/ScatterplotVivus.js'; 18 | 19 | export default { 20 | Pie:_.extend(Pie, { 21 | metaData: { 22 | settings: { 23 | fields: { 24 | data: {type: 'plainJsonEditor'}, 25 | accessorKey:{type:'string'}, 26 | options: { 27 | fields: { 28 | width: {type: 'number'}, 29 | height: {type: 'number'}, 30 | margin: {type: 'boxSizeEditor'}, 31 | r: {type: 'number'}, 32 | R: {type: 'number'}, 33 | color: {type: 'colorPicker'}, 34 | legendPosition: { 35 | type: 'select', 36 | settings: {options: ['topLeft', 'topRight', 'bottomLeft', 'bottomRight']} 37 | }, 38 | label: {type: 'fontEditor'}, 39 | animate: { 40 | fields: { 41 | type: {type: 'select', settings: {options: ['delayed', 'async', 'oneByOne']}}, 42 | duration: {type: 'number'}, 43 | fillTransition: {type: 'number'} 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } 51 | }), 52 | Tree:_.extend(Tree, { 53 | metaData: { 54 | settings: { 55 | fields: { 56 | data: {type: 'plainJsonEditor'}, 57 | options: { 58 | fields: { 59 | width: {type: 'number'}, 60 | height: {type: 'number'}, 61 | margin: {type: 'boxSizeEditor'}, 62 | r: {type: 'number'}, 63 | fill: {type: 'colorPicker'}, 64 | stroke: {type: 'colorPicker'}, 65 | label: {type: 'fontEditor'}, 66 | animate: { 67 | fields: { 68 | type: {type: 'select', settings: {options: ['delayed', 'async', 'oneByOne']}}, 69 | duration: {type: 'number'}, 70 | fillTransition: {type: 'number'} 71 | } 72 | } 73 | } 74 | } 75 | } 76 | } 77 | } 78 | }), 79 | SmoothLine:_.extend(SmoothLine, { 80 | metaData: { 81 | settings: { 82 | fields: { 83 | data: {type: 'plainJsonEditor'}, 84 | xKey:{type:'string'}, 85 | yKey:{type:'string'}, 86 | options: { 87 | fields: { 88 | width: {type: 'number'}, 89 | height: {type: 'number'}, 90 | margin: {type: 'boxSizeEditor'}, 91 | color: {type: 'colorPicker'}, 92 | animate: { 93 | fields: { 94 | type: {type: 'select', settings: {options: ['delayed', 'async', 'oneByOne']}}, 95 | duration: {type: 'number'}, 96 | fillTransition: {type: 'number'} 97 | } 98 | } 99 | , 100 | axisY: { 101 | fields: { 102 | orient: {type: 'select', settings: {options: ['left', 'right']}}, 103 | //tickValues: {type: 'tickValues'}, 104 | label: {type: 'fontEditor'}, 105 | showAxis: {type: 'boolean'}, 106 | showLines: {type: 'boolean'}, 107 | showLabels: {type: 'boolean'}, 108 | showTicks: {type: 'boolean'}, 109 | zeroAxis: {type: 'boolean'} 110 | } 111 | }, 112 | axisX: { 113 | fields: { 114 | orient: {type: 'select', settings: {options: ['top', 'bottom']}}, 115 | //tickValues: {type: 'tickValues'}, 116 | label: {type: 'fontEditor'}, 117 | showAxis: {type: 'boolean'}, 118 | showLines: {type: 'boolean'}, 119 | showLabels: {type: 'boolean'}, 120 | showTicks: {type: 'boolean'}, 121 | zeroAxis: {type: 'boolean'} 122 | } 123 | } 124 | } 125 | } 126 | } 127 | } 128 | } 129 | }), 130 | StockLine:_.extend(StockLine, { 131 | metaData: { 132 | settings: { 133 | fields: { 134 | data: {type: 'plainJsonEditor'}, 135 | xKey:{type:'string'}, 136 | yKey:{type:'string'}, 137 | options: { 138 | fields: { 139 | width: {type: 'number'}, 140 | height: {type: 'number'}, 141 | margin: {type: 'boxSizeEditor'}, 142 | color: {type: 'colorPicker'}, 143 | animate: { 144 | fields: { 145 | type: {type: 'select', settings: {options: ['delayed', 'async', 'oneByOne']}}, 146 | duration: {type: 'number'}, 147 | fillTransition: {type: 'number'} 148 | } 149 | }, 150 | axisY: { 151 | fields: { 152 | orient: {type: 'select', settings: {options: ['left', 'right']}}, 153 | //tickValues: {type: 'tickValues'}, 154 | label: {type: 'fontEditor'}, 155 | showAxis: {type: 'boolean'}, 156 | showLines: {type: 'boolean'}, 157 | showLabels: {type: 'boolean'}, 158 | showTicks: {type: 'boolean'}, 159 | zeroAxis: {type: 'boolean'} 160 | } 161 | }, 162 | axisX: { 163 | fields: { 164 | orient: {type: 'select', settings: {options: ['top', 'bottom']}}, 165 | //tickValues: {type: 'tickValues'}, 166 | label: {type: 'fontEditor'}, 167 | showAxis: {type: 'boolean'}, 168 | showLines: {type: 'boolean'}, 169 | showLabels: {type: 'boolean'}, 170 | showTicks: {type: 'boolean'}, 171 | zeroAxis: {type: 'boolean'} 172 | } 173 | } 174 | } 175 | } 176 | } 177 | } 178 | } 179 | }), 180 | Radar:_.extend(Radar, { 181 | metaData: { 182 | settings: { 183 | fields: { 184 | data: {type: 'plainJsonEditor'}, 185 | options: { 186 | fields: { 187 | width: {type: 'number'}, 188 | height: {type: 'number'}, 189 | margin: {type: 'boxSizeEditor'}, 190 | r: {type: 'number'}, 191 | max: {type: 'number'}, 192 | fill: {type: 'colorPicker'}, 193 | stroke: {type: 'colorPicker'}, 194 | label: {type: 'fontEditor'}, 195 | animate: { 196 | fields: { 197 | type: {type: 'select', settings: {options: ['delayed', 'async', 'oneByOne']}}, 198 | duration: {type: 'number'}, 199 | fillTransition: {type: 'number'} 200 | } 201 | } 202 | } 203 | } 204 | } 205 | } 206 | } 207 | }), 208 | Bar:_.extend(Bar, { 209 | metaData: { 210 | settings: { 211 | fields: { 212 | data: {type: 'plainJsonEditor'}, 213 | accessorKey:{type:'string'}, 214 | options: { 215 | fields: { 216 | width: {type: 'number'}, 217 | height: {type: 'number'}, 218 | margin: {type: 'boxSizeEditor'}, 219 | gutter: {type: 'number'}, 220 | color: {type: 'colorPicker'}, 221 | animate: { 222 | fields: { 223 | type: {type: 'select', settings: {options: ['delayed', 'async', 'oneByOne']}}, 224 | duration: {type: 'number'}, 225 | fillTransition: {type: 'number'} 226 | } 227 | }, 228 | axisY: { 229 | fields: { 230 | orient: {type: 'select', settings: {options: ['left', 'right']}}, 231 | //tickValues: {type: 'tickValues'}, 232 | label: {type: 'fontEditor'}, 233 | showAxis: {type: 'boolean'}, 234 | showLines: {type: 'boolean'}, 235 | showLabels: {type: 'boolean'}, 236 | showTicks: {type: 'boolean'}, 237 | zeroAxis: {type: 'boolean'} 238 | } 239 | }, 240 | axisX: { 241 | fields: { 242 | orient: {type: 'select', settings: {options: ['top', 'bottom']}}, 243 | //tickValues: {type: 'tickValues'}, 244 | label: {type: 'fontEditor'}, 245 | showAxis: {type: 'boolean'}, 246 | showLines: {type: 'boolean'}, 247 | showLabels: {type: 'boolean'}, 248 | showTicks: {type: 'boolean'}, 249 | zeroAxis: {type: 'boolean'} 250 | } 251 | } 252 | } 253 | } 254 | } 255 | } 256 | } 257 | }), 258 | Scatterplot:_.extend(Scatterplot, { 259 | metaData: { 260 | settings: { 261 | fields: { 262 | data: {type: 'plainJsonEditor'}, 263 | xKey:{type:'string'}, 264 | yKey:{type:'string'}, 265 | options: { 266 | fields: { 267 | width: {type: 'number'}, 268 | height: {type: 'number'}, 269 | margin: {type: 'boxSizeEditor'}, 270 | fill: {type: 'colorPicker'}, 271 | stroke: {type: 'colorPicker'}, 272 | label: {type: 'fontEditor'}, 273 | animate: { 274 | fields: { 275 | type: {type: 'select', settings: {options: ['delayed', 'async', 'oneByOne']}}, 276 | duration: {type: 'number'}, 277 | fillTransition: {type: 'number'} 278 | } 279 | } 280 | , 281 | axisY: { 282 | fields: { 283 | orient: {type: 'select', settings: {options: ['left', 'right']}}, 284 | //tickValues: {type: 'tickValues'}, 285 | label: {type: 'fontEditor'}, 286 | showAxis: {type: 'boolean'}, 287 | showLines: {type: 'boolean'}, 288 | showLabels: {type: 'boolean'}, 289 | showTicks: {type: 'boolean'}, 290 | zeroAxis: {type: 'boolean'} 291 | } 292 | }, 293 | axisX: { 294 | fields: { 295 | orient: {type: 'select', settings: {options: ['top', 'bottom']}}, 296 | //tickValues: {type: 'tickValues'}, 297 | label: {type: 'fontEditor'}, 298 | showAxis: {type: 'boolean'}, 299 | showLines: {type: 'boolean'}, 300 | showLabels: {type: 'boolean'}, 301 | showTicks: {type: 'boolean'}, 302 | zeroAxis: {type: 'boolean'} 303 | } 304 | } 305 | } 306 | } 307 | } 308 | } 309 | } 310 | }) 311 | }; 312 | -------------------------------------------------------------------------------- /src/animate.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function interpolate(a, b, t) { 4 | if (Array.isArray(b)) { 5 | return b.map(function(x, i) { 6 | return interpolate(a[i], x, t); 7 | }); 8 | } 9 | if (typeof b === 'object') { 10 | var res = {}, k; 11 | for (var k in b) { 12 | // No need to check hasOwnProperty, 13 | // we are working with object literals 14 | res[k] = interpolate(a[k], b[k], t); 15 | } 16 | return res; 17 | } 18 | if (typeof b === 'number') { 19 | return a + (b - a) * t; 20 | } 21 | return a; 22 | } 23 | 24 | function copy(obj) { 25 | var res = {}, k; 26 | for (k in obj) { 27 | if (obj.hasOwnProperty(k)) { 28 | res[k] = obj[k]; 29 | } 30 | } 31 | return res; 32 | } 33 | 34 | var s = 1.70158; 35 | 36 | var easingTypes = { 37 | linear: function(t) { 38 | return t; 39 | }, 40 | easeInQuad: function (t) { 41 | return t * t; 42 | }, 43 | easeOutQuad: function (t) { 44 | return -t * (t - 2); 45 | }, 46 | easeInOutQuad: function (t) { 47 | return (t < 1/2) ? (2 * t * t) : (-2 * t * t + 4 * t - 1); 48 | }, 49 | easeInElastic: function (t) { 50 | var q = t - 1; 51 | return -Math.pow(2, 10 * q) * Math.sin((2 * q / 0.3 - 0.5) * Math.PI); 52 | }, 53 | easeOutElastic: function (t) { 54 | return Math.pow(2, -10 * t) * Math.sin( (2 * t / 0.3 - 0.5)* Math.PI) + 1; 55 | }, 56 | easeInOutElastic: function (t) { 57 | var q = 2 * t - 1; 58 | if (t < 1/2) return -0.5 * Math.pow(2, 10 * q) * Math.sin((q / 0.225 - 0.5) * Math.PI); 59 | else return Math.pow(2,-10 * q) * Math.sin((q / 0.225 - 0.5) * Math.PI) * 0.5 + 1; 60 | }, 61 | easeInBack: function (t) { 62 | return t * t * ((s + 1) * t - s); 63 | }, 64 | easeOutBack: function (t) { 65 | var q = t - 1; 66 | return q * q * ((s + 1) * q + s) + 1; 67 | }, 68 | easeInOutBack: function (t) { 69 | var r = s * 1.525; 70 | if (t < 1 / 2) return 2 * t * t * ((r + 1) * 2 * t - r) 71 | else { 72 | var q = t - 1; 73 | return 2 * q * q * ((r + 1) * 2 * q + r) + 1; 74 | } 75 | }, 76 | easeInBounce: function (t) { 77 | return 1 - easingTypes.easeOutBounce(1 - t); 78 | }, 79 | easeOutBounce: function (t) { 80 | var q = 2.75 * t; 81 | var l = 7.5625; 82 | if (q < 1) { return l * t * t } 83 | else if (q < 2) { 84 | var p = t - 1.5 / 2.75; 85 | return l * p * p + 0.75; 86 | } 87 | else if (q < 2.5) { 88 | var p = t - 2.25 / 2.75; 89 | return l * p * p + 0.9375; 90 | } 91 | else { 92 | var p = t - 2.625 / 2.75; 93 | return l * p * p + 0.984375; 94 | } 95 | }, 96 | easeInOutBounce: function (t) { 97 | return (t < 1/2) ? 98 | easingTypes.easeInBounce(2 * t) / 2 : 99 | (easingTypes.easeOutBounce(2 * t - 1) + 1) / 2; 100 | } 101 | }; 102 | 103 | /* 104 | * 105 | * TERMS OF USE - EASING EQUATIONS 106 | * 107 | * Open source under the BSD License. 108 | * 109 | * Copyright © 2001 Robert Penner 110 | * All rights reserved. 111 | * 112 | * Redistribution and use in source and binary forms, with or without modification, 113 | * are permitted provided that the following conditions are met: 114 | * 115 | * Redistributions of source code must retain the above copyright notice, this list of 116 | * conditions and the following disclaimer. 117 | * Redistributions in binary form must reproduce the above copyright notice, this list 118 | * of conditions and the following disclaimer in the documentation and/or other materials 119 | * provided with the distribution. 120 | * 121 | * Neither the name of the author nor the names of contributors may be used to endorse 122 | * or promote products derived from this software without specific prior written permission. 123 | * 124 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 125 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 126 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 127 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 128 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 129 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 130 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 131 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 132 | * OF THE POSSIBILITY OF SUCH DAMAGE. 133 | * 134 | */ 135 | 136 | export default { 137 | easing: easingTypes, 138 | Mixin: { 139 | animateState: function (target, options) { 140 | options = options || {}; 141 | var start = Date.now(); 142 | var initialState = copy(this.state); 143 | var duration = options.duration || 500; 144 | var easing = options.easing || easingTypes.easeInOutQuad; 145 | var self = this; 146 | 147 | function updateState() { 148 | var t = Math.min(Date.now() - start, duration) / duration; 149 | self.setState(interpolate(initialState, target, easing(t))); 150 | 151 | if (t < 1) { 152 | requestAnimationFrame(updateState); 153 | } 154 | else { 155 | if (options.done) options.done(); 156 | } 157 | } 158 | 159 | requestAnimationFrame(updateState); 160 | } 161 | } 162 | }; -------------------------------------------------------------------------------- /src/charts/Bar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Colors from '../pallete/Colors.js'; 3 | import _ from 'lodash'; 4 | import Options from '../component/Options.js'; 5 | import fontAdapt from '../fontAdapter.js'; 6 | 7 | var Bar = require('paths-js/bar'); 8 | 9 | var Axis = require('../component/Axis'); 10 | 11 | function cyclic(coll, i) { 12 | return coll[i % coll.length]; 13 | } 14 | function identity(key) { 15 | return function (x) { 16 | return x[key]; 17 | } 18 | }; 19 | function color(key) { 20 | return function (x) { 21 | return x[key]; 22 | } 23 | }; 24 | 25 | export default class BarChart extends React.Component 26 | { 27 | constructor(props){ 28 | super(props); 29 | this.state = {finished: true}; 30 | } 31 | color(i) { 32 | var color = this.props.options.color; 33 | if (!_.isString(this.props.options.color)) color = color.color; 34 | var pallete = this.props.pallete || Colors.mix(color || '#9ac7f7'); 35 | return Colors.string(cyclic(pallete, i)); 36 | } 37 | getMaxAndMin(values, scale) { 38 | var maxValue = 0; 39 | var minValue = 0; 40 | 41 | var max = _.max(values); 42 | if (max > maxValue) maxValue = max; 43 | var min = _.min(values); 44 | if (min < minValue) minValue = min; 45 | 46 | return { 47 | minValue: minValue, 48 | maxValue: maxValue, 49 | min: scale(minValue), 50 | max: scale(maxValue) 51 | } 52 | } 53 | //componentWillReceiveProps(nextProps) { 54 | // if (this.props.data !== nextProps.data) this.setState({ finished:false}); 55 | //} 56 | render() { 57 | var noDataMsg = this.props.noDataMessage || "No data available"; 58 | if (this.props.data === undefined) return ({noDataMsg}); 59 | 60 | var options = new Options(this.props); 61 | var accessor = this.props.accessor || identity(this.props.accessorKey); 62 | 63 | var chart = Bar({ 64 | data: this.props.data, 65 | gutter: this.props.options.gutter || 10, 66 | width: options.chartWidth, 67 | height: options.chartHeight, 68 | accessor: accessor 69 | }); 70 | 71 | var values = _.map(chart.curves, function (curve) { 72 | return accessor(curve.item); 73 | }); 74 | 75 | var chartArea = {x: {minValue: 0, maxValue: 200, min: 0, max: options.chartWidth}, y: this.getMaxAndMin(values, chart.scale)}; 76 | 77 | var sec = options.animate.fillTransition || 0; 78 | var fillOpacityStyle = {fillOpacity:this.state.finished?1:0,transition: this.state.finished?'fill-opacity ' + sec + 's':''}; 79 | 80 | var textStyle = fontAdapt(options.axisX.label); 81 | 82 | var lines = chart.curves.map(function (c, i) { 83 | var color = this.color(i % 3); 84 | var stroke = Colors.darkenColor(color); 85 | return ( 86 | 87 | 88 | {options.axisX.showLabels ? 89 | {c.item.name} 90 | :null} 91 | 92 | ) 93 | }, this); 94 | 95 | return ( 96 | 97 | 98 | {lines} 99 | 100 | ) 101 | } 102 | }; 103 | BarChart.defaultProps ={ 104 | accessorKey:'', 105 | options: { 106 | width: 600, 107 | height: 600, 108 | margin: {top: 20, left: 20, bottom: 50, right: 20}, 109 | color: '#2980B9', 110 | gutter: 20, 111 | animate: { 112 | type: 'oneByOne', 113 | duration: 200, 114 | fillTransition: 3 115 | }, 116 | axisX: { 117 | showAxis: true, 118 | showLines: true, 119 | showLabels: true, 120 | showTicks: true, 121 | zeroAxis: false, 122 | orient: 'bottom', 123 | label: { 124 | fontFamily: 'Arial', 125 | fontSize: 14, 126 | bold: true, 127 | color: '#34495E' 128 | } 129 | }, 130 | axisY: { 131 | showAxis: true, 132 | showLines: true, 133 | showLabels: true, 134 | showTicks: true, 135 | zeroAxis: false, 136 | orient: 'left', 137 | label: { 138 | fontFamily: 'Arial', 139 | fontSize: 14, 140 | bold: true, 141 | color: '#34495E' 142 | } 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /src/charts/BarVivus.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Vivus from 'vivus'; 4 | import BarChart from './Bar.js'; 5 | 6 | export default class BarVivusChart extends BarChart { 7 | constructor(props){ 8 | super(props); 9 | this.state = { finished: false }; 10 | } 11 | componentWillReceiveProps(nextProps){ 12 | if (nextProps.replay !== this.props.replay) this.setState({finished:false}); 13 | } 14 | componentDidMount() { 15 | this.run(); 16 | } 17 | componentDidUpdate(prevProps,prevState){ 18 | if (!this.state.finished) this.run() 19 | } 20 | run(){ 21 | if (this.refs.vivus === undefined) return; 22 | var animate = this.props.options && this.props.options.animate || {}; 23 | new Vivus(ReactDOM.findDOMNode(this.refs.vivus), { 24 | type: animate.type || 'delayed', 25 | duration: animate.duration || 'delayed', 26 | start: 'autostart', 27 | selfDestroy: true 28 | }, this.finish.bind(this)); 29 | } 30 | finish() { 31 | this.setState({ finished: true }); 32 | } 33 | } -------------------------------------------------------------------------------- /src/charts/Line.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import _ from 'lodash'; 3 | import Colors from '../pallete/Colors.js'; 4 | import Options from '../component/Options.js'; 5 | import fontAdapt from '../fontAdapter.js'; 6 | 7 | var Axis = require('../component/Axis'); 8 | var Path = require('paths-js/path'); 9 | 10 | function cyclic(coll, i) { return coll[i % coll.length]; } 11 | 12 | export default class LineChart extends React.Component { 13 | constructor(props, chartType) { 14 | super(props); 15 | this.chartType = chartType; 16 | this.state = {finished: true}; 17 | } 18 | getMaxAndMin(chart, key,scale) { 19 | var maxValue; 20 | var minValue; 21 | _.each(chart.curves, function (serie) { 22 | var values = _.map(serie.item, function (item) { 23 | return item[key] 24 | }); 25 | 26 | var max = _.max(values); 27 | if (maxValue === undefined || max > maxValue) maxValue = max; 28 | var min = _.min(values); 29 | if (minValue === undefined || min < minValue) minValue = min; 30 | }); 31 | return { 32 | minValue: minValue, 33 | maxValue: maxValue, 34 | min:scale(minValue), 35 | max:scale(maxValue) 36 | } 37 | } 38 | 39 | color(i) { 40 | var color = this.props.options.color; 41 | if (!_.isString(this.props.options.color)) color = color.color; 42 | var pallete = this.props.pallete || Colors.mix(color || '#9ac7f7'); 43 | return Colors.string(cyclic(pallete, i)); 44 | } 45 | 46 | render() { 47 | var noDataMsg = this.props.noDataMessage || "No data available"; 48 | if (this.props.data === undefined) return ({noDataMsg}); 49 | 50 | var options = new Options(this.props); 51 | 52 | 53 | var accessor = function (key) { 54 | return function (x) { 55 | return x[key]; 56 | } 57 | }; 58 | var chart = this.chartType({ 59 | data: this.props.data, 60 | xaccessor: accessor(this.props.xKey), 61 | yaccessor: accessor(this.props.yKey), 62 | width: options.chartWidth, 63 | height: options.chartHeight, 64 | closed: false 65 | }); 66 | 67 | var chartArea = { 68 | x:this.getMaxAndMin(chart,this.props.xKey,chart.xscale), 69 | y:this.getMaxAndMin(chart,this.props.yKey,chart.yscale), 70 | margin:options.margin 71 | }; 72 | 73 | var transparent = {opacity: 0.5}; 74 | 75 | var lines = _.map(chart.curves, function (c, i) { 76 | return 77 | }.bind(this)); 78 | var areas = _.map(chart.curves, function (c, i) { 79 | //var transparent = { opacity: 0.5 }; 80 | return 81 | }.bind(this)); 82 | 83 | return 84 | 85 | { this.state.finished ? areas : null } 86 | { lines } 87 | 88 | 89 | 90 | 91 | } 92 | } -------------------------------------------------------------------------------- /src/charts/Pie.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Colors from '../pallete/Colors.js'; 3 | import Animate from '../animate.js'; 4 | import _ from 'lodash'; 5 | import Options from '../component/Options.js' 6 | import fontAdapt from '../fontAdapter.js'; 7 | 8 | var Pie = require('paths-js/pie'); 9 | 10 | function cyclic(coll, i) { return coll[i % coll.length]; } 11 | function identity(key) { return function (x) {return x[key];}}; 12 | function color(key) { return function (x) {return x[key];}}; 13 | 14 | export default class PieChart extends React.Component 15 | { 16 | constructor(props) 17 | { 18 | super(props); 19 | this.animateState = Animate.Mixin.animateState; 20 | this.state = { 21 | expanded:this.defaultRange, 22 | finished:true 23 | }; 24 | } 25 | get defaultRange() { 26 | return _.map(Array(this.props.data && this.props.data.length),function(){return 0}); 27 | } 28 | translate(p) { return "translate(" + p[0] + "," + p[1] + ")" } 29 | 30 | move(point, perc) { 31 | return this.translate([point[0] * perc / 3, point[1] * perc / 3]); 32 | } 33 | // 34 | //grad(i) { return "grad-" + i } 35 | // 36 | //fill(i) { return "url(#grad-" + i +")" } 37 | 38 | color(i) { 39 | var color = this.props.options.color; 40 | if (!_.isString(this.props.options.color)) color = color.color; 41 | var pallete = this.props.pallete || Colors.mix(color || '#9ac7f7'); 42 | return Colors.string(cyclic(pallete, i)); } 43 | 44 | lighten(i) { 45 | var color = this.props.options.color; 46 | if (!_.isString(this.props.options.color)) color = color.color; 47 | var pallete = this.props.pallete || Colors.mix(color || '#9ac7f7'); 48 | return Colors.string(Colors.lighten(cyclic(pallete, i))); } 49 | 50 | 51 | expand(i) { 52 | var self = this; 53 | 54 | return function() { 55 | var target = self.defaultRange; 56 | target[i] = 1; 57 | self.animateState({ expanded: target }); 58 | //self.setState({ expanded: target }); 59 | }; 60 | } 61 | 62 | render() { 63 | var noDataMsg = this.props.noDataMessage || "No data available"; 64 | if (this.props.data === undefined) return ({noDataMsg}); 65 | 66 | var options = new Options(this.props); 67 | 68 | var x = options.chartWidth / 2; 69 | var y = options.chartHeight / 2; 70 | 71 | var radius = Math.min(x, y); 72 | 73 | var chart = Pie({ 74 | center: this.props.options.center || [0,0], 75 | r: this.props.options.r || radius /2, 76 | R: this.props.options.R || radius, 77 | data: this.props.data, 78 | accessor: this.props.accessor || identity(this.props.accessorKey) 79 | }); 80 | 81 | var self = this; 82 | var coefficients = this.state.expanded; 83 | var sec = options.animate.fillTransition || 0; 84 | var fillOpacityStyle = {fillOpacity:this.state.finished?1:0,transition: this.state.finished?'fill-opacity ' + sec + 's':''}; 85 | 86 | var textStyle = fontAdapt(options.label); 87 | 88 | var slices = chart.curves.map(function(c, i) { 89 | var fill = self.color(i); 90 | var stroke = Colors.darkenColor(fill); 91 | return ( 92 | 93 | 94 | { c.item.name } 95 | 96 | ) 97 | }); 98 | var selected = _.find(this.props.data, function(c, i) { 99 | return coefficients[i] === 1; 100 | }); 101 | 102 | var legendClassName = "legend " + options.legendPosition; 103 | 104 | var table = selected ? 105 |
106 |

{ selected.name }

107 |

{ selected.population }

108 |
: null 109 | 110 | 111 | 112 | return( 113 |
114 | 115 | 116 | { slices } 117 | 118 | 119 | { table } 120 |
121 | )} 122 | }; 123 | PieChart.defaultProps = { 124 | options: { 125 | margin: {top: 20, left: 20, right: 20, bottom: 20}, 126 | width: 600, 127 | height: 600, 128 | color: '#2980B9', 129 | r: 100, 130 | R: 200, 131 | legendPosition: 'topLeft', 132 | animate: { 133 | type: 'oneByOne', 134 | duration: 200, 135 | fillTransition: 3 136 | }, 137 | label: { 138 | fontFamily: 'Arial', 139 | fontSize: 14, 140 | bold: true, 141 | color: '#ECF0F1' 142 | } 143 | } 144 | } -------------------------------------------------------------------------------- /src/charts/PieVivus.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Vivus from 'vivus'; 4 | import PieChart from './Pie.js'; 5 | 6 | export default class PieVivusChart extends PieChart { 7 | constructor(props){ 8 | super(props); 9 | this.state = { 10 | expanded:this.defaultRange, 11 | finished: false 12 | }; 13 | } 14 | componentWillReceiveProps(nextProps){ 15 | if (nextProps.replay !== this.props.replay) this.setState({finished:false}); 16 | } 17 | componentDidMount() { 18 | this.run(); 19 | } 20 | componentDidUpdate(prevProps,prevState){ 21 | if (!this.state.finished) this.run() 22 | } 23 | run(){ 24 | if (this.refs.vivus === undefined) return; 25 | var animate = this.props.options && this.props.options.animate || {}; 26 | 27 | new Vivus(ReactDOM.findDOMNode(this.refs.vivus), { 28 | type: animate.type || 'delayed', 29 | duration: animate.duration || 'delayed', 30 | start: 'autostart', 31 | selfDestroy: true 32 | }, this.finish.bind(this)); 33 | } 34 | finish() { 35 | this.setState({ finished: true }); 36 | } 37 | } -------------------------------------------------------------------------------- /src/charts/Radar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import _ from 'lodash'; 3 | import Options from '../component/Options.js'; 4 | import fontAdapt from '../fontAdapter.js'; 5 | import styleSvg from '../styleSvg.js'; 6 | 7 | var Radar = require('paths-js/radar'); 8 | 9 | function identity(key) { 10 | return function (x) { 11 | return x[key]; 12 | } 13 | }; 14 | function accessKeys(keys) { 15 | var a = {}; 16 | for (var i in keys) { 17 | var key = keys[i]; 18 | a[key] = identity(key); 19 | } 20 | return a; 21 | } 22 | 23 | export default class RadarChart extends React.Component 24 | { 25 | constructor(props){ 26 | super(props) 27 | this.state = {finished:true}; 28 | } 29 | render() { 30 | var noDataMsg = this.props.noDataMessage || "No data available"; 31 | if (this.props.data === undefined) return ({noDataMsg}); 32 | 33 | var options = new Options(this.props); 34 | 35 | var x = options.chartWidth / 2; 36 | var y = options.chartHeight / 2; 37 | var radius = Math.min(x, y); 38 | 39 | var center = this.props.center || [x, y]; 40 | 41 | var keys = Object.keys(this.props.data[0]); 42 | var chart = Radar({ 43 | center: this.props.center || [x, y], 44 | r: this.props.options.r || radius, 45 | data: this.props.data, 46 | accessor: this.props.accessor || accessKeys(keys), 47 | max: this.props.options.max 48 | }); 49 | var self = this; 50 | var colors = styleSvg({}, self.props.options); 51 | var curves = chart.curves.map(function (c, i) { 52 | return () 53 | }); 54 | 55 | //var rings = chart.rings.map(function(r, i) { 56 | // return () 57 | //}); 58 | var length = chart.rings.length; 59 | 60 | var rings = chart.rings.map(function (r, i) { 61 | if (i !== length - 1) { 62 | return () 63 | } 64 | }); 65 | // 66 | var textStyle = fontAdapt(options.label); 67 | 68 | var labels = chart.rings[length - 1].path.points().map(function (p, i) { 69 | return ( 70 | 71 | 72 | {keys[i]} 73 | 74 | ) 75 | }); 76 | return ( 77 | 78 | {labels} 79 | 80 | { rings } 81 | 82 | {this.state.finished?curves:null} 83 | 84 | 85 | 86 | 87 | ) 88 | } 89 | }; 90 | 91 | RadarChart.defaultProps = { 92 | options: { 93 | width: 600, 94 | height: 600, 95 | margin: {top: 20, left: 20, right: 20, bottom: 20}, 96 | r: 300, 97 | max: 150, 98 | fill: "#2980B9", 99 | stroke: "#2980B9", 100 | animate: { 101 | type: 'oneByOne', 102 | duration: 200, 103 | fillTransition:3 104 | }, 105 | label: { 106 | fontFamily: 'Arial', 107 | fontSize: 14, 108 | bold: true, 109 | color: '#34495E' 110 | } 111 | } 112 | } 113 | 114 | -------------------------------------------------------------------------------- /src/charts/RadarVivus.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Vivus from 'vivus'; 4 | import RadarChart from './Radar.js'; 5 | 6 | export default class RadarVivusChart extends RadarChart { 7 | constructor(props){ 8 | super(props); 9 | this.state = { finished: false }; 10 | } 11 | componentWillReceiveProps(nextProps){ 12 | if (nextProps.replay !== this.props.replay) this.setState({finished:false}); 13 | } 14 | componentDidMount() { 15 | this.run(); 16 | } 17 | componentDidUpdate(prevProps,prevState){ 18 | if (!this.state.finished) this.run() 19 | } 20 | run(){ 21 | if (this.refs.vivus === undefined) return; 22 | var animate = this.props.options && this.props.options.animate || {}; 23 | 24 | new Vivus(ReactDOM.findDOMNode(this.refs.vivus), { 25 | type: animate.type || 'delayed', 26 | duration: animate.duration || 'delayed', 27 | start: 'autostart', 28 | selfDestroy: true 29 | }, this.finish.bind(this)); 30 | } 31 | finish() { 32 | this.setState({ finished: true }); 33 | } 34 | } -------------------------------------------------------------------------------- /src/charts/Scatterplot.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import _ from 'lodash'; 3 | import Options from '../component/Options.js'; 4 | import fontAdapt from '../fontAdapter.js'; 5 | import styleSvg from '../styleSvg'; 6 | 7 | var Stock = require('paths-js/stock'); 8 | var Axis = require('../component/Axis'); 9 | var Path = require('paths-js/path'); 10 | 11 | export default class Scatterplot extends React.Component { 12 | constructor(props) { 13 | super(props); 14 | this.state = {finished:true}; 15 | } 16 | getMaxAndMin(chart, key,scale) { 17 | var maxValue; 18 | var minValue; 19 | _.each(chart.curves, function (serie) { 20 | var values = _.map(serie.item, function (item) { 21 | return item[key] 22 | }); 23 | 24 | var max = _.max(values); 25 | if (maxValue === undefined || max > maxValue) maxValue = max; 26 | var min = _.min(values); 27 | if (minValue === undefined || min < minValue) minValue = min; 28 | }); 29 | return { 30 | minValue: minValue, 31 | maxValue: maxValue, 32 | min:scale(minValue), 33 | max:scale(maxValue) 34 | } 35 | } 36 | onEnter(index,event) { 37 | this.props.data[0][index].selected = true; 38 | this.setState({data: this.props.data}); 39 | } 40 | onLeave(index,event){ 41 | this.props.data[0][index].selected = false; 42 | this.setState({data:this.props.data}); 43 | } 44 | 45 | render() { 46 | var noDataMsg = this.props.noDataMessage || "No data available"; 47 | if (this.props.data === undefined) return ({noDataMsg}); 48 | 49 | var options = new Options(this.props); 50 | 51 | var palette = this.props.palette || ["#3E90F0", "#7881C2", "#707B82"]; 52 | var accessor = function (key) { 53 | return function (x) { 54 | return x[key]; 55 | } 56 | }; 57 | var chart = Stock({ 58 | data: this.props.data, 59 | xaccessor: accessor(this.props.xKey), 60 | yaccessor: accessor(this.props.yKey), 61 | width: options.chartWidth, 62 | height: options.chartHeight, 63 | closed: false 64 | }); 65 | 66 | var chartArea = { 67 | x:this.getMaxAndMin(chart,this.props.xKey,chart.xscale), 68 | y:this.getMaxAndMin(chart,this.props.yKey,chart.yscale), 69 | margin:options.margin 70 | }; 71 | 72 | 73 | var sec = options.animate.fillTransition || 0; 74 | var fillOpacityStyle = {fillOpacity:this.state.finished?1:0,transition: this.state.finished?'fill-opacity ' + sec + 's':''}; 75 | 76 | var textStyle = fontAdapt(options.label); 77 | 78 | 79 | var colors = styleSvg({},options); 80 | var points = _.map(chart.curves, function (c, i) { 81 | return _.map(c.line.path.points(),function(p,j) { 82 | var item = c.item[j]; 83 | return ( 84 | 85 | {item.selected?{item.title}:null} 86 | ) 87 | },this) 88 | },this); 89 | 90 | return ( 91 | 92 | { points } 93 | 94 | 95 | 96 | ); 97 | } 98 | } 99 | 100 | 101 | Scatterplot.defaultProps= { 102 | xKey:'', 103 | yKey:'', 104 | options: { 105 | width: 600, 106 | height: 600, 107 | margin: {top: 40, left: 60, bottom: 30, right: 30}, 108 | fill: "#2980B9", 109 | stroke: "#3E90F0", 110 | animate: { 111 | type: 'delayed', 112 | duration: 200, 113 | fillTransition:3 114 | }, 115 | label: { 116 | fontFamily: 'Arial', 117 | fontSize: 14, 118 | bold: true, 119 | color: '#34495E' 120 | }, 121 | axisX: { 122 | showAxis: true, 123 | showLines: true, 124 | showLabels: true, 125 | showTicks: true, 126 | zeroAxis: false, 127 | orient: 'bottom', 128 | label: { 129 | fontFamily: 'Arial', 130 | fontSize: 14, 131 | bold: true, 132 | color: '#34495E' 133 | } 134 | }, 135 | axisY: { 136 | showAxis: true, 137 | showLines: true, 138 | showLabels: true, 139 | showTicks: true, 140 | zeroAxis: false, 141 | orient: 'left', 142 | label: { 143 | fontFamily: 'Arial', 144 | fontSize: 14, 145 | bold: true, 146 | color: '#34495E' 147 | } 148 | } 149 | } 150 | } -------------------------------------------------------------------------------- /src/charts/ScatterplotVivus.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Vivus from 'vivus'; 4 | import ScatterplotChart from './Scatterplot.js'; 5 | 6 | export default class ScatterplotVivusChart extends ScatterplotChart { 7 | constructor(props){ 8 | super(props); 9 | this.state = { finished: false }; 10 | } 11 | componentWillReceiveProps(nextProps){ 12 | if (nextProps.replay !== this.props.replay) this.setState({finished:false}); 13 | } 14 | componentDidMount() { 15 | this.run(); 16 | } 17 | componentDidUpdate(prevProps,prevState){ 18 | if (!this.state.finished) this.run() 19 | } 20 | run(){ 21 | if (this.refs.vivus === undefined) return; 22 | var animate = this.props.options && this.props.options.animate || {}; 23 | new Vivus(ReactDOM.findDOMNode(this.refs.vivus), { 24 | type: animate.type || 'delayed', 25 | duration: animate.duration || 'delayed', 26 | start: 'autostart', 27 | selfDestroy: true 28 | }, this.finish.bind(this)); 29 | } 30 | finish() { 31 | this.setState({ finished: true }); 32 | } 33 | } -------------------------------------------------------------------------------- /src/charts/SmoothLine.js: -------------------------------------------------------------------------------- 1 | import LineChart from './Line.js'; 2 | 3 | var SmoothLine = require('paths-js/smooth-line'); 4 | 5 | export default class SmoothLineChart extends LineChart { 6 | constructor(props) { 7 | super(props, SmoothLine); 8 | } 9 | } 10 | 11 | SmoothLineChart.defaultProps = { 12 | 13 | options: { 14 | width: 600, 15 | height: 600, 16 | color: '#2980B9', 17 | margin: {top: 40, left: 60, bottom: 50, right: 20}, 18 | animate: { 19 | type: 'delayed', 20 | duration: 200, 21 | fillTransition:3 22 | }, 23 | axisX: { 24 | showAxis: true, 25 | showLines: true, 26 | showLabels: true, 27 | showTicks: true, 28 | zeroAxis: false, 29 | orient: 'bottom', 30 | label: { 31 | fontFamily: 'Arial', 32 | fontSize: 14, 33 | bold: true, 34 | color: '#34495E' 35 | } 36 | }, 37 | axisY: { 38 | showAxis: true, 39 | showLines: true, 40 | showLabels: true, 41 | showTicks: true, 42 | zeroAxis: false, 43 | orient: 'left', 44 | label: { 45 | fontFamily: 'Arial', 46 | fontSize: 14, 47 | bold: true, 48 | color: '#34495E' 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/charts/SmoothLineVivus.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Vivus from 'vivus'; 4 | import SmoothLineChart from './SmoothLine.js'; 5 | 6 | export default class SmoothLineVivusChart extends SmoothLineChart { 7 | constructor(props){ 8 | super(props); 9 | this.state = { finished: false }; 10 | } 11 | componentWillReceiveProps(nextProps){ 12 | if (nextProps.replay !== this.props.replay) this.setState({finished:false}); 13 | } 14 | componentDidMount() { 15 | this.run(); 16 | } 17 | componentDidUpdate(prevProps,prevState){ 18 | if (!this.state.finished) this.run() 19 | } 20 | run(){ 21 | if (this.refs.vivus === undefined) return; 22 | var animate = this.props.options && this.props.options.animate || {}; 23 | new Vivus(ReactDOM.findDOMNode(this.refs.vivus), { 24 | type: animate.type || 'delayed', 25 | duration: animate.duration || 'delayed', 26 | start: 'autostart', 27 | selfDestroy: true 28 | }, this.finish.bind(this)); 29 | } 30 | finish() { 31 | this.setState({ finished: true }); 32 | } 33 | } -------------------------------------------------------------------------------- /src/charts/StockLine.js: -------------------------------------------------------------------------------- 1 | import LineChart from './Line.js'; 2 | 3 | var StockLine = require('paths-js/stock'); 4 | 5 | export default class StockLineChart extends LineChart { 6 | constructor(props) { 7 | super(props, StockLine); 8 | } 9 | } 10 | 11 | 12 | StockLineChart.defaultProps = { 13 | options: { 14 | width: 600, 15 | height: 600, 16 | color: '#2980B9', 17 | margin: {top: 40, left: 60, bottom: 50, right: 20}, 18 | animate: { 19 | type: 'delayed', 20 | duration: 200, 21 | fillTransition:3 22 | }, 23 | axisX: { 24 | showAxis: true, 25 | showLines: true, 26 | showLabels: true, 27 | showTicks: true, 28 | zeroAxis: false, 29 | orient: 'bottom', 30 | label: { 31 | fontFamily: 'Arial', 32 | fontSize: 14, 33 | bold: true, 34 | color: '#34495E' 35 | } 36 | }, 37 | axisY: { 38 | showAxis: true, 39 | showLines: true, 40 | showLabels: true, 41 | showTicks: true, 42 | zeroAxis: false, 43 | orient: 'left', 44 | label: { 45 | fontFamily: 'Arial', 46 | fontSize: 14, 47 | bold: true, 48 | color: '#34495E' 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/charts/StockLineVivus.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Vivus from 'vivus'; 4 | import StockLineChart from './StockLine.js'; 5 | 6 | export default class StockLineVivusChart extends StockLineChart { 7 | constructor(props){ 8 | super(props); 9 | this.state = { finished: false }; 10 | } 11 | componentWillReceiveProps(nextProps){ 12 | if (nextProps.replay !== this.props.replay) this.setState({finished:false}); 13 | } 14 | componentDidMount() { 15 | this.run(); 16 | } 17 | componentDidUpdate(prevProps,prevState){ 18 | if (!this.state.finished) this.run() 19 | } 20 | run(){ 21 | if (this.refs.vivus === undefined) return; 22 | var animate = this.props.options && this.props.options.animate || {}; 23 | new Vivus(ReactDOM.findDOMNode(this.refs.vivus), { 24 | type: animate.type || 'delayed', 25 | duration: animate.duration || 'delayed', 26 | start: 'autostart', 27 | selfDestroy: true 28 | }, this.finish.bind(this)); 29 | } 30 | finish() { 31 | this.setState({ finished: true }); 32 | } 33 | } -------------------------------------------------------------------------------- /src/charts/Tree.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import _ from 'lodash'; 3 | import Options from '../component/Options.js'; 4 | import fontAdapt from '../fontAdapter.js'; 5 | import styleSvg from '../styleSvg'; 6 | var Tree = require('paths-js/tree'); 7 | 8 | function children(x) { 9 | if(x.collapsed) { 10 | return [] 11 | } 12 | else { 13 | return x.children || [] 14 | } 15 | } 16 | export default class TreeChart extends React.Component { 17 | constructor(props){ 18 | super(props); 19 | this.state = {finished:true}; 20 | } 21 | render() { 22 | var noDataMsg = this.props.noDataMessage || "No data available"; 23 | if (this.props.data === undefined) return ({noDataMsg}); 24 | 25 | var options = new Options(this.props); 26 | var that = this; 27 | 28 | 29 | var tree = Tree({ 30 | data: this.props.data, 31 | children: children, 32 | width: options.chartWidth, 33 | height: options.chartHeight 34 | }); 35 | var colors = styleSvg({},options); 36 | var curves = _.map(tree.curves,function (c,i) { 37 | return 38 | }); 39 | 40 | var sec = options.animate.fillTransition || 0; 41 | var fillOpacityStyle = {fillOpacity:this.state.finished?1:0,transition: this.state.finished?'fill-opacity ' + sec + 's':''}; 42 | 43 | var textStyle = fontAdapt(options.label); 44 | 45 | 46 | 47 | var r = options.r || 5; 48 | var nodes = _.map(tree.nodes,function (n,index) { 49 | var position = "translate(" + n.point[0] + "," + n.point[1] + ")"; 50 | 51 | function toggle() { 52 | n.item.collapsed = !n.item.collapsed; 53 | that.forceUpdate(); 54 | }; 55 | 56 | if (children(n.item).length > 0) { 57 | var text = { n.item.name }; 58 | } else { 59 | var text = { n.item.name }; 60 | } 61 | 62 | return ( 63 | 64 | 65 | { text } 66 | 67 | ) 68 | }); 69 | 70 | return ( 71 | 72 | 73 | { curves } 74 | { nodes } 75 | 76 | 77 | ) 78 | } 79 | } 80 | TreeChart.defaultProps = { 81 | 82 | options: { 83 | margin: {top: 20, left: 50, right: 80, bottom: 20}, 84 | width: 600, 85 | height: 600, 86 | fill: "#2980B9", 87 | stroke: "#3E90F0", 88 | r: 5, 89 | animate: { 90 | type: 'oneByOne', 91 | duration: 200, 92 | fillTransition: 3 93 | }, 94 | label: { 95 | fontFamily: 'Arial', 96 | fontSize: 14, 97 | bold: true, 98 | fill: '#34495E' 99 | } 100 | } 101 | } -------------------------------------------------------------------------------- /src/charts/TreeVivus.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Vivus from 'vivus'; 4 | import TreeChart from './Tree.js'; 5 | 6 | export default class TreeVivusChart extends TreeChart { 7 | constructor(props){ 8 | super(props); 9 | this.state = { finished: false }; 10 | } 11 | componentWillReceiveProps(nextProps){ 12 | if (nextProps.replay !== this.props.replay) this.setState({finished:false}); 13 | } 14 | componentDidMount() { 15 | this.run(); 16 | } 17 | componentDidUpdate(prevProps,prevState){ 18 | if (!this.state.finished) this.run() 19 | } 20 | run(){ 21 | if (this.refs.vivus === undefined) return; 22 | var animate = this.props.options && this.props.options.animate || {}; 23 | new Vivus(ReactDOM.findDOMNode(this.refs.vivus), { 24 | type: animate.type || 'delayed', 25 | duration: animate.duration || 'delayed', 26 | start: 'autostart', 27 | selfDestroy: true 28 | }, this.finish.bind(this)); 29 | } 30 | finish() { 31 | this.setState({ finished: true }); 32 | } 33 | } -------------------------------------------------------------------------------- /src/component/Axis.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import _ from 'lodash'; 3 | import fontAdapt from '../fontAdapter.js'; 4 | 5 | var Path = require('paths-js/path'); 6 | 7 | class AxisStruct { 8 | constructor(scale, options, chartArea, horizontal) { 9 | this.scale = scale; 10 | this.options = options; 11 | this.chartArea = chartArea; 12 | this.margin = chartArea.margin; 13 | this.horizontal = horizontal; 14 | } 15 | 16 | 17 | static calcStepSize(range, targetSteps) 18 | { 19 | // calculate an initial guess at step size 20 | var tempStep = range / targetSteps; 21 | 22 | // get the magnitude of the step size 23 | var mag = Math.floor(Math.log(tempStep) / Math.log(10)); 24 | var magPow = Math.pow(10, mag); 25 | 26 | // calculate most significant digit of the new step size 27 | var magMsd = Math.round(tempStep / magPow + 0.5); 28 | 29 | // promote the MSD to either 1, 2, or 5 30 | if (magMsd > 5.0) 31 | magMsd = 10.0; 32 | else if (magMsd > 2.0) 33 | magMsd = 5.0; 34 | else if (magMsd > 1.0) 35 | magMsd = 2.0; 36 | 37 | return magMsd * magPow; 38 | } 39 | 40 | static getTickValues(axis, tickCount) { 41 | //var tickStep = Math.round((axis.maxValue - axis.minValue) / tickCount, 0); 42 | var tickStep = AxisStruct.calcStepSize((axis.maxValue - axis.minValue),tickCount); 43 | return _.range(axis.minValue, axis.maxValue + 1,tickStep); 44 | } 45 | 46 | axis() { 47 | 48 | var horizontal = this.horizontal; 49 | 50 | var xAxis = this.chartArea.x; 51 | var yAxis = this.chartArea.y; 52 | var currentAxis = horizontal?xAxis:yAxis; 53 | 54 | var tickInterval = this.options.tickCount || 10; 55 | 56 | var ticks = this.options.tickValues !== undefined && this.options.tickValues.length !== 0? _.map(this.options.tickValues,function(v){return v.value }):AxisStruct.getTickValues(currentAxis, tickInterval); 57 | 58 | var fixed = this.options.zeroAxis?this.scale(0):horizontal?yAxis.min:xAxis.min; 59 | 60 | var start = {x: horizontal?xAxis.min:fixed, y: horizontal?fixed:yAxis.min}; 61 | var end = {x:horizontal?xAxis.max:fixed,y: horizontal?fixed:yAxis.max}; 62 | 63 | var margin = this.margin; 64 | if (margin !== undefined){ 65 | if (horizontal){ 66 | start.x -= margin.left || 0; 67 | end.x += margin.right || 0; 68 | } 69 | else { 70 | start.y += margin.bottom || 0; 71 | end.y -= margin.top || 0; 72 | } 73 | } 74 | 75 | return { 76 | item: currentAxis, 77 | path: Path().moveto(start).lineto(end).closepath(), 78 | ticks: ticks, 79 | lines: _.map(ticks, function (c) { 80 | var lineStart = {x: horizontal ? this.scale(c) : xAxis.min, y: horizontal ? yAxis.min : this.scale(c)}; 81 | return Path().moveto(lineStart).lineto(horizontal ? lineStart.x : xAxis.max, horizontal ? yAxis.max : lineStart.y); 82 | },this) 83 | }; 84 | } 85 | } 86 | 87 | export default class Axis extends React.Component { 88 | constructor(props){ 89 | super(props) 90 | } 91 | render(){ 92 | var chartArea = this.props.chartArea; 93 | var options = this.props.options; 94 | var scale = this.props.scale; 95 | var horizontal = options.orient ==="top" || options.orient ==="bottom"; 96 | 97 | var axis = new AxisStruct(this.props.scale,this.props.options,chartArea,horizontal).axis(); 98 | 99 | var translate = function(c) { 100 | var pair = horizontal?[scale(c),chartArea.y.min]:[chartArea.x.min,scale(c)]; 101 | return "translate(" + pair[0] + "," + pair[1] + ")"; 102 | }; 103 | 104 | var transparent = {opacity: 0.5}; 105 | var textAnchor = "start"; 106 | if (options.orient === "top" || options.orient === "bottom") textAnchor = "middle"; 107 | if (options.orient === "left") textAnchor = "end"; 108 | if (options.orient === "right") textAnchor = "start"; 109 | 110 | var xy = [0,0]; 111 | if (options.orient === "top") xy = [0,-5]; 112 | if (options.orient === "bottom") xy = [0,20]; 113 | if (options.orient === "left") xy = [-5,0]; 114 | if (options.orient === "right") xy = [5,0]; 115 | 116 | var textTransform = "translate(" + xy[0] + "," + xy[1] + ")"; 117 | 118 | var textStyle = fontAdapt(options.label); 119 | 120 | var ticks =_.map(axis.ticks, function (c, i) { 121 | var label = options.labelComponent !== undefined? React.cloneElement(options.labelComponent,{value:c}):c; 122 | return ( 123 | {options.showTicks ? : null} 124 | {options.showLabels ? 125 | {label} : null} 126 | ) 127 | }); 128 | 129 | 130 | var gridLines = options.showLines ? _.map(axis.lines, function (c, i) { 131 | return () 132 | }) : []; 133 | 134 | return( 135 | {options.showAxis? : null} 136 | {ticks} 137 | {gridLines} 138 | ); 139 | 140 | } 141 | } -------------------------------------------------------------------------------- /src/component/Options.js: -------------------------------------------------------------------------------- 1 | export default class ChartOptions { 2 | 3 | constructor(props) { 4 | 5 | //var noDataMsg = this.props.noDataMessage || "No data available"; 6 | //if (this.props.data === undefined) return ({noDataMsg}); 7 | this.options = props.options || {}; 8 | 9 | this.chartWidth = this.options.width || 400; 10 | this.chartHeight = this.options.height || 400; 11 | 12 | //margins 13 | //add right + left 14 | this.width = this.chartWidth + (this.margin.right || 0) + (this.margin.left || 0); 15 | //add top + bottom 16 | this.height = this.chartHeight + (this.margin.top || 0) + (this.margin.bottom || 0); 17 | 18 | } 19 | 20 | get legendPosition(){ return this.options.legendPosition || 'topLeft';} 21 | get axisX() {return this.options.axisX || {};} 22 | get axisY() {return this.options.axisY || {};} 23 | get margin(){return this.options.margin || {};} 24 | 25 | get stroke(){return this.options.stroke;} 26 | get fill(){return this.options.fill;} 27 | get r(){return this.options.r;} 28 | 29 | get label(){return this.options.label || {};} 30 | get animate() {return this.options.animate || {};} 31 | } -------------------------------------------------------------------------------- /src/fontAdapter.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | 3 | export default function fontAdapt(fontProps) { 4 | 5 | var style = {}; 6 | if (fontProps === undefined) return style; 7 | style = _.omit(fontProps,['color','bold','italic','underline']); 8 | if (fontProps.color) style['fill'] = _.isString(fontProps.color)?fontProps.color:fontProps.color.color; 9 | if (fontProps.bold) style['fontWeight'] = 'bold'; 10 | if (fontProps.italic) style['fontStyle'] = 'italic'; 11 | if (fontProps.underline) style['borderBottom'] = '1px dashed #999'; 12 | return style; 13 | 14 | 15 | 16 | } -------------------------------------------------------------------------------- /src/pallete/Colors.js: -------------------------------------------------------------------------------- 1 | class Colors { 2 | cut(x) { 3 | return Math.min(255, Math.floor(Math.abs(x))); 4 | } 5 | 6 | multiply(factor) { 7 | return function (c) { 8 | return { 9 | r: this.cut(factor * c.r), 10 | g: this.cut(factor * c.g), 11 | b: this.cut(factor * c.b) 12 | }; 13 | }.bind(this); 14 | } 15 | 16 | average(c1, c2) { 17 | return { 18 | r: this.cut((c1.r + c2.r) / 2), 19 | g: this.cut((c1.g + c2.g) / 2), 20 | b: this.cut((c1.b + c2.b) / 2) 21 | }; 22 | } 23 | 24 | lighten(c){return this.multiply(1.2)(c)}; 25 | darken(c){return this.multiply(0.8)(c)}; 26 | darkenColor(c) {return this.string(this.darken(this.hexToRgb(c)))} 27 | 28 | mix(color1) { 29 | var c1 = this.hexToRgb(color1); 30 | var c2 = this.multiply(0.5)(c1); 31 | var c3 = this.average(c1, c2); 32 | return [this.lighten(c1), c1, this.darken(c1), this.lighten(c3), c3, this.darken(c3), this.lighten(c2), c2, this.darken(c2)]; 33 | } 34 | 35 | string(c) { 36 | return this.rgbToHex(Math.floor(c.r),Math.floor(c.g),Math.floor(c.b)); 37 | //return "rgb(" + (Math.floor(c.r)) + "," + (Math.floor(c.g)) + "," + (Math.floor(c.b)) + ")"; 38 | } 39 | hexToRgb(hex) { 40 | var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 41 | return result ? { 42 | r: parseInt(result[1], 16), 43 | g: parseInt(result[2], 16), 44 | b: parseInt(result[3], 16) 45 | } : null; 46 | } 47 | componentToHex(c) { 48 | var hex = c.toString(16); 49 | return hex.length == 1 ? "0" + hex : hex; 50 | } 51 | 52 | rgbToHex(r, g, b) { 53 | return "#" + this.componentToHex(r) + this.componentToHex(g) + this.componentToHex(b); 54 | } 55 | 56 | }; 57 | const colour = new Colors(); 58 | export default colour; 59 | -------------------------------------------------------------------------------- /src/styleSvg.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | 3 | export default function styleSvg(style, sourceProps) { 4 | 5 | if (style === undefined) style = {}; 6 | if (sourceProps === undefined) return style; 7 | 8 | if (sourceProps.fill) { 9 | style.fill = _.isString(sourceProps.fill)?sourceProps.fill:sourceProps.fill.color; 10 | style.fillOpacity = !!sourceProps.fill.alpha? sourceProps.fill.alpha/100:1; 11 | } 12 | if (sourceProps.stroke) { 13 | style.stroke = _.isString(sourceProps.stroke)?sourceProps.stroke:sourceProps.stroke.color; 14 | style.strokeOpacity =!!sourceProps.stroke.alpha? sourceProps.stroke.alpha/100:1; 15 | } 16 | if (sourceProps.strokeWidth) style.strokeWidth = sourceProps.strokeWidth; 17 | return style; 18 | } 19 | 20 | --------------------------------------------------------------------------------